@vheins/local-memory-mcp 0.19.17 → 0.19.18

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/mcp/server.js +41 -25
  2. package/package.json +1 -1
@@ -75,8 +75,8 @@ import path from "path";
75
75
  import { fileURLToPath } from "url";
76
76
  var __dirname = path.dirname(fileURLToPath(import.meta.url));
77
77
  var pkgVersion = "0.1.0";
78
- if ("0.19.17") {
79
- pkgVersion = "0.19.17";
78
+ if ("0.19.18") {
79
+ pkgVersion = "0.19.18";
80
80
  } else {
81
81
  let searchDir = __dirname;
82
82
  for (let i = 0; i < 5; i++) {
@@ -123,6 +123,7 @@ import { z } from "zod";
123
123
  import { randomUUID as randomUUID2 } from "crypto";
124
124
 
125
125
  // src/mcp/utils/code-generator.ts
126
+ import { randomBytes } from "crypto";
126
127
  var ENTITY_CONFIG = {
127
128
  task: { prefix: "TASK", table: "tasks", column: "task_code" },
128
129
  memory: { prefix: "MEM", table: "memories", column: "code" },
@@ -152,6 +153,38 @@ function generateNextCode(owner, repo, entityType, storage, batchCodes) {
152
153
  }
153
154
  return `${config.prefix}-${String(nextSeq).padStart(3, "0")}`;
154
155
  }
156
+ function resolveEntityCode(preferredCode, owner, repo, entityType, storage, options) {
157
+ const { batchCodes } = options ?? {};
158
+ if (!preferredCode) {
159
+ const code = generateNextCode(owner, repo, entityType, storage, batchCodes);
160
+ if (batchCodes) batchCodes.add(code);
161
+ return code;
162
+ }
163
+ const isTaken = (code) => {
164
+ if (batchCodes?.has(code)) return true;
165
+ switch (entityType) {
166
+ case "task":
167
+ return storage.tasks.isTaskCodeDuplicate(owner, repo, code);
168
+ case "memory":
169
+ return storage.memories.getByCode(code, owner, repo) !== null;
170
+ case "standard":
171
+ return storage.standards.getByCode(code, owner, repo) !== null;
172
+ }
173
+ };
174
+ if (!isTaken(preferredCode)) {
175
+ if (batchCodes) batchCodes.add(preferredCode);
176
+ return preferredCode;
177
+ }
178
+ for (let attempt = 0; attempt < 20; attempt++) {
179
+ const suffix = randomBytes(2).toString("hex");
180
+ const candidate = `${preferredCode}-${suffix}`;
181
+ if (!isTaken(candidate)) {
182
+ if (batchCodes) batchCodes.add(candidate);
183
+ return candidate;
184
+ }
185
+ }
186
+ return generateNextCode(owner, repo, entityType, storage, batchCodes);
187
+ }
155
188
 
156
189
  // src/mcp/tools/kg-archivist.ts
157
190
  import { randomUUID } from "crypto";
@@ -478,7 +511,7 @@ async function storeSingleMemory(params, db2, vectors2) {
478
511
  }
479
512
  const entry = {
480
513
  id: randomUUID2(),
481
- code: params.code || generateNextCode(params.scope.owner ?? "", params.scope.repo, "memory", db2),
514
+ code: resolveEntityCode(params.code, params.scope.owner ?? "", params.scope.repo, "memory", db2),
482
515
  type: params.type,
483
516
  title: params.title,
484
517
  content: params.content,
@@ -578,8 +611,9 @@ async function handleMemoryStore(params, db2, vectors2) {
578
611
  if (mem.scope.language && !tags.includes(mem.scope.language.toLowerCase())) {
579
612
  tags.push(mem.scope.language.toLowerCase());
580
613
  }
581
- const code = mem.code || generateNextCode(mem.scope.owner ?? "", mem.scope.repo, "memory", db2, batchCodes);
582
- batchCodes.add(code);
614
+ const code = resolveEntityCode(mem.code || null, mem.scope.owner ?? "", mem.scope.repo, "memory", db2, {
615
+ batchCodes
616
+ });
583
617
  entries.push({
584
618
  id: randomUUID2(),
585
619
  code,
@@ -2371,14 +2405,6 @@ async function handleTaskCreate(args, storage) {
2371
2405
  const now2 = (/* @__PURE__ */ new Date()).toISOString();
2372
2406
  const codesInRequest = /* @__PURE__ */ new Set();
2373
2407
  const batchCodes = /* @__PURE__ */ new Set();
2374
- for (const taskData of bulkTasks) {
2375
- if (!taskData.task_code) {
2376
- taskData.task_code = generateNextCode(owner ?? "", repo, "task", storage, batchCodes);
2377
- }
2378
- batchCodes.add(taskData.task_code);
2379
- }
2380
- const allCodes = bulkTasks.map((t) => t.task_code);
2381
- const existingCodes = storage.tasks.getExistingTaskCodes(owner, repo, allCodes);
2382
2408
  const initialStats = storage.taskStats.getTaskStats(owner, repo);
2383
2409
  let pendingInRequestCount = 0;
2384
2410
  const localCodeMap = /* @__PURE__ */ new Map();
@@ -2386,15 +2412,10 @@ async function handleTaskCreate(args, storage) {
2386
2412
  localCodeMap.set(taskData.task_code, randomUUID4());
2387
2413
  }
2388
2414
  for (const taskData of bulkTasks) {
2389
- const code = taskData.task_code;
2415
+ const code = resolveEntityCode(taskData.task_code ?? null, owner ?? "", repo, "task", storage, { batchCodes });
2390
2416
  if (codesInRequest.has(code)) {
2391
2417
  throw new Error(`Duplicate task_code in request: '${code}'`);
2392
2418
  }
2393
- if (existingCodes.has(code)) {
2394
- throw new Error(
2395
- `Duplicate task_code: '${code}' already exists in repository '${repo}'. Omit task_code to auto-generate, or use task-list/task-search to find available codes.`
2396
- );
2397
- }
2398
2419
  codesInRequest.add(code);
2399
2420
  let normalizedStatus = taskData.status || "backlog";
2400
2421
  if (normalizedStatus !== "backlog" && normalizedStatus !== "pending") {
@@ -2472,12 +2493,7 @@ async function handleTaskCreate(args, storage) {
2472
2493
  throw new Error("Missing required fields for single task creation (phase, title, description)");
2473
2494
  }
2474
2495
  let effectiveStatus = requestedStatus || "backlog";
2475
- const resolvedCode = task_code || generateNextCode(owner ?? "", repo, "task", storage);
2476
- if (storage.tasks.isTaskCodeDuplicate(owner, repo, resolvedCode)) {
2477
- throw new Error(
2478
- `Duplicate task_code: '${resolvedCode}' already exists in repository '${repo}'. Omit task_code to auto-generate, or use task-list/task-search to find available codes.`
2479
- );
2480
- }
2496
+ const resolvedCode = resolveEntityCode(task_code, owner ?? "", repo, "task", storage);
2481
2497
  if (requestedStatus !== "backlog" && requestedStatus !== "pending" && requestedStatus !== void 0) {
2482
2498
  throw new Error("New tasks must be created with status 'backlog' or 'pending'.");
2483
2499
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vheins/local-memory-mcp",
3
- "version": "0.19.17",
3
+ "version": "0.19.18",
4
4
  "description": "MCP Local Memory Service for coding copilot agents",
5
5
  "mcpName": "io.github.vheins/local-memory-mcp",
6
6
  "type": "module",