relayax-cli 0.1.991 → 0.1.994
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/init.js +2 -0
- package/dist/commands/install.js +19 -21
- package/dist/commands/login.js +1 -1
- package/dist/commands/publish.js +23 -0
- package/dist/commands/update.js +21 -3
- package/dist/lib/command-adapter.js +11 -0
- package/dist/lib/config.d.ts +6 -1
- package/dist/lib/config.js +25 -13
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
package/dist/commands/init.js
CHANGED
|
@@ -8,6 +8,8 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const ai_tools_js_1 = require("../lib/ai-tools.js");
|
|
10
10
|
const command_adapter_js_1 = require("../lib/command-adapter.js");
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
12
|
+
const pkg = require('../../package.json');
|
|
11
13
|
const VALID_TEAM_DIRS = ['skills', 'agents', 'rules', 'commands'];
|
|
12
14
|
function resolveTools(toolsArg) {
|
|
13
15
|
const raw = toolsArg.trim().toLowerCase();
|
package/dist/commands/install.js
CHANGED
|
@@ -9,7 +9,6 @@ const path_1 = __importDefault(require("path"));
|
|
|
9
9
|
const api_js_1 = require("../lib/api.js");
|
|
10
10
|
const storage_js_1 = require("../lib/storage.js");
|
|
11
11
|
const config_js_1 = require("../lib/config.js");
|
|
12
|
-
const preamble_js_1 = require("../lib/preamble.js");
|
|
13
12
|
function registerInstall(program) {
|
|
14
13
|
program
|
|
15
14
|
.command('install <slug>')
|
|
@@ -62,8 +61,6 @@ function registerInstall(program) {
|
|
|
62
61
|
return count;
|
|
63
62
|
}
|
|
64
63
|
const fileCount = countFiles(teamDir);
|
|
65
|
-
// 5.5. Inject update-check preamble into SKILL.md files
|
|
66
|
-
(0, preamble_js_1.injectPreambleToTeam)(teamDir, slug);
|
|
67
64
|
// 6. Record in installed.json
|
|
68
65
|
const installed = (0, config_js_1.loadInstalled)();
|
|
69
66
|
installed[slug] = {
|
|
@@ -99,26 +96,27 @@ function registerInstall(program) {
|
|
|
99
96
|
console.log(` \x1b[33m/${cmd.name}\x1b[0m - ${cmd.description}`);
|
|
100
97
|
}
|
|
101
98
|
}
|
|
102
|
-
// Builder
|
|
103
|
-
if (team.welcome) {
|
|
104
|
-
console.log(`\n ┌─ 💬 ${authorDisplayName}님의 메시지 ${'─'.repeat(Math.max(0, 38 - authorDisplayName.length))}┐`);
|
|
105
|
-
const lines = team.welcome.match(/.{1,50}/g) ?? [team.welcome];
|
|
106
|
-
for (const line of lines) {
|
|
107
|
-
console.log(` │ "${line}"`);
|
|
108
|
-
}
|
|
109
|
-
console.log(` └${'─'.repeat(44)}┘`);
|
|
110
|
-
}
|
|
99
|
+
// Builder business card
|
|
111
100
|
const contactLinks = team.author?.contact_links ?? {};
|
|
112
101
|
const contactEntries = Object.entries(contactLinks);
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
console.log(`\n
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
102
|
+
const hasCard = team.welcome || contactEntries.length > 0 || authorUsername;
|
|
103
|
+
if (hasCard) {
|
|
104
|
+
console.log(`\n \x1b[90m┌─ ${authorDisplayName || authorUsername || '빌더'}의 명함 ${'─'.repeat(Math.max(0, 34 - (authorDisplayName || authorUsername || '빌더').length))}┐\x1b[0m`);
|
|
105
|
+
if (team.welcome) {
|
|
106
|
+
const truncated = team.welcome.length > 45 ? team.welcome.slice(0, 45) + '...' : team.welcome;
|
|
107
|
+
console.log(` \x1b[90m│\x1b[0m 💬 "${truncated}"`);
|
|
108
|
+
}
|
|
109
|
+
if (contactEntries.length > 0) {
|
|
110
|
+
const parts = contactEntries.map(([k, v]) => `${k}: ${v}`).join(' ');
|
|
111
|
+
console.log(` \x1b[90m│\x1b[0m 📇 ${parts}`);
|
|
112
|
+
}
|
|
113
|
+
if (authorUsername) {
|
|
114
|
+
console.log(` \x1b[90m│\x1b[0m 👤 relayax.com/@${authorUsername}`);
|
|
115
|
+
}
|
|
116
|
+
if (team.latest_post && authorUsername) {
|
|
117
|
+
console.log(` \x1b[90m│\x1b[0m 📝 relayax.com/@${authorUsername}/posts/${team.latest_post.slug}`);
|
|
118
|
+
}
|
|
119
|
+
console.log(` \x1b[90m└${'─'.repeat(44)}┘\x1b[0m`);
|
|
122
120
|
}
|
|
123
121
|
// Follow prompt (only when logged in)
|
|
124
122
|
const token = (0, config_js_1.loadToken)();
|
package/dist/commands/login.js
CHANGED
|
@@ -96,7 +96,7 @@ function registerLogin(program) {
|
|
|
96
96
|
.option('--token <token>', '직접 토큰 입력 (브라우저 없이)')
|
|
97
97
|
.action(async (opts) => {
|
|
98
98
|
const json = program.opts().json ?? false;
|
|
99
|
-
(0, config_js_1.
|
|
99
|
+
(0, config_js_1.ensureGlobalRelayDir)();
|
|
100
100
|
let token = opts.token;
|
|
101
101
|
if (!token) {
|
|
102
102
|
try {
|
package/dist/commands/publish.js
CHANGED
|
@@ -433,6 +433,29 @@ function registerPublish(program) {
|
|
|
433
433
|
if (result.portfolio_count && result.portfolio_count > 0) {
|
|
434
434
|
console.log(` 포트폴리오: ${result.portfolio_count}개 이미지 업로드됨`);
|
|
435
435
|
}
|
|
436
|
+
// Show business card preview
|
|
437
|
+
const profile = result.profile;
|
|
438
|
+
if (profile) {
|
|
439
|
+
const contacts = profile.contact_links ?? {};
|
|
440
|
+
const contactEntries = Object.entries(contacts);
|
|
441
|
+
const welcome = profile.default_welcome ?? '';
|
|
442
|
+
console.log(`\n \x1b[90m┌─ 설치자에게 보이는 명함 ${'─'.repeat(24)}┐\x1b[0m`);
|
|
443
|
+
if (welcome) {
|
|
444
|
+
console.log(` \x1b[90m│\x1b[0m 💬 "${welcome.length > 45 ? welcome.slice(0, 45) + '...' : welcome}"`);
|
|
445
|
+
}
|
|
446
|
+
if (contactEntries.length > 0) {
|
|
447
|
+
const parts = contactEntries.map(([k, v]) => `${k}: ${v}`).join(' ');
|
|
448
|
+
console.log(` \x1b[90m│\x1b[0m 📇 ${parts}`);
|
|
449
|
+
}
|
|
450
|
+
if (profile.username) {
|
|
451
|
+
console.log(` \x1b[90m│\x1b[0m 👤 relayax.com/@${profile.username}`);
|
|
452
|
+
}
|
|
453
|
+
if (!welcome && contactEntries.length === 0) {
|
|
454
|
+
console.log(` \x1b[90m│\x1b[0m \x1b[2m명함이 비어있습니다\x1b[0m`);
|
|
455
|
+
}
|
|
456
|
+
console.log(` \x1b[90m└${'─'.repeat(44)}┘\x1b[0m`);
|
|
457
|
+
console.log(`\n \x1b[90m명함 수정: \x1b[36mwww.relayax.com/dashboard/profile\x1b[0m`);
|
|
458
|
+
}
|
|
436
459
|
}
|
|
437
460
|
}
|
|
438
461
|
catch (err) {
|
package/dist/commands/update.js
CHANGED
|
@@ -5,7 +5,6 @@ const api_js_1 = require("../lib/api.js");
|
|
|
5
5
|
const storage_js_1 = require("../lib/storage.js");
|
|
6
6
|
const installer_js_1 = require("../lib/installer.js");
|
|
7
7
|
const config_js_1 = require("../lib/config.js");
|
|
8
|
-
const preamble_js_1 = require("../lib/preamble.js");
|
|
9
8
|
function registerUpdate(program) {
|
|
10
9
|
program
|
|
11
10
|
.command('update <slug>')
|
|
@@ -55,8 +54,6 @@ function registerUpdate(program) {
|
|
|
55
54
|
await (0, storage_js_1.extractPackage)(tarPath, extractDir);
|
|
56
55
|
// Copy files to install_path
|
|
57
56
|
const files = (0, installer_js_1.installTeam)(extractDir, installPath);
|
|
58
|
-
// Inject update-check preamble into SKILL.md files
|
|
59
|
-
(0, preamble_js_1.injectPreambleToTeam)(installPath, slug);
|
|
60
57
|
// Update installed.json with new version
|
|
61
58
|
installed[slug] = {
|
|
62
59
|
version: latestVersion,
|
|
@@ -82,6 +79,27 @@ function registerUpdate(program) {
|
|
|
82
79
|
console.log(`\n\x1b[32m✓ ${team.name} ${fromLabel}v${latestVersion} 업데이트 완료\x1b[0m`);
|
|
83
80
|
console.log(` 설치 위치: \x1b[36m${installPath}\x1b[0m`);
|
|
84
81
|
console.log(` 파일 수: ${files.length}개`);
|
|
82
|
+
// Builder business card
|
|
83
|
+
const authorUsername = team.author?.username;
|
|
84
|
+
const authorDisplayName = team.author?.display_name ?? authorUsername ?? '';
|
|
85
|
+
const contactLinks = team.author?.contact_links ?? {};
|
|
86
|
+
const contactEntries = Object.entries(contactLinks);
|
|
87
|
+
const hasCard = team.welcome || contactEntries.length > 0 || authorUsername;
|
|
88
|
+
if (hasCard) {
|
|
89
|
+
console.log(`\n \x1b[90m┌─ ${authorDisplayName || '빌더'}의 명함 ${'─'.repeat(Math.max(0, 34 - (authorDisplayName || '빌더').length))}┐\x1b[0m`);
|
|
90
|
+
if (team.welcome) {
|
|
91
|
+
const truncated = team.welcome.length > 45 ? team.welcome.slice(0, 45) + '...' : team.welcome;
|
|
92
|
+
console.log(` \x1b[90m│\x1b[0m 💬 "${truncated}"`);
|
|
93
|
+
}
|
|
94
|
+
if (contactEntries.length > 0) {
|
|
95
|
+
const parts = contactEntries.map(([k, v]) => `${k}: ${v}`).join(' ');
|
|
96
|
+
console.log(` \x1b[90m│\x1b[0m 📇 ${parts}`);
|
|
97
|
+
}
|
|
98
|
+
if (authorUsername) {
|
|
99
|
+
console.log(` \x1b[90m│\x1b[0m 👤 relayax.com/@${authorUsername}`);
|
|
100
|
+
}
|
|
101
|
+
console.log(` \x1b[90m└${'─'.repeat(44)}┘\x1b[0m`);
|
|
102
|
+
}
|
|
85
103
|
}
|
|
86
104
|
}
|
|
87
105
|
catch (err) {
|
|
@@ -83,6 +83,12 @@ exports.USER_COMMANDS = [
|
|
|
83
83
|
|
|
84
84
|
## 실행 방법
|
|
85
85
|
|
|
86
|
+
### 0. 업데이트 확인
|
|
87
|
+
- 먼저 \`relay check-update\` 명령어를 실행합니다.
|
|
88
|
+
- CLI 업데이트가 있으면 사용자에게 안내합니다: "relay v{new} available. Run: npm update -g relayax-cli"
|
|
89
|
+
- 팀 업데이트가 있으면 안내합니다.
|
|
90
|
+
- 업데이트 여부와 관계없이 설치를 계속 진행합니다.
|
|
91
|
+
|
|
86
92
|
### 1. 팀 패키지 다운로드
|
|
87
93
|
- \`relay install <slug>\` 명령어를 실행합니다.
|
|
88
94
|
- 패키지가 \`.relay/teams/<slug>/\`에 다운로드됩니다.
|
|
@@ -155,6 +161,11 @@ ${LOGIN_JIT_GUIDE}
|
|
|
155
161
|
|
|
156
162
|
## 실행 방법
|
|
157
163
|
|
|
164
|
+
### 0. CLI 업데이트 확인
|
|
165
|
+
- 먼저 \`relay check-update\` 명령어를 실행합니다.
|
|
166
|
+
- CLI 업데이트가 있으면 사용자에게 안내합니다: "relay v{new} available. Run: npm update -g relayax-cli"
|
|
167
|
+
- 업데이트 여부와 관계없이 팀 업데이트를 계속 진행합니다.
|
|
168
|
+
|
|
158
169
|
### 특정 팀 업데이트
|
|
159
170
|
- 사용자가 팀 이름을 지정한 경우: \`relay update <slug> --json\` 실행
|
|
160
171
|
- 업데이트 결과를 보여줍니다 (이전 버전 → 새 버전)
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -7,8 +7,13 @@ export declare const API_URL = "https://www.relayax.com";
|
|
|
7
7
|
* 3. 감지 안 되면 현재 디렉토리에 직접 설치
|
|
8
8
|
*/
|
|
9
9
|
export declare function getInstallPath(override?: string): string;
|
|
10
|
-
|
|
10
|
+
/** ~/.relay/ — 글로벌 (token, CLI cache) */
|
|
11
|
+
export declare function ensureGlobalRelayDir(): void;
|
|
12
|
+
/** cwd/.relay/ — 프로젝트 로컬 (installed.json, teams/) */
|
|
13
|
+
export declare function ensureProjectRelayDir(): void;
|
|
11
14
|
export declare function loadToken(): string | undefined;
|
|
12
15
|
export declare function saveToken(token: string): void;
|
|
16
|
+
/** 프로젝트 로컬 installed.json 읽기 */
|
|
13
17
|
export declare function loadInstalled(): InstalledRegistry;
|
|
18
|
+
/** 프로젝트 로컬 installed.json 쓰기 */
|
|
14
19
|
export declare function saveInstalled(registry: InstalledRegistry): void;
|
package/dist/lib/config.js
CHANGED
|
@@ -5,7 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.API_URL = void 0;
|
|
7
7
|
exports.getInstallPath = getInstallPath;
|
|
8
|
-
exports.
|
|
8
|
+
exports.ensureGlobalRelayDir = ensureGlobalRelayDir;
|
|
9
|
+
exports.ensureProjectRelayDir = ensureProjectRelayDir;
|
|
9
10
|
exports.loadToken = loadToken;
|
|
10
11
|
exports.saveToken = saveToken;
|
|
11
12
|
exports.loadInstalled = loadInstalled;
|
|
@@ -15,8 +16,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
15
16
|
const os_1 = __importDefault(require("os"));
|
|
16
17
|
const ai_tools_js_1 = require("./ai-tools.js");
|
|
17
18
|
exports.API_URL = 'https://www.relayax.com';
|
|
18
|
-
const
|
|
19
|
-
const INSTALLED_FILE = path_1.default.join(RELAY_DIR, 'installed.json');
|
|
19
|
+
const GLOBAL_RELAY_DIR = path_1.default.join(os_1.default.homedir(), '.relay');
|
|
20
20
|
/**
|
|
21
21
|
* 설치 경로를 결정한다.
|
|
22
22
|
* 1. --path 옵션이 있으면 그대로 사용
|
|
@@ -37,13 +37,21 @@ function getInstallPath(override) {
|
|
|
37
37
|
}
|
|
38
38
|
return cwd;
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
/** ~/.relay/ — 글로벌 (token, CLI cache) */
|
|
41
|
+
function ensureGlobalRelayDir() {
|
|
42
|
+
if (!fs_1.default.existsSync(GLOBAL_RELAY_DIR)) {
|
|
43
|
+
fs_1.default.mkdirSync(GLOBAL_RELAY_DIR, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** cwd/.relay/ — 프로젝트 로컬 (installed.json, teams/) */
|
|
47
|
+
function ensureProjectRelayDir() {
|
|
48
|
+
const dir = path_1.default.join(process.cwd(), '.relay');
|
|
49
|
+
if (!fs_1.default.existsSync(dir)) {
|
|
50
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
43
51
|
}
|
|
44
52
|
}
|
|
45
53
|
function loadToken() {
|
|
46
|
-
const tokenFile = path_1.default.join(
|
|
54
|
+
const tokenFile = path_1.default.join(GLOBAL_RELAY_DIR, 'token');
|
|
47
55
|
if (!fs_1.default.existsSync(tokenFile))
|
|
48
56
|
return undefined;
|
|
49
57
|
try {
|
|
@@ -54,22 +62,26 @@ function loadToken() {
|
|
|
54
62
|
}
|
|
55
63
|
}
|
|
56
64
|
function saveToken(token) {
|
|
57
|
-
|
|
58
|
-
fs_1.default.writeFileSync(path_1.default.join(
|
|
65
|
+
ensureGlobalRelayDir();
|
|
66
|
+
fs_1.default.writeFileSync(path_1.default.join(GLOBAL_RELAY_DIR, 'token'), token);
|
|
59
67
|
}
|
|
68
|
+
/** 프로젝트 로컬 installed.json 읽기 */
|
|
60
69
|
function loadInstalled() {
|
|
61
|
-
|
|
70
|
+
const file = path_1.default.join(process.cwd(), '.relay', 'installed.json');
|
|
71
|
+
if (!fs_1.default.existsSync(file)) {
|
|
62
72
|
return {};
|
|
63
73
|
}
|
|
64
74
|
try {
|
|
65
|
-
const raw = fs_1.default.readFileSync(
|
|
75
|
+
const raw = fs_1.default.readFileSync(file, 'utf-8');
|
|
66
76
|
return JSON.parse(raw);
|
|
67
77
|
}
|
|
68
78
|
catch {
|
|
69
79
|
return {};
|
|
70
80
|
}
|
|
71
81
|
}
|
|
82
|
+
/** 프로젝트 로컬 installed.json 쓰기 */
|
|
72
83
|
function saveInstalled(registry) {
|
|
73
|
-
|
|
74
|
-
|
|
84
|
+
ensureProjectRelayDir();
|
|
85
|
+
const file = path_1.default.join(process.cwd(), '.relay', 'installed.json');
|
|
86
|
+
fs_1.default.writeFileSync(file, JSON.stringify(registry, null, 2));
|
|
75
87
|
}
|
package/dist/types.d.ts
CHANGED