relayax-cli 0.3.54 → 0.3.56

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.
@@ -709,8 +709,10 @@ function registerPublish(program) {
709
709
  console.log(index_js_1.GUIDE_INSTRUCTION);
710
710
  console.log(guideUrl);
711
711
  console.log('```');
712
- console.log(`\n \x1b[90m이미 relay를 쓰는 사용자는 이렇게만 하면 됩니다:\x1b[0m`);
713
- console.log(` /relay-install ${result.slug}`);
712
+ console.log(`\n \x1b[90m이미 relay를 쓰는 사용자는 이렇게만 하면 됩니다:\x1b[0m\n`);
713
+ console.log('```');
714
+ console.log(`/relay-install ${result.slug}`);
715
+ console.log('```');
714
716
  if (config.visibility === 'private') {
715
717
  console.log(`\n \x1b[90mprivate 에이전트:\x1b[0m`);
716
718
  console.log(` 접근 링크를 생성한 뒤 guide.md?code={agent_code}로 공유하세요.`);
@@ -52,6 +52,33 @@ function countFiles(dir) {
52
52
  function jsonText(obj) {
53
53
  return { type: 'text', text: JSON.stringify(obj) };
54
54
  }
55
+ // 주요 도구 응답에 CLI 업데이트 경고를 병합하는 헬퍼
56
+ // MCP 서버 프로세스는 Claude 재시작 전까지 유지되므로, 응답에 버전 정보를 포함시켜
57
+ // 에이전트가 사용자에게 재시작을 안내할 수 있도록 한다.
58
+ let _cachedCliUpdate;
59
+ async function getCliUpdateWarning() {
60
+ if (_cachedCliUpdate === undefined) {
61
+ try {
62
+ const { checkCliVersion } = await import('../lib/version-check.js');
63
+ _cachedCliUpdate = await checkCliVersion(true);
64
+ }
65
+ catch {
66
+ _cachedCliUpdate = null;
67
+ }
68
+ }
69
+ if (!_cachedCliUpdate)
70
+ return null;
71
+ return {
72
+ cli_update: {
73
+ current: pkg.version,
74
+ latest: _cachedCliUpdate.latest,
75
+ message: `relay v${_cachedCliUpdate.latest}이 있습니다. npm update -g relayax-cli 후 Claude를 재시작해주세요.`,
76
+ },
77
+ };
78
+ }
79
+ function jsonTextWithUpdate(obj, update) {
80
+ return jsonText(update ? { ...obj, ...update } : obj);
81
+ }
55
82
  // ─── Server ───
56
83
  function createMcpServer() {
57
84
  const server = new mcp_js_1.McpServer({ name: 'relay', version: pkg.version }, { capabilities: { tools: {}, prompts: {} } });
@@ -97,7 +124,8 @@ function createMcpServer() {
97
124
  (0, config_js_1.saveInstalled)(installed);
98
125
  await (0, api_js_1.reportInstall)(agent.id, fullSlug, agent.version);
99
126
  (0, api_js_1.sendUsagePing)(agent.id, fullSlug, agent.version);
100
- return { content: [jsonText({ status: 'ok', agent: agent.name, slug: fullSlug, version: agent.version, files: countFiles(agentDir), install_path: agentDir })] };
127
+ const cliUpdate = await getCliUpdateWarning();
128
+ return { content: [jsonTextWithUpdate({ status: 'ok', agent: agent.name, slug: fullSlug, version: agent.version, files: countFiles(agentDir), install_path: agentDir }, cliUpdate)] };
101
129
  }
102
130
  finally {
103
131
  (0, storage_js_1.removeTempDir)(tempDir);
@@ -232,6 +260,52 @@ function createMcpServer() {
232
260
  }
233
261
  return { content: [jsonText({ sources })] };
234
262
  });
263
+ server.tool('relay_org_list', '소속 Organization 목록을 조회합니다', {}, async () => {
264
+ try {
265
+ const token = await (0, config_js_1.getValidToken)();
266
+ if (!token) {
267
+ return { content: [jsonText({ error: 'LOGIN_REQUIRED', message: '로그인이 필요합니다.' })], isError: true };
268
+ }
269
+ const { fetchMyOrgs } = await import('../commands/orgs.js');
270
+ const orgs = await fetchMyOrgs(token);
271
+ return { content: [jsonText({ orgs: orgs.map((o) => ({ id: o.id, slug: o.slug, name: o.name, role: o.role })) })] };
272
+ }
273
+ catch (err) {
274
+ return { content: [jsonText({ error: String(err) })], isError: true };
275
+ }
276
+ });
277
+ server.tool('relay_org_create', '새 Organization을 생성합니다', {
278
+ name: zod_1.z.string().describe('Organization 이름'),
279
+ slug: zod_1.z.string().optional().describe('URL slug (미지정 시 이름에서 자동 생성)'),
280
+ }, async ({ name, slug: slugInput }) => {
281
+ try {
282
+ const token = await (0, config_js_1.getValidToken)();
283
+ if (!token) {
284
+ return { content: [jsonText({ error: 'LOGIN_REQUIRED', message: '로그인이 필요합니다.' })], isError: true };
285
+ }
286
+ const slug = slugInput ?? name
287
+ .toLowerCase()
288
+ .replace(/[^a-z0-9\s-]/g, '')
289
+ .replace(/[\s]+/g, '-')
290
+ .replace(/-+/g, '-')
291
+ .replace(/^-|-$/g, '')
292
+ .slice(0, 50);
293
+ const res = await fetch(`${config_js_1.API_URL}/api/orgs`, {
294
+ method: 'POST',
295
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
296
+ body: JSON.stringify({ name, slug }),
297
+ });
298
+ if (!res.ok) {
299
+ const body = await res.json().catch(() => ({ message: `${res.status}` }));
300
+ throw new Error(body.message ?? `Organization 생성 실패 (${res.status})`);
301
+ }
302
+ const org = await res.json();
303
+ return { content: [jsonText({ status: 'created', org })] };
304
+ }
305
+ catch (err) {
306
+ return { content: [jsonText({ error: String(err) })], isError: true };
307
+ }
308
+ });
235
309
  server.tool('relay_publish', '에이전트를 마켓플레이스에 배포합니다 (.relay/ 디렉토리를 tar로 패키징하여 업로드)', {
236
310
  project_path: zod_1.z.string().optional().describe('프로젝트 경로 (.relay/relay.yaml이 있는 디렉토리)'),
237
311
  }, async ({ project_path }) => {
@@ -264,7 +338,8 @@ function createMcpServer() {
264
338
  cli_version: pkg.version,
265
339
  };
266
340
  const result = await publishToApi(token, tarPath, metadata);
267
- return { content: [jsonText(result)] };
341
+ const cliUpdate = await getCliUpdateWarning();
342
+ return { content: [jsonTextWithUpdate(result, cliUpdate)] };
268
343
  }
269
344
  finally {
270
345
  fs_1.default.unlinkSync(tarPath);
@@ -25,12 +25,11 @@ Node.js가 없는 경우:
25
25
 
26
26
  ### 환경 B (MCP)
27
27
 
28
- **Step 1-1. 버전 확인**: `relay_check_update` tool을 반드시 호출하세요.
29
- - `status: "up_to_date"` 최신 버전. Step 1-2로.
30
- - `status: "updates_available"` → 사용자에게 업데이트 안내:
31
- > CLI 업데이트가 있습니다. 터미널에서 `npm update -g relayax-cli`를 실행해주세요.
32
-
33
- 사용자가 업데이트 완료 후 Claude를 재시작하면 최신 MCP 서버가 적용됩니다.
28
+ **Step 1-1. 버전 확인**: `relay_check_update` tool을 호출하세요.
29
+ - tool이 없으면 `relay_status`로 대체하고, 응답의 `cli.update_available` 또는 `cli_update` 필드를 확인하세요.
30
+ - `status: "up_to_date"` (또는 `update_available: null`) 최신 버전. Step 1-2로.
31
+ - `status: "updates_available"` (또는 `update_available`에 버전이 있음) 사용자에게 업데이트 안내:
32
+ > CLI 업데이트가 있습니다. 터미널에서 `npm update -g relayax-cli`를 실행한 후 Claude를 재시작해주세요.
34
33
 
35
34
  **Step 1-2. slash command 설치**: `relay_init` tool을 반드시 호출하세요.
36
35
  - `/relay-install`, `/relay-publish` 등 slash command가 설치/업데이트됩니다.
@@ -39,7 +39,7 @@ cat ~/Library/Application\ Support/Claude/claude_desktop_config.json 2>/dev/null
39
39
  "mcpServers": {
40
40
  "relay": {
41
41
  "command": "npx",
42
- "args": ["relayax-cli", "mcp"]
42
+ "args": ["relayax-cli@latest", "mcp"]
43
43
  }
44
44
  }
45
45
  }
@@ -61,5 +61,7 @@ cat ~/Library/Application\ Support/Claude/claude_desktop_config.json 2>/dev/null
61
61
  | "relay login" | `relay login` | `relay_login` tool 호출 |
62
62
  | "relay scan" | `relay package --init` | `relay_scan` tool 호출 |
63
63
  | "relay check-update X" | `relay check-update X` | `relay_check_update` tool 호출 (`slug: "X"`) |
64
+ | "relay orgs list" | `relay orgs list --json` | `relay_org_list` tool 호출 |
65
+ | "relay orgs create" | `relay orgs create "이름" --json` | `relay_org_create` tool 호출 (`name: "이름"`) |
64
66
 
65
67
  처음 판별한 환경을 이후 계속 사용합니다.
@@ -276,8 +276,15 @@ relay.yaml의 `visibility` 설정을 확인합니다.
276
276
  **응답 처리:**
277
277
  - "공개" → relay.yaml에 `visibility: public` 저장
278
278
  - "링크 공유" → relay.yaml에 `visibility: private` 저장. 배포 후 웹 대시보드(/dashboard)에서 접근 링크를 생성하고 구매 안내를 설정할 수 있다고 안내.
279
- - "비공개" → `relay orgs list --json` 실행 후 Organization 목록 표시
280
- - Org가 0개이면: "비공개 배포하려면 Organization이 필요합니다. www.relayax.com/orgs 에서 Organization을 생성하세요."라고 안내하고 중단합니다.
279
+ - "비공개" → Organization 목록을 조회합니다:
280
+ - 환경 A: `relay orgs list --json` 실행
281
+ - 환경 B: `relay_status` tool 응답을 참고하거나, 배포 시 `relay_publish` tool이 org 선택 없이 배포하면 서버가 자동 매칭합니다.
282
+ - Org가 0개이면: Organization을 생성합니다.
283
+ - 환경 A: `relay orgs create "이름" --json` 실행
284
+ - 환경 B: `relay_org_create` MCP tool 호출 (tool이 없으면 사용자에게 "www.relayax.com/orgs 에서 Organization을 생성하세요"라고 안내)
285
+ - **사용자 질문 도구 호출:**
286
+ - question: "비공개 배포를 위해 Organization을 만들어야 합니다. Organization 이름을 입력하세요."
287
+ - 생성 후 해당 org를 선택하여 계속 진행합니다.
281
288
 
282
289
  **사용자 질문 도구 호출 (Org가 1개여도 반드시 호출):**
283
290
  - question: "어떤 Organization에 배포할까요?"
@@ -395,7 +402,9 @@ requires: env 2개, cli 1개
395
402
  - options: `["배포", "취소"]`
396
403
 
397
404
  **응답 처리:**
398
- - "배포" → `relay publish --json` 실행 (슬래시 커맨드에서 이미 버전/visibility를 relay.yaml에 저장했으므로 --json으로 인터랙티브 프롬프트 생략)
405
+ - "배포":
406
+ - 환경 A: `relay publish --json` 실행 (슬래시 커맨드에서 이미 버전/visibility를 relay.yaml에 저장했으므로 --json으로 인터랙티브 프롬프트 생략)
407
+ - 환경 B: `relay_publish` MCP tool 호출 (`project_path`는 프로젝트 루트 경로)
399
408
  - "취소" → 중단
400
409
 
401
410
  #### 3-3. 배포 완료 & 온보딩 가이드
@@ -428,7 +437,7 @@ https://relayax.com/api/registry/{owner}/{slug}/guide.md
428
437
  - **private (personal)**: agent 접근 코드 사용. 코드를 사용하면 **이 에이전트에만** 접근 가능.
429
438
  - `{owner}`과 `{slug}`는 배포된 에이전트의 실제 슬러그에서 추출합니다 (`@owner/slug` → `owner`, `slug`).
430
439
  - "이 블록을 동료에게 공유하면 AI 에이전트가 환경 체크부터 설치까지 자동으로 해줍니다"라고 안내합니다.
431
- - CLI가 이미 설치된 사용자를 위한 짧은 버전도 함께 표시: `/relay:relay-install <slug>`
440
+ - CLI가 이미 설치된 사용자를 위한 짧은 버전도 코드 블록으로 함께 표시: `/relay-install <slug>`
432
441
 
433
442
  ## 예시
434
443
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relayax-cli",
3
- "version": "0.3.54",
3
+ "version": "0.3.56",
4
4
  "description": "RelayAX Agent Team Marketplace CLI - Install and manage agent teams",
5
5
  "main": "dist/index.js",
6
6
  "bin": {