@vheins/local-memory-mcp 0.18.0 → 0.18.2
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.
|
@@ -81,8 +81,8 @@ function loadServerInstructions() {
|
|
|
81
81
|
// src/mcp/capabilities.ts
|
|
82
82
|
var __dirname2 = path2.dirname(fileURLToPath2(import.meta.url));
|
|
83
83
|
var pkgVersion = "0.1.0";
|
|
84
|
-
if ("0.18.
|
|
85
|
-
pkgVersion = "0.18.
|
|
84
|
+
if ("0.18.2") {
|
|
85
|
+
pkgVersion = "0.18.2";
|
|
86
86
|
} else {
|
|
87
87
|
let searchDir = __dirname2;
|
|
88
88
|
for (let i = 0; i < 5; i++) {
|
|
@@ -666,6 +666,20 @@ var MigrationManager = class {
|
|
|
666
666
|
CREATE INDEX IF NOT EXISTS idx_memories_is_global ON memories(is_global);
|
|
667
667
|
CREATE INDEX IF NOT EXISTS idx_coding_standards_hit_count ON coding_standards(hit_count);
|
|
668
668
|
`);
|
|
669
|
+
try {
|
|
670
|
+
this.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_tasks_code_owner_repo ON tasks(owner, repo, task_code);`);
|
|
671
|
+
} catch {
|
|
672
|
+
const dupRows = this.all(
|
|
673
|
+
"SELECT task_code, COUNT(*) as cnt FROM tasks GROUP BY owner, repo, task_code HAVING cnt > 1"
|
|
674
|
+
);
|
|
675
|
+
if (dupRows.length > 0) {
|
|
676
|
+
const codes = dupRows.map((r) => `'${r.task_code}'`).join(", ");
|
|
677
|
+
throw new Error(
|
|
678
|
+
`Cannot create UNIQUE INDEX on (owner, repo, task_code): ${dupRows.length} duplicate task_code(s) found: ${codes}. Remove duplicates manually and re-run migration.`
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
throw new Error("Could not create UNIQUE INDEX on tasks(owner, repo, task_code)");
|
|
682
|
+
}
|
|
669
683
|
try {
|
|
670
684
|
this.run("UPDATE tasks SET task_code = substr(id, 1, 8) WHERE task_code IS NULL");
|
|
671
685
|
} catch {
|
|
@@ -1696,6 +1710,9 @@ var MemoryArchiveEntity = class extends BaseEntity {
|
|
|
1696
1710
|
};
|
|
1697
1711
|
|
|
1698
1712
|
// src/mcp/entities/task.ts
|
|
1713
|
+
function isSqliteError(err) {
|
|
1714
|
+
return err instanceof Error && typeof err.code === "string";
|
|
1715
|
+
}
|
|
1699
1716
|
var TaskEntity = class extends BaseEntity {
|
|
1700
1717
|
coordinationSelect(alias = "t") {
|
|
1701
1718
|
return `
|
|
@@ -1711,40 +1728,52 @@ var TaskEntity = class extends BaseEntity {
|
|
|
1711
1728
|
`;
|
|
1712
1729
|
}
|
|
1713
1730
|
insertTask(task) {
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1731
|
+
try {
|
|
1732
|
+
this.run(
|
|
1733
|
+
`INSERT INTO tasks (
|
|
1734
|
+
id, repo, owner, task_code, phase, title, description, status, priority,
|
|
1735
|
+
agent, role, doc_path, created_at, updated_at, finished_at, canceled_at, tags, suggested_skills, metadata, parent_id, depends_on, est_tokens, in_progress_at,
|
|
1736
|
+
commit_id, changed_files
|
|
1737
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
1738
|
+
[
|
|
1739
|
+
task.id,
|
|
1740
|
+
task.repo,
|
|
1741
|
+
task.owner || "",
|
|
1742
|
+
task.task_code,
|
|
1743
|
+
task.phase || null,
|
|
1744
|
+
task.title,
|
|
1745
|
+
task.description || null,
|
|
1746
|
+
task.status || "backlog",
|
|
1747
|
+
task.priority || 3,
|
|
1748
|
+
task.agent || "unknown",
|
|
1749
|
+
task.role || "unknown",
|
|
1750
|
+
task.doc_path || null,
|
|
1751
|
+
task.created_at,
|
|
1752
|
+
task.updated_at,
|
|
1753
|
+
task.finished_at || null,
|
|
1754
|
+
task.canceled_at || null,
|
|
1755
|
+
task.tags ? JSON.stringify(task.tags) : null,
|
|
1756
|
+
task.suggested_skills ? JSON.stringify(task.suggested_skills) : null,
|
|
1757
|
+
task.metadata ? JSON.stringify(task.metadata) : null,
|
|
1758
|
+
task.parent_id || null,
|
|
1759
|
+
task.depends_on || null,
|
|
1760
|
+
task.est_tokens || 0,
|
|
1761
|
+
task.in_progress_at || null,
|
|
1762
|
+
task.commit_id || null,
|
|
1763
|
+
task.changed_files ? JSON.stringify(task.changed_files) : null
|
|
1764
|
+
]
|
|
1765
|
+
);
|
|
1766
|
+
} catch (err) {
|
|
1767
|
+
this.handleDuplicateTaskCode(err, task.task_code, task.repo);
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
handleDuplicateTaskCode(err, taskCode, repo) {
|
|
1771
|
+
if (isSqliteError(err) && err.code === "SQLITE_CONSTRAINT_UNIQUE") {
|
|
1772
|
+
throw new Error(
|
|
1773
|
+
`Duplicate task_code: '${taskCode}' already exists in repository '${repo}'. The task_code must be unique within the repository.`
|
|
1774
|
+
);
|
|
1775
|
+
}
|
|
1776
|
+
throw err;
|
|
1748
1777
|
}
|
|
1749
1778
|
updateTask(id, updates) {
|
|
1750
1779
|
const fields = [];
|
|
@@ -1843,14 +1872,19 @@ var TaskEntity = class extends BaseEntity {
|
|
|
1843
1872
|
});
|
|
1844
1873
|
}
|
|
1845
1874
|
getTaskByCode(owner, repo, taskCode) {
|
|
1875
|
+
const params = [repo, taskCode];
|
|
1876
|
+
const ownerClause = owner ? "t.owner = ? AND " : "";
|
|
1877
|
+
if (owner) {
|
|
1878
|
+
params.unshift(owner);
|
|
1879
|
+
}
|
|
1846
1880
|
const row = this.get(
|
|
1847
1881
|
`SELECT t.*, d.task_code as depends_on_code, p.task_code as parent_code,
|
|
1848
1882
|
${this.coordinationSelect("t")}
|
|
1849
1883
|
FROM tasks t
|
|
1850
1884
|
LEFT JOIN tasks d ON t.depends_on = d.id
|
|
1851
1885
|
LEFT JOIN tasks p ON t.parent_id = p.id
|
|
1852
|
-
WHERE t.
|
|
1853
|
-
|
|
1886
|
+
WHERE ${ownerClause}t.repo = ? AND t.task_code = ?`,
|
|
1887
|
+
params
|
|
1854
1888
|
);
|
|
1855
1889
|
return row ? {
|
|
1856
1890
|
...this.rowToTask(row),
|
|
@@ -1996,8 +2030,12 @@ var TaskEntity = class extends BaseEntity {
|
|
|
1996
2030
|
return row?.count ?? 0;
|
|
1997
2031
|
}
|
|
1998
2032
|
isTaskCodeDuplicate(owner, repo, task_code, excludeId) {
|
|
1999
|
-
let query = "SELECT COUNT(*) as count FROM tasks WHERE
|
|
2000
|
-
const params = [
|
|
2033
|
+
let query = "SELECT COUNT(*) as count FROM tasks WHERE repo = ? AND task_code = ?";
|
|
2034
|
+
const params = [repo, task_code];
|
|
2035
|
+
if (owner) {
|
|
2036
|
+
query = "SELECT COUNT(*) as count FROM tasks WHERE owner = ? AND repo = ? AND task_code = ?";
|
|
2037
|
+
params.unshift(owner);
|
|
2038
|
+
}
|
|
2001
2039
|
if (excludeId) {
|
|
2002
2040
|
query += " AND id != ?";
|
|
2003
2041
|
params.push(excludeId);
|
|
@@ -2020,9 +2058,14 @@ var TaskEntity = class extends BaseEntity {
|
|
|
2020
2058
|
getExistingTaskCodes(owner, repo, codes) {
|
|
2021
2059
|
if (codes.length === 0) return /* @__PURE__ */ new Set();
|
|
2022
2060
|
const placeholders = codes.map(() => "?").join(",");
|
|
2061
|
+
const params = [repo, ...codes];
|
|
2062
|
+
const ownerClause = owner ? "owner = ? AND " : "";
|
|
2063
|
+
if (owner) {
|
|
2064
|
+
params.unshift(owner);
|
|
2065
|
+
}
|
|
2023
2066
|
const rows = this.all(
|
|
2024
|
-
`SELECT task_code FROM tasks WHERE
|
|
2025
|
-
|
|
2067
|
+
`SELECT task_code FROM tasks WHERE ${ownerClause}repo = ? AND task_code IN (${placeholders})`,
|
|
2068
|
+
params
|
|
2026
2069
|
);
|
|
2027
2070
|
return new Set(rows.map((r) => r.task_code));
|
|
2028
2071
|
}
|
|
@@ -3751,7 +3794,7 @@ var TaskCreateInteractiveSchema = SingleTaskCreateSchema.partial().extend({
|
|
|
3751
3794
|
structured: z.boolean().default(false)
|
|
3752
3795
|
});
|
|
3753
3796
|
var TaskUpdateSchema = z.object({
|
|
3754
|
-
owner: z.string().
|
|
3797
|
+
owner: z.string().min(1),
|
|
3755
3798
|
repo: z.string().min(1).transform(normalizeRepo),
|
|
3756
3799
|
id: z.string().uuid().optional(),
|
|
3757
3800
|
ids: z.array(z.string().uuid()).min(1).optional(),
|
|
@@ -3803,7 +3846,7 @@ var TaskSearchSchema = z.object({
|
|
|
3803
3846
|
structured: z.boolean().default(false)
|
|
3804
3847
|
});
|
|
3805
3848
|
var TaskDeleteSchema = z.object({
|
|
3806
|
-
owner: z.string().
|
|
3849
|
+
owner: z.string().min(1),
|
|
3807
3850
|
repo: z.string().min(1).transform(normalizeRepo),
|
|
3808
3851
|
id: z.string().uuid().optional(),
|
|
3809
3852
|
ids: z.array(z.string().uuid()).min(1).optional(),
|
|
@@ -3841,7 +3884,7 @@ var StandardDeleteSchema = z.object({
|
|
|
3841
3884
|
}
|
|
3842
3885
|
);
|
|
3843
3886
|
var TaskGetSchema = z.object({
|
|
3844
|
-
owner: z.string().
|
|
3887
|
+
owner: z.string().min(1),
|
|
3845
3888
|
repo: z.string().min(1).transform(normalizeRepo),
|
|
3846
3889
|
id: z.string().uuid().optional(),
|
|
3847
3890
|
task_code: z.string().optional(),
|
|
@@ -3908,7 +3951,7 @@ var ClaimListSchema = z.object({
|
|
|
3908
3951
|
structured: z.boolean().default(false)
|
|
3909
3952
|
});
|
|
3910
3953
|
var ClaimReleaseSchema = z.object({
|
|
3911
|
-
owner: z.string().
|
|
3954
|
+
owner: z.string().min(1),
|
|
3912
3955
|
repo: z.string().min(1).transform(normalizeRepo),
|
|
3913
3956
|
task_id: z.string().uuid().optional(),
|
|
3914
3957
|
task_code: z.string().optional(),
|
|
@@ -3927,7 +3970,7 @@ var StandardStoreSchema = z.object({
|
|
|
3927
3970
|
version: z.string().optional(),
|
|
3928
3971
|
language: z.string().optional(),
|
|
3929
3972
|
stack: z.array(z.string()).optional(),
|
|
3930
|
-
owner: z.string().
|
|
3973
|
+
owner: z.string().min(1),
|
|
3931
3974
|
repo: z.string().transform(normalizeRepo).optional(),
|
|
3932
3975
|
is_global: z.boolean().optional(),
|
|
3933
3976
|
tags: z.array(z.string().min(1)).min(1).optional(),
|
|
@@ -4124,6 +4167,7 @@ var TOOL_DEFINITIONS = [
|
|
|
4124
4167
|
inputSchema: {
|
|
4125
4168
|
type: "object",
|
|
4126
4169
|
properties: {
|
|
4170
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
4127
4171
|
repo: { type: "string", description: "Repository name" },
|
|
4128
4172
|
id: { type: "string", format: "uuid", description: "Task ID (optional if task_code is provided)" },
|
|
4129
4173
|
task_code: { type: "string", description: "Task code (e.g. TASK-001) (optional if id is provided)" },
|
|
@@ -4133,7 +4177,7 @@ var TOOL_DEFINITIONS = [
|
|
|
4133
4177
|
description: "If true, returns structured JSON without the text content details."
|
|
4134
4178
|
}
|
|
4135
4179
|
},
|
|
4136
|
-
required: ["repo"]
|
|
4180
|
+
required: ["repo", "owner"]
|
|
4137
4181
|
}
|
|
4138
4182
|
},
|
|
4139
4183
|
{
|
|
@@ -4776,6 +4820,7 @@ var TOOL_DEFINITIONS = [
|
|
|
4776
4820
|
inputSchema: {
|
|
4777
4821
|
type: "object",
|
|
4778
4822
|
properties: {
|
|
4823
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
4779
4824
|
repo: { type: "string", description: "Repository name" },
|
|
4780
4825
|
id: { type: "string", format: "uuid", description: "Task ID (for single update)" },
|
|
4781
4826
|
ids: { type: "array", items: { type: "string", format: "uuid" }, description: "Task IDs (for bulk update)" },
|
|
@@ -4835,7 +4880,7 @@ var TOOL_DEFINITIONS = [
|
|
|
4835
4880
|
},
|
|
4836
4881
|
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4837
4882
|
},
|
|
4838
|
-
required: ["repo"]
|
|
4883
|
+
required: ["repo", "owner"]
|
|
4839
4884
|
},
|
|
4840
4885
|
outputSchema: {
|
|
4841
4886
|
type: "object",
|
|
@@ -4868,6 +4913,7 @@ var TOOL_DEFINITIONS = [
|
|
|
4868
4913
|
inputSchema: {
|
|
4869
4914
|
type: "object",
|
|
4870
4915
|
properties: {
|
|
4916
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
4871
4917
|
repo: { type: "string", description: "Repository name" },
|
|
4872
4918
|
id: {
|
|
4873
4919
|
type: "string",
|
|
@@ -4878,7 +4924,7 @@ var TOOL_DEFINITIONS = [
|
|
|
4878
4924
|
task_code: { type: "string", description: "Task code (e.g. TASK-001). Optional if id is provided." },
|
|
4879
4925
|
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4880
4926
|
},
|
|
4881
|
-
required: ["repo"]
|
|
4927
|
+
required: ["repo", "owner"]
|
|
4882
4928
|
},
|
|
4883
4929
|
outputSchema: {
|
|
4884
4930
|
type: "object",
|
|
@@ -4896,7 +4942,7 @@ var TOOL_DEFINITIONS = [
|
|
|
4896
4942
|
{
|
|
4897
4943
|
name: "task-list",
|
|
4898
4944
|
title: "Task List",
|
|
4899
|
-
description: "PRIMARY navigation and search tool for tasks. Returns a compact tabular list of tasks (id, task_code, title, status, priority, updated_at, comments_count). Defaults to in_progress and pending tasks. Use 'query' to filter by code, title, or description. Use 'status' (comma-separated) for specific filters. AGENTS: call this once at start, pick ONE task, then call task-detail.",
|
|
4945
|
+
description: "PRIMARY navigation and search tool for tasks. Returns a compact tabular list of tasks (id, task_code, title, status, priority, updated_at, comments_count). Defaults to in_progress and pending tasks. Use 'query' to filter by code, title, or description. Use 'status' (comma-separated) for specific filters, or 'all' for all statuses. AGENTS: call this once at start, pick ONE task, then call task-detail.",
|
|
4900
4946
|
annotations: {
|
|
4901
4947
|
readOnlyHint: true,
|
|
4902
4948
|
idempotentHint: true,
|
|
@@ -4913,7 +4959,7 @@ var TOOL_DEFINITIONS = [
|
|
|
4913
4959
|
status: {
|
|
4914
4960
|
type: "string",
|
|
4915
4961
|
default: "in_progress,pending",
|
|
4916
|
-
description: "Comma-separated status filter (backlog, pending, in_progress, completed, canceled, blocked). Defaults to 'in_progress,
|
|
4962
|
+
description: "Comma-separated status filter (backlog, pending, in_progress, completed, canceled, blocked) or 'all' for all statuses. Defaults to 'backlog,pending,in_progress,blocked'."
|
|
4917
4963
|
},
|
|
4918
4964
|
phase: {
|
|
4919
4965
|
type: "string",
|
|
@@ -5258,6 +5304,7 @@ var TOOL_DEFINITIONS = [
|
|
|
5258
5304
|
inputSchema: {
|
|
5259
5305
|
type: "object",
|
|
5260
5306
|
properties: {
|
|
5307
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
5261
5308
|
repo: { type: "string", description: "Repository name" },
|
|
5262
5309
|
task_id: {
|
|
5263
5310
|
type: "string",
|
|
@@ -5268,7 +5315,7 @@ var TOOL_DEFINITIONS = [
|
|
|
5268
5315
|
agent: { type: "string", description: "Optional agent name to release only that claim" },
|
|
5269
5316
|
structured: { type: "boolean", default: false }
|
|
5270
5317
|
},
|
|
5271
|
-
required: ["repo"]
|
|
5318
|
+
required: ["repo", "owner"]
|
|
5272
5319
|
},
|
|
5273
5320
|
outputSchema: {
|
|
5274
5321
|
type: "object",
|
|
@@ -5295,6 +5342,7 @@ var TOOL_DEFINITIONS = [
|
|
|
5295
5342
|
inputSchema: {
|
|
5296
5343
|
type: "object",
|
|
5297
5344
|
properties: {
|
|
5345
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
5298
5346
|
name: { type: "string", minLength: 3, maxLength: 255, description: "Human-readable standard name" },
|
|
5299
5347
|
content: {
|
|
5300
5348
|
type: "string",
|
|
@@ -5352,7 +5400,8 @@ var TOOL_DEFINITIONS = [
|
|
|
5352
5400
|
description: "Array of standards for bulk creation"
|
|
5353
5401
|
},
|
|
5354
5402
|
structured: { type: "boolean", default: false }
|
|
5355
|
-
}
|
|
5403
|
+
},
|
|
5404
|
+
required: ["owner"]
|
|
5356
5405
|
},
|
|
5357
5406
|
outputSchema: {
|
|
5358
5407
|
type: "object",
|
|
@@ -6308,7 +6357,7 @@ async function handleTaskClaim(args, storage) {
|
|
|
6308
6357
|
storage.taskComments.insertTaskComment({
|
|
6309
6358
|
id: randomUUID2(),
|
|
6310
6359
|
task_id: task.id,
|
|
6311
|
-
owner
|
|
6360
|
+
owner,
|
|
6312
6361
|
repo,
|
|
6313
6362
|
comment: `Claimed by ${agent} \u2014 auto-promoted to in_progress`,
|
|
6314
6363
|
agent,
|
|
@@ -6456,6 +6505,7 @@ export {
|
|
|
6456
6505
|
MemoryDeleteSchema,
|
|
6457
6506
|
MemorySummarizeSchema,
|
|
6458
6507
|
MemorySynthesizeSchema,
|
|
6508
|
+
TaskStatusSchema,
|
|
6459
6509
|
TaskCreateSchema,
|
|
6460
6510
|
TaskCreateInteractiveSchema,
|
|
6461
6511
|
TaskUpdateSchema,
|
package/dist/dashboard/server.js
CHANGED
package/dist/mcp/server.js
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
TaskGetSchema,
|
|
27
27
|
TaskListSchema,
|
|
28
28
|
TaskSearchSchema,
|
|
29
|
+
TaskStatusSchema,
|
|
29
30
|
TaskUpdateSchema,
|
|
30
31
|
addLogSink,
|
|
31
32
|
buildStandardVectorText,
|
|
@@ -62,7 +63,7 @@ import {
|
|
|
62
63
|
toContextSlug,
|
|
63
64
|
updateSessionFromInitialize,
|
|
64
65
|
updateSessionRoots
|
|
65
|
-
} from "../chunk-
|
|
66
|
+
} from "../chunk-AVM7ZGOJ.js";
|
|
66
67
|
|
|
67
68
|
// src/mcp/server.ts
|
|
68
69
|
import readline from "readline";
|
|
@@ -1307,7 +1308,7 @@ async function handleTaskUpdate(args, storage, vectors2) {
|
|
|
1307
1308
|
throw new Error("est_tokens is required when changing task status to completed");
|
|
1308
1309
|
}
|
|
1309
1310
|
}
|
|
1310
|
-
if (updates.task_code && storage.tasks.isTaskCodeDuplicate(repo, updates.task_code, targetId)) {
|
|
1311
|
+
if (updates.task_code && storage.tasks.isTaskCodeDuplicate(owner, repo, updates.task_code, targetId)) {
|
|
1311
1312
|
throw new Error(`Duplicate task_code: '${updates.task_code}' already exists`);
|
|
1312
1313
|
}
|
|
1313
1314
|
const finalUpdates = { ...updates };
|
|
@@ -2502,7 +2503,14 @@ async function handleTaskSearch(args, storage) {
|
|
|
2502
2503
|
tasks = storage.tasks.getTasksByRepo(owner, repo, status, void 0, void 0, query);
|
|
2503
2504
|
}
|
|
2504
2505
|
} else {
|
|
2505
|
-
tasks = storage.tasks.
|
|
2506
|
+
tasks = storage.tasks.getTasksByMultipleStatuses(
|
|
2507
|
+
owner,
|
|
2508
|
+
repo,
|
|
2509
|
+
[...TaskStatusSchema.options],
|
|
2510
|
+
void 0,
|
|
2511
|
+
void 0,
|
|
2512
|
+
query
|
|
2513
|
+
);
|
|
2506
2514
|
}
|
|
2507
2515
|
if (phase) {
|
|
2508
2516
|
const phaseLower = phase.toLowerCase();
|