relayax-cli 0.3.66 → 0.3.67
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/init.d.ts +1 -5
- package/dist/commands/init.js +28 -6
- package/dist/commands/publish.js +44 -33
- package/dist/lib/command-adapter.js +1 -1
- package/dist/prompts/create.md +60 -14
- package/package.json +1 -1
package/dist/commands/init.d.ts
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
/**
|
|
3
|
-
* 글로벌 User 커맨드를 감지된 모든 에이전트 CLI에 설치한다.
|
|
4
|
-
* ~/{skillsDir}/commands/relay/ 에 설치.
|
|
5
|
-
* 기존 파일 중 현재 커맨드 목록에 없는 것은 제거한다.
|
|
6
|
-
*/
|
|
7
2
|
export declare function installGlobalUserCommands(): {
|
|
8
3
|
installed: boolean;
|
|
9
4
|
commands: string[];
|
|
10
5
|
tools: string[];
|
|
6
|
+
removed: string[];
|
|
11
7
|
};
|
|
12
8
|
/**
|
|
13
9
|
* 글로벌 User 커맨드가 이미 설치되어 있는지 확인한다.
|
package/dist/commands/init.js
CHANGED
|
@@ -36,10 +36,15 @@ function showWelcome() {
|
|
|
36
36
|
' 에이전트 CLI에 relay 커맨드를 연결합니다.',
|
|
37
37
|
'',
|
|
38
38
|
' \x1b[2mUser 커맨드 (글로벌)\x1b[0m',
|
|
39
|
-
' /relay-
|
|
40
|
-
' /relay-
|
|
39
|
+
' /relay-explore 에이전트 탐색 & 추천',
|
|
40
|
+
' /relay-create 에이전트 생성 & 배포',
|
|
41
|
+
' /relay-status 설치 현황 & Organization',
|
|
41
42
|
' /relay-uninstall 에이전트 삭제',
|
|
42
43
|
'',
|
|
44
|
+
' \x1b[2mCLI 명령어\x1b[0m',
|
|
45
|
+
' relay install 에이전트 설치 (CLI 한 줄 완결)',
|
|
46
|
+
' relay publish 재배포 (--patch/--minor/--major)',
|
|
47
|
+
'',
|
|
43
48
|
];
|
|
44
49
|
console.log(lines.join('\n'));
|
|
45
50
|
}
|
|
@@ -65,20 +70,28 @@ async function selectToolsInteractively(detectedIds) {
|
|
|
65
70
|
* ~/{skillsDir}/commands/relay/ 에 설치.
|
|
66
71
|
* 기존 파일 중 현재 커맨드 목록에 없는 것은 제거한다.
|
|
67
72
|
*/
|
|
73
|
+
/** 제거된 레거시 커맨드 → 대체 안내 매핑 */
|
|
74
|
+
const LEGACY_COMMANDS = {
|
|
75
|
+
'relay-install': 'relay install (CLI) 또는 /relay-explore',
|
|
76
|
+
'relay-publish': 'relay publish --patch (CLI) 또는 /relay-create',
|
|
77
|
+
};
|
|
68
78
|
function installGlobalUserCommands() {
|
|
69
79
|
const globalCLIs = (0, ai_tools_js_1.detectGlobalCLIs)();
|
|
70
80
|
const currentIds = new Set(command_adapter_js_1.USER_COMMANDS.map((c) => c.id));
|
|
71
81
|
const commands = [];
|
|
72
82
|
const tools = [];
|
|
73
|
-
|
|
83
|
+
const removed = [];
|
|
74
84
|
const targetDirs = globalCLIs.map((t) => ({ name: t.name, dir: (0, command_adapter_js_1.getGlobalCommandDirForTool)(t.skillsDir), getPath: (id) => (0, command_adapter_js_1.getGlobalCommandPathForTool)(t.skillsDir, id) }));
|
|
75
85
|
for (const target of targetDirs) {
|
|
76
86
|
fs_1.default.mkdirSync(target.dir, { recursive: true });
|
|
77
|
-
// 기존 파일 중 현재 목록에 없는 것 제거
|
|
87
|
+
// 기존 파일 중 현재 목록에 없는 것 제거 + 레거시 안내
|
|
78
88
|
for (const file of fs_1.default.readdirSync(target.dir)) {
|
|
79
89
|
const id = file.replace(/\.md$/, '');
|
|
80
90
|
if (!currentIds.has(id)) {
|
|
81
91
|
fs_1.default.unlinkSync(path_1.default.join(target.dir, file));
|
|
92
|
+
if (LEGACY_COMMANDS[id] && !removed.includes(id)) {
|
|
93
|
+
removed.push(id);
|
|
94
|
+
}
|
|
82
95
|
}
|
|
83
96
|
}
|
|
84
97
|
// 현재 커맨드 설치 (덮어쓰기)
|
|
@@ -87,11 +100,10 @@ function installGlobalUserCommands() {
|
|
|
87
100
|
}
|
|
88
101
|
tools.push(target.name);
|
|
89
102
|
}
|
|
90
|
-
// commands 목록은 한 번만
|
|
91
103
|
for (const cmd of command_adapter_js_1.USER_COMMANDS) {
|
|
92
104
|
commands.push(cmd.id);
|
|
93
105
|
}
|
|
94
|
-
return { installed: true, commands, tools };
|
|
106
|
+
return { installed: true, commands, tools, removed };
|
|
95
107
|
}
|
|
96
108
|
/**
|
|
97
109
|
* 글로벌 User 커맨드가 이미 설치되어 있는지 확인한다.
|
|
@@ -149,10 +161,12 @@ function registerInit(program) {
|
|
|
149
161
|
// ── 1. 글로벌 User 커맨드 설치 ──
|
|
150
162
|
let globalStatus = 'already';
|
|
151
163
|
let globalTools = [];
|
|
164
|
+
let removedCommands = [];
|
|
152
165
|
{
|
|
153
166
|
const result = installGlobalUserCommands();
|
|
154
167
|
globalStatus = hasGlobalUserCommands() ? 'updated' : 'installed';
|
|
155
168
|
globalTools = result.tools;
|
|
169
|
+
removedCommands = result.removed;
|
|
156
170
|
// Register relay-core in installed.json
|
|
157
171
|
const installed = (0, config_js_1.loadInstalled)();
|
|
158
172
|
installed['relay-core'] = {
|
|
@@ -245,6 +259,14 @@ function registerInit(program) {
|
|
|
245
259
|
}
|
|
246
260
|
else {
|
|
247
261
|
console.log(`\n\x1b[32m✓ relay 초기화 완료\x1b[0m\n`);
|
|
262
|
+
// 레거시 커맨드 마이그레이션 안내
|
|
263
|
+
if (removedCommands.length > 0) {
|
|
264
|
+
console.log(` \x1b[33m⚠ 변경된 커맨드:\x1b[0m`);
|
|
265
|
+
for (const id of removedCommands) {
|
|
266
|
+
console.log(` \x1b[31m✗ /${id}\x1b[0m → ${LEGACY_COMMANDS[id]}`);
|
|
267
|
+
}
|
|
268
|
+
console.log();
|
|
269
|
+
}
|
|
248
270
|
// 글로벌
|
|
249
271
|
{
|
|
250
272
|
const toolNames = globalTools.length > 0 ? globalTools.join(', ') : '(감지된 CLI 없음)';
|
package/dist/commands/publish.js
CHANGED
|
@@ -552,26 +552,31 @@ function registerPublish(program) {
|
|
|
552
552
|
// Visibility default
|
|
553
553
|
const defaultVisibility = 'public';
|
|
554
554
|
// Visibility validation: must be explicitly set
|
|
555
|
+
// internal은 org가 선택된 경우에만 옵션으로 표시
|
|
556
|
+
const hasOrg = !!selectedOrgId;
|
|
555
557
|
if (!config.visibility) {
|
|
556
558
|
if (isTTY) {
|
|
557
559
|
const { select: promptSelect } = await import('@inquirer/prompts');
|
|
558
560
|
console.error(`\n\x1b[33m⚠ relay.yaml에 visibility가 설정되지 않았습니다.\x1b[0m (기본값: ${defaultVisibility === 'public' ? '공개' : '비공개'})`);
|
|
561
|
+
const visChoices = [
|
|
562
|
+
{
|
|
563
|
+
name: `공개 — 누구나 설치${defaultVisibility === 'public' ? ' ✓ 추천' : ''}`,
|
|
564
|
+
value: 'public',
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
name: '링크 공유 — 접근 링크가 있는 사람만 설치',
|
|
568
|
+
value: 'private',
|
|
569
|
+
},
|
|
570
|
+
];
|
|
571
|
+
if (hasOrg) {
|
|
572
|
+
visChoices.push({
|
|
573
|
+
name: '비공개 — Org 멤버만 접근',
|
|
574
|
+
value: 'internal',
|
|
575
|
+
});
|
|
576
|
+
}
|
|
559
577
|
config.visibility = await promptSelect({
|
|
560
578
|
message: '공개 범위를 선택하세요:',
|
|
561
|
-
choices:
|
|
562
|
-
{
|
|
563
|
-
name: `공개 — 누구나 설치${defaultVisibility === 'public' ? ' ✓ 추천' : ''}`,
|
|
564
|
-
value: 'public',
|
|
565
|
-
},
|
|
566
|
-
{
|
|
567
|
-
name: '링크 공유 — 접근 링크가 있는 사람만 설치',
|
|
568
|
-
value: 'private',
|
|
569
|
-
},
|
|
570
|
-
{
|
|
571
|
-
name: `비공개 — Org 멤버만 접근`,
|
|
572
|
-
value: 'internal',
|
|
573
|
-
},
|
|
574
|
-
],
|
|
579
|
+
choices: visChoices,
|
|
575
580
|
default: defaultVisibility,
|
|
576
581
|
});
|
|
577
582
|
// Save back to relay.yaml
|
|
@@ -582,14 +587,17 @@ function registerPublish(program) {
|
|
|
582
587
|
}
|
|
583
588
|
else {
|
|
584
589
|
(0, error_report_js_1.reportCliError)('publish', 'MISSING_VISIBILITY', 'visibility not set in relay.yaml');
|
|
590
|
+
const visOptions = [
|
|
591
|
+
{ value: 'public', label: '공개 — 누구나 설치' },
|
|
592
|
+
{ value: 'private', label: '링크 공유 — 접근 링크가 있는 사람만 설치' },
|
|
593
|
+
];
|
|
594
|
+
if (hasOrg) {
|
|
595
|
+
visOptions.push({ value: 'internal', label: '비공개 — Org 멤버만 접근' });
|
|
596
|
+
}
|
|
585
597
|
console.error(JSON.stringify({
|
|
586
598
|
error: 'MISSING_VISIBILITY',
|
|
587
599
|
message: 'relay.yaml에 visibility를 설정해주세요.',
|
|
588
|
-
options:
|
|
589
|
-
{ value: 'public', label: '공개 — 누구나 설치' },
|
|
590
|
-
{ value: 'private', label: '링크 공유 — 접근 링크가 있는 사람만 설치' },
|
|
591
|
-
{ value: 'internal', label: '비공개 — Org 멤버만 접근' },
|
|
592
|
-
],
|
|
600
|
+
options: visOptions,
|
|
593
601
|
fix: 'relay.yaml의 visibility 필드를 위 옵션 중 하나로 설정하세요.',
|
|
594
602
|
}));
|
|
595
603
|
process.exit(1);
|
|
@@ -605,22 +613,25 @@ function registerPublish(program) {
|
|
|
605
613
|
internal: '비공개',
|
|
606
614
|
};
|
|
607
615
|
const currentVisLabel = visLabelMap[config.visibility ?? 'public'] ?? config.visibility;
|
|
616
|
+
const confirmVisChoices = [
|
|
617
|
+
{
|
|
618
|
+
name: `공개 — 누구나 설치${defaultVisibility === 'public' ? ' ✓ 추천' : ''}`,
|
|
619
|
+
value: 'public',
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
name: '링크공유 — 접근 링크가 있는 사람만 설치',
|
|
623
|
+
value: 'private',
|
|
624
|
+
},
|
|
625
|
+
];
|
|
626
|
+
if (hasOrg) {
|
|
627
|
+
confirmVisChoices.push({
|
|
628
|
+
name: '비공개 — Org 멤버만 접근',
|
|
629
|
+
value: 'internal',
|
|
630
|
+
});
|
|
631
|
+
}
|
|
608
632
|
const newVisibility = await promptConfirmVis({
|
|
609
633
|
message: `공개 범위: ${currentVisLabel} — 유지하거나 변경하세요`,
|
|
610
|
-
choices:
|
|
611
|
-
{
|
|
612
|
-
name: `공개 — 누구나 설치${defaultVisibility === 'public' ? ' ✓ 추천' : ''}`,
|
|
613
|
-
value: 'public',
|
|
614
|
-
},
|
|
615
|
-
{
|
|
616
|
-
name: '링크공유 — 접근 링크가 있는 사람만 설치',
|
|
617
|
-
value: 'private',
|
|
618
|
-
},
|
|
619
|
-
{
|
|
620
|
-
name: `비공개 — Org 멤버만 접근`,
|
|
621
|
-
value: 'internal',
|
|
622
|
-
},
|
|
623
|
-
],
|
|
634
|
+
choices: confirmVisChoices,
|
|
624
635
|
default: config.visibility ?? defaultVisibility,
|
|
625
636
|
});
|
|
626
637
|
if (newVisibility !== config.visibility) {
|
package/dist/prompts/create.md
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
에이전트를 만들거나 업데이트하여 relay에 배포합니다.
|
|
2
|
+
relay.yaml이 없으면 새로 만들고, 있으면 변경사항을 반영합니다.
|
|
3
3
|
|
|
4
4
|
> 빌더는 터미널 환경에서 작업합니다. CLI 명령어를 직접 실행하세요.
|
|
5
5
|
|
|
6
|
-
##
|
|
6
|
+
## 분기: 최초 생성 vs 업데이트
|
|
7
|
+
|
|
8
|
+
`.relay/relay.yaml`이 있는지 확인합니다.
|
|
9
|
+
|
|
10
|
+
- **없음** → 아래 "최초 생성" 플로우
|
|
11
|
+
- **있음** → 아래 "업데이트" 플로우
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 최초 생성 (relay.yaml 없음)
|
|
16
|
+
|
|
17
|
+
### 1. 콘텐츠 파악
|
|
7
18
|
|
|
8
19
|
`relay package --init --json`으로 소스를 스캔합니다.
|
|
9
20
|
결과의 `sources[]`에서 사용자에게 어떤 콘텐츠를 포함할지 물어봅니다.
|
|
@@ -12,7 +23,7 @@
|
|
|
12
23
|
- SKILL.md, 에이전트 파일, 커맨드 파일의 내용
|
|
13
24
|
- 참조하는 스킬/에이전트 의존성
|
|
14
25
|
|
|
15
|
-
|
|
26
|
+
### 2. 포지셔닝
|
|
16
27
|
|
|
17
28
|
콘텐츠 분석을 기반으로 에이전트를 하나의 "제품"으로 포지셔닝합니다.
|
|
18
29
|
|
|
@@ -24,7 +35,7 @@
|
|
|
24
35
|
이름(name)은 한국어 가능. slug는 영문 소문자+하이픈.
|
|
25
36
|
설명은 설치자 관점으로 ("~를 자동화합니다").
|
|
26
37
|
|
|
27
|
-
|
|
38
|
+
### 3. requires 판단 + 보안 점검
|
|
28
39
|
|
|
29
40
|
콘텐츠 파일을 읽고 requires를 판단합니다:
|
|
30
41
|
|
|
@@ -37,26 +48,61 @@
|
|
|
37
48
|
- **runtime**: Node.js/Python 최소 버전
|
|
38
49
|
- **agents**: 의존하는 다른 relay 에이전트
|
|
39
50
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
콘텐츠 파일에서 시크릿/개인정보를 확인합니다:
|
|
51
|
+
보안 점검:
|
|
43
52
|
- 하드코딩된 API 키, 토큰 (sk-*, ghp_*, AKIA* 등)
|
|
44
|
-
- 이메일, 전화번호 등 개인정보
|
|
45
|
-
- 발견 시 **반드시 경고**하고 환경변수 대체 안내
|
|
46
53
|
- 파일 컨텍스트를 읽어 실제 시크릿 vs 예시 코드를 구분
|
|
54
|
+
- 발견 시 **반드시 경고**하고 환경변수 대체 안내
|
|
47
55
|
|
|
48
|
-
|
|
56
|
+
### 4. relay.yaml 작성 & 배포
|
|
49
57
|
|
|
50
58
|
판단 결과를 relay.yaml에 반영합니다:
|
|
51
59
|
- name, slug, description, version, tags
|
|
52
60
|
- requires (판단 결과)
|
|
53
|
-
-
|
|
61
|
+
- org: `relay orgs list --json`으로 Org 목록을 조회합니다.
|
|
62
|
+
- Org가 있으면: 개인 배포 vs Org 배포를 사용자에게 물어봅니다.
|
|
63
|
+
- Org가 없으면: 개인 배포로 진행합니다.
|
|
64
|
+
- visibility: Org 선택 결과에 따라 옵션이 달라집니다:
|
|
65
|
+
- **Org 없이 배포**: `public`, `private` (2개)
|
|
66
|
+
- **Org에 배포**: `public`, `private`, `internal` (3개)
|
|
67
|
+
- `public` — 누구나 설치
|
|
68
|
+
- `private` — 접근 링크가 있는 사람만 설치
|
|
69
|
+
- `internal` — Org 멤버만 설치 (Org 배포 시에만 선택 가능)
|
|
54
70
|
|
|
55
71
|
`relay publish --json`으로 배포합니다.
|
|
56
72
|
|
|
57
|
-
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 업데이트 (relay.yaml 있음)
|
|
76
|
+
|
|
77
|
+
### 1. 변경 사항 확인
|
|
78
|
+
|
|
79
|
+
`relay package --json`으로 현재 상태를 확인합니다.
|
|
80
|
+
- 변경된 콘텐츠 (modified)
|
|
81
|
+
- 새로 추가된 콘텐츠 (new_items)
|
|
82
|
+
|
|
83
|
+
사용자에게 어떤 부분을 변경하려는지 물어봅니다:
|
|
84
|
+
- 콘텐츠 변경 반영 (sync)
|
|
85
|
+
- 새 스킬/커맨드 추가
|
|
86
|
+
- 설명/태그 개선
|
|
87
|
+
- requires 재분석
|
|
88
|
+
|
|
89
|
+
### 2. 필요한 부분만 업데이트
|
|
90
|
+
|
|
91
|
+
사용자 요청에 따라:
|
|
92
|
+
- **콘텐츠 추가**: 새 콘텐츠의 파일을 읽고 기능 파악 → relay.yaml의 contents에 추가
|
|
93
|
+
- **requires 변경**: 콘텐츠를 다시 읽고 requires 재판단
|
|
94
|
+
- **설명 개선**: 현재 포지셔닝을 분석하고 개선안 제안
|
|
95
|
+
- **보안 재점검**: 시크릿/개인정보 확인
|
|
96
|
+
|
|
97
|
+
### 3. 배포
|
|
98
|
+
|
|
99
|
+
`relay publish --json`으로 배포합니다.
|
|
100
|
+
버전 범프가 필요하면 사용자에게 patch/minor/major 중 확인합니다.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 공유 문구
|
|
58
105
|
|
|
59
106
|
배포 완료 후 `relay publish` 출력에 포함된 공유 문구를 보여줍니다.
|
|
60
|
-
CLI가 이미 설치된 사용자를 위한 짧은 버전도 함께 표시합니다.
|
|
61
107
|
|
|
62
108
|
{{ERROR_HANDLING_GUIDE}}
|