relayax-cli 0.1.996 → 0.1.997

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.
@@ -37,17 +37,17 @@ async function verifyToken(token) {
37
37
  return null;
38
38
  }
39
39
  }
40
- function waitForToken(port) {
41
- return new Promise((resolve, reject) => {
42
- const server = http_1.default.createServer((req, res) => {
43
- const url = new URL(req.url ?? '/', `http://localhost:${port}`);
44
- if (url.pathname === '/callback') {
45
- const token = url.searchParams.get('token');
46
- const refresh_token = url.searchParams.get('refresh_token') ?? undefined;
47
- const expires_at_raw = url.searchParams.get('expires_at');
48
- const expires_at = expires_at_raw ? Number(expires_at_raw) : undefined;
49
- res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
50
- res.end(`<!DOCTYPE html>
40
+ function parseFormBody(body) {
41
+ return new URLSearchParams(body);
42
+ }
43
+ function collectBody(req) {
44
+ return new Promise((resolve) => {
45
+ const chunks = [];
46
+ req.on('data', (chunk) => chunks.push(chunk));
47
+ req.on('end', () => resolve(Buffer.concat(chunks).toString()));
48
+ });
49
+ }
50
+ const SUCCESS_HTML = `<!DOCTYPE html>
51
51
  <html><head><title>RelayAX</title></head>
52
52
  <body style="font-family:system-ui;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#f6f5f2;color:#111318">
53
53
  <div style="text-align:center">
@@ -55,7 +55,27 @@ function waitForToken(port) {
55
55
  <p>터미널로 돌아가세요. 이 창은 닫아도 됩니다.</p>
56
56
  <script>setTimeout(()=>window.close(),2000)</script>
57
57
  </div>
58
- </body></html>`);
58
+ </body></html>`;
59
+ function waitForToken(port) {
60
+ return new Promise((resolve, reject) => {
61
+ const server = http_1.default.createServer(async (req, res) => {
62
+ const url = new URL(req.url ?? '/', `http://localhost:${port}`);
63
+ if (url.pathname === '/callback') {
64
+ // POST body (secure) 또는 GET query params (하위 호환) 모두 지원
65
+ let params;
66
+ if (req.method === 'POST') {
67
+ const body = await collectBody(req);
68
+ params = parseFormBody(body);
69
+ }
70
+ else {
71
+ params = url.searchParams;
72
+ }
73
+ const token = params.get('token');
74
+ const refresh_token = params.get('refresh_token') ?? undefined;
75
+ const expires_at_raw = params.get('expires_at');
76
+ const expires_at = expires_at_raw ? Number(expires_at_raw) : undefined;
77
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
78
+ res.end(SUCCESS_HTML);
59
79
  server.close();
60
80
  if (token) {
61
81
  resolve({ token, refresh_token, expires_at });
package/dist/lib/api.js CHANGED
@@ -8,7 +8,8 @@ exports.resolveSlugFromServer = resolveSlugFromServer;
8
8
  exports.followBuilder = followBuilder;
9
9
  const config_js_1 = require("./config.js");
10
10
  async function fetchTeamInfo(slug) {
11
- const url = `${config_js_1.API_URL}/api/registry/${slug}`;
11
+ const registrySlug = slug.startsWith('@') ? slug.slice(1) : slug;
12
+ const url = `${config_js_1.API_URL}/api/registry/${registrySlug}`;
12
13
  const res = await fetch(url);
13
14
  if (!res.ok) {
14
15
  const body = await res.text();
@@ -30,7 +31,8 @@ async function searchTeams(query, tag) {
30
31
  return data.results;
31
32
  }
32
33
  async function fetchTeamVersions(slug) {
33
- const url = `${config_js_1.API_URL}/api/registry/${slug}/versions`;
34
+ const registrySlug = slug.startsWith('@') ? slug.slice(1) : slug;
35
+ const url = `${config_js_1.API_URL}/api/registry/${registrySlug}/versions`;
34
36
  const res = await fetch(url);
35
37
  if (!res.ok) {
36
38
  const body = await res.text();
@@ -39,7 +41,8 @@ async function fetchTeamVersions(slug) {
39
41
  return res.json();
40
42
  }
41
43
  async function reportInstall(slug) {
42
- const url = `${config_js_1.API_URL}/api/registry/${slug}/install`;
44
+ const registrySlug = slug.startsWith('@') ? slug.slice(1) : slug;
45
+ const url = `${config_js_1.API_URL}/api/registry/${registrySlug}/install`;
43
46
  await fetch(url, { method: 'POST' }).catch(() => {
44
47
  // non-critical: ignore errors
45
48
  });
@@ -79,11 +79,13 @@ function loadToken() {
79
79
  }
80
80
  function saveTokenData(data) {
81
81
  ensureGlobalRelayDir();
82
- fs_1.default.writeFileSync(path_1.default.join(GLOBAL_RELAY_DIR, 'token'), JSON.stringify(data));
82
+ const tokenFile = path_1.default.join(GLOBAL_RELAY_DIR, 'token');
83
+ fs_1.default.writeFileSync(tokenFile, JSON.stringify(data), { mode: 0o600 });
83
84
  }
84
85
  function saveToken(token) {
85
86
  ensureGlobalRelayDir();
86
- fs_1.default.writeFileSync(path_1.default.join(GLOBAL_RELAY_DIR, 'token'), JSON.stringify({ access_token: token }));
87
+ const tokenFile = path_1.default.join(GLOBAL_RELAY_DIR, 'token');
88
+ fs_1.default.writeFileSync(tokenFile, JSON.stringify({ access_token: token }), { mode: 0o600 });
87
89
  }
88
90
  /**
89
91
  * 유효한 access_token을 반환한다.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relayax-cli",
3
- "version": "0.1.996",
3
+ "version": "0.1.997",
4
4
  "description": "RelayAX Agent Team Marketplace CLI - Install and manage agent teams",
5
5
  "main": "dist/index.js",
6
6
  "bin": {