@syke1/mcp-server 1.6.0 → 1.7.0
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/LICENSE +13 -57
- package/README.md +18 -21
- package/dist/ai/analyzer.js +112 -1
- package/dist/ai/context-extractor.js +224 -1
- package/dist/ai/provider.js +186 -1
- package/dist/ai/realtime-analyzer.js +253 -1
- package/dist/config.js +121 -1
- package/dist/git/change-coupling.js +250 -1
- package/dist/graph/incremental.js +313 -1
- package/dist/graph/memo-cache.js +176 -1
- package/dist/graph/scc.js +206 -1
- package/dist/graph.d.ts +0 -3
- package/dist/graph.js +130 -1
- package/dist/index.js +825 -1
- package/dist/license/validator.d.ts +0 -3
- package/dist/license/validator.js +344 -1
- package/dist/remote/proxy.d.ts +34 -0
- package/dist/remote/proxy.js +214 -0
- package/dist/remote/types.d.ts +81 -0
- package/dist/remote/types.js +8 -0
- package/dist/tools/analyze-impact.d.ts +5 -5
- package/dist/tools/analyze-impact.js +326 -1
- package/dist/tools/gate-build.d.ts +0 -3
- package/dist/tools/gate-build.js +361 -1
- package/dist/watcher/file-cache.js +281 -1
- package/dist/web/server.js +925 -1
- package/package.json +52 -69
- package/dist/scoring/pagerank.d.ts +0 -67
- package/dist/scoring/pagerank.js +0 -1
- package/dist/scoring/risk-scorer.d.ts +0 -99
- package/dist/scoring/risk-scorer.js +0 -1
package/dist/ai/provider.js
CHANGED
|
@@ -1 +1,186 @@
|
|
|
1
|
-
'use strict';const _0x493d43=_0x47b6;(function(_0x3ba2b5,_0x34bc02){const _0x5076fc={_0x147759:0x230,_0x430041:0x226},_0x5c6053=_0x47b6,_0x10849f=_0x3ba2b5();while(!![]){try{const _0x37c28d=parseInt(_0x5c6053(0x216))/0x1+parseInt(_0x5c6053(0x22b))/0x2*(-parseInt(_0x5c6053(0x224))/0x3)+parseInt(_0x5c6053(_0x5076fc._0x147759))/0x4+parseInt(_0x5c6053(0x222))/0x5+parseInt(_0x5c6053(_0x5076fc._0x430041))/0x6*(parseInt(_0x5c6053(0x1fb))/0x7)+-parseInt(_0x5c6053(0x235))/0x8+-parseInt(_0x5c6053(0x1f4))/0x9*(parseInt(_0x5c6053(0x205))/0xa);if(_0x37c28d===_0x34bc02)break;else _0x10849f['push'](_0x10849f['shift']());}catch(_0x23a8d6){_0x10849f['push'](_0x10849f['shift']());}}}(_0x3f65,0x95da1));function _0x47b6(_0x452f45,_0x542d24){_0x452f45=_0x452f45-0x1f2;const _0x3f6568=_0x3f65();let _0x47b6dd=_0x3f6568[_0x452f45];if(_0x47b6['aNPgti']===undefined){var _0x10d35f=function(_0x5bd990){const _0x2e5244='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x2e579d='',_0x1b85f5='';for(let _0x49b9b2=0x0,_0x1920b2,_0x415bcf,_0x319050=0x0;_0x415bcf=_0x5bd990['charAt'](_0x319050++);~_0x415bcf&&(_0x1920b2=_0x49b9b2%0x4?_0x1920b2*0x40+_0x415bcf:_0x415bcf,_0x49b9b2++%0x4)?_0x2e579d+=String['fromCharCode'](0xff&_0x1920b2>>(-0x2*_0x49b9b2&0x6)):0x0){_0x415bcf=_0x2e5244['indexOf'](_0x415bcf);}for(let _0x3ca0c9=0x0,_0x26dee6=_0x2e579d['length'];_0x3ca0c9<_0x26dee6;_0x3ca0c9++){_0x1b85f5+='%'+('00'+_0x2e579d['charCodeAt'](_0x3ca0c9)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1b85f5);};_0x47b6['VwMhWD']=_0x10d35f,_0x47b6['jWRAeS']={},_0x47b6['aNPgti']=!![];}const _0x467946=_0x3f6568[0x0],_0x3c0cd7=_0x452f45+_0x467946,_0x2981be=_0x47b6['jWRAeS'][_0x3c0cd7];return!_0x2981be?(_0x47b6dd=_0x47b6['VwMhWD'](_0x47b6dd),_0x47b6['jWRAeS'][_0x3c0cd7]=_0x47b6dd):_0x47b6dd=_0x2981be,_0x47b6dd;}function _0x3f65(){const _0x316568=['DMfSDwu','zuvXzwG','ue9tva','rMPQCxq','z2vTAw5PltiUns1MBgfZAa','t3bLBKfjiefqssbLCNjVCIa','w3n5A2vDifnzs0vFquLFufjpvKLervi9','Dg9mB3DLCKnHC2u','mJeYodmYmejhCLHfDa','zgvMAw5LuhjVCgvYDhK','m2Hstxjcza','t1bftKfjx0Tfwq','mJCYnJq5nKvWuvfjDW','CgfYDhm','yxbPs2v5','BMfTzq','Bwf0y2G','mJK4nJGYshruChDI','DhLWzq','zunOqNi','Bw9KzwW','C3LZDgvT','mZiWndyZnLzoyM5KDa','qgDVB2DSzs9Nzw5LCMf0AxzLlwfP','qLPZDhG','CMvZCg9UC2u','BKTtu24','nJu2nJiXnMzwy01WBa','z2v0uhjVDMLKzxjoyw1L','y2XHDwrLlxnVBM5LDc00ltiWmJuWnte0','qxbyAM4','q1PuDwy','mtqYmKXzsxDOra','yxbWBgLJyxrPB24VANnVBG','r0vnsu5jx0Tfwq','CMvZzxrbsvbYB3zPzgvY','zu1xy3i','u3PfDhi','q29UDgvUDc1uExbL','mtrVrKPXwNm','yw50AhjVCgLJ','zxjYB3i','y29UDgvUDa','tuPbwKK','B3bLBMfPs2v5','C3rYAw5NAwz5','ELHNAe4','z2vTAw5Ps2v5','yw5HBhL6zuPtt04','nde1nZbQrwX1uMe','C2PHBfy','CM9Szq','C3rHDhvZ','z2vTAw5P','DxnLCG','z2v0q29UzMLN','yw5HBhL6zq','z3b0ltrVlw1PBMK','qw50AhjVCgLJiefqssbLCNjVCIa','Dgv4Da','uLPqCvm','cGPszxnWB25KihDPDgGGsLnptIbVBMX5lIboBYbLEhbSyw5HDg9YEsb0zxH0lcbQDxn0ihb1CMuGsLnptI4','BwvZC2fNzq','Ahr0Chm6lY9HCgKUB3bLBMfPlMnVBs92ms9JAgf0l2nVBxbSzxrPB25Z','y2HVAwnLCW','thLlvwO','mta1mdyYsNjPC25m','EK1OteW','ywzfCMO','CgfYC2u'];_0x3f65=function(){return _0x316568;};return _0x3f65();}const _0x4e7095={};_0x4e7095[_0x493d43(0x21a)]=!![],Object[_0x493d43(0x223)](exports,'__esModule',_0x4e7095),exports['getAIProvider']=getAIProvider,exports[_0x493d43(0x1f7)]=resetAIProvider,exports[_0x493d43(0x236)]=getProviderName;const generative_ai_1=require(_0x493d43(0x231)),config_1=require('../config');class GeminiProvider{constructor(_0x17af78){const _0x4d82c2={};_0x4d82c2['wpXCF']='Gemini\x20(gemini-2.5-flash)';const _0x5c1551=_0x4d82c2;this['name']=_0x5c1551['wpXCF'],this['ai']=new generative_ai_1['GoogleGenerativeAI'](_0x17af78);}async['analyze'](_0x3f14ab,_0x384b28){const _0xa57cc4={_0x24ca96:0x215,_0x50e2cf:0x21e,_0x31e1ef:0x233,_0x1dddf2:0x20f},_0x20deb4=_0x493d43,_0x400b1a={};_0x400b1a[_0x20deb4(_0xa57cc4._0x24ca96)]=_0x20deb4(_0xa57cc4._0x50e2cf);const _0x451f44=_0x400b1a,_0x3931fb={};_0x3931fb[_0x20deb4(0x22e)]=_0x451f44['LyKUj'];const _0x536377=this['ai']['getGenerativeModel'](_0x3931fb),_0x45cb2d={};_0x45cb2d['text']=_0x384b28;const _0x55d503={};_0x55d503[_0x20deb4(0x207)]='user',_0x55d503[_0x20deb4(0x227)]=[_0x45cb2d];const _0x11462b={};_0x11462b[_0x20deb4(0x20f)]=_0x3f14ab;const _0x2eccac={};_0x2eccac['role']='model',_0x2eccac[_0x20deb4(0x227)]=[_0x11462b];const _0x385a2f={};_0x385a2f['contents']=[_0x55d503],_0x385a2f['systemInstruction']=_0x2eccac;const _0x374acd=await _0x536377['generateContent'](_0x385a2f);return _0x374acd[_0x20deb4(_0xa57cc4._0x31e1ef)][_0x20deb4(_0xa57cc4._0x1dddf2)]();}async['analyzeJSON'](_0x31cafb,_0x4ff7bc){const _0x5d2f34={_0x12cac5:0x22a},_0xcef717=_0x493d43,_0x162090=await this['analyze'](_0x31cafb,_0x4ff7bc);let _0x40dc9c=_0x162090;const _0xefa534=_0x162090[_0xcef717(_0x5d2f34._0x12cac5)](/```(?:json)?\s*([\s\S]*?)```/);if(_0xefa534)_0x40dc9c=_0xefa534[0x1];return JSON['parse'](_0x40dc9c['trim']());}}class OpenAIProvider{constructor(_0x412093){const _0x4bfae7=_0x493d43;this[_0x4bfae7(0x229)]='OpenAI\x20(gpt-4o-mini)',this['apiKey']=_0x412093;}async['analyze'](_0x222697,_0x5acd1d){const _0x512e2f={_0x5444d9:0x21d,_0x4dce23:0x1f2,_0x422b80:0x20d,_0x127800:0x228,_0x10c37e:0x201,_0x2bbf6f:0x1ff,_0x1f0e2c:0x206,_0x23a6a2:0x214,_0x19aac3:0x1fe},_0x42b90d=_0x493d43,_0x50e917={};_0x50e917[_0x42b90d(_0x512e2f._0x5444d9)]=_0x42b90d(0x21c),_0x50e917[_0x42b90d(_0x512e2f._0x4dce23)]='application/json',_0x50e917['MJAZI']=_0x42b90d(_0x512e2f._0x422b80),_0x50e917['sjalV']='system';const _0x480739=_0x50e917,_0x3cefb2={};_0x3cefb2['role']=_0x42b90d(0x20a),_0x3cefb2['content']=_0x5acd1d;const _0x5baee6=await fetch('https://api.openai.com/v1/chat/completions',{'method':_0x480739[_0x42b90d(_0x512e2f._0x5444d9)],'headers':{'Content-Type':_0x480739['ApXjn'],'Authorization':'Bearer\x20'+this[_0x42b90d(_0x512e2f._0x127800)]},'body':JSON[_0x42b90d(_0x512e2f._0x10c37e)]({'model':_0x480739[_0x42b90d(_0x512e2f._0x2bbf6f)],'messages':[{'role':_0x480739[_0x42b90d(_0x512e2f._0x1f0e2c)],'content':_0x222697},_0x3cefb2],'temperature':0.3})});if(!_0x5baee6['ok']){const _0x26e952=await _0x5baee6['text']();throw new Error('OpenAI\x20API\x20error\x20'+_0x5baee6['status']+':\x20'+_0x26e952);}const _0x2c1b8f=await _0x5baee6['json']();return _0x2c1b8f[_0x42b90d(_0x512e2f._0x23a6a2)][0x0]['message'][_0x42b90d(_0x512e2f._0x19aac3)];}async[_0x493d43(0x204)](_0x3480be,_0x5cbd5a){const _0xb43c0a={_0x5b5225:0x22f,_0x571788:0x1f5,_0x565650:0x207,_0x2a8580:0x22c,_0x578e87:0x21c,_0x1bd607:0x20f,_0x11eadc:0x212},_0x42b324=_0x493d43,_0x120cb9={'tDyCv':function(_0xe2bccc,_0x3b2e5f,_0x5aac4a){return _0xe2bccc(_0x3b2e5f,_0x5aac4a);},'eChBr':_0x42b324(_0xb43c0a._0x5b5225)},_0x2d0998={};_0x2d0998[_0x42b324(0x1fa)]=_0x42b324(_0xb43c0a._0x571788),_0x2d0998['Authorization']='Bearer\x20'+this['apiKey'];const _0x1b791f={};_0x1b791f[_0x42b324(_0xb43c0a._0x565650)]='user',_0x1b791f['content']=_0x5cbd5a;const _0x2d59c3={};_0x2d59c3[_0x42b324(_0xb43c0a._0x2a8580)]='json_object';const _0x25d553=await _0x120cb9['tDyCv'](fetch,_0x42b324(0x213),{'method':_0x42b324(_0xb43c0a._0x578e87),'headers':_0x2d0998,'body':JSON['stringify']({'model':'gpt-4o-mini','messages':[{'role':_0x120cb9[_0x42b324(0x22d)],'content':_0x3480be},_0x1b791f],'temperature':0.3,'response_format':_0x2d59c3})});if(!_0x25d553['ok']){const _0x37c4dd=await _0x25d553[_0x42b324(_0xb43c0a._0x1bd607)]();throw new Error(_0x42b324(0x21f)+_0x25d553[_0x42b324(0x208)]+':\x20'+_0x37c4dd);}const _0x16533f=await _0x25d553['json']();return JSON['parse'](_0x16533f['choices'][0x0][_0x42b324(_0xb43c0a._0x11eadc)]['content']);}}class AnthropicProvider{constructor(_0x875d0b){this['name']='Claude\x20(claude-sonnet-4-20250514)',this['apiKey']=_0x875d0b;}async[_0x493d43(0x20c)](_0x7c455d,_0x1807d4){const _0x289fb4={_0x4857de:0x20f,_0x86d053:0x20e,_0x3042bb:0x208,_0x163e4d:0x1fe},_0x1fb656=_0x493d43,_0x389340={'zMhLL':function(_0x4ed595,_0x28d5ec,_0x211479){return _0x4ed595(_0x28d5ec,_0x211479);},'BZstx':'POST','BcLDB':'2023-06-01','eEqeh':_0x1fb656(0x237)},_0x5efeca={};_0x5efeca[_0x1fb656(0x207)]=_0x1fb656(0x20a),_0x5efeca['content']=_0x1807d4;const _0x10b835=await _0x389340[_0x1fb656(0x217)](fetch,'https://api.anthropic.com/v1/messages',{'method':_0x389340[_0x1fb656(0x232)],'headers':{'Content-Type':'application/json','x-api-key':this['apiKey'],'anthropic-version':_0x389340['BcLDB']},'body':JSON[_0x1fb656(0x201)]({'model':_0x389340[_0x1fb656(0x21b)],'max_tokens':0x1000,'system':_0x7c455d,'messages':[_0x5efeca]})});if(!_0x10b835['ok']){const _0x7b9530=await _0x10b835[_0x1fb656(_0x289fb4._0x4857de)]();throw new Error(_0x1fb656(_0x289fb4._0x86d053)+_0x10b835[_0x1fb656(_0x289fb4._0x3042bb)]+':\x20'+_0x7b9530);}const _0xe392c5=await _0x10b835['json']();return _0xe392c5[_0x1fb656(_0x289fb4._0x163e4d)][0x0]['text'];}async['analyzeJSON'](_0x532f66,_0x29e5a6){const _0x34308d={_0x9ee060:0x211,_0x2f27f1:0x219},_0x26aeb4=_0x493d43,_0x5907ba={};_0x5907ba[_0x26aeb4(0x1f8)]=_0x26aeb4(_0x34308d._0x9ee060);const _0xa51d96=_0x5907ba,_0x2314c1=await this['analyze'](_0x532f66+_0xa51d96['eMWcr'],_0x29e5a6);let _0x3b8777=_0x2314c1;const _0x4c6ed6=_0x2314c1['match'](/```(?:json)?\s*([\s\S]*?)```/);if(_0x4c6ed6)_0x3b8777=_0x4c6ed6[0x1];return JSON[_0x26aeb4(_0x34308d._0x2f27f1)](_0x3b8777['trim']());}}let cachedProvider=undefined;function getAIProvider(){const _0x3593b3={_0x12e06e:0x1f6,_0x11de64:0x218,_0x2d224c:0x1f9,_0x25bca1:0x1fc,_0x1bd50e:0x20b,_0x369592:0x220},_0x2c6161=_0x493d43,_0x569af8={};_0x569af8['sELcH']='aiProvider',_0x569af8[_0x2c6161(0x1f3)]='SYKE_AI_PROVIDER',_0x569af8[_0x2c6161(0x234)]=_0x2c6161(0x203),_0x569af8['EYmKv']=_0x2c6161(_0x3593b3._0x12e06e),_0x569af8[_0x2c6161(_0x3593b3._0x11de64)]=_0x2c6161(0x225),_0x569af8[_0x2c6161(_0x3593b3._0x2d224c)]=function(_0x16ea99,_0xd3c884){return _0x16ea99===_0xd3c884;},_0x569af8[_0x2c6161(0x210)]=_0x2c6161(0x209),_0x569af8['GBrXH']='openai',_0x569af8['zXghN']=_0x2c6161(_0x3593b3._0x25bca1);const _0x36aaa3=_0x569af8;if(cachedProvider!==undefined)return cachedProvider;const _0x23b05a=(0x0,config_1[_0x2c6161(_0x3593b3._0x1bd50e)])(_0x36aaa3['sELcH'],_0x36aaa3['CZTuf'])?.[_0x2c6161(0x221)](),_0x5bb908=(0x0,config_1['getConfig'])(_0x36aaa3['nKSSn'],_0x36aaa3['EYmKv']),_0x510c4d=(0x0,config_1['getConfig'])(_0x2c6161(0x200),_0x36aaa3['afErj']),_0x4d1ade=(0x0,config_1['getConfig'])('anthropicKey','ANTHROPIC_KEY');if(_0x23b05a){if(_0x36aaa3[_0x2c6161(_0x3593b3._0x2d224c)](_0x23b05a,_0x36aaa3['RZPqS'])&&_0x5bb908)cachedProvider=new GeminiProvider(_0x5bb908);else{if(_0x36aaa3['SzEtr'](_0x23b05a,_0x36aaa3['GBrXH'])&&_0x510c4d)cachedProvider=new OpenAIProvider(_0x510c4d);else _0x23b05a===_0x36aaa3[_0x2c6161(0x202)]&&_0x4d1ade?cachedProvider=new AnthropicProvider(_0x4d1ade):(console[_0x2c6161(0x1fd)](_0x2c6161(_0x3593b3._0x369592)+_0x23b05a+'\x20but\x20no\x20matching\x20API\x20key\x20found'),cachedProvider=null);}return cachedProvider;}if(_0x5bb908)cachedProvider=new GeminiProvider(_0x5bb908);else{if(_0x510c4d)cachedProvider=new OpenAIProvider(_0x510c4d);else _0x4d1ade?cachedProvider=new AnthropicProvider(_0x4d1ade):cachedProvider=null;}return cachedProvider;}function resetAIProvider(){cachedProvider=undefined;}function getProviderName(){const _0x17998c=_0x493d43,_0xc0bce8={'uPcIh':function(_0x586abd){return _0x586abd();}},_0x332f0f=_0xc0bce8['uPcIh'](getAIProvider);return _0x332f0f?_0x332f0f[_0x17998c(0x229)]:'disabled';}
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AI Provider abstraction — Multi-AI support (Gemini, OpenAI, Anthropic)
|
|
4
|
+
* Automatically selects the best available provider based on API keys.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.getAIProvider = getAIProvider;
|
|
8
|
+
exports.resetAIProvider = resetAIProvider;
|
|
9
|
+
exports.getProviderName = getProviderName;
|
|
10
|
+
const generative_ai_1 = require("@google/generative-ai");
|
|
11
|
+
const config_1 = require("../config");
|
|
12
|
+
// ── Gemini ──────────────────────────────────────────────────────────
|
|
13
|
+
class GeminiProvider {
|
|
14
|
+
constructor(apiKey) {
|
|
15
|
+
this.name = "Gemini (gemini-2.5-flash)";
|
|
16
|
+
this.ai = new generative_ai_1.GoogleGenerativeAI(apiKey);
|
|
17
|
+
}
|
|
18
|
+
async analyze(systemPrompt, userPrompt) {
|
|
19
|
+
const model = this.ai.getGenerativeModel({ model: "gemini-2.5-flash" });
|
|
20
|
+
const result = await model.generateContent({
|
|
21
|
+
contents: [{ role: "user", parts: [{ text: userPrompt }] }],
|
|
22
|
+
systemInstruction: { role: "model", parts: [{ text: systemPrompt }] },
|
|
23
|
+
});
|
|
24
|
+
return result.response.text();
|
|
25
|
+
}
|
|
26
|
+
async analyzeJSON(systemPrompt, userPrompt) {
|
|
27
|
+
const text = await this.analyze(systemPrompt, userPrompt);
|
|
28
|
+
let jsonStr = text;
|
|
29
|
+
const jsonMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
30
|
+
if (jsonMatch)
|
|
31
|
+
jsonStr = jsonMatch[1];
|
|
32
|
+
return JSON.parse(jsonStr.trim());
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// ── OpenAI ──────────────────────────────────────────────────────────
|
|
36
|
+
class OpenAIProvider {
|
|
37
|
+
constructor(apiKey) {
|
|
38
|
+
this.name = "OpenAI (gpt-4o-mini)";
|
|
39
|
+
this.apiKey = apiKey;
|
|
40
|
+
}
|
|
41
|
+
async analyze(systemPrompt, userPrompt) {
|
|
42
|
+
const res = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
43
|
+
method: "POST",
|
|
44
|
+
headers: {
|
|
45
|
+
"Content-Type": "application/json",
|
|
46
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
47
|
+
},
|
|
48
|
+
body: JSON.stringify({
|
|
49
|
+
model: "gpt-4o-mini",
|
|
50
|
+
messages: [
|
|
51
|
+
{ role: "system", content: systemPrompt },
|
|
52
|
+
{ role: "user", content: userPrompt },
|
|
53
|
+
],
|
|
54
|
+
temperature: 0.3,
|
|
55
|
+
}),
|
|
56
|
+
});
|
|
57
|
+
if (!res.ok) {
|
|
58
|
+
const body = await res.text();
|
|
59
|
+
throw new Error(`OpenAI API error ${res.status}: ${body}`);
|
|
60
|
+
}
|
|
61
|
+
const data = (await res.json());
|
|
62
|
+
return data.choices[0].message.content;
|
|
63
|
+
}
|
|
64
|
+
async analyzeJSON(systemPrompt, userPrompt) {
|
|
65
|
+
const res = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
66
|
+
method: "POST",
|
|
67
|
+
headers: {
|
|
68
|
+
"Content-Type": "application/json",
|
|
69
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
70
|
+
},
|
|
71
|
+
body: JSON.stringify({
|
|
72
|
+
model: "gpt-4o-mini",
|
|
73
|
+
messages: [
|
|
74
|
+
{ role: "system", content: systemPrompt },
|
|
75
|
+
{ role: "user", content: userPrompt },
|
|
76
|
+
],
|
|
77
|
+
temperature: 0.3,
|
|
78
|
+
response_format: { type: "json_object" },
|
|
79
|
+
}),
|
|
80
|
+
});
|
|
81
|
+
if (!res.ok) {
|
|
82
|
+
const body = await res.text();
|
|
83
|
+
throw new Error(`OpenAI API error ${res.status}: ${body}`);
|
|
84
|
+
}
|
|
85
|
+
const data = (await res.json());
|
|
86
|
+
return JSON.parse(data.choices[0].message.content);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// ── Anthropic ───────────────────────────────────────────────────────
|
|
90
|
+
class AnthropicProvider {
|
|
91
|
+
constructor(apiKey) {
|
|
92
|
+
this.name = "Claude (claude-sonnet-4-20250514)";
|
|
93
|
+
this.apiKey = apiKey;
|
|
94
|
+
}
|
|
95
|
+
async analyze(systemPrompt, userPrompt) {
|
|
96
|
+
const res = await fetch("https://api.anthropic.com/v1/messages", {
|
|
97
|
+
method: "POST",
|
|
98
|
+
headers: {
|
|
99
|
+
"Content-Type": "application/json",
|
|
100
|
+
"x-api-key": this.apiKey,
|
|
101
|
+
"anthropic-version": "2023-06-01",
|
|
102
|
+
},
|
|
103
|
+
body: JSON.stringify({
|
|
104
|
+
model: "claude-sonnet-4-20250514",
|
|
105
|
+
max_tokens: 4096,
|
|
106
|
+
system: systemPrompt,
|
|
107
|
+
messages: [{ role: "user", content: userPrompt }],
|
|
108
|
+
}),
|
|
109
|
+
});
|
|
110
|
+
if (!res.ok) {
|
|
111
|
+
const body = await res.text();
|
|
112
|
+
throw new Error(`Anthropic API error ${res.status}: ${body}`);
|
|
113
|
+
}
|
|
114
|
+
const data = (await res.json());
|
|
115
|
+
return data.content[0].text;
|
|
116
|
+
}
|
|
117
|
+
async analyzeJSON(systemPrompt, userPrompt) {
|
|
118
|
+
const text = await this.analyze(systemPrompt + "\n\nRespond with JSON only. No explanatory text, just pure JSON.", userPrompt);
|
|
119
|
+
let jsonStr = text;
|
|
120
|
+
const jsonMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
121
|
+
if (jsonMatch)
|
|
122
|
+
jsonStr = jsonMatch[1];
|
|
123
|
+
return JSON.parse(jsonStr.trim());
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// ── Factory ─────────────────────────────────────────────────────────
|
|
127
|
+
let cachedProvider = undefined;
|
|
128
|
+
/**
|
|
129
|
+
* Returns the best available AI provider, or null if no API key is set.
|
|
130
|
+
*
|
|
131
|
+
* Priority:
|
|
132
|
+
* 1. SYKE_AI_PROVIDER env var forces a specific provider
|
|
133
|
+
* 2. Auto-select: GEMINI_KEY > OPENAI_KEY > ANTHROPIC_KEY
|
|
134
|
+
*/
|
|
135
|
+
function getAIProvider() {
|
|
136
|
+
if (cachedProvider !== undefined)
|
|
137
|
+
return cachedProvider;
|
|
138
|
+
const forced = (0, config_1.getConfig)("aiProvider", "SYKE_AI_PROVIDER")?.toLowerCase();
|
|
139
|
+
const geminiKey = (0, config_1.getConfig)("geminiKey", "GEMINI_KEY");
|
|
140
|
+
const openaiKey = (0, config_1.getConfig)("openaiKey", "OPENAI_KEY");
|
|
141
|
+
const anthropicKey = (0, config_1.getConfig)("anthropicKey", "ANTHROPIC_KEY");
|
|
142
|
+
if (forced) {
|
|
143
|
+
if (forced === "gemini" && geminiKey) {
|
|
144
|
+
cachedProvider = new GeminiProvider(geminiKey);
|
|
145
|
+
}
|
|
146
|
+
else if (forced === "openai" && openaiKey) {
|
|
147
|
+
cachedProvider = new OpenAIProvider(openaiKey);
|
|
148
|
+
}
|
|
149
|
+
else if (forced === "anthropic" && anthropicKey) {
|
|
150
|
+
cachedProvider = new AnthropicProvider(anthropicKey);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
console.error(`[syke] SYKE_AI_PROVIDER=${forced} but no matching API key found`);
|
|
154
|
+
cachedProvider = null;
|
|
155
|
+
}
|
|
156
|
+
return cachedProvider;
|
|
157
|
+
}
|
|
158
|
+
// Auto-select
|
|
159
|
+
if (geminiKey) {
|
|
160
|
+
cachedProvider = new GeminiProvider(geminiKey);
|
|
161
|
+
}
|
|
162
|
+
else if (openaiKey) {
|
|
163
|
+
cachedProvider = new OpenAIProvider(openaiKey);
|
|
164
|
+
}
|
|
165
|
+
else if (anthropicKey) {
|
|
166
|
+
cachedProvider = new AnthropicProvider(anthropicKey);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
cachedProvider = null;
|
|
170
|
+
}
|
|
171
|
+
return cachedProvider;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Reset the cached provider so the next getAIProvider() call re-evaluates config.
|
|
175
|
+
* Call this after changing API keys at runtime.
|
|
176
|
+
*/
|
|
177
|
+
function resetAIProvider() {
|
|
178
|
+
cachedProvider = undefined;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Human-readable name for the active AI provider (for logs/UI).
|
|
182
|
+
*/
|
|
183
|
+
function getProviderName() {
|
|
184
|
+
const provider = getAIProvider();
|
|
185
|
+
return provider ? provider.name : "disabled";
|
|
186
|
+
}
|
|
@@ -1 +1,253 @@
|
|
|
1
|
-
'use strict';const _0x16502c=_0x389d;function _0x1720(){const _0xc915d2=['cI0GuMvTB3zLzdOG','quKGyw5HBhLZAxmGC2TPChbLzdOGCMf0zsbSAw1PDcaOmtaGy2fSBhmVBwLUkq','B2XKq29UDgvUDa','zgPqqMK','C3vTBwfYEq','z2v0t3DUuhjVCgvYDhLoyw1LCW','tMv3igzPBguGywrKzwq6cMbGya','wfHxt1a','CMv2zxjZzq','cLbYB2PLy3qGBgfUz3vHz2vZoIa','CMvZDwX0','mtm4mdy5ne5cDhfYzq','yNvPBgrtBwfYDenVBNrLEhq','zgLMzG','w3n5A2u6ywLDifjHDguGBgLTAxqGCMvHy2HLzcaO','w3n5A2u6ywLDiefUywX5C2LZigvYCM9YigzVCIa','iokaLcbZA2LWCgLUzYbbssbJywXS','wgTpzfq','AgfZ','BgvUz3rO','y3jLyxrL','lI9JB250zxH0lwv4DhjHy3rVCG','BMv3u2LNBMf0DxjL','y2fSBa','odq5odqZr1nTBfnc','cN4Gq2HHBMDLzdOG','yw5HBhL6zuPtt04','mtG3mZm2nxrqy2PYzq','nJm4nZGXAgPYueTk','mtGXndq0oe1VqNfUzG','u3HIBKq','Bwq1','CMvTB3zLza','x19PBxbVCNrtDgfY','BM93','kYbm','zgLMzLnPz25HDhvYzxm','ChjVDg90ExbL','B2XKu2LNBMf0DxjL','C2LKzuvMzMvJDhm','C2XPy2u','z2v0','DhLWzq','zxjYB3i','DxbKyxrL','tM8GquKGChjVDMLKzxiGyxzHAwXHyMXLicHZzxqGr0vnsu5jx0TfwsWGt1bftKfjx0TfwsWGB3iGqu5usfjpueLdx0TfwsK','zgvMAw5LuhjVCgvYDhK','vNHzz0S','tuvesvvn','lI4VDg9VBhmVyw5HBhL6zs1PBxbHy3q','D2fYBMLUz3m','AvHSyu8','BMv3q29UDgvUDa','neneq1DNuq','yw5HBhLZAxnnCW','ChvZAa','EhDqyLC','cMbGya','zMLSzq','cIaG4OAsicaGicaGia','ywzMzwn0zwroB2rLCW','tKv5rLy','rMLSzsbKzwXLDgvKlIbqCMv2Aw91CYbJB250zw50oGPGyga','q2HHBMDLzcbSAw5LCYaODg9WidmWig9Mia','seLhsa','x19JCMvHDgvcAw5KAw5N','BMv3','D3jPDgfIBgu','BgLUzq','zgvSzxrL','BM9YBwfSAxPL','BwvZC2fNzq','mKnWC0Pera','zgvMyxvSDa','ve1nsfG','AM9PBG','ywrKzwq','Agv4','iokgKIa','C291CMnLrgLY','y3jLyxrLsgfZAa','zgvSzxrLza','nZaZndeZmgzWwunHqG','BwfW','DMfSDwu','x19LC01VzhvSzq','v2fPDcbHig1VBwvUDcbMB3iGquKGyw5HBhLZAxmGDg8GCMvZDw1L','Aw5Zzxj0zwrbDa','y2HHBMDLvhLWzq','BgfUz3vHz2vZ','Dg9vChbLCKnHC2u','u09bDxq','B2XK','DgLTzxn0yw1W','shftB2O','CMvSyxrPDMu','nJm4ntyYANfSEu5f'];_0x1720=function(){return _0xc915d2;};return _0x1720();}(function(_0x36c636,_0xc4dd1f){const _0x4d9cf8={_0x284ce2:0x16f,_0x4d9c59:0x1a4,_0x5e21f2:0x15c,_0x2eef55:0x187,_0x492c16:0x193},_0x56661f=_0x389d,_0x398371=_0x36c636();while(!![]){try{const _0x87632c=-parseInt(_0x56661f(0x1a0))/0x1*(parseInt(_0x56661f(_0x4d9cf8._0x284ce2))/0x2)+-parseInt(_0x56661f(_0x4d9cf8._0x4d9c59))/0x3*(-parseInt(_0x56661f(_0x4d9cf8._0x5e21f2))/0x4)+parseInt(_0x56661f(0x1a3))/0x5+-parseInt(_0x56661f(_0x4d9cf8._0x2eef55))/0x6+-parseInt(_0x56661f(_0x4d9cf8._0x492c16))/0x7+parseInt(_0x56661f(0x1a5))/0x8+parseInt(_0x56661f(0x179))/0x9;if(_0x87632c===_0xc4dd1f)break;else _0x398371['push'](_0x398371['shift']());}catch(_0x26eb08){_0x398371['push'](_0x398371['shift']());}}}(_0x1720,0x6c060));var __createBinding=this&&this[_0x16502c(0x168)]||(Object['create']?function(_0xfcd8d0,_0x1c9361,_0x3cc500,_0x406283){const _0xd22401={_0x297228:0x1b1,_0x4fcdc2:0x17c,_0xbfc827:0x16a,_0x3dde71:0x1b1},_0x285555=_0x16502c,_0x554566={};_0x554566['AtjVy']=function(_0x4bb6e4,_0x409927){return _0x4bb6e4===_0x409927;};const _0x1658a8=_0x554566;if(_0x1658a8['AtjVy'](_0x406283,undefined))_0x406283=_0x3cc500;var _0x12a4c1=Object['getOwnPropertyDescriptor'](_0x1c9361,_0x3cc500);if(!_0x12a4c1||(_0x285555(_0xd22401._0x297228)in _0x12a4c1?!_0x1c9361[_0x285555(_0xd22401._0x4fcdc2)]:_0x12a4c1[_0x285555(_0xd22401._0xbfc827)]||_0x12a4c1['configurable'])){const _0x191bcd={};_0x191bcd['enumerable']=!![],_0x191bcd[_0x285555(_0xd22401._0x3dde71)]=function(){return _0x1c9361[_0x3cc500];},_0x12a4c1=_0x191bcd;}Object['defineProperty'](_0xfcd8d0,_0x406283,_0x12a4c1);}:function(_0x1f577d,_0x13b3f4,_0x4edd48,_0x20eb64){if(_0x20eb64===undefined)_0x20eb64=_0x4edd48;_0x1f577d[_0x20eb64]=_0x13b3f4[_0x4edd48];}),__setModuleDefault=this&&this['__setModuleDefault']||(Object[_0x16502c(0x19c)]?function(_0x1f0ecc,_0x277450){const _0x81d4f8={_0x5052e8:0x155},_0x39b006=_0x16502c,_0x30acaa={};_0x30acaa['enumerable']=!![],_0x30acaa[_0x39b006(0x17b)]=_0x277450,Object[_0x39b006(_0x81d4f8._0x5052e8)](_0x1f0ecc,_0x39b006(0x170),_0x30acaa);}:function(_0xeb879a,_0x16055e){const _0x260f29={_0x4379e1:0x170},_0x3bad31=_0x16502c;_0xeb879a[_0x3bad31(_0x260f29._0x4379e1)]=_0x16055e;}),__importStar=this&&this[_0x16502c(0x1a9)]||(function(){const _0x4ecf84={_0x52d16b:0x19b},_0x22fc67={_0x547e90:0x185},_0x370ff9={'HqSoj':function(_0x1751cd,_0x1efece){return _0x1751cd(_0x1efece);},'WZeXy':function(_0x24e322,_0x51ecba){return _0x24e322!==_0x51ecba;}};var _0xcf7211=function(_0x39eb5b){const _0x5d97c5=_0x389d;return _0xcf7211=Object[_0x5d97c5(0x18d)]||function(_0x3e4276){const _0x185e4a=_0x5d97c5;var _0x5e9030=[];for(var _0x3f4055 in _0x3e4276)if(Object[_0x185e4a(0x1ad)]['hasOwnProperty'][_0x185e4a(0x19f)](_0x3e4276,_0x3f4055))_0x5e9030[_0x5e9030['length']]=_0x3f4055;return _0x5e9030;},_0x370ff9[_0x5d97c5(_0x22fc67._0x547e90)](_0xcf7211,_0x39eb5b);};return function(_0x4b2946){const _0x34230b=_0x389d;if(_0x4b2946&&_0x4b2946[_0x34230b(0x17c)])return _0x4b2946;var _0x52a452={};if(_0x4b2946!=null){for(var _0x51b8be=_0xcf7211(_0x4b2946),_0x202928=0x0;_0x202928<_0x51b8be[_0x34230b(_0x4ecf84._0x52d16b)];_0x202928++)if(_0x370ff9['WZeXy'](_0x51b8be[_0x202928],'default'))__createBinding(_0x52a452,_0x4b2946,_0x51b8be[_0x202928]);}return __setModuleDefault(_0x52a452,_0x4b2946),_0x52a452;};}());const _0x452df8={};_0x452df8['value']=!![],Object[_0x16502c(0x155)](exports,'__esModule',_0x452df8),exports['analyzeChangeRealtime']=analyzeChangeRealtime;const analyze_impact_1=require(_0x16502c(0x158)),crypto=__importStar(require('crypto')),path=__importStar(require('path')),provider_1=require('./provider'),context_extractor_1=require(_0x16502c(0x19d)),analysisCache=new Map(),MAX_CACHE_SIZE=0x64;function computeContentHash(_0x15c493,_0x33706a){const _0x48064e={_0x3aaa72:0x1b4},_0x47cbf3=_0x16502c,_0x2402d3={};_0x2402d3[_0x47cbf3(0x182)]=_0x47cbf3(0x1a7),_0x2402d3[_0x47cbf3(0x15a)]=function(_0x259fc8,_0x6f0990){return _0x259fc8+_0x6f0990;},_0x2402d3[_0x47cbf3(0x171)]='\x0a---\x0a';const _0x12ae44=_0x2402d3;return crypto[_0x47cbf3(0x177)](_0x12ae44['SOAut'])[_0x47cbf3(_0x48064e._0x3aaa72)](_0x12ae44['iXlaO']((_0x15c493||'')+_0x12ae44[_0x47cbf3(0x171)],_0x33706a))['digest'](_0x47cbf3(0x174));}function evictOldestCacheEntry(){const _0x16d961={_0x26f306:0x16c},_0x4f431e=_0x16502c,_0x588011={};_0x588011['nOvOo']=function(_0x52f911,_0x4743ee){return _0x52f911<_0x4743ee;};const _0x51ffd7=_0x588011;let _0x137021=null,_0x300e1d=Infinity;for(const [_0x574282,_0x3d0e67]of analysisCache){_0x51ffd7['nOvOo'](_0x3d0e67[_0x4f431e(0x17e)],_0x300e1d)&&(_0x300e1d=_0x3d0e67[_0x4f431e(0x17e)],_0x137021=_0x574282);}if(_0x137021)analysisCache[_0x4f431e(_0x16d961._0x26f306)](_0x137021);}const RATE_LIMIT_MAX=0xa,RATE_LIMIT_WINDOW_MS=0xea60,callTimestamps=[];function isRateLimited(){const _0x3e71f9={_0x596dae:0x1aa,_0x2c060a:0x156},_0x206765=_0x16502c,_0x2c767f={};_0x2c767f['VxYgK']=function(_0x4477d7,_0x3df335){return _0x4477d7>=_0x3df335;};const _0x53c88d=_0x2c767f,_0x26ff3c=Date[_0x206765(_0x3e71f9._0x596dae)]();while(callTimestamps['length']>0x0&&callTimestamps[0x0]<=_0x26ff3c-RATE_LIMIT_WINDOW_MS){callTimestamps['shift']();}return _0x53c88d[_0x206765(_0x3e71f9._0x2c060a)](callTimestamps[_0x206765(0x19b)],RATE_LIMIT_MAX);}function recordCall(){const _0x4a8f87={_0x1ae2f8:0x15e,_0x42489f:0x1aa},_0x52f2c5=_0x16502c;callTimestamps[_0x52f2c5(_0x4a8f87._0x1ae2f8)](Date[_0x52f2c5(_0x4a8f87._0x42489f)]());}function _0x389d(_0x1354e1,_0x467e3b){_0x1354e1=_0x1354e1-0x155;const _0x172018=_0x1720();let _0x389d5e=_0x172018[_0x1354e1];if(_0x389d['xzpodb']===undefined){var _0x2f49d3=function(_0x5d0a8b){const _0xa49c43='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x3c7da7='',_0x2d5af7='';for(let _0xf11820=0x0,_0x2fa26c,_0x137d5a,_0x310812=0x0;_0x137d5a=_0x5d0a8b['charAt'](_0x310812++);~_0x137d5a&&(_0x2fa26c=_0xf11820%0x4?_0x2fa26c*0x40+_0x137d5a:_0x137d5a,_0xf11820++%0x4)?_0x3c7da7+=String['fromCharCode'](0xff&_0x2fa26c>>(-0x2*_0xf11820&0x6)):0x0){_0x137d5a=_0xa49c43['indexOf'](_0x137d5a);}for(let _0x48bd7e=0x0,_0x247c85=_0x3c7da7['length'];_0x48bd7e<_0x247c85;_0x48bd7e++){_0x2d5af7+='%'+('00'+_0x3c7da7['charCodeAt'](_0x48bd7e)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x2d5af7);};_0x389d['AuMhZU']=_0x2f49d3,_0x389d['xdMPJI']={},_0x389d['xzpodb']=!![];}const _0x4fab8b=_0x172018[0x0],_0x1ef608=_0x1354e1+_0x4fab8b,_0x3709ec=_0x389d['xdMPJI'][_0x1ef608];return!_0x3709ec?(_0x389d5e=_0x389d['AuMhZU'](_0x389d5e),_0x389d['xdMPJI'][_0x1ef608]=_0x389d5e):_0x389d5e=_0x3709ec,_0x389d5e;}function getSystemPrompt(){return'You\x20are\x20a\x20senior\x20full-stack\x20architect\x20and\x20code\x20impact\x20monitoring\x20AI\x20with\x2020\x20years\x20of\x20experience.\x0aRole:\x20Detect\x20potential\x20errors\x20and\x20cascading\x20impacts\x20before\x20build\x20when\x20files\x20are\x20modified/added/deleted.\x0a\x0aAnalysis\x20principles:\x0a1.\x20Broken\x20imports/exports:\x20Check\x20if\x20deleted/renamed\x20classes/functions/variables\x20are\x20referenced\x20in\x20other\x20files\x0a2.\x20Type\x20mismatches:\x20Verify\x20parameter\x20types\x20and\x20return\x20type\x20changes\x20match\x20call\x20sites\x0a3.\x20State\x20management\x20cascade:\x20Impact\x20of\x20Provider/Notifier\x20changes\x20on\x20UI\x20and\x20business\x20logic\x0a4.\x20Routing\x20impact:\x20Effect\x20of\x20route/parameter\x20changes\x20on\x20navigation\x0a5.\x20Missing\x20initialization:\x20Whether\x20newly\x20added\x20Providers\x20are\x20properly\x20registered\x0a\x0aResponse\x20format\x20(must\x20be\x20JSON):\x0a{\x0a\x20\x20\x22riskLevel\x22:\x20\x22CRITICAL|HIGH|MEDIUM|LOW|SAFE\x22,\x0a\x20\x20\x22summary\x22:\x20\x22One-line\x20summary\x22,\x0a\x20\x20\x22brokenImports\x22:\x20[\x22List\x20of\x20potentially\x20broken\x20imports\x22],\x0a\x20\x20\x22sideEffects\x22:\x20[\x22List\x20of\x20expected\x20side\x20effects\x22],\x0a\x20\x20\x22warnings\x22:\x20[\x22List\x20of\x20warnings\x22],\x0a\x20\x20\x22suggestion\x22:\x20\x22Recommended\x20action\x22\x0a}\x0a\x0aCRITICAL:\x20Build\x20failure\x20certain\x0aHIGH:\x20Runtime\x20error\x20possible\x0aMEDIUM:\x20Behavior\x20change\x20possible\x0aLOW:\x20Minor\x20impact\x0aSAFE:\x20Safe\x20change\x0a\x0aRespond\x20with\x20JSON\x20only.\x20No\x20explanatory\x20text,\x20just\x20pure\x20JSON.';}async function analyzeChangeRealtime(_0x2a17d4,_0x420cb1,_0x364512){const _0x5002c9={_0x12f649:0x17d,_0x640095:0x1b5,_0x59d49c:0x157,_0x5aea80:0x180,_0x4397c5:0x190,_0x2fefd0:0x1b1,_0x425e65:0x186,_0x46fc84:0x176,_0x2dbfea:0x194,_0x4a317a:0x15e,_0x3ff214:0x165,_0x12f44b:0x160,_0xbcd3e6:0x1b2,_0x257e8c:0x15b,_0x961483:0x188,_0x23ec53:0x1ae,_0x3b3d98:0x194,_0x5e1060:0x191,_0x3816ce:0x172,_0x1734a9:0x19b,_0x3c3b26:0x17a,_0x4c03a9:0x198,_0x20e9ae:0x192,_0x186698:0x184,_0x122880:0x15d,_0x45eed0:0x1b3,_0x557d70:0x1b2,_0x19e775:0x18b,_0x4ed9ba:0x163,_0x3110a0:0x1a2,_0x32cdfc:0x1b2,_0x2a7e4e:0x15f,_0x33f0ac:0x197,_0xbb463f:0x184,_0x42ef10:0x164,_0x228933:0x19b,_0x54886f:0x18f},_0x2d39fb={_0x2f28ff:0x1a6,_0x11a08b:0x169,_0x398746:0x1a8,_0x405eff:0x16b,_0x51fb05:0x175},_0x154263=_0x16502c,_0xb1ed18={'SxbnD':function(_0x425aff,_0x5eb9df){return _0x425aff===_0x5eb9df;},'IVOMc':function(_0x5a3da7,_0x4e50b6){return _0x5a3da7(_0x4e50b6);},'QZFUb':function(_0x423cbf,_0x6e25bf){return _0x423cbf===_0x6e25bf;},'eqIAJ':function(_0x2993fe,_0xb28b2f){return _0x2993fe>_0xb28b2f;},'CoaEY':function(_0x35e0b5,_0x4633c8,_0xc280ad){return _0x35e0b5(_0x4633c8,_0xc280ad);},'eDdpH':function(_0x222603,_0x258f69){return _0x222603===_0x258f69;},'EpaiM':function(_0x2d97df,_0x33f47f){return _0x2d97df-_0x33f47f;},'djPBi':_0x154263(_0x5002c9._0x12f649),'XkOdT':_0x154263(_0x5002c9._0x640095),'vOfeB':function(_0x3089b7){return _0x3089b7();},'xwPbW':'LOW','zQrly':'Analysis\x20complete','BFmft':function(_0x175499,_0x3367a0){return _0x175499>=_0x3367a0;},'rIFdx':function(_0x1d7669,_0x4d406f){return _0x1d7669-_0x4d406f;},'NEyFV':function(_0x9f3d78,_0x12a8de){return _0x9f3d78>=_0x12a8de;},'XXWOP':_0x154263(_0x5002c9._0x59d49c)},_0x4dffc9=Date[_0x154263(0x1aa)](),_0x2fd773=_0x2a17d4['relativePath'],_0x1f4e6a=_0x420cb1[_0x154263(_0x5002c9._0x5aea80)][0x0]||'text',_0x3400e8=path[_0x154263(0x16d)](path['join'](_0x420cb1['sourceDir'],_0x2fd773));let _0x24bc83=[];if(_0x420cb1['files'][_0x154263(0x19a)](_0x3400e8)){const _0x1e00bc=await(0x0,analyze_impact_1['analyzeImpact'])(_0x3400e8,_0x420cb1);_0x24bc83=[..._0x1e00bc['directDependents'],..._0x1e00bc['transitiveDependents']];}const _0x3ecd10=[],_0x21e665=_0x420cb1[_0x154263(_0x5002c9._0x4397c5)][_0x154263(_0x5002c9._0x2fefd0)](_0x3400e8)||[],_0x4eb643=_0x420cb1['forward'][_0x154263(0x1b1)](_0x3400e8)||[],_0x48c1e7=[...new Set([..._0x21e665,..._0x4eb643])][_0x154263(0x1b0)](0x0,0x5);for(const _0x1ee89e of _0x48c1e7){const _0x1c52fc=path[_0x154263(_0x5002c9._0x425e65)](_0x420cb1[_0x154263(_0x5002c9._0x46fc84)],_0x1ee89e)['replace'](/\\/g,'/'),_0x52ba25=_0xb1ed18['IVOMc'](_0x364512,_0x1c52fc);if(_0x52ba25){const _0x4d0276=(0x0,context_extractor_1[_0x154263(_0x5002c9._0x2dbfea)])(_0x52ba25,_0x1f4e6a);_0x3ecd10[_0x154263(_0x5002c9._0x4a317a)]('###\x20'+_0x1c52fc+_0x154263(0x160)+_0x1f4e6a+'\x0a'+_0x4d0276+'\x0a```');}}let _0x3b9a64='';if(_0xb1ed18['QZFUb'](_0x2a17d4['type'],_0x154263(0x178)))_0x3b9a64=_0x154263(_0x5002c9._0x3ff214)+_0x1f4e6a+'\x0a'+(_0x2a17d4[_0x154263(0x18a)]||'')['split']('\x0a')['slice'](0x0,0x28)['join']('\x0a')+_0x154263(_0x5002c9._0x12f44b);else{if(_0x2a17d4[_0x154263(_0x5002c9._0xbcd3e6)]===_0x154263(0x173)){const _0x4ddceb=(0x0,context_extractor_1['buildSmartContext'])(_0x2a17d4['newContent']||'',_0x1f4e6a);_0x3b9a64=_0x154263(0x18e)+_0x1f4e6a+'\x0a'+_0x4ddceb+'\x0a```';}else{const _0x11ba11=_0x2a17d4[_0x154263(0x195)]['slice'](0x0,0x1e)[_0x154263(0x17a)](_0x6b4be0=>{const _0x248ebf=_0x154263;if(_0xb1ed18[_0x248ebf(_0x2d39fb._0x2f28ff)](_0x6b4be0[_0x248ebf(0x1b2)],'added'))return _0x248ebf(0x1ab)+_0x6b4be0['line']+':\x20'+_0x6b4be0[_0x248ebf(_0x2d39fb._0x11a08b)];if(_0x6b4be0['type']===_0x248ebf(_0x2d39fb._0x398746))return'-\x20L'+_0x6b4be0[_0x248ebf(_0x2d39fb._0x405eff)]+':\x20'+_0x6b4be0['old'];return'~\x20L'+_0x6b4be0[_0x248ebf(0x16b)]+':\x20'+_0x6b4be0[_0x248ebf(0x183)]+_0x248ebf(_0x2d39fb._0x51fb05)+_0x6b4be0[_0x248ebf(0x169)];});_0x3b9a64=_0x154263(0x166)+_0x2a17d4[_0x154263(0x195)][_0x154263(0x19b)]+'):\x0a```\x0a'+_0x11ba11['join']('\x0a')+_0x154263(0x160);if(_0x2a17d4['oldContent']&&_0x2a17d4[_0x154263(_0x5002c9._0x257e8c)]){const _0x3bd1db=(0x0,context_extractor_1[_0x154263(0x1ac)])(_0x2a17d4[_0x154263(0x18a)],_0x2a17d4[_0x154263(_0x5002c9._0x257e8c)],_0x1f4e6a);if(_0xb1ed18['eqIAJ'](_0x3bd1db['length'],0x0)){_0x3b9a64+='\x0a\x0a###\x20Structural\x20changes\x20(signature\x20diff)';for(const _0x3bb2f4 of _0x3bd1db){if(_0xb1ed18['SxbnD'](_0x3bb2f4['type'],_0x154263(0x173)))_0x3b9a64+='\x0a+\x20Added:\x20'+_0x3bb2f4[_0x154263(0x19e)];else _0x3bb2f4[_0x154263(0x1b2)]===_0x154263(0x1a8)?_0x3b9a64+=_0x154263(_0x5002c9._0x961483)+_0x3bb2f4[_0x154263(_0x5002c9._0x23ec53)]:_0x3b9a64+=_0x154263(0x1a1)+_0x3bb2f4['oldSignature']+_0x154263(0x162)+_0x3bb2f4[_0x154263(0x19e)];}}}if(_0x2a17d4[_0x154263(0x15b)]){const _0x12cd85=(0x0,context_extractor_1[_0x154263(_0x5002c9._0x3b3d98)])(_0x2a17d4[_0x154263(0x15b)],_0x1f4e6a);_0x3b9a64+='\x0a\x0aFull\x20file\x20after\x20modification:\x0a```'+_0x1f4e6a+'\x0a'+_0x12cd85+'\x0a```';}}}const _0x5754da='##\x20File\x20change\x20detected:\x20'+_0x2fd773+'\x0aChange\x20type:\x20'+_0x2a17d4['type'][_0x154263(0x181)]()+_0x154263(_0x5002c9._0x5e1060)+(_0x420cb1['languages'][_0x154263(_0x5002c9._0x3816ce)](',\x20')||'unknown')+'\x0aAffected\x20files:\x20'+_0x24bc83[_0x154263(_0x5002c9._0x1734a9)]+'\x0a\x0a'+_0x3b9a64+'\x0a\x0a'+(_0x3ecd10['length']>0x0?'##\x20Connected\x20files\x20('+_0x3ecd10[_0x154263(0x19b)]+')\x0a'+_0x3ecd10[_0x154263(_0x5002c9._0x3816ce)]('\x0a\x0a'):'No\x20connected\x20files')+'\x0a\x0aAnalyze\x20the\x20impact\x20of\x20this\x20change\x20on\x20the\x20project.',_0x197bd7=_0x2a17d4['diff'][_0x154263(_0x5002c9._0x3c3b26)](_0x3d8290=>_0x3d8290['type']+':'+_0x3d8290['line']+':'+(_0x3d8290[_0x154263(0x183)]||'')+':'+(_0x3d8290[_0x154263(0x169)]||''))[_0x154263(0x172)]('|'),_0x2def3a=_0xb1ed18['CoaEY'](computeContentHash,_0x2a17d4['newContent'],_0x197bd7),_0x2e3683=analysisCache[_0x154263(0x1b1)](_0x2fd773);if(_0x2e3683&&_0xb1ed18['eDdpH'](_0x2e3683['hash'],_0x2def3a)){console['error']('[syke:ai]\x20Cache\x20hit\x20for\x20'+_0x2fd773+_0x154263(_0x5002c9._0x4c03a9));const _0x45a0eb={..._0x2e3683[_0x154263(_0x5002c9._0x20e9ae)]};return _0x45a0eb[_0x154263(_0x5002c9._0x186698)]=_0x2a17d4['timestamp'],_0x45a0eb[_0x154263(_0x5002c9._0x122880)]=0x0,_0x45a0eb;}if(isRateLimited()){const _0xd0ac6f=_0xb1ed18['EpaiM'](Date[_0x154263(0x1aa)](),_0x4dffc9);console[_0x154263(_0x5002c9._0x45eed0)](_0x154263(0x196)+RATE_LIMIT_MAX+'/min)\x20—\x20skipping\x20AI\x20for\x20'+_0x2fd773);const _0x853194={};return _0x853194['file']=_0x2fd773,_0x853194[_0x154263(0x17f)]=_0x2a17d4[_0x154263(_0x5002c9._0x557d70)],_0x853194[_0x154263(_0x5002c9._0x186698)]=_0x2a17d4[_0x154263(0x184)],_0x853194['riskLevel']=_0x24bc83['length']>=0xa?_0x154263(0x167):_0x24bc83[_0x154263(0x19b)]>=0x5?_0x154263(0x157):'LOW',_0x853194[_0x154263(0x18c)]='Rate\x20limited\x20—\x20graph-based\x20analysis:\x20'+_0x24bc83[_0x154263(_0x5002c9._0x1734a9)]+'\x20files\x20impacted',_0x853194['brokenImports']=[],_0x853194[_0x154263(0x1af)]=[],_0x853194[_0x154263(0x159)]=[_0x154263(0x189)],_0x853194['suggestion']=_0xb1ed18[_0x154263(_0x5002c9._0x19e775)],_0x853194[_0x154263(_0x5002c9._0x4ed9ba)]=_0x24bc83,_0x853194['analysisMs']=_0xd0ac6f,_0x853194;}try{const _0x3a42c0=(0x0,provider_1['getAIProvider'])();if(!_0x3a42c0)throw new Error(_0xb1ed18[_0x154263(0x199)]);recordCall();const _0x1ef2ab=await _0x3a42c0[_0x154263(_0x5002c9._0x3110a0)](_0xb1ed18['vOfeB'](getSystemPrompt),_0x5754da),_0x3137d6=_0xb1ed18['EpaiM'](Date['now'](),_0x4dffc9),_0x123f86={};_0x123f86[_0x154263(0x161)]=_0x2fd773,_0x123f86['changeType']=_0x2a17d4[_0x154263(_0x5002c9._0x32cdfc)],_0x123f86[_0x154263(_0x5002c9._0x186698)]=_0x2a17d4['timestamp'],_0x123f86['riskLevel']=_0x1ef2ab['riskLevel']||_0xb1ed18[_0x154263(_0x5002c9._0x2a7e4e)],_0x123f86['summary']=_0x1ef2ab['summary']||_0xb1ed18['zQrly'],_0x123f86['brokenImports']=_0x1ef2ab['brokenImports']||[],_0x123f86['sideEffects']=_0x1ef2ab['sideEffects']||[],_0x123f86['warnings']=_0x1ef2ab['warnings']||[],_0x123f86['suggestion']=_0x1ef2ab['suggestion']||'',_0x123f86['affectedNodes']=_0x24bc83,_0x123f86['analysisMs']=_0x3137d6;const _0x4bec44=_0x123f86;if(_0xb1ed18['BFmft'](analysisCache['size'],MAX_CACHE_SIZE))evictOldestCacheEntry();return analysisCache['set'](_0x2fd773,{'hash':_0x2def3a,'result':_0x4bec44,'insertedAt':Date['now']()}),_0x4bec44;}catch(_0x54e5ed){const _0x2d8b5c=_0xb1ed18['rIFdx'](Date['now'](),_0x4dffc9);return console['error'](_0x154263(_0x5002c9._0x33f0ac)+_0x2fd773+':\x20'+_0x54e5ed[_0x154263(0x16e)]),{'file':_0x2fd773,'changeType':_0x2a17d4['type'],'timestamp':_0x2a17d4[_0x154263(_0x5002c9._0xbb463f)],'riskLevel':_0xb1ed18[_0x154263(_0x5002c9._0x42ef10)](_0x24bc83[_0x154263(_0x5002c9._0x228933)],0xa)?'HIGH':_0x24bc83[_0x154263(0x19b)]>=0x5?_0xb1ed18[_0x154263(_0x5002c9._0x54886f)]:_0xb1ed18[_0x154263(0x15f)],'summary':'AI\x20analysis\x20failed\x20—\x20graph-based\x20analysis:\x20'+_0x24bc83['length']+'\x20files\x20impacted','brokenImports':[],'sideEffects':[],'warnings':['AI\x20analysis\x20error:\x20'+_0x54e5ed['message']],'suggestion':'Manual\x20review\x20required','affectedNodes':_0x24bc83,'analysisMs':_0x2d8b5c};}}
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.analyzeChangeRealtime = analyzeChangeRealtime;
|
|
37
|
+
const analyze_impact_1 = require("../tools/analyze-impact");
|
|
38
|
+
const crypto = __importStar(require("crypto"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const provider_1 = require("./provider");
|
|
41
|
+
const context_extractor_1 = require("./context-extractor");
|
|
42
|
+
const analysisCache = new Map();
|
|
43
|
+
const MAX_CACHE_SIZE = 100;
|
|
44
|
+
function computeContentHash(content, diff) {
|
|
45
|
+
return crypto.createHash("md5").update((content || "") + "\n---\n" + diff).digest("hex");
|
|
46
|
+
}
|
|
47
|
+
function evictOldestCacheEntry() {
|
|
48
|
+
let oldestKey = null;
|
|
49
|
+
let oldestTime = Infinity;
|
|
50
|
+
for (const [key, entry] of analysisCache) {
|
|
51
|
+
if (entry.insertedAt < oldestTime) {
|
|
52
|
+
oldestTime = entry.insertedAt;
|
|
53
|
+
oldestKey = key;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (oldestKey)
|
|
57
|
+
analysisCache.delete(oldestKey);
|
|
58
|
+
}
|
|
59
|
+
// ── Rate limiter: max 10 AI calls per minute (sliding window) ──
|
|
60
|
+
const RATE_LIMIT_MAX = 10;
|
|
61
|
+
const RATE_LIMIT_WINDOW_MS = 60000;
|
|
62
|
+
const callTimestamps = [];
|
|
63
|
+
function isRateLimited() {
|
|
64
|
+
const now = Date.now();
|
|
65
|
+
// Remove timestamps outside the window
|
|
66
|
+
while (callTimestamps.length > 0 && callTimestamps[0] <= now - RATE_LIMIT_WINDOW_MS) {
|
|
67
|
+
callTimestamps.shift();
|
|
68
|
+
}
|
|
69
|
+
return callTimestamps.length >= RATE_LIMIT_MAX;
|
|
70
|
+
}
|
|
71
|
+
function recordCall() {
|
|
72
|
+
callTimestamps.push(Date.now());
|
|
73
|
+
}
|
|
74
|
+
function getSystemPrompt() {
|
|
75
|
+
return `You are a senior full-stack architect and code impact monitoring AI with 20 years of experience.
|
|
76
|
+
Role: Detect potential errors and cascading impacts before build when files are modified/added/deleted.
|
|
77
|
+
|
|
78
|
+
Analysis principles:
|
|
79
|
+
1. Broken imports/exports: Check if deleted/renamed classes/functions/variables are referenced in other files
|
|
80
|
+
2. Type mismatches: Verify parameter types and return type changes match call sites
|
|
81
|
+
3. State management cascade: Impact of Provider/Notifier changes on UI and business logic
|
|
82
|
+
4. Routing impact: Effect of route/parameter changes on navigation
|
|
83
|
+
5. Missing initialization: Whether newly added Providers are properly registered
|
|
84
|
+
|
|
85
|
+
Response format (must be JSON):
|
|
86
|
+
{
|
|
87
|
+
"riskLevel": "CRITICAL|HIGH|MEDIUM|LOW|SAFE",
|
|
88
|
+
"summary": "One-line summary",
|
|
89
|
+
"brokenImports": ["List of potentially broken imports"],
|
|
90
|
+
"sideEffects": ["List of expected side effects"],
|
|
91
|
+
"warnings": ["List of warnings"],
|
|
92
|
+
"suggestion": "Recommended action"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
CRITICAL: Build failure certain
|
|
96
|
+
HIGH: Runtime error possible
|
|
97
|
+
MEDIUM: Behavior change possible
|
|
98
|
+
LOW: Minor impact
|
|
99
|
+
SAFE: Safe change
|
|
100
|
+
|
|
101
|
+
Respond with JSON only. No explanatory text, just pure JSON.`;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Analyze a file change in real-time using the configured AI provider.
|
|
105
|
+
* Receives the diff + connected files context from memory cache.
|
|
106
|
+
*/
|
|
107
|
+
async function analyzeChangeRealtime(change, graph, getFileContent) {
|
|
108
|
+
const start = Date.now();
|
|
109
|
+
const relPath = change.relativePath;
|
|
110
|
+
const codeBlockLang = graph.languages[0] || "text";
|
|
111
|
+
// Get impacted files from graph
|
|
112
|
+
const absPath = path.normalize(path.join(graph.sourceDir, relPath));
|
|
113
|
+
let affectedNodes = [];
|
|
114
|
+
if (graph.files.has(absPath)) {
|
|
115
|
+
const impact = await (0, analyze_impact_1.analyzeImpact)(absPath, graph);
|
|
116
|
+
affectedNodes = [...impact.directDependents, ...impact.transitiveDependents];
|
|
117
|
+
}
|
|
118
|
+
// Build context: changed file + top 5 connected files' smart context
|
|
119
|
+
const connectedFiles = [];
|
|
120
|
+
const revDeps = graph.reverse.get(absPath) || [];
|
|
121
|
+
const fwdDeps = graph.forward.get(absPath) || [];
|
|
122
|
+
const connected = [...new Set([...revDeps, ...fwdDeps])].slice(0, 5);
|
|
123
|
+
for (const dep of connected) {
|
|
124
|
+
const depRel = path.relative(graph.sourceDir, dep).replace(/\\/g, "/");
|
|
125
|
+
const content = getFileContent(depRel);
|
|
126
|
+
if (content) {
|
|
127
|
+
const smartCtx = (0, context_extractor_1.buildSmartContext)(content, codeBlockLang);
|
|
128
|
+
connectedFiles.push(`### ${depRel}\n\`\`\`${codeBlockLang}\n${smartCtx}\n\`\`\``);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Build diff summary with signature changes
|
|
132
|
+
let diffSummary = "";
|
|
133
|
+
if (change.type === "deleted") {
|
|
134
|
+
diffSummary = `File deleted. Previous content:\n\`\`\`${codeBlockLang}\n${(change.oldContent || "").split("\n").slice(0, 40).join("\n")}\n\`\`\``;
|
|
135
|
+
}
|
|
136
|
+
else if (change.type === "added") {
|
|
137
|
+
const smartNew = (0, context_extractor_1.buildSmartContext)(change.newContent || "", codeBlockLang);
|
|
138
|
+
diffSummary = `New file added:\n\`\`\`${codeBlockLang}\n${smartNew}\n\`\`\``;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
// Modified — include signature diff
|
|
142
|
+
const diffLines = change.diff.slice(0, 30).map(d => {
|
|
143
|
+
if (d.type === "added")
|
|
144
|
+
return `+ L${d.line}: ${d.new}`;
|
|
145
|
+
if (d.type === "removed")
|
|
146
|
+
return `- L${d.line}: ${d.old}`;
|
|
147
|
+
return `~ L${d.line}: ${d.old} → ${d.new}`;
|
|
148
|
+
});
|
|
149
|
+
diffSummary = `Changed lines (top 30 of ${change.diff.length}):\n\`\`\`\n${diffLines.join("\n")}\n\`\`\``;
|
|
150
|
+
// Add structural signature changes
|
|
151
|
+
if (change.oldContent && change.newContent) {
|
|
152
|
+
const sigChanges = (0, context_extractor_1.diffSignatures)(change.oldContent, change.newContent, codeBlockLang);
|
|
153
|
+
if (sigChanges.length > 0) {
|
|
154
|
+
diffSummary += "\n\n### Structural changes (signature diff)";
|
|
155
|
+
for (const sc of sigChanges) {
|
|
156
|
+
if (sc.type === "added") {
|
|
157
|
+
diffSummary += `\n+ Added: ${sc.newSignature}`;
|
|
158
|
+
}
|
|
159
|
+
else if (sc.type === "removed") {
|
|
160
|
+
diffSummary += `\n- Removed: ${sc.oldSignature}`;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
diffSummary += `\n~ Changed: ${sc.oldSignature}\n → ${sc.newSignature}`;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (change.newContent) {
|
|
169
|
+
const smartNew = (0, context_extractor_1.buildSmartContext)(change.newContent, codeBlockLang);
|
|
170
|
+
diffSummary += `\n\nFull file after modification:\n\`\`\`${codeBlockLang}\n${smartNew}\n\`\`\``;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const userPrompt = `## File change detected: ${relPath}
|
|
174
|
+
Change type: ${change.type.toUpperCase()}
|
|
175
|
+
Project languages: ${graph.languages.join(", ") || "unknown"}
|
|
176
|
+
Affected files: ${affectedNodes.length}
|
|
177
|
+
|
|
178
|
+
${diffSummary}
|
|
179
|
+
|
|
180
|
+
${connectedFiles.length > 0 ? `## Connected files (${connectedFiles.length})\n${connectedFiles.join("\n\n")}` : "No connected files"}
|
|
181
|
+
|
|
182
|
+
Analyze the impact of this change on the project.`;
|
|
183
|
+
// ── Hash cache check: skip AI if content+diff unchanged ──
|
|
184
|
+
const diffStr = change.diff.map(d => `${d.type}:${d.line}:${d.old || ""}:${d.new || ""}`).join("|");
|
|
185
|
+
const contentHash = computeContentHash(change.newContent, diffStr);
|
|
186
|
+
const cached = analysisCache.get(relPath);
|
|
187
|
+
if (cached && cached.hash === contentHash) {
|
|
188
|
+
console.error(`[syke:ai] Cache hit for ${relPath} — skipping AI call`);
|
|
189
|
+
return { ...cached.result, timestamp: change.timestamp, analysisMs: 0 };
|
|
190
|
+
}
|
|
191
|
+
// ── Rate limit check ──
|
|
192
|
+
if (isRateLimited()) {
|
|
193
|
+
const analysisMs = Date.now() - start;
|
|
194
|
+
console.error(`[syke:ai] Rate limit reached (${RATE_LIMIT_MAX}/min) — skipping AI for ${relPath}`);
|
|
195
|
+
return {
|
|
196
|
+
file: relPath,
|
|
197
|
+
changeType: change.type,
|
|
198
|
+
timestamp: change.timestamp,
|
|
199
|
+
riskLevel: affectedNodes.length >= 10 ? "HIGH" : affectedNodes.length >= 5 ? "MEDIUM" : "LOW",
|
|
200
|
+
summary: `Rate limited — graph-based analysis: ${affectedNodes.length} files impacted`,
|
|
201
|
+
brokenImports: [],
|
|
202
|
+
sideEffects: [],
|
|
203
|
+
warnings: ["AI analysis skipped: rate limit (10 calls/min)"],
|
|
204
|
+
suggestion: "Wait a moment for AI analysis to resume",
|
|
205
|
+
affectedNodes,
|
|
206
|
+
analysisMs,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
try {
|
|
210
|
+
const provider = (0, provider_1.getAIProvider)();
|
|
211
|
+
if (!provider) {
|
|
212
|
+
throw new Error("No AI provider available (set GEMINI_KEY, OPENAI_KEY, or ANTHROPIC_KEY)");
|
|
213
|
+
}
|
|
214
|
+
recordCall();
|
|
215
|
+
const parsed = await provider.analyzeJSON(getSystemPrompt(), userPrompt);
|
|
216
|
+
const analysisMs = Date.now() - start;
|
|
217
|
+
const result = {
|
|
218
|
+
file: relPath,
|
|
219
|
+
changeType: change.type,
|
|
220
|
+
timestamp: change.timestamp,
|
|
221
|
+
riskLevel: parsed.riskLevel || "LOW",
|
|
222
|
+
summary: parsed.summary || "Analysis complete",
|
|
223
|
+
brokenImports: parsed.brokenImports || [],
|
|
224
|
+
sideEffects: parsed.sideEffects || [],
|
|
225
|
+
warnings: parsed.warnings || [],
|
|
226
|
+
suggestion: parsed.suggestion || "",
|
|
227
|
+
affectedNodes,
|
|
228
|
+
analysisMs,
|
|
229
|
+
};
|
|
230
|
+
// Store in cache
|
|
231
|
+
if (analysisCache.size >= MAX_CACHE_SIZE)
|
|
232
|
+
evictOldestCacheEntry();
|
|
233
|
+
analysisCache.set(relPath, { hash: contentHash, result, insertedAt: Date.now() });
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
const analysisMs = Date.now() - start;
|
|
238
|
+
console.error(`[syke:ai] Analysis error for ${relPath}: ${err.message}`);
|
|
239
|
+
return {
|
|
240
|
+
file: relPath,
|
|
241
|
+
changeType: change.type,
|
|
242
|
+
timestamp: change.timestamp,
|
|
243
|
+
riskLevel: affectedNodes.length >= 10 ? "HIGH" : affectedNodes.length >= 5 ? "MEDIUM" : "LOW",
|
|
244
|
+
summary: `AI analysis failed — graph-based analysis: ${affectedNodes.length} files impacted`,
|
|
245
|
+
brokenImports: [],
|
|
246
|
+
sideEffects: [],
|
|
247
|
+
warnings: [`AI analysis error: ${err.message}`],
|
|
248
|
+
suggestion: "Manual review required",
|
|
249
|
+
affectedNodes,
|
|
250
|
+
analysisMs,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
}
|
package/dist/config.js
CHANGED
|
@@ -1 +1,121 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.CONFIG_FILE_PATH = exports.CONFIG_DIR_PATH = void 0;
|
|
37
|
+
exports.getConfig = getConfig;
|
|
38
|
+
exports.getAllConfig = getAllConfig;
|
|
39
|
+
exports.setConfig = setConfig;
|
|
40
|
+
/**
|
|
41
|
+
* Central config reader for SYKE MCP Server.
|
|
42
|
+
*
|
|
43
|
+
* Priority: environment variables > ~/.syke/config.json
|
|
44
|
+
*
|
|
45
|
+
* IDE users (Cursor, Windsurf, etc.) set env vars in their MCP config.
|
|
46
|
+
* Terminal users (Claude Code CLI) edit ~/.syke/config.json directly.
|
|
47
|
+
*/
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
const os = __importStar(require("os"));
|
|
51
|
+
const CONFIG_DIR = path.join(os.homedir(), ".syke");
|
|
52
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
53
|
+
let cached = null;
|
|
54
|
+
/**
|
|
55
|
+
* Read ~/.syke/config.json (cached after first read)
|
|
56
|
+
*/
|
|
57
|
+
function readConfigFile() {
|
|
58
|
+
if (cached)
|
|
59
|
+
return cached;
|
|
60
|
+
try {
|
|
61
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
62
|
+
cached = JSON.parse(fs.readFileSync(CONFIG_FILE, "utf-8"));
|
|
63
|
+
return cached;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// ignore parse errors
|
|
68
|
+
}
|
|
69
|
+
cached = {};
|
|
70
|
+
return cached;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get a config value. Env var takes priority over config file.
|
|
74
|
+
*/
|
|
75
|
+
function getConfig(key, envVar) {
|
|
76
|
+
// 1. Environment variable
|
|
77
|
+
if (envVar && process.env[envVar]) {
|
|
78
|
+
return process.env[envVar];
|
|
79
|
+
}
|
|
80
|
+
// 2. Config file
|
|
81
|
+
const file = readConfigFile();
|
|
82
|
+
const val = file[key];
|
|
83
|
+
return val !== undefined && val !== null ? String(val) : undefined;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get all resolved config (for logging/debug)
|
|
87
|
+
*/
|
|
88
|
+
function getAllConfig() {
|
|
89
|
+
return {
|
|
90
|
+
licenseKey: getConfig("licenseKey", "SYKE_LICENSE_KEY"),
|
|
91
|
+
geminiKey: getConfig("geminiKey", "GEMINI_KEY"),
|
|
92
|
+
openaiKey: getConfig("openaiKey", "OPENAI_KEY"),
|
|
93
|
+
anthropicKey: getConfig("anthropicKey", "ANTHROPIC_KEY"),
|
|
94
|
+
aiProvider: getConfig("aiProvider", "SYKE_AI_PROVIDER"),
|
|
95
|
+
port: getConfig("port", "SYKE_WEB_PORT"),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Set a config value in ~/.syke/config.json
|
|
100
|
+
*/
|
|
101
|
+
function setConfig(key, value) {
|
|
102
|
+
const file = readConfigFile();
|
|
103
|
+
if (value === null) {
|
|
104
|
+
delete file[key];
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
file[key] = value;
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
111
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
112
|
+
}
|
|
113
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(file, null, 2));
|
|
114
|
+
cached = file;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// ignore write errors
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.CONFIG_DIR_PATH = CONFIG_DIR;
|
|
121
|
+
exports.CONFIG_FILE_PATH = CONFIG_FILE;
|