@ai-devkit/memory 0.11.0 → 0.12.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.
Files changed (50) hide show
  1. package/dist/api.d.ts +4 -4
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js +17 -46
  4. package/dist/api.js.map +1 -1
  5. package/dist/database/connection.d.ts.map +1 -1
  6. package/dist/database/connection.js +15 -45
  7. package/dist/database/connection.js.map +1 -1
  8. package/dist/database/index.d.ts +3 -3
  9. package/dist/database/index.d.ts.map +1 -1
  10. package/dist/database/index.js +2 -35
  11. package/dist/database/index.js.map +1 -1
  12. package/dist/database/schema.d.ts +1 -1
  13. package/dist/database/schema.d.ts.map +1 -1
  14. package/dist/database/schema.js +12 -34
  15. package/dist/database/schema.js.map +1 -1
  16. package/dist/handlers/search.d.ts +1 -1
  17. package/dist/handlers/search.d.ts.map +1 -1
  18. package/dist/handlers/search.js +12 -22
  19. package/dist/handlers/search.js.map +1 -1
  20. package/dist/handlers/store.d.ts +1 -1
  21. package/dist/handlers/store.d.ts.map +1 -1
  22. package/dist/handlers/store.js +17 -27
  23. package/dist/handlers/store.js.map +1 -1
  24. package/dist/handlers/update.d.ts +1 -1
  25. package/dist/handlers/update.d.ts.map +1 -1
  26. package/dist/handlers/update.js +16 -26
  27. package/dist/handlers/update.js.map +1 -1
  28. package/dist/index.d.ts +1 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +5 -21
  31. package/dist/index.js.map +1 -1
  32. package/dist/server.js +18 -39
  33. package/dist/server.js.map +1 -1
  34. package/dist/services/normalizer.js +17 -34
  35. package/dist/services/normalizer.js.map +1 -1
  36. package/dist/services/ranker.d.ts +1 -1
  37. package/dist/services/ranker.d.ts.map +1 -1
  38. package/dist/services/ranker.js +5 -11
  39. package/dist/services/ranker.js.map +1 -1
  40. package/dist/services/search.js +15 -24
  41. package/dist/services/search.js.map +1 -1
  42. package/dist/services/validator.d.ts +1 -1
  43. package/dist/services/validator.d.ts.map +1 -1
  44. package/dist/services/validator.js +9 -39
  45. package/dist/services/validator.js.map +1 -1
  46. package/dist/types/index.js +1 -4
  47. package/dist/types/index.js.map +1 -1
  48. package/dist/utils/errors.js +10 -37
  49. package/dist/utils/errors.js.map +1 -1
  50. package/package.json +11 -10
