generated from nhcarrigan/template
feat: massive overhaul to manage costs (#103)
### Explanation _No response_ ### Issue Closes #102 ### Attestations - [ ] I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/) - [ ] I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/). - [ ] My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/). ### Dependencies - [ ] I have pinned the dependencies to a specific patch version. ### Style - [ ] I have run the linter and resolved any errors. - [ ] My pull request uses an appropriate title, matching the conventional commit standards. - [ ] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request. ### Tests - [ ] My contribution adds new code, and I have added tests to cover it. - [ ] My contribution modifies existing code, and I have updated the tests to reflect these changes. - [ ] All new and existing tests pass locally with my changes. - [ ] Code coverage remains at or above the configured threshold. ### Documentation _No response_ ### Versioning _No response_ Reviewed-on: #103 Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com> Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
This commit was merged in pull request #103.
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
} from "$lib/stores/config";
|
||||
import { claudeStore } from "$lib/stores/claude";
|
||||
import { getCurrentWindow } from "@tauri-apps/api/window";
|
||||
import CostSummary from "./CostSummary.svelte";
|
||||
|
||||
let config: HikariConfig = $state({
|
||||
model: null,
|
||||
@@ -45,6 +46,11 @@
|
||||
text_secondary: null,
|
||||
border_color: null,
|
||||
},
|
||||
budget_enabled: false,
|
||||
session_token_budget: null,
|
||||
session_cost_budget: null,
|
||||
budget_action: "warn",
|
||||
budget_warning_threshold: 0.8,
|
||||
});
|
||||
|
||||
let showCustomThemeEditor = $state(false);
|
||||
@@ -74,8 +80,17 @@
|
||||
|
||||
const availableModels = [
|
||||
{ value: "", label: "Default (from ~/.claude)" },
|
||||
// Current generation (Claude 4.5)
|
||||
{ value: "claude-sonnet-4-5-20250929", label: "Claude Sonnet 4.5 (Recommended)" },
|
||||
{ value: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5 (Fast & Cheap)" },
|
||||
{ value: "claude-opus-4-5-20251101", label: "Claude Opus 4.5 (Most Capable)" },
|
||||
// Previous generation (Claude 4)
|
||||
{ value: "claude-opus-4-1-20250805", label: "Claude Opus 4.1" },
|
||||
{ value: "claude-sonnet-4-20250514", label: "Claude Sonnet 4" },
|
||||
{ value: "claude-opus-4-20250514", label: "Claude Opus 4" },
|
||||
// Legacy (Claude 3.x)
|
||||
{ value: "claude-3-7-sonnet-20250219", label: "Claude 3.7 Sonnet" },
|
||||
{ value: "claude-3-haiku-20240307", label: "Claude 3 Haiku (Cheapest)" },
|
||||
];
|
||||
|
||||
const commonTools = [
|
||||
@@ -778,6 +793,135 @@
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<!-- Budget Settings Section -->
|
||||
<section class="mb-6">
|
||||
<h3 class="text-sm font-medium text-[var(--accent-primary)] uppercase tracking-wider mb-3">
|
||||
Budget Settings
|
||||
</h3>
|
||||
|
||||
<!-- Enable Budget Tracking -->
|
||||
<div class="mb-4">
|
||||
<label class="flex items-center gap-3 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={config.budget_enabled}
|
||||
class="w-4 h-4 text-[var(--accent-primary)] bg-[var(--bg-primary)] border-[var(--border-color)] rounded focus:ring-[var(--accent-primary)] focus:ring-2"
|
||||
/>
|
||||
<span class="text-sm text-[var(--text-primary)]">Enable budget tracking</span>
|
||||
</label>
|
||||
<p class="text-xs text-[var(--text-tertiary)] mt-1 ml-7">
|
||||
Set limits on token usage and costs per session
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{#if config.budget_enabled}
|
||||
<!-- Token Budget -->
|
||||
<div class="mb-4">
|
||||
<label for="token-budget" class="block text-sm text-[var(--text-secondary)] mb-1">
|
||||
Session Token Budget
|
||||
</label>
|
||||
<div class="flex items-center gap-2">
|
||||
<input
|
||||
id="token-budget"
|
||||
type="number"
|
||||
bind:value={config.session_token_budget}
|
||||
min="0"
|
||||
step="10000"
|
||||
placeholder="e.g., 100000"
|
||||
class="flex-1 px-3 py-2 bg-[var(--bg-primary)] border border-[var(--border-color)] rounded-lg text-[var(--text-primary)] text-sm focus:outline-none focus:border-[var(--accent-primary)]"
|
||||
/>
|
||||
<span class="text-xs text-[var(--text-tertiary)]">tokens</span>
|
||||
</div>
|
||||
<p class="text-xs text-[var(--text-tertiary)] mt-1">Leave empty for unlimited tokens</p>
|
||||
</div>
|
||||
|
||||
<!-- Cost Budget -->
|
||||
<div class="mb-4">
|
||||
<label for="cost-budget" class="block text-sm text-[var(--text-secondary)] mb-1">
|
||||
Session Cost Budget
|
||||
</label>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-sm text-[var(--text-secondary)]">$</span>
|
||||
<input
|
||||
id="cost-budget"
|
||||
type="number"
|
||||
bind:value={config.session_cost_budget}
|
||||
min="0"
|
||||
step="0.50"
|
||||
placeholder="e.g., 5.00"
|
||||
class="flex-1 px-3 py-2 bg-[var(--bg-primary)] border border-[var(--border-color)] rounded-lg text-[var(--text-primary)] text-sm focus:outline-none focus:border-[var(--accent-primary)]"
|
||||
/>
|
||||
<span class="text-xs text-[var(--text-tertiary)]">USD</span>
|
||||
</div>
|
||||
<p class="text-xs text-[var(--text-tertiary)] mt-1">Leave empty for unlimited spending</p>
|
||||
</div>
|
||||
|
||||
<!-- Warning Threshold -->
|
||||
<div class="mb-4">
|
||||
<label for="warning-threshold" class="block text-sm text-[var(--text-secondary)] mb-2">
|
||||
Warning Threshold
|
||||
</label>
|
||||
<div class="flex items-center gap-3">
|
||||
<input
|
||||
id="warning-threshold"
|
||||
type="range"
|
||||
bind:value={config.budget_warning_threshold}
|
||||
min="0.5"
|
||||
max="0.95"
|
||||
step="0.05"
|
||||
class="flex-1 h-2 bg-[var(--bg-primary)] rounded-lg appearance-none cursor-pointer"
|
||||
/>
|
||||
<span class="text-sm text-[var(--text-secondary)] w-12 text-right">
|
||||
{Math.round(config.budget_warning_threshold * 100)}%
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-xs text-[var(--text-tertiary)] mt-1">
|
||||
Show warning when this percentage of budget is used
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Budget Action -->
|
||||
<div class="mb-4">
|
||||
<span class="block text-sm text-[var(--text-secondary)] mb-2"
|
||||
>When budget is exceeded</span
|
||||
>
|
||||
<div class="flex gap-2" role="group" aria-label="Budget action">
|
||||
<button
|
||||
onclick={() => (config.budget_action = "warn")}
|
||||
class="flex-1 px-3 py-2 rounded-lg border transition-colors text-sm {config.budget_action ===
|
||||
'warn'
|
||||
? 'bg-[var(--accent-primary)] border-[var(--accent-primary)] text-white'
|
||||
: 'bg-[var(--bg-primary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--accent-primary)]'}"
|
||||
>
|
||||
Warn Only
|
||||
</button>
|
||||
<button
|
||||
onclick={() => (config.budget_action = "block")}
|
||||
class="flex-1 px-3 py-2 rounded-lg border transition-colors text-sm {config.budget_action ===
|
||||
'block'
|
||||
? 'bg-[var(--accent-primary)] border-[var(--accent-primary)] text-white'
|
||||
: 'bg-[var(--bg-primary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--accent-primary)]'}"
|
||||
>
|
||||
Block Input
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-xs text-[var(--text-tertiary)] mt-2">
|
||||
{config.budget_action === "warn"
|
||||
? "Show a warning but allow continued usage"
|
||||
: "Prevent sending more messages until session is reset"}
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<!-- Cost History Section -->
|
||||
<section class="mb-6">
|
||||
<h3 class="text-sm font-medium text-[var(--accent-primary)] uppercase tracking-wider mb-3">
|
||||
Cost History
|
||||
</h3>
|
||||
<CostSummary />
|
||||
</section>
|
||||
|
||||
<!-- Notifications Section -->
|
||||
<section class="mb-6">
|
||||
<h3 class="text-sm font-medium text-[var(--accent-primary)] uppercase tracking-wider mb-3">
|
||||
|
||||
Reference in New Issue
Block a user