relayax-cli 0.2.26 → 0.2.28
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.
- package/README.md +5 -5
- package/dist/commands/create.js +3 -7
- package/dist/commands/init.d.ts +3 -1
- package/dist/commands/init.js +29 -20
- package/dist/commands/install.js +2 -1
- package/dist/commands/ping.d.ts +2 -0
- package/dist/commands/ping.js +39 -0
- package/dist/commands/publish.js +35 -71
- package/dist/index.js +2 -0
- package/dist/lib/ai-tools.d.ts +5 -0
- package/dist/lib/ai-tools.js +10 -0
- package/dist/lib/command-adapter.d.ts +11 -2
- package/dist/lib/command-adapter.js +348 -228
- package/dist/lib/preamble.d.ts +13 -4
- package/dist/lib/preamble.js +53 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,11 +6,11 @@ Agent Team Marketplace CLI - 에이전트 팀을 검색하고 설치하세요.
|
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
# 글로벌 설치 없이 바로 사용
|
|
9
|
-
npx relay-cli install
|
|
9
|
+
npx relay-cli install @author/team-name
|
|
10
10
|
|
|
11
11
|
# 또는 글로벌 설치
|
|
12
12
|
npm install -g relayax-cli
|
|
13
|
-
relay install
|
|
13
|
+
relay install @author/team-name
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
## Commands
|
|
@@ -34,9 +34,9 @@ relay CLI는 에이전트가 1차 사용자입니다. 모든 출력은 JSON 기
|
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
36
|
# 에이전트가 팀 검색
|
|
37
|
-
relay search "
|
|
37
|
+
relay search "keyword" | jq '.results[].slug'
|
|
38
38
|
|
|
39
39
|
# 에이전트가 팀 설치
|
|
40
|
-
relay install
|
|
41
|
-
# → {"status":"ok","team":"
|
|
40
|
+
relay install @author/team-name
|
|
41
|
+
# → {"status":"ok","team":"Team Name","commands":[...]}
|
|
42
42
|
```
|
package/dist/commands/create.js
CHANGED
|
@@ -9,19 +9,15 @@ const path_1 = __importDefault(require("path"));
|
|
|
9
9
|
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
10
10
|
const ai_tools_js_1 = require("../lib/ai-tools.js");
|
|
11
11
|
const command_adapter_js_1 = require("../lib/command-adapter.js");
|
|
12
|
+
const init_js_1 = require("./init.js");
|
|
12
13
|
const DEFAULT_DIRS = ['.relay/skills', '.relay/commands'];
|
|
13
14
|
/**
|
|
14
15
|
* 글로벌 User 커맨드가 없으면 설치한다.
|
|
15
16
|
*/
|
|
16
17
|
function ensureGlobalUserCommands() {
|
|
17
|
-
|
|
18
|
-
if (allExist)
|
|
18
|
+
if ((0, init_js_1.hasGlobalUserCommands)())
|
|
19
19
|
return false;
|
|
20
|
-
|
|
21
|
-
fs_1.default.mkdirSync(globalDir, { recursive: true });
|
|
22
|
-
for (const cmd of command_adapter_js_1.USER_COMMANDS) {
|
|
23
|
-
fs_1.default.writeFileSync((0, command_adapter_js_1.getGlobalCommandPath)(cmd.id), (0, command_adapter_js_1.formatCommandFile)(cmd));
|
|
24
|
-
}
|
|
20
|
+
(0, init_js_1.installGlobalUserCommands)();
|
|
25
21
|
return true;
|
|
26
22
|
}
|
|
27
23
|
function registerCreate(program) {
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
/**
|
|
3
|
-
* 글로벌 User 커맨드를
|
|
3
|
+
* 글로벌 User 커맨드를 감지된 모든 에이전트 CLI에 설치한다.
|
|
4
|
+
* ~/{skillsDir}/commands/relay/ 에 설치.
|
|
4
5
|
* 기존 파일 중 현재 커맨드 목록에 없는 것은 제거한다.
|
|
5
6
|
*/
|
|
6
7
|
export declare function installGlobalUserCommands(): {
|
|
7
8
|
installed: boolean;
|
|
8
9
|
commands: string[];
|
|
10
|
+
tools: string[];
|
|
9
11
|
};
|
|
10
12
|
/**
|
|
11
13
|
* 글로벌 User 커맨드가 이미 설치되어 있는지 확인한다.
|
package/dist/commands/init.js
CHANGED
|
@@ -35,10 +35,8 @@ function showWelcome() {
|
|
|
35
35
|
' 에이전트 CLI에 relay 커맨드를 연결합니다.',
|
|
36
36
|
'',
|
|
37
37
|
' \x1b[2mUser 커맨드 (글로벌)\x1b[0m',
|
|
38
|
-
' /relay-
|
|
39
|
-
' /relay-
|
|
40
|
-
' /relay-list 설치된 팀 목록',
|
|
41
|
-
' /relay-update 팀 업데이트',
|
|
38
|
+
' /relay-install 팀 탐색 & 설치',
|
|
39
|
+
' /relay-status 설치 현황 & Space',
|
|
42
40
|
' /relay-uninstall 팀 삭제',
|
|
43
41
|
'',
|
|
44
42
|
];
|
|
@@ -62,31 +60,39 @@ async function selectToolsInteractively(detectedIds) {
|
|
|
62
60
|
return selected;
|
|
63
61
|
}
|
|
64
62
|
/**
|
|
65
|
-
* 글로벌 User 커맨드를
|
|
63
|
+
* 글로벌 User 커맨드를 감지된 모든 에이전트 CLI에 설치한다.
|
|
64
|
+
* ~/{skillsDir}/commands/relay/ 에 설치.
|
|
66
65
|
* 기존 파일 중 현재 커맨드 목록에 없는 것은 제거한다.
|
|
67
66
|
*/
|
|
68
67
|
function installGlobalUserCommands() {
|
|
69
|
-
const
|
|
70
|
-
fs_1.default.mkdirSync(globalDir, { recursive: true });
|
|
71
|
-
// 현재 커맨드 ID 세트
|
|
68
|
+
const globalCLIs = (0, ai_tools_js_1.detectGlobalCLIs)();
|
|
72
69
|
const currentIds = new Set(command_adapter_js_1.USER_COMMANDS.map((c) => c.id));
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
const commands = [];
|
|
71
|
+
const tools = [];
|
|
72
|
+
// 감지된 CLI가 없으면 Claude Code에만 설치 (기본)
|
|
73
|
+
const targetDirs = globalCLIs.length > 0
|
|
74
|
+
? globalCLIs.map((t) => ({ name: t.name, dir: (0, command_adapter_js_1.getGlobalCommandDirForTool)(t.skillsDir), getPath: (id) => (0, command_adapter_js_1.getGlobalCommandPathForTool)(t.skillsDir, id) }))
|
|
75
|
+
: [{ name: 'Claude Code', dir: (0, command_adapter_js_1.getGlobalCommandDir)(), getPath: (id) => (0, command_adapter_js_1.getGlobalCommandPath)(id) }];
|
|
76
|
+
for (const target of targetDirs) {
|
|
77
|
+
fs_1.default.mkdirSync(target.dir, { recursive: true });
|
|
78
|
+
// 기존 파일 중 현재 목록에 없는 것 제거
|
|
79
|
+
for (const file of fs_1.default.readdirSync(target.dir)) {
|
|
76
80
|
const id = file.replace(/\.md$/, '');
|
|
77
81
|
if (!currentIds.has(id)) {
|
|
78
|
-
fs_1.default.unlinkSync(path_1.default.join(
|
|
82
|
+
fs_1.default.unlinkSync(path_1.default.join(target.dir, file));
|
|
79
83
|
}
|
|
80
84
|
}
|
|
85
|
+
// 현재 커맨드 설치 (덮어쓰기)
|
|
86
|
+
for (const cmd of command_adapter_js_1.USER_COMMANDS) {
|
|
87
|
+
fs_1.default.writeFileSync(target.getPath(cmd.id), (0, command_adapter_js_1.formatCommandFile)(cmd));
|
|
88
|
+
}
|
|
89
|
+
tools.push(target.name);
|
|
81
90
|
}
|
|
82
|
-
//
|
|
83
|
-
const commands = [];
|
|
91
|
+
// commands 목록은 한 번만
|
|
84
92
|
for (const cmd of command_adapter_js_1.USER_COMMANDS) {
|
|
85
|
-
const filePath = (0, command_adapter_js_1.getGlobalCommandPath)(cmd.id);
|
|
86
|
-
fs_1.default.writeFileSync(filePath, (0, command_adapter_js_1.formatCommandFile)(cmd));
|
|
87
93
|
commands.push(cmd.id);
|
|
88
94
|
}
|
|
89
|
-
return { installed: true, commands };
|
|
95
|
+
return { installed: true, commands, tools };
|
|
90
96
|
}
|
|
91
97
|
/**
|
|
92
98
|
* 글로벌 User 커맨드가 이미 설치되어 있는지 확인한다.
|
|
@@ -128,15 +134,17 @@ function registerInit(program) {
|
|
|
128
134
|
const isBuilder = isTeamProject(projectPath);
|
|
129
135
|
// ── 1. 글로벌 User 커맨드 설치 ──
|
|
130
136
|
let globalStatus = 'already';
|
|
137
|
+
let globalTools = [];
|
|
131
138
|
if (opts.update || !hasGlobalUserCommands()) {
|
|
132
|
-
const
|
|
139
|
+
const result = installGlobalUserCommands();
|
|
133
140
|
globalStatus = opts.update ? 'updated' : 'installed';
|
|
141
|
+
globalTools = result.tools;
|
|
134
142
|
// Register relay-core in installed.json
|
|
135
143
|
const installed = (0, config_js_1.loadInstalled)();
|
|
136
144
|
installed['relay-core'] = {
|
|
137
145
|
version: pkg.version,
|
|
138
146
|
installed_at: new Date().toISOString(),
|
|
139
|
-
files: commands.map((c) => (0, command_adapter_js_1.getGlobalCommandPath)(c)),
|
|
147
|
+
files: result.commands.map((c) => (0, command_adapter_js_1.getGlobalCommandPath)(c)),
|
|
140
148
|
type: 'system',
|
|
141
149
|
};
|
|
142
150
|
(0, config_js_1.saveInstalled)(installed);
|
|
@@ -234,8 +242,9 @@ function registerInit(program) {
|
|
|
234
242
|
console.log(`\n\x1b[32m✓ relay ${opts.update ? '업데이트' : '초기화'} 완료\x1b[0m\n`);
|
|
235
243
|
// 글로벌
|
|
236
244
|
if (globalStatus !== 'already') {
|
|
245
|
+
const toolNames = globalTools.length > 0 ? globalTools.join(', ') : 'Claude Code';
|
|
237
246
|
console.log(` \x1b[36mUser 커맨드 (글로벌)\x1b[0m — ${globalStatus === 'updated' ? '업데이트됨' : '설치됨'}`);
|
|
238
|
-
console.log(` ${
|
|
247
|
+
console.log(` 감지된 CLI: \x1b[36m${toolNames}\x1b[0m`);
|
|
239
248
|
for (const cmd of command_adapter_js_1.USER_COMMANDS) {
|
|
240
249
|
console.log(` /${cmd.id}`);
|
|
241
250
|
}
|
package/dist/commands/install.js
CHANGED
|
@@ -190,8 +190,9 @@ function registerInstall(program) {
|
|
|
190
190
|
...(spaceTarget ? { space_slug: spaceTarget.spaceSlug } : {}),
|
|
191
191
|
};
|
|
192
192
|
(0, config_js_1.saveInstalled)(installed);
|
|
193
|
-
// 7. Report install (non-blocking)
|
|
193
|
+
// 7. Report install + usage ping (non-blocking)
|
|
194
194
|
await (0, api_js_1.reportInstall)(slug, team.version);
|
|
195
|
+
(0, api_js_1.sendUsagePing)(slug, team.version);
|
|
195
196
|
const result = {
|
|
196
197
|
status: 'ok',
|
|
197
198
|
team: team.name,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerPing = registerPing;
|
|
4
|
+
const api_js_1 = require("../lib/api.js");
|
|
5
|
+
const config_js_1 = require("../lib/config.js");
|
|
6
|
+
const slug_js_1 = require("../lib/slug.js");
|
|
7
|
+
function registerPing(program) {
|
|
8
|
+
program
|
|
9
|
+
.command('ping <slug>')
|
|
10
|
+
.description('사용 현황을 기록합니다 (preamble용 경량 명령)')
|
|
11
|
+
.option('--quiet', '출력 없이 실행')
|
|
12
|
+
.action(async (slugInput, opts) => {
|
|
13
|
+
// Resolve slug
|
|
14
|
+
let slug;
|
|
15
|
+
if ((0, slug_js_1.isScopedSlug)(slugInput)) {
|
|
16
|
+
slug = slugInput;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
const localRegistry = (0, config_js_1.loadInstalled)();
|
|
20
|
+
const globalRegistry = (0, config_js_1.loadGlobalInstalled)();
|
|
21
|
+
const allKeys = [...Object.keys(localRegistry), ...Object.keys(globalRegistry)];
|
|
22
|
+
const match = allKeys.find((key) => {
|
|
23
|
+
const parsed = (0, slug_js_1.parseSlug)(key);
|
|
24
|
+
return parsed && parsed.name === slugInput;
|
|
25
|
+
});
|
|
26
|
+
slug = match ?? slugInput;
|
|
27
|
+
}
|
|
28
|
+
// Resolve version from installed registry
|
|
29
|
+
const local = (0, config_js_1.loadInstalled)();
|
|
30
|
+
const global = (0, config_js_1.loadGlobalInstalled)();
|
|
31
|
+
const entry = local[slug] ?? global[slug];
|
|
32
|
+
const version = entry?.version;
|
|
33
|
+
// Fire-and-forget ping
|
|
34
|
+
await (0, api_js_1.sendUsagePing)(slug, version);
|
|
35
|
+
if (!opts.quiet) {
|
|
36
|
+
console.log(`RELAY_READY: ${slug}`);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
package/dist/commands/publish.js
CHANGED
|
@@ -15,7 +15,7 @@ const preamble_js_1 = require("../lib/preamble.js");
|
|
|
15
15
|
const version_check_js_1 = require("../lib/version-check.js");
|
|
16
16
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
17
17
|
const cliPkg = require('../../package.json');
|
|
18
|
-
const VALID_DIRS = ['skills', 'agents', 'rules', 'commands'];
|
|
18
|
+
const VALID_DIRS = ['skills', 'agents', 'rules', 'commands', 'bin'];
|
|
19
19
|
const IMAGE_EXTS = ['.png', '.jpg', '.jpeg', '.webp'];
|
|
20
20
|
/** 개별 포트폴리오 이미지 최대 크기 (2 MB) */
|
|
21
21
|
const MAX_IMAGE_SIZE = 2 * 1024 * 1024;
|
|
@@ -125,20 +125,28 @@ function detectSkills(teamDir) {
|
|
|
125
125
|
}
|
|
126
126
|
return entries;
|
|
127
127
|
}
|
|
128
|
-
|
|
128
|
+
/**
|
|
129
|
+
* 팀 진입점 커맨드(commands/{author}-{name}.md)를 생성한다.
|
|
130
|
+
* root SKILL.md를 대체하여 팀의 얼굴 역할을 한다.
|
|
131
|
+
*/
|
|
132
|
+
function generateEntryCommand(config, commands, skills, scopedSlug) {
|
|
129
133
|
const lines = [];
|
|
130
134
|
// Frontmatter
|
|
131
135
|
lines.push('---');
|
|
132
|
-
lines.push(`name: ${config.name}`);
|
|
133
136
|
lines.push(`description: ${config.description}`);
|
|
134
137
|
lines.push('---');
|
|
135
138
|
lines.push('');
|
|
136
139
|
// Preamble
|
|
137
140
|
lines.push((0, preamble_js_1.generatePreamble)(scopedSlug));
|
|
138
141
|
lines.push('');
|
|
142
|
+
// Team header
|
|
143
|
+
lines.push(`## ${config.name}`);
|
|
144
|
+
lines.push('');
|
|
145
|
+
lines.push(`v${config.version} — ${scopedSlug}`);
|
|
146
|
+
lines.push('');
|
|
139
147
|
// Skills
|
|
140
148
|
if (skills.length > 0) {
|
|
141
|
-
lines.push('
|
|
149
|
+
lines.push('### 사용 가능한 스킬');
|
|
142
150
|
lines.push('');
|
|
143
151
|
for (const s of skills) {
|
|
144
152
|
lines.push(`- **${s.name}**: ${s.description}`);
|
|
@@ -147,68 +155,17 @@ function generateRootSkillMd(config, commands, skills, scopedSlug) {
|
|
|
147
155
|
}
|
|
148
156
|
// Commands
|
|
149
157
|
if (commands.length > 0) {
|
|
150
|
-
lines.push('
|
|
158
|
+
lines.push('### 사용 가능한 커맨드');
|
|
151
159
|
lines.push('');
|
|
152
160
|
for (const c of commands) {
|
|
153
161
|
lines.push(`- **/${c.name}**: ${c.description}`);
|
|
154
162
|
}
|
|
155
163
|
lines.push('');
|
|
156
164
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
lines.push('');
|
|
162
|
-
if (req.env && req.env.length > 0) {
|
|
163
|
-
lines.push('### 환경변수');
|
|
164
|
-
for (const e of req.env) {
|
|
165
|
-
const name = typeof e === 'string' ? e : e.name;
|
|
166
|
-
const desc = typeof e === 'string' ? '' : e.description ?? '';
|
|
167
|
-
const required = typeof e === 'string' ? true : e.required !== false;
|
|
168
|
-
lines.push(`- \`${name}\` ${required ? '(필수)' : '(선택)'}${desc ? ' — ' + desc : ''}`);
|
|
169
|
-
}
|
|
170
|
-
lines.push('');
|
|
171
|
-
}
|
|
172
|
-
if (req.cli && req.cli.length > 0) {
|
|
173
|
-
lines.push('### CLI 도구');
|
|
174
|
-
for (const c of req.cli) {
|
|
175
|
-
const install = c.install ? ` — 설치: \`${c.install}\`` : '';
|
|
176
|
-
lines.push(`- \`${c.name}\`${install}`);
|
|
177
|
-
}
|
|
178
|
-
lines.push('');
|
|
179
|
-
}
|
|
180
|
-
if (req.npm && req.npm.length > 0) {
|
|
181
|
-
lines.push('### npm 패키지');
|
|
182
|
-
for (const n of req.npm) {
|
|
183
|
-
const name = typeof n === 'string' ? n : n.name;
|
|
184
|
-
lines.push(`- \`${name}\``);
|
|
185
|
-
}
|
|
186
|
-
lines.push('');
|
|
187
|
-
}
|
|
188
|
-
if (req.mcp && req.mcp.length > 0) {
|
|
189
|
-
lines.push('### MCP 서버');
|
|
190
|
-
for (const m of req.mcp) {
|
|
191
|
-
const pkg = m.package ? ` (\`${m.package}\`)` : '';
|
|
192
|
-
lines.push(`- **${m.name}**${pkg}`);
|
|
193
|
-
}
|
|
194
|
-
lines.push('');
|
|
195
|
-
}
|
|
196
|
-
if (req.runtime) {
|
|
197
|
-
lines.push('### 런타임');
|
|
198
|
-
if (req.runtime.node)
|
|
199
|
-
lines.push(`- Node.js ${req.runtime.node}`);
|
|
200
|
-
if (req.runtime.python)
|
|
201
|
-
lines.push(`- Python ${req.runtime.python}`);
|
|
202
|
-
lines.push('');
|
|
203
|
-
}
|
|
204
|
-
if (req.teams && req.teams.length > 0) {
|
|
205
|
-
lines.push('### 의존 팀');
|
|
206
|
-
for (const t of req.teams) {
|
|
207
|
-
lines.push(`- \`${t}\``);
|
|
208
|
-
}
|
|
209
|
-
lines.push('');
|
|
210
|
-
}
|
|
211
|
-
}
|
|
165
|
+
lines.push('### 시작');
|
|
166
|
+
lines.push('');
|
|
167
|
+
lines.push('원하는 작업을 말하거나 위 커맨드를 직접 실행하세요.');
|
|
168
|
+
lines.push('');
|
|
212
169
|
return lines.join('\n');
|
|
213
170
|
}
|
|
214
171
|
function countDir(teamDir, dirName) {
|
|
@@ -292,11 +249,8 @@ function resolveLongDescription(teamDir, yamlValue) {
|
|
|
292
249
|
async function createTarball(teamDir) {
|
|
293
250
|
const tmpFile = path_1.default.join(os_1.default.tmpdir(), `relay-publish-${Date.now()}.tar.gz`);
|
|
294
251
|
const dirsToInclude = VALID_DIRS.filter((d) => fs_1.default.existsSync(path_1.default.join(teamDir, d)));
|
|
295
|
-
// Include root SKILL.md
|
|
252
|
+
// Include GUIDE.html if it exists (root SKILL.md is replaced by entry command)
|
|
296
253
|
const entries = [...dirsToInclude];
|
|
297
|
-
if (fs_1.default.existsSync(path_1.default.join(teamDir, 'SKILL.md'))) {
|
|
298
|
-
entries.push('SKILL.md');
|
|
299
|
-
}
|
|
300
254
|
if (fs_1.default.existsSync(path_1.default.join(teamDir, 'GUIDE.html'))) {
|
|
301
255
|
entries.push('GUIDE.html');
|
|
302
256
|
}
|
|
@@ -591,10 +545,19 @@ function registerPublish(program) {
|
|
|
591
545
|
console.error(`포트폴리오 이미지: ${portfolioEntries.length}개`);
|
|
592
546
|
}
|
|
593
547
|
}
|
|
594
|
-
// Generate
|
|
548
|
+
// Generate bin/relay-preamble.sh (self-contained tracking + update check)
|
|
549
|
+
(0, preamble_js_1.generatePreambleBin)(relayDir, config.slug, config_js_1.API_URL);
|
|
550
|
+
// Generate entry command (commands/{author}-{name}.md)
|
|
595
551
|
const detectedSkills = detectSkills(relayDir);
|
|
596
|
-
const
|
|
597
|
-
|
|
552
|
+
const entryContent = generateEntryCommand(config, detectedCommands, detectedSkills, config.slug);
|
|
553
|
+
const commandsDir = path_1.default.join(relayDir, 'commands');
|
|
554
|
+
if (!fs_1.default.existsSync(commandsDir)) {
|
|
555
|
+
fs_1.default.mkdirSync(commandsDir, { recursive: true });
|
|
556
|
+
}
|
|
557
|
+
// slug: @alice/cardnews → alice-cardnews.md
|
|
558
|
+
const entrySlug = config.slug.startsWith('@') ? config.slug.slice(1) : config.slug;
|
|
559
|
+
const entryFileName = entrySlug.replace('/', '-') + '.md';
|
|
560
|
+
fs_1.default.writeFileSync(path_1.default.join(commandsDir, entryFileName), entryContent);
|
|
598
561
|
let tarPath = null;
|
|
599
562
|
try {
|
|
600
563
|
tarPath = await createTarball(relayDir);
|
|
@@ -602,13 +565,14 @@ function registerPublish(program) {
|
|
|
602
565
|
console.error(`업로드 중...`);
|
|
603
566
|
}
|
|
604
567
|
const result = await publishToApi(token, tarPath, metadata, relayDir, portfolioEntries);
|
|
605
|
-
// Update
|
|
568
|
+
// Update entry command preamble with scoped slug from server (non-fatal)
|
|
606
569
|
try {
|
|
607
570
|
if (result.slug && result.slug !== config.slug) {
|
|
608
|
-
const
|
|
609
|
-
|
|
571
|
+
const serverSlug = result.slug.startsWith('@') ? result.slug.slice(1) : result.slug;
|
|
572
|
+
const entryFile = path_1.default.join(relayDir, 'commands', serverSlug.replace('/', '-') + '.md');
|
|
573
|
+
if (fs_1.default.existsSync(entryFile)) {
|
|
610
574
|
const { injectPreamble } = await import('../lib/preamble.js');
|
|
611
|
-
injectPreamble(
|
|
575
|
+
injectPreamble(entryFile, result.slug);
|
|
612
576
|
}
|
|
613
577
|
}
|
|
614
578
|
}
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,7 @@ const changelog_js_1 = require("./commands/changelog.js");
|
|
|
19
19
|
const join_js_1 = require("./commands/join.js");
|
|
20
20
|
const spaces_js_1 = require("./commands/spaces.js");
|
|
21
21
|
const deploy_record_js_1 = require("./commands/deploy-record.js");
|
|
22
|
+
const ping_js_1 = require("./commands/ping.js");
|
|
22
23
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
23
24
|
const pkg = require('../package.json');
|
|
24
25
|
const program = new commander_1.Command();
|
|
@@ -44,4 +45,5 @@ program
|
|
|
44
45
|
(0, join_js_1.registerJoin)(program);
|
|
45
46
|
(0, spaces_js_1.registerSpaces)(program);
|
|
46
47
|
(0, deploy_record_js_1.registerDeployRecord)(program);
|
|
48
|
+
(0, ping_js_1.registerPing)(program);
|
|
47
49
|
program.parse();
|
package/dist/lib/ai-tools.d.ts
CHANGED
|
@@ -12,3 +12,8 @@ export declare const AI_TOOLS: AITool[];
|
|
|
12
12
|
* 프로젝트 디렉토리에서 에이전트 CLI 디렉토리를 감지한다.
|
|
13
13
|
*/
|
|
14
14
|
export declare function detectAgentCLIs(projectPath: string): AITool[];
|
|
15
|
+
/**
|
|
16
|
+
* 홈 디렉토리에서 글로벌 에이전트 CLI 디렉토리를 감지한다.
|
|
17
|
+
* ~/{skillsDir}/ 가 존재하는 CLI를 반환.
|
|
18
|
+
*/
|
|
19
|
+
export declare function detectGlobalCLIs(): AITool[];
|
package/dist/lib/ai-tools.js
CHANGED
|
@@ -5,7 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.AI_TOOLS = void 0;
|
|
7
7
|
exports.detectAgentCLIs = detectAgentCLIs;
|
|
8
|
+
exports.detectGlobalCLIs = detectGlobalCLIs;
|
|
8
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const os_1 = __importDefault(require("os"));
|
|
9
11
|
const path_1 = __importDefault(require("path"));
|
|
10
12
|
/**
|
|
11
13
|
* Agent Skills 표준을 지원하는 에이전트 CLI 목록.
|
|
@@ -43,3 +45,11 @@ exports.AI_TOOLS = [
|
|
|
43
45
|
function detectAgentCLIs(projectPath) {
|
|
44
46
|
return exports.AI_TOOLS.filter((tool) => fs_1.default.existsSync(path_1.default.join(projectPath, tool.skillsDir)));
|
|
45
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* 홈 디렉토리에서 글로벌 에이전트 CLI 디렉토리를 감지한다.
|
|
50
|
+
* ~/{skillsDir}/ 가 존재하는 CLI를 반환.
|
|
51
|
+
*/
|
|
52
|
+
function detectGlobalCLIs() {
|
|
53
|
+
const home = path_1.default.join(os_1.default.homedir());
|
|
54
|
+
return exports.AI_TOOLS.filter((tool) => fs_1.default.existsSync(path_1.default.join(home, tool.skillsDir)));
|
|
55
|
+
}
|
|
@@ -15,14 +15,23 @@ export interface ToolCommandAdapter {
|
|
|
15
15
|
*/
|
|
16
16
|
export declare function createAdapter(tool: AITool): ToolCommandAdapter;
|
|
17
17
|
/**
|
|
18
|
-
* 글로벌 슬래시 커맨드 파일
|
|
18
|
+
* 글로벌 슬래시 커맨드 파일 경로 (Claude Code 기본).
|
|
19
19
|
* ~/.claude/commands/relay/{id}.md
|
|
20
20
|
*/
|
|
21
21
|
export declare function getGlobalCommandPath(commandId: string): string;
|
|
22
22
|
/**
|
|
23
|
-
* 글로벌 슬래시 커맨드
|
|
23
|
+
* 글로벌 슬래시 커맨드 디렉토리 (Claude Code 기본).
|
|
24
24
|
*/
|
|
25
25
|
export declare function getGlobalCommandDir(): string;
|
|
26
|
+
/**
|
|
27
|
+
* 특정 AI 도구의 글로벌 커맨드 디렉토리.
|
|
28
|
+
* ~/{skillsDir}/commands/relay/
|
|
29
|
+
*/
|
|
30
|
+
export declare function getGlobalCommandDirForTool(skillsDir: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* 특정 AI 도구의 글로벌 커맨드 파일 경로.
|
|
33
|
+
*/
|
|
34
|
+
export declare function getGlobalCommandPathForTool(skillsDir: string, commandId: string): string;
|
|
26
35
|
/**
|
|
27
36
|
* 커맨드 콘텐츠를 파일 형식으로 포맷.
|
|
28
37
|
*/
|