sp-rag 0.5.0 → 0.6.1

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 CHANGED
@@ -17,7 +17,7 @@ CLI để setup nhanh SP-RAG theo hướng dev-friendly:
17
17
  ## Trạng thái package
18
18
 
19
19
  - package npm public: `sp-rag`
20
- - version đang publish: `0.5.0`
20
+ - version đang publish: `0.6.1`
21
21
  - binary public: `sp-rag`
22
22
 
23
23
  ## Cài từ source trong monorepo
@@ -33,12 +33,13 @@ node dist/index.js doctor
33
33
  ## Cài nhanh qua `npx`
34
34
 
35
35
  ```bash
36
- npx sp-rag@latest install --client codex --mcp-token <token truy cập MCP> --doctor
37
- npx sp-rag@latest install --client cursor --scope project --cwd D:/Webs/seo-booster --mcp-token <token truy cập MCP>
38
- npx sp-rag@latest install --client vscode --scope project --cwd D:/Webs/seo-booster --mcp-token <token truy cập MCP>
39
- npx sp-rag@latest token add --token <token truy cập MCP> --client codex
40
- npx sp-rag@latest mcp add antigravity --mcp-token <token truy cập MCP>
41
- npx sp-rag@latest mcp add opencode --scope project --cwd D:/Webs/seo-booster --mcp-token <token truy cập MCP>
36
+ npx sp-rag@latest install --client codex --mcp-token <grc_pat_...> --doctor
37
+ npx sp-rag@latest install --client cursor --scope project --cwd D:/Webs/seo-booster --mcp-token <grc_pat_...>
38
+ npx sp-rag@latest install --client vscode --scope project --cwd D:/Webs/seo-booster --mcp-token <grc_pat_...>
39
+ npx sp-rag@latest token add --token <grc_pat_...> --client codex
40
+ npx sp-rag@latest token verify --token <grc_pat_...>
41
+ npx sp-rag@latest mcp add antigravity --mcp-token <grc_pat_...>
42
+ npx sp-rag@latest mcp add opencode --scope project --cwd D:/Webs/seo-booster --mcp-token <grc_pat_...>
42
43
  npx sp-rag@latest skill install --skill-client cursor --scope project --cwd D:/Webs/seo-booster
43
44
  npx sp-rag@latest skill install --skill-client vscode --scope project --cwd D:/Webs/seo-booster
44
45
  ```
@@ -46,8 +47,68 @@ npx sp-rag@latest skill install --skill-client vscode --scope project --cwd D:/W
46
47
  Tương đương bằng `npm`:
47
48
 
48
49
  ```bash
49
- npm exec --yes sp-rag@latest install -- --client codex --mcp-token <token truy cập MCP> --doctor
50
- npm exec --yes sp-rag@latest token add -- --token <token truy cập MCP> --client codex
50
+ npm exec --yes sp-rag@latest install -- --client codex --mcp-token <grc_pat_...> --doctor
51
+ npm exec --yes sp-rag@latest token add -- --token <grc_pat_...> --client codex
52
+ npm exec --yes sp-rag@latest token verify -- --token <grc_pat_...>
53
+ ```
54
+
55
+ ## Lấy token ở đâu
56
+
57
+ `sp-rag` public bây giờ dùng token gắn với tài khoản thật trên server.
58
+
59
+ Luồng chuẩn:
60
+
61
+ 1. đăng nhập dashboard hoặc API account của GraphRAG
62
+ 2. tạo `personal access token` qua account hiện tại
63
+ 3. dùng chính token `grc_pat_*` đó cho MCP và CLI
64
+ 4. kiểm tra token bằng `sp-rag token verify`
65
+
66
+ Điểm quan trọng:
67
+
68
+ - token dev dùng cho MCP nên là `grc_pat_*` của account
69
+ - quyền nhìn thấy tool/resource trên MCP bám theo role của account đó
70
+ - `viewer`, `operator`, `approver`, `admin` sẽ thấy inventory khác nhau
71
+ - `MCP_SERVER_ACCESS_TOKENS_JSON` chỉ còn là fallback legacy/break-glass, không còn là luồng chính cho dev
72
+ - khi client đã có sẵn một alias trỏ cùng MCP endpoint, CLI sẽ ưu tiên cập nhật alias đó thay vì tạo alias mới song song
73
+
74
+ Tự tạo PAT bằng API hiện có:
75
+
76
+ 1. lấy session token qua `POST /v1/account/login`
77
+ 2. gọi `POST /v1/account/personal-access-tokens`
78
+ 3. dùng trường `generated_token`
79
+
80
+ Ví dụ đầy đủ:
81
+
82
+ ```bash
83
+ curl -X POST https://sp-rag.secomapp.com/api/v1/account/login \
84
+ -H "Content-Type: application/json" \
85
+ -d '{"email":"dev@example.com","password":"<mật-khẩu>"}'
86
+ ```
87
+
88
+ Lấy `session_token`, rồi gọi tiếp:
89
+
90
+ ```bash
91
+ curl -X POST https://sp-rag.secomapp.com/api/v1/account/personal-access-tokens \
92
+ -H "Authorization: Bearer <grc_sess_...>" \
93
+ -H "Content-Type: application/json" \
94
+ -d '{"label":"SP-RAG CLI","expires_in_days":30}'
95
+ ```
96
+
97
+ Response sẽ trả `generated_token`, chính là token `grc_pat_*` để đưa vào `sp-rag`.
98
+
99
+ Ví dụ dev dùng token trực tiếp:
100
+
101
+ ```bash
102
+ npx sp-rag@latest install --client cursor --scope project --cwd D:/Webs/seo-booster --mcp-token <grc_pat_...>
103
+ npx sp-rag@latest token verify --token <grc_pat_...>
104
+ ```
105
+
106
+ Hoặc dùng biến môi trường:
107
+
108
+ ```bash
109
+ $env:GRAPHRAG_MCP_TOKEN="<grc_pat_...>"
110
+ npx sp-rag@latest mcp add vscode --scope project --cwd D:/Webs/seo-booster --auth-env-var GRAPHRAG_MCP_TOKEN
111
+ npx sp-rag@latest token verify --token $env:GRAPHRAG_MCP_TOKEN
51
112
  ```
