Skip to content

Commit 97cd91e

Browse files
author
crispasr integration
committed
Merge branch 'cleanup-final' into main
2 parents 913781d + d2b9788 commit 97cd91e

48 files changed

Lines changed: 1664 additions & 1197 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

PLAN.md

Lines changed: 41 additions & 358 deletions
Large diffs are not rendered by default.

app.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@
120120
key_wrapper = KeyWrapper()
121121

122122
try:
123-
124123
FORMAT_TRANSPLANT_OK = True
125124
FORMAT_TRANSPLANT_ERROR = None
126125
except Exception as _ft_err:
@@ -136,7 +135,6 @@ def _ft_get_provider_choices(user_state):
136135
return ft_get_provider_choices(user_state, FORMAT_TRANSPLANT_OK)
137136

138137

139-
140138
try:
141139
from tool_executor import (
142140
DEFAULT_TOOLS_ADMIN,
@@ -491,7 +489,6 @@ def clear_chat():
491489
# versions at lines ~885, ~1183, ~1385 (which pass session_state).
492490
# These were missing session_state and ran without auth.
493491

494-
495492
# ── Session initialization on page load ──────────────────────────
496493
# With auth=, the user is already authenticated when this fires.
497494
# We use request.username to look up the user and set the UI state.
@@ -508,6 +505,7 @@ def initialize_session(request: gr.Request):
508505

509506
# Look up user from DB + retrieve cached UMK (derived during auth=)
510507
from db_ops import get_cached_umk, get_user_by_username, get_user_settings
508+
511509
user = get_user_by_username(username)
512510
if not user:
513511
print(f"[SESSION] User {username} not found in DB")
@@ -615,6 +613,7 @@ def _on_logout(user_state):
615613
username = (user_state or {}).get("username")
616614
if username:
617615
from db_ops import clear_cached_umk
616+
618617
clear_cached_umk(username)
619618

620619
logout_btn.click(

app_helpers.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,9 @@ def logout_user() -> tuple[str, dict, dict, dict]:
183183
# ---------------------------------------------------------------------------
184184

185185

186-
def update_transcript_chat_ui(prov: str, force_all: bool = False, user_state: dict | None = None) -> tuple[dict, str]:
186+
def update_transcript_chat_ui(
187+
prov: str, force_all: bool = False, user_state: dict | None = None
188+
) -> tuple[dict, str]:
187189
"""
188190
Same logic as update_c_ui but for the transcript "Send to Chat" section.
189191
Returns (Dropdown update, badge HTML).
@@ -223,7 +225,9 @@ def update_transcript_chat_ui(prov: str, force_all: bool = False, user_state: di
223225
)
224226

225227

226-
def update_c_ui(prov: str, force_all: bool = False, user_state: dict | None = None) -> tuple[dict, str]:
228+
def update_c_ui(
229+
prov: str, force_all: bool = False, user_state: dict | None = None
230+
) -> tuple[dict, str]:
227231
"""Chat-tab provider dropdown updater."""
228232
print(f"\n{'#' * 30} [UI-DEBUG] START {'#' * 30}")
229233
print(f"[UI-DEBUG] Provider Input: '{prov}' | Force All: {force_all}")
@@ -297,7 +301,9 @@ def update_c_ui(prov: str, force_all: bool = False, user_state: dict | None = No
297301
)
298302

299303

300-
def update_v_ui(prov: str, force_all: bool = False, user_state: dict | None = None) -> tuple[str, dict, int]:
304+
def update_v_ui(
305+
prov: str, force_all: bool = False, user_state: dict | None = None
306+
) -> tuple[str, dict, int]:
301307
"""Vision-tab provider dropdown updater."""
302308
if not prov:
303309
return "", gr.update(choices=[], value=None), 0
@@ -341,7 +347,9 @@ def update_v_ui(prov: str, force_all: bool = False, user_state: dict | None = No
341347
)
342348

343349

344-
def update_g_ui(prov: str, force_all: bool = False, user_state: dict | None = None) -> tuple[str, dict]:
350+
def update_g_ui(
351+
prov: str, force_all: bool = False, user_state: dict | None = None
352+
) -> tuple[str, dict]:
345353
"""Image-generation-tab provider dropdown updater."""
346354
if not prov:
347355
return "", gr.update(choices=[], value=None)
@@ -378,7 +386,9 @@ def update_g_ui(prov: str, force_all: bool = False, user_state: dict | None = No
378386
return styled_badge, gr.update(choices=final_choices, value=default_val, label="Modell")
379387

380388

381-
def update_t_ui(prov: str, force_all: bool = False, user_state: dict | None = None) -> tuple[str, dict, dict, dict]:
389+
def update_t_ui(
390+
prov: str, force_all: bool = False, user_state: dict | None = None
391+
) -> tuple[str, dict, dict, dict]:
382392
"""Transcription-tab provider dropdown updater.
383393
384394
Returns: (badge, t_model_update, whisper_options_visibility).
@@ -405,6 +415,7 @@ def update_t_ui(prov: str, force_all: bool = False, user_state: dict | None = No
405415
if is_crispasr:
406416
# Filter CrispASR backends by user's max model size preference
407417
from crispasr_tool import get_filtered_backends
418+
408419
max_b = 2.0
409420
if user_state and user_state.get("max_model_size_b"):
410421
try:

chat_handlers.py

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ def _last_image_file(user_state: dict) -> str:
182182
"""Per-user path where the most recently generated/edited image is cached,
183183
so edit_image can target it via image_url='last'."""
184184
import os
185+
185186
uid = (user_state or {}).get("id", "anon")
186187
d = os.path.join(STORAGE_MOUNT_POINT, f"user_{uid}", "images")
187188
os.makedirs(d, exist_ok=True)
@@ -190,6 +191,7 @@ def _last_image_file(user_state: dict) -> str:
190191

191192
def _save_last_image(user_state: dict, src_path: str) -> None:
192193
import shutil
194+
193195
try:
194196
shutil.copyfile(src_path, _last_image_file(user_state))
195197
except Exception: # nosec B110
@@ -319,22 +321,27 @@ def _handler(args: dict):
319321

320322
image_url = (args.get("image_url") or "").strip()
321323
prompt = (args.get("prompt") or "").strip()
322-
model = ("flux-kontext-max" if args.get("high_fidelity")
323-
else "flux-kontext-pro")
324+
model = "flux-kontext-max" if args.get("high_fidelity") else "flux-kontext-pro"
324325

325326
if not prompt:
326-
return ToolResult(text="Error: 'prompt' (the edit) is required.",
327-
error=True)
327+
return ToolResult(text="Error: 'prompt' (the edit) is required.", error=True)
328328
bfl_key = api_keys.get("BFL", "")
329329
if not bfl_key:
330330
return ToolResult(
331-
text="Image editing needs a BFL API key, which is not configured.",
332-
error=True)
331+
text="Image editing needs a BFL API key, which is not configured.", error=True
332+
)
333333

334334
# Resolve the input image: a public URL, a local path, or 'last'
335335
# (the most recently generated/edited image in this session).
336-
_LAST_KW = {"", "last", "previous", "last_generated", "last image",
337-
"the last image", "previous image"}
336+
_LAST_KW = {
337+
"",
338+
"last",
339+
"previous",
340+
"last_generated",
341+
"last image",
342+
"the last image",
343+
"previous image",
344+
}
338345
if image_url.startswith(("http://", "https://")):
339346
input_image, src_label = image_url, image_url[:80]
340347
else:
@@ -343,22 +350,22 @@ def _handler(args: dict):
343350
if not os.path.exists(local):
344351
return ToolResult(
345352
text="No previous image to edit. Generate one first or "
346-
"pass a public image_url.", error=True)
353+
"pass a public image_url.",
354+
error=True,
355+
)
347356
src_label = "last generated image"
348357
elif os.path.exists(image_url):
349358
local, src_label = image_url, os.path.basename(image_url)
350359
else:
351360
return ToolResult(
352-
text="Provide a public image_url, a local path, or 'last'.",
353-
error=True)
361+
text="Provide a public image_url, a local path, or 'last'.", error=True
362+
)
354363
with open(local, "rb") as f:
355364
input_image = base64.b64encode(f.read()).decode() # BFL accepts base64
356365

