GETDEL requires Redis 6.2+; server runs 6.0.16, so every finalize_balance
and refund_balance call failed silently ('Unknown Redis command called
from Lua script'). Consequences observed under concurrent load test:
- reserve:* keys leaked until 600s TTL instead of being released at finalize
- balance:{org} never reconciled with actual cost (over-deduction by
max_cost-actual accumulated per call)
- FAILED-request refunds silently lost
GET+DEL inside a Lua script executes atomically (single-threaded),
so the pop semantics are unchanged.
gen() try/except re-raised internal errors from uapi_request → 500 response.
Moved refund_balance to uapi_request's except block where errors are properly
handled (yield error, normal generator exit).
- balance.py: reserve_balance/finalize_balance/refund_balance with Lua
- utils.py: get_model_max_cost from llmusage history, update_model_max_cost
- init.py: register reserve_balance, finalize_balance, refund_balance on env
- chat/completions/index.dspy: reserve before inference, refund on exception
- DB migration: llm.max_cost DECIMAL(10,4) for historical max charge
When client disconnects mid-stream, Python GC kills the generator with
GeneratorExit (BaseException subclass), which is NOT caught by except Exception.
write_llmusage at line 93 was never reached, causing ~16% usage records lost.
finally block ensures llmusage is written even on GeneratorExit.
- Removed iconid from get_llmproviders GROUP BY (caused duplicates)
- Replaced KeyinText with SearchBar (built-in input+search+clear)
- Switched navigation from window.location.assign to urlwidget
targeting sage_main_content (stays in workspace, no full reload)
New layout:
- Search bar (top) with fuzzy name/description match
- Category tabs (wrapping, single-select)
- Provider sidebar (left, single-select)
- Card grid (right, sorted by name, refreshed on filter change)
- Both category/provider unselected = all published models
Added get_plaza_models() for flat filtered model listing.
Supports combined filtering: provider + category + search.
get_llmage_llm and get_llms_by_catelog had ORDER BY ending
at a.id — model names within same provider/catalog appeared
in arbitrary order. Added a.name as final sort key.
- product_interface: all functions take resource_ref_id as primary param
- _resolve_llm: lookup by llm.id directly instead of model name
- load_product_category_product: write llm.id as resource_ref_id in product table
- No more code→id mapping needed in resource module
- New function: load_product_category_product(parent_category_id)
- Reads llmage catalogs + published models, writes sub-categories + products
into product_management DB directly
- Removed env registration (called via importlib, not ServerEnv)
- Add import_products_from_llmage() function that exports llmage catalogs
and published models as product categories and products
- Register on ServerEnv so product_management can call it when
resource_module='llmage'