relayax-cli 0.1.6 → 0.1.8

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.
@@ -1,2 +1,22 @@
1
1
  import { Command } from 'commander';
2
+ export interface RequiresCli {
3
+ name: string;
4
+ install?: string;
5
+ }
6
+ export interface RequiresMcp {
7
+ name: string;
8
+ package?: string;
9
+ }
10
+ export interface RequiresEnv {
11
+ name: string;
12
+ optional?: boolean;
13
+ description?: string;
14
+ }
15
+ export interface Requires {
16
+ cli?: RequiresCli[];
17
+ mcp?: RequiresMcp[];
18
+ npm?: string[];
19
+ env?: RequiresEnv[];
20
+ teams?: string[];
21
+ }
2
22
  export declare function registerPublish(program: Command): void;
@@ -7,111 +7,33 @@ exports.registerPublish = registerPublish;
7
7
  const fs_1 = __importDefault(require("fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const os_1 = __importDefault(require("os"));
10
+ const js_yaml_1 = __importDefault(require("js-yaml"));
10
11
  const tar_1 = require("tar");
11
12
  const config_js_1 = require("../lib/config.js");
12
13
  const VALID_DIRS = ['skills', 'agents', 'rules', 'commands'];
13
14
  const IMAGE_EXTS = ['.png', '.jpg', '.jpeg', '.webp'];
14
15
  function parseRelayYaml(content) {
15
- const result = {};
16
- const tags = [];
17
- const portfolio = [];
18
- let inTags = false;
19
- let inPortfolio = false;
20
- let inLongDesc = false;
21
- let longDescLines = [];
22
- let currentPortfolioItem = null;
23
- for (const line of content.split('\n')) {
24
- const trimmed = line.trim();
25
- // long_description multiline (YAML | block)
26
- if (inLongDesc) {
27
- if (line.startsWith(' ') || line.startsWith('\t') || trimmed === '') {
28
- longDescLines.push(line.replace(/^ {2}/, '').replace(/^\t/, ''));
29
- continue;
30
- }
31
- else {
32
- inLongDesc = false;
33
- result.long_description = longDescLines.join('\n').trim();
34
- }
35
- }
36
- // tags list
37
- if (inTags) {
38
- if (trimmed.startsWith('- ')) {
39
- tags.push(trimmed.slice(2).replace(/^["']|["']$/g, ''));
40
- continue;
41
- }
42
- else {
43
- inTags = false;
44
- }
45
- }
46
- // portfolio list
47
- if (inPortfolio) {
48
- if (trimmed.startsWith('- path:')) {
49
- if (currentPortfolioItem?.path) {
50
- portfolio.push({ path: currentPortfolioItem.path, title: currentPortfolioItem.title ?? '', description: currentPortfolioItem.description });
51
- }
52
- currentPortfolioItem = { path: trimmed.slice(8).replace(/^["']|["']$/g, '').trim() };
53
- continue;
54
- }
55
- if (trimmed.startsWith('title:') && currentPortfolioItem) {
56
- currentPortfolioItem.title = trimmed.slice(6).replace(/^["']|["']$/g, '').trim();
57
- continue;
58
- }
59
- if (trimmed.startsWith('description:') && currentPortfolioItem) {
60
- currentPortfolioItem.description = trimmed.slice(12).replace(/^["']|["']$/g, '').trim();
61
- continue;
62
- }
63
- if (!trimmed.startsWith('-') && !trimmed.startsWith('title:') && !trimmed.startsWith('description:') && trimmed !== '') {
64
- // End of portfolio section
65
- if (currentPortfolioItem?.path) {
66
- portfolio.push({ path: currentPortfolioItem.path, title: currentPortfolioItem.title ?? '', description: currentPortfolioItem.description });
67
- }
68
- currentPortfolioItem = null;
69
- inPortfolio = false;
70
- }
71
- else if (trimmed === '') {
72
- continue;
73
- }
74
- }
75
- if (trimmed === 'tags: []') {
76
- result.tags = [];
77
- continue;
78
- }
79
- if (trimmed === 'tags:') {
80
- inTags = true;
81
- continue;
82
- }
83
- if (trimmed === 'portfolio:') {
84
- inPortfolio = true;
85
- continue;
86
- }
87
- if (trimmed === 'portfolio: []') {
88
- continue;
89
- }
90
- if (trimmed === 'long_description: |') {
91
- inLongDesc = true;
92
- longDescLines = [];
93
- continue;
94
- }
95
- const match = trimmed.match(/^(\w+):\s*["']?(.+?)["']?$/);
96
- if (match) {
97
- result[match[1]] = match[2];
98
- }
99
- }
100
- // Flush remaining
101
- if (inLongDesc && longDescLines.length > 0) {
102
- result.long_description = longDescLines.join('\n').trim();
103
- }
104
- if (currentPortfolioItem?.path) {
105
- portfolio.push({ path: currentPortfolioItem.path, title: currentPortfolioItem.title ?? '', description: currentPortfolioItem.description });
106
- }
16
+ const raw = js_yaml_1.default.load(content) ?? {};
17
+ const tags = Array.isArray(raw.tags)
18
+ ? raw.tags.map((t) => String(t))
19
+ : [];
20
+ const portfolio = Array.isArray(raw.portfolio)
21
+ ? raw.portfolio.map((p) => ({
22
+ path: String(p.path ?? ''),
23
+ title: String(p.title ?? ''),
24
+ description: p.description ? String(p.description) : undefined,
25
+ })).filter((p) => p.path)
26
+ : [];
27
+ const requires = raw.requires;
107
28
  return {
108
- name: String(result.name ?? ''),
109
- slug: String(result.slug ?? ''),
110
- description: String(result.description ?? ''),
111
- version: String(result.version ?? '1.0.0'),
112
- long_description: result.long_description,
29
+ name: String(raw.name ?? ''),
30
+ slug: String(raw.slug ?? ''),
31
+ description: String(raw.description ?? ''),
32
+ version: String(raw.version ?? '1.0.0'),
33
+ long_description: raw.long_description ? String(raw.long_description) : undefined,
113
34
  tags,
114
35
  portfolio,
36
+ requires,
115
37
  };
116
38
  }
117
39
  function detectCommands(teamDir) {
@@ -310,6 +232,7 @@ function registerPublish(program) {
310
232
  commands: detectedCommands,
311
233
  components,
312
234
  version: config.version,
235
+ requires: config.requires,
313
236
  };
314
237
  if (!json) {
315
238
  console.error(`패키지 생성 중... (${config.name} v${config.version})`);
@@ -52,22 +52,33 @@ exports.RELAY_COMMANDS = [
52
52
  {
53
53
  id: 'relay-install',
54
54
  description: 'relay 마켓플레이스에서 에이전트 팀을 설치합니다',
55
- body: `요청된 에이전트 팀을 relay 마켓플레이스에서 다운로드하여 현재 프로젝트에 설치합니다.
55
+ body: `요청된 에이전트 팀을 relay 마켓플레이스에서 다운로드하여 현재 프로젝트에 설치하고, 의존성을 확인·설치합니다.
56
56
 
57
57
  ## 실행 방법
58
58
 
59
- 1. \`relay install <slug>\` 명령어를 실행합니다.
60
- 2. 설치 결과를 확인합니다:
61
- - 설치된 파일
62
- - 사용 가능해진 커맨드 목록
63
- 3. 커맨드의 사용법을 간단히 안내합니다.
64
- 4. "바로 사용해볼까요?"라고 제안합니다.
65
- 5. 사용자가 원하면 첫 번째 커맨드를 실행해봅니다.
59
+ ### 1. 설치
60
+ - \`relay install <slug>\` 명령어를 실행합니다.
61
+ - 설치 결과를 확인합니다 (설치된 파일 수, 사용 가능한 커맨드 목록).
62
+
63
+ ### 2. 의존성 확인 설치
64
+ 설치된 팀의 relay.yaml에 \`requires\` 섹션이 있으면 각 항목을 확인하고 처리합니다:
65
+
66
+ - **cli**: \`which <name>\`으로 확인 → 없으면 install 명령 실행 또는 안내
67
+ - **npm**: \`npm list <package>\`로 확인 → 없으면 \`npm install\`
68
+ - **env**: 환경변수 확인 → optional이면 경고, 필수면 설정 안내
69
+ - **mcp**: MCP 서버 설정 안내
70
+ - **teams**: \`relay install <team>\`으로 재귀 설치
71
+
72
+ ### 3. 완료 안내
73
+ - 의존성 결과 요약 ("✓ 확인됨", "⚠ 미설정")
74
+ - 사용 가능한 커맨드 안내
75
+ - "바로 사용해볼까요?" 제안
66
76
 
67
77
  ## 예시
68
78
 
69
79
  사용자: /relay-install contents-team
70
80
  → relay install contents-team 실행
81
+ → requires 확인: ✓ playwright, ✓ sharp 설치됨
71
82
  → "설치 완료! 다음 커맨드를 사용할 수 있습니다:"
72
83
  → /cardnews - 카드뉴스 제작
73
84
  → /detailpage - 상세페이지 제작
@@ -80,12 +91,17 @@ exports.RELAY_COMMANDS = [
80
91
 
81
92
  ## 실행 단계
82
93
 
83
- ### 1. 구조 분석
94
+ ### 1. 인증 확인 (가장 먼저)
95
+ - \`cat ~/.relay/token\` 또는 환경변수 RELAY_TOKEN으로 토큰 존재 여부를 확인합니다.
96
+ - 미인증이면 즉시 안내: "먼저 \`relay login\`으로 로그인이 필요합니다." → 로그인 후 재실행 안내.
97
+ - 인증되어 있으면 다음 단계로 진행합니다.
98
+
99
+ ### 2. 팀 구조 분석
84
100
  - skills/, agents/, rules/, commands/ 디렉토리를 탐색합니다.
85
101
  - 각 파일의 이름과 description을 추출합니다.
86
102
  - relay.yaml이 있으면 읽고, 없으면 사용자에게 팀 정보(name, slug, description, tags)를 물어보고 생성합니다.
87
103
 
88
- ### 2. 포트폴리오 생성
104
+ ### 3. 포트폴리오 생성
89
105
 
90
106
  #### Layer 1: 팀 구성 시각화 (자동)
91
107
  - 분석된 팀 구조를 HTML로 생성합니다. 내용:
@@ -105,18 +121,15 @@ exports.RELAY_COMMANDS = [
105
121
  - 사용자가 포트폴리오에 포함할 항목을 선택합니다.
106
122
  - 선택된 이미지를 ./portfolio/에 저장합니다.
107
123
 
108
- ### 3. 메타데이터 생성
124
+ ### 4. 메타데이터 생성
109
125
  - description: skills 내용 기반으로 자동 생성합니다.
110
126
  - long_description: 팀 소개 마크다운을 자동 생성합니다 (README.md가 있으면 활용).
111
127
  - tags: 팀 특성에 맞는 태그를 추천합니다.
112
128
  - 사용자에게 확인: "이대로 배포할까요?"
113
129
 
114
- ### 4. relay.yaml 업데이트
130
+ ### 5. relay.yaml 업데이트
115
131
  - 생성/수정된 메타데이터와 포트폴리오 경로를 relay.yaml에 반영합니다.
116
132
 
117
- ### 5. 인증 확인
118
- - \`relay login\`으로 인증 상태를 확인합니다. 미인증이면 로그인을 안내합니다.
119
-
120
133
  ### 6. 배포
121
134
  - \`relay publish\` 명령어를 실행합니다.
122
135
  - 배포 결과와 마켓플레이스 URL을 보여줍니다.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relayax-cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "RelayAX Agent Team Marketplace CLI - Install and manage agent teams",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -35,9 +35,11 @@
35
35
  "dependencies": {
36
36
  "@inquirer/prompts": "^8.3.2",
37
37
  "commander": "^13.1.0",
38
+ "js-yaml": "^4.1.1",
38
39
  "tar": "^7.4.0"
39
40
  },
40
41
  "devDependencies": {
42
+ "@types/js-yaml": "^4.0.9",
41
43
  "@types/node": "^20",
42
44
  "typescript": "^5"
43
45
  }