357-
print(f"[TOOLS] 🖌️ edit_image | model={model} src={src_label!r} "
358-
f"prompt={prompt[:80]!r}…")
366+
print(f"[TOOLS] 🖌️ edit_image | model={model} src={src_label!r} prompt={prompt[:80]!r}…")
359367
try:
360-
file_path, status = run_image_edit(
361-
prompt, input_image, model, bfl_key, user_state)
368+
file_path, status = run_image_edit(prompt, input_image, model, bfl_key, user_state)
362369
except Exception as e:
363370
print(f"[TOOLS] ⚠️ edit_image failed: {e}")
364371
return ToolResult(text=f"Image edit failed: {e}", error=True)
@@ -371,12 +378,14 @@ def _handler(args: dict):
371378
b64 = base64.b64encode(f.read()).decode()
372379
ext = os.path.splitext(file_path)[1].lstrip(".").lower() or "jpeg"
373380
mime = f"image/{ext}" if ext != "jpg" else "image/jpeg"
374-
img_html = (f'<img src="data:{mime};base64,{b64}" '
375-
f'style="max-width:100%;border-radius:8px;margin-top:8px;" />')
381+
img_html = (
382+
f'<img src="data:{mime};base64,{b64}" '
383+
f'style="max-width:100%;border-radius:8px;margin-top:8px;" />'
384+
)
376385
except Exception as e:
377386
img_html = f"*(edited image saved to {file_path} — could not embed: {e})*"
378387

