@team-semicolon/semo-cli 3.0.3 → 3.0.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.
Files changed (2) hide show
  1. package/dist/index.js +170 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -403,6 +403,148 @@ async function downloadExtensions(cwd, packages, force) {
403
403
  console.error(chalk_1.default.red(` ${error}`));
404
404
  }
405
405
  }
406
+ // === Orchestrator 병합 파일 생성 ===
407
+ function createMergedOrchestrator(claudeAgentsDir, orchestratorSources) {
408
+ const orchestratorDir = path.join(claudeAgentsDir, "orchestrator");
409
+ fs.mkdirSync(orchestratorDir, { recursive: true });
410
+ // _packages 디렉토리 생성 (원본 참조용)
411
+ const packagesDir = path.join(orchestratorDir, "_packages");
412
+ fs.mkdirSync(packagesDir, { recursive: true });
413
+ // 각 패키지의 orchestrator 내용 수집
414
+ const routingTables = [];
415
+ const availableAgents = [];
416
+ const availableSkills = [];
417
+ const crossPackageRouting = [];
418
+ for (const source of orchestratorSources) {
419
+ const orchestratorMdPath = path.join(source.path, "orchestrator.md");
420
+ if (!fs.existsSync(orchestratorMdPath))
421
+ continue;
422
+ const content = fs.readFileSync(orchestratorMdPath, "utf-8");
423
+ const pkgShortName = source.pkg.replace(/\//g, "-");
424
+ // 원본 파일 복사 (참조용)
425
+ fs.writeFileSync(path.join(packagesDir, `${pkgShortName}.md`), content);
426
+ // Quick Routing Table 추출
427
+ const routingMatch = content.match(/## 🔴 Quick Routing Table[\s\S]*?\n\n([\s\S]*?)(?=\n## |$)/);
428
+ if (routingMatch) {
429
+ routingTables.push(`### ${EXTENSION_PACKAGES[source.pkg]?.name || source.pkg}\n\n${routingMatch[1].trim()}`);
430
+ }
431
+ // Available Agents 추출
432
+ const agentsMatch = content.match(/## Available Agents[\s\S]*?\n\n([\s\S]*?)(?=\n## |$)/);
433
+ if (agentsMatch) {
434
+ availableAgents.push(`### ${EXTENSION_PACKAGES[source.pkg]?.name || source.pkg}\n\n${agentsMatch[1].trim()}`);
435
+ }
436
+ // Available Skills 추출
437
+ const skillsMatch = content.match(/## Available Skills[\s\S]*?\n\n([\s\S]*?)(?=\n## |$)/);
438
+ if (skillsMatch) {
439
+ availableSkills.push(`### ${EXTENSION_PACKAGES[source.pkg]?.name || source.pkg}\n\n${skillsMatch[1].trim()}`);
440
+ }
441
+ // Cross-Package Routing 추출
442
+ const crossMatch = content.match(/## 🔄 Cross-Package Routing[\s\S]*?\n\n([\s\S]*?)(?=\n## |$)/);
443
+ if (crossMatch) {
444
+ crossPackageRouting.push(crossMatch[1].trim());
445
+ }
446
+ // references 폴더가 있으면 복사
447
+ const refsDir = path.join(source.path, "references");
448
+ if (fs.existsSync(refsDir)) {
449
+ const mergedRefsDir = path.join(orchestratorDir, "references");
450
+ fs.mkdirSync(mergedRefsDir, { recursive: true });
451
+ const refs = fs.readdirSync(refsDir);
452
+ for (const ref of refs) {
453
+ const srcRef = path.join(refsDir, ref);
454
+ const destRef = path.join(mergedRefsDir, `${pkgShortName}-${ref}`);
455
+ if (fs.statSync(srcRef).isFile()) {
456
+ fs.copyFileSync(srcRef, destRef);
457
+ }
458
+ }
459
+ }
460
+ }
461
+ // 병합된 orchestrator.md 생성
462
+ const mergedContent = `---
463
+ name: orchestrator
464
+ description: |
465
+ SEMO Merged Orchestrator - Routes all user requests to appropriate agents/skills.
466
+ This orchestrator combines routing tables from ${orchestratorSources.length} packages.
467
+ PROACTIVELY delegate on ALL requests. Never process directly.
468
+ tools:
469
+ - read_file
470
+ - list_dir
471
+ - run_command
472
+ - glob
473
+ - grep
474
+ - task
475
+ - skill
476
+ model: inherit
477
+ ---
478
+
479
+ # SEMO Merged Orchestrator
480
+
481
+ > 이 파일은 **자동 생성**되었습니다. 직접 수정하지 마세요.
482
+ > 원본 파일: \`_packages/\` 디렉토리 참조
483
+
484
+ 모든 사용자 요청을 분석하고 적절한 Agent 또는 Skill로 라우팅하는 **Primary Router**입니다.
485
+
486
+ ## 🔴 설치된 패키지
487
+
488
+ ${orchestratorSources.map(s => `- **${EXTENSION_PACKAGES[s.pkg]?.name || s.pkg}**: \`semo-system/${s.pkg}\``).join("\n")}
489
+
490
+ ## �� Quick Routing Table (Merged)
491
+
492
+ > 키워드 매칭 시 **첫 번째 매칭된 패키지**로 라우팅됩니다.
493
+
494
+ ${routingTables.join("\n\n---\n\n")}
495
+
496
+ ## SEMO 메시지 포맷
497
+
498
+ ### Agent 위임
499
+
500
+ \`\`\`markdown
501
+ [SEMO] Orchestrator: 의도 분석 완료 → {intent_category}
502
+
503
+ [SEMO] Agent 위임: {agent_name} (사유: {reason})
504
+ \`\`\`
505
+
506
+ ### Skill 호출
507
+
508
+ \`\`\`markdown
509
+ [SEMO] Orchestrator: 의도 분석 완료 → {intent_category}
510
+
511
+ [SEMO] Skill 호출: {skill_name}
512
+ \`\`\`
513
+
514
+ ### 라우팅 실패
515
+
516
+ \`\`\`markdown
517
+ [SEMO] Orchestrator: 라우팅 실패 → 적절한 Agent/Skill 없음
518
+
519
+ ⚠️ 직접 처리 필요
520
+ \`\`\`
521
+
522
+ ## Critical Rules
523
+
524
+ 1. **Routing-Only**: 직접 작업 수행 금지
525
+ 2. **SEMO 메시지 필수**: 모든 위임에 SEMO 메시지 포함
526
+ 3. **Package Priority**: 라우팅 충돌 시 설치 순서대로 우선순위 적용
527
+ 4. **Cross-Package**: 다른 패키지 전문 영역 요청 시 인계 권유
528
+
529
+ ${crossPackageRouting.length > 0 ? `## 🔄 Cross-Package Routing
530
+
531
+ ${crossPackageRouting[0]}` : ""}
532
+
533
+ ${availableAgents.length > 0 ? `## Available Agents (All Packages)
534
+
535
+ ${availableAgents.join("\n\n")}` : ""}
536
+
537
+ ${availableSkills.length > 0 ? `## Available Skills (All Packages)
538
+
539
+ ${availableSkills.join("\n\n")}` : ""}
540
+
541
+ ## References
542
+
543
+ - 원본 Orchestrator: \`_packages/\` 디렉토리
544
+ - 병합된 References: \`references/\` 디렉토리
545
+ `;
546
+ fs.writeFileSync(path.join(orchestratorDir, "orchestrator.md"), mergedContent);
547
+ }
406
548
  // === Extensions 심볼릭 링크 설정 (agents/skills 병합) ===
407
549
  async function setupExtensionSymlinks(cwd, packages) {
408
550
  console.log(chalk_1.default.cyan("\n🔗 Extensions 연결"));
@@ -413,12 +555,12 @@ async function setupExtensionSymlinks(cwd, packages) {
413
555
  const claudeSkillsDir = path.join(claudeDir, "skills");
414
556
  fs.mkdirSync(claudeAgentsDir, { recursive: true });
415
557
  fs.mkdirSync(claudeSkillsDir, { recursive: true });
558
+ // Orchestrator 소스 수집 (병합용)
559
+ const orchestratorSources = [];
416
560
  for (const pkg of packages) {
417
561
  const pkgPath = path.join(semoSystemDir, pkg);
418
562
  if (!fs.existsSync(pkgPath))
419
563
  continue;
420
- // Note: .claude/semo-{pkg} 링크는 생성하지 않음 (불필요)
421
- // Extension의 agents/skills만 개별 링크하여 병합
422
564
  // 1. Extension의 agents를 .claude/agents/에 개별 링크
423
565
  const extAgentsDir = path.join(pkgPath, "agents");
424
566
  if (fs.existsSync(extAgentsDir)) {
@@ -426,6 +568,11 @@ async function setupExtensionSymlinks(cwd, packages) {
426
568
  for (const agent of agents) {
427
569
  const agentLink = path.join(claudeAgentsDir, agent);
428
570
  const agentTarget = path.join(extAgentsDir, agent);
571
+ // Orchestrator는 특별 처리 (병합 필요)
572
+ if (agent === "orchestrator") {
573
+ orchestratorSources.push({ pkg, path: agentTarget });
574
+ continue; // 심볼릭 링크 생성 안 함
575
+ }
429
576
  if (!fs.existsSync(agentLink)) {
430
577
  createSymlinkOrJunction(agentTarget, agentLink);
431
578
  console.log(chalk_1.default.green(` ✓ .claude/agents/${agent} → semo-system/${pkg}/agents/${agent}`));
@@ -446,6 +593,27 @@ async function setupExtensionSymlinks(cwd, packages) {
446
593
  }
447
594
  }
448
595
  }
596
+ // 3. Orchestrator 병합 처리
597
+ if (orchestratorSources.length > 0) {
598
+ // 기존 orchestrator 링크/디렉토리 제거
599
+ const orchestratorPath = path.join(claudeAgentsDir, "orchestrator");
600
+ if (fs.existsSync(orchestratorPath)) {
601
+ removeRecursive(orchestratorPath);
602
+ }
603
+ if (orchestratorSources.length === 1) {
604
+ // 단일 패키지: 심볼릭 링크
605
+ createSymlinkOrJunction(orchestratorSources[0].path, orchestratorPath);
606
+ console.log(chalk_1.default.green(` ✓ .claude/agents/orchestrator → semo-system/${orchestratorSources[0].pkg}/agents/orchestrator`));
607
+ }
608
+ else {
609
+ // 다중 패키지: 병합 파일 생성
610
+ createMergedOrchestrator(claudeAgentsDir, orchestratorSources);
611
+ console.log(chalk_1.default.green(` ✓ .claude/agents/orchestrator (${orchestratorSources.length}개 패키지 병합)`));
612
+ for (const source of orchestratorSources) {
613
+ console.log(chalk_1.default.gray(` - semo-system/${source.pkg}/agents/orchestrator`));
614
+ }
615
+ }
616
+ }
449
617
  }
450
618
  const BASE_MCP_SERVERS = [
451
619
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-semicolon/semo-cli",
3
- "version": "3.0.3",
3
+ "version": "3.0.4",
4
4
  "description": "SEMO CLI - AI Agent Orchestration Framework Installer",
5
5
  "main": "dist/index.js",
6
6
  "bin": {