relayax-cli 0.4.30 → 0.4.31

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.
@@ -209,7 +209,7 @@ function registerInstall(program) {
209
209
  const detectedValues = new Set(detected.map((t) => t.value));
210
210
  const { checkbox } = await import('@inquirer/prompts');
211
211
  selectedTools = await checkbox({
212
- message: '설치할 AI 도구를 선택하��요 (감지된 도구는 자동 선���됨)',
212
+ message: '설치할 AI 도구를 선택하세요 (감지된 도구는 자동 선택됨)',
213
213
  choices: ai_tools_js_1.AI_TOOLS.map((t) => ({
214
214
  name: t.name,
215
215
  value: t,
@@ -237,12 +237,12 @@ function registerInstall(program) {
237
237
  }
238
238
  else if (interactive) {
239
239
  const { select } = await import('@inquirer/prompts');
240
- const recommendLabel = defaultScope === 'global' ? '글로벌' : '로���';
240
+ const recommendLabel = defaultScope === 'global' ? '글로벌' : '로컬';
241
241
  scope = await select({
242
242
  message: `설치 범위를 선택하세요 (제작자 권장: ${recommendLabel})`,
243
243
  choices: [
244
- { name: '글로벌 (~/.relay/agents/) — 모든 프���젝트에서 사��', value: 'global' },
245
- { name: '로컬 (./.relay/agents/) — 이 프로젝트에서만 사���', value: 'local' },
244
+ { name: '글로벌 (~/.relay/agents/) — 모든 프로젝트에서 사용', value: 'global' },
245
+ { name: '로컬 (./.relay/agents/) — 이 프로젝트에서만 사용', value: 'local' },
246
246
  ],
247
247
  default: defaultScope,
248
248
  });
@@ -371,29 +371,35 @@ function registerInstall(program) {
371
371
  console.log(` 위치: \x1b[36m${agentDir}\x1b[0m`);
372
372
  console.log(` 범위: ${scopeLabel}`);
373
373
  console.log(` 파일: ${fileCount}개, symlink: ${deploy.symlinks.length}개`);
374
- if (resolvedAgent.commands.length > 0) {
374
+ const userCommands = resolvedAgent.commands.filter((c) => !c.name.startsWith('setup-'));
375
+ if (userCommands.length > 0) {
375
376
  console.log('\n 포함된 커맨드:');
376
- for (const cmd of resolvedAgent.commands) {
377
+ for (const cmd of userCommands) {
377
378
  console.log(` \x1b[33m/${cmd.name}\x1b[0m - ${cmd.description}`);
378
379
  }
379
380
  }
380
- // Usage hint (type-aware)
381
+ // Usage hint (type-aware, setup command 제외)
381
382
  const agentType = resolvedAgent.type;
383
+ const mainCommand = userCommands[0];
382
384
  if (agentType === 'passive') {
383
385
  console.log(`\n\x1b[33m💡 자동 적용됩니다. 별도 실행 없이 동작합니다.\x1b[0m`);
384
386
  }
385
- else if (agentType === 'hybrid' && resolvedAgent.commands && resolvedAgent.commands.length > 0) {
386
- console.log(`\n\x1b[33m💡 자동 적용 + \x1b[1m/${resolvedAgent.commands[0].name}\x1b[0m\x1b[33m 으로 추가 기능을 사용할 수 있습니다.\x1b[0m`);
387
+ else if (agentType === 'hybrid' && mainCommand) {
388
+ console.log(`\n\x1b[33m💡 자동 적용 + \x1b[1m/${mainCommand.name}\x1b[0m\x1b[33m 으로 추가 기능을 사용할 수 있습니다.\x1b[0m`);
387
389
  }
388
- else if (resolvedAgent.commands && resolvedAgent.commands.length > 0) {
389
- console.log(`\n\x1b[33m💡 사용법: \x1b[1m/${resolvedAgent.commands[0].name}\x1b[0m`);
390
+ else if (mainCommand) {
391
+ console.log(`\n\x1b[33m💡 사용법: \x1b[1m/${mainCommand.name}\x1b[0m`);
390
392
  }
391
393
  else {
392
394
  console.log(`\n\x1b[33m💡 설치 완료! AI 에이전트에서 사용할 수 있습니다.\x1b[0m`);
393
395
  }
394
- // Requires check
396
+ // Requires check + setup CTA
395
397
  const requiresResults = (0, installer_js_1.checkRequires)(agentDir);
396
398
  (0, installer_js_1.printRequiresCheck)(requiresResults);
399
+ const setupCmd = resolvedAgent.commands.find((c) => c.name.startsWith('setup-'));
400
+ if (setupCmd && requiresResults.some((r) => r.status === 'missing' || r.status === 'warn')) {
401
+ console.log(`\n \x1b[36m👉 설정이 필요합니다: \x1b[1m/${setupCmd.name}\x1b[0m\x1b[36m 을 실행하세요\x1b[0m`);
402
+ }
397
403
  }
398
404
  }
399
405
  catch (err) {
@@ -15,6 +15,7 @@ const paths_js_1 = require("../lib/paths.js");
15
15
  const error_report_js_1 = require("../lib/error-report.js");
16
16
  const step_tracker_js_1 = require("../lib/step-tracker.js");
17
17
  const git_operations_js_1 = require("../lib/git-operations.js");
18
+ const setup_command_js_1 = require("../lib/setup-command.js");
18
19
  // eslint-disable-next-line @typescript-eslint/no-var-requires
19
20
  const cliPkg = require('../../package.json');
20
21
  const VALID_DIRS = ['skills', 'agents', 'rules', 'commands', 'bin'];
@@ -726,6 +727,13 @@ function registerPublish(program) {
726
727
  const entrySlug = config.slug.startsWith('@') ? config.slug.slice(1) : config.slug;
727
728
  const entryFileName = entrySlug.replace('/', '-') + '.md';
728
729
  fs_1.default.writeFileSync(path_1.default.join(commandsDir, entryFileName), entryContent);
730
+ // Generate setup command if requires exist
731
+ const mainCmd = detectedCommands.find((c) => !c.name.startsWith('setup-'));
732
+ const setupContent = (0, setup_command_js_1.generateSetupCommand)(config.name, config.requires, mainCmd?.name);
733
+ if (setupContent) {
734
+ const setupFileName = `setup-${config.name}.md`;
735
+ fs_1.default.writeFileSync(path_1.default.join(commandsDir, setupFileName), setupContent);
736
+ }
729
737
  // Check git is available
730
738
  try {
731
739
  (0, git_operations_js_1.checkGitInstalled)();
@@ -0,0 +1,6 @@
1
+ import type { Requires } from '../commands/publish.js';
2
+ /**
3
+ * relay.yaml의 requires를 기반으로 setup slash command .md 내용을 생성한다.
4
+ * requires가 없거나 빈 객체이면 null을 반환한다.
5
+ */
6
+ export declare function generateSetupCommand(agentName: string, requires: Requires | undefined, mainCommandName?: string): string | null;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateSetupCommand = generateSetupCommand;
4
+ /**
5
+ * relay.yaml의 requires를 기반으로 setup slash command .md 내용을 생성한다.
6
+ * requires가 없거나 빈 객체이면 null을 반환한다.
7
+ */
8
+ function generateSetupCommand(agentName, requires, mainCommandName) {
9
+ if (!requires)
10
+ return null;
11
+ const sections = [];
12
+ // runtime
13
+ if (requires.runtime) {
14
+ const items = [];
15
+ if (requires.runtime.node)
16
+ items.push(`- Node.js \`>=${requires.runtime.node}\``);
17
+ if (requires.runtime.python)
18
+ items.push(`- Python \`>=${requires.runtime.python}\``);
19
+ if (items.length > 0) {
20
+ sections.push(`### 런타임\n${items.join('\n')}`);
21
+ }
22
+ }
23
+ // cli
24
+ if (requires.cli && requires.cli.length > 0) {
25
+ const items = requires.cli.map((c) => {
26
+ const req = c.required !== false ? '필수' : '선택';
27
+ const install = c.install ? ` — 설치: \`${c.install}\`` : '';
28
+ return `- \`${c.name}\` (${req})${install}`;
29
+ });
30
+ sections.push(`### CLI 도구\n${items.join('\n')}`);
31
+ }
32
+ // env
33
+ if (requires.env && requires.env.length > 0) {
34
+ const items = requires.env.map((e) => {
35
+ const req = e.required !== false ? '필수' : '선택';
36
+ const desc = e.description ? ` — ${e.description}` : '';
37
+ const hint = e.setup_hint ? `\n 설정 방법:\n${e.setup_hint.split('\n').map((l) => ` ${l}`).join('\n')}` : '';
38
+ return `- \`${e.name}\` (${req})${desc}${hint}`;
39
+ });
40
+ sections.push(`### 환경변수\n${items.join('\n')}`);
41
+ }
42
+ // npm
43
+ if (requires.npm && requires.npm.length > 0) {
44
+ const items = requires.npm.map((n) => {
45
+ const name = typeof n === 'string' ? n : n.name;
46
+ const req = typeof n === 'string' ? '필수' : (n.required !== false ? '필수' : '선택');
47
+ return `- \`${name}\` (${req})`;
48
+ });
49
+ sections.push(`### npm 패키지\n${items.join('\n')}`);
50
+ }
51
+ // mcp
52
+ if (requires.mcp && requires.mcp.length > 0) {
53
+ const items = requires.mcp.map((m) => {
54
+ const req = m.required !== false ? '필수' : '선택';
55
+ const pkg = m.package ? ` — 패키지: \`${m.package}\`` : '';
56
+ const envList = m.env && m.env.length > 0 ? `\n 필요한 환경변수: ${m.env.map((e) => `\`${e}\``).join(', ')}` : '';
57
+ const config = m.config ? `\n 설정: \`${JSON.stringify(m.config)}\`` : '';
58
+ return `- \`${m.name}\` MCP 서버 (${req})${pkg}${envList}${config}`;
59
+ });
60
+ sections.push(`### MCP 서버\n${items.join('\n')}`);
61
+ }
62
+ if (sections.length === 0)
63
+ return null;
64
+ const body = `# ${agentName} 설정 가이드
65
+
66
+ 아래 요구사항을 각각 체크하고, 미충족 항목이 있으면 사용자가 설정할 수 있도록 안내하세요.
67
+ 모든 항목이 충족될 때까지 멈추지 말고 끝까지 진행하세요.
68
+ ${mainCommandName ? `\n모든 설정이 완료되면 \`/${mainCommandName}\`으로 에이전트를 사용할 수 있다고 안내하세요.` : ''}
69
+
70
+ ${sections.join('\n\n')}`;
71
+ return `---\ndescription: ${agentName} 설정 가이드 — 필수 요구사항을 확인하고 설정합니다\n---\n\n${body}\n`;
72
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relayax-cli",
3
- "version": "0.4.30",
3
+ "version": "0.4.31",
4
4
  "description": "RelayAX Agent Team Marketplace CLI - Install and manage agent teams",
5
5
  "main": "dist/index.js",
6
6
  "bin": {