twskin 0.5.3
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.
- package/CHANGELOG.md +99 -0
- package/CONTRIBUTING.md +37 -0
- package/LICENSE +21 -0
- package/README.md +104 -0
- package/SECURITY.md +28 -0
- package/dist/bin/twskin.d.ts +3 -0
- package/dist/bin/twskin.d.ts.map +1 -0
- package/dist/bin/twskin.js +4 -0
- package/dist/bin/twskin.js.map +1 -0
- package/dist/commands.d.ts +41 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +421 -0
- package/dist/commands.js.map +1 -0
- package/dist/context.d.ts +14 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +51 -0
- package/dist/context.js.map +1 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +20 -0
- package/dist/errors.js.map +1 -0
- package/dist/lock.d.ts +3 -0
- package/dist/lock.d.ts.map +1 -0
- package/dist/lock.js +52 -0
- package/dist/lock.js.map +1 -0
- package/dist/main.d.ts +9 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +92 -0
- package/dist/main.js.map +1 -0
- package/dist/output.d.ts +4 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +27 -0
- package/dist/output.js.map +1 -0
- package/dist/persistent-cdp.d.ts +14 -0
- package/dist/persistent-cdp.d.ts.map +1 -0
- package/dist/persistent-cdp.js +140 -0
- package/dist/persistent-cdp.js.map +1 -0
- package/dist/system.d.ts +64 -0
- package/dist/system.d.ts.map +1 -0
- package/dist/system.js +234 -0
- package/dist/system.js.map +1 -0
- package/dist/theme-download.d.ts +9 -0
- package/dist/theme-download.d.ts.map +1 -0
- package/dist/theme-download.js +250 -0
- package/dist/theme-download.js.map +1 -0
- package/dist/themes.d.ts +9 -0
- package/dist/themes.d.ts.map +1 -0
- package/dist/themes.js +185 -0
- package/dist/themes.js.map +1 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/docs/publishing.md +45 -0
- package/docs/theme-distribution.md +62 -0
- package/package.json +74 -0
- package/runtime/component-map.mjs +200 -0
- package/runtime/injector.mjs +705 -0
- package/runtime/manifest.json +47 -0
- package/runtime/restore.sh +33 -0
- package/runtime/skin.js +1133 -0
- package/runtime/start.sh +86 -0
- package/runtime/styles/base.css +687 -0
- package/runtime/styles/manager.css +346 -0
- package/runtime/token-map.mjs +432 -0
package/dist/commands.js
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import process from "node:process";
|
|
5
|
+
import * as p from "@clack/prompts";
|
|
6
|
+
import { CliError } from "./errors.js";
|
|
7
|
+
import { withLock } from "./lock.js";
|
|
8
|
+
import { emit } from "./output.js";
|
|
9
|
+
import { appRunning, cdpVersion, commandResult, commandText, managerStatus, portOwner, readPort, resolveAppBundle, runInjector, runScript, startWatcher, stopWatcher, verifyRuntimeIntegrity, watcherStatus, } from "./system.js";
|
|
10
|
+
import { discoverThemeDirectories, installThemeDirectory, listThemes, readTheme, writeTheme } from "./themes.js";
|
|
11
|
+
import { MIN_NODE_MAJOR } from "./context.js";
|
|
12
|
+
import { downloadThemes } from "./theme-download.js";
|
|
13
|
+
import { disablePersistentCdp, enablePersistentCdp } from "./persistent-cdp.js";
|
|
14
|
+
function interactive(options) {
|
|
15
|
+
return !options.json && Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
16
|
+
}
|
|
17
|
+
function emitStartResult(payload, title, message, outro, options) {
|
|
18
|
+
if (options.json || !interactive(options)) {
|
|
19
|
+
emit(payload, `${title}\n\n${message}`, options.json);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
p.note(message, title);
|
|
23
|
+
p.outro(outro);
|
|
24
|
+
}
|
|
25
|
+
async function downloadWithProgress(context, requestedId, options) {
|
|
26
|
+
if (!interactive(options))
|
|
27
|
+
return downloadThemes(context, requestedId);
|
|
28
|
+
const progress = p.spinner();
|
|
29
|
+
progress.start("正在下载并校验官方主题包");
|
|
30
|
+
try {
|
|
31
|
+
const result = await downloadThemes(context, requestedId);
|
|
32
|
+
progress.stop(`主题包 ${result.tag} 已校验并安装`);
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
progress.stop("主题下载失败");
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function helpText(context) {
|
|
41
|
+
return `TRAE Work Skin ${context.packageVersion}
|
|
42
|
+
|
|
43
|
+
Usage:
|
|
44
|
+
twskin start [--yes] 初始化并启动 Theme Manager 与守护进程
|
|
45
|
+
twskin stop 停止 Skin 并恢复原生外观(不退出 TRAE)
|
|
46
|
+
twskin status [--json] 查看 App、CDP、守护进程和当前主题
|
|
47
|
+
twskin themes [--json] 列出本地主题
|
|
48
|
+
twskin theme <id> 切换主题
|
|
49
|
+
twskin theme download [id] 从最新 GitHub Release 下载全部或指定主题
|
|
50
|
+
twskin theme load <directory> 从本地目录加载一个或多个主题
|
|
51
|
+
twskin doctor [--json] 检查 Node、TRAE、端口和文件完整性
|
|
52
|
+
twskin restore 恢复 TRAE 原生外观
|
|
53
|
+
twskin uninstall [--yes] 恢复外观并卸载 TRAE Work Skin
|
|
54
|
+
twskin version 显示版本
|
|
55
|
+
twskin help 显示帮助
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
export async function getStatus(context) {
|
|
59
|
+
const port = readPort(context);
|
|
60
|
+
const appBundle = resolveAppBundle(context);
|
|
61
|
+
const cdp = await cdpVersion(port);
|
|
62
|
+
const owner = portOwner(context, port);
|
|
63
|
+
const watcher = watcherStatus(context);
|
|
64
|
+
const theme = readTheme(context);
|
|
65
|
+
return {
|
|
66
|
+
app: { installed: fs.existsSync(appBundle), running: appRunning(context, appBundle), bundle: appBundle },
|
|
67
|
+
cdp: {
|
|
68
|
+
reachable: Boolean(cdp),
|
|
69
|
+
port,
|
|
70
|
+
browser: cdp?.Browser || null,
|
|
71
|
+
owner: owner ? { ...owner, expected: owner.command.includes(context.app.processMatch) } : null,
|
|
72
|
+
},
|
|
73
|
+
watcher: { pid: watcher.pid, running: watcher.alive && watcher.expected, pidAlive: watcher.alive },
|
|
74
|
+
theme: { id: theme, valid: listThemes(context).some((item) => item.id === theme) },
|
|
75
|
+
version: context.packageVersion,
|
|
76
|
+
distribution: context.distribution,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export async function startCommand(context, options) {
|
|
80
|
+
await withLock(context, "start", async () => {
|
|
81
|
+
let bootstrap = null;
|
|
82
|
+
if (listThemes(context).filter((theme) => !theme.invalid).length === 0) {
|
|
83
|
+
await confirmThemeDownload(options, context.themesDir);
|
|
84
|
+
bootstrap = await downloadWithProgress(context, undefined, options);
|
|
85
|
+
}
|
|
86
|
+
const port = readPort(context);
|
|
87
|
+
const appBundle = resolveAppBundle(context);
|
|
88
|
+
const cdp = await cdpVersion(port);
|
|
89
|
+
if (cdp) {
|
|
90
|
+
const watcherBefore = watcherStatus(context);
|
|
91
|
+
const watcherMatchesConfiguration = watcherBefore.command.includes(`--port ${port}`)
|
|
92
|
+
&& watcherBefore.command.includes(`--themes ${context.themesDir}`)
|
|
93
|
+
&& watcherBefore.command.includes(path.join(context.runtimeRoot, "injector.mjs"));
|
|
94
|
+
const managerBefore = !bootstrap && watcherBefore.alive && watcherBefore.expected && watcherMatchesConfiguration
|
|
95
|
+
? managerStatus(context, port)
|
|
96
|
+
: { ready: false, version: null };
|
|
97
|
+
if (managerBefore.ready && managerBefore.version === context.packageVersion) {
|
|
98
|
+
const persistentCdp = enablePersistentCdp(context, appBundle, port);
|
|
99
|
+
const theme = readTheme(context);
|
|
100
|
+
emitStartResult({
|
|
101
|
+
command: "start",
|
|
102
|
+
state: "already_running",
|
|
103
|
+
mode: "already-running",
|
|
104
|
+
port,
|
|
105
|
+
watcherPid: watcherBefore.pid,
|
|
106
|
+
theme,
|
|
107
|
+
persistentCdp,
|
|
108
|
+
guide: { managerEntry: "TRAE Work 右下角的调色盘图标" },
|
|
109
|
+
}, "TRAE Work Skin 已经在运行", `入口:回到 TRAE Work,点击右下角的调色盘图标打开 Theme Manager。\n当前主题:${theme}`, "无需重复启动", options);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
runInjector(context, ["--once", "--port", String(port)]);
|
|
113
|
+
const pid = startWatcher(context, port);
|
|
114
|
+
const persistentCdp = enablePersistentCdp(context, appBundle, port);
|
|
115
|
+
const state = bootstrap ? "ready" : "recovered";
|
|
116
|
+
const headline = bootstrap
|
|
117
|
+
? `首次启动完成,已安装 ${bootstrap.installed.length} 套官方主题。`
|
|
118
|
+
: "TRAE Work Skin 已恢复并可以使用。";
|
|
119
|
+
emitStartResult({
|
|
120
|
+
command: "start",
|
|
121
|
+
state,
|
|
122
|
+
mode: "refresh",
|
|
123
|
+
port,
|
|
124
|
+
watcherPid: pid,
|
|
125
|
+
persistentCdp,
|
|
126
|
+
bootstrappedThemes: bootstrap?.installed.map((theme) => theme.id) || [],
|
|
127
|
+
guide: { managerEntry: "TRAE Work 右下角的调色盘图标" },
|
|
128
|
+
}, headline, "下一步:回到 TRAE Work,点击右下角的调色盘图标打开 Theme Manager。\n如暂时未看到图标,请等待页面加载完成。", "Theme Manager 已就绪", options);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const owner = portOwner(context, port);
|
|
132
|
+
if (owner && !owner.command.includes(context.app.processMatch)) {
|
|
133
|
+
throw new CliError("PORT_IN_USE", 4, `端口 ${port} 被其他进程占用:${owner.command}`, "请退出占用端口的程序后重试。");
|
|
134
|
+
}
|
|
135
|
+
await confirmAppRestart(context, appBundle, options);
|
|
136
|
+
runScript(context, "start.sh", {
|
|
137
|
+
PORT: String(port),
|
|
138
|
+
NODE_BIN: process.execPath,
|
|
139
|
+
APP_BUNDLE: appBundle,
|
|
140
|
+
APP_BUNDLE_ID: context.app.bundleId,
|
|
141
|
+
APP_PROC_MATCH: context.app.processMatch,
|
|
142
|
+
});
|
|
143
|
+
const persistentCdp = enablePersistentCdp(context, appBundle, port);
|
|
144
|
+
const headline = bootstrap
|
|
145
|
+
? `首次启动完成,已安装 ${bootstrap.installed.length} 套官方主题。`
|
|
146
|
+
: "TRAE Work Skin 已启动。";
|
|
147
|
+
emitStartResult({
|
|
148
|
+
command: "start",
|
|
149
|
+
state: "ready",
|
|
150
|
+
mode: "launch",
|
|
151
|
+
port,
|
|
152
|
+
persistentCdp,
|
|
153
|
+
bootstrappedThemes: bootstrap?.installed.map((theme) => theme.id) || [],
|
|
154
|
+
guide: { managerEntry: "TRAE Work 右下角的调色盘图标" },
|
|
155
|
+
}, headline, "下一步:等待 TRAE Work 打开,然后点击右下角的调色盘图标进入 Theme Manager。", "TRAE Work Skin 已启动", options);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
async function confirmAppRestart(context, appBundle, options) {
|
|
159
|
+
if (!appRunning(context, appBundle) || options.yes)
|
|
160
|
+
return;
|
|
161
|
+
if (!interactive(options)) {
|
|
162
|
+
throw new CliError("APP_RESTART_CONFIRMATION_REQUIRED", 2, "TRAE Work 正在运行;启用 Theme Manager 需要退出并重新打开应用。", "请先保存未完成的工作,然后交互式运行 twskin start 确认重启,或使用 twskin start --yes。");
|
|
163
|
+
}
|
|
164
|
+
const answer = await p.confirm({
|
|
165
|
+
message: "TRAE Work 正在运行。请先保存未完成的工作,是否现在退出并重新打开 TRAE Work?",
|
|
166
|
+
initialValue: false,
|
|
167
|
+
});
|
|
168
|
+
if (p.isCancel(answer) || !answer) {
|
|
169
|
+
p.cancel("已取消启动;TRAE Work 保持运行");
|
|
170
|
+
throw new CliError("CANCELLED", 2, "已取消启动;TRAE Work 保持运行。");
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async function confirmThemeDownload(options, themesDirectory) {
|
|
174
|
+
if (options.yes)
|
|
175
|
+
return;
|
|
176
|
+
if (options.json || !process.stdin.isTTY) {
|
|
177
|
+
throw new CliError("THEME_DOWNLOAD_CONFIRMATION_REQUIRED", 2, `主题目录为空:${themesDirectory}`, "交互式运行 twskin start,或使用 twskin start --yes;也可以先用 twskin theme load <directory> 加载本地主题。");
|
|
178
|
+
}
|
|
179
|
+
p.intro("TRAE Work Skin · 首次启动");
|
|
180
|
+
const answer = await p.confirm({
|
|
181
|
+
message: "未检测到本地主题,是否下载官方主题包?",
|
|
182
|
+
initialValue: true,
|
|
183
|
+
});
|
|
184
|
+
if (p.isCancel(answer) || !answer) {
|
|
185
|
+
p.cancel("已取消首次启动");
|
|
186
|
+
throw new CliError("CANCELLED", 2, "已取消首次启动。", "可运行 twskin theme load <directory> 加载本地主题。");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
export async function statusCommand(context, options) {
|
|
190
|
+
const status = await getStatus(context);
|
|
191
|
+
const ownerText = status.cdp.owner
|
|
192
|
+
? `${status.cdp.owner.expected ? "TRAE" : "其他进程"} (PID ${status.cdp.owner.pid})`
|
|
193
|
+
: "无监听";
|
|
194
|
+
const human = [
|
|
195
|
+
`App ${status.app.installed ? (status.app.running ? "运行中" : "已安装,未运行") : "未找到"}`,
|
|
196
|
+
`CDP ${status.cdp.reachable ? "可用" : "不可用"} · 127.0.0.1:${status.cdp.port} · ${ownerText}`,
|
|
197
|
+
`守护进程 ${status.watcher.running ? `运行中 (PID ${status.watcher.pid})` : "未运行"}`,
|
|
198
|
+
`当前主题 ${status.theme.id}${status.theme.valid ? "" : "(主题不存在)"}`,
|
|
199
|
+
].join("\n");
|
|
200
|
+
emit({ command: "status", status }, human, options.json);
|
|
201
|
+
}
|
|
202
|
+
export async function stopCommand(context, options) {
|
|
203
|
+
await withLock(context, "stop", async () => {
|
|
204
|
+
const port = readPort(context);
|
|
205
|
+
const cdpReachable = Boolean(await cdpVersion(port));
|
|
206
|
+
const watcherStopped = stopWatcher(context);
|
|
207
|
+
let persistentCdpRemoved = false;
|
|
208
|
+
let targets = 0;
|
|
209
|
+
let restoredTargets = 0;
|
|
210
|
+
try {
|
|
211
|
+
if (cdpReachable) {
|
|
212
|
+
const output = runInjector(context, ["--stop", "--port", String(port)]);
|
|
213
|
+
try {
|
|
214
|
+
const result = JSON.parse(output);
|
|
215
|
+
if (typeof result.targets === "number")
|
|
216
|
+
targets = result.targets;
|
|
217
|
+
if (typeof result.restoredTargets === "number")
|
|
218
|
+
restoredTargets = result.restoredTargets;
|
|
219
|
+
}
|
|
220
|
+
catch { }
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
finally {
|
|
224
|
+
persistentCdpRemoved = disablePersistentCdp(context).changed;
|
|
225
|
+
}
|
|
226
|
+
const human = cdpReachable
|
|
227
|
+
? "TRAE Work Skin 已停止,TRAE Work 已恢复原生外观。"
|
|
228
|
+
: watcherStopped || persistentCdpRemoved
|
|
229
|
+
? "TRAE Work Skin 守护进程已停止;TRAE Work 当前未启用 CDP。"
|
|
230
|
+
: "TRAE Work Skin 已经处于停止状态。";
|
|
231
|
+
emit({ command: "stop", watcherStopped, cdpReachable, targets, restoredTargets, persistentCdpRemoved }, human, options.json);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
export function themesCommand(context, options) {
|
|
235
|
+
const themes = listThemes(context);
|
|
236
|
+
const current = readTheme(context);
|
|
237
|
+
const width = Math.max(8, ...themes.map((theme) => theme.id.length));
|
|
238
|
+
const human = themes.length
|
|
239
|
+
? themes.map((theme) => `${theme.id === current ? "●" : " "} ${theme.id.padEnd(width)} ${theme.name}${theme.desc ? ` · ${theme.desc}` : ""}`).join("\n")
|
|
240
|
+
: "没有找到可用主题。";
|
|
241
|
+
emit({ command: "themes", directory: context.themesDir, current, themes }, `${human}\n\n主题目录:${context.themesDir}`, options.json);
|
|
242
|
+
}
|
|
243
|
+
export async function themeCommand(context, id, options) {
|
|
244
|
+
if (!id)
|
|
245
|
+
throw new CliError("THEME_REQUIRED", 2, "缺少主题 ID。", "先运行 twskin themes 查看可用主题。");
|
|
246
|
+
await withLock(context, "theme", async () => {
|
|
247
|
+
const theme = listThemes(context).find((item) => item.id === id && !item.invalid);
|
|
248
|
+
if (!theme)
|
|
249
|
+
throw new CliError("THEME_NOT_FOUND", 2, `找不到主题:${id}`, "运行 twskin themes 查看可用主题。");
|
|
250
|
+
const port = readPort(context);
|
|
251
|
+
const cdp = await cdpVersion(port);
|
|
252
|
+
if (cdp) {
|
|
253
|
+
runInjector(context, ["--apply", id, "--port", String(port)]);
|
|
254
|
+
emit({ command: "theme", theme, applied: true }, `已切换到主题 ${id}(热更新)。`, options.json);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
writeTheme(context, id);
|
|
258
|
+
emit({ command: "theme", theme, applied: false }, `已选择主题 ${id};下次运行 twskin start 时生效。`, options.json);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
export async function loadThemeCommand(context, sourceDirectory, options) {
|
|
263
|
+
if (!sourceDirectory)
|
|
264
|
+
throw new CliError("THEME_SOURCE_REQUIRED", 2, "缺少本地主题目录。", "用法:twskin theme load <directory>");
|
|
265
|
+
await withLock(context, "theme-load", async () => {
|
|
266
|
+
const themes = discoverThemeDirectories(sourceDirectory);
|
|
267
|
+
const installed = themes.map((theme) => installThemeDirectory(context, theme.source));
|
|
268
|
+
const ids = installed.map((theme) => theme.id);
|
|
269
|
+
emit({ command: "theme load", installed: ids, directory: context.themesDir }, `已加载 ${ids.length} 套主题:${ids.join("、")}\n主题目录:${context.themesDir}`, options.json);
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
export async function downloadThemeCommand(context, id, options) {
|
|
273
|
+
await withLock(context, "theme-download", async () => {
|
|
274
|
+
const result = await downloadWithProgress(context, id, options);
|
|
275
|
+
const ids = result.installed.map((theme) => theme.id);
|
|
276
|
+
emit({ command: "theme download", release: result.tag, digest: result.digest, installed: ids, directory: result.directory }, `已从 GitHub Release ${result.tag} 下载 ${ids.length} 套主题:${ids.join("、")}\n主题目录:${result.directory}`, options.json);
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
export async function doctorCommand(context, options) {
|
|
280
|
+
const status = await getStatus(context);
|
|
281
|
+
const required = [
|
|
282
|
+
"injector.mjs",
|
|
283
|
+
"skin.js",
|
|
284
|
+
"token-map.mjs",
|
|
285
|
+
"component-map.mjs",
|
|
286
|
+
"styles/base.css",
|
|
287
|
+
"styles/manager.css",
|
|
288
|
+
"start.sh",
|
|
289
|
+
"restore.sh",
|
|
290
|
+
];
|
|
291
|
+
const checks = [];
|
|
292
|
+
const add = (id, level, message, detail = "") => { checks.push({ id, level, message, detail }); };
|
|
293
|
+
const nodeMajor = Number(process.versions.node.split(".")[0]);
|
|
294
|
+
add("node", nodeMajor >= MIN_NODE_MAJOR ? "pass" : "fail", `Node.js ${process.version}`, `${process.execPath}(需要 v${MIN_NODE_MAJOR}+)`);
|
|
295
|
+
add("app", status.app.installed ? "pass" : "fail", status.app.installed ? "已找到 TRAE" : "未找到 TRAE", status.app.bundle);
|
|
296
|
+
const missing = required.filter((file) => !fs.existsSync(path.join(context.runtimeRoot, file)));
|
|
297
|
+
add("files", missing.length ? "fail" : "pass", missing.length ? `缺少 ${missing.length} 个运行文件` : "运行文件完整", missing.join(", "));
|
|
298
|
+
const integrity = verifyRuntimeIntegrity(context);
|
|
299
|
+
if (!integrity.available)
|
|
300
|
+
add("integrity", "warn", "当前开发/独立安装未提供 SHA-256 发布清单");
|
|
301
|
+
else
|
|
302
|
+
add("integrity", integrity.valid ? "pass" : "fail", integrity.valid ? `SHA-256 完整性通过(${integrity.checked} 个文件)` : `运行时完整性失败(${integrity.failures.length} 项)`, integrity.failures.map((item) => `${item.path}: ${item.reason}`).join(", "));
|
|
303
|
+
const themes = listThemes(context);
|
|
304
|
+
const validThemes = themes.filter((theme) => !theme.invalid);
|
|
305
|
+
add("themes", validThemes.length ? (validThemes.length === themes.length ? "pass" : "warn") : "fail", validThemes.length ? `发现 ${validThemes.length} 套有效主题` : "主题目录为空或没有有效主题", context.themesDir);
|
|
306
|
+
add("theme", status.theme.valid ? "pass" : "fail", status.theme.valid ? `当前主题 ${status.theme.id}` : `当前主题不存在:${status.theme.id}`);
|
|
307
|
+
if (status.cdp.owner && !status.cdp.owner.expected)
|
|
308
|
+
add("port", "fail", `端口 ${status.cdp.port} 被其他进程占用`, status.cdp.owner.command);
|
|
309
|
+
else
|
|
310
|
+
add("port", "pass", `端口 ${status.cdp.port} ${status.cdp.owner ? "属于 TRAE" : "空闲"}`);
|
|
311
|
+
add("cdp", status.cdp.reachable ? "pass" : "warn", status.cdp.reachable ? "CDP 可用" : "CDP 未启动;运行 twskin start 可启用");
|
|
312
|
+
add("watcher", status.watcher.running ? "pass" : "warn", status.watcher.running ? `守护进程运行中(PID ${status.watcher.pid})` : "守护进程未运行");
|
|
313
|
+
const failures = checks.filter((check) => check.level === "fail");
|
|
314
|
+
const human = checks.map((check) => `${check.level === "pass" ? "✓" : check.level === "warn" ? "!" : "✗"} ${check.message}${check.detail ? `\n ${check.detail}` : ""}`).join("\n");
|
|
315
|
+
if (failures.length) {
|
|
316
|
+
const message = `检查发现 ${failures.length} 个必须修复的问题。`;
|
|
317
|
+
if (options.json) {
|
|
318
|
+
console.log(JSON.stringify({ schemaVersion: 1, ok: false, command: "doctor", healthy: false, checks, error: { code: "DOCTOR_FAILED", message } }, null, 2));
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
console.log(human);
|
|
322
|
+
console.error(`twskin: ${message}`);
|
|
323
|
+
}
|
|
324
|
+
process.exitCode = 3;
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
emit({ command: "doctor", healthy: true, checks }, human, options.json);
|
|
328
|
+
}
|
|
329
|
+
export async function restoreCommand(context, options) {
|
|
330
|
+
await withLock(context, "restore", async () => {
|
|
331
|
+
disablePersistentCdp(context);
|
|
332
|
+
runScript(context, "restore.sh", { APP_BUNDLE: resolveAppBundle(context), APP_BUNDLE_ID: context.app.bundleId });
|
|
333
|
+
emit({ command: "restore" }, "已恢复 TRAE 原生外观。", options.json);
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
function managedPath(file, installDirectory) {
|
|
337
|
+
try {
|
|
338
|
+
const stat = fs.lstatSync(file);
|
|
339
|
+
if (stat.isSymbolicLink())
|
|
340
|
+
return fs.realpathSync(file).startsWith(`${installDirectory}${path.sep}`);
|
|
341
|
+
if (stat.isFile())
|
|
342
|
+
return fs.readFileSync(file, "utf8").includes(installDirectory);
|
|
343
|
+
}
|
|
344
|
+
catch { }
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
async function confirmUninstall(yes) {
|
|
348
|
+
if (yes)
|
|
349
|
+
return;
|
|
350
|
+
if (!process.stdin.isTTY)
|
|
351
|
+
throw new CliError("CONFIRMATION_REQUIRED", 2, "卸载需要确认。", "重新运行 twskin uninstall --yes。");
|
|
352
|
+
const answer = await p.confirm({
|
|
353
|
+
message: "确定卸载 TRAE Work Skin?这会恢复原生外观并删除本地主题状态。",
|
|
354
|
+
initialValue: false,
|
|
355
|
+
});
|
|
356
|
+
if (p.isCancel(answer) || !answer) {
|
|
357
|
+
p.cancel("已取消卸载");
|
|
358
|
+
throw new CliError("CANCELLED", 2, "已取消卸载。");
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
function removeStandaloneEntrypoints(context) {
|
|
362
|
+
const candidates = [
|
|
363
|
+
"/usr/local/bin/twskin",
|
|
364
|
+
"/opt/homebrew/bin/twskin",
|
|
365
|
+
path.join(os.homedir(), ".local/bin/twskin"),
|
|
366
|
+
path.join(os.homedir(), "Desktop/TRAE Work Skin.command"),
|
|
367
|
+
];
|
|
368
|
+
for (const file of candidates)
|
|
369
|
+
if (managedPath(file, context.dataDir))
|
|
370
|
+
try {
|
|
371
|
+
fs.unlinkSync(file);
|
|
372
|
+
}
|
|
373
|
+
catch { }
|
|
374
|
+
}
|
|
375
|
+
function removeGlobalNpmPackage(context) {
|
|
376
|
+
const globalRoot = commandText(context, "/usr/bin/env", ["npm", "root", "--global"]);
|
|
377
|
+
if (!globalRoot)
|
|
378
|
+
return { attempted: false, removed: false };
|
|
379
|
+
let packageRoot = context.packageRoot;
|
|
380
|
+
try {
|
|
381
|
+
packageRoot = fs.realpathSync(packageRoot);
|
|
382
|
+
}
|
|
383
|
+
catch { }
|
|
384
|
+
let normalizedGlobalRoot = globalRoot;
|
|
385
|
+
try {
|
|
386
|
+
normalizedGlobalRoot = fs.realpathSync(globalRoot);
|
|
387
|
+
}
|
|
388
|
+
catch { }
|
|
389
|
+
if (!packageRoot.startsWith(`${normalizedGlobalRoot}${path.sep}`))
|
|
390
|
+
return { attempted: false, removed: false };
|
|
391
|
+
const result = commandResult(context, "/usr/bin/env", ["npm", "uninstall", "--global", context.packageName], { inherit: true, cwd: os.homedir() });
|
|
392
|
+
if (result.status !== 0)
|
|
393
|
+
throw new CliError("NPM_UNINSTALL_FAILED", 5, "npm 全局包卸载失败。", `请手动运行 npm uninstall --global ${context.packageName}。`);
|
|
394
|
+
return { attempted: true, removed: true };
|
|
395
|
+
}
|
|
396
|
+
export async function uninstallCommand(context, options) {
|
|
397
|
+
await confirmUninstall(options.yes);
|
|
398
|
+
if (context.distribution === "development") {
|
|
399
|
+
throw new CliError("DEVELOPMENT_INSTALL", 2, "不能从源码工作区执行卸载。", "请使用已经安装的 twskin uninstall。");
|
|
400
|
+
}
|
|
401
|
+
await withLock(context, "uninstall", async () => {
|
|
402
|
+
disablePersistentCdp(context);
|
|
403
|
+
const port = readPort(context);
|
|
404
|
+
if (await cdpVersion(port)) {
|
|
405
|
+
runScript(context, "restore.sh", { APP_BUNDLE: resolveAppBundle(context), APP_BUNDLE_ID: context.app.bundleId });
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
stopWatcher(context);
|
|
409
|
+
}
|
|
410
|
+
removeStandaloneEntrypoints(context);
|
|
411
|
+
let npm = { attempted: false, removed: false };
|
|
412
|
+
if (context.distribution === "npm")
|
|
413
|
+
npm = removeGlobalNpmPackage(context);
|
|
414
|
+
fs.rmSync(context.dataDir, { recursive: true, force: true });
|
|
415
|
+
const suffix = context.distribution === "npm" && !npm.removed
|
|
416
|
+
? `\n当前不是全局 npm 安装;请在对应项目中移除 ${context.packageName}。`
|
|
417
|
+
: "";
|
|
418
|
+
emit({ command: "uninstall", dataDir: context.dataDir, packageRemoved: npm.removed || context.distribution === "standalone" }, `TRAE Work Skin 已卸载。${suffix}`, options.json);
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CliContext } from "./types.js";
|
|
2
|
+
export declare const PACKAGE_ROOT: string;
|
|
3
|
+
export declare const REPO_ROOT: string;
|
|
4
|
+
export declare const PACKAGE_METADATA: {
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const DEFAULT_PORT = 19527;
|
|
9
|
+
export declare const DEFAULT_APP_BUNDLE = "/Applications/TRAE SOLO CN.app";
|
|
10
|
+
export declare const DEFAULT_APP_BUNDLE_ID = "cn.trae.solo.app";
|
|
11
|
+
export declare const DEFAULT_APP_PROC_MATCH = "TRAE SOLO CN";
|
|
12
|
+
export declare const MIN_NODE_MAJOR = 22;
|
|
13
|
+
export declare function createContext(env?: NodeJS.ProcessEnv): Readonly<CliContext>;
|
|
14
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,eAAO,MAAM,YAAY,QAA2B,CAAC;AACrD,eAAO,MAAM,SAAS,QAAsC,CAAC;AAC7D,eAAO,MAAM,gBAAgB,EAAmF;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAElJ,eAAO,MAAM,YAAY,QAAQ,CAAC;AAClC,eAAO,MAAM,kBAAkB,mCAAmC,CAAC;AACnE,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AACxD,eAAO,MAAM,sBAAsB,iBAAiB,CAAC;AACrD,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,QAAQ,CAAC,UAAU,CAAC,CAuCxF"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
const SOURCE_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
export const PACKAGE_ROOT = path.dirname(SOURCE_DIR);
|
|
7
|
+
export const REPO_ROOT = path.resolve(PACKAGE_ROOT, "../..");
|
|
8
|
+
export const PACKAGE_METADATA = JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, "package.json"), "utf8"));
|
|
9
|
+
export const DEFAULT_PORT = 19527;
|
|
10
|
+
export const DEFAULT_APP_BUNDLE = "/Applications/TRAE SOLO CN.app";
|
|
11
|
+
export const DEFAULT_APP_BUNDLE_ID = "cn.trae.solo.app";
|
|
12
|
+
export const DEFAULT_APP_PROC_MATCH = "TRAE SOLO CN";
|
|
13
|
+
export const MIN_NODE_MAJOR = 22;
|
|
14
|
+
export function createContext(env = process.env) {
|
|
15
|
+
const packagedRuntime = path.join(PACKAGE_ROOT, "runtime");
|
|
16
|
+
const sourceCheckout = fs.existsSync(path.join(PACKAGE_ROOT, "src"));
|
|
17
|
+
const runtimeRoot = path.resolve(env.TWSKIN_RUNTIME_ROOT || packagedRuntime);
|
|
18
|
+
const dataDir = path.resolve(env.TWSKIN_DATA_DIR || path.join(os.homedir(), ".trae-work-skin"));
|
|
19
|
+
const stateDir = path.resolve(env.TWSKIN_STATE_DIR || path.join(dataDir, "run"));
|
|
20
|
+
const distribution = env.TWSKIN_DISTRIBUTION || (sourceCheckout ? "development" : runtimeRoot === dataDir ? "standalone" : "npm");
|
|
21
|
+
const defaultThemesDir = distribution === "development"
|
|
22
|
+
? path.join(REPO_ROOT, "themes")
|
|
23
|
+
: path.join(dataDir, "themes");
|
|
24
|
+
return Object.freeze({
|
|
25
|
+
env,
|
|
26
|
+
packageName: PACKAGE_METADATA.name,
|
|
27
|
+
packageVersion: PACKAGE_METADATA.version,
|
|
28
|
+
packageRoot: PACKAGE_ROOT,
|
|
29
|
+
runtimeRoot,
|
|
30
|
+
dataDir,
|
|
31
|
+
stateDir,
|
|
32
|
+
themesDir: path.resolve(env.TWSKIN_THEMES_DIR || defaultThemesDir),
|
|
33
|
+
distribution,
|
|
34
|
+
paths: Object.freeze({
|
|
35
|
+
themeConf: path.join(stateDir, "theme.conf"),
|
|
36
|
+
pidFile: path.join(stateDir, "injector.pid"),
|
|
37
|
+
portFile: path.join(stateDir, "port"),
|
|
38
|
+
cdpConfigState: path.join(stateDir, "cdp-config.json"),
|
|
39
|
+
lockFile: path.join(stateDir, "cli.lock"),
|
|
40
|
+
logFile: path.join(stateDir, "injector.log"),
|
|
41
|
+
runtimeManifest: path.join(runtimeRoot, "manifest.json"),
|
|
42
|
+
}),
|
|
43
|
+
app: Object.freeze({
|
|
44
|
+
bundle: env.APP_BUNDLE || DEFAULT_APP_BUNDLE,
|
|
45
|
+
bundleId: env.APP_BUNDLE_ID || DEFAULT_APP_BUNDLE_ID,
|
|
46
|
+
processMatch: env.APP_PROC_MATCH || DEFAULT_APP_PROC_MATCH,
|
|
47
|
+
...(env.TWSKIN_APP_ARGV_FILE ? { argvFile: path.resolve(env.TWSKIN_APP_ARGV_FILE) } : {}),
|
|
48
|
+
}),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare class CliError extends Error {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
readonly exitCode: number;
|
|
4
|
+
readonly hint: string;
|
|
5
|
+
readonly detail: unknown;
|
|
6
|
+
constructor(code: string, exitCode: number, message: string, hint?: string, detail?: unknown);
|
|
7
|
+
}
|
|
8
|
+
export declare function asCliError(error: unknown): CliError;
|
|
9
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEzB,YAAY,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,SAAK,EAAE,MAAM,CAAC,EAAE,OAAO,EAOvF;CACF;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAInD"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export class CliError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
exitCode;
|
|
4
|
+
hint;
|
|
5
|
+
detail;
|
|
6
|
+
constructor(code, exitCode, message, hint = "", detail) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "CliError";
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.exitCode = exitCode;
|
|
11
|
+
this.hint = hint;
|
|
12
|
+
this.detail = detail;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function asCliError(error) {
|
|
16
|
+
return error instanceof CliError
|
|
17
|
+
? error
|
|
18
|
+
: new CliError("INTERNAL_ERROR", 1, error instanceof Error ? error.message : String(error));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,CAAS;IACb,QAAQ,CAAS;IACjB,IAAI,CAAS;IACb,MAAM,CAAU;IAEzB,YAAY,IAAY,EAAE,QAAgB,EAAE,OAAe,EAAE,IAAI,GAAG,EAAE,EAAE,MAAgB;QACtF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,KAAK,YAAY,QAAQ;QAC9B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,IAAI,QAAQ,CAAC,gBAAgB,EAAE,CAAC,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAChG,CAAC"}
|
package/dist/lock.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA+B7C,wBAAsB,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAGnH"}
|
package/dist/lock.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { CliError } from "./errors.js";
|
|
5
|
+
import { pidAlive } from "./system.js";
|
|
6
|
+
function acquireLock(context, command) {
|
|
7
|
+
fs.mkdirSync(path.dirname(context.paths.lockFile), { recursive: true });
|
|
8
|
+
const attempt = () => {
|
|
9
|
+
const descriptor = fs.openSync(context.paths.lockFile, "wx", 0o600);
|
|
10
|
+
fs.writeFileSync(descriptor, `${JSON.stringify({ pid: process.pid, command, createdAt: new Date().toISOString() })}\n`);
|
|
11
|
+
fs.closeSync(descriptor);
|
|
12
|
+
};
|
|
13
|
+
try {
|
|
14
|
+
attempt();
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
if (!(error instanceof Error) || !("code" in error) || error.code !== "EEXIST")
|
|
18
|
+
throw error;
|
|
19
|
+
let owner = null;
|
|
20
|
+
try {
|
|
21
|
+
owner = JSON.parse(fs.readFileSync(context.paths.lockFile, "utf8"));
|
|
22
|
+
}
|
|
23
|
+
catch { }
|
|
24
|
+
if (owner?.pid && pidAlive(Number(owner.pid))) {
|
|
25
|
+
throw new CliError("LOCKED", 6, `另一个 twskin 命令正在执行(PID ${owner.pid})。`, "请等待它完成后重试。");
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
fs.unlinkSync(context.paths.lockFile);
|
|
29
|
+
}
|
|
30
|
+
catch { }
|
|
31
|
+
try {
|
|
32
|
+
attempt();
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
throw new CliError("LOCKED", 6, "另一个 twskin 命令正在执行。", "请稍后重试。");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return () => { try {
|
|
39
|
+
fs.unlinkSync(context.paths.lockFile);
|
|
40
|
+
}
|
|
41
|
+
catch { } };
|
|
42
|
+
}
|
|
43
|
+
export async function withLock(context, command, operation) {
|
|
44
|
+
const release = acquireLock(context, command);
|
|
45
|
+
try {
|
|
46
|
+
return await operation();
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
release();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=lock.js.map
|