sp-rag 0.6.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.6.0`
20
+ - version đang publish: `0.6.1`
21
21
  - binary public: `sp-rag`
22
22
 
23
23
  ## Cài từ source trong monorepo
@@ -69,6 +69,7 @@ Luồng chuẩn:
69
69
  - quyền nhìn thấy tool/resource trên MCP bám theo role của account đó
70
70
  - `viewer`, `operator`, `approver`, `admin` sẽ thấy inventory khác nhau
71
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
72
73
 
73
74
  Tự tạo PAT bằng API hiện có:
74
75
 
package/dist/cli.js CHANGED
@@ -511,7 +511,7 @@ export async function runCli(argv) {
511
511
  return 0;
512
512
  }
513
513
  if (group === 'version') {
514
- process.stdout.write('sp-rag 0.6.0\n');
514
+ process.stdout.write('sp-rag 0.6.1\n');
515
515
  return 0;
516
516
  }
517
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.6.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": [