memorix 1.1.7 → 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 +22 -0
- package/CLAUDE.md +6 -1
- package/README.md +21 -0
- package/README.zh-CN.md +21 -0
- package/TEAM.md +86 -86
- package/dist/cli/index.js +852 -214
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/static/index.html +201 -201
- package/dist/dashboard/static/style.css +3584 -3584
- package/dist/index.js +129 -62
- package/dist/index.js.map +1 -1
- package/dist/memcode-runtime/CHANGELOG.md +22 -0
- package/dist/memcode-runtime/package.json +4 -4
- package/dist/sdk.js +129 -62
- package/dist/sdk.js.map +1 -1
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +18 -0
- package/docs/API_REFERENCE.md +2 -0
- package/docs/CONFIGURATION.md +18 -0
- package/docs/DESIGN_DECISIONS.md +357 -357
- package/docs/SETUP.md +10 -0
- package/docs/dev-log/progress.txt +23 -30
- package/package.json +1 -1
- package/src/audit/index.ts +156 -156
- package/src/cli/commands/agent-integrations.ts +623 -0
- package/src/cli/commands/audit-list.ts +89 -89
- package/src/cli/commands/background.ts +659 -659
- package/src/cli/commands/cleanup.ts +255 -255
- package/src/cli/commands/codegraph.ts +4 -0
- package/src/cli/commands/config-get.ts +9 -2
- package/src/cli/commands/doctor.ts +26 -0
- package/src/cli/commands/formation.ts +48 -48
- package/src/cli/commands/git-hook-install.ts +111 -111
- package/src/cli/commands/handoff.ts +66 -66
- package/src/cli/commands/hooks-status.ts +63 -63
- package/src/cli/commands/ingest-commit.ts +153 -153
- package/src/cli/commands/ingest-image.ts +73 -73
- package/src/cli/commands/ingest-log.ts +180 -180
- package/src/cli/commands/ingest.ts +44 -44
- package/src/cli/commands/integrate-shared.ts +15 -15
- package/src/cli/commands/lock.ts +96 -96
- package/src/cli/commands/message.ts +121 -121
- package/src/cli/commands/poll.ts +70 -70
- package/src/cli/commands/purge-all-memory.ts +85 -85
- package/src/cli/commands/purge-project-memory.ts +83 -83
- package/src/cli/commands/reasoning.ts +132 -132
- package/src/cli/commands/repair.ts +60 -0
- package/src/cli/commands/retention.ts +108 -108
- package/src/cli/commands/serve-shared.ts +118 -118
- package/src/cli/commands/setup.ts +3 -3
- package/src/cli/commands/skills.ts +123 -123
- package/src/cli/commands/task.ts +192 -192
- package/src/cli/commands/transfer.ts +73 -73
- package/src/cli/commands/uninstall-project-artifacts.ts +85 -85
- package/src/cli/index.ts +3 -1
- package/src/cli/tui/ChatView.tsx +234 -234
- package/src/cli/tui/CommandBar.tsx +312 -312
- package/src/cli/tui/ContextRail.tsx +118 -118
- package/src/cli/tui/HeaderBar.tsx +72 -72
- package/src/cli/tui/LogoBanner.tsx +51 -51
- package/src/cli/tui/Panels.tsx +632 -632
- package/src/cli/tui/Sidebar.tsx +179 -179
- package/src/cli/tui/chat-service.ts +742 -742
- package/src/cli/tui/data.ts +547 -547
- package/src/cli/tui/index.ts +41 -41
- package/src/cli/tui/markdown-render.tsx +371 -371
- package/src/cli/tui/theme.ts +178 -178
- package/src/cli/tui/use-mouse.ts +157 -157
- package/src/cli/tui/useNavigation.ts +56 -56
- package/src/cli/update-checker.ts +211 -211
- package/src/cli/version.ts +7 -7
- package/src/cli/workbench.ts +1 -1
- package/src/codegraph/auto-context.ts +6 -0
- package/src/codegraph/context-pack.ts +7 -6
- package/src/codegraph/exclude.ts +47 -0
- package/src/codegraph/lite-provider.ts +5 -24
- package/src/codegraph/project-context.ts +13 -15
- package/src/compact/token-budget.ts +74 -74
- package/src/config/behavior.ts +59 -59
- 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/dashboard/project-classification.ts +64 -64
- package/src/dashboard/static/index.html +201 -201
- package/src/dashboard/static/style.css +3584 -3584
- package/src/embedding/fastembed-provider.ts +142 -142
- package/src/embedding/transformers-provider.ts +111 -111
- package/src/git/extractor.ts +209 -209
- package/src/git/hooks-path.ts +85 -85
- package/src/git/noise-filter.ts +210 -210
- package/src/hooks/installers/index.ts +4 -4
- package/src/hooks/official-skills.ts +1 -1
- package/src/hooks/pattern-detector.ts +173 -173
- package/src/hooks/rules/memorix-agent-rules.md +2 -2
- package/src/hooks/significance-filter.ts +250 -250
- package/src/llm/memory-manager.ts +328 -328
- package/src/llm/provider.ts +885 -885
- package/src/llm/quality.ts +248 -248
- package/src/memory/attribution-guard.ts +249 -249
- package/src/memory/auto-relations.ts +107 -107
- package/src/memory/consolidation.ts +302 -302
- package/src/memory/disclosure-policy.ts +141 -141
- package/src/memory/entity-extractor.ts +197 -197
- package/src/memory/formation/evaluate.ts +217 -217
- package/src/memory/formation/extract.ts +361 -361
- package/src/memory/formation/index.ts +417 -417
- package/src/memory/formation/resolve.ts +344 -344
- package/src/memory/formation/types.ts +315 -315
- package/src/memory/freshness.ts +122 -122
- package/src/memory/graph.ts +197 -197
- package/src/memory/refs.ts +94 -94
- package/src/memory/retention.ts +433 -433
- package/src/memory/secret-filter.ts +79 -79
- package/src/memory/session.ts +523 -523
- package/src/multimodal/image-loader.ts +143 -143
- package/src/orchestrate/adapters/claude-stream.ts +192 -192
- package/src/orchestrate/adapters/claude.ts +111 -111
- package/src/orchestrate/adapters/codex-stream.ts +134 -134
- package/src/orchestrate/adapters/codex.ts +41 -41
- package/src/orchestrate/adapters/gemini-stream.ts +166 -166
- package/src/orchestrate/adapters/gemini.ts +42 -42
- package/src/orchestrate/adapters/index.ts +73 -73
- package/src/orchestrate/adapters/opencode-stream.ts +143 -143
- package/src/orchestrate/adapters/opencode.ts +47 -47
- package/src/orchestrate/adapters/spawn-helper.ts +286 -286
- package/src/orchestrate/adapters/types.ts +77 -77
- package/src/orchestrate/capability-router.ts +284 -284
- package/src/orchestrate/context-compact.ts +188 -188
- package/src/orchestrate/cost-tracker.ts +219 -219
- package/src/orchestrate/error-recovery.ts +191 -191
- package/src/orchestrate/evidence.ts +140 -140
- package/src/orchestrate/ledger.ts +110 -110
- package/src/orchestrate/memorix-bridge.ts +380 -380
- package/src/orchestrate/output-budget.ts +80 -80
- package/src/orchestrate/permission.ts +152 -152
- package/src/orchestrate/pipeline-trace.ts +131 -131
- package/src/orchestrate/prompt-builder.ts +155 -155
- package/src/orchestrate/ring-buffer.ts +37 -37
- package/src/orchestrate/task-graph.ts +389 -389
- package/src/orchestrate/verify-gate.ts +219 -219
- package/src/orchestrate/worktree.ts +232 -232
- package/src/project/aliases.ts +374 -374
- package/src/project/detector.ts +268 -268
- package/src/rules/adapters/claude-code.ts +99 -99
- package/src/rules/adapters/codex.ts +97 -97
- package/src/rules/adapters/copilot.ts +124 -124
- package/src/rules/adapters/cursor.ts +114 -114
- package/src/rules/adapters/kiro.ts +126 -126
- package/src/rules/adapters/trae.ts +56 -56
- package/src/rules/adapters/windsurf.ts +83 -83
- package/src/rules/syncer.ts +235 -235
- package/src/sdk.ts +327 -327
- package/src/search/intent-detector.ts +289 -289
- package/src/search/query-expansion.ts +52 -52
- package/src/server/formation-timeout.ts +27 -27
- package/src/server.ts +3 -0
- package/src/skills/mini-skills.ts +386 -386
- package/src/store/chat-store.ts +119 -119
- package/src/store/file-lock.ts +100 -100
- package/src/store/graph-store.ts +249 -249
- package/src/store/mini-skill-store.ts +349 -349
- package/src/store/obs-store.ts +255 -255
- package/src/store/orama-store.ts +15 -8
- package/src/store/persistence-json.ts +212 -212
- package/src/store/persistence.ts +291 -291
- package/src/store/project-affinity.ts +195 -195
- package/src/store/session-store.ts +259 -259
- package/src/store/sqlite-store.ts +339 -339
- package/src/team/event-bus.ts +76 -76
- package/src/team/file-locks.ts +173 -173
- package/src/team/handoff.ts +167 -167
- package/src/team/messages.ts +203 -203
- package/src/team/poll.ts +132 -132
- package/src/team/tasks.ts +211 -211
- package/src/wiki/generator.ts +237 -237
- package/src/wiki/knowledge-graph.ts +334 -334
- package/src/wiki/types.ts +85 -85
- package/src/workspace/mcp-adapters/codex.ts +191 -191
- package/src/workspace/mcp-adapters/copilot.ts +105 -105
- package/src/workspace/mcp-adapters/cursor.ts +53 -53
- package/src/workspace/mcp-adapters/kiro.ts +64 -64
- package/src/workspace/mcp-adapters/opencode.ts +123 -123
- package/src/workspace/mcp-adapters/trae.ts +134 -134
- package/src/workspace/mcp-adapters/windsurf.ts +91 -91
- package/src/workspace/sanitizer.ts +60 -60
- package/src/workspace/workflow-sync.ts +131 -131
package/dist/index.js
CHANGED
|
@@ -1787,6 +1787,7 @@ function loadYamlConfig(projectRoot) {
|
|
|
1787
1787
|
agent: { ...userConfig.agent, ...projectConfig.agent },
|
|
1788
1788
|
embedding: { ...userConfig.embedding, ...projectConfig.embedding },
|
|
1789
1789
|
git: { ...userConfig.git, ...projectConfig.git },
|
|
1790
|
+
codegraph: { ...userConfig.codegraph, ...projectConfig.codegraph },
|
|
1790
1791
|
behavior: { ...userConfig.behavior, ...projectConfig.behavior },
|
|
1791
1792
|
server: { ...userConfig.server, ...projectConfig.server },
|
|
1792
1793
|
team: { ...userConfig.team, ...projectConfig.team }
|
|
@@ -2069,6 +2070,7 @@ function mergeTomlConfig(base, override) {
|
|
|
2069
2070
|
embedding: { ...base.embedding, ...override.embedding },
|
|
2070
2071
|
hooks: { ...base.hooks, ...override.hooks },
|
|
2071
2072
|
git: { ...base.git, ...override.git },
|
|
2073
|
+
codegraph: { ...base.codegraph, ...override.codegraph },
|
|
2072
2074
|
server: { ...base.server, ...override.server }
|
|
2073
2075
|
};
|
|
2074
2076
|
}
|
|
@@ -2210,6 +2212,15 @@ var init_dotenv_loader = __esm({
|
|
|
2210
2212
|
});
|
|
2211
2213
|
|
|
2212
2214
|
// src/config/resolved-config.ts
|
|
2215
|
+
var resolved_config_exports = {};
|
|
2216
|
+
__export(resolved_config_exports, {
|
|
2217
|
+
getResolvedAgentLane: () => getResolvedAgentLane,
|
|
2218
|
+
getResolvedConfig: () => getResolvedConfig,
|
|
2219
|
+
getResolvedConfigForCwd: () => getResolvedConfigForCwd,
|
|
2220
|
+
getResolvedEmbeddingLane: () => getResolvedEmbeddingLane,
|
|
2221
|
+
getResolvedMemoryLane: () => getResolvedMemoryLane,
|
|
2222
|
+
resetResolvedConfigCache: () => resetResolvedConfigCache
|
|
2223
|
+
});
|
|
2213
2224
|
import { homedir as homedir5 } from "os";
|
|
2214
2225
|
import { existsSync as existsSync6 } from "fs";
|
|
2215
2226
|
function getResolvedConfig(options = {}) {
|
|
@@ -2287,6 +2298,9 @@ function getResolvedConfig(options = {}) {
|
|
|
2287
2298
|
excludePatterns: firstArray(toml.git?.exclude_patterns, yaml2.git?.excludePatterns),
|
|
2288
2299
|
noiseKeywords: firstArray(toml.git?.noise_keywords, yaml2.git?.noiseKeywords)
|
|
2289
2300
|
},
|
|
2301
|
+
codegraph: {
|
|
2302
|
+
excludePatterns: firstArray(toml.codegraph?.exclude_patterns, yaml2.codegraph?.excludePatterns)
|
|
2303
|
+
},
|
|
2290
2304
|
server: {
|
|
2291
2305
|
transport: first(toml.server?.transport, yaml2.server?.transport),
|
|
2292
2306
|
dashboard: firstBool(toml.server?.dashboard, yaml2.server?.dashboard),
|
|
@@ -2308,6 +2322,10 @@ function getResolvedConfig(options = {}) {
|
|
|
2308
2322
|
};
|
|
2309
2323
|
return resolved;
|
|
2310
2324
|
}
|
|
2325
|
+
function getResolvedConfigForCwd(cwd = process.cwd()) {
|
|
2326
|
+
const project = detectProject(cwd);
|
|
2327
|
+
return getResolvedConfig({ projectRoot: project?.rootPath ?? null });
|
|
2328
|
+
}
|
|
2311
2329
|
function getResolvedAgentLane(options = {}) {
|
|
2312
2330
|
const resolved = getResolvedConfig(options);
|
|
2313
2331
|
return {
|
|
@@ -2324,6 +2342,8 @@ function getResolvedMemoryLane(options = {}) {
|
|
|
2324
2342
|
function getResolvedEmbeddingLane(options = {}) {
|
|
2325
2343
|
return getResolvedConfig(options).embedding;
|
|
2326
2344
|
}
|
|
2345
|
+
function resetResolvedConfigCache() {
|
|
2346
|
+
}
|
|
2327
2347
|
function first(...values) {
|
|
2328
2348
|
return values.find((value) => value !== void 0 && value !== null && value !== "");
|
|
2329
2349
|
}
|
|
@@ -4818,7 +4838,7 @@ __export(orama_store_exports, {
|
|
|
4818
4838
|
resetDb: () => resetDb,
|
|
4819
4839
|
searchObservations: () => searchObservations
|
|
4820
4840
|
});
|
|
4821
|
-
import { create, insert as insert2, search, remove as remove2, update, count } from "@orama/orama";
|
|
4841
|
+
import { create, insert as insert2, search, remove as remove2, update, count, getByID } from "@orama/orama";
|
|
4822
4842
|
function getLastSearchMode(projectId) {
|
|
4823
4843
|
return lastSearchModeByProject.get(projectId ?? SEARCH_MODE_DEFAULT_KEY) ?? "fulltext";
|
|
4824
4844
|
}
|
|
@@ -4829,8 +4849,12 @@ function makeEntryKey(projectId, observationId) {
|
|
|
4829
4849
|
return `${projectId ?? ""}::${observationId}`;
|
|
4830
4850
|
}
|
|
4831
4851
|
function rememberObservationDoc(doc) {
|
|
4832
|
-
|
|
4833
|
-
|
|
4852
|
+
const publicDoc = { ...doc };
|
|
4853
|
+
delete publicDoc.embedding;
|
|
4854
|
+
if (doc.projectId && typeof doc.observationId === "number") {
|
|
4855
|
+
docByObservationKey.set(makeEntryKey(doc.projectId, doc.observationId), publicDoc);
|
|
4856
|
+
}
|
|
4857
|
+
return publicDoc;
|
|
4834
4858
|
}
|
|
4835
4859
|
function isCommandLikeQuery(query) {
|
|
4836
4860
|
return COMMAND_LIKE_QUERY2.test(query);
|
|
@@ -4932,14 +4956,14 @@ async function batchGenerateEmbeddings(texts) {
|
|
|
4932
4956
|
}
|
|
4933
4957
|
async function hydrateIndex(observations2) {
|
|
4934
4958
|
const database = await getDb();
|
|
4935
|
-
const currentCount = await count(database);
|
|
4936
|
-
if (currentCount > 0) return 0;
|
|
4937
4959
|
let inserted = 0;
|
|
4938
4960
|
for (const obs of observations2) {
|
|
4939
4961
|
if (!obs || !obs.id || !obs.projectId) continue;
|
|
4940
4962
|
try {
|
|
4963
|
+
const id = makeOramaObservationId(obs.projectId, obs.id);
|
|
4964
|
+
if (getByID(database, id)) continue;
|
|
4941
4965
|
const doc = {
|
|
4942
|
-
id
|
|
4966
|
+
id,
|
|
4943
4967
|
observationId: obs.id,
|
|
4944
4968
|
entityName: obs.entityName || "",
|
|
4945
4969
|
type: obs.type || "discovery",
|
|
@@ -5033,6 +5057,7 @@ async function searchObservations(options) {
|
|
|
5033
5057
|
let searchParams = {
|
|
5034
5058
|
term: originalQuery,
|
|
5035
5059
|
limit: requestLimit,
|
|
5060
|
+
includeVectors: true,
|
|
5036
5061
|
...Object.keys(filters).length > 0 ? { where: filters } : {},
|
|
5037
5062
|
// Search specific fields (not tokens, accessCount, etc.)
|
|
5038
5063
|
properties: ["title", "entityName", "narrative", "facts", "concepts", "filesModified"],
|
|
@@ -5104,6 +5129,7 @@ async function searchObservations(options) {
|
|
|
5104
5129
|
const vectorOnlyParams = {
|
|
5105
5130
|
term: "",
|
|
5106
5131
|
limit: requestLimit,
|
|
5132
|
+
includeVectors: true,
|
|
5107
5133
|
...Object.keys(filters).length > 0 ? { where: filters } : {},
|
|
5108
5134
|
mode: "vector",
|
|
5109
5135
|
vector: {
|
|
@@ -5402,6 +5428,7 @@ async function getObservationsByIds(ids, projectId) {
|
|
|
5402
5428
|
}
|
|
5403
5429
|
const searchResult = await search(database, {
|
|
5404
5430
|
term: "",
|
|
5431
|
+
includeVectors: true,
|
|
5405
5432
|
where: {
|
|
5406
5433
|
observationId: { eq: id },
|
|
5407
5434
|
...projectId ? { projectId } : {}
|
|
@@ -5409,7 +5436,7 @@ async function getObservationsByIds(ids, projectId) {
|
|
|
5409
5436
|
limit: 1
|
|
5410
5437
|
});
|
|
5411
5438
|
if (searchResult.hits.length > 0) {
|
|
5412
|
-
results.push(searchResult.hits[0].document);
|
|
5439
|
+
results.push(rememberObservationDoc(searchResult.hits[0].document));
|
|
5413
5440
|
}
|
|
5414
5441
|
}
|
|
5415
5442
|
return results;
|
|
@@ -9296,6 +9323,58 @@ var init_current_facts = __esm({
|
|
|
9296
9323
|
}
|
|
9297
9324
|
});
|
|
9298
9325
|
|
|
9326
|
+
// src/codegraph/exclude.ts
|
|
9327
|
+
function normalizeCodeGraphExcludePatterns(exclude) {
|
|
9328
|
+
return [.../* @__PURE__ */ new Set([
|
|
9329
|
+
...DEFAULT_CODEGRAPH_EXCLUDES,
|
|
9330
|
+
...(exclude ?? []).map((pattern) => pattern.trim()).filter(Boolean)
|
|
9331
|
+
])];
|
|
9332
|
+
}
|
|
9333
|
+
function isCodeGraphExcludedPath(path20, exclude) {
|
|
9334
|
+
const normalized = normalizeCodePath2(path20);
|
|
9335
|
+
return normalizeCodeGraphExcludePatterns(exclude).some((pattern) => matchesPattern(normalized, normalizeCodePath2(pattern)));
|
|
9336
|
+
}
|
|
9337
|
+
function normalizeCodePath2(path20) {
|
|
9338
|
+
return path20.replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
9339
|
+
}
|
|
9340
|
+
function matchesPattern(path20, pattern) {
|
|
9341
|
+
if (pattern.endsWith("/**")) {
|
|
9342
|
+
const base = pattern.slice(0, -3);
|
|
9343
|
+
if (base.startsWith("**/")) {
|
|
9344
|
+
const suffix = base.slice(3);
|
|
9345
|
+
return path20 === suffix || path20.endsWith(`/${suffix}`) || path20.includes(`/${suffix}/`);
|
|
9346
|
+
}
|
|
9347
|
+
if (!base.includes("/")) {
|
|
9348
|
+
return path20 === base || path20.startsWith(`${base}/`) || path20.includes(`/${base}/`);
|
|
9349
|
+
}
|
|
9350
|
+
return path20 === base || path20.startsWith(`${base}/`);
|
|
9351
|
+
}
|
|
9352
|
+
if (pattern.startsWith("**/")) {
|
|
9353
|
+
const suffix = pattern.slice(3);
|
|
9354
|
+
return path20 === suffix || path20.endsWith(`/${suffix}`);
|
|
9355
|
+
}
|
|
9356
|
+
return path20 === pattern || path20.startsWith(`${pattern}/`);
|
|
9357
|
+
}
|
|
9358
|
+
var DEFAULT_CODEGRAPH_EXCLUDES;
|
|
9359
|
+
var init_exclude = __esm({
|
|
9360
|
+
"src/codegraph/exclude.ts"() {
|
|
9361
|
+
"use strict";
|
|
9362
|
+
init_esm_shims();
|
|
9363
|
+
DEFAULT_CODEGRAPH_EXCLUDES = [
|
|
9364
|
+
"node_modules/**",
|
|
9365
|
+
"dist/**",
|
|
9366
|
+
"build/**",
|
|
9367
|
+
"coverage/**",
|
|
9368
|
+
".next/**",
|
|
9369
|
+
".turbo/**",
|
|
9370
|
+
".git/**",
|
|
9371
|
+
".tmp/**",
|
|
9372
|
+
".worktrees/**",
|
|
9373
|
+
".claude/worktrees/**"
|
|
9374
|
+
];
|
|
9375
|
+
}
|
|
9376
|
+
});
|
|
9377
|
+
|
|
9299
9378
|
// src/codegraph/lite-provider.ts
|
|
9300
9379
|
import { createHash as createHash5 } from "crypto";
|
|
9301
9380
|
import { readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync2 } from "fs";
|
|
@@ -9311,18 +9390,6 @@ function languageForPath(path20) {
|
|
|
9311
9390
|
const ext = extension(path20);
|
|
9312
9391
|
return LANGUAGE_BY_EXTENSION.get(ext) ?? "unknown";
|
|
9313
9392
|
}
|
|
9314
|
-
function isExcluded(path20, exclude) {
|
|
9315
|
-
const normalized = normalizeCodePath(path20);
|
|
9316
|
-
return exclude.some((pattern) => {
|
|
9317
|
-
const p = normalizeCodePath(pattern);
|
|
9318
|
-
if (p.endsWith("/**")) {
|
|
9319
|
-
const base = p.slice(0, -3);
|
|
9320
|
-
return normalized === base || normalized.startsWith(`${base}/`);
|
|
9321
|
-
}
|
|
9322
|
-
if (p.startsWith("**/")) return normalized.endsWith(p.slice(3));
|
|
9323
|
-
return normalized === p || normalized.startsWith(`${p}/`);
|
|
9324
|
-
});
|
|
9325
|
-
}
|
|
9326
9393
|
function walk(root, exclude, maxFiles) {
|
|
9327
9394
|
const out = [];
|
|
9328
9395
|
const visit = (dir) => {
|
|
@@ -9336,9 +9403,10 @@ function walk(root, exclude, maxFiles) {
|
|
|
9336
9403
|
for (const entry of entries) {
|
|
9337
9404
|
const abs = join20(dir, entry.name);
|
|
9338
9405
|
const rel = normalizeCodePath(relative(root, abs));
|
|
9339
|
-
if (
|
|
9406
|
+
if (isCodeGraphExcludedPath(rel, exclude)) continue;
|
|
9340
9407
|
if (entry.isDirectory()) {
|
|
9341
|
-
if (entry.name === ".git" || entry.name === "node_modules") continue;
|
|
9408
|
+
if (entry.name === ".git" || entry.name === ".worktrees" || entry.name === ".tmp" || entry.name === "node_modules") continue;
|
|
9409
|
+
if (rel === ".claude/worktrees" || rel.startsWith(".claude/worktrees/")) continue;
|
|
9342
9410
|
visit(abs);
|
|
9343
9411
|
if (out.length >= maxFiles) return;
|
|
9344
9412
|
continue;
|
|
@@ -9423,15 +9491,7 @@ function extractImportEdges(projectId, file, text, indexedAt) {
|
|
|
9423
9491
|
return edges;
|
|
9424
9492
|
}
|
|
9425
9493
|
async function indexProjectLite(options) {
|
|
9426
|
-
const exclude = options.exclude
|
|
9427
|
-
"node_modules/**",
|
|
9428
|
-
"dist/**",
|
|
9429
|
-
"build/**",
|
|
9430
|
-
"coverage/**",
|
|
9431
|
-
".next/**",
|
|
9432
|
-
".turbo/**",
|
|
9433
|
-
".git/**"
|
|
9434
|
-
];
|
|
9494
|
+
const exclude = normalizeCodeGraphExcludePatterns(options.exclude);
|
|
9435
9495
|
const maxFiles = options.maxFiles ?? 5e3;
|
|
9436
9496
|
const indexedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
9437
9497
|
const paths = walk(options.projectRoot, exclude, maxFiles);
|
|
@@ -9470,6 +9530,7 @@ var init_lite_provider = __esm({
|
|
|
9470
9530
|
"use strict";
|
|
9471
9531
|
init_esm_shims();
|
|
9472
9532
|
init_ids();
|
|
9533
|
+
init_exclude();
|
|
9473
9534
|
LANGUAGE_BY_EXTENSION = /* @__PURE__ */ new Map([
|
|
9474
9535
|
[".ts", "typescript"],
|
|
9475
9536
|
[".tsx", "typescript"],
|
|
@@ -9639,23 +9700,17 @@ function countLanguages(files) {
|
|
|
9639
9700
|
}
|
|
9640
9701
|
return [...counts.entries()].map(([language, files2]) => ({ language, files: files2 })).sort((a, b) => a.language.localeCompare(b.language));
|
|
9641
9702
|
}
|
|
9642
|
-
function normalizePath2(path20) {
|
|
9643
|
-
return path20.replace(/\\/g, "/");
|
|
9644
|
-
}
|
|
9645
|
-
function isGeneratedPath(path20) {
|
|
9646
|
-
return /(^|\/)(dist|build|coverage|\.next|\.turbo|node_modules)\//i.test(normalizePath2(path20));
|
|
9647
|
-
}
|
|
9648
9703
|
function suggestedReadRank(path20) {
|
|
9649
|
-
const normalized =
|
|
9704
|
+
const normalized = path20.replace(/\\/g, "/");
|
|
9650
9705
|
if (normalized.startsWith("src/")) return 0;
|
|
9651
9706
|
if (normalized.startsWith("tests/") || normalized.startsWith("test/")) return 0;
|
|
9652
9707
|
if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 2;
|
|
9653
9708
|
return 3;
|
|
9654
9709
|
}
|
|
9655
|
-
function compactSuggestedReads(paths, limit = 8) {
|
|
9656
|
-
return uniq(paths).filter((path20) => !
|
|
9710
|
+
function compactSuggestedReads(paths, limit = 8, exclude) {
|
|
9711
|
+
return uniq(paths).filter((path20) => !isCodeGraphExcludedPath(path20, exclude)).sort((a, b) => suggestedReadRank(a) - suggestedReadRank(b)).slice(0, limit);
|
|
9657
9712
|
}
|
|
9658
|
-
function collectGraph(store, projectId, observations2) {
|
|
9713
|
+
function collectGraph(store, projectId, observations2, exclude) {
|
|
9659
9714
|
const files = store.listFiles(projectId);
|
|
9660
9715
|
const symbols = files.flatMap((file) => store.listSymbolsForFile(file.id));
|
|
9661
9716
|
const filesById = new Map(files.map((file) => [file.id, file]));
|
|
@@ -9677,7 +9732,9 @@ function collectGraph(store, projectId, observations2) {
|
|
|
9677
9732
|
freshness[result.status] += 1;
|
|
9678
9733
|
const observation = observationsById.get(ref.observationId);
|
|
9679
9734
|
if (!observation) continue;
|
|
9680
|
-
|
|
9735
|
+
const excluded = file ? isCodeGraphExcludedPath(file.path, exclude) : false;
|
|
9736
|
+
if (result.status === "current" && file && !excluded) suggestedReads.push(file.path);
|
|
9737
|
+
if (excluded) continue;
|
|
9681
9738
|
sources.push({
|
|
9682
9739
|
observationId: observation.id,
|
|
9683
9740
|
title: observation.title,
|
|
@@ -9694,12 +9751,12 @@ function collectGraph(store, projectId, observations2) {
|
|
|
9694
9751
|
refs,
|
|
9695
9752
|
freshness,
|
|
9696
9753
|
sources,
|
|
9697
|
-
suggestedReads: compactSuggestedReads(suggestedReads)
|
|
9754
|
+
suggestedReads: compactSuggestedReads(suggestedReads, 8, exclude)
|
|
9698
9755
|
};
|
|
9699
9756
|
}
|
|
9700
9757
|
function buildProjectContextOverview(input) {
|
|
9701
9758
|
const active = activeObservations(input.observations, input.project.id);
|
|
9702
|
-
const graph = collectGraph(input.store, input.project.id, active);
|
|
9759
|
+
const graph = collectGraph(input.store, input.project.id, active, input.exclude);
|
|
9703
9760
|
const status = input.store.status(input.project.id);
|
|
9704
9761
|
return {
|
|
9705
9762
|
project: input.project,
|
|
@@ -9723,7 +9780,7 @@ function buildProjectContextOverview(input) {
|
|
|
9723
9780
|
function buildProjectContextExplain(input) {
|
|
9724
9781
|
const overview = buildProjectContextOverview(input);
|
|
9725
9782
|
const active = activeObservations(input.observations, input.project.id);
|
|
9726
|
-
const graph = collectGraph(input.store, input.project.id, active);
|
|
9783
|
+
const graph = collectGraph(input.store, input.project.id, active, input.exclude);
|
|
9727
9784
|
return {
|
|
9728
9785
|
project: input.project,
|
|
9729
9786
|
sources: graph.sources.sort((a, b) => a.observationId - b.observationId || (a.path ?? "").localeCompare(b.path ?? "")),
|
|
@@ -9735,11 +9792,12 @@ var init_project_context = __esm({
|
|
|
9735
9792
|
"use strict";
|
|
9736
9793
|
init_esm_shims();
|
|
9737
9794
|
init_freshness2();
|
|
9795
|
+
init_exclude();
|
|
9738
9796
|
}
|
|
9739
9797
|
});
|
|
9740
9798
|
|
|
9741
9799
|
// src/codegraph/task-lens.ts
|
|
9742
|
-
function
|
|
9800
|
+
function normalizePath2(path20) {
|
|
9743
9801
|
return path20.replace(/\\/g, "/");
|
|
9744
9802
|
}
|
|
9745
9803
|
function tokenize(text) {
|
|
@@ -9769,7 +9827,7 @@ function resolveTaskLens(task) {
|
|
|
9769
9827
|
return best.score > 0 ? LENSES[best.id] : LENSES.general;
|
|
9770
9828
|
}
|
|
9771
9829
|
function pathKindScore(path20, lens) {
|
|
9772
|
-
const normalized =
|
|
9830
|
+
const normalized = normalizePath2(path20).toLowerCase();
|
|
9773
9831
|
const name = normalized.split("/").pop() ?? normalized;
|
|
9774
9832
|
const inDocs = normalized.startsWith("docs/") || name === "readme.md" || name.includes("readme");
|
|
9775
9833
|
const isTest = /(^|\/)(tests?|__tests__|spec|fixtures?)\//.test(normalized) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(normalized) || /\.(test|spec)\.py$/.test(normalized);
|
|
@@ -9818,7 +9876,7 @@ function sourceTaskMatchScore(source, task) {
|
|
|
9818
9876
|
return 0;
|
|
9819
9877
|
}
|
|
9820
9878
|
function fallbackPathRank(path20) {
|
|
9821
|
-
const normalized =
|
|
9879
|
+
const normalized = normalizePath2(path20);
|
|
9822
9880
|
if (normalized.startsWith("src/")) return 0;
|
|
9823
9881
|
if (normalized.startsWith("tests/") || normalized.startsWith("test/")) return 1;
|
|
9824
9882
|
if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 2;
|
|
@@ -9827,7 +9885,7 @@ function fallbackPathRank(path20) {
|
|
|
9827
9885
|
}
|
|
9828
9886
|
function rankLensPaths(paths, lens, task) {
|
|
9829
9887
|
const tokens = tokenize(task ?? "");
|
|
9830
|
-
return [...new Set(paths.map(
|
|
9888
|
+
return [...new Set(paths.map(normalizePath2))].map((path20, index) => ({
|
|
9831
9889
|
path: path20,
|
|
9832
9890
|
index,
|
|
9833
9891
|
score: pathKindScore(path20, lens) + tokenScore(path20, tokens),
|
|
@@ -10081,6 +10139,7 @@ async function buildAutoProjectContext(input) {
|
|
|
10081
10139
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
10082
10140
|
const task = input.task?.trim();
|
|
10083
10141
|
const lens = resolveTaskLens(task);
|
|
10142
|
+
const exclude = input.exclude ?? getResolvedConfig({ projectRoot: input.project.rootPath }).codegraph.excludePatterns;
|
|
10084
10143
|
const store = new CodeGraphStore();
|
|
10085
10144
|
await store.init(input.dataDir);
|
|
10086
10145
|
const initialStatus = store.status(input.project.id);
|
|
@@ -10098,7 +10157,8 @@ async function buildAutoProjectContext(input) {
|
|
|
10098
10157
|
try {
|
|
10099
10158
|
const indexed = await indexProjectLite({
|
|
10100
10159
|
projectId: input.project.id,
|
|
10101
|
-
projectRoot: input.project.rootPath
|
|
10160
|
+
projectRoot: input.project.rootPath,
|
|
10161
|
+
exclude
|
|
10102
10162
|
});
|
|
10103
10163
|
store.replaceProjectIndex(input.project.id, indexed);
|
|
10104
10164
|
const backfill = await backfillMissingObservationCodeRefs(
|
|
@@ -10118,12 +10178,14 @@ async function buildAutoProjectContext(input) {
|
|
|
10118
10178
|
const overview = buildProjectContextOverview({
|
|
10119
10179
|
project: input.project,
|
|
10120
10180
|
store,
|
|
10121
|
-
observations: input.observations
|
|
10181
|
+
observations: input.observations,
|
|
10182
|
+
exclude
|
|
10122
10183
|
});
|
|
10123
10184
|
const explain = buildProjectContextExplain({
|
|
10124
10185
|
project: input.project,
|
|
10125
10186
|
store,
|
|
10126
|
-
observations: input.observations
|
|
10187
|
+
observations: input.observations,
|
|
10188
|
+
exclude
|
|
10127
10189
|
});
|
|
10128
10190
|
return {
|
|
10129
10191
|
project: input.project,
|
|
@@ -10333,6 +10395,7 @@ var init_auto_context = __esm({
|
|
|
10333
10395
|
"src/codegraph/auto-context.ts"() {
|
|
10334
10396
|
"use strict";
|
|
10335
10397
|
init_esm_shims();
|
|
10398
|
+
init_resolved_config();
|
|
10336
10399
|
init_binder();
|
|
10337
10400
|
init_current_facts();
|
|
10338
10401
|
init_lite_provider();
|
|
@@ -10360,9 +10423,6 @@ function tokenize2(text) {
|
|
|
10360
10423
|
function timestampOf(observation) {
|
|
10361
10424
|
return Date.parse(observation.updatedAt ?? observation.createdAt ?? "") || 0;
|
|
10362
10425
|
}
|
|
10363
|
-
function isGeneratedPath2(path20) {
|
|
10364
|
-
return /(^|\/)(dist|build|coverage|\.next|\.turbo|node_modules)\//i.test(path20.replace(/\\/g, "/"));
|
|
10365
|
-
}
|
|
10366
10426
|
function relevanceScore(observation, taskTokens) {
|
|
10367
10427
|
if (taskTokens.length === 0) return 0;
|
|
10368
10428
|
const title = observation.title.toLowerCase();
|
|
@@ -10413,7 +10473,8 @@ function assembleContextPackForTask(input) {
|
|
|
10413
10473
|
refs,
|
|
10414
10474
|
files,
|
|
10415
10475
|
symbols,
|
|
10416
|
-
suggestedVerification: input.suggestedVerification
|
|
10476
|
+
suggestedVerification: input.suggestedVerification,
|
|
10477
|
+
exclude: input.exclude
|
|
10417
10478
|
});
|
|
10418
10479
|
}
|
|
10419
10480
|
function assembleContextPack(input) {
|
|
@@ -10432,6 +10493,7 @@ function assembleContextPack(input) {
|
|
|
10432
10493
|
observationIdsWithRefs.add(ref.observationId);
|
|
10433
10494
|
const file = ref.fileId ? files.get(ref.fileId) : void 0;
|
|
10434
10495
|
const symbol = ref.symbolId ? symbols.get(ref.symbolId) : void 0;
|
|
10496
|
+
if (file && isCodeGraphExcludedPath(file.path, input.exclude)) continue;
|
|
10435
10497
|
const freshness = evaluateCodeRefFreshness(ref, file, symbol);
|
|
10436
10498
|
if (freshness.status === "current") {
|
|
10437
10499
|
const memoryKey = `${observation.id}:${freshness.status}`;
|
|
@@ -10497,8 +10559,8 @@ function buildContextPackPrompt(pack) {
|
|
|
10497
10559
|
const reliableMemories = pack.memories.filter((memory) => memory.status === "current");
|
|
10498
10560
|
const unboundMemories = pack.memories.filter((memory) => memory.status === "unbound");
|
|
10499
10561
|
const lines = ["## Task", pack.task, "", "## Reliable Memories"];
|
|
10500
|
-
const visibleCodeFacts = pack.codeFacts.filter((fact) => !
|
|
10501
|
-
const visibleSuggestedReads = pack.suggestedReads.filter((path20) => !
|
|
10562
|
+
const visibleCodeFacts = pack.codeFacts.filter((fact) => !isCodeGraphExcludedPath(fact.path)).slice(0, 5);
|
|
10563
|
+
const visibleSuggestedReads = pack.suggestedReads.filter((path20) => !isCodeGraphExcludedPath(path20)).slice(0, 5);
|
|
10502
10564
|
if (reliableMemories.length === 0) lines.push("- none");
|
|
10503
10565
|
for (const memory of reliableMemories) {
|
|
10504
10566
|
lines.push(`- #${memory.id} ${memory.status}: [${memory.type}] ${memory.title} (${memory.reason})`);
|
|
@@ -10533,6 +10595,7 @@ var init_context_pack = __esm({
|
|
|
10533
10595
|
"use strict";
|
|
10534
10596
|
init_esm_shims();
|
|
10535
10597
|
init_freshness2();
|
|
10598
|
+
init_exclude();
|
|
10536
10599
|
}
|
|
10537
10600
|
});
|
|
10538
10601
|
|
|
@@ -14551,7 +14614,7 @@ var init_official_skills = __esm({
|
|
|
14551
14614
|
"",
|
|
14552
14615
|
"## Search Rules",
|
|
14553
14616
|
"",
|
|
14554
|
-
"-
|
|
14617
|
+
"- Default first step for non-trivial coding work: call `memorix_project_context` before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Pass the user's actual task so Memorix can choose a bugfix, feature, release, onboarding, refactor, docs, test, or general brief. Start by reading its suggested files.",
|
|
14555
14618
|
"- In Claude Code headless/print-mode, an initial MCP `pending` status is not a failure by itself. Prefer MCP first: use the client's tool discovery/dynamic loading to find `memorix_project_context` when it is not in the first visible tool list.",
|
|
14556
14619
|
'- Run `memorix context --task "<task>"` from the shell only after MCP is unavailable, disabled, or not discoverable, and pass the user\'s real task text. Do not skip memory, wait indefinitely on `pending`, or hand-write tool-call syntax.',
|
|
14557
14620
|
"- Use `memorix_search` for a specific decision, bug, file, or prior change that the project context did not answer.",
|
|
@@ -14862,6 +14925,7 @@ var init_audit = __esm({
|
|
|
14862
14925
|
var installers_exports = {};
|
|
14863
14926
|
__export(installers_exports, {
|
|
14864
14927
|
detectInstalledAgents: () => detectInstalledAgents,
|
|
14928
|
+
getAgentRulesPath: () => getAgentRulesPath,
|
|
14865
14929
|
getGlobalConfigPath: () => getGlobalConfigPath,
|
|
14866
14930
|
getHookStatus: () => getHookStatus,
|
|
14867
14931
|
getProjectConfigPath: () => getProjectConfigPath,
|
|
@@ -15728,7 +15792,7 @@ function getAgentRulesContent(agent, scope = "project") {
|
|
|
15728
15792
|
let frontmatter = "";
|
|
15729
15793
|
const contextNoun = scope === "global" ? "workspace" : "project";
|
|
15730
15794
|
const title = scope === "global" ? "# Memorix \u2014 Memory Tools for Active Workspaces" : "# Memorix \u2014 Project Memory Tools";
|
|
15731
|
-
const intro = scope === "global" ? "Use Memorix when the active workspace has Memorix tools available and prior context would materially help. Do not assume every workspace is configured for Memorix." : "This repository is configured to use Memorix for persistent cross-session memory.
|
|
15795
|
+
const intro = scope === "global" ? "Use Memorix when the active workspace has Memorix tools available and prior context would materially help. For non-trivial coding work, Memory Autopilot is the default entry point before local progress notes or broad file exploration. Do not assume every workspace is configured for Memorix." : "This repository is configured to use Memorix for persistent cross-session memory. For non-trivial coding work, Memory Autopilot is the default entry point before local progress notes or broad file exploration.";
|
|
15732
15796
|
if (agent === "windsurf") {
|
|
15733
15797
|
frontmatter = "---\ntrigger: always_on\n---\n\n";
|
|
15734
15798
|
} else if (agent === "cursor") {
|
|
@@ -15746,7 +15810,7 @@ alwaysApply: true
|
|
|
15746
15810
|
"",
|
|
15747
15811
|
"## Start with Memory Autopilot",
|
|
15748
15812
|
"",
|
|
15749
|
-
`
|
|
15813
|
+
`Default first step for non-trivial coding work: call \`memorix_project_context\` with the user's actual task before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Memorix will choose a task-lensed brief (bugfix, feature, release, onboarding, refactor, docs, test, or general). Treat its "Start here" files as the first ${contextNoun} files to inspect.`,
|
|
15750
15814
|
"",
|
|
15751
15815
|
'If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select `memorix_project_context` first. Run `memorix context --task "<task>"` only after MCP is unavailable, disabled, or not discoverable, and pass the user\'s real task text. Do not skip memory, wait indefinitely on MCP startup, or hand-write tool-call syntax.',
|
|
15752
15816
|
"",
|
|
@@ -20002,7 +20066,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
20002
20066
|
};
|
|
20003
20067
|
const server = existingServer ?? new McpServer({
|
|
20004
20068
|
name: "memorix",
|
|
20005
|
-
version: true ? "1.1.
|
|
20069
|
+
version: true ? "1.1.9" : "1.0.1"
|
|
20006
20070
|
});
|
|
20007
20071
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
20008
20072
|
server.registerTool = ((name, ...args) => {
|
|
@@ -20704,15 +20768,18 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
20704
20768
|
return withFreshIndex(async () => {
|
|
20705
20769
|
const { CodeGraphStore: CodeGraphStore2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
20706
20770
|
const { assembleContextPackForTask: assembleContextPackForTask2, buildContextPackPrompt: buildContextPackPrompt2 } = await Promise.resolve().then(() => (init_context_pack(), context_pack_exports));
|
|
20771
|
+
const { getResolvedConfig: getResolvedConfig2 } = await Promise.resolve().then(() => (init_resolved_config(), resolved_config_exports));
|
|
20707
20772
|
const store = new CodeGraphStore2();
|
|
20708
20773
|
await store.init(projectDir2);
|
|
20774
|
+
const exclude = getResolvedConfig2({ projectRoot: project.rootPath }).codegraph.excludePatterns;
|
|
20709
20775
|
const observations2 = getAllObservations().filter((obs) => obs.projectId === project.id && (obs.status ?? "active") === "active").reverse();
|
|
20710
20776
|
const pack = assembleContextPackForTask2({
|
|
20711
20777
|
store,
|
|
20712
20778
|
projectId: project.id,
|
|
20713
20779
|
task,
|
|
20714
20780
|
observations: observations2,
|
|
20715
|
-
limit: typeof limit === "number" ? limit : 20
|
|
20781
|
+
limit: typeof limit === "number" ? limit : 20,
|
|
20782
|
+
exclude
|
|
20716
20783
|
});
|
|
20717
20784
|
const text = buildContextPackPrompt2(pack);
|
|
20718
20785
|
return {
|