ticketpro-auto-setup 1.1.4 → 1.1.6
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.
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
* npm 包: code-abyss (by telagod)
|
|
4
4
|
* 支持: npx code-abyss --target claude|codex
|
|
5
5
|
*/
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
6
8
|
import { spawn } from 'node:child_process';
|
|
7
9
|
import ora from 'ora';
|
|
8
|
-
import { execAsync } from '../utils/shell.js';
|
|
9
|
-
import { getPlatform } from '../utils/platform.js';
|
|
10
|
+
import { execAsync, execCommand } from '../utils/shell.js';
|
|
11
|
+
import { getPlatform, getClaudeDir } from '../utils/platform.js';
|
|
10
12
|
import { log } from '../utils/logger.js';
|
|
11
13
|
/**
|
|
12
14
|
* 安装 code-abyss(邪修道统 · 安全工程技能)
|
|
@@ -42,10 +44,13 @@ export async function installCodeAbyss(target) {
|
|
|
42
44
|
async function runCodeAbyss(target, spinner) {
|
|
43
45
|
const name = target === 'codex' ? 'code-abyss (Codex)' : 'code-abyss';
|
|
44
46
|
const { npxCmd, npmCmd } = getPlatform();
|
|
45
|
-
// 方式 1: npx -y code-abyss --target <target>
|
|
47
|
+
// 方式 1: npx -y code-abyss --target <target> -y
|
|
46
48
|
spinner.text = `Installing code-abyss → ${target} (npx)...`;
|
|
47
49
|
const result = await spawnCodeAbyss(npxCmd, ['-y', 'code-abyss', '--target', target, '-y']);
|
|
48
50
|
if (result.success) {
|
|
51
|
+
if (target === 'claude') {
|
|
52
|
+
ensureCclineStatusLine();
|
|
53
|
+
}
|
|
49
54
|
spinner.succeed(`code-abyss installed → ${target}`);
|
|
50
55
|
return { name, success: true };
|
|
51
56
|
}
|
|
@@ -58,6 +63,9 @@ async function runCodeAbyss(target, spinner) {
|
|
|
58
63
|
spinner.text = `Running code-abyss → ${target} (global)...`;
|
|
59
64
|
const execResult = await spawnCodeAbyss('code-abyss', ['--target', target, '-y']);
|
|
60
65
|
if (execResult.success) {
|
|
66
|
+
if (target === 'claude') {
|
|
67
|
+
ensureCclineStatusLine();
|
|
68
|
+
}
|
|
61
69
|
spinner.succeed(`code-abyss installed → ${target} (global)`);
|
|
62
70
|
return { name, success: true };
|
|
63
71
|
}
|
|
@@ -74,11 +82,11 @@ async function runCodeAbyss(target, spinner) {
|
|
|
74
82
|
* 通过 spawn 执行 code-abyss,周期性向 stdin 写 "N\n" 自动跳过交互提示
|
|
75
83
|
* - 不阻塞事件循环(spinner 可正常旋转)
|
|
76
84
|
* - 跨平台(Windows/Linux/Mac)
|
|
77
|
-
* -
|
|
85
|
+
* - 固定 cwd 到 home,避免 uv_cwd / getcwd 异常
|
|
78
86
|
*/
|
|
79
87
|
function spawnCodeAbyss(command, args) {
|
|
80
88
|
return new Promise((resolve) => {
|
|
81
|
-
const { isWindows } = getPlatform();
|
|
89
|
+
const { isWindows, homeDir } = getPlatform();
|
|
82
90
|
const timeout = 300_000; // 5 min
|
|
83
91
|
// 用 shell -c 拼接命令字符串,避免 DEP0190 警告
|
|
84
92
|
// (spawn 同时传 args + shell: true 会触发 Node 弃用警告)
|
|
@@ -86,6 +94,7 @@ function spawnCodeAbyss(command, args) {
|
|
|
86
94
|
const shellArg = isWindows ? '/c' : '-c';
|
|
87
95
|
const fullCmd = [command, ...args].join(' ');
|
|
88
96
|
const child = spawn(shell, [shellArg, fullCmd], {
|
|
97
|
+
cwd: homeDir,
|
|
89
98
|
env: { ...process.env, CI: 'true', FORCE_COLOR: '0' },
|
|
90
99
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
91
100
|
});
|
|
@@ -121,4 +130,69 @@ function spawnCodeAbyss(command, args) {
|
|
|
121
130
|
});
|
|
122
131
|
});
|
|
123
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* 兜底确保 statusLine 指向 ccline。
|
|
135
|
+
* 某些环境下 code-abyss 可能因配置合并策略未写入该字段,
|
|
136
|
+
* 或写入了 ~/.claude/ccline/ccline 但该路径实际不存在(例如 nvm 全局安装)。
|
|
137
|
+
*/
|
|
138
|
+
function ensureCclineStatusLine() {
|
|
139
|
+
try {
|
|
140
|
+
const { homeDir } = getPlatform();
|
|
141
|
+
const claudeDir = getClaudeDir();
|
|
142
|
+
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
143
|
+
if (!fs.existsSync(settingsPath))
|
|
144
|
+
return;
|
|
145
|
+
let settings = {};
|
|
146
|
+
try {
|
|
147
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const cclineDir = path.join(claudeDir, 'ccline');
|
|
153
|
+
const localCcline = path.join(cclineDir, 'ccline');
|
|
154
|
+
// 动态解析全局 ccline 路径(兼容 nvm: ~/.nvm/.../bin/ccline)
|
|
155
|
+
let resolvedGlobal = '';
|
|
156
|
+
const whichResult = execCommand('command -v ccline', { cwd: homeDir, timeout: 5000 });
|
|
157
|
+
if (whichResult.success) {
|
|
158
|
+
resolvedGlobal = whichResult.stdout.split('\n').pop()?.trim() ?? '';
|
|
159
|
+
}
|
|
160
|
+
// 如果本地路径不存在,但全局 ccline 存在,创建软链接到本地稳定路径
|
|
161
|
+
if (!fs.existsSync(localCcline) && resolvedGlobal && fs.existsSync(resolvedGlobal)) {
|
|
162
|
+
fs.mkdirSync(cclineDir, { recursive: true });
|
|
163
|
+
try {
|
|
164
|
+
fs.symlinkSync(resolvedGlobal, localCcline);
|
|
165
|
+
log.success(`ccline linked: ${localCcline} -> ${resolvedGlobal}`);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
// ignore
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const current = settings.statusLine;
|
|
172
|
+
const currentCommand = current && typeof current === 'object' && typeof current.command === 'string'
|
|
173
|
+
? current.command
|
|
174
|
+
: '';
|
|
175
|
+
const localCmd = '~/.claude/ccline/ccline';
|
|
176
|
+
const fallbackCmd = resolvedGlobal && fs.existsSync(resolvedGlobal) ? resolvedGlobal : localCmd;
|
|
177
|
+
// 需要补丁的条件:
|
|
178
|
+
// 1) 没有 statusLine
|
|
179
|
+
// 2) statusLine 不是 ccline
|
|
180
|
+
// 3) statusLine 指向本地 ccline 但本地文件不存在(坏链路)
|
|
181
|
+
const needPatch = !currentCommand ||
|
|
182
|
+
!currentCommand.includes('ccline') ||
|
|
183
|
+
(currentCommand.includes('~/.claude/ccline/ccline') && !fs.existsSync(localCcline));
|
|
184
|
+
if (needPatch) {
|
|
185
|
+
settings.statusLine = {
|
|
186
|
+
type: 'command',
|
|
187
|
+
command: fs.existsSync(localCcline) ? localCmd : fallbackCmd,
|
|
188
|
+
padding: 0,
|
|
189
|
+
};
|
|
190
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
|
|
191
|
+
log.success(`ccline statusLine patched: ${settings.statusLine.command}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// 静默兜底,不影响主流程
|
|
196
|
+
}
|
|
197
|
+
}
|
|
124
198
|
//# sourceMappingURL=code-abyss.js.map
|