@echomem/mcp 1.4.48 → 1.4.49
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/dist/local-data-paths.js +68 -29
- package/dist/migrate.js +2 -5
- package/dist/setup.js +25 -3
- package/package.json +1 -1
package/dist/local-data-paths.js
CHANGED
|
@@ -85,41 +85,80 @@ export function resolveClaudeProjectsDir(opts = {}) {
|
|
|
85
85
|
const root = configuredRoot("CLAUDE_CONFIG_DIR", ".claude", opts);
|
|
86
86
|
return resolveReadableDirectory(root ? path.join(root, "projects") : null);
|
|
87
87
|
}
|
|
88
|
-
/**
|
|
89
|
-
|
|
90
|
-
*
|
|
91
|
-
* Cowork does not write into the normal `~/.claude/projects` profile. Claude Desktop creates an
|
|
92
|
-
* OS-specific support directory and stores each local-agent session below
|
|
93
|
-
* `local-agent-mode-sessions/<org>/<conversation>/local_<id>/`. The actual transcript is nested
|
|
94
|
-
* again under that sandbox's `.claude/projects` directory.
|
|
95
|
-
*/
|
|
96
|
-
export function resolveClaudeCoworkSessionsDir(opts = {}) {
|
|
88
|
+
/** Resolve every readable Claude Desktop support directory, including Windows Store/MSIX data. */
|
|
89
|
+
export function resolveClaudeDesktopSupportRoots(opts = {}) {
|
|
97
90
|
const homeDir = normalizedHomeDir(opts.homeDir ?? os.homedir());
|
|
98
91
|
if (!homeDir)
|
|
99
|
-
return
|
|
92
|
+
return [];
|
|
100
93
|
const env = opts.env ?? process.env;
|
|
101
94
|
const configured = env.CLAUDE_DESKTOP_SUPPORT_DIR;
|
|
102
|
-
|
|
95
|
+
const platform = opts.platform ?? process.platform;
|
|
96
|
+
const candidates = [];
|
|
103
97
|
if (typeof configured === "string" && configured.trim()) {
|
|
104
|
-
|
|
98
|
+
candidates.push(expandCurrentUserHome(configured, homeDir));
|
|
105
99
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
100
|
+
if (platform === "darwin") {
|
|
101
|
+
candidates.push(path.join(homeDir, "Library", "Application Support", "Claude"));
|
|
102
|
+
}
|
|
103
|
+
else if (platform === "win32") {
|
|
104
|
+
const appData = typeof env.APPDATA === "string" && env.APPDATA.trim()
|
|
105
|
+
? expandCurrentUserHome(env.APPDATA, homeDir)
|
|
106
|
+
: path.join(homeDir, "AppData", "Roaming");
|
|
107
|
+
if (appData)
|
|
108
|
+
candidates.push(path.join(appData, "Claude"));
|
|
109
|
+
const localAppData = typeof env.LOCALAPPDATA === "string" && env.LOCALAPPDATA.trim()
|
|
110
|
+
? expandCurrentUserHome(env.LOCALAPPDATA, homeDir)
|
|
111
|
+
: path.join(homeDir, "AppData", "Local");
|
|
112
|
+
if (localAppData) {
|
|
113
|
+
const packagesRoot = path.join(localAppData, "Packages");
|
|
114
|
+
try {
|
|
115
|
+
for (const entry of fs.readdirSync(packagesRoot, { withFileTypes: true })) {
|
|
116
|
+
if (!entry.isDirectory() || !/^Claude_/i.test(entry.name))
|
|
117
|
+
continue;
|
|
118
|
+
candidates.push(path.join(packagesRoot, entry.name, "LocalCache", "Roaming", "Claude"));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
/* A non-Store install has no Packages directory. */
|
|
123
|
+
}
|
|
122
124
|
}
|
|
123
125
|
}
|
|
124
|
-
|
|
126
|
+
else {
|
|
127
|
+
const configHome = typeof env.XDG_CONFIG_HOME === "string" && env.XDG_CONFIG_HOME.trim()
|
|
128
|
+
? expandCurrentUserHome(env.XDG_CONFIG_HOME, homeDir)
|
|
129
|
+
: path.join(homeDir, ".config");
|
|
130
|
+
if (configHome)
|
|
131
|
+
candidates.push(path.join(configHome, "Claude"));
|
|
132
|
+
}
|
|
133
|
+
const roots = [];
|
|
134
|
+
const seenRealpaths = new Set();
|
|
135
|
+
for (const candidate of candidates) {
|
|
136
|
+
const resolved = resolveReadableDirectory(candidate);
|
|
137
|
+
if (!resolved || seenRealpaths.has(resolved))
|
|
138
|
+
continue;
|
|
139
|
+
seenRealpaths.add(resolved);
|
|
140
|
+
roots.push(resolved);
|
|
141
|
+
}
|
|
142
|
+
return roots;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Resolve every Claude Desktop Cowork sandbox root. Cowork transcripts live below
|
|
146
|
+
* `local-agent-mode-sessions/<org>/<conversation>/local_<id>/.claude/projects`; Windows Store
|
|
147
|
+
* installs can have several private Claude package containers below `Packages`.
|
|
148
|
+
*/
|
|
149
|
+
export function resolveClaudeCoworkSessionRoots(opts = {}) {
|
|
150
|
+
const roots = [];
|
|
151
|
+
const seenRealpaths = new Set();
|
|
152
|
+
for (const supportRoot of resolveClaudeDesktopSupportRoots(opts)) {
|
|
153
|
+
const resolved = resolveReadableDirectory(path.join(supportRoot, "local-agent-mode-sessions"));
|
|
154
|
+
if (!resolved || seenRealpaths.has(resolved))
|
|
155
|
+
continue;
|
|
156
|
+
seenRealpaths.add(resolved);
|
|
157
|
+
roots.push(resolved);
|
|
158
|
+
}
|
|
159
|
+
return roots;
|
|
160
|
+
}
|
|
161
|
+
/** Backward-compatible first-root resolver. New discovery code should scan every returned root. */
|
|
162
|
+
export function resolveClaudeCoworkSessionsDir(opts = {}) {
|
|
163
|
+
return resolveClaudeCoworkSessionRoots(opts)[0] ?? null;
|
|
125
164
|
}
|
package/dist/migrate.js
CHANGED
|
@@ -29,7 +29,7 @@ import axios from "axios";
|
|
|
29
29
|
import { KeyStore, echoConfigDir } from "./keystore.js";
|
|
30
30
|
import { fetchEncryptionConfig } from "./encryption.js";
|
|
31
31
|
import { discoverCodexSessionFiles } from "./codex-session-files.js";
|
|
32
|
-
import {
|
|
32
|
+
import { resolveClaudeCoworkSessionRoots, resolveClaudeProjectsDir } from "./local-data-paths.js";
|
|
33
33
|
import { eachJsonLine, walkLocalFiles } from "./local-jsonl.js";
|
|
34
34
|
const API_BASE = (process.env.ECHO_API_BASE_URL || "https://echo-mem-chrome.vercel.app").replace(/\/$/, "");
|
|
35
35
|
const RATE_MAX = 28; // stay under the import-jobs /run limit of 30 / 60s
|
|
@@ -232,10 +232,7 @@ function claudeSessionCandidates(opts = {}) {
|
|
|
232
232
|
// Supplying an explicit Claude root is an isolated discovery request (tests, diagnostics, or a
|
|
233
233
|
// moved profile). Callers can still add Cowork roots explicitly. Normal onboarding supplies no
|
|
234
234
|
// roots, so the platform-default Cowork directory is included automatically.
|
|
235
|
-
const
|
|
236
|
-
? resolveClaudeCoworkSessionsDir()
|
|
237
|
-
: null;
|
|
238
|
-
const coworkRoots = opts.coworkRoots ?? (defaultCoworkRoot ? [defaultCoworkRoot] : []);
|
|
235
|
+
const coworkRoots = opts.coworkRoots ?? (opts.claudeRoot === undefined ? resolveClaudeCoworkSessionRoots() : []);
|
|
239
236
|
for (const root of coworkRoots) {
|
|
240
237
|
for (const filePath of userCreatedClaudeFiles(root)) {
|
|
241
238
|
const conversationId = coworkConversationId(filePath, root);
|
package/dist/setup.js
CHANGED
|
@@ -30,6 +30,7 @@ import { cmdMigrate, applyAccountImportStatus, applyFastAccountImportStatus, dis
|
|
|
30
30
|
import { syncCodexUsage } from "./codex-sync.js";
|
|
31
31
|
import { renderSetupPage } from "./setup-page.js";
|
|
32
32
|
import { parseSetupPreviewState } from "./setup-preview.js";
|
|
33
|
+
import { resolveClaudeDesktopSupportRoots } from "./local-data-paths.js";
|
|
33
34
|
import { installSaveCheckpointHooks, installSourceSessionHooks } from "./hud/hooks.js";
|
|
34
35
|
import { MCP_PACKAGE_LABEL, MCP_PACKAGE_NAME, MCP_PACKAGE_VERSION, MCP_UPDATE_ALL_COMMAND, MCP_UPDATE_COMMAND } from "./package-metadata.js";
|
|
35
36
|
import { checkLatestUpdateStatus, compareSemver, readCachedUpdateStatus } from "./update-check.js";
|
|
@@ -220,10 +221,18 @@ export function knownClients() {
|
|
|
220
221
|
const appSupport = process.platform === "darwin"
|
|
221
222
|
? home("Library", "Application Support")
|
|
222
223
|
: process.env.APPDATA || home(".config");
|
|
224
|
+
const defaultClaudeDesktopRoot = path.join(appSupport, "Claude");
|
|
225
|
+
const claudeDesktopRoots = resolveClaudeDesktopSupportRoots();
|
|
226
|
+
const claudeDesktopClients = (claudeDesktopRoots.length > 0 ? claudeDesktopRoots : [defaultClaudeDesktopRoot]).map((supportRoot) => ({
|
|
227
|
+
id: "claude-desktop",
|
|
228
|
+
label: "Claude Desktop",
|
|
229
|
+
kind: "json",
|
|
230
|
+
configPath: path.join(supportRoot, "claude_desktop_config.json"),
|
|
231
|
+
}));
|
|
223
232
|
return [
|
|
224
233
|
{ id: "cursor", label: "Cursor", kind: "json", configPath: home(".cursor", "mcp.json") },
|
|
225
234
|
{ id: "windsurf", label: "Windsurf", kind: "json", configPath: home(".codeium", "windsurf", "mcp_config.json") },
|
|
226
|
-
|
|
235
|
+
...claudeDesktopClients,
|
|
227
236
|
{ id: "claude-code", label: "Claude Code", kind: "snippet", note: "run: claude mcp add-json -s user echomem '<entry>' (or add to .mcp.json)" },
|
|
228
237
|
{ id: "codex", label: "Codex", kind: "command", detectDir: codexHome(), configPath: path.join(codexHome(), "config.toml"), note: "add to ~/.codex/config.toml under [mcp_servers.echomem]" },
|
|
229
238
|
];
|
|
@@ -236,7 +245,7 @@ export function detectClients() {
|
|
|
236
245
|
if (c.kind === "command")
|
|
237
246
|
return fs.existsSync(c.detectDir);
|
|
238
247
|
if (c.id === "claude-code")
|
|
239
|
-
return
|
|
248
|
+
return claudeCodeCliAvailable();
|
|
240
249
|
return false;
|
|
241
250
|
});
|
|
242
251
|
}
|
|
@@ -655,6 +664,19 @@ function execClaudeCodeSync(args, options, commandCandidates) {
|
|
|
655
664
|
}
|
|
656
665
|
throw lastError;
|
|
657
666
|
}
|
|
667
|
+
export function claudeCodeCliAvailable() {
|
|
668
|
+
try {
|
|
669
|
+
execClaudeCodeSync(["--version"], {
|
|
670
|
+
encoding: "utf8",
|
|
671
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
672
|
+
timeout: 3000,
|
|
673
|
+
});
|
|
674
|
+
return true;
|
|
675
|
+
}
|
|
676
|
+
catch {
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
658
680
|
export function writeClaudeCodeConfig(entry, options = {}) {
|
|
659
681
|
// EchoMem belongs at user scope so every Claude Code project resolves the same durable runtime.
|
|
660
682
|
// Older CLI versions wrote local/project entries, which take precedence over user scope and can
|
|
@@ -2817,7 +2839,7 @@ function selectSetupTargets(requested, all) {
|
|
|
2817
2839
|
return fs.existsSync(path.dirname(client.configPath));
|
|
2818
2840
|
if (client.kind === "command")
|
|
2819
2841
|
return fs.existsSync(client.detectDir);
|
|
2820
|
-
return client.id === "claude-code" &&
|
|
2842
|
+
return client.id === "claude-code" && claudeCodeCliAvailable();
|
|
2821
2843
|
});
|
|
2822
2844
|
}
|
|
2823
2845
|
return requested ? knownClients().filter((client) => client.id === requested) : detectClients();
|