@guidekit/core 0.1.0-beta.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.
@@ -0,0 +1,2186 @@
1
+ /**
2
+ * Canonical map of every event in the GuideKit system.
3
+ *
4
+ * Keys use a `namespace:name` convention (except the top-level `error` event).
5
+ * Values are the payload types that accompany each event.
6
+ */
7
+ interface EventMap {
8
+ 'dom:scan-complete': {
9
+ pageModel: unknown;
10
+ durationMs: number;
11
+ };
12
+ 'dom:mutation-detected': {
13
+ mutations: number;
14
+ debounced: boolean;
15
+ };
16
+ 'dom:route-change': {
17
+ from: string;
18
+ to: string;
19
+ };
20
+ 'llm:response-start': {
21
+ conversationId: string;
22
+ };
23
+ 'llm:response-chunk': {
24
+ text: string;
25
+ done: boolean;
26
+ };
27
+ 'llm:response-end': {
28
+ conversationId: string;
29
+ totalTokens: number;
30
+ };
31
+ 'llm:tool-call': {
32
+ name: string;
33
+ arguments: Record<string, unknown>;
34
+ };
35
+ 'llm:token-usage': {
36
+ prompt: number;
37
+ completion: number;
38
+ total: number;
39
+ };
40
+ 'voice:state-change': {
41
+ from: string;
42
+ to: string;
43
+ };
44
+ 'voice:transcript': {
45
+ text: string;
46
+ isFinal: boolean;
47
+ confidence: number;
48
+ };
49
+ 'voice:tts-start': {
50
+ utterance: string;
51
+ };
52
+ 'voice:tts-end': {
53
+ utterance: string;
54
+ durationMs: number;
55
+ };
56
+ 'voice:degraded': {
57
+ reason: string;
58
+ fallback: 'text';
59
+ };
60
+ 'auth:token-refreshed': {
61
+ expiresAt: number;
62
+ };
63
+ 'auth:token-refresh-failed': {
64
+ error: Error;
65
+ attemptsRemaining: number;
66
+ };
67
+ 'auth:token-expired': Record<string, never>;
68
+ 'connectivity:state-change': {
69
+ state: 'online' | 'degraded' | 'offline';
70
+ previous: 'online' | 'degraded' | 'offline';
71
+ };
72
+ 'awareness:dwell': {
73
+ sectionId: string;
74
+ durationMs: number;
75
+ };
76
+ 'awareness:idle': {
77
+ durationMs: number;
78
+ };
79
+ 'awareness:rage-click': {
80
+ selector: string;
81
+ clicks: number;
82
+ };
83
+ 'awareness:section-visible': {
84
+ sectionId: string;
85
+ ratio: number;
86
+ };
87
+ 'visual:spotlight-shown': {
88
+ selector: string;
89
+ sectionId?: string;
90
+ };
91
+ 'visual:spotlight-dismissed': Record<string, never>;
92
+ 'visual:tour-step': {
93
+ stepIndex: number;
94
+ totalSteps: number;
95
+ sectionId: string;
96
+ };
97
+ error: Error;
98
+ }
99
+ declare class EventBus {
100
+ /** Per-event listeners. Wildcard keys end with `:*`. */
101
+ private readonly listeners;
102
+ /** Listeners registered via `onAny`. */
103
+ private readonly anyListeners;
104
+ /** When true, every `emit` is logged to the console. */
105
+ private readonly debug;
106
+ constructor(options?: {
107
+ debug?: boolean;
108
+ });
109
+ /**
110
+ * Subscribe to a specific typed event.
111
+ *
112
+ * @returns An unsubscribe function.
113
+ */
114
+ on<K extends keyof EventMap>(event: K, handler: (data: EventMap[K]) => void): () => void;
115
+ /**
116
+ * Subscribe to a namespace wildcard (e.g. `'dom:*'`).
117
+ * The handler receives `(data, eventName)`.
118
+ *
119
+ * @returns An unsubscribe function.
120
+ */
121
+ on(event: `${string}:*`, handler: (data: unknown, eventName: string) => void): () => void;
122
+ /**
123
+ * Subscribe to **every** event emitted on the bus.
124
+ *
125
+ * @returns An unsubscribe function.
126
+ */
127
+ onAny(handler: (data: unknown, eventName: string) => void): () => void;
128
+ /**
129
+ * Emit a typed event.
130
+ *
131
+ * Handlers are invoked synchronously in registration order. If a handler
132
+ * throws, the error is logged and remaining handlers still execute.
133
+ */
134
+ emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void;
135
+ /**
136
+ * Subscribe to a specific event, automatically unsubscribing after the
137
+ * first invocation.
138
+ *
139
+ * @returns An unsubscribe function (also cancels a not-yet-fired listener).
140
+ */
141
+ once<K extends keyof EventMap>(event: K, handler: (data: EventMap[K]) => void): () => void;
142
+ /** Remove **all** listeners from the bus. */
143
+ removeAll(): void;
144
+ /**
145
+ * Return the number of registered listeners.
146
+ *
147
+ * - If `event` is provided, returns the count for that specific event key
148
+ * (including wildcard keys like `'dom:*'`).
149
+ * - If omitted, returns the total across all events plus `onAny` listeners.
150
+ */
151
+ listenerCount(event?: string): number;
152
+ /**
153
+ * Invoke a handler inside a try/catch so one misbehaving handler never
154
+ * prevents the remaining handlers from executing.
155
+ */
156
+ private invokeSafe;
157
+ }
158
+ /**
159
+ * Create a new {@link EventBus} instance.
160
+ *
161
+ * ```ts
162
+ * const bus = createEventBus({ debug: true });
163
+ * const unsub = bus.on('dom:scan-complete', (data) => {
164
+ * console.log(data.pageModel, data.durationMs);
165
+ * });
166
+ * bus.emit('dom:scan-complete', { pageModel: {}, durationMs: 42 });
167
+ * unsub();
168
+ * ```
169
+ */
170
+ declare function createEventBus(options?: {
171
+ debug?: boolean;
172
+ }): EventBus;
173
+
174
+ /** All translatable string keys used by the SDK UI. */
175
+ interface I18nStrings {
176
+ widgetTitle: string;
177
+ openAssistant: string;
178
+ closeAssistant: string;
179
+ closePanel: string;
180
+ sendMessage: string;
181
+ inputPlaceholder: string;
182
+ listeningPlaceholder: string;
183
+ startVoice: string;
184
+ stopVoice: string;
185
+ statusOnline: string;
186
+ statusConnecting: string;
187
+ statusOffline: string;
188
+ statusListening: string;
189
+ statusSpeaking: string;
190
+ statusProcessing: string;
191
+ emptyStateMessage: string;
192
+ errorGeneric: string;
193
+ errorNetwork: string;
194
+ errorMicDenied: string;
195
+ errorRateLimit: string;
196
+ greetingMessage: string;
197
+ idleHelpMessage: string;
198
+ voiceDegradedNotice: string;
199
+ quietModeOn: string;
200
+ quietModeOff: string;
201
+ }
202
+ type SupportedLocale = 'en' | 'es' | 'fr' | 'de' | 'ja' | 'zh' | 'ar' | 'pt';
203
+ type LocaleInput = SupportedLocale | 'auto' | I18nStrings;
204
+ interface I18nOptions {
205
+ locale?: LocaleInput;
206
+ debug?: boolean;
207
+ }
208
+ declare class I18n {
209
+ private strings;
210
+ private resolvedLocale;
211
+ private debug;
212
+ constructor(options?: I18nOptions);
213
+ /** Get a translated string by key. */
214
+ t(key: keyof I18nStrings): string;
215
+ /** Get all strings for the current locale. */
216
+ getStrings(): I18nStrings;
217
+ /** Change the current locale at runtime. */
218
+ setLocale(locale: LocaleInput): void;
219
+ /** The current resolved locale code (e.g. 'en', 'fr', or 'custom'). */
220
+ get currentLocale(): string;
221
+ private resolve;
222
+ }
223
+
224
+ /**
225
+ * @module @guidekit/core/types
226
+ *
227
+ * Shared TypeScript types for the GuideKit SDK.
228
+ * All types used across packages are defined and exported from this module.
229
+ */
230
+ /**
231
+ * Reference type matching the GuideKitError class shape defined in ../errors/.
232
+ * Used throughout the type system to avoid circular imports. The actual class
233
+ * implementation lives in the errors module; this is the structural contract.
234
+ */
235
+ type GuideKitErrorType = Error & {
236
+ readonly code: string;
237
+ readonly provider?: string;
238
+ readonly recoverable: boolean;
239
+ readonly suggestion: string;
240
+ readonly docsUrl: string;
241
+ };
242
+ /** Metadata produced by the DOM scanner indicating work performed. */
243
+ interface ScanMetadata {
244
+ totalSectionsFound: number;
245
+ sectionsIncluded: number;
246
+ totalNodesScanned: number;
247
+ scanBudgetExhausted: boolean;
248
+ }
249
+ /** A scored, labelled section of the current page. */
250
+ interface PageSection {
251
+ id: string;
252
+ selector: string;
253
+ tagName: string;
254
+ label: string;
255
+ summary: string;
256
+ isVisible: boolean;
257
+ visibilityRatio: number;
258
+ score: number;
259
+ landmark?: string;
260
+ hasInteractiveElements: boolean;
261
+ depth: number;
262
+ }
263
+ /** A navigation link discovered on the page. */
264
+ interface NavItem {
265
+ label: string;
266
+ href: string;
267
+ isCurrent: boolean;
268
+ selector: string;
269
+ }
270
+ /** An interactive element (button, link, input, etc.) on the page. */
271
+ interface InteractiveElement {
272
+ selector: string;
273
+ tagName: string;
274
+ type?: string;
275
+ label: string;
276
+ role?: string;
277
+ isDisabled: boolean;
278
+ guideKitTarget?: string;
279
+ }
280
+ /** A single field inside a form. */
281
+ interface FormField {
282
+ selector: string;
283
+ name: string;
284
+ type: string;
285
+ label: string;
286
+ isRequired: boolean;
287
+ hasError: boolean;
288
+ errorMessage?: string;
289
+ }
290
+ /** Summary representation of a <form> element. */
291
+ interface FormSummary {
292
+ selector: string;
293
+ id?: string;
294
+ action?: string;
295
+ fields: FormField[];
296
+ hasValidationErrors: boolean;
297
+ }
298
+ /** An overlay (modal, drawer, dropdown, popover) currently present in the DOM. */
299
+ interface OverlayElement {
300
+ selector: string;
301
+ type: 'modal' | 'drawer' | 'dropdown' | 'popover';
302
+ label: string;
303
+ isVisible: boolean;
304
+ }
305
+ /**
306
+ * Complete snapshot of the current page produced by the page-awareness scanner.
307
+ * Sent to the LLM as grounding context on every turn.
308
+ */
309
+ interface PageModel {
310
+ url: string;
311
+ title: string;
312
+ meta: {
313
+ description: string;
314
+ h1: string | null;
315
+ language: string;
316
+ };
317
+ sections: PageSection[];
318
+ navigation: NavItem[];
319
+ interactiveElements: InteractiveElement[];
320
+ forms: FormSummary[];
321
+ activeOverlays: OverlayElement[];
322
+ viewport: {
323
+ width: number;
324
+ height: number;
325
+ orientation: 'portrait' | 'landscape';
326
+ };
327
+ allSectionsSummary: string[];
328
+ hash: string;
329
+ timestamp: number;
330
+ scanMetadata: ScanMetadata;
331
+ }
332
+ /** Discriminated union describing every possible state the agent can be in. */
333
+ type AgentState = {
334
+ status: 'idle';
335
+ } | {
336
+ status: 'listening';
337
+ durationMs: number;
338
+ } | {
339
+ status: 'processing';
340
+ transcript: string;
341
+ } | {
342
+ status: 'speaking';
343
+ utterance: string;
344
+ } | {
345
+ status: 'error';
346
+ error: GuideKitErrorType;
347
+ };
348
+ /** Speech-to-text provider configuration. */
349
+ type STTConfig = {
350
+ provider: 'deepgram';
351
+ apiKey: string;
352
+ model?: 'nova-2' | 'nova-3';
353
+ } | {
354
+ provider: 'assemblyai';
355
+ apiKey: string;
356
+ };
357
+ /** Text-to-speech provider configuration. */
358
+ type TTSConfig = {
359
+ provider: 'elevenlabs';
360
+ apiKey: string;
361
+ voiceId?: string;
362
+ } | {
363
+ provider: 'cartesia';
364
+ apiKey: string;
365
+ voiceId?: string;
366
+ };
367
+ /** Large language model provider configuration. */
368
+ type LLMConfig = {
369
+ provider: 'gemini';
370
+ apiKey: string;
371
+ model?: 'gemini-2.5-flash' | 'gemini-2.5-pro';
372
+ } | {
373
+ provider: 'openai';
374
+ apiKey: string;
375
+ model?: 'gpt-4o' | 'gpt-4o-mini';
376
+ };
377
+ /** Top-level options that control SDK behaviour. */
378
+ interface GuideKitOptions {
379
+ locale?: string | 'auto';
380
+ mode?: 'voice' | 'text' | 'auto';
381
+ greetOnFirstVisit?: boolean;
382
+ spotlightColor?: string;
383
+ consentRequired?: boolean;
384
+ debug?: boolean;
385
+ rateLimits?: {
386
+ maxLLMCallsPerMinute?: number;
387
+ maxSTTMinutesPerSession?: number;
388
+ maxTTSCharsPerSession?: number;
389
+ };
390
+ clickableSelectors?: {
391
+ allow?: string[];
392
+ deny?: string[];
393
+ };
394
+ safetySettings?: Record<string, string>;
395
+ /** Maximum character length for user messages. Default: 10000. */
396
+ maxMessageLength?: number;
397
+ }
398
+ /** Configuration for the assistant persona. */
399
+ interface AgentConfig {
400
+ name?: string;
401
+ greeting?: string;
402
+ personality?: string;
403
+ }
404
+ /** Visual customisation of the GuideKit widget. */
405
+ interface GuideKitTheme {
406
+ primaryColor?: string;
407
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
408
+ borderRadius?: string;
409
+ }
410
+ /** A single entry in the developer-supplied content map. */
411
+ interface ContentMapEntry {
412
+ description: string;
413
+ facts?: string[];
414
+ }
415
+ /** Static content map keyed by section ID or URL pattern. */
416
+ type ContentMap = Record<string, ContentMapEntry>;
417
+ /** Callback-based content map for dynamic or async lookups. */
418
+ type ContentMapFunction = (sectionId: string) => ContentMapEntry | null | Promise<ContentMapEntry | null>;
419
+ /** Accepted input types for the content map prop. */
420
+ type ContentMapInput = ContentMap | ContentMapFunction;
421
+ /** A single turn in the conversation history. */
422
+ interface ConversationTurn {
423
+ role: 'user' | 'assistant';
424
+ content: string;
425
+ timestamp: number;
426
+ }
427
+ /** Serialisable session state for persistence across page navigations. */
428
+ interface SessionState {
429
+ conversationHistory: ConversationTurn[];
430
+ currentUrl: string;
431
+ agentStatus: AgentState['status'];
432
+ userPreference: 'voice' | 'text';
433
+ quietMode: boolean;
434
+ totalSizeBytes: number;
435
+ }
436
+ /** Network connectivity state observed by the SDK. */
437
+ type ConnectionState = 'online' | 'degraded' | 'offline';
438
+ /** An event emitted by the SDK via the `onEvent` callback. */
439
+ interface GuideKitEvent {
440
+ type: string;
441
+ data: Record<string, unknown>;
442
+ timestamp: number;
443
+ }
444
+ /** Props accepted by the `<GuideKitProvider>` React component. */
445
+ interface GuideKitProviderProps {
446
+ tokenEndpoint?: string;
447
+ stt?: STTConfig;
448
+ tts?: TTSConfig;
449
+ llm?: LLMConfig;
450
+ agent?: AgentConfig;
451
+ contentMap?: ContentMapInput;
452
+ options?: GuideKitOptions;
453
+ theme?: GuideKitTheme;
454
+ locale?: string | 'auto';
455
+ instanceId?: string;
456
+ rootElement?: HTMLElement;
457
+ onError?: (error: GuideKitErrorType) => void;
458
+ onEvent?: (event: GuideKitEvent) => void;
459
+ onReady?: () => void;
460
+ onBeforeLLMCall?: (context: {
461
+ systemPrompt: string;
462
+ userMessage: string;
463
+ conversationHistory: Array<{
464
+ role: string;
465
+ content: string;
466
+ }>;
467
+ }) => {
468
+ systemPrompt: string;
469
+ userMessage: string;
470
+ conversationHistory: Array<{
471
+ role: string;
472
+ content: string;
473
+ }>;
474
+ } | Promise<{
475
+ systemPrompt: string;
476
+ userMessage: string;
477
+ conversationHistory: Array<{
478
+ role: string;
479
+ content: string;
480
+ }>;
481
+ }>;
482
+ children?: unknown;
483
+ }
484
+ /** Definition of a tool that can be invoked by the LLM. */
485
+ interface ToolDefinition {
486
+ name: string;
487
+ description: string;
488
+ parameters: Record<string, unknown>;
489
+ schemaVersion: number;
490
+ }
491
+ /** A tool invocation request returned by the LLM. */
492
+ interface ToolCall {
493
+ id: string;
494
+ name: string;
495
+ arguments: Record<string, unknown>;
496
+ }
497
+ /** A chunk of streamed text from the LLM. */
498
+ interface TextChunk {
499
+ text: string;
500
+ done: boolean;
501
+ }
502
+ /**
503
+ * Adapter interface that each LLM provider must implement.
504
+ * Handles format conversion between GuideKit's internal representation
505
+ * and the provider-specific wire format.
506
+ */
507
+ interface LLMProviderAdapter {
508
+ formatTools(tools: ToolDefinition[]): unknown;
509
+ formatConversation(history: ConversationTurn[]): unknown;
510
+ parseResponse(stream: ReadableStream): AsyncIterable<TextChunk | ToolCall>;
511
+ formatToolResult(callId: string, result: unknown): unknown;
512
+ }
513
+ /** Decoded payload of a GuideKit session token. */
514
+ interface TokenPayload {
515
+ sessionId: string;
516
+ expiresAt: number;
517
+ audience: string[];
518
+ permissions: string[];
519
+ userId?: string;
520
+ metadata?: Record<string, unknown>;
521
+ iat: number;
522
+ }
523
+ /** Response returned by the token endpoint. */
524
+ interface TokenResponse {
525
+ token: string;
526
+ expiresIn: number;
527
+ expiresAt: number;
528
+ }
529
+ /** Options for `createSessionToken()` on the server side. */
530
+ interface CreateSessionTokenOptions {
531
+ signingSecret: string | string[];
532
+ deepgramKey?: string;
533
+ elevenlabsKey?: string;
534
+ geminiKey?: string;
535
+ expiresIn?: string;
536
+ allowedOrigins?: string[];
537
+ permissions?: string[];
538
+ userId?: string;
539
+ sessionId?: string;
540
+ metadata?: Record<string, unknown>;
541
+ }
542
+ /** Shape of the external store consumed by React hooks. */
543
+ interface GuideKitStore {
544
+ status: {
545
+ isReady: boolean;
546
+ agentState: AgentState;
547
+ error: GuideKitErrorType | null;
548
+ };
549
+ voice: {
550
+ isListening: boolean;
551
+ isSpeaking: boolean;
552
+ };
553
+ /** Whether the user has granted privacy consent. Always `true` when `consentRequired` is not enabled. Managed by the React widget layer. */
554
+ hasConsent?: boolean;
555
+ }
556
+
557
+ /**
558
+ * Canonical error codes emitted by the SDK.
559
+ * Keyed as `DOMAIN_DETAIL` so consumers can match on prefixes or exact values.
560
+ */
561
+ declare const ErrorCodes: {
562
+ readonly AUTH_INVALID_KEY: "AUTH_INVALID_KEY";
563
+ readonly AUTH_EXPIRED_TOKEN: "AUTH_EXPIRED_TOKEN";
564
+ readonly AUTH_TOKEN_REFRESH_FAILED: "AUTH_TOKEN_REFRESH_FAILED";
565
+ readonly AUTH_ENDPOINT_FAILED: "AUTH_ENDPOINT_FAILED";
566
+ readonly CONFIG_INVALID_PROVIDER: "CONFIG_INVALID_PROVIDER";
567
+ readonly CONFIG_MISSING_REQUIRED: "CONFIG_MISSING_REQUIRED";
568
+ readonly INIT_SHADOW_DOM_FAILED: "INIT_SHADOW_DOM_FAILED";
569
+ readonly INIT_BROWSER_UNSUPPORTED: "INIT_BROWSER_UNSUPPORTED";
570
+ readonly RATE_LIMIT_PROVIDER: "RATE_LIMIT_PROVIDER";
571
+ readonly RATE_LIMIT_CLIENT: "RATE_LIMIT_CLIENT";
572
+ readonly RESOURCE_EXHAUSTED_LLM: "RESOURCE_EXHAUSTED_LLM";
573
+ readonly RESOURCE_EXHAUSTED_STT: "RESOURCE_EXHAUSTED_STT";
574
+ readonly RESOURCE_EXHAUSTED_TTS: "RESOURCE_EXHAUSTED_TTS";
575
+ readonly PERMISSION_MIC_DENIED: "PERMISSION_MIC_DENIED";
576
+ readonly PERMISSION_MIC_UNAVAILABLE: "PERMISSION_MIC_UNAVAILABLE";
577
+ readonly NETWORK_WEBSOCKET_FAILED: "NETWORK_WEBSOCKET_FAILED";
578
+ readonly NETWORK_CONNECTION_LOST: "NETWORK_CONNECTION_LOST";
579
+ readonly NETWORK_TIMEOUT: "NETWORK_TIMEOUT";
580
+ readonly TIMEOUT_STT_CONNECT: "TIMEOUT_STT_CONNECT";
581
+ readonly TIMEOUT_LLM_RESPONSE: "TIMEOUT_LLM_RESPONSE";
582
+ readonly TIMEOUT_TTS_CONNECT: "TIMEOUT_TTS_CONNECT";
583
+ readonly TIMEOUT_TTS_FIRST_AUDIO: "TIMEOUT_TTS_FIRST_AUDIO";
584
+ readonly BROWSER_NO_WEB_AUDIO: "BROWSER_NO_WEB_AUDIO";
585
+ readonly BROWSER_NO_WASM: "BROWSER_NO_WASM";
586
+ readonly VAD_PACKAGE_MISSING: "VAD_PACKAGE_MISSING";
587
+ readonly CONTENT_FILTER_TRIGGERED: "CONTENT_FILTER_TRIGGERED";
588
+ readonly PRIVACY_HOOK_CANCELLED: "PRIVACY_HOOK_CANCELLED";
589
+ };
590
+ /** Union of every known error code string. */
591
+ type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
592
+ type Provider = 'deepgram' | 'elevenlabs' | 'gemini' | 'openai';
593
+ interface GuideKitErrorOptions {
594
+ code: string;
595
+ message: string;
596
+ provider?: Provider;
597
+ recoverable: boolean;
598
+ suggestion: string;
599
+ docsUrl?: string;
600
+ cause?: Error;
601
+ }
602
+ /**
603
+ * Root error for every failure surfaced by the GuideKit SDK.
604
+ *
605
+ * Every instance carries structured metadata so UI layers can present
606
+ * actionable feedback without parsing message strings.
607
+ */
608
+ declare class GuideKitError extends Error {
609
+ readonly code: string;
610
+ readonly provider?: Provider;
611
+ readonly recoverable: boolean;
612
+ readonly suggestion: string;
613
+ readonly docsUrl: string;
614
+ constructor(options: GuideKitErrorOptions);
615
+ }
616
+ /** Wrong or expired API key / token. */
617
+ declare class AuthenticationError extends GuideKitError {
618
+ constructor(options: Omit<GuideKitErrorOptions, 'recoverable'> & {
619
+ recoverable?: boolean;
620
+ });
621
+ }
622
+ /** Invalid provider configuration supplied at init time. */
623
+ declare class ConfigurationError extends GuideKitError {
624
+ constructor(options: Omit<GuideKitErrorOptions, 'recoverable'> & {
625
+ recoverable?: boolean;
626
+ });
627
+ }
628
+ /** SDK startup failure (Shadow DOM creation, browser too old, etc.). */
629
+ declare class InitializationError extends GuideKitError {
630
+ constructor(options: Omit<GuideKitErrorOptions, 'recoverable'> & {
631
+ recoverable?: boolean;
632
+ });
633
+ }
634
+ /** Provider-side rate limit hit. Includes a retry hint. */
635
+ declare class RateLimitError extends GuideKitError {
636
+ readonly retryAfterMs: number;
637
+ constructor(options: GuideKitErrorOptions & {
638
+ retryAfterMs: number;
639
+ });
640
+ }
641
+ /** Client-side cost / usage limits exhausted. */
642
+ declare class ResourceExhaustedError extends GuideKitError {
643
+ constructor(options: Omit<GuideKitErrorOptions, 'recoverable'> & {
644
+ recoverable?: boolean;
645
+ });
646
+ }
647
+ /** Microphone permission denied or device not available. */
648
+ declare class PermissionError extends GuideKitError {
649
+ constructor(options: Omit<GuideKitErrorOptions, 'recoverable'> & {
650
+ recoverable?: boolean;
651
+ });
652
+ }
653
+ /** WebSocket dropped, HTTP connection failed, etc. */
654
+ declare class NetworkError extends GuideKitError {
655
+ constructor(options: Omit<GuideKitErrorOptions, 'recoverable'> & {
656
+ recoverable?: boolean;
657
+ });
658
+ }
659
+ /** An operation exceeded its deadline. */
660
+ declare class TimeoutError extends GuideKitError {
661
+ readonly operationName: string;
662
+ readonly timeoutMs: number;
663
+ constructor(options: GuideKitErrorOptions & {
664
+ operationName: string;
665
+ timeoutMs: number;
666
+ });
667
+ }
668
+ /** Missing browser capability (Web Audio, WASM, VAD). */
669
+ declare class BrowserSupportError extends GuideKitError {
670
+ constructor(options: Omit<GuideKitErrorOptions, 'recoverable'> & {
671
+ recoverable?: boolean;
672
+ });
673
+ }
674
+ /** LLM safety / content filter triggered. */
675
+ declare class ContentFilterError extends GuideKitError {
676
+ constructor(options: Omit<GuideKitErrorOptions, 'recoverable'> & {
677
+ recoverable?: boolean;
678
+ });
679
+ }
680
+ /**
681
+ * Narrows an unknown caught value to `GuideKitError`.
682
+ *
683
+ * ```ts
684
+ * try { ... } catch (err) {
685
+ * if (isGuideKitError(err)) {
686
+ * console.log(err.code, err.suggestion);
687
+ * }
688
+ * }
689
+ * ```
690
+ */
691
+ declare function isGuideKitError(error: unknown): error is GuideKitError;
692
+
693
+ /** Result of a health check on a single service. */
694
+ interface HealthCheckStatus {
695
+ status: 'ok' | 'degraded' | 'unavailable' | 'not-configured';
696
+ latencyMs?: number;
697
+ error?: string;
698
+ }
699
+ /** Full health check result. */
700
+ interface HealthCheckResult {
701
+ llm: HealthCheckStatus;
702
+ stt: HealthCheckStatus;
703
+ tts: HealthCheckStatus;
704
+ mic: HealthCheckStatus;
705
+ overall: 'ok' | 'degraded' | 'unavailable';
706
+ }
707
+ /** Context passed to onBeforeLLMCall for privacy filtering. */
708
+ interface BeforeLLMCallContext {
709
+ systemPrompt: string;
710
+ userMessage: string;
711
+ conversationHistory: Array<{
712
+ role: string;
713
+ content: string;
714
+ }>;
715
+ }
716
+ interface GuideKitCoreOptions {
717
+ tokenEndpoint?: string;
718
+ stt?: STTConfig;
719
+ tts?: TTSConfig;
720
+ llm?: LLMConfig;
721
+ agent?: AgentConfig;
722
+ contentMap?: ContentMapInput;
723
+ options?: GuideKitOptions;
724
+ instanceId?: string;
725
+ rootElement?: HTMLElement;
726
+ onError?: (error: GuideKitError) => void;
727
+ onEvent?: (event: GuideKitEvent) => void;
728
+ onReady?: () => void;
729
+ /**
730
+ * Privacy hook: called before every LLM request. Return modified context
731
+ * or throw to cancel the request. Use for custom PII scrubbing.
732
+ */
733
+ onBeforeLLMCall?: (context: BeforeLLMCallContext) => BeforeLLMCallContext | Promise<BeforeLLMCallContext>;
734
+ }
735
+ declare class GuideKitCore {
736
+ readonly instanceId: string;
737
+ readonly bus: EventBus;
738
+ private resourceManager;
739
+ private domScanner;
740
+ private contextManager;
741
+ private llmOrchestrator;
742
+ private connectionManager;
743
+ private navigationController;
744
+ private voicePipeline;
745
+ private visualGuidance;
746
+ private toolExecutor;
747
+ private awarenessSystem;
748
+ private proactiveEngine;
749
+ private rateLimiter;
750
+ private _i18n;
751
+ private tokenManager;
752
+ private _isReady;
753
+ private _agentState;
754
+ private _currentPageModel;
755
+ private readonly _options;
756
+ private _debug;
757
+ private _sendInFlight;
758
+ private _instanceAbortController;
759
+ private _initPromise;
760
+ private storeListeners;
761
+ private _storeSnapshot;
762
+ private customActions;
763
+ constructor(options: GuideKitCoreOptions);
764
+ init(): Promise<void>;
765
+ private _doInit;
766
+ sendText(message_: string): Promise<string>;
767
+ /** Get the current page model. */
768
+ get pageModel(): PageModel | null;
769
+ /** Whether the SDK has been fully initialized. */
770
+ get isReady(): boolean;
771
+ /** Current agent state. */
772
+ get agentState(): AgentState;
773
+ /** Current auth token string, or null if not using token-based auth. */
774
+ get currentToken(): string | null;
775
+ subscribe(listener: () => void): () => void;
776
+ getSnapshot(): GuideKitStore;
777
+ registerAction(actionId: string, action: {
778
+ description: string;
779
+ parameters: Record<string, unknown>;
780
+ handler: (params: Record<string, unknown>) => Promise<unknown>;
781
+ }): void;
782
+ /** Start listening for voice input. Initializes voice pipeline on first call. */
783
+ startListening(): Promise<void>;
784
+ /** Stop listening for voice input. */
785
+ stopListening(): void;
786
+ /** Stop current TTS playback (barge-in). */
787
+ stopSpeaking(): void;
788
+ /** Whether voice pipeline is available. */
789
+ get hasVoice(): boolean;
790
+ /** Highlight an element by sectionId or CSS selector. */
791
+ highlight(params: {
792
+ sectionId?: string;
793
+ selector?: string;
794
+ tooltip?: string;
795
+ position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';
796
+ }): boolean;
797
+ /** Dismiss the current spotlight highlight. */
798
+ dismissHighlight(): void;
799
+ /** Smooth scroll to a section. */
800
+ scrollToSection(sectionId: string, offset?: number): void;
801
+ /** Smooth scroll to a CSS selector. */
802
+ scrollToSelector(selector: string, offset?: number): void;
803
+ /** Start a guided tour. */
804
+ startTour(sectionIds: string[], mode?: 'auto' | 'manual'): void;
805
+ /** Advance to next tour step. */
806
+ nextTourStep(): void;
807
+ /** Go back to previous tour step. */
808
+ prevTourStep(): void;
809
+ /** Stop the guided tour. */
810
+ stopTour(): void;
811
+ /** Navigate to a same-origin URL. */
812
+ navigate(href: string): Promise<boolean>;
813
+ setPageContext(context: Record<string, unknown>): void;
814
+ /** Get the i18n instance for localized strings. */
815
+ get i18n(): I18n;
816
+ /** Get/set quiet mode on proactive triggers. */
817
+ get quietMode(): boolean;
818
+ set quietMode(value: boolean);
819
+ /** Get/set user preference (voice/text). */
820
+ get userPreference(): 'voice' | 'text';
821
+ set userPreference(value: 'voice' | 'text');
822
+ /** Get the rate limiter for monitoring usage. */
823
+ get rateLimiterState(): RateLimiterState;
824
+ /**
825
+ * Check health of all connected services.
826
+ * Returns per-service status and an overall assessment.
827
+ */
828
+ checkHealth(): Promise<HealthCheckResult>;
829
+ destroy(): Promise<void>;
830
+ private setAgentState;
831
+ private notifyStoreListeners;
832
+ private buildSnapshot;
833
+ /**
834
+ * Register all built-in tool handlers with the ToolExecutor.
835
+ * Called once during init() after VisualGuidance and all subsystems are ready.
836
+ */
837
+ private registerBuiltinTools;
838
+ private getToolDefinitions;
839
+ }
840
+
841
+ /**
842
+ * A disposable resource that the SDK tracks for deterministic cleanup.
843
+ * Each resource has a unique name and a cleanup function that may be async.
844
+ */
845
+ interface Resource {
846
+ name: string;
847
+ cleanup: () => void | Promise<void>;
848
+ }
849
+ /** Lifecycle states for a ResourceManager instance. */
850
+ type ResourceManagerState = 'initializing' | 'ready' | 'tearing_down' | 'torn_down';
851
+ /**
852
+ * Manages the lifecycle of SDK resources (AbortControllers, event listeners,
853
+ * WebSocket connections, etc.) and ensures deterministic cleanup on unmount.
854
+ *
855
+ * Resources are cleaned up sequentially — order matters because later
856
+ * resources may depend on earlier ones still being alive during their own
857
+ * cleanup phase.
858
+ */
859
+ declare class ResourceManager {
860
+ readonly instanceId: string;
861
+ private _state;
862
+ private readonly _resources;
863
+ private _destroyPromise;
864
+ private _destroyCancelled;
865
+ constructor(instanceId?: string);
866
+ /** Current lifecycle state. */
867
+ get state(): ResourceManagerState;
868
+ /** Number of currently registered resources. */
869
+ get resourceCount(): number;
870
+ /**
871
+ * Register a resource for cleanup tracking.
872
+ *
873
+ * @throws If the manager has already been torn down.
874
+ */
875
+ register(resource: Resource): void;
876
+ /**
877
+ * Unregister a specific resource by name without invoking its cleanup.
878
+ */
879
+ unregister(name: string): void;
880
+ /**
881
+ * Create a tracked AbortController. On destroy, its `abort()` method will
882
+ * be called automatically.
883
+ */
884
+ createAbortController(name: string): AbortController;
885
+ /** Transition from `initializing` to `ready`. */
886
+ markReady(): void;
887
+ /**
888
+ * Destroy all registered resources sequentially.
889
+ *
890
+ * Each resource gets up to {@link CLEANUP_TIMEOUT_MS}ms to complete.
891
+ * If cleanup exceeds the timeout a warning is logged and the manager
892
+ * proceeds to the next resource.
893
+ *
894
+ * After all resources are processed the state transitions to `torn_down`.
895
+ * Calling `destroy()` multiple times returns the same promise.
896
+ */
897
+ destroy(): Promise<void>;
898
+ /**
899
+ * Cancel a pending destroy, transitioning back to `ready`.
900
+ *
901
+ * This exists to support React 18 StrictMode which unmounts then
902
+ * immediately re-mounts components. If the re-mount arrives while
903
+ * teardown is still in progress, cancelling prevents resource loss.
904
+ *
905
+ * @returns `true` if teardown was pending and has been cancelled.
906
+ * `false` if already torn down or not currently tearing down.
907
+ */
908
+ cancelDestroy(): boolean;
909
+ /** Sequential cleanup with per-resource timeout. */
910
+ private _performDestroy;
911
+ }
912
+ /**
913
+ * Ref-counted singleton guard keyed by `instanceId`.
914
+ *
915
+ * - `acquire()` increments the ref count (or creates the manager).
916
+ * - `release()` decrements the ref count. When it reaches 0 a
917
+ * `setTimeout(0)` is scheduled to allow React StrictMode re-mount to
918
+ * reclaim the instance before it is destroyed.
919
+ * - If a mount arrives during `TEARING_DOWN`, the teardown is cancelled
920
+ * and the manager transitions back to `READY`.
921
+ */
922
+ declare class SingletonGuard {
923
+ private static readonly _entries;
924
+ /**
925
+ * Acquire (or create) a ResourceManager for the given instanceId.
926
+ *
927
+ * @param instanceId Unique identifier for the singleton slot.
928
+ * @param factory Called to create a fresh ResourceManager when none
929
+ * exists or the previous one has been torn down.
930
+ */
931
+ static acquire(instanceId: string, factory: () => ResourceManager): ResourceManager;
932
+ /**
933
+ * Release a reference to the manager. When the ref count drops to 0 a
934
+ * `setTimeout(0)` delay is introduced before destruction so that React
935
+ * StrictMode's synchronous re-mount can reclaim the instance.
936
+ */
937
+ static release(instanceId: string): void;
938
+ /**
939
+ * Retrieve a manager by instanceId without affecting the ref count.
940
+ * Returns `undefined` if no manager exists for the given id.
941
+ */
942
+ static get(instanceId: string): ResourceManager | undefined;
943
+ }
944
+
945
+ /**
946
+ * @module @guidekit/core/dom
947
+ *
948
+ * DOM intelligence engine for the GuideKit SDK.
949
+ * Scans the current page and builds a structured PageModel that serves as
950
+ * grounding context for the LLM on every turn.
951
+ *
952
+ * Key design decisions:
953
+ * - SSR-safe: every browser API is guarded behind `typeof document/window`.
954
+ * - Privacy-first: password fields and PII patterns are never captured.
955
+ * - Budget-constrained: hard limits on node count and tree depth prevent
956
+ * runaway scans on large pages.
957
+ * - Mutation-resilient: MutationObserver is throttled and circuit-broken.
958
+ */
959
+
960
+ interface DOMScannerOptions {
961
+ rootElement?: HTMLElement;
962
+ debug?: boolean;
963
+ maxNodes?: number;
964
+ maxSections?: number;
965
+ maxDepth?: number;
966
+ }
967
+ declare class DOMScanner {
968
+ private readonly root;
969
+ private readonly debug;
970
+ private readonly maxNodes;
971
+ private readonly maxSections;
972
+ private readonly maxDepth;
973
+ private cachedModel;
974
+ private visibilityMap;
975
+ private observer;
976
+ private mutationCount;
977
+ private mutationWindowStart;
978
+ private circuitBroken;
979
+ private circuitBrokenTimer;
980
+ private debounceTimer;
981
+ private lastScanTime;
982
+ constructor(options?: DOMScannerOptions);
983
+ /** Perform a full scan and return a PageModel. */
984
+ scan(): PageModel;
985
+ /**
986
+ * Set up a MutationObserver that rescans on DOM changes.
987
+ * Returns a cleanup function to disconnect the observer.
988
+ */
989
+ observe(callback: (model: PageModel) => void): () => void;
990
+ /** Update visibility data from an IntersectionObserver. */
991
+ updateVisibility(entries: IntersectionObserverEntry[]): void;
992
+ /** Get the current cached page model. */
993
+ get currentModel(): PageModel | null;
994
+ private startObserving;
995
+ private triggerRescan;
996
+ private cleanup;
997
+ private isSectionCandidate;
998
+ private extractSections;
999
+ private buildPageSection;
1000
+ private getSectionLabel;
1001
+ private getLandmark;
1002
+ private scoreSection;
1003
+ private extractNavigation;
1004
+ private extractInteractiveElements;
1005
+ private extractForms;
1006
+ private extractFormFields;
1007
+ private extractOverlays;
1008
+ private classifyOverlay;
1009
+ private extractMeta;
1010
+ private getDepth;
1011
+ private isInViewport;
1012
+ private generateHash;
1013
+ private emptyModel;
1014
+ private log;
1015
+ }
1016
+
1017
+ /**
1018
+ * @module @guidekit/core/context
1019
+ *
1020
+ * Context manager for the GuideKit SDK.
1021
+ * Assembles the LLM system prompt from the current page model, manages
1022
+ * conversation history with automatic eviction, resolves content-map entries,
1023
+ * and persists session state across page navigations via sessionStorage.
1024
+ */
1025
+
1026
+ interface ContextManagerOptions {
1027
+ agent?: AgentConfig;
1028
+ contentMap?: ContentMapInput;
1029
+ maxTurns?: number;
1030
+ maxSessionSizeBytes?: number;
1031
+ tokenBudget?: number;
1032
+ debug?: boolean;
1033
+ }
1034
+ declare class ContextManager {
1035
+ private agent;
1036
+ private contentMap;
1037
+ private maxTurns;
1038
+ private maxSessionSizeBytes;
1039
+ private tokenBudget;
1040
+ private debug;
1041
+ private history;
1042
+ private contentCache;
1043
+ private _userPreference;
1044
+ private _quietMode;
1045
+ private _pageContext;
1046
+ constructor(options?: ContextManagerOptions);
1047
+ /**
1048
+ * Build the full system prompt from the current page model and available
1049
+ * tools. The output is capped at `tokenBudget` characters so it fits
1050
+ * comfortably inside the LLM context window alongside conversation history.
1051
+ */
1052
+ buildSystemPrompt(pageModel: PageModel, tools: ToolDefinition[]): string;
1053
+ /** Append a turn to the conversation history, enforcing size constraints. */
1054
+ addTurn(turn: ConversationTurn): void;
1055
+ /** Return a copy of the current conversation history. */
1056
+ getHistory(): ConversationTurn[];
1057
+ /** Clear all conversation history. */
1058
+ clearHistory(): void;
1059
+ /**
1060
+ * Resolve a `ContentMapEntry` for the given `sectionId`.
1061
+ *
1062
+ * - Static maps are looked up directly.
1063
+ * - Function-based maps are called with a 2-second timeout.
1064
+ * - Results are cached for 30 seconds per section ID.
1065
+ */
1066
+ getContent(sectionId: string): Promise<ContentMapEntry | null>;
1067
+ /** Replace the content map used for section lookups. Clears the cache. */
1068
+ setContentMap(contentMap: ContentMapInput): void;
1069
+ get userPreference(): 'voice' | 'text';
1070
+ set userPreference(value: 'voice' | 'text');
1071
+ get quietMode(): boolean;
1072
+ set quietMode(value: boolean);
1073
+ /** Set developer-supplied page context (merged into system prompt). */
1074
+ setPageContext(context: Record<string, unknown>): void;
1075
+ /** Get the current page context. */
1076
+ getPageContext(): Record<string, unknown>;
1077
+ /** Clear all page context. */
1078
+ clearPageContext(): void;
1079
+ /** Persist the current session state to `sessionStorage`. */
1080
+ saveSession(): void;
1081
+ /** Restore a previously persisted session from `sessionStorage`. */
1082
+ restoreSession(): SessionState | null;
1083
+ /** Build the current session state snapshot. */
1084
+ getSessionState(): SessionState;
1085
+ private buildRoleSection;
1086
+ private buildCurrentPageSection;
1087
+ private buildPageSectionsSection;
1088
+ private buildNavigationSection;
1089
+ private buildInteractiveElementsSection;
1090
+ private buildFormsSection;
1091
+ private buildViewportSection;
1092
+ private buildToolsSection;
1093
+ private buildPageContextSection;
1094
+ private buildGuidelinesSection;
1095
+ /**
1096
+ * When the assembled prompt exceeds the budget, progressively trim
1097
+ * lower-priority sections to fit.
1098
+ */
1099
+ private trimPromptToBudget;
1100
+ /**
1101
+ * Enforce `maxTurns` and `maxSessionSizeBytes` constraints on the
1102
+ * conversation history. When the history approaches 80% of `maxTurns`,
1103
+ * the oldest turns are summarised into a single recap turn.
1104
+ */
1105
+ private enforceHistoryLimits;
1106
+ /**
1107
+ * Compress the oldest half of turns into a single recap turn so the
1108
+ * context window is used more efficiently.
1109
+ */
1110
+ private summariseOldestTurns;
1111
+ /** Evict oldest turns until the serialised history fits within the byte budget. */
1112
+ private enforceByteLimit;
1113
+ private log;
1114
+ }
1115
+
1116
+ interface TokenUsage$1 {
1117
+ prompt: number;
1118
+ completion: number;
1119
+ total: number;
1120
+ }
1121
+ /**
1122
+ * Adapter that translates between GuideKit's internal types and the
1123
+ * OpenAI Chat Completions API wire format. Handles streaming via SSE,
1124
+ * tool formatting, and response parsing.
1125
+ */
1126
+ declare class OpenAIAdapter implements LLMProviderAdapter {
1127
+ private readonly apiKey;
1128
+ private readonly model;
1129
+ constructor(config: Extract<LLMConfig, {
1130
+ provider: 'openai';
1131
+ }>);
1132
+ /**
1133
+ * Convert GuideKit tool definitions into OpenAI's `tools` format.
1134
+ * Each tool is wrapped as `{ type: 'function', function: { name, description, parameters } }`.
1135
+ */
1136
+ formatTools(tools: ToolDefinition[]): unknown;
1137
+ /**
1138
+ * Convert an array of `ConversationTurn` objects into OpenAI's messages
1139
+ * format with `role: 'user' | 'assistant'`.
1140
+ */
1141
+ formatConversation(history: ConversationTurn[]): Array<{
1142
+ role: 'user' | 'assistant';
1143
+ content: string;
1144
+ }>;
1145
+ /**
1146
+ * Parse an OpenAI SSE streaming response into an async iterable of
1147
+ * `TextChunk` and `ToolCall` objects.
1148
+ *
1149
+ * The OpenAI streaming endpoint sends each chunk as a JSON object
1150
+ * prefixed by `data: `. The final line is `data: [DONE]`.
1151
+ * Text content arrives in `choices[0].delta.content` and tool calls
1152
+ * arrive in `choices[0].delta.tool_calls`.
1153
+ */
1154
+ parseResponse(stream: ReadableStream<Uint8Array>): AsyncIterable<TextChunk | ToolCall>;
1155
+ /**
1156
+ * Format a tool result so it can be sent back to OpenAI as a
1157
+ * `tool` role message with the `tool_call_id`.
1158
+ */
1159
+ formatToolResult(callId: string, result: unknown): {
1160
+ role: 'tool';
1161
+ tool_call_id: string;
1162
+ content: string;
1163
+ };
1164
+ /**
1165
+ * Build and execute a streaming request to the OpenAI Chat Completions API.
1166
+ * Returns the raw `ReadableStream` for the response body together with
1167
+ * the raw Response object.
1168
+ */
1169
+ streamRequest(params: {
1170
+ systemPrompt: string;
1171
+ contents: Array<{
1172
+ role: string;
1173
+ content: string;
1174
+ }>;
1175
+ tools?: unknown;
1176
+ signal?: AbortSignal;
1177
+ timeoutMs?: number;
1178
+ }): Promise<{
1179
+ stream: ReadableStream<Uint8Array>;
1180
+ response: Response;
1181
+ }>;
1182
+ /**
1183
+ * Extract `TextChunk` and accumulate `ToolCall` data from a single parsed
1184
+ * OpenAI SSE JSON object.
1185
+ *
1186
+ * OpenAI tool calls arrive incrementally: the first chunk for a tool call
1187
+ * carries the `id` and `function.name`, while subsequent chunks append to
1188
+ * `function.arguments`. We accumulate these in `pendingToolCalls` and only
1189
+ * yield complete `ToolCall` objects when the finish_reason is 'tool_calls'
1190
+ * or when flushed.
1191
+ */
1192
+ private extractChunks;
1193
+ /**
1194
+ * Flush all accumulated pending tool calls as complete `ToolCall` objects.
1195
+ */
1196
+ private flushPendingToolCalls;
1197
+ /**
1198
+ * Extract token usage from a parsed OpenAI response chunk.
1199
+ * Usage data typically appears in the final chunk when `stream_options`
1200
+ * includes `include_usage`, or in the non-streaming response.
1201
+ * Returns `null` if no usage data is present.
1202
+ */
1203
+ extractUsage(parsed: Record<string, unknown>): TokenUsage$1 | null;
1204
+ /**
1205
+ * Check whether a parsed OpenAI chunk indicates the response was
1206
+ * blocked by a content filter.
1207
+ *
1208
+ * OpenAI signals content filtering through:
1209
+ * - `choices[].finish_reason === 'content_filter'`
1210
+ * - `choices[].content_filter_results` with `filtered: true`
1211
+ */
1212
+ isContentFiltered(parsed: Record<string, unknown>): boolean;
1213
+ /**
1214
+ * Translate an HTTP error response from OpenAI into the appropriate
1215
+ * GuideKit error class.
1216
+ */
1217
+ private handleHttpError;
1218
+ }
1219
+
1220
+ interface TokenUsage {
1221
+ prompt: number;
1222
+ completion: number;
1223
+ total: number;
1224
+ }
1225
+ /**
1226
+ * Adapter that translates between GuideKit's internal types and the
1227
+ * Gemini REST API wire format. Handles streaming via SSE, tool formatting,
1228
+ * and response parsing.
1229
+ */
1230
+ declare class GeminiAdapter implements LLMProviderAdapter {
1231
+ private readonly apiKey;
1232
+ private readonly model;
1233
+ constructor(config: Extract<LLMConfig, {
1234
+ provider: 'gemini';
1235
+ }>);
1236
+ /**
1237
+ * Convert GuideKit tool definitions into Gemini's `functionDeclarations`
1238
+ * format, wrapped inside a `tools` array.
1239
+ */
1240
+ formatTools(tools: ToolDefinition[]): unknown;
1241
+ /**
1242
+ * Convert an array of `ConversationTurn` objects into Gemini's `contents`
1243
+ * array with `role: 'user' | 'model'`.
1244
+ */
1245
+ formatConversation(history: ConversationTurn[]): Array<{
1246
+ role: string;
1247
+ parts: Array<{
1248
+ text: string;
1249
+ }>;
1250
+ }>;
1251
+ /**
1252
+ * Parse a Gemini SSE streaming response into an async iterable of
1253
+ * `TextChunk` and `ToolCall` objects.
1254
+ *
1255
+ * The Gemini `streamGenerateContent?alt=sse` endpoint sends each chunk
1256
+ * as a JSON object prefixed by `data: `. We parse line-by-line, extract
1257
+ * text parts and function call parts, and yield the appropriate types.
1258
+ */
1259
+ parseResponse(stream: ReadableStream<Uint8Array>): AsyncIterable<TextChunk | ToolCall>;
1260
+ /**
1261
+ * Format a tool result so it can be sent back to Gemini as a
1262
+ * `functionResponse` part.
1263
+ */
1264
+ formatToolResult(callId: string, result: unknown): {
1265
+ role: string;
1266
+ parts: Array<{
1267
+ functionResponse: {
1268
+ name: string;
1269
+ response: {
1270
+ result: unknown;
1271
+ };
1272
+ };
1273
+ }>;
1274
+ };
1275
+ /**
1276
+ * Build and execute a streaming request to the Gemini API.
1277
+ * Returns the raw `ReadableStream` for the response body together with
1278
+ * a promise that resolves to token usage extracted from the final chunk.
1279
+ */
1280
+ streamRequest(params: {
1281
+ systemPrompt: string;
1282
+ contents: Array<{
1283
+ role: string;
1284
+ parts: Array<{
1285
+ text: string;
1286
+ }>;
1287
+ }>;
1288
+ tools?: unknown;
1289
+ signal?: AbortSignal;
1290
+ timeoutMs?: number;
1291
+ }): Promise<{
1292
+ stream: ReadableStream<Uint8Array>;
1293
+ response: Response;
1294
+ }>;
1295
+ /**
1296
+ * Extract `TextChunk` and `ToolCall` items from a single parsed Gemini
1297
+ * SSE JSON object.
1298
+ */
1299
+ private extractChunks;
1300
+ /**
1301
+ * Extract token usage from a parsed Gemini response chunk.
1302
+ * Returns `null` if no usage metadata is present.
1303
+ */
1304
+ extractUsage(parsed: Record<string, unknown>): TokenUsage | null;
1305
+ /**
1306
+ * Check whether a parsed Gemini chunk indicates the response was
1307
+ * blocked by a safety filter.
1308
+ */
1309
+ isContentFiltered(parsed: Record<string, unknown>): boolean;
1310
+ /**
1311
+ * Translate an HTTP error response from Gemini into the appropriate
1312
+ * GuideKit error class.
1313
+ */
1314
+ private handleHttpError;
1315
+ }
1316
+ /**
1317
+ * High-level orchestrator that manages LLM interactions for the GuideKit SDK.
1318
+ *
1319
+ * Responsibilities:
1320
+ * - Owns the active `LLMProviderAdapter` (currently only `GeminiAdapter`).
1321
+ * - Streams responses from the provider, emitting callbacks for text chunks,
1322
+ * tool calls, and token usage.
1323
+ * - Handles content filter retries: if the initial response is blocked, it
1324
+ * retries once with a stripped-down prompt (no tools).
1325
+ * - Surfaces all errors through the SDK error hierarchy.
1326
+ */
1327
+ declare class LLMOrchestrator {
1328
+ private _adapter;
1329
+ private _config;
1330
+ private readonly debug;
1331
+ private readonly callbacks;
1332
+ constructor(options: {
1333
+ config: LLMConfig;
1334
+ debug?: boolean;
1335
+ onChunk?: (chunk: TextChunk) => void;
1336
+ onToolCall?: (toolCall: ToolCall) => void;
1337
+ onTokenUsage?: (usage: TokenUsage) => void;
1338
+ onError?: (error: Error) => void;
1339
+ });
1340
+ /**
1341
+ * Send a message and stream the response from the LLM.
1342
+ *
1343
+ * Accumulates text and tool calls from the stream, invoking callbacks
1344
+ * as chunks arrive, and returns the complete result once the stream ends.
1345
+ */
1346
+ sendMessage(params: {
1347
+ systemPrompt: string;
1348
+ history: ConversationTurn[];
1349
+ userMessage: string;
1350
+ tools?: ToolDefinition[];
1351
+ signal?: AbortSignal;
1352
+ }): Promise<{
1353
+ text: string;
1354
+ toolCalls: ToolCall[];
1355
+ usage: TokenUsage;
1356
+ }>;
1357
+ /**
1358
+ * Hot-swap the LLM configuration. Creates a new adapter for the
1359
+ * updated provider/model.
1360
+ */
1361
+ updateConfig(config: LLMConfig): void;
1362
+ /** Get the current provider adapter. */
1363
+ get adapter(): LLMProviderAdapter;
1364
+ /**
1365
+ * Execute a streaming LLM request and collect the results.
1366
+ */
1367
+ private executeStream;
1368
+ /**
1369
+ * Create the appropriate adapter for the given config.
1370
+ * Currently only Gemini is implemented; other providers will be added
1371
+ * as the SDK evolves.
1372
+ */
1373
+ private createAdapter;
1374
+ /** Convenience accessor for the current provider name. */
1375
+ private get providerName();
1376
+ /** Log a debug message if debug mode is enabled. */
1377
+ private log;
1378
+ }
1379
+
1380
+ /**
1381
+ * A registered handler for a specific tool. The `name` must match the tool
1382
+ * definition's `name` field exactly.
1383
+ */
1384
+ interface ToolHandler {
1385
+ name: string;
1386
+ execute: (args: Record<string, unknown>) => Promise<unknown>;
1387
+ }
1388
+ /** Options for configuring the ToolExecutor. */
1389
+ interface ToolExecutorOptions {
1390
+ /** Max number of tool call rounds before forcing text response. Default: 5 */
1391
+ maxRounds?: number;
1392
+ /** Enable debug logging. */
1393
+ debug?: boolean;
1394
+ /** Called when a tool is about to be executed. */
1395
+ onToolCall?: (name: string, args: Record<string, unknown>) => void;
1396
+ /** Called when a tool execution completes. */
1397
+ onToolResult?: (name: string, result: unknown, durationMs: number) => void;
1398
+ /** Called when a tool execution fails. */
1399
+ onToolError?: (name: string, error: Error) => void;
1400
+ }
1401
+ /** A single executed tool call with its outcome. */
1402
+ interface ToolCallRecord {
1403
+ name: string;
1404
+ args: Record<string, unknown>;
1405
+ result: unknown;
1406
+ durationMs: number;
1407
+ error?: string;
1408
+ }
1409
+ /** Aggregated token usage across all rounds. */
1410
+ interface AggregatedUsage {
1411
+ prompt: number;
1412
+ completion: number;
1413
+ total: number;
1414
+ }
1415
+ /** The complete result of a multi-turn tool execution session. */
1416
+ interface ToolExecutionResult {
1417
+ /** The final text response from the LLM. */
1418
+ text: string;
1419
+ /** All tool calls that were executed across every round. */
1420
+ toolCallsExecuted: ToolCallRecord[];
1421
+ /** Accumulated token usage across all LLM calls. */
1422
+ totalUsage: AggregatedUsage;
1423
+ /** Number of LLM round-trips performed. */
1424
+ rounds: number;
1425
+ }
1426
+ /**
1427
+ * Manages multi-turn LLM interactions involving tool calls.
1428
+ *
1429
+ * Flow:
1430
+ * 1. Send the user message to the LLM along with available tool definitions.
1431
+ * 2. If the LLM response includes tool calls, execute them in parallel.
1432
+ * 3. Feed tool results back to the LLM as additional conversation context.
1433
+ * 4. Repeat until the LLM produces a text-only response or `maxRounds`
1434
+ * is exceeded.
1435
+ */
1436
+ declare class ToolExecutor {
1437
+ private readonly maxRounds;
1438
+ private readonly debugEnabled;
1439
+ private readonly handlers;
1440
+ private readonly onToolCallCb?;
1441
+ private readonly onToolResultCb?;
1442
+ private readonly onToolErrorCb?;
1443
+ constructor(options?: ToolExecutorOptions);
1444
+ /** Register a tool handler. Overwrites any existing handler with the same name. */
1445
+ registerTool(handler: ToolHandler): void;
1446
+ /** Unregister a tool by name. No-op if the tool is not registered. */
1447
+ unregisterTool(name: string): void;
1448
+ /** Check whether a tool handler is registered. */
1449
+ hasTool(name: string): boolean;
1450
+ /**
1451
+ * Build `ToolDefinition[]` from all registered handlers.
1452
+ *
1453
+ * Since `ToolHandler` only carries `name` and `execute`, the returned
1454
+ * definitions have empty descriptions and parameters. Callers that need
1455
+ * richer definitions should maintain their own `ToolDefinition[]` and
1456
+ * pass them directly to `executeWithTools`.
1457
+ */
1458
+ getToolDefinitions(): ToolDefinition[];
1459
+ /**
1460
+ * Execute a multi-turn conversation with tool calls.
1461
+ *
1462
+ * The method sends the initial user message to the LLM. If the LLM
1463
+ * responds with tool calls, each call is executed in parallel, the
1464
+ * results are appended to the conversation, and the updated context
1465
+ * is sent back to the LLM. This loop repeats until:
1466
+ *
1467
+ * - The LLM returns a text-only response (no tool calls), or
1468
+ * - `maxRounds` consecutive tool-calling rounds have been exhausted.
1469
+ *
1470
+ * When `maxRounds` is exceeded the executor returns whatever text the
1471
+ * LLM has produced so far (which may be empty).
1472
+ */
1473
+ executeWithTools(params: {
1474
+ llm: LLMOrchestrator;
1475
+ systemPrompt: string;
1476
+ history: ConversationTurn[];
1477
+ userMessage: string;
1478
+ tools: ToolDefinition[];
1479
+ signal?: AbortSignal;
1480
+ }): Promise<ToolExecutionResult>;
1481
+ /**
1482
+ * Execute a single tool call by looking up the registered handler and
1483
+ * invoking it. Returns the result, any error message, and the wall-clock
1484
+ * duration in milliseconds.
1485
+ */
1486
+ private executeTool;
1487
+ /**
1488
+ * Execute an array of tool calls concurrently. If the abort signal fires
1489
+ * mid-execution, already-started calls run to completion but the results
1490
+ * of all settled calls are still returned.
1491
+ */
1492
+ private executeToolCallsInParallel;
1493
+ /**
1494
+ * Convert the internal turn representation (which includes 'tool' roles
1495
+ * and assistant turns with tool call metadata) into the flat
1496
+ * `ConversationTurn[]` that `LLMOrchestrator.sendMessage` expects.
1497
+ *
1498
+ * Strategy:
1499
+ * - Standard `ConversationTurn` objects pass through unchanged.
1500
+ * - `AssistantToolCallTurn` objects are converted to an assistant turn
1501
+ * whose content describes the tool calls that were made.
1502
+ * - `ToolResultTurn` objects are converted to user turns that report
1503
+ * the tool results so the LLM can incorporate them.
1504
+ *
1505
+ * This approach works with any LLM provider since it only uses the
1506
+ * 'user' | 'assistant' role discriminator.
1507
+ */
1508
+ private flattenHistory;
1509
+ private isToolResultTurn;
1510
+ private isAssistantToolCallTurn;
1511
+ private log;
1512
+ }
1513
+
1514
+ /**
1515
+ * @module @guidekit/core/visual
1516
+ *
1517
+ * Visual Guidance System for the GuideKit SDK.
1518
+ * Provides spotlight overlays, tooltips, smooth scrolling, and guided tours
1519
+ * to visually direct users to page elements identified by the LLM.
1520
+ *
1521
+ * Key design decisions:
1522
+ * - Overlay lives on document.body (NOT Shadow DOM) so it can cover the entire page.
1523
+ * - Uses box-shadow cutout technique for the spotlight effect.
1524
+ * - Tracks element position via ResizeObserver + scroll listeners (NOT rAF polling).
1525
+ * - All text is set via textContent (never innerHTML) to prevent XSS.
1526
+ * - SSR-safe: every browser API is guarded behind typeof checks.
1527
+ * - Compositor-only animations (transform, opacity) for smooth 60fps.
1528
+ * - Respects prefers-reduced-motion.
1529
+ */
1530
+ interface VisualGuidanceOptions {
1531
+ /** Color of the spotlight overlay. Default: 'rgba(0, 0, 0, 0.5)' */
1532
+ overlayColor?: string;
1533
+ /** Color of the spotlight cutout border. Default: '#4a9eed' */
1534
+ spotlightColor?: string;
1535
+ /** Animation duration in ms. Default: 300 */
1536
+ animationDuration?: number;
1537
+ /** Padding around the highlighted element in px. Default: 8 */
1538
+ spotlightPadding?: number;
1539
+ /** Enable debug logging. Default: false */
1540
+ debug?: boolean;
1541
+ }
1542
+ interface TooltipOptions {
1543
+ text: string;
1544
+ position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';
1545
+ }
1546
+ interface SpotlightState {
1547
+ isActive: boolean;
1548
+ selector: string | null;
1549
+ sectionId: string | null;
1550
+ tooltip: string | null;
1551
+ }
1552
+ declare class VisualGuidance {
1553
+ private readonly overlayColor;
1554
+ private readonly spotlightColor;
1555
+ private readonly animationDuration;
1556
+ private readonly spotlightPadding;
1557
+ private readonly debug;
1558
+ private overlayEl;
1559
+ private spotlightEl;
1560
+ private tooltipEl;
1561
+ private liveRegionEl;
1562
+ private _state;
1563
+ private resizeObserver;
1564
+ private scrollListenerCleanups;
1565
+ private currentTargetElement;
1566
+ private tourSectionIds;
1567
+ private tourCurrentStep;
1568
+ private tourMode;
1569
+ private tourAutoTimer;
1570
+ private tourPausedByInteraction;
1571
+ private spotlightChangeCallbacks;
1572
+ private tourStepCallbacks;
1573
+ private domScanner;
1574
+ private destroyed;
1575
+ constructor(options?: VisualGuidanceOptions);
1576
+ /**
1577
+ * Highlight an element by selector or sectionId.
1578
+ * Returns true if the element was found and highlighted, false otherwise.
1579
+ */
1580
+ highlight(params: {
1581
+ sectionId?: string;
1582
+ selector?: string;
1583
+ tooltip?: string;
1584
+ position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';
1585
+ }): boolean;
1586
+ /**
1587
+ * Remove the spotlight and all associated elements.
1588
+ */
1589
+ dismissHighlight(): void;
1590
+ /**
1591
+ * Smooth scroll to a section by its sectionId.
1592
+ */
1593
+ scrollToSection(sectionId: string, offset?: number): void;
1594
+ /**
1595
+ * Smooth scroll to an element by CSS selector.
1596
+ */
1597
+ scrollToSelector(selector: string, offset?: number): void;
1598
+ /**
1599
+ * Start a guided tour through the given section IDs.
1600
+ */
1601
+ startTour(sectionIds: string[], mode?: 'auto' | 'manual'): void;
1602
+ /**
1603
+ * Move to the next tour step. No-op if no tour is active.
1604
+ */
1605
+ nextTourStep(): void;
1606
+ /**
1607
+ * Move to the previous tour step. No-op if no tour is active or at first step.
1608
+ */
1609
+ prevTourStep(): void;
1610
+ /**
1611
+ * Stop the tour and dismiss all highlights.
1612
+ */
1613
+ stopTour(): void;
1614
+ /**
1615
+ * Get the current spotlight state.
1616
+ */
1617
+ get state(): SpotlightState;
1618
+ /**
1619
+ * Get the current tour state, or null if no tour is active.
1620
+ */
1621
+ get tourState(): {
1622
+ active: boolean;
1623
+ step: number;
1624
+ total: number;
1625
+ } | null;
1626
+ /**
1627
+ * Subscribe to spotlight state changes.
1628
+ * Returns an unsubscribe function.
1629
+ */
1630
+ onSpotlightChange(callback: (state: SpotlightState) => void): () => void;
1631
+ /**
1632
+ * Subscribe to tour step events.
1633
+ * Returns an unsubscribe function.
1634
+ */
1635
+ onTourStep(callback: (step: number, total: number, sectionId: string) => void): () => void;
1636
+ /**
1637
+ * Clean up all DOM elements, observers, and event listeners.
1638
+ * After calling destroy(), the instance is unusable.
1639
+ */
1640
+ destroy(): void;
1641
+ /**
1642
+ * Resolve a target element from either a sectionId or a CSS selector.
1643
+ * If sectionId is provided, uses DOMScanner to find the section's selector.
1644
+ */
1645
+ private resolveTarget;
1646
+ /**
1647
+ * Build a CSS selector for an element, using the same priority hierarchy
1648
+ * as the DOMScanner.
1649
+ */
1650
+ private buildSelectorForElement;
1651
+ private buildStructuralPath;
1652
+ /**
1653
+ * Ensure the full-page overlay element exists on document.body.
1654
+ */
1655
+ private ensureOverlay;
1656
+ /**
1657
+ * Ensure the spotlight (cutout) element exists on document.body.
1658
+ */
1659
+ private ensureSpotlight;
1660
+ /**
1661
+ * Position the spotlight element over the target's bounding rect.
1662
+ */
1663
+ private positionSpotlight;
1664
+ /**
1665
+ * Show the overlay and spotlight with entrance animation.
1666
+ */
1667
+ private showOverlay;
1668
+ /**
1669
+ * Hide the overlay and spotlight.
1670
+ */
1671
+ private hideOverlay;
1672
+ /**
1673
+ * Show a tooltip near the target element.
1674
+ */
1675
+ private showTooltip;
1676
+ /**
1677
+ * Remove the tooltip element from the DOM.
1678
+ */
1679
+ private removeTooltip;
1680
+ /**
1681
+ * Remove aria-describedby from the current target element.
1682
+ */
1683
+ private removeAriaDescribedBy;
1684
+ /**
1685
+ * Compute the best auto-position for the tooltip relative to the target rect.
1686
+ * Preference order: bottom, top, right, left.
1687
+ */
1688
+ private computeAutoPosition;
1689
+ /**
1690
+ * Position the tooltip element relative to the target rect.
1691
+ */
1692
+ private positionTooltip;
1693
+ /**
1694
+ * Apply an arrow on the tooltip pointing toward the target element.
1695
+ * Uses a child div with CSS border triangle technique.
1696
+ */
1697
+ private applyTooltipArrow;
1698
+ /**
1699
+ * Adjust arrow horizontal position so it points toward the target center
1700
+ * even when the tooltip is clamped to viewport edges.
1701
+ */
1702
+ private adjustArrowHorizontal;
1703
+ /**
1704
+ * Set up ResizeObserver and scroll listeners to track the target element
1705
+ * and update spotlight/tooltip positions.
1706
+ */
1707
+ private setupPositionTracking;
1708
+ /**
1709
+ * Remove all tracking observers and event listeners.
1710
+ */
1711
+ private cleanupTrackingInfrastructure;
1712
+ /**
1713
+ * Update spotlight and tooltip positions based on the current target
1714
+ * element's bounding rect.
1715
+ */
1716
+ private updatePositions;
1717
+ /**
1718
+ * Scroll to an element, respecting reduced motion preferences.
1719
+ */
1720
+ private scrollToElement;
1721
+ /**
1722
+ * Execute the current tour step: scroll to and highlight the section.
1723
+ */
1724
+ private executeTourStep;
1725
+ /**
1726
+ * Schedule auto-advance to the next tour step.
1727
+ */
1728
+ private scheduleAutoAdvance;
1729
+ /**
1730
+ * Clear the auto-advance timer.
1731
+ */
1732
+ private clearAutoTimer;
1733
+ /**
1734
+ * Announce a message to screen readers via an aria-live region.
1735
+ */
1736
+ private announce;
1737
+ private notifySpotlightChange;
1738
+ /**
1739
+ * Get the transition duration, respecting prefers-reduced-motion.
1740
+ */
1741
+ private getTransitionDuration;
1742
+ /**
1743
+ * Debug logger.
1744
+ */
1745
+ private log;
1746
+ }
1747
+
1748
+ /** A message held for replay once connectivity is restored. */
1749
+ interface QueuedMessage {
1750
+ content: string;
1751
+ timestamp: number;
1752
+ pageUrl: string;
1753
+ }
1754
+ interface ConnectionManagerOptions {
1755
+ /** Server endpoint for lightweight health-check pings. */
1756
+ healthEndpoint?: string;
1757
+ /** When `true`, diagnostic messages are logged to the console. */
1758
+ debug?: boolean;
1759
+ }
1760
+ type StateChangeCallback = (state: ConnectionState, previous: ConnectionState) => void;
1761
+ /**
1762
+ * Monitors network connectivity and exposes a reactive {@link ConnectionState}.
1763
+ *
1764
+ * Strategy:
1765
+ * 1. Listen to `window.online` / `window.offline` events (coarse signal).
1766
+ * 2. Periodically ping the configured `healthEndpoint` (fine-grained signal).
1767
+ * 3. Compute a rolling average of the last {@link ROLLING_WINDOW} ping
1768
+ * latencies to detect degraded connections (> {@link DEGRADED_THRESHOLD_MS}).
1769
+ * 4. When fully offline (`navigator.onLine === false`), suspend pinging and
1770
+ * wait for the browser's `online` event before resuming.
1771
+ *
1772
+ * All browser APIs are gated behind `typeof window !== 'undefined'` so the
1773
+ * class can be safely imported (though not meaningfully used) in SSR contexts.
1774
+ */
1775
+ declare class ConnectionManager {
1776
+ private readonly healthEndpoint;
1777
+ private readonly debugEnabled;
1778
+ private _state;
1779
+ private _running;
1780
+ /** Rolling window of recent ping latencies (ms). */
1781
+ private readonly pingLatencies;
1782
+ /** Queued messages awaiting replay on reconnect. */
1783
+ private readonly messageQueue;
1784
+ /** Registered state-change subscribers. */
1785
+ private readonly subscribers;
1786
+ /** Timer handle for the periodic ping loop. */
1787
+ private pingTimer;
1788
+ /** Bound event handlers (stored for deterministic removal). */
1789
+ private readonly handleOnline;
1790
+ private readonly handleOffline;
1791
+ constructor(options?: ConnectionManagerOptions);
1792
+ /** Current connection state. */
1793
+ get state(): ConnectionState;
1794
+ /**
1795
+ * Start monitoring connectivity.
1796
+ *
1797
+ * Attaches browser event listeners and begins the periodic ping loop.
1798
+ * Calling `start()` when already running is a no-op.
1799
+ */
1800
+ start(): void;
1801
+ /**
1802
+ * Stop monitoring connectivity.
1803
+ *
1804
+ * Removes all event listeners, clears timers, and resets internal state.
1805
+ */
1806
+ stop(): void;
1807
+ /**
1808
+ * Subscribe to connection state changes.
1809
+ *
1810
+ * @returns An unsubscribe function. Calling it more than once is safe.
1811
+ */
1812
+ onStateChange(callback: StateChangeCallback): () => void;
1813
+ /**
1814
+ * Queue a message for replay once the connection is restored.
1815
+ *
1816
+ * The queue is capped at {@link MAX_QUEUE_SIZE} messages. When the cap is
1817
+ * exceeded the oldest message is discarded.
1818
+ */
1819
+ queueMessage(message: QueuedMessage): void;
1820
+ /**
1821
+ * Drain the message queue and return its contents.
1822
+ *
1823
+ * Messages whose `pageUrl` no longer matches the current browser URL are
1824
+ * silently discarded (the user has navigated away since queueing).
1825
+ */
1826
+ drainQueue(): QueuedMessage[];
1827
+ /**
1828
+ * Force an immediate connectivity check.
1829
+ *
1830
+ * @returns The updated {@link ConnectionState} after the check completes.
1831
+ */
1832
+ checkNow(): Promise<ConnectionState>;
1833
+ private onBrowserOnline;
1834
+ private onBrowserOffline;
1835
+ /**
1836
+ * Execute a single health-check ping and update state accordingly.
1837
+ */
1838
+ private ping;
1839
+ /**
1840
+ * Record a latency sample, keeping only the last {@link ROLLING_WINDOW}
1841
+ * entries.
1842
+ */
1843
+ private recordLatency;
1844
+ /** Compute the arithmetic mean of recorded latencies. */
1845
+ private rollingAverage;
1846
+ /**
1847
+ * Schedule the next ping according to the current state's interval.
1848
+ *
1849
+ * When in the `offline` state, pinging is suspended entirely — the
1850
+ * manager waits for the browser's `online` event to resume.
1851
+ */
1852
+ private schedulePing;
1853
+ private clearPingTimer;
1854
+ /**
1855
+ * Transition to a new state, notifying subscribers if the state actually
1856
+ * changed.
1857
+ */
1858
+ private transition;
1859
+ /** Return the current page URL, or an empty string in SSR contexts. */
1860
+ private getCurrentUrl;
1861
+ /** Conditional debug logging. */
1862
+ private log;
1863
+ }
1864
+
1865
+ interface NavigationControllerOptions {
1866
+ debug?: boolean;
1867
+ /** Developer-provided router for guaranteed SPA navigation. */
1868
+ router?: {
1869
+ push: (href: string) => void | Promise<void>;
1870
+ };
1871
+ }
1872
+ /**
1873
+ * Manages SPA navigation detection and programmatic routing.
1874
+ *
1875
+ * - Prefers the Navigation API (Chrome 102+) where available.
1876
+ * - Falls back to `popstate` + periodic URL polling (200ms).
1877
+ * - Developer can pass a `router` prop for guaranteed SPA nav.
1878
+ */
1879
+ declare class NavigationController {
1880
+ private readonly debug;
1881
+ private readonly router?;
1882
+ private currentUrl;
1883
+ private pollingTimer;
1884
+ private callbacks;
1885
+ private cleanups;
1886
+ constructor(options?: NavigationControllerOptions);
1887
+ /** Start listening for navigation events. */
1888
+ start(): void;
1889
+ /** Stop listening for navigation events. */
1890
+ stop(): void;
1891
+ /**
1892
+ * Subscribe to route changes.
1893
+ * @returns Unsubscribe function.
1894
+ */
1895
+ onRouteChange(callback: (from: string, to: string) => void): () => void;
1896
+ /**
1897
+ * Programmatically navigate to a URL.
1898
+ * Validates same-origin before navigating.
1899
+ */
1900
+ navigate(href: string): Promise<boolean>;
1901
+ /** Get the current URL. */
1902
+ get url(): string;
1903
+ private handleRouteChange;
1904
+ }
1905
+
1906
+ interface AwarenessOptions {
1907
+ bus: EventBus;
1908
+ rootElement?: HTMLElement;
1909
+ idleTimeoutMs?: number;
1910
+ dwellTimeoutMs?: number;
1911
+ rageClickThreshold?: number;
1912
+ rageClickWindowMs?: number;
1913
+ debug?: boolean;
1914
+ }
1915
+ interface AwarenessState {
1916
+ scrollPercent: number;
1917
+ scrollDirection: 'up' | 'down' | 'none';
1918
+ focusedSectionId: string | null;
1919
+ focusedSectionDwellMs: number;
1920
+ isIdle: boolean;
1921
+ lastInteractionAt: number;
1922
+ visibleSections: Map<string, number>;
1923
+ }
1924
+ /**
1925
+ * Observes user interactions with the page and emits structured awareness
1926
+ * events on the shared {@link EventBus}.
1927
+ *
1928
+ * All browser API usage is gated behind `typeof window !== 'undefined'` so
1929
+ * the module can be safely imported in SSR contexts.
1930
+ */
1931
+ declare class AwarenessSystem {
1932
+ private readonly bus;
1933
+ private readonly rootElement;
1934
+ private readonly idleTimeoutMs;
1935
+ private readonly dwellTimeoutMs;
1936
+ private readonly rageClickThreshold;
1937
+ private readonly rageClickWindowMs;
1938
+ private readonly debugEnabled;
1939
+ private running;
1940
+ /** AbortController whose signal is passed to every addEventListener call. */
1941
+ private abortController;
1942
+ /** IntersectionObserver for section visibility tracking. */
1943
+ private sectionObserver;
1944
+ /** Section id -> current visibility ratio. */
1945
+ private readonly visibleSections;
1946
+ private scrollPercent;
1947
+ private scrollDirection;
1948
+ private lastScrollY;
1949
+ private scrollRafPending;
1950
+ private focusedSectionId;
1951
+ private focusedSectionSince;
1952
+ private dwellTimer;
1953
+ private dwellEmitted;
1954
+ private lastInteractionAt;
1955
+ private idleTimer;
1956
+ private isIdle;
1957
+ private readonly recentClicks;
1958
+ private lastMouseMoveAt;
1959
+ constructor(options: AwarenessOptions);
1960
+ /** Begin observing user behavior. No-op if already running or in SSR. */
1961
+ start(): void;
1962
+ /** Stop all observers and listeners. */
1963
+ stop(): void;
1964
+ /** Alias for {@link stop}. */
1965
+ destroy(): void;
1966
+ /** Return a snapshot of the current awareness state. */
1967
+ getState(): AwarenessState;
1968
+ private readonly handleScroll;
1969
+ private readonly handleMouseMove;
1970
+ private readonly handleClick;
1971
+ private readonly handleInteraction;
1972
+ private recordInteraction;
1973
+ private scheduleIdleTimer;
1974
+ private clearIdleTimer;
1975
+ /**
1976
+ * Periodically (every 1s) check whether the user has been focused on the
1977
+ * same section long enough to trigger a dwell event.
1978
+ */
1979
+ private readonly checkDwell;
1980
+ private clearDwellTimer;
1981
+ private initSectionObserver;
1982
+ /**
1983
+ * Query the DOM for observable sections and start observing them.
1984
+ */
1985
+ private observeSections;
1986
+ /**
1987
+ * Derive a stable string identifier for a DOM element used as a section.
1988
+ *
1989
+ * Priority: `data-guidekit-target` > `id` > tagName.
1990
+ */
1991
+ private getSectionId;
1992
+ /**
1993
+ * Build a simple CSS selector string for an element, suitable for
1994
+ * inclusion in rage-click events.
1995
+ */
1996
+ private buildSelector;
1997
+ /** Conditional debug logging. */
1998
+ private log;
1999
+ }
2000
+
2001
+ interface ProactiveOptions {
2002
+ bus: EventBus;
2003
+ debug?: boolean;
2004
+ /** Callback invoked whenever a proactive trigger fires. */
2005
+ onTrigger?: (trigger: ProactiveTrigger) => void;
2006
+ }
2007
+ type ProactiveTriggerType = 'greeting' | 'idle-help' | 'dwell-commentary' | 'navigation-commentary' | 'frustration' | 'form-abandonment';
2008
+ interface ProactiveTrigger {
2009
+ type: ProactiveTriggerType;
2010
+ sectionId?: string;
2011
+ selector?: string;
2012
+ /** Suggested context message for the LLM. */
2013
+ message?: string;
2014
+ timestamp: number;
2015
+ }
2016
+ declare class ProactiveTriggerEngine {
2017
+ private readonly bus;
2018
+ private readonly debug;
2019
+ private readonly onTrigger?;
2020
+ /** Collected unsubscribe functions from bus.on(). */
2021
+ private unsubs;
2022
+ /** Cooldown map: trigger key → last-fired timestamp. */
2023
+ private cooldowns;
2024
+ /** Progressive dwell: sectionId → number of times triggered. */
2025
+ private dwellCounts;
2026
+ /** Track forms the user started interacting with. */
2027
+ private formTimers;
2028
+ /** Track sections where frustration already fired (once per section). */
2029
+ private frustrationFired;
2030
+ /** Track whether idle-help has fired on this page. */
2031
+ private idleFiredThisPage;
2032
+ private _quietMode;
2033
+ private started;
2034
+ constructor(options: ProactiveOptions);
2035
+ get quietMode(): boolean;
2036
+ set quietMode(value: boolean);
2037
+ /** Subscribe to bus events and check for first-visit greeting. */
2038
+ start(): void;
2039
+ /** Unsubscribe all bus listeners and clear internal state. */
2040
+ stop(): void;
2041
+ /** Alias for {@link stop}. */
2042
+ destroy(): void;
2043
+ /**
2044
+ * Notify the engine about a route change.
2045
+ * Called from the NavigationController or externally.
2046
+ */
2047
+ onRouteChange(from: string, to: string): void;
2048
+ /**
2049
+ * Notify the engine that the user started interacting with a form.
2050
+ * If the user does not continue within {@link FORM_ABANDON_MS}, a
2051
+ * `form-abandonment` trigger fires (once per form).
2052
+ */
2053
+ onFormInteractionStart(formSelector: string): void;
2054
+ /** Reset all cooldowns and internal tracking state (useful for testing). */
2055
+ resetCooldowns(): void;
2056
+ private checkFirstVisitGreeting;
2057
+ private handleIdle;
2058
+ private handleDwell;
2059
+ private handleRageClick;
2060
+ private handleNavigation;
2061
+ /**
2062
+ * Handler for the bus `dom:route-change` event.
2063
+ * Delegates to the shared navigation logic.
2064
+ */
2065
+ private handleDomRouteChange;
2066
+ /**
2067
+ * Fire a trigger if quiet mode is off, recording the cooldown timestamp.
2068
+ */
2069
+ private fireTrigger;
2070
+ private isCooldownActive;
2071
+ }
2072
+
2073
+ interface RateLimits {
2074
+ maxLLMCallsPerMinute?: number;
2075
+ maxSTTMinutesPerSession?: number;
2076
+ maxTTSCharsPerSession?: number;
2077
+ }
2078
+ interface RateLimiterOptions {
2079
+ bus?: EventBus;
2080
+ limits?: RateLimits;
2081
+ debug?: boolean;
2082
+ }
2083
+ interface RateLimiterState {
2084
+ llmCallsInWindow: number;
2085
+ sttMinutesUsed: number;
2086
+ ttsCharsUsed: number;
2087
+ llmWindowStart: number;
2088
+ }
2089
+ declare class RateLimiter {
2090
+ private readonly bus;
2091
+ private readonly debug;
2092
+ private maxLLMCallsPerMinute;
2093
+ private maxSTTMinutesPerSession;
2094
+ private maxTTSCharsPerSession;
2095
+ private llmCallTimestamps;
2096
+ private sttMs;
2097
+ private sttStartedAt;
2098
+ private ttsChars;
2099
+ constructor(options?: RateLimiterOptions);
2100
+ /**
2101
+ * Check whether an LLM call is allowed. If allowed, records the call.
2102
+ * Throws `ResourceExhaustedError` if the limit is exceeded.
2103
+ */
2104
+ checkLLMCall(): void;
2105
+ /** Call when STT streaming starts. */
2106
+ sttStart(): void;
2107
+ /** Call when STT streaming stops. Accumulates duration. */
2108
+ sttStop(): void;
2109
+ /**
2110
+ * Check whether STT streaming is within limits.
2111
+ * Throws `ResourceExhaustedError` if exceeded.
2112
+ */
2113
+ checkSTT(): void;
2114
+ /** Current STT minutes used (including active stream). */
2115
+ private get sttMinutesUsed();
2116
+ /**
2117
+ * Record TTS character usage. Throws `ResourceExhaustedError` if limit exceeded.
2118
+ */
2119
+ checkTTS(charCount: number): void;
2120
+ /** Get the current rate limiter state for monitoring. */
2121
+ getState(): RateLimiterState;
2122
+ /** Update limits at runtime. */
2123
+ setLimits(limits: RateLimits): void;
2124
+ /** Reset all counters (e.g., for testing or new session). */
2125
+ reset(): void;
2126
+ private emitError;
2127
+ private log;
2128
+ }
2129
+
2130
+ interface TokenData {
2131
+ token: string;
2132
+ expiresAt: number;
2133
+ expiresIn: number;
2134
+ fetchedAt: number;
2135
+ }
2136
+ interface TokenManagerOptions {
2137
+ tokenEndpoint: string;
2138
+ instanceId: string;
2139
+ bus: EventBus;
2140
+ debug?: boolean;
2141
+ }
2142
+ declare class TokenManager {
2143
+ private readonly endpoint;
2144
+ private readonly instanceId;
2145
+ private readonly bus;
2146
+ private readonly debug;
2147
+ private _token;
2148
+ private _refreshTimer;
2149
+ private _isLeader;
2150
+ private _bc;
2151
+ private _destroyed;
2152
+ constructor(options: TokenManagerOptions);
2153
+ /** Current token string, or null if not yet fetched. */
2154
+ get token(): string | null;
2155
+ /** Current token data, or null if not yet fetched. */
2156
+ get tokenData(): TokenData | null;
2157
+ /** Whether this tab is the leader for token refresh. */
2158
+ get isLeader(): boolean;
2159
+ /**
2160
+ * Initialize the token manager: elect leader, fetch initial token,
2161
+ * schedule auto-refresh.
2162
+ */
2163
+ start(): Promise<void>;
2164
+ /**
2165
+ * Force a token refresh, regardless of TTL.
2166
+ */
2167
+ refresh(): Promise<void>;
2168
+ /**
2169
+ * Clean up timers, BroadcastChannel, and release leader.
2170
+ */
2171
+ destroy(): void;
2172
+ private fetchToken;
2173
+ private scheduleRefresh;
2174
+ private scheduleExpiredCheck;
2175
+ private setupBroadcastChannel;
2176
+ private readonly _tabId;
2177
+ private electLeader;
2178
+ private broadcastToken;
2179
+ private get storageKey();
2180
+ private saveToStorage;
2181
+ private loadFromStorage;
2182
+ private isExpired;
2183
+ private log;
2184
+ }
2185
+
2186
+ export { type AgentConfig, type AgentState, type AggregatedUsage, AuthenticationError, type AwarenessOptions, type AwarenessState, AwarenessSystem, type BeforeLLMCallContext, BrowserSupportError, ConfigurationError, ConnectionManager, type ConnectionManagerOptions, type ConnectionState, ContentFilterError, type ContentMap, type ContentMapEntry, type ContentMapFunction, type ContentMapInput, ContextManager, type ContextManagerOptions, type ConversationTurn, type CreateSessionTokenOptions, DOMScanner, type DOMScannerOptions, type ErrorCode, ErrorCodes, EventBus, type EventMap, type FormField, type FormSummary, GeminiAdapter, GuideKitCore, type GuideKitCoreOptions, GuideKitError, type GuideKitErrorOptions, type GuideKitErrorType, type GuideKitEvent, type GuideKitOptions, type GuideKitProviderProps, type GuideKitStore, type GuideKitTheme, type HealthCheckResult, type HealthCheckStatus, I18n, type I18nOptions, type I18nStrings, InitializationError, type InteractiveElement, type LLMConfig, LLMOrchestrator, type LLMProviderAdapter, type LocaleInput, type NavItem, NavigationController, type NavigationControllerOptions, NetworkError, OpenAIAdapter, type OverlayElement, type PageModel, type PageSection, PermissionError, type ProactiveOptions, type ProactiveTrigger, ProactiveTriggerEngine, type ProactiveTriggerType, type Provider, type QueuedMessage, RateLimitError, RateLimiter, type RateLimiterOptions, type RateLimiterState, type RateLimits, type Resource, ResourceExhaustedError, ResourceManager, type ResourceManagerState, type STTConfig, type ScanMetadata, type SessionState, SingletonGuard, type SpotlightState, type SupportedLocale, type TTSConfig, type TextChunk, TimeoutError, type TokenData, TokenManager, type TokenManagerOptions, type TokenPayload, type TokenResponse, type ToolCall, type ToolCallRecord, type ToolDefinition, type ToolExecutionResult, ToolExecutor, type ToolExecutorOptions, type ToolHandler, type TooltipOptions, VisualGuidance, type VisualGuidanceOptions, createEventBus, isGuideKitError };