Compare commits

..

1 Commits

Author SHA1 Message Date
minori 9afab03047 deps: update jsdom to 28.0.0
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 1m15s
CI / Lint & Test (pull_request) Successful in 16m55s
CI / Build Linux (pull_request) Successful in 19m49s
CI / Build Windows (cross-compile) (pull_request) Successful in 29m42s
2026-02-12 07:11:07 -08:00
6 changed files with 71 additions and 155 deletions
+1 -1
View File
@@ -81,7 +81,7 @@
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-plugin-svelte": "^3.14.0", "eslint-plugin-svelte": "^3.14.0",
"globals": "^17.0.0", "globals": "^17.0.0",
"jsdom": "^27.4.0", "jsdom": "28.0.0",
"prettier": "^3.8.0", "prettier": "^3.8.0",
"prettier-plugin-svelte": "^3.4.1", "prettier-plugin-svelte": "^3.4.1",
"svelte": "^5.0.0", "svelte": "^5.0.0",
+52 -57
View File
@@ -149,10 +149,10 @@ importers:
version: 6.9.1 version: 6.9.1
'@testing-library/svelte': '@testing-library/svelte':
specifier: ^5.3.1 specifier: ^5.3.1
version: 5.3.1(svelte@5.46.3)(vite@6.4.1(jiti@2.6.1)(lightningcss@1.30.2))(vitest@4.0.17(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.30.2)) version: 5.3.1(svelte@5.46.3)(vite@6.4.1(jiti@2.6.1)(lightningcss@1.30.2))(vitest@4.0.17(jiti@2.6.1)(jsdom@28.0.0)(lightningcss@1.30.2))
'@vitest/coverage-v8': '@vitest/coverage-v8':
specifier: ^4.0.18 specifier: ^4.0.18
version: 4.0.18(vitest@4.0.17(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.30.2)) version: 4.0.18(vitest@4.0.17(jiti@2.6.1)(jsdom@28.0.0)(lightningcss@1.30.2))
eslint: eslint:
specifier: ^9.39.2 specifier: ^9.39.2
version: 9.39.2(jiti@2.6.1) version: 9.39.2(jiti@2.6.1)
@@ -166,8 +166,8 @@ importers:
specifier: ^17.0.0 specifier: ^17.0.0
version: 17.0.0 version: 17.0.0
jsdom: jsdom:
specifier: ^27.4.0 specifier: 28.0.0
version: 27.4.0 version: 28.0.0
prettier: prettier:
specifier: ^3.8.0 specifier: ^3.8.0
version: 3.8.0 version: 3.8.0
@@ -194,7 +194,7 @@ importers:
version: 6.4.1(jiti@2.6.1)(lightningcss@1.30.2) version: 6.4.1(jiti@2.6.1)(lightningcss@1.30.2)
vitest: vitest:
specifier: ^4.0.17 specifier: ^4.0.17
version: 4.0.17(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.30.2) version: 4.0.17(jiti@2.6.1)(jsdom@28.0.0)(lightningcss@1.30.2)
packages: packages:
@@ -552,13 +552,13 @@ packages:
resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@exodus/bytes@1.8.0': '@exodus/bytes@1.14.0':
resolution: {integrity: sha512-8JPn18Bcp8Uo1T82gR8lh2guEOa5KKU/IEKvvdp0sgmi7coPBWf1Doi1EXsGZb2ehc8ym/StJCjffYV+ne7sXQ==} resolution: {integrity: sha512-YiY1OmY6Qhkvmly8vZiD8wZRpW/npGZNg+0Sk8mstxirRHCg6lolHt5tSODCfuNPE/fBsAqRwDJE417x7jDDHA==}
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
peerDependencies: peerDependencies:
'@exodus/crypto': ^1.0.0-rc.4 '@noble/hashes': ^1.8.0 || ^2.0.0
peerDependenciesMeta: peerDependenciesMeta:
'@exodus/crypto': '@noble/hashes':
optional: true optional: true
'@humanfs/core@0.19.1': '@humanfs/core@0.19.1':
@@ -1277,9 +1277,9 @@ packages:
resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==} resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==}
engines: {node: '>=20'} engines: {node: '>=20'}
data-urls@6.0.0: data-urls@7.0.0:
resolution: {integrity: sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==} resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==}
engines: {node: '>=20'} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
debug@4.4.3: debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
@@ -1551,8 +1551,8 @@ packages:
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
hasBin: true hasBin: true
jsdom@27.4.0: jsdom@28.0.0:
resolution: {integrity: sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==} resolution: {integrity: sha512-KDYJgZ6T2TKdU8yBfYueq5EPG/EylMsBvCaenWMJb2OXmjgczzwveRCoJ+Hgj1lXPDyasvrgneSn4GBuR1hYyA==}
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
peerDependencies: peerDependencies:
canvas: ^3.0.0 canvas: ^3.0.0
@@ -1990,6 +1990,10 @@ packages:
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
hasBin: true hasBin: true
undici@7.21.0:
resolution: {integrity: sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg==}
engines: {node: '>=20.18.1'}
uri-js@4.4.1: uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@@ -2089,14 +2093,14 @@ packages:
resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==}
engines: {node: '>=20'} engines: {node: '>=20'}
whatwg-mimetype@4.0.0: whatwg-mimetype@5.0.0:
resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==}
engines: {node: '>=18'}
whatwg-url@15.1.0:
resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==}
engines: {node: '>=20'} engines: {node: '>=20'}
whatwg-url@16.0.0:
resolution: {integrity: sha512-9CcxtEKsf53UFwkSUZjG+9vydAsFO4lFHBpJUtjBcoJOCJpKnSJNwCw813zrYJHpCJ7sgfbtOe0V5Ku7Pa1XMQ==}
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
which@2.0.2: which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@@ -2111,18 +2115,6 @@ packages:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
ws@8.19.0:
resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: '>=5.0.2'
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
xml-name-validator@5.0.0: xml-name-validator@5.0.0:
resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
engines: {node: '>=18'} engines: {node: '>=18'}
@@ -2544,7 +2536,7 @@ snapshots:
'@eslint/core': 0.17.0 '@eslint/core': 0.17.0
levn: 0.4.1 levn: 0.4.1
'@exodus/bytes@1.8.0': {} '@exodus/bytes@1.14.0': {}
'@humanfs/core@0.19.1': {} '@humanfs/core@0.19.1': {}
@@ -2974,14 +2966,14 @@ snapshots:
dependencies: dependencies:
svelte: 5.46.3 svelte: 5.46.3
'@testing-library/svelte@5.3.1(svelte@5.46.3)(vite@6.4.1(jiti@2.6.1)(lightningcss@1.30.2))(vitest@4.0.17(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.30.2))': '@testing-library/svelte@5.3.1(svelte@5.46.3)(vite@6.4.1(jiti@2.6.1)(lightningcss@1.30.2))(vitest@4.0.17(jiti@2.6.1)(jsdom@28.0.0)(lightningcss@1.30.2))':
dependencies: dependencies:
'@testing-library/dom': 10.4.1 '@testing-library/dom': 10.4.1
'@testing-library/svelte-core': 1.0.0(svelte@5.46.3) '@testing-library/svelte-core': 1.0.0(svelte@5.46.3)
svelte: 5.46.3 svelte: 5.46.3
optionalDependencies: optionalDependencies:
vite: 6.4.1(jiti@2.6.1)(lightningcss@1.30.2) vite: 6.4.1(jiti@2.6.1)(lightningcss@1.30.2)
vitest: 4.0.17(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.30.2) vitest: 4.0.17(jiti@2.6.1)(jsdom@28.0.0)(lightningcss@1.30.2)
'@types/aria-query@5.0.4': {} '@types/aria-query@5.0.4': {}
@@ -3089,7 +3081,7 @@ snapshots:
'@typescript-eslint/types': 8.53.0 '@typescript-eslint/types': 8.53.0
eslint-visitor-keys: 4.2.1 eslint-visitor-keys: 4.2.1
'@vitest/coverage-v8@4.0.18(vitest@4.0.17(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.30.2))': '@vitest/coverage-v8@4.0.18(vitest@4.0.17(jiti@2.6.1)(jsdom@28.0.0)(lightningcss@1.30.2))':
dependencies: dependencies:
'@bcoe/v8-coverage': 1.0.2 '@bcoe/v8-coverage': 1.0.2
'@vitest/utils': 4.0.18 '@vitest/utils': 4.0.18
@@ -3101,7 +3093,7 @@ snapshots:
obug: 2.1.1 obug: 2.1.1
std-env: 3.10.0 std-env: 3.10.0
tinyrainbow: 3.0.3 tinyrainbow: 3.0.3
vitest: 4.0.17(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.30.2) vitest: 4.0.17(jiti@2.6.1)(jsdom@28.0.0)(lightningcss@1.30.2)
'@vitest/expect@4.0.17': '@vitest/expect@4.0.17':
dependencies: dependencies:
@@ -3266,10 +3258,12 @@ snapshots:
css-tree: 3.1.0 css-tree: 3.1.0
lru-cache: 11.2.4 lru-cache: 11.2.4
data-urls@6.0.0: data-urls@7.0.0:
dependencies: dependencies:
whatwg-mimetype: 4.0.0 whatwg-mimetype: 5.0.0
whatwg-url: 15.1.0 whatwg-url: 16.0.0
transitivePeerDependencies:
- '@noble/hashes'
debug@4.4.3: debug@4.4.3:
dependencies: dependencies:
@@ -3480,9 +3474,9 @@ snapshots:
html-encoding-sniffer@6.0.0: html-encoding-sniffer@6.0.0:
dependencies: dependencies:
'@exodus/bytes': 1.8.0 '@exodus/bytes': 1.14.0
transitivePeerDependencies: transitivePeerDependencies:
- '@exodus/crypto' - '@noble/hashes'
html-escaper@2.0.2: {} html-escaper@2.0.2: {}
@@ -3550,13 +3544,13 @@ snapshots:
dependencies: dependencies:
argparse: 2.0.1 argparse: 2.0.1
jsdom@27.4.0: jsdom@28.0.0:
dependencies: dependencies:
'@acemir/cssom': 0.9.31 '@acemir/cssom': 0.9.31
'@asamuzakjp/dom-selector': 6.7.6 '@asamuzakjp/dom-selector': 6.7.6
'@exodus/bytes': 1.8.0 '@exodus/bytes': 1.14.0
cssstyle: 5.3.7 cssstyle: 5.3.7
data-urls: 6.0.0 data-urls: 7.0.0
decimal.js: 10.6.0 decimal.js: 10.6.0
html-encoding-sniffer: 6.0.0 html-encoding-sniffer: 6.0.0
http-proxy-agent: 7.0.2 http-proxy-agent: 7.0.2
@@ -3566,17 +3560,15 @@ snapshots:
saxes: 6.0.0 saxes: 6.0.0
symbol-tree: 3.2.4 symbol-tree: 3.2.4
tough-cookie: 6.0.0 tough-cookie: 6.0.0
undici: 7.21.0
w3c-xmlserializer: 5.0.0 w3c-xmlserializer: 5.0.0
webidl-conversions: 8.0.1 webidl-conversions: 8.0.1
whatwg-mimetype: 4.0.0 whatwg-mimetype: 5.0.0
whatwg-url: 15.1.0 whatwg-url: 16.0.0
ws: 8.19.0
xml-name-validator: 5.0.0 xml-name-validator: 5.0.0
transitivePeerDependencies: transitivePeerDependencies:
- '@exodus/crypto' - '@noble/hashes'
- bufferutil
- supports-color - supports-color
- utf-8-validate
json-buffer@3.0.1: {} json-buffer@3.0.1: {}
@@ -3965,6 +3957,8 @@ snapshots:
typescript@5.6.3: {} typescript@5.6.3: {}
undici@7.21.0: {}
uri-js@4.4.1: uri-js@4.4.1:
dependencies: dependencies:
punycode: 2.3.1 punycode: 2.3.1
@@ -3988,7 +3982,7 @@ snapshots:
optionalDependencies: optionalDependencies:
vite: 6.4.1(jiti@2.6.1)(lightningcss@1.30.2) vite: 6.4.1(jiti@2.6.1)(lightningcss@1.30.2)
vitest@4.0.17(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.30.2): vitest@4.0.17(jiti@2.6.1)(jsdom@28.0.0)(lightningcss@1.30.2):
dependencies: dependencies:
'@vitest/expect': 4.0.17 '@vitest/expect': 4.0.17
'@vitest/mocker': 4.0.17(vite@6.4.1(jiti@2.6.1)(lightningcss@1.30.2)) '@vitest/mocker': 4.0.17(vite@6.4.1(jiti@2.6.1)(lightningcss@1.30.2))
@@ -4011,7 +4005,7 @@ snapshots:
vite: 6.4.1(jiti@2.6.1)(lightningcss@1.30.2) vite: 6.4.1(jiti@2.6.1)(lightningcss@1.30.2)
why-is-node-running: 2.3.0 why-is-node-running: 2.3.0
optionalDependencies: optionalDependencies:
jsdom: 27.4.0 jsdom: 28.0.0
transitivePeerDependencies: transitivePeerDependencies:
- jiti - jiti
- less - less
@@ -4033,12 +4027,15 @@ snapshots:
webidl-conversions@8.0.1: {} webidl-conversions@8.0.1: {}
whatwg-mimetype@4.0.0: {} whatwg-mimetype@5.0.0: {}
whatwg-url@15.1.0: whatwg-url@16.0.0:
dependencies: dependencies:
'@exodus/bytes': 1.14.0
tr46: 6.0.0 tr46: 6.0.0
webidl-conversions: 8.0.1 webidl-conversions: 8.0.1
transitivePeerDependencies:
- '@noble/hashes'
which@2.0.2: which@2.0.2:
dependencies: dependencies:
@@ -4051,8 +4048,6 @@ snapshots:
word-wrap@1.2.5: {} word-wrap@1.2.5: {}
ws@8.19.0: {}
xml-name-validator@5.0.0: {} xml-name-validator@5.0.0: {}
xmlchars@2.2.0: {} xmlchars@2.2.0: {}
+1 -3
View File
@@ -86,9 +86,8 @@ 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.6 family // Claude 4.6 family - 200K standard (1M beta available via header)
"claude-opus-4-6" => 200_000, "claude-opus-4-6" => 200_000,
"claude-sonnet-4-6" => 1_000_000, // 1M token context window
// 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"
@@ -503,7 +502,6 @@ pub fn calculate_cost(
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.6) // Current 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),
+16 -91
View File
@@ -125,19 +125,15 @@ impl WslBridge {
} }
pub fn start(&mut self, app: AppHandle, options: ClaudeStartOptions) -> Result<(), String> { pub fn start(&mut self, app: AppHandle, options: ClaudeStartOptions) -> Result<(), String> {
// If a process handle exists but the process has already exited (e.g. due to a
// failed working directory), clean up the stale handle so we can restart cleanly.
if let Some(ref mut process) = self.process {
if process.try_wait().map(|s| s.is_some()).unwrap_or(false) {
self.process = None;
self.stdin = None;
}
}
if self.process.is_some() { if self.process.is_some() {
return Err("Process already running".to_string()); return Err("Process already running".to_string());
} }
// Check if Claude binary is installed before attempting to start
if Command::new("which").arg("claude").output().ok().is_none_or(|output| !output.status.success()) {
return Err("Claude Code is not installed. Please install it using:\n\ncurl -fsSL https://claude.ai/install.sh | bash".to_string());
}
// Load saved achievements and stats when starting a new session // Load saved achievements and stats when starting a new session
let app_clone = app.clone(); let app_clone = app.clone();
let stats = self.stats.clone(); let stats = self.stats.clone();
@@ -266,30 +262,6 @@ impl WslBridge {
} 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
tracing::debug!("Windows path - using wsl"); tracing::debug!("Windows path - using wsl");
// Check if Claude binary is installed inside WSL
let binary_check = Command::new("wsl")
.args(["-e", "bash", "-lc", "which claude"])
.output();
if let Ok(output) = binary_check {
if !output.status.success() {
return Err("Claude Code is not installed. Please install it using:\n\ncurl -fsSL https://claude.ai/install.sh | bash".to_string());
}
}
// Validate the working directory exists inside WSL before spawning
let dir_check = Command::new("wsl")
.args(["-e", "test", "-d", working_dir])
.output();
if let Ok(output) = dir_check {
if !output.status.success() {
return Err(format!(
"Working directory does not exist: {}",
working_dir
));
}
}
let mut cmd = Command::new("wsl"); let mut cmd = Command::new("wsl");
// Build the claude command with all arguments // Build the claude command with all arguments
@@ -1902,66 +1874,19 @@ mod tests {
} }
#[test] #[test]
fn test_stale_process_detection_with_try_wait() { fn test_claude_binary_check_command_structure() {
// Spawn a real process that exits immediately so we can verify try_wait detects it // Test that we're using the correct command to check for Claude binary
let mut child = Command::new("true").spawn().expect("Failed to spawn 'true'"); let output = Command::new("which").arg("claude").output();
// Wait for it to exit // The command should execute successfully (even if claude is not found)
let _ = child.wait(); // We're just verifying the command structure is valid
assert!(output.is_ok(), "which command should execute without error");
// try_wait on an already-exited process should return Some(_) // Verify the check logic returns a boolean
let status = child.try_wait(); // This is the same logic used in start() to check if claude is installed
assert!( let _result = output.ok().is_none_or(|o| !o.status.success());
status.is_ok(), // If claude is not installed, _result will be true (show error)
"try_wait should not error on an exited process" // If claude is installed, _result will be false (proceed with connection)
);
// The process has already been waited on, so try_wait might return None or Some
// depending on the OS - what matters is that the call succeeds
}
#[test]
fn test_stale_process_is_some_after_exit() {
// Verify the logic used in start(): a process that has exited is detected
// and the handle is cleaned up so start() can proceed
let mut child = Command::new("true").spawn().expect("Failed to spawn 'true'");
// Let it exit
let _ = child.wait();
// This mirrors the check in start()
let has_exited = child
.try_wait()
.map(|s| s.is_some())
.unwrap_or(false);
// After wait(), try_wait() returns None (already reaped), which means
// unwrap_or(false) → false. The important thing is the call doesn't panic
// and the control flow logic compiles and runs correctly.
let _ = has_exited; // suppress unused warning
}
/// Build the WSL binary check command structure without executing it (for testing)
#[cfg(test)]
fn build_wsl_binary_check_args() -> Vec<&'static str> {
vec!["-e", "bash", "-lc", "which claude"]
}
#[test]
fn test_wsl_binary_check_command_structure() {
// Windows path: verify Claude is detected inside WSL via `wsl -e bash -lc "which claude"`
let args = build_wsl_binary_check_args();
assert_eq!(args[0], "-e");
assert_eq!(args[1], "bash");
assert_eq!(args[2], "-lc");
assert_eq!(args[3], "which claude");
}
#[test]
fn test_linux_binary_check_does_not_panic() {
// Linux/WSL path: find_claude_binary() searches Linux filesystem paths.
// We just verify it runs without panicking; whether it returns Some depends
// on whether Claude is actually installed in this environment.
let _result = find_claude_binary();
} }
#[test] #[test]
+1 -2
View File
@@ -83,9 +83,8 @@
{ value: "", label: "Default (from ~/.claude)" }, { value: "", label: "Default (from ~/.claude)" },
// Current generation (Claude 4.6) // Current generation (Claude 4.6)
{ value: "claude-opus-4-6", label: "Claude Opus 4.6 (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)" },
// 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 (Recommended)" },
{ value: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5 (Fast & Cheap)" }, { 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)
-1
View File
@@ -12,7 +12,6 @@ export type BudgetType = "token" | "cost";
export const MODEL_PRICING: Record<string, { input: number; output: number }> = { export const MODEL_PRICING: Record<string, { input: number; output: number }> = {
// Current generation (Claude 4.6) // Current 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 },