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/cli/memcode.js
CHANGED
|
@@ -2,7 +2,18 @@
|
|
|
2
2
|
import {spawnSync as __ms} from "node:child_process";
|
|
3
3
|
import {fileURLToPath as __fu} from "node:url";
|
|
4
4
|
if(!process.env.__MEMORIX_HEAP){process.env.__MEMORIX_HEAP="1";
|
|
5
|
-
|
|
5
|
+
const __args=process.argv.slice(2);
|
|
6
|
+
let __cmd;
|
|
7
|
+
for(let __i=0;__i<__args.length;__i++){
|
|
8
|
+
const __a=__args[__i];
|
|
9
|
+
if(__a==="--")break;
|
|
10
|
+
if(__a.startsWith("-")){if(!__a.includes("=")&&__args[__i+1]&&!__args[__i+1].startsWith("-"))__i++;continue;}
|
|
11
|
+
__cmd=__a;break;}
|
|
12
|
+
const __fallback=__cmd==="hook"?512:4096;
|
|
13
|
+
const __raw=__cmd==="hook"?process.env.MEMORIX_HOOK_HEAP_MB:process.env.MEMORIX_HEAP_MB;
|
|
14
|
+
const __n=Number(__raw);
|
|
15
|
+
const __heap=(Number.isFinite(__n)&&__n>=64&&__n<=16384)?String(Math.floor(__n)):String(__fallback);
|
|
16
|
+
let r=__ms(process.execPath,["--max-old-space-size="+__heap,__fu(import.meta.url),...process.argv.slice(2)],{stdio:"inherit",env:process.env,windowsHide:true});
|
|
6
17
|
process.exit(r.status??1);}
|
|
7
18
|
import {createRequire as __memorix_cjsRequire} from "module";
|
|
8
19
|
const require = __memorix_cjsRequire(import.meta.url);
|
package/dist/index.js
CHANGED
|
@@ -4438,6 +4438,7 @@ __export(provider_exports, {
|
|
|
4438
4438
|
MAX_INLINE_EMBEDDING_BYTES: () => MAX_INLINE_EMBEDDING_BYTES,
|
|
4439
4439
|
UnsupportedEmbeddingModalityError: () => UnsupportedEmbeddingModalityError,
|
|
4440
4440
|
getEmbeddingProvider: () => getEmbeddingProvider,
|
|
4441
|
+
getEmbeddingRuntimeHealth: () => getEmbeddingRuntimeHealth,
|
|
4441
4442
|
isEmbeddingExplicitlyDisabled: () => isEmbeddingExplicitlyDisabled,
|
|
4442
4443
|
isVectorSearchAvailable: () => isVectorSearchAvailable,
|
|
4443
4444
|
resetProvider: () => resetProvider,
|
|
@@ -4545,13 +4546,36 @@ function isTemporaryEmbeddingFailure(error) {
|
|
|
4545
4546
|
if (!(error instanceof Error)) return false;
|
|
4546
4547
|
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);
|
|
4547
4548
|
}
|
|
4549
|
+
function classifyEmbeddingFailure(error) {
|
|
4550
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4551
|
+
if (/embedding api error \(401\)|invalid_api_key|incorrect api key|unauthorized/i.test(message)) {
|
|
4552
|
+
return "authorization";
|
|
4553
|
+
}
|
|
4554
|
+
if (/embedding api error \(402\)|quota exceeded|account balance/i.test(message)) {
|
|
4555
|
+
return "billing";
|
|
4556
|
+
}
|
|
4557
|
+
if (/embedding api timeout|abort/i.test(message)) {
|
|
4558
|
+
return "timeout";
|
|
4559
|
+
}
|
|
4560
|
+
return "upstream";
|
|
4561
|
+
}
|
|
4548
4562
|
function markTemporaryFailure(reason) {
|
|
4549
4563
|
provider = null;
|
|
4550
4564
|
initPromise = null;
|
|
4551
4565
|
lastInitWasTemporaryFailure = true;
|
|
4552
4566
|
lastFailureTimestamp = Date.now();
|
|
4567
|
+
lastEmbeddingFailure = {
|
|
4568
|
+
kind: classifyEmbeddingFailure(reason),
|
|
4569
|
+
occurredAt: lastFailureTimestamp
|
|
4570
|
+
};
|
|
4553
4571
|
const message = reason instanceof Error ? reason.message : String(reason);
|
|
4554
|
-
warnOnce(`[memorix] Embedding provider
|
|
4572
|
+
warnOnce(`[memorix] Embedding provider unavailable at runtime: ${message}`);
|
|
4573
|
+
}
|
|
4574
|
+
function markProviderReady(candidate) {
|
|
4575
|
+
provider = wrapProvider(candidate);
|
|
4576
|
+
lastInitWasTemporaryFailure = false;
|
|
4577
|
+
lastEmbeddingFailure = null;
|
|
4578
|
+
return provider;
|
|
4555
4579
|
}
|
|
4556
4580
|
async function createFastEmbedProvider() {
|
|
4557
4581
|
try {
|
|
@@ -4667,35 +4691,35 @@ async function getEmbeddingProvider(options = {}) {
|
|
|
4667
4691
|
if (mode === "fastembed") {
|
|
4668
4692
|
const initialized = await createFastEmbedProvider();
|
|
4669
4693
|
if (!initialized) return null;
|
|
4670
|
-
provider =
|
|
4694
|
+
provider = markProviderReady(initialized);
|
|
4671
4695
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4672
4696
|
return provider;
|
|
4673
4697
|
}
|
|
4674
4698
|
if (mode === "transformers") {
|
|
4675
4699
|
const initialized = await createTransformersProvider();
|
|
4676
4700
|
if (!initialized) return null;
|
|
4677
|
-
provider =
|
|
4701
|
+
provider = markProviderReady(initialized);
|
|
4678
4702
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4679
4703
|
return provider;
|
|
4680
4704
|
}
|
|
4681
4705
|
if (mode === "api") {
|
|
4682
4706
|
const initialized = await createAPIProvider(options);
|
|
4683
4707
|
if (!initialized) return null;
|
|
4684
|
-
provider =
|
|
4708
|
+
provider = markProviderReady(initialized);
|
|
4685
4709
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4686
4710
|
return provider;
|
|
4687
4711
|
}
|
|
4688
4712
|
if (hasAPIEmbeddingConfig()) {
|
|
4689
4713
|
const initialized = await createAPIProvider(options);
|
|
4690
4714
|
if (initialized) {
|
|
4691
|
-
provider =
|
|
4715
|
+
provider = markProviderReady(initialized);
|
|
4692
4716
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4693
4717
|
return provider;
|
|
4694
4718
|
}
|
|
4695
4719
|
}
|
|
4696
4720
|
const localFallback = await createLocalFallbackProvider();
|
|
4697
4721
|
if (localFallback) {
|
|
4698
|
-
provider =
|
|
4722
|
+
provider = markProviderReady(localFallback);
|
|
4699
4723
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4700
4724
|
return provider;
|
|
4701
4725
|
}
|
|
@@ -4717,6 +4741,27 @@ async function isVectorSearchAvailable() {
|
|
|
4717
4741
|
const p = await getEmbeddingProvider();
|
|
4718
4742
|
return p !== null;
|
|
4719
4743
|
}
|
|
4744
|
+
function getEmbeddingRuntimeHealth() {
|
|
4745
|
+
const mode = getEmbeddingMode2();
|
|
4746
|
+
if (mode === "off") return { status: "disabled" };
|
|
4747
|
+
if (lastInitWasTemporaryFailure && lastEmbeddingFailure) {
|
|
4748
|
+
return {
|
|
4749
|
+
status: "degraded",
|
|
4750
|
+
failure: {
|
|
4751
|
+
kind: lastEmbeddingFailure.kind,
|
|
4752
|
+
occurredAt: new Date(lastEmbeddingFailure.occurredAt).toISOString(),
|
|
4753
|
+
retryAfterMs: Math.max(0, RETRY_COOLDOWN_MS - (Date.now() - lastEmbeddingFailure.occurredAt))
|
|
4754
|
+
}
|
|
4755
|
+
};
|
|
4756
|
+
}
|
|
4757
|
+
if (provider) {
|
|
4758
|
+
return {
|
|
4759
|
+
status: "ready",
|
|
4760
|
+
provider: { name: provider.name, dimensions: provider.dimensions }
|
|
4761
|
+
};
|
|
4762
|
+
}
|
|
4763
|
+
return { status: "uninitialized" };
|
|
4764
|
+
}
|
|
4720
4765
|
function isEmbeddingExplicitlyDisabled() {
|
|
4721
4766
|
return getEmbeddingMode2() === "off";
|
|
4722
4767
|
}
|
|
@@ -4725,10 +4770,11 @@ function resetProvider() {
|
|
|
4725
4770
|
initPromise = null;
|
|
4726
4771
|
lastInitWasTemporaryFailure = false;
|
|
4727
4772
|
lastFailureTimestamp = 0;
|
|
4773
|
+
lastEmbeddingFailure = null;
|
|
4728
4774
|
lastEmbeddingWarning = "";
|
|
4729
4775
|
lastEmbeddingWarningAt = 0;
|
|
4730
4776
|
}
|
|
4731
|
-
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
4777
|
+
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
4732
4778
|
var init_provider = __esm({
|
|
4733
4779
|
"src/embedding/provider.ts"() {
|
|
4734
4780
|
"use strict";
|
|
@@ -4753,6 +4799,7 @@ var init_provider = __esm({
|
|
|
4753
4799
|
provider = null;
|
|
4754
4800
|
initPromise = null;
|
|
4755
4801
|
lastInitWasTemporaryFailure = false;
|
|
4802
|
+
lastEmbeddingFailure = null;
|
|
4756
4803
|
lastEmbeddingWarning = "";
|
|
4757
4804
|
lastEmbeddingWarningAt = 0;
|
|
4758
4805
|
WARNING_COOLDOWN_MS = 3e4;
|
|
@@ -148858,6 +148905,7 @@ var init_task_lens = __esm({
|
|
|
148858
148905
|
var workflows_exports = {};
|
|
148859
148906
|
__export(workflows_exports, {
|
|
148860
148907
|
WORKFLOW_ADAPTER_TARGETS: () => WORKFLOW_ADAPTER_TARGETS,
|
|
148908
|
+
WORKFLOW_AGENT_TARGETS: () => WORKFLOW_AGENT_TARGETS,
|
|
148861
148909
|
applyWorkflowAdapter: () => applyWorkflowAdapter,
|
|
148862
148910
|
importWindsurfWorkflows: () => importWindsurfWorkflows,
|
|
148863
148911
|
parseWorkflowMarkdown: () => parseWorkflowMarkdown,
|
|
@@ -148923,7 +148971,7 @@ function optionalStatus(data) {
|
|
|
148923
148971
|
return value;
|
|
148924
148972
|
}
|
|
148925
148973
|
function normalizeAgents(values) {
|
|
148926
|
-
const unknown3 = values.filter((value) => !
|
|
148974
|
+
const unknown3 = values.filter((value) => !WORKFLOW_AGENT_TARGETS.includes(value));
|
|
148927
148975
|
if (unknown3.length > 0) {
|
|
148928
148976
|
throw new Error("workflow frontmatter has unsupported agent: " + unknown3[0]);
|
|
148929
148977
|
}
|
|
@@ -149199,7 +149247,7 @@ function taskScore(workflow, task) {
|
|
|
149199
149247
|
return { score, reasons: [...new Set(reasons)] };
|
|
149200
149248
|
}
|
|
149201
149249
|
function selectWorkflows(input) {
|
|
149202
|
-
const selected = input.workflows.filter((workflow) => workflow.status === "active").map((workflow) => {
|
|
149250
|
+
const selected = input.workflows.filter((workflow) => workflow.status === "active" && (!input.agent || workflow.compatibleAgents.includes(input.agent))).map((workflow) => {
|
|
149203
149251
|
const match2 = taskScore(workflow, input.task);
|
|
149204
149252
|
const cautions = input.store && input.projectId ? input.store.recentFailureCautions(input.projectId, workflow.id) : [];
|
|
149205
149253
|
return {
|
|
@@ -149479,7 +149527,7 @@ async function selectWorkspaceWorkflows(input) {
|
|
|
149479
149527
|
errors: synced.errors
|
|
149480
149528
|
};
|
|
149481
149529
|
}
|
|
149482
|
-
var
|
|
149530
|
+
var WORKFLOW_AGENT_TARGETS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
|
|
149483
149531
|
var init_workflows2 = __esm({
|
|
149484
149532
|
"src/knowledge/workflows.ts"() {
|
|
149485
149533
|
"use strict";
|
|
@@ -149491,7 +149539,7 @@ var init_workflows2 = __esm({
|
|
|
149491
149539
|
init_workflow_store();
|
|
149492
149540
|
init_outcome_store();
|
|
149493
149541
|
init_task_lens();
|
|
149494
|
-
|
|
149542
|
+
WORKFLOW_AGENT_TARGETS = [
|
|
149495
149543
|
"windsurf",
|
|
149496
149544
|
"cursor",
|
|
149497
149545
|
"claude-code",
|
|
@@ -157127,6 +157175,15 @@ function workflowOutput(selection) {
|
|
|
157127
157175
|
cautions: selection.cautions.map((caution) => short(caution, 22))
|
|
157128
157176
|
};
|
|
157129
157177
|
}
|
|
157178
|
+
function workflowLoadout(agent, selections) {
|
|
157179
|
+
if (!agent) return void 0;
|
|
157180
|
+
return {
|
|
157181
|
+
agent,
|
|
157182
|
+
workflowIds: selections.map((selection) => selection.workflow.id),
|
|
157183
|
+
requiredContext: unique(selections.flatMap((selection) => selection.workflow.requiredContext)).map((item) => short(item, 18)).slice(0, 4),
|
|
157184
|
+
allowedTools: unique(selections.flatMap((selection) => selection.workflow.allowedTools)).map((item) => short(item, 12)).slice(0, 6)
|
|
157185
|
+
};
|
|
157186
|
+
}
|
|
157130
157187
|
function appendLine(lines, candidate, maxTokens, omitted, omittedKind, selected, receiptSelection) {
|
|
157131
157188
|
const next = lines.length ? lines.join("\n") + "\n" + candidate : candidate;
|
|
157132
157189
|
if (countTextTokens(next) <= maxTokens) {
|
|
@@ -157587,6 +157644,22 @@ function renderTaskWorksetPrompt(input) {
|
|
|
157587
157644
|
);
|
|
157588
157645
|
}
|
|
157589
157646
|
}
|
|
157647
|
+
if (input.agentLoadout) {
|
|
157648
|
+
appendLine(lines, "", maxTokens, omitted, "agent-loadout-heading");
|
|
157649
|
+
appendLine(lines, "Agent loadout (" + input.agentLoadout.agent + ")", maxTokens, omitted, "agent-loadout-heading");
|
|
157650
|
+
for (const required of input.agentLoadout.requiredContext.slice(0, 2)) {
|
|
157651
|
+
appendLine(lines, "- Need: " + required, maxTokens, omitted, "agent-loadout-context");
|
|
157652
|
+
}
|
|
157653
|
+
if (input.agentLoadout.allowedTools.length > 0) {
|
|
157654
|
+
appendLine(
|
|
157655
|
+
lines,
|
|
157656
|
+
"- Workflow tools: " + input.agentLoadout.allowedTools.join(", "),
|
|
157657
|
+
maxTokens,
|
|
157658
|
+
omitted,
|
|
157659
|
+
"agent-loadout-tools"
|
|
157660
|
+
);
|
|
157661
|
+
}
|
|
157662
|
+
}
|
|
157590
157663
|
if (input.verification.length > 0) {
|
|
157591
157664
|
appendLine(lines, "", maxTokens, omitted, "verification-heading");
|
|
157592
157665
|
appendLine(lines, "Verify", maxTokens, omitted, "verification-heading");
|
|
@@ -157678,6 +157751,7 @@ async function buildTaskWorkset(input) {
|
|
|
157678
157751
|
let workspace;
|
|
157679
157752
|
let pages = [];
|
|
157680
157753
|
let workflows = [];
|
|
157754
|
+
let workflowSelections = [];
|
|
157681
157755
|
try {
|
|
157682
157756
|
workspace = await preferredWorkspace(input.projectId, input.dataDir);
|
|
157683
157757
|
if (workspace) {
|
|
@@ -157694,14 +157768,15 @@ async function buildTaskWorkset(input) {
|
|
|
157694
157768
|
if (task) {
|
|
157695
157769
|
const workflowStore = new WorkflowStore();
|
|
157696
157770
|
await workflowStore.init(input.dataDir);
|
|
157697
|
-
|
|
157771
|
+
workflowSelections = selectWorkflows({
|
|
157698
157772
|
workflows: workflowStore.listWorkflows(workspace.id, "active"),
|
|
157699
157773
|
task,
|
|
157700
157774
|
projectId: input.projectId,
|
|
157701
157775
|
store: workflowStore,
|
|
157776
|
+
...input.agent ? { agent: input.agent } : {},
|
|
157702
157777
|
limit: 2
|
|
157703
157778
|
});
|
|
157704
|
-
workflows =
|
|
157779
|
+
workflows = workflowSelections.map(workflowOutput);
|
|
157705
157780
|
for (const workflow of workflows) {
|
|
157706
157781
|
for (const caution of workflow.cautions) {
|
|
157707
157782
|
cautions.push({ kind: "workflow-failed-verification", message: caution });
|
|
@@ -157723,6 +157798,10 @@ async function buildTaskWorkset(input) {
|
|
|
157723
157798
|
workflows
|
|
157724
157799
|
});
|
|
157725
157800
|
const governedDurableIds = new Set(governed.durableMemory.map((memory) => memory.id));
|
|
157801
|
+
const agentLoadout = workflowLoadout(
|
|
157802
|
+
input.agent,
|
|
157803
|
+
workflowSelections.filter((selection2) => governed.workflows.some((workflow) => workflow.id === selection2.workflow.id))
|
|
157804
|
+
);
|
|
157726
157805
|
const evidenceIds = unique(governed.claims.flatMap((claim) => evidenceIdsForClaim(
|
|
157727
157806
|
claim,
|
|
157728
157807
|
evidenceByClaim.get(claim.id) ?? []
|
|
@@ -157767,6 +157846,7 @@ async function buildTaskWorkset(input) {
|
|
|
157767
157846
|
pages: pages.filter((page) => page.claimIds.some((claimId) => governed.claims.some((claim) => claim.id === claimId))),
|
|
157768
157847
|
durableMemory: governed.durableMemory,
|
|
157769
157848
|
workflows: governed.workflows,
|
|
157849
|
+
...agentLoadout ? { agentLoadout } : {},
|
|
157770
157850
|
cautions: normalizedCautions,
|
|
157771
157851
|
verification,
|
|
157772
157852
|
evidenceIds,
|
|
@@ -157985,10 +158065,12 @@ var init_current_facts = __esm({
|
|
|
157985
158065
|
var external_provider_exports = {};
|
|
157986
158066
|
__export(external_provider_exports, {
|
|
157987
158067
|
DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS: () => DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS,
|
|
158068
|
+
EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS: () => EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS,
|
|
157988
158069
|
MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES: () => MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES,
|
|
157989
158070
|
MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS: () => MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS,
|
|
157990
158071
|
getExternalCodeGraphContext: () => getExternalCodeGraphContext,
|
|
157991
|
-
inspectExternalCodeGraph: () => inspectExternalCodeGraph
|
|
158072
|
+
inspectExternalCodeGraph: () => inspectExternalCodeGraph,
|
|
158073
|
+
runExternalCodeGraphLifecycle: () => runExternalCodeGraphLifecycle
|
|
157992
158074
|
});
|
|
157993
158075
|
import { spawn as spawn5 } from "child_process";
|
|
157994
158076
|
import { existsSync as existsSync15, readFileSync as readFileSync10 } from "fs";
|
|
@@ -158187,6 +158269,66 @@ async function inspectExternalCodeGraph(input) {
|
|
|
158187
158269
|
const health = healthFromStatus(status);
|
|
158188
158270
|
return { health, quality: providerQuality({ mode, health }) };
|
|
158189
158271
|
}
|
|
158272
|
+
async function runExternalCodeGraphLifecycle(input) {
|
|
158273
|
+
const mode = input.mode ?? "auto";
|
|
158274
|
+
if (mode === "off") {
|
|
158275
|
+
const health = { state: "disabled", reason: "External CodeGraph is disabled by configuration." };
|
|
158276
|
+
return {
|
|
158277
|
+
action: input.action,
|
|
158278
|
+
performed: false,
|
|
158279
|
+
message: "External CodeGraph is disabled by configuration.",
|
|
158280
|
+
health,
|
|
158281
|
+
quality: providerQuality({ mode, health })
|
|
158282
|
+
};
|
|
158283
|
+
}
|
|
158284
|
+
const indexPath = join20(input.projectRoot, ".codegraph");
|
|
158285
|
+
if (input.action === "sync" && !existsSync15(indexPath)) {
|
|
158286
|
+
const health = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
|
|
158287
|
+
return {
|
|
158288
|
+
action: input.action,
|
|
158289
|
+
performed: false,
|
|
158290
|
+
message: 'Initialize CodeGraph first with "memorix codegraph init".',
|
|
158291
|
+
health,
|
|
158292
|
+
quality: providerQuality({ mode, health })
|
|
158293
|
+
};
|
|
158294
|
+
}
|
|
158295
|
+
if (input.action === "init" && existsSync15(indexPath)) {
|
|
158296
|
+
const inspected2 = await inspectExternalCodeGraph(input);
|
|
158297
|
+
return {
|
|
158298
|
+
action: input.action,
|
|
158299
|
+
performed: false,
|
|
158300
|
+
message: "A local CodeGraph directory already exists; no initialization was performed.",
|
|
158301
|
+
...inspected2
|
|
158302
|
+
};
|
|
158303
|
+
}
|
|
158304
|
+
const result = await runSafely(input.runner ?? defaultRunner, {
|
|
158305
|
+
command: input.command,
|
|
158306
|
+
args: input.action === "init" ? ["init", input.projectRoot] : ["sync", input.projectRoot, "--quiet"],
|
|
158307
|
+
cwd: input.projectRoot,
|
|
158308
|
+
// A context read must stay fast; an explicit user-requested index sync is
|
|
158309
|
+
// a different operation and gets its own bounded maintenance window.
|
|
158310
|
+
timeoutMs: EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS,
|
|
158311
|
+
maxOutputBytes: MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES
|
|
158312
|
+
});
|
|
158313
|
+
if (!result.ok) {
|
|
158314
|
+
const health = unavailableHealth(result);
|
|
158315
|
+
return {
|
|
158316
|
+
action: input.action,
|
|
158317
|
+
performed: false,
|
|
158318
|
+
message: "CodeGraph " + input.action + " did not complete: " + (health.reason ?? "unknown local error"),
|
|
158319
|
+
health,
|
|
158320
|
+
quality: providerQuality({ mode, health })
|
|
158321
|
+
};
|
|
158322
|
+
}
|
|
158323
|
+
const inspected = await inspectExternalCodeGraph(input);
|
|
158324
|
+
const remainsStale = inspected.health.state === "stale";
|
|
158325
|
+
return {
|
|
158326
|
+
action: input.action,
|
|
158327
|
+
performed: true,
|
|
158328
|
+
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.",
|
|
158329
|
+
...inspected
|
|
158330
|
+
};
|
|
158331
|
+
}
|
|
158190
158332
|
function safeRelativePath(projectRoot, value, exclude) {
|
|
158191
158333
|
const path37 = safeText(value, 1024);
|
|
158192
158334
|
if (!path37 || isAbsolute(path37)) return void 0;
|
|
@@ -158312,7 +158454,7 @@ async function getExternalCodeGraphContext(input) {
|
|
|
158312
158454
|
quality: providerQuality({ mode, health: inspected.health, ...contributes ? { selected: "external" } : {} })
|
|
158313
158455
|
};
|
|
158314
158456
|
}
|
|
158315
|
-
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;
|
|
158457
|
+
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;
|
|
158316
158458
|
var init_external_provider = __esm({
|
|
158317
158459
|
"src/codegraph/external-provider.ts"() {
|
|
158318
158460
|
"use strict";
|
|
@@ -158322,6 +158464,7 @@ var init_external_provider = __esm({
|
|
|
158322
158464
|
init_ids();
|
|
158323
158465
|
DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS = 1200;
|
|
158324
158466
|
MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS = 5e3;
|
|
158467
|
+
EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS = 3e4;
|
|
158325
158468
|
MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES = 256 * 1024;
|
|
158326
158469
|
MAX_EXTERNAL_NODE_COUNT = 16;
|
|
158327
158470
|
MAX_EXTERNAL_EDGE_COUNT = 24;
|
|
@@ -159147,6 +159290,7 @@ async function buildAutoProjectContext(input) {
|
|
|
159147
159290
|
projectId: input.project.id,
|
|
159148
159291
|
dataDir: input.dataDir,
|
|
159149
159292
|
...task ? { task } : {},
|
|
159293
|
+
...input.agent ? { agent: input.agent } : {},
|
|
159150
159294
|
lens: lens.id,
|
|
159151
159295
|
startHere,
|
|
159152
159296
|
...alwaysOn.profile.length > 0 || alwaysOn.state || alwaysOn.durable.length > 0 ? { alwaysOn } : {},
|
|
@@ -159483,6 +159627,34 @@ var init_auto_context = __esm({
|
|
|
159483
159627
|
}
|
|
159484
159628
|
});
|
|
159485
159629
|
|
|
159630
|
+
// src/knowledge/context-receipt.ts
|
|
159631
|
+
var context_receipt_exports = {};
|
|
159632
|
+
__export(context_receipt_exports, {
|
|
159633
|
+
buildBoundedContextReceipt: () => buildBoundedContextReceipt
|
|
159634
|
+
});
|
|
159635
|
+
function buildBoundedContextReceipt(input) {
|
|
159636
|
+
const provider2 = input.providerQuality ?? input.workset.provenance.codeProvider;
|
|
159637
|
+
return {
|
|
159638
|
+
schemaVersion: "1",
|
|
159639
|
+
task: input.workset.task,
|
|
159640
|
+
brief: input.workset.prompt,
|
|
159641
|
+
receipt: input.workset.receipt,
|
|
159642
|
+
code: {
|
|
159643
|
+
selected: provider2?.selected ?? "lite",
|
|
159644
|
+
quality: provider2?.selectedQuality ?? "heuristic",
|
|
159645
|
+
externalState: provider2?.external.state ?? "not-detected",
|
|
159646
|
+
...input.workset.provenance.snapshotId ? { snapshotId: input.workset.provenance.snapshotId } : {}
|
|
159647
|
+
},
|
|
159648
|
+
...input.workset.agentLoadout ? { loadout: input.workset.agentLoadout } : {}
|
|
159649
|
+
};
|
|
159650
|
+
}
|
|
159651
|
+
var init_context_receipt = __esm({
|
|
159652
|
+
"src/knowledge/context-receipt.ts"() {
|
|
159653
|
+
"use strict";
|
|
159654
|
+
init_esm_shims();
|
|
159655
|
+
}
|
|
159656
|
+
});
|
|
159657
|
+
|
|
159486
159658
|
// src/codegraph/context-pack.ts
|
|
159487
159659
|
var context_pack_exports = {};
|
|
159488
159660
|
__export(context_pack_exports, {
|
|
@@ -159641,6 +159813,7 @@ async function attachTaskWorkset(input) {
|
|
|
159641
159813
|
projectId: input.projectId,
|
|
159642
159814
|
dataDir: input.dataDir,
|
|
159643
159815
|
task: input.pack.task,
|
|
159816
|
+
...input.agent ? { agent: input.agent } : {},
|
|
159644
159817
|
lens: input.lens,
|
|
159645
159818
|
currentFacts: input.currentFacts ?? [],
|
|
159646
159819
|
...input.codeState ? { codeState: input.codeState } : {},
|
|
@@ -164033,8 +164206,8 @@ var init_official_skills = __esm({
|
|
|
164033
164206
|
"",
|
|
164034
164207
|
"| Situation | Prefer | CLI fallback |",
|
|
164035
164208
|
"|---|---|---|",
|
|
164036
|
-
'| Starting a coding task and needing the best task-lensed project map | `memorix_project_context` with the user\'s task | `memorix context "<task>" --json` |',
|
|
164037
|
-
'| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --json` |',
|
|
164209
|
+
'| 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` |',
|
|
164210
|
+
'| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --brief-json` |',
|
|
164038
164211
|
'| Need structured refs/freshness for code-bound memories | `memorix_context_pack` | `memorix codegraph context-pack --task "<topic>"` |',
|
|
164039
164212
|
'| Explicit memory graph question | `memorix_graph_context` | `memorix memory graph-context --query "<topic>"` |',
|
|
164040
164213
|
'| Specific past decision, bug, file, or change | `memorix_search` | `memorix memory search --query "<topic>"` |',
|
|
@@ -164047,7 +164220,7 @@ var init_official_skills = __esm({
|
|
|
164047
164220
|
"",
|
|
164048
164221
|
"- 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.",
|
|
164049
164222
|
"- 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.",
|
|
164050
|
-
'- 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.',
|
|
164223
|
+
'- 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.',
|
|
164051
164224
|
"- 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.",
|
|
164052
164225
|
"- 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.",
|
|
164053
164226
|
"- 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.",
|
|
@@ -165306,7 +165479,7 @@ alwaysApply: true
|
|
|
165306
165479
|
"",
|
|
165307
165480
|
`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.`,
|
|
165308
165481
|
"",
|
|
165309
|
-
'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.',
|
|
165482
|
+
'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.',
|
|
165310
165483
|
"",
|
|
165311
165484
|
"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.",
|
|
165312
165485
|
"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.",
|
|
@@ -165970,7 +166143,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
165970
166143
|
};
|
|
165971
166144
|
const server = existingServer ?? new McpServer({
|
|
165972
166145
|
name: "memorix",
|
|
165973
|
-
version: true ? "1.
|
|
166146
|
+
version: true ? "1.6.1" : "1.0.1"
|
|
165974
166147
|
});
|
|
165975
166148
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
165976
166149
|
server.registerTool = ((name, ...args) => {
|
|
@@ -166804,13 +166977,28 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
166804
166977
|
refresh: z626.enum(["auto", "always", "never"]).optional().default("auto").describe(
|
|
166805
166978
|
"Code Memory refresh policy. auto refreshes only when missing or stale."
|
|
166806
166979
|
),
|
|
166807
|
-
format: z626.enum(["prompt", "summary", "json"]).optional().default("prompt").describe(
|
|
166808
|
-
'Output format. "prompt" is agent-ready; "summary" is human-readable; "json" is
|
|
166980
|
+
format: z626.enum(["prompt", "summary", "json", "receipt"]).optional().default("prompt").describe(
|
|
166981
|
+
'Output format. "prompt" is agent-ready; "summary" is human-readable; "receipt" is bounded JSON; "json" is detailed diagnostics.'
|
|
166809
166982
|
),
|
|
166983
|
+
agent: z626.enum([
|
|
166984
|
+
"windsurf",
|
|
166985
|
+
"cursor",
|
|
166986
|
+
"claude-code",
|
|
166987
|
+
"codex",
|
|
166988
|
+
"copilot",
|
|
166989
|
+
"antigravity",
|
|
166990
|
+
"gemini-cli",
|
|
166991
|
+
"openclaw",
|
|
166992
|
+
"hermes",
|
|
166993
|
+
"omp",
|
|
166994
|
+
"kiro",
|
|
166995
|
+
"opencode",
|
|
166996
|
+
"trae"
|
|
166997
|
+
]).optional().describe("Optional target agent for compatible workflow selection."),
|
|
166810
166998
|
limit: z626.number().optional().describe("Reserved for future source limits; current prompt stays compact by default.")
|
|
166811
166999
|
}
|
|
166812
167000
|
},
|
|
166813
|
-
async ({ task, refresh, format }) => {
|
|
167001
|
+
async ({ task, refresh, format, agent }) => {
|
|
166814
167002
|
const unresolved = requireResolvedProject("build project context for the current project");
|
|
166815
167003
|
if (unresolved) return unresolved;
|
|
166816
167004
|
const [
|
|
@@ -166822,12 +167010,14 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
166822
167010
|
},
|
|
166823
167011
|
{ getObservationStore: getObservationStore2 },
|
|
166824
167012
|
{ MaintenanceJobStore: MaintenanceJobStore2 },
|
|
166825
|
-
{ enqueueCodegraphRefresh: enqueueCodegraphRefresh2 }
|
|
167013
|
+
{ enqueueCodegraphRefresh: enqueueCodegraphRefresh2 },
|
|
167014
|
+
{ buildBoundedContextReceipt: buildBoundedContextReceipt2 }
|
|
166826
167015
|
] = await Promise.all([
|
|
166827
167016
|
Promise.resolve().then(() => (init_auto_context(), auto_context_exports)),
|
|
166828
167017
|
Promise.resolve().then(() => (init_obs_store(), obs_store_exports)),
|
|
166829
167018
|
Promise.resolve().then(() => (init_maintenance_jobs(), maintenance_jobs_exports)),
|
|
166830
|
-
Promise.resolve().then(() => (init_lifecycle(), lifecycle_exports))
|
|
167019
|
+
Promise.resolve().then(() => (init_lifecycle(), lifecycle_exports)),
|
|
167020
|
+
Promise.resolve().then(() => (init_context_receipt(), context_receipt_exports))
|
|
166831
167021
|
]);
|
|
166832
167022
|
const observations2 = filterReadableObservations(
|
|
166833
167023
|
await getObservationStore2().loadByProject(project.id, { status: "active" }),
|
|
@@ -166838,6 +167028,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
166838
167028
|
dataDir: projectDir2,
|
|
166839
167029
|
observations: observations2,
|
|
166840
167030
|
task,
|
|
167031
|
+
agent,
|
|
166841
167032
|
refresh: refresh ?? "auto",
|
|
166842
167033
|
reader: getObservationReader(),
|
|
166843
167034
|
enqueueRefresh: () => {
|
|
@@ -166850,7 +167041,10 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
166850
167041
|
});
|
|
166851
167042
|
}
|
|
166852
167043
|
});
|
|
166853
|
-
const text2 = format === "json" ? JSON.stringify({ ...context, brief: buildAutoProjectBrief2(context) }, null, 2) : format === "
|
|
167044
|
+
const text2 = format === "json" ? JSON.stringify({ ...context, brief: buildAutoProjectBrief2(context) }, null, 2) : format === "receipt" ? JSON.stringify(buildBoundedContextReceipt2({
|
|
167045
|
+
workset: context.workset,
|
|
167046
|
+
providerQuality: context.providerQuality
|
|
167047
|
+
}), null, 2) : format === "summary" ? formatAutoProjectContextSummary2(context) : formatAutoProjectContextPrompt2(context);
|
|
166854
167048
|
autopilotRetrievalBoundary = {
|
|
166855
167049
|
projectId: project.id,
|
|
166856
167050
|
issuedAt: Date.now(),
|
|
@@ -170355,7 +170549,7 @@ var init_serve_shared = __esm({
|
|
|
170355
170549
|
|
|
170356
170550
|
// src/cli/version.ts
|
|
170357
170551
|
function getCliVersion() {
|
|
170358
|
-
return true ? "1.
|
|
170552
|
+
return true ? "1.6.1" : pkg.version;
|
|
170359
170553
|
}
|
|
170360
170554
|
var init_version3 = __esm({
|
|
170361
170555
|
"src/cli/version.ts"() {
|