52
113
 
53
114
  ## MCP client được hỗ trợ
@@ -102,17 +163,18 @@ Ghi chú:
102
163
  ## Luồng khuyên dùng cho dev mới
103
164
 
104
165
  ```bash
105
- sp-rag install --client codex --mcp-token <token truy cập MCP> --doctor
106
- sp-rag token add --token <token truy cập MCP> --client codex
166
+ sp-rag install --client codex --mcp-token <grc_pat_...> --doctor
167
+ sp-rag token add --token <grc_pat_...> --client codex
168
+ sp-rag token verify --token <grc_pat_...>
107
169
  sp-rag config show
108
170
  sp-rag codegraph status
109
171
  sp-rag codegraph watch --interval-ms 2000
110
172
  sp-rag codegraph runs --limit 5
111
173
  sp-rag codegraph metrics
112
174
  sp-rag codegraph recover --reason "Ops dọn stale run sau crash"
113
- sp-rag mcp add antigravity --mcp-token <token truy cập MCP>
114
- sp-rag mcp add vscode --scope project --cwd D:/Webs/seo-booster --mcp-token <token truy cập MCP>
115
- sp-rag mcp add opencode --scope project --cwd D:/Webs/seo-booster --mcp-token <token truy cập MCP>
175
+ sp-rag mcp add antigravity --mcp-token <grc_pat_...>
176
+ sp-rag mcp add vscode --scope project --cwd D:/Webs/seo-booster --mcp-token <grc_pat_...>
177
+ sp-rag mcp add opencode --scope project --cwd D:/Webs/seo-booster --mcp-token <grc_pat_...>
116
178
  sp-rag skill install
117
179
  sp-rag skill install --skill-client cursor --scope project --cwd D:/Webs/seo-booster
118
180
  sp-rag skill install --skill-client vscode --scope project --cwd D:/Webs/seo-booster
@@ -122,8 +184,9 @@ sp-rag eval run --file ./examples/eval-suite.sample.json
122
184
  ## Lệnh chính
123
185
 
124
186
  ```bash
125
- sp-rag install --client codex --mcp-token <token truy cập MCP> --doctor
126
- sp-rag token add --token <token truy cập MCP> --client codex
187
+ sp-rag install --client codex --mcp-token <grc_pat_...> --doctor
188
+ sp-rag token add --token <grc_pat_...> --client codex
189
+ sp-rag token verify --token <grc_pat_...>
127
190
  sp-rag config show
128
191
  sp-rag doctor
129
192
  sp-rag codegraph status
@@ -133,10 +196,10 @@ sp-rag codegraph metrics
133
196
  sp-rag codegraph recover --reason "Ops dọn stale run sau crash"
134
197
  sp-rag codegraph sync --branch master --commit-sha <sha> --webhook-token <token webhook codegraph> --gitlab-job-token <ci-job-token>
135
198
  sp-rag docs get public --format md
