feat: make context limit configurable in API settings

Add context limit field to API settings that:
- Stores context limit in config (defaults to 200000)
- Allows users to set custom limits for different models
- Uses configured limit in token counter display
- Shows format like "2.5k / 200k tokens" using actual limit

This allows proper token tracking for non-Claude models with
different context windows.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-16 22:20:13 -07:00
parent e47bd3bf87
commit a7c9657ff1
3 changed files with 33 additions and 3 deletions

View File

@@ -20,6 +20,12 @@ struct ApiConfig {
active_character_id: Option<String>, active_character_id: Option<String>,
#[serde(default)] #[serde(default)]
stream: bool, stream: bool,
#[serde(default = "default_context_limit")]
context_limit: u32,
}
fn default_context_limit() -> u32 {
200000
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -1161,7 +1167,7 @@ async fn validate_api(base_url: String, api_key: String) -> Result<Vec<String>,
} }
#[tauri::command] #[tauri::command]
async fn save_api_config(base_url: String, api_key: String, model: String, stream: bool) -> Result<(), String> { async fn save_api_config(base_url: String, api_key: String, model: String, stream: bool, context_limit: u32) -> Result<(), String> {
// Preserve existing active_character_id if it exists // Preserve existing active_character_id if it exists
let active_character_id = load_config().and_then(|c| c.active_character_id); let active_character_id = load_config().and_then(|c| c.active_character_id);
@@ -1171,6 +1177,7 @@ async fn save_api_config(base_url: String, api_key: String, model: String, strea
model, model,
active_character_id, active_character_id,
stream, stream,
context_limit,
}; };
save_config(&config) save_config(&config)
} }

View File

@@ -350,6 +350,19 @@
</select> </select>
</div> </div>
<div class="form-group">
<label for="context-limit">Context Limit (tokens)</label>
<input
type="number"
id="context-limit"
placeholder="200000"
value="200000"
min="1000"
step="1000"
/>
<small style="color: var(--text-secondary); margin-top: 4px; display: block;">Maximum tokens for model context (e.g., 200000 for Claude)</small>
</div>
<div class="form-group"> <div class="form-group">
<label> <label>
<input type="checkbox" id="stream-toggle" /> <input type="checkbox" id="stream-toggle" />

View File

@@ -1457,6 +1457,7 @@ async function handleSaveSettings(e) {
const apiKey = document.getElementById('api-key').value.trim(); const apiKey = document.getElementById('api-key').value.trim();
const model = document.getElementById('model-select').value; const model = document.getElementById('model-select').value;
const stream = document.getElementById('stream-toggle').checked; const stream = document.getElementById('stream-toggle').checked;
const contextLimit = parseInt(document.getElementById('context-limit').value) || 200000;
const saveBtn = document.getElementById('save-settings-btn'); const saveBtn = document.getElementById('save-settings-btn');
const validationMsg = document.getElementById('validation-message'); const validationMsg = document.getElementById('validation-message');
@@ -1472,7 +1473,7 @@ async function handleSaveSettings(e) {
setStatus('Saving configuration...', 'default'); setStatus('Saving configuration...', 'default');
try { try {
await invoke('save_api_config', { baseUrl, apiKey, model, stream }); await invoke('save_api_config', { baseUrl, apiKey, model, stream, contextLimit });
validationMsg.textContent = 'Configuration saved successfully'; validationMsg.textContent = 'Configuration saved successfully';
validationMsg.className = 'validation-message success'; validationMsg.className = 'validation-message success';
setStatus('Configuration saved', 'success'); setStatus('Configuration saved', 'success');
@@ -1661,10 +1662,18 @@ async function updateTokenCount() {
currentInput currentInput
}); });
// Get context limit from config
let contextLimit = 200000; // Default
try {
const config = await invoke('get_api_config');
contextLimit = config.context_limit || 200000;
} catch (e) {
// Use default if config not available
}
// Update total display // Update total display
const tokenCounter = document.getElementById('token-counter'); const tokenCounter = document.getElementById('token-counter');
const tokenCountTotal = document.getElementById('token-count-total'); const tokenCountTotal = document.getElementById('token-count-total');
const contextLimit = 200000; // Claude 200k context
// Format: "2.5k / 200k tokens" // Format: "2.5k / 200k tokens"
tokenCountTotal.textContent = `${formatTokenCount(tokenData.total)} / ${formatTokenCount(contextLimit)} tokens`; tokenCountTotal.textContent = `${formatTokenCount(tokenData.total)} / ${formatTokenCount(contextLimit)} tokens`;
@@ -3339,6 +3348,7 @@ async function loadExistingConfig() {
document.getElementById('api-base-url').value = config.base_url; document.getElementById('api-base-url').value = config.base_url;
document.getElementById('api-key').value = config.api_key; document.getElementById('api-key').value = config.api_key;
document.getElementById('stream-toggle').checked = config.stream || false; document.getElementById('stream-toggle').checked = config.stream || false;
document.getElementById('context-limit').value = config.context_limit || 200000;
const modelSelect = document.getElementById('model-select'); const modelSelect = document.getElementById('model-select');
modelSelect.innerHTML = ''; // Clear existing options modelSelect.innerHTML = ''; // Clear existing options