379-
text_summary = (f"✅ Image edited via BFL/{model}.\nEdit: {prompt[:120]}")
388+
text_summary = f"✅ Image edited via BFL/{model}.\nEdit: {prompt[:120]}"
380389
return ToolResult(text=text_summary, ui=f"{text_summary}\n\n{img_html}")
381390

382391
return _handler
@@ -456,6 +465,7 @@ def _handler(args: dict) -> str:
456465
# Load transcription history from DB
457466
try:
458467
from db_ops import get_user_transcriptions
468+
459469
transcriptions = get_user_transcriptions(user_id, limit=100)
460470
except Exception as e:
461471
return f"Could not load transcription history: {e}"
@@ -471,18 +481,21 @@ def _handler(args: dict) -> str:
471481
if text and len(text) > 20:
472482
# Truncate very long texts to keep embedding fast
473483
docs.append(text[:2000])
474-
meta.append({
475-
"id": t.get("id"),
476-
"provider": t.get("provider", "?"),
477-
"created": str(t.get("created_at", "?")),
478-
"full_len": len(text),
479-
})
484+
meta.append(
485+
{
486+
"id": t.get("id"),
487+
"provider": t.get("provider", "?"),
488+
"created": str(t.get("created_at", "?")),
489+
"full_len": len(text),
490+
}
491+
)
480492

481493
if not docs:
482494
return "No transcription texts found (all empty)."
483495

484496
try:
485497
from crispembed_tool import semantic_search
498+
486499
results = semantic_search(query, docs, top_k=top_k)
487500
except Exception as e:
488501
return f"Semantic search failed: {e}"
@@ -551,7 +564,9 @@ def no_creds_error(*args, **kwargs): # type: ignore[no-untyped-def]
551564
"exchange_contact_edit": no_creds_error,
552565
}
553566

554-
logger.info("[EXCH] Credentials loaded for user_id=%s: email=%s", user_id, creds.get("email", "?"))
567+
logger.info(
568+
"[EXCH] Credentials loaded for user_id=%s: email=%s", user_id, creds.get("email", "?")
569+
)
555570

556571
def handle_exchange_list(args: dict) -> str:
557572
logger.debug("[EXCH] exchange_list called with args=%s", args)
@@ -1200,9 +1215,8 @@ def run_chat(
12001215
# ppt-llm presentation tools (provider/model/key + per-user storage)
12011216
try:
12021217
from pptx_tool import make_pptx_tool_handlers
1203-
handlers.update(make_pptx_tool_handlers(
1204-
API_KEYS, user_state, provider, model, key
1205-
))
1218+
1219+
handlers.update(make_pptx_tool_handlers(API_KEYS, user_state, provider, model, key))
12061220
except Exception as _ppt_e:
12071221
logger.debug(f"[TOOLS] pptx handlers unavailable: {_ppt_e}")
12081222

context_utils.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ def summarize_turns(turns: list[dict[str, Any]], client: Any, model: str) -> str
126126
return ""
127127

128128

129-
def prune_messages(messages: list[dict[str, Any]], model_limit: int, max_output_tokens: int = 1000) -> list[dict[str, Any]]:
129+
def prune_messages(
130+
messages: list[dict[str, Any]], model_limit: int, max_output_tokens: int = 1000
131+
) -> list[dict[str, Any]]:
130132
"""
131133
Smartly trims conversation history with verbose CLI logging.
132134
Always keeps the system prompt and the latest user message.

0 commit comments

Comments
 (0)