136
- sp-rag mcp add codex --mcp-token <token truy cập MCP>
137
- sp-rag mcp add antigravity --mcp-token <token truy cập MCP>
138
- sp-rag mcp add vscode --scope project --cwd D:/Webs/seo-booster --mcp-token <token truy cập MCP>
139
- sp-rag mcp add opencode --scope project --cwd D:/Webs/seo-booster --mcp-token <token truy cập MCP>
199
+ sp-rag mcp add codex --mcp-token <grc_pat_...>
200
+ sp-rag mcp add antigravity --mcp-token <grc_pat_...>
201
+ sp-rag mcp add vscode --scope project --cwd D:/Webs/seo-booster --mcp-token <grc_pat_...>
202
+ sp-rag mcp add opencode --scope project --cwd D:/Webs/seo-booster --mcp-token <grc_pat_...>
140
203
  sp-rag skill install
141
204
  sp-rag skill install --skill-client cursor --scope project --cwd D:/Webs/seo-booster
142
205
  sp-rag skill install --skill-client vscode --scope project --cwd D:/Webs/seo-booster
package/dist/cli.js CHANGED
@@ -140,6 +140,7 @@ Lệnh chính:
140
140
  sp-rag install [--base-url URL] [--mcp-url URL] [--client codex|cursor|claude-code|antigravity|vscode|opencode] [--skill-client codex|cursor|claude-code|antigravity|vscode|opencode] [--scope global|project] [--mcp-token TOKEN] [--auth-env-var ENV_VAR] [--target-dir PATH]
141
141
  sp-rag init [--base-url URL] [--mcp-url URL] [--client codex|cursor|claude-code|antigravity|vscode|opencode] [--skill-client codex|cursor|claude-code|antigravity|vscode|opencode] [--scope global|project] [--auth-env-var ENV_VAR] [--target-dir PATH]
142
142
  sp-rag token add --token TOKEN [--client codex|cursor|claude-code|antigravity|vscode|opencode] [--scope global|project] [--cwd PATH]
143
+ sp-rag token verify [--token TOKEN] [--base-url URL]
143
144
  sp-rag config show
144
145
  sp-rag doctor [--base-url URL]
145
146
  sp-rag codegraph status [--base-url URL]
@@ -375,6 +376,21 @@ async function runTokenAdd(parsed) {
375
376
  },
376
377
  }, nextDefaults, client);
377
378
  }
