memobank-cli 0.2.0 → 0.6.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/CHANGELOG.md +24 -0
- package/README.md +330 -83
- package/dist/cli.js +180 -13
- package/dist/cli.js.map +1 -1
- package/dist/commands/capture.d.ts +1 -0
- package/dist/commands/capture.d.ts.map +1 -1
- package/dist/commands/capture.js +38 -15
- package/dist/commands/capture.js.map +1 -1
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +94 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install.d.ts +1 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +56 -4
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/lifecycle.d.ts +2 -0
- package/dist/commands/lifecycle.d.ts.map +1 -1
- package/dist/commands/lifecycle.js +10 -0
- package/dist/commands/lifecycle.js.map +1 -1
- package/dist/commands/migrate.d.ts +22 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +130 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/onboarding.d.ts +8 -7
- package/dist/commands/onboarding.d.ts.map +1 -1
- package/dist/commands/onboarding.js +411 -343
- package/dist/commands/onboarding.js.map +1 -1
- package/dist/commands/recall.d.ts +4 -2
- package/dist/commands/recall.d.ts.map +1 -1
- package/dist/commands/recall.js +27 -30
- package/dist/commands/recall.js.map +1 -1
- package/dist/commands/scan.d.ts +27 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +147 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +7 -2
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/setup.js +2 -2
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/team.d.ts +18 -0
- package/dist/commands/team.d.ts.map +1 -0
- package/dist/commands/team.js +215 -0
- package/dist/commands/team.js.map +1 -0
- package/dist/commands/workspace.d.ts +12 -0
- package/dist/commands/workspace.d.ts.map +1 -0
- package/dist/commands/workspace.js +189 -0
- package/dist/commands/workspace.js.map +1 -0
- package/dist/commands/write.d.ts.map +1 -1
- package/dist/commands/write.js +4 -0
- package/dist/commands/write.js.map +1 -1
- package/dist/components/MultiSelect.d.ts +17 -0
- package/dist/components/MultiSelect.d.ts.map +1 -0
- package/dist/components/MultiSelect.js +7 -0
- package/dist/components/MultiSelect.js.map +1 -0
- package/dist/config.d.ts +3 -15
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +28 -61
- package/dist/config.js.map +1 -1
- package/dist/core/decay-engine.d.ts +11 -0
- package/dist/core/decay-engine.d.ts.map +1 -1
- package/dist/core/decay-engine.js +11 -0
- package/dist/core/decay-engine.js.map +1 -1
- package/dist/core/embedding.d.ts +1 -1
- package/dist/core/embedding.d.ts.map +1 -1
- package/dist/core/embedding.js +13 -0
- package/dist/core/embedding.js.map +1 -1
- package/dist/core/lifecycle-manager.d.ts +16 -0
- package/dist/core/lifecycle-manager.d.ts.map +1 -1
- package/dist/core/lifecycle-manager.js +86 -0
- package/dist/core/lifecycle-manager.js.map +1 -1
- package/dist/core/reranker.d.ts +14 -0
- package/dist/core/reranker.d.ts.map +1 -0
- package/dist/core/reranker.js +64 -0
- package/dist/core/reranker.js.map +1 -0
- package/dist/core/retriever.d.ts +2 -5
- package/dist/core/retriever.d.ts.map +1 -1
- package/dist/core/retriever.js +96 -16
- package/dist/core/retriever.js.map +1 -1
- package/dist/core/sanitizer.d.ts +10 -0
- package/dist/core/sanitizer.d.ts.map +1 -1
- package/dist/core/sanitizer.js +57 -39
- package/dist/core/sanitizer.js.map +1 -1
- package/dist/core/store.d.ts +16 -30
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +121 -71
- package/dist/core/store.js.map +1 -1
- package/dist/engines/lancedb-engine.d.ts.map +1 -1
- package/dist/engines/lancedb-engine.js +2 -1
- package/dist/engines/lancedb-engine.js.map +1 -1
- package/dist/platforms/claude-code.d.ts +2 -1
- package/dist/platforms/claude-code.d.ts.map +1 -1
- package/dist/platforms/claude-code.js +21 -3
- package/dist/platforms/claude-code.js.map +1 -1
- package/dist/platforms/gemini.d.ts +7 -0
- package/dist/platforms/gemini.d.ts.map +1 -0
- package/dist/platforms/gemini.js +109 -0
- package/dist/platforms/gemini.js.map +1 -0
- package/dist/platforms/qwen.d.ts +7 -0
- package/dist/platforms/qwen.d.ts.map +1 -0
- package/dist/platforms/qwen.js +109 -0
- package/dist/platforms/qwen.js.map +1 -0
- package/dist/types.d.ts +32 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +1 -1
- package/package.json +3 -2
package/dist/core/retriever.js
CHANGED
|
@@ -2,51 +2,122 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Retriever module
|
|
4
4
|
* Orchestrates engine search and formats output for MEMORY.md injection
|
|
5
|
-
* Tracks access patterns for lifecycle management
|
|
6
5
|
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
7
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
40
|
exports.recall = recall;
|
|
9
41
|
exports.writeRecallResults = writeRecallResults;
|
|
42
|
+
const path = __importStar(require("path"));
|
|
10
43
|
const store_1 = require("./store");
|
|
11
44
|
const text_engine_1 = require("../engines/text-engine");
|
|
12
45
|
const lifecycle_manager_1 = require("./lifecycle-manager");
|
|
13
|
-
|
|
46
|
+
const reranker_1 = require("./reranker");
|
|
14
47
|
function estimateTokenCount(text) {
|
|
15
48
|
return Math.ceil(text.length / 4);
|
|
16
49
|
}
|
|
17
50
|
/**
|
|
18
51
|
* Recall memories for a query
|
|
19
|
-
* Returns both the results and formatted markdown
|
|
20
|
-
* Records access for lifecycle tracking
|
|
21
52
|
*/
|
|
22
|
-
async function recall(query, repoRoot, config, engine) {
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
53
|
+
async function recall(query, repoRoot, config, engine, scope = 'all', explain = false) {
|
|
54
|
+
const globalDir = (0, store_1.getGlobalDir)(config.project.name);
|
|
55
|
+
const workspaceDir = config.workspace?.enabled
|
|
56
|
+
? (0, store_1.getWorkspaceDir)(path.basename(config.workspace.remote ?? '', '.git'))
|
|
57
|
+
: undefined;
|
|
58
|
+
const memories = (0, store_1.loadAll)(repoRoot, scope, globalDir, workspaceDir);
|
|
26
59
|
const searchEngine = engine || new text_engine_1.TextEngine();
|
|
27
|
-
|
|
60
|
+
const accessLogs = (0, lifecycle_manager_1.loadAccessLogs)(repoRoot);
|
|
28
61
|
let results = await searchEngine.search(query, memories, config.memory.top_k);
|
|
29
|
-
//
|
|
62
|
+
// Apply access frequency boost
|
|
63
|
+
results = results.map(result => {
|
|
64
|
+
const log = accessLogs[result.memory.path];
|
|
65
|
+
const accessCount = log?.accessCount ?? 0;
|
|
66
|
+
const boost = Math.min(1.5, 1.0 + Math.log1p(accessCount) / 10);
|
|
67
|
+
return { ...result, score: Math.min(1.0, result.score * boost) };
|
|
68
|
+
});
|
|
69
|
+
results.sort((a, b) => b.score - a.score);
|
|
30
70
|
for (const result of results) {
|
|
31
71
|
(0, lifecycle_manager_1.recordAccess)(repoRoot, result.memory.path, query);
|
|
32
72
|
}
|
|
33
|
-
//
|
|
34
|
-
|
|
73
|
+
// Update status for recalled memories
|
|
74
|
+
for (const result of results) {
|
|
75
|
+
(0, lifecycle_manager_1.updateStatusOnRecall)(repoRoot, result.memory.path);
|
|
76
|
+
}
|
|
77
|
+
// Apply reranker if configured
|
|
78
|
+
if (config.reranker?.enabled && results.length > 1) {
|
|
79
|
+
try {
|
|
80
|
+
results = await (0, reranker_1.rerank)(query, results, {
|
|
81
|
+
provider: config.reranker.provider,
|
|
82
|
+
model: config.reranker.model,
|
|
83
|
+
top_n: config.reranker.top_n ?? config.memory.top_k,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
// Reranker failure is non-fatal — use original order
|
|
88
|
+
console.warn(`Reranker skipped: ${e.message}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (explain && results.length > 0 && results.every(r => !r.scoreBreakdown)) {
|
|
92
|
+
console.warn('--explain: score breakdown not available for the current engine.');
|
|
93
|
+
}
|
|
94
|
+
let markdown = formatResultsAsMarkdown(results, query, config.embedding.engine, memories.length, scope, explain);
|
|
35
95
|
let tokenCount = estimateTokenCount(markdown);
|
|
36
96
|
if (tokenCount > config.memory.token_budget) {
|
|
37
|
-
// Remove results until under budget
|
|
38
97
|
while (results.length > 0 && tokenCount > config.memory.token_budget) {
|
|
39
98
|
results.pop();
|
|
40
|
-
markdown = formatResultsAsMarkdown(results, query, config.embedding.engine, memories.length);
|
|
99
|
+
markdown = formatResultsAsMarkdown(results, query, config.embedding.engine, memories.length, scope, explain);
|
|
41
100
|
tokenCount = estimateTokenCount(markdown);
|
|
42
101
|
}
|
|
43
102
|
}
|
|
44
103
|
return { results, markdown };
|
|
45
104
|
}
|
|
105
|
+
function scopeLabel(scope) {
|
|
106
|
+
if (scope === 'workspace') {
|
|
107
|
+
return '🌐 workspace';
|
|
108
|
+
}
|
|
109
|
+
if (scope === 'project') {
|
|
110
|
+
return '📁 project';
|
|
111
|
+
}
|
|
112
|
+
if (scope === 'personal') {
|
|
113
|
+
return '👤 personal';
|
|
114
|
+
}
|
|
115
|
+
return '';
|
|
116
|
+
}
|
|
46
117
|
/**
|
|
47
118
|
* Format recall results as markdown for MEMORY.md
|
|
48
119
|
*/
|
|
49
|
-
function formatResultsAsMarkdown(results, query, engine, totalMemories) {
|
|
120
|
+
function formatResultsAsMarkdown(results, query, engine, totalMemories, scope = 'all', explain = false) {
|
|
50
121
|
let markdown = `<!-- Last updated: ${new Date().toISOString()} | query: "${query}" | engine: ${engine} | top ${results.length} of ${totalMemories} -->\n\n`;
|
|
51
122
|
markdown += `## Recalled Memory\n\n`;
|
|
52
123
|
if (results.length === 0) {
|
|
@@ -58,10 +129,19 @@ function formatResultsAsMarkdown(results, query, engine, totalMemories) {
|
|
|
58
129
|
const confidenceStr = memory.confidence ? ` · ${memory.confidence} confidence` : '';
|
|
59
130
|
const tagStr = memory.tags.length > 0 ? ` · tags: ${memory.tags.join(', ')}` : '';
|
|
60
131
|
const relativePath = memory.path.replace(/^.*\/memobank\//, '');
|
|
61
|
-
|
|
132
|
+
// Show scope label only when results come from both sources
|
|
133
|
+
const showScope = scope === 'all' && memory.scope !== undefined;
|
|
134
|
+
const sourcePart = showScope ? ` | ${scopeLabel(memory.scope)}` : '';
|
|
135
|
+
markdown += `### [score: ${score.toFixed(2)}${sourcePart}] ${memory.name}${confidenceStr}\n`;
|
|
136
|
+
if (explain && result.scoreBreakdown) {
|
|
137
|
+
const b = result.scoreBreakdown;
|
|
138
|
+
const parts = [`keyword(${b.keyword.toFixed(2)})`, `tags(${b.tags.toFixed(2)})`, `recency(${b.recency.toFixed(2)})`];
|
|
139
|
+
markdown += ` matched: ${parts.join(' + ')}\n`;
|
|
140
|
+
}
|
|
62
141
|
markdown += `> ${memory.description}\n`;
|
|
63
142
|
markdown += `> \`${relativePath}\`${tagStr}\n\n`;
|
|
64
143
|
}
|
|
144
|
+
markdown += `---\n*To flag a result: memo correct <file> --reason "not relevant"*\n\n`;
|
|
65
145
|
}
|
|
66
146
|
const tokenCount = estimateTokenCount(markdown);
|
|
67
147
|
markdown += `---\n`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retriever.js","sourceRoot":"","sources":["../../src/core/retriever.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"retriever.js","sourceRoot":"","sources":["../../src/core/retriever.ts"],"names":[],"mappings":"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"}
|
package/dist/core/sanitizer.d.ts
CHANGED
|
@@ -6,4 +6,14 @@
|
|
|
6
6
|
* Sanitize content by replacing sensitive patterns with [REDACTED]
|
|
7
7
|
*/
|
|
8
8
|
export declare function sanitize(content: string): string;
|
|
9
|
+
export interface SecretFinding {
|
|
10
|
+
line: number;
|
|
11
|
+
content: string;
|
|
12
|
+
label: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Scan content for potential secrets without modifying it.
|
|
16
|
+
* Returns human-readable findings with line numbers.
|
|
17
|
+
*/
|
|
18
|
+
export declare function scanForSecrets(content: string): string[];
|
|
9
19
|
//# sourceMappingURL=sanitizer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../../src/core/sanitizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../../src/core/sanitizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAyBH;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkBhD;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBxD"}
|
package/dist/core/sanitizer.js
CHANGED
|
@@ -5,53 +5,71 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.sanitize = sanitize;
|
|
8
|
+
exports.scanForSecrets = scanForSecrets;
|
|
9
|
+
/** Patterns used both for sanitization and scanning */
|
|
10
|
+
const SECRET_PATTERNS = [
|
|
11
|
+
{ pattern: /sk-[A-Za-z0-9]{20,}/g, label: 'OpenAI API key' },
|
|
12
|
+
{ pattern: /ghp_[A-Za-z0-9]{36}/g, label: 'GitHub token' },
|
|
13
|
+
{ pattern: /Bearer [A-Za-z0-9._-]{20,}/g, label: 'Bearer token' },
|
|
14
|
+
{ pattern: /AKIA[0-9A-Z]{16}/g, label: 'AWS access key' },
|
|
15
|
+
{ pattern: /eyJ[A-Za-z0-9._-]{50,}\.[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+/g, label: 'JWT token' },
|
|
16
|
+
{ pattern: /[A-Z_]+=["']?[A-Za-z0-9/+]{20,}["']?/g, label: '.env secret' },
|
|
17
|
+
// IPv4 private ranges (full octets to avoid matching version numbers/dates)
|
|
18
|
+
{ pattern: /\b192\.168\.\d{1,3}\.\d{1,3}\b/g, label: 'private IP (192.168.x.x)' },
|
|
19
|
+
{ pattern: /\b10\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g, label: 'private IP (10.x.x.x)' },
|
|
20
|
+
{ pattern: /\b172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}\b/g, label: 'private IP (172.16-31.x.x)' },
|
|
21
|
+
// IPv6
|
|
22
|
+
{ pattern: /\b([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/g, label: 'IPv6 address' },
|
|
23
|
+
// Semantic password/secret patterns
|
|
24
|
+
{ pattern: /password\s*(is|=|:)\s*\S+/gi, label: 'password value' },
|
|
25
|
+
{ pattern: /secret\s*(is|=|:)\s*\S+/gi, label: 'secret value' },
|
|
26
|
+
{ pattern: /token\s*(is|=|:)\s*\S+/gi, label: 'token value' },
|
|
27
|
+
// Chinese-language patterns
|
|
28
|
+
{ pattern: /密码[是为::]\s*\S+/g, label: '中文密码' },
|
|
29
|
+
{ pattern: /密钥[是为::]\s*\S+/g, label: '中文密钥' },
|
|
30
|
+
];
|
|
8
31
|
/**
|
|
9
32
|
* Sanitize content by replacing sensitive patterns with [REDACTED]
|
|
10
33
|
*/
|
|
11
34
|
function sanitize(content) {
|
|
12
35
|
let sanitized = content;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
sanitized = sanitized.replace(/Bearer [A-Za-z0-9._-]{20,}/g, 'Bearer [REDACTED]');
|
|
20
|
-
// 2. IP addresses
|
|
21
|
-
// IPv4
|
|
22
|
-
sanitized = sanitized.replace(/\b\d{1,3}(\.\d{1,3}){3}\b/g, (match) => {
|
|
23
|
-
const parts = match.split('.');
|
|
24
|
-
// Check if it's a valid IP (all parts 0-255)
|
|
25
|
-
if (parts.every((part) => {
|
|
26
|
-
const num = parseInt(part, 10);
|
|
27
|
-
return num >= 0 && num <= 255;
|
|
28
|
-
})) {
|
|
29
|
-
return '[REDACTED]';
|
|
30
|
-
}
|
|
31
|
-
return match;
|
|
32
|
-
});
|
|
33
|
-
// IPv6 (simplified pattern)
|
|
34
|
-
sanitized = sanitized.replace(/\b([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/g, '[REDACTED]');
|
|
35
|
-
// 3. JWT tokens
|
|
36
|
-
sanitized = sanitized.replace(/eyJ[A-Za-z0-9._-]{50,}\.[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+/g, '[REDACTED]');
|
|
37
|
-
// 4. .env-style variables with long values
|
|
38
|
-
sanitized = sanitized.replace(/[A-Z_]+=["']?[A-Za-z0-9/+]{20,}["']?/g, (match) => {
|
|
39
|
-
// Replace the value part only
|
|
40
|
-
return match.replace(/=["']?[A-Za-z0-9/+]{20,}["']?/, '=[REDACTED]');
|
|
41
|
-
});
|
|
42
|
-
// 5. AWS Access Keys
|
|
43
|
-
sanitized = sanitized.replace(/AKIA[0-9A-Z]{16}/g, '[REDACTED]');
|
|
44
|
-
// 6. Generic API keys (alphanumeric with special chars, 20+ chars)
|
|
36
|
+
for (const { pattern } of SECRET_PATTERNS) {
|
|
37
|
+
// Reset lastIndex for global patterns
|
|
38
|
+
pattern.lastIndex = 0;
|
|
39
|
+
sanitized = sanitized.replace(pattern, '[REDACTED]');
|
|
40
|
+
}
|
|
41
|
+
// Generic 20+ char alphanumeric (excludes hashes)
|
|
45
42
|
sanitized = sanitized.replace(/\b[A-Za-z0-9_\-]{20,}\b/g, (match) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (/^[a-f0-9]{40}$/.test(match))
|
|
50
|
-
return match;
|
|
51
|
-
|
|
52
|
-
|
|
43
|
+
if (/^[a-f0-9]{32}$/.test(match)) {
|
|
44
|
+
return match;
|
|
45
|
+
} // MD5
|
|
46
|
+
if (/^[a-f0-9]{40}$/.test(match)) {
|
|
47
|
+
return match;
|
|
48
|
+
} // SHA1
|
|
49
|
+
if (/^[a-f0-9]{64}$/.test(match)) {
|
|
50
|
+
return match;
|
|
51
|
+
} // SHA256
|
|
53
52
|
return '[REDACTED]';
|
|
54
53
|
});
|
|
55
54
|
return sanitized;
|
|
56
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Scan content for potential secrets without modifying it.
|
|
58
|
+
* Returns human-readable findings with line numbers.
|
|
59
|
+
*/
|
|
60
|
+
function scanForSecrets(content) {
|
|
61
|
+
const lines = content.split('\n');
|
|
62
|
+
const findings = [];
|
|
63
|
+
for (let i = 0; i < lines.length; i++) {
|
|
64
|
+
const line = lines[i];
|
|
65
|
+
for (const { pattern, label } of SECRET_PATTERNS) {
|
|
66
|
+
pattern.lastIndex = 0;
|
|
67
|
+
if (pattern.test(line)) {
|
|
68
|
+
findings.push(`line ${i + 1} (${label}): ${line.substring(0, 120)}`);
|
|
69
|
+
break; // one finding per line
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return findings;
|
|
74
|
+
}
|
|
57
75
|
//# sourceMappingURL=sanitizer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../../src/core/sanitizer.ts"],"names":[],"mappings":";AAAA;;;GAGG;;
|
|
1
|
+
{"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../../src/core/sanitizer.ts"],"names":[],"mappings":"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"}
|
package/dist/core/store.d.ts
CHANGED
|
@@ -1,40 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
* Resolution order:
|
|
9
|
-
* 1. --repo CLI flag (passed as parameter)
|
|
10
|
-
* 2. MEMOBANK_REPO env var
|
|
11
|
-
* 3. meta/config.yaml in cwd or parent dirs (walk up)
|
|
12
|
-
* 4. ~/.memobank/<git-repo-name>/
|
|
13
|
-
* 5. ~/.memobank/default/
|
|
14
|
-
*/
|
|
1
|
+
import { MemoryFile, MemoryScope, Status } from '../types';
|
|
2
|
+
/** Personal tier: ~/.memobank/<project-name>/ */
|
|
3
|
+
export declare function getGlobalDir(projectName: string): string;
|
|
4
|
+
/** Project/team tier: the repo root itself (.memobank/ in repo) */
|
|
5
|
+
export declare function getProjectDir(repoRoot: string): string;
|
|
6
|
+
/** Workspace tier (cross-repo): ~/.memobank/_workspace/<name>/ */
|
|
7
|
+
export declare function getWorkspaceDir(workspaceName: string): string;
|
|
15
8
|
export declare function findRepoRoot(cwd: string, repoFlag?: string): string;
|
|
9
|
+
/** Find the git repo root (the dir containing .git), or return cwd. */
|
|
10
|
+
export declare function findGitRoot(cwd: string): string;
|
|
16
11
|
/**
|
|
17
|
-
* Load
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Load a single memory file
|
|
12
|
+
* Load memories from all configured tiers.
|
|
13
|
+
* Priority: project > personal > workspace (for deduplication by filename).
|
|
14
|
+
* globalDir and workspaceDir are optional; if absent, those tiers are skipped silently.
|
|
22
15
|
*/
|
|
16
|
+
export declare function loadAll(repoRoot: string, scope?: MemoryScope | 'all', globalDir?: string, workspaceDir?: string): MemoryFile[];
|
|
23
17
|
export declare function loadFile(filePath: string): MemoryFile;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
*/
|
|
28
|
-
export declare function writeMemory(repoRoot: string, memory: Omit<MemoryFile, 'path'>): string;
|
|
29
|
-
/**
|
|
30
|
-
* Update MEMORY.md with recall results
|
|
31
|
-
*/
|
|
18
|
+
export declare function writeMemory(repoRoot: string, memory: Omit<MemoryFile, 'path' | 'scope'>): string;
|
|
19
|
+
/** Patch status in a memory file's frontmatter in-place */
|
|
20
|
+
export declare function updateMemoryStatus(filePath: string, status: Status): void;
|
|
32
21
|
export declare function writeMemoryMd(repoRoot: string, results: Array<{
|
|
33
22
|
memory: MemoryFile;
|
|
34
23
|
score: number;
|
|
35
24
|
}>, query: string, engine: string): void;
|
|
36
|
-
/**
|
|
37
|
-
* Read MEMORY.md content
|
|
38
|
-
*/
|
|
39
25
|
export declare function readMemoryMd(repoRoot: string): string | null;
|
|
40
26
|
//# sourceMappingURL=store.d.ts.map
|
package/dist/core/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/core/store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/core/store.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAA0B,WAAW,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAQnF,iDAAiD;AACjD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE7D;AAQD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAmCnE;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO/C;AAoBD;;;;GAIG;AACH,wBAAgB,OAAO,CACrB,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,WAAW,GAAG,KAAa,EAClC,SAAS,CAAC,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,UAAU,EAAE,CA8Bd;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAyBrD;AAED,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,GACzC,MAAM,CAyBR;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAKzE;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,KAAK,CAAC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EACrD,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,IAAI,CAuBN;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI5D"}
|