feat: License tab in Settings (activate/deactivate UI) + startup refresh
This commit is contained in:
parent
fa1f36dc8d
commit
6585d9ec75
2 changed files with 56 additions and 2 deletions
|
|
@ -61,6 +61,13 @@ def _startup() -> None:
|
|||
|
||||
_startup()
|
||||
|
||||
# Silent license refresh on startup — no-op if unreachable
|
||||
try:
|
||||
from scripts.license import refresh_if_needed as _refresh_license
|
||||
_refresh_license()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# ── First-run wizard gate ───────────────────────────────────────────────────────
|
||||
from scripts.user_profile import UserProfile as _UserProfile
|
||||
_USER_YAML = Path(__file__).parent.parent / "config" / "user.yaml"
|
||||
|
|
|
|||
|
|
@ -89,12 +89,12 @@ _show_dev_tab = _dev_mode or bool(_u_for_dev.get("dev_tier_override"))
|
|||
_tab_names = [
|
||||
"👤 My Profile", "🔎 Search", "🤖 LLM Backends", "📚 Notion",
|
||||
"🔌 Services", "📝 Resume Profile", "📧 Email", "🏷️ Skills",
|
||||
"🔗 Integrations", "🎯 Fine-Tune"
|
||||
"🔗 Integrations", "🎯 Fine-Tune", "🔑 License"
|
||||
]
|
||||
if _show_dev_tab:
|
||||
_tab_names.append("🛠️ Developer")
|
||||
_all_tabs = st.tabs(_tab_names)
|
||||
tab_profile, tab_search, tab_llm, tab_notion, tab_services, tab_resume, tab_email, tab_skills, tab_integrations, tab_finetune = _all_tabs[:10]
|
||||
tab_profile, tab_search, tab_llm, tab_notion, tab_services, tab_resume, tab_email, tab_skills, tab_integrations, tab_finetune, tab_license = _all_tabs[:11]
|
||||
|
||||
with tab_profile:
|
||||
from scripts.user_profile import UserProfile as _UP, _DEFAULTS as _UP_DEFAULTS
|
||||
|
|
@ -1129,6 +1129,53 @@ with tab_finetune:
|
|||
if col_refresh.button("🔄 Check model status", key="ft_refresh3"):
|
||||
st.rerun()
|
||||
|
||||
# ── License tab ───────────────────────────────────────────────────────────────
|
||||
with tab_license:
|
||||
st.subheader("🔑 License")
|
||||
|
||||
from scripts.license import (
|
||||
verify_local as _verify_local,
|
||||
activate as _activate,
|
||||
deactivate as _deactivate,
|
||||
_DEFAULT_LICENSE_PATH,
|
||||
_DEFAULT_PUBLIC_KEY_PATH,
|
||||
)
|
||||
|
||||
_lic = _verify_local()
|
||||
|
||||
if _lic:
|
||||
_grace_note = " _(grace period active)_" if _lic.get("in_grace") else ""
|
||||
st.success(f"**{_lic['tier'].title()} tier** active{_grace_note}")
|
||||
try:
|
||||
import json as _json
|
||||
_key_display = _json.loads(_DEFAULT_LICENSE_PATH.read_text()).get("key_display", "—")
|
||||
except Exception:
|
||||
_key_display = "—"
|
||||
st.caption(f"Key: `{_key_display}`")
|
||||
if _lic.get("notice"):
|
||||
st.info(_lic["notice"])
|
||||
if st.button("Deactivate this machine", type="secondary", key="lic_deactivate"):
|
||||
_deactivate()
|
||||
st.success("Deactivated. Restart the app to apply.")
|
||||
st.rerun()
|
||||
else:
|
||||
st.info("No active license — running on **free tier**.")
|
||||
st.caption("Enter a license key to unlock paid features.")
|
||||
_key_input = st.text_input(
|
||||
"License key",
|
||||
placeholder="CFG-PRNG-XXXX-XXXX-XXXX",
|
||||
label_visibility="collapsed",
|
||||
key="lic_key_input",
|
||||
)
|
||||
if st.button("Activate", disabled=not (_key_input or "").strip(), key="lic_activate"):
|
||||
with st.spinner("Activating…"):
|
||||
try:
|
||||
result = _activate(_key_input.strip())
|
||||
st.success(f"Activated! Tier: **{result['tier']}**")
|
||||
st.rerun()
|
||||
except Exception as _e:
|
||||
st.error(f"Activation failed: {_e}")
|
||||
|
||||
# ── Developer tab ─────────────────────────────────────────────────────────────
|
||||
if _show_dev_tab:
|
||||
with _all_tabs[-1]:
|
||||
|
|
|
|||
Loading…
Reference in a new issue