379
+ async function runTokenVerify(parsed) {
380
+ const defaults = await loadRuntimeDefaults(parsed);
381
+ const token = optionString(parsed, 'token') ?? optionString(parsed, 'mcp-token') ?? defaults.mcpToken;
382
+ if (!token?.trim()) {
383
+ throw new Error('Thiếu token. Dùng --token <token>.');
384
+ }
385
+ const baseUrl = defaults.baseUrl.replace(/\/+$/, '');
386
+ const result = await fetchJson(`${baseUrl}/api/v1/ops/operator-auth`, {
387
+ method: 'GET',
388
+ headers: {
389
+ authorization: `Bearer ${token.trim()}`,
390
+ },
391
+ });
392
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
393
+ }
378
394
  async function runConfigShow(parsed) {
379
395
  const config = await loadCliConfig(optionString(parsed, 'home-dir'));
380
396
  process.stdout.write(`${JSON.stringify(config ?? {}, null, 2)}\n`);
@@ -427,6 +443,10 @@ export async function runCli(argv) {
427
443
  await runTokenAdd(parsed);
428
444
  return 0;
429
445
  }
446
+ if (group === 'token' && action === 'verify') {
447
+ await runTokenVerify(parsed);
448
+ return 0;
449
+ }
430
450
  if (group === 'config' && action === 'show') {
431
451
  await runConfigShow(parsed);
432
452
  return 0;
@@ -491,7 +511,7 @@ export async function runCli(argv) {
491
511
  return 0;
492
512
  }
493
513
  if (group === 'version') {
494
- process.stdout.write('sp-rag 0.5.0\n');
514
+ process.stdout.write('sp-rag 0.6.1\n');
495
515
  return 0;
496
516
  }
497
517
  process.stdout.write(helpText());
@@ -19,6 +19,13 @@ function withHeaders(target, headers) {
19
19
  headers,
20
20
  };
21
21
  }
22
+ function normalizeEndpoint(value) {
23
+ if (typeof value !== 'string') {
24
+ return null;
25
+ }
26
+ const trimmed = value.trim();
27
+ return trimmed ? trimmed.replace(/\/+$/, '') : null;
28
+ }
22
29
  function bearerHeader(authToken, authEnvVar, envStyle = 'shell') {
23
30
  const trimmedToken = authToken?.trim();
24
31
  if (trimmedToken) {
@@ -55,6 +62,29 @@ function upsertObjectEntry(base, sectionKey, entryKey, entryValue) {
55
62
  [sectionKey]: section,
56
63
  };
57
64
  }
65
+ function upsertObjectEntryPreservingAliasByEndpoint(base, sectionKey, entryKey, entryValue, endpointKey) {
66
+ const section = base[sectionKey] && typeof base[sectionKey] === 'object'
67
+ ? { ...base[sectionKey] }
68
+ : {};
69
+ const targetEndpoint = normalizeEndpoint(entryValue[endpointKey]);
70
+ const existingAlias = targetEndpoint
71
+ ? Object.entries(section).find(([alias, value]) => {
72
+ if (alias === entryKey || !value || typeof value !== 'object') {
73
+ return false;
74
+ }
75
+ return normalizeEndpoint(value[endpointKey]) === targetEndpoint;
76
+ })?.[0]
77
+ : undefined;
78
+ const aliasToWrite = existingAlias ?? entryKey;
79
+ section[aliasToWrite] = entryValue;
80
+ if (existingAlias && existingAlias !== entryKey && entryKey in section) {
81
+ delete section[entryKey];
82
+ }
83
+ return {
84
+ ...base,
85
+ [sectionKey]: section,
86
+ };
87
+ }
58
88
  function vscodeGlobalConfigPath(home) {
59
89
  if (process.platform === 'win32') {
60
90
  const appData = process.env['APPDATA']?.trim() || path.join(home, 'AppData', 'Roaming');
@@ -98,14 +128,14 @@ export function upsertJsonMcpConfig(existing, options) {
98
128
  ...(options.includeTypeHttp ? { type: 'http' } : {}),
99
129
  url: options.url,
100
130
  }, bearerHeader(options.authToken, options.authEnvVar, 'shell'));
101
- return `${JSON.stringify(upsertObjectEntry(base, 'mcpServers', options.serverAlias, serverConfig), null, 2)}\n`;
131
+ return `${JSON.stringify(upsertObjectEntryPreservingAliasByEndpoint(base, 'mcpServers', options.serverAlias, serverConfig, 'url'), null, 2)}\n`;
102
132
  }
103
133
  export function upsertAntigravityConfig(existing, options) {
104
134
  const base = parseJsonObject(existing);
105
135
  const serverConfig = withHeaders({
106
136
  serverUrl: options.url,
107
137
  }, bearerHeader(options.authToken, options.authEnvVar, 'shell'));
108
- return `${JSON.stringify(upsertObjectEntry(base, 'mcpServers', options.serverAlias, serverConfig), null, 2)}\n`;
138
+ return `${JSON.stringify(upsertObjectEntryPreservingAliasByEndpoint(base, 'mcpServers', options.serverAlias, serverConfig, 'serverUrl'), null, 2)}\n`;
109
139
  }
110
140
  export function upsertVsCodeConfig(existing, options) {
111
141
  const base = parseJsonObject(existing);
@@ -113,7 +143,7 @@ export function upsertVsCodeConfig(existing, options) {
113
143
  type: 'http',
114
144
  url: options.url,
115
145
  }, bearerHeader(options.authToken, options.authEnvVar, 'vscode'));
116
- return `${JSON.stringify(upsertObjectEntry(base, 'servers', options.serverAlias, serverConfig), null, 2)}\n`;
146
+ return `${JSON.stringify(upsertObjectEntryPreservingAliasByEndpoint(base, 'servers', options.serverAlias, serverConfig, 'url'), null, 2)}\n`;
117
147
  }
118
148
  export function upsertOpenCodeConfig(existing, options) {
119
149
  const base = parseJsonObject(existing);
@@ -130,7 +160,7 @@ export function upsertOpenCodeConfig(existing, options) {
130
160
  enabled: true,
131
161
  ...(headers ? { oauth: false } : {}),
132
162
  }, headers);
133
- return `${JSON.stringify(upsertObjectEntry(nextBase, 'mcp', options.serverAlias, serverConfig), null, 2)}\n`;
163
+ return `${JSON.stringify(upsertObjectEntryPreservingAliasByEndpoint(nextBase, 'mcp', options.serverAlias, serverConfig, 'url'), null, 2)}\n`;
134
164
  }
135
165
  export function resolveMcpConfigPath(options) {
136
166
  const inferredScope = options.client === 'codex' || options.client === 'antigravity'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sp-rag",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "CLI cho setup MCP, codegraph GitNexus và skill của SP-RAG",
5
5
  "type": "module",
6
6
  "files": [