@marsapi/cli 0.0.154 → 0.0.155

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.
@@ -37,7 +37,7 @@
37
37
  },
38
38
  {
39
39
  "description": "100 万上下文 | 12.8 万输出 | 低延迟 | 高频轻量任务",
40
- "group": "grp_6eg2dq9ywgrg",
40
+ "group": "grp_6lyxfgbs440g",
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_6eg2dq9ywgrg",
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_6co8aqwefsoh",
58
+ "group": "grp_pzxnceygmqlp",
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_irydsgijuckh",
67
+ "group": "grp_6lyxfgbs440g",
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_6eg2dq9ywgrg",
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_6lyxfgbs440g",
85
+ "group": "grp_irydsgijuckh",
86
86
  "group_name": "",
87
87
  "hidden": false,
88
88
  "id": "claude-opus-5-5",
@@ -100,7 +100,7 @@
100
100
  },
101
101
  {
102
102
  "description": "100 万上下文 | Agent 编程 | 工具调用 | 知识工作",
103
- "group": "grp_6eg2dq9ywgrg",
103
+ "group": "grp_pzxnceygmqlp",
104
104
  "group_name": "",
105
105
  "hidden": false,
106
106
  "id": "claude-sonnet-5",
@@ -109,7 +109,7 @@
109
109
  },
110
110
  {
111
111
  "description": "100 万上下文 | 12.8 万输出 | Agent 编程 | 知识工作",
112
- "group": "grp_6lyxfgbs440g",
112
+ "group": "grp_6co8aqwefsoh",
113
113
  "group_name": "",
114
114
  "hidden": false,
115
115
  "id": "claude-sonnet-5-5",
@@ -129,7 +129,7 @@
129
129
  },
130
130
  {
131
131
  "description": "105 万上下文 | 12.8 万输出 | 前沿档",
132
- "group": "grp_irydsgijuckh",
132
+ "group": "grp_squ2qzjnehps",
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_squ2qzjnehps",
150
+ "group": "grp_bsbtt432saoq",
151
151
  "group_name": "",
152
152
  "hidden": false,
153
153
  "id": "gpt-6-astra",
@@ -165,7 +165,7 @@
165
165
  },
166
166
  {
167
167
  "description": "105 万上下文 | 12.8 万输出 | 复杂编程与 Agent 工作流",
168
- "group": "grp_irydsgijuckh",
168
+ "group": "grp_squ2qzjnehps",
169
169
  "group_name": "",
170
170
  "hidden": false,
171
171
  "id": "gpt-6-sol",
@@ -174,7 +174,7 @@
174
174
  },
175
175
  {
176
176
  "description": "105 万上下文 | 12.8 万输出 | 文字与图像输入 | 工具调用、联网搜索、结构化输出 | 工具调用使用 Responses API",
177
- "group": "grp_irydsgijuckh",
177
+ "group": "grp_squ2qzjnehps",
178
178
  "group_name": "",
179
179
  "hidden": false,
180
180
  "id": "gpt-6.1-sol",
@@ -221,7 +221,7 @@
221
221
  },
222
222
  {
223
223
  "description": "约 100 万上下文 | 深度推理 | 密集长文档",
224
- "group": "grp_z5khwusxuh2j",
224
+ "group": "grp_3pi5kyqkp51b",
225
225
  "group_name": "",
226
226
  "hidden": false,
227
227
  "id": "gemini-3.1-pro",
@@ -248,7 +248,7 @@
248
248
  },
