memorix 1.8.1 → 1.8.3
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 +36 -0
- package/dist/cli/index.js +577 -58
- package/dist/index.js +832 -321
- package/dist/maintenance-runner.js +31 -25
- package/dist/media-audio-runner.js +31 -25
- package/dist/media-video-runner.js +31 -25
- package/dist/memcode-runtime/CHANGELOG.md +36 -0
- package/dist/sdk.js +585 -315
- package/dist/vector-backfill-runner.js +31 -25
- package/docs/1.2.0-PROVIDER-QUALITY.md +15 -6
- package/docs/1.3.3-MULTIMODAL-MEDIA-AND-MCP-COMPAT.md +7 -6
- package/docs/1.8.0-RELEASE-CANDIDATE-SPEC.md +13 -8
- package/docs/API_REFERENCE.md +14 -11
- package/docs/CONFIGURATION.md +2 -2
- package/docs/DEVELOPMENT.md +3 -2
- package/docs/README.md +13 -7
- package/package.json +2 -1
- package/plugins/antigravity/memorix/plugin.json +2 -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/hermes/memorix/plugin.yaml +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 +3 -3
- package/src/cli/commands/serve-http.ts +10 -2
- package/src/cli/commands/serve.ts +26 -7
- package/src/codegraph/external-provider.ts +299 -19
- package/src/config/dotenv-loader.ts +9 -4
- package/src/config.ts +16 -16
- package/src/dashboard/maintenance.ts +4 -1
- package/src/llm/provider.ts +17 -4
- package/src/server/mcp-compat.ts +63 -0
- package/src/server/mcp-diagnostics.ts +13 -4
- package/src/server/mcp-discovery.ts +61 -0
- package/src/server/stdio-startup-gate.ts +263 -0
- package/src/server.ts +4 -4
package/dist/index.js
CHANGED
|
@@ -3279,8 +3279,10 @@ function loadEnvFile(filePath) {
|
|
|
3279
3279
|
loadedEnvFiles.push(filePath);
|
|
3280
3280
|
}
|
|
3281
3281
|
function loadDotenv(projectRoot, options = {}) {
|
|
3282
|
-
|
|
3283
|
-
|
|
3282
|
+
const userHomeDir = options.userHomeDir ?? homedir4();
|
|
3283
|
+
const normalizedProjectRoot = projectRoot ?? null;
|
|
3284
|
+
if (dotenvLoaded && dotenvProjectRoot === normalizedProjectRoot && dotenvHomeDir === userHomeDir) return;
|
|
3285
|
+
if (dotenvLoaded && (dotenvProjectRoot !== normalizedProjectRoot || dotenvHomeDir !== userHomeDir)) {
|
|
3284
3286
|
resetDotenv();
|
|
3285
3287
|
}
|
|
3286
3288
|
loadedEnvFiles.length = 0;
|
|
@@ -3289,9 +3291,10 @@ function loadDotenv(projectRoot, options = {}) {
|
|
|
3289
3291
|
if (projectRoot) {
|
|
3290
3292
|
loadEnvFile(getProjectDotenvPath(projectRoot));
|
|
3291
3293
|
}
|
|
3292
|
-
loadEnvFile(getGlobalDotenvPath(
|
|
3294
|
+
loadEnvFile(getGlobalDotenvPath(userHomeDir));
|
|
3293
3295
|
dotenvLoaded = true;
|
|
3294
|
-
dotenvProjectRoot =
|
|
3296
|
+
dotenvProjectRoot = normalizedProjectRoot;
|
|
3297
|
+
dotenvHomeDir = userHomeDir;
|
|
3295
3298
|
}
|
|
3296
3299
|
function resetDotenv() {
|
|
3297
3300
|
for (const key of injectedKeys) {
|
|
@@ -3300,6 +3303,7 @@ function resetDotenv() {
|
|
|
3300
3303
|
injectedKeys.clear();
|
|
3301
3304
|
dotenvLoaded = false;
|
|
3302
3305
|
dotenvProjectRoot = null;
|
|
3306
|
+
dotenvHomeDir = null;
|
|
3303
3307
|
loadedEnvFiles.length = 0;
|
|
3304
3308
|
loadedEnvKeys.clear();
|
|
3305
3309
|
}
|
|
@@ -3312,7 +3316,7 @@ function getLoadedEnvKeys() {
|
|
|
3312
3316
|
function getLoadedEnvValue(key) {
|
|
3313
3317
|
return loadedEnvValues.get(key);
|
|
3314
3318
|
}
|
|
3315
|
-
var dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, loadedEnvKeys, loadedEnvValues, injectedKeys;
|
|
3319
|
+
var dotenvLoaded, dotenvProjectRoot, dotenvHomeDir, loadedEnvFiles, loadedEnvKeys, loadedEnvValues, injectedKeys;
|
|
3316
3320
|
var init_dotenv_loader = __esm({
|
|
3317
3321
|
"src/config/dotenv-loader.ts"() {
|
|
3318
3322
|
"use strict";
|
|
@@ -3320,6 +3324,7 @@ var init_dotenv_loader = __esm({
|
|
|
3320
3324
|
init_config_paths();
|
|
3321
3325
|
dotenvLoaded = false;
|
|
3322
3326
|
dotenvProjectRoot = null;
|
|
3327
|
+
dotenvHomeDir = null;
|
|
3323
3328
|
loadedEnvFiles = [];
|
|
3324
3329
|
loadedEnvKeys = /* @__PURE__ */ new Set();
|
|
3325
3330
|
loadedEnvValues = /* @__PURE__ */ new Map();
|
|
@@ -3671,33 +3676,33 @@ __export(config_exports, {
|
|
|
3671
3676
|
resetConfigCache: () => resetConfigCache,
|
|
3672
3677
|
resetDotenv: () => resetDotenv
|
|
3673
3678
|
});
|
|
3674
|
-
function getLLMApiKey() {
|
|
3675
|
-
return getResolvedMemoryLane().llm.apiKey;
|
|
3679
|
+
function getLLMApiKey(options = {}) {
|
|
3680
|
+
return getResolvedMemoryLane(options).llm.apiKey;
|
|
3676
3681
|
}
|
|
3677
|
-
function getLLMProvider() {
|
|
3678
|
-
const provider2 = getResolvedMemoryLane().llm.provider;
|
|
3682
|
+
function getLLMProvider(options = {}) {
|
|
3683
|
+
const provider2 = getResolvedMemoryLane(options).llm.provider;
|
|
3679
3684
|
if (provider2) return provider2;
|
|
3680
3685
|
if (process.env.ANTHROPIC_API_KEY && !process.env.OPENAI_API_KEY) return "anthropic";
|
|
3681
3686
|
if (process.env.OPENROUTER_API_KEY && !process.env.OPENAI_API_KEY) return "openrouter";
|
|
3682
3687
|
return "openai";
|
|
3683
3688
|
}
|
|
3684
|
-
function getLLMModel(providerDefault) {
|
|
3685
|
-
return getResolvedMemoryLane().llm.model || providerDefault;
|
|
3689
|
+
function getLLMModel(providerDefault, options = {}) {
|
|
3690
|
+
return getResolvedMemoryLane(options).llm.model || providerDefault;
|
|
3686
3691
|
}
|
|
3687
|
-
function getLLMBaseUrl(providerDefault) {
|
|
3688
|
-
return getResolvedMemoryLane().llm.baseUrl || providerDefault;
|
|
3692
|
+
function getLLMBaseUrl(providerDefault, options = {}) {
|
|
3693
|
+
return getResolvedMemoryLane(options).llm.baseUrl || providerDefault;
|
|
3689
3694
|
}
|
|
3690
|
-
function getAgentLLMApiKey() {
|
|
3691
|
-
return getResolvedAgentLane().apiKey;
|
|
3695
|
+
function getAgentLLMApiKey(options = {}) {
|
|
3696
|
+
return getResolvedAgentLane(options).apiKey;
|
|
3692
3697
|
}
|
|
3693
|
-
function getAgentLLMProvider() {
|
|
3694
|
-
return getResolvedAgentLane().provider || getLLMProvider();
|
|
3698
|
+
function getAgentLLMProvider(options = {}) {
|
|
3699
|
+
return getResolvedAgentLane(options).provider || getLLMProvider(options);
|
|
3695
3700
|
}
|
|
3696
|
-
function getAgentLLMModel(providerDefault) {
|
|
3697
|
-
return getResolvedAgentLane().model || getLLMModel(providerDefault);
|
|
3701
|
+
function getAgentLLMModel(providerDefault, options = {}) {
|
|
3702
|
+
return getResolvedAgentLane(options).model || getLLMModel(providerDefault, options);
|
|
3698
3703
|
}
|
|
3699
|
-
function getAgentLLMBaseUrl(providerDefault) {
|
|
3700
|
-
return getResolvedAgentLane().baseUrl || getLLMBaseUrl(providerDefault);
|
|
3704
|
+
function getAgentLLMBaseUrl(providerDefault, options = {}) {
|
|
3705
|
+
return getResolvedAgentLane(options).baseUrl || getLLMBaseUrl(providerDefault, options);
|
|
3701
3706
|
}
|
|
3702
3707
|
function getEmbeddingMode() {
|
|
3703
3708
|
const provider2 = getResolvedEmbeddingLane().provider?.toLowerCase()?.trim();
|
|
@@ -5956,18 +5961,19 @@ async function* callLLMWithToolsStream(messages, tools) {
|
|
|
5956
5961
|
}
|
|
5957
5962
|
function initLLM(options = {}) {
|
|
5958
5963
|
const scope = options.scope ?? "memory";
|
|
5959
|
-
const
|
|
5964
|
+
const configOptions = { projectRoot: options.projectRoot, homeDir: options.homeDir };
|
|
5965
|
+
const apiKey = scope === "agent" ? getAgentLLMApiKey(configOptions) : getLLMApiKey(configOptions);
|
|
5960
5966
|
if (!apiKey) {
|
|
5961
5967
|
currentConfig = null;
|
|
5962
5968
|
return null;
|
|
5963
5969
|
}
|
|
5964
|
-
const provider2 = scope === "agent" ? getAgentLLMProvider() : getLLMProvider();
|
|
5970
|
+
const provider2 = scope === "agent" ? getAgentLLMProvider(configOptions) : getLLMProvider(configOptions);
|
|
5965
5971
|
const defaults2 = PROVIDER_DEFAULTS[provider2] ?? PROVIDER_DEFAULTS.openai;
|
|
5966
5972
|
currentConfig = {
|
|
5967
5973
|
provider: provider2,
|
|
5968
5974
|
apiKey,
|
|
5969
|
-
model: scope === "agent" ? getAgentLLMModel(defaults2.model) : getLLMModel(defaults2.model),
|
|
5970
|
-
baseUrl: scope === "agent" ? getAgentLLMBaseUrl(defaults2.baseUrl) : getLLMBaseUrl(defaults2.baseUrl)
|
|
5975
|
+
model: scope === "agent" ? getAgentLLMModel(defaults2.model, configOptions) : getLLMModel(defaults2.model, configOptions),
|
|
5976
|
+
baseUrl: scope === "agent" ? getAgentLLMBaseUrl(defaults2.baseUrl, configOptions) : getLLMBaseUrl(defaults2.baseUrl, configOptions)
|
|
5971
5977
|
};
|
|
5972
5978
|
return currentConfig;
|
|
5973
5979
|
}
|
|
@@ -65987,11 +65993,11 @@ var require_bignumber = __commonJS({
|
|
|
65987
65993
|
return n > 0 || n === i2 ? i2 : i2 - 1;
|
|
65988
65994
|
}
|
|
65989
65995
|
function coeffToString(a) {
|
|
65990
|
-
var s2,
|
|
65996
|
+
var s2, z628, i2 = 1, j = a.length, r2 = a[0] + "";
|
|
65991
65997
|
for (; i2 < j; ) {
|
|
65992
65998
|
s2 = a[i2++] + "";
|
|
65993
|
-
|
|
65994
|
-
for (;
|
|
65999
|
+
z628 = LOG_BASE - s2.length;
|
|
66000
|
+
for (; z628--; s2 = "0" + s2) ;
|
|
65995
66001
|
r2 += s2;
|
|
65996
66002
|
}
|
|
65997
66003
|
for (j = r2.length; r2.charCodeAt(--j) === 48; ) ;
|
|
@@ -66024,15 +66030,15 @@ var require_bignumber = __commonJS({
|
|
|
66024
66030
|
function toExponential(str2, e2) {
|
|
66025
66031
|
return (str2.length > 1 ? str2.charAt(0) + "." + str2.slice(1) : str2) + (e2 < 0 ? "e" : "e+") + e2;
|
|
66026
66032
|
}
|
|
66027
|
-
function toFixedPoint(str2, e2,
|
|
66033
|
+
function toFixedPoint(str2, e2, z628) {
|
|
66028
66034
|
var len, zs;
|
|
66029
66035
|
if (e2 < 0) {
|
|
66030
|
-
for (zs =
|
|
66036
|
+
for (zs = z628 + "."; ++e2; zs += z628) ;
|
|
66031
66037
|
str2 = zs + str2;
|
|
66032
66038
|
} else {
|
|
66033
66039
|
len = str2.length;
|
|
66034
66040
|
if (++e2 > len) {
|
|
66035
|
-
for (zs =
|
|
66041
|
+
for (zs = z628, e2 -= len; --e2; zs += z628) ;
|
|
66036
66042
|
str2 += zs;
|
|
66037
66043
|
} else if (e2 < len) {
|
|
66038
66044
|
str2 = str2.slice(0, e2) + "." + str2.slice(e2);
|
|
@@ -158111,6 +158117,74 @@ var init_request_context = __esm({
|
|
|
158111
158117
|
}
|
|
158112
158118
|
});
|
|
158113
158119
|
|
|
158120
|
+
// src/server/mcp-discovery.ts
|
|
158121
|
+
function getMcpServerInfo() {
|
|
158122
|
+
return {
|
|
158123
|
+
name: "memorix",
|
|
158124
|
+
version: true ? "1.8.3" : "1.0.1"
|
|
158125
|
+
};
|
|
158126
|
+
}
|
|
158127
|
+
function createMcpDiscoverResult(capabilities, serverInfo) {
|
|
158128
|
+
return {
|
|
158129
|
+
resultType: "complete",
|
|
158130
|
+
supportedVersions: [
|
|
158131
|
+
MCP_MODERN_PROTOCOL_VERSION,
|
|
158132
|
+
MCP_LEGACY_PROTOCOL_VERSION,
|
|
158133
|
+
MCP_OLDEST_LEGACY_PROTOCOL_VERSION
|
|
158134
|
+
],
|
|
158135
|
+
capabilities,
|
|
158136
|
+
_meta: {
|
|
158137
|
+
[MCP_SERVER_INFO_META_KEY]: { ...serverInfo }
|
|
158138
|
+
},
|
|
158139
|
+
// v1 has no response-cache negotiation. A zero private TTL prevents clients
|
|
158140
|
+
// from inventing a shared cache for an implementation that cannot invalidate it.
|
|
158141
|
+
ttlMs: 0,
|
|
158142
|
+
cacheScope: "private"
|
|
158143
|
+
};
|
|
158144
|
+
}
|
|
158145
|
+
function createMcpStartupDiscoverResult(serverInfo) {
|
|
158146
|
+
return createMcpDiscoverResult({ tools: { listChanged: true } }, serverInfo);
|
|
158147
|
+
}
|
|
158148
|
+
var MCP_MODERN_PROTOCOL_VERSION, MCP_LEGACY_PROTOCOL_VERSION, MCP_OLDEST_LEGACY_PROTOCOL_VERSION, MCP_SERVER_DISCOVER_METHOD, MCP_SERVER_INFO_META_KEY;
|
|
158149
|
+
var init_mcp_discovery = __esm({
|
|
158150
|
+
"src/server/mcp-discovery.ts"() {
|
|
158151
|
+
"use strict";
|
|
158152
|
+
init_esm_shims();
|
|
158153
|
+
MCP_MODERN_PROTOCOL_VERSION = "2026-07-28";
|
|
158154
|
+
MCP_LEGACY_PROTOCOL_VERSION = "2025-11-25";
|
|
158155
|
+
MCP_OLDEST_LEGACY_PROTOCOL_VERSION = "2024-11-05";
|
|
158156
|
+
MCP_SERVER_DISCOVER_METHOD = "server/discover";
|
|
158157
|
+
MCP_SERVER_INFO_META_KEY = "io.modelcontextprotocol/serverInfo";
|
|
158158
|
+
}
|
|
158159
|
+
});
|
|
158160
|
+
|
|
158161
|
+
// src/server/mcp-compat.ts
|
|
158162
|
+
import { RequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
158163
|
+
import { z as z625 } from "zod/v4";
|
|
158164
|
+
function buildMcpDiscoverResult(server, serverInfo) {
|
|
158165
|
+
const getCapabilities = server.server.getCapabilities.bind(server.server);
|
|
158166
|
+
return createMcpDiscoverResult(getCapabilities(), serverInfo);
|
|
158167
|
+
}
|
|
158168
|
+
function registerMcpDiscovery(server, serverInfo) {
|
|
158169
|
+
if (registeredServers.has(server)) return;
|
|
158170
|
+
server.server.setRequestHandler(ServerDiscoverRequestSchema, async () => buildMcpDiscoverResult(server, serverInfo));
|
|
158171
|
+
registeredServers.add(server);
|
|
158172
|
+
}
|
|
158173
|
+
var ServerDiscoverRequestSchema, registeredServers;
|
|
158174
|
+
var init_mcp_compat = __esm({
|
|
158175
|
+
"src/server/mcp-compat.ts"() {
|
|
158176
|
+
"use strict";
|
|
158177
|
+
init_esm_shims();
|
|
158178
|
+
init_mcp_discovery();
|
|
158179
|
+
init_mcp_discovery();
|
|
158180
|
+
ServerDiscoverRequestSchema = RequestSchema.extend({
|
|
158181
|
+
method: z625.literal(MCP_SERVER_DISCOVER_METHOD),
|
|
158182
|
+
params: z625.looseObject({}).optional()
|
|
158183
|
+
});
|
|
158184
|
+
registeredServers = /* @__PURE__ */ new WeakSet();
|
|
158185
|
+
}
|
|
158186
|
+
});
|
|
158187
|
+
|
|
158114
158188
|
// src/runtime/maintenance-targets.ts
|
|
158115
158189
|
var maintenance_targets_exports = {};
|
|
158116
158190
|
__export(maintenance_targets_exports, {
|
|
@@ -159841,6 +159915,27 @@ function unavailableHealth(result) {
|
|
|
159841
159915
|
if (result.outputLimited) return { state: "invalid", reason: "A local CodeGraph response exceeded the safety limit." };
|
|
159842
159916
|
return { state: "unavailable", reason: "A local CodeGraph command did not complete." };
|
|
159843
159917
|
}
|
|
159918
|
+
function notAttemptedDiagnostic(command) {
|
|
159919
|
+
return { command, attempted: false, outcome: "not-attempted" };
|
|
159920
|
+
}
|
|
159921
|
+
function commandDiagnostic(command, result, outcome, reason) {
|
|
159922
|
+
return {
|
|
159923
|
+
command,
|
|
159924
|
+
attempted: true,
|
|
159925
|
+
outcome,
|
|
159926
|
+
...typeof result.exitCode === "number" ? { exitCode: result.exitCode } : {},
|
|
159927
|
+
...reason ? { reason: sanitizeCredentials(reason).slice(0, 240) } : {}
|
|
159928
|
+
};
|
|
159929
|
+
}
|
|
159930
|
+
function failedCommandDiagnostic(command, result) {
|
|
159931
|
+
const outcome = result.timedOut ? "timed-out" : result.outputLimited ? "output-limited" : "failed";
|
|
159932
|
+
return commandDiagnostic(
|
|
159933
|
+
command,
|
|
159934
|
+
result,
|
|
159935
|
+
outcome,
|
|
159936
|
+
result.error || result.stderr || "CodeGraph command did not complete."
|
|
159937
|
+
);
|
|
159938
|
+
}
|
|
159844
159939
|
async function runSafely(runner, input) {
|
|
159845
159940
|
try {
|
|
159846
159941
|
return await runner.run(input);
|
|
@@ -159990,6 +160085,7 @@ function parseOutline(value, projectRoot, exclude) {
|
|
|
159990
160085
|
if (nodes.some((node) => !node)) return void 0;
|
|
159991
160086
|
const byId = /* @__PURE__ */ new Map();
|
|
159992
160087
|
for (const node of nodes) {
|
|
160088
|
+
if (byId.has(node.id)) return void 0;
|
|
159993
160089
|
byId.set(node.id, externalSymbol(node));
|
|
159994
160090
|
}
|
|
159995
160091
|
const entryPoints = value.entryPoints.map((item) => parseNode(item, projectRoot, exclude)).filter((node) => Boolean(node)).map(externalSymbol).filter((node, index, items) => items.findIndex((item) => item.id === node.id) === index).slice(0, 5);
|
|
@@ -160003,7 +160099,7 @@ function parseOutline(value, projectRoot, exclude) {
|
|
|
160003
160099
|
if (!source || !target || !kind || rawEdge.line !== void 0 && (!line || line < 1)) return void 0;
|
|
160004
160100
|
const from = byId.get(source);
|
|
160005
160101
|
const to = byId.get(target);
|
|
160006
|
-
if (!from || !to)
|
|
160102
|
+
if (!from || !to) return void 0;
|
|
160007
160103
|
relations.push({ from, to, kind, ...line ? { line } : {} });
|
|
160008
160104
|
}
|
|
160009
160105
|
const relatedFiles = value.relatedFiles.map((item) => safeRelativePath(projectRoot, item, exclude));
|
|
@@ -160021,45 +160117,234 @@ function parseOutline(value, projectRoot, exclude) {
|
|
|
160021
160117
|
stats: { nodes: nodeCount, edges: edgeCount, files: fileCount }
|
|
160022
160118
|
};
|
|
160023
160119
|
}
|
|
160120
|
+
function parseTextLocation(value) {
|
|
160121
|
+
const match2 = value.trim().match(/^(.*?)(?::([1-9]\d*))?$/);
|
|
160122
|
+
if (!match2?.[1]) return void 0;
|
|
160123
|
+
return {
|
|
160124
|
+
filePath: match2[1].trim(),
|
|
160125
|
+
...match2[2] ? { line: Number(match2[2]) } : {}
|
|
160126
|
+
};
|
|
160127
|
+
}
|
|
160128
|
+
function parseExploreText(value, projectRoot, exclude) {
|
|
160129
|
+
if (!value.trim() || Buffer.byteLength(value, "utf8") > MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES) return void 0;
|
|
160130
|
+
const entryPoints = [];
|
|
160131
|
+
const nodes = [];
|
|
160132
|
+
const relatedFiles = /* @__PURE__ */ new Set();
|
|
160133
|
+
const byName = /* @__PURE__ */ new Map();
|
|
160134
|
+
let section = null;
|
|
160135
|
+
let relationKind = "references";
|
|
160136
|
+
const addNode = (node, entry) => {
|
|
160137
|
+
const key = `${node.filePath}\0${node.name}`;
|
|
160138
|
+
const existing = byName.get(key);
|
|
160139
|
+
if (existing) return;
|
|
160140
|
+
byName.set(key, node);
|
|
160141
|
+
relatedFiles.add(node.filePath);
|
|
160142
|
+
(entry ? entryPoints : nodes).push(node);
|
|
160143
|
+
};
|
|
160144
|
+
for (const rawLine of value.split(/\r?\n/)) {
|
|
160145
|
+
const line = rawLine.trim();
|
|
160146
|
+
const fileHeader = line.match(/^\*\*`([^`]+)`\*\*\s+(?:—|-)\s+(.+)$/);
|
|
160147
|
+
if (fileHeader) {
|
|
160148
|
+
const filePath = safeRelativePath(projectRoot, fileHeader[1], exclude);
|
|
160149
|
+
if (!filePath) return void 0;
|
|
160150
|
+
const symbolText = fileHeader[2].split(/\s+·\s+/, 1)[0] ?? "";
|
|
160151
|
+
const symbols = [...symbolText.matchAll(/([^,]+?)\(([^()]+)\)/g)];
|
|
160152
|
+
if (symbols.length === 0) return void 0;
|
|
160153
|
+
const isFirstFile = entryPoints.length === 0 && nodes.length === 0;
|
|
160154
|
+
for (const symbol of symbols.slice(0, MAX_EXTERNAL_NODE_COUNT)) {
|
|
160155
|
+
const name = symbol[1]?.trim();
|
|
160156
|
+
const kind = symbol[2]?.trim();
|
|
160157
|
+
if (!name || !kind) return void 0;
|
|
160158
|
+
addNode({
|
|
160159
|
+
id: `explore:${filePath}:${name}`,
|
|
160160
|
+
kind,
|
|
160161
|
+
name,
|
|
160162
|
+
filePath
|
|
160163
|
+
}, isFirstFile);
|
|
160164
|
+
}
|
|
160165
|
+
section = null;
|
|
160166
|
+
continue;
|
|
160167
|
+
}
|
|
160168
|
+
if (/^#{2,3}\s+Entry Points?\b/i.test(line)) {
|
|
160169
|
+
section = "entry";
|
|
160170
|
+
continue;
|
|
160171
|
+
}
|
|
160172
|
+
if (/^#{2,3}\s+Related Symbols?\b/i.test(line)) {
|
|
160173
|
+
section = "related";
|
|
160174
|
+
continue;
|
|
160175
|
+
}
|
|
160176
|
+
if (/^\*\*Relationships\*\*$/i.test(line)) {
|
|
160177
|
+
section = "relationships";
|
|
160178
|
+
continue;
|
|
160179
|
+
}
|
|
160180
|
+
if (/^\*\*(?:Source Code|Code)\*\*$/i.test(line) || /^#{2,3}\s+/i.test(line)) {
|
|
160181
|
+
section = null;
|
|
160182
|
+
continue;
|
|
160183
|
+
}
|
|
160184
|
+
if (section === "entry") {
|
|
160185
|
+
const match2 = line.match(/^-\s+\*\*(.+?)\*\*\s+\(([^)]+)\)\s+-\s+(.+)$/);
|
|
160186
|
+
if (!match2) continue;
|
|
160187
|
+
const location = parseTextLocation(match2[3]);
|
|
160188
|
+
if (!location) return void 0;
|
|
160189
|
+
const filePath = safeRelativePath(projectRoot, location.filePath, exclude);
|
|
160190
|
+
if (!filePath) return void 0;
|
|
160191
|
+
addNode({
|
|
160192
|
+
id: `explore:${filePath}:${match2[1]}`,
|
|
160193
|
+
kind: match2[2],
|
|
160194
|
+
name: match2[1],
|
|
160195
|
+
filePath,
|
|
160196
|
+
...location.line ? { startLine: location.line, endLine: location.line } : {}
|
|
160197
|
+
}, true);
|
|
160198
|
+
continue;
|
|
160199
|
+
}
|
|
160200
|
+
if (section === "related") {
|
|
160201
|
+
const match2 = line.match(/^-\s+([^:]+):\s+(.+)$/);
|
|
160202
|
+
if (!match2) continue;
|
|
160203
|
+
const filePath = safeRelativePath(projectRoot, match2[1], exclude);
|
|
160204
|
+
if (!filePath) return void 0;
|
|
160205
|
+
relatedFiles.add(filePath);
|
|
160206
|
+
for (const rawSymbol of match2[2].split(",")) {
|
|
160207
|
+
const symbol = rawSymbol.trim().match(/^(.+?)(?::([1-9]\d*))?$/);
|
|
160208
|
+
if (!symbol?.[1]) return void 0;
|
|
160209
|
+
addNode({
|
|
160210
|
+
id: `explore:${filePath}:${symbol[1].trim()}`,
|
|
160211
|
+
kind: "unknown",
|
|
160212
|
+
name: symbol[1].trim(),
|
|
160213
|
+
filePath,
|
|
160214
|
+
...symbol[2] ? { startLine: Number(symbol[2]), endLine: Number(symbol[2]) } : {}
|
|
160215
|
+
}, false);
|
|
160216
|
+
}
|
|
160217
|
+
continue;
|
|
160218
|
+
}
|
|
160219
|
+
if (section === "relationships") {
|
|
160220
|
+
const kind = line.match(/^\*\*([^*]+):\*\*$/);
|
|
160221
|
+
if (kind?.[1]) {
|
|
160222
|
+
relationKind = kind[1].trim();
|
|
160223
|
+
continue;
|
|
160224
|
+
}
|
|
160225
|
+
}
|
|
160226
|
+
}
|
|
160227
|
+
const bySymbolName = /* @__PURE__ */ new Map();
|
|
160228
|
+
for (const node of [...entryPoints, ...nodes]) {
|
|
160229
|
+
if (!bySymbolName.has(node.name)) bySymbolName.set(node.name, node);
|
|
160230
|
+
}
|
|
160231
|
+
const relations = [];
|
|
160232
|
+
if (section === "relationships") {
|
|
160233
|
+
for (const rawLine of value.split(/\r?\n/)) {
|
|
160234
|
+
const line = rawLine.trim();
|
|
160235
|
+
const match2 = line.match(/^-\s+(.+?)\s+(?:\u2192|->)\s+(.+)$/);
|
|
160236
|
+
if (!match2) continue;
|
|
160237
|
+
const from = bySymbolName.get(match2[1].trim());
|
|
160238
|
+
const to = bySymbolName.get(match2[2].trim());
|
|
160239
|
+
if (!from || !to) continue;
|
|
160240
|
+
relations.push({
|
|
160241
|
+
from: externalSymbol(from),
|
|
160242
|
+
to: externalSymbol(to),
|
|
160243
|
+
kind: relationKind
|
|
160244
|
+
});
|
|
160245
|
+
}
|
|
160246
|
+
} else {
|
|
160247
|
+
const relationshipStart = value.split(/\r?\n/).findIndex((line) => /^\s*\*\*Relationships\*\*\s*$/i.test(line));
|
|
160248
|
+
if (relationshipStart >= 0) {
|
|
160249
|
+
const relationshipLines = value.split(/\r?\n/).slice(relationshipStart + 1);
|
|
160250
|
+
for (const rawLine of relationshipLines) {
|
|
160251
|
+
const line = rawLine.trim();
|
|
160252
|
+
if (/^\*\*(?:Source Code|Code)\*\*$/i.test(line) || /^#{2,3}\s+/i.test(line)) break;
|
|
160253
|
+
const kind = line.match(/^\*\*([^*]+):\*\*$/);
|
|
160254
|
+
if (kind?.[1]) {
|
|
160255
|
+
relationKind = kind[1].trim();
|
|
160256
|
+
continue;
|
|
160257
|
+
}
|
|
160258
|
+
const match2 = line.match(/^-\s+(.+?)\s+(?:\u2192|->)\s+(.+)$/);
|
|
160259
|
+
if (!match2) continue;
|
|
160260
|
+
const from = bySymbolName.get(match2[1].trim());
|
|
160261
|
+
const to = bySymbolName.get(match2[2].trim());
|
|
160262
|
+
if (from && to) relations.push({ from: externalSymbol(from), to: externalSymbol(to), kind: relationKind });
|
|
160263
|
+
}
|
|
160264
|
+
}
|
|
160265
|
+
}
|
|
160266
|
+
const allNodes = [...entryPoints, ...nodes];
|
|
160267
|
+
if (allNodes.length === 0) return void 0;
|
|
160268
|
+
return {
|
|
160269
|
+
provider: "external",
|
|
160270
|
+
entryPoints: entryPoints.map(externalSymbol).slice(0, 5),
|
|
160271
|
+
relations: relations.slice(0, 6),
|
|
160272
|
+
relatedFiles: [...relatedFiles].slice(0, 5),
|
|
160273
|
+
stats: {
|
|
160274
|
+
nodes: allNodes.length,
|
|
160275
|
+
edges: relations.length,
|
|
160276
|
+
files: relatedFiles.size
|
|
160277
|
+
}
|
|
160278
|
+
};
|
|
160279
|
+
}
|
|
160280
|
+
function parseExplorePayload(value, projectRoot, exclude) {
|
|
160281
|
+
if (typeof value === "string") return parseExploreText(value, projectRoot, exclude);
|
|
160282
|
+
if (isRecord3(value) && isRecord3(value.result)) value = value.result;
|
|
160283
|
+
if (isRecord3(value) && Array.isArray(value.content)) {
|
|
160284
|
+
const text2 = value.content.filter((item) => isRecord3(item) && item.type === "text" && typeof item.text === "string").map((item) => item.text).join("\n");
|
|
160285
|
+
return parseExploreText(text2, projectRoot, exclude);
|
|
160286
|
+
}
|
|
160287
|
+
return parseOutline(value, projectRoot, exclude);
|
|
160288
|
+
}
|
|
160024
160289
|
function fallbackCaution(health) {
|
|
160025
160290
|
if (health.state === "disabled" || health.state === "not-detected" || health.state === "not-initialized" || health.state === "ready") return void 0;
|
|
160026
160291
|
return "External semantic CodeGraph is " + health.state + "; using Lite structural evidence for this brief.";
|
|
160027
160292
|
}
|
|
160293
|
+
function queryFallbackCaution(diagnostics) {
|
|
160294
|
+
return `External semantic CodeGraph context was unavailable (context: ${diagnostics.context.outcome}; explore: ${diagnostics.explore.outcome}); using Lite structural evidence.`;
|
|
160295
|
+
}
|
|
160028
160296
|
async function getExternalCodeGraphContext(input) {
|
|
160029
160297
|
const inspected = await inspectExternalCodeGraph(input);
|
|
160030
160298
|
if (inspected.health.state !== "ready") {
|
|
160031
160299
|
return { ...inspected, caution: fallbackCaution(inspected.health) };
|
|
160032
160300
|
}
|
|
160033
160301
|
const mode = input.mode ?? "auto";
|
|
160034
|
-
const
|
|
160302
|
+
const runner = input.runner ?? defaultRunner;
|
|
160303
|
+
const contextResult = await runSafely(runner, {
|
|
160035
160304
|
command: input.command,
|
|
160036
160305
|
args: ["context", "--path", input.projectRoot, "--format", "json", "--max-nodes", "8", "--no-code", input.task],
|
|
160037
160306
|
cwd: input.projectRoot,
|
|
160038
160307
|
timeoutMs: boundedTimeout(input.timeoutMs),
|
|
160039
160308
|
maxOutputBytes: MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES
|
|
160040
160309
|
});
|
|
160041
|
-
|
|
160042
|
-
|
|
160310
|
+
const diagnostics = {
|
|
160311
|
+
context: contextResult.ok ? commandDiagnostic("context", contextResult, "success") : failedCommandDiagnostic("context", contextResult),
|
|
160312
|
+
explore: notAttemptedDiagnostic("explore")
|
|
160313
|
+
};
|
|
160314
|
+
const contextOutline = contextResult.ok ? parseOutline(parseJson2(contextResult.stdout), input.projectRoot, input.exclude) : void 0;
|
|
160315
|
+
if (contextOutline && (contextOutline.entryPoints.length > 0 || contextOutline.relations.length > 0 || contextOutline.relatedFiles.length > 0)) {
|
|
160043
160316
|
return {
|
|
160044
|
-
|
|
160045
|
-
|
|
160046
|
-
|
|
160317
|
+
...inspected,
|
|
160318
|
+
outline: contextOutline,
|
|
160319
|
+
diagnostics,
|
|
160320
|
+
quality: providerQuality({ mode, health: inspected.health, selected: "external" })
|
|
160047
160321
|
};
|
|
160048
160322
|
}
|
|
160049
|
-
|
|
160050
|
-
|
|
160051
|
-
|
|
160323
|
+
if (contextResult.ok) diagnostics.context = commandDiagnostic("context", contextResult, "invalid-output", "The context payload failed validation or contained no safe outline.");
|
|
160324
|
+
const exploreResult = await runSafely(runner, {
|
|
160325
|
+
command: input.command,
|
|
160326
|
+
args: ["explore", "--path", input.projectRoot, "--max-files", "4", input.task],
|
|
160327
|
+
cwd: input.projectRoot,
|
|
160328
|
+
timeoutMs: boundedTimeout(input.timeoutMs),
|
|
160329
|
+
maxOutputBytes: MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES
|
|
160330
|
+
});
|
|
160331
|
+
diagnostics.explore = exploreResult.ok ? commandDiagnostic("explore", exploreResult, "success") : failedCommandDiagnostic("explore", exploreResult);
|
|
160332
|
+
const exploreOutline = exploreResult.ok ? parseExplorePayload(parseJson2(exploreResult.stdout) ?? exploreResult.stdout, input.projectRoot, input.exclude) : void 0;
|
|
160333
|
+
if (exploreOutline && (exploreOutline.entryPoints.length > 0 || exploreOutline.relations.length > 0 || exploreOutline.relatedFiles.length > 0)) {
|
|
160052
160334
|
return {
|
|
160053
|
-
|
|
160054
|
-
|
|
160055
|
-
|
|
160335
|
+
...inspected,
|
|
160336
|
+
outline: exploreOutline,
|
|
160337
|
+
diagnostics,
|
|
160338
|
+
quality: providerQuality({ mode, health: inspected.health, selected: "external" })
|
|
160056
160339
|
};
|
|
160057
160340
|
}
|
|
160058
|
-
|
|
160341
|
+
if (exploreResult.ok) diagnostics.explore = commandDiagnostic("explore", exploreResult, "invalid-output", "The explore payload failed validation or contained no safe outline.");
|
|
160342
|
+
const health = exploreResult.ok ? { state: "invalid", reason: "The local CodeGraph context and explore payloads failed validation." } : unavailableHealth(exploreResult);
|
|
160059
160343
|
return {
|
|
160060
|
-
|
|
160061
|
-
|
|
160062
|
-
|
|
160344
|
+
health,
|
|
160345
|
+
quality: providerQuality({ mode, health }),
|
|
160346
|
+
diagnostics,
|
|
160347
|
+
caution: queryFallbackCaution(diagnostics)
|
|
160063
160348
|
};
|
|
160064
160349
|
}
|
|
160065
160350
|
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;
|
|
@@ -160070,7 +160355,7 @@ var init_external_provider = __esm({
|
|
|
160070
160355
|
init_secret_filter();
|
|
160071
160356
|
init_exclude3();
|
|
160072
160357
|
init_ids();
|
|
160073
|
-
DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS =
|
|
160358
|
+
DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS = 3e3;
|
|
160074
160359
|
MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS = 5e3;
|
|
160075
160360
|
EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS = 3e4;
|
|
160076
160361
|
MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES = 256 * 1024;
|
|
@@ -163353,6 +163638,7 @@ async function executeCleanup(context, payload, token) {
|
|
|
163353
163638
|
return { action: "cleanup", projectId: context.projectId, ...result };
|
|
163354
163639
|
}
|
|
163355
163640
|
async function previewDeduplicate(context) {
|
|
163641
|
+
initLLM({ scope: "memory", projectRoot: context.projectRoot });
|
|
163356
163642
|
if (!isLLMEnabled()) {
|
|
163357
163643
|
return {
|
|
163358
163644
|
action: "deduplicate",
|
|
@@ -165109,7 +165395,7 @@ var init_event_bus = __esm({
|
|
|
165109
165395
|
});
|
|
165110
165396
|
|
|
165111
165397
|
// src/orchestrate/task-graph.ts
|
|
165112
|
-
import { z as
|
|
165398
|
+
import { z as z626 } from "zod";
|
|
165113
165399
|
function parseTaskGraph(raw) {
|
|
165114
165400
|
const json2 = extractJson(raw);
|
|
165115
165401
|
if (!json2) {
|
|
@@ -165301,25 +165587,25 @@ var init_task_graph = __esm({
|
|
|
165301
165587
|
"src/orchestrate/task-graph.ts"() {
|
|
165302
165588
|
"use strict";
|
|
165303
165589
|
init_esm_shims();
|
|
165304
|
-
TaskNodeSchema =
|
|
165305
|
-
tempId:
|
|
165306
|
-
role:
|
|
165307
|
-
description:
|
|
165308
|
-
deps:
|
|
165309
|
-
files:
|
|
165590
|
+
TaskNodeSchema = z626.object({
|
|
165591
|
+
tempId: z626.string().min(1).describe('Temporary ID like "t1", "t2"'),
|
|
165592
|
+
role: z626.enum(["pm", "engineer", "qa", "reviewer"]),
|
|
165593
|
+
description: z626.string().min(30).describe("Self-contained task description with all context"),
|
|
165594
|
+
deps: z626.array(z626.string()).describe("tempIds of prerequisite tasks"),
|
|
165595
|
+
files: z626.array(z626.string()).optional().describe("Files this task will create or modify"),
|
|
165310
165596
|
/** Phase 7: Natural-language acceptance criteria (Goal-First Testing) */
|
|
165311
|
-
goals:
|
|
165597
|
+
goals: z626.array(z626.string()).optional().describe("Acceptance criteria for task verification")
|
|
165312
165598
|
});
|
|
165313
|
-
TaskGraphSchema =
|
|
165314
|
-
summary:
|
|
165315
|
-
tasks:
|
|
165599
|
+
TaskGraphSchema = z626.object({
|
|
165600
|
+
summary: z626.string().min(10).describe("One-paragraph plan summary"),
|
|
165601
|
+
tasks: z626.array(TaskNodeSchema).min(2).max(30)
|
|
165316
165602
|
}).superRefine((data, ctx) => {
|
|
165317
165603
|
const ids = new Set(data.tasks.map((t2) => t2.tempId));
|
|
165318
165604
|
for (const task of data.tasks) {
|
|
165319
165605
|
for (const dep of task.deps) {
|
|
165320
165606
|
if (!ids.has(dep)) {
|
|
165321
165607
|
ctx.addIssue({
|
|
165322
|
-
code:
|
|
165608
|
+
code: z626.ZodIssueCode.custom,
|
|
165323
165609
|
message: `Task "${task.tempId}" references unknown dependency "${dep}"`,
|
|
165324
165610
|
path: ["tasks"]
|
|
165325
165611
|
});
|
|
@@ -165327,7 +165613,7 @@ var init_task_graph = __esm({
|
|
|
165327
165613
|
}
|
|
165328
165614
|
if (task.deps.includes(task.tempId)) {
|
|
165329
165615
|
ctx.addIssue({
|
|
165330
|
-
code:
|
|
165616
|
+
code: z626.ZodIssueCode.custom,
|
|
165331
165617
|
message: `Task "${task.tempId}" depends on itself`,
|
|
165332
165618
|
path: ["tasks"]
|
|
165333
165619
|
});
|
|
@@ -165335,21 +165621,21 @@ var init_task_graph = __esm({
|
|
|
165335
165621
|
}
|
|
165336
165622
|
if (data.tasks.length > 0 && data.tasks[data.tasks.length - 1].role !== "reviewer") {
|
|
165337
165623
|
ctx.addIssue({
|
|
165338
|
-
code:
|
|
165624
|
+
code: z626.ZodIssueCode.custom,
|
|
165339
165625
|
message: 'Last task must have role "reviewer"',
|
|
165340
165626
|
path: ["tasks"]
|
|
165341
165627
|
});
|
|
165342
165628
|
}
|
|
165343
165629
|
if (hasCycle(data.tasks)) {
|
|
165344
165630
|
ctx.addIssue({
|
|
165345
|
-
code:
|
|
165631
|
+
code: z626.ZodIssueCode.custom,
|
|
165346
165632
|
message: "Task graph contains a cycle",
|
|
165347
165633
|
path: ["tasks"]
|
|
165348
165634
|
});
|
|
165349
165635
|
}
|
|
165350
165636
|
if (ids.size !== data.tasks.length) {
|
|
165351
165637
|
ctx.addIssue({
|
|
165352
|
-
code:
|
|
165638
|
+
code: z626.ZodIssueCode.custom,
|
|
165353
165639
|
message: "Duplicate tempId values detected",
|
|
165354
165640
|
path: ["tasks"]
|
|
165355
165641
|
});
|
|
@@ -167812,7 +168098,7 @@ __export(server_exports2, {
|
|
|
167812
168098
|
});
|
|
167813
168099
|
import { createHash as createHash16 } from "crypto";
|
|
167814
168100
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
167815
|
-
import { z as
|
|
168101
|
+
import { z as z627 } from "zod";
|
|
167816
168102
|
function formatFormationStageDurations(stageDurationsMs) {
|
|
167817
168103
|
const orderedStages = ["extract", "resolve", "evaluate"];
|
|
167818
168104
|
const parts = orderedStages.filter((stage) => stageDurationsMs[stage] !== void 0).map((stage) => `${stage}=${stageDurationsMs[stage]}ms`);
|
|
@@ -168184,10 +168470,9 @@ The path should point to a directory containing a .git folder.`
|
|
|
168184
168470
|
isError: true
|
|
168185
168471
|
};
|
|
168186
168472
|
};
|
|
168187
|
-
const
|
|
168188
|
-
|
|
168189
|
-
|
|
168190
|
-
});
|
|
168473
|
+
const serverInfo = getMcpServerInfo();
|
|
168474
|
+
const server = existingServer ?? new McpServer(serverInfo);
|
|
168475
|
+
registerMcpDiscovery(server, serverInfo);
|
|
168191
168476
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
168192
168477
|
server.registerTool = ((name, ...args) => {
|
|
168193
168478
|
if (!isToolInProfile(name, toolProfile)) {
|
|
@@ -168270,42 +168555,42 @@ The path should point to a directory containing a .git folder.`
|
|
|
168270
168555
|
title: "Store Memory",
|
|
168271
168556
|
description: "Store a new observation/memory. Automatically indexed for search. Use type to classify: gotcha ([GOTCHA] critical pitfall), decision ([DECISION] architecture choice), problem-solution ([FIX] bug fix), how-it-works ([INFO] explanation), what-changed ([CHANGE] change), discovery ([DISCOVERY] insight), why-it-exists ([WHY] rationale), trade-off ([TRADEOFF] compromise), session-request ([SESSION] original goal). Project visibility is the default. Personal or team visibility requires an explicitly joined coordination identity. Set longTerm only when the caller explicitly wants an additional source-backed long-term candidate; it is never injected until an operator records a review through the CLI. For a read-only task, do not store unless the user explicitly asks to save a record.",
|
|
168272
168557
|
inputSchema: {
|
|
168273
|
-
entityName:
|
|
168274
|
-
type:
|
|
168275
|
-
title:
|
|
168276
|
-
narrative:
|
|
168277
|
-
facts:
|
|
168278
|
-
filesModified:
|
|
168279
|
-
concepts:
|
|
168280
|
-
topicKey:
|
|
168558
|
+
entityName: z627.string().describe('The entity this observation belongs to (e.g., "auth-module", "port-config")'),
|
|
168559
|
+
type: z627.enum(OBSERVATION_TYPES).describe("Observation type for classification"),
|
|
168560
|
+
title: z627.string().describe("Short descriptive title (~5-10 words)"),
|
|
168561
|
+
narrative: z627.string().describe("Full description of the observation"),
|
|
168562
|
+
facts: z627.array(z627.string()).optional().describe('Structured facts (e.g., "Default timeout: 60s")'),
|
|
168563
|
+
filesModified: z627.array(z627.string()).optional().describe("Files involved"),
|
|
168564
|
+
concepts: z627.array(z627.string()).optional().describe("Related concepts/keywords"),
|
|
168565
|
+
topicKey: z627.string().optional().describe(
|
|
168281
168566
|
'Optional topic identifier for upserts (e.g., "architecture/auth-model"). If an observation with the same topicKey already exists in this project, it will be UPDATED instead of creating a new one. Use memorix_suggest_topic_key to generate a stable key. Good for evolving decisions, architecture docs, etc.'
|
|
168282
168567
|
),
|
|
168283
|
-
progress:
|
|
168284
|
-
feature:
|
|
168285
|
-
status:
|
|
168286
|
-
completion:
|
|
168568
|
+
progress: z627.object({
|
|
168569
|
+
feature: z627.string().describe("Feature or task name"),
|
|
168570
|
+
status: z627.enum(["in-progress", "completed", "blocked"]).describe("Current status"),
|
|
168571
|
+
completion: z627.number().optional().describe("Completion percentage 0-100")
|
|
168287
168572
|
}).optional().describe("Progress tracking for task/feature observations"),
|
|
168288
|
-
relatedCommits:
|
|
168289
|
-
relatedEntities:
|
|
168290
|
-
visibility:
|
|
168573
|
+
relatedCommits: z627.array(z627.string()).optional().describe("Git commit hashes this memory relates to (links ground truth \u2194 reasoning)"),
|
|
168574
|
+
relatedEntities: z627.array(z627.string()).optional().describe("Other entity names this memory cross-references"),
|
|
168575
|
+
visibility: z627.enum(["personal", "project", "team"]).optional().describe(
|
|
168291
168576
|
"Retrieval scope. Project is the normal shared default; personal/team require memorix_session_start with joinTeam=true."
|
|
168292
168577
|
),
|
|
168293
|
-
longTerm:
|
|
168294
|
-
kind:
|
|
168295
|
-
scope:
|
|
168296
|
-
tags:
|
|
168297
|
-
applicability:
|
|
168578
|
+
longTerm: z627.object({
|
|
168579
|
+
kind: z627.enum(["episodic", "semantic", "procedural"]).describe("Cognitive kind for an additional long-term candidate."),
|
|
168580
|
+
scope: z627.enum(["project", "user", "team"]).optional().default("project").describe("Long-term scope. User capture is private source evidence and needs a bound agent identity."),
|
|
168581
|
+
tags: z627.array(z627.string()).optional().describe("Small set of retrieval tags for the candidate."),
|
|
168582
|
+
applicability: z627.string().optional().describe("When this durable fact or procedure applies.")
|
|
168298
168583
|
}).optional().describe("Optional explicit request to create a source-backed long-term candidate alongside this observation. Candidates are not automatically injected."),
|
|
168299
|
-
overrideReadOnly:
|
|
168584
|
+
overrideReadOnly: z627.boolean().optional().describe(
|
|
168300
168585
|
"Use only when the user explicitly asks to save memory during a read-only or no-modification task."
|
|
168301
168586
|
),
|
|
168302
|
-
attachments:
|
|
168303
|
-
modality:
|
|
168304
|
-
url:
|
|
168587
|
+
attachments: z627.array(z627.object({
|
|
168588
|
+
modality: z627.enum(["image", "audio", "video", "document"]),
|
|
168589
|
+
url: z627.string().describe(
|
|
168305
168590
|
"Public HTTPS provenance reference without query parameters or fragments. Memorix does not fetch this URL: attachment metadata is persisted and BM25-searchable, while observation vectors remain text-only."
|
|
168306
168591
|
),
|
|
168307
|
-
mimeType:
|
|
168308
|
-
name:
|
|
168592
|
+
mimeType: z627.string().optional(),
|
|
168593
|
+
name: z627.string().optional()
|
|
168309
168594
|
})).optional().describe("Safe public provenance references. They are stored as metadata for lexical retrieval; raw inline media is never stored.")
|
|
168310
168595
|
}
|
|
168311
168596
|
},
|
|
@@ -168843,8 +169128,8 @@ Entity: ${entityName} | Type: ${type} | Project: ${project.id}${obs.topicKey ? `
|
|
|
168843
169128
|
title: "Suggest Topic Key",
|
|
168844
169129
|
description: 'Suggest a stable topic_key for memory upserts. Use this before memorix_store when you want evolving topics (like architecture decisions, config docs) to update a single observation over time instead of creating duplicates. Returns a key like "architecture/auth-model" or "bug/timeout-in-api-gateway".',
|
|
168845
169130
|
inputSchema: {
|
|
168846
|
-
type:
|
|
168847
|
-
title:
|
|
169131
|
+
type: z627.string().describe("Observation type (e.g., decision, architecture, bugfix, discovery)"),
|
|
169132
|
+
title: z627.string().describe("Observation title \u2014 used to generate the stable key")
|
|
168848
169133
|
}
|
|
168849
169134
|
},
|
|
168850
169135
|
async ({ type: obsType, title }) => {
|
|
@@ -168869,28 +169154,28 @@ Use this as the \`topicKey\` parameter in \`memorix_store\` to enable upsert beh
|
|
|
168869
169154
|
title: "Search Memory",
|
|
168870
169155
|
description: "Search project memory. Returns a compact index (~50-100 tokens/result). Do not use as a follow-up to a complete memorix_project_context brief unless a specific fact is still missing or the user asks for deeper history; provide purpose when intentionally expanding. Use memorix_detail to fetch full content for specific IDs. Use memorix_timeline to see chronological context. Searches across all observations stored from any IDE session \u2014 enabling cross-session and cross-agent context retrieval.",
|
|
168871
169156
|
inputSchema: {
|
|
168872
|
-
query:
|
|
168873
|
-
limit:
|
|
168874
|
-
type:
|
|
168875
|
-
maxTokens:
|
|
168876
|
-
scope:
|
|
169157
|
+
query: z627.string().describe("Search query (natural language or keywords)"),
|
|
169158
|
+
limit: z627.number().optional().describe("Max results (default: 20)"),
|
|
169159
|
+
type: z627.enum(OBSERVATION_TYPES).optional().describe("Filter by observation type"),
|
|
169160
|
+
maxTokens: z627.number().optional().describe("Token budget \u2014 trim results to fit (0 = unlimited)"),
|
|
169161
|
+
scope: z627.enum(["project", "global"]).optional().default("project").describe(
|
|
168877
169162
|
'Search scope: "project" (default) only searches current project, "global" searches all projects'
|
|
168878
169163
|
),
|
|
168879
|
-
since:
|
|
168880
|
-
until:
|
|
168881
|
-
status:
|
|
169164
|
+
since: z627.string().optional().describe('Only return observations created after this date (ISO 8601 or natural like "2025-01-15")'),
|
|
169165
|
+
until: z627.string().optional().describe('Only return observations created before this date (ISO 8601 or natural like "2025-02-01")'),
|
|
169166
|
+
status: z627.enum(["active", "resolved", "archived", "all"]).optional().default("active").describe(
|
|
168882
169167
|
'Filter by memory status. "active" (default) shows current memories, "all" includes resolved/archived.'
|
|
168883
169168
|
),
|
|
168884
|
-
source:
|
|
169169
|
+
source: z627.enum(["agent", "git", "manual"]).optional().describe(
|
|
168885
169170
|
'Filter by memory source. "git" returns only commit-derived ground truth memories. Omit for all sources.'
|
|
168886
169171
|
),
|
|
168887
|
-
quality:
|
|
169172
|
+
quality: z627.enum(["fast", "balanced", "thorough"]).optional().default("balanced").describe(
|
|
168888
169173
|
"Retrieval profile: fast stays local, balanced uses configured embeddings, thorough explicitly permits optional LLM refinement."
|
|
168889
169174
|
),
|
|
168890
|
-
purpose:
|
|
169175
|
+
purpose: z627.string().optional().describe(
|
|
168891
169176
|
"Why this must expand beyond the latest Autopilot brief. Name the missing fact or the user's explicit request."
|
|
168892
169177
|
),
|
|
168893
|
-
force:
|
|
169178
|
+
force: z627.boolean().optional().describe(
|
|
168894
169179
|
"Use only when the user explicitly asks to read a record already represented in the latest Autopilot brief."
|
|
168895
169180
|
)
|
|
168896
169181
|
}
|
|
@@ -168979,9 +169264,9 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
168979
169264
|
title: "Memory Graph Context",
|
|
168980
169265
|
description: "Build a compact, prompt-ready memory graph context packet for the current project. Use this for broad memory overview questions, project memory graph questions, or task-specific memory grounding. Returns high-signal memories, entities, relations, and risks as background context, not instructions.",
|
|
168981
169266
|
inputSchema: {
|
|
168982
|
-
query:
|
|
168983
|
-
limit:
|
|
168984
|
-
format:
|
|
169267
|
+
query: z627.string().describe("Current task or topic to build memory graph context for"),
|
|
169268
|
+
limit: z627.number().optional().describe("Max high-signal memories to include (default: 5)"),
|
|
169269
|
+
format: z627.enum(["prompt", "summary"]).optional().default("prompt").describe(
|
|
168985
169270
|
'Output format. "prompt" is agent-ready; "summary" is a compact human overview.'
|
|
168986
169271
|
)
|
|
168987
169272
|
}
|
|
@@ -169016,14 +169301,14 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
169016
169301
|
title: "Memory Autopilot Project Context",
|
|
169017
169302
|
description: "Build a compact Memory Autopilot brief for the current coding task. Schedules Code Memory refresh when needed, includes Start here files, reliable code-bound memories, stale/suspect cautions, and verification hints. Use this at the start of a new coding turn or after switching tasks.",
|
|
169018
169303
|
inputSchema: {
|
|
169019
|
-
task:
|
|
169020
|
-
refresh:
|
|
169304
|
+
task: z627.string().optional().describe("Current coding task or question"),
|
|
169305
|
+
refresh: z627.enum(["auto", "always", "never"]).optional().default("auto").describe(
|
|
169021
169306
|
"Code Memory refresh policy. auto refreshes only when missing or stale."
|
|
169022
169307
|
),
|
|
169023
|
-
format:
|
|
169308
|
+
format: z627.enum(["prompt", "summary", "json", "receipt"]).optional().default("prompt").describe(
|
|
169024
169309
|
'Output format. "prompt" is agent-ready; "summary" is human-readable; "receipt" is bounded JSON; "json" is detailed diagnostics.'
|
|
169025
169310
|
),
|
|
169026
|
-
agent:
|
|
169311
|
+
agent: z627.enum([
|
|
169027
169312
|
"windsurf",
|
|
169028
169313
|
"cursor",
|
|
169029
169314
|
"claude-code",
|
|
@@ -169038,7 +169323,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
169038
169323
|
"opencode",
|
|
169039
169324
|
"trae"
|
|
169040
169325
|
]).optional().describe("Optional target agent for compatible workflow selection."),
|
|
169041
|
-
limit:
|
|
169326
|
+
limit: z627.number().optional().describe("Reserved for future source limits; current prompt stays compact by default.")
|
|
169042
169327
|
}
|
|
169043
169328
|
},
|
|
169044
169329
|
async ({ task, refresh, format, agent }) => {
|
|
@@ -169139,12 +169424,12 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
169139
169424
|
title: "Context Pack",
|
|
169140
169425
|
description: "Build a prompt-ready working context pack for a coding task. Combines relevant memories, CodeGraph Memory facts, freshness warnings, suggested reads, and verification hints. After a complete memorix_project_context brief, provide purpose only when deliberately expanding beyond it.",
|
|
169141
169426
|
inputSchema: {
|
|
169142
|
-
task:
|
|
169143
|
-
limit:
|
|
169427
|
+
task: z627.string().describe("Current coding task or question"),
|
|
169428
|
+
limit: z627.preprocess(
|
|
169144
169429
|
(value) => typeof value === "string" && value.trim() !== "" ? Number(value) : value,
|
|
169145
|
-
|
|
169430
|
+
z627.number().int().positive().max(100)
|
|
169146
169431
|
).optional().describe("Max active memories to inspect before code-ref filtering (default: 20)"),
|
|
169147
|
-
purpose:
|
|
169432
|
+
purpose: z627.string().optional().describe(
|
|
169148
169433
|
"Why this must expand beyond the latest Autopilot brief. Name the missing fact or the user's explicit request."
|
|
169149
169434
|
)
|
|
169150
169435
|
}
|
|
@@ -169239,7 +169524,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
169239
169524
|
title: "Knowledge Workspace",
|
|
169240
169525
|
description: "Manage the reviewable project Knowledge Workspace. Use it only for deliberate knowledge operations: initialize a local or versioned workspace, review source-backed claims, compile proposals, lint, apply a reviewed proposal, or manage canonical workflows. It is intentionally absent from the default micro/lite profiles.",
|
|
169241
169526
|
inputSchema: {
|
|
169242
|
-
action:
|
|
169527
|
+
action: z627.enum([
|
|
169243
169528
|
"workspace_init",
|
|
169244
169529
|
"status",
|
|
169245
169530
|
"claim_list",
|
|
@@ -169254,21 +169539,21 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
169254
169539
|
"workflow_apply",
|
|
169255
169540
|
"workflow_run"
|
|
169256
169541
|
]).describe("Knowledge operation to perform"),
|
|
169257
|
-
mode:
|
|
169258
|
-
path:
|
|
169259
|
-
proposalId:
|
|
169260
|
-
allowManualOverwrite:
|
|
169261
|
-
claimId:
|
|
169262
|
-
claimReviewState:
|
|
169263
|
-
reviewDetail:
|
|
169264
|
-
workflowId:
|
|
169265
|
-
agent:
|
|
169266
|
-
task:
|
|
169267
|
-
outcome:
|
|
169268
|
-
verificationVerdict:
|
|
169269
|
-
failureReason:
|
|
169270
|
-
startingSnapshotId:
|
|
169271
|
-
evidenceIds:
|
|
169542
|
+
mode: z627.enum(["local", "versioned"]).optional().default("local").describe("Workspace mode; versioned writes require an explicit project path during workspace_init"),
|
|
169543
|
+
path: z627.string().optional().describe("Explicit versioned workspace path, used only by workspace_init"),
|
|
169544
|
+
proposalId: z627.string().optional().describe("Pending proposal id for proposal_apply"),
|
|
169545
|
+
allowManualOverwrite: z627.boolean().optional().default(false).describe("Explicitly allow proposal_apply to replace a manually edited page"),
|
|
169546
|
+
claimId: z627.string().optional().describe("Source-backed claim id for claim_review"),
|
|
169547
|
+
claimReviewState: z627.enum(["approved", "rejected"]).optional().describe("Deliberate review verdict for claim_review"),
|
|
169548
|
+
reviewDetail: z627.string().max(2e3).optional().describe("Evidence check performed before approving or rejecting a claim"),
|
|
169549
|
+
workflowId: z627.string().optional().describe("Canonical workflow id for workflow preview, apply, or run"),
|
|
169550
|
+
agent: z627.string().optional().describe("Target agent for a workflow adapter"),
|
|
169551
|
+
task: z627.string().optional().describe("Task text for workflow selection or a workflow run"),
|
|
169552
|
+
outcome: z627.enum(["passed", "failed", "cancelled", "in-progress"]).optional().describe("Workflow run outcome"),
|
|
169553
|
+
verificationVerdict: z627.enum(["passed", "failed", "not-run"]).optional().describe("Workflow run verification verdict"),
|
|
169554
|
+
failureReason: z627.string().optional().describe("Sanitized workflow failure reason"),
|
|
169555
|
+
startingSnapshotId: z627.string().optional().describe("Code snapshot id present when a workflow run began"),
|
|
169556
|
+
evidenceIds: z627.array(z627.string()).max(24).optional().describe("Selected evidence ids for a workflow run")
|
|
169272
169557
|
}
|
|
169273
169558
|
},
|
|
169274
169559
|
async ({
|
|
@@ -169544,8 +169829,8 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
169544
169829
|
title: "Resolve Memories",
|
|
169545
169830
|
description: `Mark observations as resolved (completed/no longer active). Resolved memories are hidden from default search but can still be found with status="all". Use this to mark completed tasks, fixed bugs, or outdated information so they don't pollute future context.`,
|
|
169546
169831
|
inputSchema: {
|
|
169547
|
-
ids:
|
|
169548
|
-
status:
|
|
169832
|
+
ids: z627.array(z627.number()).describe("Observation IDs to mark as resolved"),
|
|
169833
|
+
status: z627.enum(["resolved", "archived"]).optional().default("resolved").describe(
|
|
169549
169834
|
'Target status: "resolved" (default, completed/done) or "archived" (permanently hidden)'
|
|
169550
169835
|
)
|
|
169551
169836
|
}
|
|
@@ -169583,17 +169868,17 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
169583
169868
|
title: "Store Reasoning Trace",
|
|
169584
169869
|
description: "Store a reasoning trace \u2014 WHY you chose this approach, what alternatives you considered, and what outcome you expect. This creates a searchable record of your decision-making process. Use this when making non-trivial technical decisions, choosing between approaches, or solving complex problems. Unlike regular memories that record WHAT happened, reasoning memories record HOW you thought about it.",
|
|
169585
169870
|
inputSchema: {
|
|
169586
|
-
entityName:
|
|
169587
|
-
decision:
|
|
169588
|
-
alternatives:
|
|
169589
|
-
rationale:
|
|
169590
|
-
constraints:
|
|
169591
|
-
expectedOutcome:
|
|
169592
|
-
risks:
|
|
169593
|
-
concepts:
|
|
169594
|
-
filesModified:
|
|
169595
|
-
relatedCommits:
|
|
169596
|
-
relatedEntities:
|
|
169871
|
+
entityName: z627.string().describe('The entity this reasoning applies to (e.g., "auth-module", "database-schema")'),
|
|
169872
|
+
decision: z627.string().describe("What was decided or chosen"),
|
|
169873
|
+
alternatives: z627.array(z627.string()).optional().describe("Other options that were considered"),
|
|
169874
|
+
rationale: z627.string().describe("Why this approach was chosen over alternatives"),
|
|
169875
|
+
constraints: z627.array(z627.string()).optional().describe("Constraints that influenced the decision (time, perf, compat, etc.)"),
|
|
169876
|
+
expectedOutcome: z627.string().optional().describe("What outcome is expected from this decision"),
|
|
169877
|
+
risks: z627.array(z627.string()).optional().describe("Known risks or potential downsides"),
|
|
169878
|
+
concepts: z627.array(z627.string()).optional().describe("Related technical concepts"),
|
|
169879
|
+
filesModified: z627.array(z627.string()).optional().describe("Files related to this reasoning"),
|
|
169880
|
+
relatedCommits: z627.array(z627.string()).optional().describe("Git commit hashes this reasoning explains (links ground truth \u2194 reasoning)"),
|
|
169881
|
+
relatedEntities: z627.array(z627.string()).optional().describe("Other entity names this reasoning relates to (cross-references)")
|
|
169597
169882
|
}
|
|
169598
169883
|
},
|
|
169599
169884
|
async ({ entityName, decision, alternatives, rationale, constraints, expectedOutcome, risks, concepts, filesModified, relatedCommits, relatedEntities }) => {
|
|
@@ -169668,7 +169953,7 @@ Entity: ${entityName} | ${facts.length} facts | ${obs.tokens} tokens${reasoningA
|
|
|
169668
169953
|
title: "Audit Project Attribution",
|
|
169669
169954
|
description: "Scan the current project for observations that may have been written to the wrong project bucket. Identifies observations whose entityName appears exclusively in a different project. Read-only \u2014 no data is changed. Use memorix_resolve to archive confirmed mis-attributed observations.",
|
|
169670
169955
|
inputSchema: {
|
|
169671
|
-
threshold:
|
|
169956
|
+
threshold: z627.number().int().min(1).optional().describe(
|
|
169672
169957
|
"Minimum occurrences of an entityName in another project to flag it as suspicious (default: 2)"
|
|
169673
169958
|
)
|
|
169674
169959
|
}
|
|
@@ -169732,9 +170017,9 @@ Entity: ${entityName} | ${facts.length} facts | ${obs.tokens} tokens${reasoningA
|
|
|
169732
170017
|
title: "Search Reasoning Patterns",
|
|
169733
170018
|
description: "Search past reasoning traces to understand WHY decisions were made. Returns reasoning memories that explain the thought process behind technical choices. Use this when revisiting code, questioning a design decision, or looking for precedent on how similar problems were solved before.",
|
|
169734
170019
|
inputSchema: {
|
|
169735
|
-
query:
|
|
169736
|
-
limit:
|
|
169737
|
-
scope:
|
|
170020
|
+
query: z627.string().describe('Search query \u2014 describe what reasoning you want to find (e.g., "why did we choose PostgreSQL", "auth approach rationale")'),
|
|
170021
|
+
limit: z627.number().optional().describe("Max results (default: 10)"),
|
|
170022
|
+
scope: z627.enum(["project", "global"]).optional().default("project").describe("Search scope")
|
|
169738
170023
|
}
|
|
169739
170024
|
},
|
|
169740
170025
|
async ({ query, limit: limit2, scope }) => {
|
|
@@ -169768,8 +170053,8 @@ ${result.formatted}` }]
|
|
|
169768
170053
|
title: "Deduplicate Memories",
|
|
169769
170054
|
description: "Scan active memories for duplicates, contradictions, and outdated information using LLM analysis. Automatically resolves redundant memories. Requires LLM to be configured (set MEMORIX_LLM_API_KEY or OPENAI_API_KEY environment variable). Without LLM, falls back to basic similarity-based consolidation.",
|
|
169770
170055
|
inputSchema: {
|
|
169771
|
-
query:
|
|
169772
|
-
dryRun:
|
|
170056
|
+
query: z627.string().optional().describe("Optional query to scope dedup to a topic (default: scan all)"),
|
|
170057
|
+
dryRun: z627.boolean().optional().default(false).describe("Preview only \u2014 show what would be resolved without making changes")
|
|
169773
170058
|
}
|
|
169774
170059
|
},
|
|
169775
170060
|
async ({ query, dryRun }) => {
|
|
@@ -169838,9 +170123,9 @@ ${actionLines.join("\n")}`
|
|
|
169838
170123
|
title: "Memory Timeline",
|
|
169839
170124
|
description: "Deep retrieval: expand chronological context around a specific observation \u2014 distinguishes explicit memory evolution, hook activity traces, and git-backed facts. Natural follow-up after session L1 routing hints (hook traces) or L3 evidence pointers (git memory).",
|
|
169840
170125
|
inputSchema: {
|
|
169841
|
-
anchorId:
|
|
169842
|
-
depthBefore:
|
|
169843
|
-
depthAfter:
|
|
170126
|
+
anchorId: z627.number().describe("Observation ID to center the timeline on"),
|
|
170127
|
+
depthBefore: z627.number().optional().describe("Number of observations before (default: 3)"),
|
|
170128
|
+
depthAfter: z627.number().optional().describe("Number of observations after (default: 3)")
|
|
169844
170129
|
}
|
|
169845
170130
|
},
|
|
169846
170131
|
async ({ anchorId, depthBefore, depthAfter }) => {
|
|
@@ -169870,18 +170155,18 @@ ${actionLines.join("\n")}`
|
|
|
169870
170155
|
title: "Memory Details",
|
|
169871
170156
|
description: 'Fetch full observation, mini-skill, or curated durable-memory details \u2014 includes source kind (explicit memory / hook trace / git evidence), value category, and cross-references (~500-1000 tokens each). Do not re-fetch content already covered by a complete memorix_project_context brief unless a specific fact is still missing or the user asks for deeper history; provide purpose when intentionally expanding. Always use memorix_search first to find relevant IDs, then fetch only what you need. Accepts typed refs from search results (e.g. "obs:42", "skill:3") and durable refs from a project brief (e.g. "durable:<uuid>") via the typedRefs field, or legacy numeric ids / object refs for backward compatibility.',
|
|
169872
170157
|
inputSchema: {
|
|
169873
|
-
ids:
|
|
169874
|
-
refs:
|
|
169875
|
-
|
|
169876
|
-
id:
|
|
169877
|
-
projectId:
|
|
170158
|
+
ids: z627.array(z627.number()).optional().describe("Observation IDs to fetch (legacy, from memorix_search results)"),
|
|
170159
|
+
refs: z627.array(
|
|
170160
|
+
z627.object({
|
|
170161
|
+
id: z627.number().describe("Observation ID"),
|
|
170162
|
+
projectId: z627.string().optional().describe("Project ID for global-search disambiguation")
|
|
169878
170163
|
})
|
|
169879
170164
|
).optional().describe("Explicit observation refs. Prefer this for global search results."),
|
|
169880
|
-
typedRefs:
|
|
169881
|
-
purpose:
|
|
170165
|
+
typedRefs: z627.array(z627.string()).optional().describe('Typed memory refs from search results or a project brief, e.g. "obs:42", "skill:3", "durable:<uuid>", "obs:42@org/proj"'),
|
|
170166
|
+
purpose: z627.string().optional().describe(
|
|
169882
170167
|
"Why this must expand beyond the latest Autopilot brief. Name the missing fact or the user's explicit request."
|
|
169883
170168
|
),
|
|
169884
|
-
force:
|
|
170169
|
+
force: z627.boolean().optional().describe(
|
|
169885
170170
|
"Use only when the user explicitly asks to read a record already represented in the latest Autopilot brief."
|
|
169886
170171
|
)
|
|
169887
170172
|
}
|
|
@@ -169960,7 +170245,7 @@ ${actionLines.join("\n")}`
|
|
|
169960
170245
|
title: "Memory Retention Status & Archive",
|
|
169961
170246
|
description: 'Show memory retention status or archive expired memories. action="report" (default): show active/stale/archive-candidate counts. action="archive": move expired observations to archive file (reversible). action="stale": list stale observations with full retention explanation. Uses exponential decay scoring based on importance, age, and access patterns.',
|
|
169962
170247
|
inputSchema: {
|
|
169963
|
-
action:
|
|
170248
|
+
action: z627.enum(["report", "archive", "stale"]).optional().describe('Action: "report" (show status, default) or "archive" (move expired to archive) or "stale" (list stale observations with explanation)')
|
|
169964
170249
|
}
|
|
169965
170250
|
},
|
|
169966
170251
|
async (args) => {
|
|
@@ -170225,10 +170510,10 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
170225
170510
|
title: "Create Entities",
|
|
170226
170511
|
description: "Create multiple new entities in the knowledge graph",
|
|
170227
170512
|
inputSchema: {
|
|
170228
|
-
entities:
|
|
170229
|
-
name:
|
|
170230
|
-
entityType:
|
|
170231
|
-
observations:
|
|
170513
|
+
entities: z627.array(z627.object({
|
|
170514
|
+
name: z627.string().describe("The name of the entity"),
|
|
170515
|
+
entityType: z627.string().describe("The type of the entity"),
|
|
170516
|
+
observations: z627.array(z627.string()).describe("Initial observations")
|
|
170232
170517
|
}))
|
|
170233
170518
|
}
|
|
170234
170519
|
},
|
|
@@ -170248,10 +170533,10 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
170248
170533
|
title: "Create Relations",
|
|
170249
170534
|
description: "Create multiple new relations between entities in the knowledge graph. Relations should be in active voice. Recommended relation types (from mcp-memory-service): causes, fixes, supports, opposes, contradicts, depends_on, implements, extends, replaces, documents",
|
|
170250
170535
|
inputSchema: {
|
|
170251
|
-
relations:
|
|
170252
|
-
from:
|
|
170253
|
-
to:
|
|
170254
|
-
relationType:
|
|
170536
|
+
relations: z627.array(z627.object({
|
|
170537
|
+
from: z627.string().describe("Source entity name"),
|
|
170538
|
+
to: z627.string().describe("Target entity name"),
|
|
170539
|
+
relationType: z627.string().describe("Type of relation (e.g., causes, fixes, supports, depends_on, implements)")
|
|
170255
170540
|
}))
|
|
170256
170541
|
}
|
|
170257
170542
|
},
|
|
@@ -170271,9 +170556,9 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
170271
170556
|
title: "Add Observations",
|
|
170272
170557
|
description: "Add new observations to existing entities in the knowledge graph",
|
|
170273
170558
|
inputSchema: {
|
|
170274
|
-
observations:
|
|
170275
|
-
entityName:
|
|
170276
|
-
contents:
|
|
170559
|
+
observations: z627.array(z627.object({
|
|
170560
|
+
entityName: z627.string().describe("Entity name to add observations to"),
|
|
170561
|
+
contents: z627.array(z627.string()).describe("Observation contents to add")
|
|
170277
170562
|
}))
|
|
170278
170563
|
}
|
|
170279
170564
|
},
|
|
@@ -170293,7 +170578,7 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
170293
170578
|
title: "Delete Entities",
|
|
170294
170579
|
description: "Delete multiple entities and their associated relations from the knowledge graph",
|
|
170295
170580
|
inputSchema: {
|
|
170296
|
-
entityNames:
|
|
170581
|
+
entityNames: z627.array(z627.string()).describe("Entity names to delete")
|
|
170297
170582
|
}
|
|
170298
170583
|
},
|
|
170299
170584
|
async ({ entityNames }) => {
|
|
@@ -170312,9 +170597,9 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
170312
170597
|
title: "Delete Observations",
|
|
170313
170598
|
description: "Delete specific observations from entities in the knowledge graph",
|
|
170314
170599
|
inputSchema: {
|
|
170315
|
-
deletions:
|
|
170316
|
-
entityName:
|
|
170317
|
-
observations:
|
|
170600
|
+
deletions: z627.array(z627.object({
|
|
170601
|
+
entityName: z627.string().describe("Entity containing the observations"),
|
|
170602
|
+
observations: z627.array(z627.string()).describe("Observations to delete")
|
|
170318
170603
|
}))
|
|
170319
170604
|
}
|
|
170320
170605
|
},
|
|
@@ -170334,10 +170619,10 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
170334
170619
|
title: "Delete Relations",
|
|
170335
170620
|
description: "Delete multiple relations from the knowledge graph",
|
|
170336
170621
|
inputSchema: {
|
|
170337
|
-
relations:
|
|
170338
|
-
from:
|
|
170339
|
-
to:
|
|
170340
|
-
relationType:
|
|
170622
|
+
relations: z627.array(z627.object({
|
|
170623
|
+
from: z627.string(),
|
|
170624
|
+
to: z627.string(),
|
|
170625
|
+
relationType: z627.string()
|
|
170341
170626
|
}))
|
|
170342
170627
|
}
|
|
170343
170628
|
},
|
|
@@ -170386,7 +170671,7 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
170386
170671
|
title: "Search Nodes",
|
|
170387
170672
|
description: "Search for nodes in the knowledge graph based on a query",
|
|
170388
170673
|
inputSchema: {
|
|
170389
|
-
query:
|
|
170674
|
+
query: z627.string().describe("Search query to match against entity names, types, and observations")
|
|
170390
170675
|
}
|
|
170391
170676
|
},
|
|
170392
170677
|
async ({ query }) => {
|
|
@@ -170405,7 +170690,7 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
170405
170690
|
title: "Open Nodes",
|
|
170406
170691
|
description: "Open specific nodes in the knowledge graph by their names",
|
|
170407
170692
|
inputSchema: {
|
|
170408
|
-
names:
|
|
170693
|
+
names: z627.array(z627.string()).describe("Entity names to retrieve")
|
|
170409
170694
|
}
|
|
170410
170695
|
},
|
|
170411
170696
|
async ({ names }) => {
|
|
@@ -170427,8 +170712,8 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
170427
170712
|
title: "Rules Sync",
|
|
170428
170713
|
description: "Scan project for agent rule files (Cursor, Claude Code, Codex, Windsurf, Antigravity, Gemini CLI, Copilot, Kiro, OpenCode, Trae), deduplicate, detect conflicts, and optionally generate rules for a target agent format. Without target: returns sync status report. With target: generates converted rule files.",
|
|
170429
170714
|
inputSchema: {
|
|
170430
|
-
action:
|
|
170431
|
-
target:
|
|
170715
|
+
action: z627.enum(["status", "generate"]).describe('Action: "status" for report, "generate" to produce target files'),
|
|
170716
|
+
target: z627.enum(RULE_SOURCES).optional().describe("Target agent format for generation (required when action=generate)")
|
|
170432
170717
|
}
|
|
170433
170718
|
},
|
|
170434
170719
|
async ({ action, target }) => {
|
|
@@ -170483,9 +170768,9 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
170483
170768
|
title: "Workspace Sync",
|
|
170484
170769
|
description: 'Migrate your entire workspace environment between AI coding agents (Cursor, Windsurf, Claude Code, Codex, Copilot, Gemini CLI, OpenClaw, Hermes Agent, Oh-my-Pi, Kiro, Antigravity, OpenCode, Trae). Syncs MCP server configs, workflows, rules, and skills across IDEs. Action "scan": detect all workspace configs. Action "migrate": generate configs for target agent (preview only). Action "apply": migrate AND write configs to disk with backup/rollback.',
|
|
170485
170770
|
inputSchema: {
|
|
170486
|
-
action:
|
|
170487
|
-
target:
|
|
170488
|
-
items:
|
|
170771
|
+
action: z627.enum(["scan", "migrate", "apply"]).describe('Action: "scan" to detect configs, "migrate" to preview, "apply" to write to disk'),
|
|
170772
|
+
target: z627.enum(AGENT_TARGETS).optional().describe("Target agent for migration (required for migrate)"),
|
|
170773
|
+
items: z627.array(z627.string()).optional().describe('Selective sync: list specific MCP server or skill names to sync (e.g. ["figma-remote-mcp-server", "create-subagent"]). Omit to sync all.')
|
|
170489
170774
|
}
|
|
170490
170775
|
},
|
|
170491
170776
|
async ({ action, target, items }) => {
|
|
@@ -170581,10 +170866,10 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
170581
170866
|
title: "Project Skills",
|
|
170582
170867
|
description: `Memory-driven project skills. Action "list": show all available skills from all agents. Action "generate": auto-generate project-specific skills from observation patterns (gotchas, decisions, how-it-works). Action "inject": return a specific skill's full content for direct use. Generated skills follow the SKILL.md standard and can be synced across Cursor, Windsurf, Claude Code, Codex, Copilot, Kiro, Antigravity, OpenCode, and Trae. OpenClaw, Hermes Agent, and Oh-my-Pi receive skills through their official bundle/plugin/package setup lanes rather than generic workspace skill copy.`,
|
|
170583
170868
|
inputSchema: {
|
|
170584
|
-
action:
|
|
170585
|
-
name:
|
|
170586
|
-
target:
|
|
170587
|
-
write:
|
|
170869
|
+
action: z627.enum(["list", "generate", "inject"]).describe('Action: "list" to discover skills, "generate" to create from memory, "inject" to get skill content'),
|
|
170870
|
+
name: z627.string().optional().describe('Skill name (required for "inject")'),
|
|
170871
|
+
target: z627.enum(AGENT_TARGETS).optional().describe('Target agent to write generated skills to (optional for "generate")'),
|
|
170872
|
+
write: z627.boolean().optional().describe("Whether to write generated skills to disk (default: false, preview only)")
|
|
170588
170873
|
}
|
|
170589
170874
|
},
|
|
170590
170875
|
async ({ action, name, target, write }) => {
|
|
@@ -170694,12 +170979,12 @@ ${skill2.content}` }]
|
|
|
170694
170979
|
title: "Promote to Mini-Skill",
|
|
170695
170980
|
description: 'Promote observations to permanent mini-skills that never decay and are auto-injected at session start. Action "promote": convert observation(s) to a mini-skill. Action "list": show all active mini-skills. Action "delete": remove a mini-skill by ID.\n\nMini-skills are project-specific specialized knowledge derived from your actual memories \u2014 gotchas, decisions, fixes that generic online skills cannot provide.',
|
|
170696
170981
|
inputSchema: {
|
|
170697
|
-
action:
|
|
170698
|
-
observationIds:
|
|
170699
|
-
skillId:
|
|
170700
|
-
trigger:
|
|
170701
|
-
instruction:
|
|
170702
|
-
tags:
|
|
170982
|
+
action: z627.enum(["promote", "list", "delete"]).describe("Action to perform"),
|
|
170983
|
+
observationIds: z627.array(z627.number()).optional().describe('Observation IDs to promote (required for "promote")'),
|
|
170984
|
+
skillId: z627.number().optional().describe('Mini-skill ID to delete (required for "delete")'),
|
|
170985
|
+
trigger: z627.string().optional().describe("Override: when this skill should be applied"),
|
|
170986
|
+
instruction: z627.string().optional().describe("Override: what the agent should do"),
|
|
170987
|
+
tags: z627.array(z627.string()).optional().describe("Extra classification tags")
|
|
170703
170988
|
}
|
|
170704
170989
|
},
|
|
170705
170990
|
async ({ action, observationIds, skillId, trigger, instruction, tags }) => {
|
|
@@ -170778,8 +171063,8 @@ ${skill2.content}` }]
|
|
|
170778
171063
|
title: "Consolidate Memories",
|
|
170779
171064
|
description: 'Find and merge similar observations to reduce memory bloat. Uses text similarity to cluster related observations by entity+type, then merges them into single consolidated records. Use action="preview" to see candidates without changing data, action="execute" to merge.\n\nExample: 10 similar gotchas about Windows paths \u2192 1 consolidated gotcha with all facts preserved.',
|
|
170780
171065
|
inputSchema: {
|
|
170781
|
-
action:
|
|
170782
|
-
threshold:
|
|
171066
|
+
action: z627.enum(["preview", "execute"]).describe("preview = dry run showing candidates, execute = actually merge"),
|
|
171067
|
+
threshold: z627.number().optional().describe("Similarity threshold 0.0-1.0 (default: 0.45). Lower = more aggressive merging")
|
|
170783
171068
|
}
|
|
170784
171069
|
},
|
|
170785
171070
|
async ({ action, threshold }) => {
|
|
@@ -170825,13 +171110,13 @@ ${skill2.content}` }]
|
|
|
170825
171110
|
title: "Start Session",
|
|
170826
171111
|
description: "Start a new coding session. Returns a compact continuation card with the latest handoff and a few memory references. Call this at the beginning of a session to track activity; retrieve a referenced memory only when it is relevant. Any previous active session for this project will be auto-closed. By default this is lightweight: it binds the project, opens a session, and avoids dumping full history into the new context. Coordination identity is opt-in via `joinTeam: true` or a separate `team_manage` join call.\n\nIMPORTANT for HTTP/control-plane mode: pass `projectRoot` with the absolute path to your workspace root (e.g., the directory open in your IDE). Memorix uses this to detect the git project and bind this session to the correct project context. Without it, project-scoped tools will be disabled.",
|
|
170827
171112
|
inputSchema: {
|
|
170828
|
-
sessionId:
|
|
170829
|
-
agent:
|
|
170830
|
-
agentType:
|
|
170831
|
-
instanceId:
|
|
170832
|
-
joinTeam:
|
|
170833
|
-
role:
|
|
170834
|
-
projectRoot:
|
|
171113
|
+
sessionId: z627.string().optional().describe("Custom session ID (auto-generated if omitted)"),
|
|
171114
|
+
agent: z627.string().optional().describe('Agent/IDE name (e.g., "cursor", "windsurf", "claude-code")'),
|
|
171115
|
+
agentType: z627.string().optional().describe('Agent type used for optional coordination identity mapping (e.g., "windsurf", "cursor").'),
|
|
171116
|
+
instanceId: z627.string().optional().describe("Stable instance ID for optional coordination identity across restarts. If omitted with joinTeam=true, Memorix derives a deterministic fallback from the project and agent identity."),
|
|
171117
|
+
joinTeam: z627.boolean().optional().describe("If true, also join orchestration coordination state for this session. Defaults to false."),
|
|
171118
|
+
role: z627.string().optional().describe("Explicit role override used only when joinTeam=true."),
|
|
171119
|
+
projectRoot: z627.string().optional().describe(
|
|
170835
171120
|
"Absolute path to the workspace/project root directory (e.g., the folder open in your IDE). Memorix will detect the git project from this path and bind this session to it. Required for HTTP transport when multiple projects are open simultaneously or when rebinding an existing control-plane session."
|
|
170836
171121
|
)
|
|
170837
171122
|
}
|
|
@@ -171038,8 +171323,8 @@ ${s2.instruction}`.toLowerCase();
|
|
|
171038
171323
|
title: "End Session",
|
|
171039
171324
|
description: "End a coding session with a structured summary. This summary will be injected into the next session so the next agent can resume work seamlessly.\n\nRecommended summary format:\n## Goal\n[What we were working on]\n\n## Discoveries\n- [Technical findings, gotchas, learnings]\n\n## Accomplished\n- [OK] [Completed tasks]\n- [PENDING] [Pending for next session]\n\n## Relevant Files\n- path/to/file \u2014 [what changed]",
|
|
171040
171325
|
inputSchema: {
|
|
171041
|
-
sessionId:
|
|
171042
|
-
summary:
|
|
171326
|
+
sessionId: z627.string().describe("Session ID to close (from memorix_session_start)"),
|
|
171327
|
+
summary: z627.string().optional().describe("Structured session summary (Goal/Discoveries/Accomplished/Files format)")
|
|
171043
171328
|
}
|
|
171044
171329
|
},
|
|
171045
171330
|
async ({ sessionId, summary }) => {
|
|
@@ -171067,7 +171352,7 @@ ${summary ? "Summary saved for next session context injection." : "No summary pr
|
|
|
171067
171352
|
title: "Session Context",
|
|
171068
171353
|
description: "Get context from previous coding sessions. Use this after compaction to recover lost context, or to manually review session history. Returns previous session summaries and key observations.",
|
|
171069
171354
|
inputSchema: {
|
|
171070
|
-
limit:
|
|
171355
|
+
limit: z627.number().optional().describe("Number of recent sessions to include (default: 3)")
|
|
171071
171356
|
}
|
|
171072
171357
|
},
|
|
171073
171358
|
async ({ limit: limit2 }) => {
|
|
@@ -171100,14 +171385,14 @@ ${summary ? "Summary saved for next session context injection." : "No summary pr
|
|
|
171100
171385
|
title: "Compact Continuity Checkpoints",
|
|
171101
171386
|
description: "Inspect, preview, or archive bounded checkpoints recorded around a host-native context compaction. Use only to debug or explicitly review compaction continuity. These are lifecycle records, not durable memories or transcript backups. CLI equivalent: memorix checkpoint list|show|context|archive.",
|
|
171102
171387
|
inputSchema: {
|
|
171103
|
-
action:
|
|
171104
|
-
id:
|
|
171105
|
-
sessionId:
|
|
171106
|
-
agent:
|
|
171107
|
-
task:
|
|
171108
|
-
maxTokens:
|
|
171109
|
-
limit:
|
|
171110
|
-
includeArchived:
|
|
171388
|
+
action: z627.enum(["list", "show", "context", "archive"]).default("list"),
|
|
171389
|
+
id: z627.string().optional().describe("Checkpoint ID for show, context, or archive"),
|
|
171390
|
+
sessionId: z627.string().optional().describe("Optional host session ID filter"),
|
|
171391
|
+
agent: z627.string().optional().describe("Optional host agent filter"),
|
|
171392
|
+
task: z627.string().optional().describe("Current task for a bounded context preview"),
|
|
171393
|
+
maxTokens: z627.number().optional().describe("Maximum tokens for action=context (default: 420)"),
|
|
171394
|
+
limit: z627.number().optional().describe("Maximum records for action=list (default: 20)"),
|
|
171395
|
+
includeArchived: z627.boolean().optional().default(false).describe("Include archived records in action=list")
|
|
171111
171396
|
}
|
|
171112
171397
|
},
|
|
171113
171398
|
async ({ action, id, sessionId, agent, task, maxTokens, limit: limit2, includeArchived }) => {
|
|
@@ -171180,9 +171465,9 @@ ${summary ? "Summary saved for next session context injection." : "No summary pr
|
|
|
171180
171465
|
title: "Transfer Memories",
|
|
171181
171466
|
description: 'Export or import project memories. Action "export": export observations visible to the current agent and project sessions (JSON or Markdown). Action "import": import from a JSON export (re-assigns IDs, skips duplicate topicKeys).',
|
|
171182
171467
|
inputSchema: {
|
|
171183
|
-
action:
|
|
171184
|
-
format:
|
|
171185
|
-
data:
|
|
171468
|
+
action: z627.enum(["export", "import"]).describe("Operation: export or import"),
|
|
171469
|
+
format: z627.enum(["json", "markdown"]).optional().describe("Export format (for export, default: json)"),
|
|
171470
|
+
data: z627.string().optional().describe("JSON string from a previous export (for import)")
|
|
171186
171471
|
}
|
|
171187
171472
|
},
|
|
171188
171473
|
async ({ action, format, data: jsonStr }) => {
|
|
@@ -171231,7 +171516,7 @@ ${json2}
|
|
|
171231
171516
|
title: "Launch Dashboard",
|
|
171232
171517
|
description: "Launch the Memorix Web Dashboard in the browser. In HTTP control-plane mode, this reuses the current control-plane dashboard. In stdio/standalone mode, it starts the standalone dashboard server.",
|
|
171233
171518
|
inputSchema: {
|
|
171234
|
-
port:
|
|
171519
|
+
port: z627.number().optional().describe("Optional port override for standalone mode. In HTTP control-plane mode, the active dashboard port is reused.")
|
|
171235
171520
|
}
|
|
171236
171521
|
},
|
|
171237
171522
|
async ({ port: dashboardPort }) => {
|
|
@@ -171395,13 +171680,13 @@ ${json2}
|
|
|
171395
171680
|
title: "Evidence Cards",
|
|
171396
171681
|
description: "Inspect the bounded, project-scoped provenance cards behind Memorix context. Use list for a compact index, get/events for one source, sync to repair the projection, and stale when known source files changed. Cards expose sourceRef, locator, capturedHash, and freshness.",
|
|
171397
171682
|
inputSchema: {
|
|
171398
|
-
action:
|
|
171399
|
-
candidateKind:
|
|
171400
|
-
candidateId:
|
|
171401
|
-
query:
|
|
171402
|
-
paths:
|
|
171403
|
-
reason:
|
|
171404
|
-
limit:
|
|
171683
|
+
action: z627.enum(["list", "get", "sync", "stale", "events"]).describe("Evidence operation"),
|
|
171684
|
+
candidateKind: z627.enum(["observation", "code", "git", "test", "document", "workflow", "graph"]).optional().default("observation"),
|
|
171685
|
+
candidateId: z627.string().optional().describe("Candidate id, usually an observation id"),
|
|
171686
|
+
query: z627.string().optional().describe("Optional title/source query for list"),
|
|
171687
|
+
paths: z627.array(z627.string()).max(200).optional().describe("Changed source paths for stale"),
|
|
171688
|
+
reason: z627.string().max(500).optional().describe("Why evidence became stale"),
|
|
171689
|
+
limit: z627.number().int().positive().max(100).optional().default(20)
|
|
171405
171690
|
}
|
|
171406
171691
|
},
|
|
171407
171692
|
async ({ action, candidateKind, candidateId, query, paths, reason, limit: limit2 }) => {
|
|
@@ -171441,15 +171726,15 @@ ${json2}
|
|
|
171441
171726
|
title: "Memory Feedback",
|
|
171442
171727
|
description: "Record or inspect auditable memory outcomes. Positive verification/use strengthens recall; correction, conflict, source change, or weaken lowers it. Use revoke with targetEventId to undo one prior signal without deleting audit history.",
|
|
171443
171728
|
inputSchema: {
|
|
171444
|
-
action:
|
|
171445
|
-
candidateKind:
|
|
171446
|
-
candidateId:
|
|
171447
|
-
signal:
|
|
171448
|
-
sourceRef:
|
|
171449
|
-
actor:
|
|
171450
|
-
note:
|
|
171451
|
-
targetEventId:
|
|
171452
|
-
limit:
|
|
171729
|
+
action: z627.enum(["record", "show", "audit"]).describe("Feedback operation"),
|
|
171730
|
+
candidateKind: z627.enum(["observation", "claim", "durable-memory", "workflow"]).optional().default("observation"),
|
|
171731
|
+
candidateId: z627.string().describe("Memory or knowledge candidate id"),
|
|
171732
|
+
signal: z627.enum(["user-correction", "verification-success", "verification-failure", "code-change", "used", "not-used", "code-conflict", "strengthen", "weaken", "revoke"]).optional(),
|
|
171733
|
+
sourceRef: z627.string().max(500).optional().describe("Source of this feedback, such as test:run-42 or user:chat"),
|
|
171734
|
+
actor: z627.string().max(200).optional(),
|
|
171735
|
+
note: z627.string().max(2e3).optional(),
|
|
171736
|
+
targetEventId: z627.string().optional().describe("Existing event id when action=record and signal=revoke"),
|
|
171737
|
+
limit: z627.number().int().positive().max(200).optional().default(100)
|
|
171453
171738
|
}
|
|
171454
171739
|
},
|
|
171455
171740
|
async ({ action, candidateKind, candidateId, signal, sourceRef, actor, note, targetEventId, limit: limit2 }) => {
|
|
@@ -171515,19 +171800,19 @@ ${json2}
|
|
|
171515
171800
|
title: "Coordination Management",
|
|
171516
171801
|
description: 'Register, unregister, or list agents in the project coordination state. Action "join": register this agent (returns agent ID and instance ID for reactivation). Action "leave": mark agent inactive, release locks. Action "status": list all agents with roles and capabilities, plus role occupancy. Action "listRoles": show defined roles for this project. Action "addRole": define a new role for this project. Action "removeRole": remove a role definition.',
|
|
171517
171802
|
inputSchema: {
|
|
171518
|
-
action:
|
|
171519
|
-
name:
|
|
171520
|
-
agentType:
|
|
171521
|
-
instanceId:
|
|
171522
|
-
role:
|
|
171523
|
-
capabilities:
|
|
171524
|
-
agentId:
|
|
171803
|
+
action: z627.enum(["join", "leave", "status", "listRoles", "addRole", "removeRole"]).describe("Operation to perform"),
|
|
171804
|
+
name: z627.string().optional().describe('Agent display name for join (e.g., "cursor-frontend")'),
|
|
171805
|
+
agentType: z627.string().optional().describe('Agent type for join (e.g., "windsurf", "cursor", "claude-code")'),
|
|
171806
|
+
instanceId: z627.string().optional().describe("Stable instance ID for join (preserves identity across restarts)"),
|
|
171807
|
+
role: z627.string().optional().describe("Agent role for join (defaults by agentType if omitted)"),
|
|
171808
|
+
capabilities: z627.array(z627.string()).optional().describe("Agent capabilities for join"),
|
|
171809
|
+
agentId: z627.string().optional().describe("Agent ID for leave"),
|
|
171525
171810
|
// Role management params
|
|
171526
|
-
roleId:
|
|
171527
|
-
label:
|
|
171528
|
-
roleDescription:
|
|
171529
|
-
preferredAgentTypes:
|
|
171530
|
-
maxConcurrent:
|
|
171811
|
+
roleId: z627.string().optional().describe("Role ID (for addRole/removeRole)"),
|
|
171812
|
+
label: z627.string().optional().describe("Role label (for addRole)"),
|
|
171813
|
+
roleDescription: z627.string().optional().describe("Role description (for addRole)"),
|
|
171814
|
+
preferredAgentTypes: z627.array(z627.string()).optional().describe("Preferred agent types for this role (for addRole)"),
|
|
171815
|
+
maxConcurrent: z627.number().optional().describe("Max concurrent agents for this role (for addRole, default 1)")
|
|
171531
171816
|
}
|
|
171532
171817
|
},
|
|
171533
171818
|
async ({ action, name, agentType, instanceId, role, capabilities, agentId, roleId, label, roleDescription, preferredAgentTypes, maxConcurrent }) => {
|
|
@@ -171640,9 +171925,9 @@ ${agentLines.join("\n")}`
|
|
|
171640
171925
|
title: "File Lock Management",
|
|
171641
171926
|
description: 'Advisory file locks to prevent conflicting edits. Auto-releases after 10 min TTL. Action "lock": acquire lock. Action "unlock": release lock. Action "status": check lock status.',
|
|
171642
171927
|
inputSchema: {
|
|
171643
|
-
action:
|
|
171644
|
-
file:
|
|
171645
|
-
agentId:
|
|
171928
|
+
action: z627.enum(["lock", "unlock", "status"]).describe("Operation to perform"),
|
|
171929
|
+
file: z627.string().optional().describe("File path (required for lock/unlock, optional for status \u2014 omit to list all)"),
|
|
171930
|
+
agentId: z627.string().optional().describe("Agent ID (required for lock/unlock)")
|
|
171646
171931
|
}
|
|
171647
171932
|
},
|
|
171648
171933
|
async ({ action, file, agentId }) => {
|
|
@@ -171684,17 +171969,17 @@ ${lines.join("\n")}` }] };
|
|
|
171684
171969
|
title: "Task Status",
|
|
171685
171970
|
description: 'Create, claim, complete, or list tasks in the team task board. Supports dependencies. Action "create": create a task. Action "claim": assign to yourself (atomic, race-safe). Action "complete": mark done with result. Action "list": show tasks.',
|
|
171686
171971
|
inputSchema: {
|
|
171687
|
-
action:
|
|
171688
|
-
description:
|
|
171689
|
-
deps:
|
|
171690
|
-
taskId:
|
|
171691
|
-
agentId:
|
|
171692
|
-
result:
|
|
171693
|
-
status:
|
|
171694
|
-
available:
|
|
171695
|
-
metadata:
|
|
171696
|
-
requiredRole:
|
|
171697
|
-
preferredRole:
|
|
171972
|
+
action: z627.enum(["create", "claim", "complete", "list"]).describe("Operation to perform"),
|
|
171973
|
+
description: z627.string().optional().describe("Task description (for create)"),
|
|
171974
|
+
deps: z627.array(z627.string()).optional().describe("Dependency task IDs (for create)"),
|
|
171975
|
+
taskId: z627.string().optional().describe("Task ID (for claim/complete)"),
|
|
171976
|
+
agentId: z627.string().optional().describe("Agent ID (for claim/complete)"),
|
|
171977
|
+
result: z627.string().optional().describe("Result summary (for complete)"),
|
|
171978
|
+
status: z627.enum(["pending", "in_progress", "completed", "failed"]).optional().describe("Filter by status (for list)"),
|
|
171979
|
+
available: z627.boolean().optional().describe("Show only claimable tasks (for list)"),
|
|
171980
|
+
metadata: z627.string().optional().describe("JSON metadata for the task (for create). Used by planner/review tasks for autonomous mode."),
|
|
171981
|
+
requiredRole: z627.string().optional().describe("Required role for this task (for create). Agents without this role cannot claim."),
|
|
171982
|
+
preferredRole: z627.string().optional().describe("Preferred role for this task (for create). Agents with this role are prioritized.")
|
|
171698
171983
|
}
|
|
171699
171984
|
},
|
|
171700
171985
|
async ({ action, description: desc, deps, taskId, agentId, result, status, available, metadata, requiredRole, preferredRole }) => {
|
|
@@ -171767,15 +172052,15 @@ ${lines.join("\n")}` }] };
|
|
|
171767
172052
|
title: "Team Messaging",
|
|
171768
172053
|
description: `Send, broadcast, or read messages between agents. Durable: messages survive restarts and reach inactive recipients. Action "send": direct message to one agent. Action "broadcast": message all agents. Action "inbox": read this agent's inbox.`,
|
|
171769
172054
|
inputSchema: {
|
|
171770
|
-
action:
|
|
171771
|
-
from:
|
|
171772
|
-
to:
|
|
171773
|
-
type:
|
|
171774
|
-
content:
|
|
171775
|
-
agentId:
|
|
171776
|
-
markRead:
|
|
171777
|
-
toRole:
|
|
171778
|
-
handoffStatus:
|
|
172055
|
+
action: z627.enum(["send", "broadcast", "inbox"]).describe("Operation to perform"),
|
|
172056
|
+
from: z627.string().optional().describe("Your sender agent ID. Omit it to use this session identity."),
|
|
172057
|
+
to: z627.string().optional().describe("Receiver agent ID (for send)"),
|
|
172058
|
+
type: z627.enum(["request", "response", "info", "announcement", "contract", "error", "handoff"]).optional().describe("Message type (for send/broadcast)"),
|
|
172059
|
+
content: z627.string().optional().describe("Message content (for send/broadcast)"),
|
|
172060
|
+
agentId: z627.string().optional().describe("Agent ID (for inbox)"),
|
|
172061
|
+
markRead: z627.boolean().optional().default(false).describe("Mark messages as read (for inbox)"),
|
|
172062
|
+
toRole: z627.string().optional().describe("Target role for role-based messaging/handoff (for send)"),
|
|
172063
|
+
handoffStatus: z627.enum(["open", "claimed", "completed", "archived"]).optional().describe("Handoff status (for send with type=handoff)")
|
|
171779
172064
|
}
|
|
171780
172065
|
},
|
|
171781
172066
|
async ({ action, from, to, type: msgType, content, agentId, markRead, toRole, handoffStatus }) => {
|
|
@@ -171845,8 +172130,8 @@ ${lines.join("\n")}` }] };
|
|
|
171845
172130
|
title: "Team Poll \u2014 Situational Awareness",
|
|
171846
172131
|
description: "Get a full snapshot of your project coordination state in one call. Returns: your agent info, watermark (new observations since last session), inbox (unread messages), tasks (your in-progress, available to claim, completed, failed), and team roster (active agents). Use this to decide what to work on next.",
|
|
171847
172132
|
inputSchema: {
|
|
171848
|
-
agentId:
|
|
171849
|
-
markInboxRead:
|
|
172133
|
+
agentId: z627.string().optional().describe("Your agent ID (from team_manage join or session_start with joinTeam=true). If omitted, returns project-level overview only."),
|
|
172134
|
+
markInboxRead: z627.boolean().optional().describe("If true, mark all inbox messages as read after returning them.")
|
|
171850
172135
|
}
|
|
171851
172136
|
},
|
|
171852
172137
|
async ({ agentId, markInboxRead }) => {
|
|
@@ -171940,13 +172225,13 @@ ${lines.join("\n")}` }] };
|
|
|
171940
172225
|
title: "Team Handoff \u2014 Agent Context Transfer",
|
|
171941
172226
|
description: "Create a structured handoff artifact when passing work to another agent. A targeted handoff is visible only to its sender and recipient; a broadcast handoff is team-visible. The handoff is stored as a durable observation (immune to archival) and a notification message is sent to the recipient. Use this when completing a task and another agent should continue, or when you want to leave context for whoever works on this next.",
|
|
171942
172227
|
inputSchema: {
|
|
171943
|
-
fromAgentId:
|
|
171944
|
-
summary:
|
|
171945
|
-
context:
|
|
171946
|
-
toAgentId:
|
|
171947
|
-
taskId:
|
|
171948
|
-
filesModified:
|
|
171949
|
-
concepts:
|
|
172228
|
+
fromAgentId: z627.string().describe("Your agent ID (from team_manage join or session_start with joinTeam=true)"),
|
|
172229
|
+
summary: z627.string().describe("Human-readable summary of what you did and what needs to happen next"),
|
|
172230
|
+
context: z627.string().describe("Detailed context for the next agent: what was done, current state, known issues, next steps"),
|
|
172231
|
+
toAgentId: z627.string().optional().describe("Specific recipient agent ID. Omit to broadcast to all."),
|
|
172232
|
+
taskId: z627.string().optional().describe("Link to a specific team_task ID"),
|
|
172233
|
+
filesModified: z627.array(z627.string()).optional().describe("Files you modified during this work"),
|
|
172234
|
+
concepts: z627.array(z627.string()).optional().describe("Key concepts for search discoverability")
|
|
171950
172235
|
}
|
|
171951
172236
|
},
|
|
171952
172237
|
async ({ fromAgentId, summary, context, toAgentId, taskId, filesModified, concepts }) => {
|
|
@@ -172026,7 +172311,7 @@ ${lines.join("\n")}` }] };
|
|
|
172026
172311
|
title: "Manage Controlled Media",
|
|
172027
172312
|
description: "Use the controlled local media library for an explicit import, attachment, inspection, or MiniMax generation request. Assets stay outside the Git worktree and enter normal memory only when attach is explicitly true. Use the CLI for destructive removal, quota cleanup, and direct generation. MCP generation is disabled by default and requires MEMORIX_MCP_MEDIA_GENERATION=1 after the operator reviews provider billing.",
|
|
172028
172313
|
inputSchema: {
|
|
172029
|
-
action:
|
|
172314
|
+
action: z627.enum([
|
|
172030
172315
|
"import",
|
|
172031
172316
|
"attach",
|
|
172032
172317
|
"list",
|
|
@@ -172037,32 +172322,32 @@ ${lines.join("\n")}` }] };
|
|
|
172037
172322
|
...mediaTranscriptionEnabled ? ["derive-audio"] : [],
|
|
172038
172323
|
...mediaGenerationEnabled ? ["generate-image", "generate-video"] : []
|
|
172039
172324
|
]),
|
|
172040
|
-
path:
|
|
172041
|
-
assetId:
|
|
172042
|
-
jobId:
|
|
172043
|
-
kind:
|
|
172044
|
-
limit:
|
|
172045
|
-
title:
|
|
172046
|
-
narrative:
|
|
172047
|
-
maxPages:
|
|
172048
|
-
maxChars:
|
|
172049
|
-
attach:
|
|
172325
|
+
path: z627.string().optional().describe("Explicit local image/audio/video/PDF path for import."),
|
|
172326
|
+
assetId: z627.string().optional().describe("Controlled MediaAsset ID for attach/show."),
|
|
172327
|
+
jobId: z627.string().optional().describe("Durable media job ID for status."),
|
|
172328
|
+
kind: z627.enum(["image", "audio", "video", "document"]).optional().describe("Optional asset list filter."),
|
|
172329
|
+
limit: z627.number().int().min(1).max(100).optional().describe("Maximum assets to list."),
|
|
172330
|
+
title: z627.string().optional().describe("Observation title when attaching generated/imported output."),
|
|
172331
|
+
narrative: z627.string().optional().describe("Short retrieval text when attaching an asset."),
|
|
172332
|
+
maxPages: z627.number().int().min(1).max(100).optional().describe("Bounded PDF extraction page limit."),
|
|
172333
|
+
maxChars: z627.number().int().min(1).max(6e4).optional().describe("Bounded PDF extraction character limit."),
|
|
172334
|
+
attach: z627.boolean().optional().describe("Attach generated/imported output to normal project memory explicitly."),
|
|
172050
172335
|
...mediaGenerationOrTranscription ? {
|
|
172051
|
-
model:
|
|
172052
|
-
prompt:
|
|
172336
|
+
model: z627.string().max(160).optional().describe("Provider model for the selected media action."),
|
|
172337
|
+
prompt: z627.string().optional().describe("Explicit prompt for generation or transcription.")
|
|
172053
172338
|
} : {},
|
|
172054
172339
|
...mediaTranscriptionEnabled ? {
|
|
172055
|
-
provider:
|
|
172056
|
-
language:
|
|
172340
|
+
provider: z627.enum(["openai", "groq"]).optional().describe("Explicit audio transcription provider."),
|
|
172341
|
+
language: z627.string().max(32).optional().describe("Optional ISO-639-1 hint for audio transcription.")
|
|
172057
172342
|
} : {},
|
|
172058
172343
|
...mediaGenerationEnabled ? {
|
|
172059
|
-
image:
|
|
172060
|
-
region:
|
|
172061
|
-
n:
|
|
172062
|
-
ratio:
|
|
172063
|
-
width:
|
|
172064
|
-
height:
|
|
172065
|
-
duration:
|
|
172344
|
+
image: z627.string().optional().describe("Base64-encoded reference image for image-to-image generation."),
|
|
172345
|
+
region: z627.enum(["global", "cn"]).optional().describe("MiniMax deployment region."),
|
|
172346
|
+
n: z627.number().int().min(1).max(4).optional().describe("Image output count."),
|
|
172347
|
+
ratio: z627.enum(["adaptive", "1:1", "16:9", "4:3", "3:2", "2:3", "3:4", "9:16", "21:9"]).optional().describe("Image or video aspect ratio."),
|
|
172348
|
+
width: z627.number().int().min(1).max(8192).optional().describe("Requested image width."),
|
|
172349
|
+
height: z627.number().int().min(1).max(8192).optional().describe("Requested image height."),
|
|
172350
|
+
duration: z627.union([z627.literal(5), z627.literal(10)]).optional().describe("MiniMax video duration in seconds.")
|
|
172066
172351
|
} : {}
|
|
172067
172352
|
}
|
|
172068
172353
|
},
|
|
@@ -172260,10 +172545,10 @@ ${lines.join("\n")}` }] };
|
|
|
172260
172545
|
title: "Ingest Image",
|
|
172261
172546
|
description: "Legacy compatibility path: import caller-provided image bytes into the controlled local asset library, then store a text retrieval projection. For durable media operations, prefer memorix_media or the media CLI.",
|
|
172262
172547
|
inputSchema: {
|
|
172263
|
-
base64:
|
|
172264
|
-
mimeType:
|
|
172265
|
-
filename:
|
|
172266
|
-
prompt:
|
|
172548
|
+
base64: z627.string().describe("Base64-encoded image data"),
|
|
172549
|
+
mimeType: z627.string().optional().describe("Deprecated compatibility hint. Memorix detects the actual MIME type from the image bytes."),
|
|
172550
|
+
filename: z627.string().optional().describe("Original filename"),
|
|
172551
|
+
prompt: z627.string().optional().describe("Custom analysis prompt")
|
|
172267
172552
|
}
|
|
172268
172553
|
},
|
|
172269
172554
|
async (args) => {
|
|
@@ -172563,6 +172848,7 @@ var init_server2 = __esm({
|
|
|
172563
172848
|
init_secret_filter();
|
|
172564
172849
|
init_surfaced_registry();
|
|
172565
172850
|
init_request_context();
|
|
172851
|
+
init_mcp_compat();
|
|
172566
172852
|
FORMATION_TIMEOUT_MS = parseFormationTimeoutMs(process.env.MEMORIX_FORMATION_TIMEOUT_MS);
|
|
172567
172853
|
COMPACT_ON_WRITE_TIMEOUT_MS = 12e3;
|
|
172568
172854
|
COMPRESSION_TIMEOUT_MS = 5e3;
|
|
@@ -172591,6 +172877,218 @@ var init_server2 = __esm({
|
|
|
172591
172877
|
}
|
|
172592
172878
|
});
|
|
172593
172879
|
|
|
172880
|
+
// src/server/stdio-startup-gate.ts
|
|
172881
|
+
import { PassThrough as PassThrough3 } from "stream";
|
|
172882
|
+
var STDIO_STARTUP_GATE_MAX_BUFFER_SIZE, StdioStartupGate;
|
|
172883
|
+
var init_stdio_startup_gate = __esm({
|
|
172884
|
+
"src/server/stdio-startup-gate.ts"() {
|
|
172885
|
+
"use strict";
|
|
172886
|
+
init_esm_shims();
|
|
172887
|
+
init_mcp_discovery();
|
|
172888
|
+
STDIO_STARTUP_GATE_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
|
|
172889
|
+
StdioStartupGate = class {
|
|
172890
|
+
input = new PassThrough3();
|
|
172891
|
+
stdin;
|
|
172892
|
+
stdout;
|
|
172893
|
+
serverInfo;
|
|
172894
|
+
maxBufferSize;
|
|
172895
|
+
onError;
|
|
172896
|
+
onEnd;
|
|
172897
|
+
queuedMessages = [];
|
|
172898
|
+
pendingInput = "";
|
|
172899
|
+
queuedBytes = 0;
|
|
172900
|
+
started = false;
|
|
172901
|
+
ready = false;
|
|
172902
|
+
stopped = false;
|
|
172903
|
+
stdinEnded = false;
|
|
172904
|
+
endNotified = false;
|
|
172905
|
+
onData = (chunk) => {
|
|
172906
|
+
if (this.stopped) return;
|
|
172907
|
+
if (this.ready) {
|
|
172908
|
+
if (Buffer.byteLength(chunk, "utf8") > this.maxBufferSize) {
|
|
172909
|
+
this.fail(new Error(`stdio input chunk exceeded ${this.maxBufferSize} bytes`));
|
|
172910
|
+
return;
|
|
172911
|
+
}
|
|
172912
|
+
this.input.write(chunk);
|
|
172913
|
+
return;
|
|
172914
|
+
}
|
|
172915
|
+
const text2 = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
172916
|
+
if (this.queuedBytes + Buffer.byteLength(this.pendingInput, "utf8") + Buffer.byteLength(text2, "utf8") > this.maxBufferSize) {
|
|
172917
|
+
this.fail(new Error(`stdio startup input exceeded ${this.maxBufferSize} bytes before a complete JSON-RPC line`));
|
|
172918
|
+
return;
|
|
172919
|
+
}
|
|
172920
|
+
this.pendingInput += text2;
|
|
172921
|
+
let newline = this.pendingInput.indexOf("\n");
|
|
172922
|
+
while (newline >= 0 && !this.stopped) {
|
|
172923
|
+
const line = this.pendingInput.slice(0, newline + 1);
|
|
172924
|
+
this.pendingInput = this.pendingInput.slice(newline + 1);
|
|
172925
|
+
this.handleLine(line);
|
|
172926
|
+
newline = this.pendingInput.indexOf("\n");
|
|
172927
|
+
}
|
|
172928
|
+
if (!this.stopped && Buffer.byteLength(this.pendingInput, "utf8") > this.maxBufferSize) {
|
|
172929
|
+
this.fail(new Error(`stdio startup input exceeded ${this.maxBufferSize} bytes`));
|
|
172930
|
+
}
|
|
172931
|
+
};
|
|
172932
|
+
onStdinError = (error) => {
|
|
172933
|
+
this.fail(error);
|
|
172934
|
+
};
|
|
172935
|
+
onStdinEnd = () => {
|
|
172936
|
+
this.stdinEnded = true;
|
|
172937
|
+
if (this.ready) this.finishInput();
|
|
172938
|
+
};
|
|
172939
|
+
constructor(options) {
|
|
172940
|
+
this.stdin = options.stdin;
|
|
172941
|
+
this.stdout = options.stdout;
|
|
172942
|
+
this.serverInfo = { ...options.serverInfo };
|
|
172943
|
+
this.maxBufferSize = options.maxBufferSize ?? STDIO_STARTUP_GATE_MAX_BUFFER_SIZE;
|
|
172944
|
+
this.onError = options.onError;
|
|
172945
|
+
this.onEnd = options.onEnd;
|
|
172946
|
+
}
|
|
172947
|
+
start() {
|
|
172948
|
+
if (this.started || this.stopped) return;
|
|
172949
|
+
this.started = true;
|
|
172950
|
+
this.stdin.on("data", this.onData);
|
|
172951
|
+
this.stdin.on("error", this.onStdinError);
|
|
172952
|
+
this.stdin.on("end", this.onStdinEnd);
|
|
172953
|
+
}
|
|
172954
|
+
/** Release queued messages only after StdioServerTransport has installed its listener. */
|
|
172955
|
+
markReady() {
|
|
172956
|
+
if (this.stopped || this.ready) return;
|
|
172957
|
+
this.ready = true;
|
|
172958
|
+
for (const message of this.queuedMessages) this.input.write(message);
|
|
172959
|
+
this.queuedMessages.length = 0;
|
|
172960
|
+
this.queuedBytes = 0;
|
|
172961
|
+
if (this.pendingInput) {
|
|
172962
|
+
this.input.write(this.pendingInput);
|
|
172963
|
+
this.pendingInput = "";
|
|
172964
|
+
}
|
|
172965
|
+
if (this.stdinEnded) this.finishInput();
|
|
172966
|
+
}
|
|
172967
|
+
stop() {
|
|
172968
|
+
if (this.stopped) return;
|
|
172969
|
+
this.stopped = true;
|
|
172970
|
+
this.stdin.off("data", this.onData);
|
|
172971
|
+
this.stdin.off("error", this.onStdinError);
|
|
172972
|
+
this.stdin.off("end", this.onStdinEnd);
|
|
172973
|
+
this.queuedMessages.length = 0;
|
|
172974
|
+
this.pendingInput = "";
|
|
172975
|
+
this.queuedBytes = 0;
|
|
172976
|
+
if (!this.input.destroyed) this.input.end();
|
|
172977
|
+
}
|
|
172978
|
+
handleLine(line) {
|
|
172979
|
+
const parsed = this.parseLine(line);
|
|
172980
|
+
if (!parsed) return;
|
|
172981
|
+
if ("error" in parsed) {
|
|
172982
|
+
this.writeJsonRpcError(null, parsed.error.code, parsed.error.message);
|
|
172983
|
+
return;
|
|
172984
|
+
}
|
|
172985
|
+
if (!this.ready && this.isDiscoveryRequest(parsed.message)) {
|
|
172986
|
+
const response = {
|
|
172987
|
+
jsonrpc: "2.0",
|
|
172988
|
+
id: parsed.message.id,
|
|
172989
|
+
result: createMcpStartupDiscoverResult(this.serverInfo)
|
|
172990
|
+
};
|
|
172991
|
+
try {
|
|
172992
|
+
this.stdout.write(`${JSON.stringify(response)}
|
|
172993
|
+
`);
|
|
172994
|
+
} catch (error) {
|
|
172995
|
+
this.fail(error instanceof Error ? error : new Error(String(error)));
|
|
172996
|
+
}
|
|
172997
|
+
return;
|
|
172998
|
+
}
|
|
172999
|
+
if (this.ready) {
|
|
173000
|
+
this.input.write(line);
|
|
173001
|
+
return;
|
|
173002
|
+
}
|
|
173003
|
+
const bytes = Buffer.byteLength(line, "utf8");
|
|
173004
|
+
if (this.queuedBytes + bytes > this.maxBufferSize) {
|
|
173005
|
+
this.fail(new Error(`stdio startup queue exceeded ${this.maxBufferSize} bytes`));
|
|
173006
|
+
return;
|
|
173007
|
+
}
|
|
173008
|
+
this.queuedMessages.push(line);
|
|
173009
|
+
this.queuedBytes += bytes;
|
|
173010
|
+
}
|
|
173011
|
+
parseLine(line) {
|
|
173012
|
+
const trimmed = line.endsWith("\n") ? line.slice(0, -1).replace(/\r$/, "") : line;
|
|
173013
|
+
if (!trimmed.trim()) return null;
|
|
173014
|
+
let value;
|
|
173015
|
+
try {
|
|
173016
|
+
value = JSON.parse(trimmed);
|
|
173017
|
+
} catch {
|
|
173018
|
+
return { error: { code: -32700, message: "Parse error" } };
|
|
173019
|
+
}
|
|
173020
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
173021
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
173022
|
+
}
|
|
173023
|
+
const message = value;
|
|
173024
|
+
if (message.jsonrpc !== "2.0") {
|
|
173025
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
173026
|
+
}
|
|
173027
|
+
const hasId = Object.prototype.hasOwnProperty.call(message, "id");
|
|
173028
|
+
const hasMethod = typeof message.method === "string";
|
|
173029
|
+
const hasResult = Object.prototype.hasOwnProperty.call(message, "result");
|
|
173030
|
+
const hasError = Object.prototype.hasOwnProperty.call(message, "error");
|
|
173031
|
+
if (hasMethod && (hasResult || hasError)) {
|
|
173032
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
173033
|
+
}
|
|
173034
|
+
if (!hasMethod && !hasResult && !hasError) {
|
|
173035
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
173036
|
+
}
|
|
173037
|
+
if (hasId && !this.isValidRequestId(message.id)) {
|
|
173038
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
173039
|
+
}
|
|
173040
|
+
if (!hasMethod && !hasId) {
|
|
173041
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
173042
|
+
}
|
|
173043
|
+
return { message };
|
|
173044
|
+
}
|
|
173045
|
+
isDiscoveryRequest(message) {
|
|
173046
|
+
if (message.method !== MCP_SERVER_DISCOVER_METHOD) return false;
|
|
173047
|
+
if (!Object.prototype.hasOwnProperty.call(message, "id")) return false;
|
|
173048
|
+
const params = message.params;
|
|
173049
|
+
return params === void 0 || typeof params === "object" && params !== null && !Array.isArray(params);
|
|
173050
|
+
}
|
|
173051
|
+
isValidRequestId(id) {
|
|
173052
|
+
return id === null || typeof id === "string" || typeof id === "number" && Number.isFinite(id);
|
|
173053
|
+
}
|
|
173054
|
+
writeJsonRpcError(id, code, message) {
|
|
173055
|
+
try {
|
|
173056
|
+
this.stdout.write(`${JSON.stringify({
|
|
173057
|
+
jsonrpc: "2.0",
|
|
173058
|
+
id,
|
|
173059
|
+
error: { code, message }
|
|
173060
|
+
})}
|
|
173061
|
+
`);
|
|
173062
|
+
} catch (error) {
|
|
173063
|
+
this.fail(error instanceof Error ? error : new Error(String(error)));
|
|
173064
|
+
}
|
|
173065
|
+
}
|
|
173066
|
+
finishInput() {
|
|
173067
|
+
if (!this.ready || this.input.destroyed || this.input.writableEnded) return;
|
|
173068
|
+
this.input.end();
|
|
173069
|
+
this.input.once("end", () => this.notifyEnd());
|
|
173070
|
+
}
|
|
173071
|
+
notifyEnd() {
|
|
173072
|
+
if (this.endNotified) return;
|
|
173073
|
+
this.endNotified = true;
|
|
173074
|
+
this.onEnd?.();
|
|
173075
|
+
}
|
|
173076
|
+
fail(error) {
|
|
173077
|
+
if (this.stopped) return;
|
|
173078
|
+
this.stopped = true;
|
|
173079
|
+
this.stdin.off("data", this.onData);
|
|
173080
|
+
this.stdin.off("error", this.onStdinError);
|
|
173081
|
+
this.stdin.off("end", this.onStdinEnd);
|
|
173082
|
+
this.queuedMessages.length = 0;
|
|
173083
|
+
this.pendingInput = "";
|
|
173084
|
+
this.queuedBytes = 0;
|
|
173085
|
+
if (!this.input.destroyed) this.input.destroy();
|
|
173086
|
+
this.onError?.(error);
|
|
173087
|
+
}
|
|
173088
|
+
};
|
|
173089
|
+
}
|
|
173090
|
+
});
|
|
173091
|
+
|
|
172594
173092
|
// src/cli/mcp-root-path.ts
|
|
172595
173093
|
import path35 from "path";
|
|
172596
173094
|
function mcpFileUriToPath(uri, platform = process.platform) {
|
|
@@ -172735,7 +173233,7 @@ var init_serve_shared = __esm({
|
|
|
172735
173233
|
|
|
172736
173234
|
// src/cli/version.ts
|
|
172737
173235
|
function getCliVersion() {
|
|
172738
|
-
return true ? "1.8.
|
|
173236
|
+
return true ? "1.8.3" : pkg.version;
|
|
172739
173237
|
}
|
|
172740
173238
|
var init_version3 = __esm({
|
|
172741
173239
|
"src/cli/version.ts"() {
|
|
@@ -172965,6 +173463,8 @@ var init_serve = __esm({
|
|
|
172965
173463
|
"use strict";
|
|
172966
173464
|
init_esm_shims();
|
|
172967
173465
|
init_tool_profile();
|
|
173466
|
+
init_mcp_discovery();
|
|
173467
|
+
init_stdio_startup_gate();
|
|
172968
173468
|
init_mcp_root_path();
|
|
172969
173469
|
serve_default = defineCommand({
|
|
172970
173470
|
meta: {
|
|
@@ -172989,15 +173489,25 @@ var init_serve = __esm({
|
|
|
172989
173489
|
}
|
|
172990
173490
|
},
|
|
172991
173491
|
run: async ({ args }) => {
|
|
173492
|
+
const startupGate = new StdioStartupGate({
|
|
173493
|
+
stdin: process.stdin,
|
|
173494
|
+
stdout: process.stdout,
|
|
173495
|
+
serverInfo: getMcpServerInfo(),
|
|
173496
|
+
onError: (error) => {
|
|
173497
|
+
console.error(`[memorix] stdio startup gate error: ${error.message}`);
|
|
173498
|
+
process.exit(1);
|
|
173499
|
+
},
|
|
173500
|
+
onEnd: () => {
|
|
173501
|
+
console.error("[memorix] stdin closed \u2014 exiting");
|
|
173502
|
+
process.exitCode = 0;
|
|
173503
|
+
}
|
|
173504
|
+
});
|
|
173505
|
+
startupGate.start();
|
|
172992
173506
|
const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
|
|
172993
173507
|
const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server2(), server_exports2));
|
|
172994
173508
|
const { detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
|
|
172995
173509
|
const { homedir: homedir27 } = await import("os");
|
|
172996
173510
|
const { resolveServeProject: resolveServeProject2 } = await Promise.resolve().then(() => (init_serve_shared(), serve_shared_exports));
|
|
172997
|
-
process.stdin.on("end", () => {
|
|
172998
|
-
console.error("[memorix] stdin closed \u2014 exiting");
|
|
172999
|
-
process.exit(0);
|
|
173000
|
-
});
|
|
173001
173511
|
let safeCwd;
|
|
173002
173512
|
try {
|
|
173003
173513
|
safeCwd = process.cwd();
|
|
@@ -173032,8 +173542,9 @@ var init_serve = __esm({
|
|
|
173032
173542
|
const toolProfile = resolveToolProfile({ explicit: args.mode, envValue: process.env.MEMORIX_MODE, fallback: "micro" });
|
|
173033
173543
|
const serverOptions = detected ? { toolProfile, deferProjectRuntimeInit: true } : { allowUntrackedFallback: allowUntracked, deferProjectInitUntilBound: !allowUntracked, deferProjectRuntimeInit: true, toolProfile };
|
|
173034
173544
|
const { server, projectId, deferredInit, switchProject } = await createMemorixServer2(projectRoot, void 0, void 0, serverOptions);
|
|
173035
|
-
const transport = new StdioServerTransport();
|
|
173545
|
+
const transport = new StdioServerTransport(startupGate.input, process.stdout);
|
|
173036
173546
|
await server.connect(transport);
|
|
173547
|
+
startupGate.markReady();
|
|
173037
173548
|
console.error(`[memorix] MCP Server running on stdio (project: ${projectId})`);
|
|
173038
173549
|
console.error(`[memorix] Project root: ${detected?.rootPath ?? projectRoot}`);
|
|
173039
173550
|
const tryRootsSwitch = async () => {
|