@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.
Files changed (2) hide show
  1. package/dist/index.js +232 -73
  2. 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.14";
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
- if (hasSemoSystem) {
160
- // semo-core semo-system 바깥에 있음
161
- const corePath = path.join(cwd, "semo-core", "VERSION");
162
- const localCore = fs.existsSync(corePath) ? fs.readFileSync(corePath, "utf-8").trim() : null;
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
- if (localCore) {
165
- versionInfos.push({
166
- name: "semo-core",
167
- local: localCore,
168
- remote: remoteCore,
169
- needsUpdate: remoteCore ? isVersionLower(localCore, remoteCore) : false,
170
- });
171
- }
172
- // semo-skills
173
- const skillsPath = path.join(cwd, "semo-skills", "VERSION");
174
- const localSkills = fs.existsSync(skillsPath) ? fs.readFileSync(skillsPath, "utf-8").trim() : null;
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
- if (localSkills) {
177
- versionInfos.push({
178
- name: "semo-skills",
179
- local: localSkills,
180
- remote: remoteSkills,
181
- needsUpdate: remoteSkills ? isVersionLower(localSkills, remoteSkills) : false,
182
- });
183
- }
184
- // Extensions (semo-system 내부)
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
- console.log(chalk_1.default.cyan.bold("\n📦 SEMO CLI 버전 정보\n"));
403
- // 현재 버전 표시
404
- console.log(chalk_1.default.white(` 현재 버전: ${chalk_1.default.green.bold(VERSION)}`));
405
- // 최신 버전 확인
406
- const spinner = (0, ora_1.default)(" 최신 버전 확인 중...").start();
407
- const latestVersion = await getLatestVersion();
408
- if (latestVersion === null) {
409
- spinner.warn(" 최신 버전 확인 실패 (네트워크 오류)");
410
- console.log(chalk_1.default.gray(" npm registry에 접속할 수 없습니다.\n"));
411
- return;
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
- spinner.stop();
414
- console.log(chalk_1.default.white(` 최신 버전: ${chalk_1.default.blue.bold(latestVersion)}`));
415
- // 버전 비교 업데이트 권유
416
- if (isVersionLower(VERSION, latestVersion)) {
417
- console.log();
418
- console.log(chalk_1.default.yellow.bold(" ⚠️ 새로운 버전이 있습니다!"));
419
- console.log();
420
- console.log(chalk_1.default.white(" 업데이트 방법:"));
421
- console.log(chalk_1.default.cyan(` npm update -g ${PACKAGE_NAME}`));
422
- console.log();
423
- console.log(chalk_1.default.gray(" 또는 프로젝트 내 SEMO 업데이트:"));
424
- console.log(chalk_1.default.gray(" semo update"));
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
- console.log();
428
- console.log(chalk_1.default.green(" ✓ 최신 버전을 사용 중입니다."));
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. [SEMO] Orchestrator 메시지 출력 (의도 분석)
1773
- 3. Orchestrator가 적절한 Agent/Skill 라우팅
1774
- 4. [SEMO] Agent/Skill 메시지 출력
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
- **반드시 읽어야 할 파일**: \`semo-system/semo-core/agents/orchestrator/orchestrator.md\`
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-semicolon/semo-cli",
3
- "version": "3.0.16",
3
+ "version": "3.0.18",
4
4
  "description": "SEMO CLI - AI Agent Orchestration Framework Installer",
5
5
  "main": "dist/index.js",
6
6
  "bin": {