@vheins/local-memory-mcp 0.19.10 → 0.19.12

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.
@@ -1914,6 +1914,14 @@ var TaskEntity = class extends BaseEntity {
1914
1914
  }
1915
1915
  }
1916
1916
  const rows = this.all(query, params);
1917
+ if (rows.length === 0 && owner) {
1918
+ const fallbackQuery = query.replace(/t\.owner\s*=\s*\?\s*AND\s*/i, "");
1919
+ const fallbackParams = params.slice(1);
1920
+ const fallbackRows = this.all(fallbackQuery, fallbackParams);
1921
+ if (fallbackRows.length > 0) {
1922
+ return fallbackRows.map((r) => this.rowToTask(r));
1923
+ }
1924
+ }
1917
1925
  return rows.map((r) => this.rowToTask(r));
1918
1926
  }
1919
1927
  countTasks(owner, repo, status, search) {
@@ -1994,6 +2002,14 @@ var TaskEntity = class extends BaseEntity {
1994
2002
  }
1995
2003
  }
1996
2004
  const rows = this.all(query, params);
2005
+ if (rows.length === 0 && owner) {
2006
+ const fallbackQuery = query.replace(/t\.owner\s*=\s*\?\s*AND\s*/i, "");
2007
+ const fallbackParams = params.slice(1);
2008
+ const fallbackRows = this.all(fallbackQuery, fallbackParams);
2009
+ if (fallbackRows.length > 0) {
2010
+ return fallbackRows.map((r) => this.rowToTask(r));
2011
+ }
2012
+ }
1997
2013
  return rows.map((r) => this.rowToTask(r));
1998
2014
  }
