relayax-cli 0.1.98 → 0.1.99

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.
@@ -84,7 +84,10 @@ function registerInstall(program) {
84
84
  console.log(JSON.stringify(result));
85
85
  }
86
86
  else {
87
- console.log(`\n\x1b[32m✓ ${team.name} 다운로드 완료\x1b[0m v${team.version}`);
87
+ const authorUsername = team.author?.username;
88
+ const authorDisplayName = team.author?.display_name ?? authorUsername ?? '';
89
+ const authorSuffix = authorUsername ? ` \x1b[90mby @${authorUsername}\x1b[0m` : '';
90
+ console.log(`\n\x1b[32m✓ ${team.name} 다운로드 완료\x1b[0m v${team.version}${authorSuffix}`);
88
91
  console.log(` 위치: \x1b[36m${teamDir}\x1b[0m`);
89
92
  console.log(` 파일: ${fileCount}개`);
90
93
  if (team.commands.length > 0) {
@@ -93,6 +96,45 @@ function registerInstall(program) {
93
96
  console.log(` \x1b[33m/${cmd.name}\x1b[0m - ${cmd.description}`);
94
97
  }
95
98
  }
99
+ // Builder info block
100
+ if (team.welcome) {
101
+ console.log(`\n ┌─ 💬 ${authorDisplayName}님의 메시지 ${'─'.repeat(Math.max(0, 38 - authorDisplayName.length))}┐`);
102
+ const lines = team.welcome.match(/.{1,50}/g) ?? [team.welcome];
103
+ for (const line of lines) {
104
+ console.log(` │ "${line}"`);
105
+ }
106
+ console.log(` └${'─'.repeat(44)}┘`);
107
+ }
108
+ const contactLinks = team.author?.contact_links ?? {};
109
+ const contactEntries = Object.entries(contactLinks);
110
+ if (contactEntries.length > 0) {
111
+ const parts = contactEntries.map(([key, val]) => `${key}: ${val}`);
112
+ console.log(`\n 연락처: ${parts.join(' | ')}`);
113
+ }
114
+ if (authorUsername) {
115
+ console.log(`\n \x1b[90m👤 프로필: relayax.com/@${authorUsername}\x1b[0m`);
116
+ }
117
+ if (team.latest_post && authorUsername) {
118
+ console.log(` \x1b[90m📝 활용 팁: relayax.com/@${authorUsername}/posts/${team.latest_post.slug}\x1b[0m`);
119
+ }
120
+ // Follow prompt (only when logged in)
121
+ const token = (0, config_js_1.loadToken)();
122
+ if (authorUsername && token) {
123
+ try {
124
+ const { confirm } = await import('@inquirer/prompts');
125
+ const shouldFollow = await confirm({
126
+ message: `@${authorUsername}을 팔로우하시겠습니까? (이메일로 새 소식을 받습니다)`,
127
+ default: true,
128
+ });
129
+ if (shouldFollow) {
130
+ await (0, api_js_1.followBuilder)(authorUsername);
131
+ console.log(`\x1b[32m ✓ @${authorUsername} 팔로우 완료\x1b[0m`);
132
+ }
133
+ }
134
+ catch {
135
+ // non-critical: skip on error or non-interactive terminal
136
+ }
137
+ }
96
138
  console.log('\n 에이전트가 /relay-install로 환경을 구성합니다.');
97
139
  }
98
140
  }
package/dist/lib/api.d.ts CHANGED
@@ -8,3 +8,4 @@ export interface TeamVersionInfo {
8
8
  }
9
9
  export declare function fetchTeamVersions(slug: string): Promise<TeamVersionInfo[]>;
10
10
  export declare function reportInstall(slug: string): Promise<void>;
11
+ export declare function followBuilder(username: string): Promise<void>;
package/dist/lib/api.js CHANGED
@@ -4,6 +4,7 @@ exports.fetchTeamInfo = fetchTeamInfo;
4
4
  exports.searchTeams = searchTeams;
5
5
  exports.fetchTeamVersions = fetchTeamVersions;
6
6
  exports.reportInstall = reportInstall;
7
+ exports.followBuilder = followBuilder;
7
8
  const config_js_1 = require("./config.js");
8
9
  async function fetchTeamInfo(slug) {
9
10
  const url = `${config_js_1.API_URL}/api/registry/${slug}`;
@@ -42,3 +43,21 @@ async function reportInstall(slug) {
42
43
  // non-critical: ignore errors
43
44
  });
44
45
  }
