relayax-cli 0.3.50 → 0.3.51

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,4 +1,13 @@
1
1
  import { Command } from 'commander';
2
+ interface CommandEntry {
3
+ name: string;
4
+ description: string;
5
+ }
6
+ interface Components {
7
+ agents: number;
8
+ rules: number;
9
+ skills: number;
10
+ }
2
11
  export interface RequiresCli {
3
12
  name: string;
4
13
  install?: string;
@@ -35,4 +44,49 @@ export interface Requires {
35
44
  };
36
45
  permissions?: string[];
37
46
  }
47
+ interface AgentDetail {
48
+ name: string;
49
+ description: string;
50
+ uses: string[];
51
+ }
52
+ interface SkillDetail {
53
+ name: string;
54
+ description: string;
55
+ uses: string[];
56
+ }
57
+ export interface PublishMetadata {
58
+ slug: string;
59
+ name: string;
60
+ description: string;
61
+ long_description?: string;
62
+ tags: string[];
63
+ commands: CommandEntry[];
64
+ components: Components;
65
+ version: string;
66
+ changelog?: string;
67
+ requires?: Requires;
68
+ visibility?: 'public' | 'private' | 'internal';
69
+ type?: 'command' | 'passive' | 'hybrid';
70
+ cli_version?: string;
71
+ agent_names?: string[];
72
+ skill_names?: string[];
73
+ agent_details?: AgentDetail[];
74
+ skill_details?: SkillDetail[];
75
+ org_slug?: string;
76
+ }
77
+ export declare function createTarball(agentDir: string): Promise<string>;
78
+ interface PublishResult {
79
+ status: string;
80
+ slug: string;
81
+ version: string;
82
+ url: string;
83
+ profile?: {
84
+ username?: string;
85
+ display_name?: string;
86
+ contact_links?: Record<string, string>;
87
+ default_welcome?: string;
88
+ } | null;
89
+ }
90
+ export declare function publishToApi(token: string, tarPath: string, metadata: PublishMetadata): Promise<PublishResult>;
38
91
  export declare function registerPublish(program: Command): void;
92
+ export {};
@@ -3,6 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createTarball = createTarball;
7
+ exports.publishToApi = publishToApi;
6
8
  exports.registerPublish = registerPublish;
7
9
  const fs_1 = __importDefault(require("fs"));
8
10
  const path_1 = __importDefault(require("path"));
@@ -13,6 +13,36 @@ exports.formatCommandFile = formatCommandFile;
13
13
  const os_1 = __importDefault(require("os"));
14
14
  const path_1 = __importDefault(require("path"));
15
15
  const index_js_1 = require("../prompts/index.js");
