@marsapi/cli 0.0.142 → 0.0.144

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,7 +10,7 @@
10
10
  "claude": [
11
11
  {
12
12
  "description": "100 万上下文 | 高强度推理 | 长时 Agent | SWE-bench Verified 95%",
13
- "group": "grp_6eg2dq9ywgrg",
13
+ "group": "grp_rld6af0zorqd",
14
14
  "group_name": "",
15
15
  "hidden": false,
16
16
  "id": "claude-fable-5",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  {
39
39
  "description": "100 万上下文 | 12.8 万输出 | 低延迟 | 高频轻量任务",
40
- "group": "grp_rld6af0zorqd",
40
+ "group": "grp_6eg2dq9ywgrg",
41
41
  "group_name": "",
42
42
  "hidden": false,
43
43
  "id": "claude-haiku-5-5",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  {
48
48
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
49
- "group": "grp_pzxnceygmqlp",
49
+ "group": "grp_6co8aqwefsoh",
50
50
  "group_name": "",
51
51
  "hidden": false,
52
52
  "id": "claude-opus-4-6",
@@ -55,7 +55,7 @@
55
55
  },
56
56
  {
57
57
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
58
- "group": "grp_6lyxfgbs440g",
58
+ "group": "grp_6eg2dq9ywgrg",
59
59
  "group_name": "",
60
60
  "hidden": false,
61
61
  "id": "claude-opus-4-7",
@@ -64,7 +64,7 @@
64
64
  },
65
65
  {
66
66
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
67
- "group": "grp_6lyxfgbs440g",
67
+ "group": "grp_6eg2dq9ywgrg",
68
68
  "group_name": "",
69
69
  "hidden": false,
70
70
  "id": "claude-opus-4-8",
@@ -73,7 +73,7 @@
73
73
  },
74
74
  {
75
75
  "description": "100 万上下文 | 12.8 万输出 | 自适应思考五档 | Agent 编程",
76
- "group": "grp_pzxnceygmqlp",
76
+ "group": "grp_irydsgijuckh",
77
77
  "group_name": "",
78
78
  "hidden": false,
79
79
  "id": "claude-opus-5",
@@ -82,7 +82,7 @@
82
82
  },
83
83
  {
84
84
  "description": "100 万上下文 | 长时 Agent 编程 | 知识工作",
85
- "group": "grp_irydsgijuckh",
85
+ "group": "grp_rld6af0zorqd",
86
86
  "group_name": "",
87
87
  "hidden": false,
88
88
  "id": "claude-opus-5-5",
@@ -91,7 +91,7 @@
91
91
  },
92
92
  {
93
93
  "description": "100 万上下文 | Agent 编程 | 长上下文不加价",
94
- "group": "grp_6lyxfgbs440g",
94
+ "group": "grp_irydsgijuckh",
95
95
  "group_name": "",
96
96
  "hidden": false,
97
97
  "id": "claude-sonnet-4-6",
@@ -109,7 +109,7 @@
109
109
  },
110
110
  {
111
111
  "description": "100 万上下文 | 12.8 万输出 | Agent 编程 | 知识工作",
112
- "group": "grp_rld6af0zorqd",
112
+ "group": "grp_6lyxfgbs440g",
113
113
  "group_name": "",
114
114
  "hidden": false,
115
115
  "id": "claude-sonnet-5-5",
@@ -120,7 +120,7 @@
120
120
  "codex": [
121
121
  {
122
122
  "description": "105 万上下文 | 12.8 万输出 | 大批量低成本档",
123
- "group": "grp_squ2qzjnehps",
123
+ "group": "grp_bsbtt432saoq",
124
124
  "group_name": "",
125
125
  "hidden": false,
126
126
  "id": "gpt-5.6-luna",
@@ -129,7 +129,7 @@
129
129
  },
130
130
  {
131
131
  "description": "105 万上下文 | 12.8 万输出 | 前沿档",
132
- "group": "grp_6co8aqwefsoh",
132
+ "group": "grp_irydsgijuckh",
133
133
  "group_name": "",
134
134
  "hidden": false,
135
135
  "id": "gpt-5.6-sol",
@@ -147,7 +147,7 @@
147
147
  },
148
148
  {
149
149
  "description": "105 万上下文 | 12.8 万输出 | 思考强度至 max | 计算机操作 / 编码 / 科学基准接近饱和",
150
- "group": "grp_mb5v069lpnze",
150
+ "group": "grp_irydsgijuckh",
151
151
  "group_name": "",
152
152
  "hidden": false,
153
153
  "id": "gpt-6-astra",
@@ -156,7 +156,7 @@
156
156
  },
157
157
  {
158
158
  "description": "转发至 gpt-6-sol | 实际由 gpt-6-sol 响应 | 105 万上下文 | 12.8 万输出",
159
- "group": "grp_mb5v069lpnze",
159
+ "group": "grp_irydsgijuckh",
160
160
  "group_name": "",
161
161
  "hidden": false,
162
162
  "id": "gpt-6-luna",
@@ -183,7 +183,7 @@
183
183
  },
184
184
  {
185
185
  "description": "105 万上下文 | 12.8 万输出 | 计算机操作与日常 Agent 任务 | 均衡档",
186
- "group": "grp_squ2qzjnehps",
186
+ "group": "grp_irydsgijuckh",
187
187
  "group_name": "",
188
188
  "hidden": false,
189
189
  "id": "gpt-6.1-terra",
@@ -230,7 +230,7 @@
230
230
  },
231
231
  {
232
232
  "description": "Gemini 3.1 Pro 预览版 | 约 100 万上下文 | 深度推理 | 文本、图像、音视频输入",
233
- "group": "grp_z5khwusxuh2j",
233
+ "group": "grp_3pi5kyqkp51b",
234
234
  "group_name": "",
235
235
  "hidden": false,
236
236
  "id": "gemini-3.1-pro-preview",
@@ -239,7 +239,7 @@
239
239
  },
240
240
  {
241
241
  "description": "高吞吐 | 低成本 | 大批量常规任务",
242
- "group": "grp_3pi5kyqkp51b",
242
+ "group": "grp_z5khwusxuh2j",
243
243
  "group_name": "",
244
244
  "hidden": false,
245
245
  "id": "gemini-3.5-flash",
@@ -257,7 +257,7 @@
257
257
  },
258
258
  {
259
259
  "description": "Agent 主力 | 软件工程 | 网页开发",
260
- "group": "grp_3pi5kyqkp51b",
260
+ "group": "grp_z5khwusxuh2j",
261
261
  "group_name": "",
262
262
  "hidden": false,
263
263
  "id": "gemini-3.7-flash",
@@ -295,7 +295,7 @@
295
295
  "grok": [
296
296
  {
297
297
  "description": "50 万上下文 | 1.5 万亿参数 MoE | 编码与 Agent",
298
- "group": "grp_l34dwliv4yas",
298
+ "group": "grp_irydsgijuckh",
299
299
  "group_name": "",
300
300
  "hidden": false,
301
301
  "id": "grok-4.5",
@@ -304,7 +304,7 @@
304
304
  },
305
305
  {
306
306
  "description": "50 万上下文 | 思考强度四档 | 编码与 Agent",
307
- "group": "grp_irydsgijuckh",
307
+ "group": "grp_l34dwliv4yas",
308
308
  "group_name": "",
309
309
  "hidden": false,
310
310
  "id": "grok-4.6",
@@ -10,7 +10,7 @@
10
10
  "claude": [
11
11
  {
12
12
  "description": "100 万上下文 | 高强度推理 | 长时 Agent | SWE-bench Verified 95%",
13
- "group": "grp_6eg2dq9ywgrg",
13
+ "group": "grp_rld6af0zorqd",
14
14
  "group_name": "",
15
15
  "hidden": false,
16
16
  "id": "claude-fable-5",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  {
39
39
  "description": "100 万上下文 | 12.8 万输出 | 低延迟 | 高频轻量任务",
40
- "group": "grp_rld6af0zorqd",
40
+ "group": "grp_6eg2dq9ywgrg",
41
41
  "group_name": "",
42
42
  "hidden": false,
43
43
  "id": "claude-haiku-5-5",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  {
48
48
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
49
- "group": "grp_pzxnceygmqlp",
49
+ "group": "grp_6co8aqwefsoh",
50
50
  "group_name": "",
51
51
  "hidden": false,
52
52
  "id": "claude-opus-4-6",
@@ -55,7 +55,7 @@
55
55
  },
56
56
  {
57
57
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
58
- "group": "grp_6lyxfgbs440g",
58
+ "group": "grp_6eg2dq9ywgrg",
59
59
  "group_name": "",
60
60
  "hidden": false,
61
61
  "id": "claude-opus-4-7",
@@ -64,7 +64,7 @@
64
64
  },
65
65
  {
66
66
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
67
- "group": "grp_6lyxfgbs440g",
67
+ "group": "grp_6eg2dq9ywgrg",
68
68
  "group_name": "",
69
69
  "hidden": false,
70
70
  "id": "claude-opus-4-8",
@@ -73,7 +73,7 @@
73
73
  },
74
74
  {
75
75
  "description": "100 万上下文 | 12.8 万输出 | 自适应思考五档 | Agent 编程",
76
- "group": "grp_pzxnceygmqlp",
76
+ "group": "grp_irydsgijuckh",
77
77
  "group_name": "",
78
78
  "hidden": false,
79
79
  "id": "claude-opus-5",
@@ -82,7 +82,7 @@
82
82
  },
83
83
  {
84
84
  "description": "100 万上下文 | 长时 Agent 编程 | 知识工作",
85
- "group": "grp_irydsgijuckh",
85
+ "group": "grp_rld6af0zorqd",
86
86
  "group_name": "",
87
87
  "hidden": false,
88
88
  "id": "claude-opus-5-5",
@@ -91,7 +91,7 @@
91
91
  },
92
92
  {
93
93
  "description": "100 万上下文 | Agent 编程 | 长上下文不加价",
94
- "group": "grp_6lyxfgbs440g",
94
+ "group": "grp_irydsgijuckh",
95
95
  "group_name": "",
96
96
  "hidden": false,
97
97
  "id": "claude-sonnet-4-6",
@@ -109,7 +109,7 @@
109
109
  },
110
110
  {
111
111
  "description": "100 万上下文 | 12.8 万输出 | Agent 编程 | 知识工作",
112
- "group": "grp_rld6af0zorqd",
112
+ "group": "grp_6lyxfgbs440g",
113
113
  "group_name": "",
114
114
  "hidden": false,
115
115
  "id": "claude-sonnet-5-5",
@@ -120,7 +120,7 @@
120
120
  "codex": [
121
121
  {
122
122
  "description": "105 万上下文 | 12.8 万输出 | 大批量低成本档",
123
- "group": "grp_squ2qzjnehps",
123
+ "group": "grp_bsbtt432saoq",
124
124
  "group_name": "",
125
125
  "hidden": false,
126
126
  "id": "gpt-5.6-luna",
@@ -129,7 +129,7 @@
129
129
  },
130
130
  {
131
131
  "description": "105 万上下文 | 12.8 万输出 | 前沿档",
132
- "group": "grp_6co8aqwefsoh",
132
+ "group": "grp_irydsgijuckh",
133
133
  "group_name": "",
134
134
  "hidden": false,
135
135
  "id": "gpt-5.6-sol",
@@ -147,7 +147,7 @@
147
147
  },
148
148
  {
149
149
  "description": "105 万上下文 | 12.8 万输出 | 思考强度至 max | 计算机操作 / 编码 / 科学基准接近饱和",
150
- "group": "grp_mb5v069lpnze",
150
+ "group": "grp_irydsgijuckh",
151
151
  "group_name": "",
152
152
  "hidden": false,
153
153
  "id": "gpt-6-astra",
@@ -156,7 +156,7 @@
156
156
  },
157
157
  {
158
158
  "description": "转发至 gpt-6-sol | 实际由 gpt-6-sol 响应 | 105 万上下文 | 12.8 万输出",
159
- "group": "grp_mb5v069lpnze",
159
+ "group": "grp_irydsgijuckh",
160
160
  "group_name": "",
161
161
  "hidden": false,
162
162
  "id": "gpt-6-luna",
@@ -183,7 +183,7 @@
183
183
  },
184
184
  {
185
185
  "description": "105 万上下文 | 12.8 万输出 | 计算机操作与日常 Agent 任务 | 均衡档",
186
- "group": "grp_squ2qzjnehps",
186
+ "group": "grp_irydsgijuckh",
187
187
  "group_name": "",
188
188
  "hidden": false,
189
189
  "id": "gpt-6.1-terra",
@@ -230,7 +230,7 @@
230
230
  },
231
231
  {
232
232
  "description": "Gemini 3.1 Pro 预览版 | 约 100 万上下文 | 深度推理 | 文本、图像、音视频输入",
233
- "group": "grp_z5khwusxuh2j",
233
+ "group": "grp_3pi5kyqkp51b",
234
234
  "group_name": "",
235
235
  "hidden": false,
236
236
  "id": "gemini-3.1-pro-preview",
@@ -239,7 +239,7 @@
239
239
  },
240
240
  {
241
241
  "description": "高吞吐 | 低成本 | 大批量常规任务",
242
- "group": "grp_3pi5kyqkp51b",
242
+ "group": "grp_z5khwusxuh2j",
243
243
  "group_name": "",
244
244
  "hidden": false,
245
245
  "id": "gemini-3.5-flash",
@@ -257,7 +257,7 @@
257
257
  },
258
258
  {
259
259
  "description": "Agent 主力 | 软件工程 | 网页开发",
260
- "group": "grp_3pi5kyqkp51b",
260
+ "group": "grp_z5khwusxuh2j",
261
261
  "group_name": "",
262
262
  "hidden": false,
263
263
  "id": "gemini-3.7-flash",
@@ -295,7 +295,7 @@
295
295
  "grok": [
296
296
  {
297
297
  "description": "50 万上下文 | 1.5 万亿参数 MoE | 编码与 Agent",
298
- "group": "grp_l34dwliv4yas",
298
+ "group": "grp_irydsgijuckh",
299
299
  "group_name": "",
300
300
  "hidden": false,
301
301
  "id": "grok-4.5",
@@ -304,7 +304,7 @@
304
304
  },
305
305
  {
306
306
  "description": "50 万上下文 | 思考强度四档 | 编码与 Agent",
307
- "group": "grp_irydsgijuckh",
307
+ "group": "grp_l34dwliv4yas",
308
308
  "group_name": "",
309
309
  "hidden": false,
310
310
  "id": "grok-4.6",
@@ -1 +1 @@
1
- import{execFileSync as e}from"child_process";import{createHash as t}from"crypto";import{createReadStream as r,createWriteStream as s,existsSync as o,readdirSync as i,readFileSync as n}from"fs";import{copyFile as a,mkdir as l,readFile as c,rename as u,rm as f,writeFile as p}from"fs/promises";import{isAbsolute as d,join as h,normalize as m,sep as w}from"path";import{Readable as g,Writable as b}from"stream";import{pipeline as D}from"stream/promises";import*as y from"zlib";import{logger as v}from"../../utils/logger.js";import{brandEnv as k}from"../brand.js";import{downloadNativeBinary as $,nativeLayout as C,nativePlatformKey as N}from"./claude-native-mirror.js";import{WINDOWS_PACKAGE_FAMILIES as x}from"./desktop-process.js";import{toolHome as A}from"./types.js";export function readDesktopCliPin(e,t,r=!1){const s=e.indexOf('claude-code-releases","sdkWrapperVersion"');if(s<0)return null;const o=e.lastIndexOf("JSON.parse('",s),i=e.indexOf("')",s);if(o<0||i<0)return null;try{const s=JSON.parse(e.subarray(o+12,i).toString("utf-8")),n="string"==typeof s.version?s.version:"",a=s.manifest?.platforms?.[t],l=r?a?.bundle?.checksum:a?.checksum;return/^\d+\.\d+\.\d+$/.test(n)&&"string"==typeof l&&/^[0-9a-f]{64}$/.test(l)?{version:n,checksum:l}:null}catch{return null}}class L extends b{dest;buffer=Buffer.alloc(0);remaining=0;padding=0;file=null;longName=null;collectingLongName=null;constructor(e){super(),this.dest=e}_write(e,t,r){this.buffer=this.buffer.length?Buffer.concat([this.buffer,e]):e,this.drain().then(()=>r()).catch(r)}_final(e){this.remaining>0?e(new Error("archive ends inside an entry")):e()}target(e){const t=m(e);if(!t||d(t)||".."===t||t.startsWith(`..${w}`))throw new Error(`unsafe path in archive: ${e}`);return h(this.dest,t)}async closeFile(){const e=this.file;this.file=null,e&&await new Promise((t,r)=>e.end(e=>e?r(e):t()))}async drain(){for(;;){if(this.remaining>0){if(0===this.buffer.length)return;const e=this.buffer.subarray(0,Math.min(this.remaining,this.buffer.length));this.buffer=this.buffer.subarray(e.length),this.remaining-=e.length,this.collectingLongName?this.collectingLongName.push(e):this.file&&!this.file.write(e)&&await new Promise(e=>this.file.once("drain",()=>e())),0===this.remaining&&(this.collectingLongName&&(this.longName=Buffer.concat(this.collectingLongName).toString("utf-8").replace(/\0.*$/s,""),this.collectingLongName=null),await this.closeFile());continue}if(this.padding>0){if(this.buffer.length<this.padding)return;this.buffer=this.buffer.subarray(this.padding),this.padding=0}if(this.buffer.length<512)return;const e=this.buffer.subarray(0,512);if(this.buffer=this.buffer.subarray(512),e.every(e=>0===e))continue;const t=(t,r)=>e.subarray(t,t+r).toString("utf-8").replace(/\0.*$/s,""),r=t(345,155);let o=r?`${r}/${t(0,100)}`:t(0,100);null!==this.longName&&(o=this.longName,this.longName=null);const i=parseInt(t(124,12).trim()||"0",8),n=511&parseInt(t(100,8).trim()||"644",8),a=t(156,1)||"0";if(this.remaining=i,this.padding=(512-i%512)%512,"L"===a)this.collectingLongName=[];else if("x"===a||"g"===a);else if("5"===a)await l(this.target(o),{recursive:!0});else{if("0"!==a)throw new Error(`unexpected entry type ${a} in archive: ${o}`);{const e=this.target(o);await l(h(e,".."),{recursive:!0}),this.file=s(e,{mode:n||420}),0===i&&await this.closeFile()}}}}}export async function installDesktopCli(e){const s=readDesktopCliPin(e.asar,e.platformKey,e.bundle);if(!s)return{status:"skipped",reason:"unknown app layout"};if(e.bundle&&!e.download)return{status:"skipped",reason:"no bundle mirror"};const i=e.platformKey.startsWith("win32")?"claude.exe":"claude",n=h(e.userDataDir,"claude-code",s.version),d=h(n,s.checksum.slice(0,12)),m=e.bundle?h(d,"claude.app","Contents","MacOS","claude"):h(d,i),w=h(d,".verified");try{if(o(m)&&(await c(w,"utf-8")).trim()===s.checksum)return{status:"present",version:s.version}}catch{}await l(n,{recursive:!0});const g=h(n,`.partial-${s.checksum.slice(0,12)}`),v=`${g}.download`;try{await f(w,{force:!0}),await f(g,{recursive:!0,force:!0});let i="mirror";if(e.bundle){if(e.onDownload?.(s.version),await e.download(s.version,v),await async function(e,s,o){const i=t("sha256");if(await D(r(e),new b({write(e,t,r){i.update(e),r()}})),i.digest("hex")!==s)throw new Error("downloaded bundle does not match the app's checksum");const n=y.createZstdDecompress;if(!n)throw new Error(`Node ${process.version} cannot decompress zstd (needs 22.15 or newer)`);await D(r(e),n(),new L(o))}(v,s.checksum,g),!o(h(g,"claude.app","Contents","MacOS","claude")))throw new Error("bundle has no claude.app");await f(d,{recursive:!0,force:!0}),await u(g,d)}else{const t=e.localVersionsDir?h(e.localVersionsDir,s.version):null;if(t&&o(t))await a(t,g),i="local";else{e.onDownload?.(s.version);const t=e.download??((t,r)=>$(e.platformKey,t,r));await t(s.version,g)}await l(d,{recursive:!0}),await u(g,m)}return await p(w,s.checksum),{status:"installed",version:s.version,source:i}}finally{await f(g,{recursive:!0,force:!0}),await f(v,{force:!0}),await f(`${g}.download`,{force:!0})}}let P=(...e)=>fetch(...e);export function setDesktopCliFetchForTests(e){P=e}export async function ensureDesktopCli(t){const r=N();if(!r)return{status:"skipped",reason:"unsupported architecture"};if("win32"===process.platform){const s=function(){const t=h(process.env.LOCALAPPDATA||"","AnthropicClaude");if(process.env.LOCALAPPDATA&&o(t)){const e=i(t).filter(e=>/^app-\d+\.\d+\.\d+$/.test(e)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}));for(const r of e){const e=h(t,r,"resources","app.asar");if(o(e))return e}}try{const t=e("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${x.map(e=>`'${e}'`).join(",")}) -contains $_.PackageFamilyName } | ForEach-Object { $_.InstallLocation }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"]});for(const e of t.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)){const t=h(e,"app","resources","app.asar");if(o(t))return t}}catch(e){v.logError("claude-desktop-cli.windowsAsarPath",e)}return null}();return s?installDesktopCli({userDataDir:t.userDataDir,asar:n(s),platformKey:r,localVersionsDir:C().versionsDir,onDownload:t.onDownload}):{status:"skipped",reason:"app.asar not found"}}if("darwin"===process.platform){const e=function(){for(const e of["/Applications/Claude.app",h(A(),"Applications","Claude.app")]){const t=h(e,"Contents","Resources","app.asar");if(o(t))return t}return null}();if(!e)return{status:"skipped",reason:"app.asar not found"};const{mirrorRepo:i,desktopVersion:a}=t;return installDesktopCli({userDataDir:t.userDataDir,asar:n(e),platformKey:r,bundle:!0,onDownload:t.onDownload,download:i&&a?(e,t)=>async function(e,t){const r=await P(e,{signal:AbortSignal.timeout(9e5)});if(!r.ok||!r.body)throw new Error(`${e}: HTTP ${r.status}`);await D(g.fromWeb(r.body),s(t))}(`${i}/-/releases/download/v${a}/claude-code-${e}-${r}.app.tar.zst`,t):void 0})}if("linux"===process.platform){const e=function(){if(k("TEST_HOME")?.trim())return null;for(const e of["/usr/lib/claude-desktop","/opt/Claude"]){const t=h(e,"resources","app.asar");if(o(t))return t}return null}();return e?installDesktopCli({userDataDir:t.userDataDir,asar:n(e),platformKey:r.replace(/-musl$/,""),localVersionsDir:r.endsWith("-musl")?void 0:C().versionsDir,onDownload:t.onDownload}):{status:"skipped",reason:"app.asar not found"}}return{status:"skipped",reason:"unsupported platform"}}
1
+ import{execFileSync as e}from"child_process";import{createHash as t}from"crypto";import{createReadStream as r,createWriteStream as s,existsSync as o,readdirSync as n,readFileSync as i}from"fs";import{copyFile as a,mkdir as l,readFile as c,rename as u,rm as f,writeFile as p}from"fs/promises";import{isAbsolute as d,join as m,normalize as h,sep as w}from"path";import{Readable as g,Writable as b}from"stream";import{pipeline as D}from"stream/promises";import*as y from"zlib";import{logger as v}from"../../utils/logger.js";import{brandEnv as k}from"../brand.js";import{downloadNativeBinary as $,nativeLayout as C,nativePlatformKey as x}from"./claude-native-mirror.js";import{WINDOWS_PACKAGE_FAMILIES as N}from"./desktop-process.js";import{toolHome as A}from"./types.js";export function readDesktopCliPin(e,t,r=!1){const s=e.indexOf('claude-code-releases","sdkWrapperVersion"');if(s<0)return null;const o=e.lastIndexOf("JSON.parse('",s),n=e.indexOf("')",s);if(o<0||n<0)return null;try{const s=JSON.parse(e.subarray(o+12,n).toString("utf-8")),i="string"==typeof s.version?s.version:"",a=s.manifest?.platforms?.[t],l=r?a?.bundle?.checksum:a?.checksum;return/^\d+\.\d+\.\d+$/.test(i)&&"string"==typeof l&&/^[0-9a-f]{64}$/.test(l)?{version:i,checksum:l}:null}catch{return null}}function P(){const t=m(process.env.LOCALAPPDATA||"","AnthropicClaude");if(process.env.LOCALAPPDATA&&o(t)){const e=n(t).filter(e=>/^app-\d+\.\d+\.\d+$/.test(e)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}));for(const r of e){const e=m(t,r,"resources","app.asar");if(o(e))return e}}try{const t=e("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${N.map(e=>`'${e}'`).join(",")}) -contains $_.PackageFamilyName } | ForEach-Object { $_.InstallLocation }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"]});for(const e of t.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)){const t=m(e,"app","resources","app.asar");if(o(t))return t}}catch(e){v.logError("claude-desktop-cli.windowsAsarPath",e)}return null}function L(){if(k("TEST_HOME")?.trim())return null;for(const e of["/usr/lib/claude-desktop","/opt/Claude"]){const t=m(e,"resources","app.asar");if(o(t))return t}return null}function O(){for(const e of["/Applications/Claude.app",m(A(),"Applications","Claude.app")]){const t=m(e,"Contents","Resources","app.asar");if(o(t))return t}return null}export function installedDesktopAsarPath(){return"win32"===process.platform?P():"darwin"===process.platform?O():"linux"===process.platform?L():null}class E extends b{dest;buffer=Buffer.alloc(0);remaining=0;padding=0;file=null;longName=null;collectingLongName=null;constructor(e){super(),this.dest=e}_write(e,t,r){this.buffer=this.buffer.length?Buffer.concat([this.buffer,e]):e,this.drain().then(()=>r()).catch(r)}_final(e){this.remaining>0?e(new Error("archive ends inside an entry")):e()}target(e){const t=h(e);if(!t||d(t)||".."===t||t.startsWith(`..${w}`))throw new Error(`unsafe path in archive: ${e}`);return m(this.dest,t)}async closeFile(){const e=this.file;this.file=null,e&&await new Promise((t,r)=>e.end(e=>e?r(e):t()))}async drain(){for(;;){if(this.remaining>0){if(0===this.buffer.length)return;const e=this.buffer.subarray(0,Math.min(this.remaining,this.buffer.length));this.buffer=this.buffer.subarray(e.length),this.remaining-=e.length,this.collectingLongName?this.collectingLongName.push(e):this.file&&!this.file.write(e)&&await new Promise(e=>this.file.once("drain",()=>e())),0===this.remaining&&(this.collectingLongName&&(this.longName=Buffer.concat(this.collectingLongName).toString("utf-8").replace(/\0.*$/s,""),this.collectingLongName=null),await this.closeFile());continue}if(this.padding>0){if(this.buffer.length<this.padding)return;this.buffer=this.buffer.subarray(this.padding),this.padding=0}if(this.buffer.length<512)return;const e=this.buffer.subarray(0,512);if(this.buffer=this.buffer.subarray(512),e.every(e=>0===e))continue;const t=(t,r)=>e.subarray(t,t+r).toString("utf-8").replace(/\0.*$/s,""),r=t(345,155);let o=r?`${r}/${t(0,100)}`:t(0,100);null!==this.longName&&(o=this.longName,this.longName=null);const n=parseInt(t(124,12).trim()||"0",8),i=511&parseInt(t(100,8).trim()||"644",8),a=t(156,1)||"0";if(this.remaining=n,this.padding=(512-n%512)%512,"L"===a)this.collectingLongName=[];else if("x"===a||"g"===a);else if("5"===a)await l(this.target(o),{recursive:!0});else{if("0"!==a)throw new Error(`unexpected entry type ${a} in archive: ${o}`);{const e=this.target(o);await l(m(e,".."),{recursive:!0}),this.file=s(e,{mode:i||420}),0===n&&await this.closeFile()}}}}}export async function installDesktopCli(e){const s=readDesktopCliPin(e.asar,e.platformKey,e.bundle);if(!s)return{status:"skipped",reason:"unknown app layout"};if(e.bundle&&!e.download)return{status:"skipped",reason:"no bundle mirror"};const n=e.platformKey.startsWith("win32")?"claude.exe":"claude",i=m(e.userDataDir,"claude-code",s.version),d=m(i,s.checksum.slice(0,12)),h=e.bundle?m(d,"claude.app","Contents","MacOS","claude"):m(d,n),w=m(d,".verified");try{if(o(h)&&(await c(w,"utf-8")).trim()===s.checksum)return{status:"present",version:s.version}}catch{}await l(i,{recursive:!0});const g=m(i,`.partial-${s.checksum.slice(0,12)}`),v=`${g}.download`;try{await f(w,{force:!0}),await f(g,{recursive:!0,force:!0});let n="mirror";if(e.bundle){if(e.onDownload?.(s.version),await e.download(s.version,v),await async function(e,s,o){const n=t("sha256");if(await D(r(e),new b({write(e,t,r){n.update(e),r()}})),n.digest("hex")!==s)throw new Error("downloaded bundle does not match the app's checksum");const i=y.createZstdDecompress;if(!i)throw new Error(`Node ${process.version} cannot decompress zstd (needs 22.15 or newer)`);await D(r(e),i(),new E(o))}(v,s.checksum,g),!o(m(g,"claude.app","Contents","MacOS","claude")))throw new Error("bundle has no claude.app");await f(d,{recursive:!0,force:!0}),await u(g,d)}else{const t=e.localVersionsDir?m(e.localVersionsDir,s.version):null;if(t&&o(t))await a(t,g),n="local";else{e.onDownload?.(s.version);const t=e.download??((t,r)=>$(e.platformKey,t,r));await t(s.version,g)}await l(d,{recursive:!0}),await u(g,h)}return await p(w,s.checksum),{status:"installed",version:s.version,source:n}}finally{await f(g,{recursive:!0,force:!0}),await f(v,{force:!0}),await f(`${g}.download`,{force:!0})}}let S=(...e)=>fetch(...e);export function setDesktopCliFetchForTests(e){S=e}export async function ensureDesktopCli(e){const t=x();if(!t)return{status:"skipped",reason:"unsupported architecture"};if("win32"===process.platform){const r=P();return r?installDesktopCli({userDataDir:e.userDataDir,asar:i(r),platformKey:t,localVersionsDir:C().versionsDir,onDownload:e.onDownload}):{status:"skipped",reason:"app.asar not found"}}if("darwin"===process.platform){const r=O();if(!r)return{status:"skipped",reason:"app.asar not found"};const{mirrorRepo:o,desktopVersion:n}=e;return installDesktopCli({userDataDir:e.userDataDir,asar:i(r),platformKey:t,bundle:!0,onDownload:e.onDownload,download:o&&n?(e,r)=>async function(e,t){const r=await S(e,{signal:AbortSignal.timeout(9e5)});if(!r.ok||!r.body)throw new Error(`${e}: HTTP ${r.status}`);await D(g.fromWeb(r.body),s(t))}(`${o}/-/releases/download/v${n}/claude-code-${e}-${t}.app.tar.zst`,r):void 0})}if("linux"===process.platform){const r=L();return r?installDesktopCli({userDataDir:e.userDataDir,asar:i(r),platformKey:t.replace(/-musl$/,""),localVersionsDir:t.endsWith("-musl")?void 0:C().versionsDir,onDownload:e.onDownload}):{status:"skipped",reason:"app.asar not found"}}return{status:"skipped",reason:"unsupported platform"}}
@@ -1 +1 @@
1
- import{chmodSync as e,existsSync as t,mkdirSync as o,readdirSync as n,readFileSync as r,rmSync as s}from"fs";import{dirname as i}from"path";import{join as l}from"path";import{randomUUID as a}from"crypto";import{execFileSync as c}from"child_process";import{userInfo as d}from"os";import p from"chalk";import{logger as u}from"../../utils/logger.js";import{track as f}from"../telemetry.js";import{ensureDesktopCli as m}from"./claude-desktop-cli.js";import{i18n as g}from"../i18n.js";import{BRAND_NAME as y,brand as h,brandEnv as k,CLI_NAME as _}from"../brand.js";import{backupBeforeWrite as b,atomicWriteFile as D}from"./backup.js";import{toolHome as A}from"./types.js";import{canRestartDesktop as C,isDesktopRunning as w,restartDesktop as E,WINDOWS_PACKAGE_FAMILIES as v}from"./desktop-process.js";import{setUserRegistryElevated as M}from"./elevated-reg.js";import{UserActionNeeded as O}from"./types.js";import{baseModelId as x,isClaudeModel as S}from"../model-catalog.js";import{getDefaultModels as P}from"../model-registry.js";import{claudeFormat as j,nestedClaudeProjectFiles as L}from"../sessions/formats.js";const I=y;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";export const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING="force_registry";const T=/^[a-f0-9-]{36}$/;function $(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}export function claudeDesktopUserDataDir(){const e=process.env.CLAUDE_USER_DATA_DIR?.trim();if(e)return e;const o=A(),n=Boolean(k("TEST_HOME")?.trim());switch(process.platform){case"darwin":return l(o,"Library","Application Support","Claude-3p");case"win32":{const e=!n&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(o,"AppData","Local");return v.map(t=>l(e,"Packages",t,"LocalCache","Local","Claude-3p")).find(e=>t(e))??l(e,"Claude-3p")}default:{const e=!n&&process.env.XDG_CONFIG_HOME?process.env.XDG_CONFIG_HOME:l(o,".config");return l(e,"Claude-3p")}}}const R=()=>l(claudeDesktopUserDataDir(),"configLibrary"),G=()=>l(R(),"_meta.json"),K=e=>l(R(),`${e}.json`),N=()=>l(claudeDesktopUserDataDir(),"claude_desktop_config.json");function U(e){if(!t(e))return null;const o=r(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return $(e)?e:null}catch(t){throw new Error(`Existing ${e} cannot be parsed; back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}}function F(n,r){const s=i(n);t(s)||o(s,{recursive:!0,mode:448}),b(n),D(n,JSON.stringify(r,null,2)+"\n");try{e(n,384)}catch(e){u.logError("claude-desktop.writeJson.chmod",e)}}function H(){const e=U(G());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>$(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function B(e){return e?.entries.find(e=>e.name===I&&T.test(e.id))}const V={opus:0,fable:1,sonnet:2,haiku:3};function W(e){let t=/^claude-(opus|sonnet|haiku|fable)-(\d+(?:-\d+)*)/i.exec(e);return t?{family:t[1].toLowerCase(),version:t[2].split("-").map(Number)}:(t=/^claude-(\d+(?:-\d+)*)-(opus|sonnet|haiku)/i.exec(e),t?{family:t[2].toLowerCase(),version:t[1].split("-").map(Number)}:null)}export function humanizeModelId(e){const t=W(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function J(e){return W(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>x(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(S)){i=[...new Set(t.models.filter(S).map(x))];for(const e of t.oneMillion)r.add(e)}else{i=[];for(const t of["opus","sonnet","haiku","reasoning"]){const o=(e[t]||"").trim(),n=x(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const l=e=>V[J(e)??""]??9;i.sort((e,t)=>{if(e===o)return-1;if(t===o)return 1;const n=l(e)-l(t);if(0!==n)return n;const r=W(e),s=W(t);return r&&s?function(e,t){const o=Math.max(e.length,t.length);for(let n=0;n<o;n++){const o=(t[n]??0)-(e[n]??0);if(0!==o)return o}return 0}(r.version,s.version):e.localeCompare(t)});const a=new Set,c=new Map,d=new Set(Object.values(P()).map(e=>x(e||"")));for(const e of n){const t=J(e);t&&i.includes(e)&&!d.has(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=J(e),o={name:e,labelOverride:s[e]||humanizeModelId(e)};if(r.has(e)&&(o.supports1m=!0,o.prefer1m=!0),t){o.anthropicFamilyTier=t;const n=c.get(t);n&&n!==e||a.has(t)||(o.isFamilyDefault=!0,a.add(t))}return o})}let z=null,Z=null,q=null,X=null,Y=null;function Q(e){return{inferenceProvider:"gateway",inferenceCredentialKind:"static",inferenceGatewayBaseUrl:(e.baseUrl||"").trim().replace(/\/+$/,""),inferenceGatewayApiKey:e.apiKey,inferenceModels:buildInferenceModels(e.models,e.catalog),disableDeploymentModeChooser:!1!==e.settings?.hide_official_login,chatTabEnabled:!0,chatAdvancedFileAnalysisEnabled:!0,autoModeEnabled:!0,coworkEgressAllowedHosts:["*"],disableEssentialTelemetry:!0,disableNonessentialTelemetry:!0,disableNonessentialServices:!1}}const ee={defaultModelEffort:"medium",modelPrefer1mContext:!0,skipWebFetchPreflight:!0,toolSearchEnabled:!0,builtinBrowserEnabled:!0,isDesktopExtensionEnabled:!0,sshHostAllowlist:["*"],claudeAiImport:{enabled:!0,automatic3pImport:!0,exportEnabled:!0},coworkVmIpv6Enabled:!0,mcpToolTimeoutSec:3600,updateViaUpdatesHost:!0,banner:{enabled:!1}};function te(e){return Object.fromEntries(Object.entries(ee).filter(([t])=>!e(t)))}const oe="SOFTWARE\\Policies\\Claude",ne=`HKCU\\${oe}`,re="HKLM\\SOFTWARE\\Policies\\Claude",se=`${_}-claude-policy.reg`,ie=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let le=ie;export function setRegRunnerForTests(e){le=e??ie}function ae(){return"win32"===process.platform}function ce(e){let t;try{t=le(["query",e])}catch{return null}const o=new Map;for(const e of t.split(/\r?\n/)){const t=/^\s{2,}(\S+)\s+(REG_[A-Z_]+)\s*(.*)$/.exec(e);t&&o.set(t[1],t[3])}return o}function de(){if(null===ce(ne))return;const e=l(claudeDesktopUserDataDir(),se);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),b(e),le(["export",ne,e,"/y"])}catch(e){u.logError("claude-desktop.snapshotPolicy",e)}}function pe(e){de();for(const[t,o]of Object.entries(e)){const[e,n]="boolean"==typeof o?["REG_DWORD",o?"1":"0"]:"number"==typeof o?["REG_DWORD",String(o)]:"string"==typeof o?["REG_SZ",o]:["REG_SZ",JSON.stringify(o)];le(["add",ne,"/v",t,"/t",e,"/d",n,"/f"])}}function ue(e){const t=ce(ne);if(!t)return;de();let o=t.size;for(const n of e)t.has(n)&&(le(["delete",ne,"/v",n,"/f"]),o-=1);o<=0&&le(["delete",ne,"/f"])}function fe(){const e=!Boolean(k("TEST_HOME")?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(A(),"AppData","Local");return!!t(l(e,"AnthropicClaude"))||v.some(o=>t(l(e,"Packages",o,"LocalCache","Local","Claude-3p")))}const me=[...Object.keys(Q({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(ee)];export function detectManagedConfig(){try{if("darwin"===process.platform){let e="";try{e=d().username}catch{}return[e?`/Library/Managed Preferences/${e}/com.anthropic.claudefordesktop.plist`:"","/Library/Managed Preferences/com.anthropic.claudefordesktop.plist"].filter(Boolean).find(e=>t(e))??null}if("win32"===process.platform)return ce(re)?re:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return u.logError("claude-desktop.detectManagedConfig",e),null}}function ge(){const e=A();let o;switch(process.platform){case"darwin":o=["/Applications/Claude.app",l(e,"Applications","Claude.app")];break;case"win32":{const t=process.env.LOCALAPPDATA||l(e,"AppData","Local");o=[l(t,"AnthropicClaude"),l(t,"Programs","Claude"),...v.map(e=>l(t,"Packages",e))];break}default:o=["/usr/lib/claude-desktop","/opt/Claude","/usr/bin/claude-desktop",l(e,".local","bin","claude-desktop")]}return o.push(claudeDesktopUserDataDir(),l(claudeDesktopUserDataDir(),"..","Claude")),o.some(e=>t(e))}const ye=/\d+\.\d+\.\d+/;function he(e){const t=e=>e.split(".").map(Number);return e.sort((e,o)=>{const[n,r]=[t(e),t(o)];for(let e=0;e<3;e++)if(n[e]!==r[e])return r[e]-n[e];return 0})[0]??null}function ke(){if("darwin"===process.platform){for(const e of["/Applications/Claude.app",l(A(),"Applications","Claude.app")]){const o=l(e,"Contents","Info.plist");if(!t(o))continue;const n=/<key>CFBundleShortVersionString<\/key>\s*<string>([^<]+)<\/string>/.exec(r(o,"utf-8")),s=n?ye.exec(n[1])?.[0]:void 0;if(s)return s}return null}if("win32"===process.platform){const e=l(process.env.LOCALAPPDATA||l(A(),"AppData","Local"),"AnthropicClaude");if(t(e)){const t=n(e).map(e=>/^app-(\d+\.\d+\.\d+)$/.exec(e)?.[1]).filter(e=>!!e);if(t.length>0)return he(t)}const o=v.map(e=>`'${e}'`).join(",");return he(c("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${o}) -contains $_.PackageFamilyName } | ForEach-Object { $_.Version.ToString() }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"]}).split(/\r?\n/).flatMap(e=>ye.exec(e)?.[0]??[]))}if("linux"===process.platform)try{const e=c("dpkg-query",["-W","-f=${Version}","claude-desktop"],{encoding:"utf-8",timeout:5e3,stdio:["ignore","pipe","ignore"]});return ye.exec(e)?.[0]??null}catch{return null}return null}const _e="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",be="darwin"!==process.platform&&"win32"!==process.platform||!h().installMirror?.claudeDesktop?"https://claude.ai/download":h().installMirror.claudeDesktop,De="darwin"===process.platform?`open ${be}`:"win32"===process.platform?`start ${be}`:`xdg-open ${be}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:_e,installCommand:De,configPath:G(),sessions:{format:j,files:()=>L(l(claudeDesktopUserDataDir(),"local-agent-mode-sessions"))},isInstalled:ge,installedVersion:ke,prepareRuntime:async function(){if(!["win32","darwin","linux"].includes(process.platform)||!ge())return[];const e=Date.now();try{const t=await m({userDataDir:claudeDesktopUserDataDir(),onDownload:e=>console.log(p.gray(" "+g.t("tools.claude_desktop.code_cli_downloading",{version:e}))),desktopVersion:"darwin"===process.platform?ke():null,mirrorRepo:h().installMirror?.claudeDesktop?.replace(/\/-\/releases\/latest\/?$/,"")??null});return f("desktop-code-cli","skipped"===t.status?"skip":"ok",{duration_ms:Date.now()-e,detail:{...t}}),"installed"!==t.status?[]:[{kind:"summary",text:g.t("tools.claude_desktop.code_cli_installed",{version:t.version})}]}catch(t){return u.logError("claude-desktop.prepareCodeTabCli",t),f("desktop-code-cli","fail",{duration_ms:Date.now()-e,error:t}),[{kind:"action",text:g.t("tools.claude_desktop.code_cli_failed",{reason:t instanceof Error?t.message:String(t)})}]}},runningApp:C()?{isRunning:w,restart:E}:void 0,wantsModelCatalog:!0,loadPrivateConfig(e){const t=H()??{appliedId:"",entries:[]};let o=B(t);o||(o={id:a(),name:I},t.entries.push(o));const n=Q(e);Z=!0===n.disableDeploymentModeChooser,z={models:n.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const r=U(K(o.id))??{};F(K(o.id),{...te(e=>e in r),...r,...n}),t.appliedId=o.id,F(G(),t);const s=U(N())??{};if("3p"!==s.deploymentMode&&F(N(),{...s,deploymentMode:"3p"}),X=null,Y=null,q=null,ae()){const t=ce(ne),o=me.filter(e=>t?.has(e)),r={...te(e=>t?.has(e)??!1),...n},s=!0===e.settings?.force_registry,i=!s&&fe();try{i?ue(me):pe(r),q=i?"removed":"written"}catch(e){u.logError("claude-desktop.policy",e),X=e instanceof Error?e.message.trim():String(e),(o.length>0||s)&&(Y=i?{action:"remove",values:Object.fromEntries(o.map(e=>[e,null])),deleteKey:o.length===t.size}:{action:"write",values:r,deleteKey:!1})}}},pendingElevation(){const e=Y;return e?{prompt:g.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!M(oe,e.values,e.deleteKey))return!1;const t=ce(ne),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(Y=null,X=null),o}}:null},unloadPrivateConfig(){if(ae())try{ue(me)}catch(e){u.logError("claude-desktop.removePolicy",e)}const e=H(),t=B(e);if(!e||!t)return;b(K(t.id)),s(K(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(b(G()),s(G(),{force:!0})):F(G(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=H(),t=B(e);if(!t||e?.appliedId!==t.id)return null;const o=U(K(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=H(),o=B(t);if(!o||t?.appliedId!==o.id)return;const n=U(K(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog),s=JSON.stringify(n.inferenceModels)!==JSON.stringify(r);Y=null;const i=ae()?ce(ne):null;if(!i?.has("inferenceModels"))return void(s&&F(K(o.id),{...n,inferenceModels:r}));const l=me.filter(e=>i.has(e)),a=!0!==e.settings?.force_registry&&fe();if(a||s){s&&F(K(o.id),{...n,inferenceModels:r});try{a?ue(me):pe({inferenceModels:r})}catch(e){throw u.logError("claude-desktop.refreshModelMenu registry",e),Y=a?{action:"remove",values:Object.fromEntries(l.map(e=>[e,null])),deleteKey:l.length===i.size}:{action:"write",values:{inferenceModels:r},deleteKey:!1},new O(g.t("tools.claude_desktop.refresh_needs_admin"))}}},detectCurrentConfig(){try{if(ae()){const e=ce(ne)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=B(H());if(!e)return{apiKey:null};const t=U(K(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return u.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=H(),t=B(e);return{meta:e,applied:t?U(K(t.id)):null,desktop:U(N()),...ae()?{policy:Object.fromEntries(ce(ne)??[])}:{}}}catch(e){return u.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;ae()&&ce(ne)?.has("inferenceModels")&&(de(),le(["delete",ne,"/v","inferenceModels","/f"]),e=!0);const t=B(H()),o=t?U(K(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;F(K(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(z&&z.models.length>0){const{models:t,source:o,groups:n}=z;e.push({kind:"summary",text:g.t("tools.claude_desktop.models_summary",{count:String(t.length),default:t[0].labelOverride??t[0].name})}),e.push({kind:"detail",text:g.t(`tools.claude_desktop.models_written_${o}`,{count:String(t.length),list:t.map(e=>`${e.labelOverride}${e.supports1m?" (1M)":""}`).join(", "),groups:n.join(" / ")})})}null!==Z&&e.push({kind:"detail",text:g.t(Z?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),C()&&!w()||e.push({kind:"action",text:g.t("tools.claude_desktop.restart_hint")}),Y?(e.push({kind:"action",text:g.t(`tools.claude_desktop.policy_stale_${Y.action}`)}),e.push({kind:"detail",text:X??""})):X?(e.push({kind:"detail",text:g.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:X})):ae()&&q&&e.push({kind:"detail",text:g.t(`tools.claude_desktop.registry_${q}`,{key:ne})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:g.t("tools.claude_desktop.managed_conflict",{path:t})}),e},forceResetPaths(){const e=[G(),N()];try{const t=B(H());t&&e.push(K(t.id))}catch{}return e},backupPaths(){const e=[G(),N()];ae()&&e.push(l(claudeDesktopUserDataDir(),se));try{const t=B(H());t&&e.push(K(t.id))}catch{}return e}};
1
+ import{chmodSync as e,existsSync as t,mkdirSync as o,readdirSync as n,readFileSync as r,rmSync as s}from"fs";import{dirname as i}from"path";import{join as l}from"path";import{randomUUID as a}from"crypto";import{execFileSync as c}from"child_process";import{userInfo as d}from"os";import p from"chalk";import{logger as u}from"../../utils/logger.js";import{track as f}from"../telemetry.js";import{ensureDesktopCli as m,installedDesktopAsarPath as g}from"./claude-desktop-cli.js";import{i18n as y}from"../i18n.js";import{BRAND_NAME as h,brand as k,brandEnv as _,CLI_NAME as D}from"../brand.js";import{backupBeforeWrite as b,atomicWriteFile as A}from"./backup.js";import{toolHome as C}from"./types.js";import{canRestartDesktop as w,isDesktopRunning as E,restartDesktop as v,WINDOWS_PACKAGE_FAMILIES as M}from"./desktop-process.js";import{setUserRegistryElevated as O}from"./elevated-reg.js";import{UserActionNeeded as S}from"./types.js";import{baseModelId as x,isClaudeModel as j}from"../model-catalog.js";import{getDefaultModels as P}from"../model-registry.js";import{claudeFormat as L,nestedClaudeProjectFiles as T}from"../sessions/formats.js";const I=h;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";export const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING="force_registry";const $=/^[a-f0-9-]{36}$/;function N(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}export function claudeDesktopUserDataDir(){const e=process.env.CLAUDE_USER_DATA_DIR?.trim();if(e)return e;const o=C(),n=Boolean(_("TEST_HOME")?.trim());switch(process.platform){case"darwin":return l(o,"Library","Application Support","Claude-3p");case"win32":{const e=!n&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(o,"AppData","Local");return M.map(t=>l(e,"Packages",t,"LocalCache","Local","Claude-3p")).find(e=>t(e))??l(e,"Claude-3p")}default:{const e=!n&&process.env.XDG_CONFIG_HOME?process.env.XDG_CONFIG_HOME:l(o,".config");return l(e,"Claude-3p")}}}const R=()=>l(claudeDesktopUserDataDir(),"configLibrary"),G=()=>l(R(),"_meta.json"),K=e=>l(R(),`${e}.json`),U=()=>l(claudeDesktopUserDataDir(),"claude_desktop_config.json");function F(e){if(!t(e))return null;const o=r(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return N(e)?e:null}catch(t){throw new Error(`Existing ${e} cannot be parsed; back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}}function H(n,r){const s=i(n);t(s)||o(s,{recursive:!0,mode:448}),b(n),A(n,JSON.stringify(r,null,2)+"\n");try{e(n,384)}catch(e){u.logError("claude-desktop.writeJson.chmod",e)}}function J(){const e=F(G());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>N(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function B(e){return e?.entries.find(e=>e.name===I&&$.test(e.id))}const V={opus:0,fable:1,sonnet:2,haiku:3};function W(e){let t=/^claude-(opus|sonnet|haiku|fable)-(\d+(?:-\d+)*)/i.exec(e);return t?{family:t[1].toLowerCase(),version:t[2].split("-").map(Number)}:(t=/^claude-(\d+(?:-\d+)*)-(opus|sonnet|haiku)/i.exec(e),t?{family:t[2].toLowerCase(),version:t[1].split("-").map(Number)}:null)}export function humanizeModelId(e){const t=W(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function z(e){return W(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>x(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(j)){i=[...new Set(t.models.filter(j).map(x))];for(const e of t.oneMillion)r.add(e)}else{i=[];for(const t of["opus","sonnet","haiku","reasoning"]){const o=(e[t]||"").trim(),n=x(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const l=e=>V[z(e)??""]??9;i.sort((e,t)=>{if(e===o)return-1;if(t===o)return 1;const n=l(e)-l(t);if(0!==n)return n;const r=W(e),s=W(t);return r&&s?function(e,t){const o=Math.max(e.length,t.length);for(let n=0;n<o;n++){const o=(t[n]??0)-(e[n]??0);if(0!==o)return o}return 0}(r.version,s.version):e.localeCompare(t)});const a=new Set,c=new Map,d=new Set(Object.values(P()).map(e=>x(e||"")));for(const e of n){const t=z(e);t&&i.includes(e)&&!d.has(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=z(e),o={name:e,labelOverride:s[e]||humanizeModelId(e)};if(r.has(e)&&(o.supports1m=!0,o.prefer1m=!0),t){o.anthropicFamilyTier=t;const n=c.get(t);n&&n!==e||a.has(t)||(o.isFamilyDefault=!0,a.add(t))}return o})}let Z=null,q=null,X=null,Y=null,Q=null;function ee(e){return{inferenceProvider:"gateway",inferenceCredentialKind:"static",inferenceGatewayBaseUrl:(e.baseUrl||"").trim().replace(/\/+$/,""),inferenceGatewayApiKey:e.apiKey,inferenceModels:buildInferenceModels(e.models,e.catalog),disableDeploymentModeChooser:!1!==e.settings?.hide_official_login,chatTabEnabled:!0,chatAdvancedFileAnalysisEnabled:!0,autoModeEnabled:!0,coworkEgressAllowedHosts:["*"],disableEssentialTelemetry:!0,disableNonessentialTelemetry:!0,disableNonessentialServices:!1}}const te={defaultModelEffort:"medium",modelPrefer1mContext:!0,skipWebFetchPreflight:!0,toolSearchEnabled:!0,builtinBrowserEnabled:!0,isDesktopExtensionEnabled:!0,sshHostAllowlist:["*"],claudeAiImport:{enabled:!0,automatic3pImport:!0,exportEnabled:!0},coworkVmIpv6Enabled:!0,mcpToolTimeoutSec:3600,updateViaUpdatesHost:!0,banner:{enabled:!1}},oe=()=>{if(_("TEST_HOME")?.trim())return null;const e=g();return e?r(e):null};let ne=oe,re=null;export function setDesktopAsarForTests(e){ne=void 0===e?oe:()=>e,re=null}function se(){if(re)return re;let e=null;try{e=ne()}catch(e){u.logError("claude-desktop.unsupportedDefaults",e)}return re=new Set(e?Object.keys(te).filter(t=>!e.includes(t)):[]),re}function ie(e){const t=se();return Object.fromEntries(Object.entries(te).filter(([o])=>!e(o)&&!t.has(o)))}function le(e){const t={...ie(t=>t in e),...e};for(const e of se())e in t&&JSON.stringify(t[e])===JSON.stringify(te[e])&&delete t[e];return t}const ae="SOFTWARE\\Policies\\Claude",ce=`HKCU\\${ae}`,de="HKLM\\SOFTWARE\\Policies\\Claude",pe=`${D}-claude-policy.reg`,ue=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let fe=ue;export function setRegRunnerForTests(e){fe=e??ue}function me(){return"win32"===process.platform}function ge(e){let t;try{t=fe(["query",e])}catch{return null}const o=new Map;for(const e of t.split(/\r?\n/)){const t=/^\s{2,}(\S+)\s+(REG_[A-Z_]+)\s*(.*)$/.exec(e);t&&o.set(t[1],t[3])}return o}function ye(){if(null===ge(ce))return;const e=l(claudeDesktopUserDataDir(),pe);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),b(e),fe(["export",ce,e,"/y"])}catch(e){u.logError("claude-desktop.snapshotPolicy",e)}}function he(e){ye();for(const[t,o]of Object.entries(e)){const[e,n]="boolean"==typeof o?["REG_DWORD",o?"1":"0"]:"number"==typeof o?["REG_DWORD",String(o)]:"string"==typeof o?["REG_SZ",o]:["REG_SZ",JSON.stringify(o)];fe(["add",ce,"/v",t,"/t",e,"/d",n,"/f"])}}function ke(e){const t=ge(ce);if(!t)return;ye();let o=t.size;for(const n of e)t.has(n)&&(fe(["delete",ce,"/v",n,"/f"]),o-=1);o<=0&&fe(["delete",ce,"/f"])}function _e(){const e=!Boolean(_("TEST_HOME")?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(C(),"AppData","Local");return!!t(l(e,"AnthropicClaude"))||M.some(o=>t(l(e,"Packages",o,"LocalCache","Local","Claude-3p")))}const De=[...Object.keys(ee({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(te)];export function detectManagedConfig(){try{if("darwin"===process.platform){let e="";try{e=d().username}catch{}return[e?`/Library/Managed Preferences/${e}/com.anthropic.claudefordesktop.plist`:"","/Library/Managed Preferences/com.anthropic.claudefordesktop.plist"].filter(Boolean).find(e=>t(e))??null}if("win32"===process.platform)return ge(de)?de:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return u.logError("claude-desktop.detectManagedConfig",e),null}}function be(){const e=C();let o;switch(process.platform){case"darwin":o=["/Applications/Claude.app",l(e,"Applications","Claude.app")];break;case"win32":{const t=process.env.LOCALAPPDATA||l(e,"AppData","Local");o=[l(t,"AnthropicClaude"),l(t,"Programs","Claude"),...M.map(e=>l(t,"Packages",e))];break}default:o=["/usr/lib/claude-desktop","/opt/Claude","/usr/bin/claude-desktop",l(e,".local","bin","claude-desktop")]}return o.push(claudeDesktopUserDataDir(),l(claudeDesktopUserDataDir(),"..","Claude")),o.some(e=>t(e))}const Ae=/\d+\.\d+\.\d+/;function Ce(e){const t=e=>e.split(".").map(Number);return e.sort((e,o)=>{const[n,r]=[t(e),t(o)];for(let e=0;e<3;e++)if(n[e]!==r[e])return r[e]-n[e];return 0})[0]??null}function we(){if("darwin"===process.platform){for(const e of["/Applications/Claude.app",l(C(),"Applications","Claude.app")]){const o=l(e,"Contents","Info.plist");if(!t(o))continue;const n=/<key>CFBundleShortVersionString<\/key>\s*<string>([^<]+)<\/string>/.exec(r(o,"utf-8")),s=n?Ae.exec(n[1])?.[0]:void 0;if(s)return s}return null}if("win32"===process.platform){const e=l(process.env.LOCALAPPDATA||l(C(),"AppData","Local"),"AnthropicClaude");if(t(e)){const t=n(e).map(e=>/^app-(\d+\.\d+\.\d+)$/.exec(e)?.[1]).filter(e=>!!e);if(t.length>0)return Ce(t)}const o=M.map(e=>`'${e}'`).join(",");return Ce(c("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${o}) -contains $_.PackageFamilyName } | ForEach-Object { $_.Version.ToString() }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"]}).split(/\r?\n/).flatMap(e=>Ae.exec(e)?.[0]??[]))}if("linux"===process.platform)try{const e=c("dpkg-query",["-W","-f=${Version}","claude-desktop"],{encoding:"utf-8",timeout:5e3,stdio:["ignore","pipe","ignore"]});return Ae.exec(e)?.[0]??null}catch{return null}return null}const Ee="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",ve="darwin"!==process.platform&&"win32"!==process.platform||!k().installMirror?.claudeDesktop?"https://claude.ai/download":k().installMirror.claudeDesktop,Me="darwin"===process.platform?`open ${ve}`:"win32"===process.platform?`start ${ve}`:`xdg-open ${ve}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:Ee,installCommand:Me,configPath:G(),sessions:{format:L,files:()=>T(l(claudeDesktopUserDataDir(),"local-agent-mode-sessions"))},isInstalled:be,installedVersion:we,prepareRuntime:async function(){if(!["win32","darwin","linux"].includes(process.platform)||!be())return[];const e=Date.now();try{const t=await m({userDataDir:claudeDesktopUserDataDir(),onDownload:e=>console.log(p.gray(" "+y.t("tools.claude_desktop.code_cli_downloading",{version:e}))),desktopVersion:"darwin"===process.platform?we():null,mirrorRepo:k().installMirror?.claudeDesktop?.replace(/\/-\/releases\/latest\/?$/,"")??null});return f("desktop-code-cli","skipped"===t.status?"skip":"ok",{duration_ms:Date.now()-e,detail:{...t}}),"installed"!==t.status?[]:[{kind:"summary",text:y.t("tools.claude_desktop.code_cli_installed",{version:t.version})}]}catch(t){return u.logError("claude-desktop.prepareCodeTabCli",t),f("desktop-code-cli","fail",{duration_ms:Date.now()-e,error:t}),[{kind:"action",text:y.t("tools.claude_desktop.code_cli_failed",{reason:t instanceof Error?t.message:String(t)})}]}},runningApp:w()?{isRunning:E,restart:v}:void 0,wantsModelCatalog:!0,loadPrivateConfig(e){const t=J()??{appliedId:"",entries:[]};let o=B(t);o||(o={id:a(),name:I},t.entries.push(o));const n=ee(e);q=!0===n.disableDeploymentModeChooser,Z={models:n.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const r=F(K(o.id))??{};H(K(o.id),{...le(r),...n}),t.appliedId=o.id,H(G(),t);const s=F(U())??{};if("3p"!==s.deploymentMode&&H(U(),{...s,deploymentMode:"3p"}),Y=null,Q=null,X=null,me()){const t=ge(ce),o=De.filter(e=>t?.has(e)),r={...ie(e=>t?.has(e)??!1),...n},s=!0===e.settings?.force_registry,i=!s&&_e();try{i?ke(De):he(r),X=i?"removed":"written"}catch(e){u.logError("claude-desktop.policy",e),Y=e instanceof Error?e.message.trim():String(e),(o.length>0||s)&&(Q=i?{action:"remove",values:Object.fromEntries(o.map(e=>[e,null])),deleteKey:o.length===t.size}:{action:"write",values:r,deleteKey:!1})}}},pendingElevation(){const e=Q;return e?{prompt:y.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!O(ae,e.values,e.deleteKey))return!1;const t=ge(ce),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(Q=null,Y=null),o}}:null},unloadPrivateConfig(){if(me())try{ke(De)}catch(e){u.logError("claude-desktop.removePolicy",e)}const e=J(),t=B(e);if(!e||!t)return;b(K(t.id)),s(K(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(b(G()),s(G(),{force:!0})):H(G(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=J(),t=B(e);if(!t||e?.appliedId!==t.id)return null;const o=F(K(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=J(),o=B(t);if(!o||t?.appliedId!==o.id)return;const n=F(K(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog),s=JSON.stringify(n.inferenceModels)!==JSON.stringify(r),i={...le(n),inferenceModels:r},l=JSON.stringify(i)!==JSON.stringify(n);Q=null;const a=me()?ge(ce):null;if(!a?.has("inferenceModels"))return void(l&&H(K(o.id),i));const c=De.filter(e=>a.has(e)),d=!0!==e.settings?.force_registry&&_e();if(l&&H(K(o.id),i),d||s)try{d?ke(De):he({inferenceModels:r})}catch(e){throw u.logError("claude-desktop.refreshModelMenu registry",e),Q=d?{action:"remove",values:Object.fromEntries(c.map(e=>[e,null])),deleteKey:c.length===a.size}:{action:"write",values:{inferenceModels:r},deleteKey:!1},new S(y.t("tools.claude_desktop.refresh_needs_admin"))}},detectCurrentConfig(){try{if(me()){const e=ge(ce)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=B(J());if(!e)return{apiKey:null};const t=F(K(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return u.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=J(),t=B(e);return{meta:e,applied:t?F(K(t.id)):null,desktop:F(U()),...me()?{policy:Object.fromEntries(ge(ce)??[])}:{}}}catch(e){return u.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;me()&&ge(ce)?.has("inferenceModels")&&(ye(),fe(["delete",ce,"/v","inferenceModels","/f"]),e=!0);const t=B(J()),o=t?F(K(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;H(K(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(Z&&Z.models.length>0){const{models:t,source:o,groups:n}=Z;e.push({kind:"summary",text:y.t("tools.claude_desktop.models_summary",{count:String(t.length),default:t[0].labelOverride??t[0].name})}),e.push({kind:"detail",text:y.t(`tools.claude_desktop.models_written_${o}`,{count:String(t.length),list:t.map(e=>`${e.labelOverride}${e.supports1m?" (1M)":""}`).join(", "),groups:n.join(" / ")})})}null!==q&&e.push({kind:"detail",text:y.t(q?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),w()&&!E()||e.push({kind:"action",text:y.t("tools.claude_desktop.restart_hint")}),Q?(e.push({kind:"action",text:y.t(`tools.claude_desktop.policy_stale_${Q.action}`)}),e.push({kind:"detail",text:Y??""})):Y?(e.push({kind:"detail",text:y.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:Y})):me()&&X&&e.push({kind:"detail",text:y.t(`tools.claude_desktop.registry_${X}`,{key:ce})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:y.t("tools.claude_desktop.managed_conflict",{path:t})}),e},forceResetPaths(){const e=[G(),U()];try{const t=B(J());t&&e.push(K(t.id))}catch{}return e},backupPaths(){const e=[G(),U()];me()&&e.push(l(claudeDesktopUserDataDir(),pe));try{const t=B(J());t&&e.push(K(t.id))}catch{}return e}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marsapi/cli",
3
- "version": "0.0.142",
3
+ "version": "0.0.144",
4
4
  "description": "Configure Claude Code, Codex, Grok Build and other coding tools for Mars AI with one command",
5
5
  "main": "dist/index.js",
6
6
  "bin": {