1999
2015
  countTasksByMultipleStatuses(owner, repo, statuses, search) {
@@ -3447,6 +3463,7 @@ var RealVectorStore = class {
3447
3463
  };
3448
3464
 
3449
3465
  // src/mcp/session.ts
3466
+ import fs4 from "fs";
3450
3467
  import path3 from "path";
3451
3468
  import { fileURLToPath } from "url";
3452
3469
  function createSessionContext() {
@@ -3505,8 +3522,31 @@ function inferRepoFromSession(session) {
3505
3522
  }
3506
3523
  return void 0;
3507
3524
  }
3525
+ function inferOwnerFromGit(cwd) {
3526
+ try {
3527
+ const gitConfigPath = path3.join(cwd, ".git", "config");
3528
+ if (!fs4.existsSync(gitConfigPath)) return void 0;
3529
+ const content = fs4.readFileSync(gitConfigPath, "utf-8");
3530
+ const match = content.match(
3531
+ /url\s*=\s*(?:git@github\.com:|https?:\/\/github\.com\/|git:\/\/github\.com\/)([^\/\s]+)/
3532
+ );
3533
+ return match?.[1] || void 0;
3534
+ } catch {
3535
+ return void 0;
3536
+ }
3537
+ }
3508
3538
  function inferOwnerFromSession(session) {
3509
3539
  const roots = getFilesystemRoots(session);
3540
+ let cwd;
3541
+ if (roots.length === 1) {
3542
+ cwd = roots[0];
3543
+ } else if (roots.length === 0 && session) {
3544
+ cwd = process.cwd();
3545
+ }
3546
+ if (cwd) {
3547
+ const gitOwner = inferOwnerFromGit(cwd);
3548
+ if (gitOwner) return gitOwner;
3549
+ }
3510
3550
  if (roots.length === 1) {
3511
3551
  const parts = roots[0].split(path3.sep).filter(Boolean);
3512
3552
  if (parts.length >= 2) {
@@ -3515,8 +3555,8 @@ function inferOwnerFromSession(session) {
3515
3555
  }
3516
3556
  if (roots.length === 0) {
3517
3557
  if (!session) return void 0;
3518
- const cwd = process.cwd();
3519
- const parts = cwd.split(path3.sep).filter(Boolean);
3558
+ const workdir = process.cwd();
3559
+ const parts = workdir.split(path3.sep).filter(Boolean);
3520
3560
  if (parts.length >= 2) {
3521
3561
  return parts[parts.length - 2];
3522
3562
  }
@@ -3525,7 +3565,7 @@ function inferOwnerFromSession(session) {
3525
3565
  }
3526
3566
 
3527
3567
  // src/mcp/prompts/loader.ts
3528
- import fs4 from "fs";
3568
+ import fs5 from "fs";
3529
3569
  import path4 from "path";
3530
3570
  import { fileURLToPath as fileURLToPath2 } from "url";
3531
3571
  import matter from "gray-matter";
@@ -3541,8 +3581,8 @@ function findPromptDir() {
3541
3581
  "./definitions"
3542
3582
  ].map((relPath) => path4.resolve(__dirname, relPath));
3543
3583
  for (const dir of candidates) {
3544
- if (fs4.existsSync(dir)) {
3545
- const files = fs4.readdirSync(dir);
3584
+ if (fs5.existsSync(dir)) {
3585
+ const files = fs5.readdirSync(dir);
3546
3586
  if (files.some((f) => f.endsWith(".md"))) {
3547
3587
  return dir;
3548
3588
  }
@@ -3553,17 +3593,17 @@ function findPromptDir() {
3553
3593
  var PROMPT_DIR = findPromptDir();
3554
3594
  var promptCache = /* @__PURE__ */ new Map();
3555
3595
  function listPromptFiles() {
3556
- if (!fs4.existsSync(PROMPT_DIR)) return [];
3557
- return fs4.readdirSync(PROMPT_DIR).filter((file) => file.endsWith(".md")).map((file) => file.replace(/\.md$/, "")).sort();
3596
+ if (!fs5.existsSync(PROMPT_DIR)) return [];
3597
+ return fs5.readdirSync(PROMPT_DIR).filter((file) => file.endsWith(".md")).map((file) => file.replace(/\.md$/, "")).sort();
3558
3598
  }
3559
3599
  function loadPromptFromMarkdown(name) {
3560
3600
  const cached = promptCache.get(name);
3561
3601
  if (cached) return cached;
3562
3602
  const filePath = path4.join(PROMPT_DIR, `${name}.md`);
3563
- if (!fs4.existsSync(filePath)) {
3603
+ if (!fs5.existsSync(filePath)) {
3564
3604
  throw new Error(`Prompt file not found: ${filePath}`);
3565
3605
  }
3566
- const fileContent = fs4.readFileSync(filePath, "utf-8");
3606
+ const fileContent = fs5.readFileSync(filePath, "utf-8");
3567
3607
  const { data, content } = matter(fileContent);
3568
3608
  const result = {
3569
3609
  name: data.name || name,
@@ -3585,9 +3625,9 @@ function findServerInstructionsDir() {
3585
3625
  "./server"
3586
3626
  ].map((relPath) => path4.resolve(__dirname, relPath));
3587
3627
  for (const dir of candidates) {
3588
- if (fs4.existsSync(dir)) {
3628
+ if (fs5.existsSync(dir)) {
3589
3629
  const filePath = path4.join(dir, "instructions.md");
3590
- if (fs4.existsSync(filePath)) {
3630
+ if (fs5.existsSync(filePath)) {
3591
3631
  return dir;
3592
3632
  }
3593
3633
  }
@@ -3599,10 +3639,10 @@ var serverInstructionsCache = null;
3599
3639
  function loadServerInstructions() {
3600
3640
  if (serverInstructionsCache !== null) return serverInstructionsCache;
3601
3641
  const filePath = path4.join(SERVER_DIR, "instructions.md");
3602
- if (!fs4.existsSync(filePath)) {
3642
+ if (!fs5.existsSync(filePath)) {
3603
3643
  throw new Error(`Server instructions file not found: ${filePath}`);
3604
3644
  }
3605
- const fileContent = fs4.readFileSync(filePath, "utf-8");
3645
+ const fileContent = fs5.readFileSync(filePath, "utf-8");
3606
3646
  const { content } = matter(fileContent);
3607
3647
  serverInstructionsCache = content.trim();
3608
3648
  return serverInstructionsCache;
@@ -3718,7 +3758,7 @@ var MEMORY_TOOL_DEFINITIONS = [
3718
3758
  title: {
3719
3759
  type: "string",
3720
3760
  minLength: 3,
3721
- maxLength: 100,
3761
+ maxLength: 255,
3722
3762
  description: "Short human-readable title for the memory. Do not embed bracketed metadata like agent/role/date prefixes here."
3723
3763
  },
3724
3764
  content: {
@@ -3738,6 +3778,7 @@ var MEMORY_TOOL_DEFINITIONS = [
3738
3778
  },
3739
3779
  role: {
3740
3780
  type: "string",
3781
+ default: "unknown",
3741
3782
  description: "Role of the agent creating this memory"
3742
3783
  },
3743
3784
  model: {
@@ -3765,7 +3806,11 @@ var MEMORY_TOOL_DEFINITIONS = [
3765
3806
  type: "object",
3766
3807
  description: "Structured metadata for non-title context such as source agent, claim fields, or timestamps"
3767
3808
  },
3768
- is_global: { type: "boolean", description: "If true, this memory is shared across all repositories" },
3809
+ is_global: {
3810
+ type: "boolean",
3811
+ default: false,
3812
+ description: "If true, this memory is shared across all repositories"
3813
+ },
3769
3814
  ttlDays: {
3770
3815
  type: "number",
3771
3816
  minimum: 1,
@@ -3796,7 +3841,7 @@ var MEMORY_TOOL_DEFINITIONS = [
3796
3841
  enum: ["code_fact", "decision", "mistake", "pattern", "task_archive"],
3797
3842
  description: "Type of durable knowledge being stored"
3798
3843
  },
3799
- title: { type: "string", minLength: 3, maxLength: 100, description: "Short human-readable title" },
3844
+ title: { type: "string", minLength: 3, maxLength: 255, description: "Short human-readable title" },
3800
3845
  content: { type: "string", minLength: 10, description: "The memory content" },
3801
3846
  importance: { type: "number", minimum: 1, maximum: 5, description: "Importance score (1-5)" },
3802
3847
  agent: { type: "string", description: "Name of the agent creating this memory" },
@@ -6628,14 +6673,14 @@ var StructuredDataSchema = z2.unknown().refine(isJsonSerializable, { message: "V
6628
6673
  import { z as z3 } from "zod";
6629
6674
  var MemoryStoreSchema = z3.object({
6630
6675
  code: z3.string().max(20).optional(),
6631
- type: MemoryTypeSchema.optional(),
6632
- title: z3.string().min(3).max(255).optional(),
6633
- content: z3.string().min(10).optional(),
6634
- importance: z3.number().min(1).max(5).optional(),
6635
- agent: z3.string().min(1).optional(),
6676
+ type: MemoryTypeSchema,
6677
+ title: z3.string().min(3).max(255),
6678
+ content: z3.string().min(10),
6679
+ importance: z3.number().min(1).max(5),
6680
+ agent: z3.string().min(1),
6636
6681
  role: z3.string().optional().default("unknown"),
6637
- model: z3.string().min(1).optional(),
6638
- scope: MemoryScopeSchema.optional(),
6682
+ model: z3.string().min(1),
6683
+ scope: MemoryScopeSchema,
6639
6684
  ttlDays: z3.number().min(1).optional(),
6640
6685
  supersedes: z3.string().optional(),
6641
6686
  tags: z3.array(z3.string()).optional(),
@@ -6643,15 +6688,7 @@ var MemoryStoreSchema = z3.object({
6643
6688
  is_global: z3.boolean().default(false),
6644
6689
  structured: z3.boolean().default(false),
6645
6690
  memories: z3.array(SingleMemorySchema).min(1).optional()
6646
- }).refine(
6647
- (data) => {
6648
- if (data.memories) return true;
6649
- return !!(data.type && data.title && data.content && data.importance && data.agent && data.model && data.scope);
6650
- },
6651
- {
6652
- message: "Either 'memories' array or single memory fields (type, title, content, importance, agent, model, scope) must be provided"
6653
- }
6654
- );
6691
+ });
6655
6692
  var MemoryUpdateSchema = z3.object({
6656
6693
  id: z3.string().uuid().optional(),
6657
6694
  code: z3.string().max(20).optional(),
@@ -15,7 +15,7 @@ import {
15
15
  handleTaskClaim,
16
16
  listResources,
17
17
  logger
18
- } from "../chunk-QOGYLJYW.js";
18
+ } from "../chunk-H7BLOZB6.js";
19
19
 
20
20
  // src/dashboard/server.ts
21
21
  import express from "express";
@@ -61,7 +61,7 @@ import {
61
61
  parseRepoInput,
62
62
  rankCompletionValues,
63
63
  toContextSlug
64
- } from "../chunk-QOGYLJYW.js";
64
+ } from "../chunk-H7BLOZB6.js";
65
65
 
66
66
  // src/mcp/server.ts
67
67
  import { serveStdio } from "@modelcontextprotocol/server/stdio";
@@ -74,8 +74,8 @@ import path from "path";
74
74
  import { fileURLToPath } from "url";
75
75
  var __dirname = path.dirname(fileURLToPath(import.meta.url));
76
76
  var pkgVersion = "0.1.0";
77
- if ("0.19.10") {
78
- pkgVersion = "0.19.10";
77
+ if ("0.19.12") {
78
+ pkgVersion = "0.19.12";
79
79
  } else {
80
80
  let searchDir = __dirname;
81
81
  for (let i = 0; i < 5; i++) {
@@ -3547,9 +3547,11 @@ function validateRootBoundPath(value, field, session) {
3547
3547
  }
3548
3548
  function normalizeToolArgs(args, session) {
3549
3549
  const anyArgs = args;
3550
+ const scopeVal = anyArgs.scope;
3550
3551
  const nextArgs = {
3551
3552
  ...anyArgs,
3552
- scope: anyArgs.scope ? { ...anyArgs.scope } : void 0
3553
+ // Handle string scope gracefully: "my-repo" { repo: "my-repo" }
3554
+ scope: typeof scopeVal === "string" ? { repo: scopeVal } : scopeVal ? { ...scopeVal } : void 0
3553
3555
  };
3554
3556
  validateRootBoundPath(nextArgs.current_file_path, "current_file_path", session);
3555
3557
  validateRootBoundPath(nextArgs.doc_path, "doc_path", session);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vheins/local-memory-mcp",
3
- "version": "0.19.10",
3
+ "version": "0.19.12",
4
4
  "description": "MCP Local Memory Service for coding copilot agents",
5
5
  "mcpName": "io.github.vheins/local-memory-mcp",
6
6
  "type": "module",