memorix 1.1.8 → 1.1.9
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 +9 -0
- package/dist/cli/index.js +132 -74
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +123 -63
- package/dist/index.js.map +1 -1
- package/dist/memcode-runtime/CHANGELOG.md +9 -0
- package/dist/memcode-runtime/package.json +4 -4
- package/dist/sdk.js +123 -63
- package/dist/sdk.js.map +1 -1
- package/docs/API_REFERENCE.md +2 -0
- package/docs/CONFIGURATION.md +18 -0
- package/docs/dev-log/progress.txt +15 -31
- package/package.json +1 -1
- package/src/cli/commands/codegraph.ts +4 -0
- package/src/cli/commands/config-get.ts +9 -2
- package/src/cli/commands/doctor.ts +3 -0
- package/src/codegraph/auto-context.ts +6 -0
- package/src/codegraph/context-pack.ts +7 -10
- package/src/codegraph/exclude.ts +47 -0
- package/src/codegraph/lite-provider.ts +3 -26
- package/src/codegraph/project-context.ts +13 -19
- package/src/config/resolved-config.ts +6 -0
- package/src/config/toml-loader.ts +4 -0
- package/src/config/yaml-loader.ts +7 -0
- package/src/server.ts +3 -0
- package/src/store/orama-store.ts +15 -8
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.1.9] - 2026-07-12
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **Configurable CodeGraph excludes** -- Added `[codegraph].exclude_patterns` / YAML `codegraph.excludePatterns` support so CodeGraph, Project Context suggested reads, context packs, diagnostics, and related CLI flows can skip project-specific generated or vendor paths while keeping the built-in defaults.
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **Config inspection aliases** -- `memorix config get` now accepts TOML-style snake_case dotted keys such as `codegraph.exclude_patterns` when reading resolved camelCase config values.
|
|
12
|
+
- **Orama search index consistency** -- Search access tracking now preserves internally stored vector-backed documents, public/detail cache results continue to strip embeddings, and hydration reconciles persisted observations by exact composite ID instead of skipping observation hydration when a shared index already contains mini-skills.
|
|
13
|
+
|
|
5
14
|
## [1.1.8] - 2026-07-08
|
|
6
15
|
|
|
7
16
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memorix/memcode",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.9",
|
|
4
4
|
"description": "Memorix-native coding agent CLI with terminal chat, project memory, hooks, and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"piConfig": {
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"prepublishOnly": "npm run clean && npm run build"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@memorix/agent-core": "1.1.
|
|
38
|
-
"@memorix/ai": "1.1.
|
|
39
|
-
"@memorix/tui": "1.1.
|
|
37
|
+
"@memorix/agent-core": "1.1.9",
|
|
38
|
+
"@memorix/ai": "1.1.9",
|
|
39
|
+
"@memorix/tui": "1.1.9",
|
|
40
40
|
"@opentui/core": "^0.3.4",
|
|
41
41
|
"@opentui/react": "^0.3.4",
|
|
42
42
|
"@silvia-odwyer/photon-node": "0.3.4",
|
package/dist/sdk.js
CHANGED
|
@@ -1791,6 +1791,7 @@ function loadYamlConfig(projectRoot) {
|
|
|
1791
1791
|
agent: { ...userConfig.agent, ...projectConfig.agent },
|
|
1792
1792
|
embedding: { ...userConfig.embedding, ...projectConfig.embedding },
|
|
1793
1793
|
git: { ...userConfig.git, ...projectConfig.git },
|
|
1794
|
+
codegraph: { ...userConfig.codegraph, ...projectConfig.codegraph },
|
|
1794
1795
|
behavior: { ...userConfig.behavior, ...projectConfig.behavior },
|
|
1795
1796
|
server: { ...userConfig.server, ...projectConfig.server },
|
|
1796
1797
|
team: { ...userConfig.team, ...projectConfig.team }
|
|
@@ -2073,6 +2074,7 @@ function mergeTomlConfig(base, override) {
|
|
|
2073
2074
|
embedding: { ...base.embedding, ...override.embedding },
|
|
2074
2075
|
hooks: { ...base.hooks, ...override.hooks },
|
|
2075
2076
|
git: { ...base.git, ...override.git },
|
|
2077
|
+
codegraph: { ...base.codegraph, ...override.codegraph },
|
|
2076
2078
|
server: { ...base.server, ...override.server }
|
|
2077
2079
|
};
|
|
2078
2080
|
}
|
|
@@ -2214,6 +2216,15 @@ var init_dotenv_loader = __esm({
|
|
|
2214
2216
|
});
|
|
2215
2217
|
|
|
2216
2218
|
// src/config/resolved-config.ts
|
|
2219
|
+
var resolved_config_exports = {};
|
|
2220
|
+
__export(resolved_config_exports, {
|
|
2221
|
+
getResolvedAgentLane: () => getResolvedAgentLane,
|
|
2222
|
+
getResolvedConfig: () => getResolvedConfig,
|
|
2223
|
+
getResolvedConfigForCwd: () => getResolvedConfigForCwd,
|
|
2224
|
+
getResolvedEmbeddingLane: () => getResolvedEmbeddingLane,
|
|
2225
|
+
getResolvedMemoryLane: () => getResolvedMemoryLane,
|
|
2226
|
+
resetResolvedConfigCache: () => resetResolvedConfigCache
|
|
2227
|
+
});
|
|
2217
2228
|
import { homedir as homedir5 } from "os";
|
|
2218
2229
|
import { existsSync as existsSync6 } from "fs";
|
|
2219
2230
|
function getResolvedConfig(options = {}) {
|
|
@@ -2291,6 +2302,9 @@ function getResolvedConfig(options = {}) {
|
|
|
2291
2302
|
excludePatterns: firstArray(toml.git?.exclude_patterns, yaml2.git?.excludePatterns),
|
|
2292
2303
|
noiseKeywords: firstArray(toml.git?.noise_keywords, yaml2.git?.noiseKeywords)
|
|
2293
2304
|
},
|
|
2305
|
+
codegraph: {
|
|
2306
|
+
excludePatterns: firstArray(toml.codegraph?.exclude_patterns, yaml2.codegraph?.excludePatterns)
|
|
2307
|
+
},
|
|
2294
2308
|
server: {
|
|
2295
2309
|
transport: first(toml.server?.transport, yaml2.server?.transport),
|
|
2296
2310
|
dashboard: firstBool(toml.server?.dashboard, yaml2.server?.dashboard),
|
|
@@ -2312,6 +2326,10 @@ function getResolvedConfig(options = {}) {
|
|
|
2312
2326
|
};
|
|
2313
2327
|
return resolved;
|
|
2314
2328
|
}
|
|
2329
|
+
function getResolvedConfigForCwd(cwd = process.cwd()) {
|
|
2330
|
+
const project = detectProject(cwd);
|
|
2331
|
+
return getResolvedConfig({ projectRoot: project?.rootPath ?? null });
|
|
2332
|
+
}
|
|
2315
2333
|
function getResolvedAgentLane(options = {}) {
|
|
2316
2334
|
const resolved = getResolvedConfig(options);
|
|
2317
2335
|
return {
|
|
@@ -2328,6 +2346,8 @@ function getResolvedMemoryLane(options = {}) {
|
|
|
2328
2346
|
function getResolvedEmbeddingLane(options = {}) {
|
|
2329
2347
|
return getResolvedConfig(options).embedding;
|
|
2330
2348
|
}
|
|
2349
|
+
function resetResolvedConfigCache() {
|
|
2350
|
+
}
|
|
2331
2351
|
function first(...values) {
|
|
2332
2352
|
return values.find((value) => value !== void 0 && value !== null && value !== "");
|
|
2333
2353
|
}
|
|
@@ -4822,7 +4842,7 @@ __export(orama_store_exports, {
|
|
|
4822
4842
|
resetDb: () => resetDb,
|
|
4823
4843
|
searchObservations: () => searchObservations
|
|
4824
4844
|
});
|
|
4825
|
-
import { create, insert as insert2, search, remove as remove2, update, count } from "@orama/orama";
|
|
4845
|
+
import { create, insert as insert2, search, remove as remove2, update, count, getByID } from "@orama/orama";
|
|
4826
4846
|
function getLastSearchMode(projectId) {
|
|
4827
4847
|
return lastSearchModeByProject.get(projectId ?? SEARCH_MODE_DEFAULT_KEY) ?? "fulltext";
|
|
4828
4848
|
}
|
|
@@ -4833,8 +4853,12 @@ function makeEntryKey(projectId, observationId) {
|
|
|
4833
4853
|
return `${projectId ?? ""}::${observationId}`;
|
|
4834
4854
|
}
|
|
4835
4855
|
function rememberObservationDoc(doc) {
|
|
4836
|
-
|
|
4837
|
-
|
|
4856
|
+
const publicDoc = { ...doc };
|
|
4857
|
+
delete publicDoc.embedding;
|
|
4858
|
+
if (doc.projectId && typeof doc.observationId === "number") {
|
|
4859
|
+
docByObservationKey.set(makeEntryKey(doc.projectId, doc.observationId), publicDoc);
|
|
4860
|
+
}
|
|
4861
|
+
return publicDoc;
|
|
4838
4862
|
}
|
|
4839
4863
|
function isCommandLikeQuery(query) {
|
|
4840
4864
|
return COMMAND_LIKE_QUERY2.test(query);
|
|
@@ -4936,14 +4960,14 @@ async function batchGenerateEmbeddings(texts) {
|
|
|
4936
4960
|
}
|
|
4937
4961
|
async function hydrateIndex(observations2) {
|
|
4938
4962
|
const database = await getDb();
|
|
4939
|
-
const currentCount = await count(database);
|
|
4940
|
-
if (currentCount > 0) return 0;
|
|
4941
4963
|
let inserted = 0;
|
|
4942
4964
|
for (const obs of observations2) {
|
|
4943
4965
|
if (!obs || !obs.id || !obs.projectId) continue;
|
|
4944
4966
|
try {
|
|
4967
|
+
const id = makeOramaObservationId(obs.projectId, obs.id);
|
|
4968
|
+
if (getByID(database, id)) continue;
|
|
4945
4969
|
const doc = {
|
|
4946
|
-
id
|
|
4970
|
+
id,
|
|
4947
4971
|
observationId: obs.id,
|
|
4948
4972
|
entityName: obs.entityName || "",
|
|
4949
4973
|
type: obs.type || "discovery",
|
|
@@ -5037,6 +5061,7 @@ async function searchObservations(options) {
|
|
|
5037
5061
|
let searchParams = {
|
|
5038
5062
|
term: originalQuery,
|
|
5039
5063
|
limit: requestLimit,
|
|
5064
|
+
includeVectors: true,
|
|
5040
5065
|
...Object.keys(filters).length > 0 ? { where: filters } : {},
|
|
5041
5066
|
// Search specific fields (not tokens, accessCount, etc.)
|
|
5042
5067
|
properties: ["title", "entityName", "narrative", "facts", "concepts", "filesModified"],
|
|
@@ -5108,6 +5133,7 @@ async function searchObservations(options) {
|
|
|
5108
5133
|
const vectorOnlyParams = {
|
|
5109
5134
|
term: "",
|
|
5110
5135
|
limit: requestLimit,
|
|
5136
|
+
includeVectors: true,
|
|
5111
5137
|
...Object.keys(filters).length > 0 ? { where: filters } : {},
|
|
5112
5138
|
mode: "vector",
|
|
5113
5139
|
vector: {
|
|
@@ -5406,6 +5432,7 @@ async function getObservationsByIds(ids, projectId) {
|
|
|
5406
5432
|
}
|
|
5407
5433
|
const searchResult = await search(database, {
|
|
5408
5434
|
term: "",
|
|
5435
|
+
includeVectors: true,
|
|
5409
5436
|
where: {
|
|
5410
5437
|
observationId: { eq: id },
|
|
5411
5438
|
...projectId ? { projectId } : {}
|
|
@@ -5413,7 +5440,7 @@ async function getObservationsByIds(ids, projectId) {
|
|
|
5413
5440
|
limit: 1
|
|
5414
5441
|
});
|
|
5415
5442
|
if (searchResult.hits.length > 0) {
|
|
5416
|
-
results.push(searchResult.hits[0].document);
|
|
5443
|
+
results.push(rememberObservationDoc(searchResult.hits[0].document));
|
|
5417
5444
|
}
|
|
5418
5445
|
}
|
|
5419
5446
|
return results;
|
|
@@ -9300,6 +9327,58 @@ var init_current_facts = __esm({
|
|
|
9300
9327
|
}
|
|
9301
9328
|
});
|
|
9302
9329
|
|
|
9330
|
+
// src/codegraph/exclude.ts
|
|
9331
|
+
function normalizeCodeGraphExcludePatterns(exclude) {
|
|
9332
|
+
return [.../* @__PURE__ */ new Set([
|
|
9333
|
+
...DEFAULT_CODEGRAPH_EXCLUDES,
|
|
9334
|
+
...(exclude ?? []).map((pattern) => pattern.trim()).filter(Boolean)
|
|
9335
|
+
])];
|
|
9336
|
+
}
|
|
9337
|
+
function isCodeGraphExcludedPath(path20, exclude) {
|
|
9338
|
+
const normalized = normalizeCodePath2(path20);
|
|
9339
|
+
return normalizeCodeGraphExcludePatterns(exclude).some((pattern) => matchesPattern(normalized, normalizeCodePath2(pattern)));
|
|
9340
|
+
}
|
|
9341
|
+
function normalizeCodePath2(path20) {
|
|
9342
|
+
return path20.replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
9343
|
+
}
|
|
9344
|
+
function matchesPattern(path20, pattern) {
|
|
9345
|
+
if (pattern.endsWith("/**")) {
|
|
9346
|
+
const base = pattern.slice(0, -3);
|
|
9347
|
+
if (base.startsWith("**/")) {
|
|
9348
|
+
const suffix = base.slice(3);
|
|
9349
|
+
return path20 === suffix || path20.endsWith(`/${suffix}`) || path20.includes(`/${suffix}/`);
|
|
9350
|
+
}
|
|
9351
|
+
if (!base.includes("/")) {
|
|
9352
|
+
return path20 === base || path20.startsWith(`${base}/`) || path20.includes(`/${base}/`);
|
|
9353
|
+
}
|
|
9354
|
+
return path20 === base || path20.startsWith(`${base}/`);
|
|
9355
|
+
}
|
|
9356
|
+
if (pattern.startsWith("**/")) {
|
|
9357
|
+
const suffix = pattern.slice(3);
|
|
9358
|
+
return path20 === suffix || path20.endsWith(`/${suffix}`);
|
|
9359
|
+
}
|
|
9360
|
+
return path20 === pattern || path20.startsWith(`${pattern}/`);
|
|
9361
|
+
}
|
|
9362
|
+
var DEFAULT_CODEGRAPH_EXCLUDES;
|
|
9363
|
+
var init_exclude = __esm({
|
|
9364
|
+
"src/codegraph/exclude.ts"() {
|
|
9365
|
+
"use strict";
|
|
9366
|
+
init_esm_shims();
|
|
9367
|
+
DEFAULT_CODEGRAPH_EXCLUDES = [
|
|
9368
|
+
"node_modules/**",
|
|
9369
|
+
"dist/**",
|
|
9370
|
+
"build/**",
|
|
9371
|
+
"coverage/**",
|
|
9372
|
+
".next/**",
|
|
9373
|
+
".turbo/**",
|
|
9374
|
+
".git/**",
|
|
9375
|
+
".tmp/**",
|
|
9376
|
+
".worktrees/**",
|
|
9377
|
+
".claude/worktrees/**"
|
|
9378
|
+
];
|
|
9379
|
+
}
|
|
9380
|
+
});
|
|
9381
|
+
|
|
9303
9382
|
// src/codegraph/lite-provider.ts
|
|
9304
9383
|
import { createHash as createHash5 } from "crypto";
|
|
9305
9384
|
import { readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync2 } from "fs";
|
|
@@ -9315,18 +9394,6 @@ function languageForPath(path20) {
|
|
|
9315
9394
|
const ext = extension(path20);
|
|
9316
9395
|
return LANGUAGE_BY_EXTENSION.get(ext) ?? "unknown";
|
|
9317
9396
|
}
|
|
9318
|
-
function isExcluded(path20, exclude) {
|
|
9319
|
-
const normalized = normalizeCodePath(path20);
|
|
9320
|
-
return exclude.some((pattern) => {
|
|
9321
|
-
const p = normalizeCodePath(pattern);
|
|
9322
|
-
if (p.endsWith("/**")) {
|
|
9323
|
-
const base = p.slice(0, -3);
|
|
9324
|
-
return normalized === base || normalized.startsWith(`${base}/`);
|
|
9325
|
-
}
|
|
9326
|
-
if (p.startsWith("**/")) return normalized.endsWith(p.slice(3));
|
|
9327
|
-
return normalized === p || normalized.startsWith(`${p}/`);
|
|
9328
|
-
});
|
|
9329
|
-
}
|
|
9330
9397
|
function walk(root, exclude, maxFiles) {
|
|
9331
9398
|
const out = [];
|
|
9332
9399
|
const visit = (dir) => {
|
|
@@ -9340,7 +9407,7 @@ function walk(root, exclude, maxFiles) {
|
|
|
9340
9407
|
for (const entry of entries) {
|
|
9341
9408
|
const abs = join20(dir, entry.name);
|
|
9342
9409
|
const rel = normalizeCodePath(relative(root, abs));
|
|
9343
|
-
if (
|
|
9410
|
+
if (isCodeGraphExcludedPath(rel, exclude)) continue;
|
|
9344
9411
|
if (entry.isDirectory()) {
|
|
9345
9412
|
if (entry.name === ".git" || entry.name === ".worktrees" || entry.name === ".tmp" || entry.name === "node_modules") continue;
|
|
9346
9413
|
if (rel === ".claude/worktrees" || rel.startsWith(".claude/worktrees/")) continue;
|
|
@@ -9428,18 +9495,7 @@ function extractImportEdges(projectId, file, text, indexedAt) {
|
|
|
9428
9495
|
return edges;
|
|
9429
9496
|
}
|
|
9430
9497
|
async function indexProjectLite(options) {
|
|
9431
|
-
const exclude = options.exclude
|
|
9432
|
-
"node_modules/**",
|
|
9433
|
-
"dist/**",
|
|
9434
|
-
"build/**",
|
|
9435
|
-
"coverage/**",
|
|
9436
|
-
".next/**",
|
|
9437
|
-
".turbo/**",
|
|
9438
|
-
".git/**",
|
|
9439
|
-
".tmp/**",
|
|
9440
|
-
".worktrees/**",
|
|
9441
|
-
".claude/worktrees/**"
|
|
9442
|
-
];
|
|
9498
|
+
const exclude = normalizeCodeGraphExcludePatterns(options.exclude);
|
|
9443
9499
|
const maxFiles = options.maxFiles ?? 5e3;
|
|
9444
9500
|
const indexedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
9445
9501
|
const paths = walk(options.projectRoot, exclude, maxFiles);
|
|
@@ -9478,6 +9534,7 @@ var init_lite_provider = __esm({
|
|
|
9478
9534
|
"use strict";
|
|
9479
9535
|
init_esm_shims();
|
|
9480
9536
|
init_ids();
|
|
9537
|
+
init_exclude();
|
|
9481
9538
|
LANGUAGE_BY_EXTENSION = /* @__PURE__ */ new Map([
|
|
9482
9539
|
[".ts", "typescript"],
|
|
9483
9540
|
[".tsx", "typescript"],
|
|
@@ -9647,24 +9704,17 @@ function countLanguages(files) {
|
|
|
9647
9704
|
}
|
|
9648
9705
|
return [...counts.entries()].map(([language, files2]) => ({ language, files: files2 })).sort((a, b) => a.language.localeCompare(b.language));
|
|
9649
9706
|
}
|
|
9650
|
-
function normalizePath2(path20) {
|
|
9651
|
-
return path20.replace(/\\/g, "/");
|
|
9652
|
-
}
|
|
9653
|
-
function isGeneratedPath(path20) {
|
|
9654
|
-
const normalized = normalizePath2(path20);
|
|
9655
|
-
return /(^|\/)(dist|build|coverage|\.next|\.turbo|node_modules|\.git|\.tmp|\.worktrees)(\/|$)/i.test(normalized) || /(^|\/)\.claude\/worktrees(\/|$)/i.test(normalized);
|
|
9656
|
-
}
|
|
9657
9707
|
function suggestedReadRank(path20) {
|
|
9658
|
-
const normalized =
|
|
9708
|
+
const normalized = path20.replace(/\\/g, "/");
|
|
9659
9709
|
if (normalized.startsWith("src/")) return 0;
|
|
9660
9710
|
if (normalized.startsWith("tests/") || normalized.startsWith("test/")) return 0;
|
|
9661
9711
|
if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 2;
|
|
9662
9712
|
return 3;
|
|
9663
9713
|
}
|
|
9664
|
-
function compactSuggestedReads(paths, limit = 8) {
|
|
9665
|
-
return uniq(paths).filter((path20) => !
|
|
9714
|
+
function compactSuggestedReads(paths, limit = 8, exclude) {
|
|
9715
|
+
return uniq(paths).filter((path20) => !isCodeGraphExcludedPath(path20, exclude)).sort((a, b) => suggestedReadRank(a) - suggestedReadRank(b)).slice(0, limit);
|
|
9666
9716
|
}
|
|
9667
|
-
function collectGraph(store, projectId, observations2) {
|
|
9717
|
+
function collectGraph(store, projectId, observations2, exclude) {
|
|
9668
9718
|
const files = store.listFiles(projectId);
|
|
9669
9719
|
const symbols = files.flatMap((file) => store.listSymbolsForFile(file.id));
|
|
9670
9720
|
const filesById = new Map(files.map((file) => [file.id, file]));
|
|
@@ -9686,7 +9736,9 @@ function collectGraph(store, projectId, observations2) {
|
|
|
9686
9736
|
freshness[result.status] += 1;
|
|
9687
9737
|
const observation = observationsById.get(ref.observationId);
|
|
9688
9738
|
if (!observation) continue;
|
|
9689
|
-
|
|
9739
|
+
const excluded = file ? isCodeGraphExcludedPath(file.path, exclude) : false;
|
|
9740
|
+
if (result.status === "current" && file && !excluded) suggestedReads.push(file.path);
|
|
9741
|
+
if (excluded) continue;
|
|
9690
9742
|
sources.push({
|
|
9691
9743
|
observationId: observation.id,
|
|
9692
9744
|
title: observation.title,
|
|
@@ -9703,12 +9755,12 @@ function collectGraph(store, projectId, observations2) {
|
|
|
9703
9755
|
refs,
|
|
9704
9756
|
freshness,
|
|
9705
9757
|
sources,
|
|
9706
|
-
suggestedReads: compactSuggestedReads(suggestedReads)
|
|
9758
|
+
suggestedReads: compactSuggestedReads(suggestedReads, 8, exclude)
|
|
9707
9759
|
};
|
|
9708
9760
|
}
|
|
9709
9761
|
function buildProjectContextOverview(input) {
|
|
9710
9762
|
const active = activeObservations(input.observations, input.project.id);
|
|
9711
|
-
const graph = collectGraph(input.store, input.project.id, active);
|
|
9763
|
+
const graph = collectGraph(input.store, input.project.id, active, input.exclude);
|
|
9712
9764
|
const status = input.store.status(input.project.id);
|
|
9713
9765
|
return {
|
|
9714
9766
|
project: input.project,
|
|
@@ -9732,7 +9784,7 @@ function buildProjectContextOverview(input) {
|
|
|
9732
9784
|
function buildProjectContextExplain(input) {
|
|
9733
9785
|
const overview = buildProjectContextOverview(input);
|
|
9734
9786
|
const active = activeObservations(input.observations, input.project.id);
|
|
9735
|
-
const graph = collectGraph(input.store, input.project.id, active);
|
|
9787
|
+
const graph = collectGraph(input.store, input.project.id, active, input.exclude);
|
|
9736
9788
|
return {
|
|
9737
9789
|
project: input.project,
|
|
9738
9790
|
sources: graph.sources.sort((a, b) => a.observationId - b.observationId || (a.path ?? "").localeCompare(b.path ?? "")),
|
|
@@ -9744,11 +9796,12 @@ var init_project_context = __esm({
|
|
|
9744
9796
|
"use strict";
|
|
9745
9797
|
init_esm_shims();
|
|
9746
9798
|
init_freshness2();
|
|
9799
|
+
init_exclude();
|
|
9747
9800
|
}
|
|
9748
9801
|
});
|
|
9749
9802
|
|
|
9750
9803
|
// src/codegraph/task-lens.ts
|
|
9751
|
-
function
|
|
9804
|
+
function normalizePath2(path20) {
|
|
9752
9805
|
return path20.replace(/\\/g, "/");
|
|
9753
9806
|
}
|
|
9754
9807
|
function tokenize(text) {
|
|
@@ -9778,7 +9831,7 @@ function resolveTaskLens(task) {
|
|
|
9778
9831
|
return best.score > 0 ? LENSES[best.id] : LENSES.general;
|
|
9779
9832
|
}
|
|
9780
9833
|
function pathKindScore(path20, lens) {
|
|
9781
|
-
const normalized =
|
|
9834
|
+
const normalized = normalizePath2(path20).toLowerCase();
|
|
9782
9835
|
const name = normalized.split("/").pop() ?? normalized;
|
|
9783
9836
|
const inDocs = normalized.startsWith("docs/") || name === "readme.md" || name.includes("readme");
|
|
9784
9837
|
const isTest = /(^|\/)(tests?|__tests__|spec|fixtures?)\//.test(normalized) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(normalized) || /\.(test|spec)\.py$/.test(normalized);
|
|
@@ -9827,7 +9880,7 @@ function sourceTaskMatchScore(source, task) {
|
|
|
9827
9880
|
return 0;
|
|
9828
9881
|
}
|
|
9829
9882
|
function fallbackPathRank(path20) {
|
|
9830
|
-
const normalized =
|
|
9883
|
+
const normalized = normalizePath2(path20);
|
|
9831
9884
|
if (normalized.startsWith("src/")) return 0;
|
|
9832
9885
|
if (normalized.startsWith("tests/") || normalized.startsWith("test/")) return 1;
|
|
9833
9886
|
if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 2;
|
|
@@ -9836,7 +9889,7 @@ function fallbackPathRank(path20) {
|
|
|
9836
9889
|
}
|
|
9837
9890
|
function rankLensPaths(paths, lens, task) {
|
|
9838
9891
|
const tokens = tokenize(task ?? "");
|
|
9839
|
-
return [...new Set(paths.map(
|
|
9892
|
+
return [...new Set(paths.map(normalizePath2))].map((path20, index) => ({
|
|
9840
9893
|
path: path20,
|
|
9841
9894
|
index,
|
|
9842
9895
|
score: pathKindScore(path20, lens) + tokenScore(path20, tokens),
|
|
@@ -10090,6 +10143,7 @@ async function buildAutoProjectContext(input) {
|
|
|
10090
10143
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
10091
10144
|
const task = input.task?.trim();
|
|
10092
10145
|
const lens = resolveTaskLens(task);
|
|
10146
|
+
const exclude = input.exclude ?? getResolvedConfig({ projectRoot: input.project.rootPath }).codegraph.excludePatterns;
|
|
10093
10147
|
const store = new CodeGraphStore();
|
|
10094
10148
|
await store.init(input.dataDir);
|
|
10095
10149
|
const initialStatus = store.status(input.project.id);
|
|
@@ -10107,7 +10161,8 @@ async function buildAutoProjectContext(input) {
|
|
|
10107
10161
|
try {
|
|
10108
10162
|
const indexed = await indexProjectLite({
|
|
10109
10163
|
projectId: input.project.id,
|
|
10110
|
-
projectRoot: input.project.rootPath
|
|
10164
|
+
projectRoot: input.project.rootPath,
|
|
10165
|
+
exclude
|
|
10111
10166
|
});
|
|
10112
10167
|
store.replaceProjectIndex(input.project.id, indexed);
|
|
10113
10168
|
const backfill = await backfillMissingObservationCodeRefs(
|
|
@@ -10127,12 +10182,14 @@ async function buildAutoProjectContext(input) {
|
|
|
10127
10182
|
const overview = buildProjectContextOverview({
|
|
10128
10183
|
project: input.project,
|
|
10129
10184
|
store,
|
|
10130
|
-
observations: input.observations
|
|
10185
|
+
observations: input.observations,
|
|
10186
|
+
exclude
|
|
10131
10187
|
});
|
|
10132
10188
|
const explain = buildProjectContextExplain({
|
|
10133
10189
|
project: input.project,
|
|
10134
10190
|
store,
|
|
10135
|
-
observations: input.observations
|
|
10191
|
+
observations: input.observations,
|
|
10192
|
+
exclude
|
|
10136
10193
|
});
|
|
10137
10194
|
return {
|
|
10138
10195
|
project: input.project,
|
|
@@ -10342,6 +10399,7 @@ var init_auto_context = __esm({
|
|
|
10342
10399
|
"src/codegraph/auto-context.ts"() {
|
|
10343
10400
|
"use strict";
|
|
10344
10401
|
init_esm_shims();
|
|
10402
|
+
init_resolved_config();
|
|
10345
10403
|
init_binder();
|
|
10346
10404
|
init_current_facts();
|
|
10347
10405
|
init_lite_provider();
|
|
@@ -10369,10 +10427,6 @@ function tokenize2(text) {
|
|
|
10369
10427
|
function timestampOf(observation) {
|
|
10370
10428
|
return Date.parse(observation.updatedAt ?? observation.createdAt ?? "") || 0;
|
|
10371
10429
|
}
|
|
10372
|
-
function isGeneratedPath2(path20) {
|
|
10373
|
-
const normalized = path20.replace(/\\/g, "/");
|
|
10374
|
-
return /(^|\/)(dist|build|coverage|\.next|\.turbo|node_modules|\.git|\.tmp|\.worktrees)(\/|$)/i.test(normalized) || /(^|\/)\.claude\/worktrees(\/|$)/i.test(normalized);
|
|
10375
|
-
}
|
|
10376
10430
|
function relevanceScore(observation, taskTokens) {
|
|
10377
10431
|
if (taskTokens.length === 0) return 0;
|
|
10378
10432
|
const title = observation.title.toLowerCase();
|
|
@@ -10423,7 +10477,8 @@ function assembleContextPackForTask(input) {
|
|
|
10423
10477
|
refs,
|
|
10424
10478
|
files,
|
|
10425
10479
|
symbols,
|
|
10426
|
-
suggestedVerification: input.suggestedVerification
|
|
10480
|
+
suggestedVerification: input.suggestedVerification,
|
|
10481
|
+
exclude: input.exclude
|
|
10427
10482
|
});
|
|
10428
10483
|
}
|
|
10429
10484
|
function assembleContextPack(input) {
|
|
@@ -10442,6 +10497,7 @@ function assembleContextPack(input) {
|
|
|
10442
10497
|
observationIdsWithRefs.add(ref.observationId);
|
|
10443
10498
|
const file = ref.fileId ? files.get(ref.fileId) : void 0;
|
|
10444
10499
|
const symbol = ref.symbolId ? symbols.get(ref.symbolId) : void 0;
|
|
10500
|
+
if (file && isCodeGraphExcludedPath(file.path, input.exclude)) continue;
|
|
10445
10501
|
const freshness = evaluateCodeRefFreshness(ref, file, symbol);
|
|
10446
10502
|
if (freshness.status === "current") {
|
|
10447
10503
|
const memoryKey = `${observation.id}:${freshness.status}`;
|
|
@@ -10507,8 +10563,8 @@ function buildContextPackPrompt(pack) {
|
|
|
10507
10563
|
const reliableMemories = pack.memories.filter((memory) => memory.status === "current");
|
|
10508
10564
|
const unboundMemories = pack.memories.filter((memory) => memory.status === "unbound");
|
|
10509
10565
|
const lines = ["## Task", pack.task, "", "## Reliable Memories"];
|
|
10510
|
-
const visibleCodeFacts = pack.codeFacts.filter((fact) => !
|
|
10511
|
-
const visibleSuggestedReads = pack.suggestedReads.filter((path20) => !
|
|
10566
|
+
const visibleCodeFacts = pack.codeFacts.filter((fact) => !isCodeGraphExcludedPath(fact.path)).slice(0, 5);
|
|
10567
|
+
const visibleSuggestedReads = pack.suggestedReads.filter((path20) => !isCodeGraphExcludedPath(path20)).slice(0, 5);
|
|
10512
10568
|
if (reliableMemories.length === 0) lines.push("- none");
|
|
10513
10569
|
for (const memory of reliableMemories) {
|
|
10514
10570
|
lines.push(`- #${memory.id} ${memory.status}: [${memory.type}] ${memory.title} (${memory.reason})`);
|
|
@@ -10543,6 +10599,7 @@ var init_context_pack = __esm({
|
|
|
10543
10599
|
"use strict";
|
|
10544
10600
|
init_esm_shims();
|
|
10545
10601
|
init_freshness2();
|
|
10602
|
+
init_exclude();
|
|
10546
10603
|
}
|
|
10547
10604
|
});
|
|
10548
10605
|
|
|
@@ -19924,7 +19981,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
19924
19981
|
};
|
|
19925
19982
|
const server = existingServer ?? new McpServer({
|
|
19926
19983
|
name: "memorix",
|
|
19927
|
-
version: true ? "1.1.
|
|
19984
|
+
version: true ? "1.1.9" : "1.0.1"
|
|
19928
19985
|
});
|
|
19929
19986
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
19930
19987
|
server.registerTool = ((name, ...args) => {
|
|
@@ -20626,15 +20683,18 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
20626
20683
|
return withFreshIndex(async () => {
|
|
20627
20684
|
const { CodeGraphStore: CodeGraphStore2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
20628
20685
|
const { assembleContextPackForTask: assembleContextPackForTask2, buildContextPackPrompt: buildContextPackPrompt2 } = await Promise.resolve().then(() => (init_context_pack(), context_pack_exports));
|
|
20686
|
+
const { getResolvedConfig: getResolvedConfig2 } = await Promise.resolve().then(() => (init_resolved_config(), resolved_config_exports));
|
|
20629
20687
|
const store = new CodeGraphStore2();
|
|
20630
20688
|
await store.init(projectDir2);
|
|
20689
|
+
const exclude = getResolvedConfig2({ projectRoot: project.rootPath }).codegraph.excludePatterns;
|
|
20631
20690
|
const observations2 = getAllObservations().filter((obs) => obs.projectId === project.id && (obs.status ?? "active") === "active").reverse();
|
|
20632
20691
|
const pack = assembleContextPackForTask2({
|
|
20633
20692
|
store,
|
|
20634
20693
|
projectId: project.id,
|
|
20635
20694
|
task,
|
|
20636
20695
|
observations: observations2,
|
|
20637
|
-
limit: typeof limit === "number" ? limit : 20
|
|
20696
|
+
limit: typeof limit === "number" ? limit : 20,
|
|
20697
|
+
exclude
|
|
20638
20698
|
});
|
|
20639
20699
|
const text = buildContextPackPrompt2(pack);
|
|
20640
20700
|
return {
|