16
+ /**
17
+ * 환경 감지 프리앰블.
18
+ * slash command 실행 시 MCP tool 사용 가능 여부를 먼저 판별하여,
19
+ * 이후 모든 CLI 명령어를 적절한 방식으로 실행하도록 안내.
20
+ */
21
+ const ENV_PREAMBLE = `## 환경 감지
22
+
23
+ 이 커맨드를 실행하기 전에 환경을 판별하세요:
24
+
25
+ 1. **relay MCP tool 사용 가능 여부 확인**: relay_status 같은 relay MCP tool을 호출할 수 있는지 확인하세요.
26
+ - 사용 가능 → **MCP 모드**로 실행 (아래 표 참고)
27
+ - 사용 불가 → **CLI 모드**로 실행 (bash 명령어 그대로 사용)
28
+
29
+ 2. MCP 모드에서의 명령어 변환:
30
+
31
+ | CLI 명령어 | MCP tool |
32
+ |---|---|
33
+ | \`relay status\` | \`relay_status\` tool 호출 |
34
+ | \`relay list --json\` | \`relay_list\` tool 호출 |
35
+ | \`relay search <keyword>\` | \`relay_search\` tool 호출 |
36
+ | \`relay install <slug>\` | \`relay_install\` tool 호출 |
37
+ | \`relay uninstall <slug>\` | \`relay_uninstall\` tool 호출 |
38
+ | \`relay package --init\` | \`relay_scan\` tool 호출 |
39
+ | \`relay publish\` | \`relay_publish\` tool 호출 |
40
+
41
+ **중요**: 이후 지시에서 \`relay <명령어>\`로 표기된 것은 판별된 환경에 따라 변환하여 실행하세요.
42
+
43
+ ---
44
+
45
+ `;
16
46
  /**
17
47
  * 로컬 어댑터 — 프로젝트 디렉토리 기준.
18
48
  * {projectPath}/{skillsDir}/commands/relay/{id}.md
@@ -66,12 +96,12 @@ exports.USER_COMMANDS = [
66
96
  {
67
97
  id: 'relay-install',
68
98
  description: 'relay에서 에이전트를 설치합니다',
69
- body: index_js_1.INSTALL_PROMPT,
99
+ body: ENV_PREAMBLE + index_js_1.INSTALL_PROMPT,
70
100
  },
71
101
  {
72
102
  id: 'relay-status',
73
103
  description: '설치된 에이전트와 Organization 현황을 확인합니다',
74
- body: `현재 설치된 에이전트와 소속 Organization 현황을 한눈에 보여줍니다.
104
+ body: ENV_PREAMBLE + `현재 설치된 에이전트와 소속 Organization 현황을 한눈에 보여줍니다.
75
105
 
76
106
  ## 실행 방법
77
107
 
@@ -160,7 +190,7 @@ ${index_js_1.ERROR_HANDLING_GUIDE}
160
190
  {
161
191
  id: 'relay-uninstall',
162
192
  description: '설치된 에이전트를 삭제합니다',
163
- body: `설치된 에이전트를 제거합니다. CLI가 패키지와 배치된 파일을 모두 정리합니다.
193
+ body: ENV_PREAMBLE + `설치된 에이전트를 제거합니다. CLI가 패키지와 배치된 파일을 모두 정리합니다.
164
194
 
165
195
  ## 실행 방법
166
196
 
@@ -181,7 +211,7 @@ ${index_js_1.ERROR_HANDLING_GUIDE}
181
211
  {
182
212
  id: 'relay-publish',
183
213
  description: '현재 에이전트 패키지를 relay에 배포합니다',
184
- body: index_js_1.PUBLISH_PROMPT,
214
+ body: ENV_PREAMBLE + index_js_1.PUBLISH_PROMPT,
185
215
  },
186
216
  ];
187
217
  // ─── Builder Commands (로컬 설치) ───
@@ -16,6 +16,7 @@ const ai_tools_js_1 = require("../lib/ai-tools.js");
16
16
  const preamble_js_1 = require("../lib/preamble.js");
17
17
  const installer_js_1 = require("../lib/installer.js");
18
18
  const paths_js_1 = require("../lib/paths.js");
19
+ // prompts are used in MCP Prompt definitions below
19
20
  const fs_1 = __importDefault(require("fs"));
20
21
  const path_1 = __importDefault(require("path"));
21
22
  const js_yaml_1 = __importDefault(require("js-yaml"));
@@ -161,7 +162,30 @@ function createMcpServer() {
161
162
  }
162
163
  catch { /* skip */ }
163
164
  }
164
- return { content: [jsonText({ login: { authenticated: !!token, username }, agent_clis: detected.map((t) => t.name), mounted_paths: mounted.map((m) => m.basePath), project })] };
165
+ // 버전 확인
166
+ const { checkCliVersion } = await import('../lib/version-check.js');
167
+ const cliUpdate = await checkCliVersion(true);
168
+ return { content: [jsonText({
169
+ cli: { version: pkg.version, update_available: cliUpdate ? cliUpdate.latest : null },
170
+ login: { authenticated: !!token, username },
171
+ agent_clis: detected.map((t) => t.name),
172
+ mounted_paths: mounted.map((m) => m.basePath),
173
+ project,
174
+ })] };
175
+ });
176
+ server.tool('relay_check_update', 'CLI 및 에이전트 업데이트를 확인합니다', {}, async () => {
177
+ const { checkCliVersion, checkAllAgents } = await import('../lib/version-check.js');
178
+ const cliUpdate = await checkCliVersion(true);
179
+ const agentUpdates = await checkAllAgents(true);
180
+ const updates = [];
181
+ if (cliUpdate)
182
+ updates.push({ type: 'cli', current: cliUpdate.current, latest: cliUpdate.latest });
183
+ for (const u of agentUpdates)
184
+ updates.push({ type: 'agent', slug: u.slug, current: u.current, latest: u.latest });
185
+ if (updates.length === 0) {
186
+ return { content: [jsonText({ status: 'up_to_date', message: '모두 최신 버전입니다.', cli_version: pkg.version })] };
187
+ }
188
+ return { content: [jsonText({ status: 'updates_available', updates, message: 'CLI를 업데이트하려면: npm update -g relayax-cli' })] };
165
189
  });
