sp-rag 0.6.15 → 0.6.16

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
@@ -32,9 +32,10 @@ CLI để setup nhanh SP-RAG theo hướng dev-friendly:
32
32
 
33
33
  ## Trạng thái package
34
34
 
35
- - package npm public: `sp-rag`
36
- - version đang publish: `0.6.15`
37
- - binary public: `sp-rag`
35
+ - package npm public: `sp-rag`
36
+ - version trong repo: `0.6.16`
37
+ - npm latest hiện tại: `0.6.15`
38
+ - binary public: `sp-rag`
38
39
 
39
40
  ## Cài từ source trong monorepo
40
41
 
@@ -289,10 +290,11 @@ sp-rag uninstall --client codex
289
290
 
290
291
  - ping các endpoint `api`, `mcp`, `codegraph`
291
292
  - đọc đúng file MCP của client để kiểm:
292
- - IDE đang nhìn vào file nào
293
- - server entry nào được match theo alias hoặc theo endpoint
294
- - `Authorization` đang là token literal, env var hợp lệ, hay đang thiếu
295
- - khả năng IDE sẽ bật link đăng nhập OAuth
293
+ - IDE đang nhìn vào file nào
294
+ - server entry nào được match theo alias hoặc theo endpoint
295
+ - `Authorization` đang là token literal, env var hợp lệ, hay đang thiếu
296
+ - riêng Codex, xác nhận `bearer_token_env_var`/`http_headers` thay legacy `[mcp_servers.<alias>.headers]`
297
+ - khả năng IDE sẽ bật link đăng nhập OAuth
296
298
 
297
299
  Ví dụ:
298
300
 
@@ -361,6 +363,10 @@ Day JSON signal do `sp-audit` tao ra vao server memory import path:
361
363
  sp-rag audit signal --file ./sp-audit-signal.json
