memorix 1.8.3 → 1.8.5
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 +53 -0
- package/CLAUDE.md +3 -0
- package/README.md +4 -4
- package/README.zh-CN.md +5 -3
- package/dist/cli/index.js +1544 -635
- package/dist/dashboard/static/app.js +29 -885
- package/dist/dashboard/static/index.html +1 -5
- package/dist/dashboard/static/style.css +36 -503
- package/dist/index.d.ts +4 -4
- package/dist/index.js +214 -73
- package/dist/memcode/index.js +28035 -169
- package/dist/memcode-runtime/CHANGELOG.md +53 -0
- package/dist/sdk.js +30 -14
- package/docs/1.8.0-RELEASE-CANDIDATE-SPEC.md +22 -16
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +2 -2
- package/docs/API_REFERENCE.md +10 -8
- package/docs/DASHBOARD.md +23 -0
- package/docs/DEVELOPMENT.md +2 -2
- package/docs/DOCKER.md +6 -3
- package/docs/INTEGRATIONS.md +1 -1
- package/docs/MODULES.md +46 -20
- package/docs/PERFORMANCE.md +1 -1
- package/docs/README.md +8 -7
- package/docs/SETUP.md +3 -3
- package/package.json +11 -11
- package/plugins/antigravity/memorix/plugin.json +1 -1
- package/plugins/antigravity/memorix/rules/memorix.md +5 -0
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/memorix/skills/memorix-memory/SKILL.md +3 -0
- package/plugins/claude/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
- package/plugins/claude/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/skills/memorix-memory/SKILL.md +3 -0
- package/plugins/codebuddy/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
- package/plugins/codebuddy/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/skills/memorix-memory/SKILL.md +3 -0
- package/plugins/codex/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
- package/plugins/codex/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/copilot/memorix/skills/memorix-memory/SKILL.md +3 -0
- package/plugins/copilot/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
- package/plugins/copilot/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
- package/plugins/cursor/memorix/skills/memorix-memory/SKILL.md +3 -0
- package/plugins/cursor/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
- package/plugins/cursor/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
- package/plugins/gemini/memorix/GEMINI.md +5 -0
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/hermes/memorix/plugin.yaml +7 -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/plugins/pi/memorix/skills/memorix-memory/SKILL.md +3 -0
- package/plugins/pi/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
- package/plugins/pi/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
- package/server.json +2 -2
- package/src/cli/command-guide.ts +52 -1
- package/src/cli/commands/background.ts +166 -6
- package/src/cli/commands/serve-http.ts +74 -86
- package/src/cli/commands/serve.ts +95 -93
- package/src/cli/index.ts +1 -1
- package/src/dashboard/static/index.html +1 -5
- package/src/dashboard/static/style.css +36 -503
- package/src/hooks/installers/index.ts +3 -0
- package/src/hooks/official-skills.ts +13 -6
- package/src/memory/graph.ts +2 -2
- package/src/server/mcp-diagnostics.ts +9 -7
- package/src/server/mcp-discovery.ts +0 -1
- package/src/server/modern-mcp-bridge.ts +108 -0
- package/src/server/stdio-startup-gate.ts +41 -2
- package/src/server/tool-profile.ts +7 -6
- package/src/server.ts +1 -1
- package/src/store/orama-store.ts +2 -2
- package/src/wiki/types.ts +2 -2
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* memorix serve
|
|
2
|
+
* memorix serve - Start MCP Server on stdio transport.
|
|
3
|
+
*
|
|
4
|
+
* The official MCP v2 stdio entry owns modern discovery, per-request metadata,
|
|
5
|
+
* legacy compatibility, and protocol lifecycle. Memorix keeps its startup
|
|
6
|
+
* gate in front of that entry so early claim-less discovery remains compatible
|
|
7
|
+
* with clients shipped before the 2026 protocol revision.
|
|
3
8
|
*/
|
|
4
9
|
|
|
5
10
|
import { defineCommand } from 'citty';
|
|
@@ -7,6 +12,7 @@ import { resolveToolProfile } from '../../server/tool-profile.js';
|
|
|
7
12
|
import { getMcpServerInfo } from '../../server/mcp-discovery.js';
|
|
8
13
|
import { StdioStartupGate } from '../../server/stdio-startup-gate.js';
|
|
9
14
|
import { mcpFileUriToPath } from '../mcp-root-path.js';
|
|
15
|
+
import type { ModernMcpBridge } from '../../server/modern-mcp-bridge.js';
|
|
10
16
|
|
|
11
17
|
export default defineCommand({
|
|
12
18
|
meta: {
|
|
@@ -31,40 +37,42 @@ export default defineCommand({
|
|
|
31
37
|
},
|
|
32
38
|
},
|
|
33
39
|
run: async ({ args }) => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
const { serveStdio, StdioServerTransport } = await import('@modelcontextprotocol/server/stdio');
|
|
41
|
+
const { createModernMcpBridge } = await import('../../server/modern-mcp-bridge.js');
|
|
42
|
+
const { detectProject, findGitInSubdirs, isSystemDirectory } = await import('../../project/detector.js');
|
|
43
|
+
const { homedir } = await import('node:os');
|
|
44
|
+
const { writeLastProjectRoot } = await import('../../project/launch-root.js');
|
|
45
|
+
const { resolveServeProject } = await import('./serve-shared.js');
|
|
46
|
+
|
|
47
|
+
// Take ownership of stdin before project/config/runtime initialization.
|
|
48
|
+
// The gate answers the old claim-less discover probe and queues every
|
|
49
|
+
// other line until the official v2 transport is listening.
|
|
50
|
+
let stdioHandle: { close: () => Promise<void> } | undefined;
|
|
51
|
+
let stdinEndedBeforeHandle = false;
|
|
37
52
|
const startupGate = new StdioStartupGate({
|
|
38
53
|
stdin: process.stdin,
|
|
39
54
|
stdout: process.stdout,
|
|
40
55
|
serverInfo: getMcpServerInfo(),
|
|
41
56
|
onError: (error) => {
|
|
42
57
|
console.error(`[memorix] stdio startup gate error: ${error.message}`);
|
|
43
|
-
// The stream is no longer safe to replay after an input-limit or I/O
|
|
44
|
-
// failure. Exit instead of leaving a half-connected MCP process alive.
|
|
45
58
|
process.exit(1);
|
|
46
59
|
},
|
|
47
60
|
onEnd: () => {
|
|
48
|
-
console.error('[memorix] stdin closed
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
61
|
+
console.error('[memorix] stdin closed - exiting');
|
|
62
|
+
if (stdioHandle) {
|
|
63
|
+
void stdioHandle.close().catch((error) => {
|
|
64
|
+
console.error(`[memorix] stdio close error: ${error instanceof Error ? error.message : String(error)}`);
|
|
65
|
+
});
|
|
66
|
+
} else {
|
|
67
|
+
stdinEndedBeforeHandle = true;
|
|
68
|
+
}
|
|
52
69
|
},
|
|
53
70
|
});
|
|
54
71
|
startupGate.start();
|
|
55
72
|
|
|
56
|
-
|
|
57
|
-
'@modelcontextprotocol/sdk/server/stdio.js'
|
|
58
|
-
);
|
|
59
|
-
const { createMemorixServer } = await import('../../server.js');
|
|
60
|
-
const { detectProject, findGitInSubdirs, isSystemDirectory } = await import('../../project/detector.js');
|
|
61
|
-
const { homedir } = await import('node:os');
|
|
62
|
-
const { resolveServeProject } = await import('./serve-shared.js');
|
|
63
|
-
|
|
64
|
-
// Priority: explicit --cwd arg > MEMORIX_PROJECT_ROOT env > INIT_CWD (npm lifecycle) > process.cwd()
|
|
73
|
+
// Priority: explicit --cwd arg > MEMORIX_PROJECT_ROOT > INIT_CWD > process.cwd().
|
|
65
74
|
let safeCwd: string;
|
|
66
75
|
try { safeCwd = process.cwd(); } catch { safeCwd = homedir(); }
|
|
67
|
-
|
|
68
76
|
const resolution = resolveServeProject(
|
|
69
77
|
{
|
|
70
78
|
cwdArg: args.cwd,
|
|
@@ -75,101 +83,95 @@ export default defineCommand({
|
|
|
75
83
|
},
|
|
76
84
|
{ detectProject, findGitInSubdirs, isSystemDirectory },
|
|
77
85
|
);
|
|
78
|
-
|
|
79
|
-
for (const message of resolution.messages) {
|
|
80
|
-
console.error(message);
|
|
81
|
-
}
|
|
86
|
+
for (const message of resolution.messages) console.error(message);
|
|
82
87
|
|
|
83
88
|
if (!resolution.detectedProject) {
|
|
84
89
|
console.error(`[memorix] [WARN] ${resolution.error}`);
|
|
85
|
-
console.error(
|
|
86
|
-
console.error(
|
|
87
|
-
// Don't exit — allow deferred binding via session_start or MCP roots (fixes Cursor stdio #75)
|
|
90
|
+
console.error('[memorix] Starting in deferred-binding mode - bind with memorix_session_start(projectRoot=...) when needed.');
|
|
91
|
+
console.error('[memorix] For non-git directories, use --allow-untracked to enable untracked/ fallback.');
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
const detected = resolution.detectedProject;
|
|
91
95
|
const projectRoot = resolution.projectRoot;
|
|
92
|
-
if (detected)
|
|
93
|
-
const { writeLastProjectRoot } = await import('../../project/launch-root.js');
|
|
94
|
-
writeLastProjectRoot(detected.rootPath);
|
|
95
|
-
}
|
|
96
|
+
if (detected) writeLastProjectRoot(detected.rootPath);
|
|
96
97
|
|
|
97
|
-
// Always register ALL tools BEFORE connecting transport.
|
|
98
|
-
// This ensures tools/list returns the full tool set immediately on connect.
|
|
99
|
-
// When no project detected, use deferred binding (allowUntrackedFallback=false, deferProjectInitUntilBound=true)
|
|
100
98
|
const allowUntracked = args['allow-untracked'] ?? false;
|
|
101
|
-
const toolProfile = resolveToolProfile({
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
:
|
|
105
|
-
|
|
106
|
-
const transport = new StdioServerTransport(startupGate.input, process.stdout);
|
|
107
|
-
await server.connect(transport);
|
|
108
|
-
startupGate.markReady();
|
|
109
|
-
|
|
110
|
-
console.error(`[memorix] MCP Server running on stdio (project: ${projectId})`);
|
|
111
|
-
console.error(`[memorix] Project root: ${detected?.rootPath ?? projectRoot}`);
|
|
99
|
+
const toolProfile = resolveToolProfile({
|
|
100
|
+
explicit: args.mode,
|
|
101
|
+
envValue: process.env.MEMORIX_MODE,
|
|
102
|
+
fallback: 'micro',
|
|
103
|
+
});
|
|
112
104
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
105
|
+
const transport = new StdioServerTransport(startupGate.input, process.stdout);
|
|
106
|
+
const createBridge = async (): Promise<ModernMcpBridge> => {
|
|
107
|
+
const bridge = await createModernMcpBridge({
|
|
108
|
+
projectRoot,
|
|
109
|
+
allowUntrackedFallback: allowUntracked,
|
|
110
|
+
deferProjectInitUntilBound: !allowUntracked,
|
|
111
|
+
deferProjectRuntimeInit: true,
|
|
112
|
+
toolProfile,
|
|
113
|
+
});
|
|
121
114
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
115
|
+
const tryRootsSwitch = async (): Promise<void> => {
|
|
116
|
+
try {
|
|
117
|
+
if (bridge.memorix.isExplicitlyBound()) return;
|
|
118
|
+
const { roots } = await bridge.server.listRoots();
|
|
119
|
+
for (const root of roots ?? []) {
|
|
120
|
+
if (!root.uri.startsWith('file://')) continue;
|
|
121
|
+
const rootPath = mcpFileUriToPath(root.uri);
|
|
122
|
+
if (!rootPath) continue;
|
|
126
123
|
|
|
127
|
-
|
|
128
|
-
if (rootDetected) {
|
|
129
|
-
const switched = await switchProject(rootPath);
|
|
124
|
+
const switched = await bridge.memorix.switchProject(rootPath, 'mcp-roots');
|
|
130
125
|
if (switched) {
|
|
131
|
-
console.error(`[memorix] [UPDATED] Project updated via MCP roots: ${
|
|
126
|
+
console.error(`[memorix] [UPDATED] Project updated via MCP roots: ${rootPath}`);
|
|
127
|
+
return;
|
|
132
128
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
// Root itself has no .git — try its subdirs
|
|
136
|
-
const subGit = findGitInSubdirs(rootPath);
|
|
137
|
-
if (subGit) {
|
|
138
|
-
const switched = await switchProject(subGit);
|
|
139
|
-
if (switched) {
|
|
129
|
+
const subGit = findGitInSubdirs(rootPath);
|
|
130
|
+
if (subGit && await bridge.memorix.switchProject(subGit, 'mcp-roots')) {
|
|
140
131
|
console.error(`[memorix] [UPDATED] Project updated via MCP roots (subdir): ${subGit}`);
|
|
132
|
+
return;
|
|
141
133
|
}
|
|
142
|
-
return;
|
|
143
134
|
}
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error(`[memorix] MCP roots not available (${error instanceof Error ? error.message : 'unsupported'})`);
|
|
144
137
|
}
|
|
145
|
-
}
|
|
146
|
-
// Client doesn't support roots — that's OK, fall back to existing detection
|
|
147
|
-
console.error(`[memorix] MCP roots not available (${(err as Error).message ?? 'unsupported'})`);
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
// Do NOT proactively call listRoots() after connect — this violates MCP SEP-2260
|
|
152
|
-
// which requires server-initiated requests to be associated with a client request.
|
|
153
|
-
// Some clients (e.g. Codex) treat standalone roots/list as unexpected and may
|
|
154
|
-
// fail to inject MCP tools. Instead, rely on:
|
|
155
|
-
// 1. RootsListChangedNotification (client-initiated, then we respond)
|
|
156
|
-
// 2. memorix_session_start({ projectRoot }) for explicit binding
|
|
157
|
-
// 3. cwd-based detection as fallback (already done in deferred-binding)
|
|
138
|
+
};
|
|
158
139
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
server.server.setNotificationHandler(RootsListChangedNotificationSchema, async () => {
|
|
163
|
-
console.error(`[memorix] Roots changed — re-detecting project...`);
|
|
140
|
+
// roots/list is a legacy-era request. The v2 SDK rejects it on the
|
|
141
|
+
// modern era, while retaining this handler keeps existing IDE clients.
|
|
142
|
+
bridge.server.setNotificationHandler('notifications/roots/list_changed', async () => {
|
|
164
143
|
await tryRootsSwitch();
|
|
165
144
|
});
|
|
166
|
-
} catch { /* notification handler setup is optional */ }
|
|
167
145
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
146
|
+
const deferredInitTimer = setTimeout(() => {
|
|
147
|
+
bridge.memorix.deferredInit().catch((error) => {
|
|
148
|
+
console.error(`[memorix] Deferred init error: ${error instanceof Error ? error.message : String(error)}`);
|
|
149
|
+
});
|
|
150
|
+
}, 5_000);
|
|
151
|
+
deferredInitTimer.unref?.();
|
|
152
|
+
|
|
153
|
+
const originalClose = bridge.close.bind(bridge);
|
|
154
|
+
bridge.close = async () => {
|
|
155
|
+
clearTimeout(deferredInitTimer);
|
|
156
|
+
await originalClose();
|
|
157
|
+
};
|
|
158
|
+
return bridge;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
stdioHandle = serveStdio(createBridge, {
|
|
162
|
+
transport,
|
|
163
|
+
legacy: 'serve',
|
|
164
|
+
onerror: (error) => console.error(`[memorix] stdio MCP error: ${error.message}`),
|
|
165
|
+
});
|
|
166
|
+
startupGate.markReady();
|
|
167
|
+
if (stdinEndedBeforeHandle) {
|
|
168
|
+
void stdioHandle.close().catch((error) => {
|
|
169
|
+
console.error(`[memorix] stdio close error: ${error instanceof Error ? error.message : String(error)}`);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
console.error(`[memorix] MCP Server running on stdio (profile: ${toolProfile}, project: ${detected?.id ?? 'deferred'})`);
|
|
174
|
+
console.error(`[memorix] Project root: ${detected?.rootPath ?? projectRoot}`);
|
|
173
175
|
import('../update-checker.js').then(m => m.checkForUpdates()).catch(() => {});
|
|
174
176
|
},
|
|
175
177
|
});
|
package/src/cli/index.ts
CHANGED
|
@@ -389,7 +389,7 @@ const main = defineCommand({
|
|
|
389
389
|
console.error(' integrate Install one IDE integration into the current repo');
|
|
390
390
|
console.error(' status Show project info + stats');
|
|
391
391
|
console.error(' dashboard Open standalone dashboard (read-mostly)');
|
|
392
|
-
console.error(' hooks
|
|
392
|
+
console.error(' hooks Install, inspect, or remove agent hooks');
|
|
393
393
|
console.error(' cleanup Remove old memories');
|
|
394
394
|
console.error(' purge Retire all memories (project by default, --all for everything)');
|
|
395
395
|
console.error(' sync Rules/workspace sync plus interactive wizard');
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
<path d="M23 21v-2a4 4 0 0 0-3-3.87"/>
|
|
143
143
|
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
|
|
144
144
|
</svg>
|
|
145
|
-
<span class="nav-label">
|
|
145
|
+
<span class="nav-label">Coordination</span>
|
|
146
146
|
</button>
|
|
147
147
|
</div>
|
|
148
148
|
<div class="sidebar-spacer"></div>
|
|
@@ -211,10 +211,6 @@
|
|
|
211
211
|
|
|
212
212
|
<!-- Apache ECharts 5 — Knowledge Graph renderer -->
|
|
213
213
|
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js"></script>
|
|
214
|
-
<!-- Cytoscape.js + Dagre — legacy entity-graph fallback -->
|
|
215
|
-
<script src="https://unpkg.com/cytoscape@3.30.4/dist/cytoscape.min.js"></script>
|
|
216
|
-
<script src="https://unpkg.com/dagre@0.8.5/dist/dagre.min.js"></script>
|
|
217
|
-
<script src="https://unpkg.com/cytoscape-dagre@2.5.0/cytoscape-dagre.js"></script>
|
|
218
214
|
<script>
|
|
219
215
|
// Cache-bust app.js by appending mtime-based version so edits always hit the browser.
|
|
220
216
|
(function () {
|