@danhachuel/thunderbolt 0.7.62 → 0.7.64
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 -19
- package/hermes_ui/provider_routing.py +2 -2
- package/package.json +1 -1
package/app/main.py
CHANGED
|
@@ -6574,21 +6574,8 @@ def render_facebook_automation() -> None:
|
|
|
6574
6574
|
_render_facebook_automation_cards()
|
|
6575
6575
|
|
|
6576
6576
|
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
st.caption("Agendamento diário da geração por canal. O worker verifica o relógio local do computador e coloca os lotes agendados na fila.")
|
|
6580
|
-
_sync_saved_scripts_to_youtube_automation()
|
|
6581
|
-
worker_status = load_worker_status()
|
|
6582
|
-
local_now = datetime.now().astimezone()
|
|
6583
|
-
if worker_status.get("alive"):
|
|
6584
|
-
st.success(f"Worker activo · relógio local: {local_now.strftime('%d/%m/%Y %H:%M:%S %Z')}")
|
|
6585
|
-
else:
|
|
6586
|
-
st.warning("Worker de automação não está activo. Inicie o Thunderbolt pelo launcher (`npx.cmd --yes @danhachuel/thunderbolt`) para activar as verificações horárias.")
|
|
6587
|
-
last_tick = worker_status.get("last_tick_local")
|
|
6588
|
-
if last_tick:
|
|
6589
|
-
st.caption(f"Última verificação do worker: {last_tick}")
|
|
6590
|
-
if worker_status.get("last_error"):
|
|
6591
|
-
st.error(f"Último erro do worker: {worker_status['last_error']}")
|
|
6577
|
+
@st.fragment
|
|
6578
|
+
def _render_youtube_automation_channel_cards():
|
|
6592
6579
|
channels = [channel for channel in read_json("channels.json", []) if is_youtube_channel_record(channel)]
|
|
6593
6580
|
if not channels:
|
|
6594
6581
|
st.info("Nenhum canal cadastrado para configurar.")
|
|
@@ -6688,19 +6675,41 @@ def render_automation():
|
|
|
6688
6675
|
elif not valid_hhmm(average_video_time):
|
|
6689
6676
|
st.error("O Tempo Medio de Video deve estar no formato MM:SS, por exemplo 12:00.")
|
|
6690
6677
|
else:
|
|
6678
|
+
paired_id = str(paired_thumbnail.get("id") or "Youtube_Generic_Thumbnail_Blueprint")
|
|
6691
6679
|
update_channel(channel_id, {
|
|
6692
6680
|
"automation_on": bool(enabled),
|
|
6693
6681
|
"automation_time": schedule_time.strip(),
|
|
6694
6682
|
"average_video_time": average_video_time.strip() or DEFAULT_AVERAGE_VIDEO_TIME,
|
|
6695
6683
|
"average_video_word_count": words_from_channel_time(average_video_time),
|
|
6696
6684
|
"format": automation_format,
|
|
6685
|
+
"blueprint_id": automation_blueprint,
|
|
6686
|
+
"default_blueprint_id": automation_blueprint,
|
|
6687
|
+
"voice": automation_voice,
|
|
6688
|
+
"default_voice": automation_voice,
|
|
6689
|
+
"thumbnail_blueprint_id": paired_id,
|
|
6690
|
+
"default_thumbnail_blueprint_id": paired_id,
|
|
6697
6691
|
})
|
|
6698
|
-
set_channel_defaults(channel_id, automation_blueprint, automation_voice)
|
|
6699
|
-
paired_id = str(paired_thumbnail.get("id") or "Youtube_Generic_Thumbnail_Blueprint")
|
|
6700
|
-
update_channel(channel_id, {"thumbnail_blueprint_id": paired_id, "default_thumbnail_blueprint_id": paired_id})
|
|
6701
6692
|
st.success("Agendamento guardado.")
|
|
6702
|
-
st.rerun()
|
|
6693
|
+
st.rerun(scope="fragment")
|
|
6703
6694
|
|
|
6695
|
+
|
|
6696
|
+
|
|
6697
|
+
def render_automation():
|
|
6698
|
+
st.title("Automação Youtube")
|
|
6699
|
+
st.caption("Agendamento diário da geração por canal. O worker verifica o relógio local do computador e coloca os lotes agendados na fila.")
|
|
6700
|
+
_sync_saved_scripts_to_youtube_automation()
|
|
6701
|
+
worker_status = load_worker_status()
|
|
6702
|
+
local_now = datetime.now().astimezone()
|
|
6703
|
+
if worker_status.get("alive"):
|
|
6704
|
+
st.success(f"Worker activo · relógio local: {local_now.strftime('%d/%m/%Y %H:%M:%S %Z')}")
|
|
6705
|
+
else:
|
|
6706
|
+
st.warning("Worker de automação não está activo. Inicie o Thunderbolt pelo launcher (`npx.cmd --yes @danhachuel/thunderbolt`) para activar as verificações horárias.")
|
|
6707
|
+
last_tick = worker_status.get("last_tick_local")
|
|
6708
|
+
if last_tick:
|
|
6709
|
+
st.caption(f"Última verificação do worker: {last_tick}")
|
|
6710
|
+
if worker_status.get("last_error"):
|
|
6711
|
+
st.error(f"Último erro do worker: {worker_status['last_error']}")
|
|
6712
|
+
_render_youtube_automation_channel_cards()
|
|
6704
6713
|
_render_youtube_automation_cards()
|
|
6705
6714
|
|
|
6706
6715
|
def render_upload_direct():
|
|
@@ -426,11 +426,11 @@ def route_json_request(
|
|
|
426
426
|
record_provider_attempt(record)
|
|
427
427
|
if exc.retryable or exc.category in {"credential", "endpoint_or_model"}:
|
|
428
428
|
set_provider_cooldown(card, exc.retry_after or cooldown or DEFAULT_COOLDOWN_SECONDS)
|
|
429
|
-
if not exc.retryable:
|
|
429
|
+
if not exc.retryable and pool != POOL_LLM:
|
|
430
430
|
raise ProviderRoutingError(str(exc), attempts=attempts) from exc
|
|
431
431
|
if exc.retry_after:
|
|
432
432
|
time.sleep(min(3600.0, exc.retry_after))
|
|
433
|
-
elif cooldown > 0 and len(attempts) < maximum:
|
|
433
|
+
elif exc.retryable and cooldown > 0 and len(attempts) < maximum:
|
|
434
434
|
time.sleep(min(cooldown, 5.0))
|
|
435
435
|
except requests.RequestException as exc:
|
|
436
436
|
classified = classify_request_exception(exc)
|
package/package.json
CHANGED