@dusky-bluehour/agent-service 0.6.3 → 0.6.4
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/README.md +4 -0
- package/package.json +1 -1
- package/scripts/init.mjs +161 -49
package/README.md
CHANGED
package/package.json
CHANGED
package/scripts/init.mjs
CHANGED
|
@@ -1146,32 +1146,82 @@ function statusLabel(status) {
|
|
|
1146
1146
|
}
|
|
1147
1147
|
}
|
|
1148
1148
|
|
|
1149
|
-
function
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1149
|
+
function statusIcon(status) {
|
|
1150
|
+
switch (status) {
|
|
1151
|
+
case 'copied':
|
|
1152
|
+
return '✅';
|
|
1153
|
+
case 'overwritten':
|
|
1154
|
+
return '♻️';
|
|
1155
|
+
case 'skipped':
|
|
1156
|
+
return '⏭️';
|
|
1157
|
+
case 'would-copy':
|
|
1158
|
+
return '📝';
|
|
1159
|
+
case 'would-overwrite':
|
|
1160
|
+
return '🛠️';
|
|
1161
|
+
default:
|
|
1162
|
+
return '•';
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1155
1165
|
|
|
1156
|
-
|
|
1166
|
+
function normalizeChoiceInput(value) {
|
|
1167
|
+
return value
|
|
1168
|
+
.trim()
|
|
1169
|
+
.toLowerCase()
|
|
1170
|
+
.replaceAll('1', '1')
|
|
1171
|
+
.replaceAll('2', '2')
|
|
1172
|
+
.replaceAll('3', '3')
|
|
1173
|
+
.replaceAll('4', '4')
|
|
1174
|
+
.replaceAll('5', '5');
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
function printPlan(catalog, selection, mode, targetDir, dryRun = false) {
|
|
1178
|
+
console.log('');
|
|
1179
|
+
console.log('━━━━━━━━ 실행 계획 ━━━━━━━━');
|
|
1180
|
+
console.log(`모드 : ${mode}`);
|
|
1181
|
+
console.log(`실행 타입 : ${dryRun ? 'dry-run (실제 파일 변경 없음)' : '실행 (파일 변경 반영)'}`);
|
|
1182
|
+
console.log(`프리셋 : ${selection.presetId ?? '수동/없음'}`);
|
|
1183
|
+
console.log(`대상 경로 : ${targetDir}`);
|
|
1184
|
+
console.log(`선택 도구 : ${selection.selectedToolIds.length}개`);
|
|
1185
|
+
|
|
1186
|
+
selection.selectedToolIds.forEach((toolId, index) => {
|
|
1157
1187
|
const tool = findTool(catalog, toolId);
|
|
1188
|
+
if (!tool) {
|
|
1189
|
+
return;
|
|
1190
|
+
}
|
|
1158
1191
|
const installRoot = getEffectiveInstallRoot(tool, selection);
|
|
1159
1192
|
const installReferences = getToolInstallReferences(tool);
|
|
1160
1193
|
const componentIds = selection.componentSelection[toolId] ?? [];
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
console.log(
|
|
1166
|
-
|
|
1167
|
-
)
|
|
1194
|
+
|
|
1195
|
+
console.log('');
|
|
1196
|
+
console.log(`${index + 1}. ${tool.title} (${tool.id})`);
|
|
1197
|
+
console.log(` 설치 루트 : ${installRoot}`);
|
|
1198
|
+
console.log(' 구성요소 :');
|
|
1199
|
+
|
|
1200
|
+
if (componentIds.length === 0) {
|
|
1201
|
+
console.log(' - 선택된 항목 없음');
|
|
1202
|
+
} else {
|
|
1203
|
+
for (const componentId of componentIds) {
|
|
1204
|
+
const component = tool.components.find((candidate) => candidate.id === componentId);
|
|
1205
|
+
if (!component) continue;
|
|
1206
|
+
console.log(
|
|
1207
|
+
` - ${component.title} (${component.id}) -> ${path.join(
|
|
1208
|
+
installRoot,
|
|
1209
|
+
getComponentInstallPath(component)
|
|
1210
|
+
)}`
|
|
1211
|
+
);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1168
1215
|
if (tool.install_root_basis) {
|
|
1169
|
-
console.log(`
|
|
1216
|
+
console.log(` 경로 기준 : ${tool.install_root_basis}`);
|
|
1170
1217
|
}
|
|
1171
1218
|
if (installReferences.length > 0) {
|
|
1172
|
-
console.log(
|
|
1219
|
+
console.log(' 참고 문서 :');
|
|
1220
|
+
installReferences.forEach((ref) => {
|
|
1221
|
+
console.log(` - ${ref}`);
|
|
1222
|
+
});
|
|
1173
1223
|
}
|
|
1174
|
-
}
|
|
1224
|
+
});
|
|
1175
1225
|
}
|
|
1176
1226
|
|
|
1177
1227
|
async function confirmProceed(yesFlag) {
|
|
@@ -1180,9 +1230,23 @@ async function confirmProceed(yesFlag) {
|
|
|
1180
1230
|
|
|
1181
1231
|
const rl = createInterface({ input, output });
|
|
1182
1232
|
try {
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1233
|
+
while (true) {
|
|
1234
|
+
console.log('');
|
|
1235
|
+
console.log('진행 여부를 선택해 주세요.');
|
|
1236
|
+
console.log('1) 진행');
|
|
1237
|
+
console.log('2) 취소 (기본값)');
|
|
1238
|
+
const answer = await rl.question('번호를 입력하세요. [기본: 2]\n> ');
|
|
1239
|
+
const normalized = normalizeChoiceInput(answer);
|
|
1240
|
+
|
|
1241
|
+
if (!normalized || normalized === '2' || normalized === '취소' || normalized === '아니오') {
|
|
1242
|
+
return false;
|
|
1243
|
+
}
|
|
1244
|
+
if (normalized === '1' || normalized === '진행' || normalized === '예') {
|
|
1245
|
+
return true;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
console.log('잘못된 입력입니다. 1 또는 2를 입력해 주세요.');
|
|
1249
|
+
}
|
|
1186
1250
|
} finally {
|
|
1187
1251
|
rl.close();
|
|
1188
1252
|
}
|
|
@@ -1289,12 +1353,40 @@ async function runInstallOrUpdate({ catalog, packageData, mode, selection, force
|
|
|
1289
1353
|
}
|
|
1290
1354
|
|
|
1291
1355
|
console.log('');
|
|
1292
|
-
console.log('적용 결과');
|
|
1356
|
+
console.log('━━━━━━━━ 적용 결과 ━━━━━━━━');
|
|
1357
|
+
const summaryCounter = {
|
|
1358
|
+
copied: 0,
|
|
1359
|
+
overwritten: 0,
|
|
1360
|
+
skipped: 0,
|
|
1361
|
+
'would-copy': 0,
|
|
1362
|
+
'would-overwrite': 0
|
|
1363
|
+
};
|
|
1293
1364
|
for (const item of results) {
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1365
|
+
if (item.status in summaryCounter) {
|
|
1366
|
+
summaryCounter[item.status] += 1;
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
const groupedResults = new Map();
|
|
1371
|
+
for (const item of results) {
|
|
1372
|
+
const list = groupedResults.get(item.toolId) ?? [];
|
|
1373
|
+
list.push(item);
|
|
1374
|
+
groupedResults.set(item.toolId, list);
|
|
1375
|
+
}
|
|
1376
|
+
for (const toolId of selection.selectedToolIds) {
|
|
1377
|
+
const items = groupedResults.get(toolId) ?? [];
|
|
1378
|
+
if (items.length === 0) continue;
|
|
1379
|
+
console.log(`[${toolId}]`);
|
|
1380
|
+
for (const item of items) {
|
|
1381
|
+
console.log(
|
|
1382
|
+
` - ${statusIcon(item.status)} ${statusLabel(item.status)} | ${item.source} -> ${item.destination}`
|
|
1383
|
+
);
|
|
1384
|
+
}
|
|
1297
1385
|
}
|
|
1386
|
+
console.log('');
|
|
1387
|
+
console.log(
|
|
1388
|
+
`요약: 복사 ${summaryCounter.copied} · 업데이트 ${summaryCounter.overwritten} · 건너뜀 ${summaryCounter.skipped} · 복사예정 ${summaryCounter['would-copy']} · 업데이트예정 ${summaryCounter['would-overwrite']}`
|
|
1389
|
+
);
|
|
1298
1390
|
|
|
1299
1391
|
const usageGuidePath = path.join(targetDir, STATE_DIR_NAME, GUIDE_FILE_NAME);
|
|
1300
1392
|
if (dryRun) {
|
|
@@ -1313,46 +1405,61 @@ async function runInstallOrUpdate({ catalog, packageData, mode, selection, force
|
|
|
1313
1405
|
|
|
1314
1406
|
function printList(catalog) {
|
|
1315
1407
|
console.log('');
|
|
1316
|
-
console.log(
|
|
1317
|
-
console.log(
|
|
1318
|
-
|
|
1408
|
+
console.log('━━━━━━━━ 도구 카탈로그 ━━━━━━━━');
|
|
1409
|
+
console.log(`CLI: ${CLI_NAME}`);
|
|
1410
|
+
|
|
1411
|
+
catalog.tools.forEach((tool, toolIndex) => {
|
|
1319
1412
|
const installRoot = getToolInstallRoot(tool);
|
|
1320
1413
|
const installReferences = getToolInstallReferences(tool);
|
|
1321
|
-
console.log(
|
|
1322
|
-
console.log(
|
|
1323
|
-
console.log(`
|
|
1414
|
+
console.log('');
|
|
1415
|
+
console.log(`${toolIndex + 1}. ${tool.title} (${tool.id})`);
|
|
1416
|
+
console.log(` 설명 : ${tool.description}`);
|
|
1417
|
+
console.log(` 설치 루트 : ${installRoot}`);
|
|
1324
1418
|
if (tool.install_root_basis) {
|
|
1325
|
-
console.log(`
|
|
1419
|
+
console.log(` 경로 기준 : ${tool.install_root_basis}`);
|
|
1326
1420
|
}
|
|
1327
1421
|
if (installReferences.length > 0) {
|
|
1328
|
-
console.log(
|
|
1422
|
+
console.log(' 참고 문서 :');
|
|
1423
|
+
installReferences.forEach((ref) => {
|
|
1424
|
+
console.log(` - ${ref}`);
|
|
1425
|
+
});
|
|
1329
1426
|
}
|
|
1330
|
-
console.log('
|
|
1331
|
-
|
|
1427
|
+
console.log(' 구성요소 :');
|
|
1428
|
+
tool.components.forEach((component) => {
|
|
1332
1429
|
console.log(
|
|
1333
|
-
`
|
|
1430
|
+
` - ${component.title} (${component.id}) -> ${path.join(
|
|
1334
1431
|
installRoot,
|
|
1335
1432
|
getComponentInstallPath(component)
|
|
1336
1433
|
)}`
|
|
1337
1434
|
);
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1435
|
+
if (component.description) {
|
|
1436
|
+
console.log(` ${component.description}`);
|
|
1437
|
+
}
|
|
1438
|
+
});
|
|
1439
|
+
});
|
|
1341
1440
|
|
|
1342
1441
|
const presets = Array.isArray(catalog.presets) ? catalog.presets : [];
|
|
1343
1442
|
if (presets.length > 0) {
|
|
1344
|
-
console.log('
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1443
|
+
console.log('');
|
|
1444
|
+
console.log('━━━━━━━━ 프리셋 목록 ━━━━━━━━');
|
|
1445
|
+
presets.forEach((preset, index) => {
|
|
1446
|
+
const toolCount = Array.isArray(preset.tools) ? preset.tools.length : 0;
|
|
1447
|
+
console.log(`${index + 1}. ${preset.title} (${preset.id})`);
|
|
1448
|
+
console.log(` 설명 : ${preset.description}`);
|
|
1449
|
+
console.log(` 포함 도구 : ${toolCount}개 (${(preset.tools ?? []).join(', ')})`);
|
|
1450
|
+
});
|
|
1451
|
+
console.log('');
|
|
1452
|
+
console.log('프리셋 사용 예시:');
|
|
1453
|
+
console.log(
|
|
1454
|
+
` ${CLI_NAME} install --preset balanced-core --target /path/to/project --yes --non-interactive`
|
|
1455
|
+
);
|
|
1349
1456
|
console.log('');
|
|
1350
1457
|
}
|
|
1351
1458
|
|
|
1352
|
-
console.log('권장
|
|
1353
|
-
console.log(
|
|
1354
|
-
console.log('2) 설치 후 state.json
|
|
1355
|
-
console.log('3) update 시 필요한 도구만 부분
|
|
1459
|
+
console.log('━━━━━━━━ 권장 흐름 ━━━━━━━━');
|
|
1460
|
+
console.log(`1) pnpm dlx ${CLI_NAME} --interactive`);
|
|
1461
|
+
console.log('2) 설치 후 .tri-agent-manager/state.json 기준으로 update');
|
|
1462
|
+
console.log('3) update 시 필요한 도구만 부분 갱신');
|
|
1356
1463
|
}
|
|
1357
1464
|
|
|
1358
1465
|
async function main() {
|
|
@@ -1427,7 +1534,7 @@ async function main() {
|
|
|
1427
1534
|
})
|
|
1428
1535
|
};
|
|
1429
1536
|
|
|
1430
|
-
printPlan(catalog, selection, command, selection.targetDir);
|
|
1537
|
+
printPlan(catalog, selection, command, selection.targetDir, options.dryRun);
|
|
1431
1538
|
|
|
1432
1539
|
const proceed = await confirmProceed(options.yes);
|
|
1433
1540
|
if (!proceed) {
|
|
@@ -1445,7 +1552,12 @@ async function main() {
|
|
|
1445
1552
|
});
|
|
1446
1553
|
|
|
1447
1554
|
console.log('');
|
|
1448
|
-
|
|
1555
|
+
if (options.dryRun) {
|
|
1556
|
+
console.log('완료: dry-run 계획 확인이 끝났습니다. 실제 반영하려면 --dry-run 없이 다시 실행해 주세요.');
|
|
1557
|
+
} else {
|
|
1558
|
+
console.log('완료: 선택한 운영팩 반영이 끝났습니다.');
|
|
1559
|
+
console.log(`가이드 확인: ${path.join(selection.targetDir, STATE_DIR_NAME, GUIDE_FILE_NAME)}`);
|
|
1560
|
+
}
|
|
1449
1561
|
}
|
|
1450
1562
|
|
|
1451
1563
|
main().catch((error) => {
|