teammind 0.1.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.
- package/README.md +366 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +667 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.js +55 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +9 -0
- package/dist/constants.js +18 -0
- package/dist/constants.js.map +1 -0
- package/dist/db.d.ts +60 -0
- package/dist/db.js +246 -0
- package/dist/db.js.map +1 -0
- package/dist/embed.d.ts +6 -0
- package/dist/embed.js +107 -0
- package/dist/embed.js.map +1 -0
- package/dist/extract.d.ts +9 -0
- package/dist/extract.js +101 -0
- package/dist/extract.js.map +1 -0
- package/dist/git.d.ts +9 -0
- package/dist/git.js +54 -0
- package/dist/git.js.map +1 -0
- package/dist/search.d.ts +11 -0
- package/dist/search.js +131 -0
- package/dist/search.js.map +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +153 -0
- package/dist/server.js.map +1 -0
- package/dist/staleness.d.ts +10 -0
- package/dist/staleness.js +40 -0
- package/dist/staleness.js.map +1 -0
- package/dist/sync.d.ts +22 -0
- package/dist/sync.js +92 -0
- package/dist/sync.js.map +1 -0
- package/package.json +38 -0
package/dist/extract.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.extractMemoriesFromTranscript = extractMemoriesFromTranscript;
|
|
7
|
+
exports.formatTranscript = formatTranscript;
|
|
8
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
9
|
+
const constants_1 = require("./constants");
|
|
10
|
+
const EXTRACTION_PROMPT = `You are analyzing a Claude Code session transcript to extract high-value memories for a development team.
|
|
11
|
+
|
|
12
|
+
Extract ONLY memories that provide non-obvious, lasting value:
|
|
13
|
+
✓ Bugs found and their root cause
|
|
14
|
+
✓ Architectural decisions made and WHY
|
|
15
|
+
✓ Non-obvious gotchas or undocumented behaviors
|
|
16
|
+
✓ Performance findings
|
|
17
|
+
✓ Security considerations
|
|
18
|
+
✓ API quirks or workarounds discovered
|
|
19
|
+
✓ Important constraints or business rules discovered in code
|
|
20
|
+
|
|
21
|
+
DO NOT extract:
|
|
22
|
+
✗ Generic programming advice
|
|
23
|
+
✗ Things obvious from reading the code
|
|
24
|
+
✗ Temporary debugging steps that were reverted
|
|
25
|
+
✗ Standard library usage
|
|
26
|
+
✗ Basic explanations of how code works
|
|
27
|
+
|
|
28
|
+
For each memory output valid JSON with these exact fields:
|
|
29
|
+
- content: Full explanation (2-5 sentences, enough context to be useful later)
|
|
30
|
+
- summary: One line, max 80 chars, action-oriented
|
|
31
|
+
- tags: Array from ["bug","decision","gotcha","pattern","performance","security","config","api"]
|
|
32
|
+
- file_paths: Array of relative file paths involved (empty array if none)
|
|
33
|
+
- functions: Array of "ClassName.methodName" or "functionName" (empty array if none)
|
|
34
|
+
|
|
35
|
+
Respond with ONLY a JSON array. If nothing worth remembering, respond with [].
|
|
36
|
+
|
|
37
|
+
TRANSCRIPT:
|
|
38
|
+
{{TRANSCRIPT}}`;
|
|
39
|
+
async function extractMemoriesFromTranscript(transcript, apiKey) {
|
|
40
|
+
const key = apiKey || process.env.ANTHROPIC_API_KEY;
|
|
41
|
+
if (!key)
|
|
42
|
+
return [];
|
|
43
|
+
try {
|
|
44
|
+
const client = new sdk_1.default({ apiKey: key });
|
|
45
|
+
// Trim transcript to avoid huge token counts (keep last 80k chars which is ~20k tokens)
|
|
46
|
+
const trimmed = transcript.length > 80000
|
|
47
|
+
? transcript.slice(-80000)
|
|
48
|
+
: transcript;
|
|
49
|
+
const response = await client.messages.create({
|
|
50
|
+
model: constants_1.HAIKU_MODEL,
|
|
51
|
+
max_tokens: 4096,
|
|
52
|
+
messages: [{
|
|
53
|
+
role: 'user',
|
|
54
|
+
content: EXTRACTION_PROMPT.replace('{{TRANSCRIPT}}', trimmed)
|
|
55
|
+
}]
|
|
56
|
+
});
|
|
57
|
+
const text = response.content[0].type === 'text' ? response.content[0].text : '';
|
|
58
|
+
// Extract JSON array — handle markdown code fences if present
|
|
59
|
+
const jsonMatch = text.match(/```(?:json)?\s*([\s\S]*?)\s*```/) ||
|
|
60
|
+
text.match(/(\[[\s\S]*\])/);
|
|
61
|
+
if (!jsonMatch)
|
|
62
|
+
return [];
|
|
63
|
+
const raw = JSON.parse(jsonMatch[1] || jsonMatch[0]);
|
|
64
|
+
if (!Array.isArray(raw))
|
|
65
|
+
return [];
|
|
66
|
+
return raw
|
|
67
|
+
.filter((m) => m && typeof m.content === 'string' && m.content.length > 10)
|
|
68
|
+
.map((m) => ({
|
|
69
|
+
content: String(m.content || '').slice(0, 2000),
|
|
70
|
+
summary: String(m.summary || m.content || '').slice(0, 80),
|
|
71
|
+
tags: Array.isArray(m.tags) ? m.tags.slice(0, 5) : [],
|
|
72
|
+
file_paths: Array.isArray(m.file_paths) ? m.file_paths : [],
|
|
73
|
+
functions: Array.isArray(m.functions) ? m.functions : [],
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Format a conversation transcript from Claude Code's hook payload
|
|
81
|
+
function formatTranscript(hookPayload) {
|
|
82
|
+
try {
|
|
83
|
+
const transcript = hookPayload?.transcript || hookPayload?.messages || [];
|
|
84
|
+
if (!Array.isArray(transcript) || transcript.length === 0) {
|
|
85
|
+
return typeof hookPayload === 'string' ? hookPayload : JSON.stringify(hookPayload);
|
|
86
|
+
}
|
|
87
|
+
return transcript
|
|
88
|
+
.map((msg) => {
|
|
89
|
+
const role = (msg.role || 'unknown').toUpperCase();
|
|
90
|
+
const content = Array.isArray(msg.content)
|
|
91
|
+
? msg.content.map((c) => (typeof c === 'string' ? c : c?.text || '')).join('\n')
|
|
92
|
+
: String(msg.content || '');
|
|
93
|
+
return `[${role}]: ${content}`;
|
|
94
|
+
})
|
|
95
|
+
.join('\n\n');
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return JSON.stringify(hookPayload).slice(0, 50000);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"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"}
|
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface GitContext {
|
|
2
|
+
root: string;
|
|
3
|
+
branch: string;
|
|
4
|
+
commit: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function normalizePath(p: string): string;
|
|
7
|
+
export declare function getGitContext(cwd: string): Promise<GitContext | null>;
|
|
8
|
+
export declare function hashFile(filePath: string): string;
|
|
9
|
+
export declare function resolveFilePaths(filePaths: string[], repoRoot: string): string[];
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.normalizePath = normalizePath;
|
|
7
|
+
exports.getGitContext = getGitContext;
|
|
8
|
+
exports.hashFile = hashFile;
|
|
9
|
+
exports.resolveFilePaths = resolveFilePaths;
|
|
10
|
+
const crypto_1 = require("crypto");
|
|
11
|
+
const fs_1 = require("fs");
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
14
|
+
function normalizePath(p) {
|
|
15
|
+
return p.replace(/\\/g, '/');
|
|
16
|
+
}
|
|
17
|
+
async function getGitContext(cwd) {
|
|
18
|
+
try {
|
|
19
|
+
const git = (0, simple_git_1.default)(cwd);
|
|
20
|
+
const isRepo = await git.checkIsRepo();
|
|
21
|
+
if (!isRepo)
|
|
22
|
+
return null;
|
|
23
|
+
const root = normalizePath((await git.revparse(['--show-toplevel'])).trim());
|
|
24
|
+
const branchResult = await git.branch();
|
|
25
|
+
const branch = branchResult.current || 'unknown';
|
|
26
|
+
const commit = (await git.revparse(['HEAD'])).trim();
|
|
27
|
+
return { root, branch, commit };
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function hashFile(filePath) {
|
|
34
|
+
try {
|
|
35
|
+
if (!(0, fs_1.existsSync)(filePath))
|
|
36
|
+
return '';
|
|
37
|
+
const content = (0, fs_1.readFileSync)(filePath);
|
|
38
|
+
return (0, crypto_1.createHash)('sha256').update(content).digest('hex').slice(0, 16);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return '';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function resolveFilePaths(filePaths, repoRoot) {
|
|
45
|
+
return filePaths
|
|
46
|
+
.map(fp => {
|
|
47
|
+
// If already absolute, keep. Otherwise resolve from repo root.
|
|
48
|
+
if (path_1.default.isAbsolute(fp))
|
|
49
|
+
return fp;
|
|
50
|
+
return path_1.default.join(repoRoot, fp);
|
|
51
|
+
})
|
|
52
|
+
.filter(fp => (0, fs_1.existsSync)(fp));
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":";;;;;AAWA,sCAEC;AAED,sCAeC;AAED,4BAQC;AAED,4CAQC;AAlDD,mCAAmC;AACnC,2BAA6C;AAC7C,gDAAuB;AACvB,4DAAkC;AAQlC,SAAgB,aAAa,CAAC,CAAS;IACrC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;AAC9B,CAAC;AAEM,KAAK,UAAU,aAAa,CAAC,GAAW;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAA,oBAAS,EAAC,GAAG,CAAC,CAAA;QAC1B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,WAAW,EAAE,CAAA;QACtC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAA;QAExB,MAAM,IAAI,GAAG,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;QAC5E,MAAM,YAAY,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,CAAA;QACvC,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,IAAI,SAAS,CAAA;QAChD,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QAEpD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,SAAgB,QAAQ,CAAC,QAAgB;IACvC,IAAI,CAAC;QACH,IAAI,CAAC,IAAA,eAAU,EAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAA;QACpC,MAAM,OAAO,GAAG,IAAA,iBAAY,EAAC,QAAQ,CAAC,CAAA;QACtC,OAAO,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,SAAgB,gBAAgB,CAAC,SAAmB,EAAE,QAAgB;IACpE,OAAO,SAAS;SACb,GAAG,CAAC,EAAE,CAAC,EAAE;QACR,+DAA+D;QAC/D,IAAI,cAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAAE,OAAO,EAAE,CAAA;QAClC,OAAO,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;IAChC,CAAC,CAAC;SACD,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,IAAA,eAAU,EAAC,EAAE,CAAC,CAAC,CAAA;AACjC,CAAC"}
|
package/dist/search.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Memory } from './db';
|
|
2
|
+
export interface SearchResult extends Memory {
|
|
3
|
+
score: number;
|
|
4
|
+
}
|
|
5
|
+
export declare function searchMemories(query: string, repoPath: string, opts?: {
|
|
6
|
+
filePath?: string;
|
|
7
|
+
limit?: number;
|
|
8
|
+
}): Promise<SearchResult[]>;
|
|
9
|
+
export declare function rankMemoriesForInjection(repoPath: string, branch: string, limit?: number): Memory[];
|
|
10
|
+
export declare function findDuplicate(content: string, repoPath: string, threshold?: number): Promise<string | null>;
|
|
11
|
+
export declare function formatMemoriesForContext(memories: Memory[], projectName: string, branch: string): string;
|
package/dist/search.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.searchMemories = searchMemories;
|
|
4
|
+
exports.rankMemoriesForInjection = rankMemoriesForInjection;
|
|
5
|
+
exports.findDuplicate = findDuplicate;
|
|
6
|
+
exports.formatMemoriesForContext = formatMemoriesForContext;
|
|
7
|
+
const db_1 = require("./db");
|
|
8
|
+
const embed_1 = require("./embed");
|
|
9
|
+
const constants_1 = require("./constants");
|
|
10
|
+
// Full semantic + keyword hybrid search — used by MCP tool (mid-session)
|
|
11
|
+
async function searchMemories(query, repoPath, opts = {}) {
|
|
12
|
+
const { filePath, limit = 5 } = opts;
|
|
13
|
+
const memories = (0, db_1.getAllMemoriesWithEmbeddings)(repoPath);
|
|
14
|
+
if (memories.length === 0)
|
|
15
|
+
return [];
|
|
16
|
+
// Embed query
|
|
17
|
+
let queryVec = null;
|
|
18
|
+
try {
|
|
19
|
+
queryVec = await (0, embed_1.embed)(query);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Fall back to keyword search if embedding fails
|
|
23
|
+
}
|
|
24
|
+
const scored = memories.map(m => {
|
|
25
|
+
let score = 0;
|
|
26
|
+
// Semantic score
|
|
27
|
+
if (queryVec && m.embedding) {
|
|
28
|
+
const memVec = (0, embed_1.deserializeVec)(m.embedding);
|
|
29
|
+
score += (0, embed_1.cosineSimilarity)(queryVec, memVec) * 2;
|
|
30
|
+
}
|
|
31
|
+
// Keyword score
|
|
32
|
+
score += (0, embed_1.keywordScore)(query, m.content + ' ' + m.summary);
|
|
33
|
+
// Recency boost: memories from last 14 days get +0.1
|
|
34
|
+
const ageDays = (Date.now() - m.created_at) / (1000 * 60 * 60 * 24);
|
|
35
|
+
if (ageDays < 14)
|
|
36
|
+
score += 0.1 * (1 - ageDays / 14);
|
|
37
|
+
// File path relevance boost
|
|
38
|
+
if (filePath) {
|
|
39
|
+
const normalizedFp = filePath.replace(/\\/g, '/');
|
|
40
|
+
if (m.file_paths.some(fp => normalizedFp.includes(fp) || fp.includes(normalizedFp))) {
|
|
41
|
+
score += 0.5;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Tag boost for high-priority tags
|
|
45
|
+
if (m.tags.includes('bug') || m.tags.includes('gotcha'))
|
|
46
|
+
score += 0.05;
|
|
47
|
+
if (m.tags.includes('security'))
|
|
48
|
+
score += 0.1;
|
|
49
|
+
return { ...m, score };
|
|
50
|
+
});
|
|
51
|
+
// Apply file filter if provided
|
|
52
|
+
const filtered = filePath
|
|
53
|
+
? scored.filter(m => {
|
|
54
|
+
const normalizedFp = filePath.replace(/\\/g, '/');
|
|
55
|
+
return m.file_paths.length === 0 ||
|
|
56
|
+
m.file_paths.some(fp => normalizedFp.includes(fp) || fp.includes(normalizedFp));
|
|
57
|
+
})
|
|
58
|
+
: scored;
|
|
59
|
+
return filtered
|
|
60
|
+
.filter(m => m.score > 0)
|
|
61
|
+
.sort((a, b) => b.score - a.score)
|
|
62
|
+
.slice(0, limit);
|
|
63
|
+
}
|
|
64
|
+
// Fast keyword-only ranking — used for session injection (no model needed, must be fast)
|
|
65
|
+
function rankMemoriesForInjection(repoPath, branch, limit = constants_1.MAX_INJECT_MEMORIES) {
|
|
66
|
+
const memories = (0, db_1.getMemories)(repoPath, { limit: 200, includeStale: false });
|
|
67
|
+
if (memories.length === 0)
|
|
68
|
+
return [];
|
|
69
|
+
const scored = memories.map(m => {
|
|
70
|
+
let score = 0;
|
|
71
|
+
// Recency: most recent gets highest score
|
|
72
|
+
const ageDays = (Date.now() - m.created_at) / (1000 * 60 * 60 * 24);
|
|
73
|
+
score += Math.max(0, 10 - ageDays * 0.5);
|
|
74
|
+
// Branch match boost
|
|
75
|
+
if (m.git_branch === branch)
|
|
76
|
+
score += 3;
|
|
77
|
+
// Tag priority
|
|
78
|
+
if (m.tags.includes('gotcha') || m.tags.includes('bug'))
|
|
79
|
+
score += 2;
|
|
80
|
+
if (m.tags.includes('security'))
|
|
81
|
+
score += 3;
|
|
82
|
+
if (m.tags.includes('config'))
|
|
83
|
+
score += 1;
|
|
84
|
+
return { ...m, score };
|
|
85
|
+
});
|
|
86
|
+
return scored
|
|
87
|
+
.sort((a, b) => b.score - a.score)
|
|
88
|
+
.slice(0, limit);
|
|
89
|
+
}
|
|
90
|
+
// Check if a memory is a near-duplicate of an existing one
|
|
91
|
+
// Returns the ID of the duplicate if found, null otherwise
|
|
92
|
+
async function findDuplicate(content, repoPath, threshold = 0.88) {
|
|
93
|
+
const existing = (0, db_1.getAllMemoriesWithEmbeddings)(repoPath);
|
|
94
|
+
if (existing.length === 0)
|
|
95
|
+
return null;
|
|
96
|
+
let queryVec = null;
|
|
97
|
+
try {
|
|
98
|
+
queryVec = await (0, embed_1.embed)(content);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null; // can't dedup without embeddings
|
|
102
|
+
}
|
|
103
|
+
for (const m of existing) {
|
|
104
|
+
if (!m.embedding)
|
|
105
|
+
continue;
|
|
106
|
+
const memVec = (0, embed_1.deserializeVec)(m.embedding);
|
|
107
|
+
const sim = (0, embed_1.cosineSimilarity)(queryVec, memVec);
|
|
108
|
+
if (sim >= threshold)
|
|
109
|
+
return m.id;
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
// Format memories for injection into Claude's context
|
|
114
|
+
function formatMemoriesForContext(memories, projectName, branch) {
|
|
115
|
+
if (memories.length === 0)
|
|
116
|
+
return '';
|
|
117
|
+
const lines = [
|
|
118
|
+
`<team_memory project="${projectName}" branch="${branch}">`
|
|
119
|
+
];
|
|
120
|
+
for (let i = 0; i < memories.length; i++) {
|
|
121
|
+
const m = memories[i];
|
|
122
|
+
const tag = m.tags[0] || 'note';
|
|
123
|
+
const staleTag = m.stale ? ' [may be outdated]' : '';
|
|
124
|
+
const fileHint = m.file_paths.length > 0 ? ` — ${m.file_paths[0]}` : '';
|
|
125
|
+
lines.push(`${i + 1}. [${tag}] ${m.summary}${staleTag}${fileHint}`);
|
|
126
|
+
}
|
|
127
|
+
lines.push(`</team_memory>`);
|
|
128
|
+
lines.push(`(${memories.length} memories loaded — use memory_search tool for details or more)`);
|
|
129
|
+
return lines.join('\n');
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":";;AASA,wCA8DC;AAGD,4DAyBC;AAID,sCAuBC;AAGD,4DAmBC;AApJD,6BAAwE;AACxE,mCAA+E;AAC/E,2CAAiD;AAMjD,yEAAyE;AAClE,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,QAAgB,EAChB,OAA8C,EAAE;IAEhD,MAAM,EAAE,QAAQ,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,IAAI,CAAA;IAEpC,MAAM,QAAQ,GAAG,IAAA,iCAA4B,EAAC,QAAQ,CAAC,CAAA;IACvD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAEpC,cAAc;IACd,IAAI,QAAQ,GAAwB,IAAI,CAAA;IACxC,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,IAAA,aAAK,EAAC,KAAK,CAAC,CAAA;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,iDAAiD;IACnD,CAAC;IAED,MAAM,MAAM,GAAmB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QAC9C,IAAI,KAAK,GAAG,CAAC,CAAA;QAEb,iBAAiB;QACjB,IAAI,QAAQ,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,IAAA,sBAAc,EAAC,CAAC,CAAC,SAAS,CAAC,CAAA;YAC1C,KAAK,IAAI,IAAA,wBAAgB,EAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAAA;QACjD,CAAC;QAED,gBAAgB;QAChB,KAAK,IAAI,IAAA,oBAAY,EAAC,KAAK,EAAE,CAAC,CAAC,OAAO,GAAG,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAA;QAEzD,qDAAqD;QACrD,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;QACnE,IAAI,OAAO,GAAG,EAAE;YAAE,KAAK,IAAI,GAAG,GAAG,CAAC,CAAC,GAAG,OAAO,GAAG,EAAE,CAAC,CAAA;QAEnD,4BAA4B;QAC5B,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YACjD,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;gBACpF,KAAK,IAAI,GAAG,CAAA;YACd,CAAC;QACH,CAAC;QAED,mCAAmC;QACnC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,KAAK,IAAI,IAAI,CAAA;QACtE,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;YAAE,KAAK,IAAI,GAAG,CAAA;QAE7C,OAAO,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAA;IACxB,CAAC,CAAC,CAAA;IAEF,gCAAgC;IAChC,MAAM,QAAQ,GAAG,QAAQ;QACvB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YAChB,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YACjD,OAAO,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;gBACzB,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAA;QACxF,CAAC,CAAC;QACJ,CAAC,CAAC,MAAM,CAAA;IAEV,OAAO,QAAQ;SACZ,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;SACxB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;SACjC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;AACpB,CAAC;AAED,yFAAyF;AACzF,SAAgB,wBAAwB,CAAC,QAAgB,EAAE,MAAc,EAAE,KAAK,GAAG,+BAAmB;IACpG,MAAM,QAAQ,GAAG,IAAA,gBAAW,EAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAA;IAC3E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAEpC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QAC9B,IAAI,KAAK,GAAG,CAAC,CAAA;QAEb,0CAA0C;QAC1C,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;QACnE,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,GAAG,GAAG,CAAC,CAAA;QAExC,qBAAqB;QACrB,IAAI,CAAC,CAAC,UAAU,KAAK,MAAM;YAAE,KAAK,IAAI,CAAC,CAAA;QAEvC,eAAe;QACf,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,KAAK,IAAI,CAAC,CAAA;QACnE,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;YAAE,KAAK,IAAI,CAAC,CAAA;QAC3C,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,KAAK,IAAI,CAAC,CAAA;QAEzC,OAAO,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAA;IACxB,CAAC,CAAC,CAAA;IAEF,OAAO,MAAM;SACV,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;SACjC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;AACpB,CAAC;AAED,2DAA2D;AAC3D,2DAA2D;AACpD,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,QAAgB,EAChB,SAAS,GAAG,IAAI;IAEhB,MAAM,QAAQ,GAAG,IAAA,iCAA4B,EAAC,QAAQ,CAAC,CAAA;IACvD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAEtC,IAAI,QAAQ,GAAwB,IAAI,CAAA;IACxC,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,IAAA,aAAK,EAAC,OAAO,CAAC,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA,CAAC,iCAAiC;IAC/C,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,CAAC,SAAS;YAAE,SAAQ;QAC1B,MAAM,MAAM,GAAG,IAAA,sBAAc,EAAC,CAAC,CAAC,SAAS,CAAC,CAAA;QAC1C,MAAM,GAAG,GAAG,IAAA,wBAAgB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAC9C,IAAI,GAAG,IAAI,SAAS;YAAE,OAAO,CAAC,CAAC,EAAE,CAAA;IACnC,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,sDAAsD;AACtD,SAAgB,wBAAwB,CAAC,QAAkB,EAAE,WAAmB,EAAE,MAAc;IAC9F,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAEpC,MAAM,KAAK,GAAa;QACtB,yBAAyB,WAAW,aAAa,MAAM,IAAI;KAC5D,CAAA;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;QACrB,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAA;QAC/B,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAA;QACpD,MAAM,QAAQ,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QACvE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,GAAG,QAAQ,GAAG,QAAQ,EAAE,CAAC,CAAA;IACrE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;IAC5B,KAAK,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,MAAM,gEAAgE,CAAC,CAAA;IAE/F,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function startMcpServer(): Promise<void>;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.startMcpServer = startMcpServer;
|
|
7
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
8
|
+
// Use McpServer (high-level API from SDK v1.27+) with require() to bypass
|
|
9
|
+
// TypeScript's module resolution for packages using the exports map
|
|
10
|
+
const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
11
|
+
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const os_1 = __importDefault(require("os"));
|
|
14
|
+
const zod_1 = require("zod");
|
|
15
|
+
const search_1 = require("./search");
|
|
16
|
+
const db_1 = require("./db");
|
|
17
|
+
const git_1 = require("./git");
|
|
18
|
+
const embed_1 = require("./embed");
|
|
19
|
+
const staleness_1 = require("./staleness");
|
|
20
|
+
async function startMcpServer() {
|
|
21
|
+
const cwd = (0, git_1.normalizePath)(process.cwd());
|
|
22
|
+
const server = new McpServer({
|
|
23
|
+
name: 'teammind',
|
|
24
|
+
version: '0.1.0',
|
|
25
|
+
});
|
|
26
|
+
// ─── memory_search ──────────────────────────────────────────────────────────
|
|
27
|
+
server.registerTool('memory_search', {
|
|
28
|
+
description: 'Search team memory for relevant context about code, bugs, decisions, or patterns. Call this proactively when you open a file or encounter a problem that might have prior context.',
|
|
29
|
+
inputSchema: {
|
|
30
|
+
query: zod_1.z.string().describe('Natural language query, e.g. "auth middleware behavior" or "stripe webhook handling"'),
|
|
31
|
+
file_path: zod_1.z.string().optional().describe('Narrow results to memories about a specific file'),
|
|
32
|
+
limit: zod_1.z.number().optional().describe('Max results to return (default 5)'),
|
|
33
|
+
},
|
|
34
|
+
}, async ({ query, file_path, limit }) => {
|
|
35
|
+
const gitCtx = await (0, git_1.getGitContext)(cwd);
|
|
36
|
+
const repoPath = gitCtx?.root || cwd;
|
|
37
|
+
const results = await (0, search_1.searchMemories)(query, repoPath, {
|
|
38
|
+
filePath: file_path,
|
|
39
|
+
limit: limit || 5,
|
|
40
|
+
});
|
|
41
|
+
if (results.length === 0) {
|
|
42
|
+
return text('No relevant memories found for this query.');
|
|
43
|
+
}
|
|
44
|
+
const formatted = results.map((m, i) => {
|
|
45
|
+
const staleNote = m.stale ? ' [MAY BE OUTDATED]' : '';
|
|
46
|
+
const files = m.file_paths.length > 0 ? `\n Files: ${m.file_paths.join(', ')}` : '';
|
|
47
|
+
const fns = m.functions.length > 0 ? `\n Functions: ${m.functions.join(', ')}` : '';
|
|
48
|
+
const tags = `[${m.tags.join(', ') || 'note'}]`;
|
|
49
|
+
return `${i + 1}. ${tags} ${m.summary}${staleNote}\n ${m.content}${files}${fns}`;
|
|
50
|
+
}).join('\n\n');
|
|
51
|
+
return text(formatted);
|
|
52
|
+
});
|
|
53
|
+
// ─── memory_add ─────────────────────────────────────────────────────────────
|
|
54
|
+
server.registerTool('memory_add', {
|
|
55
|
+
description: 'Save an important insight, decision, bug fix, or pattern to team memory so future sessions can benefit from it. Use this when you discover something non-obvious.',
|
|
56
|
+
inputSchema: {
|
|
57
|
+
content: zod_1.z.string().describe('Full description (2-5 sentences with enough context to be useful later)'),
|
|
58
|
+
summary: zod_1.z.string().describe('One-line summary, max 80 chars'),
|
|
59
|
+
tags: zod_1.z.array(zod_1.z.string()).optional().describe('Tags: bug, decision, gotcha, pattern, performance, security, config, api'),
|
|
60
|
+
file_paths: zod_1.z.array(zod_1.z.string()).optional().describe('Relative file paths this memory relates to'),
|
|
61
|
+
functions: zod_1.z.array(zod_1.z.string()).optional().describe('Function or method names, e.g. ["UserAuth.handleOAuth"]'),
|
|
62
|
+
},
|
|
63
|
+
}, async ({ content, summary, tags, file_paths, functions }) => {
|
|
64
|
+
const gitCtx = await (0, git_1.getGitContext)(cwd);
|
|
65
|
+
const repoPath = gitCtx?.root || cwd;
|
|
66
|
+
let embedding = null;
|
|
67
|
+
try {
|
|
68
|
+
const vec = await (0, embed_1.embed)(content);
|
|
69
|
+
embedding = (0, embed_1.serializeVec)(vec);
|
|
70
|
+
}
|
|
71
|
+
catch { /* embedding optional */ }
|
|
72
|
+
const id = (0, db_1.saveMemory)({
|
|
73
|
+
content,
|
|
74
|
+
summary,
|
|
75
|
+
tags: tags || [],
|
|
76
|
+
file_paths: file_paths || [],
|
|
77
|
+
functions: functions || [],
|
|
78
|
+
embedding,
|
|
79
|
+
repo_path: repoPath,
|
|
80
|
+
git_commit: gitCtx?.commit || null,
|
|
81
|
+
git_branch: gitCtx?.branch || null,
|
|
82
|
+
created_by: os_1.default.userInfo().username || 'local',
|
|
83
|
+
source: 'manual',
|
|
84
|
+
stale: 0,
|
|
85
|
+
});
|
|
86
|
+
if (file_paths && file_paths.length > 0) {
|
|
87
|
+
const absFiles = (0, git_1.resolveFilePaths)(file_paths, repoPath);
|
|
88
|
+
(0, db_1.saveMemoryFiles)(id, absFiles.map(fp => ({
|
|
89
|
+
path: path_1.default.relative(repoPath, fp),
|
|
90
|
+
hash: (0, git_1.hashFile)(fp),
|
|
91
|
+
})));
|
|
92
|
+
}
|
|
93
|
+
const total = (0, db_1.countMemories)(repoPath);
|
|
94
|
+
return text(`Memory saved. (${total} total memories for this project)`);
|
|
95
|
+
});
|
|
96
|
+
// ─── memory_list ────────────────────────────────────────────────────────────
|
|
97
|
+
server.registerTool('memory_list', {
|
|
98
|
+
description: 'List recent memories for the current project.',
|
|
99
|
+
inputSchema: {
|
|
100
|
+
limit: zod_1.z.number().optional().describe('Number of memories to list (default 10)'),
|
|
101
|
+
},
|
|
102
|
+
}, async ({ limit }) => {
|
|
103
|
+
const gitCtx = await (0, git_1.getGitContext)(cwd);
|
|
104
|
+
const repoPath = gitCtx?.root || cwd;
|
|
105
|
+
const memories = (0, db_1.getMemories)(repoPath, { limit: limit || 10 });
|
|
106
|
+
if (memories.length === 0) {
|
|
107
|
+
return text('No memories yet for this project. They will be captured automatically at session end, or use memory_add.');
|
|
108
|
+
}
|
|
109
|
+
const formatted = memories.map((m, i) => {
|
|
110
|
+
const staleNote = m.stale ? ' ⚠ stale' : '';
|
|
111
|
+
const tags = `[${m.tags.join(', ') || 'note'}]`;
|
|
112
|
+
const age = formatAge(m.created_at);
|
|
113
|
+
return `${i + 1}. ${tags} ${m.summary}${staleNote} — ${age}`;
|
|
114
|
+
}).join('\n');
|
|
115
|
+
const total = (0, db_1.countMemories)(repoPath);
|
|
116
|
+
return text(`${formatted}\n\n(${total} total)`);
|
|
117
|
+
});
|
|
118
|
+
// ─── memory_stale ───────────────────────────────────────────────────────────
|
|
119
|
+
server.registerTool('memory_stale', {
|
|
120
|
+
description: 'Check which memories may be outdated because their referenced files changed. Run this periodically or when you suspect something is stale.',
|
|
121
|
+
inputSchema: {},
|
|
122
|
+
}, async () => {
|
|
123
|
+
const gitCtx = await (0, git_1.getGitContext)(cwd);
|
|
124
|
+
const repoPath = gitCtx?.root || cwd;
|
|
125
|
+
const report = await (0, staleness_1.checkAndMarkStaleness)(repoPath);
|
|
126
|
+
if (report.markedStale === 0) {
|
|
127
|
+
return text(`All ${report.checked} tracked memories are fresh.`);
|
|
128
|
+
}
|
|
129
|
+
const details = report.staleMemories
|
|
130
|
+
.map(m => `- ${m.summary}\n Changed files: ${m.changedFiles.join(', ')}`)
|
|
131
|
+
.join('\n');
|
|
132
|
+
return text(`Marked ${report.markedStale} memories as stale (files changed since capture):\n${details}\n\n` +
|
|
133
|
+
`These will still appear tagged [may be outdated] but are deprioritized in injection.`);
|
|
134
|
+
});
|
|
135
|
+
const transport = new StdioServerTransport();
|
|
136
|
+
await server.connect(transport);
|
|
137
|
+
}
|
|
138
|
+
function text(content) {
|
|
139
|
+
return { content: [{ type: 'text', text: content }] };
|
|
140
|
+
}
|
|
141
|
+
function formatAge(ts) {
|
|
142
|
+
const days = Math.floor((Date.now() - ts) / (1000 * 60 * 60 * 24));
|
|
143
|
+
if (days === 0)
|
|
144
|
+
return 'today';
|
|
145
|
+
if (days === 1)
|
|
146
|
+
return 'yesterday';
|
|
147
|
+
if (days < 30)
|
|
148
|
+
return `${days}d ago`;
|
|
149
|
+
if (days < 365)
|
|
150
|
+
return `${Math.floor(days / 30)}mo ago`;
|
|
151
|
+
return `${Math.floor(days / 365)}y ago`;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface StalenessReport {
|
|
2
|
+
checked: number;
|
|
3
|
+
markedStale: number;
|
|
4
|
+
staleMemories: Array<{
|
|
5
|
+
id: string;
|
|
6
|
+
summary: string;
|
|
7
|
+
changedFiles: string[];
|
|
8
|
+
}>;
|
|
9
|
+
}
|
|
10
|
+
export declare function checkAndMarkStaleness(repoPath: string): Promise<StalenessReport>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.checkAndMarkStaleness = checkAndMarkStaleness;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const db_1 = require("./db");
|
|
9
|
+
const git_1 = require("./git");
|
|
10
|
+
async function checkAndMarkStaleness(repoPath) {
|
|
11
|
+
const memories = (0, db_1.getMemoriesWithFiles)(repoPath);
|
|
12
|
+
const report = { checked: 0, markedStale: 0, staleMemories: [] };
|
|
13
|
+
for (const memory of memories) {
|
|
14
|
+
if (memory.tracked_files.length === 0)
|
|
15
|
+
continue;
|
|
16
|
+
report.checked++;
|
|
17
|
+
const changedFiles = [];
|
|
18
|
+
for (const tf of memory.tracked_files) {
|
|
19
|
+
const absPath = path_1.default.isAbsolute(tf.file_path)
|
|
20
|
+
? tf.file_path
|
|
21
|
+
: path_1.default.join(repoPath, tf.file_path);
|
|
22
|
+
const currentHash = (0, git_1.hashFile)(absPath);
|
|
23
|
+
// Empty hash means file doesn't exist or couldn't be read
|
|
24
|
+
if (tf.file_hash && currentHash && currentHash !== tf.file_hash) {
|
|
25
|
+
changedFiles.push(tf.file_path);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (changedFiles.length > 0) {
|
|
29
|
+
(0, db_1.markMemoryStale)(memory.id);
|
|
30
|
+
report.markedStale++;
|
|
31
|
+
report.staleMemories.push({
|
|
32
|
+
id: memory.id,
|
|
33
|
+
summary: memory.summary,
|
|
34
|
+
changedFiles,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return report;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=staleness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness.js","sourceRoot":"","sources":["../src/staleness.ts"],"names":[],"mappings":";;;;;AAUA,sDAmCC;AA7CD,gDAAuB;AACvB,6BAA4D;AAC5D,+BAAgC;AAQzB,KAAK,UAAU,qBAAqB,CAAC,QAAgB;IAC1D,MAAM,QAAQ,GAAG,IAAA,yBAAoB,EAAC,QAAQ,CAAC,CAAA;IAC/C,MAAM,MAAM,GAAoB,EAAE,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,CAAA;IAEjF,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC;YAAE,SAAQ;QAC/C,MAAM,CAAC,OAAO,EAAE,CAAA;QAEhB,MAAM,YAAY,GAAa,EAAE,CAAA;QAEjC,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,cAAI,CAAC,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC;gBAC3C,CAAC,CAAC,EAAE,CAAC,SAAS;gBACd,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,CAAA;YAErC,MAAM,WAAW,GAAG,IAAA,cAAQ,EAAC,OAAO,CAAC,CAAA;YAErC,0DAA0D;YAC1D,IAAI,EAAE,CAAC,SAAS,IAAI,WAAW,IAAI,WAAW,KAAK,EAAE,CAAC,SAAS,EAAE,CAAC;gBAChE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,CAAA;YACjC,CAAC;QACH,CAAC;QAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,IAAA,oBAAe,EAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YAC1B,MAAM,CAAC,WAAW,EAAE,CAAA;YACpB,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;gBACxB,EAAE,EAAE,MAAM,CAAC,EAAE;gBACb,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,YAAY;aACb,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/dist/sync.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface TeamMemoryExport {
|
|
2
|
+
version: '1.0';
|
|
3
|
+
exported_at: string;
|
|
4
|
+
memories: Array<{
|
|
5
|
+
id: string;
|
|
6
|
+
content: string;
|
|
7
|
+
summary: string;
|
|
8
|
+
tags: string[];
|
|
9
|
+
file_paths: string[];
|
|
10
|
+
functions: string[];
|
|
11
|
+
git_commit: string | null;
|
|
12
|
+
git_branch: string | null;
|
|
13
|
+
created_by: string;
|
|
14
|
+
created_at: string;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
export declare function exportMemories(repoPath: string): TeamMemoryExport;
|
|
18
|
+
export declare function importMemories(filePath: string, repoPath: string, createdBy?: string): Promise<{
|
|
19
|
+
imported: number;
|
|
20
|
+
skipped: number;
|
|
21
|
+
}>;
|
|
22
|
+
export declare function writeExportFile(exportData: TeamMemoryExport, outputPath: string): void;
|