166
190
  server.tool('relay_scan', '배포 가능한 스킬/에이전트/커맨드를 스캔합니다', {
167
191
  project_path: zod_1.z.string().optional().describe('프로젝트 경로'),
@@ -190,73 +214,61 @@ function createMcpServer() {
190
214
  }
191
215
  return { content: [jsonText({ sources })] };
192
216
  });
193
- server.tool('relay_publish', '에이전트를 마켓플레이스에 배포합니다', {
194
- project_path: zod_1.z.string().optional().describe('프로젝트 경로'),
217
+ server.tool('relay_publish', '에이전트를 마켓플레이스에 배포합니다 (.relay/ 디렉토리를 tar로 패키징하여 업로드)', {
218
+ project_path: zod_1.z.string().optional().describe('프로젝트 경로 (.relay/relay.yaml이 있는 디렉토리)'),
195
219
  }, async ({ project_path }) => {
196
- const projectPath = project_path ?? (0, paths_js_1.resolveProjectPath)();
197
- const relayYaml = path_1.default.join(projectPath, '.relay', 'relay.yaml');
198
- if (!fs_1.default.existsSync(relayYaml)) {
199
- return { content: [jsonText({ error: 'NOT_INITIALIZED', message: '.relay/relay.yaml이 없습니다. relay-publish 프롬프트를 사용하여 프로젝트를 먼저 설정하세요.' })], isError: true };
220
+ try {
221
+ const projectPath = project_path ?? (0, paths_js_1.resolveProjectPath)();
222
+ const relayDir = path_1.default.join(projectPath, '.relay');
223
+ const relayYaml = path_1.default.join(relayDir, 'relay.yaml');
224
+ if (!fs_1.default.existsSync(relayYaml)) {
225
+ return { content: [jsonText({ error: 'NOT_INITIALIZED', message: '.relay/relay.yaml이 없습니다.' })], isError: true };
226
+ }
227
+ const token = await (0, config_js_1.getValidToken)();
228
+ if (!token) {
229
+ return { content: [jsonText({ error: 'LOGIN_REQUIRED', message: '배포하려면 로그인이 필요합니다.' })], isError: true };
230
+ }
231
+ const cfg = js_yaml_1.default.load(fs_1.default.readFileSync(relayYaml, 'utf-8'));
232
+ const { createTarball, publishToApi } = await import('../commands/publish.js');
233
+ const tarPath = await createTarball(relayDir);
234
+ try {
235
+ const metadata = {
236
+ slug: cfg.slug,
237
+ name: cfg.name,
238
+ description: cfg.description ?? '',
239
+ tags: cfg.tags ?? [],
240
+ commands: [],
241
+ components: { skills: 0, agents: 0, rules: 0, commands: 0 },
242
+ version: cfg.version,
243
+ visibility: cfg.visibility ?? 'public',
244
+ cli_version: pkg.version,
245
+ };
246
+ const result = await publishToApi(token, tarPath, metadata);
247
+ return { content: [jsonText(result)] };
248
+ }
249
+ finally {
250
+ fs_1.default.unlinkSync(tarPath);
251
+ }
200
252
  }
201
- const token = await (0, config_js_1.getValidToken)();
202
- if (!token) {
203
- return { content: [jsonText({ error: 'LOGIN_REQUIRED', message: '배포하려면 로그인이 필요합니다.' })], isError: true };
253
+ catch (err) {
254
+ return { content: [jsonText({ error: String(err) })], isError: true };
255
+ }
256
+ });
257
+ // ═══ relay_init — slash command 설치 ═══
258
+ server.tool('relay_init', 'relay slash command를 설치합니다 (/relay-install, /relay-publish 등)', {}, async () => {
259
+ try {
260
+ const { installGlobalUserCommands, hasGlobalUserCommands } = await import('../commands/init.js');
261
+ if (hasGlobalUserCommands()) {
262
+ installGlobalUserCommands(); // 업데이트
263
+ return { content: [jsonText({ status: 'updated', message: 'relay slash command가 업데이트되었습니다.' })] };
264
+ }
265
+ installGlobalUserCommands();
266
+ return { content: [jsonText({ status: 'installed', message: 'relay slash command가 설치되었습니다. /relay-install, /relay-publish 등을 사용할 수 있습니다.' })] };
267
+ }
268
+ catch (err) {
269
+ return { content: [jsonText({ error: String(err) })], isError: true };
204
270
  }
205
- const cfg = js_yaml_1.default.load(fs_1.default.readFileSync(relayYaml, 'utf-8'));
206
- return { content: [jsonText({ status: 'ready', project_path: projectPath, name: cfg.name, slug: cfg.slug, version: cfg.version, message: '배포 준비 완료. relay-publish 프롬프트로 전체 워크플로우를 실행하세요.' })] };
207
271
  });
208
- // ═══ Prompts ═══
209
- server.prompt('relay-install', '에이전트 검색 → 설치 가이드 워크플로우', {}, () => ({
210
- messages: [{
211
- role: 'user',
212
- content: { type: 'text', text: `다음 가이드를 따라 에이전트를 설치하세요. relay MCP tool을 사용하여 각 단계를 실행합니다.
213
-
214
- 사용 가능한 tool: relay_status, relay_search, relay_install, relay_list, relay_status
215
-
216
- ## 워크플로우
217
-
218
- 1. relay_status로 로그인 상태 확인. 미인증이면 사용자에게 터미널에서 \`npx relayax-cli login --device\` 실행을 안내.
219
- 2. 사용자에게 어떤 에이전트를 찾는지 물어보기.
220
- 3. relay_search로 검색.
221
- 4. 검색 결과를 보여주고 선택하게 하기.
222
- 5. relay_install로 설치.
223
- 6. 설치 결과와 사용법 안내.` },
224
- }],
225
- }));
226
- server.prompt('relay-publish', '에이전트 배포 가이드 워크플로우', {}, () => ({
227
- messages: [{
228
- role: 'user',
229
- content: { type: 'text', text: `다음 가이드를 따라 에이전트를 배포하세요. relay MCP tool을 사용합니다.
230
-
231
- 사용 가능한 tool: relay_status, relay_scan, relay_status, relay_publish
232
-
233
- ## 워크플로우
234
-
235
- 1. relay_status로 로그인 상태 확인. 미인증이면 터미널에서 \`npx relayax-cli login --device\` 안내.
236
- 2. relay_scan으로 배포 가능한 스킬/에이전트/커맨드 목록 스캔.
237
- 3. 스캔 결과를 보여주고 사용자에게 어떤 항목을 배포할지 선택하게 하기.
238
- 4. relay_status로 프로젝트 상태 확인. .relay/relay.yaml이 없으면 프로젝트 생성 안내.
239
- 5. relay_publish로 배포.
240
- 6. 배포 결과를 사용자에게 보여주기.` },
241
- }],
242
- }));
243
- server.prompt('relay-status', '환경 상태 확인', {}, () => ({
244
- messages: [{
245
- role: 'user',
246
- content: { type: 'text', text: 'relay_status, relay_status, relay_list, relay_scan tool을 사용하여 현재 relay 환경 상태를 확인하고 사용자에게 보여주세요. 로그인 상태, 감지된 AI 도구, 프로젝트 정보, 설치된 에이전트, 배포 가능한 스킬 목록을 포함합니다.' },
247
- }],
248
- }));
249
- server.prompt('relay-uninstall', '에이전트 제거 가이드', {}, () => ({
250
- messages: [{
251
- role: 'user',
252
- content: { type: 'text', text: `다음 워크플로우를 따라 에이전트를 제거하세요:
253
-
254
- 1. relay_list로 설치된 에이전트 목록 표시.
255
- 2. 사용자에게 제거할 에이전트 선택하게 하기.
256
- 3. relay_uninstall로 제거.
257
- 4. 결과 보여주기.` },
258
- }],
259
- }));
260
272
  return server;
261
273
  }
262
274
  // ─── Start ───
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relayax-cli",
3
- "version": "0.3.50",
3
+ "version": "0.3.51",
4
4
  "description": "RelayAX Agent Team Marketplace CLI - Install and manage agent teams",
5
5
  "main": "dist/index.js",
6
6
  "bin": {