relayax-cli 0.2.41 → 0.3.42
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/commands/access.js +12 -12
- package/dist/commands/changelog.js +2 -2
- package/dist/commands/check-update.js +12 -12
- package/dist/commands/create.js +46 -19
- package/dist/commands/deploy-record.js +2 -2
- package/dist/commands/diff.d.ts +2 -0
- package/dist/commands/diff.js +72 -0
- package/dist/commands/grant.d.ts +33 -0
- package/dist/commands/grant.js +190 -0
- package/dist/commands/init.js +10 -10
- package/dist/commands/install.js +125 -256
- package/dist/commands/join.d.ts +3 -2
- package/dist/commands/join.js +18 -69
- package/dist/commands/list.js +23 -26
- package/dist/commands/login.js +10 -3
- package/dist/commands/orgs.d.ts +10 -0
- package/dist/commands/orgs.js +128 -0
- package/dist/commands/outdated.js +7 -7
- package/dist/commands/package.d.ts +18 -0
- package/dist/commands/package.js +355 -146
- package/dist/commands/ping.js +5 -5
- package/dist/commands/publish.d.ts +1 -1
- package/dist/commands/publish.js +105 -103
- package/dist/commands/search.js +2 -2
- package/dist/commands/status.js +11 -11
- package/dist/commands/uninstall.js +7 -7
- package/dist/commands/update.js +22 -22
- package/dist/commands/versions.d.ts +2 -0
- package/dist/commands/versions.js +44 -0
- package/dist/index.js +8 -2
- package/dist/lib/ai-tools.d.ts +15 -0
- package/dist/lib/ai-tools.js +48 -1
- package/dist/lib/api.d.ts +13 -12
- package/dist/lib/api.js +24 -39
- package/dist/lib/command-adapter.js +41 -693
- package/dist/lib/config.d.ts +10 -5
- package/dist/lib/config.js +106 -24
- package/dist/lib/guide.js +34 -79
- package/dist/lib/installer.d.ts +2 -2
- package/dist/lib/installer.js +4 -4
- package/dist/lib/preamble.d.ts +4 -4
- package/dist/lib/preamble.js +14 -15
- package/dist/lib/slug.d.ts +5 -1
- package/dist/lib/slug.js +52 -9
- package/dist/lib/update-cache.js +4 -4
- package/dist/lib/version-check.d.ts +3 -3
- package/dist/lib/version-check.js +13 -13
- package/dist/prompts/_business-card.md +41 -0
- package/dist/prompts/_error-handling.md +38 -0
- package/dist/prompts/_requirements-check.md +59 -0
- package/dist/prompts/_setup-cli.md +19 -0
- package/dist/prompts/_setup-login.md +7 -0
- package/dist/prompts/_setup-org.md +27 -0
- package/dist/prompts/business-card.md +41 -0
- package/dist/prompts/error-handling.md +38 -0
- package/dist/prompts/index.d.ts +7 -0
- package/dist/prompts/index.js +28 -0
- package/dist/prompts/install.md +187 -0
- package/dist/prompts/publish.md +444 -0
- package/dist/prompts/requirements-check.md +59 -0
- package/dist/types.d.ts +10 -10
- package/package.json +3 -3
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
현재 디렉토리의 에이전트(.relay/)를 분석하고, 보안 점검 및 requirements를 구성한 뒤, 사용가이드를 생성하고 relay에 배포합니다.
|
|
2
|
+
|
|
3
|
+
## 사전 준비
|
|
4
|
+
|
|
5
|
+
### 0-1. 인증 확인
|
|
6
|
+
|
|
7
|
+
- `relay status --json` 명령어를 실행하여 로그인 상태를 확인합니다.
|
|
8
|
+
- 인증되어 있으면 다음 단계로 진행합니다.
|
|
9
|
+
- 미인증이면 바로 로그인을 진행합니다:
|
|
10
|
+
1. `relay login` 실행 (timeout 300초)
|
|
11
|
+
- 브라우저가 자동으로 열리고, 사용자가 로그인을 완료하면 토큰이 자동 저장됩니다.
|
|
12
|
+
2. 완료 후 `relay status --json`으로 로그인 성공을 확인합니다.
|
|
13
|
+
|
|
14
|
+
### 0-2. 소스 패키징 (콘텐츠 선택 → .relay/)
|
|
15
|
+
|
|
16
|
+
`relay package` CLI 명령을 사용하여 소스의 콘텐츠를 .relay/로 동기화합니다.
|
|
17
|
+
소스 탐색과 파일 비교는 CLI가 결정적으로 처리하고, 에이전트는 결과를 사용자에게 보여주고 흐름을 조율합니다.
|
|
18
|
+
|
|
19
|
+
**핵심 원칙:**
|
|
20
|
+
- `.relay/`는 배포 산출물이지, 작업 공간이 아닙니다. 사용자의 작업 공간은 소스 디렉토리(로컬/글로벌)입니다.
|
|
21
|
+
- 로컬 소스와 글로벌 소스를 동일하게 취급합니다. 구분은 내부 경로로만 처리합니다.
|
|
22
|
+
- 소스 디렉토리 통째가 아닌 개별 스킬/에이전트를 체리픽하여 패키지에 포함합니다.
|
|
23
|
+
- relay.yaml의 `contents[]` 매니페스트로 "뭘 어디서 가져왔나"를 추적합니다.
|
|
24
|
+
|
|
25
|
+
#### A. 최초 배포 (.relay/relay.yaml이 없음)
|
|
26
|
+
|
|
27
|
+
##### 1단계: 소스 탐색
|
|
28
|
+
|
|
29
|
+
`relay package --init --json` 실행
|
|
30
|
+
- CLI가 프로젝트 로컬(.claude/, .codex/ 등)과 글로벌 홈(~/.claude/, ~/.codex/ 등)을 모두 스캔합니다.
|
|
31
|
+
- 각 소스의 skills/, agents/, commands/, rules/ 내 개별 항목 목록을 반환합니다.
|
|
32
|
+
- 동시에 `~/.relay/agents/`에 기존 글로벌 에이전트 패키지가 있는지도 확인합니다.
|
|
33
|
+
- JSON 결과:
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"status": "init_required",
|
|
37
|
+
"sources": [
|
|
38
|
+
{
|
|
39
|
+
"path": ".claude",
|
|
40
|
+
"location": "local",
|
|
41
|
+
"name": "Claude Code",
|
|
42
|
+
"items": [
|
|
43
|
+
{ "name": "code-review", "type": "skill", "relativePath": "skills/code-review" },
|
|
44
|
+
{ "name": "deploy", "type": "command", "relativePath": "commands/deploy.md" }
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"path": "~/.claude",
|
|
49
|
+
"location": "global",
|
|
50
|
+
"name": "Claude Code (global)",
|
|
51
|
+
"items": [
|
|
52
|
+
{ "name": "qa-testing", "type": "skill", "relativePath": "skills/qa-testing" },
|
|
53
|
+
{ "name": "dev-lead", "type": "agent", "relativePath": "agents/dev-lead.md" }
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"existing_agents": []
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
- 아래 케이스로 분기합니다:
|
|
62
|
+
|
|
63
|
+
| sources | existing_agents | 동작 |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| 항목 있음 | 없음 | 콘텐츠 선택 → 패키징 (1-b단계) |
|
|
66
|
+
| 항목 있음 | 있음 | 기존 에이전트 재배포 또는 새 에이전트 생성 선택 |
|
|
67
|
+
| 항목 없음 | 있음 | 기존 에이전트 재배포 선택 |
|
|
68
|
+
| 항목 없음 | 없음 | "배포 가능한 에이전트 콘텐츠가 없습니다." 안내 후 중단 |
|
|
69
|
+
|
|
70
|
+
**기존 글로벌 에이전트가 있을 때:**
|
|
71
|
+
|
|
72
|
+
**AskUserQuestion 호출:**
|
|
73
|
+
- question: "기존 에이전트를 발견했습니다. 어떤 작업을 할까요?"
|
|
74
|
+
- options: `["<name> (v<version>) — 재배포", ..., "새 에이전트 만들기"]`
|
|
75
|
+
- 재배포 선택 시 → B. 재배포 플로우로 이동 (해당 에이전트의 relay.yaml 경로 사용)
|
|
76
|
+
- 새 에이전트 선택 시 → 아래 1-b단계로 진행
|
|
77
|
+
|
|
78
|
+
##### 1-b단계: 콘텐츠 선택
|
|
79
|
+
|
|
80
|
+
`sources[]`의 모든 항목을 사용자에게 표시하고, 패키지에 포함할 콘텐츠를 선택받습니다.
|
|
81
|
+
각 항목의 SKILL.md, 에이전트 파일 등의 **내용을 직접 읽어** 기능을 파악한 후 설명과 함께 표시합니다.
|
|
82
|
+
|
|
83
|
+
**AskUserQuestion 호출:**
|
|
84
|
+
- question: "배포할 콘텐츠를 선택하세요"
|
|
85
|
+
- options: 모든 소스의 항목을 기능 설명과 함께 나열
|
|
86
|
+
- 예: `["code-review — 코드 리뷰 자동화 (로컬)", "qa-testing — QA 테스트 (글로벌)", "dev-lead — 개발 리드 에이전트 (글로벌)", "전체 선택"]`
|
|
87
|
+
- **중요:** 소스 경로(.claude 등)는 내부적으로만 추적합니다. 사용자에게는 기능 설명으로 보여줍니다. 로컬/글로벌 구분은 참고용으로만 표시합니다.
|
|
88
|
+
|
|
89
|
+
**에이전트 의존성 분석:**
|
|
90
|
+
- 사용자가 에이전트를 선택하면, 해당 에이전트 파일의 **내용을 직접 읽어** 참조하는 스킬을 파악합니다.
|
|
91
|
+
- 슬래시 커맨드 참조, 스킬 이름 언급, "~를 사용" 패턴 등을 탐색합니다.
|
|
92
|
+
- 의존 스킬이 sources에 존재하면: "dev-lead가 code-review, qa-testing을 참조합니다. 함께 포함합니다."라고 안내하고 자동 포함 대상으로 표시합니다.
|
|
93
|
+
- 의존 스킬이 sources에 없으면: "dev-lead가 참조하는 missing-skill을 찾을 수 없습니다"라고 경고합니다.
|
|
94
|
+
- 사용자가 자동 포함을 거부하면 해당 스킬은 제외합니다.
|
|
95
|
+
|
|
96
|
+
##### 2단계: 콘텐츠 분석 & 에이전트 포지셔닝
|
|
97
|
+
|
|
98
|
+
선택된 콘텐츠의 내용을 직접 읽어 에이전트의 정체성을 파악합니다.
|
|
99
|
+
|
|
100
|
+
**분석 관점:**
|
|
101
|
+
- 이 에이전트가 **무엇을 하는 에이전트**인지 (코드 리뷰? QA? 문서 생성? 데이터 분석?)
|
|
102
|
+
- 어떤 **기술 스택/도메인**에 특화되어 있는지 (Supabase? React? Python?)
|
|
103
|
+
- 설치자에게 **어떤 가치**를 제공하는지
|
|
104
|
+
|
|
105
|
+
이 분석을 기반으로 에이전트를 하나의 "제품"으로 포지셔닝합니다.
|
|
106
|
+
|
|
107
|
+
**중요: 소스 디렉토리 이름(.claude 등)이나 글로벌/로컬 구분은 인프라 디테일이므로 사용자에게 노출하지 않습니다.**
|
|
108
|
+
사용자에게는 에이전트의 기능과 정체성 중심으로 질문합니다.
|
|
109
|
+
|
|
110
|
+
##### 3단계: 에이전트 정보 확정
|
|
111
|
+
|
|
112
|
+
포지셔닝 분석을 기반으로 에이전트 이름과 설명을 제안합니다.
|
|
113
|
+
|
|
114
|
+
**이름(name)과 slug는 별개입니다:**
|
|
115
|
+
- **이름(name)**: 마켓플레이스에 표시되는 이름. 한국어 등 자유로운 문자 사용 가능 (예: "콘텐츠 에이전트", "Supabase 웹 개발")
|
|
116
|
+
- **slug**: URL과 `relay install`에 사용되는 식별자. 영문 소문자, 숫자, 하이픈만 가능 (예: "content-agent", "supabase-web-dev")
|
|
117
|
+
|
|
118
|
+
**AskUserQuestion 호출:**
|
|
119
|
+
- question: "에이전트 이름을 확인해주세요 (한국어 가능)"
|
|
120
|
+
- 분석된 포지셔닝에서 자연스러운 에이전트 이름을 제안합니다 (예: "콘텐츠 에이전트", "Supabase 웹 개발")
|
|
121
|
+
- 현재 디렉토리명이 아닌, **콘텐츠 기반** 이름을 기본값으로 제시합니다.
|
|
122
|
+
|
|
123
|
+
**한국어 이름은 자동으로 로마자 slug가 생성됩니다.** 자동 생성된 slug를 확인합니다:
|
|
124
|
+
|
|
125
|
+
**AskUserQuestion 호출:**
|
|
126
|
+
- question: "Slug를 확인해주세요 (URL/설치용 영문 식별자)"
|
|
127
|
+
- 한국어 이름은 로마자 변환 slug를 기본값으로 제시합니다 (예: "콘텐츠 에이전트" → "kontencheu-eijenteu").
|
|
128
|
+
- 로마자 변환이 길거나 부자연스러우면 콘텐츠 기반 영문 slug를 대안으로 제안합니다 (예: "content-agent").
|
|
129
|
+
- 영문 이름이면 자동 slug를 그대로 사용하고 이 단계를 건너뜁니다.
|
|
130
|
+
|
|
131
|
+
**AskUserQuestion 호출:**
|
|
132
|
+
- question: "에이전트 설명을 확인해주세요 (마켓플레이스에 표시됩니다)"
|
|
133
|
+
- 분석한 콘텐츠를 기반으로 설치자 관점의 설명을 제안합니다.
|
|
134
|
+
- 좋은 예: "Supabase 기반 웹앱의 DB 마이그레이션, API 개발, 테스트를 자동화합니다"
|
|
135
|
+
- 나쁜 예: ".claude 디렉토리의 skills와 commands를 패키징한 에이전트"
|
|
136
|
+
|
|
137
|
+
##### 4단계: 초기화 & 패키징
|
|
138
|
+
|
|
139
|
+
자동 처리:
|
|
140
|
+
|
|
141
|
+
**패키지 홈 결정:**
|
|
142
|
+
- 프로젝트 디렉토리에 `.relay/`가 있거나 만들 수 있으면 → 프로젝트 `.relay/` 사용
|
|
143
|
+
- 프로젝트 디렉토리가 없으면 (데스크톱앱 등) → `~/.relay/agents/<slug>/` 에 생성
|
|
144
|
+
|
|
145
|
+
**relay.yaml 생성:**
|
|
146
|
+
```yaml
|
|
147
|
+
name: <확정된 이름> # 한국어 가능
|
|
148
|
+
slug: <확정된 slug> # 영문만
|
|
149
|
+
description: <확정된 설명>
|
|
150
|
+
version: 1.0.0
|
|
151
|
+
tags: []
|
|
152
|
+
contents:
|
|
153
|
+
- name: code-review
|
|
154
|
+
type: skill
|
|
155
|
+
from: .claude/skills/code-review
|
|
156
|
+
- name: qa-testing
|
|
157
|
+
type: skill
|
|
158
|
+
from: ~/.claude/skills/qa-testing
|
|
159
|
+
- name: dev-lead
|
|
160
|
+
type: agent
|
|
161
|
+
from: ~/.claude/agents/dev-lead.md
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
- 선택된 각 콘텐츠의 `from` 경로: 로컬이면 상대 경로 (`.claude/skills/...`), 글로벌이면 `~/` 접두사 (`~/.claude/skills/...`)
|
|
165
|
+
- `relay package --sync --json` 실행하여 선택된 콘텐츠를 .relay/로 복사
|
|
166
|
+
- `relay init --auto` 실행하여 글로벌 커맨드 설치 보장
|
|
167
|
+
- 결과를 사용자에게 표시
|
|
168
|
+
|
|
169
|
+
#### B. 재배포 (.relay/relay.yaml이 있음)
|
|
170
|
+
|
|
171
|
+
##### B-0. 기존 source 필드 마이그레이션
|
|
172
|
+
|
|
173
|
+
relay.yaml에 기존 `source` 필드만 있고 `contents`가 없으면:
|
|
174
|
+
1. "기존 source 형식을 새로운 contents 형식으로 마이그레이션합니다."라고 안내
|
|
175
|
+
2. `relay package --migrate --json` 실행
|
|
176
|
+
3. 마이그레이션 결과를 사용자에게 보여줌
|
|
177
|
+
4. 이후 정상 재배포 플로우로 진행
|
|
178
|
+
|
|
179
|
+
##### B-1. 콘텐츠 동기화
|
|
180
|
+
|
|
181
|
+
`relay package --json` 실행
|
|
182
|
+
- CLI가 relay.yaml의 `contents[]` 매니페스트를 읽고, 각 항목의 원본(from 경로)과 .relay/ 내 복사본을 파일 해시로 비교합니다.
|
|
183
|
+
- 동시에 소스 디렉토리를 다시 스캔하여 새로 추가된 항목도 탐지합니다.
|
|
184
|
+
- JSON 결과:
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"diff": [
|
|
188
|
+
{ "name": "code-review", "type": "skill", "status": "modified", "files": [...] },
|
|
189
|
+
{ "name": "qa-testing", "type": "skill", "status": "unchanged" }
|
|
190
|
+
],
|
|
191
|
+
"new_items": [
|
|
192
|
+
{ "name": "new-skill", "type": "skill", "source": "~/.claude", "relativePath": "skills/new-skill" }
|
|
193
|
+
],
|
|
194
|
+
"synced": false,
|
|
195
|
+
"summary": { "modified": 1, "unchanged": 1, "source_missing": 0, "new_available": 1 }
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
##### B-2. 변경 사항 처리
|
|
200
|
+
|
|
201
|
+
**변경이 있으면** (modified > 0):
|
|
202
|
+
|
|
203
|
+
변경된 항목을 표시합니다:
|
|
204
|
+
```
|
|
205
|
+
콘텐츠 동기화 상태
|
|
206
|
+
변경: code-review (skill)
|
|
207
|
+
modified: SKILL.md
|
|
208
|
+
유지: qa-testing (skill)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**AskUserQuestion 호출:**
|
|
212
|
+
- question: "변경된 콘텐츠를 반영할까요?"
|
|
213
|
+
- options: `["반영", "변경 확인", "건너뛰기"]`
|
|
214
|
+
|
|
215
|
+
**응답 처리:**
|
|
216
|
+
- "반영" → `relay package --sync --json` 실행하여 동기화
|
|
217
|
+
- "변경 확인" → 변경된 파일의 내용을 직접 읽어 diff를 상세히 보여준 후 다시 AskUserQuestion
|
|
218
|
+
- "건너뛰기" → 현재 .relay/ 그대로 배포
|
|
219
|
+
|
|
220
|
+
**변경이 없으면** → "✓ 모든 콘텐츠가 동기화 상태입니다." 표시 후 다음 단계로
|
|
221
|
+
|
|
222
|
+
**source_missing인 항목이 있으면:**
|
|
223
|
+
- "⚠ code-review의 원본(~/.claude/skills/code-review)을 찾을 수 없습니다. .relay/ 내 복사본을 사용합니다."라고 안내
|
|
224
|
+
|
|
225
|
+
##### B-3. 새 콘텐츠 추가
|
|
226
|
+
|
|
227
|
+
**new_items가 있으면:**
|
|
228
|
+
|
|
229
|
+
새로 발견된 항목의 파일 내용을 직접 읽어 기능을 파악한 후 표시합니다:
|
|
230
|
+
|
|
231
|
+
**AskUserQuestion 호출:**
|
|
232
|
+
- question: "새로 발견된 콘텐츠가 있습니다. 패키지에 추가할까요?"
|
|
233
|
+
- options: 각 항목을 기능 설명과 함께 나열 + "건너뛰기"
|
|
234
|
+
- 예: `["new-skill — 새 유틸리티 스킬", "건너뛰기"]`
|
|
235
|
+
|
|
236
|
+
추가 선택 시:
|
|
237
|
+
- 해당 항목을 relay.yaml의 `contents[]`에 추가
|
|
238
|
+
- .relay/로 복사
|
|
239
|
+
|
|
240
|
+
**new_items가 없으면** → 이 단계 건너뜀
|
|
241
|
+
|
|
242
|
+
**contents가 없으면** (contents 필드가 빈 배열) → .relay/ 내 콘텐츠를 직접 편집하는 모드로 간주하고 동기화를 건너뜁니다.
|
|
243
|
+
|
|
244
|
+
## 인터랙션 플로우
|
|
245
|
+
|
|
246
|
+
이 커맨드는 4단계 인터랙션으로 진행됩니다. 각 단계에서 반드시 AskUserQuestion 도구를 사용하세요.
|
|
247
|
+
|
|
248
|
+
### Step 1. 버전 범프
|
|
249
|
+
|
|
250
|
+
relay.yaml의 현재 `version`을 읽고 semver 범프를 제안합니다.
|
|
251
|
+
|
|
252
|
+
**AskUserQuestion 호출:**
|
|
253
|
+
- question: "버전을 올릴까요? (현재 v{version})"
|
|
254
|
+
- options: `["v{patch} — patch (버그 수정)", "v{minor} — minor (기능 추가)", "v{major} — major (큰 변경)", "v{version} — 유지"]`
|
|
255
|
+
|
|
256
|
+
예시: 현재 v1.0.0이면 → `["v1.0.1 — patch", "v1.1.0 — minor", "v2.0.0 — major", "v1.0.0 — 유지"]`
|
|
257
|
+
|
|
258
|
+
**응답 처리:**
|
|
259
|
+
- 유지 외 선택 → relay.yaml의 version을 선택된 값으로 업데이트
|
|
260
|
+
- 유지 → 그대로 진행
|
|
261
|
+
|
|
262
|
+
### Step 1. 공개 범위 선택
|
|
263
|
+
|
|
264
|
+
relay.yaml의 `visibility` 설정을 확인합니다.
|
|
265
|
+
|
|
266
|
+
#### 신규 배포 (visibility 미설정)
|
|
267
|
+
|
|
268
|
+
**AskUserQuestion 호출:**
|
|
269
|
+
- question: "공개 범위를 선택하세요"
|
|
270
|
+
- options: `["공개 — 누구나 설치", "링크 공유 — 접근 링크가 있는 사람만 설치", "비공개 — Org 멤버만"]`
|
|
271
|
+
|
|
272
|
+
**응답 처리:**
|
|
273
|
+
- "공개" → relay.yaml에 `visibility: public` 저장
|
|
274
|
+
- "링크 공유" → relay.yaml에 `visibility: private` 저장. 배포 후 웹 대시보드(/dashboard)에서 접근 링크를 생성하고 구매 안내를 설정할 수 있다고 안내.
|
|
275
|
+
- "비공개" → `relay orgs list --json` 실행 후 Organization 목록 표시
|
|
276
|
+
- Org가 0개이면: "비공개 배포하려면 Organization이 필요합니다. www.relayax.com/orgs 에서 Organization을 생성하세요."라고 안내하고 중단합니다.
|
|
277
|
+
|
|
278
|
+
**AskUserQuestion 호출 (Org가 1개여도 반드시 호출):**
|
|
279
|
+
- question: "어떤 Organization에 배포할까요?"
|
|
280
|
+
- options: `["<org1_name>", "<org2_name>", ...]`
|
|
281
|
+
- **중요: Org가 1개라도 자동 선택하지 말고 반드시 사용자에게 확인받으세요.**
|
|
282
|
+
|
|
283
|
+
→ relay.yaml에 `visibility: internal`, `org: <selected_slug>` 저장
|
|
284
|
+
|
|
285
|
+
#### 재배포 (visibility 이미 설정됨)
|
|
286
|
+
|
|
287
|
+
현재 설정을 확인합니다:
|
|
288
|
+
|
|
289
|
+
**AskUserQuestion 호출:**
|
|
290
|
+
- question: 공개일 때 "현재 **공개** 설정입니다. 유지할까요?", 링크공유일 때 "현재 **링크 공유** 설정입니다. 접근 링크가 있는 사람만 설치 가능합니다. 유지할까요?", 비공개일 때 "현재 **비공개** 설정입니다 (Org: {name}). 유지할까요?"
|
|
291
|
+
- options: `["유지", "변경"]`
|
|
292
|
+
|
|
293
|
+
"변경" → 신규 배포와 동일한 플로우
|
|
294
|
+
|
|
295
|
+
### Step 2. 보안 점검 & requires 확인
|
|
296
|
+
|
|
297
|
+
.relay/ 내 모든 파일을 자동 분석합니다.
|
|
298
|
+
|
|
299
|
+
#### 2-1. 시크릿 스캔 (자동)
|
|
300
|
+
- 하드코딩된 API 키, 토큰, 비밀번호, Private Key 등을 탐색합니다.
|
|
301
|
+
- 예: sk-..., ghp_..., AKIA..., Bearer 토큰, JWT, -----BEGIN PRIVATE KEY----- 등
|
|
302
|
+
- 발견 시 **즉시 사용자에게 경고**하고, 환경변수로 대체하도록 안내합니다.
|
|
303
|
+
- 시크릿이 제거되지 않으면 배포를 진행하지 않습니다.
|
|
304
|
+
|
|
305
|
+
#### 2-2. 환경변수 & 의존성 분석 (자동)
|
|
306
|
+
분석 대상:
|
|
307
|
+
- **env**: 환경변수 참조 (process.env.*, ${VAR}, os.environ 등)
|
|
308
|
+
- **cli**: 참조하는 CLI 도구 (playwright, ffmpeg, sharp 등)
|
|
309
|
+
- **npm**: import/require되는 npm 패키지
|
|
310
|
+
- **mcp**: MCP 서버 설정
|
|
311
|
+
- **runtime**: Node.js/Python 등 최소 버전
|
|
312
|
+
- **agents**: 의존하는 다른 relay 에이전트
|
|
313
|
+
|
|
314
|
+
분석 결과를 요약 표시합니다:
|
|
315
|
+
|
|
316
|
+
```
|
|
317
|
+
requires 분석 결과
|
|
318
|
+
|
|
319
|
+
환경변수:
|
|
320
|
+
OPENAI_API_KEY — 필수 (LLM API 호출)
|
|
321
|
+
SLACK_WEBHOOK_URL — 선택 (알림 전송)
|
|
322
|
+
|
|
323
|
+
CLI: playwright (필수)
|
|
324
|
+
npm: sharp (필수)
|
|
325
|
+
MCP: supabase (선택)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**AskUserQuestion 호출:**
|
|
329
|
+
- question: "requires 설정이 맞나요?"
|
|
330
|
+
- options: `["확인", "수정"]`
|
|
331
|
+
|
|
332
|
+
**응답 처리:**
|
|
333
|
+
- "확인" → .relay/relay.yaml에 requires 섹션 저장, 다음 단계로
|
|
334
|
+
- "수정" → 사용자와 텍스트 대화로 수정 후 다시 확인
|
|
335
|
+
|
|
336
|
+
```yaml
|
|
337
|
+
# .relay/relay.yaml requires 구조
|
|
338
|
+
requires:
|
|
339
|
+
env:
|
|
340
|
+
- name: OPENAI_API_KEY
|
|
341
|
+
required: true
|
|
342
|
+
description: "LLM API 호출에 필요"
|
|
343
|
+
- name: SLACK_WEBHOOK_URL
|
|
344
|
+
required: false
|
|
345
|
+
description: "알림 전송 (선택)"
|
|
346
|
+
cli:
|
|
347
|
+
- name: playwright
|
|
348
|
+
install: "npx playwright install"
|
|
349
|
+
required: true
|
|
350
|
+
npm:
|
|
351
|
+
- name: sharp
|
|
352
|
+
required: true
|
|
353
|
+
mcp:
|
|
354
|
+
- name: supabase
|
|
355
|
+
package: "@supabase/mcp-server"
|
|
356
|
+
required: false
|
|
357
|
+
config:
|
|
358
|
+
command: "npx"
|
|
359
|
+
args: ["-y", "@supabase/mcp-server"]
|
|
360
|
+
env: [SUPABASE_URL, SUPABASE_SECRET_KEY]
|
|
361
|
+
runtime:
|
|
362
|
+
node: ">=18"
|
|
363
|
+
permissions:
|
|
364
|
+
- filesystem
|
|
365
|
+
- network
|
|
366
|
+
agents:
|
|
367
|
+
- @alice/doc-writer
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Step 3. 최종 확인 & 배포
|
|
371
|
+
|
|
372
|
+
#### 3-1. 메타데이터 생성 (자동)
|
|
373
|
+
- description: skills 내용 기반으로 자동 생성합니다.
|
|
374
|
+
- long_description: 에이전트 소개 마크다운을 자동 생성합니다 (README.md가 있으면 활용).
|
|
375
|
+
- tags: 에이전트 특성에 맞는 태그를 추천합니다.
|
|
376
|
+
|
|
377
|
+
#### 3-2. 배포 요약 + 최종 확인
|
|
378
|
+
배포할 내용을 요약 표시합니다:
|
|
379
|
+
|
|
380
|
+
```
|
|
381
|
+
배포 요약
|
|
382
|
+
|
|
383
|
+
에이전트: my-agent v1.0.0
|
|
384
|
+
공개: 공개
|
|
385
|
+
Skills: 3개, Commands: 5개
|
|
386
|
+
requires: env 2개, cli 1개
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
**AskUserQuestion 호출:**
|
|
390
|
+
- question: "이대로 배포할까요?"
|
|
391
|
+
- options: `["배포", "취소"]`
|
|
392
|
+
|
|
393
|
+
**응답 처리:**
|
|
394
|
+
- "배포" → `relay publish --json` 실행 (슬래시 커맨드에서 이미 버전/visibility를 relay.yaml에 저장했으므로 --json으로 인터랙티브 프롬프트 생략)
|
|
395
|
+
- "취소" → 중단
|
|
396
|
+
|
|
397
|
+
#### 3-3. 배포 완료 & 온보딩 가이드
|
|
398
|
+
- 배포 결과와 에이전트 URL을 보여줍니다.
|
|
399
|
+
- `relay publish` 출력 끝에 코드블록 형태의 온보딩 가이드가 포함됩니다.
|
|
400
|
+
- 이 코드블록을 사용자에게 그대로 보여줍니다.
|
|
401
|
+
- 출력에 코드블록이 없으면 아래 형태로 직접 생성합니다:
|
|
402
|
+
- `relay publish --json` 응답의 `access_code` 필드가 있으면 (internal agent) 가이드 URL에 `?code={access_code}` 포함:
|
|
403
|
+
|
|
404
|
+
\`\`\`
|
|
405
|
+
아래 가이드를 읽고 그대로 따라해줘:
|
|
406
|
+
https://relayax.com/api/registry/{owner}/{slug}/guide.md?code={access_code}
|
|
407
|
+
\`\`\`
|
|
408
|
+
|
|
409
|
+
- `access_code`가 없으면 (public agent) code 파라미터 없이:
|
|
410
|
+
|
|
411
|
+
\`\`\`
|
|
412
|
+
아래 가이드를 읽고 그대로 따라해줘:
|
|
413
|
+
https://relayax.com/api/registry/{owner}/{slug}/guide.md
|
|
414
|
+
\`\`\`
|
|
415
|
+
|
|
416
|
+
- private agent의 경우:
|
|
417
|
+
- "접근 코드를 생성할까요?" 사용자 확인 → `relay grant create --agent {slug}` 실행 → 생성된 코드로 `guide.md?code={agent_code}` 표시
|
|
418
|
+
- 이미 접근 코드가 있으면 기존 코드 사용 가능
|
|
419
|
+
|
|
420
|
+
**접근 코드 영향범위 안내** (visibility별로 publish 후 표시):
|
|
421
|
+
- **public**: 접근 코드 불필요. 누구나 설치 가능.
|
|
422
|
+
- **internal**: org 접근 코드 사용. 코드를 사용하면 Organization 멤버로 가입되며, 해당 org의 **모든 internal 에이전트**에 접근 가능.
|
|
423
|
+
- **private (org)**: agent 접근 코드 사용. 코드를 사용하면 **이 에이전트에만** 접근 가능 + org 자동 가입.
|
|
424
|
+
- **private (personal)**: agent 접근 코드 사용. 코드를 사용하면 **이 에이전트에만** 접근 가능.
|
|
425
|
+
- `{owner}`과 `{slug}`는 배포된 에이전트의 실제 슬러그에서 추출합니다 (`@owner/slug` → `owner`, `slug`).
|
|
426
|
+
- "이 블록을 동료에게 공유하면 Claude가 환경 체크부터 설치까지 자동으로 해줍니다"라고 안내합니다.
|
|
427
|
+
- CLI가 이미 설치된 사용자를 위한 짧은 버전도 함께 표시: `/relay:relay-install <slug>`
|
|
428
|
+
{{BUSINESS_CARD_FORMAT}}
|
|
429
|
+
|
|
430
|
+
## 예시
|
|
431
|
+
|
|
432
|
+
사용자: /relay-publish
|
|
433
|
+
→ 인증 확인 ✓, 에이전트 구조 분석 (skills 3개, commands 5개)
|
|
434
|
+
→ AskUserQuestion: "어디에 배포할까요?" → ["공개", "링크 공유", "비공개 (Org 전용)"]
|
|
435
|
+
→ "공개" 선택
|
|
436
|
+
→ 보안 스캔 ✓ 시크릿 없음 → requires 분석 결과 표시
|
|
437
|
+
→ AskUserQuestion: "requires 설정이 맞나요?" → ["확인", "수정"]
|
|
438
|
+
→ "확인"
|
|
439
|
+
→ 배포 요약 표시
|
|
440
|
+
→ AskUserQuestion: "이대로 배포할까요?" → ["배포", "취소"]
|
|
441
|
+
→ "배포" → relay publish 실행
|
|
442
|
+
→ "배포 완료! URL: https://relayax.com/@my-org/my-agent"
|
|
443
|
+
→ 온보딩 가이드 코드블록 표시
|
|
444
|
+
{{ERROR_HANDLING_GUIDE}}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
### Requirements 체크리스트 (필수 — 항목이 있으면 반드시 수행)
|
|
2
|
+
|
|
3
|
+
`relay.yaml`의 `requires` 섹션을 읽고, **각 항목을 하나씩 확인하여 체크리스트로 표시**합니다.
|
|
4
|
+
requires 섹션이 없거나 비어있으면 이 단계를 건너뜁니다.
|
|
5
|
+
|
|
6
|
+
**출력 형식** (반드시 이 형식으로 사용자에게 보여줍니다):
|
|
7
|
+
```
|
|
8
|
+
📋 Requirements 확인
|
|
9
|
+
|
|
10
|
+
[runtime]
|
|
11
|
+
✅ Node.js >=18 — v20.11.0 확인됨
|
|
12
|
+
❌ Python >=3.10 — v3.8.5 (업그레이드 필요)
|
|
13
|
+
|
|
14
|
+
[cli]
|
|
15
|
+
✅ playwright — 설치됨
|
|
16
|
+
❌ ffmpeg — 미설치 → 설치 명령: brew install ffmpeg
|
|
17
|
+
|
|
18
|
+
[npm]
|
|
19
|
+
✅ sharp — 설치됨
|
|
20
|
+
❌ puppeteer — 미설치 → 설치 중...
|
|
21
|
+
|
|
22
|
+
[env]
|
|
23
|
+
✅ OPENAI_API_KEY — 설정됨
|
|
24
|
+
❌ SLACK_WEBHOOK_URL (선택) — 미설정. 알림 전송에 필요
|
|
25
|
+
|
|
26
|
+
[mcp]
|
|
27
|
+
⚙️ supabase — MCP 서버 설정 필요 (아래 안내 참고)
|
|
28
|
+
|
|
29
|
+
[teams]
|
|
30
|
+
✅ @alice/doc-writer — 이미 설치됨
|
|
31
|
+
📦 @bob/utils — 미설치 → 설치 중...
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**처리 규칙 (각 카테고리별):**
|
|
35
|
+
|
|
36
|
+
1. **runtime**: `node --version`, `python3 --version`으로 확인. 버전 미달이면 ❌ 표시 후 업그레이드 안내.
|
|
37
|
+
2. **cli**: `which <name>`으로 확인.
|
|
38
|
+
- 설치됨 → ✅
|
|
39
|
+
- 미설치 + `install` 필드 있음 → 사용자에게 설치할지 물어본 후 실행
|
|
40
|
+
- 미설치 + `install` 필드 없음 → ❌ 표시 후 수동 설치 안내
|
|
41
|
+
3. **npm**: `npm list <package> 2>/dev/null`으로 확인.
|
|
42
|
+
- 설치됨 → ✅
|
|
43
|
+
- 미설치 + required → `npm install <package>` 실행
|
|
44
|
+
- 미설치 + optional → ❌ 표시 후 안내만
|
|
45
|
+
4. **env**: `echo $<NAME>`으로 확인.
|
|
46
|
+
- 설정됨 → ✅
|
|
47
|
+
- 미설정 + required → ❌ 표시 후 `description`과 함께 설정 방법 안내
|
|
48
|
+
- 미설정 + optional → ⚠️ 표시 후 용도 안내
|
|
49
|
+
5. **mcp**: MCP 서버 설정이 필요한 경우 ⚙️ 표시 후 설정 방법을 상세히 안내.
|
|
50
|
+
- `config` 필드가 있으면 settings.json에 추가할 JSON 블록을 보여줍니다.
|
|
51
|
+
- `env` 필드가 있으면 필요한 환경변수도 함께 안내합니다.
|
|
52
|
+
6. **teams**: `relay list --json`으로 설치 여부 확인.
|
|
53
|
+
- 설치됨 → ✅
|
|
54
|
+
- 미설치 → `relay install <@author/team> --json` 실행하여 재귀 설치
|
|
55
|
+
|
|
56
|
+
**중요**: 모든 required 항목이 ❌인 경우, 체크리스트 끝에 경고를 표시합니다:
|
|
57
|
+
```
|
|
58
|
+
⚠️ 필수 요구사항이 충족되지 않았습니다. 팀 기능이 제한될 수 있습니다.
|
|
59
|
+
```
|
package/dist/types.d.ts
CHANGED
|
@@ -3,15 +3,15 @@ export interface ContactItem {
|
|
|
3
3
|
label: string;
|
|
4
4
|
value: string;
|
|
5
5
|
}
|
|
6
|
-
export interface
|
|
7
|
-
/**
|
|
8
|
-
|
|
6
|
+
export interface InstalledAgent {
|
|
7
|
+
/** agent UUID — 설치 카운트/핑 등 서버 통신에 사용 */
|
|
8
|
+
agent_id?: string;
|
|
9
9
|
version: string;
|
|
10
10
|
installed_at: string;
|
|
11
11
|
files: string[];
|
|
12
|
-
type?: '
|
|
13
|
-
/**
|
|
14
|
-
|
|
12
|
+
type?: 'agent' | 'system';
|
|
13
|
+
/** Org 소속 에이전트인 경우 Org slug */
|
|
14
|
+
org_slug?: string;
|
|
15
15
|
/** 배치 범위 — 에이전트가 relay deploy-record로 기록 */
|
|
16
16
|
deploy_scope?: 'global' | 'local';
|
|
17
17
|
/** 배치된 파일 절대경로 목록 — 에이전트가 relay deploy-record로 기록 */
|
|
@@ -19,10 +19,10 @@ export interface InstalledTeam {
|
|
|
19
19
|
}
|
|
20
20
|
/** 키는 scoped slug 포맷: "@owner/name" */
|
|
21
21
|
export interface InstalledRegistry {
|
|
22
|
-
[scopedSlug: string]:
|
|
22
|
+
[scopedSlug: string]: InstalledAgent;
|
|
23
23
|
}
|
|
24
|
-
export interface
|
|
25
|
-
/**
|
|
24
|
+
export interface AgentRegistryInfo {
|
|
25
|
+
/** agent UUID */
|
|
26
26
|
id: string;
|
|
27
27
|
/** scoped slug 포맷: "@owner/name" */
|
|
28
28
|
slug: string;
|
|
@@ -51,7 +51,7 @@ export interface TeamRegistryInfo {
|
|
|
51
51
|
tags?: string[];
|
|
52
52
|
install_count?: number;
|
|
53
53
|
requires?: Record<string, unknown>;
|
|
54
|
-
visibility?: "public" | "
|
|
54
|
+
visibility?: "public" | "internal" | "private";
|
|
55
55
|
welcome?: string | null;
|
|
56
56
|
contact?: Record<string, string> | null;
|
|
57
57
|
author?: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "relayax-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.42",
|
|
4
4
|
"description": "RelayAX Agent Team Marketplace CLI - Install and manage agent teams",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"README.md"
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
|
-
"build": "tsc",
|
|
14
|
+
"build": "tsc && cp src/prompts/*.md dist/prompts/",
|
|
15
15
|
"dev": "tsc --watch",
|
|
16
16
|
"start": "node dist/index.js",
|
|
17
17
|
"prepublishOnly": "npm run build"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"repository": {
|
|
31
31
|
"type": "git",
|
|
32
|
-
"url": "https://github.com/
|
|
32
|
+
"url": "https://github.com/Musibe/relayax-cli-public"
|
|
33
33
|
},
|
|
34
34
|
"homepage": "https://relayax.com",
|
|
35
35
|
"dependencies": {
|