memorix 1.0.9 → 1.0.10
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 +19 -0
- package/README.md +16 -14
- package/README.zh-CN.md +8 -9
- package/dist/cli/index.js +615 -280
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +96 -21
- package/dist/index.js.map +1 -1
- package/dist/sdk.js +96 -21
- package/dist/sdk.js.map +1 -1
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +28 -29
- package/docs/API_REFERENCE.md +19 -2
- package/docs/CONFIGURATION.md +80 -33
- package/docs/DEVELOPMENT.md +10 -10
- package/docs/README.md +2 -2
- package/docs/SETUP.md +50 -26
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1607,6 +1607,7 @@ var init_mini_skills = __esm({
|
|
|
1607
1607
|
// src/config/yaml-loader.ts
|
|
1608
1608
|
var yaml_loader_exports = {};
|
|
1609
1609
|
__export(yaml_loader_exports, {
|
|
1610
|
+
clearProjectRoot: () => clearProjectRoot,
|
|
1610
1611
|
initProjectRoot: () => initProjectRoot,
|
|
1611
1612
|
loadYamlConfig: () => loadYamlConfig,
|
|
1612
1613
|
resetYamlConfigCache: () => resetYamlConfigCache
|
|
@@ -1618,6 +1619,9 @@ function initProjectRoot(root) {
|
|
|
1618
1619
|
globalProjectRoot = root;
|
|
1619
1620
|
configCache.delete(root);
|
|
1620
1621
|
}
|
|
1622
|
+
function clearProjectRoot() {
|
|
1623
|
+
globalProjectRoot = null;
|
|
1624
|
+
}
|
|
1621
1625
|
function loadYamlConfig(projectRoot) {
|
|
1622
1626
|
const resolvedRoot = projectRoot === null ? null : projectRoot ?? globalProjectRoot ?? null;
|
|
1623
1627
|
const cached2 = configCache.get(resolvedRoot ?? null);
|
|
@@ -1645,6 +1649,7 @@ function loadYamlConfig(projectRoot) {
|
|
|
1645
1649
|
...projectConfig,
|
|
1646
1650
|
// Deep merge for nested objects where both exist
|
|
1647
1651
|
llm: { ...userConfig.llm, ...projectConfig.llm },
|
|
1652
|
+
agent: { ...userConfig.agent, ...projectConfig.agent },
|
|
1648
1653
|
embedding: { ...userConfig.embedding, ...projectConfig.embedding },
|
|
1649
1654
|
git: { ...userConfig.git, ...projectConfig.git },
|
|
1650
1655
|
behavior: { ...userConfig.behavior, ...projectConfig.behavior },
|
|
@@ -1747,6 +1752,10 @@ var init_dotenv_loader = __esm({
|
|
|
1747
1752
|
// src/config.ts
|
|
1748
1753
|
var config_exports = {};
|
|
1749
1754
|
__export(config_exports, {
|
|
1755
|
+
getAgentLLMApiKey: () => getAgentLLMApiKey,
|
|
1756
|
+
getAgentLLMBaseUrl: () => getAgentLLMBaseUrl,
|
|
1757
|
+
getAgentLLMModel: () => getAgentLLMModel,
|
|
1758
|
+
getAgentLLMProvider: () => getAgentLLMProvider,
|
|
1750
1759
|
getEmbeddingApiKey: () => getEmbeddingApiKey,
|
|
1751
1760
|
getEmbeddingBaseUrl: () => getEmbeddingBaseUrl,
|
|
1752
1761
|
getEmbeddingDimensions: () => getEmbeddingDimensions,
|
|
@@ -1806,6 +1815,23 @@ function getLLMModel(providerDefault) {
|
|
|
1806
1815
|
function getLLMBaseUrl(providerDefault) {
|
|
1807
1816
|
return process.env.MEMORIX_LLM_BASE_URL || loadYamlConfig().llm?.baseUrl || loadFileConfig().llm?.baseUrl || providerDefault;
|
|
1808
1817
|
}
|
|
1818
|
+
function getAgentLLMApiKey() {
|
|
1819
|
+
return process.env.MEMORIX_AGENT_LLM_API_KEY || loadYamlConfig().agent?.apiKey || loadFileConfig().agent?.apiKey || getLLMApiKey();
|
|
1820
|
+
}
|
|
1821
|
+
function getAgentLLMProvider() {
|
|
1822
|
+
if (process.env.MEMORIX_AGENT_LLM_PROVIDER) return process.env.MEMORIX_AGENT_LLM_PROVIDER;
|
|
1823
|
+
const yml = loadYamlConfig();
|
|
1824
|
+
if (yml.agent?.provider) return yml.agent.provider;
|
|
1825
|
+
const cfg = loadFileConfig();
|
|
1826
|
+
if (cfg.agent?.provider) return cfg.agent.provider;
|
|
1827
|
+
return getLLMProvider();
|
|
1828
|
+
}
|
|
1829
|
+
function getAgentLLMModel(providerDefault) {
|
|
1830
|
+
return process.env.MEMORIX_AGENT_LLM_MODEL || loadYamlConfig().agent?.model || loadFileConfig().agent?.model || getLLMModel(providerDefault);
|
|
1831
|
+
}
|
|
1832
|
+
function getAgentLLMBaseUrl(providerDefault) {
|
|
1833
|
+
return process.env.MEMORIX_AGENT_LLM_BASE_URL || loadYamlConfig().agent?.baseUrl || loadFileConfig().agent?.baseUrl || getLLMBaseUrl(providerDefault);
|
|
1834
|
+
}
|
|
1809
1835
|
function getEmbeddingMode() {
|
|
1810
1836
|
const env = process.env.MEMORIX_EMBEDDING?.toLowerCase()?.trim();
|
|
1811
1837
|
if (env === "fastembed" || env === "transformers" || env === "api" || env === "auto") return env;
|
|
@@ -3095,20 +3121,20 @@ async function* callLLMWithToolsStream(messages, tools) {
|
|
|
3095
3121
|
}
|
|
3096
3122
|
yield* callOpenAIWithToolsStream(messages, tools);
|
|
3097
3123
|
}
|
|
3098
|
-
function initLLM() {
|
|
3099
|
-
const
|
|
3100
|
-
const apiKey =
|
|
3124
|
+
function initLLM(options = {}) {
|
|
3125
|
+
const scope = options.scope ?? "memory";
|
|
3126
|
+
const apiKey = scope === "agent" ? getAgentLLMApiKey() : getLLMApiKey();
|
|
3101
3127
|
if (!apiKey) {
|
|
3102
3128
|
currentConfig = null;
|
|
3103
3129
|
return null;
|
|
3104
3130
|
}
|
|
3105
|
-
const provider2 =
|
|
3131
|
+
const provider2 = scope === "agent" ? getAgentLLMProvider() : getLLMProvider();
|
|
3106
3132
|
const defaults = PROVIDER_DEFAULTS[provider2] ?? PROVIDER_DEFAULTS.openai;
|
|
3107
3133
|
currentConfig = {
|
|
3108
3134
|
provider: provider2,
|
|
3109
3135
|
apiKey,
|
|
3110
|
-
model:
|
|
3111
|
-
baseUrl:
|
|
3136
|
+
model: scope === "agent" ? getAgentLLMModel(defaults.model) : getLLMModel(defaults.model),
|
|
3137
|
+
baseUrl: scope === "agent" ? getAgentLLMBaseUrl(defaults.baseUrl) : getLLMBaseUrl(defaults.baseUrl)
|
|
3112
3138
|
};
|
|
3113
3139
|
return currentConfig;
|
|
3114
3140
|
}
|
|
@@ -3615,6 +3641,7 @@ var init_provider2 = __esm({
|
|
|
3615
3641
|
"src/llm/provider.ts"() {
|
|
3616
3642
|
"use strict";
|
|
3617
3643
|
init_esm_shims();
|
|
3644
|
+
init_config();
|
|
3618
3645
|
LLM_TIMEOUT_DEFAULT_MS = 3e4;
|
|
3619
3646
|
LLM_TIMEOUT_MIN_MS = 1e3;
|
|
3620
3647
|
LLM_TIMEOUT_MAX_MS = 3e5;
|
|
@@ -10279,6 +10306,7 @@ var init_knowledge_graph = __esm({
|
|
|
10279
10306
|
// src/dashboard/server.ts
|
|
10280
10307
|
var server_exports = {};
|
|
10281
10308
|
__export(server_exports, {
|
|
10309
|
+
prepareDashboardConfig: () => prepareDashboardConfig,
|
|
10282
10310
|
startDashboard: () => startDashboard
|
|
10283
10311
|
});
|
|
10284
10312
|
import { createServer } from "http";
|
|
@@ -10304,6 +10332,25 @@ function isActiveStatus(status) {
|
|
|
10304
10332
|
function filterActiveByProject(items, projectId) {
|
|
10305
10333
|
return items.filter((item) => item.projectId === projectId && isActiveStatus(item.status));
|
|
10306
10334
|
}
|
|
10335
|
+
function prepareDashboardConfig(projectRoot) {
|
|
10336
|
+
if (!projectRoot) {
|
|
10337
|
+
if (preparedDashboardProjectRoot !== null) {
|
|
10338
|
+
resetDotenv();
|
|
10339
|
+
preparedDashboardProjectRoot = null;
|
|
10340
|
+
}
|
|
10341
|
+
clearProjectRoot();
|
|
10342
|
+
return;
|
|
10343
|
+
}
|
|
10344
|
+
try {
|
|
10345
|
+
if (preparedDashboardProjectRoot !== null && preparedDashboardProjectRoot !== projectRoot) {
|
|
10346
|
+
resetDotenv();
|
|
10347
|
+
}
|
|
10348
|
+
initProjectRoot(projectRoot);
|
|
10349
|
+
loadDotenv(projectRoot);
|
|
10350
|
+
preparedDashboardProjectRoot = projectRoot;
|
|
10351
|
+
} catch {
|
|
10352
|
+
}
|
|
10353
|
+
}
|
|
10307
10354
|
function computeProjectGraphCounts(allEntities, allRelations, projectObs) {
|
|
10308
10355
|
const entityNames = new Set(
|
|
10309
10356
|
projectObs.filter((o) => (o.status ?? "active") === "active" && o.entityName).map((o) => o.entityName)
|
|
@@ -10329,6 +10376,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
10329
10376
|
effectiveProjectResolved = true;
|
|
10330
10377
|
effectiveProjectRoot = null;
|
|
10331
10378
|
}
|
|
10379
|
+
prepareDashboardConfig(effectiveProjectRoot);
|
|
10332
10380
|
try {
|
|
10333
10381
|
switch (apiPath) {
|
|
10334
10382
|
case "/projects": {
|
|
@@ -10583,7 +10631,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
10583
10631
|
const configProjectRoot = effectiveProjectRoot;
|
|
10584
10632
|
try {
|
|
10585
10633
|
const { loadYamlConfig: loadYamlConfig2 } = await Promise.resolve().then(() => (init_yaml_loader(), yaml_loader_exports));
|
|
10586
|
-
yml = loadYamlConfig2();
|
|
10634
|
+
yml = configProjectRoot ? loadYamlConfig2(configProjectRoot) : loadYamlConfig2(null);
|
|
10587
10635
|
} catch {
|
|
10588
10636
|
}
|
|
10589
10637
|
if (configProjectRoot) {
|
|
@@ -10646,6 +10694,19 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
10646
10694
|
} else {
|
|
10647
10695
|
values.push({ key: "llm.apiKey", value: "not set", source: "none" });
|
|
10648
10696
|
}
|
|
10697
|
+
const agentProvider = process.env.MEMORIX_AGENT_LLM_PROVIDER || yml.agent?.provider;
|
|
10698
|
+
if (agentProvider) values.push({ key: "agent.llm.provider", value: agentProvider, source: await getEnvSource("MEMORIX_AGENT_LLM_PROVIDER", yml.agent?.provider ? "memorix.yml" : void 0) });
|
|
10699
|
+
const agentModel = process.env.MEMORIX_AGENT_LLM_MODEL || yml.agent?.model;
|
|
10700
|
+
if (agentModel) values.push({ key: "agent.llm.model", value: agentModel, source: await getEnvSource("MEMORIX_AGENT_LLM_MODEL", yml.agent?.model ? "memorix.yml" : void 0) });
|
|
10701
|
+
const agentKey = process.env.MEMORIX_AGENT_LLM_API_KEY || yml.agent?.apiKey;
|
|
10702
|
+
if (agentKey) {
|
|
10703
|
+
let src = "unknown";
|
|
10704
|
+
if (process.env.MEMORIX_AGENT_LLM_API_KEY) src = await getEnvSource("MEMORIX_AGENT_LLM_API_KEY");
|
|
10705
|
+
else if (yml.agent?.apiKey) src = "memorix.yml (move to .env!)";
|
|
10706
|
+
values.push({ key: "agent.llm.apiKey", value: "****" + agentKey.slice(-4), source: src, sensitive: true });
|
|
10707
|
+
} else {
|
|
10708
|
+
values.push({ key: "agent.llm.apiKey", value: "fallback to llm.apiKey", source: "default" });
|
|
10709
|
+
}
|
|
10649
10710
|
const embProvider = process.env.MEMORIX_EMBEDDING || yml.embedding?.provider || "off";
|
|
10650
10711
|
values.push({ key: "embedding.provider", value: embProvider, source: await getEnvSource("MEMORIX_EMBEDDING", yml.embedding?.provider ? "memorix.yml" : void 0) });
|
|
10651
10712
|
values.push({ key: "git.autoHook", value: String(yml.git?.autoHook ?? false), source: yml.git?.autoHook !== void 0 ? "memorix.yml" : "default" });
|
|
@@ -11081,7 +11142,7 @@ async function startDashboard(dataDir, port, staticDir, projectId, projectName,
|
|
|
11081
11142
|
});
|
|
11082
11143
|
});
|
|
11083
11144
|
}
|
|
11084
|
-
var MIME_TYPES;
|
|
11145
|
+
var MIME_TYPES, preparedDashboardProjectRoot;
|
|
11085
11146
|
var init_server = __esm({
|
|
11086
11147
|
"src/dashboard/server.ts"() {
|
|
11087
11148
|
"use strict";
|
|
@@ -11090,6 +11151,10 @@ var init_server = __esm({
|
|
|
11090
11151
|
init_obs_store();
|
|
11091
11152
|
init_session_store();
|
|
11092
11153
|
init_graph_store();
|
|
11154
|
+
init_dotenv_loader();
|
|
11155
|
+
init_dotenv_loader();
|
|
11156
|
+
init_yaml_loader();
|
|
11157
|
+
init_yaml_loader();
|
|
11093
11158
|
MIME_TYPES = {
|
|
11094
11159
|
".html": "text/html; charset=utf-8",
|
|
11095
11160
|
".css": "text/css; charset=utf-8",
|
|
@@ -11099,6 +11164,7 @@ var init_server = __esm({
|
|
|
11099
11164
|
".png": "image/png",
|
|
11100
11165
|
".ico": "image/x-icon"
|
|
11101
11166
|
};
|
|
11167
|
+
preparedDashboardProjectRoot = null;
|
|
11102
11168
|
}
|
|
11103
11169
|
});
|
|
11104
11170
|
|
|
@@ -12255,7 +12321,7 @@ function generateKiroHookFiles() {
|
|
|
12255
12321
|
when: { type: "promptSubmit" },
|
|
12256
12322
|
then: {
|
|
12257
12323
|
type: "askAgent",
|
|
12258
|
-
prompt: "Before responding, load context:\n1. Call
|
|
12324
|
+
prompt: "Before responding, load useful project context:\n1. Call memorix_search with a query related to the user's prompt for relevant memories\n2. If search results are found, use memorix_detail to fetch the most relevant ones\n3. If memorix_search says this is a fresh project with no Memorix memories yet, do not repeat memorix_search again in the same turn unless the user explicitly asks for history/context or new memories were written\n4. Call memorix_session_start only when explicit session semantics are useful, such as handoff, long-running work, team coordination, or HTTP project binding\n5. Reference relevant memories naturally in your response"
|
|
12259
12325
|
}
|
|
12260
12326
|
}, null, 2)
|
|
12261
12327
|
},
|
|
@@ -12866,20 +12932,18 @@ alwaysApply: true
|
|
|
12866
12932
|
|
|
12867
12933
|
You have access to Memorix memory tools. Follow these rules to maintain persistent context across sessions.
|
|
12868
12934
|
|
|
12869
|
-
## RULE 1:
|
|
12935
|
+
## RULE 1: Use Memory When Useful
|
|
12870
12936
|
|
|
12871
|
-
At the
|
|
12937
|
+
At the beginning of a conversation, use Memorix when prior project context would materially help the task. Do not require a session bind for every conversation.
|
|
12872
12938
|
|
|
12873
|
-
1. Call \`
|
|
12874
|
-
|
|
12875
|
-
|
|
12876
|
-
|
|
12877
|
-
|
|
12878
|
-
3. If search results are found, use \`memorix_detail\` to fetch the most relevant ones
|
|
12879
|
-
4. Reference relevant memories naturally \u2014 the user should feel you "remember" them
|
|
12939
|
+
1. Call \`memorix_search\` with a query related to the user's first message or current task.
|
|
12940
|
+
2. If search results are found, use \`memorix_detail\` to fetch the most relevant ones.
|
|
12941
|
+
3. If \`memorix_search\` says this is a fresh project with no Memorix memories yet, treat that as a successful cold-start signal. Do not repeat \`memorix_search\` again in the same turn unless the user explicitly asks for history/context or new memories were written.
|
|
12942
|
+
4. Call \`memorix_session_start\` only when explicit session semantics are useful: handoff, long-running work, team coordination, restoring prior session context, or HTTP project binding.
|
|
12943
|
+
5. Reference relevant memories naturally \u2014 the user should feel you understand the project, not that you are following a ritual.
|
|
12880
12944
|
|
|
12881
12945
|
**Important:** \`projectRoot\` is a detection anchor only; Git remains the source of truth for project identity.
|
|
12882
|
-
In HTTP control-plane mode (\`memorix serve-http\` / \`memorix background start\`), explicit \`projectRoot\` binding is required for correct multi-project isolation.
|
|
12946
|
+
In HTTP control-plane mode (\`memorix serve-http\` / \`memorix background start\`), explicit \`projectRoot\` binding is recommended when the workspace path is available and required for correct multi-project isolation.
|
|
12883
12947
|
\`memorix_session_start\` is lightweight by default: it starts memory/session context only. Do not set \`joinTeam\` unless the user explicitly needs autonomous Agent Team tasks, messages, file locks, or orchestrated CLI-agent workflows.
|
|
12884
12948
|
|
|
12885
12949
|
## RULE 2: Store Important Context
|
|
@@ -13724,7 +13788,18 @@ init_mini_skills();
|
|
|
13724
13788
|
init_secret_filter();
|
|
13725
13789
|
async function compactSearch(options) {
|
|
13726
13790
|
const entries = await searchObservations(options);
|
|
13727
|
-
|
|
13791
|
+
let formatted = formatIndexTable(entries, options.query, !options.projectId);
|
|
13792
|
+
if (entries.length === 0 && options.projectId) {
|
|
13793
|
+
const allObservations = getAllObservations();
|
|
13794
|
+
const projectHasStoredMemory = allObservations.some((obs) => obs.projectId === options.projectId);
|
|
13795
|
+
if (!projectHasStoredMemory) {
|
|
13796
|
+
formatted = `This project does not have any Memorix memories yet.
|
|
13797
|
+
|
|
13798
|
+
It looks like a fresh project: the tool call worked, but there is nothing stored to retrieve yet.
|
|
13799
|
+
|
|
13800
|
+
Memories will start appearing after observations, session summaries, hook captures, or git-memory are written.`;
|
|
13801
|
+
}
|
|
13802
|
+
}
|
|
13728
13803
|
const totalTokens = countTextTokens(formatted);
|
|
13729
13804
|
return { entries, formatted, totalTokens };
|
|
13730
13805
|
}
|
|
@@ -16392,7 +16467,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
16392
16467
|
};
|
|
16393
16468
|
const server = existingServer ?? new McpServer({
|
|
16394
16469
|
name: "memorix",
|
|
16395
|
-
version: true ? "1.0.
|
|
16470
|
+
version: true ? "1.0.10" : "1.0.1"
|
|
16396
16471
|
});
|
|
16397
16472
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
16398
16473
|
server.registerTool = ((name, ...args) => {
|