362
364
  ```
363
365
 
366
+ `audit signal` posts through the existing knowledge-source import API with
367
+ `normalizer_provider=heuristic` and `warm_cache=false`, so small audit feedback
368
+ records do not block on AI normalization or semantic-cache materialization.
369
+
364
370
  Native paths cua audit workflow:
365
371
 
366
372
  - Codex: `~/.codex/skills/sp-audit/SKILL.md`
package/dist/cli.js CHANGED
@@ -655,6 +655,8 @@ async function runAuditSignal(parsed) {
655
655
  content_type: 'application/json',
656
656
  title_hint: titleHint,
657
657
  provider: optionString(parsed, 'provider') ?? 'builtin',
658
+ normalizer_provider: 'heuristic',
659
+ warm_cache: 'false',
658
660
  });
659
661
  const result = await fetchJson(`${defaults.baseUrl.replace(/\/+$/, '')}/api/v1/import/knowledge-source/file?${params.toString()}`, {
660
662
  method: 'POST',
@@ -62,7 +62,16 @@ function parseTomlEntries(raw) {
62
62
  const headersMatch = line.match(/^\[mcp_servers\.(?:"([^"]+)"|([^\].]+))\.headers\]$/);
63
63
  if (headersMatch) {
64
64
  currentAlias = headersMatch[1] || headersMatch[2];
65
- currentSection = 'headers';
65
+ currentSection = 'legacy_headers';
66
+ if (!entries.has(currentAlias)) {
67
+ entries.set(currentAlias, { alias: currentAlias });
68
+ }
69
+ continue;
70
+ }
71
+ const httpHeadersMatch = line.match(/^\[mcp_servers\.(?:"([^"]+)"|([^\].]+))\.http_headers\]$/);
72
+ if (httpHeadersMatch) {
73
+ currentAlias = httpHeadersMatch[1] || httpHeadersMatch[2];
74
+ currentSection = 'http_headers';
66
75
  if (!entries.has(currentAlias)) {
67
76
  entries.set(currentAlias, { alias: currentAlias });
68
77
  }
@@ -89,12 +98,21 @@ function parseTomlEntries(raw) {
89
98
  if (currentSection === 'server' && key === 'url') {
90
99
  entry.endpoint = normalizeEndpoint(value);
91
100
  }
92
- if (currentSection === 'headers') {
101
+ if (currentSection === 'server' && key === 'bearer_token_env_var') {
102
+ entry.bearerTokenEnvVar = value;
103
+ }
104
+ if (currentSection === 'http_headers') {
93
105
  entry.headers = {
94
106
  ...(entry.headers ?? {}),
95
107
  [key]: value,
96
108
  };
97
109
  }
110
+ if (currentSection === 'legacy_headers') {
111
+ entry.legacyHeaders = {
112
+ ...(entry.legacyHeaders ?? {}),
113
+ [key]: value,
114
+ };
115
+ }
98
116
  entries.set(currentAlias, entry);
99
117
  }
100
118
  return [...entries.values()];
@@ -186,6 +204,12 @@ function analyzeAuthorization(headerValue) {
186
204
  likelyOAuthLogin: true,
187
205
  };
188
206
  }
207
+ function analyzeEntryAuthorization(entry) {
208
+ if (entry.bearerTokenEnvVar?.trim()) {
209
+ return analyzeAuthorization(`Bearer \${${entry.bearerTokenEnvVar.trim()}}`);
210
+ }
211
+ return analyzeAuthorization(entry.headers?.Authorization ?? entry.headers?.authorization);
212
+ }
189
213
  function entriesForClient(raw, client) {
190
214
  if (client === 'codex') {
191
215
  return parseTomlEntries(raw);
@@ -233,8 +257,11 @@ export async function diagnoseMcpConfig(options) {
233
257
  ],
234
258
  };
235
259
  }
236
- const authorization = analyzeAuthorization(entry.headers?.Authorization ?? entry.headers?.authorization);
260
+ const authorization = analyzeEntryAuthorization(entry);
237
261
  const issues = [...baseResult.issues];
262
+ if (options.client === 'codex' && entry.legacyHeaders) {
263
+ issues.push('Codex config đang dùng legacy [mcp_servers.<alias>.headers]. Streamable HTTP MCP cần http_headers, env_http_headers hoặc bearer_token_env_var; legacy headers có thể không expose tools.');
264
+ }
238
265
  if (authorization.authorizationState === 'missing') {
239
266
  issues.push('Thiếu Authorization header. IDE rất dễ rơi sang luồng đăng nhập OAuth.');
240
267
  }
@@ -134,28 +134,38 @@ export function upsertCodexConfig(existing, options) {
134
134
  const aliasPattern = escapeRegex(alias);
135
135
  const cleaned = existing
136
136
  .replace(new RegExp(`(?:^|\\n)\\[mcp_servers\\.(?:"${aliasPattern}"|${aliasPattern})\\.headers\\][\\s\\S]*?(?=(?:\\n\\[[^\\n]+\\])|$)`, 'g'), '')
137
+ .replace(new RegExp(`(?:^|\\n)\\[mcp_servers\\.(?:"${aliasPattern}"|${aliasPattern})\\.http_headers\\][\\s\\S]*?(?=(?:\\n\\[[^\\n]+\\])|$)`, 'g'), '')
137
138
  .replace(new RegExp(`(?:^|\\n)\\[mcp_servers\\.(?:"${aliasPattern}"|${aliasPattern})\\][\\s\\S]*?(?=(?:\\n\\[[^\\n]+\\])|$)`, 'g'), '')
138
139
  .trimEnd();
139
140
  const lines = [
140
141
  `[mcp_servers.${quotedTomlKey(alias)}]`,
141
142
  `url = "${options.url}"`,
142
143
  ];
143
- const headers = bearerHeader(options.authToken, options.authEnvVar, 'shell');
144
- if (headers?.Authorization) {
145
- lines.push('', `[mcp_servers.${quotedTomlKey(alias)}.headers]`);
146
- lines.push(`Authorization = "${headers.Authorization.replace(/"/g, '\\"')}"`);
144
+ const literalHeaders = bearerHeader(options.authToken, undefined, 'shell');
145
+ if (literalHeaders?.Authorization) {
146
+ lines.push('', `[mcp_servers.${quotedTomlKey(alias)}.http_headers]`);
147
+ lines.push(`Authorization = "${literalHeaders.Authorization.replace(/"/g, '\\"')}"`);
148
+ }
149
+ else if (options.authEnvVar?.trim()) {
150
+ lines.push(`bearer_token_env_var = "${options.authEnvVar.trim().replace(/"/g, '\\"')}"`);
147
151
  }
