memorix 1.5.1 → 1.6.1
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 +47 -0
- package/README.md +3 -3
- package/README.zh-CN.md +3 -3
- package/dist/cli/index.js +558 -102
- package/dist/cli/memcode.js +12 -1
- package/dist/index.js +221 -27
- package/dist/maintenance-runner.js +59 -11
- package/dist/media-audio-runner.js +59 -11
- package/dist/media-video-runner.js +59 -11
- package/dist/memcode-runtime/CHANGELOG.md +47 -0
- package/dist/sdk.js +220 -26
- package/dist/vector-backfill-runner.js +59 -11
- package/docs/1.2.4-PERSISTENT-MEMORY-DELIVERY.md +1 -1
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +11 -3
- package/docs/API_REFERENCE.md +2 -2
- package/docs/DEVELOPMENT.md +5 -3
- package/docs/DOCKER.md +5 -1
- package/docs/PERFORMANCE.md +2 -2
- package/docs/README.md +3 -1
- package/docs/SETUP.md +8 -2
- package/package.json +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/cli/commands/agent-integrations.ts +9 -3
- package/src/cli/commands/codegraph.ts +48 -5
- package/src/cli/commands/context.ts +20 -4
- package/src/cli/commands/doctor.ts +46 -15
- package/src/cli/commands/hook.ts +13 -1
- package/src/cli/commands/resume.ts +4 -0
- package/src/cli/commands/serve-http.ts +68 -7
- package/src/cli/heap.ts +76 -0
- package/src/cli/invocation.ts +7 -4
- package/src/codegraph/auto-context.ts +4 -1
- package/src/codegraph/context-pack.ts +3 -1
- package/src/codegraph/external-provider.ts +93 -0
- package/src/embedding/provider.ts +76 -6
- package/src/hooks/handler.ts +9 -18
- package/src/hooks/installers/index.ts +1 -1
- package/src/hooks/lifecycle.ts +173 -0
- package/src/hooks/official-skills.ts +3 -3
- package/src/hooks/rules/memorix-agent-rules.md +1 -1
- package/src/knowledge/context-receipt.ts +41 -0
- package/src/knowledge/workflows.ts +6 -3
- package/src/knowledge/workset.ts +56 -2
- package/src/server.ts +15 -3
package/dist/sdk.js
CHANGED
|
@@ -4442,6 +4442,7 @@ __export(provider_exports, {
|
|
|
4442
4442
|
MAX_INLINE_EMBEDDING_BYTES: () => MAX_INLINE_EMBEDDING_BYTES,
|
|
4443
4443
|
UnsupportedEmbeddingModalityError: () => UnsupportedEmbeddingModalityError,
|
|
4444
4444
|
getEmbeddingProvider: () => getEmbeddingProvider,
|
|
4445
|
+
getEmbeddingRuntimeHealth: () => getEmbeddingRuntimeHealth,
|
|
4445
4446
|
isEmbeddingExplicitlyDisabled: () => isEmbeddingExplicitlyDisabled,
|
|
4446
4447
|
isVectorSearchAvailable: () => isVectorSearchAvailable,
|
|
4447
4448
|
resetProvider: () => resetProvider,
|
|
@@ -4549,13 +4550,36 @@ function isTemporaryEmbeddingFailure(error) {
|
|
|
4549
4550
|
if (!(error instanceof Error)) return false;
|
|
4550
4551
|
return /embedding api error \(401\)/i.test(error.message) || /invalid_api_key/i.test(error.message) || /incorrect api key/i.test(error.message) || /unauthorized/i.test(error.message) || /embedding api timeout/i.test(error.message) || /embedding api error \((402|429|5\d\d)\)/i.test(error.message) || /quota exceeded/i.test(error.message) || /account balance/i.test(error.message) || /fetch failed/i.test(error.message) || /econnreset/i.test(error.message) || /econnrefused/i.test(error.message) || /temporarily unavailable/i.test(error.message);
|
|
4551
4552
|
}
|
|
4553
|
+
function classifyEmbeddingFailure(error) {
|
|
4554
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4555
|
+
if (/embedding api error \(401\)|invalid_api_key|incorrect api key|unauthorized/i.test(message)) {
|
|
4556
|
+
return "authorization";
|
|
4557
|
+
}
|
|
4558
|
+
if (/embedding api error \(402\)|quota exceeded|account balance/i.test(message)) {
|
|
4559
|
+
return "billing";
|
|
4560
|
+
}
|
|
4561
|
+
if (/embedding api timeout|abort/i.test(message)) {
|
|
4562
|
+
return "timeout";
|
|
4563
|
+
}
|
|
4564
|
+
return "upstream";
|
|
4565
|
+
}
|
|
4552
4566
|
function markTemporaryFailure(reason) {
|
|
4553
4567
|
provider = null;
|
|
4554
4568
|
initPromise = null;
|
|
4555
4569
|
lastInitWasTemporaryFailure = true;
|
|
4556
4570
|
lastFailureTimestamp = Date.now();
|
|
4571
|
+
lastEmbeddingFailure = {
|
|
4572
|
+
kind: classifyEmbeddingFailure(reason),
|
|
4573
|
+
occurredAt: lastFailureTimestamp
|
|
4574
|
+
};
|
|
4557
4575
|
const message = reason instanceof Error ? reason.message : String(reason);
|
|
4558
|
-
warnOnce(`[memorix] Embedding provider
|
|
4576
|
+
warnOnce(`[memorix] Embedding provider unavailable at runtime: ${message}`);
|
|
4577
|
+
}
|
|
4578
|
+
function markProviderReady(candidate) {
|
|
4579
|
+
provider = wrapProvider(candidate);
|
|
4580
|
+
lastInitWasTemporaryFailure = false;
|
|
4581
|
+
lastEmbeddingFailure = null;
|
|
4582
|
+
return provider;
|
|
4559
4583
|
}
|
|
4560
4584
|
async function createFastEmbedProvider() {
|
|
4561
4585
|
try {
|
|
@@ -4671,35 +4695,35 @@ async function getEmbeddingProvider(options = {}) {
|
|
|
4671
4695
|
if (mode === "fastembed") {
|
|
4672
4696
|
const initialized = await createFastEmbedProvider();
|
|
4673
4697
|
if (!initialized) return null;
|
|
4674
|
-
provider =
|
|
4698
|
+
provider = markProviderReady(initialized);
|
|
4675
4699
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4676
4700
|
return provider;
|
|
4677
4701
|
}
|
|
4678
4702
|
if (mode === "transformers") {
|
|
4679
4703
|
const initialized = await createTransformersProvider();
|
|
4680
4704
|
if (!initialized) return null;
|
|
4681
|
-
provider =
|
|
4705
|
+
provider = markProviderReady(initialized);
|
|
4682
4706
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4683
4707
|
return provider;
|
|
4684
4708
|
}
|
|
4685
4709
|
if (mode === "api") {
|
|
4686
4710
|
const initialized = await createAPIProvider(options);
|
|
4687
4711
|
if (!initialized) return null;
|
|
4688
|
-
provider =
|
|
4712
|
+
provider = markProviderReady(initialized);
|
|
4689
4713
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4690
4714
|
return provider;
|
|
4691
4715
|
}
|
|
4692
4716
|
if (hasAPIEmbeddingConfig()) {
|
|
4693
4717
|
const initialized = await createAPIProvider(options);
|
|
4694
4718
|
if (initialized) {
|
|
4695
|
-
provider =
|
|
4719
|
+
provider = markProviderReady(initialized);
|
|
4696
4720
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4697
4721
|
return provider;
|
|
4698
4722
|
}
|
|
4699
4723
|
}
|
|
4700
4724
|
const localFallback = await createLocalFallbackProvider();
|
|
4701
4725
|
if (localFallback) {
|
|
4702
|
-
provider =
|
|
4726
|
+
provider = markProviderReady(localFallback);
|
|
4703
4727
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4704
4728
|
return provider;
|
|
4705
4729
|
}
|
|
@@ -4721,6 +4745,27 @@ async function isVectorSearchAvailable() {
|
|
|
4721
4745
|
const p = await getEmbeddingProvider();
|
|
4722
4746
|
return p !== null;
|
|
4723
4747
|
}
|
|
4748
|
+
function getEmbeddingRuntimeHealth() {
|
|
4749
|
+
const mode = getEmbeddingMode2();
|
|
4750
|
+
if (mode === "off") return { status: "disabled" };
|
|
4751
|
+
if (lastInitWasTemporaryFailure && lastEmbeddingFailure) {
|
|
4752
|
+
return {
|
|
4753
|
+
status: "degraded",
|
|
4754
|
+
failure: {
|
|
4755
|
+
kind: lastEmbeddingFailure.kind,
|
|
4756
|
+
occurredAt: new Date(lastEmbeddingFailure.occurredAt).toISOString(),
|
|
4757
|
+
retryAfterMs: Math.max(0, RETRY_COOLDOWN_MS - (Date.now() - lastEmbeddingFailure.occurredAt))
|
|
4758
|
+
}
|
|
4759
|
+
};
|
|
4760
|
+
}
|
|
4761
|
+
if (provider) {
|
|
4762
|
+
return {
|
|
4763
|
+
status: "ready",
|
|
4764
|
+
provider: { name: provider.name, dimensions: provider.dimensions }
|
|
4765
|
+
};
|
|
4766
|
+
}
|
|
4767
|
+
return { status: "uninitialized" };
|
|
4768
|
+
}
|
|
4724
4769
|
function isEmbeddingExplicitlyDisabled() {
|
|
4725
4770
|
return getEmbeddingMode2() === "off";
|
|
4726
4771
|
}
|
|
@@ -4729,10 +4774,11 @@ function resetProvider() {
|
|
|
4729
4774
|
initPromise = null;
|
|
4730
4775
|
lastInitWasTemporaryFailure = false;
|
|
4731
4776
|
lastFailureTimestamp = 0;
|
|
4777
|
+
lastEmbeddingFailure = null;
|
|
4732
4778
|
lastEmbeddingWarning = "";
|
|
4733
4779
|
lastEmbeddingWarningAt = 0;
|
|
4734
4780
|
}
|
|
4735
|
-
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
4781
|
+
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
4736
4782
|
var init_provider = __esm({
|
|
4737
4783
|
"src/embedding/provider.ts"() {
|
|
4738
4784
|
"use strict";
|
|
@@ -4757,6 +4803,7 @@ var init_provider = __esm({
|
|
|
4757
4803
|
provider = null;
|
|
4758
4804
|
initPromise = null;
|
|
4759
4805
|
lastInitWasTemporaryFailure = false;
|
|
4806
|
+
lastEmbeddingFailure = null;
|
|
4760
4807
|
lastEmbeddingWarning = "";
|
|
4761
4808
|
lastEmbeddingWarningAt = 0;
|
|
4762
4809
|
WARNING_COOLDOWN_MS = 3e4;
|
|
@@ -148862,6 +148909,7 @@ var init_task_lens = __esm({
|
|
|
148862
148909
|
var workflows_exports = {};
|
|
148863
148910
|
__export(workflows_exports, {
|
|
148864
148911
|
WORKFLOW_ADAPTER_TARGETS: () => WORKFLOW_ADAPTER_TARGETS,
|
|
148912
|
+
WORKFLOW_AGENT_TARGETS: () => WORKFLOW_AGENT_TARGETS,
|
|
148865
148913
|
applyWorkflowAdapter: () => applyWorkflowAdapter,
|
|
148866
148914
|
importWindsurfWorkflows: () => importWindsurfWorkflows,
|
|
148867
148915
|
parseWorkflowMarkdown: () => parseWorkflowMarkdown,
|
|
@@ -148927,7 +148975,7 @@ function optionalStatus(data) {
|
|
|
148927
148975
|
return value;
|
|
148928
148976
|
}
|
|
148929
148977
|
function normalizeAgents(values) {
|
|
148930
|
-
const unknown3 = values.filter((value) => !
|
|
148978
|
+
const unknown3 = values.filter((value) => !WORKFLOW_AGENT_TARGETS.includes(value));
|
|
148931
148979
|
if (unknown3.length > 0) {
|
|
148932
148980
|
throw new Error("workflow frontmatter has unsupported agent: " + unknown3[0]);
|
|
148933
148981
|
}
|
|
@@ -149203,7 +149251,7 @@ function taskScore(workflow, task) {
|
|
|
149203
149251
|
return { score, reasons: [...new Set(reasons)] };
|
|
149204
149252
|
}
|
|
149205
149253
|
function selectWorkflows(input) {
|
|
149206
|
-
const selected = input.workflows.filter((workflow) => workflow.status === "active").map((workflow) => {
|
|
149254
|
+
const selected = input.workflows.filter((workflow) => workflow.status === "active" && (!input.agent || workflow.compatibleAgents.includes(input.agent))).map((workflow) => {
|
|
149207
149255
|
const match2 = taskScore(workflow, input.task);
|
|
149208
149256
|
const cautions = input.store && input.projectId ? input.store.recentFailureCautions(input.projectId, workflow.id) : [];
|
|
149209
149257
|
return {
|
|
@@ -149483,7 +149531,7 @@ async function selectWorkspaceWorkflows(input) {
|
|
|
149483
149531
|
errors: synced.errors
|
|
149484
149532
|
};
|
|
149485
149533
|
}
|
|
149486
|
-
var
|
|
149534
|
+
var WORKFLOW_AGENT_TARGETS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
|
|
149487
149535
|
var init_workflows2 = __esm({
|
|
149488
149536
|
"src/knowledge/workflows.ts"() {
|
|
149489
149537
|
"use strict";
|
|
@@ -149495,7 +149543,7 @@ var init_workflows2 = __esm({
|
|
|
149495
149543
|
init_workflow_store();
|
|
149496
149544
|
init_outcome_store();
|
|
149497
149545
|
init_task_lens();
|
|
149498
|
-
|
|
149546
|
+
WORKFLOW_AGENT_TARGETS = [
|
|
149499
149547
|
"windsurf",
|
|
149500
149548
|
"cursor",
|
|
149501
149549
|
"claude-code",
|
|
@@ -153146,6 +153194,15 @@ function workflowOutput(selection) {
|
|
|
153146
153194
|
cautions: selection.cautions.map((caution) => short(caution, 22))
|
|
153147
153195
|
};
|
|
153148
153196
|
}
|
|
153197
|
+
function workflowLoadout(agent, selections) {
|
|
153198
|
+
if (!agent) return void 0;
|
|
153199
|
+
return {
|
|
153200
|
+
agent,
|
|
153201
|
+
workflowIds: selections.map((selection) => selection.workflow.id),
|
|
153202
|
+
requiredContext: unique(selections.flatMap((selection) => selection.workflow.requiredContext)).map((item) => short(item, 18)).slice(0, 4),
|
|
153203
|
+
allowedTools: unique(selections.flatMap((selection) => selection.workflow.allowedTools)).map((item) => short(item, 12)).slice(0, 6)
|
|
153204
|
+
};
|
|
153205
|
+
}
|
|
153149
153206
|
function appendLine(lines, candidate, maxTokens, omitted, omittedKind, selected, receiptSelection) {
|
|
153150
153207
|
const next = lines.length ? lines.join("\n") + "\n" + candidate : candidate;
|
|
153151
153208
|
if (countTextTokens(next) <= maxTokens) {
|
|
@@ -153606,6 +153663,22 @@ function renderTaskWorksetPrompt(input) {
|
|
|
153606
153663
|
);
|
|
153607
153664
|
}
|
|
153608
153665
|
}
|
|
153666
|
+
if (input.agentLoadout) {
|
|
153667
|
+
appendLine(lines, "", maxTokens, omitted, "agent-loadout-heading");
|
|
153668
|
+
appendLine(lines, "Agent loadout (" + input.agentLoadout.agent + ")", maxTokens, omitted, "agent-loadout-heading");
|
|
153669
|
+
for (const required of input.agentLoadout.requiredContext.slice(0, 2)) {
|
|
153670
|
+
appendLine(lines, "- Need: " + required, maxTokens, omitted, "agent-loadout-context");
|
|
153671
|
+
}
|
|
153672
|
+
if (input.agentLoadout.allowedTools.length > 0) {
|
|
153673
|
+
appendLine(
|
|
153674
|
+
lines,
|
|
153675
|
+
"- Workflow tools: " + input.agentLoadout.allowedTools.join(", "),
|
|
153676
|
+
maxTokens,
|
|
153677
|
+
omitted,
|
|
153678
|
+
"agent-loadout-tools"
|
|
153679
|
+
);
|
|
153680
|
+
}
|
|
153681
|
+
}
|
|
153609
153682
|
if (input.verification.length > 0) {
|
|
153610
153683
|
appendLine(lines, "", maxTokens, omitted, "verification-heading");
|
|
153611
153684
|
appendLine(lines, "Verify", maxTokens, omitted, "verification-heading");
|
|
@@ -153697,6 +153770,7 @@ async function buildTaskWorkset(input) {
|
|
|
153697
153770
|
let workspace;
|
|
153698
153771
|
let pages = [];
|
|
153699
153772
|
let workflows = [];
|
|
153773
|
+
let workflowSelections = [];
|
|
153700
153774
|
try {
|
|
153701
153775
|
workspace = await preferredWorkspace(input.projectId, input.dataDir);
|
|
153702
153776
|
if (workspace) {
|
|
@@ -153713,14 +153787,15 @@ async function buildTaskWorkset(input) {
|
|
|
153713
153787
|
if (task) {
|
|
153714
153788
|
const workflowStore = new WorkflowStore();
|
|
153715
153789
|
await workflowStore.init(input.dataDir);
|
|
153716
|
-
|
|
153790
|
+
workflowSelections = selectWorkflows({
|
|
153717
153791
|
workflows: workflowStore.listWorkflows(workspace.id, "active"),
|
|
153718
153792
|
task,
|
|
153719
153793
|
projectId: input.projectId,
|
|
153720
153794
|
store: workflowStore,
|
|
153795
|
+
...input.agent ? { agent: input.agent } : {},
|
|
153721
153796
|
limit: 2
|
|
153722
153797
|
});
|
|
153723
|
-
workflows =
|
|
153798
|
+
workflows = workflowSelections.map(workflowOutput);
|
|
153724
153799
|
for (const workflow of workflows) {
|
|
153725
153800
|
for (const caution of workflow.cautions) {
|
|
153726
153801
|
cautions.push({ kind: "workflow-failed-verification", message: caution });
|
|
@@ -153742,6 +153817,10 @@ async function buildTaskWorkset(input) {
|
|
|
153742
153817
|
workflows
|
|
153743
153818
|
});
|
|
153744
153819
|
const governedDurableIds = new Set(governed.durableMemory.map((memory) => memory.id));
|
|
153820
|
+
const agentLoadout = workflowLoadout(
|
|
153821
|
+
input.agent,
|
|
153822
|
+
workflowSelections.filter((selection2) => governed.workflows.some((workflow) => workflow.id === selection2.workflow.id))
|
|
153823
|
+
);
|
|
153745
153824
|
const evidenceIds = unique(governed.claims.flatMap((claim) => evidenceIdsForClaim(
|
|
153746
153825
|
claim,
|
|
153747
153826
|
evidenceByClaim.get(claim.id) ?? []
|
|
@@ -153786,6 +153865,7 @@ async function buildTaskWorkset(input) {
|
|
|
153786
153865
|
pages: pages.filter((page) => page.claimIds.some((claimId) => governed.claims.some((claim) => claim.id === claimId))),
|
|
153787
153866
|
durableMemory: governed.durableMemory,
|
|
153788
153867
|
workflows: governed.workflows,
|
|
153868
|
+
...agentLoadout ? { agentLoadout } : {},
|
|
153789
153869
|
cautions: normalizedCautions,
|
|
153790
153870
|
verification,
|
|
153791
153871
|
evidenceIds,
|
|
@@ -154004,10 +154084,12 @@ var init_current_facts = __esm({
|
|
|
154004
154084
|
var external_provider_exports = {};
|
|
154005
154085
|
__export(external_provider_exports, {
|
|
154006
154086
|
DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS: () => DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS,
|
|
154087
|
+
EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS: () => EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS,
|
|
154007
154088
|
MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES: () => MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES,
|
|
154008
154089
|
MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS: () => MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS,
|
|
154009
154090
|
getExternalCodeGraphContext: () => getExternalCodeGraphContext,
|
|
154010
|
-
inspectExternalCodeGraph: () => inspectExternalCodeGraph
|
|
154091
|
+
inspectExternalCodeGraph: () => inspectExternalCodeGraph,
|
|
154092
|
+
runExternalCodeGraphLifecycle: () => runExternalCodeGraphLifecycle
|
|
154011
154093
|
});
|
|
154012
154094
|
import { spawn as spawn5 } from "child_process";
|
|
154013
154095
|
import { existsSync as existsSync15, readFileSync as readFileSync10 } from "fs";
|
|
@@ -154206,6 +154288,66 @@ async function inspectExternalCodeGraph(input) {
|
|
|
154206
154288
|
const health = healthFromStatus(status);
|
|
154207
154289
|
return { health, quality: providerQuality({ mode, health }) };
|
|
154208
154290
|
}
|
|
154291
|
+
async function runExternalCodeGraphLifecycle(input) {
|
|
154292
|
+
const mode = input.mode ?? "auto";
|
|
154293
|
+
if (mode === "off") {
|
|
154294
|
+
const health = { state: "disabled", reason: "External CodeGraph is disabled by configuration." };
|
|
154295
|
+
return {
|
|
154296
|
+
action: input.action,
|
|
154297
|
+
performed: false,
|
|
154298
|
+
message: "External CodeGraph is disabled by configuration.",
|
|
154299
|
+
health,
|
|
154300
|
+
quality: providerQuality({ mode, health })
|
|
154301
|
+
};
|
|
154302
|
+
}
|
|
154303
|
+
const indexPath = join20(input.projectRoot, ".codegraph");
|
|
154304
|
+
if (input.action === "sync" && !existsSync15(indexPath)) {
|
|
154305
|
+
const health = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
|
|
154306
|
+
return {
|
|
154307
|
+
action: input.action,
|
|
154308
|
+
performed: false,
|
|
154309
|
+
message: 'Initialize CodeGraph first with "memorix codegraph init".',
|
|
154310
|
+
health,
|
|
154311
|
+
quality: providerQuality({ mode, health })
|
|
154312
|
+
};
|
|
154313
|
+
}
|
|
154314
|
+
if (input.action === "init" && existsSync15(indexPath)) {
|
|
154315
|
+
const inspected2 = await inspectExternalCodeGraph(input);
|
|
154316
|
+
return {
|
|
154317
|
+
action: input.action,
|
|
154318
|
+
performed: false,
|
|
154319
|
+
message: "A local CodeGraph directory already exists; no initialization was performed.",
|
|
154320
|
+
...inspected2
|
|
154321
|
+
};
|
|
154322
|
+
}
|
|
154323
|
+
const result = await runSafely(input.runner ?? defaultRunner, {
|
|
154324
|
+
command: input.command,
|
|
154325
|
+
args: input.action === "init" ? ["init", input.projectRoot] : ["sync", input.projectRoot, "--quiet"],
|
|
154326
|
+
cwd: input.projectRoot,
|
|
154327
|
+
// A context read must stay fast; an explicit user-requested index sync is
|
|
154328
|
+
// a different operation and gets its own bounded maintenance window.
|
|
154329
|
+
timeoutMs: EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS,
|
|
154330
|
+
maxOutputBytes: MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES
|
|
154331
|
+
});
|
|
154332
|
+
if (!result.ok) {
|
|
154333
|
+
const health = unavailableHealth(result);
|
|
154334
|
+
return {
|
|
154335
|
+
action: input.action,
|
|
154336
|
+
performed: false,
|
|
154337
|
+
message: "CodeGraph " + input.action + " did not complete: " + (health.reason ?? "unknown local error"),
|
|
154338
|
+
health,
|
|
154339
|
+
quality: providerQuality({ mode, health })
|
|
154340
|
+
};
|
|
154341
|
+
}
|
|
154342
|
+
const inspected = await inspectExternalCodeGraph(input);
|
|
154343
|
+
const remainsStale = inspected.health.state === "stale";
|
|
154344
|
+
return {
|
|
154345
|
+
action: input.action,
|
|
154346
|
+
performed: true,
|
|
154347
|
+
message: input.action === "init" ? 'Local CodeGraph initialization completed. Run "memorix codegraph sync" when source changes.' : remainsStale ? "Local CodeGraph synchronization completed, but the graph remains stale against the current worktree; this task will use Lite evidence." : "Local CodeGraph synchronization completed and is ready for task-scoped semantic context.",
|
|
154348
|
+
...inspected
|
|
154349
|
+
};
|
|
154350
|
+
}
|
|
154209
154351
|
function safeRelativePath(projectRoot, value, exclude) {
|
|
154210
154352
|
const path34 = safeText(value, 1024);
|
|
154211
154353
|
if (!path34 || isAbsolute(path34)) return void 0;
|
|
@@ -154331,7 +154473,7 @@ async function getExternalCodeGraphContext(input) {
|
|
|
154331
154473
|
quality: providerQuality({ mode, health: inspected.health, ...contributes ? { selected: "external" } : {} })
|
|
154332
154474
|
};
|
|
154333
154475
|
}
|
|
154334
|
-
var DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS, MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS, MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES, MAX_EXTERNAL_NODE_COUNT, MAX_EXTERNAL_EDGE_COUNT, MAX_EXTERNAL_FILE_COUNT, MAX_EXTERNAL_TEXT_LENGTH, LITE_SUPPORTED_LANGUAGES, defaultRunner;
|
|
154476
|
+
var DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS, MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS, EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS, MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES, MAX_EXTERNAL_NODE_COUNT, MAX_EXTERNAL_EDGE_COUNT, MAX_EXTERNAL_FILE_COUNT, MAX_EXTERNAL_TEXT_LENGTH, LITE_SUPPORTED_LANGUAGES, defaultRunner;
|
|
154335
154477
|
var init_external_provider = __esm({
|
|
154336
154478
|
"src/codegraph/external-provider.ts"() {
|
|
154337
154479
|
"use strict";
|
|
@@ -154341,6 +154483,7 @@ var init_external_provider = __esm({
|
|
|
154341
154483
|
init_ids();
|
|
154342
154484
|
DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS = 1200;
|
|
154343
154485
|
MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS = 5e3;
|
|
154486
|
+
EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS = 3e4;
|
|
154344
154487
|
MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES = 256 * 1024;
|
|
154345
154488
|
MAX_EXTERNAL_NODE_COUNT = 16;
|
|
154346
154489
|
MAX_EXTERNAL_EDGE_COUNT = 24;
|
|
@@ -155166,6 +155309,7 @@ async function buildAutoProjectContext(input) {
|
|
|
155166
155309
|
projectId: input.project.id,
|
|
155167
155310
|
dataDir: input.dataDir,
|
|
155168
155311
|
...task ? { task } : {},
|
|
155312
|
+
...input.agent ? { agent: input.agent } : {},
|
|
155169
155313
|
lens: lens.id,
|
|
155170
155314
|
startHere,
|
|
155171
155315
|
...alwaysOn.profile.length > 0 || alwaysOn.state || alwaysOn.durable.length > 0 ? { alwaysOn } : {},
|
|
@@ -155502,6 +155646,34 @@ var init_auto_context = __esm({
|
|
|
155502
155646
|
}
|
|
155503
155647
|
});
|
|
155504
155648
|
|
|
155649
|
+
// src/knowledge/context-receipt.ts
|
|
155650
|
+
var context_receipt_exports = {};
|
|
155651
|
+
__export(context_receipt_exports, {
|
|
155652
|
+
buildBoundedContextReceipt: () => buildBoundedContextReceipt
|
|
155653
|
+
});
|
|
155654
|
+
function buildBoundedContextReceipt(input) {
|
|
155655
|
+
const provider2 = input.providerQuality ?? input.workset.provenance.codeProvider;
|
|
155656
|
+
return {
|
|
155657
|
+
schemaVersion: "1",
|
|
155658
|
+
task: input.workset.task,
|
|
155659
|
+
brief: input.workset.prompt,
|
|
155660
|
+
receipt: input.workset.receipt,
|
|
155661
|
+
code: {
|
|
155662
|
+
selected: provider2?.selected ?? "lite",
|
|
155663
|
+
quality: provider2?.selectedQuality ?? "heuristic",
|
|
155664
|
+
externalState: provider2?.external.state ?? "not-detected",
|
|
155665
|
+
...input.workset.provenance.snapshotId ? { snapshotId: input.workset.provenance.snapshotId } : {}
|
|
155666
|
+
},
|
|
155667
|
+
...input.workset.agentLoadout ? { loadout: input.workset.agentLoadout } : {}
|
|
155668
|
+
};
|
|
155669
|
+
}
|
|
155670
|
+
var init_context_receipt = __esm({
|
|
155671
|
+
"src/knowledge/context-receipt.ts"() {
|
|
155672
|
+
"use strict";
|
|
155673
|
+
init_esm_shims();
|
|
155674
|
+
}
|
|
155675
|
+
});
|
|
155676
|
+
|
|
155505
155677
|
// src/codegraph/context-pack.ts
|
|
155506
155678
|
var context_pack_exports = {};
|
|
155507
155679
|
__export(context_pack_exports, {
|
|
@@ -155660,6 +155832,7 @@ async function attachTaskWorkset(input) {
|
|
|
155660
155832
|
projectId: input.projectId,
|
|
155661
155833
|
dataDir: input.dataDir,
|
|
155662
155834
|
task: input.pack.task,
|
|
155835
|
+
...input.agent ? { agent: input.agent } : {},
|
|
155663
155836
|
lens: input.lens,
|
|
155664
155837
|
currentFacts: input.currentFacts ?? [],
|
|
155665
155838
|
...input.codeState ? { codeState: input.codeState } : {},
|
|
@@ -160052,8 +160225,8 @@ var init_official_skills = __esm({
|
|
|
160052
160225
|
"",
|
|
160053
160226
|
"| Situation | Prefer | CLI fallback |",
|
|
160054
160227
|
"|---|---|---|",
|
|
160055
|
-
'| Starting a coding task and needing the best task-lensed project map | `memorix_project_context` with the user\'s task | `memorix context "<task>" --json` |',
|
|
160056
|
-
'| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --json` |',
|
|
160228
|
+
'| Starting a coding task and needing the best task-lensed project map | `memorix_project_context` with the user\'s task | `memorix context "<task>" --brief-json` |',
|
|
160229
|
+
'| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --brief-json` |',
|
|
160057
160230
|
'| Need structured refs/freshness for code-bound memories | `memorix_context_pack` | `memorix codegraph context-pack --task "<topic>"` |',
|
|
160058
160231
|
'| Explicit memory graph question | `memorix_graph_context` | `memorix memory graph-context --query "<topic>"` |',
|
|
160059
160232
|
'| Specific past decision, bug, file, or change | `memorix_search` | `memorix memory search --query "<topic>"` |',
|
|
@@ -160066,7 +160239,7 @@ var init_official_skills = __esm({
|
|
|
160066
160239
|
"",
|
|
160067
160240
|
"- 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.",
|
|
160068
160241
|
"- 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.",
|
|
160069
|
-
'- Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run `memorix resume "<task>" --json` exactly once before inspecting files, Git history, progress notes, or guessing. The absence of `.memorix` or visible memory files never proves project memory is empty. For a new task, use `memorix context "<task>" --json` instead. If that one command fails, report it and proceed normally; do not probe help, enumerate commands, or chain broad searches.',
|
|
160242
|
+
'- Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run `memorix resume "<task>" --brief-json` exactly once before inspecting files, Git history, progress notes, or guessing. The absence of `.memorix` or visible memory files never proves project memory is empty. For a new task, use `memorix context "<task>" --brief-json` instead. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally; do not probe help, enumerate commands, or chain broad searches.',
|
|
160070
160243
|
"- After a successful `memorix_project_context`, the brief is the default retrieval boundary. Do not call more Memorix retrieval tools after a complete brief. Use Context Pack, search, or detail only when the brief lacks a specific reference, freshness field, or fact needed for the task, or when the user explicitly asks for deeper history. In MCP, name that missing fact in `purpose` when intentionally expanding beyond the brief. Do not retrieve the same decision twice just to confirm an already-complete brief.",
|
|
160071
160244
|
"- If the user asks for read-only work or says not to modify files, do not call `memorix_store` just to record an assessment. Store only when the user explicitly asks to preserve it.",
|
|
160072
160245
|
"- Use `memorix_search` for a specific decision, bug, file, or prior change that the project context did not answer. Fetch detail only for a result you still need after the brief.",
|
|
@@ -161325,7 +161498,7 @@ alwaysApply: true
|
|
|
161325
161498
|
"",
|
|
161326
161499
|
`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). When the task is continuing prior work, the same brief also includes a bounded prior-work projection. Treat its "Start here" files as the first ${contextNoun} files to inspect.`,
|
|
161327
161500
|
"",
|
|
161328
|
-
'If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select `memorix_project_context` first. Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run exactly one CLI brief with the user\'s real task before inspecting files, Git history, progress notes, or guessing: `memorix resume "<task>" --json`. For a new task, use `memorix context "<task>" --json` instead. The absence of `.memorix` or visible memory files never proves project memory is empty. If that one command fails, report it and proceed normally. Do not probe help, enumerate commands, chain broad searches, wait indefinitely on MCP startup, or hand-write tool-call syntax.',
|
|
161501
|
+
'If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select `memorix_project_context` first. Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run exactly one CLI brief with the user\'s real task before inspecting files, Git history, progress notes, or guessing: `memorix resume "<task>" --brief-json`. For a new task, use `memorix context "<task>" --brief-json` instead. The absence of `.memorix` or visible memory files never proves project memory is empty. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally. Do not probe help, enumerate commands, chain broad searches, wait indefinitely on MCP startup, or hand-write tool-call syntax.',
|
|
161329
161502
|
"",
|
|
161330
161503
|
"After a successful `memorix_project_context` result, the brief is the default retrieval boundary. Do not call more Memorix retrieval tools after a complete brief. Use `memorix_context_pack`, `memorix_search`, or `memorix_detail` only when the brief lacks a specific reference, freshness field, or fact needed for the task, or when the user explicitly asks for deeper history. In MCP, name that missing fact in `purpose` when intentionally expanding beyond the brief. Do not retrieve the same decision twice just to confirm an already-complete brief.",
|
|
161331
161504
|
"If the user asks for read-only work or says not to modify files, do not call `memorix_store` just to record an assessment. Store only when the user explicitly asks to preserve it.",
|
|
@@ -165778,7 +165951,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
165778
165951
|
};
|
|
165779
165952
|
const server = existingServer ?? new McpServer({
|
|
165780
165953
|
name: "memorix",
|
|
165781
|
-
version: true ? "1.
|
|
165954
|
+
version: true ? "1.6.1" : "1.0.1"
|
|
165782
165955
|
});
|
|
165783
165956
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
165784
165957
|
server.registerTool = ((name, ...args) => {
|
|
@@ -166612,13 +166785,28 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
166612
166785
|
refresh: z626.enum(["auto", "always", "never"]).optional().default("auto").describe(
|
|
166613
166786
|
"Code Memory refresh policy. auto refreshes only when missing or stale."
|
|
166614
166787
|
),
|
|
166615
|
-
format: z626.enum(["prompt", "summary", "json"]).optional().default("prompt").describe(
|
|
166616
|
-
'Output format. "prompt" is agent-ready; "summary" is human-readable; "json" is
|
|
166788
|
+
format: z626.enum(["prompt", "summary", "json", "receipt"]).optional().default("prompt").describe(
|
|
166789
|
+
'Output format. "prompt" is agent-ready; "summary" is human-readable; "receipt" is bounded JSON; "json" is detailed diagnostics.'
|
|
166617
166790
|
),
|
|
166791
|
+
agent: z626.enum([
|
|
166792
|
+
"windsurf",
|
|
166793
|
+
"cursor",
|
|
166794
|
+
"claude-code",
|
|
166795
|
+
"codex",
|
|
166796
|
+
"copilot",
|
|
166797
|
+
"antigravity",
|
|
166798
|
+
"gemini-cli",
|
|
166799
|
+
"openclaw",
|
|
166800
|
+
"hermes",
|
|
166801
|
+
"omp",
|
|
166802
|
+
"kiro",
|
|
166803
|
+
"opencode",
|
|
166804
|
+
"trae"
|
|
166805
|
+
]).optional().describe("Optional target agent for compatible workflow selection."),
|
|
166618
166806
|
limit: z626.number().optional().describe("Reserved for future source limits; current prompt stays compact by default.")
|
|
166619
166807
|
}
|
|
166620
166808
|
},
|
|
166621
|
-
async ({ task, refresh, format }) => {
|
|
166809
|
+
async ({ task, refresh, format, agent }) => {
|
|
166622
166810
|
const unresolved = requireResolvedProject("build project context for the current project");
|
|
166623
166811
|
if (unresolved) return unresolved;
|
|
166624
166812
|
const [
|
|
@@ -166630,12 +166818,14 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
166630
166818
|
},
|
|
166631
166819
|
{ getObservationStore: getObservationStore2 },
|
|
166632
166820
|
{ MaintenanceJobStore: MaintenanceJobStore2 },
|
|
166633
|
-
{ enqueueCodegraphRefresh: enqueueCodegraphRefresh2 }
|
|
166821
|
+
{ enqueueCodegraphRefresh: enqueueCodegraphRefresh2 },
|
|
166822
|
+
{ buildBoundedContextReceipt: buildBoundedContextReceipt2 }
|
|
166634
166823
|
] = await Promise.all([
|
|
166635
166824
|
Promise.resolve().then(() => (init_auto_context(), auto_context_exports)),
|
|
166636
166825
|
Promise.resolve().then(() => (init_obs_store(), obs_store_exports)),
|
|
166637
166826
|
Promise.resolve().then(() => (init_maintenance_jobs(), maintenance_jobs_exports)),
|
|
166638
|
-
Promise.resolve().then(() => (init_lifecycle(), lifecycle_exports))
|
|
166827
|
+
Promise.resolve().then(() => (init_lifecycle(), lifecycle_exports)),
|
|
166828
|
+
Promise.resolve().then(() => (init_context_receipt(), context_receipt_exports))
|
|
166639
166829
|
]);
|
|
166640
166830
|
const observations2 = filterReadableObservations(
|
|
166641
166831
|
await getObservationStore2().loadByProject(project.id, { status: "active" }),
|
|
@@ -166646,6 +166836,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
166646
166836
|
dataDir: projectDir2,
|
|
166647
166837
|
observations: observations2,
|
|
166648
166838
|
task,
|
|
166839
|
+
agent,
|
|
166649
166840
|
refresh: refresh ?? "auto",
|
|
166650
166841
|
reader: getObservationReader(),
|
|
166651
166842
|
enqueueRefresh: () => {
|
|
@@ -166658,7 +166849,10 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
166658
166849
|
});
|
|
166659
166850
|
}
|
|
166660
166851
|
});
|
|
166661
|
-
const text2 = format === "json" ? JSON.stringify({ ...context, brief: buildAutoProjectBrief2(context) }, null, 2) : format === "
|
|
166852
|
+
const text2 = format === "json" ? JSON.stringify({ ...context, brief: buildAutoProjectBrief2(context) }, null, 2) : format === "receipt" ? JSON.stringify(buildBoundedContextReceipt2({
|
|
166853
|
+
workset: context.workset,
|
|
166854
|
+
providerQuality: context.providerQuality
|
|
166855
|
+
}), null, 2) : format === "summary" ? formatAutoProjectContextSummary2(context) : formatAutoProjectContextPrompt2(context);
|
|
166662
166856
|
autopilotRetrievalBoundary = {
|
|
166663
166857
|
projectId: project.id,
|
|
166664
166858
|
issuedAt: Date.now(),
|