@levalicious/server-memory 0.0.2 → 0.0.3

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 (2) hide show
  1. package/dist/index.js +168 -104
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -15,6 +15,8 @@ const MEMORY_FILE_PATH = process.env.MEMORY_FILE_PATH
15
15
  : defaultMemoryPath;
16
16
  // The KnowledgeGraphManager class contains all operations to interact with the knowledge graph
17
17
  class KnowledgeGraphManager {
18
+ bclCtr = 0;
19
+ bclTerm = "";
18
20
  async loadGraph() {
19
21
  try {
20
22
  const data = await fs.readFile(MEMORY_FILE_PATH, "utf-8");
@@ -243,126 +245,161 @@ class KnowledgeGraphManager {
243
245
  }
244
246
  // BCL (Binary Combinatory Logic) evaluator
245
247
  async evaluateBCL(program, maxSteps) {
246
- let current = program;
247
248
  let stepCount = 0;
248
- // Find and apply one reduction rule to the leftmost applicable position
249
- const applyOneRule = (term) => {
250
- // Scan left-to-right for rule applications
251
- for (let pos = 0; pos <= term.length - 6; pos++) { // minimum pattern "1100xy" needs at least 6 chars
252
- // Rule 1: 1100xy → x
253
- if (pos <= term.length - 6 && term.substring(pos, pos + 4) === '1100') {
254
- let parsePos = pos + 4;
255
- // Parse x
256
- const xResult = this.parseBCLTerm(term, parsePos);
257
- if (xResult.success) {
258
- parsePos = xResult.nextPos;
259
- // Parse y
260
- const yResult = this.parseBCLTerm(term, parsePos);
261
- if (yResult.success) {
262
- // Apply Rule 1: 1100xy → x
263
- const before = term.substring(0, pos);
264
- const after = term.substring(yResult.nextPos);
265
- const newTerm = before + xResult.term + after;
266
- return {
267
- newTerm,
268
- applied: true,
269
- rule: `Rule 1: 1100${xResult.term}${yResult.term} → ${xResult.term}`
270
- };
271
- }
272
- }
249
+ let max_size = program.length;
250
+ let mode = 0;
251
+ let ctr = 1;
252
+ let t0 = program;
253
+ let t1 = '';
254
+ let t2 = '';
255
+ let t3 = '';
256
+ let t4 = '';
257
+ while (stepCount < maxSteps) {
258
+ if (t0.length == 0)
259
+ break;
260
+ let b = t0[0];
261
+ t0 = t0.slice(1);
262
+ if (mode === 0) {
263
+ t1 += b;
264
+ let size = t1.length + t0.length;
265
+ if (size > max_size)
266
+ max_size = size;
267
+ if (t1.slice(-4) === '1100') {
268
+ mode = 1;
269
+ t1 = t1.slice(0, -4);
273
270
  }
274
- // Rule 2: 11101xyz → 11xz1yz (need minimum 8 chars)
275
- if (pos <= term.length - 8 && term.substring(pos, pos + 5) === '11101') {
276
- let parsePos = pos + 5;
277
- // Parse x
278
- const xResult = this.parseBCLTerm(term, parsePos);
279
- if (xResult.success) {
280
- parsePos = xResult.nextPos;
281
- // Parse y
282
- const yResult = this.parseBCLTerm(term, parsePos);
283
- if (yResult.success) {
284
- parsePos = yResult.nextPos;
285
- // Parse z
286
- const zResult = this.parseBCLTerm(term, parsePos);
287
- if (zResult.success) {
288
- // Apply Rule 2: 11101xyz → 11xz1yz
289
- const x = xResult.term;
290
- const y = yResult.term;
291
- const z = zResult.term;
292
- const before = term.substring(0, pos);
293
- const after = term.substring(zResult.nextPos);
294
- const replacement = `11${x}${z}1${y}${z}`;
295
- const newTerm = before + replacement + after;
296
- return {
297
- newTerm,
298
- applied: true,
299
- rule: `Rule 2: 11101${x}${y}${z} → 11${x}${z}1${y}${z}`
300
- };
301
- }
302
- }
303
- }
271
+ else if (t1.slice(-5) === '11101') {
272
+ mode = 3;
273
+ t1 = t1.slice(0, -5);
304
274
  }
305
275
  }
306
- return { newTerm: term, applied: false, rule: '' };
307
- };
308
- // Validate input is a well-formed BCL term
309
- const validation = this.parseBCLTerm(current, 0);
310
- if (!validation.success || validation.nextPos !== current.length) {
311
- return {
312
- result: current,
313
- info: `Error: Invalid BCL term - parse failed at position ${validation.nextPos}`,
314
- halted: false
315
- };
316
- }
317
- let max_size = current.length;
318
- while (stepCount < maxSteps) {
319
- const result = applyOneRule(current);
320
- if (!result.applied) {
321
- // Normal form reached - no more reductions possible
322
- break;
276
+ else if (mode === 1) {
277
+ t2 += b;
278
+ if (b == '1') {
279
+ ctr += 1;
280
+ }
281
+ else if (b == '0') {
282
+ ctr -= 1;
283
+ t2 += t0[0];
284
+ t0 = t0.slice(1);
285
+ }
286
+ if (ctr === 0) {
287
+ mode = 2;
288
+ ctr = 1;
289
+ }
290
+ }
291
+ else if (mode === 2) {
292
+ if (b == '1') {
293
+ ctr += 1;
294
+ }
295
+ else if (b == '0') {
296
+ ctr -= 1;
297
+ t0 = t0.slice(1);
298
+ }
299
+ if (ctr === 0) {
300
+ t0 = t2 + t0;
301
+ t2 = '';
302
+ mode = 0;
303
+ ctr = 1;
304
+ stepCount += 1;
305
+ }
323
306
  }
324
- current = result.newTerm;
325
- if (current.length > max_size) {
326
- max_size = current.length;
307
+ else if (mode === 3) {
308
+ t2 += b;
309
+ if (b == '1') {
310
+ ctr += 1;
311
+ }
312
+ else if (b == '0') {
313
+ ctr -= 1;
314
+ t2 += t0[0];
315
+ t0 = t0.slice(1);
316
+ }
317
+ if (ctr === 0) {
318
+ mode = 4;
319
+ ctr = 1;
320
+ }
321
+ }
322
+ else if (mode === 4) {
323
+ t3 += b;
324
+ if (b == '1') {
325
+ ctr += 1;
326
+ }
327
+ else if (b == '0') {
328
+ ctr -= 1;
329
+ t3 += t0[0];
330
+ t0 = t0.slice(1);
331
+ }
332
+ if (ctr === 0) {
333
+ mode = 5;
334
+ ctr = 1;
335
+ }
336
+ }
337
+ else if (mode === 5) {
338
+ t4 += b;
339
+ if (b == '1') {
340
+ ctr += 1;
341
+ }
342
+ else if (b == '0') {
343
+ ctr -= 1;
344
+ t4 += t0[0];
345
+ t0 = t0.slice(1);
346
+ }
347
+ if (ctr === 0) {
348
+ t0 = '11' + t2 + t4 + '1' + t3 + t4 + t0;
349
+ t2 = '';
350
+ t3 = '';
351
+ t4 = '';
352
+ mode = 0;
353
+ ctr = 1;
354
+ stepCount += 1;
355
+ }
327
356
  }
328
- stepCount++;
329
357
  }
330
358
  const halted = stepCount < maxSteps;
331
359
  return {
332
- result: current,
360
+ result: t1,
333
361
  info: `${stepCount} steps, max size ${max_size}`,
334
- halted
362
+ halted,
363
+ errored: halted && mode != 0,
335
364
  };
336
365
  }
337
- // Helper function to parse a single BCL term from a given position
338
- parseBCLTerm(input, startPos) {
339
- if (startPos >= input.length) {
340
- return { success: false, term: '', nextPos: startPos };
366
+ async addBCLTerm(term) {
367
+ const termset = ["1", "00", "01"];
368
+ if (!term || term.trim() === "") {
369
+ throw new Error("BCL term cannot be empty");
341
370
  }
342
- // Check for 00 (K combinator)
343
- if (startPos + 1 < input.length && input.substring(startPos, startPos + 2) === '00') {
344
- return { success: true, term: '00', nextPos: startPos + 2 };
371
+ // Term can be 1, 00, 01, or K, S, App (application)
372
+ const validTerms = ["1", "App", "00", "K", "01", "S"];
373
+ if (!validTerms.includes(term)) {
374
+ throw new Error(`Invalid BCL term: ${term}\nExpected one of: ${validTerms.join(", ")}`);
345
375
  }
346
- // Check for 01 (S combinator)
347
- if (startPos + 1 < input.length && input.substring(startPos, startPos + 2) === '01') {
348
- return { success: true, term: '01', nextPos: startPos + 2 };
376
+ let processedTerm = 0;
377
+ if (term === "00" || term === "K")
378
+ processedTerm = 1;
379
+ else if (term === "01" || term === "S")
380
+ processedTerm = 2;
381
+ this.bclTerm += termset[processedTerm];
382
+ if (processedTerm === 0) {
383
+ if (this.bclCtr === 0)
384
+ this.bclCtr += 1;
385
+ this.bclCtr += 1;
349
386
  }
350
- // Check for 1 (application)
351
- if (input[startPos] === '1') {
352
- // Parse first subterm
353
- const leftResult = this.parseBCLTerm(input, startPos + 1);
354
- if (!leftResult.success) {
355
- return leftResult;
356
- }
357
- // Parse second subterm
358
- const rightResult = this.parseBCLTerm(input, leftResult.nextPos);
359
- if (!rightResult.success) {
360
- return rightResult;
361
- }
362
- const term = '1' + leftResult.term + rightResult.term;
363
- return { success: true, term, nextPos: rightResult.nextPos };
387
+ else {
388
+ this.bclCtr -= 1;
389
+ }
390
+ if (this.bclCtr <= 0) {
391
+ const constructedProgram = this.bclTerm;
392
+ this.bclCtr = 0;
393
+ this.bclTerm = "";
394
+ return `Constructed Program: ${constructedProgram}`;
395
+ }
396
+ else {
397
+ return `Need ${this.bclCtr} more term(s) to complete the program.`;
364
398
  }
365
- return { success: false, term: '', nextPos: startPos };
399
+ }
400
+ async clearBCLTerm() {
401
+ this.bclCtr = 0;
402
+ this.bclTerm = "";
366
403
  }
367
404
  }
368
405
  const knowledgeGraphManager = new KnowledgeGraphManager();
@@ -651,6 +688,28 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
651
688
  required: ["program"],
652
689
  },
653
690
  },
691
+ {
692
+ name: "add_bcl_term",
693
+ description: "Add a BCL term to the constructor, maintaining valid syntax. Returns completion status.",
694
+ inputSchema: {
695
+ type: "object",
696
+ properties: {
697
+ term: {
698
+ type: "string",
699
+ description: "BCL term to add. Valid values: '1' or 'App' (application), '00' or 'K' (K combinator), '01' or 'S' (S combinator)"
700
+ },
701
+ },
702
+ required: ["term"],
703
+ },
704
+ },
705
+ {
706
+ name: "clear_bcl_term",
707
+ description: "Clear the current BCL term being constructed and reset the constructor state",
708
+ inputSchema: {
709
+ type: "object",
710
+ properties: {},
711
+ },
712
+ },
654
713
  ],
655
714
  };
656
715
  });
@@ -701,6 +760,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
701
760
  return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.validateGraph(), null, 2) }] };
702
761
  case "evaluate_bcl":
703
762
  return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.evaluateBCL(args.program, args.maxSteps), null, 2) }] };
763
+ case "add_bcl_term":
764
+ return { content: [{ type: "text", text: await knowledgeGraphManager.addBCLTerm(args.term) }] };
765
+ case "clear_bcl_term":
766
+ await knowledgeGraphManager.clearBCLTerm();
767
+ return { content: [{ type: "text", text: "BCL term constructor cleared successfully" }] };
704
768
  default:
705
769
  throw new Error(`Unknown tool: ${name}`);
706
770
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@levalicious/server-memory",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "MCP server for enabling memory for Claude through a knowledge graph",
5
5
  "license": "MIT",
6
6
  "author": "Levalicious",
@@ -19,7 +19,7 @@
19
19
  "watch": "tsc --watch"
20
20
  },
21
21
  "dependencies": {
22
- "@modelcontextprotocol/sdk": "1.16.0"
22
+ "@modelcontextprotocol/sdk": "1.21.0"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/node": "^24",