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.
Files changed (62) hide show
  1. package/dist/commands/access.js +12 -12
  2. package/dist/commands/changelog.js +2 -2
  3. package/dist/commands/check-update.js +12 -12
  4. package/dist/commands/create.js +46 -19
  5. package/dist/commands/deploy-record.js +2 -2
  6. package/dist/commands/diff.d.ts +2 -0
  7. package/dist/commands/diff.js +72 -0
  8. package/dist/commands/grant.d.ts +33 -0
  9. package/dist/commands/grant.js +190 -0
  10. package/dist/commands/init.js +10 -10
  11. package/dist/commands/install.js +125 -256
  12. package/dist/commands/join.d.ts +3 -2
  13. package/dist/commands/join.js +18 -69
  14. package/dist/commands/list.js +23 -26
  15. package/dist/commands/login.js +10 -3
  16. package/dist/commands/orgs.d.ts +10 -0
  17. package/dist/commands/orgs.js +128 -0
  18. package/dist/commands/outdated.js +7 -7
  19. package/dist/commands/package.d.ts +18 -0
  20. package/dist/commands/package.js +355 -146
  21. package/dist/commands/ping.js +5 -5
  22. package/dist/commands/publish.d.ts +1 -1
  23. package/dist/commands/publish.js +105 -103
  24. package/dist/commands/search.js +2 -2
  25. package/dist/commands/status.js +11 -11
  26. package/dist/commands/uninstall.js +7 -7
  27. package/dist/commands/update.js +22 -22
  28. package/dist/commands/versions.d.ts +2 -0
  29. package/dist/commands/versions.js +44 -0
  30. package/dist/index.js +8 -2
  31. package/dist/lib/ai-tools.d.ts +15 -0
  32. package/dist/lib/ai-tools.js +48 -1
  33. package/dist/lib/api.d.ts +13 -12
  34. package/dist/lib/api.js +24 -39
  35. package/dist/lib/command-adapter.js +41 -693
  36. package/dist/lib/config.d.ts +10 -5
  37. package/dist/lib/config.js +106 -24
  38. package/dist/lib/guide.js +34 -79
  39. package/dist/lib/installer.d.ts +2 -2
  40. package/dist/lib/installer.js +4 -4
  41. package/dist/lib/preamble.d.ts +4 -4
  42. package/dist/lib/preamble.js +14 -15
  43. package/dist/lib/slug.d.ts +5 -1
  44. package/dist/lib/slug.js +52 -9
  45. package/dist/lib/update-cache.js +4 -4
  46. package/dist/lib/version-check.d.ts +3 -3
  47. package/dist/lib/version-check.js +13 -13
  48. package/dist/prompts/_business-card.md +41 -0
  49. package/dist/prompts/_error-handling.md +38 -0
  50. package/dist/prompts/_requirements-check.md +59 -0
  51. package/dist/prompts/_setup-cli.md +19 -0
  52. package/dist/prompts/_setup-login.md +7 -0
  53. package/dist/prompts/_setup-org.md +27 -0
  54. package/dist/prompts/business-card.md +41 -0
  55. package/dist/prompts/error-handling.md +38 -0
  56. package/dist/prompts/index.d.ts +7 -0
  57. package/dist/prompts/index.js +28 -0
  58. package/dist/prompts/install.md +187 -0
  59. package/dist/prompts/publish.md +444 -0
  60. package/dist/prompts/requirements-check.md +59 -0
  61. package/dist/types.d.ts +10 -10
  62. package/package.json +3 -3
@@ -1,54 +1,38 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.joinSpace = joinSpace;
3
+ exports.joinOrg = joinOrg;
4
4
  exports.registerJoin = registerJoin;
5
5
  const config_js_1 = require("../lib/config.js");
6
6
  const init_js_1 = require("./init.js");