249
249
  {
250
250
  "description": "约 208 token/秒 | 高吞吐 | 多语言 | 编码",
251
- "group": "grp_irydsgijuckh",
251
+ "group": "grp_z5khwusxuh2j",
252
252
  "group_name": "",
253
253
  "hidden": false,
254
254
  "id": "gemini-3.6-flash",
package/components.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema": 1,
3
3
  "about": "Components the CLI installs and upgrades (its list / install / upgrade commands). Read by src/lib/components.ts and by scripts/gen-components-doc.mjs (docs, the install scripts' README). {scripts} = the brand's installMirror.scripts, {agy} = installMirror.agy, {devtools} = the neutral CNB mirror of fnm / uv / Git for Windows.",
4
- "devtools": "https://cnb.cool/lib/devtools/-/releases/latest/download",
4
+ "devtools": "https://cnb.cool/lib/mirrors/-/releases/download/devtools",
5
5
  "components": [
6
6
  {
7
7
  "id": "node",
@@ -124,8 +124,8 @@
124
124
  "app": "claude-desktop",
125
125
  "latest": { "type": "app" },
126
126
  "sources": {
127
- "darwin": "高速下载站 lib/claude-desktop(官方 dmg)",
128
- "win32": "高速下载站 lib/claude-desktop(官方 MSIX)"
127
+ "darwin": "高速下载站 lib/mirrors 的 claude-desktop(官方 dmg)",
128
+ "win32": "高速下载站 lib/mirrors 的 claude-desktop(官方 MSIX)"
129
129
  },
130
130
  "verify": {
131
131
  "checksum": "SHA256SUMS",
@@ -143,8 +143,8 @@
143
143
  "app": "chatgpt",
144
144
  "latest": { "type": "app" },
145
145
  "sources": {
146
- "darwin": "高速下载站 lib/chatgpt-desktop(官方 dmg,只有 Apple 芯片版)",
147
- "win32": "高速下载站 lib/chatgpt-desktop(Microsoft Store 同一个 MSIX)"
146
+ "darwin": "高速下载站 lib/mirrors 的 chatgpt-desktop(官方 dmg,只有 Apple 芯片版)",
147
+ "win32": "高速下载站 lib/mirrors 的 chatgpt-desktop(Microsoft Store 同一个 MSIX)"
148
148
  },
149
149
  "verify": {
150
150
  "checksum": "SHA256SUMS",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  {
39
39
  "description": "100 万上下文 | 12.8 万输出 | 低延迟 | 高频轻量任务",
40
- "group": "grp_6eg2dq9ywgrg",
40
+ "group": "grp_6lyxfgbs440g",
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_6eg2dq9ywgrg",
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_6co8aqwefsoh",
58
+ "group": "grp_pzxnceygmqlp",
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_irydsgijuckh",
67
+ "group": "grp_6lyxfgbs440g",
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_6eg2dq9ywgrg",
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_6lyxfgbs440g",
85
+ "group": "grp_irydsgijuckh",
86
86
  "group_name": "",
87
87
  "hidden": false,
88
88
  "id": "claude-opus-5-5",
@@ -100,7 +100,7 @@
100
100
  },
101
101
  {
102
102
  "description": "100 万上下文 | Agent 编程 | 工具调用 | 知识工作",
103
- "group": "grp_6eg2dq9ywgrg",
103
+ "group": "grp_pzxnceygmqlp",
104
104
  "group_name": "",
105
105
  "hidden": false,
106
106
  "id": "claude-sonnet-5",
@@ -109,7 +109,7 @@
109
109
  },
110
110
  {
111
111
  "description": "100 万上下文 | 12.8 万输出 | Agent 编程 | 知识工作",
112
- "group": "grp_6lyxfgbs440g",
112
+ "group": "grp_6co8aqwefsoh",
113
113
  "group_name": "",
114
114
  "hidden": false,
115
115
  "id": "claude-sonnet-5-5",
@@ -129,7 +129,7 @@
129
129
  },
130
130
  {
131
131
  "description": "105 万上下文 | 12.8 万输出 | 前沿档",
132
- "group": "grp_irydsgijuckh",
132
+ "group": "grp_squ2qzjnehps",
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_squ2qzjnehps",
150
+ "group": "grp_bsbtt432saoq",
151
151
  "group_name": "",
152
152
  "hidden": false,
153
153
  "id": "gpt-6-astra",
@@ -165,7 +165,7 @@
165
165
  },
166
166
  {
167
167
  "description": "105 万上下文 | 12.8 万输出 | 复杂编程与 Agent 工作流",
168
- "group": "grp_irydsgijuckh",
168
+ "group": "grp_squ2qzjnehps",
169
169
  "group_name": "",
170
170
  "hidden": false,
171
171
  "id": "gpt-6-sol",
@@ -174,7 +174,7 @@
174
174
  },
175
175
  {
176
176
  "description": "105 万上下文 | 12.8 万输出 | 文字与图像输入 | 工具调用、联网搜索、结构化输出 | 工具调用使用 Responses API",
177
- "group": "grp_irydsgijuckh",
177
+ "group": "grp_squ2qzjnehps",
178
178
  "group_name": "",
179
179
  "hidden": false,
180
180
  "id": "gpt-6.1-sol",
@@ -221,7 +221,7 @@
221
221
  },
222
222
  {
223
223
  "description": "约 100 万上下文 | 深度推理 | 密集长文档",
224
- "group": "grp_z5khwusxuh2j",
224
+ "group": "grp_3pi5kyqkp51b",
225
225
  "group_name": "",
226
226
  "hidden": false,
227
227
  "id": "gemini-3.1-pro",
@@ -248,7 +248,7 @@
248
248
  },
249
249
  {
250
250
  "description": "约 208 token/秒 | 高吞吐 | 多语言 | 编码",
251
- "group": "grp_irydsgijuckh",
251
+ "group": "grp_z5khwusxuh2j",
252
252
  "group_name": "",
253
253
  "hidden": false,
254
254
  "id": "gemini-3.6-flash",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema": 1,
3
3
  "about": "Components the CLI installs and upgrades (its list / install / upgrade commands). Read by src/lib/components.ts and by scripts/gen-components-doc.mjs (docs, the install scripts' README). {scripts} = the brand's installMirror.scripts, {agy} = installMirror.agy, {devtools} = the neutral CNB mirror of fnm / uv / Git for Windows.",
4
- "devtools": "https://cnb.cool/lib/devtools/-/releases/latest/download",
4
+ "devtools": "https://cnb.cool/lib/mirrors/-/releases/download/devtools",
5
5
  "components": [
6
6
  {
7
7
  "id": "node",
@@ -124,8 +124,8 @@
124
124
  "app": "claude-desktop",
125
125
  "latest": { "type": "app" },
126
126
  "sources": {
127
- "darwin": "高速下载站 lib/claude-desktop(官方 dmg)",
128
- "win32": "高速下载站 lib/claude-desktop(官方 MSIX)"
127
+ "darwin": "高速下载站 lib/mirrors 的 claude-desktop(官方 dmg)",
128
+ "win32": "高速下载站 lib/mirrors 的 claude-desktop(官方 MSIX)"
129
129
  },
130
130
  "verify": {
131
131
  "checksum": "SHA256SUMS",
@@ -143,8 +143,8 @@
143
143
  "app": "chatgpt",
144
144
  "latest": { "type": "app" },
145
145
  "sources": {
146
- "darwin": "高速下载站 lib/chatgpt-desktop(官方 dmg,只有 Apple 芯片版)",
147
- "win32": "高速下载站 lib/chatgpt-desktop(Microsoft Store 同一个 MSIX)"
146
+ "darwin": "高速下载站 lib/mirrors 的 chatgpt-desktop(官方 dmg,只有 Apple 芯片版)",
147
+ "win32": "高速下载站 lib/mirrors 的 chatgpt-desktop(Microsoft Store 同一个 MSIX)"
148
148
  },
149
149
  "verify": {
150
150
  "checksum": "SHA256SUMS",
@@ -0,0 +1 @@
1
+ const e=/\/-\/releases\/latest$/;export function mirrorFileUrl(r,t,l){const s=r.replace(/\/+$/,"");if(e.test(s)){const r=s.replace(e,"");return l?`${r}/-/releases/download/${l}/${t}`:`${r}/-/releases/latest/download/${t}`}return`${s}/${t}`}export function mirrorPageUrl(e){const r=e.replace(/\/+$/,""),t=/^(.*\/-\/releases)\/download\/([^/]+)$/.exec(r);return t?`${t[1]}/tag/${t[2]}`:r.replace(/\/-\/releases\/latest\/download$/,"/-/releases/latest")}
@@ -1 +1 @@
1
- import{existsSync as e}from"fs";import{join as t}from"path";import{brand as s}from"../brand.js";import{WINDOWS_PACKAGE_FAMILIES as o}from"./desktop-process.js";import{createDesktopAppInstaller as r}from"./desktop-app-installer.js";import{toolHome as a}from"./types.js";export const ANTHROPIC_TEAM_ID="Q6L2SF6YDW";export{DesktopInstallError,parseSha256Sums,setDesktopAppDepsForTests}from"./desktop-app-installer.js";const p=r({id:"claude-desktop",mirror:()=>s().installMirror?.claudeDesktop,asset:(e,t)=>"darwin"===e?"Claude-mac-universal.dmg":"win32"===e?t?"Claude-win-arm64.msix":"Claude-win-x64.msix":null,versionFile:()=>"version.txt",releaseTag:e=>`v${e}`,macApp:{source:"Claude.app",installedNames:["Claude.app"],bundleId:"com.anthropic.claudefordesktop",teamId:"Q6L2SF6YDW"},windows:{signer:/(^|,\s*)O="?Anthropic, PBC"?(,|$)/,packageFilter:`@(${o.map(e=>`'${e}'`).join(",")}) -contains $_.PackageFamilyName`},extraBlocker:s=>"win32"===s&&function(){const s=process.env.LOCALAPPDATA||t(a(),"AppData","Local");return e(t(s,"AnthropicClaude","Update.exe"))}()?"classic_install":null});export const desktopMirrorRepo=p.mirrorRepo;export const desktopAssetName=p.assetName;export const desktopInstallBlocker=p.blocker;export const fetchLatestDesktopVersion=(e=8e3)=>p.latestVersion(e);export const installedMacApp=p.installedMacApp;export const verifyMacApp=p.verifyMacApp;export const verifyWindowsPackage=p.verifyWindowsPackage;export function installLatestDesktop(e={}){return p.install(e)}
1
+ import{existsSync as e}from"fs";import{join as s}from"path";import{brand as t}from"../brand.js";import{WINDOWS_PACKAGE_FAMILIES as o}from"./desktop-process.js";import{createDesktopAppInstaller as a}from"./desktop-app-installer.js";import{toolHome as r}from"./types.js";export const ANTHROPIC_TEAM_ID="Q6L2SF6YDW";export{DesktopInstallError,parseSha256Sums,setDesktopAppDepsForTests}from"./desktop-app-installer.js";const p=a({id:"claude-desktop",mirror:()=>t().installMirror?.claudeDesktop,asset:(e,s)=>"darwin"===e?"Claude-mac-universal.dmg":"win32"===e?s?"Claude-win-arm64.msix":"Claude-win-x64.msix":null,versionFile:()=>"version.txt",releaseTag:e=>`v${e}`,macApp:{source:"Claude.app",installedNames:["Claude.app"],bundleId:"com.anthropic.claudefordesktop",teamId:"Q6L2SF6YDW"},windows:{signer:/(^|,\s*)O="?Anthropic, PBC"?(,|$)/,packageFilter:`@(${o.map(e=>`'${e}'`).join(",")}) -contains $_.PackageFamilyName`},extraBlocker:t=>"win32"===t&&function(){const t=process.env.LOCALAPPDATA||s(r(),"AppData","Local");return e(s(t,"AnthropicClaude","Update.exe"))}()?"classic_install":null});export const desktopAssetName=p.assetName;export const desktopInstallBlocker=p.blocker;export const fetchLatestDesktopVersion=(e=8e3)=>p.latestVersion(e);export const installedMacApp=p.installedMacApp;export const verifyMacApp=p.verifyMacApp;export const verifyWindowsPackage=p.verifyWindowsPackage;export function installLatestDesktop(e={}){return p.install(e)}
@@ -1 +1 @@
1
- import{execFileSync as e}from"child_process";import{createHash as r}from"crypto";import{createReadStream as t,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 p,writeFile as f}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 v from"zlib";import{logger as y}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";import{powerShellEnv as P}from"../powershell-env.js";export function readDesktopCliPin(e,r,t=!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?.[r],l=t?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 L(){const r=m(process.env.LOCALAPPDATA||"","AnthropicClaude");if(process.env.LOCALAPPDATA&&o(r)){const e=n(r).filter(e=>/^app-\d+\.\d+\.\d+$/.test(e)).sort((e,r)=>r.localeCompare(e,void 0,{numeric:!0}));for(const t of e){const e=m(r,t,"resources","app.asar");if(o(e))return e}}try{const r=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"],env:P()});for(const e of r.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)){const r=m(e,"app","resources","app.asar");if(o(r))return r}}catch(e){y.logError("claude-desktop-cli.windowsAsarPath",e)}return null}function O(){if(k("TEST_HOME")?.trim())return null;for(const e of["/usr/lib/claude-desktop","/opt/Claude"]){const r=m(e,"resources","app.asar");if(o(r))return r}return null}function E(){for(const e of["/Applications/Claude.app",m(A(),"Applications","Claude.app")]){const r=m(e,"Contents","Resources","app.asar");if(o(r))return r}return null}export function installedDesktopAsarPath(){return"win32"===process.platform?L():"darwin"===process.platform?E():"linux"===process.platform?O():null}class j 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,r,t){this.buffer=this.buffer.length?Buffer.concat([this.buffer,e]):e,this.drain().then(()=>t()).catch(t)}_final(e){this.remaining>0?e(new Error("archive ends inside an entry")):e()}target(e){const r=h(e);if(!r||d(r)||".."===r||r.startsWith(`..${w}`))throw new Error(`unsafe path in archive: ${e}`);return m(this.dest,r)}async closeFile(){const e=this.file;this.file=null,e&&await new Promise((r,t)=>e.end(e=>e?t(e):r()))}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 r=(r,t)=>e.subarray(r,r+t).toString("utf-8").replace(/\0.*$/s,""),t=r(345,155);let o=t?`${t}/${r(0,100)}`:r(0,100);null!==this.longName&&(o=this.longName,this.longName=null);const n=parseInt(r(124,12).trim()||"0",8),i=511&parseInt(r(100,8).trim()||"644",8),a=r(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)}`),y=`${g}.download`;try{await p(w,{force:!0}),await p(g,{recursive:!0,force:!0});let n="mirror";if(e.bundle){if(e.onDownload?.(s.version),await e.download(s.version,y),await async function(e,s,o){const n=r("sha256");if(await D(t(e),new b({write(e,r,t){n.update(e),t()}})),n.digest("hex")!==s)throw new Error("downloaded bundle does not match the app's checksum");const i=v.createZstdDecompress;if(!i)throw new Error(`Node ${process.version} cannot decompress zstd (needs 22.15 or newer)`);await D(t(e),i(),new j(o))}(y,s.checksum,g),!o(m(g,"claude.app","Contents","MacOS","claude")))throw new Error("bundle has no claude.app");await p(d,{recursive:!0,force:!0}),await u(g,d)}else{const r=e.localVersionsDir?m(e.localVersionsDir,s.version):null;if(r&&o(r))await a(r,g),n="local";else{e.onDownload?.(s.version);const r=e.download??((r,t)=>$(e.platformKey,r,t));await r(s.version,g)}await l(d,{recursive:!0}),await u(g,h)}return await f(w,s.checksum),{status:"installed",version:s.version,source:n}}finally{await p(g,{recursive:!0,force:!0}),await p(y,{force:!0}),await p(`${g}.download`,{force:!0})}}let S=(...e)=>fetch(...e);export function setDesktopCliFetchForTests(e){S=e}export async function ensureDesktopCli(e){const r=x();if(!r)return{status:"skipped",reason:"unsupported architecture"};if("win32"===process.platform){const t=L();return t?installDesktopCli({userDataDir:e.userDataDir,asar:i(t),platformKey:r,localVersionsDir:C().versionsDir,onDownload:e.onDownload}):{status:"skipped",reason:"app.asar not found"}}if("darwin"===process.platform){const t=E();if(!t)return{status:"skipped",reason:"app.asar not found"};const{mirrorRepo:o,desktopVersion:n}=e;return installDesktopCli({userDataDir:e.userDataDir,asar:i(t),platformKey:r,bundle:!0,onDownload:e.onDownload,download:o&&n?(e,t)=>async function(e,r){const t=await S(e,{signal:AbortSignal.timeout(9e5)});if(!t.ok||!t.body)throw new Error(`${e}: HTTP ${t.status}`);await D(g.fromWeb(t.body),s(r))}(`${o}/-/releases/download/v${n}/claude-code-${e}-${r}.app.tar.zst`,t):void 0})}if("linux"===process.platform){const t=O();return t?installDesktopCli({userDataDir:e.userDataDir,asar:i(t),platformKey:r.replace(/-musl$/,""),localVersionsDir:r.endsWith("-musl")?void 0:C().versionsDir,onDownload:e.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 r}from"crypto";import{createReadStream as t,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 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 v from"zlib";import{logger as y}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";import{mirrorFileUrl as P}from"../mirror-url.js";import{powerShellEnv as L}from"../powershell-env.js";export function readDesktopCliPin(e,r,t=!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?.[r],l=t?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}}function O(){const r=m(process.env.LOCALAPPDATA||"","AnthropicClaude");if(process.env.LOCALAPPDATA&&o(r)){const e=i(r).filter(e=>/^app-\d+\.\d+\.\d+$/.test(e)).sort((e,r)=>r.localeCompare(e,void 0,{numeric:!0}));for(const t of e){const e=m(r,t,"resources","app.asar");if(o(e))return e}}try{const r=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"],env:L()});for(const e of r.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)){const r=m(e,"app","resources","app.asar");if(o(r))return r}}catch(e){y.logError("claude-desktop-cli.windowsAsarPath",e)}return null}function E(){if(k("TEST_HOME")?.trim())return null;for(const e of["/usr/lib/claude-desktop","/opt/Claude"]){const r=m(e,"resources","app.asar");if(o(r))return r}return null}function j(){for(const e of["/Applications/Claude.app",m(A(),"Applications","Claude.app")]){const r=m(e,"Contents","Resources","app.asar");if(o(r))return r}return null}export function installedDesktopAsarPath(){return"win32"===process.platform?O():"darwin"===process.platform?j():"linux"===process.platform?E():null}class S 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,r,t){this.buffer=this.buffer.length?Buffer.concat([this.buffer,e]):e,this.drain().then(()=>t()).catch(t)}_final(e){this.remaining>0?e(new Error("archive ends inside an entry")):e()}target(e){const r=h(e);if(!r||d(r)||".."===r||r.startsWith(`..${w}`))throw new Error(`unsafe path in archive: ${e}`);return m(this.dest,r)}async closeFile(){const e=this.file;this.file=null,e&&await new Promise((r,t)=>e.end(e=>e?t(e):r()))}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 r=(r,t)=>e.subarray(r,r+t).toString("utf-8").replace(/\0.*$/s,""),t=r(345,155);let o=t?`${t}/${r(0,100)}`:r(0,100);null!==this.longName&&(o=this.longName,this.longName=null);const i=parseInt(r(124,12).trim()||"0",8),n=511&parseInt(r(100,8).trim()||"644",8),a=r(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(m(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=m(e.userDataDir,"claude-code",s.version),d=m(n,s.checksum.slice(0,12)),h=e.bundle?m(d,"claude.app","Contents","MacOS","claude"):m(d,i),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(n,{recursive:!0});const g=m(n,`.partial-${s.checksum.slice(0,12)}`),y=`${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,y),await async function(e,s,o){const i=r("sha256");if(await D(t(e),new b({write(e,r,t){i.update(e),t()}})),i.digest("hex")!==s)throw new Error("downloaded bundle does not match the app's checksum");const n=v.createZstdDecompress;if(!n)throw new Error(`Node ${process.version} cannot decompress zstd (needs 22.15 or newer)`);await D(t(e),n(),new S(o))}(y,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 r=e.localVersionsDir?m(e.localVersionsDir,s.version):null;if(r&&o(r))await a(r,g),i="local";else{e.onDownload?.(s.version);const r=e.download??((r,t)=>$(e.platformKey,r,t));await r(s.version,g)}await l(d,{recursive:!0}),await u(g,h)}return await p(w,s.checksum),{status:"installed",version:s.version,source:i}}finally{await f(g,{recursive:!0,force:!0}),await f(y,{force:!0}),await f(`${g}.download`,{force:!0})}}let F=(...e)=>fetch(...e);export function setDesktopCliFetchForTests(e){F=e}export async function ensureDesktopCli(e){const r=x();if(!r)return{status:"skipped",reason:"unsupported architecture"};if("win32"===process.platform){const t=O();return t?installDesktopCli({userDataDir:e.userDataDir,asar:n(t),platformKey:r,localVersionsDir:C().versionsDir,onDownload:e.onDownload}):{status:"skipped",reason:"app.asar not found"}}if("darwin"===process.platform){const t=j();if(!t)return{status:"skipped",reason:"app.asar not found"};const{mirror:o,desktopVersion:i}=e;return installDesktopCli({userDataDir:e.userDataDir,asar:n(t),platformKey:r,bundle:!0,onDownload:e.onDownload,download:o&&i?(e,t)=>async function(e,r){const t=await F(e,{signal:AbortSignal.timeout(9e5)});if(!t.ok||!t.body)throw new Error(`${e}: HTTP ${t.status}`);await D(g.fromWeb(t.body),s(r))}(P(o,`claude-code-${e}-${r}.app.tar.zst`,`v${i}`),t):void 0})}if("linux"===process.platform){const t=E();return t?installDesktopCli({userDataDir:e.userDataDir,asar:n(t),platformKey:r.replace(/-musl$/,""),localVersionsDir:r.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 u from"chalk";import{logger as p}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 w}from"../brand.js";import{backupBeforeWrite as b,atomicWriteFile as D}from"./backup.js";import{toolHome as A}from"./types.js";import{canRestartDesktop as C,desktopQuitRefused as v,isDesktopRunning as E,launchDesktop as M,quitDesktop as O,restartDesktop as S,WINDOWS_PACKAGE_FAMILIES as x}from"./desktop-process.js";import{desktopInstallBlocker as j,fetchLatestDesktopVersion as P,installedMacApp as I,installLatestDesktop as L}from"./claude-desktop-app.js";import{setUserRegistryElevated as T}from"./elevated-reg.js";import{UserActionNeeded as $}from"./types.js";import{savedApiKeys as G}from"../config.js";import{isOurGatewayUrl as N,noteWrittenGatewayUrl as U}from"../gateway-addresses.js";import{baseModelId as R,isClaudeModel as K}from"../model-catalog.js";import{getDefaultModels as F}from"../model-registry.js";import{claudeFormat as B,nestedClaudeProjectFiles as H}from"../sessions/formats.js";import{powerShellEnv as J}from"../powershell-env.js";const V=h;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";export const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING="force_registry";const W=/^[a-f0-9-]{36}$/;function z(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(_("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 x.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 q=()=>l(claudeDesktopUserDataDir(),"configLibrary"),X=()=>l(q(),"_meta.json"),Z=e=>l(q(),`${e}.json`),Y=()=>l(claudeDesktopUserDataDir(),"claude_desktop_config.json");function Q(e){if(!t(e))return null;const o=r(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return z(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 ee(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){p.logError("claude-desktop.writeJson.chmod",e)}}function te(){const e=Q(X());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>z(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function oe(e){return e?.entries.find(e=>e.name===V&&W.test(e.id))}const ne={opus:0,fable:1,sonnet:2,haiku:3};function re(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=re(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function se(e){return re(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>R(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(K)){i=[...new Set(t.models.filter(K).map(R))];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=R(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const l=e=>ne[se(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=re(e),s=re(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(F()).map(e=>R(e||"")));for(const e of n){const t=se(e);t&&i.includes(e)&&!d.has(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=se(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 ie=null,le=null,ae=null,ce=null,de=null;function ue(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 pe={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}},fe=()=>{if(_("TEST_HOME")?.trim())return null;const e=g();return e?r(e):null};let me=fe,ge=null;export function setDesktopAsarForTests(e){me=void 0===e?fe:()=>e,ge=null}function ye(){if(ge)return ge;let e=null;try{e=me()}catch(e){p.logError("claude-desktop.unsupportedDefaults",e)}return ge=new Set(e?Object.keys(pe).filter(t=>!e.includes(t)):[]),ge}function he(e){const t=ye();return Object.fromEntries(Object.entries(pe).filter(([o])=>!e(o)&&!t.has(o)))}function ke(e){const t={...he(t=>t in e),...e};for(const e of ye())e in t&&JSON.stringify(t[e])===JSON.stringify(pe[e])&&delete t[e];return t}const _e="SOFTWARE\\Policies\\Claude",we=`HKCU\\${_e}`,be="HKLM\\SOFTWARE\\Policies\\Claude",De=`${w}-claude-policy.reg`,Ae=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let Ce=Ae;export function setRegRunnerForTests(e){Ce=e??Ae}function ve(){return"win32"===process.platform}function Ee(e){let t;try{t=Ce(["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 Me(){if(null===Ee(we))return;const e=l(claudeDesktopUserDataDir(),De);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),b(e),Ce(["export",we,e,"/y"])}catch(e){p.logError("claude-desktop.snapshotPolicy",e)}}function Oe(e){Me();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)];Ce(["add",we,"/v",t,"/t",e,"/d",n,"/f"])}}function Se(e){const t=Ee(we);if(!t)return;Me();let o=t.size;for(const n of e)t.has(n)&&(Ce(["delete",we,"/v",n,"/f"]),o-=1);o<=0&&Ce(["delete",we,"/f"])}function xe(){const e=!Boolean(_("TEST_HOME")?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(A(),"AppData","Local");return!!t(l(e,"AnthropicClaude"))||x.some(o=>t(l(e,"Packages",o,"LocalCache","Local","Claude-3p")))}const je=[...Object.keys(ue({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(pe)];function Pe(e){if(!e||!je.some(t=>e.has(t)))return"none";const t=e.get("inferenceGatewayApiKey")?.trim();return N(e.get("inferenceGatewayBaseUrl"))||t&&G().includes(t)?"ours":"foreign"}function Ie(){const e=Q(Y())?.deploymentMode;if(void 0!==e&&"3p"!==e)return{kind:"mode"};const t=te(),o=t?.entries.find(e=>e.id===t.appliedId);if(!o||o.id===oe(t)?.id)return null;const n=Q(Z(o.id));return n&&(n.inferenceProvider||n.inferenceGatewayBaseUrl)?{kind:"entry",name:o.name}:null}function Le(e){return"mode"===e.kind?y.t("tools.claude_desktop.current_official"):y.t("tools.claude_desktop.current_entry",{name:e.name})}let Te=null,$e=null;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 Ee(be)?be:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return p.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"),...x.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 Ne=/\d+\.\d+\.\d+/;function Ue(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 Re(){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?Ne.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 Ue(t)}const o=x.map(e=>`'${e}'`).join(",");return Ue(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"],env:J()}).split(/\r?\n/).flatMap(e=>Ne.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 Ne.exec(e)?.[0]??null}catch{return null}return null}const Ke="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",Fe="darwin"!==process.platform&&"win32"!==process.platform||!k().installMirror?.claudeDesktop?"https://claude.ai/download":k().installMirror.claudeDesktop,Be="darwin"===process.platform?`open ${Fe}`:"win32"===process.platform?`start ${Fe}`:`xdg-open ${Fe}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:Ke,installCommand:Be,configPath:X(),sessions:{format:B,files:()=>H(l(claudeDesktopUserDataDir(),"local-agent-mode-sessions"))},isInstalled:Ge,installedVersion:Re,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(u.gray(" "+y.t("tools.claude_desktop.code_cli_downloading",{version:e}))),desktopVersion:"darwin"===process.platform?Re():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 p.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:C()?{isRunning:E,restart:S,quit:O,quitRefused:v,launch:M}:void 0,appInstaller:{vendor:"Anthropic",sizeMb:()=>300,downloadPage:"https://claude.ai/download",blocker:j,latestVersion:()=>P(),installedPath(){if("darwin"===process.platform)return I();if("win32"!==process.platform)return null;try{return Re()?"MSIX":null}catch(e){return p.logError("claude-desktop.installedPath",e),null}},install:e=>L(e)},wantsModelCatalog:!0,loadPrivateConfig(e){const t=te()??{appliedId:"",entries:[]};let o=oe(t);o||(o={id:a(),name:V},t.entries.push(o));const n=ue(e);U(String(n.inferenceGatewayBaseUrl)),le=!0===n.disableDeploymentModeChooser,ie={models:n.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const r=Q(Z(o.id))??{};ee(Z(o.id),{...ke(r),...n});const s=Ie();Te=s&&!e.takeOver?Le(s):null,Te||(t.appliedId=o.id),ee(X(),t);const i=Q(Y())??{};Te||"3p"===i.deploymentMode||ee(Y(),{...i,deploymentMode:"3p"}),ce=null,de=null,ae=null,$e=null;const l=!0===e.settings?.force_registry,c=ve()?Ee(we):null;if(ve()&&"foreign"===Pe(c)&&!l)$e=c?.get("inferenceGatewayBaseUrl")||we;else if(ve()){const t=Ee(we),o=je.filter(e=>t?.has(e)),r={...he(e=>t?.has(e)??!1),...n},s=!0===e.settings?.force_registry,i=!s&&xe();try{i?Se(je):Oe(r),ae=i?"removed":"written"}catch(e){p.logError("claude-desktop.policy",e),ce=e instanceof Error?e.message.trim():String(e),(o.length>0||s)&&(de=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=de;return e?{prompt:y.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!T(_e,e.values,e.deleteKey))return!1;const t=Ee(we),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(de=null,ce=null),o}}:null},unloadPrivateConfig(){if(ve()&&"ours"===Pe(Ee(we)))try{Se(je)}catch(e){p.logError("claude-desktop.removePolicy",e)}const e=te(),t=oe(e);if(!e||!t)return;b(Z(t.id)),s(Z(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(b(X()),s(X(),{force:!0})):ee(X(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=te(),t=oe(e);if(!t||e?.appliedId!==t.id)return null;const o=Q(Z(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=te(),o=oe(t);if(!o||t?.appliedId!==o.id)return;const n=Q(Z(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog),s=JSON.stringify(n.inferenceModels)!==JSON.stringify(r),i={...ke(n),inferenceModels:r},l=JSON.stringify(i)!==JSON.stringify(n);de=null;const a=ve()?Ee(we):null,c="foreign"===Pe(a)&&!0!==e.settings?.force_registry;if(!a?.has("inferenceModels")||c)return void(l&&ee(Z(o.id),i));const d=je.filter(e=>a.has(e)),u=!0!==e.settings?.force_registry&&xe();if(l&&ee(Z(o.id),i),u||s)try{u?Se(je):Oe({inferenceModels:r})}catch(e){throw p.logError("claude-desktop.refreshModelMenu registry",e),de=u?{action:"remove",values:Object.fromEntries(d.map(e=>[e,null])),deleteKey:d.length===a.size}:{action:"write",values:{inferenceModels:r},deleteKey:!1},new $(y.t("tools.claude_desktop.refresh_needs_admin"))}},detectCurrentConfig(){try{if(ve()){const e=Ee(we)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=oe(te());if(!e)return{apiKey:null};const t=Q(Z(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return p.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=te(),t=oe(e);return{meta:e,applied:t?Q(Z(t.id)):null,desktop:Q(Y()),...ve()?{policy:Object.fromEntries(Ee(we)??[])}:{}}}catch(e){return p.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;ve()&&Ee(we)?.has("inferenceModels")&&(Me(),Ce(["delete",we,"/v","inferenceModels","/f"]),e=!0);const t=oe(te()),o=t?Q(Z(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;ee(Z(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(ie&&ie.models.length>0){const{models:t,source:o,groups:n}=ie;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!==le&&e.push({kind:"detail",text:y.t(le?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),C()&&!E()||e.push({kind:"action",text:y.t("tools.claude_desktop.restart_hint")}),de?(e.push({kind:"action",text:y.t(`tools.claude_desktop.policy_stale_${de.action}`)}),e.push({kind:"detail",text:ce??""})):ce?(e.push({kind:"detail",text:y.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:ce})):ve()&&ae&&e.push({kind:"detail",text:y.t(`tools.claude_desktop.registry_${ae}`,{key:we})}),Te&&e.push({kind:"action",text:y.t("tools.claude_desktop.not_switched",{current:Te})}),$e&&e.push({kind:"action",text:y.t("tools.claude_desktop.foreign_policy",{key:we,url:$e})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:y.t("tools.claude_desktop.managed_conflict",{path:t})}),e},planNotes(){const e=[],t=Ie();if(t&&e.push(y.t("tools.claude_desktop.plan_switch",{current:Le(t)})),ve()){const t=Ee(we);"foreign"===Pe(t)&&e.push(y.t("tools.claude_desktop.plan_foreign_policy",{key:we,url:t?.get("inferenceGatewayBaseUrl")||"-"}))}return e},forceResetPaths(){const e=[X(),Y()];try{const t=oe(te());t&&e.push(Z(t.id))}catch{}return e},backupPaths(){const e=[X(),Y()];ve()&&e.push(l(claudeDesktopUserDataDir(),De));try{const t=oe(te());t&&e.push(Z(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 u from"chalk";import{logger as p}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 w}from"../brand.js";import{mirrorPageUrl as b}from"../mirror-url.js";import{backupBeforeWrite as D,atomicWriteFile as A}from"./backup.js";import{toolHome as C}from"./types.js";import{canRestartDesktop as v,desktopQuitRefused as E,isDesktopRunning as M,launchDesktop as O,quitDesktop as S,restartDesktop as x,WINDOWS_PACKAGE_FAMILIES as j}from"./desktop-process.js";import{desktopInstallBlocker as P,fetchLatestDesktopVersion as I,installedMacApp as L,installLatestDesktop as T}from"./claude-desktop-app.js";import{setUserRegistryElevated as $}from"./elevated-reg.js";import{UserActionNeeded as G}from"./types.js";import{savedApiKeys as N}from"../config.js";import{isOurGatewayUrl as U,noteWrittenGatewayUrl as K}from"../gateway-addresses.js";import{baseModelId as R,isClaudeModel as F}from"../model-catalog.js";import{getDefaultModels as B}from"../model-registry.js";import{claudeFormat as H,nestedClaudeProjectFiles as J}from"../sessions/formats.js";import{powerShellEnv as V}from"../powershell-env.js";const W=h;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";export const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING="force_registry";const z=/^[a-f0-9-]{36}$/;function q(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 j.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 X=()=>l(claudeDesktopUserDataDir(),"configLibrary"),Z=()=>l(X(),"_meta.json"),Y=e=>l(X(),`${e}.json`),Q=()=>l(claudeDesktopUserDataDir(),"claude_desktop_config.json");function ee(e){if(!t(e))return null;const o=r(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return q(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 te(n,r){const s=i(n);t(s)||o(s,{recursive:!0,mode:448}),D(n),A(n,JSON.stringify(r,null,2)+"\n");try{e(n,384)}catch(e){p.logError("claude-desktop.writeJson.chmod",e)}}function oe(){const e=ee(Z());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>q(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function ne(e){return e?.entries.find(e=>e.name===W&&z.test(e.id))}const re={opus:0,fable:1,sonnet:2,haiku:3};function se(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=se(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function ie(e){return se(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>R(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(F)){i=[...new Set(t.models.filter(F).map(R))];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=R(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const l=e=>re[ie(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=se(e),s=se(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(B()).map(e=>R(e||"")));for(const e of n){const t=ie(e);t&&i.includes(e)&&!d.has(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=ie(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 le=null,ae=null,ce=null,de=null,ue=null;function pe(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 fe={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}},me=()=>{if(_("TEST_HOME")?.trim())return null;const e=g();return e?r(e):null};let ge=me,ye=null;export function setDesktopAsarForTests(e){ge=void 0===e?me:()=>e,ye=null}function he(){if(ye)return ye;let e=null;try{e=ge()}catch(e){p.logError("claude-desktop.unsupportedDefaults",e)}return ye=new Set(e?Object.keys(fe).filter(t=>!e.includes(t)):[]),ye}function ke(e){const t=he();return Object.fromEntries(Object.entries(fe).filter(([o])=>!e(o)&&!t.has(o)))}function _e(e){const t={...ke(t=>t in e),...e};for(const e of he())e in t&&JSON.stringify(t[e])===JSON.stringify(fe[e])&&delete t[e];return t}const we="SOFTWARE\\Policies\\Claude",be=`HKCU\\${we}`,De="HKLM\\SOFTWARE\\Policies\\Claude",Ae=`${w}-claude-policy.reg`,Ce=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let ve=Ce;export function setRegRunnerForTests(e){ve=e??Ce}function Ee(){return"win32"===process.platform}function Me(e){let t;try{t=ve(["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 Oe(){if(null===Me(be))return;const e=l(claudeDesktopUserDataDir(),Ae);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),D(e),ve(["export",be,e,"/y"])}catch(e){p.logError("claude-desktop.snapshotPolicy",e)}}function Se(e){Oe();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)];ve(["add",be,"/v",t,"/t",e,"/d",n,"/f"])}}function xe(e){const t=Me(be);if(!t)return;Oe();let o=t.size;for(const n of e)t.has(n)&&(ve(["delete",be,"/v",n,"/f"]),o-=1);o<=0&&ve(["delete",be,"/f"])}function je(){const e=!Boolean(_("TEST_HOME")?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(C(),"AppData","Local");return!!t(l(e,"AnthropicClaude"))||j.some(o=>t(l(e,"Packages",o,"LocalCache","Local","Claude-3p")))}const Pe=[...Object.keys(pe({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(fe)];function Ie(e){if(!e||!Pe.some(t=>e.has(t)))return"none";const t=e.get("inferenceGatewayApiKey")?.trim();return U(e.get("inferenceGatewayBaseUrl"))||t&&N().includes(t)?"ours":"foreign"}function Le(){const e=ee(Q())?.deploymentMode;if(void 0!==e&&"3p"!==e)return{kind:"mode"};const t=oe(),o=t?.entries.find(e=>e.id===t.appliedId);if(!o||o.id===ne(t)?.id)return null;const n=ee(Y(o.id));return n&&(n.inferenceProvider||n.inferenceGatewayBaseUrl)?{kind:"entry",name:o.name}:null}function Te(e){return"mode"===e.kind?y.t("tools.claude_desktop.current_official"):y.t("tools.claude_desktop.current_entry",{name:e.name})}let $e=null,Ge=null;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 Me(De)?De:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return p.logError("claude-desktop.detectManagedConfig",e),null}}function Ne(){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"),...j.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 Ue=/\d+\.\d+\.\d+/;function Ke(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 Re(){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?Ue.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 Ke(t)}const o=j.map(e=>`'${e}'`).join(",");return Ke(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"],env:V()}).split(/\r?\n/).flatMap(e=>Ue.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 Ue.exec(e)?.[0]??null}catch{return null}return null}const Fe="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",Be="darwin"!==process.platform&&"win32"!==process.platform||!k().installMirror?.claudeDesktop?"https://claude.ai/download":b(k().installMirror.claudeDesktop),He="darwin"===process.platform?`open ${Be}`:"win32"===process.platform?`start ${Be}`:`xdg-open ${Be}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:Fe,installCommand:He,configPath:Z(),sessions:{format:H,files:()=>J(l(claudeDesktopUserDataDir(),"local-agent-mode-sessions"))},isInstalled:Ne,installedVersion:Re,prepareRuntime:async function(){if(!["win32","darwin","linux"].includes(process.platform)||!Ne())return[];const e=Date.now();try{const t=await m({userDataDir:claudeDesktopUserDataDir(),onDownload:e=>console.log(u.gray(" "+y.t("tools.claude_desktop.code_cli_downloading",{version:e}))),desktopVersion:"darwin"===process.platform?Re():null,mirror:k().installMirror?.claudeDesktop??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 p.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:v()?{isRunning:M,restart:x,quit:S,quitRefused:E,launch:O}:void 0,appInstaller:{vendor:"Anthropic",sizeMb:()=>300,downloadPage:"https://claude.ai/download",blocker:P,latestVersion:()=>I(),installedPath(){if("darwin"===process.platform)return L();if("win32"!==process.platform)return null;try{return Re()?"MSIX":null}catch(e){return p.logError("claude-desktop.installedPath",e),null}},install:e=>T(e)},wantsModelCatalog:!0,loadPrivateConfig(e){const t=oe()??{appliedId:"",entries:[]};let o=ne(t);o||(o={id:a(),name:W},t.entries.push(o));const n=pe(e);K(String(n.inferenceGatewayBaseUrl)),ae=!0===n.disableDeploymentModeChooser,le={models:n.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const r=ee(Y(o.id))??{};te(Y(o.id),{..._e(r),...n});const s=Le();$e=s&&!e.takeOver?Te(s):null,$e||(t.appliedId=o.id),te(Z(),t);const i=ee(Q())??{};$e||"3p"===i.deploymentMode||te(Q(),{...i,deploymentMode:"3p"}),de=null,ue=null,ce=null,Ge=null;const l=!0===e.settings?.force_registry,c=Ee()?Me(be):null;if(Ee()&&"foreign"===Ie(c)&&!l)Ge=c?.get("inferenceGatewayBaseUrl")||be;else if(Ee()){const t=Me(be),o=Pe.filter(e=>t?.has(e)),r={...ke(e=>t?.has(e)??!1),...n},s=!0===e.settings?.force_registry,i=!s&&je();try{i?xe(Pe):Se(r),ce=i?"removed":"written"}catch(e){p.logError("claude-desktop.policy",e),de=e instanceof Error?e.message.trim():String(e),(o.length>0||s)&&(ue=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=ue;return e?{prompt:y.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!$(we,e.values,e.deleteKey))return!1;const t=Me(be),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(ue=null,de=null),o}}:null},unloadPrivateConfig(){if(Ee()&&"ours"===Ie(Me(be)))try{xe(Pe)}catch(e){p.logError("claude-desktop.removePolicy",e)}const e=oe(),t=ne(e);if(!e||!t)return;D(Y(t.id)),s(Y(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(D(Z()),s(Z(),{force:!0})):te(Z(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=oe(),t=ne(e);if(!t||e?.appliedId!==t.id)return null;const o=ee(Y(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=oe(),o=ne(t);if(!o||t?.appliedId!==o.id)return;const n=ee(Y(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog),s=JSON.stringify(n.inferenceModels)!==JSON.stringify(r),i={..._e(n),inferenceModels:r},l=JSON.stringify(i)!==JSON.stringify(n);ue=null;const a=Ee()?Me(be):null,c="foreign"===Ie(a)&&!0!==e.settings?.force_registry;if(!a?.has("inferenceModels")||c)return void(l&&te(Y(o.id),i));const d=Pe.filter(e=>a.has(e)),u=!0!==e.settings?.force_registry&&je();if(l&&te(Y(o.id),i),u||s)try{u?xe(Pe):Se({inferenceModels:r})}catch(e){throw p.logError("claude-desktop.refreshModelMenu registry",e),ue=u?{action:"remove",values:Object.fromEntries(d.map(e=>[e,null])),deleteKey:d.length===a.size}:{action:"write",values:{inferenceModels:r},deleteKey:!1},new G(y.t("tools.claude_desktop.refresh_needs_admin"))}},detectCurrentConfig(){try{if(Ee()){const e=Me(be)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=ne(oe());if(!e)return{apiKey:null};const t=ee(Y(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return p.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=oe(),t=ne(e);return{meta:e,applied:t?ee(Y(t.id)):null,desktop:ee(Q()),...Ee()?{policy:Object.fromEntries(Me(be)??[])}:{}}}catch(e){return p.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;Ee()&&Me(be)?.has("inferenceModels")&&(Oe(),ve(["delete",be,"/v","inferenceModels","/f"]),e=!0);const t=ne(oe()),o=t?ee(Y(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;te(Y(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(le&&le.models.length>0){const{models:t,source:o,groups:n}=le;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!==ae&&e.push({kind:"detail",text:y.t(ae?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),v()&&!M()||e.push({kind:"action",text:y.t("tools.claude_desktop.restart_hint")}),ue?(e.push({kind:"action",text:y.t(`tools.claude_desktop.policy_stale_${ue.action}`)}),e.push({kind:"detail",text:de??""})):de?(e.push({kind:"detail",text:y.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:de})):Ee()&&ce&&e.push({kind:"detail",text:y.t(`tools.claude_desktop.registry_${ce}`,{key:be})}),$e&&e.push({kind:"action",text:y.t("tools.claude_desktop.not_switched",{current:$e})}),Ge&&e.push({kind:"action",text:y.t("tools.claude_desktop.foreign_policy",{key:be,url:Ge})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:y.t("tools.claude_desktop.managed_conflict",{path:t})}),e},planNotes(){const e=[],t=Le();if(t&&e.push(y.t("tools.claude_desktop.plan_switch",{current:Te(t)})),Ee()){const t=Me(be);"foreign"===Ie(t)&&e.push(y.t("tools.claude_desktop.plan_foreign_policy",{key:be,url:t?.get("inferenceGatewayBaseUrl")||"-"}))}return e},forceResetPaths(){const e=[Z(),Q()];try{const t=ne(oe());t&&e.push(Y(t.id))}catch{}return e},backupPaths(){const e=[Z(),Q()];Ee()&&e.push(l(claudeDesktopUserDataDir(),Ae));try{const t=ne(oe());t&&e.push(Y(t.id))}catch{}return e}};
@@ -1 +1 @@
1
- import{spawnSync as t}from"child_process";import{createHash as e}from"crypto";import{accessSync as r,constants as o,copyFileSync as n,createReadStream as s,createWriteStream as a,existsSync as i,mkdirSync as c,mkdtempSync as l,readFileSync as p,renameSync as u,rmSync as d}from"fs";import{cpus as f,tmpdir as m}from"os";import{basename as g,dirname as h,join as w}from"path";import{Readable as $,Transform as S}from"stream";import{pipeline as A}from"stream/promises";import{logger as x}from"../../utils/logger.js";import{i18n as y}from"../i18n.js";import{powerShellEnv as E}from"../powershell-env.js";import{toolHome as v}from"./types.js";import{configManager as k}from"../config.js";const _=(e,r,o={})=>{const n=t(e,r,{encoding:"utf-8",timeout:o.timeout??12e4,windowsHide:!0,input:o.input,stdio:[void 0===o.input?"ignore":"pipe","pipe","pipe"],maxBuffer:16777216,env:E()});return n.error&&x.logError(`desktop-app: ${e}`,n.error),{status:n.status,stdout:`${n.stdout??""}`,stderr:`${n.stderr??""}`}};let P=_,I=(...t)=>fetch(...t),b=null,C=null,T=null,M=null;export function setDesktopAppDepsForTests(t){void 0!==t.run&&(P=t.run??_),void 0!==t.fetch&&(I=t.fetch??((...t)=>fetch(...t))),void 0!==t.platform&&(b=t.platform),void 0!==t.arm64&&(C=t.arm64),void 0!==t.privileged&&(T=t.privileged),void 0!==t.remote&&(M=t.remote)}export function appPlatform(){return b??process.platform}export function isArm64Machine(){return null!==C?C:"arm64"===process.arch||("win32"===appPlatform()?"ARM64"===process.env.PROCESSOR_ARCHITECTURE||"ARM64"===process.env.PROCESSOR_ARCHITEW6432:"darwin"===appPlatform()&&/\bApple\b/.test(f()[0]?.model??""))}export class DesktopInstallError extends Error{key;constructor(t,e){super(t),this.name="DesktopInstallError",this.key=e}}export const fail=(t,e={})=>{const r={};for(const[t,o]of Object.entries(e))r[t]=o.trim()||y.t("app_update.reason_unknown");throw new DesktopInstallError(y.t(`app_update.error_${t}`,r),t)};export function parseSha256Sums(t){const e=new Map;for(const r of t.split(/\r?\n/)){const t=/^([0-9a-f]{64})\s+\*?(\S.*)$/i.exec(r.trim());t&&e.set(t[2].trim(),t[1].toLowerCase())}return e}async function R(t){const r=e("sha256");for await(const e of s(t))r.update(e);return r.digest("hex")}async function F(t,e){const r=await I(t,{signal:AbortSignal.timeout(e)});if(!r.ok)throw new Error(`${t}: HTTP ${r.status}`);return(await r.text()).trim()}function O(t,e){try{const r=p(w(t,"Contents","Info.plist"),"utf-8");return new RegExp(`<key>${e}</key>\\s*<string>([^<]*)</string>`).exec(r)?.[1]??null}catch{return null}}export function macBundleId(t){return O(t,"CFBundleIdentifier")}export function macAppVersion(t){return/^\d+\.\d+\.\d+/.exec(O(t,"CFBundleShortVersionString")??"")?.[0]??null}function j(t){try{return r(t,o.W_OK),!0}catch{return!1}}const N=t=>`'${t.replace(/'/g,"''")}'`;function B(t,e=12e4){return P("powershell.exe",["-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-Command","[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; "+t],{timeout:e})}export function powerShellError(t){return t.replace(/#< CLIXML/g,"").replace(/_x000D__x000A_/g,"\n").replace(/<\/S>/g,"\n").replace(/<[^>]+>/g,"").replace(/_x[0-9A-F]{4}_/g,"").replace(/&apos;/g,"'").replace(/&quot;/g,'"').replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").split(/\r?\n/).map(t=>t.trim()).find(t=>t&&!/^(At line|At char|所在位置|\+|~|CategoryInfo|FullyQualifiedErrorId)/i.test(t))??""}export function createDesktopAppInstaller(t){const e=()=>t.mirror()?.replace(/\/-\/releases\/latest\/?$/,"")??null,r=()=>t.asset(appPlatform(),isArm64Machine()),o=()=>{const o=appPlatform();return"darwin"!==o&&"win32"!==o?"unsupported_platform":r()?e()?"darwin"===o&&(T??0===process.getuid?.())?"root":"win32"===o&&(null!==T?T:/\\system32\\config\\systemprofile/i.test(process.env.USERPROFILE??"")||!0===process.env.USERNAME?.endsWith("$"))?"system_account":"win32"===o&&(null!==M?M:Boolean(process.env.SSH_CONNECTION||process.env.SSH_CLIENT))?"remote_session":t.extraBlocker?.(o)??null:"no_mirror":"darwin"===o?"unsupported_arch":"unsupported_platform"},s=async(r=8e3)=>{const o=e();if(!o)throw new Error("no mirror");const n=t.versionFile(appPlatform(),isArm64Machine()),s=await F(`${o}/-/releases/latest/download/${n}`,r),a=/^(\d+\.\d+\.\d+)(\.\d+)?$/.exec(s)?.[1];if(!a)throw new Error(`unexpected ${n}: ${s.slice(0,40)}`);return a},f=()=>{for(const e of["/Applications",w(v(),"Applications")])for(const r of t.macApp.installedNames){const o=w(e,r);if(!i(w(o,"Contents","Info.plist")))continue;const n=macBundleId(o);if(null===n||n===t.macApp.bundleId)return o}return null},E=e=>{const r=P("codesign",["--verify","--deep","--strict",e],{timeout:6e5});0!==r.status&&fail("signature",{reason:(r.stderr||r.stdout).trim().split("\n")[0]||`codesign ${r.status}`});const o=P("codesign",["-dv",e]),n=`${o.stdout}\n${o.stderr}`,s=/^TeamIdentifier=(\S+)/m.exec(n)?.[1],a=/^Identifier=(\S+)/m.exec(n)?.[1];s===t.macApp.teamId&&a===t.macApp.bundleId||fail("signature",{reason:`TeamIdentifier=${s??"?"} Identifier=${a??"?"}`});const i=P("spctl",["-a","-t","exec","-vv",e],{timeout:3e5});0!==i.status&&fail("signature",{reason:(i.stderr||i.stdout).trim().split("\n")[0]||`spctl ${i.status}`})},_=()=>{const e=f();let r=e;if(!r){const e=j("/Applications")?"/Applications":w(v(),"Applications");r=w(e,t.macApp.installedNames[0])}const o=h(r);return(i(o)&&!j(o)||e&&!j(e))&&fail("no_permission",{path:r}),{target:r,existing:e}},b=e=>{const r=B(`$s = Get-AuthenticodeSignature -LiteralPath ${N(e)}; [pscustomobject]@{ status = [string]$s.Status; subject = [string]$s.SignerCertificate.Subject } | ConvertTo-Json -Compress`);let o={};try{o=JSON.parse(r.stdout.trim()||"{}")}catch{}if("Valid"!==o.status||!t.windows.signer.test(o.subject??"")){const t=o.status?`${o.status} ${o.subject??""}`:powerShellError(r.stderr)||powerShellError(r.stdout.trim().startsWith("{")?"":r.stdout)||`exit ${r.status}`;fail("signature",{reason:t.trim()})}},C=()=>{const e=B(`Get-AppxPackage | Where-Object { ${t.windows.packageFilter} } | ForEach-Object { $_.Version.ToString() }`,3e4);return/\d+\.\d+\.\d+/.exec(e.stdout)?.[0]??null};return{mirrorRepo:e,assetName:r,blocker:o,latestVersion:s,installedMacApp:f,windowsPackageVersion:C,verifyMacApp:E,verifyWindowsPackage:b,install:async(f={})=>{const v=o();v&&fail("blocked",{reason:y.t(`app_update.reason_${v}`)});const T=e(),M=r();let O;try{O=await s(15e3)}catch(t){fail("download",{reason:t instanceof Error?t.message:String(t)})}const j=t.releaseTag?`${T}/-/releases/download/${t.releaseTag(O)}`:`${T}/-/releases/latest/download`;let D;try{D=parseSha256Sums(await F(`${j}/SHA256SUMS`,15e3)).get(M)}catch(e){x.logError(`${t.id}: SHA256SUMS`,e)}D||fail("no_checksum",{file:M}),"darwin"===appPlatform()&&_();const H=w(k.getConfigDir(),"downloads",t.id),W=w(H,M),V=l(w(m(),`${t.id}-`));let L=w(V,M),U=!1;try{i(W)&&await R(W)===D?(L=W,f.reusing?.(O)):(f.downloading?.(O),await async function(t,e,r){let o;try{o=await I(t,{signal:AbortSignal.timeout(18e5)})}catch(t){fail("download",{reason:t instanceof Error?t.message:String(t)})}o.ok&&o.body||fail("download",{reason:`HTTP ${o.status}`});const n=Number(o.headers.get("content-length"))||0;let s=0,i=-1;const c=new S({transform(t,e,o){s+=t.length;const a=n?Math.floor(100*s/n):-1;a>=0&&a!==i&&(i=a,r?.(a)),o(null,t)}});try{await A($.fromWeb(o.body),c,a(e))}catch(t){d(e,{force:!0}),fail("download",{reason:t instanceof Error?t.message:String(t)})}}(`${j}/${M}`,L,f.percent)),f.verifying?.();const e=await R(L);e!==D&&fail("checksum",{file:M,expected:D.slice(0,12),actual:e.slice(0,12)}),f.installing?.();const r="darwin"===appPlatform()?await(async(e,r)=>{const o=w(r,"mnt");c(o,{recursive:!0});const n=P("hdiutil",["attach","-nobrowse","-readonly","-noautoopen","-mountpoint",o,e],{timeout:3e5,input:"Y\n"});0!==n.status&&fail("mount",{reason:(n.stderr||n.stdout).trim().split("\n").pop()??""});let s=null;try{const e=w(o,t.macApp.source);i(e)||fail("bad_package",{reason:t.macApp.source});const{target:r,existing:n}=_(),a=h(r),l=g(r);c(a,{recursive:!0}),s=w(a,`.${l}.${process.pid}.new`),d(s,{recursive:!0,force:!0});const p=P("ditto",[e,s],{timeout:9e5});0!==p.status&&fail("copy",{reason:(p.stderr||p.stdout).trim().split("\n")[0]??""}),E(s);const f=macAppVersion(s);f||fail("bad_package",{reason:"Info.plist"});const m=w(a,`.${l}.${process.pid}.old`);try{n&&u(n,m)}catch(t){throw["EPERM","EACCES"].includes(t.code??"")&&fail("app_management",{path:n}),t}try{u(s,r)}catch(t){throw n&&u(m,n),t}return s=null,d(m,{recursive:!0,force:!0}),{version:f,location:r}}finally{s&&d(s,{recursive:!0,force:!0}),P("hdiutil",["detach",o,"-force"],{timeout:6e4})}})(L,V):await(async(t,e)=>{b(t);const r=B(`$ErrorActionPreference = 'Stop'; Add-AppxPackage -Path ${N(t)} -ForceApplicationShutdown`,9e5);if(0!==r.status){const o=powerShellError(r.stderr)||powerShellError(r.stdout)||`Add-AppxPackage ${r.status}`;/0x80073D28/i.test(`${r.stderr}\n${r.stdout}`)||fail("install",{reason:o}),await(e.elevate?.())||fail("needs_admin");const n=(t=>{const e=w(h(t),"elevated-install.log"),r=`$ErrorActionPreference = 'Stop'; try { Add-AppxPackage -Path ${N(t)} -ForceApplicationShutdown; exit 0 } catch { [IO.File]::WriteAllText(${N(e)}, $_.Exception.Message, [Text.Encoding]::UTF8); exit 1 }`,o=B(`$ErrorActionPreference = 'Stop'; $p = Start-Process -FilePath 'powershell.exe' -ArgumentList @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-EncodedCommand', '${Buffer.from(r,"utf16le").toString("base64")}') -Verb RunAs -Wait -PassThru -WindowStyle Hidden; exit $p.ExitCode`,12e5);if(0===o.status)return null;let n="";try{n=p(e,"utf-8").trim()}catch{}return n||powerShellError(o.stderr)||powerShellError(o.stdout)||`exit ${o.status}`})(t);n&&fail("install",{reason:n}),C()||fail("other_account")}const o=C();return o||fail("install",{reason:"Get-AppxPackage"}),{version:o,location:"MSIX"}})(L,f);return U=!0,r}catch(t){const e=t instanceof DesktopInstallError?t.key:void 0;throw L!==W&&i(L)&&!["checksum","signature","bad_package","mount"].includes(e??"")&&function(t,e,r){try{d(e,{recursive:!0,force:!0}),c(e,{recursive:!0});try{u(t,r)}catch{n(t,r)}}catch(t){x.logError("desktop-app: keep package",t),d(e,{recursive:!0,force:!0})}}(L,H,W),L===W&&["signature","bad_package","mount"].includes(e??"")&&d(H,{recursive:!0,force:!0}),t}finally{U&&d(H,{recursive:!0,force:!0}),d(V,{recursive:!0,force:!0})}}}}
1
+ import{spawnSync as t}from"child_process";import{createHash as e}from"crypto";import{accessSync as r,constants as o,copyFileSync as n,createReadStream as s,createWriteStream as i,existsSync as a,mkdirSync as c,mkdtempSync as l,readFileSync as p,renameSync as u,rmSync as d}from"fs";import{cpus as f,tmpdir as m}from"os";import{basename as g,dirname as h,join as w}from"path";import{Readable as S,Transform as A}from"stream";import{pipeline as x}from"stream/promises";import{logger as y}from"../../utils/logger.js";import{i18n as E}from"../i18n.js";import{powerShellEnv as $}from"../powershell-env.js";import{toolHome as v}from"./types.js";import{configManager as k}from"../config.js";import{mirrorFileUrl as _}from"../mirror-url.js";const P=(e,r,o={})=>{const n=t(e,r,{encoding:"utf-8",timeout:o.timeout??12e4,windowsHide:!0,input:o.input,stdio:[void 0===o.input?"ignore":"pipe","pipe","pipe"],maxBuffer:16777216,env:$()});return n.error&&y.logError(`desktop-app: ${e}`,n.error),{status:n.status,stdout:`${n.stdout??""}`,stderr:`${n.stderr??""}`}};let I=P,b=(...t)=>fetch(...t),C=null,T=null,M=null,F=null;export function setDesktopAppDepsForTests(t){void 0!==t.run&&(I=t.run??P),void 0!==t.fetch&&(b=t.fetch??((...t)=>fetch(...t))),void 0!==t.platform&&(C=t.platform),void 0!==t.arm64&&(T=t.arm64),void 0!==t.privileged&&(M=t.privileged),void 0!==t.remote&&(F=t.remote)}export function appPlatform(){return C??process.platform}export function isArm64Machine(){return null!==T?T:"arm64"===process.arch||("win32"===appPlatform()?"ARM64"===process.env.PROCESSOR_ARCHITECTURE||"ARM64"===process.env.PROCESSOR_ARCHITEW6432:"darwin"===appPlatform()&&/\bApple\b/.test(f()[0]?.model??""))}export class DesktopInstallError extends Error{key;constructor(t,e){super(t),this.name="DesktopInstallError",this.key=e}}export const fail=(t,e={})=>{const r={};for(const[t,o]of Object.entries(e))r[t]=o.trim()||E.t("app_update.reason_unknown");throw new DesktopInstallError(E.t(`app_update.error_${t}`,r),t)};export function parseSha256Sums(t){const e=new Map;for(const r of t.split(/\r?\n/)){const t=/^([0-9a-f]{64})\s+\*?(\S.*)$/i.exec(r.trim());t&&e.set(t[2].trim(),t[1].toLowerCase())}return e}async function R(t){const r=e("sha256");for await(const e of s(t))r.update(e);return r.digest("hex")}async function j(t,e){const r=await b(t,{signal:AbortSignal.timeout(e)});if(!r.ok)throw new Error(`${t}: HTTP ${r.status}`);return(await r.text()).trim()}function O(t,e){try{const r=p(w(t,"Contents","Info.plist"),"utf-8");return new RegExp(`<key>${e}</key>\\s*<string>([^<]*)</string>`).exec(r)?.[1]??null}catch{return null}}export function macBundleId(t){return O(t,"CFBundleIdentifier")}export function macAppVersion(t){return/^\d+\.\d+\.\d+/.exec(O(t,"CFBundleShortVersionString")??"")?.[0]??null}function N(t){try{return r(t,o.W_OK),!0}catch{return!1}}const B=t=>`'${t.replace(/'/g,"''")}'`;function D(t,e=12e4){return I("powershell.exe",["-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-Command","[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; "+t],{timeout:e})}export function powerShellError(t){return t.replace(/#< CLIXML/g,"").replace(/_x000D__x000A_/g,"\n").replace(/<\/S>/g,"\n").replace(/<[^>]+>/g,"").replace(/_x[0-9A-F]{4}_/g,"").replace(/&apos;/g,"'").replace(/&quot;/g,'"').replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").split(/\r?\n/).map(t=>t.trim()).find(t=>t&&!/^(At line|At char|所在位置|\+|~|CategoryInfo|FullyQualifiedErrorId)/i.test(t))??""}export function createDesktopAppInstaller(t){const e=()=>t.mirror()||null,r=()=>t.asset(appPlatform(),isArm64Machine()),o=()=>{const o=appPlatform();return"darwin"!==o&&"win32"!==o?"unsupported_platform":r()?e()?"darwin"===o&&(M??0===process.getuid?.())?"root":"win32"===o&&(null!==M?M:/\\system32\\config\\systemprofile/i.test(process.env.USERPROFILE??"")||!0===process.env.USERNAME?.endsWith("$"))?"system_account":"win32"===o&&(null!==F?F:Boolean(process.env.SSH_CONNECTION||process.env.SSH_CLIENT))?"remote_session":t.extraBlocker?.(o)??null:"no_mirror":"darwin"===o?"unsupported_arch":"unsupported_platform"},s=async(r=8e3)=>{const o=e();if(!o)throw new Error("no mirror");const n=t.versionFile(appPlatform(),isArm64Machine()),s=await j(_(o,n),r),i=/^(\d+\.\d+\.\d+)(\.\d+)?$/.exec(s)?.[1];if(!i)throw new Error(`unexpected ${n}: ${s.slice(0,40)}`);return i},f=()=>{for(const e of["/Applications",w(v(),"Applications")])for(const r of t.macApp.installedNames){const o=w(e,r);if(!a(w(o,"Contents","Info.plist")))continue;const n=macBundleId(o);if(null===n||n===t.macApp.bundleId)return o}return null},$=e=>{const r=I("codesign",["--verify","--deep","--strict",e],{timeout:6e5});0!==r.status&&fail("signature",{reason:(r.stderr||r.stdout).trim().split("\n")[0]||`codesign ${r.status}`});const o=I("codesign",["-dv",e]),n=`${o.stdout}\n${o.stderr}`,s=/^TeamIdentifier=(\S+)/m.exec(n)?.[1],i=/^Identifier=(\S+)/m.exec(n)?.[1];s===t.macApp.teamId&&i===t.macApp.bundleId||fail("signature",{reason:`TeamIdentifier=${s??"?"} Identifier=${i??"?"}`});const a=I("spctl",["-a","-t","exec","-vv",e],{timeout:3e5});0!==a.status&&fail("signature",{reason:(a.stderr||a.stdout).trim().split("\n")[0]||`spctl ${a.status}`})},P=()=>{const e=f();let r=e;if(!r){const e=N("/Applications")?"/Applications":w(v(),"Applications");r=w(e,t.macApp.installedNames[0])}const o=h(r);return(a(o)&&!N(o)||e&&!N(e))&&fail("no_permission",{path:r}),{target:r,existing:e}},C=e=>{const r=D(`$s = Get-AuthenticodeSignature -LiteralPath ${B(e)}; [pscustomobject]@{ status = [string]$s.Status; subject = [string]$s.SignerCertificate.Subject } | ConvertTo-Json -Compress`);let o={};try{o=JSON.parse(r.stdout.trim()||"{}")}catch{}if("Valid"!==o.status||!t.windows.signer.test(o.subject??"")){const t=o.status?`${o.status} ${o.subject??""}`:powerShellError(r.stderr)||powerShellError(r.stdout.trim().startsWith("{")?"":r.stdout)||`exit ${r.status}`;fail("signature",{reason:t.trim()})}},T=()=>{const e=D(`Get-AppxPackage | Where-Object { ${t.windows.packageFilter} } | ForEach-Object { $_.Version.ToString() }`,3e4);return/\d+\.\d+\.\d+/.exec(e.stdout)?.[0]??null};return{assetName:r,blocker:o,latestVersion:s,installedMacApp:f,windowsPackageVersion:T,verifyMacApp:$,verifyWindowsPackage:C,install:async(f={})=>{const v=o();v&&fail("blocked",{reason:E.t(`app_update.reason_${v}`)});const M=e(),F=r();let O;try{O=await s(15e3)}catch(t){fail("download",{reason:t instanceof Error?t.message:String(t)})}const N=e=>_(M,e,t.releaseTag?.(O));let H;try{H=parseSha256Sums(await j(N("SHA256SUMS"),15e3)).get(F)}catch(e){y.logError(`${t.id}: SHA256SUMS`,e)}H||fail("no_checksum",{file:F}),"darwin"===appPlatform()&&P();const W=w(k.getConfigDir(),"downloads",t.id),V=w(W,F),L=l(w(m(),`${t.id}-`));let U=w(L,F),G=!1;try{a(V)&&await R(V)===H?(U=V,f.reusing?.(O)):(f.downloading?.(O),await async function(t,e,r){let o;try{o=await b(t,{signal:AbortSignal.timeout(18e5)})}catch(t){fail("download",{reason:t instanceof Error?t.message:String(t)})}o.ok&&o.body||fail("download",{reason:`HTTP ${o.status}`});const n=Number(o.headers.get("content-length"))||0;let s=0,a=-1;const c=new A({transform(t,e,o){s+=t.length;const i=n?Math.floor(100*s/n):-1;i>=0&&i!==a&&(a=i,r?.(i)),o(null,t)}});try{await x(S.fromWeb(o.body),c,i(e))}catch(t){d(e,{force:!0}),fail("download",{reason:t instanceof Error?t.message:String(t)})}}(N(F),U,f.percent)),f.verifying?.();const e=await R(U);e!==H&&fail("checksum",{file:F,expected:H.slice(0,12),actual:e.slice(0,12)}),f.installing?.();const r="darwin"===appPlatform()?await(async(e,r)=>{const o=w(r,"mnt");c(o,{recursive:!0});const n=I("hdiutil",["attach","-nobrowse","-readonly","-noautoopen","-mountpoint",o,e],{timeout:3e5,input:"Y\n"});0!==n.status&&fail("mount",{reason:(n.stderr||n.stdout).trim().split("\n").pop()??""});let s=null;try{const e=w(o,t.macApp.source);a(e)||fail("bad_package",{reason:t.macApp.source});const{target:r,existing:n}=P(),i=h(r),l=g(r);c(i,{recursive:!0}),s=w(i,`.${l}.${process.pid}.new`),d(s,{recursive:!0,force:!0});const p=I("ditto",[e,s],{timeout:9e5});0!==p.status&&fail("copy",{reason:(p.stderr||p.stdout).trim().split("\n")[0]??""}),$(s);const f=macAppVersion(s);f||fail("bad_package",{reason:"Info.plist"});const m=w(i,`.${l}.${process.pid}.old`);try{n&&u(n,m)}catch(t){throw["EPERM","EACCES"].includes(t.code??"")&&fail("app_management",{path:n}),t}try{u(s,r)}catch(t){throw n&&u(m,n),t}return s=null,d(m,{recursive:!0,force:!0}),{version:f,location:r}}finally{s&&d(s,{recursive:!0,force:!0}),I("hdiutil",["detach",o,"-force"],{timeout:6e4})}})(U,L):await(async(t,e)=>{C(t);const r=D(`$ErrorActionPreference = 'Stop'; Add-AppxPackage -Path ${B(t)} -ForceApplicationShutdown`,9e5);if(0!==r.status){const o=powerShellError(r.stderr)||powerShellError(r.stdout)||`Add-AppxPackage ${r.status}`;/0x80073D28/i.test(`${r.stderr}\n${r.stdout}`)||fail("install",{reason:o}),await(e.elevate?.())||fail("needs_admin");const n=(t=>{const e=w(h(t),"elevated-install.log"),r=`$ErrorActionPreference = 'Stop'; try { Add-AppxPackage -Path ${B(t)} -ForceApplicationShutdown; exit 0 } catch { [IO.File]::WriteAllText(${B(e)}, $_.Exception.Message, [Text.Encoding]::UTF8); exit 1 }`,o=D(`$ErrorActionPreference = 'Stop'; $p = Start-Process -FilePath 'powershell.exe' -ArgumentList @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-EncodedCommand', '${Buffer.from(r,"utf16le").toString("base64")}') -Verb RunAs -Wait -PassThru -WindowStyle Hidden; exit $p.ExitCode`,12e5);if(0===o.status)return null;let n="";try{n=p(e,"utf-8").trim()}catch{}return n||powerShellError(o.stderr)||powerShellError(o.stdout)||`exit ${o.status}`})(t);n&&fail("install",{reason:n}),T()||fail("other_account")}const o=T();return o||fail("install",{reason:"Get-AppxPackage"}),{version:o,location:"MSIX"}})(U,f);return G=!0,r}catch(t){const e=t instanceof DesktopInstallError?t.key:void 0;throw U!==V&&a(U)&&!["checksum","signature","bad_package","mount"].includes(e??"")&&function(t,e,r){try{d(e,{recursive:!0,force:!0}),c(e,{recursive:!0});try{u(t,r)}catch{n(t,r)}}catch(t){y.logError("desktop-app: keep package",t),d(e,{recursive:!0,force:!0})}}(U,W,V),U===V&&["signature","bad_package","mount"].includes(e??"")&&d(W,{recursive:!0,force:!0}),t}finally{G&&d(W,{recursive:!0,force:!0}),d(L,{recursive:!0,force:!0})}}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marsapi/cli",
3
- "version": "0.0.154",
3
+ "version": "0.0.155",
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": {