relayax-cli 0.4.27 → 0.4.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/dist/commands/install.js
CHANGED
|
@@ -256,7 +256,7 @@ function registerInstall(program) {
|
|
|
256
256
|
// 4.5. Inject preamble (update check) into SKILL.md and commands
|
|
257
257
|
(0, preamble_js_1.injectPreambleToAgent)(agentDir, slug);
|
|
258
258
|
// 5. Deploy symlinks to detected AI tool directories
|
|
259
|
-
const deploy = (0, installer_js_1.deploySymlinks)(agentDir, scope, projectPath);
|
|
259
|
+
const deploy = await (0, installer_js_1.deploySymlinks)(agentDir, scope, projectPath);
|
|
260
260
|
for (const w of deploy.warnings) {
|
|
261
261
|
if (!json)
|
|
262
262
|
console.error(`\x1b[33m${w}\x1b[0m`);
|
|
@@ -68,6 +68,7 @@ export interface PublishMetadata {
|
|
|
68
68
|
requires?: Requires;
|
|
69
69
|
visibility?: 'public' | 'private' | 'internal';
|
|
70
70
|
type?: 'command' | 'passive' | 'hybrid';
|
|
71
|
+
recommended_scope?: 'global' | 'local';
|
|
71
72
|
cli_version?: string;
|
|
72
73
|
agent_names?: string[];
|
|
73
74
|
skill_names?: string[];
|
package/dist/commands/publish.js
CHANGED
|
@@ -45,6 +45,7 @@ function parseRelayYaml(content) {
|
|
|
45
45
|
requires,
|
|
46
46
|
visibility,
|
|
47
47
|
type,
|
|
48
|
+
recommended_scope: raw.recommended_scope === 'global' ? 'global' : raw.recommended_scope === 'local' ? 'local' : undefined,
|
|
48
49
|
source: raw.source ? String(raw.source) : undefined,
|
|
49
50
|
org_slug: raw.org_slug ? String(raw.org_slug) : undefined,
|
|
50
51
|
};
|
|
@@ -268,6 +269,7 @@ function registerPublish(program) {
|
|
|
268
269
|
.option('--token <token>', '인증 토큰')
|
|
269
270
|
.option('--space <slug>', '배포할 Space 지정')
|
|
270
271
|
.option('--org <slug>', 'Organization slug 지정')
|
|
272
|
+
.option('--no-org', '개인 계정으로 배포 (Organization 무시)')
|
|
271
273
|
.option('--version <version>', '배포 버전 지정 (relay.yaml 업데이트)')
|
|
272
274
|
.option('--patch', 'patch 버전 범프')
|
|
273
275
|
.option('--minor', 'minor 버전 범프')
|
|
@@ -470,10 +472,18 @@ function registerPublish(program) {
|
|
|
470
472
|
try {
|
|
471
473
|
const { fetchMyOrgs } = await import('./orgs.js');
|
|
472
474
|
const orgs = await fetchMyOrgs(token);
|
|
475
|
+
// --no-org: skip org selection entirely (personal deployment)
|
|
476
|
+
const skipOrg = opts.noOrg === true;
|
|
473
477
|
// Determine explicit org slug: --org > --space (legacy) > relay.yaml org_slug
|
|
474
|
-
const explicitOrgSlug = opts.org ?? opts.space ?? config.org_slug;
|
|
478
|
+
const explicitOrgSlug = skipOrg ? undefined : (opts.org ?? opts.space ?? config.org_slug);
|
|
475
479
|
// --org / --space / relay.yaml org_slug: resolve Org by slug
|
|
476
|
-
if (
|
|
480
|
+
if (skipOrg) {
|
|
481
|
+
// Personal deployment — no org
|
|
482
|
+
if (!json) {
|
|
483
|
+
console.error('\x1b[2m 개인 계정으로 배포합니다.\x1b[0m\n');
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
else if (explicitOrgSlug) {
|
|
477
487
|
const matched = orgs.find((o) => o.slug === explicitOrgSlug);
|
|
478
488
|
if (matched) {
|
|
479
489
|
selectedOrgId = matched.id;
|
|
@@ -528,18 +538,22 @@ function registerPublish(program) {
|
|
|
528
538
|
console.error(` → Organization: ${chosenLabel}\n`);
|
|
529
539
|
}
|
|
530
540
|
}
|
|
531
|
-
else if (orgs.length >
|
|
532
|
-
// --json 모드 +
|
|
533
|
-
(0, error_report_js_1.reportCliError)('publish', 'MISSING_ORG',
|
|
541
|
+
else if (orgs.length > 0 && json) {
|
|
542
|
+
// --json 모드 + Org 있음: 에이전트가 선택할 수 있도록 에러 반환
|
|
543
|
+
(0, error_report_js_1.reportCliError)('publish', 'MISSING_ORG', `${orgs.length} orgs, none selected`);
|
|
534
544
|
console.error(JSON.stringify({
|
|
535
545
|
error: 'MISSING_ORG',
|
|
536
|
-
message: '
|
|
537
|
-
fix:
|
|
538
|
-
options:
|
|
546
|
+
message: '배포 대상을 선택하세요.',
|
|
547
|
+
fix: `개인 배포: relay publish --no-org --json / Org 배포: relay publish --org <slug> --json`,
|
|
548
|
+
options: [
|
|
549
|
+
{ value: '__personal__', label: '개인 계정으로 배포' },
|
|
550
|
+
...orgs.map((o) => ({ value: o.slug, label: `${o.name} (${o.slug})` })),
|
|
551
|
+
],
|
|
539
552
|
}));
|
|
540
553
|
process.exit(1);
|
|
541
554
|
}
|
|
542
555
|
else if (orgs.length > 0) {
|
|
556
|
+
// non-json, non-TTY fallback (rare) — auto-select first org
|
|
543
557
|
selectedOrgId = orgs[0].id;
|
|
544
558
|
selectedOrgSlug = orgs[0].slug;
|
|
545
559
|
}
|
|
@@ -691,6 +705,7 @@ function registerPublish(program) {
|
|
|
691
705
|
agent_names: listDir(relayDir, 'agents'),
|
|
692
706
|
skill_names: listDir(relayDir, 'skills'),
|
|
693
707
|
type: config.type ?? 'hybrid',
|
|
708
|
+
recommended_scope: config.recommended_scope,
|
|
694
709
|
agent_details: detectedAgents,
|
|
695
710
|
skill_details: detectedSkills,
|
|
696
711
|
...(selectedOrgId ? { org_id: selectedOrgId } : {}),
|
package/dist/commands/update.js
CHANGED
|
@@ -98,7 +98,7 @@ function registerUpdate(program) {
|
|
|
98
98
|
// Inject preamble
|
|
99
99
|
(0, preamble_js_1.injectPreambleToAgent)(agentDir, slug);
|
|
100
100
|
// Deploy symlinks (always — handles migration from legacy deployed_files)
|
|
101
|
-
const deploy = (0, installer_js_1.deploySymlinks)(agentDir, currentScope, projectPath);
|
|
101
|
+
const deploy = await (0, installer_js_1.deploySymlinks)(agentDir, currentScope, projectPath);
|
|
102
102
|
// Update installed.json
|
|
103
103
|
const installRecord = {
|
|
104
104
|
agent_id: agent.id,
|
package/dist/lib/installer.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface DeployResult {
|
|
|
11
11
|
* @param scope 'global' | 'local'
|
|
12
12
|
* @param projectPath 프로젝트 루트 경로 (local scope 시 사용)
|
|
13
13
|
*/
|
|
14
|
-
export declare function deploySymlinks(agentDir: string, scope: 'global' | 'local', projectPath: string): DeployResult
|
|
14
|
+
export declare function deploySymlinks(agentDir: string, scope: 'global' | 'local', projectPath: string): Promise<DeployResult>;
|
|
15
15
|
/**
|
|
16
16
|
* symlink 목록을 기반으로 symlink를 제거한다.
|
|
17
17
|
*/
|
package/dist/lib/installer.js
CHANGED
|
@@ -26,19 +26,34 @@ const SYMLINK_DIRS = ['skills', 'commands', 'agents', 'rules'];
|
|
|
26
26
|
* @param scope 'global' | 'local'
|
|
27
27
|
* @param projectPath 프로젝트 루트 경로 (local scope 시 사용)
|
|
28
28
|
*/
|
|
29
|
-
function deploySymlinks(agentDir, scope, projectPath) {
|
|
29
|
+
async function deploySymlinks(agentDir, scope, projectPath) {
|
|
30
30
|
const result = { symlinks: [], warnings: [] };
|
|
31
31
|
// 감지된 AI tool 목록
|
|
32
32
|
const tools = scope === 'global'
|
|
33
33
|
? (0, ai_tools_js_1.detectGlobalCLIs)()
|
|
34
34
|
: (0, ai_tools_js_1.detectAgentCLIs)(projectPath);
|
|
35
|
-
// Claude Code를 기본으로 포함
|
|
35
|
+
// 글로벌: Claude Code를 기본으로 포함
|
|
36
36
|
if (scope === 'global') {
|
|
37
37
|
const hasClaudeCode = tools.some((t) => t.value === 'claude');
|
|
38
38
|
if (!hasClaudeCode) {
|
|
39
39
|
tools.push({ name: 'Claude Code', value: 'claude', skillsDir: '.claude' });
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
// 로컬: AI tool 디렉토리가 없으면 TTY에서 선택
|
|
43
|
+
if (scope === 'local' && tools.length === 0) {
|
|
44
|
+
if (process.stdout.isTTY) {
|
|
45
|
+
const { checkbox } = await import('@inquirer/prompts');
|
|
46
|
+
const selected = await checkbox({
|
|
47
|
+
message: `Select tools to set up (${ai_tools_js_1.AI_TOOLS.length} available)`,
|
|
48
|
+
choices: ai_tools_js_1.AI_TOOLS.map((t) => ({ name: t.name, value: t })),
|
|
49
|
+
});
|
|
50
|
+
tools.push(...selected);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// Non-TTY (JSON 모드 등): Claude Code 기본
|
|
54
|
+
tools.push({ name: 'Claude Code', value: 'claude', skillsDir: '.claude' });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
42
57
|
for (const tool of tools) {
|
|
43
58
|
const baseDir = scope === 'global'
|
|
44
59
|
? path_1.default.join(os_1.default.homedir(), tool.skillsDir)
|
|
@@ -75,7 +90,8 @@ function deploySymlinks(agentDir, scope, projectPath) {
|
|
|
75
90
|
continue;
|
|
76
91
|
}
|
|
77
92
|
}
|
|
78
|
-
|
|
93
|
+
const relativeSrc = path_1.default.relative(path_1.default.dirname(destPath), srcPath);
|
|
94
|
+
fs_1.default.symlinkSync(relativeSrc, destPath);
|
|
79
95
|
result.symlinks.push(destPath);
|
|
80
96
|
}
|
|
81
97
|
}
|
package/dist/prompts/create.md
CHANGED
|
@@ -110,8 +110,17 @@ relay.yaml이 없으면 새로 만들고, 있으면 변경사항을 반영합니
|
|
|
110
110
|
- name, slug, description, version, tags
|
|
111
111
|
- requires (판단 결과)
|
|
112
112
|
- org, visibility
|
|
113
|
+
- **recommended_scope** — 설치 시 기본 배치 범위:
|
|
114
|
+
- `local` — rules/ 디렉토리가 있거나 프레임워크 특화 태그(nextjs, react, vue, angular, svelte, nuxt, remix, astro, django, rails, laravel, spring, express, fastapi, flask)가 있을 때
|
|
115
|
+
- `global` — 그 외 범용 도구
|
|
113
116
|
|
|
114
|
-
**사용자에게 질문하여 최종 확인** 후
|
|
117
|
+
**사용자에게 질문하여 최종 확인** 후 배포합니다.
|
|
118
|
+
|
|
119
|
+
배포 명령어는 사용자의 선택에 따라 다릅니다:
|
|
120
|
+
- **개인 배포**: `relay publish --no-org --json`
|
|
121
|
+
- **Org 배포**: `relay publish --org {org_slug} --json`
|
|
122
|
+
|
|
123
|
+
⚠️ `relay publish --json`만 실행하면 org 선택 에러가 발생합니다. 반드시 `--no-org` 또는 `--org`를 명시하세요.
|
|
115
124
|
|
|
116
125
|
---
|
|
117
126
|
|
|
@@ -140,7 +149,10 @@ relay.yaml이 없으면 새로 만들고, 있으면 변경사항을 반영합니
|
|
|
140
149
|
### 3. 배포
|
|
141
150
|
|
|
142
151
|
변경 요약을 보여주고 **사용자에게 질문하여 최종 확인** 후 배포합니다.
|
|
143
|
-
|
|
152
|
+
|
|
153
|
+
배포 명령어는 사용자의 선택(또는 기존 relay.yaml 설정)에 따라:
|
|
154
|
+
- **개인 배포**: `relay publish --no-org --json`
|
|
155
|
+
- **Org 배포**: `relay publish --org {org_slug} --json`
|
|
144
156
|
버전 범프가 필요하면 사용자에게 질문하여 patch/minor/major 중 확인합니다.
|
|
145
157
|
|
|
146
158
|
---
|