148
152
  return `${cleaned ? `${cleaned}\n\n` : ''}${lines.join('\n')}\n`;
149
153
  }
150
- export function removeCodexConfigContent(existing, serverAlias) {
151
- const alias = serverAlias.trim();
152
- const aliasPattern = escapeRegex(alias);
154
+ function removeCodexSubtable(existing, aliasPattern, subtable) {
153
155
  let removed = false;
154
- const withoutHeaders = existing.replace(new RegExp(`(?:^|\\n)\\[mcp_servers\\.(?:"${aliasPattern}"|${aliasPattern})\\.headers\\][\\s\\S]*?(?=(?:\\n\\[[^\\n]+\\])|$)`, 'g'), () => {
156
+ const content = existing.replace(new RegExp(`(?:^|\\n)\\[mcp_servers\\.(?:"${aliasPattern}"|${aliasPattern})\\.${subtable}\\][\\s\\S]*?(?=(?:\\n\\[[^\\n]+\\])|$)`, 'g'), () => {
155
157
  removed = true;
156
158
  return '';
157
159
  });
158
- const cleaned = withoutHeaders.replace(new RegExp(`(?:^|\\n)\\[mcp_servers\\.(?:"${aliasPattern}"|${aliasPattern})\\][\\s\\S]*?(?=(?:\\n\\[[^\\n]+\\])|$)`, 'g'), () => {
160
+ return { content, removed };
161
+ }
162
+ export function removeCodexConfigContent(existing, serverAlias) {
163
+ const alias = serverAlias.trim();
164
+ const aliasPattern = escapeRegex(alias);
165
+ const withoutLegacyHeaders = removeCodexSubtable(existing, aliasPattern, 'headers');
166
+ const withoutHttpHeaders = removeCodexSubtable(withoutLegacyHeaders.content, aliasPattern, 'http_headers');
167
+ let removed = withoutLegacyHeaders.removed || withoutHttpHeaders.removed;
168
+ const cleaned = withoutHttpHeaders.content.replace(new RegExp(`(?:^|\\n)\\[mcp_servers\\.(?:"${aliasPattern}"|${aliasPattern})\\][\\s\\S]*?(?=(?:\\n\\[[^\\n]+\\])|$)`, 'g'), () => {
159
169
  removed = true;
160
170
  return '';
161
171
  });
package/dist/lib/skill.js CHANGED
@@ -139,6 +139,7 @@ Docs URL: \`${context.docsUrl}\`
139
139
 
140
140
  ${seoBoosterProjectGuard}
141
141
  ${seoBoosterReportGuard}
142
+ - Codex streamable HTTP MCP config must use \`http_headers\`, \`env_http_headers\`, or \`bearer_token_env_var\`; \`[mcp_servers.<alias>.headers]\` is legacy-invalid and will not expose tools.
142
143
  - Find root cause before fixing bugs.
143
144
  - Use evidence before conclusions; do not claim completion without verification.
144
145
  - For behavior changes, write or update tests before implementation when feasible.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sp-rag",
3
- "version": "0.6.15",
3
+ "version": "0.6.16",
4
4
  "description": "CLI cho setup MCP, codegraph GitNexus và skill của SP-RAG",
5
5
  "type": "module",
6
6
  "files": [