46
+ async function followBuilder(username) {
47
+ const token = (0, config_js_1.loadToken)();
48
+ const headers = {
49
+ 'Content-Type': 'application/json',
50
+ };
51
+ if (token) {
52
+ headers['Authorization'] = `Bearer ${token}`;
53
+ }
54
+ const res = await fetch(`https://www.relayax.com/api/follows`, {
55
+ method: 'POST',
56
+ headers,
57
+ body: JSON.stringify({ following_username: username, email_opt_in: true }),
58
+ });
59
+ if (!res.ok) {
60
+ const body = await res.text();
61
+ throw new Error(`팔로우 실패 (${res.status}): ${body}`);
62
+ }
63
+ }
@@ -300,13 +300,30 @@ requires:
300
300
  - .relay/portfolio/cover.png에 저장합니다.
301
301
  - 사용자에게 "이 cover를 사용할까요?" 확인. 직접 제공도 가능.
302
302
 
303
- #### 슬롯 2: demo (선택 — 동작 시연)
304
- - 유형에 따라 제안 여부를 판단합니다:
305
- - 브라우저 자동화 키워드 감지 (playwright, puppeteer, crawl, scrape, browser) → GIF 데모 제안
306
- - 그 외 → 건너뜀 (사용자가 원하면 수동 추가)
307
- - GIF: 최대 5MB, .relay/portfolio/demo.gif에 저장
308
- - 또는 외부 영상 URL (YouTube, Loom 등)을 relay.yaml에 기록
309
- - 사용자에게 "데모를 녹화할까요?" / "영상 URL이 있나요?" 확인
303
+ #### 슬롯 2: demo (자동 생성 — 동작 시연)
304
+ 에이전트가 **직접 팀의 커맨드를 실행하여** demo를 자동 생성합니다. 사용자에게 묻기 전에 먼저 만듭니다.
305
+
306
+ **생성 절차:**
307
+ 1. .relay/commands/ 의 커맨드 목록을 읽고, 가장 대표적인 커맨드를 선택합니다.
308
+ 2. 해당 커맨드를 예시 주제/데이터로 실행합니다.
309
+ - 콘텐츠 팀: "라즈베리파이5 신제품 소개" 같은 예시 주제로 커맨드 실행
310
+ - 크롤링 팀: 예시 URL로 실행하며 브라우저 동작을 녹화
311
+ - 분석 팀: 샘플 데이터로 실행하여 결과 캡처
312
+ 3. 실행 결과물로 demo를 생성합니다:
313
+ - 여러 장 이미지 (카드뉴스 등): 슬라이드쇼 GIF (각 장 2초 간격)
314
+ - 브라우저 동작: 동작 녹화 GIF
315
+ - 단일 결과물: 결과 이미지를 demo로 사용
316
+ 4. 생성된 demo를 사용자에게 보여줍니다: "이 demo를 사용할까요?"
317
+ - 수정 요청 가능: "다른 주제로 다시 만들어줘", "좀 더 짧게"
318
+ - 확정 시 .relay/portfolio/demo.gif에 저장
319
+
320
+ **예시 주제 선택 기준:**
321
+ - relay.yaml의 description, tags에서 도메인 힌트 추출
322
+ - 기존 output/에 결과물이 있으면 같은 주제 활용
323
+ - 없으면 팀 설명에서 가장 그럴듯한 예시 주제를 자체 생성
324
+
325
+ **GIF 규격:** 최대 5MB, .relay/portfolio/demo.gif
326
+ **대안:** 외부 영상 URL (YouTube, Loom)도 가능 — relay.yaml에 기록
310
327
 
311
328
  #### 슬롯 3: gallery (선택 — 결과물 쇼케이스, 최대 5장)
312
329
  - 규격: 800x600px 이하, WebP, 각 500KB 이하
package/dist/types.d.ts CHANGED
@@ -9,6 +9,7 @@ export interface InstalledRegistry {
9
9
  export interface TeamRegistryInfo {
10
10
  slug: string;
11
11
  name: string;
12
+ description?: string;
12
13
  version: string;
13
14
  package_url: string;
14
15
  commands: {
@@ -20,7 +21,21 @@ export interface TeamRegistryInfo {
20
21
  rules: number;
21
22
  skills: number;
22
23
  };
24
+ tags?: string[];
25
+ install_count?: number;
26
+ requires?: Record<string, unknown>;
23
27
  visibility?: "public" | "login-only" | "invite-only";
28
+ welcome?: string | null;
29
+ contact?: Record<string, string> | null;
30
+ author?: {
31
+ username: string;
32
+ display_name: string | null;
33
+ contact_links: Record<string, string>;
34
+ } | null;
35
+ latest_post?: {
36
+ title: string;
37
+ slug: string;
38
+ } | null;
24
39
  }
25
40
  export interface SearchResult {
26
41
  slug: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relayax-cli",
3
- "version": "0.1.98",
3
+ "version": "0.1.99",
4
4
  "description": "RelayAX Agent Team Marketplace CLI - Install and manage agent teams",
5
5
  "main": "dist/index.js",
6
6
  "bin": {