codemolt-mcp 0.4.0 → 0.5.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/README.md +3 -3
- package/dist/index.js +279 -356
- package/dist/lib/analyzer.d.ts +2 -0
- package/dist/lib/analyzer.js +225 -0
- package/dist/lib/fs-utils.d.ts +9 -0
- package/dist/lib/fs-utils.js +147 -0
- package/dist/lib/platform.d.ts +6 -0
- package/dist/lib/platform.js +50 -0
- package/dist/lib/registry.d.ts +13 -0
- package/dist/lib/registry.js +48 -0
- package/dist/lib/types.d.ts +47 -0
- package/dist/lib/types.js +1 -0
- package/dist/scanners/aider.d.ts +2 -0
- package/dist/scanners/aider.js +130 -0
- package/dist/scanners/claude-code.d.ts +2 -0
- package/dist/scanners/claude-code.js +187 -0
- package/dist/scanners/codex.d.ts +2 -0
- package/dist/scanners/codex.js +142 -0
- package/dist/scanners/continue-dev.d.ts +2 -0
- package/dist/scanners/continue-dev.js +134 -0
- package/dist/scanners/cursor.d.ts +2 -0
- package/dist/scanners/cursor.js +219 -0
- package/dist/scanners/index.d.ts +1 -0
- package/dist/scanners/index.js +22 -0
- package/dist/scanners/vscode-copilot.d.ts +2 -0
- package/dist/scanners/vscode-copilot.js +177 -0
- package/dist/scanners/warp.d.ts +2 -0
- package/dist/scanners/warp.js +20 -0
- package/dist/scanners/windsurf.d.ts +2 -0
- package/dist/scanners/windsurf.js +171 -0
- package/dist/scanners/zed.d.ts +2 -0
- package/dist/scanners/zed.js +119 -0
- package/package.json +6 -4
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import { getHome, getPlatform } from "../lib/platform.js";
|
|
3
|
+
import { listFiles, safeReadJson, safeStats } from "../lib/fs-utils.js";
|
|
4
|
+
// Zed editor stores AI assistant conversations in:
|
|
5
|
+
// macOS: ~/Library/Application Support/Zed/conversations/
|
|
6
|
+
// ~/.config/zed/conversations/
|
|
7
|
+
// Linux: ~/.config/zed/conversations/
|
|
8
|
+
// Windows: %APPDATA%/Zed/conversations/
|
|
9
|
+
export const zedScanner = {
|
|
10
|
+
name: "Zed",
|
|
11
|
+
sourceType: "zed",
|
|
12
|
+
description: "Zed editor AI assistant conversations",
|
|
13
|
+
getSessionDirs() {
|
|
14
|
+
const home = getHome();
|
|
15
|
+
const platform = getPlatform();
|
|
16
|
+
const candidates = [];
|
|
17
|
+
if (platform === "macos") {
|
|
18
|
+
candidates.push(path.join(home, "Library", "Application Support", "Zed", "conversations"));
|
|
19
|
+
}
|
|
20
|
+
if (platform === "windows") {
|
|
21
|
+
const appData = process.env.APPDATA || path.join(home, "AppData", "Roaming");
|
|
22
|
+
candidates.push(path.join(appData, "Zed", "conversations"));
|
|
23
|
+
}
|
|
24
|
+
candidates.push(path.join(home, ".config", "zed", "conversations"));
|
|
25
|
+
return candidates.filter((d) => {
|
|
26
|
+
try {
|
|
27
|
+
return require("fs").existsSync(d);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
scan(limit) {
|
|
35
|
+
const sessions = [];
|
|
36
|
+
const dirs = this.getSessionDirs();
|
|
37
|
+
for (const dir of dirs) {
|
|
38
|
+
const jsonFiles = listFiles(dir, [".json", ".zed"], true);
|
|
39
|
+
for (const filePath of jsonFiles) {
|
|
40
|
+
const stats = safeStats(filePath);
|
|
41
|
+
if (!stats || stats.size < 100)
|
|
42
|
+
continue;
|
|
43
|
+
const data = safeReadJson(filePath);
|
|
44
|
+
if (!data)
|
|
45
|
+
continue;
|
|
46
|
+
const turns = extractZedTurns(data);
|
|
47
|
+
if (turns.length < 2)
|
|
48
|
+
continue;
|
|
49
|
+
const humanMsgs = turns.filter((t) => t.role === "human");
|
|
50
|
+
const preview = humanMsgs[0]?.content.slice(0, 200) || "(zed session)";
|
|
51
|
+
sessions.push({
|
|
52
|
+
id: path.basename(filePath).replace(/\.\w+$/, ""),
|
|
53
|
+
source: "zed",
|
|
54
|
+
project: data.project || path.basename(path.dirname(filePath)),
|
|
55
|
+
title: data.title || preview.slice(0, 80),
|
|
56
|
+
messageCount: turns.length,
|
|
57
|
+
humanMessages: humanMsgs.length,
|
|
58
|
+
aiMessages: turns.length - humanMsgs.length,
|
|
59
|
+
preview,
|
|
60
|
+
filePath,
|
|
61
|
+
modifiedAt: stats.mtime,
|
|
62
|
+
sizeBytes: stats.size,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return sessions.slice(0, limit);
|
|
67
|
+
},
|
|
68
|
+
parse(filePath, maxTurns) {
|
|
69
|
+
const data = safeReadJson(filePath);
|
|
70
|
+
if (!data)
|
|
71
|
+
return null;
|
|
72
|
+
const stats = safeStats(filePath);
|
|
73
|
+
const turns = extractZedTurns(data, maxTurns);
|
|
74
|
+
if (turns.length === 0)
|
|
75
|
+
return null;
|
|
76
|
+
const humanMsgs = turns.filter((t) => t.role === "human");
|
|
77
|
+
const aiMsgs = turns.filter((t) => t.role === "assistant");
|
|
78
|
+
return {
|
|
79
|
+
id: path.basename(filePath).replace(/\.\w+$/, ""),
|
|
80
|
+
source: "zed",
|
|
81
|
+
project: data.project || path.basename(path.dirname(filePath)),
|
|
82
|
+
title: data.title || humanMsgs[0]?.content.slice(0, 80) || "Zed session",
|
|
83
|
+
messageCount: turns.length,
|
|
84
|
+
humanMessages: humanMsgs.length,
|
|
85
|
+
aiMessages: aiMsgs.length,
|
|
86
|
+
preview: humanMsgs[0]?.content.slice(0, 200) || "",
|
|
87
|
+
filePath,
|
|
88
|
+
modifiedAt: stats?.mtime || new Date(),
|
|
89
|
+
sizeBytes: stats?.size || 0,
|
|
90
|
+
turns,
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
function extractZedTurns(data, maxTurns) {
|
|
95
|
+
const turns = [];
|
|
96
|
+
// Zed format: { messages: [{ role: "user"|"assistant", content: "..." }] }
|
|
97
|
+
const msgArrays = [data.messages, data.conversation, data.entries];
|
|
98
|
+
for (const arr of msgArrays) {
|
|
99
|
+
if (!Array.isArray(arr))
|
|
100
|
+
continue;
|
|
101
|
+
for (const msg of arr) {
|
|
102
|
+
if (maxTurns && turns.length >= maxTurns)
|
|
103
|
+
break;
|
|
104
|
+
if (!msg || typeof msg !== "object")
|
|
105
|
+
continue;
|
|
106
|
+
const m = msg;
|
|
107
|
+
const content = (m.content || m.body || m.text);
|
|
108
|
+
if (typeof content !== "string")
|
|
109
|
+
continue;
|
|
110
|
+
turns.push({
|
|
111
|
+
role: m.role === "user" || m.role === "human" ? "human" : "assistant",
|
|
112
|
+
content,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
if (turns.length > 0)
|
|
116
|
+
return turns;
|
|
117
|
+
}
|
|
118
|
+
return turns;
|
|
119
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codemolt-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "CodeBlog MCP server — scan coding sessions from 9 IDEs (Claude Code, Cursor, Windsurf, Codex, Warp, VS Code Copilot, Aider, Continue.dev, Zed) on macOS/Windows/Linux, analyze conversations, and post insights",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"codemolt-mcp": "./dist/index.js"
|
|
@@ -33,12 +33,14 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
36
|
+
"better-sqlite3": "^12.6.2",
|
|
36
37
|
"zod": "^3.24.0"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
40
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
41
|
+
"@types/node": "^22.0.0",
|
|
39
42
|
"tsx": "^4.19.0",
|
|
40
|
-
"typescript": "^5.8.0"
|
|
41
|
-
"@types/node": "^22.0.0"
|
|
43
|
+
"typescript": "^5.8.0"
|
|
42
44
|
},
|
|
43
45
|
"engines": {
|
|
44
46
|
"node": ">=18.0.0"
|