@team-semicolon/semo-cli 3.0.16 → 3.0.18
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 +232 -73
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -59,7 +59,7 @@ const child_process_1 = require("child_process");
|
|
|
59
59
|
const fs = __importStar(require("fs"));
|
|
60
60
|
const path = __importStar(require("path"));
|
|
61
61
|
const os = __importStar(require("os"));
|
|
62
|
-
const VERSION = "3.0.
|
|
62
|
+
const VERSION = "3.0.17";
|
|
63
63
|
const PACKAGE_NAME = "@team-semicolon/semo-cli";
|
|
64
64
|
// === 버전 비교 유틸리티 ===
|
|
65
65
|
/**
|
|
@@ -156,32 +156,36 @@ async function showVersionComparison(cwd) {
|
|
|
156
156
|
remote: latestCliVersion,
|
|
157
157
|
needsUpdate: latestCliVersion ? isVersionLower(currentCliVersion, latestCliVersion) : false,
|
|
158
158
|
});
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
159
|
+
// semo-core (루트 또는 semo-system 내부)
|
|
160
|
+
const corePathRoot = path.join(cwd, "semo-core", "VERSION");
|
|
161
|
+
const corePathSystem = path.join(semoSystemDir, "semo-core", "VERSION");
|
|
162
|
+
const corePath = fs.existsSync(corePathRoot) ? corePathRoot : corePathSystem;
|
|
163
|
+
if (fs.existsSync(corePath)) {
|
|
164
|
+
const localCore = fs.readFileSync(corePath, "utf-8").trim();
|
|
163
165
|
const remoteCore = await getRemoteCoreVersion("semo-core");
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
166
|
+
versionInfos.push({
|
|
167
|
+
name: "semo-core",
|
|
168
|
+
local: localCore,
|
|
169
|
+
remote: remoteCore,
|
|
170
|
+
needsUpdate: remoteCore ? isVersionLower(localCore, remoteCore) : false,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
// semo-skills (루트 또는 semo-system 내부)
|
|
174
|
+
const skillsPathRoot = path.join(cwd, "semo-skills", "VERSION");
|
|
175
|
+
const skillsPathSystem = path.join(semoSystemDir, "semo-skills", "VERSION");
|
|
176
|
+
const skillsPath = fs.existsSync(skillsPathRoot) ? skillsPathRoot : skillsPathSystem;
|
|
177
|
+
if (fs.existsSync(skillsPath)) {
|
|
178
|
+
const localSkills = fs.readFileSync(skillsPath, "utf-8").trim();
|
|
175
179
|
const remoteSkills = await getRemoteCoreVersion("semo-skills");
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
180
|
+
versionInfos.push({
|
|
181
|
+
name: "semo-skills",
|
|
182
|
+
local: localSkills,
|
|
183
|
+
remote: remoteSkills,
|
|
184
|
+
needsUpdate: remoteSkills ? isVersionLower(localSkills, remoteSkills) : false,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
// Extensions (semo-system 내부)
|
|
188
|
+
if (hasSemoSystem) {
|
|
185
189
|
for (const key of Object.keys(EXTENSION_PACKAGES)) {
|
|
186
190
|
const extVersionPath = path.join(semoSystemDir, key, "VERSION");
|
|
187
191
|
if (fs.existsSync(extVersionPath)) {
|
|
@@ -196,6 +200,39 @@ async function showVersionComparison(cwd) {
|
|
|
196
200
|
}
|
|
197
201
|
}
|
|
198
202
|
}
|
|
203
|
+
// packages/ 디렉토리의 설치된 패키지들 (로컬 버전만 표시)
|
|
204
|
+
const packagesDir = path.join(cwd, "packages");
|
|
205
|
+
if (fs.existsSync(packagesDir)) {
|
|
206
|
+
// 패키지 경로 매핑 (표시 이름 → 상대 경로)
|
|
207
|
+
const packagePaths = {
|
|
208
|
+
"packages/core": "core",
|
|
209
|
+
"packages/meta": "meta",
|
|
210
|
+
"packages/eng/nextjs": "eng/nextjs",
|
|
211
|
+
"packages/eng/spring": "eng/spring",
|
|
212
|
+
"packages/eng/ms": "eng/ms",
|
|
213
|
+
"packages/eng/infra": "eng/infra",
|
|
214
|
+
"packages/biz/discovery": "biz/discovery",
|
|
215
|
+
"packages/biz/management": "biz/management",
|
|
216
|
+
"packages/biz/design": "biz/design",
|
|
217
|
+
"packages/biz/poc": "biz/poc",
|
|
218
|
+
"packages/ops/qa": "ops/qa",
|
|
219
|
+
"packages/ops/monitor": "ops/monitor",
|
|
220
|
+
"packages/ops/improve": "ops/improve",
|
|
221
|
+
};
|
|
222
|
+
for (const [displayName, relativePath] of Object.entries(packagePaths)) {
|
|
223
|
+
const pkgVersionPath = path.join(packagesDir, relativePath, "VERSION");
|
|
224
|
+
if (fs.existsSync(pkgVersionPath)) {
|
|
225
|
+
const localPkg = fs.readFileSync(pkgVersionPath, "utf-8").trim();
|
|
226
|
+
const remotePkg = await getRemotePackageVersion(`packages/${relativePath}`);
|
|
227
|
+
versionInfos.push({
|
|
228
|
+
name: displayName,
|
|
229
|
+
local: localPkg,
|
|
230
|
+
remote: remotePkg,
|
|
231
|
+
needsUpdate: remotePkg ? isVersionLower(localPkg, remotePkg) : false,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
199
236
|
spinner.stop();
|
|
200
237
|
// 결과 출력
|
|
201
238
|
const needsUpdateCount = versionInfos.filter(v => v.needsUpdate).length;
|
|
@@ -399,33 +436,144 @@ program
|
|
|
399
436
|
* 상세 버전 정보 표시 및 업데이트 확인
|
|
400
437
|
*/
|
|
401
438
|
async function showVersionInfo() {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
//
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
439
|
+
const cwd = process.cwd();
|
|
440
|
+
console.log(chalk_1.default.cyan.bold("\n📦 SEMO 버전 정보\n"));
|
|
441
|
+
const versionInfos = [];
|
|
442
|
+
// 1. CLI 버전
|
|
443
|
+
const latestCliVersion = await getLatestVersion();
|
|
444
|
+
versionInfos.push({
|
|
445
|
+
name: "semo-cli",
|
|
446
|
+
local: VERSION,
|
|
447
|
+
remote: latestCliVersion,
|
|
448
|
+
needsUpdate: latestCliVersion ? isVersionLower(VERSION, latestCliVersion) : false,
|
|
449
|
+
});
|
|
450
|
+
// 2. semo-core 버전 (루트 또는 semo-system 내부)
|
|
451
|
+
const corePathRoot = path.join(cwd, "semo-core", "VERSION");
|
|
452
|
+
const corePathSystem = path.join(cwd, "semo-system", "semo-core", "VERSION");
|
|
453
|
+
const corePath = fs.existsSync(corePathRoot) ? corePathRoot : corePathSystem;
|
|
454
|
+
if (fs.existsSync(corePath)) {
|
|
455
|
+
const localCore = fs.readFileSync(corePath, "utf-8").trim();
|
|
456
|
+
const remoteCore = await getRemoteCoreVersion("semo-core");
|
|
457
|
+
versionInfos.push({
|
|
458
|
+
name: "semo-core",
|
|
459
|
+
local: localCore,
|
|
460
|
+
remote: remoteCore,
|
|
461
|
+
needsUpdate: remoteCore ? isVersionLower(localCore, remoteCore) : false,
|
|
462
|
+
});
|
|
412
463
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
464
|
+
// 3. semo-skills 버전 (루트 또는 semo-system 내부)
|
|
465
|
+
const skillsPathRoot = path.join(cwd, "semo-skills", "VERSION");
|
|
466
|
+
const skillsPathSystem = path.join(cwd, "semo-system", "semo-skills", "VERSION");
|
|
467
|
+
const skillsPath = fs.existsSync(skillsPathRoot) ? skillsPathRoot : skillsPathSystem;
|
|
468
|
+
if (fs.existsSync(skillsPath)) {
|
|
469
|
+
const localSkills = fs.readFileSync(skillsPath, "utf-8").trim();
|
|
470
|
+
const remoteSkills = await getRemoteCoreVersion("semo-skills");
|
|
471
|
+
versionInfos.push({
|
|
472
|
+
name: "semo-skills",
|
|
473
|
+
local: localSkills,
|
|
474
|
+
remote: remoteSkills,
|
|
475
|
+
needsUpdate: remoteSkills ? isVersionLower(localSkills, remoteSkills) : false,
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
// 4. Extension 패키지들 (semo-system 내부)
|
|
479
|
+
const semoSystemDir = path.join(cwd, "semo-system");
|
|
480
|
+
if (fs.existsSync(semoSystemDir)) {
|
|
481
|
+
for (const key of Object.keys(EXTENSION_PACKAGES)) {
|
|
482
|
+
const extVersionPath = path.join(semoSystemDir, key, "VERSION");
|
|
483
|
+
if (fs.existsSync(extVersionPath)) {
|
|
484
|
+
const localExt = fs.readFileSync(extVersionPath, "utf-8").trim();
|
|
485
|
+
const remoteExt = await getRemotePackageVersion(key);
|
|
486
|
+
versionInfos.push({
|
|
487
|
+
name: key,
|
|
488
|
+
local: localExt,
|
|
489
|
+
remote: remoteExt,
|
|
490
|
+
needsUpdate: remoteExt ? isVersionLower(localExt, remoteExt) : false,
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
// 5. packages/ 디렉토리의 설치된 패키지들
|
|
496
|
+
const packagesDir = path.join(cwd, "packages");
|
|
497
|
+
if (fs.existsSync(packagesDir)) {
|
|
498
|
+
const packagePaths = {
|
|
499
|
+
"packages/core": "core",
|
|
500
|
+
"packages/meta": "meta",
|
|
501
|
+
"packages/eng/nextjs": "eng/nextjs",
|
|
502
|
+
"packages/eng/spring": "eng/spring",
|
|
503
|
+
"packages/eng/ms": "eng/ms",
|
|
504
|
+
"packages/eng/infra": "eng/infra",
|
|
505
|
+
"packages/biz/discovery": "biz/discovery",
|
|
506
|
+
"packages/biz/management": "biz/management",
|
|
507
|
+
"packages/biz/design": "biz/design",
|
|
508
|
+
"packages/biz/poc": "biz/poc",
|
|
509
|
+
"packages/ops/qa": "ops/qa",
|
|
510
|
+
"packages/ops/monitor": "ops/monitor",
|
|
511
|
+
"packages/ops/improve": "ops/improve",
|
|
512
|
+
};
|
|
513
|
+
for (const [displayName, relativePath] of Object.entries(packagePaths)) {
|
|
514
|
+
const pkgVersionPath = path.join(packagesDir, relativePath, "VERSION");
|
|
515
|
+
if (fs.existsSync(pkgVersionPath)) {
|
|
516
|
+
const localPkg = fs.readFileSync(pkgVersionPath, "utf-8").trim();
|
|
517
|
+
const remotePkg = await getRemotePackageVersion(`packages/${relativePath}`);
|
|
518
|
+
versionInfos.push({
|
|
519
|
+
name: displayName,
|
|
520
|
+
local: localPkg,
|
|
521
|
+
remote: remotePkg,
|
|
522
|
+
needsUpdate: remotePkg ? isVersionLower(localPkg, remotePkg) : false,
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
// 결과 출력
|
|
528
|
+
const needsUpdateCount = versionInfos.filter(v => v.needsUpdate).length;
|
|
529
|
+
if (versionInfos.length === 1) {
|
|
530
|
+
// CLI만 있는 경우 (SEMO 미설치)
|
|
531
|
+
const cli = versionInfos[0];
|
|
532
|
+
console.log(chalk_1.default.white(` semo-cli: ${chalk_1.default.green.bold(cli.local)}`));
|
|
533
|
+
if (cli.remote) {
|
|
534
|
+
console.log(chalk_1.default.gray(` (최신: ${cli.remote})`));
|
|
535
|
+
}
|
|
536
|
+
if (cli.needsUpdate) {
|
|
537
|
+
console.log();
|
|
538
|
+
console.log(chalk_1.default.yellow.bold(" ⚠️ CLI 업데이트 가능"));
|
|
539
|
+
console.log(chalk_1.default.cyan(` npm update -g ${PACKAGE_NAME}`));
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
console.log();
|
|
543
|
+
console.log(chalk_1.default.green(" ✓ 최신 버전"));
|
|
544
|
+
}
|
|
425
545
|
}
|
|
426
546
|
else {
|
|
427
|
-
|
|
428
|
-
console.log(chalk_1.default.
|
|
547
|
+
// 테이블 형식으로 출력
|
|
548
|
+
console.log(chalk_1.default.gray(" ┌────────────────────────┬──────────┬──────────┬────────┐"));
|
|
549
|
+
console.log(chalk_1.default.gray(" │ 패키지 │ 설치됨 │ 최신 │ 상태 │"));
|
|
550
|
+
console.log(chalk_1.default.gray(" ├────────────────────────┼──────────┼──────────┼────────┤"));
|
|
551
|
+
for (const info of versionInfos) {
|
|
552
|
+
const name = info.name.padEnd(22);
|
|
553
|
+
const local = (info.local || "-").padEnd(8);
|
|
554
|
+
const remote = (info.remote || "-").padEnd(8);
|
|
555
|
+
const status = info.needsUpdate ? "⬆ 업데이트" : "✓ 최신 ";
|
|
556
|
+
const statusColor = info.needsUpdate ? chalk_1.default.yellow : chalk_1.default.green;
|
|
557
|
+
console.log(chalk_1.default.gray(" │ ") +
|
|
558
|
+
chalk_1.default.white(name) +
|
|
559
|
+
chalk_1.default.gray(" │ ") +
|
|
560
|
+
chalk_1.default.green(local) +
|
|
561
|
+
chalk_1.default.gray(" │ ") +
|
|
562
|
+
chalk_1.default.blue(remote) +
|
|
563
|
+
chalk_1.default.gray(" │ ") +
|
|
564
|
+
statusColor(status) +
|
|
565
|
+
chalk_1.default.gray(" │"));
|
|
566
|
+
}
|
|
567
|
+
console.log(chalk_1.default.gray(" └────────────────────────┴──────────┴──────────┴────────┘"));
|
|
568
|
+
if (needsUpdateCount > 0) {
|
|
569
|
+
console.log();
|
|
570
|
+
console.log(chalk_1.default.yellow.bold(` ⚠️ ${needsUpdateCount}개 패키지 업데이트 가능`));
|
|
571
|
+
console.log(chalk_1.default.gray(" semo update 명령으로 업데이트하세요."));
|
|
572
|
+
}
|
|
573
|
+
else {
|
|
574
|
+
console.log();
|
|
575
|
+
console.log(chalk_1.default.green(" ✓ 모든 패키지가 최신 버전입니다."));
|
|
576
|
+
}
|
|
429
577
|
}
|
|
430
578
|
console.log();
|
|
431
579
|
}
|
|
@@ -1755,6 +1903,35 @@ async function setupClaudeMd(cwd, extensions, force) {
|
|
|
1755
1903
|
console.log(chalk_1.default.gray(` + ${pkg}/CLAUDE.md 병합됨`));
|
|
1756
1904
|
}
|
|
1757
1905
|
}
|
|
1906
|
+
// 4. Orchestrator 참조 경로 결정 (Extension 패키지 우선)
|
|
1907
|
+
// Extension 패키지 중 orchestrator가 있는 첫 번째 패키지를 Primary로 설정
|
|
1908
|
+
let primaryOrchestratorPath = "semo-core/agents/orchestrator/orchestrator.md";
|
|
1909
|
+
const orchestratorPaths = [];
|
|
1910
|
+
for (const pkg of extensions) {
|
|
1911
|
+
const pkgOrchestratorPath = path.join(semoSystemDir, pkg, "agents/orchestrator/orchestrator.md");
|
|
1912
|
+
if (fs.existsSync(pkgOrchestratorPath)) {
|
|
1913
|
+
orchestratorPaths.push(`semo-system/${pkg}/agents/orchestrator/orchestrator.md`);
|
|
1914
|
+
// 첫 번째 Extension 패키지의 orchestrator를 Primary로 설정
|
|
1915
|
+
if (primaryOrchestratorPath === "semo-core/agents/orchestrator/orchestrator.md") {
|
|
1916
|
+
primaryOrchestratorPath = `${pkg}/agents/orchestrator/orchestrator.md`;
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
// semo-core orchestrator는 항상 포함
|
|
1921
|
+
orchestratorPaths.unshift("semo-system/semo-core/agents/orchestrator/orchestrator.md");
|
|
1922
|
+
// Orchestrator 참조 섹션 생성
|
|
1923
|
+
const orchestratorRefSection = orchestratorPaths.length > 1
|
|
1924
|
+
? `**Primary Orchestrator**: \`semo-system/${primaryOrchestratorPath}\`
|
|
1925
|
+
|
|
1926
|
+
> Extension 패키지가 설치되어 해당 패키지의 Orchestrator를 우선 참조합니다.
|
|
1927
|
+
|
|
1928
|
+
**모든 Orchestrator 파일** (라우팅 테이블 병합됨):
|
|
1929
|
+
${orchestratorPaths.map(p => `- \`${p}\``).join("\n")}
|
|
1930
|
+
|
|
1931
|
+
이 파일들에서 라우팅 테이블, 의도 분류, 메시지 포맷을 확인하세요.`
|
|
1932
|
+
: `**반드시 읽어야 할 파일**: \`semo-system/semo-core/agents/orchestrator/orchestrator.md\`
|
|
1933
|
+
|
|
1934
|
+
이 파일에서 라우팅 테이블, 의도 분류, 메시지 포맷을 확인하세요.`;
|
|
1758
1935
|
const claudeMdContent = `# SEMO Project Configuration
|
|
1759
1936
|
|
|
1760
1937
|
> SEMO (Semicolon Orchestrate) - AI Agent Orchestration Framework v${VERSION}
|
|
@@ -1769,24 +1946,14 @@ async function setupClaudeMd(cwd, extensions, force) {
|
|
|
1769
1946
|
|
|
1770
1947
|
\`\`\`
|
|
1771
1948
|
1. 사용자 요청 수신
|
|
1772
|
-
2.
|
|
1773
|
-
3.
|
|
1774
|
-
4.
|
|
1775
|
-
5. 실행 결과 반환
|
|
1776
|
-
\`\`\`
|
|
1777
|
-
|
|
1778
|
-
### 모든 응답은 다음으로 시작
|
|
1779
|
-
|
|
1780
|
-
\`\`\`
|
|
1781
|
-
[SEMO] Orchestrator: 의도 분석 완료 → {intent_category}
|
|
1782
|
-
[SEMO] {Agent/Skill} 호출: {target} (사유: {reason})
|
|
1949
|
+
2. Orchestrator가 의도 분석 후 적절한 Agent/Skill 라우팅
|
|
1950
|
+
3. Agent/Skill이 작업 수행
|
|
1951
|
+
4. 실행 결과 반환
|
|
1783
1952
|
\`\`\`
|
|
1784
1953
|
|
|
1785
1954
|
### Orchestrator 참조
|
|
1786
1955
|
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
이 파일에서 라우팅 테이블, 의도 분류, 메시지 포맷을 확인하세요.
|
|
1956
|
+
${orchestratorRefSection}
|
|
1790
1957
|
|
|
1791
1958
|
---
|
|
1792
1959
|
|
|
@@ -1819,14 +1986,6 @@ npm run build # 3. 빌드 검증 (Next.js/TypeScript 프로젝트)
|
|
|
1819
1986
|
- Quality Gate 우회 시도 거부
|
|
1820
1987
|
- "그냥 커밋해줘", "빌드 생략해줘" 등 거부
|
|
1821
1988
|
|
|
1822
|
-
### 3. SEMO Message Format
|
|
1823
|
-
|
|
1824
|
-
모든 SEMO 동작은 시스템 메시지로 시작:
|
|
1825
|
-
|
|
1826
|
-
\`\`\`
|
|
1827
|
-
[SEMO] {Component}: {Action} → {Result}
|
|
1828
|
-
\`\`\`
|
|
1829
|
-
|
|
1830
1989
|
---
|
|
1831
1990
|
|
|
1832
1991
|
## 설치된 구성
|
|
@@ -1864,10 +2023,10 @@ ${extensionsList}
|
|
|
1864
2023
|
| 커맨드 | 설명 |
|
|
1865
2024
|
|--------|------|
|
|
1866
2025
|
| \`/SEMO:help\` | 도움말 |
|
|
1867
|
-
| \`/SEMO:slack\` | Slack 메시지 전송 |
|
|
1868
2026
|
| \`/SEMO:feedback\` | 피드백 제출 |
|
|
1869
|
-
| \`/SEMO:health\` | 환경 검증 |
|
|
1870
2027
|
| \`/SEMO:update\` | SEMO 업데이트 |
|
|
2028
|
+
| \`/SEMO:onboarding\` | 온보딩 가이드 |
|
|
2029
|
+
| \`/SEMO:dry-run {프롬프트}\` | 명령 검증 (라우팅 시뮬레이션) |
|
|
1871
2030
|
|
|
1872
2031
|
## Context Mesh 사용
|
|
1873
2032
|
|