When a function call was already registered under its output_index key
via response.output_item.added, the synthetic events built from the
terminal response.completed output carry no output_index and resolve to
a different item-based key. ensureToolForEvent then created a second
tool index and resent the full arguments, so Chat Completions clients
received the same tool call twice.
Reuse the tool registered under itemIDToKey/callIDToKey before creating
a new one, and alias the new key to the existing tool.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
DataTableRow's React.memo did not depend on columnVisibility.
TanStack row references stay stable when visible columns change, so the
table body did not refresh after View -> Toggle columns until another
action rebuilt the column definitions.
Capture a visible column id signature (visibleColumnIds) outside the
memo and compare it, matching the existing isSelected snapshot pattern.
All tables that use DataTableRow pick up the fix.
* fix: add server-side sorting to user list, prevent client-side sort on paged data
The user management table applied client-side sorting to the current
page slice while pagination was handled server-side, causing ID-asc
views to show pages out of order (e.g. 23-42, 3-22, 1-2).
Backend: add sort_by/sort_order query params to GetAllUsers and
SearchUsers with a column whitelist for safe ORDER BY generation.
Frontend: pass sorting state to the API and reset to page 1 on sort
change. Generic useDataTable hook now disables client-side sorted row
model and sort UI for tables with manual pagination but no server-side
sort handler.
* fix: add id tie-breaker to non-unique sort columns, remove side effect from state updater
Append secondary ORDER BY id DESC when sorting by non-unique columns
(quota, created_at, etc.) to prevent row duplication/skipping across
OFFSET pages.
Move onPaginationChange out of setSorting updater to avoid side effects
inside a pure function (React Strict Mode double-invocation safety).
- widen the quota column and add consistent spacing between remaining and total values.
- extract quota rendering into a dedicated component and truncate oversized text within the cell.
- preserve full-value tooltips, progress indicators, and the zero-quota state.
* fix: purge authentication data on hard user deletion
* fix: fail closed when 2FA status lookup fails
* fix: reject stale Telegram login callbacks
* fix(twofa): prevent concurrent backup code and lockout bypasses
* fix(auth): harden user deletion and Telegram verification
Persist committed editor drafts to the source model during batch copy so
targets never carry pricing the source would lose, surface loading/error
states for the enabled-models query, and compare saved* props in the
visual editor memo so rows leave the unset list reliably after save.
Parse OpenAI's native cache_write_tokens (chat prompt_tokens_details /
responses input_tokens_details), bill it at the cache-creation ratio, and
clamp the uncached prompt remainder at zero since cached + cache-write can
exceed prompt_tokens. Propagate the field through chat/responses/claude
format conversions and tiered expression billing (cc variable).
* refactor: consolidate relay protocol converters
* refactor relayconvert text converters
* feat: refine relay converters and advanced custom routing
* refactor: enhance logging and add thought signature handling for Gemini requests
* refactor: enhance channel cache and pricing endpoint handling for advanced custom models
* feat: preserve billing usage semantics
* feat: add protocol-aware billing usage
* Delete useless files
* chore: update action versions in workflow files
* chore: update Docker action versions in workflow files
* fix: harden billing usage settlement and hot-path route matching
- estimate Gemini completion tokens locally when billable usageMetadata is
prompt-only but output content was received (e.g. client aborts the stream
before the final chunk), and rebuild the attached billing_usage as estimated
so settlement does not bill zero output tokens
- guard NewClaudeMessagesBillingUsage against all-zero ClaudeUsage, matching
the OpenAI/Gemini constructors, so a zero billing_usage cannot override a
non-zero top-level usage during settlement
- cache compiled advanced-custom route model regexes; they run on the request
hot path and were recompiled per request
- move the effectiveBillingUsage remap to PostTextConsumeQuota only, and
document that calculateTextQuotaSummary expects remapped usage
- document the updatePricingLock -> channelSyncLock lock ordering that
InitChannelCache/CacheUpdateChannel rely on, and the aux-struct pitfall in
GeminiChatResponse.UnmarshalJSON
Revert 6869cd94b (perf(web): align table badge spacing).
Restores px padding on status badges so usage-log timing/duration
pills are not flush against the edges.
The custom home page URL iframe only allows allow-forms/allow-popups/
allow-popups-to-escape-sandbox/allow-scripts, without allow-top-navigation*.
As a result, target="_top" nav/menu links inside the (admin-configured,
trusted) embedded page cannot navigate the top-level window on desktop
browsers, while some mobile browsers still allow it via allow-popups —
causing inconsistent behavior rather than an intended restriction.
Add allow-top-navigation-by-user-activation so user-clicked top-level
links work consistently across devices. This token only permits
user-activated top navigation and does NOT grant same-origin access,
so it avoids the security concern of allow-same-origin.
Co-authored-by: 贺. <kuang@M1.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace collapsible card details with always-visible label/value rows, add badge-list full display for cards, and polish pricing/channel toolbars and mobile cards.
- remove built-in horizontal padding from status badges so table columns align with headers.
- drop legacy negative-margin compensation from badge cells and affected table renderers.
- clean touched table components to satisfy lint rules around type imports, keys, and JSX flow.
- keep input focus and invalid rings inside the shared Input component to avoid clipping in constrained containers.
- make the sync channel selector table use a fixed header, internal body scrolling, and fixed pagination inside the dialog.
- align status cells with their header and translate channel status labels through existing i18n keys.
- batch select and unselect operations into single state updates to reduce lag with large model lists.
- align current price and upstream preset rows by rendering the same ordered field set.
- switch the table to a fixed header, internal body scrolling, and fixed pagination layout with compact upstream header counts.
- hide synthesized preset internal IDs and count only effective selectable resolutions.
- expose playground controls for sampling, penalty, token, and seed parameters.
- reuse the existing persisted config and parameter-enabled state so requests only send enabled values.
- add localized parameter copy and keep the panel scrollable on short screens.
controller/task_video.go and service/pre_consume_quota.go were already
removed in ba25ba88f and 116004fd4 (logic lives in service/task_polling.go
and BillingSession now), then brought back as stale copies by a42b39760.
Both have zero callers.
controller/swag_video.go is a leftover swag stub: the swaggo pipeline is
gone and docs/openapi/relay.json already documents these routes.
- constrain the desktop selector panel so long group and model lists scroll within a shared height.
- make the selected model stand out with stronger row and label styling.
- scroll both lists to the active selections after the popover opens.