@pcircle/memesh 4.8.5 → 4.9.0
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/mcp.json +6 -4
- package/.codex-plugin/plugin.json +1 -1
- package/AGENTS.md +60 -14
- package/README.de.md +83 -556
- package/README.md +83 -582
- package/README.zh-TW.md +84 -573
- package/dashboard/dist/index.html +10 -10
- package/dist/cli/view-live.d.ts.map +1 -1
- package/dist/cli/view-live.js +154 -384
- package/dist/cli/view-live.js.map +1 -1
- package/dist/core/agent-router.d.ts +11 -10
- package/dist/core/agent-router.d.ts.map +1 -1
- package/dist/core/agent-router.js +29 -14
- package/dist/core/agent-router.js.map +1 -1
- package/dist/core/agent-scope-id.d.ts.map +1 -1
- package/dist/core/agent-scope-id.js.map +1 -1
- package/dist/core/analytics.d.ts.map +1 -1
- package/dist/core/analytics.js.map +1 -1
- package/dist/core/config.d.ts +4 -40
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +75 -141
- package/dist/core/config.js.map +1 -1
- package/dist/core/demo.d.ts.map +1 -1
- package/dist/core/demo.js +6 -6
- package/dist/core/demo.js.map +1 -1
- package/dist/core/doctor.d.ts +1 -6
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +55 -227
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/dreamer.d.ts +32 -47
- package/dist/core/dreamer.d.ts.map +1 -1
- package/dist/core/dreamer.js +211 -703
- package/dist/core/dreamer.js.map +1 -1
- package/dist/core/install-channel.d.ts.map +1 -1
- package/dist/core/install-channel.js +4 -47
- package/dist/core/install-channel.js.map +1 -1
- package/dist/core/install-id.d.ts.map +1 -1
- package/dist/core/install-id.js.map +1 -1
- package/dist/core/kg-backfill.d.ts.map +1 -1
- package/dist/core/kg-backfill.js.map +1 -1
- package/dist/core/lesson-engine.d.ts +0 -5
- package/dist/core/lesson-engine.d.ts.map +1 -1
- package/dist/core/lesson-engine.js +0 -25
- package/dist/core/lesson-engine.js.map +1 -1
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +54 -48
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/core/memory-tool.d.ts.map +1 -1
- package/dist/core/memory-tool.js +17 -17
- package/dist/core/memory-tool.js.map +1 -1
- package/dist/core/operations.d.ts +2 -26
- package/dist/core/operations.d.ts.map +1 -1
- package/dist/core/operations.js +9 -244
- package/dist/core/operations.js.map +1 -1
- package/dist/core/paths.d.ts +4 -1
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +88 -14
- package/dist/core/paths.js.map +1 -1
- package/dist/core/product-improvements.js +2 -2
- package/dist/core/product-improvements.js.map +1 -1
- package/dist/core/schema-export.d.ts.map +1 -1
- package/dist/core/schema-export.js +10 -0
- package/dist/core/schema-export.js.map +1 -1
- package/dist/core/semver.d.ts +7 -0
- package/dist/core/semver.d.ts.map +1 -0
- package/dist/core/semver.js +49 -0
- package/dist/core/semver.js.map +1 -0
- package/dist/core/serializer.d.ts.map +1 -1
- package/dist/core/serializer.js +69 -57
- package/dist/core/serializer.js.map +1 -1
- package/dist/core/signal-scorer.d.ts.map +1 -1
- package/dist/core/signal-scorer.js.map +1 -1
- package/dist/core/transcript-extractor.d.ts +1 -85
- package/dist/core/transcript-extractor.d.ts.map +1 -1
- package/dist/core/transcript-extractor.js +5 -364
- package/dist/core/transcript-extractor.js.map +1 -1
- package/dist/core/transcript-source.d.ts +22 -6
- package/dist/core/transcript-source.d.ts.map +1 -1
- package/dist/core/transcript-source.js +108 -69
- package/dist/core/transcript-source.js.map +1 -1
- package/dist/core/types.d.ts +1 -17
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/version-check.d.ts.map +1 -1
- package/dist/core/version-check.js +11 -1
- package/dist/core/version-check.js.map +1 -1
- package/dist/db.d.ts +0 -34
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +3 -287
- package/dist/db.js.map +1 -1
- package/dist/host-runtime/acp.d.ts.map +1 -1
- package/dist/host-runtime/acp.js +2 -2
- package/dist/host-runtime/acp.js.map +1 -1
- package/dist/host-runtime/claude.d.ts.map +1 -1
- package/dist/host-runtime/claude.js +9 -7
- package/dist/host-runtime/claude.js.map +1 -1
- package/dist/host-runtime/codex-session.d.ts +9 -1
- package/dist/host-runtime/codex-session.d.ts.map +1 -1
- package/dist/host-runtime/codex-session.js +474 -29
- package/dist/host-runtime/codex-session.js.map +1 -1
- package/dist/host-runtime/codex.d.ts.map +1 -1
- package/dist/host-runtime/codex.js +2 -2
- package/dist/host-runtime/codex.js.map +1 -1
- package/dist/host-runtime/config.d.ts +1 -0
- package/dist/host-runtime/config.d.ts.map +1 -1
- package/dist/host-runtime/config.js +4 -0
- package/dist/host-runtime/config.js.map +1 -1
- package/dist/host-runtime/router-client.d.ts.map +1 -1
- package/dist/host-runtime/router-client.js +62 -15
- package/dist/host-runtime/router-client.js.map +1 -1
- package/dist/host-runtime/router.js +2 -2
- package/dist/host-runtime/router.js.map +1 -1
- package/dist/knowledge-graph.d.ts.map +1 -1
- package/dist/knowledge-graph.js +54 -45
- package/dist/knowledge-graph.js.map +1 -1
- package/dist/mcp/THIRD_PARTY_NOTICES.txt +217 -0
- package/dist/mcp/server.js +30685 -38
- package/dist/mcp/server.js.map +6 -1
- package/dist/skills-manifest.json +22 -22
- package/dist/storage/entity-index.d.ts +0 -1
- package/dist/storage/entity-index.d.ts.map +1 -1
- package/dist/storage/entity-index.js +0 -7
- package/dist/storage/entity-index.js.map +1 -1
- package/dist/storage/fts-index.d.ts.map +1 -1
- package/dist/storage/fts-index.js +6 -7
- package/dist/storage/fts-index.js.map +1 -1
- package/dist/storage/graph-repairs.d.ts +0 -5
- package/dist/storage/graph-repairs.d.ts.map +1 -1
- package/dist/storage/graph-repairs.js +4 -91
- package/dist/storage/graph-repairs.js.map +1 -1
- package/dist/storage/schema.d.ts +1 -1
- package/dist/storage/schema.d.ts.map +1 -1
- package/dist/storage/schema.js +1 -2
- package/dist/storage/schema.js.map +1 -1
- package/dist/storage/sqlite.d.ts +0 -1
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/transports/agent-messaging.d.ts.map +1 -1
- package/dist/transports/agent-messaging.js +5 -7
- package/dist/transports/agent-messaging.js.map +1 -1
- package/dist/transports/cli/cli.d.ts.map +1 -1
- package/dist/transports/cli/cli.js +52 -674
- package/dist/transports/cli/cli.js.map +1 -1
- package/dist/transports/http/retired-routes.js +1 -1
- package/dist/transports/http/retired-routes.js.map +1 -1
- package/dist/transports/http/server.d.ts.map +1 -1
- package/dist/transports/http/server.js +13 -232
- package/dist/transports/http/server.js.map +1 -1
- package/dist/transports/mcp/handlers.d.ts +127 -1
- package/dist/transports/mcp/handlers.d.ts.map +1 -1
- package/dist/transports/mcp/handlers.js +53 -4
- package/dist/transports/mcp/handlers.js.map +1 -1
- package/dist/transports/schemas.d.ts +52 -0
- package/dist/transports/schemas.d.ts.map +1 -1
- package/dist/transports/schemas.js +39 -0
- package/dist/transports/schemas.js.map +1 -1
- package/docs/platforms/README.md +5 -4
- package/docs/platforms/agent-messaging.md +124 -60
- package/hooks/hooks.json +13 -2
- package/llms-install.md +62 -30
- package/package.json +4 -5
- package/scripts/hooks/_generated/core-paths.js +88 -14
- package/scripts/hooks/_generated/fts-index.js +6 -7
- package/scripts/hooks/_generated/schema.js +1 -2
- package/scripts/hooks/_shared.js +14 -20
- package/scripts/hooks/session-start.js +8 -6
- package/scripts/hooks/session-summary.js +19 -374
- package/skills/memesh/SKILL.md +19 -14
- package/skills/memesh-review/SKILL.md +7 -6
- package/dist/core/auto-tagger.d.ts +0 -10
- package/dist/core/auto-tagger.d.ts.map +0 -1
- package/dist/core/auto-tagger.js +0 -63
- package/dist/core/auto-tagger.js.map +0 -1
- package/dist/core/conflict-candidates.d.ts +0 -20
- package/dist/core/conflict-candidates.d.ts.map +0 -1
- package/dist/core/conflict-candidates.js +0 -71
- package/dist/core/conflict-candidates.js.map +0 -1
- package/dist/core/conflict-judge.d.ts +0 -58
- package/dist/core/conflict-judge.d.ts.map +0 -1
- package/dist/core/conflict-judge.js +0 -189
- package/dist/core/conflict-judge.js.map +0 -1
- package/dist/core/digest-validator.d.ts +0 -18
- package/dist/core/digest-validator.d.ts.map +0 -1
- package/dist/core/digest-validator.js +0 -85
- package/dist/core/digest-validator.js.map +0 -1
- package/dist/core/embedder.d.ts +0 -20
- package/dist/core/embedder.d.ts.map +0 -1
- package/dist/core/embedder.js +0 -245
- package/dist/core/embedder.js.map +0 -1
- package/dist/core/failure-analyzer.d.ts +0 -19
- package/dist/core/failure-analyzer.d.ts.map +0 -1
- package/dist/core/failure-analyzer.js +0 -83
- package/dist/core/failure-analyzer.js.map +0 -1
- package/dist/core/json-utils.d.ts +0 -3
- package/dist/core/json-utils.d.ts.map +0 -1
- package/dist/core/json-utils.js +0 -46
- package/dist/core/json-utils.js.map +0 -1
- package/dist/core/llm-client.d.ts +0 -22
- package/dist/core/llm-client.d.ts.map +0 -1
- package/dist/core/llm-client.js +0 -203
- package/dist/core/llm-client.js.map +0 -1
- package/dist/core/llm-telemetry.d.ts +0 -47
- package/dist/core/llm-telemetry.d.ts.map +0 -1
- package/dist/core/llm-telemetry.js +0 -117
- package/dist/core/llm-telemetry.js.map +0 -1
- package/dist/core/llm-validator.d.ts +0 -20
- package/dist/core/llm-validator.d.ts.map +0 -1
- package/dist/core/llm-validator.js +0 -231
- package/dist/core/llm-validator.js.map +0 -1
- package/dist/core/ollama-host.d.ts +0 -6
- package/dist/core/ollama-host.d.ts.map +0 -1
- package/dist/core/ollama-host.js +0 -62
- package/dist/core/ollama-host.js.map +0 -1
- package/dist/core/output-language.d.ts +0 -6
- package/dist/core/output-language.d.ts.map +0 -1
- package/dist/core/output-language.js +0 -25
- package/dist/core/output-language.js.map +0 -1
- package/dist/core/prompt-safety.d.ts +0 -4
- package/dist/core/prompt-safety.d.ts.map +0 -1
- package/dist/core/prompt-safety.js +0 -20
- package/dist/core/prompt-safety.js.map +0 -1
- package/dist/storage/vector-index.d.ts +0 -3
- package/dist/storage/vector-index.d.ts.map +0 -1
- package/dist/storage/vector-index.js +0 -13
- package/dist/storage/vector-index.js.map +0 -1
package/dist/core/doctor.js
CHANGED
|
@@ -4,22 +4,16 @@ import path from 'path';
|
|
|
4
4
|
import net from 'node:net';
|
|
5
5
|
import { createHash } from 'crypto';
|
|
6
6
|
import { createRequire } from 'module';
|
|
7
|
-
import { pathToFileURL } from 'url';
|
|
8
7
|
import { execFileSync } from 'child_process';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { probeProvider } from './llm-validator.js';
|
|
12
|
-
import { openDatabase, closeDatabase, getPendingReindexInfo, isDatabaseOpen, readVectorGeneration, generationRowIds, } from '../db.js';
|
|
8
|
+
import { findRetiredConfigKeys, getConfigPath, readConfig } from './config.js';
|
|
9
|
+
import { openDatabase, closeDatabase, isDatabaseOpen, } from '../db.js';
|
|
13
10
|
import { getUpdateCheck } from './version-check.js';
|
|
14
11
|
import { classifyBump } from './updater.js';
|
|
15
12
|
import { getCurrentInstallChannel, getInstallChannelSupport, detectPluginHost, pluginHostConfigRoot, versionedPluginCacheRoots, PLUGIN_REFRESH_COMMANDS, } from './install-channel.js';
|
|
16
13
|
import { getInstallRecord } from './install-id.js';
|
|
17
14
|
import { citationRulePath, citationRuleState } from './citation-rule.js';
|
|
18
|
-
import { getDbPath, getMemeshDirFromDbPath, homeDir, memeshDir
|
|
15
|
+
import { getAgentRouterSocketPath, getDbPath, getMemeshDirFromDbPath, homeDir, memeshDir } from './paths.js';
|
|
19
16
|
import { detectPluginRuntime, readInstallMarker } from './install-hooks.js';
|
|
20
|
-
import { lastTranscriptMineAt } from './transcript-source.js';
|
|
21
|
-
import { countMissingVectors } from './operations.js';
|
|
22
|
-
import { hasVectorIndex } from '../storage/vector-index.js';
|
|
23
17
|
import { UNSPACED_SCRIPT_GLOB_RUN3 } from '../storage/fts-index.js';
|
|
24
18
|
import { MemeshDatabase } from '../storage/sqlite.js';
|
|
25
19
|
import { AUTO_CAPTURE_TAG } from './types.js';
|
|
@@ -28,8 +22,6 @@ import { autoCaptureDecision } from './capture-flag.js';
|
|
|
28
22
|
import { guardFromMetadata } from './guards.js';
|
|
29
23
|
import { getAgentMessageStorageReport } from './agent-message-storage.js';
|
|
30
24
|
import { readHostConfigFile } from '../host-runtime/config.js';
|
|
31
|
-
import { summariseTelemetry } from './llm-telemetry.js';
|
|
32
|
-
const EMBEDDING_PROBE_TIMEOUT_MS = 15000;
|
|
33
25
|
const EXPECTED_HOOK_TYPES = ['PreToolUse', 'SessionStart', 'PostToolUse', 'Stop', 'PreCompact'];
|
|
34
26
|
const AGENT_MESSAGE_STORAGE_QUOTA_ENV = 'MEMESH_AGENT_MESSAGE_STORAGE_QUOTA_BYTES';
|
|
35
27
|
const LOCALE_README_FILES = [
|
|
@@ -154,9 +146,9 @@ function inspectCodexSessionSetup(codexPluginCacheDetected, existsSyncImpl) {
|
|
|
154
146
|
return null;
|
|
155
147
|
const configPath = path.join(getMemeshDirFromDbPath(), 'hosts', 'codex-session.json');
|
|
156
148
|
if (existsSyncImpl(configPath)) {
|
|
157
|
-
return
|
|
149
|
+
return createInfo('codex-session-setup', 'Codex ordinary-session notifications', 'A Codex identity override file is present and will be validated at SessionStart. A valid override applies only in its configured workspace; other Codex plugin sessions use automatic thread-scoped identities. A cached plugin copy does not prove a live registration; use `memesh message discover --project <project>` to read current presence.');
|
|
158
150
|
}
|
|
159
|
-
return
|
|
151
|
+
return createInfo('codex-session-setup', 'Codex ordinary-session notifications', 'No explicit identity override is configured. When the Codex plugin is enabled, each startup or resumed thread registers automatically under a thread-scoped identity. A cached plugin copy does not prove a live registration; use `memesh message discover --project <project>` to read current presence.');
|
|
160
152
|
}
|
|
161
153
|
function configuredAgentMessageStoragePolicy(explicit) {
|
|
162
154
|
if (explicit !== undefined)
|
|
@@ -195,14 +187,10 @@ function parseJsonFile(filePath, readFileSyncImpl) {
|
|
|
195
187
|
};
|
|
196
188
|
}
|
|
197
189
|
}
|
|
198
|
-
function inspectConfigFile(existsSyncImpl, readFileSyncImpl, getConfigPathImpl
|
|
190
|
+
function inspectConfigFile(existsSyncImpl, readFileSyncImpl, getConfigPathImpl) {
|
|
199
191
|
const configPath = getConfigPathImpl();
|
|
200
192
|
if (!existsSyncImpl(configPath)) {
|
|
201
|
-
return createCheck('config', 'Config', 'pass',
|
|
202
|
-
? `No config file yet (${configPath}), but your environment names ${envLlm.provider}${envLlm.apiKey ? ' (via its API key)' : ' (via OLLAMA_HOST)'}, which enables Smart Mode. A file is only needed to pin a provider or change defaults.`
|
|
203
|
-
: `No config file yet (${configPath}). MeMesh will run in Core mode until you configure Smart Mode.`, envLlm
|
|
204
|
-
? `Optional: \`memesh config set llm.provider ${envLlm.provider}\` pins it so it does not depend on which shell you run from.`
|
|
205
|
-
: 'Optional: run `memesh config list` or set an LLM with `memesh config set llm.provider anthropic`.');
|
|
193
|
+
return createCheck('config', 'Config', 'pass', `No config file yet (${configPath}); default settings are in effect.`, 'Optional: run memesh config list to inspect settings.');
|
|
206
194
|
}
|
|
207
195
|
try {
|
|
208
196
|
const raw = readFileSyncImpl(configPath, 'utf8');
|
|
@@ -210,11 +198,21 @@ function inspectConfigFile(existsSyncImpl, readFileSyncImpl, getConfigPathImpl,
|
|
|
210
198
|
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
211
199
|
return createCheck('config', 'Config', 'fail', `${configPath} parsed but is not a JSON object — every setting is being ignored.`, `Fix or remove ${configPath}, then re-run memesh doctor.`, { code: 'config-parse.not-object', params: { path: configPath } });
|
|
212
200
|
}
|
|
201
|
+
const retiredKeys = findRetiredConfigKeys(parsed);
|
|
202
|
+
if (retiredKeys.length > 0) {
|
|
203
|
+
const keys = retiredKeys.join(', ');
|
|
204
|
+
return createCheck('config', 'Config', 'warn', `${configPath} is valid JSON but still contains ${retiredKeys.length} retired top-level setting(s) (${keys}). ` +
|
|
205
|
+
'This version ignores them, but legacy provider credentials or settings may remain on disk.', `Review ${configPath} locally and remove only those retired top-level keys. ` +
|
|
206
|
+
'Do not paste the file into an issue because it may contain credentials. Then run memesh doctor again.', {
|
|
207
|
+
code: 'config-parse.retired-settings',
|
|
208
|
+
params: { path: configPath, count: retiredKeys.length, keys },
|
|
209
|
+
});
|
|
210
|
+
}
|
|
213
211
|
return createCheck('config', 'Config', 'pass', `${configPath} is valid JSON and its settings are in effect.`);
|
|
214
212
|
}
|
|
215
213
|
catch (err) {
|
|
216
214
|
const msg = err instanceof Error ? err.message : String(err);
|
|
217
|
-
return createCheck('config', 'Config', 'fail', `${configPath} could not be read or parsed (${msg}).
|
|
215
|
+
return createCheck('config', 'Config', 'fail', `${configPath} could not be read or parsed (${msg}). Its settings are being ignored right now.`, `Fix the JSON or remove the file to fall back to defaults: mv ${configPath} ${configPath}.bak`, { code: 'config-parse.unreadable', params: { path: configPath, detail: msg } });
|
|
218
216
|
}
|
|
219
217
|
}
|
|
220
218
|
const MCP_PLACEHOLDER = '${CLAUDE_PLUGIN_ROOT}';
|
|
@@ -552,19 +550,11 @@ function defaultResolveShellMemesh() {
|
|
|
552
550
|
return null;
|
|
553
551
|
}
|
|
554
552
|
}
|
|
555
|
-
|
|
556
|
-
function defaultNativeBindingProbe(packageRoot) {
|
|
553
|
+
function defaultNativeBindingProbe(_packageRoot) {
|
|
557
554
|
try {
|
|
558
|
-
const probe = new MemeshDatabase(':memory:'
|
|
555
|
+
const probe = new MemeshDatabase(':memory:');
|
|
559
556
|
try {
|
|
560
|
-
|
|
561
|
-
return { ok: false, message: `${RUNTIME_TOO_OLD}: node:sqlite in ${process.version} has no enableLoadExtension` };
|
|
562
|
-
}
|
|
563
|
-
probe.enableLoadExtension(true);
|
|
564
|
-
const localRequire = createRequire(pathToFileURL(path.join(packageRoot, 'package.json')).href);
|
|
565
|
-
const sqliteVec = localRequire('sqlite-vec');
|
|
566
|
-
sqliteVec.load(probe);
|
|
567
|
-
probe.prepare('SELECT vec_version()').get();
|
|
557
|
+
probe.prepare('SELECT 1').get();
|
|
568
558
|
}
|
|
569
559
|
finally {
|
|
570
560
|
probe.close();
|
|
@@ -629,17 +619,9 @@ export function hasBuiltInSqlite() {
|
|
|
629
619
|
}
|
|
630
620
|
function inspectNativeBinding(packageRoot, _existsSyncImpl, probeImpl = defaultNativeBindingProbe) {
|
|
631
621
|
const result = probeImpl(packageRoot);
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
if (result.message.startsWith(RUNTIME_TOO_OLD)) {
|
|
636
|
-
return createCheck('native-binding', 'SQLite and vector search', 'fail', `The node:sqlite in this Node (${process.version}) is too old for memesh — it cannot load the vector-search extension. The complete version arrived in Node 22.13.`, 'Upgrade Node to 22.13 or newer, then re-run `memesh doctor`.', { code: 'native-binding.node-too-old', params: { version: process.version } });
|
|
637
|
-
}
|
|
638
|
-
const isMissingPackage = /MODULE_NOT_FOUND|Cannot find module/i.test(result.message);
|
|
639
|
-
if (isMissingPackage) {
|
|
640
|
-
return createCheck('native-binding', 'SQLite and vector search', 'warn', 'sqlite-vec is not installed, so memesh cannot search by meaning. Memories are still saved, and still found by keyword.', 'Run: npm install (in the directory that depends on @pcircle/memesh)', { code: 'native-binding.not-installed' });
|
|
641
|
-
}
|
|
642
|
-
return createCheck('native-binding', 'SQLite and vector search', 'warn', `sqlite-vec could not be loaded: ${result.message}. Memories are still saved and found by keyword; only search by meaning is off.`, `Run: cd "${packageRoot}" && npm install --omit=dev`, { code: 'native-binding.load-failed', params: { detail: result.message, root: packageRoot } });
|
|
622
|
+
return result.ok
|
|
623
|
+
? createCheck('native-binding', 'SQLite', 'pass', 'node:sqlite opened a database (probe succeeded).')
|
|
624
|
+
: createCheck('native-binding', 'SQLite', 'fail', `SQLite could not open a database: ${result.message}`, 'Check the Node runtime and reinstall if necessary.', { code: 'native-binding.load-failed', params: { detail: result.message, root: packageRoot } });
|
|
643
625
|
}
|
|
644
626
|
function readVersionFromInstalledBinary(binaryPath, existsSyncImpl, readFileSyncImpl, realpathSyncImpl = fs.realpathSync) {
|
|
645
627
|
let resolved;
|
|
@@ -677,29 +659,19 @@ function inspectShellCli(installChannel, packageRoot, packageVersion, resolveShe
|
|
|
677
659
|
}
|
|
678
660
|
if (hasDistinctShellCli) {
|
|
679
661
|
const shellVersion = readVersionFromInstalledBinary(shellPath, existsSyncImpl, readFileSyncImpl);
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
? `Update this install (a ${installChannel}) to ${shellVersion} or newer via its own channel — see \`memesh status\`.`
|
|
689
|
-
: pluginHost
|
|
690
|
-
? `Run \`${PLUGIN_REFRESH_COMMANDS[pluginHost]}\` to bring this plugin copy to ${shellVersion} (or newer).`
|
|
691
|
-
: `Bring this plugin copy to ${shellVersion} (or newer) with your host's refresh command — `
|
|
692
|
-
+ `Claude Code: \`${PLUGIN_REFRESH_COMMANDS['claude-code']}\`; `
|
|
693
|
-
+ `Codex: \`${PLUGIN_REFRESH_COMMANDS.codex}\`.`;
|
|
694
|
-
return createCheck('shell-cli', 'Shell CLI on PATH', 'warn', `\`memesh\` resolves to ${shellPath} (separate from this install at ${packageRoot}), and it is running ${shellVersion} — ahead of this install's ${packageVersion}.`, fix);
|
|
695
|
-
}
|
|
696
|
-
return createCheck('shell-cli', 'Shell CLI on PATH', 'pass', `\`memesh\` resolves to ${shellPath} (separate from this install at ${packageRoot}). Both paths coexist and share the same DB`
|
|
697
|
-
+ (shellVersion ? `, both on ${packageVersion}.` : ' — could not read the shell copy\'s own version to compare.'));
|
|
662
|
+
if (shellVersion) {
|
|
663
|
+
return {
|
|
664
|
+
...createInfo('shell-cli', 'Shell CLI on PATH', `Installed versions: this interface ${packageVersion}; terminal ${shellVersion}.`),
|
|
665
|
+
code: 'shell-cli.versions',
|
|
666
|
+
params: { current: packageVersion, terminal: shellVersion, shellPath: shellPath, packageRoot },
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
return createCheck('shell-cli', 'Shell CLI on PATH', 'pass', `\`memesh\` resolves to ${shellPath} (separate from this install at ${packageRoot}) — could not read the shell copy's own version to compare.`);
|
|
698
670
|
}
|
|
699
671
|
if (installChannel === 'plugin-marketplace') {
|
|
700
672
|
const host = detectPluginHost(packageRoot) === 'codex' ? 'Codex CLI' : 'Claude Code';
|
|
701
673
|
return createCheck('shell-cli', 'Shell CLI on PATH', 'warn', 'Plugin is installed but `memesh` is not on the shell PATH. Typing `memesh` in a regular terminal will report `command not found`. '
|
|
702
|
-
+ `${host} MCP / hooks / \`/memesh\` skill still work — this only affects standalone shell usage and other MCP clients (Cursor, Cline, etc.).`, 'Run `npm install -g @pcircle/memesh`
|
|
674
|
+
+ `${host} MCP / hooks / \`/memesh\` skill still work — this only affects standalone shell usage and other MCP clients (Cursor, Cline, etc.).`, 'Run `npm install -g @pcircle/memesh` if you want the separate shell CLI. Its database path depends on its environment and configuration.', { code: 'shell-cli.not-on-path' });
|
|
703
675
|
}
|
|
704
676
|
return createCheck('shell-cli', 'Shell CLI on PATH', 'pass', shellPath
|
|
705
677
|
? `\`memesh\` resolves to ${shellPath}.`
|
|
@@ -892,32 +864,23 @@ function inspectPluginCacheCurrency(installChannel, pluginHost, packageRoot, ins
|
|
|
892
864
|
}
|
|
893
865
|
return createCheck('plugin-cache', `Plugin cache source record is current (${hostLabel})`, 'warn', `The plugin cache records commit ${installedSha.slice(0, 8)}, but the marketplace has moved to ${marketplaceSha.slice(0, 8)} under the same version — ${hostLabel} does not normally refresh a cache whose version did not change, so refresh the cache before relying on the newer marketplace code.`, `Run \`${command}\` to refresh the cache in place, then restart ${hostLabel}.`, { code: 'plugin-cache.stale', params: { installed: installedSha.slice(0, 8), marketplace: marketplaceSha.slice(0, 8), host: hostLabel, command } });
|
|
894
866
|
}
|
|
895
|
-
function
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
const skewNote = `This npm-global install is on ${runningVersion}; the ${hostLabel} plugin cache is on ${discoveredVersion}. `
|
|
901
|
-
+ 'The plugin marketplace\'s own auto-updater only ever refreshes its plugin copy — it cannot and will not update this separate npm-global install.';
|
|
902
|
-
const skewFix = `Run \`memesh update\` to bring this npm-global install to ${discoveredVersion} (or newer) — it does not update itself automatically.`;
|
|
903
|
-
amended = {
|
|
904
|
-
...amended,
|
|
905
|
-
status: amended.status === 'pass' ? 'warn' : amended.status,
|
|
906
|
-
summary: `${amended.summary} ${skewNote}`,
|
|
907
|
-
fix: amended.fix ? `${amended.fix} Also: ${skewFix}` : skewFix,
|
|
908
|
-
code: undefined,
|
|
909
|
-
params: undefined,
|
|
910
|
-
};
|
|
867
|
+
function isClaudeChannelCommand(command) {
|
|
868
|
+
if (command === 'memesh-host-claude')
|
|
869
|
+
return true;
|
|
870
|
+
if (typeof command !== 'string' || !path.isAbsolute(command) || path.basename(command) !== 'memesh-host-claude') {
|
|
871
|
+
return false;
|
|
911
872
|
}
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
873
|
+
try {
|
|
874
|
+
const target = fs.realpathSync(command);
|
|
875
|
+
const stat = fs.statSync(target);
|
|
876
|
+
if (!stat.isFile())
|
|
877
|
+
return false;
|
|
878
|
+
fs.accessSync(target, fs.constants.X_OK);
|
|
879
|
+
return true;
|
|
880
|
+
}
|
|
881
|
+
catch {
|
|
882
|
+
return false;
|
|
919
883
|
}
|
|
920
|
-
return amended;
|
|
921
884
|
}
|
|
922
885
|
function inspectClaudeChannelRegistration(existsSyncImpl, readFileSyncImpl) {
|
|
923
886
|
const configPath = path.join(homeDir(), '.claude.json');
|
|
@@ -967,14 +930,15 @@ function inspectClaudeChannelRegistration(existsSyncImpl, readFileSyncImpl) {
|
|
|
967
930
|
targetConfigValid = false;
|
|
968
931
|
}
|
|
969
932
|
}
|
|
970
|
-
const
|
|
933
|
+
const commandValid = isClaudeChannelCommand(command);
|
|
934
|
+
const coherent = commandValid
|
|
971
935
|
&& args !== null
|
|
972
936
|
&& args.length === 2
|
|
973
937
|
&& configIndex === 0
|
|
974
938
|
&& target !== null
|
|
975
939
|
&& targetConfigValid;
|
|
976
940
|
if (!coherent) {
|
|
977
|
-
const reason =
|
|
941
|
+
const reason = !commandValid || args === null || configIndex !== 0 || target === null
|
|
978
942
|
? 'the command or --config declaration is malformed'
|
|
979
943
|
: 'the declared owner config target is missing, insecure, malformed, or incomplete';
|
|
980
944
|
return createCheck('claude-channel', 'Claude Channel registration', 'warn', `The user-scoped memesh-channel registration is present but ${reason}. Live Claude Channel notification is not established.`, 'Remove and re-register the owner-controlled memesh-channel entry with `memesh agent setup claude`; keep its generated config file owner-private.');
|
|
@@ -1197,8 +1161,7 @@ function inspectMessageCapability(packageRoot, enabled, probe) {
|
|
|
1197
1161
|
return createCheck('message-capability', 'Message adapter imports', 'fail', `Installed message capability probe failed: ${result.message}.`, 'Reinstall or rebuild this package, then retry with MEMESH_DOCTOR_PROBE_MESSAGE_CAPABILITY=1.', { code: 'message-capability.probe-failed', params: { detail: result.message } });
|
|
1198
1162
|
}
|
|
1199
1163
|
async function defaultMessageRouterStatusProbe() {
|
|
1200
|
-
const socketPath = process.env.MEMESH_ROUTER_SOCKET
|
|
1201
|
-
?? path.join(getMemeshDirFromDbPath(), 'agent-router.sock');
|
|
1164
|
+
const socketPath = process.env.MEMESH_ROUTER_SOCKET ?? getAgentRouterSocketPath();
|
|
1202
1165
|
let stat;
|
|
1203
1166
|
try {
|
|
1204
1167
|
stat = fs.lstatSync(socketPath);
|
|
@@ -1245,81 +1208,6 @@ async function inspectMessageRouterStatus(enabled, probe) {
|
|
|
1245
1208
|
return createCheck('message-router-status', 'Live message router / host registration', 'warn', `An owner-private router socket exists at ${result.socket_path}, but it did not accept a local connection. No host registration or native delivery is verified.`, 'Check the owner-configured `memesh-router` process, then run this opt-in probe again.', { code: 'message-router.socket-unreachable', params: { path: result.socket_path } });
|
|
1246
1209
|
}
|
|
1247
1210
|
}
|
|
1248
|
-
async function inspectEmbeddingProbe(capabilities, probeCapabilities, embedTextImpl) {
|
|
1249
|
-
if (capabilities.embeddings === 'tfidf') {
|
|
1250
|
-
return createInfo('embeddings_probe', 'Embeddings work', 'No neural embedder configured — recall runs on FTS5 keyword search alone. That is a supported mode, not a fault.');
|
|
1251
|
-
}
|
|
1252
|
-
if (!probeCapabilities) {
|
|
1253
|
-
return createInfo('embeddings_probe', 'Embeddings work', `NOT VERIFIED. Config names "${capabilities.embeddings}", but generating a test embedding is a network call (billed on hosted providers) so it was not made — a revoked key or an unreachable host would look identical to a healthy setup here.`, 'Run: memesh doctor --probe (generates one test embedding to confirm)');
|
|
1254
|
-
}
|
|
1255
|
-
let timer;
|
|
1256
|
-
try {
|
|
1257
|
-
const vector = await Promise.race([
|
|
1258
|
-
embedTextImpl('memesh doctor embedding probe'),
|
|
1259
|
-
new Promise((_, reject) => {
|
|
1260
|
-
timer = setTimeout(() => reject(new Error(`no response within ${EMBEDDING_PROBE_TIMEOUT_MS / 1000}s`)), EMBEDDING_PROBE_TIMEOUT_MS);
|
|
1261
|
-
}),
|
|
1262
|
-
]);
|
|
1263
|
-
if (!vector || vector.length === 0) {
|
|
1264
|
-
return createCheck('embeddings_probe', 'Embeddings work', 'warn', `Config selects "${capabilities.embeddings}" but generating a test embedding returned nothing. Semantic recall is degraded to FTS5-only; keyword search still works.`, 'Run: memesh doctor --probe for detail, or check network access to the embedding provider.', { code: 'embeddings.empty', params: { provider: String(capabilities.embeddings) } });
|
|
1265
|
-
}
|
|
1266
|
-
return createCheck('embeddings_probe', 'Embeddings work', 'pass', `Generated a ${vector.length}-dim test embedding via "${capabilities.embeddings}".`);
|
|
1267
|
-
}
|
|
1268
|
-
catch (err) {
|
|
1269
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1270
|
-
return createCheck('embeddings_probe', 'Embeddings work', 'warn', `Config selects "${capabilities.embeddings}" but the embedder threw (${msg}). Semantic recall is degraded to FTS5-only.`, 'Check the embedding provider is reachable (e.g. run `ollama serve`), or remove embedder config to use keyword-only search.', { code: 'embeddings.threw', params: { provider: String(capabilities.embeddings), detail: msg } });
|
|
1271
|
-
}
|
|
1272
|
-
finally {
|
|
1273
|
-
clearTimeout(timer);
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1276
|
-
const LLM_TELEMETRY_HEALTH_WINDOW_DAYS = 7;
|
|
1277
|
-
const LLM_TELEMETRY_HEALTH_MIN_CALLS = 3;
|
|
1278
|
-
function inspectLlmTelemetryHealth(db, windowDays = LLM_TELEMETRY_HEALTH_WINDOW_DAYS, minCalls = LLM_TELEMETRY_HEALTH_MIN_CALLS) {
|
|
1279
|
-
let summaries;
|
|
1280
|
-
try {
|
|
1281
|
-
summaries = summariseTelemetry(windowDays, db);
|
|
1282
|
-
}
|
|
1283
|
-
catch {
|
|
1284
|
-
return undefined;
|
|
1285
|
-
}
|
|
1286
|
-
if (summaries.length === 0)
|
|
1287
|
-
return undefined;
|
|
1288
|
-
const broken = summaries
|
|
1289
|
-
.filter((s) => s.total_calls >= minCalls && s.successes === 0)
|
|
1290
|
-
.sort((a, b) => b.total_calls - a.total_calls);
|
|
1291
|
-
if (broken.length > 0) {
|
|
1292
|
-
const detail = broken.map((s) => `${s.flow} (${s.total_calls} call${s.total_calls === 1 ? '' : 's'}, 0 succeeded)`).join(', ');
|
|
1293
|
-
return createCheck('llm_telemetry_health', 'AI feature health', 'warn', `${broken.length} AI-backed feature${broken.length === 1 ? '' : 's'} failed every call in the last `
|
|
1294
|
-
+ `${windowDays} days: ${detail}. Those features are silently doing nothing.`, 'Run `memesh telemetry` for the full per-flow detail, then check the model/provider configured for '
|
|
1295
|
-
+ 'the failing flow. `memesh doctor --probe` confirms whether it answers a live call.', { code: 'llm-telemetry.silent-failure', params: { count: broken.length, detail, windowDays } });
|
|
1296
|
-
}
|
|
1297
|
-
const totalCalls = summaries.reduce((n, s) => n + s.total_calls, 0);
|
|
1298
|
-
const totalSuccesses = summaries.reduce((n, s) => n + s.successes, 0);
|
|
1299
|
-
const rate = totalCalls > 0 ? Math.round((totalSuccesses / totalCalls) * 100) : 100;
|
|
1300
|
-
return createInfo('llm_telemetry_health', 'AI feature health', `${summaries.length} AI-backed flow${summaries.length === 1 ? '' : 's'} made ${totalCalls} call(s) in the `
|
|
1301
|
-
+ `last ${windowDays} days; ${rate}% succeeded.`);
|
|
1302
|
-
}
|
|
1303
|
-
async function inspectLlmProbe(capabilities, probeCapabilities, probeProviderImpl) {
|
|
1304
|
-
const llm = capabilities.llm;
|
|
1305
|
-
if (!llm) {
|
|
1306
|
-
return createInfo('llm_probe', 'LLM reachable', 'No LLM configured — Core Mode. Write-side features (lessons, auto-tag, dream) are off by design.');
|
|
1307
|
-
}
|
|
1308
|
-
if (!probeCapabilities) {
|
|
1309
|
-
return createInfo('llm_probe', 'LLM reachable', `NOT VERIFIED. Config names ${llm.provider} (${llm.model ?? 'default'}), but no live call was made — an expired key or an unreachable host would look identical to a healthy setup here.`, 'Run: memesh doctor --probe (makes one small live call to confirm)');
|
|
1310
|
-
}
|
|
1311
|
-
try {
|
|
1312
|
-
const result = await probeProviderImpl(llm.provider, llm.apiKey);
|
|
1313
|
-
if (result.valid) {
|
|
1314
|
-
return createCheck('llm_probe', 'LLM reachable', 'pass', `${llm.provider} answered a live probe.`);
|
|
1315
|
-
}
|
|
1316
|
-
return createCheck('llm_probe', 'LLM reachable', 'fail', `${llm.provider} is configured but did not answer: ${result.error ?? 'unknown error'}. Every LLM-backed feature is silently doing nothing.`, 'Check the API key / host, then re-run: memesh doctor --probe', { code: 'llm.unreachable', params: { provider: llm.provider, detail: result.error ?? 'unknown error' } });
|
|
1317
|
-
}
|
|
1318
|
-
catch (err) {
|
|
1319
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1320
|
-
return createCheck('llm_probe', 'LLM reachable', 'fail', `${llm.provider} probe threw: ${msg}. Every LLM-backed feature is silently doing nothing.`, 'Check the API key / host, then re-run: memesh doctor --probe', { code: 'llm.threw', params: { provider: llm.provider, detail: msg } });
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
1211
|
function summarizeOverallStatus(checks) {
|
|
1324
1212
|
const assertions = checks.filter((check) => !check.informational);
|
|
1325
1213
|
if (assertions.some((check) => check.status === 'fail'))
|
|
@@ -1329,7 +1217,7 @@ function summarizeOverallStatus(checks) {
|
|
|
1329
1217
|
return 'PASS';
|
|
1330
1218
|
}
|
|
1331
1219
|
export async function runDoctor(options) {
|
|
1332
|
-
const { packageRoot, packageVersion, probeHttp = false,
|
|
1220
|
+
const { packageRoot, packageVersion, probeHttp = false, httpBaseUrl = 'http://127.0.0.1:3737', platform = process.platform, envImpl = process.env, openDatabaseImpl = openDatabase, closeDatabaseImpl = closeDatabase, isDatabaseOpenImpl = isDatabaseOpen, getConfigPathImpl = getConfigPath, getUpdateCheckImpl = getUpdateCheck, getCurrentInstallChannelImpl = getCurrentInstallChannel, installedPluginsPathImpl, marketplaceHeadShaImpl = defaultMarketplaceHeadSha, pluginCacheDiscoveryImpl, getInstallChannelSupportImpl = getInstallChannelSupport, existsSyncImpl = fs.existsSync, readFileSyncImpl = fs.readFileSync, statSyncImpl = fs.statSync, fetchImpl = fetch, agentMessageStoragePolicy, nativeBindingProbeImpl, resolveShellMemeshImpl = defaultResolveShellMemesh, probeMessageCapability = process.env.MEMESH_DOCTOR_PROBE_MESSAGE_CAPABILITY === '1', messageCapabilityProbeImpl = probeInstalledMessageCapability, probeMessageRouterStatus = process.env.MEMESH_DOCTOR_PROBE_MESSAGE_ROUTER === '1', messageRouterStatusProbeImpl = defaultMessageRouterStatusProbe, } = options;
|
|
1333
1221
|
const wasDbOpenBeforeUs = isDatabaseOpenImpl();
|
|
1334
1222
|
const safeCloseDatabaseImpl = wasDbOpenBeforeUs
|
|
1335
1223
|
? () => undefined
|
|
@@ -1365,46 +1253,6 @@ export async function runDoctor(options) {
|
|
|
1365
1253
|
`automatic rebuild cannot notice. Re-run doctor after the rebuild: this count should be 0.`, `Run 'memesh reindex --fts' to rebuild the keyword index.`, { code: 'fts.unsegmented', params: { count: unsegmented.c } }, 'fts-rebuild'));
|
|
1366
1254
|
}
|
|
1367
1255
|
}
|
|
1368
|
-
const pendingReindex = getPendingReindexInfo();
|
|
1369
|
-
const vectorDb = db;
|
|
1370
|
-
let missingVectors;
|
|
1371
|
-
let vectorsPossible = true;
|
|
1372
|
-
try {
|
|
1373
|
-
vectorsPossible = hasVectorIndex(vectorDb);
|
|
1374
|
-
missingVectors = vectorsPossible ? countMissingVectors(vectorDb) : 0;
|
|
1375
|
-
}
|
|
1376
|
-
catch {
|
|
1377
|
-
missingVectors = null;
|
|
1378
|
-
}
|
|
1379
|
-
const payableDebt = pendingReindex && !(pendingReindex.reason === 'vectors-missing' && !vectorsPossible);
|
|
1380
|
-
if (payableDebt || missingVectors === null || missingVectors > 0) {
|
|
1381
|
-
const owed = pendingReindex && pendingReindex.reason !== 'vectors-missing'
|
|
1382
|
-
? 'Search index needs rebuilding (embedding configuration changed)'
|
|
1383
|
-
: missingVectors === null
|
|
1384
|
-
? 'The vector index could not be read, so how much of your memory semantic recall can see is unknown'
|
|
1385
|
-
: `${missingVectors} memor${missingVectors === 1 ? 'y has' : 'ies have'} no search vector, `
|
|
1386
|
-
+ 'so semantic recall cannot find them (keyword search still works)';
|
|
1387
|
-
const noEmbedderConfigured = detectCapabilitiesImpl().embeddings === 'tfidf';
|
|
1388
|
-
const vectorIndexFix = noEmbedderConfigured
|
|
1389
|
-
? `No embedder is configured, so reindex has nothing to embed with — run 'memesh config set embedder.provider ollama' (or 'openai') first, then 'memesh reindex'.`
|
|
1390
|
-
: `Run 'memesh reindex' to fix. This will restore full search functionality.`;
|
|
1391
|
-
dbChecks.push(createCheck('vector_index', 'Vector Index', 'warn', owed, vectorIndexFix, {
|
|
1392
|
-
code: noEmbedderConfigured ? 'vector-index.stale-no-embedder' : 'vector-index.stale',
|
|
1393
|
-
params: { missing: missingVectors ?? -1 },
|
|
1394
|
-
}));
|
|
1395
|
-
}
|
|
1396
|
-
const generation = readVectorGeneration();
|
|
1397
|
-
if (generation.state !== 'none') {
|
|
1398
|
-
const staged = generationRowIds().size;
|
|
1399
|
-
const detail = generation.state === 'open'
|
|
1400
|
-
? `${staged} vectors staged at ${generation.info.dimension} dimensions `
|
|
1401
|
-
+ `(provider ${generation.info.provider}, started ${generation.info.startedAt})`
|
|
1402
|
-
: `${staged} vectors staged, but the marker cannot be read (${generation.detail})`;
|
|
1403
|
-
dbChecks.push(createCheck('vector_generation', 'Half-built search index', 'warn', `An unfinished index rebuild is holding disk space: ${detail}.`, generation.state === 'open'
|
|
1404
|
-
? `Run 'memesh reindex' to finish it (the vectors already produced are reused), `
|
|
1405
|
-
+ `or 'memesh reindex --discard-generation' to reclaim the space.`
|
|
1406
|
-
: `Run 'memesh reindex --discard-generation' to clear it, then 'memesh reindex'.`, { code: 'vector-generation.open', params: { staged } }));
|
|
1407
|
-
}
|
|
1408
1256
|
try {
|
|
1409
1257
|
const guardRows = db
|
|
1410
1258
|
.prepare(`SELECT id, name, metadata FROM entities
|
|
@@ -1472,9 +1320,6 @@ export async function runDoctor(options) {
|
|
|
1472
1320
|
dbChecks.push(createInfo('citation_compliance', 'Memory citation rate', `${cited} of ${citationTotal} session(s) with injected memories cited at least one (${rate}%).`));
|
|
1473
1321
|
}
|
|
1474
1322
|
}
|
|
1475
|
-
const llmTelemetryHealth = inspectLlmTelemetryHealth(db);
|
|
1476
|
-
if (llmTelemetryHealth)
|
|
1477
|
-
dbChecks.push(llmTelemetryHealth);
|
|
1478
1323
|
}
|
|
1479
1324
|
catch (err) {
|
|
1480
1325
|
const message = err instanceof Error ? err.message : 'unknown database error';
|
|
@@ -1541,7 +1386,7 @@ export async function runDoctor(options) {
|
|
|
1541
1386
|
catch {
|
|
1542
1387
|
}
|
|
1543
1388
|
}
|
|
1544
|
-
checks.push(inspectConfigFile(existsSyncImpl, readFileSyncImpl, getConfigPathImpl
|
|
1389
|
+
checks.push(inspectConfigFile(existsSyncImpl, readFileSyncImpl, getConfigPathImpl));
|
|
1545
1390
|
checks.push(inspectMcpConfig(packageRoot, install, existsSyncImpl, readFileSyncImpl, envImpl));
|
|
1546
1391
|
checks.push(...inspectHooksConfig(packageRoot, platform, existsSyncImpl, readFileSyncImpl, statSyncImpl));
|
|
1547
1392
|
const pluginHost = detectPluginHost(packageRoot);
|
|
@@ -1561,12 +1406,9 @@ export async function runDoctor(options) {
|
|
|
1561
1406
|
codexPluginCacheDetected = true;
|
|
1562
1407
|
if (discovered.host === 'claude-code')
|
|
1563
1408
|
claudePluginCacheDetected = true;
|
|
1564
|
-
|
|
1409
|
+
const check = discovered.unverifiableReason
|
|
1565
1410
|
? pluginCacheUnverifiable(discovered.host, discovered.unverifiableReason)
|
|
1566
1411
|
: inspectPluginCacheCurrency('plugin-marketplace', discovered.host, discovered.packageRoot, discovered.installedPluginsPath, readFileSyncImpl, existsSyncImpl, marketplaceHeadShaImpl);
|
|
1567
|
-
if (check && !discovered.unverifiableReason) {
|
|
1568
|
-
check = annotateNpmGlobalPluginCacheVersion(check, discovered.packageRoot, discovered.host === 'codex' ? 'Codex' : 'Claude Code', packageVersion);
|
|
1569
|
-
}
|
|
1570
1412
|
if (check) {
|
|
1571
1413
|
const hostName = discovered.host;
|
|
1572
1414
|
const index = (discoveredCounts.get(discovered.host) ?? 0) + 1;
|
|
@@ -1592,20 +1434,6 @@ export async function runDoctor(options) {
|
|
|
1592
1434
|
checks.push(verifySkillsManifest(packageRoot, existsSyncImpl, readFileSyncImpl, installSupport));
|
|
1593
1435
|
checks.push(inspectMessageCapability(packageRoot, probeMessageCapability, messageCapabilityProbeImpl));
|
|
1594
1436
|
checks.push(await inspectMessageRouterStatus(probeMessageRouterStatus, messageRouterStatusProbeImpl));
|
|
1595
|
-
const capabilities = detectCapabilitiesImpl();
|
|
1596
|
-
checks.push(createInfo('capabilities', 'Capabilities (configured)', `Search level ${capabilities.searchLevel} (${capabilities.searchLevel === 1 ? 'Smart Mode' : 'Core'}); embeddings: ${capabilities.embeddings}; LLM: ${capabilities.llm ? `${capabilities.llm.provider} (${capabilities.llm.model ?? 'default'})` : 'not configured'}. Configured values only — see the probe rows below for what actually works.`));
|
|
1597
|
-
if (!isTranscriptMiningEnabled()) {
|
|
1598
|
-
checks.push(createInfo('transcript-mining', 'Scheduled transcript mining', 'Off (opt-in). memesh can mine this project\'s Claude Code session transcripts for decisions and lessons and STAGE them for your review. Turn it on with `memesh config set transcriptMining true`, then have a scheduler (cron/launchd) run `memesh dream run --from-transcripts --if-due` — it self-throttles and stages only, so nothing enters your graph without `dream accept`.'));
|
|
1599
|
-
}
|
|
1600
|
-
else {
|
|
1601
|
-
const last = lastTranscriptMineAt(getProjectName(process.cwd()));
|
|
1602
|
-
const when = last === null
|
|
1603
|
-
? 'not yet run for this project'
|
|
1604
|
-
: `last mined ${((Date.now() - last) / 3600_000).toFixed(1)}h ago`;
|
|
1605
|
-
checks.push(createInfo('transcript-mining', 'Scheduled transcript mining', `On for this project — ${when}. Have a scheduler run \`memesh dream run --from-transcripts --if-due\`; it mines when due (default every 24h) and stages proposals. Review the queue with \`memesh dream list\`.`));
|
|
1606
|
-
}
|
|
1607
|
-
checks.push(await inspectEmbeddingProbe(capabilities, probeCapabilities, embedTextImpl));
|
|
1608
|
-
checks.push(await inspectLlmProbe(capabilities, probeCapabilities, probeProviderImpl));
|
|
1609
1437
|
checks.push(await inspectUpdateStatus(packageVersion, getUpdateCheckImpl, installSupport));
|
|
1610
1438
|
try {
|
|
1611
1439
|
const record = getInstallRecord();
|