memorix 1.6.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/TEAM.md +86 -86
- package/dist/cli/index.js +317 -62
- package/dist/cli/memcode.js +12 -1
- package/dist/index.js +56 -9
- package/dist/maintenance-runner.js +54 -7
- package/dist/media-audio-runner.js +54 -7
- package/dist/media-video-runner.js +54 -7
- package/dist/memcode-runtime/CHANGELOG.md +24 -0
- package/dist/sdk.js +55 -8
- package/dist/vector-backfill-runner.js +54 -7
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +11 -3
- package/docs/API_REFERENCE.md +1 -1
- package/docs/DESIGN_DECISIONS.md +357 -357
- package/docs/DOCKER.md +5 -1
- package/docs/PERFORMANCE.md +2 -2
- package/docs/README.md +3 -1
- package/docs/SETUP.md +8 -2
- package/package.json +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/audit/index.ts +156 -156
- package/src/cli/commands/agent-integrations.ts +9 -3
- package/src/cli/commands/doctor.ts +46 -15
- package/src/cli/commands/formation.ts +48 -48
- package/src/cli/commands/git-hook-install.ts +111 -111
- package/src/cli/commands/handoff.ts +54 -54
- package/src/cli/commands/hook.ts +13 -1
- package/src/cli/commands/hooks-status.ts +63 -63
- package/src/cli/commands/ingest.ts +44 -44
- package/src/cli/commands/integrate-shared.ts +15 -15
- package/src/cli/commands/lock.ts +82 -82
- package/src/cli/commands/message.ts +104 -104
- package/src/cli/commands/poll.ts +58 -58
- package/src/cli/commands/reasoning.ts +118 -118
- package/src/cli/commands/serve-http.ts +68 -7
- package/src/cli/commands/skills.ts +114 -114
- package/src/cli/commands/task.ts +167 -167
- package/src/cli/commands/transfer.ts +47 -47
- package/src/cli/heap.ts +76 -0
- package/src/cli/index.ts +406 -406
- package/src/cli/invocation.ts +7 -4
- package/src/cli/tui/ChatView.tsx +234 -234
- package/src/cli/tui/CommandBar.tsx +312 -312
- package/src/cli/tui/ContextRail.tsx +118 -118
- package/src/cli/tui/HeaderBar.tsx +72 -72
- package/src/cli/tui/LogoBanner.tsx +51 -51
- package/src/cli/tui/index.ts +41 -41
- package/src/cli/version.ts +7 -7
- package/src/cli/workbench.ts +1 -1
- package/src/dashboard/project-classification.ts +64 -64
- package/src/embedding/provider.ts +76 -6
- package/src/git/hooks-path.ts +85 -85
- package/src/hooks/handler.ts +9 -18
- package/src/hooks/lifecycle.ts +173 -0
- package/src/hooks/pattern-detector.ts +173 -173
- package/src/hooks/significance-filter.ts +250 -250
- package/src/llm/memory-manager.ts +328 -328
- package/src/llm/quality.ts +248 -248
- package/src/memory/attribution-guard.ts +249 -249
- package/src/memory/disclosure-policy.ts +135 -135
- package/src/memory/entity-extractor.ts +197 -197
- package/src/memory/formation/evaluate.ts +217 -217
- package/src/memory/freshness.ts +122 -122
- package/src/memory/graph.ts +197 -197
- package/src/memory/refs.ts +94 -94
- package/src/memory/secret-filter.ts +79 -79
- package/src/orchestrate/adapters/claude-stream.ts +192 -192
- package/src/orchestrate/adapters/claude.ts +111 -111
- package/src/orchestrate/adapters/codex-stream.ts +134 -134
- package/src/orchestrate/adapters/codex.ts +41 -41
- package/src/orchestrate/adapters/gemini-stream.ts +166 -166
- package/src/orchestrate/adapters/gemini.ts +42 -42
- package/src/orchestrate/adapters/index.ts +73 -73
- package/src/orchestrate/adapters/opencode-stream.ts +143 -143
- package/src/orchestrate/adapters/opencode.ts +47 -47
- package/src/orchestrate/adapters/types.ts +77 -77
- package/src/orchestrate/capability-router.ts +284 -284
- package/src/orchestrate/cost-tracker.ts +219 -219
- package/src/orchestrate/error-recovery.ts +191 -191
- package/src/orchestrate/evidence.ts +140 -140
- package/src/orchestrate/ledger.ts +110 -110
- package/src/orchestrate/memorix-bridge.ts +343 -343
- package/src/orchestrate/output-budget.ts +80 -80
- package/src/orchestrate/permission.ts +152 -152
- package/src/orchestrate/pipeline-trace.ts +131 -131
- package/src/orchestrate/prompt-builder.ts +155 -155
- package/src/orchestrate/ring-buffer.ts +37 -37
- package/src/orchestrate/task-graph.ts +389 -389
- package/src/project/aliases.ts +374 -374
- package/src/rules/adapters/trae.ts +56 -56
- package/src/rules/syncer.ts +235 -235
- package/src/search/query-expansion.ts +52 -52
- package/src/server/formation-timeout.ts +27 -27
- package/src/skills/mini-skills.ts +386 -386
- package/src/store/chat-store.ts +119 -119
- package/src/store/graph-store.ts +249 -249
- package/src/store/mini-skill-store.ts +349 -349
- package/src/store/persistence-json.ts +212 -212
- package/src/store/persistence.ts +291 -291
- package/src/store/project-affinity.ts +195 -195
- package/src/team/event-bus.ts +76 -76
- package/src/team/handoff.ts +161 -161
- package/src/team/poll.ts +132 -132
- package/src/workspace/mcp-adapters/codex.ts +191 -191
- package/src/workspace/mcp-adapters/copilot.ts +105 -105
- package/src/workspace/mcp-adapters/cursor.ts +53 -53
- package/src/workspace/mcp-adapters/kiro.ts +64 -64
- package/src/workspace/mcp-adapters/opencode.ts +123 -123
- package/src/workspace/mcp-adapters/trae.ts +134 -134
- package/src/workspace/mcp-adapters/windsurf.ts +91 -91
- package/src/workspace/sanitizer.ts +60 -60
package/dist/cli/index.js
CHANGED
|
@@ -2,7 +2,18 @@
|
|
|
2
2
|
import {spawnSync as __ms} from "node:child_process";
|
|
3
3
|
import {fileURLToPath as __fu} from "node:url";
|
|
4
4
|
if(!process.env.__MEMORIX_HEAP){process.env.__MEMORIX_HEAP="1";
|
|
5
|
-
|
|
5
|
+
const __args=process.argv.slice(2);
|
|
6
|
+
let __cmd;
|
|
7
|
+
for(let __i=0;__i<__args.length;__i++){
|
|
8
|
+
const __a=__args[__i];
|
|
9
|
+
if(__a==="--")break;
|
|
10
|
+
if(__a.startsWith("-")){if(!__a.includes("=")&&__args[__i+1]&&!__args[__i+1].startsWith("-"))__i++;continue;}
|
|
11
|
+
__cmd=__a;break;}
|
|
12
|
+
const __fallback=__cmd==="hook"?512:4096;
|
|
13
|
+
const __raw=__cmd==="hook"?process.env.MEMORIX_HOOK_HEAP_MB:process.env.MEMORIX_HEAP_MB;
|
|
14
|
+
const __n=Number(__raw);
|
|
15
|
+
const __heap=(Number.isFinite(__n)&&__n>=64&&__n<=16384)?String(Math.floor(__n)):String(__fallback);
|
|
16
|
+
let r=__ms(process.execPath,["--max-old-space-size="+__heap,__fu(import.meta.url),...process.argv.slice(2)],{stdio:"inherit",env:process.env,windowsHide:true});
|
|
6
17
|
process.exit(r.status??1);}
|
|
7
18
|
import {createRequire as __memorix_cjsRequire} from "module";
|
|
8
19
|
const require = __memorix_cjsRequire(import.meta.url);
|
|
@@ -3221,7 +3232,7 @@ ${import_picocolors.default.gray(m3)} ${s4}
|
|
|
3221
3232
|
|
|
3222
3233
|
// src/cli/version.ts
|
|
3223
3234
|
function getCliVersion() {
|
|
3224
|
-
return true ? "1.6.
|
|
3235
|
+
return true ? "1.6.1" : pkg.version;
|
|
3225
3236
|
}
|
|
3226
3237
|
var init_version = __esm({
|
|
3227
3238
|
"src/cli/version.ts"() {
|
|
@@ -3231,7 +3242,7 @@ var init_version = __esm({
|
|
|
3231
3242
|
});
|
|
3232
3243
|
|
|
3233
3244
|
// src/cli/invocation.ts
|
|
3234
|
-
import { existsSync as existsSync2, statSync } from "fs";
|
|
3245
|
+
import { existsSync as existsSync2, realpathSync, statSync } from "fs";
|
|
3235
3246
|
import { resolve as resolve2 } from "path";
|
|
3236
3247
|
function readOption(argument) {
|
|
3237
3248
|
const equals = argument.indexOf("=");
|
|
@@ -3261,10 +3272,11 @@ function normalizeCliInvocation(argv2 = process.argv) {
|
|
|
3261
3272
|
if (inlineValue === void 0) index += 1;
|
|
3262
3273
|
}
|
|
3263
3274
|
if (invocation.projectRoot) {
|
|
3264
|
-
const
|
|
3265
|
-
if (!existsSync2(
|
|
3266
|
-
throw new Error(`CLI project directory does not exist: ${
|
|
3275
|
+
const resolvedProjectRoot = resolve2(invocation.projectRoot);
|
|
3276
|
+
if (!existsSync2(resolvedProjectRoot) || !statSync(resolvedProjectRoot).isDirectory()) {
|
|
3277
|
+
throw new Error(`CLI project directory does not exist: ${resolvedProjectRoot}`);
|
|
3267
3278
|
}
|
|
3279
|
+
const projectRoot = realpathSync(resolvedProjectRoot);
|
|
3268
3280
|
process.chdir(projectRoot);
|
|
3269
3281
|
process.env.MEMORIX_CLI_PROJECT_ROOT = projectRoot;
|
|
3270
3282
|
invocation.projectRoot = projectRoot;
|
|
@@ -22778,6 +22790,7 @@ __export(provider_exports, {
|
|
|
22778
22790
|
MAX_INLINE_EMBEDDING_BYTES: () => MAX_INLINE_EMBEDDING_BYTES,
|
|
22779
22791
|
UnsupportedEmbeddingModalityError: () => UnsupportedEmbeddingModalityError,
|
|
22780
22792
|
getEmbeddingProvider: () => getEmbeddingProvider,
|
|
22793
|
+
getEmbeddingRuntimeHealth: () => getEmbeddingRuntimeHealth,
|
|
22781
22794
|
isEmbeddingExplicitlyDisabled: () => isEmbeddingExplicitlyDisabled,
|
|
22782
22795
|
isVectorSearchAvailable: () => isVectorSearchAvailable,
|
|
22783
22796
|
resetProvider: () => resetProvider,
|
|
@@ -22885,13 +22898,36 @@ function isTemporaryEmbeddingFailure(error40) {
|
|
|
22885
22898
|
if (!(error40 instanceof Error)) return false;
|
|
22886
22899
|
return /embedding api error \(401\)/i.test(error40.message) || /invalid_api_key/i.test(error40.message) || /incorrect api key/i.test(error40.message) || /unauthorized/i.test(error40.message) || /embedding api timeout/i.test(error40.message) || /embedding api error \((402|429|5\d\d)\)/i.test(error40.message) || /quota exceeded/i.test(error40.message) || /account balance/i.test(error40.message) || /fetch failed/i.test(error40.message) || /econnreset/i.test(error40.message) || /econnrefused/i.test(error40.message) || /temporarily unavailable/i.test(error40.message);
|
|
22887
22900
|
}
|
|
22901
|
+
function classifyEmbeddingFailure(error40) {
|
|
22902
|
+
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
22903
|
+
if (/embedding api error \(401\)|invalid_api_key|incorrect api key|unauthorized/i.test(message)) {
|
|
22904
|
+
return "authorization";
|
|
22905
|
+
}
|
|
22906
|
+
if (/embedding api error \(402\)|quota exceeded|account balance/i.test(message)) {
|
|
22907
|
+
return "billing";
|
|
22908
|
+
}
|
|
22909
|
+
if (/embedding api timeout|abort/i.test(message)) {
|
|
22910
|
+
return "timeout";
|
|
22911
|
+
}
|
|
22912
|
+
return "upstream";
|
|
22913
|
+
}
|
|
22888
22914
|
function markTemporaryFailure(reason) {
|
|
22889
22915
|
provider = null;
|
|
22890
22916
|
initPromise = null;
|
|
22891
22917
|
lastInitWasTemporaryFailure = true;
|
|
22892
22918
|
lastFailureTimestamp = Date.now();
|
|
22919
|
+
lastEmbeddingFailure = {
|
|
22920
|
+
kind: classifyEmbeddingFailure(reason),
|
|
22921
|
+
occurredAt: lastFailureTimestamp
|
|
22922
|
+
};
|
|
22893
22923
|
const message = reason instanceof Error ? reason.message : String(reason);
|
|
22894
|
-
warnOnce(`[memorix] Embedding provider
|
|
22924
|
+
warnOnce(`[memorix] Embedding provider unavailable at runtime: ${message}`);
|
|
22925
|
+
}
|
|
22926
|
+
function markProviderReady(candidate2) {
|
|
22927
|
+
provider = wrapProvider(candidate2);
|
|
22928
|
+
lastInitWasTemporaryFailure = false;
|
|
22929
|
+
lastEmbeddingFailure = null;
|
|
22930
|
+
return provider;
|
|
22895
22931
|
}
|
|
22896
22932
|
async function createFastEmbedProvider() {
|
|
22897
22933
|
try {
|
|
@@ -23007,35 +23043,35 @@ async function getEmbeddingProvider(options = {}) {
|
|
|
23007
23043
|
if (mode === "fastembed") {
|
|
23008
23044
|
const initialized = await createFastEmbedProvider();
|
|
23009
23045
|
if (!initialized) return null;
|
|
23010
|
-
provider =
|
|
23046
|
+
provider = markProviderReady(initialized);
|
|
23011
23047
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
23012
23048
|
return provider;
|
|
23013
23049
|
}
|
|
23014
23050
|
if (mode === "transformers") {
|
|
23015
23051
|
const initialized = await createTransformersProvider();
|
|
23016
23052
|
if (!initialized) return null;
|
|
23017
|
-
provider =
|
|
23053
|
+
provider = markProviderReady(initialized);
|
|
23018
23054
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
23019
23055
|
return provider;
|
|
23020
23056
|
}
|
|
23021
23057
|
if (mode === "api") {
|
|
23022
23058
|
const initialized = await createAPIProvider(options);
|
|
23023
23059
|
if (!initialized) return null;
|
|
23024
|
-
provider =
|
|
23060
|
+
provider = markProviderReady(initialized);
|
|
23025
23061
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
23026
23062
|
return provider;
|
|
23027
23063
|
}
|
|
23028
23064
|
if (hasAPIEmbeddingConfig()) {
|
|
23029
23065
|
const initialized = await createAPIProvider(options);
|
|
23030
23066
|
if (initialized) {
|
|
23031
|
-
provider =
|
|
23067
|
+
provider = markProviderReady(initialized);
|
|
23032
23068
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
23033
23069
|
return provider;
|
|
23034
23070
|
}
|
|
23035
23071
|
}
|
|
23036
23072
|
const localFallback = await createLocalFallbackProvider();
|
|
23037
23073
|
if (localFallback) {
|
|
23038
|
-
provider =
|
|
23074
|
+
provider = markProviderReady(localFallback);
|
|
23039
23075
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
23040
23076
|
return provider;
|
|
23041
23077
|
}
|
|
@@ -23057,6 +23093,27 @@ async function isVectorSearchAvailable() {
|
|
|
23057
23093
|
const p3 = await getEmbeddingProvider();
|
|
23058
23094
|
return p3 !== null;
|
|
23059
23095
|
}
|
|
23096
|
+
function getEmbeddingRuntimeHealth() {
|
|
23097
|
+
const mode = getEmbeddingMode2();
|
|
23098
|
+
if (mode === "off") return { status: "disabled" };
|
|
23099
|
+
if (lastInitWasTemporaryFailure && lastEmbeddingFailure) {
|
|
23100
|
+
return {
|
|
23101
|
+
status: "degraded",
|
|
23102
|
+
failure: {
|
|
23103
|
+
kind: lastEmbeddingFailure.kind,
|
|
23104
|
+
occurredAt: new Date(lastEmbeddingFailure.occurredAt).toISOString(),
|
|
23105
|
+
retryAfterMs: Math.max(0, RETRY_COOLDOWN_MS - (Date.now() - lastEmbeddingFailure.occurredAt))
|
|
23106
|
+
}
|
|
23107
|
+
};
|
|
23108
|
+
}
|
|
23109
|
+
if (provider) {
|
|
23110
|
+
return {
|
|
23111
|
+
status: "ready",
|
|
23112
|
+
provider: { name: provider.name, dimensions: provider.dimensions }
|
|
23113
|
+
};
|
|
23114
|
+
}
|
|
23115
|
+
return { status: "uninitialized" };
|
|
23116
|
+
}
|
|
23060
23117
|
function isEmbeddingExplicitlyDisabled() {
|
|
23061
23118
|
return getEmbeddingMode2() === "off";
|
|
23062
23119
|
}
|
|
@@ -23065,10 +23122,11 @@ function resetProvider() {
|
|
|
23065
23122
|
initPromise = null;
|
|
23066
23123
|
lastInitWasTemporaryFailure = false;
|
|
23067
23124
|
lastFailureTimestamp = 0;
|
|
23125
|
+
lastEmbeddingFailure = null;
|
|
23068
23126
|
lastEmbeddingWarning = "";
|
|
23069
23127
|
lastEmbeddingWarningAt = 0;
|
|
23070
23128
|
}
|
|
23071
|
-
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
23129
|
+
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
23072
23130
|
var init_provider = __esm({
|
|
23073
23131
|
"src/embedding/provider.ts"() {
|
|
23074
23132
|
"use strict";
|
|
@@ -23093,6 +23151,7 @@ var init_provider = __esm({
|
|
|
23093
23151
|
provider = null;
|
|
23094
23152
|
initPromise = null;
|
|
23095
23153
|
lastInitWasTemporaryFailure = false;
|
|
23154
|
+
lastEmbeddingFailure = null;
|
|
23096
23155
|
lastEmbeddingWarning = "";
|
|
23097
23156
|
lastEmbeddingWarningAt = 0;
|
|
23098
23157
|
WARNING_COOLDOWN_MS = 3e4;
|
|
@@ -259024,7 +259083,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
259024
259083
|
};
|
|
259025
259084
|
const server = existingServer ?? new McpServer({
|
|
259026
259085
|
name: "memorix",
|
|
259027
|
-
version: true ? "1.6.
|
|
259086
|
+
version: true ? "1.6.1" : "1.0.1"
|
|
259028
259087
|
});
|
|
259029
259088
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
259030
259089
|
server.registerTool = ((name, ...args) => {
|
|
@@ -265892,6 +265951,7 @@ var init_control_plane_maintenance = __esm({
|
|
|
265892
265951
|
var serve_http_exports = {};
|
|
265893
265952
|
__export(serve_http_exports, {
|
|
265894
265953
|
DEFAULT_SESSION_TIMEOUT_MS: () => DEFAULT_SESSION_TIMEOUT_MS,
|
|
265954
|
+
EXPIRED_SESSION_TTL_MS: () => EXPIRED_SESSION_TTL_MS,
|
|
265895
265955
|
_testing: () => _testing2,
|
|
265896
265956
|
default: () => serve_http_default,
|
|
265897
265957
|
parseSessionTimeoutMs: () => parseSessionTimeoutMs,
|
|
@@ -265901,7 +265961,7 @@ function parseSessionTimeoutMs(raw) {
|
|
|
265901
265961
|
const value = raw?.trim();
|
|
265902
265962
|
if (!value) return DEFAULT_SESSION_TIMEOUT_MS;
|
|
265903
265963
|
const parsed = Number(value);
|
|
265904
|
-
if (!Number.isFinite(parsed) || parsed
|
|
265964
|
+
if (!Number.isFinite(parsed) || parsed < 0) return DEFAULT_SESSION_TIMEOUT_MS;
|
|
265905
265965
|
return Math.floor(parsed);
|
|
265906
265966
|
}
|
|
265907
265967
|
function resolveServeHttpDefaults(argsPort, configured) {
|
|
@@ -265913,7 +265973,7 @@ function resolveServeHttpDefaults(argsPort, configured) {
|
|
|
265913
265973
|
const transportNotice = configured.transport === "stdio" ? '[memorix] config server.transport = "stdio"; serve-http continues on HTTP (the explicit command wins).' : void 0;
|
|
265914
265974
|
return { port, transportNotice };
|
|
265915
265975
|
}
|
|
265916
|
-
var DEFAULT_SESSION_TIMEOUT_MS, serve_http_default, _testing2;
|
|
265976
|
+
var DEFAULT_SESSION_TIMEOUT_MS, EXPIRED_SESSION_TTL_MS, serve_http_default, _testing2;
|
|
265917
265977
|
var init_serve_http = __esm({
|
|
265918
265978
|
"src/cli/commands/serve-http.ts"() {
|
|
265919
265979
|
"use strict";
|
|
@@ -265925,7 +265985,8 @@ var init_serve_http = __esm({
|
|
|
265925
265985
|
init_visibility();
|
|
265926
265986
|
init_port();
|
|
265927
265987
|
init_mcp_root_path();
|
|
265928
|
-
DEFAULT_SESSION_TIMEOUT_MS =
|
|
265988
|
+
DEFAULT_SESSION_TIMEOUT_MS = 12 * 60 * 60 * 1e3;
|
|
265989
|
+
EXPIRED_SESSION_TTL_MS = 10 * 60 * 1e3;
|
|
265929
265990
|
serve_http_default = defineCommand({
|
|
265930
265991
|
meta: {
|
|
265931
265992
|
name: "serve-http",
|
|
@@ -265984,7 +266045,9 @@ var init_serve_http = __esm({
|
|
|
265984
266045
|
console.error(`[memorix] HTTP transport starting on ${host}:${port}`);
|
|
265985
266046
|
console.error(`[memorix] Project root: ${projectRoot}`);
|
|
265986
266047
|
const sessionTimeoutMs = parseSessionTimeoutMs(process.env.MEMORIX_SESSION_TIMEOUT_MS);
|
|
265987
|
-
console.error(
|
|
266048
|
+
console.error(
|
|
266049
|
+
sessionTimeoutMs === 0 ? "[memorix] HTTP session idle timeout: disabled" : `[memorix] HTTP session idle timeout: ${Math.round(sessionTimeoutMs / 6e4)}min (${sessionTimeoutMs}ms)`
|
|
266050
|
+
);
|
|
265988
266051
|
const teamStoreCache = /* @__PURE__ */ new Map();
|
|
265989
266052
|
const { initTeamStore: initTeamStore2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
|
|
265990
266053
|
async function getTeamStore2(dataDir) {
|
|
@@ -266001,6 +266064,7 @@ var init_serve_http = __esm({
|
|
|
266001
266064
|
const sharedTeamStore = await getTeamStore2(teamDataDir);
|
|
266002
266065
|
const sessions = /* @__PURE__ */ new Map();
|
|
266003
266066
|
const sessionLastActivity = /* @__PURE__ */ new Map();
|
|
266067
|
+
const expiredSessions = /* @__PURE__ */ new Map();
|
|
266004
266068
|
let suppressedProbeCount = 0;
|
|
266005
266069
|
let lastProbeSummaryTime = Date.now();
|
|
266006
266070
|
const PROBE_SUMMARY_INTERVAL_MS = 6e4;
|
|
@@ -266013,6 +266077,26 @@ var init_serve_http = __esm({
|
|
|
266013
266077
|
lastProbeSummaryTime = Date.now();
|
|
266014
266078
|
}
|
|
266015
266079
|
}
|
|
266080
|
+
function forgetExpiredSessions(now3 = Date.now()) {
|
|
266081
|
+
for (const [sessionId, expiresAt] of expiredSessions) {
|
|
266082
|
+
if (expiresAt <= now3) expiredSessions.delete(sessionId);
|
|
266083
|
+
}
|
|
266084
|
+
}
|
|
266085
|
+
function sendUnknownSession(res, sessionId, jsonRpc = false) {
|
|
266086
|
+
const expired = Boolean(sessionId && expiredSessions.has(sessionId));
|
|
266087
|
+
const message = expired ? "MCP session expired after inactivity. Initialize a new session and retry the request." : "MCP session not found. Initialize a new session and retry the request.";
|
|
266088
|
+
if (jsonRpc) {
|
|
266089
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
266090
|
+
res.end(JSON.stringify({
|
|
266091
|
+
jsonrpc: "2.0",
|
|
266092
|
+
error: { code: -32001, message },
|
|
266093
|
+
id: null
|
|
266094
|
+
}));
|
|
266095
|
+
return;
|
|
266096
|
+
}
|
|
266097
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
266098
|
+
res.end(message);
|
|
266099
|
+
}
|
|
266016
266100
|
function parseBody(req) {
|
|
266017
266101
|
return new Promise((resolve6, reject) => {
|
|
266018
266102
|
const chunks = [];
|
|
@@ -266129,6 +266213,10 @@ var init_serve_http = __esm({
|
|
|
266129
266213
|
await sessions.get(sessionId).transport.handleRequest(req, res, body);
|
|
266130
266214
|
return;
|
|
266131
266215
|
}
|
|
266216
|
+
if (sessionId) {
|
|
266217
|
+
sendUnknownSession(res, sessionId, true);
|
|
266218
|
+
return;
|
|
266219
|
+
}
|
|
266132
266220
|
if (!sessionId && isInitializeRequest2(body)) {
|
|
266133
266221
|
let createdState = null;
|
|
266134
266222
|
const transport = new StreamableHTTPServerTransport2({
|
|
@@ -266227,8 +266315,12 @@ var init_serve_http = __esm({
|
|
|
266227
266315
|
async function handleGet(req, res) {
|
|
266228
266316
|
const sessionId = req.headers["mcp-session-id"];
|
|
266229
266317
|
if (!sessionId || !sessions.has(sessionId)) {
|
|
266230
|
-
|
|
266231
|
-
|
|
266318
|
+
if (!sessionId) {
|
|
266319
|
+
res.writeHead(400, { "Content-Type": "text/plain" });
|
|
266320
|
+
res.end("Missing MCP session ID");
|
|
266321
|
+
return;
|
|
266322
|
+
}
|
|
266323
|
+
sendUnknownSession(res, sessionId);
|
|
266232
266324
|
return;
|
|
266233
266325
|
}
|
|
266234
266326
|
await sessions.get(sessionId).transport.handleRequest(req, res);
|
|
@@ -266236,8 +266328,12 @@ var init_serve_http = __esm({
|
|
|
266236
266328
|
async function handleDelete(req, res) {
|
|
266237
266329
|
const sessionId = req.headers["mcp-session-id"];
|
|
266238
266330
|
if (!sessionId || !sessions.has(sessionId)) {
|
|
266239
|
-
|
|
266240
|
-
|
|
266331
|
+
if (!sessionId) {
|
|
266332
|
+
res.writeHead(400, { "Content-Type": "text/plain" });
|
|
266333
|
+
res.end("Missing MCP session ID");
|
|
266334
|
+
return;
|
|
266335
|
+
}
|
|
266336
|
+
sendUnknownSession(res, sessionId);
|
|
266241
266337
|
return;
|
|
266242
266338
|
}
|
|
266243
266339
|
await sessions.get(sessionId).transport.handleRequest(req, res);
|
|
@@ -266986,13 +267082,15 @@ var init_serve_http = __esm({
|
|
|
266986
267082
|
}
|
|
266987
267083
|
const url2 = new URL(req.url || "/", `http://localhost:${port}`);
|
|
266988
267084
|
if (url2.pathname === "/health") {
|
|
267085
|
+
const { getEmbeddingRuntimeHealth: getEmbeddingRuntimeHealth2 } = await Promise.resolve().then(() => (init_provider(), provider_exports));
|
|
266989
267086
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
266990
267087
|
res.end(JSON.stringify({
|
|
266991
267088
|
status: "ok",
|
|
266992
267089
|
mode: "control-plane",
|
|
266993
267090
|
port,
|
|
266994
267091
|
uptime: Math.round(process.uptime()),
|
|
266995
|
-
pid: process.pid
|
|
267092
|
+
pid: process.pid,
|
|
267093
|
+
embedding: getEmbeddingRuntimeHealth2()
|
|
266996
267094
|
}));
|
|
266997
267095
|
return;
|
|
266998
267096
|
}
|
|
@@ -267050,6 +267148,8 @@ var init_serve_http = __esm({
|
|
|
267050
267148
|
}
|
|
267051
267149
|
await serveDashStatic(req, res);
|
|
267052
267150
|
});
|
|
267151
|
+
httpServer.keepAliveTimeout = 6e4;
|
|
267152
|
+
httpServer.headersTimeout = 65e3;
|
|
267053
267153
|
httpServer.listen(port, host, () => {
|
|
267054
267154
|
try {
|
|
267055
267155
|
const memorixDir = (process.env.HOME || process.env.USERPROFILE || "").replace(/\\/g, "/") + "/.memorix";
|
|
@@ -267073,10 +267173,13 @@ var init_serve_http = __esm({
|
|
|
267073
267173
|
const gcInterval = setInterval(() => {
|
|
267074
267174
|
maybeProbeSummary();
|
|
267075
267175
|
const now3 = Date.now();
|
|
267176
|
+
forgetExpiredSessions(now3);
|
|
267177
|
+
if (SESSION_TIMEOUT_MS === 0) return;
|
|
267076
267178
|
for (const [sid, state] of sessions) {
|
|
267077
267179
|
const lastActive = sessionLastActivity.get(sid) ?? 0;
|
|
267078
267180
|
if (now3 - lastActive > SESSION_TIMEOUT_MS) {
|
|
267079
267181
|
console.error(`[memorix] Session ${sid.slice(0, 8)}\u2026 timed out (idle ${Math.round((now3 - lastActive) / 6e4)}min), closing`);
|
|
267182
|
+
expiredSessions.set(sid, now3 + EXPIRED_SESSION_TTL_MS);
|
|
267080
267183
|
state.transport.close().catch(() => {
|
|
267081
267184
|
});
|
|
267082
267185
|
sessions.delete(sid);
|
|
@@ -268715,6 +268818,144 @@ var init_pattern_detector = __esm({
|
|
|
268715
268818
|
}
|
|
268716
268819
|
});
|
|
268717
268820
|
|
|
268821
|
+
// src/hooks/lifecycle.ts
|
|
268822
|
+
var lifecycle_exports2 = {};
|
|
268823
|
+
__export(lifecycle_exports2, {
|
|
268824
|
+
DEFAULT_HOOK_STDIN_TIMEOUT_MS: () => DEFAULT_HOOK_STDIN_TIMEOUT_MS,
|
|
268825
|
+
DEFAULT_HOOK_TIMEOUT_MS: () => DEFAULT_HOOK_TIMEOUT_MS,
|
|
268826
|
+
MAX_HOOK_STDIN_TIMEOUT_MS: () => MAX_HOOK_STDIN_TIMEOUT_MS,
|
|
268827
|
+
MAX_HOOK_TIMEOUT_MS: () => MAX_HOOK_TIMEOUT_MS,
|
|
268828
|
+
MIN_HOOK_STDIN_TIMEOUT_MS: () => MIN_HOOK_STDIN_TIMEOUT_MS,
|
|
268829
|
+
MIN_HOOK_TIMEOUT_MS: () => MIN_HOOK_TIMEOUT_MS,
|
|
268830
|
+
hookObservationRuntimeOptions: () => hookObservationRuntimeOptions,
|
|
268831
|
+
readHookStdin: () => readHookStdin,
|
|
268832
|
+
resolveHookStdinTimeoutMs: () => resolveHookStdinTimeoutMs,
|
|
268833
|
+
resolveHookTimeoutMs: () => resolveHookTimeoutMs,
|
|
268834
|
+
runHookWithDeadline: () => runHookWithDeadline
|
|
268835
|
+
});
|
|
268836
|
+
function parseBoundedMs(raw, fallback, min, max) {
|
|
268837
|
+
const value = raw?.trim();
|
|
268838
|
+
if (!value) return fallback;
|
|
268839
|
+
const parsed = Number(value);
|
|
268840
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
|
|
268841
|
+
return Math.max(min, Math.min(max, Math.floor(parsed)));
|
|
268842
|
+
}
|
|
268843
|
+
function resolveHookTimeoutMs(env3 = process.env) {
|
|
268844
|
+
return parseBoundedMs(
|
|
268845
|
+
env3.MEMORIX_HOOK_TIMEOUT_MS,
|
|
268846
|
+
DEFAULT_HOOK_TIMEOUT_MS,
|
|
268847
|
+
MIN_HOOK_TIMEOUT_MS,
|
|
268848
|
+
MAX_HOOK_TIMEOUT_MS
|
|
268849
|
+
);
|
|
268850
|
+
}
|
|
268851
|
+
function resolveHookStdinTimeoutMs(env3 = process.env) {
|
|
268852
|
+
return parseBoundedMs(
|
|
268853
|
+
env3.MEMORIX_HOOK_STDIN_TIMEOUT_MS,
|
|
268854
|
+
DEFAULT_HOOK_STDIN_TIMEOUT_MS,
|
|
268855
|
+
MIN_HOOK_STDIN_TIMEOUT_MS,
|
|
268856
|
+
MAX_HOOK_STDIN_TIMEOUT_MS
|
|
268857
|
+
);
|
|
268858
|
+
}
|
|
268859
|
+
function hookObservationRuntimeOptions(projectRoot) {
|
|
268860
|
+
return {
|
|
268861
|
+
embeddingWriteMode: "deferred",
|
|
268862
|
+
projectRoot
|
|
268863
|
+
};
|
|
268864
|
+
}
|
|
268865
|
+
async function readHookStdin(stdin2, timeoutMs) {
|
|
268866
|
+
return new Promise((resolve6) => {
|
|
268867
|
+
const chunks = [];
|
|
268868
|
+
let settled = false;
|
|
268869
|
+
const finish = () => {
|
|
268870
|
+
if (settled) return;
|
|
268871
|
+
settled = true;
|
|
268872
|
+
clearTimeout(timer);
|
|
268873
|
+
stdin2.removeListener("data", onData);
|
|
268874
|
+
stdin2.removeListener("end", finish);
|
|
268875
|
+
stdin2.removeListener("error", finish);
|
|
268876
|
+
stdin2.pause?.();
|
|
268877
|
+
if (!stdin2.isTTY) {
|
|
268878
|
+
stdin2.destroy?.();
|
|
268879
|
+
} else {
|
|
268880
|
+
stdin2.unref?.();
|
|
268881
|
+
}
|
|
268882
|
+
resolve6(Buffer.concat(chunks).toString("utf-8").trim());
|
|
268883
|
+
};
|
|
268884
|
+
const onData = (chunk) => {
|
|
268885
|
+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
268886
|
+
};
|
|
268887
|
+
const timer = setTimeout(finish, timeoutMs);
|
|
268888
|
+
stdin2.on("data", onData);
|
|
268889
|
+
stdin2.on("end", finish);
|
|
268890
|
+
stdin2.on("error", finish);
|
|
268891
|
+
});
|
|
268892
|
+
}
|
|
268893
|
+
function writeContinue(stdout2) {
|
|
268894
|
+
try {
|
|
268895
|
+
stdout2.write(JSON.stringify({ continue: true }));
|
|
268896
|
+
} catch {
|
|
268897
|
+
}
|
|
268898
|
+
}
|
|
268899
|
+
async function runHookWithDeadline(options) {
|
|
268900
|
+
const stdout2 = options.stdout ?? process.stdout;
|
|
268901
|
+
const stderr = options.stderr ?? process.stderr;
|
|
268902
|
+
const exit = options.exit ?? ((code) => {
|
|
268903
|
+
process.exit(code);
|
|
268904
|
+
});
|
|
268905
|
+
await new Promise((resolve6) => {
|
|
268906
|
+
let finished2 = false;
|
|
268907
|
+
const settle = () => {
|
|
268908
|
+
if (finished2) return;
|
|
268909
|
+
finished2 = true;
|
|
268910
|
+
clearTimeout(timer);
|
|
268911
|
+
resolve6();
|
|
268912
|
+
};
|
|
268913
|
+
const timer = setTimeout(() => {
|
|
268914
|
+
if (finished2) return;
|
|
268915
|
+
try {
|
|
268916
|
+
stderr.write(`[memorix] hook timed out after ${options.timeoutMs}ms
|
|
268917
|
+
`);
|
|
268918
|
+
} catch {
|
|
268919
|
+
}
|
|
268920
|
+
writeContinue(stdout2);
|
|
268921
|
+
exit(0);
|
|
268922
|
+
settle();
|
|
268923
|
+
}, options.timeoutMs);
|
|
268924
|
+
options.run().then(
|
|
268925
|
+
() => {
|
|
268926
|
+
if (finished2) return;
|
|
268927
|
+
exit(0);
|
|
268928
|
+
settle();
|
|
268929
|
+
},
|
|
268930
|
+
(error40) => {
|
|
268931
|
+
if (finished2) return;
|
|
268932
|
+
try {
|
|
268933
|
+
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
268934
|
+
stderr.write(`[memorix] hook failed: ${message}
|
|
268935
|
+
`);
|
|
268936
|
+
} catch {
|
|
268937
|
+
}
|
|
268938
|
+
writeContinue(stdout2);
|
|
268939
|
+
exit(0);
|
|
268940
|
+
settle();
|
|
268941
|
+
}
|
|
268942
|
+
);
|
|
268943
|
+
});
|
|
268944
|
+
}
|
|
268945
|
+
var DEFAULT_HOOK_TIMEOUT_MS, MIN_HOOK_TIMEOUT_MS, MAX_HOOK_TIMEOUT_MS, DEFAULT_HOOK_STDIN_TIMEOUT_MS, MIN_HOOK_STDIN_TIMEOUT_MS, MAX_HOOK_STDIN_TIMEOUT_MS;
|
|
268946
|
+
var init_lifecycle2 = __esm({
|
|
268947
|
+
"src/hooks/lifecycle.ts"() {
|
|
268948
|
+
"use strict";
|
|
268949
|
+
init_esm_shims();
|
|
268950
|
+
DEFAULT_HOOK_TIMEOUT_MS = 2e4;
|
|
268951
|
+
MIN_HOOK_TIMEOUT_MS = 1e3;
|
|
268952
|
+
MAX_HOOK_TIMEOUT_MS = 12e4;
|
|
268953
|
+
DEFAULT_HOOK_STDIN_TIMEOUT_MS = 3e3;
|
|
268954
|
+
MIN_HOOK_STDIN_TIMEOUT_MS = 100;
|
|
268955
|
+
MAX_HOOK_STDIN_TIMEOUT_MS = 3e4;
|
|
268956
|
+
}
|
|
268957
|
+
});
|
|
268958
|
+
|
|
268718
268959
|
// src/hooks/handler.ts
|
|
268719
268960
|
var handler_exports = {};
|
|
268720
268961
|
__export(handler_exports, {
|
|
@@ -269194,26 +269435,7 @@ function formatHookOutput(agent, rawEventName, output) {
|
|
|
269194
269435
|
return finalOutput;
|
|
269195
269436
|
}
|
|
269196
269437
|
async function runHook(agentOverride, eventOverride) {
|
|
269197
|
-
const rawInput = await
|
|
269198
|
-
const chunks = [];
|
|
269199
|
-
const finish = () => resolve6(Buffer.concat(chunks).toString("utf-8").trim());
|
|
269200
|
-
const timer = setTimeout(() => {
|
|
269201
|
-
process.stdin.removeAllListeners("data");
|
|
269202
|
-
process.stdin.removeAllListeners("end");
|
|
269203
|
-
finish();
|
|
269204
|
-
}, 3e3);
|
|
269205
|
-
process.stdin.on("data", (chunk) => {
|
|
269206
|
-
chunks.push(chunk);
|
|
269207
|
-
});
|
|
269208
|
-
process.stdin.on("end", () => {
|
|
269209
|
-
clearTimeout(timer);
|
|
269210
|
-
finish();
|
|
269211
|
-
});
|
|
269212
|
-
process.stdin.on("error", () => {
|
|
269213
|
-
clearTimeout(timer);
|
|
269214
|
-
finish();
|
|
269215
|
-
});
|
|
269216
|
-
});
|
|
269438
|
+
const rawInput = await readHookStdin(process.stdin, resolveHookStdinTimeoutMs());
|
|
269217
269439
|
if (!rawInput) {
|
|
269218
269440
|
process.stdout.write(JSON.stringify({ continue: true }));
|
|
269219
269441
|
return;
|
|
@@ -269263,7 +269485,7 @@ async function runHook(agentOverride, eventOverride) {
|
|
|
269263
269485
|
await initObservationStore2(dataDir);
|
|
269264
269486
|
await initMSStore(dataDir);
|
|
269265
269487
|
await initSessStore(dataDir);
|
|
269266
|
-
await initObservations2(dataDir);
|
|
269488
|
+
await initObservations2(dataDir, hookObservationRuntimeOptions(rawProject.rootPath));
|
|
269267
269489
|
await storeObservation2({ ...observation, projectId, sourceDetail: "hook" });
|
|
269268
269490
|
} catch (storeErr) {
|
|
269269
269491
|
console.error("[memorix] hook store failed:", storeErr?.message ?? storeErr);
|
|
@@ -269309,6 +269531,7 @@ var init_handler = __esm({
|
|
|
269309
269531
|
init_normalizer();
|
|
269310
269532
|
init_pattern_detector();
|
|
269311
269533
|
init_significance_filter();
|
|
269534
|
+
init_lifecycle2();
|
|
269312
269535
|
TYPE_EMOJI2 = {
|
|
269313
269536
|
"gotcha": "[GOTCHA]",
|
|
269314
269537
|
"decision": "[DECISION]",
|
|
@@ -269365,7 +269588,11 @@ var init_hook = __esm({
|
|
|
269365
269588
|
},
|
|
269366
269589
|
run: async ({ args }) => {
|
|
269367
269590
|
const { runHook: runHook2 } = await Promise.resolve().then(() => (init_handler(), handler_exports));
|
|
269368
|
-
await
|
|
269591
|
+
const { resolveHookTimeoutMs: resolveHookTimeoutMs2, runHookWithDeadline: runHookWithDeadline2 } = await Promise.resolve().then(() => (init_lifecycle2(), lifecycle_exports2));
|
|
269592
|
+
await runHookWithDeadline2({
|
|
269593
|
+
timeoutMs: resolveHookTimeoutMs2(),
|
|
269594
|
+
run: () => runHook2(args.agent, args.event)
|
|
269595
|
+
});
|
|
269369
269596
|
}
|
|
269370
269597
|
});
|
|
269371
269598
|
}
|
|
@@ -272131,7 +272358,7 @@ __export(agent_integrations_exports, {
|
|
|
272131
272358
|
repairAgentIntegrations: () => repairAgentIntegrations
|
|
272132
272359
|
});
|
|
272133
272360
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
272134
|
-
import { existsSync as existsSync28 } from "fs";
|
|
272361
|
+
import { existsSync as existsSync28, realpathSync as realpathSync2 } from "fs";
|
|
272135
272362
|
import { mkdir as mkdir8, readFile as readFile9, writeFile as writeFile9 } from "fs/promises";
|
|
272136
272363
|
import { basename as basename5, dirname as dirname8, resolve as resolve4 } from "path";
|
|
272137
272364
|
import { homedir as homedir34 } from "os";
|
|
@@ -272525,10 +272752,15 @@ function sanitizeServer(server) {
|
|
|
272525
272752
|
};
|
|
272526
272753
|
}
|
|
272527
272754
|
function normalizeProjectKey(projectRoot) {
|
|
272528
|
-
return
|
|
272755
|
+
return canonicalProjectPath(projectRoot).toLowerCase();
|
|
272529
272756
|
}
|
|
272530
272757
|
function defaultClaudeProjectKey(projectRoot) {
|
|
272531
|
-
return
|
|
272758
|
+
return canonicalProjectPath(projectRoot);
|
|
272759
|
+
}
|
|
272760
|
+
function canonicalProjectPath(projectRoot) {
|
|
272761
|
+
const resolved = resolve4(projectRoot);
|
|
272762
|
+
const canonical = existsSync28(resolved) ? realpathSync2(resolved) : resolved;
|
|
272763
|
+
return canonical.replace(/\\/g, "/");
|
|
272532
272764
|
}
|
|
272533
272765
|
function getClaudeLocalConfigPath() {
|
|
272534
272766
|
return `${homedir34()}/.claude.json`;
|
|
@@ -273137,6 +273369,7 @@ var init_doctor = __esm({
|
|
|
273137
273369
|
let bgRunning = false;
|
|
273138
273370
|
let bgPort = 0;
|
|
273139
273371
|
let bgPid = 0;
|
|
273372
|
+
let backgroundHealthy = false;
|
|
273140
273373
|
try {
|
|
273141
273374
|
if (existsSync33(bgStatePath)) {
|
|
273142
273375
|
const bgState = JSON.parse(readFileSync22(bgStatePath, "utf-8"));
|
|
@@ -273154,7 +273387,7 @@ var init_doctor = __esm({
|
|
|
273154
273387
|
lines.push(ok(`Background control plane running (PID ${bgPid}, port ${bgPort})`));
|
|
273155
273388
|
try {
|
|
273156
273389
|
const http3 = await import("http");
|
|
273157
|
-
|
|
273390
|
+
backgroundHealthy = await new Promise((resolve6) => {
|
|
273158
273391
|
const req = http3.request({ hostname: "127.0.0.1", port: bgPort, path: "/api/team", timeout: 3e3 }, (res) => {
|
|
273159
273392
|
res.resume();
|
|
273160
273393
|
resolve6(res.statusCode === 200);
|
|
@@ -273166,7 +273399,7 @@ var init_doctor = __esm({
|
|
|
273166
273399
|
});
|
|
273167
273400
|
req.end();
|
|
273168
273401
|
});
|
|
273169
|
-
if (
|
|
273402
|
+
if (backgroundHealthy) {
|
|
273170
273403
|
lines.push(ok("Health check: OK"));
|
|
273171
273404
|
} else {
|
|
273172
273405
|
lines.push(warn2("Health check: FAILED (process alive but not responding)"));
|
|
@@ -273174,8 +273407,9 @@ var init_doctor = __esm({
|
|
|
273174
273407
|
}
|
|
273175
273408
|
} catch {
|
|
273176
273409
|
lines.push(warn2("Health check: could not connect"));
|
|
273410
|
+
issues.push('Background process is alive but its health endpoint could not be reached. Try "memorix background restart".');
|
|
273177
273411
|
}
|
|
273178
|
-
report.mode = { type: "background", pid: bgPid, port: bgPort, healthy:
|
|
273412
|
+
report.mode = { type: "background", pid: bgPid, port: bgPort, healthy: backgroundHealthy };
|
|
273179
273413
|
} else {
|
|
273180
273414
|
lines.push(info2("Background control plane: not running"));
|
|
273181
273415
|
lines.push(info2("Current invocation: CLI (stdio)"));
|
|
@@ -273216,18 +273450,39 @@ var init_doctor = __esm({
|
|
|
273216
273450
|
report.embedding = { mode: "off", status: "disabled" };
|
|
273217
273451
|
} else {
|
|
273218
273452
|
lines.push(ok(`Mode: ${mode}`));
|
|
273219
|
-
|
|
273220
|
-
|
|
273221
|
-
|
|
273222
|
-
|
|
273223
|
-
|
|
273224
|
-
|
|
273225
|
-
|
|
273453
|
+
let controlPlaneEmbedding;
|
|
273454
|
+
if (bgRunning) {
|
|
273455
|
+
try {
|
|
273456
|
+
const response = await fetch(`http://127.0.0.1:${bgPort}/health`, { signal: AbortSignal.timeout(3e3) });
|
|
273457
|
+
if (response.ok) {
|
|
273458
|
+
const health = await response.json();
|
|
273459
|
+
controlPlaneEmbedding = health.embedding;
|
|
273460
|
+
}
|
|
273461
|
+
} catch {
|
|
273462
|
+
}
|
|
273463
|
+
}
|
|
273464
|
+
if (controlPlaneEmbedding?.status === "degraded") {
|
|
273465
|
+
const kind = controlPlaneEmbedding.failure?.kind ?? "upstream";
|
|
273466
|
+
const retryAfterMs = controlPlaneEmbedding.failure?.retryAfterMs;
|
|
273467
|
+
const retry2 = typeof retryAfterMs === "number" && retryAfterMs > 0 ? `; retry in ${Math.ceil(retryAfterMs / 1e3)}s` : "";
|
|
273468
|
+
lines.push(warn2(`Status: degraded in the running control plane (${kind}${retry2})`));
|
|
273469
|
+
lines.push(info2("Search: degraded to BM25 fulltext until the provider recovers"));
|
|
273470
|
+
issues.push("The running control plane has an unavailable embedding provider. Check provider credentials, billing, or connectivity.");
|
|
273471
|
+
report.embedding = { mode, status: "degraded", failure: kind };
|
|
273226
273472
|
} else {
|
|
273227
|
-
|
|
273228
|
-
|
|
273229
|
-
|
|
273230
|
-
|
|
273473
|
+
const { getEmbeddingProvider: getEmbeddingProvider2 } = await Promise.resolve().then(() => (init_provider(), provider_exports));
|
|
273474
|
+
const provider2 = await getEmbeddingProvider2();
|
|
273475
|
+
if (provider2) {
|
|
273476
|
+
lines.push(ok(`Provider: ${provider2.name} (${provider2.dimensions}d)`));
|
|
273477
|
+
lines.push(ok("Status: ready"));
|
|
273478
|
+
lines.push(info2("Search: hybrid (BM25 + vector)"));
|
|
273479
|
+
report.embedding = { mode, status: "ready", provider: provider2.name, dimensions: provider2.dimensions };
|
|
273480
|
+
} else {
|
|
273481
|
+
lines.push(warn2("Status: temporarily unavailable"));
|
|
273482
|
+
lines.push(info2("Search: degraded to BM25 fulltext (no vector similarity)"));
|
|
273483
|
+
issues.push(`Embedding mode is "${mode}" but provider failed to initialize. Check API keys/connectivity.`);
|
|
273484
|
+
report.embedding = { mode, status: "temporarily_unavailable" };
|
|
273485
|
+
}
|
|
273231
273486
|
}
|
|
273232
273487
|
try {
|
|
273233
273488
|
const cachePath = join34(memorixDir, "embedding-cache.json");
|