@danhachuel/thunderbolt 0.3.78 → 0.3.79
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/app/main.py +28 -2
- package/package.json +1 -1
- package/scripts/cli.mjs +11 -2
package/app/main.py
CHANGED
|
@@ -5397,11 +5397,25 @@ def _render_api_test_feedback(settings: dict[str, Any], test_key: str, result: d
|
|
|
5397
5397
|
st.error(ui_text("Último teste: chamada falhou", language) + suffix)
|
|
5398
5398
|
|
|
5399
5399
|
|
|
5400
|
-
def _render_api_test_control(
|
|
5401
|
-
|
|
5400
|
+
def _render_api_test_control(
|
|
5401
|
+
settings: dict[str, Any],
|
|
5402
|
+
test_key: str,
|
|
5403
|
+
callback: Any,
|
|
5404
|
+
*,
|
|
5405
|
+
widget_key: str,
|
|
5406
|
+
persist_callback: Any = None,
|
|
5407
|
+
) -> None:
|
|
5408
|
+
"""Render a form-safe diagnostic button and persist its redacted result.
|
|
5409
|
+
|
|
5410
|
+
``persist_callback`` keeps a card whose fields live in the global form
|
|
5411
|
+
consistent: testing it must not appear successful while its values remain
|
|
5412
|
+
only in the browser session.
|
|
5413
|
+
"""
|
|
5402
5414
|
if st.form_submit_button("Testar chamada API", use_container_width=True, key=widget_key):
|
|
5403
5415
|
with st.spinner(ui_text("A testar chamada API…", current_ui_language())):
|
|
5404
5416
|
try:
|
|
5417
|
+
if persist_callback is not None:
|
|
5418
|
+
persist_callback()
|
|
5405
5419
|
result = callback()
|
|
5406
5420
|
except Exception:
|
|
5407
5421
|
result = {"status": "error", "message": "A chamada de diagnóstico falhou."}
|
|
@@ -5832,11 +5846,23 @@ def render_settings():
|
|
|
5832
5846
|
azure_speech_key = text_setting("Azure Speech key", "azure_speech_key", secret=True)
|
|
5833
5847
|
_render_credential_status(azure_speech_key)
|
|
5834
5848
|
azure_speech_region = text_setting("Azure Speech region", "azure_speech_region")
|
|
5849
|
+
|
|
5850
|
+
def save_azure_speech() -> None:
|
|
5851
|
+
settings.update({
|
|
5852
|
+
"azure_speech_key": azure_speech_key.strip(),
|
|
5853
|
+
"azure_speech_region": azure_speech_region.strip(),
|
|
5854
|
+
})
|
|
5855
|
+
write_json("settings.json", settings)
|
|
5856
|
+
|
|
5857
|
+
if st.form_submit_button("Guardar Azure Speech", type="primary", use_container_width=True, key="save_azure_speech"):
|
|
5858
|
+
save_azure_speech()
|
|
5859
|
+
st.success("Azure Speech guardado.")
|
|
5835
5860
|
_render_api_test_control(
|
|
5836
5861
|
settings,
|
|
5837
5862
|
"voice:azure_speech",
|
|
5838
5863
|
lambda: test_voice_provider("azure_speech", {"azure_speech_key": azure_speech_key, "azure_speech_region": azure_speech_region}),
|
|
5839
5864
|
widget_key="api_test_voice_azure",
|
|
5865
|
+
persist_callback=save_azure_speech,
|
|
5840
5866
|
)
|
|
5841
5867
|
|
|
5842
5868
|
with st.container(border=True):
|
package/package.json
CHANGED
package/scripts/cli.mjs
CHANGED
|
@@ -193,6 +193,11 @@ const proxy = http.createServer((request, response) => {
|
|
|
193
193
|
});
|
|
194
194
|
|
|
195
195
|
proxy.on("upgrade", (request, clientSocket, head) => {
|
|
196
|
+
// Clientes remotos podem encerrar o WebSocket antes de o Streamlit concluir
|
|
197
|
+
// a resposta. Tratar ECONNRESET impede que o Node termine o launcher.
|
|
198
|
+
clientSocket.on("error", () => {
|
|
199
|
+
if (!clientSocket.destroyed) clientSocket.destroy();
|
|
200
|
+
});
|
|
196
201
|
const upstreamSocket = net.connect(backendPort, "127.0.0.1", () => {
|
|
197
202
|
const headers = Object.entries(request.headers)
|
|
198
203
|
.map(([name, value]) => `${name}: ${Array.isArray(value) ? value.join(", ") : value}`)
|
|
@@ -201,10 +206,14 @@ proxy.on("upgrade", (request, clientSocket, head) => {
|
|
|
201
206
|
if (head.length) upstreamSocket.write(head);
|
|
202
207
|
clientSocket.pipe(upstreamSocket).pipe(clientSocket);
|
|
203
208
|
});
|
|
204
|
-
upstreamSocket.on("error", () =>
|
|
209
|
+
upstreamSocket.on("error", () => {
|
|
210
|
+
if (!clientSocket.destroyed) clientSocket.destroy();
|
|
211
|
+
});
|
|
205
212
|
});
|
|
206
213
|
|
|
207
|
-
|
|
214
|
+
// O backend Streamlit fica em 127.0.0.1; apenas o proxy escuta em todas as
|
|
215
|
+
// interfaces para que o encaminhamento seguro do ambiente consiga alcançá-lo.
|
|
216
|
+
proxy.listen(publicPort, () => {
|
|
208
217
|
console.log(`Thunderbolt: interface disponível em http://localhost:${publicPort}/`);
|
|
209
218
|
});
|
|
210
219
|
const worker = spawn(python, ["-m", "hermes_ui.automation_worker"], {
|