@@ -1,27 +1,17 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "storeKnowledge", {
6
- enumerable: true,
7
- get: function() {
8
- return storeKnowledge;
9
- }
10
- });
11
- const _uuid = require("uuid");
12
- const _database = require("../database");
13
- const _validator = require("../services/validator");
14
- const _normalizer = require("../services/normalizer");
15
- const _errors = require("../utils/errors");
16
- function storeKnowledge(input) {
17
- (0, _validator.validateStoreInput)(input);
18
- const db = (0, _database.getDatabase)();
1
+ import { v4 as uuidv4 } from 'uuid';
2
+ import { getDatabase } from '../database/index.js';
3
+ import { validateStoreInput } from '../services/validator.js';
4
+ import { normalizeTitle, normalizeScope, normalizeTags, hashContent } from '../services/normalizer.js';
5
+ import { DuplicateError, StorageError } from '../utils/errors.js';
6
+ export function storeKnowledge(input) {
7
+ validateStoreInput(input);
8
+ const db = getDatabase();
19
9
  const now = new Date().toISOString();
20
- const normalizedTitle = (0, _normalizer.normalizeTitle)(input.title);
21
- const scope = (0, _normalizer.normalizeScope)(input.scope);
22
- const tags = (0, _normalizer.normalizeTags)(input.tags ?? []);
23
- const contentHash = (0, _normalizer.hashContent)(input.content);
24
- const id = (0, _uuid.v4)();
10
+ const normalizedTitle = normalizeTitle(input.title);
11
+ const scope = normalizeScope(input.scope);
12
+ const tags = normalizeTags(input.tags ?? []);
13
+ const contentHash = hashContent(input.content);
14
+ const id = uuidv4();
25
15
  try {
26
16
  return db.transaction(()=>{
27
17
  const existingByTitle = db.queryOne('SELECT id FROM knowledge WHERE normalized_title = ? AND scope = ?', [
@@ -29,14 +19,14 @@ function storeKnowledge(input) {
29
19
  scope
30
20
  ]);
31
21
  if (existingByTitle) {
32
- throw new _errors.DuplicateError('Knowledge with similar title already exists in this scope', existingByTitle.id, 'title');
22
+ throw new DuplicateError('Knowledge with similar title already exists in this scope', existingByTitle.id, 'title');
33
23
  }
34
24
  const existingByHash = db.queryOne('SELECT id FROM knowledge WHERE content_hash = ? AND scope = ?', [
35
25
  contentHash,
36
26
  scope
37
27
  ]);
38
28
  if (existingByHash) {
39
- throw new _errors.DuplicateError('Knowledge with identical content already exists in this scope', existingByHash.id, 'content');
29
+ throw new DuplicateError('Knowledge with identical content already exists in this scope', existingByHash.id, 'content');
40
30
  }
41
31
  db.execute(`INSERT INTO knowledge (
42
32
  id, title, content, tags, scope,
@@ -59,10 +49,10 @@ function storeKnowledge(input) {
59
49
  };
60
50
  });
61
51
  } catch (error) {
62
- if (error instanceof _errors.DuplicateError) {
52
+ if (error instanceof DuplicateError) {
63
53
  throw error;
64
54
  }
65
- throw new _errors.StorageError('Failed to store knowledge', {
55
+ throw new StorageError('Failed to store knowledge', {
66
56
  originalError: error instanceof Error ? error.message : String(error)
67
57
  });
68
58
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/handlers/store.ts"],"sourcesContent":["import { v4 as uuidv4 } from 'uuid';\nimport { getDatabase } from '../database';\nimport { validateStoreInput } from '../services/validator';\nimport { normalizeTitle, normalizeScope, normalizeTags, hashContent } from '../services/normalizer';\nimport { DuplicateError, StorageError } from '../utils/errors';\nimport type { StoreKnowledgeInput, StoreKnowledgeResult, KnowledgeRow } from '../types';\n\nexport function storeKnowledge(input: StoreKnowledgeInput): StoreKnowledgeResult {\n validateStoreInput(input);\n\n const db = getDatabase();\n const now = new Date().toISOString();\n const normalizedTitle = normalizeTitle(input.title);\n const scope = normalizeScope(input.scope);\n const tags = normalizeTags(input.tags ?? []);\n const contentHash = hashContent(input.content);\n const id = uuidv4();\n\n try {\n return db.transaction(() => {\n const existingByTitle = db.queryOne<KnowledgeRow>(\n 'SELECT id FROM knowledge WHERE normalized_title = ? AND scope = ?',\n [normalizedTitle, scope]\n );\n\n if (existingByTitle) {\n throw new DuplicateError(\n 'Knowledge with similar title already exists in this scope',\n existingByTitle.id,\n 'title'\n );\n }\n\n const existingByHash = db.queryOne<KnowledgeRow>(\n 'SELECT id FROM knowledge WHERE content_hash = ? AND scope = ?',\n [contentHash, scope]\n );\n\n if (existingByHash) {\n throw new DuplicateError(\n 'Knowledge with identical content already exists in this scope',\n existingByHash.id,\n 'content'\n );\n }\n\n db.execute(\n `INSERT INTO knowledge (\n id, title, content, tags, scope,\n normalized_title, content_hash, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n id,\n input.title.trim(),\n input.content.trim(),\n JSON.stringify(tags),\n scope,\n normalizedTitle,\n contentHash,\n now,\n now\n ]\n );\n\n return {\n success: true,\n id,\n message: 'Knowledge stored successfully'\n };\n });\n } catch (error) {\n if (error instanceof DuplicateError) {\n throw error;\n }\n throw new StorageError(\n 'Failed to store knowledge',\n { originalError: error instanceof Error ? error.message : String(error) }\n );\n }\n}"],"names":["storeKnowledge","input","validateStoreInput","db","getDatabase","now","Date","toISOString","normalizedTitle","normalizeTitle","title","scope","normalizeScope","tags","normalizeTags","contentHash","hashContent","content","id","uuidv4","transaction","existingByTitle","queryOne","DuplicateError","existingByHash","execute","trim","JSON","stringify","success","message","error","StorageError","originalError","Error","String"],"mappings":";;;;+BAOgBA;;;eAAAA;;;sBAPa;0BACD;2BACO;4BACwC;wBAC9B;AAGtC,SAASA,eAAeC,KAA0B;IACrDC,IAAAA,6BAAkB,EAACD;IAEnB,MAAME,KAAKC,IAAAA,qBAAW;IACtB,MAAMC,MAAM,IAAIC,OAAOC,WAAW;IAClC,MAAMC,kBAAkBC,IAAAA,0BAAc,EAACR,MAAMS,KAAK;IAClD,MAAMC,QAAQC,IAAAA,0BAAc,EAACX,MAAMU,KAAK;IACxC,MAAME,OAAOC,IAAAA,yBAAa,EAACb,MAAMY,IAAI,IAAI,EAAE;IAC3C,MAAME,cAAcC,IAAAA,uBAAW,EAACf,MAAMgB,OAAO;IAC7C,MAAMC,KAAKC,IAAAA,QAAM;IAEjB,IAAI;QACA,OAAOhB,GAAGiB,WAAW,CAAC;YAClB,MAAMC,kBAAkBlB,GAAGmB,QAAQ,CAC/B,qEACA;gBAACd;gBAAiBG;aAAM;YAG5B,IAAIU,iBAAiB;gBACjB,MAAM,IAAIE,sBAAc,CACpB,6DACAF,gBAAgBH,EAAE,EAClB;YAER;YAEA,MAAMM,iBAAiBrB,GAAGmB,QAAQ,CAC9B,iEACA;gBAACP;gBAAaJ;aAAM;YAGxB,IAAIa,gBAAgB;gBAChB,MAAM,IAAID,sBAAc,CACpB,iEACAC,eAAeN,EAAE,EACjB;YAER;YAEAf,GAAGsB,OAAO,CACN,CAAC;;;4CAG2B,CAAC,EAC7B;gBACIP;gBACAjB,MAAMS,KAAK,CAACgB,IAAI;gBAChBzB,MAAMgB,OAAO,CAACS,IAAI;gBAClBC,KAAKC,SAAS,CAACf;gBACfF;gBACAH;gBACAO;gBACAV;gBACAA;aACH;YAGL,OAAO;gBACHwB,SAAS;gBACTX;gBACAY,SAAS;YACb;QACJ;IACJ,EAAE,OAAOC,OAAO;QACZ,IAAIA,iBAAiBR,sBAAc,EAAE;YACjC,MAAMQ;QACV;QACA,MAAM,IAAIC,oBAAY,CAClB,6BACA;YAAEC,eAAeF,iBAAiBG,QAAQH,MAAMD,OAAO,GAAGK,OAAOJ;QAAO;IAEhF;AACJ"}
1
+ {"version":3,"sources":["../../src/handlers/store.ts"],"sourcesContent":["import { v4 as uuidv4 } from 'uuid';\nimport { getDatabase } from '../database/index.js';\nimport { validateStoreInput } from '../services/validator.js';\nimport { normalizeTitle, normalizeScope, normalizeTags, hashContent } from '../services/normalizer.js';\nimport { DuplicateError, StorageError } from '../utils/errors.js';\nimport type { StoreKnowledgeInput, StoreKnowledgeResult, KnowledgeRow } from '../types/index.js';\n\nexport function storeKnowledge(input: StoreKnowledgeInput): StoreKnowledgeResult {\n validateStoreInput(input);\n\n const db = getDatabase();\n const now = new Date().toISOString();\n const normalizedTitle = normalizeTitle(input.title);\n const scope = normalizeScope(input.scope);\n const tags = normalizeTags(input.tags ?? []);\n const contentHash = hashContent(input.content);\n const id = uuidv4();\n\n try {\n return db.transaction(() => {\n const existingByTitle = db.queryOne<KnowledgeRow>(\n 'SELECT id FROM knowledge WHERE normalized_title = ? AND scope = ?',\n [normalizedTitle, scope]\n );\n\n if (existingByTitle) {\n throw new DuplicateError(\n 'Knowledge with similar title already exists in this scope',\n existingByTitle.id,\n 'title'\n );\n }\n\n const existingByHash = db.queryOne<KnowledgeRow>(\n 'SELECT id FROM knowledge WHERE content_hash = ? AND scope = ?',\n [contentHash, scope]\n );\n\n if (existingByHash) {\n throw new DuplicateError(\n 'Knowledge with identical content already exists in this scope',\n existingByHash.id,\n 'content'\n );\n }\n\n db.execute(\n `INSERT INTO knowledge (\n id, title, content, tags, scope,\n normalized_title, content_hash, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n id,\n input.title.trim(),\n input.content.trim(),\n JSON.stringify(tags),\n scope,\n normalizedTitle,\n contentHash,\n now,\n now\n ]\n );\n\n return {\n success: true,\n id,\n message: 'Knowledge stored successfully'\n };\n });\n } catch (error) {\n if (error instanceof DuplicateError) {\n throw error;\n }\n throw new StorageError(\n 'Failed to store knowledge',\n { originalError: error instanceof Error ? error.message : String(error) }\n );\n }\n}"],"names":["v4","uuidv4","getDatabase","validateStoreInput","normalizeTitle","normalizeScope","normalizeTags","hashContent","DuplicateError","StorageError","storeKnowledge","input","db","now","Date","toISOString","normalizedTitle","title","scope","tags","contentHash","content","id","transaction","existingByTitle","queryOne","existingByHash","execute","trim","JSON","stringify","success","message","error","originalError","Error","String"],"mappings":"AAAA,SAASA,MAAMC,MAAM,QAAQ,OAAO;AACpC,SAASC,WAAW,QAAQ,uBAAuB;AACnD,SAASC,kBAAkB,QAAQ,2BAA2B;AAC9D,SAASC,cAAc,EAAEC,cAAc,EAAEC,aAAa,EAAEC,WAAW,QAAQ,4BAA4B;AACvG,SAASC,cAAc,EAAEC,YAAY,QAAQ,qBAAqB;AAGlE,OAAO,SAASC,eAAeC,KAA0B;IACrDR,mBAAmBQ;IAEnB,MAAMC,KAAKV;IACX,MAAMW,MAAM,IAAIC,OAAOC,WAAW;IAClC,MAAMC,kBAAkBZ,eAAeO,MAAMM,KAAK;IAClD,MAAMC,QAAQb,eAAeM,MAAMO,KAAK;IACxC,MAAMC,OAAOb,cAAcK,MAAMQ,IAAI,IAAI,EAAE;IAC3C,MAAMC,cAAcb,YAAYI,MAAMU,OAAO;IAC7C,MAAMC,KAAKrB;IAEX,IAAI;QACA,OAAOW,GAAGW,WAAW,CAAC;YAClB,MAAMC,kBAAkBZ,GAAGa,QAAQ,CAC/B,qEACA;gBAACT;gBAAiBE;aAAM;YAG5B,IAAIM,iBAAiB;gBACjB,MAAM,IAAIhB,eACN,6DACAgB,gBAAgBF,EAAE,EAClB;YAER;YAEA,MAAMI,iBAAiBd,GAAGa,QAAQ,CAC9B,iEACA;gBAACL;gBAAaF;aAAM;YAGxB,IAAIQ,gBAAgB;gBAChB,MAAM,IAAIlB,eACN,iEACAkB,eAAeJ,EAAE,EACjB;YAER;YAEAV,GAAGe,OAAO,CACN,CAAC;;;4CAG2B,CAAC,EAC7B;gBACIL;gBACAX,MAAMM,KAAK,CAACW,IAAI;gBAChBjB,MAAMU,OAAO,CAACO,IAAI;gBAClBC,KAAKC,SAAS,CAACX;gBACfD;gBACAF;gBACAI;gBACAP;gBACAA;aACH;YAGL,OAAO;gBACHkB,SAAS;gBACTT;gBACAU,SAAS;YACb;QACJ;IACJ,EAAE,OAAOC,OAAO;QACZ,IAAIA,iBAAiBzB,gBAAgB;YACjC,MAAMyB;QACV;QACA,MAAM,IAAIxB,aACN,6BACA;YAAEyB,eAAeD,iBAAiBE,QAAQF,MAAMD,OAAO,GAAGI,OAAOH;QAAO;IAEhF;AACJ"}
@@ -1,3 +1,3 @@
1
- import type { UpdateKnowledgeInput, UpdateKnowledgeResult } from '../types';
1
+ import type { UpdateKnowledgeInput, UpdateKnowledgeResult } from '../types/index.js';
2
2
  export declare function updateKnowledge(input: UpdateKnowledgeInput): UpdateKnowledgeResult;
3
3
  //# sourceMappingURL=update.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/handlers/update.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,EAAgB,MAAM,UAAU,CAAC;AAE1F,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CAkFlF"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/handlers/update.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,EAAgB,MAAM,mBAAmB,CAAC;AAEnG,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CAkFlF"}
@@ -1,20 +1,10 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "updateKnowledge", {
6
- enumerable: true,
7
- get: function() {
8
- return updateKnowledge;
9
- }
10
- });
11
- const _database = require("../database");
12
- const _validator = require("../services/validator");
13
- const _normalizer = require("../services/normalizer");
14
- const _errors = require("../utils/errors");
15
- function updateKnowledge(input) {
16
- (0, _validator.validateUpdateInput)(input);
17
- const db = (0, _database.getDatabase)();
1
+ import { getDatabase } from '../database/index.js';
2
+ import { validateUpdateInput } from '../services/validator.js';
3
+ import { normalizeTitle, normalizeScope, normalizeTags, hashContent } from '../services/normalizer.js';
4
+ import { DuplicateError, NotFoundError, StorageError } from '../utils/errors.js';
5
+ export function updateKnowledge(input) {
6
+ validateUpdateInput(input);
7
+ const db = getDatabase();
18
8
  const now = new Date().toISOString();
19
9
  try {
20
10
  return db.transaction(()=>{
@@ -22,21 +12,21 @@ function updateKnowledge(input) {
22
12
  input.id
23
13
  ]);
24
14
  if (!existing) {
25
- throw new _errors.NotFoundError(`Knowledge item not found: ${input.id}`, input.id);
15
+ throw new NotFoundError(`Knowledge item not found: ${input.id}`, input.id);
26
16
  }
27
17
  const title = input.title !== undefined ? input.title.trim() : existing.title;
28
18
  const content = input.content !== undefined ? input.content.trim() : existing.content;
29
- const tags = input.tags !== undefined ? (0, _normalizer.normalizeTags)(input.tags) : JSON.parse(existing.tags);
30
- const scope = input.scope !== undefined ? (0, _normalizer.normalizeScope)(input.scope) : existing.scope;
31
- const normalizedTitle = (0, _normalizer.normalizeTitle)(title);
32
- const contentHash = (0, _normalizer.hashContent)(content);
19
+ const tags = input.tags !== undefined ? normalizeTags(input.tags) : JSON.parse(existing.tags);
20
+ const scope = input.scope !== undefined ? normalizeScope(input.scope) : existing.scope;
21
+ const normalizedTitle = normalizeTitle(title);
22
+ const contentHash = hashContent(content);
33
23
  const existingByTitle = db.queryOne('SELECT id FROM knowledge WHERE normalized_title = ? AND scope = ? AND id != ?', [
34
24
  normalizedTitle,
35
25
  scope,
36
26
  input.id
37
27
  ]);
38
28
  if (existingByTitle) {
39
- throw new _errors.DuplicateError('Knowledge with similar title already exists in this scope', existingByTitle.id, 'title');
29
+ throw new DuplicateError('Knowledge with similar title already exists in this scope', existingByTitle.id, 'title');
40
30
  }
41
31
  const existingByHash = db.queryOne('SELECT id FROM knowledge WHERE content_hash = ? AND scope = ? AND id != ?', [
42
32
  contentHash,
@@ -44,7 +34,7 @@ function updateKnowledge(input) {
44
34
  input.id
45
35
  ]);
46
36
  if (existingByHash) {
47
- throw new _errors.DuplicateError('Knowledge with identical content already exists in this scope', existingByHash.id, 'content');
37
+ throw new DuplicateError('Knowledge with identical content already exists in this scope', existingByHash.id, 'content');
48
38
  }
49
39
  db.execute(`UPDATE knowledge SET
50
40
  title = ?, content = ?, tags = ?, scope = ?,
@@ -66,10 +56,10 @@ function updateKnowledge(input) {
66
56
  };
67
57
  });
68
58
  } catch (error) {
69
- if (error instanceof _errors.DuplicateError || error instanceof _errors.NotFoundError) {
59
+ if (error instanceof DuplicateError || error instanceof NotFoundError) {
70
60
  throw error;
71
61
  }
72
- throw new _errors.StorageError('Failed to update knowledge', {
62
+ throw new StorageError('Failed to update knowledge', {
73
63
  originalError: error instanceof Error ? error.message : String(error)
74
64
  });
75
65
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/handlers/update.ts"],"sourcesContent":["import { getDatabase } from '../database';\nimport { validateUpdateInput } from '../services/validator';\nimport { normalizeTitle, normalizeScope, normalizeTags, hashContent } from '../services/normalizer';\nimport { DuplicateError, NotFoundError, StorageError } from '../utils/errors';\nimport type { UpdateKnowledgeInput, UpdateKnowledgeResult, KnowledgeRow } from '../types';\n\nexport function updateKnowledge(input: UpdateKnowledgeInput): UpdateKnowledgeResult {\n validateUpdateInput(input);\n\n const db = getDatabase();\n const now = new Date().toISOString();\n\n try {\n return db.transaction(() => {\n const existing = db.queryOne<KnowledgeRow>(\n 'SELECT * FROM knowledge WHERE id = ?',\n [input.id]\n );\n\n if (!existing) {\n throw new NotFoundError(`Knowledge item not found: ${input.id}`, input.id);\n }\n\n const title = input.title !== undefined ? input.title.trim() : existing.title;\n const content = input.content !== undefined ? input.content.trim() : existing.content;\n const tags = input.tags !== undefined ? normalizeTags(input.tags) : JSON.parse(existing.tags);\n const scope = input.scope !== undefined ? normalizeScope(input.scope) : existing.scope;\n const normalizedTitle = normalizeTitle(title);\n const contentHash = hashContent(content);\n\n const existingByTitle = db.queryOne<KnowledgeRow>(\n 'SELECT id FROM knowledge WHERE normalized_title = ? AND scope = ? AND id != ?',\n [normalizedTitle, scope, input.id]\n );\n\n if (existingByTitle) {\n throw new DuplicateError(\n 'Knowledge with similar title already exists in this scope',\n existingByTitle.id,\n 'title'\n );\n }\n\n const existingByHash = db.queryOne<KnowledgeRow>(\n 'SELECT id FROM knowledge WHERE content_hash = ? AND scope = ? AND id != ?',\n [contentHash, scope, input.id]\n );\n\n if (existingByHash) {\n throw new DuplicateError(\n 'Knowledge with identical content already exists in this scope',\n existingByHash.id,\n 'content'\n );\n }\n\n db.execute(\n `UPDATE knowledge SET\n title = ?, content = ?, tags = ?, scope = ?,\n normalized_title = ?, content_hash = ?, updated_at = ?\n WHERE id = ?`,\n [\n title,\n content,\n JSON.stringify(tags),\n scope,\n normalizedTitle,\n contentHash,\n now,\n input.id\n ]\n );\n\n return {\n success: true,\n id: input.id,\n message: 'Knowledge updated successfully'\n };\n });\n } catch (error) {\n if (error instanceof DuplicateError || error instanceof NotFoundError) {\n throw error;\n }\n throw new StorageError(\n 'Failed to update knowledge',\n { originalError: error instanceof Error ? error.message : String(error) }\n );\n }\n}\n"],"names":["updateKnowledge","input","validateUpdateInput","db","getDatabase","now","Date","toISOString","transaction","existing","queryOne","id","NotFoundError","title","undefined","trim","content","tags","normalizeTags","JSON","parse","scope","normalizeScope","normalizedTitle","normalizeTitle","contentHash","hashContent","existingByTitle","DuplicateError","existingByHash","execute","stringify","success","message","error","StorageError","originalError","Error","String"],"mappings":";;;;+BAMgBA;;;eAAAA;;;0BANY;2BACQ;4BACuC;wBACf;AAGrD,SAASA,gBAAgBC,KAA2B;IACvDC,IAAAA,8BAAmB,EAACD;IAEpB,MAAME,KAAKC,IAAAA,qBAAW;IACtB,MAAMC,MAAM,IAAIC,OAAOC,WAAW;IAElC,IAAI;QACA,OAAOJ,GAAGK,WAAW,CAAC;YAClB,MAAMC,WAAWN,GAAGO,QAAQ,CACxB,wCACA;gBAACT,MAAMU,EAAE;aAAC;YAGd,IAAI,CAACF,UAAU;gBACX,MAAM,IAAIG,qBAAa,CAAC,CAAC,0BAA0B,EAAEX,MAAMU,EAAE,EAAE,EAAEV,MAAMU,EAAE;YAC7E;YAEA,MAAME,QAAQZ,MAAMY,KAAK,KAAKC,YAAYb,MAAMY,KAAK,CAACE,IAAI,KAAKN,SAASI,KAAK;YAC7E,MAAMG,UAAUf,MAAMe,OAAO,KAAKF,YAAYb,MAAMe,OAAO,CAACD,IAAI,KAAKN,SAASO,OAAO;YACrF,MAAMC,OAAOhB,MAAMgB,IAAI,KAAKH,YAAYI,IAAAA,yBAAa,EAACjB,MAAMgB,IAAI,IAAIE,KAAKC,KAAK,CAACX,SAASQ,IAAI;YAC5F,MAAMI,QAAQpB,MAAMoB,KAAK,KAAKP,YAAYQ,IAAAA,0BAAc,EAACrB,MAAMoB,KAAK,IAAIZ,SAASY,KAAK;YACtF,MAAME,kBAAkBC,IAAAA,0BAAc,EAACX;YACvC,MAAMY,cAAcC,IAAAA,uBAAW,EAACV;YAEhC,MAAMW,kBAAkBxB,GAAGO,QAAQ,CAC/B,iFACA;gBAACa;gBAAiBF;gBAAOpB,MAAMU,EAAE;aAAC;YAGtC,IAAIgB,iBAAiB;gBACjB,MAAM,IAAIC,sBAAc,CACpB,6DACAD,gBAAgBhB,EAAE,EAClB;YAER;YAEA,MAAMkB,iBAAiB1B,GAAGO,QAAQ,CAC9B,6EACA;gBAACe;gBAAaJ;gBAAOpB,MAAMU,EAAE;aAAC;YAGlC,IAAIkB,gBAAgB;gBAChB,MAAM,IAAID,sBAAc,CACpB,iEACAC,eAAelB,EAAE,EACjB;YAER;YAEAR,GAAG2B,OAAO,CACN,CAAC;;;4BAGW,CAAC,EACb;gBACIjB;gBACAG;gBACAG,KAAKY,SAAS,CAACd;gBACfI;gBACAE;gBACAE;gBACApB;gBACAJ,MAAMU,EAAE;aACX;YAGL,OAAO;gBACHqB,SAAS;gBACTrB,IAAIV,MAAMU,EAAE;gBACZsB,SAAS;YACb;QACJ;IACJ,EAAE,OAAOC,OAAO;QACZ,IAAIA,iBAAiBN,sBAAc,IAAIM,iBAAiBtB,qBAAa,EAAE;YACnE,MAAMsB;QACV;QACA,MAAM,IAAIC,oBAAY,CAClB,8BACA;YAAEC,eAAeF,iBAAiBG,QAAQH,MAAMD,OAAO,GAAGK,OAAOJ;QAAO;IAEhF;AACJ"}
1
+ {"version":3,"sources":["../../src/handlers/update.ts"],"sourcesContent":["import { getDatabase } from '../database/index.js';\nimport { validateUpdateInput } from '../services/validator.js';\nimport { normalizeTitle, normalizeScope, normalizeTags, hashContent } from '../services/normalizer.js';\nimport { DuplicateError, NotFoundError, StorageError } from '../utils/errors.js';\nimport type { UpdateKnowledgeInput, UpdateKnowledgeResult, KnowledgeRow } from '../types/index.js';\n\nexport function updateKnowledge(input: UpdateKnowledgeInput): UpdateKnowledgeResult {\n validateUpdateInput(input);\n\n const db = getDatabase();\n const now = new Date().toISOString();\n\n try {\n return db.transaction(() => {\n const existing = db.queryOne<KnowledgeRow>(\n 'SELECT * FROM knowledge WHERE id = ?',\n [input.id]\n );\n\n if (!existing) {\n throw new NotFoundError(`Knowledge item not found: ${input.id}`, input.id);\n }\n\n const title = input.title !== undefined ? input.title.trim() : existing.title;\n const content = input.content !== undefined ? input.content.trim() : existing.content;\n const tags = input.tags !== undefined ? normalizeTags(input.tags) : JSON.parse(existing.tags);\n const scope = input.scope !== undefined ? normalizeScope(input.scope) : existing.scope;\n const normalizedTitle = normalizeTitle(title);\n const contentHash = hashContent(content);\n\n const existingByTitle = db.queryOne<KnowledgeRow>(\n 'SELECT id FROM knowledge WHERE normalized_title = ? AND scope = ? AND id != ?',\n [normalizedTitle, scope, input.id]\n );\n\n if (existingByTitle) {\n throw new DuplicateError(\n 'Knowledge with similar title already exists in this scope',\n existingByTitle.id,\n 'title'\n );\n }\n\n const existingByHash = db.queryOne<KnowledgeRow>(\n 'SELECT id FROM knowledge WHERE content_hash = ? AND scope = ? AND id != ?',\n [contentHash, scope, input.id]\n );\n\n if (existingByHash) {\n throw new DuplicateError(\n 'Knowledge with identical content already exists in this scope',\n existingByHash.id,\n 'content'\n );\n }\n\n db.execute(\n `UPDATE knowledge SET\n title = ?, content = ?, tags = ?, scope = ?,\n normalized_title = ?, content_hash = ?, updated_at = ?\n WHERE id = ?`,\n [\n title,\n content,\n JSON.stringify(tags),\n scope,\n normalizedTitle,\n contentHash,\n now,\n input.id\n ]\n );\n\n return {\n success: true,\n id: input.id,\n message: 'Knowledge updated successfully'\n };\n });\n } catch (error) {\n if (error instanceof DuplicateError || error instanceof NotFoundError) {\n throw error;\n }\n throw new StorageError(\n 'Failed to update knowledge',\n { originalError: error instanceof Error ? error.message : String(error) }\n );\n }\n}\n"],"names":["getDatabase","validateUpdateInput","normalizeTitle","normalizeScope","normalizeTags","hashContent","DuplicateError","NotFoundError","StorageError","updateKnowledge","input","db","now","Date","toISOString","transaction","existing","queryOne","id","title","undefined","trim","content","tags","JSON","parse","scope","normalizedTitle","contentHash","existingByTitle","existingByHash","execute","stringify","success","message","error","originalError","Error","String"],"mappings":"AAAA,SAASA,WAAW,QAAQ,uBAAuB;AACnD,SAASC,mBAAmB,QAAQ,2BAA2B;AAC/D,SAASC,cAAc,EAAEC,cAAc,EAAEC,aAAa,EAAEC,WAAW,QAAQ,4BAA4B;AACvG,SAASC,cAAc,EAAEC,aAAa,EAAEC,YAAY,QAAQ,qBAAqB;AAGjF,OAAO,SAASC,gBAAgBC,KAA2B;IACvDT,oBAAoBS;IAEpB,MAAMC,KAAKX;IACX,MAAMY,MAAM,IAAIC,OAAOC,WAAW;IAElC,IAAI;QACA,OAAOH,GAAGI,WAAW,CAAC;YAClB,MAAMC,WAAWL,GAAGM,QAAQ,CACxB,wCACA;gBAACP,MAAMQ,EAAE;aAAC;YAGd,IAAI,CAACF,UAAU;gBACX,MAAM,IAAIT,cAAc,CAAC,0BAA0B,EAAEG,MAAMQ,EAAE,EAAE,EAAER,MAAMQ,EAAE;YAC7E;YAEA,MAAMC,QAAQT,MAAMS,KAAK,KAAKC,YAAYV,MAAMS,KAAK,CAACE,IAAI,KAAKL,SAASG,KAAK;YAC7E,MAAMG,UAAUZ,MAAMY,OAAO,KAAKF,YAAYV,MAAMY,OAAO,CAACD,IAAI,KAAKL,SAASM,OAAO;YACrF,MAAMC,OAAOb,MAAMa,IAAI,KAAKH,YAAYhB,cAAcM,MAAMa,IAAI,IAAIC,KAAKC,KAAK,CAACT,SAASO,IAAI;YAC5F,MAAMG,QAAQhB,MAAMgB,KAAK,KAAKN,YAAYjB,eAAeO,MAAMgB,KAAK,IAAIV,SAASU,KAAK;YACtF,MAAMC,kBAAkBzB,eAAeiB;YACvC,MAAMS,cAAcvB,YAAYiB;YAEhC,MAAMO,kBAAkBlB,GAAGM,QAAQ,CAC/B,iFACA;gBAACU;gBAAiBD;gBAAOhB,MAAMQ,EAAE;aAAC;YAGtC,IAAIW,iBAAiB;gBACjB,MAAM,IAAIvB,eACN,6DACAuB,gBAAgBX,EAAE,EAClB;YAER;YAEA,MAAMY,iBAAiBnB,GAAGM,QAAQ,CAC9B,6EACA;gBAACW;gBAAaF;gBAAOhB,MAAMQ,EAAE;aAAC;YAGlC,IAAIY,gBAAgB;gBAChB,MAAM,IAAIxB,eACN,iEACAwB,eAAeZ,EAAE,EACjB;YAER;YAEAP,GAAGoB,OAAO,CACN,CAAC;;;4BAGW,CAAC,EACb;gBACIZ;gBACAG;gBACAE,KAAKQ,SAAS,CAACT;gBACfG;gBACAC;gBACAC;gBACAhB;gBACAF,MAAMQ,EAAE;aACX;YAGL,OAAO;gBACHe,SAAS;gBACTf,IAAIR,MAAMQ,EAAE;gBACZgB,SAAS;YACb;QACJ;IACJ,EAAE,OAAOC,OAAO;QACZ,IAAIA,iBAAiB7B,kBAAkB6B,iBAAiB5B,eAAe;YACnE,MAAM4B;QACV;QACA,MAAM,IAAI3B,aACN,8BACA;YAAE4B,eAAeD,iBAAiBE,QAAQF,MAAMD,OAAO,GAAGI,OAAOH;QAAO;IAEhF;AACJ"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- export * from './api';
2
+ export * from './api.js';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAIA,cAAc,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAKA,cAAc,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -1,27 +1,11 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- const _server = require("./server");
7
- _export_star(require("./api"), exports);
8
- function _export_star(from, to) {
9
- Object.keys(from).forEach(function(k) {
10
- if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
11
- Object.defineProperty(to, k, {
12
- enumerable: true,
13
- get: function() {
14
- return from[k];
15
- }
16
- });
17
- }
18
- });
19
- return from;
20
- }
2
+ import { fileURLToPath } from 'url';
3
+ import { runServer } from './server.js';
4
+ export * from './api.js';
21
5
  // Only start MCP server when this file is run directly as a binary
22
6
  // Not when imported as a library (e.g., by CLI commands)
23
- if (require.main === module) {
24
- (0, _server.runServer)().catch((error)=>{
7
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
8
+ runServer().catch((error)=>{
25
9
  console.error('Failed to start server:', error);
26
10
  process.exit(1);
27
11
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { runServer } from './server';\n\nexport * from './api';\n\n// Only start MCP server when this file is run directly as a binary\n// Not when imported as a library (e.g., by CLI commands)\nif (require.main === module) {\n runServer().catch((error: Error) => {\n console.error('Failed to start server:', error);\n process.exit(1);\n });\n}\n"],"names":["require","main","module","runServer","catch","error","console","process","exit"],"mappings":";;;;;wBAE0B;qBAEZ;;;;;;;;;;;;;;AAEd,mEAAmE;AACnE,yDAAyD;AACzD,IAAIA,QAAQC,IAAI,KAAKC,QAAQ;IACzBC,IAAAA,iBAAS,IAAGC,KAAK,CAAC,CAACC;QACfC,QAAQD,KAAK,CAAC,2BAA2BA;QACzCE,QAAQC,IAAI,CAAC;IACjB;AACJ"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { fileURLToPath } from 'url';\nimport { runServer } from './server.js';\n\nexport * from './api.js';\n\n// Only start MCP server when this file is run directly as a binary\n// Not when imported as a library (e.g., by CLI commands)\nif (process.argv[1] === fileURLToPath(import.meta.url)) {\n runServer().catch((error: Error) => {\n console.error('Failed to start server:', error);\n process.exit(1);\n });\n}\n"],"names":["fileURLToPath","runServer","process","argv","url","catch","error","console","exit"],"mappings":";AAEA,SAASA,aAAa,QAAQ,MAAM;AACpC,SAASC,SAAS,QAAQ,cAAc;AAExC,cAAc,WAAW;AAEzB,mEAAmE;AACnE,yDAAyD;AACzD,IAAIC,QAAQC,IAAI,CAAC,EAAE,KAAKH,cAAc,YAAYI,GAAG,GAAG;IACpDH,YAAYI,KAAK,CAAC,CAACC;QACfC,QAAQD,KAAK,CAAC,2BAA2BA;QACzCJ,QAAQM,IAAI,CAAC;IACjB;AACJ"}
package/dist/server.js CHANGED
@@ -1,31 +1,10 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- function _export(target, all) {
6
- for(var name in all)Object.defineProperty(target, name, {
7
- enumerable: true,
8
- get: Object.getOwnPropertyDescriptor(all, name).get
9
- });
10
- }
11
- _export(exports, {
12
- get TOOLS () {
13
- return TOOLS;
14
- },
15
- get createServer () {
16
- return createServer;
17
- },
18
- get runServer () {
19
- return runServer;
20
- }
21
- });
22
- const _index = require("@modelcontextprotocol/sdk/server/index.js");
23
- const _stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
24
- const _types = require("@modelcontextprotocol/sdk/types.js");
25
- const _store = require("./handlers/store");
26
- const _search = require("./handlers/search");
27
- const _update = require("./handlers/update");
28
- const _errors = require("./utils/errors");
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
4
+ import { storeKnowledge } from './handlers/store.js';
5
+ import { searchKnowledge } from './handlers/search.js';
6
+ import { updateKnowledge } from './handlers/update.js';
7
+ import { KnowledgeMemoryError } from './utils/errors.js';
29
8
  const SERVER_NAME = 'ai-devkit-memory';
30
9
  const SERVER_VERSION = '0.1.0';
31
10
  const STORE_TOOL = {
@@ -126,13 +105,13 @@ const SEARCH_TOOL = {
126
105
  ]
127
106
  }
128
107
  };
129
- const TOOLS = [
108
+ export const TOOLS = [
130
109
  STORE_TOOL,
131
110
  UPDATE_TOOL,
132
111
  SEARCH_TOOL
133
112
  ];
134
- function createServer() {
135
- const server = new _index.Server({
113
+ export function createServer() {
114
+ const server = new Server({
136
115
  name: SERVER_NAME,
137
116
  version: SERVER_VERSION
138
117
  }, {
@@ -141,7 +120,7 @@ function createServer() {
141
120
  }
142
121
  });
143
122
  // List available tools
144
- server.setRequestHandler(_types.ListToolsRequestSchema, async ()=>{
123
+ server.setRequestHandler(ListToolsRequestSchema, async ()=>{
145
124
  return {
146
125
  tools: [
147
126
  STORE_TOOL,
@@ -151,14 +130,14 @@ function createServer() {
151
130
  };
152
131
  });
153
132
  // Handle tool calls
154
- server.setRequestHandler(_types.CallToolRequestSchema, async (request)=>{
133
+ server.setRequestHandler(CallToolRequestSchema, async (request)=>{
155
134
  const { name, arguments: args } = request.params;
156
135
  try {
157
136
  // Backward-compat: accept deprecated dotted names so agents with
158
137
  // stale prompts/templates continue to work. Remove in next major.
159
138
  if (name === 'memory_storeKnowledge' || name === 'memory.storeKnowledge') {
160
139
  const input = args;
161
- const result = (0, _store.storeKnowledge)(input);
140
+ const result = storeKnowledge(input);
162
141
  return {
163
142
  content: [
164
143
  {
@@ -170,7 +149,7 @@ function createServer() {
170
149
  }
171
150
  if (name === 'memory_updateKnowledge' || name === 'memory.updateKnowledge') {
172
151
  const input = args;
173
- const result = (0, _update.updateKnowledge)(input);
152
+ const result = updateKnowledge(input);
174
153
  return {
175
154
  content: [
176
155
  {
@@ -182,7 +161,7 @@ function createServer() {
182
161
  }
183
162
  if (name === 'memory_searchKnowledge' || name === 'memory.searchKnowledge') {
184
163
  const input = args;
185
- const result = (0, _search.searchKnowledge)(input);
164
+ const result = searchKnowledge(input);
186
165
  return {
187
166
  content: [
188
167
  {
@@ -205,7 +184,7 @@ function createServer() {
205
184
  isError: true
206
185
  };
207
186
  } catch (error) {
208
- const errorResponse = error instanceof _errors.KnowledgeMemoryError ? error.toJSON() : {
187
+ const errorResponse = error instanceof KnowledgeMemoryError ? error.toJSON() : {
209
188
  error: 'INTERNAL_ERROR',
210
189
  message: error instanceof Error ? error.message : String(error)
211
190
  };
@@ -222,9 +201,9 @@ function createServer() {
222
201
  });
223
202
  return server;
224
203
  }
225
- async function runServer() {
204
+ export async function runServer() {
226
205
  const server = createServer();
227
- const transport = new _stdio.StdioServerTransport();
206
+ const transport = new StdioServerTransport();
228
207
  await server.connect(transport);
229
208
  }
230
209
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { storeKnowledge } from './handlers/store';\nimport { searchKnowledge } from './handlers/search';\nimport { updateKnowledge } from './handlers/update';\nimport { KnowledgeMemoryError } from './utils/errors';\nimport type { StoreKnowledgeInput, SearchKnowledgeInput, UpdateKnowledgeInput } from './types';\n\nconst SERVER_NAME = 'ai-devkit-memory';\nconst SERVER_VERSION = '0.1.0';\n\nconst STORE_TOOL = {\n name: 'memory_storeKnowledge',\n description: 'Store a new knowledge item. Use this to save actionable guidelines, rules, or patterns for future reference.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n title: {\n type: 'string',\n description: 'Short, explicit description of the rule (5-12 words, 10-100 chars)',\n },\n content: {\n type: 'string',\n description: 'Detailed explanation in markdown format. Supports code blocks and examples. (50-5000 chars)',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional domain keywords (e.g., [\"api\", \"backend\"]). Max 10 tags.',\n },\n scope: {\n type: 'string',\n description: 'Optional scope: \"global\", \"project:<name>\", or \"repo:<name>\". Default: \"global\"',\n },\n },\n required: ['title', 'content'],\n },\n};\n\nconst UPDATE_TOOL = {\n name: 'memory_updateKnowledge',\n description: 'Update an existing knowledge item by ID. Use this to correct outdated or inaccurate knowledge.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'UUID of the knowledge item to update',\n },\n title: {\n type: 'string',\n description: 'New title (10-100 chars). Only provide if changing.',\n },\n content: {\n type: 'string',\n description: 'New content in markdown format (50-5000 chars). Only provide if changing.',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: 'New tags (replaces existing). Only provide if changing. Max 10 tags.',\n },\n scope: {\n type: 'string',\n description: 'New scope: \"global\", \"project:<name>\", or \"repo:<name>\". Only provide if changing.',\n },\n },\n required: ['id'],\n },\n};\n\nconst SEARCH_TOOL = {\n name: 'memory_searchKnowledge',\n description: 'Search for relevant knowledge based on a task description. Returns ranked results.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n query: {\n type: 'string',\n description: 'Natural language task description to search for relevant knowledge (3-500 chars)',\n },\n contextTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional tags to boost matching results (e.g., [\"api\", \"backend\"])',\n },\n scope: {\n type: 'string',\n description: 'Optional project/repo scope filter. Results from this scope are prioritized.',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results to return (1-20, default: 5)',\n },\n },\n required: ['query'],\n },\n};\n\nexport const TOOLS = [STORE_TOOL, UPDATE_TOOL, SEARCH_TOOL];\n\nexport function createServer(): Server {\n const server = new Server(\n {\n name: SERVER_NAME,\n version: SERVER_VERSION,\n },\n {\n capabilities: {\n tools: {},\n },\n }\n );\n\n // List available tools\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [STORE_TOOL, UPDATE_TOOL, SEARCH_TOOL],\n };\n });\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n // Backward-compat: accept deprecated dotted names so agents with\n // stale prompts/templates continue to work. Remove in next major.\n if (name === 'memory_storeKnowledge' || name === 'memory.storeKnowledge') {\n const input = args as unknown as StoreKnowledgeInput;\n const result = storeKnowledge(input);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n if (name === 'memory_updateKnowledge' || name === 'memory.updateKnowledge') {\n const input = args as unknown as UpdateKnowledgeInput;\n const result = updateKnowledge(input);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n if (name === 'memory_searchKnowledge' || name === 'memory.searchKnowledge') {\n const input = args as unknown as SearchKnowledgeInput;\n const result = searchKnowledge(input);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ error: 'UNKNOWN_TOOL', message: `Unknown tool: ${name}` }),\n },\n ],\n isError: true,\n };\n } catch (error) {\n const errorResponse = error instanceof KnowledgeMemoryError\n ? error.toJSON()\n : { error: 'INTERNAL_ERROR', message: error instanceof Error ? error.message : String(error) };\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(errorResponse, null, 2),\n },\n ],\n isError: true,\n };\n }\n });\n\n return server;\n}\n\nexport async function runServer(): Promise<void> {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n"],"names":["TOOLS","createServer","runServer","SERVER_NAME","SERVER_VERSION","STORE_TOOL","name","description","inputSchema","type","properties","title","content","tags","items","scope","required","UPDATE_TOOL","id","SEARCH_TOOL","query","contextTags","limit","server","Server","version","capabilities","tools","setRequestHandler","ListToolsRequestSchema","CallToolRequestSchema","request","arguments","args","params","input","result","storeKnowledge","text","JSON","stringify","updateKnowledge","searchKnowledge","error","message","isError","errorResponse","KnowledgeMemoryError","toJSON","Error","String","transport","StdioServerTransport","connect"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/server.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { storeKnowledge } from './handlers/store.js';\nimport { searchKnowledge } from './handlers/search.js';\nimport { updateKnowledge } from './handlers/update.js';\nimport { KnowledgeMemoryError } from './utils/errors.js';\nimport type { StoreKnowledgeInput, SearchKnowledgeInput, UpdateKnowledgeInput } from './types/index.js';\n\nconst SERVER_NAME = 'ai-devkit-memory';\nconst SERVER_VERSION = '0.1.0';\n\nconst STORE_TOOL = {\n name: 'memory_storeKnowledge',\n description: 'Store a new knowledge item. Use this to save actionable guidelines, rules, or patterns for future reference.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n title: {\n type: 'string',\n description: 'Short, explicit description of the rule (5-12 words, 10-100 chars)',\n },\n content: {\n type: 'string',\n description: 'Detailed explanation in markdown format. Supports code blocks and examples. (50-5000 chars)',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional domain keywords (e.g., [\"api\", \"backend\"]). Max 10 tags.',\n },\n scope: {\n type: 'string',\n description: 'Optional scope: \"global\", \"project:<name>\", or \"repo:<name>\". Default: \"global\"',\n },\n },\n required: ['title', 'content'],\n },\n};\n\nconst UPDATE_TOOL = {\n name: 'memory_updateKnowledge',\n description: 'Update an existing knowledge item by ID. Use this to correct outdated or inaccurate knowledge.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'UUID of the knowledge item to update',\n },\n title: {\n type: 'string',\n description: 'New title (10-100 chars). Only provide if changing.',\n },\n content: {\n type: 'string',\n description: 'New content in markdown format (50-5000 chars). Only provide if changing.',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: 'New tags (replaces existing). Only provide if changing. Max 10 tags.',\n },\n scope: {\n type: 'string',\n description: 'New scope: \"global\", \"project:<name>\", or \"repo:<name>\". Only provide if changing.',\n },\n },\n required: ['id'],\n },\n};\n\nconst SEARCH_TOOL = {\n name: 'memory_searchKnowledge',\n description: 'Search for relevant knowledge based on a task description. Returns ranked results.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n query: {\n type: 'string',\n description: 'Natural language task description to search for relevant knowledge (3-500 chars)',\n },\n contextTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional tags to boost matching results (e.g., [\"api\", \"backend\"])',\n },\n scope: {\n type: 'string',\n description: 'Optional project/repo scope filter. Results from this scope are prioritized.',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results to return (1-20, default: 5)',\n },\n },\n required: ['query'],\n },\n};\n\nexport const TOOLS = [STORE_TOOL, UPDATE_TOOL, SEARCH_TOOL];\n\nexport function createServer(): Server {\n const server = new Server(\n {\n name: SERVER_NAME,\n version: SERVER_VERSION,\n },\n {\n capabilities: {\n tools: {},\n },\n }\n );\n\n // List available tools\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [STORE_TOOL, UPDATE_TOOL, SEARCH_TOOL],\n };\n });\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n // Backward-compat: accept deprecated dotted names so agents with\n // stale prompts/templates continue to work. Remove in next major.\n if (name === 'memory_storeKnowledge' || name === 'memory.storeKnowledge') {\n const input = args as unknown as StoreKnowledgeInput;\n const result = storeKnowledge(input);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n if (name === 'memory_updateKnowledge' || name === 'memory.updateKnowledge') {\n const input = args as unknown as UpdateKnowledgeInput;\n const result = updateKnowledge(input);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n if (name === 'memory_searchKnowledge' || name === 'memory.searchKnowledge') {\n const input = args as unknown as SearchKnowledgeInput;\n const result = searchKnowledge(input);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ error: 'UNKNOWN_TOOL', message: `Unknown tool: ${name}` }),\n },\n ],\n isError: true,\n };\n } catch (error) {\n const errorResponse = error instanceof KnowledgeMemoryError\n ? error.toJSON()\n : { error: 'INTERNAL_ERROR', message: error instanceof Error ? error.message : String(error) };\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(errorResponse, null, 2),\n },\n ],\n isError: true,\n };\n }\n });\n\n return server;\n}\n\nexport async function runServer(): Promise<void> {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n"],"names":["Server","StdioServerTransport","CallToolRequestSchema","ListToolsRequestSchema","storeKnowledge","searchKnowledge","updateKnowledge","KnowledgeMemoryError","SERVER_NAME","SERVER_VERSION","STORE_TOOL","name","description","inputSchema","type","properties","title","content","tags","items","scope","required","UPDATE_TOOL","id","SEARCH_TOOL","query","contextTags","limit","TOOLS","createServer","server","version","capabilities","tools","setRequestHandler","request","arguments","args","params","input","result","text","JSON","stringify","error","message","isError","errorResponse","toJSON","Error","String","runServer","transport","connect"],"mappings":"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"}
@@ -1,48 +1,31 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- function _export(target, all) {
6
- for(var name in all)Object.defineProperty(target, name, {
7
- enumerable: true,
8
- get: Object.getOwnPropertyDescriptor(all, name).get
9
- });
10
- }
11
- _export(exports, {
12
- get hashContent () {
13
- return hashContent;
14
- },
15
- get normalizeContent () {
16
- return normalizeContent;
17
- },
18
- get normalizeScope () {
19
- return normalizeScope;
20
- },
21
- get normalizeTags () {
22
- return normalizeTags;
23
- },
24
- get normalizeTitle () {
25
- return normalizeTitle;
26
- }
27
- });
28
- const _crypto = require("crypto");
29
- function normalizeTitle(title) {
1
+ import { createHash } from 'crypto';
2
+ /**
3
+ * Normalize title for deduplication
4
+ */ export function normalizeTitle(title) {
30
5
  return title.toLowerCase().trim().replace(/\s+/g, ' ');
31
6
  }
32
- function normalizeContent(content) {
7
+ /**
8
+ * Normalize content for hashing
9
+ */ export function normalizeContent(content) {
33
10
  return content.trim().replace(/\r\n/g, '\n').replace(/\r/g, '\n').replace(/\n{3,}/g, '\n\n');
34
11
  }
35
- function hashContent(content) {
12
+ /**
13
+ * Generate SHA-256 hash of normalized content for deduplication
14
+ */ export function hashContent(content) {
36
15
  const normalized = normalizeContent(content);
37
- return (0, _crypto.createHash)('sha256').update(normalized, 'utf8').digest('hex');
16
+ return createHash('sha256').update(normalized, 'utf8').digest('hex');
38
17
  }
39
- function normalizeTags(tags) {
18
+ /**
19
+ * Normalize tags
20
+ */ export function normalizeTags(tags) {
40
21
  const normalized = tags.map((tag)=>tag.toLowerCase().trim()).filter((tag)=>tag.length > 0);
41
22
  return [
42
23
  ...new Set(normalized)
43
24
  ];
44
25
  }
45
- function normalizeScope(scope) {
26
+ /**
27
+ * Validate and normalize scope
28
+ */ export function normalizeScope(scope) {
46
29
  if (!scope || scope.trim() === '') {
47
30
  return 'global';
48
31
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/normalizer.ts"],"sourcesContent":["import { createHash } from 'crypto';\n\n/**\n * Normalize title for deduplication\n */\nexport function normalizeTitle(title: string): string {\n return title\n .toLowerCase()\n .trim()\n .replace(/\\s+/g, ' ');\n}\n\n/**\n * Normalize content for hashing\n */\nexport function normalizeContent(content: string): string {\n return content\n .trim()\n .replace(/\\r\\n/g, '\\n')\n .replace(/\\r/g, '\\n')\n .replace(/\\n{3,}/g, '\\n\\n');\n}\n\n/**\n * Generate SHA-256 hash of normalized content for deduplication\n */\nexport function hashContent(content: string): string {\n const normalized = normalizeContent(content);\n return createHash('sha256').update(normalized, 'utf8').digest('hex');\n}\n\n/**\n * Normalize tags\n */\nexport function normalizeTags(tags: string[]): string[] {\n const normalized = tags\n .map(tag => tag.toLowerCase().trim())\n .filter(tag => tag.length > 0);\n\n return [...new Set(normalized)];\n}\n\n/**\n * Validate and normalize scope\n */\nexport function normalizeScope(scope?: string): string {\n if (!scope || scope.trim() === '') {\n return 'global';\n }\n return scope.trim().toLowerCase();\n}"],"names":["hashContent","normalizeContent","normalizeScope","normalizeTags","normalizeTitle","title","toLowerCase","trim","replace","content","normalized","createHash","update","digest","tags","map","tag","filter","length","Set","scope"],"mappings":";;;;;;;;;;;QA0BgBA;eAAAA;;QAXAC;eAAAA;;QA8BAC;eAAAA;;QAXAC;eAAAA;;QA7BAC;eAAAA;;;wBALW;AAKpB,SAASA,eAAeC,KAAa;IACxC,OAAOA,MACFC,WAAW,GACXC,IAAI,GACJC,OAAO,CAAC,QAAQ;AACzB;AAKO,SAASP,iBAAiBQ,OAAe;IAC5C,OAAOA,QACFF,IAAI,GACJC,OAAO,CAAC,SAAS,MACjBA,OAAO,CAAC,OAAO,MACfA,OAAO,CAAC,WAAW;AAC5B;AAKO,SAASR,YAAYS,OAAe;IACvC,MAAMC,aAAaT,iBAAiBQ;IACpC,OAAOE,IAAAA,kBAAU,EAAC,UAAUC,MAAM,CAACF,YAAY,QAAQG,MAAM,CAAC;AAClE;AAKO,SAASV,cAAcW,IAAc;IACxC,MAAMJ,aAAaI,KACdC,GAAG,CAACC,CAAAA,MAAOA,IAAIV,WAAW,GAAGC,IAAI,IACjCU,MAAM,CAACD,CAAAA,MAAOA,IAAIE,MAAM,GAAG;IAEhC,OAAO;WAAI,IAAIC,IAAIT;KAAY;AACnC;AAKO,SAASR,eAAekB,KAAc;IACzC,IAAI,CAACA,SAASA,MAAMb,IAAI,OAAO,IAAI;QAC/B,OAAO;IACX;IACA,OAAOa,MAAMb,IAAI,GAAGD,WAAW;AACnC"}
1
+ {"version":3,"sources":["../../src/services/normalizer.ts"],"sourcesContent":["import { createHash } from 'crypto';\n\n/**\n * Normalize title for deduplication\n */\nexport function normalizeTitle(title: string): string {\n return title\n .toLowerCase()\n .trim()\n .replace(/\\s+/g, ' ');\n}\n\n/**\n * Normalize content for hashing\n */\nexport function normalizeContent(content: string): string {\n return content\n .trim()\n .replace(/\\r\\n/g, '\\n')\n .replace(/\\r/g, '\\n')\n .replace(/\\n{3,}/g, '\\n\\n');\n}\n\n/**\n * Generate SHA-256 hash of normalized content for deduplication\n */\nexport function hashContent(content: string): string {\n const normalized = normalizeContent(content);\n return createHash('sha256').update(normalized, 'utf8').digest('hex');\n}\n\n/**\n * Normalize tags\n */\nexport function normalizeTags(tags: string[]): string[] {\n const normalized = tags\n .map(tag => tag.toLowerCase().trim())\n .filter(tag => tag.length > 0);\n\n return [...new Set(normalized)];\n}\n\n/**\n * Validate and normalize scope\n */\nexport function normalizeScope(scope?: string): string {\n if (!scope || scope.trim() === '') {\n return 'global';\n }\n return scope.trim().toLowerCase();\n}"],"names":["createHash","normalizeTitle","title","toLowerCase","trim","replace","normalizeContent","content","hashContent","normalized","update","digest","normalizeTags","tags","map","tag","filter","length","Set","normalizeScope","scope"],"mappings":"AAAA,SAASA,UAAU,QAAQ,SAAS;AAEpC;;CAEC,GACD,OAAO,SAASC,eAAeC,KAAa;IACxC,OAAOA,MACFC,WAAW,GACXC,IAAI,GACJC,OAAO,CAAC,QAAQ;AACzB;AAEA;;CAEC,GACD,OAAO,SAASC,iBAAiBC,OAAe;IAC5C,OAAOA,QACFH,IAAI,GACJC,OAAO,CAAC,SAAS,MACjBA,OAAO,CAAC,OAAO,MACfA,OAAO,CAAC,WAAW;AAC5B;AAEA;;CAEC,GACD,OAAO,SAASG,YAAYD,OAAe;IACvC,MAAME,aAAaH,iBAAiBC;IACpC,OAAOP,WAAW,UAAUU,MAAM,CAACD,YAAY,QAAQE,MAAM,CAAC;AAClE;AAEA;;CAEC,GACD,OAAO,SAASC,cAAcC,IAAc;IACxC,MAAMJ,aAAaI,KACdC,GAAG,CAACC,CAAAA,MAAOA,IAAIZ,WAAW,GAAGC,IAAI,IACjCY,MAAM,CAACD,CAAAA,MAAOA,IAAIE,MAAM,GAAG;IAEhC,OAAO;WAAI,IAAIC,IAAIT;KAAY;AACnC;AAEA;;CAEC,GACD,OAAO,SAASU,eAAeC,KAAc;IACzC,IAAI,CAACA,SAASA,MAAMhB,IAAI,OAAO,IAAI;QAC/B,OAAO;IACX;IACA,OAAOgB,MAAMhB,IAAI,GAAGD,WAAW;AACnC"}
@@ -1,4 +1,4 @@
1
- import type { SearchResultItem } from '../types';
1
+ import type { SearchResultItem } from '../types/index.js';
2
2
  interface RawSearchResult {
3
3
  id: string;
4
4
  title: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ranker.d.ts","sourceRoot":"","sources":["../../src/services/ranker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD,UAAU,eAAe;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,cAAc;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAwCD;;;;GAIG;AACH,wBAAgB,WAAW,CACvB,OAAO,EAAE,eAAe,EAAE,EAC1B,OAAO,EAAE,cAAc,GACxB,gBAAgB,EAAE,CAgCpB"}
1
+ {"version":3,"file":"ranker.d.ts","sourceRoot":"","sources":["../../src/services/ranker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,UAAU,eAAe;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,cAAc;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAwCD;;;;GAIG;AACH,wBAAgB,WAAW,CACvB,OAAO,EAAE,eAAe,EAAE,EAC1B,OAAO,EAAE,cAAc,GACxB,gBAAgB,EAAE,CAgCpB"}
@@ -1,13 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "rankResults", {
6
- enumerable: true,
7
- get: function() {
8
- return rankResults;
9
- }
10
- });
11
1
  /**
12
2
  * Calculate tag boost based on matching contextTags
13
3
  * +10% per matching tag
@@ -39,7 +29,11 @@ Object.defineProperty(exports, "rankResults", {
39
29
  }
40
30
  return 0;
41
31
  }
42
- function rankResults(results, context) {
32
+ /**
33
+ * Apply ranking formula to search results
34
+ *
35
+ * Formula: final_score = bm25_score × tag_boost + scope_boost
36
+ */ export function rankResults(results, context) {
43
37
  const ranked = results.map((result)=>{
44
38
  let tags;
45
39
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/ranker.ts"],"sourcesContent":["import type { SearchResultItem } from '../types';\n\ninterface RawSearchResult {\n id: string;\n title: string;\n content: string;\n tags: string;\n scope: string;\n bm25_score: number;\n}\n\ninterface RankingContext {\n contextTags?: string[];\n queryScope?: string | null;\n}\n\n/**\n * Calculate tag boost based on matching contextTags\n * +10% per matching tag\n */\nfunction calculateTagBoost(itemTags: string[], contextTags: string[]): number {\n if (!contextTags || contextTags.length === 0) {\n return 1.0;\n }\n\n const itemTagsLower = itemTags.map(t => t.toLowerCase());\n const contextTagsLower = contextTags.map(t => t.toLowerCase());\n\n let matchCount = 0;\n for (const tag of contextTagsLower) {\n if (itemTagsLower.includes(tag)) {\n matchCount++;\n }\n }\n\n return 1 + (matchCount * 0.1);\n}\n\n/**\n * Calculate scope boost\n * +0.5 if scope matches query scope\n * +0.2 if global\n * 0 otherwise\n */\nfunction calculateScopeBoost(itemScope: string, queryScope?: string | null): number {\n if (queryScope && itemScope === queryScope) {\n return 0.5;\n }\n if (itemScope === 'global') {\n return 0.2;\n }\n return 0;\n}\n\n/**\n * Apply ranking formula to search results\n * \n * Formula: final_score = bm25_score × tag_boost + scope_boost\n */\nexport function rankResults(\n results: RawSearchResult[],\n context: RankingContext\n): SearchResultItem[] {\n const ranked = results.map(result => {\n let tags: string[];\n try {\n tags = JSON.parse(result.tags) as string[];\n } catch {\n tags = [];\n }\n\n const tagBoost = calculateTagBoost(tags, context.contextTags ?? []);\n const scopeBoost = calculateScopeBoost(result.scope, context.queryScope);\n\n // BM25 returns negative values (closer to 0 = better match)\n // We negate it to make higher values better\n const normalizedBm25 = -result.bm25_score;\n\n const finalScore = (normalizedBm25 * tagBoost) + scopeBoost;\n\n return {\n id: result.id,\n title: result.title,\n content: result.content,\n tags,\n scope: result.scope,\n score: Math.round(finalScore * 1000) / 1000,\n };\n });\n\n // Sort by score descending\n ranked.sort((a, b) => b.score - a.score);\n\n return ranked;\n}\n"],"names":["rankResults","calculateTagBoost","itemTags","contextTags","length","itemTagsLower","map","t","toLowerCase","contextTagsLower","matchCount","tag","includes","calculateScopeBoost","itemScope","queryScope","results","context","ranked","result","tags","JSON","parse","tagBoost","scopeBoost","scope","normalizedBm25","bm25_score","finalScore","id","title","content","score","Math","round","sort","a","b"],"mappings":";;;;+BA2DgBA;;;eAAAA;;;AA3ChB;;;CAGC,GACD,SAASC,kBAAkBC,QAAkB,EAAEC,WAAqB;IAChE,IAAI,CAACA,eAAeA,YAAYC,MAAM,KAAK,GAAG;QAC1C,OAAO;IACX;IAEA,MAAMC,gBAAgBH,SAASI,GAAG,CAACC,CAAAA,IAAKA,EAAEC,WAAW;IACrD,MAAMC,mBAAmBN,YAAYG,GAAG,CAACC,CAAAA,IAAKA,EAAEC,WAAW;IAE3D,IAAIE,aAAa;IACjB,KAAK,MAAMC,OAAOF,iBAAkB;QAChC,IAAIJ,cAAcO,QAAQ,CAACD,MAAM;YAC7BD;QACJ;IACJ;IAEA,OAAO,IAAKA,aAAa;AAC7B;AAEA;;;;;CAKC,GACD,SAASG,oBAAoBC,SAAiB,EAAEC,UAA0B;IACtE,IAAIA,cAAcD,cAAcC,YAAY;QACxC,OAAO;IACX;IACA,IAAID,cAAc,UAAU;QACxB,OAAO;IACX;IACA,OAAO;AACX;AAOO,SAASd,YACZgB,OAA0B,EAC1BC,OAAuB;IAEvB,MAAMC,SAASF,QAAQV,GAAG,CAACa,CAAAA;QACvB,IAAIC;QACJ,IAAI;YACAA,OAAOC,KAAKC,KAAK,CAACH,OAAOC,IAAI;QACjC,EAAE,OAAM;YACJA,OAAO,EAAE;QACb;QAEA,MAAMG,WAAWtB,kBAAkBmB,MAAMH,QAAQd,WAAW,IAAI,EAAE;QAClE,MAAMqB,aAAaX,oBAAoBM,OAAOM,KAAK,EAAER,QAAQF,UAAU;QAEvE,4DAA4D;QAC5D,4CAA4C;QAC5C,MAAMW,iBAAiB,CAACP,OAAOQ,UAAU;QAEzC,MAAMC,aAAa,AAACF,iBAAiBH,WAAYC;QAEjD,OAAO;YACHK,IAAIV,OAAOU,EAAE;YACbC,OAAOX,OAAOW,KAAK;YACnBC,SAASZ,OAAOY,OAAO;YACvBX;YACAK,OAAON,OAAOM,KAAK;YACnBO,OAAOC,KAAKC,KAAK,CAACN,aAAa,QAAQ;QAC3C;IACJ;IAEA,2BAA2B;IAC3BV,OAAOiB,IAAI,CAAC,CAACC,GAAGC,IAAMA,EAAEL,KAAK,GAAGI,EAAEJ,KAAK;IAEvC,OAAOd;AACX"}
1
+ {"version":3,"sources":["../../src/services/ranker.ts"],"sourcesContent":["import type { SearchResultItem } from '../types/index.js';\n\ninterface RawSearchResult {\n id: string;\n title: string;\n content: string;\n tags: string;\n scope: string;\n bm25_score: number;\n}\n\ninterface RankingContext {\n contextTags?: string[];\n queryScope?: string | null;\n}\n\n/**\n * Calculate tag boost based on matching contextTags\n * +10% per matching tag\n */\nfunction calculateTagBoost(itemTags: string[], contextTags: string[]): number {\n if (!contextTags || contextTags.length === 0) {\n return 1.0;\n }\n\n const itemTagsLower = itemTags.map(t => t.toLowerCase());\n const contextTagsLower = contextTags.map(t => t.toLowerCase());\n\n let matchCount = 0;\n for (const tag of contextTagsLower) {\n if (itemTagsLower.includes(tag)) {\n matchCount++;\n }\n }\n\n return 1 + (matchCount * 0.1);\n}\n\n/**\n * Calculate scope boost\n * +0.5 if scope matches query scope\n * +0.2 if global\n * 0 otherwise\n */\nfunction calculateScopeBoost(itemScope: string, queryScope?: string | null): number {\n if (queryScope && itemScope === queryScope) {\n return 0.5;\n }\n if (itemScope === 'global') {\n return 0.2;\n }\n return 0;\n}\n\n/**\n * Apply ranking formula to search results\n * \n * Formula: final_score = bm25_score × tag_boost + scope_boost\n */\nexport function rankResults(\n results: RawSearchResult[],\n context: RankingContext\n): SearchResultItem[] {\n const ranked = results.map(result => {\n let tags: string[];\n try {\n tags = JSON.parse(result.tags) as string[];\n } catch {\n tags = [];\n }\n\n const tagBoost = calculateTagBoost(tags, context.contextTags ?? []);\n const scopeBoost = calculateScopeBoost(result.scope, context.queryScope);\n\n // BM25 returns negative values (closer to 0 = better match)\n // We negate it to make higher values better\n const normalizedBm25 = -result.bm25_score;\n\n const finalScore = (normalizedBm25 * tagBoost) + scopeBoost;\n\n return {\n id: result.id,\n title: result.title,\n content: result.content,\n tags,\n scope: result.scope,\n score: Math.round(finalScore * 1000) / 1000,\n };\n });\n\n // Sort by score descending\n ranked.sort((a, b) => b.score - a.score);\n\n return ranked;\n}\n"],"names":["calculateTagBoost","itemTags","contextTags","length","itemTagsLower","map","t","toLowerCase","contextTagsLower","matchCount","tag","includes","calculateScopeBoost","itemScope","queryScope","rankResults","results","context","ranked","result","tags","JSON","parse","tagBoost","scopeBoost","scope","normalizedBm25","bm25_score","finalScore","id","title","content","score","Math","round","sort","a","b"],"mappings":"AAgBA;;;CAGC,GACD,SAASA,kBAAkBC,QAAkB,EAAEC,WAAqB;IAChE,IAAI,CAACA,eAAeA,YAAYC,MAAM,KAAK,GAAG;QAC1C,OAAO;IACX;IAEA,MAAMC,gBAAgBH,SAASI,GAAG,CAACC,CAAAA,IAAKA,EAAEC,WAAW;IACrD,MAAMC,mBAAmBN,YAAYG,GAAG,CAACC,CAAAA,IAAKA,EAAEC,WAAW;IAE3D,IAAIE,aAAa;IACjB,KAAK,MAAMC,OAAOF,iBAAkB;QAChC,IAAIJ,cAAcO,QAAQ,CAACD,MAAM;YAC7BD;QACJ;IACJ;IAEA,OAAO,IAAKA,aAAa;AAC7B;AAEA;;;;;CAKC,GACD,SAASG,oBAAoBC,SAAiB,EAAEC,UAA0B;IACtE,IAAIA,cAAcD,cAAcC,YAAY;QACxC,OAAO;IACX;IACA,IAAID,cAAc,UAAU;QACxB,OAAO;IACX;IACA,OAAO;AACX;AAEA;;;;CAIC,GACD,OAAO,SAASE,YACZC,OAA0B,EAC1BC,OAAuB;IAEvB,MAAMC,SAASF,QAAQX,GAAG,CAACc,CAAAA;QACvB,IAAIC;QACJ,IAAI;YACAA,OAAOC,KAAKC,KAAK,CAACH,OAAOC,IAAI;QACjC,EAAE,OAAM;YACJA,OAAO,EAAE;QACb;QAEA,MAAMG,WAAWvB,kBAAkBoB,MAAMH,QAAQf,WAAW,IAAI,EAAE;QAClE,MAAMsB,aAAaZ,oBAAoBO,OAAOM,KAAK,EAAER,QAAQH,UAAU;QAEvE,4DAA4D;QAC5D,4CAA4C;QAC5C,MAAMY,iBAAiB,CAACP,OAAOQ,UAAU;QAEzC,MAAMC,aAAa,AAACF,iBAAiBH,WAAYC;QAEjD,OAAO;YACHK,IAAIV,OAAOU,EAAE;YACbC,OAAOX,OAAOW,KAAK;YACnBC,SAASZ,OAAOY,OAAO;YACvBX;YACAK,OAAON,OAAOM,KAAK;YACnBO,OAAOC,KAAKC,KAAK,CAACN,aAAa,QAAQ;QAC3C;IACJ;IAEA,2BAA2B;IAC3BV,OAAOiB,IAAI,CAAC,CAACC,GAAGC,IAAMA,EAAEL,KAAK,GAAGI,EAAEJ,KAAK;IAEvC,OAAOd;AACX"}