7
- async function fetchSpaceTeams(spaceSlug, token) {
8
- const res = await fetch(`${config_js_1.API_URL}/api/spaces/${spaceSlug}/teams`, {
9
- headers: { Authorization: `Bearer ${token}` },
10
- signal: AbortSignal.timeout(5000),
11
- });
12
- if (!res.ok)
13
- throw new Error(`${res.status}`);
14
- const data = (await res.json());
15
- if (Array.isArray(data))
16
- return data;
17
- return data.teams ?? [];
18
- }
19
- async function joinSpace(spaceSlug, code) {
7
+ async function joinOrg(orgSlug, code) {
20
8
  const token = await (0, config_js_1.getValidToken)();
21
9
  if (!token) {
22
10
  throw new Error('LOGIN_REQUIRED');
23
11
  }
24
- const res = await fetch(`${config_js_1.API_URL}/api/spaces/${spaceSlug}/join`, {
12
+ // Use the access code via API
13
+ const res = await fetch(`${config_js_1.API_URL}/api/access-codes/${code}/use`, {
25
14
  method: 'POST',
26
15
  headers: {
27
16
  'Content-Type': 'application/json',
28
17
  Authorization: `Bearer ${token}`,
29
18
  },
30
- body: JSON.stringify({ code }),
31
19
  });
32
- const body = (await res.json().catch(() => ({})));
33
20
  if (!res.ok) {
21
+ const body = await res.json().catch(() => ({}));
34
22
  const errCode = body.error ?? String(res.status);
35
23
  switch (errCode) {
36
- case 'INVALID_CODE':
37
- throw new Error('초대 코드가 올바르지 않습니다.');
38
- case 'EXPIRED_CODE':
39
- throw new Error('초대 코드가 만료되었습니다.');
40
- case 'ALREADY_MEMBER':
41
- throw new Error('ALREADY_MEMBER');
24
+ case 'INVALID_LINK':
25
+ throw new Error('초대 코드가 유효하지 않거나 만료되었습니다.');
42
26
  default:
43
- throw new Error(body.message ?? `Space 가입 실패 (${res.status})`);
27
+ throw new Error(body.message ?? `가입 실패 (${res.status})`);
44
28
  }
45
29
  }
46
- return { spaceName: body.space_name ?? spaceSlug };
30
+ return res.json();
47
31
  }
48
32
  function registerJoin(program) {
49
33
  program
50
34
  .command('join <slug>')
51
- .description('Space에 초대 코드로 가입합니다')
35
+ .description('Organization에 초대 코드로 가입합니다')
52
36
  .requiredOption('--code <code>', '초대 코드 (UUID)')
53
37
  .action(async (slug, opts) => {
54
38
  const json = program.opts().json ?? false;
@@ -62,57 +46,22 @@ function registerJoin(program) {
62
46
  process.exit(1);
63
47
  }
64
48
  try {
65
- const { spaceName } = await joinSpace(slug, opts.code);
49
+ const result = await joinOrg(slug, opts.code);
66
50
  if (json) {
67
- // best-effort: fetch teams for JSON response
68
- let teams = [];
69
- try {
70
- const token = await (0, config_js_1.getValidToken)();
71
- if (token)
72
- teams = await fetchSpaceTeams(slug, token);
73
- }
74
- catch {
75
- // ignore
76
- }
77
- console.log(JSON.stringify({ status: 'ok', space: slug, space_name: spaceName, teams: teams.map((t) => ({ slug: t.slug, name: t.name })) }));
51
+ console.log(JSON.stringify({ status: 'ok', ...result }));
78
52
  }
79
53
  else {
80
- console.log(`\x1b[32m✅ ${spaceName} Space에 가입했습니다\x1b[0m`);
81
- // best-effort: show available teams
82
- try {
83
- const token = await (0, config_js_1.getValidToken)();
84
- if (token) {
85
- const teams = await fetchSpaceTeams(slug, token);
86
- if (teams.length === 0) {
87
- console.log('\n아직 추가된 팀이 없습니다.');
88
- }
89
- else {
90
- console.log('\n\x1b[1m📦 사용 가능한 팀:\x1b[0m');
91
- for (const t of teams) {
92
- const desc = t.description ? ` \x1b[90m— ${t.description}\x1b[0m` : '';
93
- console.log(` \x1b[36m•\x1b[0m \x1b[1m${t.slug}\x1b[0m${desc}`);
94
- }
95
- console.log(`\n\x1b[33m💡 전체 설치: relay install @spaces/${slug}/<팀슬러그>\x1b[0m`);
96
- console.log(`\x1b[33m💡 가이드 URL 공유: https://relayax.com/api/spaces/${slug}/guide.md\x1b[0m`);
97
- }
98
- }
54
+ if (result.type === 'org') {
55
+ console.log(`\x1b[32m✅ @${slug} Organization에 가입했습니다 (역할: ${result.role ?? 'member'})\x1b[0m`);
56
+ console.log(`\n\x1b[33m 대시보드: www.relayax.com/orgs/${slug}\x1b[0m`);
99
57
  }
100
- catch {
101
- // ignore success message was already shown
58
+ else {
59
+ console.log(`\x1b[32m✅ 에이전트 접근 권한이 부여되었습니다\x1b[0m`);
102
60
  }
103
61
  }
104
62
  }
105
63
  catch (err) {
106
64
  const message = err instanceof Error ? err.message : String(err);
107
- if (message === 'ALREADY_MEMBER') {
108
- if (json) {
109
- console.log(JSON.stringify({ status: 'already_member', space: slug }));
110
- }
111
- else {
112
- console.log(`\x1b[33m이미 ${slug} Space의 멤버입니다.\x1b[0m`);
113
- }
114
- return;
115
- }
116
65
  if (message === 'LOGIN_REQUIRED') {
117
66
  if (json) {
118
67
  console.error(JSON.stringify({
@@ -128,7 +77,7 @@ function registerJoin(program) {
128
77
  process.exit(1);
129
78
  }
130
79
  if (json) {
131
- console.error(JSON.stringify({ error: 'JOIN_FAILED', message, fix: 'Space slug와 초대 코드를 확인 후 재시도하세요.' }));
80
+ console.error(JSON.stringify({ error: 'JOIN_FAILED', message, fix: 'slug와 초대 코드를 확인 후 재시도하세요.' }));
132
81
  }
133
82
  else {
134
83
  console.error(`\x1b[31m오류: ${message}\x1b[0m`);
@@ -2,30 +2,27 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registerList = registerList;
4
4
  const config_js_1 = require("../lib/config.js");
5
- async function fetchSpaceTeamList(spaceSlug, token) {
6
- const res = await fetch(`${config_js_1.API_URL}/api/spaces/${spaceSlug}/teams`, {
5
+ async function fetchOrgAgentList(orgSlug, token) {
6
+ const res = await fetch(`${config_js_1.API_URL}/api/orgs/${orgSlug}/agents`, {
7
7
  headers: { Authorization: `Bearer ${token}` },
8
8
  signal: AbortSignal.timeout(8000),
9
9
  });
10
10
  if (!res.ok) {
11
11
  const body = await res.text();
12
- throw new Error(`Space 목록 조회 실패 (${res.status}): ${body}`);
12
+ throw new Error(`Org 에이전트 목록 조회 실패 (${res.status}): ${body}`);
13
13
  }
14
- const data = (await res.json());
15
- if (Array.isArray(data))
16
- return data;
17
- return data.teams ?? [];
14
+ return (await res.json());
18
15
  }
19
16
  function registerList(program) {
20
17
  program
21
18
  .command('list')
22
- .description('설치된 에이전트 목록')
23
- .option('--space <slug>', 'Space 목록 조회')
19
+ .description('설치된 에이전트 목록')
20
+ .option('--org <slug>', 'Organization 에이전트 목록 조회')
24
21
  .action(async (opts) => {
25
22
  const json = program.opts().json ?? false;
26
- // --space 옵션: Space 목록
27
- if (opts.space) {
28
- const spaceSlug = opts.space;
23
+ // --org 옵션: Org 에이전트 목록
24
+ if (opts.org) {
25
+ const orgSlug = opts.org;
29
26
  const token = await (0, config_js_1.getValidToken)();
30
27
  if (!token) {
31
28
  if (json) {
@@ -38,23 +35,23 @@ function registerList(program) {
38
35
  process.exit(1);
39
36
  }
40
37
  try {
41
- const teams = await fetchSpaceTeamList(spaceSlug, token);
38
+ const agents = await fetchOrgAgentList(orgSlug, token);
42
39
  if (json) {
43
- console.log(JSON.stringify({ space: spaceSlug, teams }));
40
+ console.log(JSON.stringify({ org: orgSlug, agents }));
44
41
  return;
45
42
  }
46
- if (teams.length === 0) {
47
- console.log(`\n${spaceSlug} Space추가된 팀이 없습니다.`);
43
+ if (agents.length === 0) {
44
+ console.log(`\n@${orgSlug} Organization에이전트가 없습니다.`);
48
45
  return;
49
46
  }
50
- console.log(`\n\x1b[1m${spaceSlug} Space 목록\x1b[0m (${teams.length}개):\n`);
51
- for (const t of teams) {
47
+ console.log(`\n\x1b[1m@${orgSlug} 에이전트 목록\x1b[0m (${agents.length}개):\n`);
48
+ for (const t of agents) {
52
49
  const desc = t.description
53
50
  ? ` \x1b[90m${t.description.length > 50 ? t.description.slice(0, 50) + '...' : t.description}\x1b[0m`
54
51
  : '';
55
- console.log(` \x1b[36m${t.slug}\x1b[0m \x1b[1m${t.name}\x1b[0m${desc}`);
52
+ console.log(` \x1b[36m@${t.owner}/${t.slug}\x1b[0m \x1b[1m${t.name}\x1b[0m${desc}`);
56
53
  }
57
- console.log(`\n\x1b[33m💡 설치: relay install @spaces/${spaceSlug}/<팀슬러그>\x1b[0m`);
54
+ console.log(`\n\x1b[33m 설치: relay install @${orgSlug}/<에이전트슬러그>\x1b[0m`);
58
55
  }
59
56
  catch (err) {
60
57
  const message = err instanceof Error ? err.message : String(err);
@@ -80,7 +77,7 @@ function registerList(program) {
80
77
  installed_at: info.installed_at,
81
78
  scope: 'global',
82
79
  deploy_scope: info.deploy_scope,
83
- space_slug: info.space_slug,
80
+ org_slug: info.org_slug,
84
81
  });
85
82
  seen.add(slug);
86
83
  }
@@ -94,7 +91,7 @@ function registerList(program) {
94
91
  installed_at: info.installed_at,
95
92
  scope: 'local',
96
93
  deploy_scope: info.deploy_scope,
97
- space_slug: info.space_slug,
94
+ org_slug: info.org_slug,
98
95
  });
99
96
  }
100
97
  if (json) {
@@ -102,10 +99,10 @@ function registerList(program) {
102
99
  }
103
100
  else {
104
101
  if (allEntries.length === 0) {
105
- console.log('\n설치된 팀이 없습니다. `relay install <slug>`로 설치하세요.');
102
+ console.log('\n설치된 에이전트가 없습니다. `relay install <slug>`로 설치하세요.');
106
103
  return;
107
104
  }
108
- console.log(`\n설치된 (${allEntries.length}개):\n`);
105
+ console.log(`\n설치된 에이전트 (${allEntries.length}개):\n`);
109
106
  for (const item of allEntries) {
110
107
  const date = new Date(item.installed_at).toLocaleDateString('ko-KR');
111
108
  const scopeLabel = item.deploy_scope === 'global'
@@ -113,8 +110,8 @@ function registerList(program) {
113
110
  : item.deploy_scope === 'local'
114
111
  ? '\x1b[33m로컬\x1b[0m'
115
112
  : '\x1b[90m미배치\x1b[0m';
116
- const spaceLabel = item.space_slug ? ` \x1b[90m[Space: ${item.space_slug}]\x1b[0m` : '';
117
- console.log(` \x1b[36m${item.slug}\x1b[0m v${item.version} ${scopeLabel} (${date})${spaceLabel}`);
113
+ const orgLabel = item.org_slug ? ` \x1b[90m[Org: ${item.org_slug}]\x1b[0m` : '';
114
+ console.log(` \x1b[36m${item.slug}\x1b[0m v${item.version} ${scopeLabel} (${date})${orgLabel}`);
118
115
  }
119
116
  }
120
117
  });
@@ -20,9 +20,10 @@ function openBrowser(url) {
20
20
  else {
21
21
  (0, child_process_1.execSync)(`xdg-open "${url}"`, { stdio: 'ignore' });
22
22
  }
23
+ return true;
23
24
  }
24
25
  catch {
25
- // ignore browser open errors
26
+ return false;
26
27
  }
27
28
  }
28
29
  async function verifyToken(token) {
@@ -106,10 +107,16 @@ function findAvailablePort() {
106
107
  async function loginWithBrowser(json) {
107
108
  const port = await findAvailablePort();
108
109
  const loginUrl = `${config_js_1.API_URL}/auth/cli-login?port=${port}`;
110
+ const opened = openBrowser(loginUrl);
109
111
  if (!json) {
110
- console.error(`브라우저에서 로그인 페이지를 엽니다...`);
112
+ if (opened) {
113
+ console.error(`브라우저에서 로그인 페이지를 엽니다...`);
114
+ }
115
+ else {
116
+ console.error(`브라우저를 자동으로 열 수 없습니다. 아래 URL을 브라우저에서 직접 열어주세요:\n`);
117
+ console.error(` ${loginUrl}\n`);
118
+ }
111
119
  }
112
- openBrowser(loginUrl);
113
120
  return waitForToken(port);
114
121
  }
115
122
  /**
@@ -0,0 +1,10 @@
1
+ import { Command } from 'commander';
2
+ export interface OrgInfo {
3
+ id: string;
4
+ slug: string;
5
+ name: string;
6
+ description: string | null;
7
+ role: string;
8
+ }
9
+ export declare function fetchMyOrgs(token: string): Promise<OrgInfo[]>;
10
+ export declare function registerOrgs(program: Command): void;
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchMyOrgs = fetchMyOrgs;
4
+ exports.registerOrgs = registerOrgs;
5
+ const config_js_1 = require("../lib/config.js");
6
+ async function fetchMyOrgs(token) {
7
+ const res = await fetch(`${config_js_1.API_URL}/api/orgs`, {
8
+ headers: { Authorization: `Bearer ${token}` },
9
+ signal: AbortSignal.timeout(8000),
10
+ });
11
+ if (!res.ok) {
12
+ throw new Error(`Organization 목록 조회 실패 (${res.status})`);
13
+ }
14
+ return (await res.json());
15
+ }
16
+ function registerOrgs(program) {
17
+ const orgsCmd = program
18
+ .command('orgs')
19
+ .description('Organization 관련 명령어');
20
+ orgsCmd
21
+ .command('list')
22
+ .description('내 Organization 목록을 확인합니다')
23
+ .action(async () => {
24
+ const json = program.opts().json ?? false;
25
+ const token = await (0, config_js_1.getValidToken)();
26
+ if (!token) {
27
+ if (json) {
28
+ console.error(JSON.stringify({ error: 'LOGIN_REQUIRED', message: '로그인이 필요합니다.', fix: 'relay login 실행 후 재시도하세요.' }));
29
+ }
30
+ else {
31
+ console.error('\x1b[31m오류: 로그인이 필요합니다.\x1b[0m');
32
+ console.error(' relay login을 먼저 실행하세요.');
33
+ }
34
+ process.exit(1);
35
+ }
36
+ try {
37
+ const orgs = await fetchMyOrgs(token);
38
+ if (json) {
39
+ console.log(JSON.stringify({ orgs }));
40
+ return;
41
+ }
42
+ if (orgs.length === 0) {
43
+ console.log('\nOrganization이 없습니다.');
44
+ console.log('\x1b[33m Organization을 만들려면: relay orgs create "이름"\x1b[0m');
45
+ }
46
+ else {
47
+ console.log(`\n\x1b[1m내 Organization\x1b[0m (${orgs.length}개):\n`);
48
+ for (const o of orgs) {
49
+ const role = o.role === 'owner' ? '\x1b[33m오너\x1b[0m'
50
+ : o.role === 'admin' ? '\x1b[36m관리자\x1b[0m'
51
+ : o.role === 'builder' ? '\x1b[36m빌더\x1b[0m'
52
+ : '\x1b[90m멤버\x1b[0m';
53
+ const desc = o.description
54
+ ? ` \x1b[90m${o.description.length > 40 ? o.description.slice(0, 40) + '...' : o.description}\x1b[0m`
55
+ : '';
56
+ console.log(` \x1b[36m@${o.slug}\x1b[0m \x1b[1m${o.name}\x1b[0m ${role}${desc}`);
57
+ }
58
+ }
59
+ }
60
+ catch (err) {
61
+ const message = err instanceof Error ? err.message : String(err);
62
+ if (json) {
63
+ console.error(JSON.stringify({ error: 'FETCH_FAILED', message, fix: '네트워크 연결을 확인하거나 잠시 후 재시도하세요.' }));
64
+ }
65
+ else {
66
+ console.error(`\x1b[31m오류: ${message}\x1b[0m`);
67
+ }
68
+ process.exit(1);
69
+ }
70
+ });
71
+ orgsCmd
72
+ .command('create <name>')
73
+ .description('새 Organization을 생성합니다')
74
+ .option('--slug <slug>', 'URL slug (미지정 시 이름에서 자동 생성)')
75
+ .action(async (name, opts) => {
76
+ const json = program.opts().json ?? false;
77
+ const token = await (0, config_js_1.getValidToken)();
78
+ if (!token) {
79
+ if (json) {
80
+ console.error(JSON.stringify({ error: 'LOGIN_REQUIRED', message: '로그인이 필요합니다.', fix: 'relay login 실행 후 재시도하세요.' }));
81
+ }
82
+ else {
83
+ console.error('\x1b[31m오류: 로그인이 필요합니다.\x1b[0m');
84
+ }
85
+ process.exit(1);
86
+ }
87
+ const slug = opts.slug ?? name
88
+ .toLowerCase()
89
+ .replace(/[^a-z0-9\s-]/g, '')
90
+ .replace(/[\s]+/g, '-')
91
+ .replace(/-+/g, '-')
92
+ .replace(/^-|-$/g, '')
93
+ .slice(0, 50);
94
+ try {
95
+ const res = await fetch(`${config_js_1.API_URL}/api/orgs`, {
96
+ method: 'POST',
97
+ headers: {
98
+ 'Content-Type': 'application/json',
99
+ Authorization: `Bearer ${token}`,
100
+ },
101
+ body: JSON.stringify({ name, slug }),
102
+ });
103
+ if (!res.ok) {
104
+ const body = await res.json().catch(() => ({ message: `${res.status}` }));
105
+ throw new Error(body.message ?? `Organization 생성 실패 (${res.status})`);
106
+ }
107
+ const org = await res.json();
108
+ if (json) {
109
+ console.log(JSON.stringify({ status: 'created', org }));
110
+ }
111
+ else {
112
+ console.log(`\x1b[32m✅ Organization "${org.name}" (@${org.slug}) 생성 완료\x1b[0m`);
113
+ console.log(`\n\x1b[33m 에이전트 배포: relay publish --org ${org.slug}\x1b[0m`);
114
+ console.log(`\x1b[33m 멤버 초대: www.relayax.com/orgs/${org.slug}/members\x1b[0m`);
115
+ }
116
+ }
117
+ catch (err) {
118
+ const message = err instanceof Error ? err.message : String(err);
119
+ if (json) {
120
+ console.error(JSON.stringify({ error: 'CREATE_FAILED', message }));
121
+ }
122
+ else {
123
+ console.error(`\x1b[31m오류: ${message}\x1b[0m`);
124
+ }
125
+ process.exit(1);
126
+ }
127
+ });
128
+ }
@@ -6,7 +6,7 @@ const config_js_1 = require("../lib/config.js");
6
6
  function registerOutdated(program) {
7
7
  program
8
8
  .command('outdated')
9
- .description('설치된 팀의 업데이트 가능 여부를 확인합니다')
9
+ .description('설치된 에이전트의 업데이트 가능 여부를 확인합니다')
10
10
  .action(async () => {
11
11
  const json = program.opts().json ?? false;
12
12
  const installed = (0, config_js_1.loadInstalled)();
@@ -16,7 +16,7 @@ function registerOutdated(program) {
16
16
  console.log(JSON.stringify([]));
17
17
  }
18
18
  else {
19
- console.log('설치된 팀이 없습니다.');
19
+ console.log('설치된 에이전트가 없습니다.');
20
20
  }
21
21
  return;
22
22
  }
@@ -24,8 +24,8 @@ function registerOutdated(program) {
24
24
  const results = await Promise.all(slugs.map(async (slug) => {
25
25
  const current = installed[slug].version;
26
26
  try {
27
- const team = await (0, api_js_1.fetchTeamInfo)(slug);
28
- const latest = team.version;
27
+ const agent = await (0, api_js_1.fetchAgentInfo)(slug);
28
+ const latest = agent.version;
29
29
  return {
30
30
  slug,
31
31
  current,
@@ -43,15 +43,15 @@ function registerOutdated(program) {
43
43
  }
44
44
  const allUpToDate = results.every((r) => r.status === 'up-to-date');
45
45
  if (allUpToDate) {
46
- console.log('모든 팀이 최신 버전입니다.');
46
+ console.log('모든 에이전트가 최신 버전입니다.');
47
47
  return;
48
48
  }
49
49
  // Determine column widths
50
- const COL_TEAM = Math.max(4, ...results.map((r) => r.slug.length));
50
+ const COL_TEAM = Math.max(9, ...results.map((r) => r.slug.length));
51
51
  const COL_CURRENT = Math.max(4, ...results.map((r) => `v${r.current}`.length));
52
52
  const COL_LATEST = Math.max(4, ...results.map((r) => `v${r.latest}`.length));
53
53
  const pad = (s, len) => s.padEnd(len);
54
- const header = `${pad('', COL_TEAM)} ${pad('현재', COL_CURRENT)} ${pad('최신', COL_LATEST)} 상태`;
54
+ const header = `${pad('에이전트', COL_TEAM)} ${pad('현재', COL_CURRENT)} ${pad('최신', COL_LATEST)} 상태`;
55
55
  const separator = '-'.repeat(header.length);
56
56
  console.log(header);
57
57
  console.log(separator);
@@ -1,2 +1,20 @@
1
1
  import { Command } from 'commander';
2
+ import type { ContentType } from '../lib/ai-tools.js';
3
+ export interface ContentEntry {
4
+ name: string;
5
+ type: ContentType;
6
+ from: string;
7
+ }
8
+ /**
9
+ * 패키지 홈 디렉토리를 결정한다.
10
+ * 1. 프로젝트에 .relay/가 있으면 → projectPath/.relay/
11
+ * 2. 없으면 → ~/.relay/agents/<slug>/ (slug 필요)
12
+ *
13
+ * slug가 없고 프로젝트에도 .relay/가 없으면 null 반환.
14
+ */
15
+ export declare function resolveRelayDir(projectPath: string, slug?: string): string | null;
16
+ /**
17
+ * 글로벌 에이전트 홈에 패키지 구조를 초기화한다.
18
+ */
19
+ export declare function initGlobalAgentHome(slug: string, yamlData: Record<string, unknown>): string;
2
20
  export declare function registerPackage(program: Command): void;