memorix 1.8.0 → 1.8.2
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 +29 -0
- package/dist/cli/index.js +407 -130
- package/dist/dashboard/static/app.js +37 -23
- package/dist/dashboard/static/index.html +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +633 -391
- 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 +29 -0
- package/dist/sdk.js +625 -390
- 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 +10 -8
- package/docs/API_REFERENCE.md +12 -8
- package/docs/ARCHITECTURE.md +3 -1
- package/docs/CONFIGURATION.md +2 -2
- package/docs/DASHBOARD.md +6 -0
- package/docs/DEVELOPMENT.md +2 -2
- package/docs/README.md +14 -8
- package/package.json +1 -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/dashboard.ts +1 -1
- package/src/cli/commands/serve-http.ts +38 -3
- 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/dashboard/server.ts +85 -86
- package/src/dashboard/static/index.html +1 -1
- package/src/llm/provider.ts +17 -4
- package/src/server/mcp-compat.ts +82 -0
- package/src/server/mcp-diagnostics.ts +13 -4
- package/src/server.ts +9 -6
|
@@ -104,8 +104,10 @@ function loadEnvFile(filePath) {
|
|
|
104
104
|
loadedEnvFiles.push(filePath);
|
|
105
105
|
}
|
|
106
106
|
function loadDotenv(projectRoot, options = {}) {
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
const userHomeDir = options.userHomeDir ?? homedir();
|
|
108
|
+
const normalizedProjectRoot = projectRoot ?? null;
|
|
109
|
+
if (dotenvLoaded && dotenvProjectRoot === normalizedProjectRoot && dotenvHomeDir === userHomeDir) return;
|
|
110
|
+
if (dotenvLoaded && (dotenvProjectRoot !== normalizedProjectRoot || dotenvHomeDir !== userHomeDir)) {
|
|
109
111
|
resetDotenv();
|
|
110
112
|
}
|
|
111
113
|
loadedEnvFiles.length = 0;
|
|
@@ -114,9 +116,10 @@ function loadDotenv(projectRoot, options = {}) {
|
|
|
114
116
|
if (projectRoot) {
|
|
115
117
|
loadEnvFile(getProjectDotenvPath(projectRoot));
|
|
116
118
|
}
|
|
117
|
-
loadEnvFile(getGlobalDotenvPath(
|
|
119
|
+
loadEnvFile(getGlobalDotenvPath(userHomeDir));
|
|
118
120
|
dotenvLoaded = true;
|
|
119
|
-
dotenvProjectRoot =
|
|
121
|
+
dotenvProjectRoot = normalizedProjectRoot;
|
|
122
|
+
dotenvHomeDir = userHomeDir;
|
|
120
123
|
}
|
|
121
124
|
function resetDotenv() {
|
|
122
125
|
for (const key of injectedKeys) {
|
|
@@ -125,13 +128,14 @@ function resetDotenv() {
|
|
|
125
128
|
injectedKeys.clear();
|
|
126
129
|
dotenvLoaded = false;
|
|
127
130
|
dotenvProjectRoot = null;
|
|
131
|
+
dotenvHomeDir = null;
|
|
128
132
|
loadedEnvFiles.length = 0;
|
|
129
133
|
loadedEnvKeys.clear();
|
|
130
134
|
}
|
|
131
135
|
function getLoadedEnvFiles() {
|
|
132
136
|
return loadedEnvFiles;
|
|
133
137
|
}
|
|
134
|
-
var dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, loadedEnvKeys, loadedEnvValues, injectedKeys;
|
|
138
|
+
var dotenvLoaded, dotenvProjectRoot, dotenvHomeDir, loadedEnvFiles, loadedEnvKeys, loadedEnvValues, injectedKeys;
|
|
135
139
|
var init_dotenv_loader = __esm({
|
|
136
140
|
"src/config/dotenv-loader.ts"() {
|
|
137
141
|
"use strict";
|
|
@@ -139,6 +143,7 @@ var init_dotenv_loader = __esm({
|
|
|
139
143
|
init_config_paths();
|
|
140
144
|
dotenvLoaded = false;
|
|
141
145
|
dotenvProjectRoot = null;
|
|
146
|
+
dotenvHomeDir = null;
|
|
142
147
|
loadedEnvFiles = [];
|
|
143
148
|
loadedEnvKeys = /* @__PURE__ */ new Set();
|
|
144
149
|
loadedEnvValues = /* @__PURE__ */ new Map();
|
|
@@ -2372,33 +2377,33 @@ __export(config_exports, {
|
|
|
2372
2377
|
resetConfigCache: () => resetConfigCache,
|
|
2373
2378
|
resetDotenv: () => resetDotenv
|
|
2374
2379
|
});
|
|
2375
|
-
function getLLMApiKey() {
|
|
2376
|
-
return getResolvedMemoryLane().llm.apiKey;
|
|
2380
|
+
function getLLMApiKey(options = {}) {
|
|
2381
|
+
return getResolvedMemoryLane(options).llm.apiKey;
|
|
2377
2382
|
}
|
|
2378
|
-
function getLLMProvider() {
|
|
2379
|
-
const provider2 = getResolvedMemoryLane().llm.provider;
|
|
2383
|
+
function getLLMProvider(options = {}) {
|
|
2384
|
+
const provider2 = getResolvedMemoryLane(options).llm.provider;
|
|
2380
2385
|
if (provider2) return provider2;
|
|
2381
2386
|
if (process.env.ANTHROPIC_API_KEY && !process.env.OPENAI_API_KEY) return "anthropic";
|
|
2382
2387
|
if (process.env.OPENROUTER_API_KEY && !process.env.OPENAI_API_KEY) return "openrouter";
|
|
2383
2388
|
return "openai";
|
|
2384
2389
|
}
|
|
2385
|
-
function getLLMModel(providerDefault) {
|
|
2386
|
-
return getResolvedMemoryLane().llm.model || providerDefault;
|
|
2390
|
+
function getLLMModel(providerDefault, options = {}) {
|
|
2391
|
+
return getResolvedMemoryLane(options).llm.model || providerDefault;
|
|
2387
2392
|
}
|
|
2388
|
-
function getLLMBaseUrl(providerDefault) {
|
|
2389
|
-
return getResolvedMemoryLane().llm.baseUrl || providerDefault;
|
|
2393
|
+
function getLLMBaseUrl(providerDefault, options = {}) {
|
|
2394
|
+
return getResolvedMemoryLane(options).llm.baseUrl || providerDefault;
|
|
2390
2395
|
}
|
|
2391
|
-
function getAgentLLMApiKey() {
|
|
2392
|
-
return getResolvedAgentLane().apiKey;
|
|
2396
|
+
function getAgentLLMApiKey(options = {}) {
|
|
2397
|
+
return getResolvedAgentLane(options).apiKey;
|
|
2393
2398
|
}
|
|
2394
|
-
function getAgentLLMProvider() {
|
|
2395
|
-
return getResolvedAgentLane().provider || getLLMProvider();
|
|
2399
|
+
function getAgentLLMProvider(options = {}) {
|
|
2400
|
+
return getResolvedAgentLane(options).provider || getLLMProvider(options);
|
|
2396
2401
|
}
|
|
2397
|
-
function getAgentLLMModel(providerDefault) {
|
|
2398
|
-
return getResolvedAgentLane().model || getLLMModel(providerDefault);
|
|
2402
|
+
function getAgentLLMModel(providerDefault, options = {}) {
|
|
2403
|
+
return getResolvedAgentLane(options).model || getLLMModel(providerDefault, options);
|
|
2399
2404
|
}
|
|
2400
|
-
function getAgentLLMBaseUrl(providerDefault) {
|
|
2401
|
-
return getResolvedAgentLane().baseUrl || getLLMBaseUrl(providerDefault);
|
|
2405
|
+
function getAgentLLMBaseUrl(providerDefault, options = {}) {
|
|
2406
|
+
return getResolvedAgentLane(options).baseUrl || getLLMBaseUrl(providerDefault, options);
|
|
2402
2407
|
}
|
|
2403
2408
|
function getEmbeddingMode() {
|
|
2404
2409
|
const provider2 = getResolvedEmbeddingLane().provider?.toLowerCase()?.trim();
|
|
@@ -4657,18 +4662,19 @@ async function* callLLMWithToolsStream(messages, tools) {
|
|
|
4657
4662
|
}
|
|
4658
4663
|
function initLLM(options = {}) {
|
|
4659
4664
|
const scope = options.scope ?? "memory";
|
|
4660
|
-
const
|
|
4665
|
+
const configOptions = { projectRoot: options.projectRoot, homeDir: options.homeDir };
|
|
4666
|
+
const apiKey = scope === "agent" ? getAgentLLMApiKey(configOptions) : getLLMApiKey(configOptions);
|
|
4661
4667
|
if (!apiKey) {
|
|
4662
4668
|
currentConfig = null;
|
|
4663
4669
|
return null;
|
|
4664
4670
|
}
|
|
4665
|
-
const provider2 = scope === "agent" ? getAgentLLMProvider() : getLLMProvider();
|
|
4671
|
+
const provider2 = scope === "agent" ? getAgentLLMProvider(configOptions) : getLLMProvider(configOptions);
|
|
4666
4672
|
const defaults2 = PROVIDER_DEFAULTS[provider2] ?? PROVIDER_DEFAULTS.openai;
|
|
4667
4673
|
currentConfig = {
|
|
4668
4674
|
provider: provider2,
|
|
4669
4675
|
apiKey,
|
|
4670
|
-
model: scope === "agent" ? getAgentLLMModel(defaults2.model) : getLLMModel(defaults2.model),
|
|
4671
|
-
baseUrl: scope === "agent" ? getAgentLLMBaseUrl(defaults2.baseUrl) : getLLMBaseUrl(defaults2.baseUrl)
|
|
4676
|
+
model: scope === "agent" ? getAgentLLMModel(defaults2.model, configOptions) : getLLMModel(defaults2.model, configOptions),
|
|
4677
|
+
baseUrl: scope === "agent" ? getAgentLLMBaseUrl(defaults2.baseUrl, configOptions) : getLLMBaseUrl(defaults2.baseUrl, configOptions)
|
|
4672
4678
|
};
|
|
4673
4679
|
return currentConfig;
|
|
4674
4680
|
}
|
|
@@ -58,8 +58,9 @@ Memorix only considers the external provider when all of these are true:
|
|
|
58
58
|
root;
|
|
59
59
|
4. the index has no reported pending changes or worktree mismatch;
|
|
60
60
|
5. the bounded command completes before its configured timeout; and
|
|
61
|
-
6. the returned JSON
|
|
62
|
-
|
|
61
|
+
6. the returned context JSON, or the official v1.5.0 `explore` output after a
|
|
62
|
+
context-command failure, passes Memorix's schema, path, relation, count,
|
|
63
|
+
and output-size validation.
|
|
63
64
|
|
|
64
65
|
Memorix never runs `codegraph init`, `index`, or `sync` on the user's behalf.
|
|
65
66
|
It does not transmit the repository to a remote service. Its default request is
|
|
@@ -90,7 +91,7 @@ external_context = "auto"
|
|
|
90
91
|
# external_command = "C:\\tools\\codegraph.cmd"
|
|
91
92
|
|
|
92
93
|
# A bounded local query. Values outside the safe range are clamped.
|
|
93
|
-
external_timeout_ms =
|
|
94
|
+
external_timeout_ms = 3000
|
|
94
95
|
~~~
|
|
95
96
|
|
|
96
97
|
The equivalent YAML keys are `externalContext`, `externalCommand`, and
|
|
@@ -114,12 +115,19 @@ The status is visible through `memorix codegraph status --json`, `memorix
|
|
|
114
115
|
doctor --json`, and Project Context JSON. Prompt output keeps it compact: it
|
|
115
116
|
adds semantic start points only when a valid external outline is available, and
|
|
116
117
|
adds one caution when a requested external outline was not safe to use.
|
|
118
|
+
An external status of `ready` means only that the index is initialized and
|
|
119
|
+
current; it does not prove that the installed CLI exposes `context`. The task
|
|
120
|
+
diagnostics therefore record `context` and `explore` independently.
|
|
117
121
|
|
|
118
122
|
## Validation and Fallback
|
|
119
123
|
|
|
120
124
|
The external adapter executes without a shell, pins the working directory to
|
|
121
|
-
the actual project root, uses a bounded timeout and stdout limit, and
|
|
122
|
-
|
|
125
|
+
the actual project root, uses a bounded timeout and stdout limit, and tries
|
|
126
|
+
`context` first. CodeGraph v1.5.0 does not register that command, so a failed
|
|
127
|
+
or invalid context result triggers the official `explore --path <root>
|
|
128
|
+
--max-files 4 <task>` command. JSON context output and the stable explore
|
|
129
|
+
outline/relationship markers are accepted only after the same strict path and
|
|
130
|
+
relation validation. It rejects a result when:
|
|
123
131
|
|
|
124
132
|
- the status belongs to another project root;
|
|
125
133
|
- the index is uninitialized, has pending changes, or reports a worktree
|
|
@@ -145,7 +153,8 @@ runner. It verifies:
|
|
|
145
153
|
3. Stale, mismatched, malformed, timed-out, and oversized external output
|
|
146
154
|
safely falls back to Lite.
|
|
147
155
|
4. Raw code blocks and credentials do not enter the default Workset.
|
|
148
|
-
5. `codegraph status` and `doctor` identify the active/fallback provider
|
|
156
|
+
5. `codegraph status` and `doctor` identify the active/fallback provider, and
|
|
157
|
+
distinguish a healthy index from a usable task-query command.
|
|
149
158
|
|
|
150
159
|
The optional real smoke can be run on a Windows project that already has an
|
|
151
160
|
indexed CodeGraph installation:
|
|
@@ -158,15 +158,16 @@ layer, not Memorix product identity.
|
|
|
158
158
|
- Product operations receive a resolved project/workspace binding and explicit
|
|
159
159
|
actor metadata; they do not read an HTTP session map directly.
|
|
160
160
|
- The old `Mcp-Session-Id` map remains isolated in `serve-http` as a legacy
|
|
161
|
-
adapter
|
|
162
|
-
2026-07-28
|
|
161
|
+
adapter. A low-level `server/discover` adapter now covers the required
|
|
162
|
+
2026-07-28 discovery result without upgrading the pinned v1 SDK.
|
|
163
163
|
- Asset IDs, media job IDs, project IDs, and attachment targets are explicit
|
|
164
164
|
durable identifiers. They are never inferred from a live MCP connection.
|
|
165
165
|
- New media tools work through stdio, legacy streamable HTTP, and direct CLI
|
|
166
166
|
invocation with identical project binding behavior.
|
|
167
|
-
- No release depends on
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
- No release depends on the MCP TypeScript SDK v2. The current server remains
|
|
168
|
+
compatible with existing legacy clients and supports versionless list/call
|
|
169
|
+
through the v1 SDK's legacy envelopes. The adapter does not claim modern
|
|
170
|
+
result caching, Tasks, subscriptions, or complete 2026 conformance.
|
|
170
171
|
|
|
171
172
|
## Non-goals
|
|
172
173
|
|
|
@@ -177,7 +178,7 @@ layer, not Memorix product identity.
|
|
|
177
178
|
- No automatic audio/video transcription, frame extraction, or arbitrary media
|
|
178
179
|
understanding in 1.3.3. The asset model makes those future derivations safe.
|
|
179
180
|
- No forced migration to a protocol version that the published MCP TypeScript
|
|
180
|
-
SDK does not yet support.
|
|
181
|
+
SDK does not yet support; discovery is a narrow compatibility adapter.
|
|
181
182
|
- No additional swarm of low-level MCP tools; CLI is the complete management
|
|
182
183
|
surface and MCP exposes only small agent-facing operations.
|
|
183
184
|
|
|
@@ -17,14 +17,16 @@ Status: accepted implementation contract for Memorix 1.8.0.
|
|
|
17
17
|
|
|
18
18
|
## Compatibility Contract
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
Memorix preserves the legacy 2025-era initialize contract, including stdio and
|
|
21
|
+
stateful Streamable HTTP with `Mcp-Session-Id`. Memorix 1.8.2 also registers a
|
|
22
|
+
low-level `server/discover` compatibility adapter for the 2026-07-28 request.
|
|
23
|
+
Its `DiscoverResult` is complete for the required identity, versions,
|
|
24
|
+
capabilities, and private zero-TTL cache hint. Versionless `tools/list` and
|
|
25
|
+
`tools/call` are accepted by the pinned v1 SDK and retain its legacy result
|
|
26
|
+
envelopes. HTTP stateless project handles remain a compatibility adapter: they
|
|
27
|
+
own project routing, but do not turn the v1 SDK into a complete 2026 runtime.
|
|
28
|
+
Tasks, subscriptions, and list-response caching are unsupported and are not
|
|
29
|
+
advertised or simulated.
|
|
28
30
|
|
|
29
31
|
Antigravity is the primary setup target. Gemini CLI remains a compatibility and
|
|
30
32
|
migration path. GitHub issue #204 (WorkBuddy) is intentionally not merged or
|
package/docs/API_REFERENCE.md
CHANGED
|
@@ -150,14 +150,16 @@ feedback projection.
|
|
|
150
150
|
### HTTP MCP Compatibility
|
|
151
151
|
|
|
152
152
|
Legacy clients use stateful Streamable HTTP with `Mcp-Session-Id`. Current
|
|
153
|
-
|
|
154
|
-
`Mcp-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
153
|
+
Legacy clients use the 2025-era `initialize` handshake and stateful
|
|
154
|
+
`Mcp-Session-Id`. The stdio server also accepts the 2026-07-28
|
|
155
|
+
`server/discover` request before `initialize` and returns the required
|
|
156
|
+
`DiscoverResult`. Versionless `tools/list` and `tools/call` use the pinned
|
|
157
|
+
SDK's legacy result envelopes. HTTP stateless clients may use a durable
|
|
158
|
+
`Mcp-Project-Handle`; `/protocol-diagnostics` labels this as compatibility-only.
|
|
159
|
+
Modern result metadata is discovery-only with a private zero-TTL hint. Tasks,
|
|
160
|
+
subscriptions, and list-response caching are unsupported. When MCP discovery
|
|
161
|
+
is unavailable, use one bounded `memorix context --fallback` request for a
|
|
162
|
+
task; repeated fallback probing is rejected by the local budget.
|
|
161
163
|
|
|
162
164
|
The built-in Lite provider indexes common code files with lightweight file, symbol, and import facts. It is a structural fallback, not a language-server-quality graph. When a project already has a healthy local CodeGraph index, `[codegraph].external_context = "auto"` may add a validated, bounded semantic outline to the Workset. Memorix never initializes, syncs, or exports that external index, and never stores its raw source output. `memorix codegraph status --json`, `memorix doctor --json`, and Project Context JSON identify the actual provider quality.
|
|
163
165
|
|
|
@@ -864,6 +866,8 @@ Important inputs:
|
|
|
864
866
|
|
|
865
867
|
When using HTTP mode, the main dashboard is usually served from the same port as `serve-http`.
|
|
866
868
|
|
|
869
|
+
The Dashboard's Coordination Status page is read-only. It reads the selected project's agents, tasks, locks, handoffs, messages, and poll state from the persistent SQLite `TeamStore`; it does not expose team/task write endpoints or replace task execution and orchestration tools. A coordination read failure is returned as an explicit degraded/error response rather than an empty healthy snapshot.
|
|
870
|
+
|
|
867
871
|
---
|
|
868
872
|
|
|
869
873
|
## 12. Optional Graph Compatibility Tools
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -498,7 +498,9 @@ It provides an operational view for:
|
|
|
498
498
|
- sessions
|
|
499
499
|
- retention state
|
|
500
500
|
- preview-first cleanup, consolidation, intelligent deduplication, and retention archival
|
|
501
|
-
- read-only
|
|
501
|
+
- read-only Coordination Status derived from the project-scoped SQLite `TeamStore`; the page is a projection, not a task execution surface
|
|
502
|
+
|
|
503
|
+
`TeamStore` is the real persistent coordination layer for agents, tasks, messages, locks, handoffs, and poll state. Dashboard coordination reads use that same SQLite state and return an explicit degraded/error status when it cannot be read; they must not substitute a normal-looking empty snapshot.
|
|
502
504
|
|
|
503
505
|
Dashboard maintenance is not a separate business-logic implementation. CLI, MCP, background jobs, and Dashboard routes share the same cleanup, consolidation, deduplication, and retention functions. Mutation routes issue a project-bound signed preview token and reject execution when the candidate set changed after preview.
|
|
504
506
|
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -74,7 +74,7 @@ max_file_bytes = 2097152
|
|
|
74
74
|
# Optional: use an already-indexed local CodeGraph only when it is healthy.
|
|
75
75
|
external_context = "auto"
|
|
76
76
|
# external_command = "C:\\tools\\codegraph.cmd"
|
|
77
|
-
external_timeout_ms =
|
|
77
|
+
external_timeout_ms = 3000
|
|
78
78
|
|
|
79
79
|
[server]
|
|
80
80
|
transport = "stdio"
|
|
@@ -334,7 +334,7 @@ Common keys:
|
|
|
334
334
|
- `max_file_bytes = 2097152` (2 MiB per source file by default)
|
|
335
335
|
- `external_context = "auto"` (`"off"` keeps the built-in Lite provider only)
|
|
336
336
|
- `external_command = "C:\\tools\\codegraph.cmd"` (optional path when CodeGraph is not on `PATH`)
|
|
337
|
-
- `external_timeout_ms =
|
|
337
|
+
- `external_timeout_ms = 3000` (bounded local semantic-query timeout; values are clamped to 5 seconds)
|
|
338
338
|
|
|
339
339
|
Legacy YAML uses `codegraph.excludePatterns`, `codegraph.maxFileBytes`,
|
|
340
340
|
`codegraph.externalContext`, `codegraph.externalCommand`, and
|
package/docs/DASHBOARD.md
CHANGED
|
@@ -19,6 +19,12 @@ memorix dashboard
|
|
|
19
19
|
|
|
20
20
|
Both modes read the same project-scoped stores. The project switcher changes the active project filter; it does not merge projects or grant access to personal memories.
|
|
21
21
|
|
|
22
|
+
## Coordination Status
|
|
23
|
+
|
|
24
|
+
The Coordination Status page is a read-only projection of the selected project's persistent coordination state. `TeamStore` is the canonical SQLite layer for agents, tasks, messages, locks, handoffs, and poll state; the Dashboard does not keep a second in-memory coordination registry.
|
|
25
|
+
|
|
26
|
+
The page reports agents, task status, file locks, and handoffs for the selected project. It exposes no team or task write endpoints and is not a task execution or full orchestration platform. If the SQLite read fails, the API returns an explicit degraded/error status and the page shows that the status is unavailable instead of presenting an empty result as healthy.
|
|
27
|
+
|
|
22
28
|
## Maintenance Workbench
|
|
23
29
|
|
|
24
30
|
The Observations page exposes three explicit maintenance actions:
|
package/docs/DEVELOPMENT.md
CHANGED
|
@@ -13,8 +13,8 @@ Memorix is a TypeScript project built around:
|
|
|
13
13
|
|
|
14
14
|
## Current Development Baseline
|
|
15
15
|
|
|
16
|
-
The current release work targets the **1.8.
|
|
17
|
-
is kept at `1.8.
|
|
16
|
+
The current release work targets the **1.8.2 release line** and package metadata
|
|
17
|
+
is kept at `1.8.2` for this release commit.
|
|
18
18
|
|
|
19
19
|
Contributors should assume the following areas are part of the current release line:
|
|
20
20
|
|
package/docs/README.md
CHANGED
|
@@ -33,7 +33,7 @@ The public docs are organized by user intent:
|
|
|
33
33
|
| CLI commands and MCP tools | [API_REFERENCE.md](API_REFERENCE.md) |
|
|
34
34
|
| Memory Autopilot, Code State, and context packs | [API_REFERENCE.md § Memory Autopilot, Code State, and Context Packs](API_REFERENCE.md#memory-autopilot-code-state-and-context-packs), [1.2 Code State](1.2.0-CODE-STATE.md), and [1.2 Workset Retrieval](1.2.0-WORKSET-RETRIEVAL.md) |
|
|
35
35
|
| Reviewed episodic, semantic, and procedural long-term memory | [1.3 Memory Architecture](1.3-MEMORY-ARCHITECTURE.md) |
|
|
36
|
-
| Browse memory and
|
|
36
|
+
| Browse memory, maintenance, and read-only Coordination Status | [Dashboard](DASHBOARD.md) |
|
|
37
37
|
| Reviewable knowledge pages and workflow inheritance | [API_REFERENCE.md § Knowledge Workspace and Workflows](API_REFERENCE.md#knowledge-workspace-and-workflows), [1.2 Knowledge Workspace](1.2.0-KNOWLEDGE-WORKSPACE.md), and [1.2 Workflow Inheritance](1.2.0-WORKFLOW-INHERITANCE.md) |
|
|
38
38
|
| Git-derived engineering memory | [GIT_MEMORY.md](GIT_MEMORY.md) |
|
|
39
39
|
| Memory formation and quality pipeline | [MEMORY_FORMATION_PIPELINE.md](MEMORY_FORMATION_PIPELINE.md) |
|
|
@@ -63,6 +63,7 @@ The public docs are organized by user intent:
|
|
|
63
63
|
| Topic | Document |
|
|
64
64
|
| --- | --- |
|
|
65
65
|
| MCP / CLI commands | [API_REFERENCE.md](API_REFERENCE.md) |
|
|
66
|
+
| MCP protocol discovery and compatibility boundaries | [API_REFERENCE.md](API_REFERENCE.md), [1.3.3 MCP Compatibility](1.3.3-MULTIMODAL-MEDIA-AND-MCP-COMPAT.md), and [1.8.0 Release Specification](1.8.0-RELEASE-CANDIDATE-SPEC.md) |
|
|
66
67
|
| Plugin, rules, hooks, skills, and MCP support matrix | [INTEGRATIONS.md](INTEGRATIONS.md) |
|
|
67
68
|
| TypeScript SDK | [../README.md#sdk](../README.md#sdk) |
|
|
68
69
|
| Workspace and rules sync | [API_REFERENCE.md § Workspace and Rules](API_REFERENCE.md#8-workspace-and-rules-tools) |
|
|
@@ -93,7 +94,7 @@ The public docs are organized by user intent:
|
|
|
93
94
|
| 1.2 honest Lite and optional semantic CodeGraph provider contract | [1.2 Provider Quality](1.2.0-PROVIDER-QUALITY.md) |
|
|
94
95
|
| 1.3 long-term memory model, source boundary, and lifecycle | [1.3 Memory Architecture](1.3-MEMORY-ARCHITECTURE.md) |
|
|
95
96
|
| Active context-control work | [1.2.2 Memory Control Plane](1.2.2-MEMORY-CONTROL-PLANE.md) |
|
|
96
|
-
| 1.8 context-control acceptance contract | [1.8.0 Release Specification](1.8.0-RELEASE-CANDIDATE-SPEC.md) |
|
|
97
|
+
| 1.8.2 context-control and compatibility acceptance contract | [1.8.0 Release Specification](1.8.0-RELEASE-CANDIDATE-SPEC.md) |
|
|
97
98
|
| Historical cloud sync and multi-agent research | [CLOUD_SYNC_AND_MULTI_AGENT_RESEARCH.md](CLOUD_SYNC_AND_MULTI_AGENT_RESEARCH.md) |
|
|
98
99
|
| Known issues and old roadmap notes | [KNOWN_ISSUES_AND_ROADMAP.md](KNOWN_ISSUES_AND_ROADMAP.md) |
|
|
99
100
|
|
|
@@ -121,7 +122,7 @@ Historical/deep-reference documents may describe older designs. If they conflict
|
|
|
121
122
|
|
|
122
123
|
## Current Product Line
|
|
123
124
|
|
|
124
|
-
The current product line is **1.8.
|
|
125
|
+
The current product line is **1.8.2**. The authoritative acceptance contract is
|
|
125
126
|
[1.8.0 Release Specification](1.8.0-RELEASE-CANDIDATE-SPEC.md).
|
|
126
127
|
The current baseline has:
|
|
127
128
|
|
|
@@ -130,6 +131,9 @@ The current baseline has:
|
|
|
130
131
|
- `memorix background start` runs the shared HTTP MCP service and dashboard
|
|
131
132
|
- Dashboard maintenance is preview-first, project-scoped, and uses the same
|
|
132
133
|
cleanup and deduplication planners as CLI and MCP
|
|
134
|
+
- Dashboard Coordination Status is read-only and projects the persistent SQLite
|
|
135
|
+
`TeamStore` truth; its task section is `Task Status` and failed reads are
|
|
136
|
+
explicit `error`/`degraded` states
|
|
133
137
|
- context and CodeGraph commands return bounded task receipts before detailed diagnostics
|
|
134
138
|
- HTTP MCP sessions have a bounded, explicit lifecycle and fail with a reinitialize hint after expiry
|
|
135
139
|
- `memorix integrate --agent <agent>` and `memorix hooks install --agent <agent>` remain manual/fallback generation commands
|
|
@@ -137,8 +141,10 @@ The current baseline has:
|
|
|
137
141
|
- `~/.memorix/config.toml` and project `memorix.toml` are the user-facing configuration model
|
|
138
142
|
- legacy `memorix.yml`, `.env`, and `config.json` files are still read for compatibility, but new setups should use TOML
|
|
139
143
|
|
|
140
|
-
For MCP compatibility, 1.8 preserves legacy
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
the
|
|
144
|
+
For MCP compatibility, 1.8.2 preserves legacy 2025-era initialize and
|
|
145
|
+
stateful Streamable HTTP behavior, and adds a tested 2026-07-28
|
|
146
|
+
`server/discover` adapter. Versionless `tools/list` and `tools/call` continue
|
|
147
|
+
through the SDK's legacy result envelopes. Modern result metadata is limited to
|
|
148
|
+
the discovery response (`ttlMs: 0`, private cache scope); Tasks, subscriptions,
|
|
149
|
+
and list-response caching are unsupported. Stateless HTTP project handles are
|
|
150
|
+
a compatibility adapter, not a claim of complete 2026 conformance.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memorix",
|
|
3
3
|
"mcpName": "io.github.AVIDS2/memorix",
|
|
4
|
-
"version": "1.8.
|
|
4
|
+
"version": "1.8.2",
|
|
5
5
|
"description": "Local-first shared memory layer for AI coding agents across MCP clients, Git history, reasoning context, and project sessions.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
package/server.json
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.AVIDS2/memorix",
|
|
4
4
|
"title": "Memorix",
|
|
5
|
-
"description": "Local-first
|
|
5
|
+
"description": "Local-first project memory with legacy MCP and 2026 discovery compatibility.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "https://github.com/AVIDS2/memorix",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "1.8.
|
|
10
|
+
"version": "1.8.2",
|
|
11
11
|
"websiteUrl": "https://github.com/AVIDS2/memorix#readme",
|
|
12
12
|
"icons": [
|
|
13
13
|
{
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
{
|
|
23
23
|
"registryType": "npm",
|
|
24
24
|
"identifier": "memorix",
|
|
25
|
-
"version": "1.8.
|
|
25
|
+
"version": "1.8.2",
|
|
26
26
|
"runtimeHint": "npx",
|
|
27
27
|
"packageArguments": [
|
|
28
28
|
{
|
|
@@ -59,7 +59,7 @@ export default defineCommand({
|
|
|
59
59
|
const cliDir = path.dirname(fileURLToPath(import.meta.url));
|
|
60
60
|
const staticDir = path.join(cliDir, '..', 'dashboard', 'static');
|
|
61
61
|
|
|
62
|
-
await startDashboard(dataDir, port, staticDir, project.id, project.name, true,
|
|
62
|
+
await startDashboard(dataDir, port, staticDir, project.id, project.name, true, project.rootPath, true);
|
|
63
63
|
|
|
64
64
|
// Keep alive
|
|
65
65
|
await new Promise(() => { });
|
|
@@ -40,6 +40,12 @@ export const EXPIRED_SESSION_TTL_MS = 10 * 60 * 1000;
|
|
|
40
40
|
/** Pinned SDK protocol accepted internally while the HTTP boundary speaks the current stateless contract. */
|
|
41
41
|
export const MCP_SDK_COMPAT_PROTOCOL_VERSION = '2025-11-25';
|
|
42
42
|
|
|
43
|
+
/** Modern discovery is allowed before a durable project handle exists. */
|
|
44
|
+
export function isServerDiscoverRequest(body: unknown): boolean {
|
|
45
|
+
return Boolean(body && typeof body === 'object' && !Array.isArray(body)
|
|
46
|
+
&& (body as { method?: unknown }).method === 'server/discover');
|
|
47
|
+
}
|
|
48
|
+
|
|
43
49
|
export function parseSessionTimeoutMs(raw: string | undefined): number {
|
|
44
50
|
const value = raw?.trim();
|
|
45
51
|
if (!value) return DEFAULT_SESSION_TIMEOUT_MS;
|
|
@@ -427,7 +433,7 @@ export default defineCommand({
|
|
|
427
433
|
? req.headers['mcp-project-root']
|
|
428
434
|
: undefined;
|
|
429
435
|
const root = persisted?.projectRoot ?? requestedRoot ?? projectRoot;
|
|
430
|
-
if (!persisted && !isInitializeRequest(body)) {
|
|
436
|
+
if (!persisted && !isInitializeRequest(body) && !isServerDiscoverRequest(body)) {
|
|
431
437
|
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
432
438
|
res.end(JSON.stringify({ jsonrpc: '2.0', error: { code: -32000, message: 'Stateless MCP requests require Mcp-Project-Handle; initialize first.' }, id: null }));
|
|
433
439
|
return;
|
|
@@ -505,7 +511,9 @@ export default defineCommand({
|
|
|
505
511
|
|
|
506
512
|
const requestedProtocol = req.headers['mcp-protocol-version'];
|
|
507
513
|
const statelessRequested = req.headers['mcp-stateless'] === 'true'
|
|
508
|
-
|| requestedProtocol === CURRENT_MCP_PROTOCOL_VERSION
|
|
514
|
+
|| requestedProtocol === CURRENT_MCP_PROTOCOL_VERSION
|
|
515
|
+
|| typeof req.headers['mcp-project-handle'] === 'string'
|
|
516
|
+
|| isServerDiscoverRequest(body);
|
|
509
517
|
if (!sessionId && statelessRequested) {
|
|
510
518
|
await handleStatelessPost(req, res, body);
|
|
511
519
|
return;
|
|
@@ -889,6 +897,15 @@ export default defineCommand({
|
|
|
889
897
|
}
|
|
890
898
|
|
|
891
899
|
if (apiPath === '/team') {
|
|
900
|
+
if (req.method !== 'GET') {
|
|
901
|
+
sendJson({
|
|
902
|
+
status: 'error',
|
|
903
|
+
readOnly: true,
|
|
904
|
+
error: 'Coordination status is read-only',
|
|
905
|
+
errorCode: 'COORDINATION_STATUS_READ_ONLY',
|
|
906
|
+
}, 405);
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
892
909
|
// Phase 4a: All team state is in SQLite via TeamStore
|
|
893
910
|
const { projectId: teamProjectId, dataDir: teamDataDir } = await resolveRequestProject(url);
|
|
894
911
|
const ts = await getTeamStore(teamDataDir);
|
|
@@ -967,8 +984,9 @@ export default defineCommand({
|
|
|
967
984
|
const openHandoffs = handoffs.filter((handoff: any) => handoff.status !== 'completed').length;
|
|
968
985
|
|
|
969
986
|
sendJson({
|
|
987
|
+
status: 'ok',
|
|
970
988
|
mode: 'control-plane',
|
|
971
|
-
readOnly:
|
|
989
|
+
readOnly: true,
|
|
972
990
|
scope,
|
|
973
991
|
agents: withTier,
|
|
974
992
|
// Primary headline number
|
|
@@ -1650,6 +1668,23 @@ export default defineCommand({
|
|
|
1650
1668
|
|
|
1651
1669
|
sendJson({ error: 'Not found' }, 404);
|
|
1652
1670
|
} catch (err) {
|
|
1671
|
+
if (apiPath === '/team') {
|
|
1672
|
+
const scope = url.searchParams.get('scope') === 'global' ? 'global' : 'project';
|
|
1673
|
+
console.error('[memorix] coordination snapshot unavailable', { status: 'error', scope });
|
|
1674
|
+
sendJson({
|
|
1675
|
+
status: 'error',
|
|
1676
|
+
mode: 'control-plane',
|
|
1677
|
+
readOnly: true,
|
|
1678
|
+
scope,
|
|
1679
|
+
agents: [],
|
|
1680
|
+
locks: [],
|
|
1681
|
+
tasks: [],
|
|
1682
|
+
handoffs: [],
|
|
1683
|
+
error: 'Coordination state unavailable',
|
|
1684
|
+
errorCode: 'COORDINATION_STATE_UNAVAILABLE',
|
|
1685
|
+
}, 503);
|
|
1686
|
+
return;
|
|
1687
|
+
}
|
|
1653
1688
|
sendJson({ error: err instanceof Error ? err.message : 'Unknown error' }, 500);
|
|
1654
1689
|
}
|
|
1655
1690
|
}
|