mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-12 08:05:44 +00:00
* feat: track token cost in AI sessions and chats * fix: address review findings on AI cost tracking * fix: price inherited and overridden models at their real rates * fix: stop newer model revisions inheriting an older price * fix: stop a sub-model inheriting its family's price * fix: keep alias suffixes resolving to their model's price * fix: count OpenRouter cache writes and drop unverifiable rates * refactor: move AI spend out of the chat into workspace and user settings * fix: pin the usage workspace per turn and stop inventing cache rates * fix: leave Sonnet 5 unpriced while its promotional rate runs * docs: record the new table in the schema summary and tighten comments * fix: mark estimated AI costs with ~ and drop session grouping Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: name the workspace in the self-scoped AI usage title Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: state that overrides never replace a provider-returned cost Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: let a cleared cache rate inherit again and flag partial totals Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: clear a refused rate's error when the input snaps back Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: stop a revision variant inheriting its base family's rate Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: report AI usage before tools run and price self usage consistently Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: key pricing rows on the model id usage is reported under Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: surface Bedrock and Gemini usage the chat proxy was dropping Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: count Gemini tool-use prompt tokens as input Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: price flat-rate Gemini Flash models Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: state the tool-use token invariant once Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
136 lines
4.0 KiB
Svelte
136 lines
4.0 KiB
Svelte
<script lang="ts">
|
|
import Drawer from '$lib/components/common/drawer/Drawer.svelte'
|
|
import DrawerContent from '$lib/components/common/drawer/DrawerContent.svelte'
|
|
import Version from './Version.svelte'
|
|
import DarkModeToggle from './sidebar/DarkModeToggle.svelte'
|
|
import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte'
|
|
import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte'
|
|
import TokensTable from './settings/TokensTable.svelte'
|
|
import { createEventDispatcher } from 'svelte'
|
|
import UserInfoSettings from './settings/UserInfoSettings.svelte'
|
|
import AIUserSettings from './settings/AIUserSettings.svelte'
|
|
import AiUsagePanel from './workspaceSettings/AiUsagePanel.svelte'
|
|
import { copilotInfo, copilotWorkspace } from '$lib/aiStore'
|
|
import {
|
|
getDarkModeVariant,
|
|
setDarkModeVariant,
|
|
type DarkModeVariant
|
|
} from '$lib/darkModeVariant'
|
|
|
|
interface Props {
|
|
scopes?: string[] | undefined
|
|
newTokenLabel?: string | undefined
|
|
newTokenWorkspace?: string | undefined
|
|
newToken?: string | undefined
|
|
showMcpMode?: boolean
|
|
disableChatOffset?: boolean
|
|
}
|
|
|
|
let {
|
|
scopes = undefined,
|
|
newTokenLabel = undefined,
|
|
newTokenWorkspace = undefined,
|
|
newToken = $bindable(undefined),
|
|
showMcpMode = false,
|
|
disableChatOffset = false
|
|
}: Props = $props()
|
|
|
|
let drawer: Drawer | undefined = $state()
|
|
let openWithMcpMode = $state(false)
|
|
let darkVariant = $state<DarkModeVariant>(getDarkModeVariant())
|
|
|
|
const dispatch = createEventDispatcher()
|
|
|
|
export function openDrawer(mcpMode: boolean = false) {
|
|
openWithMcpMode = mcpMode
|
|
drawer?.openDrawer()
|
|
}
|
|
|
|
export function closeDrawer() {
|
|
drawer?.closeDrawer()
|
|
removeHash()
|
|
}
|
|
|
|
function removeHash() {
|
|
window.location.hash = ''
|
|
}
|
|
|
|
function handleTokenCreated(token: string) {
|
|
newToken = token
|
|
dispatch('tokenCreated', token)
|
|
}
|
|
</script>
|
|
|
|
<Drawer
|
|
bind:this={drawer}
|
|
size="900px"
|
|
on:open={() => (darkVariant = getDarkModeVariant())}
|
|
on:close={removeHash}
|
|
{disableChatOffset}
|
|
>
|
|
<DrawerContent title="User settings" on:close={closeDrawer}>
|
|
<div class="flex flex-col gap-6 pb-8">
|
|
{#if scopes == undefined}
|
|
<div
|
|
class="flex flex-row justify-between items-start gap-2 border border-border-light p-4 rounded-md"
|
|
>
|
|
<div class="flex flex-col gap-2">
|
|
<div class="font-semibold text-emphasis text-xs flex items-center">
|
|
Theme <DarkModeToggle forcedDarkMode={false} />
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<span class="text-xs text-secondary">Dark variant</span>
|
|
<ToggleButtonGroup
|
|
selected={darkVariant}
|
|
class="w-fit"
|
|
onSelected={(v) => {
|
|
darkVariant = v
|
|
setDarkModeVariant(v)
|
|
}}
|
|
>
|
|
{#snippet children({ item })}
|
|
<ToggleButton value="default" label="Default" size="sm" {item} />
|
|
<ToggleButton value="github" label="GitHub" size="sm" {item} />
|
|
{/snippet}
|
|
</ToggleButtonGroup>
|
|
</div>
|
|
</div>
|
|
<div class="text-xs text-emphasis flex-col flex">
|
|
Windmill <Version />
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 w-full gap-4">
|
|
<div class="min-w-0">
|
|
<UserInfoSettings />
|
|
</div>
|
|
<div class="min-w-0">
|
|
<AIUserSettings />
|
|
</div>
|
|
</div>
|
|
<!-- Keyed on the workspace `copilotInfo` reflects, not on `$workspaceStore`:
|
|
a session acting on another workspace loads that workspace's AI config
|
|
while navigation stays put, and pricing usage from one workspace with
|
|
another's rates would silently misstate it. -->
|
|
{#if $copilotWorkspace}
|
|
<AiUsagePanel
|
|
workspace={$copilotWorkspace}
|
|
modelPricing={$copilotInfo.modelPricing ?? {}}
|
|
scope="self"
|
|
/>
|
|
{/if}
|
|
{/if}
|
|
|
|
<div class="grow min-h-0">
|
|
<TokensTable
|
|
{showMcpMode}
|
|
{openWithMcpMode}
|
|
defaultNewTokenLabel={newTokenLabel}
|
|
defaultNewTokenWorkspace={newTokenWorkspace}
|
|
{scopes}
|
|
onTokenCreated={handleTokenCreated}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</DrawerContent>
|
|
</Drawer>
|