@team-semicolon/semo-cli 3.0.2 → 3.0.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/dist/index.js +122 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1141,10 +1141,40 @@ program
|
|
|
1141
1141
|
program
|
|
1142
1142
|
.command("update")
|
|
1143
1143
|
.description("SEMO를 최신 버전으로 업데이트합니다")
|
|
1144
|
-
.
|
|
1144
|
+
.option("--self", "CLI만 업데이트")
|
|
1145
|
+
.option("--system", "semo-system만 업데이트")
|
|
1146
|
+
.option("--skip-cli", "CLI 업데이트 건너뛰기")
|
|
1147
|
+
.action(async (options) => {
|
|
1145
1148
|
console.log(chalk_1.default.cyan.bold("\n🔄 SEMO 업데이트\n"));
|
|
1146
1149
|
const cwd = process.cwd();
|
|
1147
1150
|
const semoSystemDir = path.join(cwd, "semo-system");
|
|
1151
|
+
const claudeDir = path.join(cwd, ".claude");
|
|
1152
|
+
// === 1. CLI 자체 업데이트 ===
|
|
1153
|
+
if (options.self || (!options.system && !options.skipCli)) {
|
|
1154
|
+
console.log(chalk_1.default.cyan("📦 CLI 업데이트"));
|
|
1155
|
+
const cliSpinner = (0, ora_1.default)(" @team-semicolon/semo-cli 업데이트 중...").start();
|
|
1156
|
+
try {
|
|
1157
|
+
(0, child_process_1.execSync)("npm update -g @team-semicolon/semo-cli", { stdio: "pipe" });
|
|
1158
|
+
cliSpinner.succeed(" CLI 업데이트 완료");
|
|
1159
|
+
}
|
|
1160
|
+
catch (error) {
|
|
1161
|
+
cliSpinner.fail(" CLI 업데이트 실패");
|
|
1162
|
+
const errorMsg = String(error);
|
|
1163
|
+
if (errorMsg.includes("EACCES") || errorMsg.includes("permission")) {
|
|
1164
|
+
console.log(chalk_1.default.yellow("\n 💡 권한 오류: 다음 명령어로 재시도하세요:"));
|
|
1165
|
+
console.log(chalk_1.default.white(" sudo npm update -g @team-semicolon/semo-cli\n"));
|
|
1166
|
+
}
|
|
1167
|
+
else {
|
|
1168
|
+
console.error(chalk_1.default.gray(` ${errorMsg}`));
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
// --self 옵션만 있으면 여기서 종료
|
|
1172
|
+
if (options.self) {
|
|
1173
|
+
console.log(chalk_1.default.green.bold("\n✅ CLI 업데이트 완료!\n"));
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
// === 2. semo-system 업데이트 ===
|
|
1148
1178
|
if (!fs.existsSync(semoSystemDir)) {
|
|
1149
1179
|
console.log(chalk_1.default.red("SEMO가 설치되어 있지 않습니다. 'semo init'을 먼저 실행하세요."));
|
|
1150
1180
|
process.exit(1);
|
|
@@ -1156,13 +1186,14 @@ program
|
|
|
1156
1186
|
installedExtensions.push(key);
|
|
1157
1187
|
}
|
|
1158
1188
|
}
|
|
1159
|
-
console.log(chalk_1.default.cyan("업데이트
|
|
1160
|
-
console.log(chalk_1.default.gray("
|
|
1161
|
-
console.log(chalk_1.default.gray("
|
|
1189
|
+
console.log(chalk_1.default.cyan("\n📚 semo-system 업데이트"));
|
|
1190
|
+
console.log(chalk_1.default.gray(" 대상:"));
|
|
1191
|
+
console.log(chalk_1.default.gray(" - semo-core"));
|
|
1192
|
+
console.log(chalk_1.default.gray(" - semo-skills"));
|
|
1162
1193
|
installedExtensions.forEach(pkg => {
|
|
1163
|
-
console.log(chalk_1.default.gray(`
|
|
1194
|
+
console.log(chalk_1.default.gray(` - ${pkg}`));
|
|
1164
1195
|
});
|
|
1165
|
-
const spinner = (0, ora_1.default)("\n최신 버전 다운로드 중...").start();
|
|
1196
|
+
const spinner = (0, ora_1.default)("\n 최신 버전 다운로드 중...").start();
|
|
1166
1197
|
try {
|
|
1167
1198
|
const tempDir = path.join(cwd, ".semo-temp");
|
|
1168
1199
|
removeRecursive(tempDir);
|
|
@@ -1182,11 +1213,93 @@ program
|
|
|
1182
1213
|
}
|
|
1183
1214
|
}
|
|
1184
1215
|
removeRecursive(tempDir);
|
|
1185
|
-
spinner.succeed("
|
|
1216
|
+
spinner.succeed(" semo-system 업데이트 완료");
|
|
1186
1217
|
}
|
|
1187
1218
|
catch (error) {
|
|
1188
|
-
spinner.fail("업데이트 실패");
|
|
1189
|
-
console.error(chalk_1.default.red(
|
|
1219
|
+
spinner.fail(" semo-system 업데이트 실패");
|
|
1220
|
+
console.error(chalk_1.default.red(` ${error}`));
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
// === 3. 심볼릭 링크 재생성 ===
|
|
1224
|
+
console.log(chalk_1.default.cyan("\n🔗 심볼릭 링크 재생성"));
|
|
1225
|
+
// 기존 링크 정리
|
|
1226
|
+
const claudeAgentsDir = path.join(claudeDir, "agents");
|
|
1227
|
+
const claudeSkillsDir = path.join(claudeDir, "skills");
|
|
1228
|
+
if (fs.existsSync(claudeAgentsDir)) {
|
|
1229
|
+
const existingLinks = fs.readdirSync(claudeAgentsDir);
|
|
1230
|
+
for (const link of existingLinks) {
|
|
1231
|
+
const linkPath = path.join(claudeAgentsDir, link);
|
|
1232
|
+
if (fs.lstatSync(linkPath).isSymbolicLink()) {
|
|
1233
|
+
fs.unlinkSync(linkPath);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
if (fs.existsSync(claudeSkillsDir)) {
|
|
1238
|
+
const existingLinks = fs.readdirSync(claudeSkillsDir);
|
|
1239
|
+
for (const link of existingLinks) {
|
|
1240
|
+
const linkPath = path.join(claudeSkillsDir, link);
|
|
1241
|
+
if (fs.lstatSync(linkPath).isSymbolicLink()) {
|
|
1242
|
+
fs.unlinkSync(linkPath);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
// Standard 심볼릭 링크 재생성
|
|
1247
|
+
await createStandardSymlinks(cwd);
|
|
1248
|
+
// Extensions 심볼릭 링크 재생성
|
|
1249
|
+
if (installedExtensions.length > 0) {
|
|
1250
|
+
await setupExtensionSymlinks(cwd, installedExtensions);
|
|
1251
|
+
}
|
|
1252
|
+
// === 4. CLAUDE.md 재생성 ===
|
|
1253
|
+
console.log(chalk_1.default.cyan("\n📄 CLAUDE.md 재생성"));
|
|
1254
|
+
await setupClaudeMd(cwd, installedExtensions, true);
|
|
1255
|
+
// === 5. MCP 서버 동기화 ===
|
|
1256
|
+
console.log(chalk_1.default.cyan("\n🔧 MCP 서버 동기화"));
|
|
1257
|
+
// Extension의 MCP 설정 확인 및 병합
|
|
1258
|
+
const allServers = [...BASE_MCP_SERVERS];
|
|
1259
|
+
for (const pkg of installedExtensions) {
|
|
1260
|
+
const extSettingsPath = path.join(semoSystemDir, pkg, "settings.local.json");
|
|
1261
|
+
if (fs.existsSync(extSettingsPath)) {
|
|
1262
|
+
try {
|
|
1263
|
+
const extSettings = JSON.parse(fs.readFileSync(extSettingsPath, "utf-8"));
|
|
1264
|
+
if (extSettings.mcpServers) {
|
|
1265
|
+
for (const [name, config] of Object.entries(extSettings.mcpServers)) {
|
|
1266
|
+
const serverConfig = config;
|
|
1267
|
+
allServers.push({
|
|
1268
|
+
name,
|
|
1269
|
+
command: serverConfig.command,
|
|
1270
|
+
args: serverConfig.args,
|
|
1271
|
+
env: serverConfig.env,
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
catch {
|
|
1277
|
+
// 파싱 실패 무시
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
// MCP 서버 등록 상태 확인
|
|
1282
|
+
const missingServers = [];
|
|
1283
|
+
for (const server of allServers) {
|
|
1284
|
+
if (!isMCPServerRegistered(server.name)) {
|
|
1285
|
+
missingServers.push(server);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
if (missingServers.length === 0) {
|
|
1289
|
+
console.log(chalk_1.default.green(" ✓ 모든 MCP 서버가 등록되어 있습니다"));
|
|
1290
|
+
}
|
|
1291
|
+
else {
|
|
1292
|
+
console.log(chalk_1.default.yellow(` ${missingServers.length}개 MCP 서버 미등록`));
|
|
1293
|
+
for (const server of missingServers) {
|
|
1294
|
+
const result = registerMCPServer(server);
|
|
1295
|
+
if (result.success) {
|
|
1296
|
+
console.log(chalk_1.default.green(` ✓ ${server.name} 등록 완료`));
|
|
1297
|
+
}
|
|
1298
|
+
else {
|
|
1299
|
+
console.log(chalk_1.default.red(` ✗ ${server.name} 등록 실패`));
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1190
1302
|
}
|
|
1303
|
+
console.log(chalk_1.default.green.bold("\n✅ SEMO 업데이트 완료!\n"));
|
|
1191
1304
|
});
|
|
1192
1305
|
program.parse();
|