@fiodos/web-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/LICENSE +77 -0
  2. package/dist/cjs/adapters/webNavigationAdapter.d.ts +31 -0
  3. package/dist/cjs/adapters/webNavigationAdapter.js +45 -0
  4. package/dist/cjs/adapters/webStorageAdapter.d.ts +13 -0
  5. package/dist/cjs/adapters/webStorageAdapter.js +57 -0
  6. package/dist/cjs/adapters/webVoiceAdapter.d.ts +16 -0
  7. package/dist/cjs/adapters/webVoiceAdapter.js +477 -0
  8. package/dist/cjs/api/backendClient.d.ts +31 -0
  9. package/dist/cjs/api/backendClient.js +182 -0
  10. package/dist/cjs/api/backendTelemetry.d.ts +23 -0
  11. package/dist/cjs/api/backendTelemetry.js +80 -0
  12. package/dist/cjs/api/clientBootstrap.d.ts +44 -0
  13. package/dist/cjs/api/clientBootstrap.js +68 -0
  14. package/dist/cjs/api/errors.d.ts +11 -0
  15. package/dist/cjs/api/errors.js +16 -0
  16. package/dist/cjs/bridge/createBridge.d.ts +13 -0
  17. package/dist/cjs/bridge/createBridge.js +15 -0
  18. package/dist/cjs/config/types.d.ts +63 -0
  19. package/dist/cjs/config/types.js +9 -0
  20. package/dist/cjs/context/screenContextStore.d.ts +26 -0
  21. package/dist/cjs/context/screenContextStore.js +25 -0
  22. package/dist/cjs/controller/AgentController.d.ts +115 -0
  23. package/dist/cjs/controller/AgentController.js +594 -0
  24. package/dist/cjs/core/turnEngine.d.ts +70 -0
  25. package/dist/cjs/core/turnEngine.js +96 -0
  26. package/dist/cjs/dropin/createFiodosAgent.d.ts +60 -0
  27. package/dist/cjs/dropin/createFiodosAgent.js +143 -0
  28. package/dist/cjs/dropin/createFyodosAgent.d.ts +60 -0
  29. package/dist/cjs/dropin/createFyodosAgent.js +143 -0
  30. package/dist/cjs/index.d.ts +45 -0
  31. package/dist/cjs/index.js +67 -0
  32. package/dist/cjs/orb/mountOrb.d.ts +24 -0
  33. package/dist/cjs/orb/mountOrb.js +694 -0
  34. package/dist/cjs/orb/orbView.d.ts +56 -0
  35. package/dist/cjs/orb/orbView.js +426 -0
  36. package/dist/cjs/orb/publishedConfig.d.ts +32 -0
  37. package/dist/cjs/orb/publishedConfig.js +70 -0
  38. package/dist/cjs/package.json +1 -0
  39. package/dist/cjs/speech/speechSession.d.ts +35 -0
  40. package/dist/cjs/speech/speechSession.js +60 -0
  41. package/dist/cjs/ui/messages.d.ts +36 -0
  42. package/dist/cjs/ui/messages.js +41 -0
  43. package/dist/esm/adapters/webNavigationAdapter.d.ts +31 -0
  44. package/dist/esm/adapters/webNavigationAdapter.js +41 -0
  45. package/dist/esm/adapters/webStorageAdapter.d.ts +13 -0
  46. package/dist/esm/adapters/webStorageAdapter.js +54 -0
  47. package/dist/esm/adapters/webVoiceAdapter.d.ts +16 -0
  48. package/dist/esm/adapters/webVoiceAdapter.js +474 -0
  49. package/dist/esm/api/backendClient.d.ts +31 -0
  50. package/dist/esm/api/backendClient.js +178 -0
  51. package/dist/esm/api/backendTelemetry.d.ts +23 -0
  52. package/dist/esm/api/backendTelemetry.js +77 -0
  53. package/dist/esm/api/clientBootstrap.d.ts +44 -0
  54. package/dist/esm/api/clientBootstrap.js +63 -0
  55. package/dist/esm/api/errors.d.ts +11 -0
  56. package/dist/esm/api/errors.js +11 -0
  57. package/dist/esm/bridge/createBridge.d.ts +13 -0
  58. package/dist/esm/bridge/createBridge.js +12 -0
  59. package/dist/esm/config/types.d.ts +63 -0
  60. package/dist/esm/config/types.js +6 -0
  61. package/dist/esm/context/screenContextStore.d.ts +26 -0
  62. package/dist/esm/context/screenContextStore.js +22 -0
  63. package/dist/esm/controller/AgentController.d.ts +115 -0
  64. package/dist/esm/controller/AgentController.js +590 -0
  65. package/dist/esm/core/turnEngine.d.ts +70 -0
  66. package/dist/esm/core/turnEngine.js +92 -0
  67. package/dist/esm/dropin/createFiodosAgent.d.ts +60 -0
  68. package/dist/esm/dropin/createFiodosAgent.js +140 -0
  69. package/dist/esm/dropin/createFyodosAgent.d.ts +60 -0
  70. package/dist/esm/dropin/createFyodosAgent.js +140 -0
  71. package/dist/esm/index.d.ts +45 -0
  72. package/dist/esm/index.js +38 -0
  73. package/dist/esm/orb/mountOrb.d.ts +24 -0
  74. package/dist/esm/orb/mountOrb.js +691 -0
  75. package/dist/esm/orb/orbView.d.ts +56 -0
  76. package/dist/esm/orb/orbView.js +421 -0
  77. package/dist/esm/orb/publishedConfig.d.ts +32 -0
  78. package/dist/esm/orb/publishedConfig.js +67 -0
  79. package/dist/esm/package.json +1 -0
  80. package/dist/esm/speech/speechSession.d.ts +35 -0
  81. package/dist/esm/speech/speechSession.js +57 -0
  82. package/dist/esm/ui/messages.d.ts +36 -0
  83. package/dist/esm/ui/messages.js +38 -0
  84. package/package.json +38 -0
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Default Fiodos telemetry adapter (web) — identical wire contract to the
3
+ * React / React Native ones. Maps the SDK's agent events to the backend's
4
+ * privacy-safe usage events and ships them to POST /v1/agent/events.
5
+ *
6
+ * Privacy: ONLY the event type, the action intent and an opaque session id
7
+ * leave the browser. Never any message, transcript or context content.
8
+ */
9
+ import type { TelemetryAdapter } from '@fiodos/core';
10
+ export interface FiodosTelemetryOptions {
11
+ baseUrl: string;
12
+ /** Client API key sent as x-api-key (same contract as the backend client). */
13
+ apiKey?: string;
14
+ /** End-user id sent as x-user-id (rate-limit correlation). */
15
+ getUserId?: () => string | null;
16
+ /** Extra headers merged into every request. */
17
+ headers?: Record<string, string>;
18
+ /** Max ms to buffer events before flushing (default 4000). */
19
+ flushIntervalMs?: number;
20
+ /** Max events buffered before an immediate flush (default 20). */
21
+ maxBatch?: number;
22
+ }
23
+ export declare function createFiodosTelemetry(options: FiodosTelemetryOptions): TelemetryAdapter;
@@ -0,0 +1,77 @@
1
+ function mapEvent(params) {
2
+ const intent = params.intentDetected ?? null;
3
+ const sessionId = params.sessionId ?? null;
4
+ switch (params.eventType) {
5
+ case 'agent_session_started':
6
+ return [{ type: 'session', session_id: sessionId }];
7
+ case 'action_executed': {
8
+ const events = [{ type: 'action', intent, session_id: sessionId }];
9
+ const confirmed = params.actionExecuted != null &&
10
+ params.actionExecuted.confirmed === true;
11
+ if (confirmed) {
12
+ events.push({ type: 'confirmation_completed', intent, session_id: sessionId });
13
+ }
14
+ return events;
15
+ }
16
+ case 'action_confirmation_requested':
17
+ return [{ type: 'confirmation_requested', intent, session_id: sessionId }];
18
+ default:
19
+ return [];
20
+ }
21
+ }
22
+ export function createFiodosTelemetry(options) {
23
+ const baseUrl = options.baseUrl.replace(/\/$/, '');
24
+ const flushIntervalMs = options.flushIntervalMs ?? 4000;
25
+ const maxBatch = options.maxBatch ?? 20;
26
+ let queue = [];
27
+ let timer = null;
28
+ function buildHeaders() {
29
+ const userId = options.getUserId?.();
30
+ return {
31
+ 'Content-Type': 'application/json',
32
+ ...(options.apiKey ? { 'x-api-key': options.apiKey } : {}),
33
+ ...(userId ? { 'x-user-id': userId } : {}),
34
+ ...(options.headers ?? {}),
35
+ };
36
+ }
37
+ function flush() {
38
+ if (timer) {
39
+ clearTimeout(timer);
40
+ timer = null;
41
+ }
42
+ if (queue.length === 0)
43
+ return;
44
+ const batch = queue;
45
+ queue = [];
46
+ void (async () => {
47
+ try {
48
+ await fetch(`${baseUrl}/v1/agent/events`, {
49
+ method: 'POST',
50
+ headers: buildHeaders(),
51
+ body: JSON.stringify({ events: batch }),
52
+ });
53
+ }
54
+ catch {
55
+ /* drop — analytics are best-effort */
56
+ }
57
+ })();
58
+ }
59
+ function scheduleFlush() {
60
+ if (timer)
61
+ return;
62
+ timer = setTimeout(flush, flushIntervalMs);
63
+ }
64
+ return {
65
+ logEvent(params) {
66
+ const mapped = mapEvent(params);
67
+ if (mapped.length === 0)
68
+ return;
69
+ for (const ev of mapped)
70
+ queue.push(ev);
71
+ if (queue.length >= maxBatch)
72
+ flush();
73
+ else
74
+ scheduleFlush();
75
+ },
76
+ };
77
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Client self-bootstrap helpers — the web equivalent of what @fiodos/react's
3
+ * <FiodosAgent/> does internally:
4
+ *
5
+ * 1. fetchClientManifest() → GET /v1/client/manifest (by x-api-key)
6
+ * so a drop-in never forces the developer to paste the manifest JSON.
7
+ * 2. sendOrbSeen() → POST /v1/client/orb-seen (by x-api-key)
8
+ * the heartbeat the dashboard "Conexión" step waits on to prove the orb
9
+ * actually booted inside the running app (not merely that a manifest was
10
+ * published). Every web binding (Vue/Svelte/Angular) inherits this through
11
+ * createFiodosAgent, so the dashboard detects the orb on ALL of them.
12
+ *
13
+ * No client source code is ever sent — only the API key header.
14
+ */
15
+ import type { AppManifest } from '@fiodos/core';
16
+ /**
17
+ * Default public Fiodos backend, mirrored from @fiodos/react's DEFAULT_API_URL.
18
+ * A drop-in that only receives an apiKey talks to this unless apiUrl is given.
19
+ */
20
+ export declare const DEFAULT_WEB_API_URL = "https://api.fyodos.com";
21
+ export type ManifestBootstrapStatus = 'ready' | 'no-manifest';
22
+ export interface ManifestBootstrapResult {
23
+ status: ManifestBootstrapStatus;
24
+ manifest: AppManifest | null;
25
+ }
26
+ /**
27
+ * Fetch the published manifest by API key. Throws a descriptive Error on a
28
+ * rejected key / network failure so a silent orb is never a mystery (same
29
+ * philosophy as the React drop-in). Returns `{ status: 'no-manifest' }` when
30
+ * the project exists but nothing has been published yet.
31
+ */
32
+ export declare function fetchClientManifest(opts: {
33
+ baseUrl: string;
34
+ apiKey: string;
35
+ }): Promise<ManifestBootstrapResult>;
36
+ /**
37
+ * Best-effort heartbeat proving the orb booted. Never throws and never blocks
38
+ * the orb — failures are swallowed (the dashboard simply won't flip to ✓).
39
+ */
40
+ export declare function sendOrbSeen(opts: {
41
+ baseUrl: string;
42
+ apiKey: string;
43
+ platform?: string;
44
+ }): Promise<void>;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Default public Fiodos backend, mirrored from @fiodos/react's DEFAULT_API_URL.
3
+ * A drop-in that only receives an apiKey talks to this unless apiUrl is given.
4
+ */
5
+ export const DEFAULT_WEB_API_URL = 'https://api.fyodos.com';
6
+ function trimUrl(baseUrl) {
7
+ return baseUrl.replace(/\/$/, '');
8
+ }
9
+ /**
10
+ * Fetch the published manifest by API key. Throws a descriptive Error on a
11
+ * rejected key / network failure so a silent orb is never a mystery (same
12
+ * philosophy as the React drop-in). Returns `{ status: 'no-manifest' }` when
13
+ * the project exists but nothing has been published yet.
14
+ */
15
+ export async function fetchClientManifest(opts) {
16
+ const baseUrl = trimUrl(opts.baseUrl);
17
+ if (!opts.apiKey) {
18
+ throw new Error('[fyodos] A drop-in agent requires an apiKey. Set it to the project key ' +
19
+ 'from your Fiodos dashboard (e.g. VITE_FYODOS_API_KEY).');
20
+ }
21
+ const res = await fetch(`${baseUrl}/v1/client/manifest`, {
22
+ method: 'GET',
23
+ headers: { 'x-api-key': opts.apiKey },
24
+ });
25
+ if (!res.ok) {
26
+ if (res.status === 401) {
27
+ throw new Error(`[fyodos] The orb did not load: the API key was rejected (HTTP 401) by ${baseUrl}. ` +
28
+ 'Check that your FYODOS API key matches the current project key in the dashboard ' +
29
+ '(a deleted/recreated project gets a NEW key).');
30
+ }
31
+ throw new Error(`[fyodos] The orb did not load: could not fetch the manifest (HTTP ${res.status}) from ${baseUrl}.`);
32
+ }
33
+ const data = (await res.json());
34
+ if (!data.manifest) {
35
+ return { status: 'no-manifest', manifest: null };
36
+ }
37
+ return { status: 'ready', manifest: data.manifest };
38
+ }
39
+ function detectPlatform() {
40
+ if (typeof navigator !== 'undefined' && /Mobi|Android|iPhone|iPad/i.test(navigator.userAgent)) {
41
+ return 'web-mobile';
42
+ }
43
+ return 'web';
44
+ }
45
+ /**
46
+ * Best-effort heartbeat proving the orb booted. Never throws and never blocks
47
+ * the orb — failures are swallowed (the dashboard simply won't flip to ✓).
48
+ */
49
+ export async function sendOrbSeen(opts) {
50
+ if (!opts.apiKey)
51
+ return;
52
+ const baseUrl = trimUrl(opts.baseUrl);
53
+ try {
54
+ await fetch(`${baseUrl}/v1/client/orb-seen`, {
55
+ method: 'POST',
56
+ headers: { 'Content-Type': 'application/json', 'x-api-key': opts.apiKey },
57
+ body: JSON.stringify({ platform: opts.platform ?? detectPlatform() }),
58
+ });
59
+ }
60
+ catch {
61
+ /* heartbeat is best-effort; never block the orb on it */
62
+ }
63
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Typed agent API errors — shared by every web framework binding. Identical
3
+ * contract to @fiodos/react's errors so the orchestrator can branch on codes.
4
+ */
5
+ export type AgentApiErrorCode = 'timeout' | 'cancelled' | 'network' | 'unauthorized' | 'rate_limited' | 'quota_exceeded' | 'not_found' | 'server_error' | 'invalid_response' | 'unknown';
6
+ export declare class AgentApiError extends Error {
7
+ readonly code: AgentApiErrorCode;
8
+ readonly status?: number;
9
+ constructor(code: AgentApiErrorCode, message?: string, status?: number);
10
+ }
11
+ export declare function isAgentApiError(value: unknown): value is AgentApiError;
@@ -0,0 +1,11 @@
1
+ export class AgentApiError extends Error {
2
+ constructor(code, message, status) {
3
+ super(message ?? code);
4
+ this.name = 'AgentApiError';
5
+ this.code = code;
6
+ this.status = status;
7
+ }
8
+ }
9
+ export function isAgentApiError(value) {
10
+ return value instanceof AgentApiError;
11
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Bridge pattern — connect SDK action handlers to app state that lives in a
3
+ * framework's reactive store (Pinia, Svelte stores, Angular services…), which
4
+ * cannot be referenced from a plain handler function. Framework-agnostic.
5
+ */
6
+ export interface Bridge<T extends object> {
7
+ /** Debug name surfaced in error messages. */
8
+ readonly name: string;
9
+ set(impl: T | null): void;
10
+ /** Current implementation, or null if the app has not registered it yet. */
11
+ get(): T | null;
12
+ }
13
+ export declare function createBridge<T extends object>(name?: string): Bridge<T>;
@@ -0,0 +1,12 @@
1
+ export function createBridge(name = 'bridge') {
2
+ let current = null;
3
+ return {
4
+ name,
5
+ set(impl) {
6
+ current = impl;
7
+ },
8
+ get() {
9
+ return current;
10
+ },
11
+ };
12
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Web SDK configuration — the single place where a web app plugs everything in.
3
+ * Mirrors @fiodos/react's FiodosWebAgentConfig (same adapters, same lifecycle).
4
+ * Shared by every framework binding through the AgentController.
5
+ */
6
+ import type { ActionRegistries, AgentBackendClient, AgentMessages, AppManifest, ConfirmationLexicon, MessageCatalog, NavigationAdapter, Sanitizer, StorageAdapter, TelemetryAdapter, VoiceAdapter } from '@fiodos/core';
7
+ import type { ResolveUiMessagesOptions, WebUiMessages } from '../ui/messages.js';
8
+ export type AgentPhase = 'idle' | 'listening' | 'thinking' | 'speaking' | 'confirming';
9
+ export interface AgentTimings {
10
+ /** Watchdog: 'thinking' may never outlive this. */
11
+ thinkingWatchdogMs: number;
12
+ /** Hard cap on a listening session (seconds). */
13
+ maxListeningSeconds: number;
14
+ /** Voice-confirmation listening window after speaking the question. */
15
+ confirmationVoiceWindowMs: number;
16
+ /** Transcripts shorter than this are treated as noise. */
17
+ minTranscriptChars: number;
18
+ }
19
+ export declare const DEFAULT_AGENT_TIMINGS: AgentTimings;
20
+ export type TurnGateVerdict = {
21
+ ok: true;
22
+ } | {
23
+ ok: false;
24
+ message?: string;
25
+ };
26
+ export interface FiodosWebAgentConfig {
27
+ /** The app manifest (validated with validateManifest on mount). */
28
+ manifest: AppManifest;
29
+ /** Agent locale (reply language, message catalogs). MANDATORY. */
30
+ locale: string;
31
+ /** Speech recognition locale, e.g. 'en-US', 'es-ES'. MANDATORY. */
32
+ sttLocale: string;
33
+ /** Device-TTS fallback locale. Defaults to sttLocale. */
34
+ ttsLocale?: string;
35
+ navigation: NavigationAdapter;
36
+ registries: ActionRegistries;
37
+ backend: AgentBackendClient;
38
+ voice: VoiceAdapter;
39
+ storage: StorageAdapter;
40
+ telemetry?: TelemetryAdapter;
41
+ /** Host auth check, required by manifest actions declaring requiresAuth. */
42
+ isAuthenticated?: () => boolean;
43
+ messages?: {
44
+ catalogs?: Record<string, MessageCatalog>;
45
+ overrides?: Partial<AgentMessages>;
46
+ };
47
+ uiMessages?: ResolveUiMessagesOptions;
48
+ confirmationLexicon?: ConfirmationLexicon;
49
+ getUserContextText?: () => string | null;
50
+ sanitizer?: Sanitizer;
51
+ contextMaxChars?: number;
52
+ routeContextFallback?: (route: string | null) => string | null;
53
+ gateTurn?: () => TurnGateVerdict;
54
+ onTurnCompleted?: () => void;
55
+ onPhaseChange?: (phase: AgentPhase, previous: AgentPhase) => void;
56
+ /** Error surface. Default: console.error. The orb also shows a transient note. */
57
+ notifyError?: (message: string) => void;
58
+ onQuotaExceeded?: () => void;
59
+ ttsVoice?: string | (() => string | undefined);
60
+ consentVersion?: number;
61
+ timings?: Partial<AgentTimings>;
62
+ }
63
+ export type { WebUiMessages };
@@ -0,0 +1,6 @@
1
+ export const DEFAULT_AGENT_TIMINGS = {
2
+ thinkingWatchdogMs: 25000,
3
+ maxListeningSeconds: 60,
4
+ confirmationVoiceWindowMs: 8000,
5
+ minTranscriptChars: 2,
6
+ };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Screen-context store — screens register WHAT IS VISIBLE while mounted; the
3
+ * agent reads it lazily when a turn is invoked. Framework-agnostic (the same
4
+ * store the React/React Native bindings use).
5
+ */
6
+ import type { AgentScreenContext } from '@fiodos/core';
7
+ export interface AgentScreenSnapshot {
8
+ /** App-defined tag of the screen type (free string, for telemetry/debug). */
9
+ kind: string;
10
+ /** Pre-formatted context text for the LLM (the app's own language/wording). */
11
+ text: string;
12
+ /** Structured snapshot used by 'execute' actions (target ids, etc.). */
13
+ context?: AgentScreenContext;
14
+ }
15
+ export interface ScreenContextStore {
16
+ set(ownerId: symbol, snapshot: AgentScreenSnapshot): void;
17
+ clear(ownerId: symbol): void;
18
+ /** Registered text, or the route fallback, or null. */
19
+ getText(): string | null;
20
+ /** Structured snapshot or null. */
21
+ getSnapshot(): AgentScreenSnapshot | null;
22
+ }
23
+ export declare function createScreenContextStore(options: {
24
+ getCurrentRoute: () => string | null;
25
+ routeFallback?: (route: string | null) => string | null;
26
+ }): ScreenContextStore;
@@ -0,0 +1,22 @@
1
+ export function createScreenContextStore(options) {
2
+ let entry = null;
3
+ return {
4
+ set(ownerId, snapshot) {
5
+ entry = { ownerId, snapshot };
6
+ },
7
+ clear(ownerId) {
8
+ if (entry?.ownerId === ownerId)
9
+ entry = null;
10
+ },
11
+ getText() {
12
+ const registered = entry?.snapshot.text?.trim();
13
+ if (registered)
14
+ return registered;
15
+ const fallback = options.routeFallback?.(options.getCurrentRoute())?.trim();
16
+ return fallback || null;
17
+ },
18
+ getSnapshot() {
19
+ return entry?.snapshot ?? null;
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * AgentController — the framework-free orchestrator.
3
+ *
4
+ * This is the vanilla port of @fiodos/react's `useAgent` hook: it assembles the
5
+ * @fiodos/core runtime (executor, consent, sanitizer, telemetry, messages,
6
+ * lexicon, conversation) ONCE, drives the listen → think → (confirm) → speak
7
+ * state machine, and exposes its state through a `subscribe` listener and
8
+ * imperative methods. Every framework binding (Vue, Svelte, Angular) wraps the
9
+ * SAME controller, so the security and reasoning behaviour is identical across
10
+ * frameworks and matches React / React Native.
11
+ *
12
+ * Security invariants (unchanged from the shared core):
13
+ * - The MANIFEST decides what needs confirmation, never the LLM.
14
+ * - Strict (payment-grade) confirmations still require the exact phrase or a
15
+ * deliberate modal tap; a loose "yes" never confirms them.
16
+ * - The agent only ever executes actions declared in the manifest.
17
+ */
18
+ import { type AgentMessages, type ConfirmationLexicon } from '@fiodos/core';
19
+ import { type ScreenContextStore } from '../context/screenContextStore.js';
20
+ import { type AgentPhase, type FiodosWebAgentConfig } from '../config/types.js';
21
+ import { type WebUiMessages } from '../ui/messages.js';
22
+ export interface AgentExchange {
23
+ userText: string;
24
+ replyText: string;
25
+ }
26
+ /** The reactive snapshot every framework binding renders. */
27
+ export interface AgentState {
28
+ phase: AgentPhase;
29
+ interimText: string;
30
+ volumeLevel: number;
31
+ showWaveform: boolean;
32
+ showThinking: boolean;
33
+ isBusy: boolean;
34
+ isListening: boolean;
35
+ lastExchange: AgentExchange | null;
36
+ /** Confirmation question to show in the modal, or null. */
37
+ confirmationMessage: string | null;
38
+ /** Visible-only hint for strict actions (the exact phrase), or null. */
39
+ confirmationVoiceHint: string | null;
40
+ consentModalVisible: boolean;
41
+ /** Mic denied/unusable: the orb should fall back to the keyboard channel. */
42
+ voiceBlocked: boolean;
43
+ }
44
+ export declare class AgentController {
45
+ readonly config: FiodosWebAgentConfig;
46
+ readonly messages: AgentMessages;
47
+ readonly ui: WebUiMessages;
48
+ readonly lexicon: ConfirmationLexicon;
49
+ readonly screenStore: ScreenContextStore;
50
+ private readonly sanitizer;
51
+ private readonly telemetry;
52
+ private readonly consent;
53
+ private readonly executor;
54
+ private readonly timings;
55
+ private readonly ttsLocale;
56
+ private readonly speech;
57
+ private readonly notifyError;
58
+ private enabled;
59
+ private phase;
60
+ private lastExchange;
61
+ private confirmationMessage;
62
+ private confirmationVoiceHint;
63
+ private consentModalVisible;
64
+ private readonly sessionId;
65
+ private sessionStarted;
66
+ private readonly conversation;
67
+ private pending;
68
+ private confirmationReasked;
69
+ private confirmationVoiceActive;
70
+ private silentTurn;
71
+ private voiceBlocked;
72
+ private abort;
73
+ private watchdog;
74
+ private confirmWindow;
75
+ private pendingConsentIntent;
76
+ private readonly listeners;
77
+ private unsubscribeSpeech;
78
+ constructor(config: FiodosWebAgentConfig);
79
+ getState(): AgentState;
80
+ /** Whether speech recognition can actually run (API present AND mic not denied). */
81
+ get voiceAvailable(): boolean;
82
+ /** Unlock audio playback inside a user gesture (orb tap) so the spoken reply
83
+ * is allowed/audible on mobile browsers. Must be called synchronously from
84
+ * the tap handler, before any await. No-op where unnecessary. */
85
+ primeAudio(): void;
86
+ /** Flag the mic as denied/unusable (called on a permission error or upfront
87
+ * permission detection) so the orb routes taps to the keyboard instead. */
88
+ markVoiceBlocked(blocked: boolean): void;
89
+ subscribe(listener: (state: AgentState) => void): () => void;
90
+ private emit;
91
+ setEnabled(value: boolean): void;
92
+ private getTtsVoice;
93
+ private setPhase;
94
+ private clearWatchdog;
95
+ private clearConfirmWindow;
96
+ private speakReply;
97
+ private beginConfirmationVoiceWindow;
98
+ confirmPendingAction(): Promise<void>;
99
+ cancelPendingAction(): void;
100
+ private handleConfirmationTranscript;
101
+ private handleTranscript;
102
+ private onTranscript;
103
+ private onSpeechError;
104
+ private beginListening;
105
+ toggleListening(): Promise<void>;
106
+ submitTextTurn(text: string, options?: {
107
+ speak?: boolean;
108
+ }): Promise<void>;
109
+ acceptConsent(): Promise<void>;
110
+ declineConsent(): void;
111
+ cancelAll(): void;
112
+ /** Best-effort backend warm-up (cold-start mitigation). */
113
+ warmUp(): void;
114
+ dispose(): void;
115
+ }