@mosaicoo/svg-engine 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.
- package/LICENSE +201 -0
- package/NOTICE +21 -0
- package/README.md +249 -0
- package/fesm2022/mosaicoo-svg-engine-ai-nlu-ui.mjs +459 -0
- package/fesm2022/mosaicoo-svg-engine-ai-nlu-voice-wasm.mjs +1 -0
- package/fesm2022/mosaicoo-svg-engine-ai-nlu.mjs +11 -0
- package/fesm2022/mosaicoo-svg-engine-core.mjs +3 -0
- package/fesm2022/mosaicoo-svg-engine-edit.mjs +2292 -0
- package/fesm2022/mosaicoo-svg-engine-io.mjs +47 -0
- package/fesm2022/mosaicoo-svg-engine-optimize.mjs +1 -0
- package/fesm2022/mosaicoo-svg-engine-render.mjs +301 -0
- package/fesm2022/mosaicoo-svg-engine-ui.mjs +14236 -0
- package/fesm2022/mosaicoo-svg-engine.mjs +1 -0
- package/package.json +105 -0
- package/types/mosaicoo-svg-engine-ai-nlu-ui.d.ts +416 -0
- package/types/mosaicoo-svg-engine-ai-nlu-voice-wasm.d.ts +175 -0
- package/types/mosaicoo-svg-engine-ai-nlu.d.ts +1834 -0
- package/types/mosaicoo-svg-engine-core.d.ts +5139 -0
- package/types/mosaicoo-svg-engine-edit.d.ts +11922 -0
- package/types/mosaicoo-svg-engine-io.d.ts +476 -0
- package/types/mosaicoo-svg-engine-optimize.d.ts +183 -0
- package/types/mosaicoo-svg-engine-render.d.ts +628 -0
- package/types/mosaicoo-svg-engine-ui.d.ts +6861 -0
- package/types/mosaicoo-svg-engine.d.ts +30 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const E="0.1.0";export{E as SVG_ENGINE_VERSION};
|
package/package.json
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mosaicoo/svg-engine",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "Headless-first, plugin-extensible SVG editor library for Angular v21+. Render, manipulate and optimize SVG inside any Angular app — 9 secondary entry points (core/render/io/optimize/edit/ui + ai/nlu + ai/nlu-ui + ai/nlu-voice-wasm), Material UI is opt-in and local Whisper voice is opt-in.",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"svg",
|
|
10
|
+
"svg-editor",
|
|
11
|
+
"svg-renderer",
|
|
12
|
+
"svg-optimizer",
|
|
13
|
+
"vector",
|
|
14
|
+
"vector-graphics",
|
|
15
|
+
"angular",
|
|
16
|
+
"angular-library",
|
|
17
|
+
"ng-packagr",
|
|
18
|
+
"headless",
|
|
19
|
+
"plugin",
|
|
20
|
+
"pathfinder",
|
|
21
|
+
"anchor-editor"
|
|
22
|
+
],
|
|
23
|
+
"author": "Mosaicoo",
|
|
24
|
+
"license": "Apache-2.0",
|
|
25
|
+
"homepage": "https://github.com/mosaicoo/svg-engine#readme",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/mosaicoo/svg-engine/issues"
|
|
28
|
+
},
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/mosaicoo/svg-engine.git",
|
|
32
|
+
"directory": "projects/svg-engine"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@angular/common": "^21.2.0",
|
|
36
|
+
"@angular/core": "^21.2.0",
|
|
37
|
+
"@angular/material": "^21.2.0",
|
|
38
|
+
"@angular/cdk": "^21.2.0",
|
|
39
|
+
"@huggingface/transformers": "^4.2.0"
|
|
40
|
+
},
|
|
41
|
+
"peerDependenciesMeta": {
|
|
42
|
+
"@angular/material": {
|
|
43
|
+
"optional": true
|
|
44
|
+
},
|
|
45
|
+
"@angular/cdk": {
|
|
46
|
+
"optional": true
|
|
47
|
+
},
|
|
48
|
+
"@huggingface/transformers": {
|
|
49
|
+
"optional": true
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"polygon-clipping": "^0.15.7",
|
|
54
|
+
"tslib": "^2.3.0"
|
|
55
|
+
},
|
|
56
|
+
"sideEffects": false,
|
|
57
|
+
"module": "fesm2022/mosaicoo-svg-engine.mjs",
|
|
58
|
+
"typings": "types/mosaicoo-svg-engine.d.ts",
|
|
59
|
+
"exports": {
|
|
60
|
+
"./package.json": {
|
|
61
|
+
"default": "./package.json"
|
|
62
|
+
},
|
|
63
|
+
".": {
|
|
64
|
+
"types": "./types/mosaicoo-svg-engine.d.ts",
|
|
65
|
+
"default": "./fesm2022/mosaicoo-svg-engine.mjs"
|
|
66
|
+
},
|
|
67
|
+
"./ai/nlu": {
|
|
68
|
+
"types": "./types/mosaicoo-svg-engine-ai-nlu.d.ts",
|
|
69
|
+
"default": "./fesm2022/mosaicoo-svg-engine-ai-nlu.mjs"
|
|
70
|
+
},
|
|
71
|
+
"./ai/nlu-ui": {
|
|
72
|
+
"types": "./types/mosaicoo-svg-engine-ai-nlu-ui.d.ts",
|
|
73
|
+
"default": "./fesm2022/mosaicoo-svg-engine-ai-nlu-ui.mjs"
|
|
74
|
+
},
|
|
75
|
+
"./ai/nlu-voice-wasm": {
|
|
76
|
+
"types": "./types/mosaicoo-svg-engine-ai-nlu-voice-wasm.d.ts",
|
|
77
|
+
"default": "./fesm2022/mosaicoo-svg-engine-ai-nlu-voice-wasm.mjs"
|
|
78
|
+
},
|
|
79
|
+
"./core": {
|
|
80
|
+
"types": "./types/mosaicoo-svg-engine-core.d.ts",
|
|
81
|
+
"default": "./fesm2022/mosaicoo-svg-engine-core.mjs"
|
|
82
|
+
},
|
|
83
|
+
"./edit": {
|
|
84
|
+
"types": "./types/mosaicoo-svg-engine-edit.d.ts",
|
|
85
|
+
"default": "./fesm2022/mosaicoo-svg-engine-edit.mjs"
|
|
86
|
+
},
|
|
87
|
+
"./io": {
|
|
88
|
+
"types": "./types/mosaicoo-svg-engine-io.d.ts",
|
|
89
|
+
"default": "./fesm2022/mosaicoo-svg-engine-io.mjs"
|
|
90
|
+
},
|
|
91
|
+
"./optimize": {
|
|
92
|
+
"types": "./types/mosaicoo-svg-engine-optimize.d.ts",
|
|
93
|
+
"default": "./fesm2022/mosaicoo-svg-engine-optimize.mjs"
|
|
94
|
+
},
|
|
95
|
+
"./render": {
|
|
96
|
+
"types": "./types/mosaicoo-svg-engine-render.d.ts",
|
|
97
|
+
"default": "./fesm2022/mosaicoo-svg-engine-render.mjs"
|
|
98
|
+
},
|
|
99
|
+
"./ui": {
|
|
100
|
+
"types": "./types/mosaicoo-svg-engine-ui.d.ts",
|
|
101
|
+
"default": "./fesm2022/mosaicoo-svg-engine-ui.mjs"
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"type": "module"
|
|
105
|
+
}
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { Signal } from '@angular/core';
|
|
3
|
+
import { VoiceEngine, NluCandidate, NluExecuteResult, NaturalLanguageService, LlmIntentResolverService } from '@mosaicoo/svg-engine/ai/nlu';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* **`VoiceEngineService`** — orquestrador de voz com engine
|
|
7
|
+
* **selecionável pelo usuário** (D-046 voz híbrida).
|
|
8
|
+
*
|
|
9
|
+
* Expõe a MESMA surface de um {@link VoiceProvider}
|
|
10
|
+
* (`isSupported`/`listening`/`lastError`/`listen`/`stop`) para o
|
|
11
|
+
* `<svge-nlu-input>` consumir de forma transparente, mas internamente
|
|
12
|
+
* delega para:
|
|
13
|
+
* - **Web Speech** ({@link VoiceRecognitionService}) — sempre presente.
|
|
14
|
+
* - **Whisper local** (via {@link VOICE_WHISPER_PROVIDER}) — opcional,
|
|
15
|
+
* só quando o app chamou `provideWhisperVoiceEngine()`.
|
|
16
|
+
*
|
|
17
|
+
* **Modos** ({@link VoiceEngine}):
|
|
18
|
+
* - `'web-speech'`: usa só a Web Speech API.
|
|
19
|
+
* - `'whisper'`: usa só o Whisper local (offline).
|
|
20
|
+
* - `'auto'`: tenta Web Speech e, em **falha** (ex.: `network`),
|
|
21
|
+
* cai automaticamente para o Whisper. Só fica disponível quando as
|
|
22
|
+
* duas engines existem.
|
|
23
|
+
*
|
|
24
|
+
* O `lastError` é **próprio** do orquestrador (não espelha os providers
|
|
25
|
+
* diretamente): zera no início de cada `listen()` e só é setado quando
|
|
26
|
+
* a tentativa realmente falha — assim um erro `network` do Web Speech
|
|
27
|
+
* não fica "preso" na UI após um fallback Whisper bem-sucedido.
|
|
28
|
+
*/
|
|
29
|
+
declare class VoiceEngineService {
|
|
30
|
+
private readonly webSpeech;
|
|
31
|
+
/** Provider Whisper, se o app registrou; senão `null`. */
|
|
32
|
+
private readonly whisper;
|
|
33
|
+
private readonly _engine;
|
|
34
|
+
/** Engine atualmente selecionada. */
|
|
35
|
+
readonly engine: Signal<VoiceEngine>;
|
|
36
|
+
/** `true` se a voz local (Whisper) está registrada. */
|
|
37
|
+
readonly whisperAvailable: Signal<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Engines disponíveis (suportadas no ambiente atual). `'auto'` só
|
|
40
|
+
* aparece quando as duas engines básicas existem. A UI mostra o
|
|
41
|
+
* seletor apenas quando há mais de uma opção.
|
|
42
|
+
*/
|
|
43
|
+
readonly availableEngines: Signal<readonly VoiceEngine[]>;
|
|
44
|
+
/** `false` quando nenhuma engine está disponível (UI esconde o mic). */
|
|
45
|
+
readonly isSupported: Signal<boolean>;
|
|
46
|
+
/** `true` enquanto qualquer provider está capturando/processando. */
|
|
47
|
+
readonly listening: Signal<boolean>;
|
|
48
|
+
/** `true` durante o carregamento do modelo Whisper (primeira vez). */
|
|
49
|
+
readonly modelLoading: Signal<boolean>;
|
|
50
|
+
private readonly _lastError;
|
|
51
|
+
/** Último erro do orquestrador (limpo a cada `listen` bem-sucedido). */
|
|
52
|
+
readonly lastError: Signal<string | null>;
|
|
53
|
+
constructor();
|
|
54
|
+
/** Troca a engine ativa. Ignora valores não disponíveis no ambiente. */
|
|
55
|
+
setEngine(engine: VoiceEngine): void;
|
|
56
|
+
/**
|
|
57
|
+
* Inicia a captura na engine selecionada e resolve com a transcrição.
|
|
58
|
+
* Em `'auto'`, tenta Web Speech e cai para o Whisper se falhar.
|
|
59
|
+
*/
|
|
60
|
+
listen(lang?: string, options?: {
|
|
61
|
+
readonly timeoutMs?: number;
|
|
62
|
+
}): Promise<string>;
|
|
63
|
+
/** Encerra a captura ativa em ambos os providers (seguro se inativos). */
|
|
64
|
+
stop(): void;
|
|
65
|
+
/** Executa um provider único, propagando o erro para `_lastError`. */
|
|
66
|
+
private runProvider;
|
|
67
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<VoiceEngineService, never>;
|
|
68
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<VoiceEngineService>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Opção de idioma de voz exibida no seletor. */
|
|
72
|
+
interface VoiceLanguageOption {
|
|
73
|
+
/** BCP-47 (Web Speech usa direto; Whisper mapeia p/ nome do idioma). */
|
|
74
|
+
readonly code: string;
|
|
75
|
+
/** Rótulo completo no menu. */
|
|
76
|
+
readonly label: string;
|
|
77
|
+
/** Rótulo curto (chip/tooltip). */
|
|
78
|
+
readonly short: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* **`<svge-nlu-input>`** — D-046 Fase 1 UI surface.
|
|
82
|
+
*
|
|
83
|
+
* Input textual + voice button para enviar comandos em linguagem
|
|
84
|
+
* natural ao {@link NaturalLanguageService}. Mostra:
|
|
85
|
+
*
|
|
86
|
+
* - Campo de texto Material outlined + prefix icon (smart_toy)
|
|
87
|
+
* - **Mic button** (Web Speech API) com pulse animation enquanto grava
|
|
88
|
+
* - **Run button** (Enter também dispara)
|
|
89
|
+
* - **Live preview** do top candidate (label + confidence% + bar colorida)
|
|
90
|
+
* - **Status** do último execute (success / rejeição com motivo humano)
|
|
91
|
+
* - **Botão "Confirmar"** quando rejection é destructive ou low-confidence
|
|
92
|
+
* — usuário aprova explicitamente em vez de ficar travado
|
|
93
|
+
* - **Lista de alternativas** clicável (cada click respeita threshold +
|
|
94
|
+
* destructive via `nlu.executeCandidate`)
|
|
95
|
+
*
|
|
96
|
+
* **Por que `window.confirm` default e não Material dialog**: zero
|
|
97
|
+
* dependência circular `nlu-ui → ui` (D-017-style isolation entre
|
|
98
|
+
* camadas AI e dialogs Material). Consumer pode override via input
|
|
99
|
+
* `confirmGate` se quiser dialog próprio.
|
|
100
|
+
*
|
|
101
|
+
* **Multi-editor (D-042/D-043)**: passa `{ injector: this.hostInjector }`
|
|
102
|
+
* para `executeCandidate`/`execute` — handlers resolvem services do
|
|
103
|
+
* scope ativo automaticamente.
|
|
104
|
+
*
|
|
105
|
+
* **Acessibilidade**:
|
|
106
|
+
* - Input ARIA-described com hint do top candidate
|
|
107
|
+
* - Mic button: `aria-pressed` reativo
|
|
108
|
+
* - Lista de alternatives: `role="listbox"` + `role="option"` + `aria-selected="false"`
|
|
109
|
+
* - Status com `aria-live="polite"`
|
|
110
|
+
*/
|
|
111
|
+
declare class SvgeNluInput {
|
|
112
|
+
/** Label do input (Material outline). Default em PT. */
|
|
113
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
114
|
+
/** Placeholder textual. Default exemplo PT. */
|
|
115
|
+
readonly placeholder: _angular_core.InputSignal<string>;
|
|
116
|
+
/**
|
|
117
|
+
* BCP-47 language tag pra voice recognition. Default `pt-BR`.
|
|
118
|
+
*
|
|
119
|
+
* **D-046 review-10 (M14)**: quando `autoDetectLanguage = true`,
|
|
120
|
+
* o componente sobreescreve esse default usando `detectLanguage(text)`
|
|
121
|
+
* (PT/EN). Override manual deste input sempre tem prioridade.
|
|
122
|
+
*/
|
|
123
|
+
readonly voiceLang: _angular_core.InputSignal<string>;
|
|
124
|
+
/**
|
|
125
|
+
* **D-046 review-10 (M14)**: auto-detecta idioma do input via
|
|
126
|
+
* dicionários PT/EN (hits count). Quando `true`, passa o resultado
|
|
127
|
+
* pra `voice.listen()` em vez de `voiceLang()` estático.
|
|
128
|
+
*
|
|
129
|
+
* Útil pra apps que aceitam PT E EN sem o user trocar config manual.
|
|
130
|
+
*/
|
|
131
|
+
readonly autoDetectLanguage: _angular_core.InputSignal<boolean>;
|
|
132
|
+
/**
|
|
133
|
+
* **D-046 review-10 (M5)**: debounce em ms antes de rodar `parse()`.
|
|
134
|
+
* Default 0 (sem debounce — mantém comportamento Fase 1).
|
|
135
|
+
* Recomendado `150` pra voice input rápido (~6 keystrokes/s).
|
|
136
|
+
* Acima de 300 fica perceptível pro user.
|
|
137
|
+
*/
|
|
138
|
+
readonly parseDebounceMs: _angular_core.InputSignal<number>;
|
|
139
|
+
/**
|
|
140
|
+
* Confidence mínima pra auto-execute. Abaixo disso, o componente
|
|
141
|
+
* **não** dispara automaticamente — mostra "Confirmar" pra usuário
|
|
142
|
+
* aprovar explicitamente, OU rejeita se gate não aprovar.
|
|
143
|
+
*/
|
|
144
|
+
readonly autoExecuteThreshold: _angular_core.InputSignal<number>;
|
|
145
|
+
/**
|
|
146
|
+
* Gate de confirmação customizado. Quando ausente (default), usa
|
|
147
|
+
* **`window.confirm`** nativo — funciona sem dependência extra, é
|
|
148
|
+
* universal, e dispensa abrir Material dialog (privacy + zero
|
|
149
|
+
* coupling com `svg-engine/ui`).
|
|
150
|
+
*
|
|
151
|
+
* Override pra integrar com Material dialog próprio ou tela custom:
|
|
152
|
+
* ```ts
|
|
153
|
+
* <svge-nlu-input [confirmGate]="myDialogGate" />
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* O gate recebe o candidate (com `intent.id`, `intent.destructive`,
|
|
157
|
+
* `confidence`, `slots`) e retorna `boolean | Promise<boolean>`.
|
|
158
|
+
*/
|
|
159
|
+
readonly confirmGate: _angular_core.InputSignal<((candidate: NluCandidate) => boolean | Promise<boolean>) | null>;
|
|
160
|
+
/**
|
|
161
|
+
* **D-093** — habilita o **fallback LLM**: quando o NLU rule-based não
|
|
162
|
+
* reconhece o pedido (`no-match`), escala para o
|
|
163
|
+
* {@link LlmIntentResolverService}, que pede um plano de comandos ao LLM
|
|
164
|
+
* e o executa pelo mesmo pipeline seguro. Só dispara se um provider LLM
|
|
165
|
+
* estiver registrado (`AI_CHAT_PROVIDER`); senão é no-op. Default `true`.
|
|
166
|
+
*/
|
|
167
|
+
readonly enableLlmFallback: _angular_core.InputSignal<boolean>;
|
|
168
|
+
/**
|
|
169
|
+
* **D-093** — modelo a usar no fallback LLM (roteamento por
|
|
170
|
+
* complexidade). `null` = usa o default do provider. O consumer pode
|
|
171
|
+
* passar `qwen2.5:7b` para pedidos pesados, por exemplo.
|
|
172
|
+
*/
|
|
173
|
+
readonly llmModel: _angular_core.InputSignal<string | null>;
|
|
174
|
+
/** Evento emitido após cada execute (sucesso ou rejeição). */
|
|
175
|
+
readonly executed: _angular_core.OutputEmitterRef<NluExecuteResult>;
|
|
176
|
+
protected readonly nlu: NaturalLanguageService;
|
|
177
|
+
protected readonly llm: LlmIntentResolverService;
|
|
178
|
+
protected readonly voice: VoiceEngineService;
|
|
179
|
+
private readonly hostInjector;
|
|
180
|
+
private readonly textInputRef;
|
|
181
|
+
protected readonly text: _angular_core.WritableSignal<string>;
|
|
182
|
+
/**
|
|
183
|
+
* **D-046 review-10 (M5)**: signal debouncado pra reduzir parse rate.
|
|
184
|
+
* Quando `parseDebounceMs=0`, sempre igual a `text()`. Caso contrário,
|
|
185
|
+
* só atualiza após o delay sem mudanças (typing burst absorve).
|
|
186
|
+
*/
|
|
187
|
+
protected readonly debouncedText: _angular_core.WritableSignal<string>;
|
|
188
|
+
private debounceHandle;
|
|
189
|
+
protected readonly lastResult: _angular_core.WritableSignal<NluExecuteResult | null>;
|
|
190
|
+
/** **D-093** — `true` enquanto o fallback LLM está interpretando (spinner). */
|
|
191
|
+
protected readonly llmThinking: _angular_core.WritableSignal<boolean>;
|
|
192
|
+
/** **D-093** — mensagem de erro do fallback LLM (rede / JSON inválido / sem comandos). */
|
|
193
|
+
protected readonly llmError: _angular_core.WritableSignal<string | null>;
|
|
194
|
+
/**
|
|
195
|
+
* **D-094 — modo de geração do LLM.** `'catalog'` (default) escala para o
|
|
196
|
+
* resolver de **intents** (o LLM devolve um plano de comandos já
|
|
197
|
+
* registrados); `'raw-svg'` pede um **SVG completo** e o desenha no canvas
|
|
198
|
+
* (sem catálogo). Trocável pelo usuário no menu de configuração da IA.
|
|
199
|
+
*/
|
|
200
|
+
protected readonly llmMode: _angular_core.WritableSignal<"catalog" | "raw-svg">;
|
|
201
|
+
/**
|
|
202
|
+
* **D-094 — modelo escolhido pelo usuário** no seletor (`null` = usa o
|
|
203
|
+
* default do provider). Tem prioridade sobre o input {@link llmModel}.
|
|
204
|
+
*/
|
|
205
|
+
protected readonly selectedModel: _angular_core.WritableSignal<string | null>;
|
|
206
|
+
/** **D-094 — modelos disponíveis** descobertos no backend (Ollama /api/tags). */
|
|
207
|
+
protected readonly availableModels: _angular_core.WritableSignal<readonly string[]>;
|
|
208
|
+
/**
|
|
209
|
+
* **D-094/D-095** — opções do seletor de modelo: funde os modelos
|
|
210
|
+
* **descobertos** ao vivo (`/api/tags`, instalados de fato) com os
|
|
211
|
+
* **curados** ({@link LlmIntentResolverService.suggestedModels} — ex.: os
|
|
212
|
+
* `qwen2.5-coder`) e garante o default do provider na lista, tudo
|
|
213
|
+
* deduplicado. Os curados servem de fallback quando a descoberta falha.
|
|
214
|
+
*/
|
|
215
|
+
protected readonly modelOptions: _angular_core.Signal<readonly string[]>;
|
|
216
|
+
/**
|
|
217
|
+
* **D-094** — modelo que **de fato** será usado na próxima chamada:
|
|
218
|
+
* seleção do usuário › input `llmModel` › default do provider. Usado no
|
|
219
|
+
* seletor (checkmark) e como rótulo no tooltip.
|
|
220
|
+
*/
|
|
221
|
+
protected readonly effectiveModel: _angular_core.Signal<string | null>;
|
|
222
|
+
constructor();
|
|
223
|
+
/**
|
|
224
|
+
* **D-094** — carrega a lista de modelos do backend (Ollama `/api/tags`)
|
|
225
|
+
* para o seletor. Best-effort: backend offline ou sem suporte a listagem
|
|
226
|
+
* mantém a lista vazia (o seletor cai no default do provider).
|
|
227
|
+
*/
|
|
228
|
+
private loadModels;
|
|
229
|
+
/** **D-094** — troca o modo de geração do LLM (catálogo ↔ SVG livre). */
|
|
230
|
+
protected setLlmMode(mode: 'catalog' | 'raw-svg'): void;
|
|
231
|
+
/** **D-094** — seleciona o modelo do seletor (override do default). */
|
|
232
|
+
protected selectModel(model: string): void;
|
|
233
|
+
/**
|
|
234
|
+
* **D-094** — modelo a enviar na próxima chamada LLM: seleção do usuário ›
|
|
235
|
+
* input `llmModel` › `undefined` (provider usa seu default).
|
|
236
|
+
*/
|
|
237
|
+
private requestModel;
|
|
238
|
+
/**
|
|
239
|
+
* Candidates ordenados por confidence — recomputa quando
|
|
240
|
+
* `debouncedText` muda OU quando o registry de intents muda.
|
|
241
|
+
*/
|
|
242
|
+
protected readonly candidates: _angular_core.Signal<readonly NluCandidate[]>;
|
|
243
|
+
/**
|
|
244
|
+
* **D-046 review-10 (M14)**: idioma detectado do input (PT/EN/unknown).
|
|
245
|
+
* Quando `autoDetectLanguage = true`, este valor sobreescreve `voiceLang()`
|
|
246
|
+
* default pra escolher o engine STT do browser correto.
|
|
247
|
+
*/
|
|
248
|
+
protected readonly detectedLanguage: _angular_core.Signal<"unknown" | "pt" | "en">;
|
|
249
|
+
/**
|
|
250
|
+
* Idioma de voz selecionado (BCP-47). Default = **locale do navegador**
|
|
251
|
+
* (normalizado p/ PT-BR/EN-US/ES-ES), trocável pelo usuário no seletor
|
|
252
|
+
* de idioma. Serve às duas engines: a Web Speech usa o BCP-47 direto; o
|
|
253
|
+
* Whisper mapeia para o nome do idioma (pt-BR → "portuguese").
|
|
254
|
+
*/
|
|
255
|
+
protected readonly selectedLanguage: _angular_core.WritableSignal<string>;
|
|
256
|
+
/** Opções do seletor de idioma. */
|
|
257
|
+
protected readonly languages: readonly VoiceLanguageOption[];
|
|
258
|
+
/**
|
|
259
|
+
* Resolve BCP-47 efetivo pro `voice.listen(lang)`: o idioma do seletor.
|
|
260
|
+
* Quando `autoDetectLanguage = true`, o idioma detectado do **texto
|
|
261
|
+
* digitado** (PT/EN) tem prioridade sobre a seleção manual.
|
|
262
|
+
*/
|
|
263
|
+
protected readonly effectiveVoiceLang: _angular_core.Signal<string>;
|
|
264
|
+
protected readonly topCandidate: _angular_core.Signal<NluCandidate | null>;
|
|
265
|
+
protected readonly alternatives: _angular_core.Signal<readonly NluCandidate[]>;
|
|
266
|
+
/**
|
|
267
|
+
* Mensagem **acionável** pra erro do Web Speech API. Mapeia os codes
|
|
268
|
+
* crus (`'network'`, `'not-allowed'`, `'no-speech'`, `'audio-capture'`,
|
|
269
|
+
* `'service-not-allowed'`) pra texto humano em PT com o passo concreto
|
|
270
|
+
* que o usuário pode tomar pra resolver. Retorna `null` quando não
|
|
271
|
+
* deve mostrar nada (sem erro OU erro `'aborted'` que é silencioso).
|
|
272
|
+
*
|
|
273
|
+
* **Por que `'network'` é comum no Chrome**: o Web Speech API delega
|
|
274
|
+
* o reconhecimento a servidores Google STT — sem internet, com
|
|
275
|
+
* firewall corporativo ou com bloqueador (uBlock/Brave Shields)
|
|
276
|
+
* filtrando `*.google.com`, o handshake falha e o navegador dispara
|
|
277
|
+
* esse erro. Não é bug do app — é dependência arquitetural do
|
|
278
|
+
* Web Speech API spec ao backend STT do vendor.
|
|
279
|
+
*/
|
|
280
|
+
protected readonly voiceErrorMessage: _angular_core.Signal<string | null>;
|
|
281
|
+
/** Troca o idioma de voz (seletor) e persiste a escolha. */
|
|
282
|
+
protected setLanguage(code: string): void;
|
|
283
|
+
/** Rótulo curto do idioma atual (chip do seletor). */
|
|
284
|
+
protected languageShort(code: string): string;
|
|
285
|
+
/** Rótulo humano para cada engine de voz. */
|
|
286
|
+
protected engineLabel(engine: VoiceEngine): string;
|
|
287
|
+
/** Ícone Material para cada engine de voz. */
|
|
288
|
+
protected engineIcon(engine: VoiceEngine): string;
|
|
289
|
+
/** Tooltip do botão de microfone (reflete carregamento/gravação). */
|
|
290
|
+
protected micTooltip(): string;
|
|
291
|
+
/**
|
|
292
|
+
* Input handler — atualiza o signal a partir do valor nativo. Não
|
|
293
|
+
* usamos `[value]` binding (que conflita com o controle interno do
|
|
294
|
+
* MatInput em digitação rápida); em vez disso lemos do input direto
|
|
295
|
+
* e setamos programaticamente via `setTextProgrammatically` quando
|
|
296
|
+
* preciso (voice transcript, limpar pós-execute).
|
|
297
|
+
*/
|
|
298
|
+
protected onInput(value: string): void;
|
|
299
|
+
/**
|
|
300
|
+
* Seta o valor do input programaticamente (voice transcript, clear
|
|
301
|
+
* pós-execute). Atualiza o signal E o input element value — o input
|
|
302
|
+
* nativo não escuta mudanças de signal sozinho.
|
|
303
|
+
*
|
|
304
|
+
* **D-046 review-10**: também atualiza `debouncedText` IMEDIATO
|
|
305
|
+
* (sem debounce) — caller programático sabe que o valor é final.
|
|
306
|
+
*/
|
|
307
|
+
private setTextProgrammatically;
|
|
308
|
+
protected runNow(): Promise<void>;
|
|
309
|
+
/**
|
|
310
|
+
* **D-093** — fallback LLM. Pede um plano de comandos ao
|
|
311
|
+
* {@link LlmIntentResolverService} e o executa pelo mesmo pipeline
|
|
312
|
+
* seguro. Mostra spinner enquanto interpreta (pode levar segundos no
|
|
313
|
+
* hardware local) e mensagem amigável em caso de erro/sem-comandos.
|
|
314
|
+
* Não limpa o input em falha (o usuário pode reformular).
|
|
315
|
+
*/
|
|
316
|
+
private escalateToLlm;
|
|
317
|
+
/**
|
|
318
|
+
* **D-094 — modo SEM catálogo.** Pede um SVG completo ao
|
|
319
|
+
* {@link LlmIntentResolverService.generateAndInsertSvg}, que o parseia,
|
|
320
|
+
* saneia e desenha no canvas. Em sucesso limpa o input; em falha mostra o
|
|
321
|
+
* erro amigável do resolver. Erros de rede sobem para o `catch` de
|
|
322
|
+
* {@link escalateToLlm}.
|
|
323
|
+
*/
|
|
324
|
+
private escalateRawSvg;
|
|
325
|
+
/**
|
|
326
|
+
* **D-093 Fase 3** — escape hatch explícito: manda o texto **direto**
|
|
327
|
+
* ao LLM, ignorando o rule-based. Útil quando o usuário sabe que quer a
|
|
328
|
+
* IA (ex.: composição complexa) independente do que o rule-based acharia.
|
|
329
|
+
*/
|
|
330
|
+
protected askAi(): Promise<void>;
|
|
331
|
+
/**
|
|
332
|
+
* Executa um candidate específico (clique na lista de alternativas)
|
|
333
|
+
* — usa `nlu.executeCandidate` que aplica gate + threshold +
|
|
334
|
+
* destructive check, em vez de chamar `intent.execute` direto
|
|
335
|
+
* (que bypassaria toda a defesa).
|
|
336
|
+
*/
|
|
337
|
+
protected execCandidate(cand: NluCandidate): Promise<void>;
|
|
338
|
+
/**
|
|
339
|
+
* Força a execução do top candidate **após** o usuário clicar
|
|
340
|
+
* "Confirmar" — passa um gate `() => true` overridand a rejeição
|
|
341
|
+
* `'destructive-no-gate'` / `'below-threshold'` anterior.
|
|
342
|
+
*/
|
|
343
|
+
protected forceExecute(rejected: NluExecuteResult): Promise<void>;
|
|
344
|
+
/**
|
|
345
|
+
* `true` quando o último resultado merece um botão "Confirmar" na
|
|
346
|
+
* UI: usuário escolheu rodar e bateu numa proteção (destrutivo sem
|
|
347
|
+
* gate, ou confidence baixa sem gate), mas há candidate concreto
|
|
348
|
+
* pra forçar execução manualmente.
|
|
349
|
+
*/
|
|
350
|
+
protected canForceExecute(result: NluExecuteResult): boolean;
|
|
351
|
+
protected toggleVoice(): Promise<void>;
|
|
352
|
+
/**
|
|
353
|
+
* Texto humano pra exibir do candidate. Prioridade:
|
|
354
|
+
* 1. `intent.description` (quando explícita)
|
|
355
|
+
* 2. Keywords joined (mais legível que reverse-DNS id)
|
|
356
|
+
* 3. `intent.id` (último recurso)
|
|
357
|
+
*/
|
|
358
|
+
protected describeIntent(c: NluCandidate): string;
|
|
359
|
+
protected confidencePercent(c: NluCandidate): number;
|
|
360
|
+
protected describeRejection(result: NluExecuteResult): string;
|
|
361
|
+
/**
|
|
362
|
+
* Monta as `NluExecuteOptions` consolidadas: thresholds + gate.
|
|
363
|
+
* Quando o consumer não passou `confirmGate` via input, usa
|
|
364
|
+
* `window.confirm` como default — universal, zero dep.
|
|
365
|
+
*/
|
|
366
|
+
private executeOptions;
|
|
367
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SvgeNluInput, never>;
|
|
368
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SvgeNluInput, "svge-nlu-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "voiceLang": { "alias": "voiceLang"; "required": false; "isSignal": true; }; "autoDetectLanguage": { "alias": "autoDetectLanguage"; "required": false; "isSignal": true; }; "parseDebounceMs": { "alias": "parseDebounceMs"; "required": false; "isSignal": true; }; "autoExecuteThreshold": { "alias": "autoExecuteThreshold"; "required": false; "isSignal": true; }; "confirmGate": { "alias": "confirmGate"; "required": false; "isSignal": true; }; "enableLlmFallback": { "alias": "enableLlmFallback"; "required": false; "isSignal": true; }; "llmModel": { "alias": "llmModel"; "required": false; "isSignal": true; }; }, { "executed": "executed"; }, never, never, true, never>;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
declare class VoiceRecognitionService {
|
|
372
|
+
/** Quando `false`, a UI deve esconder/desabilitar o botão de voz. */
|
|
373
|
+
readonly isSupported: Signal<boolean>;
|
|
374
|
+
private readonly _listening;
|
|
375
|
+
/** `true` enquanto o microfone está capturando. */
|
|
376
|
+
readonly listening: Signal<boolean>;
|
|
377
|
+
private readonly _lastError;
|
|
378
|
+
/**
|
|
379
|
+
* Último erro do recognizer (`'no-speech'`, `'aborted'`,
|
|
380
|
+
* `'not-allowed'`, etc.). Reseta no próximo `start()`.
|
|
381
|
+
*/
|
|
382
|
+
readonly lastError: Signal<string | null>;
|
|
383
|
+
private activeRec;
|
|
384
|
+
/**
|
|
385
|
+
* Default timeout pra `listen()` (D-046 review-10).
|
|
386
|
+
* 30 segundos cobre comandos longos sem deixar Promise pendurada
|
|
387
|
+
* indefinidamente quando o recognizer entra em estado patológico
|
|
388
|
+
* (tab em background, perda de conexão, browser sem disparar onend).
|
|
389
|
+
*/
|
|
390
|
+
static readonly DEFAULT_LISTEN_TIMEOUT_MS = 30000;
|
|
391
|
+
/**
|
|
392
|
+
* Default do **watchdog de silêncio** (VAD) — encerra a captura
|
|
393
|
+
* `DEFAULT_SILENCE_MS` ms após a última palavra reconhecida, espelhando
|
|
394
|
+
* o auto-stop do provider Whisper local. A Web Speech API não tem
|
|
395
|
+
* config nativa de endpointing; emulamos via `interimResults`.
|
|
396
|
+
*/
|
|
397
|
+
static readonly DEFAULT_SILENCE_MS = 1000;
|
|
398
|
+
/**
|
|
399
|
+
* Inicia a captura. Resolve com a transcrição final quando o
|
|
400
|
+
* recognizer terminar. Rejeita em erro, em timeout ou se chamado sem suporte.
|
|
401
|
+
*
|
|
402
|
+
* @param lang BCP-47 language tag (default `pt-BR`)
|
|
403
|
+
* @param options.timeoutMs timeout em ms (default 30000). Após
|
|
404
|
+
* expirar, aborta o recognizer e rejeita com `'timeout'`.
|
|
405
|
+
*/
|
|
406
|
+
listen(lang?: string, options?: {
|
|
407
|
+
readonly timeoutMs?: number;
|
|
408
|
+
readonly silenceMs?: number;
|
|
409
|
+
}): Promise<string>;
|
|
410
|
+
/** Aborta a captura ativa, se houver. */
|
|
411
|
+
stop(): void;
|
|
412
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<VoiceRecognitionService, never>;
|
|
413
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<VoiceRecognitionService>;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export { SvgeNluInput, VoiceEngineService, VoiceRecognitionService };
|