generated from nhcarrigan/template
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 79de8ace44 |
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hikari-desktop",
|
"name": "hikari-desktop",
|
||||||
"version": "1.15.0",
|
"version": "1.14.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
"@tauri-apps/api": "2.10.1",
|
"@tauri-apps/api": "2.10.1",
|
||||||
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
||||||
"@tauri-apps/plugin-dialog": "2.6.0",
|
"@tauri-apps/plugin-dialog": "2.6.0",
|
||||||
"@tauri-apps/plugin-fs": "2.4.5",
|
"@tauri-apps/plugin-fs": "2.5.0",
|
||||||
"@tauri-apps/plugin-notification": "2.3.3",
|
"@tauri-apps/plugin-notification": "2.3.3",
|
||||||
"@tauri-apps/plugin-opener": "2.5.3",
|
"@tauri-apps/plugin-opener": "2.5.3",
|
||||||
"@tauri-apps/plugin-os": "2.3.2",
|
"@tauri-apps/plugin-os": "2.3.2",
|
||||||
|
|||||||
Generated
+5
-5
@@ -96,8 +96,8 @@ importers:
|
|||||||
specifier: 2.6.0
|
specifier: 2.6.0
|
||||||
version: 2.6.0
|
version: 2.6.0
|
||||||
'@tauri-apps/plugin-fs':
|
'@tauri-apps/plugin-fs':
|
||||||
specifier: 2.4.5
|
specifier: 2.5.0
|
||||||
version: 2.4.5
|
version: 2.5.0
|
||||||
'@tauri-apps/plugin-notification':
|
'@tauri-apps/plugin-notification':
|
||||||
specifier: 2.3.3
|
specifier: 2.3.3
|
||||||
version: 2.3.3
|
version: 2.3.3
|
||||||
@@ -993,8 +993,8 @@ packages:
|
|||||||
'@tauri-apps/plugin-dialog@2.6.0':
|
'@tauri-apps/plugin-dialog@2.6.0':
|
||||||
resolution: {integrity: sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==}
|
resolution: {integrity: sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==}
|
||||||
|
|
||||||
'@tauri-apps/plugin-fs@2.4.5':
|
'@tauri-apps/plugin-fs@2.5.0':
|
||||||
resolution: {integrity: sha512-dVxWWGE6VrOxC7/jlhyE+ON/Cc2REJlM35R3PJX3UvFw2XwYhLGQVAIyrehenDdKjotipjYEVc4YjOl3qq90fA==}
|
resolution: {integrity: sha512-c83kbz61AK+rKjhS+je9+stIO27nXj7p9cqeg36TwkIUtxpCFTttlHHtqon6h6FN54cXjyAjlMPOJcW3mwE5XQ==}
|
||||||
|
|
||||||
'@tauri-apps/plugin-notification@2.3.3':
|
'@tauri-apps/plugin-notification@2.3.3':
|
||||||
resolution: {integrity: sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg==}
|
resolution: {integrity: sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg==}
|
||||||
@@ -2935,7 +2935,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@tauri-apps/api': 2.10.1
|
'@tauri-apps/api': 2.10.1
|
||||||
|
|
||||||
'@tauri-apps/plugin-fs@2.4.5':
|
'@tauri-apps/plugin-fs@2.5.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tauri-apps/api': 2.10.1
|
'@tauri-apps/api': 2.10.1
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -1648,7 +1648,7 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hikari-desktop"
|
name = "hikari-desktop"
|
||||||
version = "1.15.0"
|
version = "1.14.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"dirs 5.0.1",
|
"dirs 5.0.1",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "hikari-desktop"
|
name = "hikari-desktop"
|
||||||
version = "1.15.0"
|
version = "1.14.0"
|
||||||
description = "Hikari - Claude Code Visual Assistant"
|
description = "Hikari - Claude Code Visual Assistant"
|
||||||
authors = ["Naomi Carrigan"]
|
authors = ["Naomi Carrigan"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -70,16 +70,6 @@ pub struct ClaudeStartOptions {
|
|||||||
/// Sets `ANTHROPIC_CUSTOM_MODEL_OPTION` env var for custom model providers (v2.1.81+).
|
/// Sets `ANTHROPIC_CUSTOM_MODEL_OPTION` env var for custom model providers (v2.1.81+).
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub custom_model_option: Option<String>,
|
pub custom_model_option: Option<String>,
|
||||||
|
|
||||||
/// Passes `--effort <level>` to set the effort level (v2.1.111+).
|
|
||||||
/// Valid values: "low", "medium", "high", "xhigh" (Opus 4.7 only), "max". None uses CLI default.
|
|
||||||
#[serde(default)]
|
|
||||||
pub effort_level: Option<String>,
|
|
||||||
|
|
||||||
/// Sets `ENABLE_PROMPT_CACHING_1H=1` or `FORCE_PROMPT_CACHING_5M=1` env var (v2.1.108+).
|
|
||||||
/// Values: "1h" → 1-hour TTL, "5m" → force 5-minute TTL. None uses CLI default.
|
|
||||||
#[serde(default)]
|
|
||||||
pub prompt_caching_ttl: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@@ -246,16 +236,6 @@ pub struct HikariConfig {
|
|||||||
/// Sets `ANTHROPIC_CUSTOM_MODEL_OPTION` env var for custom model providers (v2.1.81+).
|
/// Sets `ANTHROPIC_CUSTOM_MODEL_OPTION` env var for custom model providers (v2.1.81+).
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub custom_model_option: Option<String>,
|
pub custom_model_option: Option<String>,
|
||||||
|
|
||||||
/// Passes `--effort <level>` to set the effort level (v2.1.111+).
|
|
||||||
/// Valid values: "low", "medium", "high", "xhigh" (Opus 4.7 only), "max". None uses CLI default.
|
|
||||||
#[serde(default)]
|
|
||||||
pub effort_level: Option<String>,
|
|
||||||
|
|
||||||
/// Sets `ENABLE_PROMPT_CACHING_1H=1` or `FORCE_PROMPT_CACHING_5M=1` env var (v2.1.108+).
|
|
||||||
/// Values: "1h" → 1-hour TTL, "5m" → force 5-minute TTL. None uses CLI default.
|
|
||||||
#[serde(default)]
|
|
||||||
pub prompt_caching_ttl: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for HikariConfig {
|
impl Default for HikariConfig {
|
||||||
@@ -311,8 +291,6 @@ impl Default for HikariConfig {
|
|||||||
bare_mode: false,
|
bare_mode: false,
|
||||||
show_clear_context_on_plan_accept: true,
|
show_clear_context_on_plan_accept: true,
|
||||||
custom_model_option: None,
|
custom_model_option: None,
|
||||||
effort_level: None,
|
|
||||||
prompt_caching_ttl: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -530,8 +508,6 @@ mod tests {
|
|||||||
bare_mode: false,
|
bare_mode: false,
|
||||||
show_clear_context_on_plan_accept: true,
|
show_clear_context_on_plan_accept: true,
|
||||||
custom_model_option: None,
|
custom_model_option: None,
|
||||||
effort_level: None,
|
|
||||||
prompt_caching_ttl: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let json = serde_json::to_string(&config).unwrap();
|
let json = serde_json::to_string(&config).unwrap();
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ pub async fn list_sessions(app: AppHandle) -> Result<Vec<SessionListItem>, Strin
|
|||||||
let mut items: Vec<SessionListItem> = sessions.iter().map(SessionListItem::from).collect();
|
let mut items: Vec<SessionListItem> = sessions.iter().map(SessionListItem::from).collect();
|
||||||
|
|
||||||
// Sort by last activity, most recent first
|
// Sort by last activity, most recent first
|
||||||
items.sort_by_key(|b| std::cmp::Reverse(b.last_activity_at));
|
items.sort_by(|a, b| b.last_activity_at.cmp(&a.last_activity_at));
|
||||||
|
|
||||||
Ok(items)
|
Ok(items)
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ pub async fn search_sessions(app: AppHandle, query: String) -> Result<Vec<Sessio
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Sort by last activity, most recent first
|
// Sort by last activity, most recent first
|
||||||
matching.sort_by_key(|b| std::cmp::Reverse(b.last_activity_at));
|
matching.sort_by(|a, b| b.last_activity_at.cmp(&a.last_activity_at));
|
||||||
|
|
||||||
Ok(matching)
|
Ok(matching)
|
||||||
}
|
}
|
||||||
@@ -348,7 +348,7 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Sort by last activity, most recent first (mimics list_sessions behavior)
|
// Sort by last activity, most recent first (mimics list_sessions behavior)
|
||||||
sessions.sort_by_key(|b| std::cmp::Reverse(b.last_activity_at));
|
sessions.sort_by(|a, b| b.last_activity_at.cmp(&a.last_activity_at));
|
||||||
|
|
||||||
assert_eq!(sessions[0].id, "new");
|
assert_eq!(sessions[0].id, "new");
|
||||||
assert_eq!(sessions[1].id, "old");
|
assert_eq!(sessions[1].id, "old");
|
||||||
|
|||||||
+7
-30
@@ -86,10 +86,9 @@ impl ContextWarning {
|
|||||||
/// Get the context window limit (in tokens) for a given model
|
/// Get the context window limit (in tokens) for a given model
|
||||||
fn get_context_window_limit(model: &str) -> u64 {
|
fn get_context_window_limit(model: &str) -> u64 {
|
||||||
match model {
|
match model {
|
||||||
// Claude 4.7 - 1M token context window
|
// Claude 4.6 family
|
||||||
"claude-opus-4-7" => 1_000_000,
|
"claude-opus-4-6" => 200_000,
|
||||||
// Claude 4.6 family - 1M token context window
|
"claude-sonnet-4-6" => 1_000_000, // 1M token context window
|
||||||
"claude-opus-4-6" | "claude-sonnet-4-6" => 1_000_000,
|
|
||||||
// Claude 4.5 family - 200K standard context
|
// Claude 4.5 family - 200K standard context
|
||||||
"claude-opus-4-5-20251101"
|
"claude-opus-4-5-20251101"
|
||||||
| "claude-sonnet-4-5-20250929"
|
| "claude-sonnet-4-5-20250929"
|
||||||
@@ -491,7 +490,7 @@ fn is_consecutive_day(prev_date: &str, current_date: &str) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pricing as of May 2026
|
// Pricing as of February 2026
|
||||||
// https://platform.claude.com/docs/en/about-claude/models/overview
|
// https://platform.claude.com/docs/en/about-claude/models/overview
|
||||||
// Cache pricing: https://platform.claude.com/docs/en/build-with-claude/prompt-caching
|
// Cache pricing: https://platform.claude.com/docs/en/build-with-claude/prompt-caching
|
||||||
pub fn calculate_cost(
|
pub fn calculate_cost(
|
||||||
@@ -502,17 +501,14 @@ pub fn calculate_cost(
|
|||||||
cache_read_tokens: Option<u64>,
|
cache_read_tokens: Option<u64>,
|
||||||
) -> f64 {
|
) -> f64 {
|
||||||
let (input_price_per_million, output_price_per_million) = match model {
|
let (input_price_per_million, output_price_per_million) = match model {
|
||||||
// Current generation (Claude 4.7/4.6/4.5)
|
// Current generation (Claude 4.6)
|
||||||
"claude-opus-4-7" => (5.0, 25.0),
|
|
||||||
"claude-sonnet-4-6" => (3.0, 15.0),
|
|
||||||
"claude-haiku-4-5-20251001" => (1.0, 5.0),
|
|
||||||
|
|
||||||
// Previous generation (Claude 4.6)
|
|
||||||
"claude-opus-4-6" => (5.0, 25.0),
|
"claude-opus-4-6" => (5.0, 25.0),
|
||||||
|
"claude-sonnet-4-6" => (3.0, 15.0),
|
||||||
|
|
||||||
// Previous generation (Claude 4.5)
|
// Previous generation (Claude 4.5)
|
||||||
"claude-opus-4-5-20251101" => (5.0, 25.0),
|
"claude-opus-4-5-20251101" => (5.0, 25.0),
|
||||||
"claude-sonnet-4-5-20250929" => (3.0, 15.0),
|
"claude-sonnet-4-5-20250929" => (3.0, 15.0),
|
||||||
|
"claude-haiku-4-5-20251001" => (1.0, 5.0),
|
||||||
|
|
||||||
// Previous generation (Claude 4.x)
|
// Previous generation (Claude 4.x)
|
||||||
"claude-opus-4-1-20250805" => (15.0, 75.0),
|
"claude-opus-4-1-20250805" => (15.0, 75.0),
|
||||||
@@ -685,15 +681,6 @@ mod tests {
|
|||||||
assert!((cost - 0.165).abs() < 0.0001);
|
assert!((cost - 0.165).abs() < 0.0001);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cost_calculation_opus_47() {
|
|
||||||
let cost = calculate_cost(1000, 2000, "claude-opus-4-7", None, None);
|
|
||||||
// Opus 4.7 pricing: $5/MTok input, $25/MTok output
|
|
||||||
// 1000 input tokens = $0.005, 2000 output tokens = $0.05
|
|
||||||
// Total = $0.055
|
|
||||||
assert!((cost - 0.055).abs() < 0.0001);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cost_calculation_opus_45() {
|
fn test_cost_calculation_opus_45() {
|
||||||
let cost = calculate_cost(1000, 2000, "claude-opus-4-5-20251101", None, None);
|
let cost = calculate_cost(1000, 2000, "claude-opus-4-5-20251101", None, None);
|
||||||
@@ -1032,16 +1019,6 @@ mod tests {
|
|||||||
// Context Window Tracking tests
|
// Context Window Tracking tests
|
||||||
// =====================
|
// =====================
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_context_window_limit_opus_47() {
|
|
||||||
assert_eq!(get_context_window_limit("claude-opus-4-7"), 1_000_000);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_context_window_limit_opus_46() {
|
|
||||||
assert_eq!(get_context_window_limit("claude-opus-4-6"), 1_000_000);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_context_window_limit_claude_4() {
|
fn test_context_window_limit_claude_4() {
|
||||||
assert_eq!(get_context_window_limit("claude-opus-4-5-20251101"), 200_000);
|
assert_eq!(get_context_window_limit("claude-opus-4-5-20251101"), 200_000);
|
||||||
|
|||||||
@@ -98,10 +98,6 @@ pub enum ClaudeMessage {
|
|||||||
/// Output style hint from Claude Code (v2.1.81+). Informational only.
|
/// Output style hint from Claude Code (v2.1.81+). Informational only.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
output_style: Option<String>,
|
output_style: Option<String>,
|
||||||
/// Plugin errors from Claude Code (v2.1.111+). Populated when plugins are demoted
|
|
||||||
/// due to unsatisfied dependencies.
|
|
||||||
#[serde(default)]
|
|
||||||
plugin_errors: Option<serde_json::Value>,
|
|
||||||
},
|
},
|
||||||
#[serde(rename = "assistant")]
|
#[serde(rename = "assistant")]
|
||||||
Assistant {
|
Assistant {
|
||||||
@@ -334,14 +330,6 @@ pub struct PostCompactEvent {
|
|||||||
pub conversation_id: Option<String>,
|
pub conversation_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct PreCompactEvent {
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub session_id: Option<String>,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub conversation_id: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct CwdChangedEvent {
|
pub struct CwdChangedEvent {
|
||||||
pub cwd: String,
|
pub cwd: String,
|
||||||
@@ -802,30 +790,6 @@ mod tests {
|
|||||||
assert!(!serialized.contains("conversation_id"));
|
assert!(!serialized.contains("conversation_id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_pre_compact_event_serialization() {
|
|
||||||
let event = PreCompactEvent {
|
|
||||||
session_id: Some("sess-abc".to_string()),
|
|
||||||
conversation_id: Some("conv-123".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let serialized = serde_json::to_string(&event).unwrap();
|
|
||||||
assert!(serialized.contains("\"session_id\":\"sess-abc\""));
|
|
||||||
assert!(serialized.contains("\"conversation_id\":\"conv-123\""));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_pre_compact_event_omits_none_fields() {
|
|
||||||
let event = PreCompactEvent {
|
|
||||||
session_id: None,
|
|
||||||
conversation_id: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let serialized = serde_json::to_string(&event).unwrap();
|
|
||||||
assert!(!serialized.contains("session_id"));
|
|
||||||
assert!(!serialized.contains("conversation_id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cwd_changed_event_serialization() {
|
fn test_cwd_changed_event_serialization() {
|
||||||
let event = CwdChangedEvent {
|
let event = CwdChangedEvent {
|
||||||
@@ -981,44 +945,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_system_init_with_plugin_errors() {
|
|
||||||
let json = r#"{"type":"system","subtype":"init","session_id":"sess-1","plugin_errors":["Plugin 'foo' requires 'bar' which is not installed","Plugin 'baz' failed to load"]}"#;
|
|
||||||
let msg: ClaudeMessage = serde_json::from_str(json).unwrap();
|
|
||||||
if let ClaudeMessage::System { plugin_errors, .. } = msg {
|
|
||||||
let errors = plugin_errors.expect("plugin_errors should be present");
|
|
||||||
let arr = errors.as_array().expect("plugin_errors should be an array");
|
|
||||||
assert_eq!(arr.len(), 2);
|
|
||||||
assert_eq!(arr[0].as_str(), Some("Plugin 'foo' requires 'bar' which is not installed"));
|
|
||||||
} else {
|
|
||||||
panic!("Expected System variant");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_system_init_without_plugin_errors() {
|
|
||||||
let json = r#"{"type":"system","subtype":"init","session_id":"sess-1"}"#;
|
|
||||||
let msg: ClaudeMessage = serde_json::from_str(json).unwrap();
|
|
||||||
if let ClaudeMessage::System { plugin_errors, .. } = msg {
|
|
||||||
assert!(plugin_errors.is_none());
|
|
||||||
} else {
|
|
||||||
panic!("Expected System variant");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_system_init_with_empty_plugin_errors() {
|
|
||||||
let json = r#"{"type":"system","subtype":"init","session_id":"sess-1","plugin_errors":[]}"#;
|
|
||||||
let msg: ClaudeMessage = serde_json::from_str(json).unwrap();
|
|
||||||
if let ClaudeMessage::System { plugin_errors, .. } = msg {
|
|
||||||
let errors = plugin_errors.expect("plugin_errors should be present");
|
|
||||||
let arr = errors.as_array().expect("plugin_errors should be an array");
|
|
||||||
assert!(arr.is_empty());
|
|
||||||
} else {
|
|
||||||
panic!("Expected System variant");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_result_message_with_fast_mode_state() {
|
fn test_result_message_with_fast_mode_state() {
|
||||||
let json = r#"{"type":"result","subtype":"success","fast_mode_state":"enabled"}"#;
|
let json = r#"{"type":"result","subtype":"success","fast_mode_state":"enabled"}"#;
|
||||||
|
|||||||
+6
-119
@@ -17,7 +17,7 @@ use crate::types::{
|
|||||||
AgentEndEvent, AgentStartEvent, CharacterState, ClaudeMessage, ConnectionEvent,
|
AgentEndEvent, AgentStartEvent, CharacterState, ClaudeMessage, ConnectionEvent,
|
||||||
ConnectionStatus, ContentBlock, CwdChangedEvent, ElicitationEvent, ElicitationResultEvent,
|
ConnectionStatus, ContentBlock, CwdChangedEvent, ElicitationEvent, ElicitationResultEvent,
|
||||||
FileChangedEvent, MessageCost, OutputEvent, PermissionDeniedEvent, PermissionPromptEvent,
|
FileChangedEvent, MessageCost, OutputEvent, PermissionDeniedEvent, PermissionPromptEvent,
|
||||||
PermissionPromptEventItem, PostCompactEvent, PreCompactEvent, QuestionOption, SessionEvent, StateChangeEvent,
|
PermissionPromptEventItem, PostCompactEvent, QuestionOption, SessionEvent, StateChangeEvent,
|
||||||
StopFailureEvent, TaskCreatedEvent, TodoItem, TodoUpdateEvent, UserQuestionEvent,
|
StopFailureEvent, TaskCreatedEvent, TodoItem, TodoUpdateEvent, UserQuestionEvent,
|
||||||
WorkingDirectoryEvent, WorktreeEvent, WorktreeInfo,
|
WorkingDirectoryEvent, WorktreeEvent, WorktreeInfo,
|
||||||
};
|
};
|
||||||
@@ -308,14 +308,6 @@ impl WslBridge {
|
|||||||
cmd.arg("--bare");
|
cmd.arg("--bare");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add effort level if specified (v2.1.111+)
|
|
||||||
if let Some(ref level) = options.effort_level {
|
|
||||||
if !level.is_empty() {
|
|
||||||
cmd.arg("--effort");
|
|
||||||
cmd.arg(level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass combined settings via --settings flag if any settings are specified
|
// Pass combined settings via --settings flag if any settings are specified
|
||||||
{
|
{
|
||||||
let has_memory_dir = options
|
let has_memory_dir = options
|
||||||
@@ -410,15 +402,6 @@ impl WslBridge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set prompt caching TTL env var if specified (v2.1.108+)
|
|
||||||
if let Some(ref ttl) = options.prompt_caching_ttl {
|
|
||||||
match ttl.as_str() {
|
|
||||||
"1h" => { cmd.env("ENABLE_PROMPT_CACHING_1H", "1"); }
|
|
||||||
"5m" => { cmd.env("FORCE_PROMPT_CACHING_5M", "1"); }
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd
|
cmd
|
||||||
} else {
|
} else {
|
||||||
// Running on Windows - use wsl with bash login shell to ensure PATH is loaded
|
// Running on Windows - use wsl with bash login shell to ensure PATH is loaded
|
||||||
@@ -494,15 +477,6 @@ impl WslBridge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set prompt caching TTL env var if specified (v2.1.108+)
|
|
||||||
if let Some(ref ttl) = options.prompt_caching_ttl {
|
|
||||||
match ttl.as_str() {
|
|
||||||
"1h" => { claude_cmd.push_str("ENABLE_PROMPT_CACHING_1H=1 "); }
|
|
||||||
"5m" => { claude_cmd.push_str("FORCE_PROMPT_CACHING_5M=1 "); }
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
claude_cmd.push_str(
|
claude_cmd.push_str(
|
||||||
"claude --output-format stream-json --input-format stream-json --verbose",
|
"claude --output-format stream-json --input-format stream-json --verbose",
|
||||||
);
|
);
|
||||||
@@ -558,13 +532,6 @@ impl WslBridge {
|
|||||||
claude_cmd.push_str(" --bare");
|
claude_cmd.push_str(" --bare");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add effort level if specified (v2.1.111+)
|
|
||||||
if let Some(ref level) = options.effort_level {
|
|
||||||
if !level.is_empty() {
|
|
||||||
claude_cmd.push_str(&format!(" --effort {}", level));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass combined settings via --settings flag if any settings are specified
|
// Pass combined settings via --settings flag if any settings are specified
|
||||||
{
|
{
|
||||||
let has_memory_dir = options
|
let has_memory_dir = options
|
||||||
@@ -920,9 +887,10 @@ impl WslBridge {
|
|||||||
let stats = self.stats.read();
|
let stats = self.stats.read();
|
||||||
for tool_name in &tools {
|
for tool_name in &tools {
|
||||||
if let Some(tool_stats) = stats.session_tools_usage.get(tool_name) {
|
if let Some(tool_stats) = stats.session_tools_usage.get(tool_name) {
|
||||||
if let Some(avg_tokens) = (tool_stats.estimated_input_tokens + tool_stats.estimated_output_tokens)
|
if tool_stats.call_count > 0 {
|
||||||
.checked_div(tool_stats.call_count)
|
// Use session average tokens per call for this tool
|
||||||
{
|
let avg_tokens = (tool_stats.estimated_input_tokens + tool_stats.estimated_output_tokens)
|
||||||
|
/ tool_stats.call_count;
|
||||||
tool_overhead_tokens += avg_tokens;
|
tool_overhead_tokens += avg_tokens;
|
||||||
tracing::info!("[COST ESTIMATION] Tool {} average: {} tokens", tool_name, avg_tokens);
|
tracing::info!("[COST ESTIMATION] Tool {} average: {} tokens", tool_name, avg_tokens);
|
||||||
}
|
}
|
||||||
@@ -1172,7 +1140,6 @@ fn handle_stderr(
|
|||||||
let is_elicitation = line.contains("[Elicitation Hook]");
|
let is_elicitation = line.contains("[Elicitation Hook]");
|
||||||
let is_elicitation_result = line.contains("[ElicitationResult Hook]");
|
let is_elicitation_result = line.contains("[ElicitationResult Hook]");
|
||||||
let is_stop_failure = line.contains("[StopFailure Hook]");
|
let is_stop_failure = line.contains("[StopFailure Hook]");
|
||||||
let is_pre_compact = line.contains("[PreCompact Hook]");
|
|
||||||
let is_post_compact = line.contains("[PostCompact Hook]");
|
let is_post_compact = line.contains("[PostCompact Hook]");
|
||||||
let is_cwd_changed = line.contains("[CwdChanged Hook]");
|
let is_cwd_changed = line.contains("[CwdChanged Hook]");
|
||||||
let is_file_changed = line.contains("[FileChanged Hook]");
|
let is_file_changed = line.contains("[FileChanged Hook]");
|
||||||
@@ -1187,7 +1154,7 @@ fn handle_stderr(
|
|||||||
"elicitation"
|
"elicitation"
|
||||||
} else if is_stop_failure {
|
} else if is_stop_failure {
|
||||||
"error"
|
"error"
|
||||||
} else if is_pre_compact || is_post_compact {
|
} else if is_post_compact {
|
||||||
"compact-prompt"
|
"compact-prompt"
|
||||||
} else if is_cwd_changed {
|
} else if is_cwd_changed {
|
||||||
"cwd-changed"
|
"cwd-changed"
|
||||||
@@ -1313,28 +1280,6 @@ fn handle_stderr(
|
|||||||
parent_tool_use_id: None,
|
parent_tool_use_id: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else if is_pre_compact {
|
|
||||||
let data = parse_pre_compact_hook(&line);
|
|
||||||
|
|
||||||
let _ = app.emit(
|
|
||||||
"claude:pre-compact",
|
|
||||||
PreCompactEvent {
|
|
||||||
session_id: data.session_id,
|
|
||||||
conversation_id: conversation_id.clone(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let _ = app.emit(
|
|
||||||
"claude:output",
|
|
||||||
OutputEvent {
|
|
||||||
line_type: "compact-prompt".to_string(),
|
|
||||||
content: "Compacting context — conversation history is being summarised to free up space.".to_string(),
|
|
||||||
tool_name: None,
|
|
||||||
conversation_id: conversation_id.clone(),
|
|
||||||
cost: None,
|
|
||||||
parent_tool_use_id: None,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else if is_post_compact {
|
} else if is_post_compact {
|
||||||
let data = parse_post_compact_hook(&line);
|
let data = parse_post_compact_hook(&line);
|
||||||
|
|
||||||
@@ -1678,16 +1623,6 @@ fn build_stop_failure_message(data: &StopFailureData) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct PreCompactData {
|
|
||||||
session_id: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_pre_compact_hook(line: &str) -> PreCompactData {
|
|
||||||
let session_id = extract_debug_string_value(line, "session_id");
|
|
||||||
PreCompactData { session_id }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct PostCompactData {
|
struct PostCompactData {
|
||||||
session_id: Option<String>,
|
session_id: Option<String>,
|
||||||
@@ -1849,7 +1784,6 @@ fn process_json_line(
|
|||||||
subtype,
|
subtype,
|
||||||
session_id,
|
session_id,
|
||||||
cwd,
|
cwd,
|
||||||
plugin_errors,
|
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if subtype == "init" {
|
if subtype == "init" {
|
||||||
@@ -1874,31 +1808,6 @@ fn process_json_line(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn about any plugins that failed to load (v2.1.111+)
|
|
||||||
if let Some(errors) = plugin_errors {
|
|
||||||
if let Some(arr) = errors.as_array() {
|
|
||||||
for error in arr {
|
|
||||||
let msg = if let Some(s) = error.as_str() {
|
|
||||||
s.to_string()
|
|
||||||
} else {
|
|
||||||
error.to_string()
|
|
||||||
};
|
|
||||||
let _ = app.emit(
|
|
||||||
"claude:output",
|
|
||||||
OutputEvent {
|
|
||||||
line_type: "error".to_string(),
|
|
||||||
content: format!("Plugin error: {}", msg),
|
|
||||||
tool_name: None,
|
|
||||||
conversation_id: conversation_id.clone(),
|
|
||||||
cost: None,
|
|
||||||
parent_tool_use_id: None,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit_state_change(app, CharacterState::Idle, None, conversation_id.clone());
|
emit_state_change(app, CharacterState::Idle, None, conversation_id.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3978,28 +3887,6 @@ mod tests {
|
|||||||
assert_eq!(data.session_id, None);
|
assert_eq!(data.session_id, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_pre_compact_hook_with_session_id() {
|
|
||||||
let line =
|
|
||||||
r#"[PreCompact Hook] session_id=Some("sess-abc123"), conversation_id=Some("conv-xyz")"#;
|
|
||||||
let data = parse_pre_compact_hook(line);
|
|
||||||
assert_eq!(data.session_id, Some("sess-abc123".to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_pre_compact_hook_without_session_id() {
|
|
||||||
let line = "[PreCompact Hook] session_id=None";
|
|
||||||
let data = parse_pre_compact_hook(line);
|
|
||||||
assert_eq!(data.session_id, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_pre_compact_hook_empty_line() {
|
|
||||||
let line = "[PreCompact Hook]";
|
|
||||||
let data = parse_pre_compact_hook(line);
|
|
||||||
assert_eq!(data.session_id, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_cwd_changed_hook_with_cwd_key() {
|
fn test_parse_cwd_changed_hook_with_cwd_key() {
|
||||||
let line = r#"[CwdChanged Hook] cwd="/home/naomi/code/my-project""#;
|
let line = r#"[CwdChanged Hook] cwd="/home/naomi/code/my-project""#;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "hikari-desktop",
|
"productName": "hikari-desktop",
|
||||||
"version": "1.15.0",
|
"version": "1.14.0",
|
||||||
"identifier": "com.naomi.hikari-desktop",
|
"identifier": "com.naomi.hikari-desktop",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "pnpm dev",
|
"beforeDevCommand": "pnpm dev",
|
||||||
|
|||||||
@@ -77,8 +77,6 @@ async function changeDirectory(path: string): Promise<void> {
|
|||||||
bare_mode: config.bare_mode ?? false,
|
bare_mode: config.bare_mode ?? false,
|
||||||
show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true,
|
show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true,
|
||||||
custom_model_option: config.custom_model_option || null,
|
custom_model_option: config.custom_model_option || null,
|
||||||
effort_level: config.effort_level || null,
|
|
||||||
prompt_caching_ttl: config.prompt_caching_ttl || null,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -166,8 +164,6 @@ async function startNewConversation(): Promise<void> {
|
|||||||
bare_mode: config.bare_mode ?? false,
|
bare_mode: config.bare_mode ?? false,
|
||||||
show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true,
|
show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true,
|
||||||
custom_model_option: config.custom_model_option || null,
|
custom_model_option: config.custom_model_option || null,
|
||||||
effort_level: config.effort_level || null,
|
|
||||||
prompt_caching_ttl: config.prompt_caching_ttl || null,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
const SUPPORTED_CLI_VERSION = "2.1.131";
|
const SUPPORTED_CLI_VERSION = "2.1.104";
|
||||||
|
|
||||||
let installedVersion = $state("Loading...");
|
let installedVersion = $state("Loading...");
|
||||||
let latestNpmVersion = $state<string | null>(null);
|
let latestNpmVersion = $state<string | null>(null);
|
||||||
|
|||||||
@@ -78,8 +78,6 @@
|
|||||||
task_loop_auto_commit: false,
|
task_loop_auto_commit: false,
|
||||||
task_loop_commit_prefix: "feat",
|
task_loop_commit_prefix: "feat",
|
||||||
task_loop_include_summary: false,
|
task_loop_include_summary: false,
|
||||||
effort_level: null,
|
|
||||||
prompt_caching_ttl: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let showCustomThemeEditor = $state(false);
|
let showCustomThemeEditor = $state(false);
|
||||||
@@ -146,20 +144,17 @@
|
|||||||
|
|
||||||
const availableModels = [
|
const availableModels = [
|
||||||
{ value: "", label: "Default (from ~/.claude)" },
|
{ value: "", label: "Default (from ~/.claude)" },
|
||||||
// Current generation (Claude 4.7/4.6/4.5)
|
// Current generation (Claude 4.6)
|
||||||
{ value: "claude-opus-4-7", label: "Claude Opus 4.7 (Most Capable)" },
|
{ value: "claude-opus-4-6", label: "Claude Opus 4.6 (Most Capable)" },
|
||||||
{ value: "claude-sonnet-4-6", label: "Claude Sonnet 4.6 (Recommended)" },
|
{ value: "claude-sonnet-4-6", label: "Claude Sonnet 4.6 (Recommended)" },
|
||||||
{ value: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5 (Fast & Cheap)" },
|
|
||||||
// Previous generation (Claude 4.6)
|
|
||||||
{ value: "claude-opus-4-6", label: "Claude Opus 4.6" },
|
|
||||||
// Previous generation (Claude 4.5)
|
// Previous generation (Claude 4.5)
|
||||||
{ value: "claude-sonnet-4-5-20250929", label: "Claude Sonnet 4.5" },
|
{ value: "claude-sonnet-4-5-20250929", label: "Claude Sonnet 4.5" },
|
||||||
|
{ value: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5 (Fast & Cheap)" },
|
||||||
{ value: "claude-opus-4-5-20251101", label: "Claude Opus 4.5" },
|
{ value: "claude-opus-4-5-20251101", label: "Claude Opus 4.5" },
|
||||||
// Previous generation (Claude 4.x)
|
// Previous generation (Claude 4.x)
|
||||||
{ value: "claude-opus-4-1-20250805", label: "Claude Opus 4.1" },
|
{ value: "claude-opus-4-1-20250805", label: "Claude Opus 4.1" },
|
||||||
// Deprecated — retire June 15, 2026
|
{ value: "claude-sonnet-4-20250514", label: "Claude Sonnet 4" },
|
||||||
{ value: "claude-sonnet-4-20250514", label: "Claude Sonnet 4 (Deprecated)" },
|
{ value: "claude-opus-4-20250514", label: "Claude Opus 4" },
|
||||||
{ value: "claude-opus-4-20250514", label: "Claude Opus 4 (Deprecated)" },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const commonTools = [
|
const commonTools = [
|
||||||
@@ -718,49 +713,6 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Effort Level -->
|
|
||||||
<div class="mb-4">
|
|
||||||
<label class="block text-sm text-[var(--text-primary)] mb-1" for="effort-level"
|
|
||||||
>Effort level</label
|
|
||||||
>
|
|
||||||
<select
|
|
||||||
id="effort-level"
|
|
||||||
bind:value={config.effort_level}
|
|
||||||
class="w-full px-3 py-2 rounded border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] text-sm focus:outline-none focus:ring-1 focus:ring-[var(--accent-primary)]"
|
|
||||||
>
|
|
||||||
<option value={null}>Default (CLI decides)</option>
|
|
||||||
<option value="low">Low</option>
|
|
||||||
<option value="medium">Medium</option>
|
|
||||||
<option value="high">High</option>
|
|
||||||
<option value="xhigh">Extra High (Opus 4.7 only)</option>
|
|
||||||
<option value="max">Max</option>
|
|
||||||
</select>
|
|
||||||
<p class="text-xs text-[var(--text-tertiary)] mt-1">
|
|
||||||
Passes <code class="font-mono">--effort</code> to tune speed vs. intelligence. Requires Claude
|
|
||||||
Code v2.1.111+.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Prompt Caching TTL -->
|
|
||||||
<div class="mb-4">
|
|
||||||
<label class="block text-sm text-[var(--text-primary)] mb-1" for="prompt-caching-ttl"
|
|
||||||
>Prompt caching TTL</label
|
|
||||||
>
|
|
||||||
<select
|
|
||||||
id="prompt-caching-ttl"
|
|
||||||
bind:value={config.prompt_caching_ttl}
|
|
||||||
class="w-full px-3 py-2 rounded border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] text-sm focus:outline-none focus:ring-1 focus:ring-[var(--accent-primary)]"
|
|
||||||
>
|
|
||||||
<option value={null}>Default (CLI decides)</option>
|
|
||||||
<option value="1h">1-hour TTL (reduces cost for long sessions)</option>
|
|
||||||
<option value="5m">Force 5-minute TTL</option>
|
|
||||||
</select>
|
|
||||||
<p class="text-xs text-[var(--text-tertiary)] mt-1">
|
|
||||||
Sets <code class="font-mono">ENABLE_PROMPT_CACHING_1H</code> or
|
|
||||||
<code class="font-mono">FORCE_PROMPT_CACHING_5M</code>. Requires Claude Code v2.1.108+.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bare Mode -->
|
<!-- Bare Mode -->
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label class="flex items-center gap-3 cursor-pointer">
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
|
|||||||
@@ -78,8 +78,6 @@
|
|||||||
bare_mode: config.bare_mode ?? false,
|
bare_mode: config.bare_mode ?? false,
|
||||||
show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true,
|
show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true,
|
||||||
custom_model_option: config.custom_model_option || null,
|
custom_model_option: config.custom_model_option || null,
|
||||||
effort_level: config.effort_level || null,
|
|
||||||
prompt_caching_ttl: config.prompt_caching_ttl || null,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -412,8 +412,6 @@ User: ${formattedMessage}`;
|
|||||||
bare_mode: config.bare_mode ?? false,
|
bare_mode: config.bare_mode ?? false,
|
||||||
show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true,
|
show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true,
|
||||||
custom_model_option: config.custom_model_option || null,
|
custom_model_option: config.custom_model_option || null,
|
||||||
effort_level: config.effort_level || null,
|
|
||||||
prompt_caching_ttl: config.prompt_caching_ttl || null,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -99,8 +99,6 @@
|
|||||||
bare_mode: config.bare_mode ?? false,
|
bare_mode: config.bare_mode ?? false,
|
||||||
show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true,
|
show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true,
|
||||||
custom_model_option: config.custom_model_option || null,
|
custom_model_option: config.custom_model_option || null,
|
||||||
effort_level: config.effort_level || null,
|
|
||||||
prompt_caching_ttl: config.prompt_caching_ttl || null,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -97,8 +97,6 @@
|
|||||||
bare_mode: false,
|
bare_mode: false,
|
||||||
show_clear_context_on_plan_accept: true,
|
show_clear_context_on_plan_accept: true,
|
||||||
custom_model_option: null,
|
custom_model_option: null,
|
||||||
effort_level: null,
|
|
||||||
prompt_caching_ttl: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let streamerModeActive = $state(false);
|
let streamerModeActive = $state(false);
|
||||||
@@ -191,8 +189,6 @@
|
|||||||
show_clear_context_on_plan_accept:
|
show_clear_context_on_plan_accept:
|
||||||
currentConfig.show_clear_context_on_plan_accept ?? true,
|
currentConfig.show_clear_context_on_plan_accept ?? true,
|
||||||
custom_model_option: currentConfig.custom_model_option || null,
|
custom_model_option: currentConfig.custom_model_option || null,
|
||||||
effort_level: currentConfig.effort_level || null,
|
|
||||||
prompt_caching_ttl: currentConfig.prompt_caching_ttl || null,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -361,8 +357,6 @@
|
|||||||
show_clear_context_on_plan_accept:
|
show_clear_context_on_plan_accept:
|
||||||
currentConfig.show_clear_context_on_plan_accept ?? true,
|
currentConfig.show_clear_context_on_plan_accept ?? true,
|
||||||
custom_model_option: currentConfig.custom_model_option || null,
|
custom_model_option: currentConfig.custom_model_option || null,
|
||||||
effort_level: currentConfig.effort_level || null,
|
|
||||||
prompt_caching_ttl: currentConfig.prompt_caching_ttl || null,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -228,8 +228,6 @@
|
|||||||
bare_mode: cfg.bare_mode ?? false,
|
bare_mode: cfg.bare_mode ?? false,
|
||||||
show_clear_context_on_plan_accept: cfg.show_clear_context_on_plan_accept ?? true,
|
show_clear_context_on_plan_accept: cfg.show_clear_context_on_plan_accept ?? true,
|
||||||
custom_model_option: cfg.custom_model_option || null,
|
custom_model_option: cfg.custom_model_option || null,
|
||||||
effort_level: cfg.effort_level || null,
|
|
||||||
prompt_caching_ttl: cfg.prompt_caching_ttl || null,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -118,8 +118,6 @@
|
|||||||
bare_mode: config.bare_mode ?? false,
|
bare_mode: config.bare_mode ?? false,
|
||||||
show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true,
|
show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true,
|
||||||
custom_model_option: config.custom_model_option || null,
|
custom_model_option: config.custom_model_option || null,
|
||||||
effort_level: config.effort_level || null,
|
|
||||||
prompt_caching_ttl: config.prompt_caching_ttl || null,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -229,8 +229,6 @@ describe("config store", () => {
|
|||||||
bare_mode: false,
|
bare_mode: false,
|
||||||
show_clear_context_on_plan_accept: true,
|
show_clear_context_on_plan_accept: true,
|
||||||
custom_model_option: null,
|
custom_model_option: null,
|
||||||
effort_level: null,
|
|
||||||
prompt_caching_ttl: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(config.model).toBe("claude-sonnet-4");
|
expect(config.model).toBe("claude-sonnet-4");
|
||||||
@@ -299,8 +297,6 @@ describe("config store", () => {
|
|||||||
bare_mode: false,
|
bare_mode: false,
|
||||||
show_clear_context_on_plan_accept: true,
|
show_clear_context_on_plan_accept: true,
|
||||||
custom_model_option: null,
|
custom_model_option: null,
|
||||||
effort_level: null,
|
|
||||||
prompt_caching_ttl: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(config.model).toBeNull();
|
expect(config.model).toBeNull();
|
||||||
@@ -924,8 +920,6 @@ describe("config store", () => {
|
|||||||
bare_mode: false,
|
bare_mode: false,
|
||||||
show_clear_context_on_plan_accept: true,
|
show_clear_context_on_plan_accept: true,
|
||||||
custom_model_option: null,
|
custom_model_option: null,
|
||||||
effort_level: null,
|
|
||||||
prompt_caching_ttl: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockInvokeImpl = vi.mocked(invoke);
|
const mockInvokeImpl = vi.mocked(invoke);
|
||||||
|
|||||||
@@ -99,10 +99,6 @@ export interface HikariConfig {
|
|||||||
show_clear_context_on_plan_accept: boolean;
|
show_clear_context_on_plan_accept: boolean;
|
||||||
// Custom model option env var (v2.1.81+)
|
// Custom model option env var (v2.1.81+)
|
||||||
custom_model_option: string | null;
|
custom_model_option: string | null;
|
||||||
// Effort level for Claude Code (v2.1.111+) — null means use CLI default
|
|
||||||
effort_level: string | null;
|
|
||||||
// Prompt caching TTL override (v2.1.108+) — null means use CLI default
|
|
||||||
prompt_caching_ttl: string | null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultConfig: HikariConfig = {
|
const defaultConfig: HikariConfig = {
|
||||||
@@ -165,8 +161,6 @@ const defaultConfig: HikariConfig = {
|
|||||||
bare_mode: false,
|
bare_mode: false,
|
||||||
show_clear_context_on_plan_accept: true,
|
show_clear_context_on_plan_accept: true,
|
||||||
custom_model_option: null,
|
custom_model_option: null,
|
||||||
effort_level: null,
|
|
||||||
prompt_caching_ttl: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function createConfigStore() {
|
function createConfigStore() {
|
||||||
|
|||||||
@@ -10,15 +10,13 @@ export type BudgetType = "token" | "cost";
|
|||||||
// Model pricing (per million tokens) - keep in sync with stats.rs
|
// Model pricing (per million tokens) - keep in sync with stats.rs
|
||||||
// Source: https://platform.claude.com/docs/en/about-claude/models/overview
|
// Source: https://platform.claude.com/docs/en/about-claude/models/overview
|
||||||
export const MODEL_PRICING: Record<string, { input: number; output: number }> = {
|
export const MODEL_PRICING: Record<string, { input: number; output: number }> = {
|
||||||
// Current generation (Claude 4.7/4.6/4.5)
|
// Current generation (Claude 4.6)
|
||||||
"claude-opus-4-7": { input: 5.0, output: 25.0 },
|
|
||||||
"claude-sonnet-4-6": { input: 3.0, output: 15.0 },
|
|
||||||
"claude-haiku-4-5-20251001": { input: 1.0, output: 5.0 },
|
|
||||||
// Previous generation (Claude 4.6)
|
|
||||||
"claude-opus-4-6": { input: 5.0, output: 25.0 },
|
"claude-opus-4-6": { input: 5.0, output: 25.0 },
|
||||||
|
"claude-sonnet-4-6": { input: 3.0, output: 15.0 },
|
||||||
// Previous generation (Claude 4.5)
|
// Previous generation (Claude 4.5)
|
||||||
"claude-opus-4-5-20251101": { input: 5.0, output: 25.0 },
|
"claude-opus-4-5-20251101": { input: 5.0, output: 25.0 },
|
||||||
"claude-sonnet-4-5-20250929": { input: 3.0, output: 15.0 },
|
"claude-sonnet-4-5-20250929": { input: 3.0, output: 15.0 },
|
||||||
|
"claude-haiku-4-5-20251001": { input: 1.0, output: 5.0 },
|
||||||
// Previous generation (Claude 4.x)
|
// Previous generation (Claude 4.x)
|
||||||
"claude-opus-4-1-20250805": { input: 15.0, output: 75.0 },
|
"claude-opus-4-1-20250805": { input: 15.0, output: 75.0 },
|
||||||
"claude-opus-4-20250514": { input: 15.0, output: 75.0 },
|
"claude-opus-4-20250514": { input: 15.0, output: 75.0 },
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import type {
|
|||||||
ElicitationEvent,
|
ElicitationEvent,
|
||||||
PermissionPromptEvent,
|
PermissionPromptEvent,
|
||||||
PostCompactEvent,
|
PostCompactEvent,
|
||||||
PreCompactEvent,
|
|
||||||
StopFailureEvent,
|
StopFailureEvent,
|
||||||
UserQuestionEvent,
|
UserQuestionEvent,
|
||||||
} from "$lib/types/messages";
|
} from "$lib/types/messages";
|
||||||
@@ -662,12 +661,6 @@ export async function initializeTauriListeners() {
|
|||||||
});
|
});
|
||||||
unlisteners.push(stopFailureUnlisten);
|
unlisteners.push(stopFailureUnlisten);
|
||||||
|
|
||||||
const preCompactUnlisten = await listen<PreCompactEvent>("claude:pre-compact", () => {
|
|
||||||
toastStore.addInfo("Compacting context...", "🗜️");
|
|
||||||
characterState.setTemporaryState("thinking", 3000);
|
|
||||||
});
|
|
||||||
unlisteners.push(preCompactUnlisten);
|
|
||||||
|
|
||||||
const postCompactUnlisten = await listen<PostCompactEvent>("claude:post-compact", () => {
|
const postCompactUnlisten = await listen<PostCompactEvent>("claude:post-compact", () => {
|
||||||
toastStore.addInfo("Context compacted", "🗜️");
|
toastStore.addInfo("Context compacted", "🗜️");
|
||||||
characterState.setTemporaryState("success", 2000);
|
characterState.setTemporaryState("success", 2000);
|
||||||
|
|||||||
@@ -187,11 +187,6 @@ export interface PostCompactEvent {
|
|||||||
conversation_id?: string;
|
conversation_id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PreCompactEvent {
|
|
||||||
session_id?: string;
|
|
||||||
conversation_id?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ConnectionStatus = "disconnected" | "connecting" | "connected" | "error";
|
export type ConnectionStatus = "disconnected" | "connecting" | "connected" | "error";
|
||||||
|
|
||||||
export interface Attachment {
|
export interface Attachment {
|
||||||
|
|||||||
Reference in New Issue
Block a user