@vpxa/aikit 0.1.99 → 0.1.100
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 +29 -33
- package/package.json +1 -2
- package/packages/aikit-client/dist/index.d.ts +27 -27
- package/packages/aikit-client/dist/index.js +2 -2
- package/packages/analyzers/dist/index.js +2 -2
- package/packages/cli/dist/index.js +2 -2
- package/packages/cli/dist/init-DlY4IHCF.js +7 -0
- package/packages/cli/dist/{templates-DVcEiTlc.js → templates-Dz2d2veK.js} +9 -9
- package/packages/cli/dist/{user-Dj8KE0_0.js → user-DfEC00FY.js} +1 -1
- package/packages/core/dist/index.d.ts +8 -8
- package/packages/core/dist/index.js +1 -1
- package/packages/dashboard/dist/assets/{index-C6D-PCp0.js → index-CxrC6OtB.js} +3 -3
- package/packages/dashboard/dist/index.html +1 -1
- package/packages/enterprise-bridge/dist/index.d.ts +1 -1
- package/packages/enterprise-bridge/dist/index.js +1 -1
- package/packages/indexer/dist/index.d.ts +6 -6
- package/packages/server/dist/index.d.ts +1 -1
- package/packages/server/dist/index.js +1 -1
- package/packages/server/dist/server-DfCR_Bix.js +1282 -0
- package/packages/server/dist/{version-check-AMfxaZUw.js → version-check-Bj07vc5x.js} +1 -1
- package/packages/store/dist/index.d.ts +9 -22
- package/packages/store/dist/index.js +6 -6
- package/packages/tools/dist/index.d.ts +16 -15
- package/packages/tools/dist/index.js +6 -6
- package/scaffold/dist/adapters/intellij.mjs +3 -0
- package/scaffold/dist/adapters/zed.mjs +4 -0
- package/scaffold/dist/definitions/agents.mjs +1 -1
- package/scaffold/dist/definitions/bodies.mjs +16 -16
- package/scaffold/dist/definitions/flows.mjs +32 -32
- package/scaffold/dist/definitions/hooks.mjs +1 -1
- package/scaffold/dist/definitions/prompts.mjs +7 -7
- package/scaffold/dist/definitions/protocols.mjs +28 -24
- package/scaffold/dist/definitions/skills.mjs +67 -67
- package/scaffold/dist/definitions/tools.mjs +1 -1
- package/packages/cli/dist/init-CVtbu7zj.js +0 -7
- package/packages/server/dist/server-DZ1V42_x.js +0 -1282
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
html, body, #root { width: 100%; height: 100%; overflow: hidden; }
|
|
10
10
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0d1117; color: #c9d1d9; }
|
|
11
11
|
</style>
|
|
12
|
-
<script type="module" crossorigin src="/_dashboard/assets/index-
|
|
12
|
+
<script type="module" crossorigin src="/_dashboard/assets/index-CxrC6OtB.js"></script>
|
|
13
13
|
<link rel="stylesheet" crossorigin href="/_dashboard/assets/index-CHpVij2M.css">
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SearchResult } from "../../core/dist/index.js";
|
|
2
2
|
|
|
3
3
|
//#region packages/enterprise-bridge/src/types.d.ts
|
|
4
|
-
/** ER bridge configuration (subset of
|
|
4
|
+
/** ER bridge configuration (subset of AikitConfig.er) */
|
|
5
5
|
interface ERBridgeConfig {
|
|
6
6
|
enabled: boolean;
|
|
7
7
|
baseUrl: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as e,mkdirSync as t,readFileSync as n,writeFileSync as r}from"node:fs";import{join as i}from"node:path";import{createLogger as a}from"../../core/dist/index.js";var o=class e{cache=new Map;maxEntries;defaultTtl;constructor(e){this.maxEntries=e?.maxEntries??100,this.defaultTtl=e?.defaultTtl??216e5}static normalizeKey(e){return e.toLowerCase().trim().replace(/\s+/g,` `)}get(t){let n=e.normalizeKey(t),r=this.cache.get(n);if(r){if(Date.now()-r.cachedAt>r.ttl){this.cache.delete(n);return}return this.cache.delete(n),this.cache.set(n,r),r.results}}set(t,n,r){let i=e.normalizeKey(t);if(this.cache.size>=this.maxEntries&&!this.cache.has(i)){let e=this.cache.keys().next().value;e!==void 0&&this.cache.delete(e)}this.cache.set(i,{results:n,query:i,cachedAt:Date.now(),ttl:r??this.defaultTtl})}invalidate(t){let n=e.normalizeKey(t);return this.cache.delete(n)}clear(){this.cache.clear()}get size(){return this.cache.size}stats(){return{size:this.cache.size,maxEntries:this.maxEntries,defaultTtlMs:this.defaultTtl}}},s=class extends Error{constructor(e,t){super(e),this.statusCode=t,this.name=`ERTransientError`}},c=class e{baseUrl;apiKey;timeoutMs;circuitState=`closed`;consecutiveFailures=0;openUntil=0;halfOpenProbeInFlight=!1;static FAILURE_THRESHOLD=3;static RESET_TIMEOUT_MS=6e4;constructor(e){let t=new URL(e.baseUrl);if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`Unsupported protocol: ${t.protocol} — only http/https allowed`);let n=t.hostname===`localhost`||t.hostname===`127.0.0.1`||t.hostname===`::1`;if(t.protocol===`http:`&&!n)throw Error(`Non-TLS (http://) ER endpoints are only allowed for localhost. Use https:// to avoid leaking API keys.`);this.baseUrl=e.baseUrl.replace(/\/+$/,``),this.apiKey=e.apiKey,this.timeoutMs=e.timeoutMs}async search(e,t=5){let n=await this.fetch(`/api/v1/search`,{method:`POST`,body:JSON.stringify({query:e,maxResults:t,generateResponse:!1})});if(!n.ok)throw Error(`ER search failed: ${n.status} ${n.statusText}`);return((await n.json()).sources??[]).map(e=>{let t=typeof e.score==`number`?e.score:void 0,n=typeof e.confidence==`number`?e.confidence:void 0;return{content:e.content,sourcePath:e.metadata?.sourceUri??`unknown`,score:t??n??0,metadata:e.metadata}})}async push(e){let t=await this.fetch(`/mcp/tools`,{method:`POST`,body:JSON.stringify({name:`curated_remember`,arguments:{title:e.title,content:e.content,category:e.category??`conventions`,tags:[...e.tags??[],`pushed-from-kb`]}})});if(!t.ok)return{pushed:!1,status:`failed`,timestamp:new Date().toISOString(),error:`ER push failed: ${t.status} ${t.statusText}`};let n=await t.json();return{pushed:!0,status:`stored`,remotePath:typeof n.path==`string`?n.path:void 0,timestamp:new Date().toISOString()}}async pull(e,t=10){return this.search(e,t)}async health(){try{let e=await this.fetch(`/api/v1/health`,{method:`GET`});return{healthy:e.ok,status:e.status}}catch{return{healthy:!1}}}async listTools(){try{let e=await this.fetch(`/mcp/tools`,{method:`GET`});return e.ok?((await e.json()).tools??[]).map(e=>e.name):[]}catch{return[]}}async fetch(e,t){this.checkCircuit();let n;for(let r=0;r<=2;r++){let i=new AbortController,a=setTimeout(()=>i.abort(),this.timeoutMs);try{let n=await fetch(`${this.baseUrl}${e}`,{...t,headers:{"Content-Type":`application/json`,"X-Api-Key":this.apiKey,"User-Agent":`aikit-enterprise-bridge/1.0`,...t.headers},signal:i.signal});if(n.ok||n.status>=400&&n.status<500&&n.status!==429)return this.recordSuccess(),n;if(r<2){let e=this.parseRetryAfter(n)??this.backoffMs(r);await this.sleep(e);continue}return this.recordFailure(),n}catch(e){n=e,r<2&&await this.sleep(this.backoffMs(r))}finally{clearTimeout(a)}}throw this.recordFailure(),n??Error(`Fetch failed after retries`)}checkCircuit(){if(this.circuitState===`open`)if(Date.now()>=this.openUntil){if(this.halfOpenProbeInFlight)throw new s(`ER circuit breaker is half-open — probe in progress`);this.circuitState=`half-open`,this.halfOpenProbeInFlight=!0}else throw new s(`ER circuit breaker is open — skipping request`)}recordSuccess(){this.consecutiveFailures=0,this.circuitState=`closed`,this.halfOpenProbeInFlight=!1}recordFailure(){this.consecutiveFailures++,this.halfOpenProbeInFlight=!1,this.consecutiveFailures>=e.FAILURE_THRESHOLD&&(this.circuitState=`open`,this.openUntil=Date.now()+e.RESET_TIMEOUT_MS)}backoffMs(e){let t=500*3**e,n=t*.25*(Math.random()*2-1);return Math.round(t+n)}parseRetryAfter(e){let t=e.headers.get(`Retry-After`);if(!t)return;let n=Number(t);if(!Number.isNaN(n)&&n>=0)return Math.min(n*1e3,3e4)}sleep(e){return new Promise(t=>setTimeout(t,e))}},l=class{searchEvents=[];classificationEvents=[];pushEvents=[];startedAt;constructor(){this.startedAt=new Date().toISOString()}recordSearch(e,t,n){this.searchEvents.push({query:e.toLowerCase().trim(),erFallbackTriggered:t,erCacheHit:n,timestamp:Date.now()}),this.trimEvents()}recordClassification(e,t,n){this.classificationEvents.push({entryTitle:e,matchingRuleIds:t,pushRecommended:n,timestamp:Date.now()}),this.trimEvents()}recordPush(e,t,n){this.pushEvents.push({entryId:e,ruleId:n,success:t,timestamp:Date.now()}),this.trimEvents()}getMetrics(){let e=this.searchEvents.length,t=this.searchEvents.filter(e=>e.erFallbackTriggered).length,n=this.searchEvents.filter(e=>e.erCacheHit).length,r=new Map;for(let e of this.searchEvents)e.erFallbackTriggered&&r.set(e.query,(r.get(e.query)??0)+1);let i=[...r.entries()].sort((e,t)=>t[1]-e[1]).slice(0,20).map(([e,t])=>({query:e,count:t})),a=this.pushEvents.length,o=this.pushEvents.filter(e=>e.success).length,s=this.classificationEvents.length,c=this.classificationEvents.filter(e=>e.pushRecommended).length,l={},u={};for(let e of this.classificationEvents)for(let t of e.matchingRuleIds)l[t]=(l[t]??0)+1;for(let e of this.pushEvents)e.ruleId&&(u[e.ruleId]=(u[e.ruleId]??0)+1);let d=Object.entries(l).map(([e,t])=>{let n=u[e]??0;return{ruleId:e,matchCount:t,pushCount:n,conversionRate:t>0?n/t:0}}).filter(e=>e.matchCount>=3&&e.conversionRate<.3).sort((e,t)=>e.conversionRate-t.conversionRate);return{search:{totalSearches:e,erFallbackCount:t,erFallbackRate:e>0?t/e:0,erCacheHitCount:n,erCacheHitRate:t>0?n/t:0,topMissedQueries:i},push:{totalPushes:a,successCount:o,failCount:a-o,pushRate:s>0?a/s:0,classificationMatchRate:s>0?c/s:0,pushAcceptanceRate:c>0?a/c:0},rules:{matchCounts:l,pushCounts:u,lowConversionRules:d},period:{startedAt:this.startedAt,queriedAt:new Date().toISOString(),totalEvents:this.searchEvents.length+this.classificationEvents.length+this.pushEvents.length}}}reset(){this.searchEvents=[],this.classificationEvents=[],this.pushEvents=[]}trimEvents(){this.searchEvents.length>500&&(this.searchEvents=this.searchEvents.slice(-500)),this.classificationEvents.length>500&&(this.classificationEvents=this.classificationEvents.slice(-500)),this.pushEvents.length>500&&(this.pushEvents=this.pushEvents.slice(-500))}};const u=a(`bridge`),d=()=>new Date().toISOString(),f=[{id:`cross-repo-contract`,patterns:[`contract`,`interface`,`api`,`event schema`,`publishes`,`subscribes`],category:`contract`,pushWeight:.8,description:`Knowledge describing cross-service interfaces`,examples:[`Service X publishes OrderCreated event with fields...`],autoPush:!1,enabled:!0,createdAt:d(),updatedAt:d()},{id:`architecture-decision`,patterns:[`decided`,`chose`,`tradeoff`,`adr`,`because we need`],category:`decision`,pushWeight:.7,description:`Architecture decisions that affect the ecosystem`,examples:[`We decided to use event sourcing because...`],autoPush:!1,enabled:!0,createdAt:d(),updatedAt:d()},{id:`shared-pattern`,patterns:[`pattern`,`convention`,`standard`,`guideline`,`always use`],category:`pattern`,pushWeight:.6,description:`Patterns and conventions that maintain consistency across repos`,examples:[`Always use the Result type for error handling...`],autoPush:!1,enabled:!0,createdAt:d(),updatedAt:d()},{id:`company-term`,patterns:[`means`,`defined as`,`acronym`,`refers to`],category:`glossary`,pushWeight:.7,description:`Shared vocabulary and terminology definitions`,examples:[`DDD means Domain-Driven Design in our context...`],autoPush:!1,enabled:!0,createdAt:d(),updatedAt:d()},{id:`implementation-detail`,patterns:[`private`,`internal`,`helper`,`todo`,`hack`,`workaround`],category:`local-only`,pushWeight:0,description:`Local-only implementation details — never push`,examples:[`TODO: refactor this helper`,`Internal workaround for...`],autoPush:!1,enabled:!0,createdAt:d(),updatedAt:d()}];var p=class{rules=[];rulesPath;constructor(r){let a=i(r,`_policy`);if(this.rulesPath=i(a,`rules.json`),e(a)||t(a,{recursive:!0}),e(this.rulesPath))try{let e=n(this.rulesPath,`utf-8`),t=JSON.parse(e);if(!Array.isArray(t))throw Error(`rules.json must be an array`);for(let e of t)if(typeof e!=`object`||!e||typeof e.id!=`string`||!Array.isArray(e.patterns)||typeof e.category!=`string`||typeof e.pushWeight!=`number`)throw Error(`Invalid rule: ${JSON.stringify(e).slice(0,100)}`);this.rules=t}catch{u.warn(`Failed to parse policy rules, resetting to starter set`),this.rules=[...f],this.save()}else this.rules=[...f],this.save()}classify(e,t,n){let r=`${e} ${t} ${n.join(` `)}`.toLowerCase(),i=[];for(let e of this.rules){if(!e.enabled)continue;let t=e.patterns.filter(e=>r.includes(e.toLowerCase()));t.length>0&&i.push({ruleId:e.id,category:e.category,pushWeight:e.pushWeight,matchedPatterns:t})}let a=i.length>0?Math.max(...i.map(e=>e.pushWeight)):0;return{matchingRules:i,pushRecommended:a>=.5,maxPushWeight:a}}getRules(){return[...this.rules]}getRule(e){return this.rules.find(t=>t.id===e)}updateRule(e,t){let n=this.rules.find(t=>t.id===e);if(n)return Object.assign(n,t,{updatedAt:new Date().toISOString(),autoPush:!1}),this.save(),n}addRule(e){if(this.rules.find(t=>t.id===e.id))throw Error(`Rule with id '${e.id}' already exists`);let t=new Date().toISOString(),n={...e,autoPush:!1,createdAt:t,updatedAt:t};return this.rules.push(n),this.save(),n}deleteRule(e){let t=this.rules.findIndex(t=>t.id===e);return t===-1?!1:(this.rules.splice(t,1),this.save(),!0)}save(){r(this.rulesPath,JSON.stringify(this.rules,null,2),`utf-8`)}},m=class e{client;syncHistory=[];static MAX_HISTORY=100;constructor(e){this.client=e}async push(t,n){let r=await this.client.push(n);for(this.syncHistory.push({entryId:t,title:n.title,pushedAt:r.timestamp,status:r.status,remotePath:r.remotePath});this.syncHistory.length>e.MAX_HISTORY;)this.syncHistory.shift();return r}getHistory(){return[...this.syncHistory]}getStatus(){let e=this.syncHistory.filter(e=>e.status===`stored`).length;return{totalPushed:this.syncHistory.length,successCount:e,failCount:this.syncHistory.length-e,lastPush:this.syncHistory.at(-1)}}};function h(e){return{content:e.record.content,sourcePath:e.record.sourcePath,score:e.score,source:`local`,startLine:e.record.startLine,endLine:e.record.endLine,contentType:e.record.contentType,headingPath:e.record.headingPath,origin:e.record.origin,category:e.record.category,tags:e.record.tags}}function g(e){return{content:e.content,sourcePath:e.sourcePath,score:e.score,source:`er`,metadata:e.metadata}}function _(e){return`${e.slice(0,200).replace(/\s+/g,` `)}:${e.length}`}function v(e,t,n){let r=new Set,i=[];for(let t of e){let e=_(t.record.content);r.has(e)||(r.add(e),i.push(h(t)))}let a=[...t].sort((e,t)=>t.score-e.score);for(let e of a){let t=_(e.content);r.has(t)||(r.add(t),i.push(g(e)))}return i.slice(0,n)}export{o as ERCache,c as ERClient,s as ERTransientError,l as EvolutionCollector,p as PolicyStore,m as PushAdapter,v as mergeResults};
|
|
1
|
+
import{existsSync as e,mkdirSync as t,readFileSync as n,writeFileSync as r}from"node:fs";import{join as i}from"node:path";import{createLogger as a}from"../../core/dist/index.js";var o=class e{cache=new Map;maxEntries;defaultTtl;constructor(e){this.maxEntries=e?.maxEntries??100,this.defaultTtl=e?.defaultTtl??216e5}static normalizeKey(e){return e.toLowerCase().trim().replace(/\s+/g,` `)}get(t){let n=e.normalizeKey(t),r=this.cache.get(n);if(r){if(Date.now()-r.cachedAt>r.ttl){this.cache.delete(n);return}return this.cache.delete(n),this.cache.set(n,r),r.results}}set(t,n,r){let i=e.normalizeKey(t);if(this.cache.size>=this.maxEntries&&!this.cache.has(i)){let e=this.cache.keys().next().value;e!==void 0&&this.cache.delete(e)}this.cache.set(i,{results:n,query:i,cachedAt:Date.now(),ttl:r??this.defaultTtl})}invalidate(t){let n=e.normalizeKey(t);return this.cache.delete(n)}clear(){this.cache.clear()}get size(){return this.cache.size}stats(){return{size:this.cache.size,maxEntries:this.maxEntries,defaultTtlMs:this.defaultTtl}}},s=class extends Error{constructor(e,t){super(e),this.statusCode=t,this.name=`ERTransientError`}},c=class e{baseUrl;apiKey;timeoutMs;circuitState=`closed`;consecutiveFailures=0;openUntil=0;halfOpenProbeInFlight=!1;static FAILURE_THRESHOLD=3;static RESET_TIMEOUT_MS=6e4;constructor(e){let t=new URL(e.baseUrl);if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`Unsupported protocol: ${t.protocol} — only http/https allowed`);let n=t.hostname===`localhost`||t.hostname===`127.0.0.1`||t.hostname===`::1`;if(t.protocol===`http:`&&!n)throw Error(`Non-TLS (http://) ER endpoints are only allowed for localhost. Use https:// to avoid leaking API keys.`);this.baseUrl=e.baseUrl.replace(/\/+$/,``),this.apiKey=e.apiKey,this.timeoutMs=e.timeoutMs}async search(e,t=5){let n=await this.fetch(`/api/v1/search`,{method:`POST`,body:JSON.stringify({query:e,maxResults:t,generateResponse:!1})});if(!n.ok)throw Error(`ER search failed: ${n.status} ${n.statusText}`);return((await n.json()).sources??[]).map(e=>{let t=typeof e.score==`number`?e.score:void 0,n=typeof e.confidence==`number`?e.confidence:void 0;return{content:e.content,sourcePath:e.metadata?.sourceUri??`unknown`,score:t??n??0,metadata:e.metadata}})}async push(e){let t=await this.fetch(`/mcp/tools`,{method:`POST`,body:JSON.stringify({name:`curated_remember`,arguments:{title:e.title,content:e.content,category:e.category??`conventions`,tags:[...e.tags??[],`pushed-from-aikit`]}})});if(!t.ok)return{pushed:!1,status:`failed`,timestamp:new Date().toISOString(),error:`ER push failed: ${t.status} ${t.statusText}`};let n=await t.json();return{pushed:!0,status:`stored`,remotePath:typeof n.path==`string`?n.path:void 0,timestamp:new Date().toISOString()}}async pull(e,t=10){return this.search(e,t)}async health(){try{let e=await this.fetch(`/api/v1/health`,{method:`GET`});return{healthy:e.ok,status:e.status}}catch{return{healthy:!1}}}async listTools(){try{let e=await this.fetch(`/mcp/tools`,{method:`GET`});return e.ok?((await e.json()).tools??[]).map(e=>e.name):[]}catch{return[]}}async fetch(e,t){this.checkCircuit();let n;for(let r=0;r<=2;r++){let i=new AbortController,a=setTimeout(()=>i.abort(),this.timeoutMs);try{let n=await fetch(`${this.baseUrl}${e}`,{...t,headers:{"Content-Type":`application/json`,"X-Api-Key":this.apiKey,"User-Agent":`aikit-enterprise-bridge/1.0`,...t.headers},signal:i.signal});if(n.ok||n.status>=400&&n.status<500&&n.status!==429)return this.recordSuccess(),n;if(r<2){let e=this.parseRetryAfter(n)??this.backoffMs(r);await this.sleep(e);continue}return this.recordFailure(),n}catch(e){n=e,r<2&&await this.sleep(this.backoffMs(r))}finally{clearTimeout(a)}}throw this.recordFailure(),n??Error(`Fetch failed after retries`)}checkCircuit(){if(this.circuitState===`open`)if(Date.now()>=this.openUntil){if(this.halfOpenProbeInFlight)throw new s(`ER circuit breaker is half-open — probe in progress`);this.circuitState=`half-open`,this.halfOpenProbeInFlight=!0}else throw new s(`ER circuit breaker is open — skipping request`)}recordSuccess(){this.consecutiveFailures=0,this.circuitState=`closed`,this.halfOpenProbeInFlight=!1}recordFailure(){this.consecutiveFailures++,this.halfOpenProbeInFlight=!1,this.consecutiveFailures>=e.FAILURE_THRESHOLD&&(this.circuitState=`open`,this.openUntil=Date.now()+e.RESET_TIMEOUT_MS)}backoffMs(e){let t=500*3**e,n=t*.25*(Math.random()*2-1);return Math.round(t+n)}parseRetryAfter(e){let t=e.headers.get(`Retry-After`);if(!t)return;let n=Number(t);if(!Number.isNaN(n)&&n>=0)return Math.min(n*1e3,3e4)}sleep(e){return new Promise(t=>setTimeout(t,e))}},l=class{searchEvents=[];classificationEvents=[];pushEvents=[];startedAt;constructor(){this.startedAt=new Date().toISOString()}recordSearch(e,t,n){this.searchEvents.push({query:e.toLowerCase().trim(),erFallbackTriggered:t,erCacheHit:n,timestamp:Date.now()}),this.trimEvents()}recordClassification(e,t,n){this.classificationEvents.push({entryTitle:e,matchingRuleIds:t,pushRecommended:n,timestamp:Date.now()}),this.trimEvents()}recordPush(e,t,n){this.pushEvents.push({entryId:e,ruleId:n,success:t,timestamp:Date.now()}),this.trimEvents()}getMetrics(){let e=this.searchEvents.length,t=this.searchEvents.filter(e=>e.erFallbackTriggered).length,n=this.searchEvents.filter(e=>e.erCacheHit).length,r=new Map;for(let e of this.searchEvents)e.erFallbackTriggered&&r.set(e.query,(r.get(e.query)??0)+1);let i=[...r.entries()].sort((e,t)=>t[1]-e[1]).slice(0,20).map(([e,t])=>({query:e,count:t})),a=this.pushEvents.length,o=this.pushEvents.filter(e=>e.success).length,s=this.classificationEvents.length,c=this.classificationEvents.filter(e=>e.pushRecommended).length,l={},u={};for(let e of this.classificationEvents)for(let t of e.matchingRuleIds)l[t]=(l[t]??0)+1;for(let e of this.pushEvents)e.ruleId&&(u[e.ruleId]=(u[e.ruleId]??0)+1);let d=Object.entries(l).map(([e,t])=>{let n=u[e]??0;return{ruleId:e,matchCount:t,pushCount:n,conversionRate:t>0?n/t:0}}).filter(e=>e.matchCount>=3&&e.conversionRate<.3).sort((e,t)=>e.conversionRate-t.conversionRate);return{search:{totalSearches:e,erFallbackCount:t,erFallbackRate:e>0?t/e:0,erCacheHitCount:n,erCacheHitRate:t>0?n/t:0,topMissedQueries:i},push:{totalPushes:a,successCount:o,failCount:a-o,pushRate:s>0?a/s:0,classificationMatchRate:s>0?c/s:0,pushAcceptanceRate:c>0?a/c:0},rules:{matchCounts:l,pushCounts:u,lowConversionRules:d},period:{startedAt:this.startedAt,queriedAt:new Date().toISOString(),totalEvents:this.searchEvents.length+this.classificationEvents.length+this.pushEvents.length}}}reset(){this.searchEvents=[],this.classificationEvents=[],this.pushEvents=[]}trimEvents(){this.searchEvents.length>500&&(this.searchEvents=this.searchEvents.slice(-500)),this.classificationEvents.length>500&&(this.classificationEvents=this.classificationEvents.slice(-500)),this.pushEvents.length>500&&(this.pushEvents=this.pushEvents.slice(-500))}};const u=a(`bridge`),d=()=>new Date().toISOString(),f=[{id:`cross-repo-contract`,patterns:[`contract`,`interface`,`api`,`event schema`,`publishes`,`subscribes`],category:`contract`,pushWeight:.8,description:`Knowledge describing cross-service interfaces`,examples:[`Service X publishes OrderCreated event with fields...`],autoPush:!1,enabled:!0,createdAt:d(),updatedAt:d()},{id:`architecture-decision`,patterns:[`decided`,`chose`,`tradeoff`,`adr`,`because we need`],category:`decision`,pushWeight:.7,description:`Architecture decisions that affect the ecosystem`,examples:[`We decided to use event sourcing because...`],autoPush:!1,enabled:!0,createdAt:d(),updatedAt:d()},{id:`shared-pattern`,patterns:[`pattern`,`convention`,`standard`,`guideline`,`always use`],category:`pattern`,pushWeight:.6,description:`Patterns and conventions that maintain consistency across repos`,examples:[`Always use the Result type for error handling...`],autoPush:!1,enabled:!0,createdAt:d(),updatedAt:d()},{id:`company-term`,patterns:[`means`,`defined as`,`acronym`,`refers to`],category:`glossary`,pushWeight:.7,description:`Shared vocabulary and terminology definitions`,examples:[`DDD means Domain-Driven Design in our context...`],autoPush:!1,enabled:!0,createdAt:d(),updatedAt:d()},{id:`implementation-detail`,patterns:[`private`,`internal`,`helper`,`todo`,`hack`,`workaround`],category:`local-only`,pushWeight:0,description:`Local-only implementation details — never push`,examples:[`TODO: refactor this helper`,`Internal workaround for...`],autoPush:!1,enabled:!0,createdAt:d(),updatedAt:d()}];var p=class{rules=[];rulesPath;constructor(r){let a=i(r,`_policy`);if(this.rulesPath=i(a,`rules.json`),e(a)||t(a,{recursive:!0}),e(this.rulesPath))try{let e=n(this.rulesPath,`utf-8`),t=JSON.parse(e);if(!Array.isArray(t))throw Error(`rules.json must be an array`);for(let e of t)if(typeof e!=`object`||!e||typeof e.id!=`string`||!Array.isArray(e.patterns)||typeof e.category!=`string`||typeof e.pushWeight!=`number`)throw Error(`Invalid rule: ${JSON.stringify(e).slice(0,100)}`);this.rules=t}catch{u.warn(`Failed to parse policy rules, resetting to starter set`),this.rules=[...f],this.save()}else this.rules=[...f],this.save()}classify(e,t,n){let r=`${e} ${t} ${n.join(` `)}`.toLowerCase(),i=[];for(let e of this.rules){if(!e.enabled)continue;let t=e.patterns.filter(e=>r.includes(e.toLowerCase()));t.length>0&&i.push({ruleId:e.id,category:e.category,pushWeight:e.pushWeight,matchedPatterns:t})}let a=i.length>0?Math.max(...i.map(e=>e.pushWeight)):0;return{matchingRules:i,pushRecommended:a>=.5,maxPushWeight:a}}getRules(){return[...this.rules]}getRule(e){return this.rules.find(t=>t.id===e)}updateRule(e,t){let n=this.rules.find(t=>t.id===e);if(n)return Object.assign(n,t,{updatedAt:new Date().toISOString(),autoPush:!1}),this.save(),n}addRule(e){if(this.rules.find(t=>t.id===e.id))throw Error(`Rule with id '${e.id}' already exists`);let t=new Date().toISOString(),n={...e,autoPush:!1,createdAt:t,updatedAt:t};return this.rules.push(n),this.save(),n}deleteRule(e){let t=this.rules.findIndex(t=>t.id===e);return t===-1?!1:(this.rules.splice(t,1),this.save(),!0)}save(){r(this.rulesPath,JSON.stringify(this.rules,null,2),`utf-8`)}},m=class e{client;syncHistory=[];static MAX_HISTORY=100;constructor(e){this.client=e}async push(t,n){let r=await this.client.push(n);for(this.syncHistory.push({entryId:t,title:n.title,pushedAt:r.timestamp,status:r.status,remotePath:r.remotePath});this.syncHistory.length>e.MAX_HISTORY;)this.syncHistory.shift();return r}getHistory(){return[...this.syncHistory]}getStatus(){let e=this.syncHistory.filter(e=>e.status===`stored`).length;return{totalPushed:this.syncHistory.length,successCount:e,failCount:this.syncHistory.length-e,lastPush:this.syncHistory.at(-1)}}};function h(e){return{content:e.record.content,sourcePath:e.record.sourcePath,score:e.score,source:`local`,startLine:e.record.startLine,endLine:e.record.endLine,contentType:e.record.contentType,headingPath:e.record.headingPath,origin:e.record.origin,category:e.record.category,tags:e.record.tags}}function g(e){return{content:e.content,sourcePath:e.sourcePath,score:e.score,source:`er`,metadata:e.metadata}}function _(e){return`${e.slice(0,200).replace(/\s+/g,` `)}:${e.length}`}function v(e,t,n){let r=new Set,i=[];for(let t of e){let e=_(t.record.content);r.has(e)||(r.add(e),i.push(h(t)))}let a=[...t].sort((e,t)=>t.score-e.score);for(let e of a){let t=_(e.content);r.has(t)||(r.add(t),i.push(g(e)))}return i.slice(0,n)}export{o as ERCache,c as ERClient,s as ERTransientError,l as EvolutionCollector,p as PolicyStore,m as PushAdapter,v as mergeResults};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AikitConfig, IndexStats } from "../../core/dist/index.js";
|
|
2
2
|
import { GraphEdge, GraphNode, IGraphStore, IKnowledgeStore } from "../../store/dist/index.js";
|
|
3
3
|
import { IEmbedder } from "../../embeddings/dist/index.js";
|
|
4
4
|
|
|
@@ -121,17 +121,17 @@ declare class IncrementalIndexer {
|
|
|
121
121
|
* Sources are crawled in parallel, and file processing runs concurrently
|
|
122
122
|
* up to `config.indexing.concurrency` (default: 50% of CPU cores, minimum 2, maximum 4).
|
|
123
123
|
*/
|
|
124
|
-
index(config:
|
|
124
|
+
index(config: AikitConfig, onProgress?: ProgressCallback): Promise<IndexResult>;
|
|
125
125
|
/**
|
|
126
126
|
* Crawl sources and return file paths whose content has changed since the last index.
|
|
127
127
|
* This performs a read-only scan and does not modify the store.
|
|
128
128
|
*/
|
|
129
|
-
getChangedFiles(config:
|
|
129
|
+
getChangedFiles(config: AikitConfig): Promise<string[]>;
|
|
130
130
|
/**
|
|
131
131
|
* Index only the specified file paths.
|
|
132
132
|
* Files that have not changed are skipped.
|
|
133
133
|
*/
|
|
134
|
-
indexFiles(config:
|
|
134
|
+
indexFiles(config: AikitConfig, paths: string[], onProgress?: ProgressCallback): Promise<IndexResult>;
|
|
135
135
|
private doIndex;
|
|
136
136
|
private doIndexFiles;
|
|
137
137
|
private crawlSources;
|
|
@@ -143,7 +143,7 @@ declare class IncrementalIndexer {
|
|
|
143
143
|
/**
|
|
144
144
|
* Force re-index all files (ignoring hashes).
|
|
145
145
|
*/
|
|
146
|
-
reindexAll(config:
|
|
146
|
+
reindexAll(config: AikitConfig, onProgress?: ProgressCallback): Promise<IndexResult>;
|
|
147
147
|
private doReindex;
|
|
148
148
|
/**
|
|
149
149
|
* Get current index statistics.
|
|
@@ -167,7 +167,7 @@ declare class SmartIndexScheduler {
|
|
|
167
167
|
private changedFiles;
|
|
168
168
|
private lastRefreshTime;
|
|
169
169
|
private refreshing;
|
|
170
|
-
constructor(indexer: IncrementalIndexer, config:
|
|
170
|
+
constructor(indexer: IncrementalIndexer, config: AikitConfig, store?: {
|
|
171
171
|
createFtsIndex: () => Promise<void>;
|
|
172
172
|
} | undefined);
|
|
173
173
|
/** Start the trickle indexing loop. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./curated-manager-CXSPygmJ.js";import{readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{fileURLToPath as i,pathToFileURL as a}from"node:url";import{parseArgs as o}from"node:util";import{createLogger as s,serializeError as c}from"../../core/dist/index.js";const l=n(i(import.meta.url)),u=(()=>{try{let e=r(l,`..`,`..`,`..`,`package.json`);return JSON.parse(t(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}})(),d=s(`server`);function f(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}const{values:p}=(()=>{let e=process.argv[1];if(!e)return!1;try{return import.meta.url===a(e).href}catch{return!1}})()?o({allowPositionals:!0,options:{transport:{type:`string`,default:f()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}):{values:{transport:f(),port:process.env.AIKIT_PORT??`3210`}};async function m(){if(process.on(`unhandledRejection`,e=>{d.error(`Unhandled rejection`,c(e))}),d.info(`Starting MCP AI Kit server`,{version:u}),p.transport===`http`){let[{default:e},{loadConfig:t,resolveIndexMode:n},{registerDashboardRoutes:r,resolveDashboardDir:i},{registerSettingsRoutes:a,resolveSettingsDir:o},{createSettingsRouter:s}]=await Promise.all([import(`express`),import(`./config-C5IU9Lau.js`),import(`./dashboard-static-BfIe0Si1.js`),import(`./settings-static-BosGZSPf.js`),import(`./routes-0OCkdgRe.js`)]),l=t();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path});let u=e();u.use(e.json());let f=Number(p.port);u.use((e,t,n)=>{if(t.setHeader(`Access-Control-Allow-Origin`,process.env.AIKIT_CORS_ORIGIN??`http://localhost:${f}`),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization`),e.method===`OPTIONS`){t.status(204).end();return}n()}),r(u,i(),d);let m=new Date().toISOString();u.use(`/settings/api`,s({log:d,mcpInfo:()=>({transport:`http`,port:f,pid:process.pid,startedAt:m})})),a(u,o(),d),u.get(`/health`,(e,t)=>{t.json({status:`ok`})});let h=!1,g=null,_=null,v=null,y=Promise.resolve();u.post(`/mcp`,async(e,t)=>{if(!h||!_||!v){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let n=y,r;y=new Promise(e=>{r=e}),await n;try{let n=new v({sessionIdGenerator:void 0});await _.connect(n),await n.handleRequest(e,t,e.body),n.close()}catch(e){if(d.error(`MCP handler error`,c(e)),!t.headersSent){let n=e instanceof Error?e.message:String(e),r=n.includes(`Not Acceptable`);t.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?n:`Internal server error`},id:null})}}finally{r()}}),u.get(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))}),u.delete(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))});let b=u.listen(f,`127.0.0.1`,()=>{d.info(`MCP server listening`,{url:`http://127.0.0.1:${f}/mcp`,port:f}),setTimeout(async()=>{try{let[{createLazyServer:e,ALL_TOOL_NAMES:t},{StreamableHTTPServerTransport:r},{checkForUpdates:i,autoUpgradeScaffold:a}]=await Promise.all([import(`./server-
|
|
1
|
+
import{t as e}from"./curated-manager-CXSPygmJ.js";import{readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{fileURLToPath as i,pathToFileURL as a}from"node:url";import{parseArgs as o}from"node:util";import{createLogger as s,serializeError as c}from"../../core/dist/index.js";const l=n(i(import.meta.url)),u=(()=>{try{let e=r(l,`..`,`..`,`..`,`package.json`);return JSON.parse(t(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}})(),d=s(`server`);function f(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}const{values:p}=(()=>{let e=process.argv[1];if(!e)return!1;try{return import.meta.url===a(e).href}catch{return!1}})()?o({allowPositionals:!0,options:{transport:{type:`string`,default:f()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}):{values:{transport:f(),port:process.env.AIKIT_PORT??`3210`}};async function m(){if(process.on(`unhandledRejection`,e=>{d.error(`Unhandled rejection`,c(e))}),d.info(`Starting MCP AI Kit server`,{version:u}),p.transport===`http`){let[{default:e},{loadConfig:t,resolveIndexMode:n},{registerDashboardRoutes:r,resolveDashboardDir:i},{registerSettingsRoutes:a,resolveSettingsDir:o},{createSettingsRouter:s}]=await Promise.all([import(`express`),import(`./config-C5IU9Lau.js`),import(`./dashboard-static-BfIe0Si1.js`),import(`./settings-static-BosGZSPf.js`),import(`./routes-0OCkdgRe.js`)]),l=t();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path});let u=e();u.use(e.json());let f=Number(p.port);u.use((e,t,n)=>{if(t.setHeader(`Access-Control-Allow-Origin`,process.env.AIKIT_CORS_ORIGIN??`http://localhost:${f}`),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization`),e.method===`OPTIONS`){t.status(204).end();return}n()}),r(u,i(),d);let m=new Date().toISOString();u.use(`/settings/api`,s({log:d,mcpInfo:()=>({transport:`http`,port:f,pid:process.pid,startedAt:m})})),a(u,o(),d),u.get(`/health`,(e,t)=>{t.json({status:`ok`})});let h=!1,g=null,_=null,v=null,y=Promise.resolve();u.post(`/mcp`,async(e,t)=>{if(!h||!_||!v){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let n=y,r;y=new Promise(e=>{r=e}),await n;try{let n=new v({sessionIdGenerator:void 0});await _.connect(n),await n.handleRequest(e,t,e.body),n.close()}catch(e){if(d.error(`MCP handler error`,c(e)),!t.headersSent){let n=e instanceof Error?e.message:String(e),r=n.includes(`Not Acceptable`);t.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?n:`Internal server error`},id:null})}}finally{r()}}),u.get(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))}),u.delete(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))});let b=u.listen(f,`127.0.0.1`,()=>{d.info(`MCP server listening`,{url:`http://127.0.0.1:${f}/mcp`,port:f}),setTimeout(async()=>{try{let[{createLazyServer:e,ALL_TOOL_NAMES:t},{StreamableHTTPServerTransport:r},{checkForUpdates:i,autoUpgradeScaffold:a}]=await Promise.all([import(`./server-DfCR_Bix.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-Bj07vc5x.js`)]);i(),a();let o=n(l),s=e(l,o);_=s.server,v=r,h=!0,d.info(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:t.length,resourceCount:2}),s.startInit(),o===`auto`?s.ready.then(async()=>{try{let e=l.sources.map(e=>e.path).join(`, `);d.info(`Running initial index`,{sourcePaths:e}),await s.runInitialIndex(),d.info(`Initial index complete`)}catch(e){d.error(`Initial index failed; will retry on aikit_reindex`,c(e))}}).catch(e=>d.error(`AI Kit init or indexing failed`,c(e))):o===`smart`?s.ready.then(async()=>{try{if(!s.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`);g=new e(s.aikit.indexer,l,s.aikit.store),g.start(),s.setSmartScheduler(g),d.info(`Smart index scheduler started (HTTP mode)`)}catch(e){d.error(`Failed to start smart index scheduler`,c(e))}}).catch(e=>d.error(`AI Kit initialization failed`,c(e))):(s.ready.catch(e=>d.error(`AI Kit initialization failed`,c(e))),d.info(`Initial full indexing skipped in HTTP mode`,{indexMode:o}))}catch(e){d.error(`Failed to load server modules`,c(e))}},100)}),x=async e=>{d.info(`Shutdown signal received`,{signal:e}),g?.stop(),b.close(),_&&await _.close(),process.exit(0)};process.on(`SIGINT`,()=>x(`SIGINT`)),process.on(`SIGTERM`,()=>x(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:n},{createLazyServer:r},{checkForUpdates:a,autoUpgradeScaffold:o},{RootsListChangedNotificationSchema:s}]=await Promise.all([import(`./config-C5IU9Lau.js`),import(`./server-DfCR_Bix.js`),import(`./version-check-Bj07vc5x.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),a(),o();let u=n(l),f=r(l,u),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),d.info(`MCP server started`,{transport:`stdio`});let y=e=>{if(e.length===0)return!1;let n=e[0].uri,r=n.startsWith(`file://`)?i(n):n;return d.info(`MCP roots resolved`,{rootUri:n,rootPath:r,rootCount:e.length}),t(l,r),l.allRoots=e.map(e=>{let t=e.uri;return t.startsWith(`file://`)?i(t):t}),!0},b=!1;try{b=y((await p.server.listRoots()).roots),b||d.info(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){d.warn(`MCP roots/list not supported by client; using cwd fallback`,{cwd:process.cwd(),...c(e)}),b=!0}b||=await new Promise(e=>{let t=setTimeout(()=>{d.warn(`Timed out waiting for MCP roots/list_changed; using cwd fallback`,{cwd:process.cwd()}),e(!1)},5e3);p.server.setNotificationHandler(s,async()=>{clearTimeout(t);try{e(y((await p.server.listRoots()).roots))}catch(t){d.warn(`roots/list retry failed after notification`,c(t)),e(!1)}})}),m();let x=null,S=()=>{x&&clearTimeout(x),x=setTimeout(()=>{d.info(`Auto-shutdown: no activity for 30 minutes — exiting`),process.exit(0)},18e5),x.unref&&x.unref()};S(),process.stdin.on(`data`,()=>S()),h.catch(e=>{d.error(`Initialization failed — server will continue with limited tools`,c(e))}),u===`auto`?g().catch(e=>d.error(`Initial index failed`,c(e))):u===`smart`?h.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,l,f.aikit.store);t.start(),f.setSmartScheduler(t),d.info(`Smart index scheduler started (stdio mode)`)}catch(e){d.error(`Failed to start smart index scheduler`,c(e))}}).catch(e=>d.error(`AI Kit init failed for smart scheduler`,c(e))):d.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:u})}}m().catch(e=>{d.error(`Fatal error`,c(e)),process.exit(1)});export{e as CuratedKnowledgeManager};
|