claude-sessions-mcp 0.2.1 → 0.3.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/dist/mcp/index.js +169 -128
- package/dist/mcp/index.js.map +1 -1
- package/dist/web/client/_app/immutable/assets/0.XO-DXdC4.css +1 -0
- package/dist/web/client/_app/immutable/assets/0.XO-DXdC4.css.br +0 -0
- package/dist/web/client/_app/immutable/assets/0.XO-DXdC4.css.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/B2IHY0Hs.js +1 -0
- package/dist/web/client/_app/immutable/chunks/B2IHY0Hs.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/B2IHY0Hs.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/BCJVXGHY.js +1 -0
- package/dist/web/client/_app/immutable/chunks/BCJVXGHY.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/BCJVXGHY.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/CMwK7N_O.js +1 -0
- package/dist/web/client/_app/immutable/chunks/CMwK7N_O.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/CMwK7N_O.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/CZTho13P.js +1 -0
- package/dist/web/client/_app/immutable/chunks/CZTho13P.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/CZTho13P.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/F-H9hLgW.js +2 -0
- package/dist/web/client/_app/immutable/chunks/F-H9hLgW.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/F-H9hLgW.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/gR9AL7GA.js +2 -0
- package/dist/web/client/_app/immutable/chunks/gR9AL7GA.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/gR9AL7GA.js.gz +0 -0
- package/dist/web/client/_app/immutable/entry/app.Boej0hfY.js +2 -0
- package/dist/web/client/_app/immutable/entry/app.Boej0hfY.js.br +0 -0
- package/dist/web/client/_app/immutable/entry/app.Boej0hfY.js.gz +0 -0
- package/dist/web/client/_app/immutable/entry/start.CVYJWPd9.js +1 -0
- package/dist/web/client/_app/immutable/entry/start.CVYJWPd9.js.br +2 -0
- package/dist/web/client/_app/immutable/entry/start.CVYJWPd9.js.gz +0 -0
- package/dist/web/client/_app/immutable/nodes/0.Lbeu1dpo.js +1 -0
- package/dist/web/client/_app/immutable/nodes/0.Lbeu1dpo.js.br +0 -0
- package/dist/web/client/_app/immutable/nodes/0.Lbeu1dpo.js.gz +0 -0
- package/dist/web/client/_app/immutable/nodes/1.DvRsCtcA.js +1 -0
- package/dist/web/client/_app/immutable/nodes/1.DvRsCtcA.js.br +0 -0
- package/dist/web/client/_app/immutable/nodes/1.DvRsCtcA.js.gz +0 -0
- package/dist/web/client/_app/immutable/nodes/2.CjVN0Bwe.js +73 -0
- package/dist/web/client/_app/immutable/nodes/2.CjVN0Bwe.js.br +0 -0
- package/dist/web/client/_app/immutable/nodes/2.CjVN0Bwe.js.gz +0 -0
- package/dist/web/client/_app/version.json +1 -1
- package/dist/web/client/_app/version.json.br +0 -0
- package/dist/web/client/_app/version.json.gz +0 -0
- package/dist/web/server/chunks/{0-CpLgwGZT.js → 0-C_hzGzlo.js} +4 -4
- package/dist/web/server/chunks/{0-CpLgwGZT.js.map → 0-C_hzGzlo.js.map} +1 -1
- package/dist/web/server/chunks/{1-Co8-9FdW.js → 1-CSNAjAzD.js} +2 -2
- package/dist/web/server/chunks/{1-Co8-9FdW.js.map → 1-CSNAjAzD.js.map} +1 -1
- package/dist/web/server/chunks/2-D_ZAFGkV.js +9 -0
- package/dist/web/server/chunks/{2-CXKmp7vO.js.map → 2-D_ZAFGkV.js.map} +1 -1
- package/dist/web/server/chunks/{_layout.svelte-g4K2eFdi.js → _layout.svelte-BWDuddeu.js} +6 -2
- package/dist/web/server/chunks/_layout.svelte-BWDuddeu.js.map +1 -0
- package/dist/web/server/chunks/{_page.svelte-Bu5w4fE4.js → _page.svelte-BTPPI5f9.js} +12 -4
- package/dist/web/server/chunks/_page.svelte-BTPPI5f9.js.map +1 -0
- package/dist/web/server/chunks/{_server.ts-9dSpOSZD.js → _server.ts-B0JVJ9FB.js} +2 -2
- package/dist/web/server/chunks/{_server.ts-9dSpOSZD.js.map → _server.ts-B0JVJ9FB.js.map} +1 -1
- package/dist/web/server/chunks/{_server.ts-uDQ4gQW0.js → _server.ts-BLGLFyUk.js} +2 -2
- package/dist/web/server/chunks/{_server.ts-uDQ4gQW0.js.map → _server.ts-BLGLFyUk.js.map} +1 -1
- package/dist/web/server/chunks/{_server.ts-XEsSs7Il.js → _server.ts-BaqmP9oG.js} +2 -2
- package/dist/web/server/chunks/{_server.ts-XEsSs7Il.js.map → _server.ts-BaqmP9oG.js.map} +1 -1
- package/dist/web/server/chunks/{_server.ts-BoS0ijI9.js → _server.ts-Beze9L3_.js} +2 -2
- package/dist/web/server/chunks/{_server.ts-BoS0ijI9.js.map → _server.ts-Beze9L3_.js.map} +1 -1
- package/dist/web/server/chunks/{_server.ts-C9C0bsVO.js → _server.ts-BlgHsHoW.js} +2 -2
- package/dist/web/server/chunks/{_server.ts-C9C0bsVO.js.map → _server.ts-BlgHsHoW.js.map} +1 -1
- package/dist/web/server/chunks/{_server.ts-DCZgqkA_.js → _server.ts-Cb5-fa8C.js} +2 -2
- package/dist/web/server/chunks/{_server.ts-DCZgqkA_.js.map → _server.ts-Cb5-fa8C.js.map} +1 -1
- package/dist/web/server/chunks/{_server.ts-zkRNh3d2.js → _server.ts-ChE2aT-W.js} +6 -3
- package/dist/web/server/chunks/_server.ts-ChE2aT-W.js.map +1 -0
- package/dist/web/server/chunks/{_server.ts-Dq5i1Bg9.js → _server.ts-Cksv90lD.js} +2 -2
- package/dist/web/server/chunks/{_server.ts-Dq5i1Bg9.js.map → _server.ts-Cksv90lD.js.map} +1 -1
- package/dist/web/server/chunks/_server.ts-D80JJ66s.js +26 -0
- package/dist/web/server/chunks/_server.ts-D80JJ66s.js.map +1 -0
- package/dist/web/server/chunks/{_server.ts-DNSYjrWg.js → _server.ts-DjWf5N-i.js} +2 -2
- package/dist/web/server/chunks/{_server.ts-DNSYjrWg.js.map → _server.ts-DjWf5N-i.js.map} +1 -1
- package/dist/web/server/chunks/{session-BAE596_s.js → session-DmOGNZUD.js} +380 -13
- package/dist/web/server/chunks/session-DmOGNZUD.js.map +1 -0
- package/dist/web/server/index.js +1 -1
- package/dist/web/server/index.js.map +1 -1
- package/dist/web/server/manifest.js +20 -13
- package/dist/web/server/manifest.js.map +1 -1
- package/package.json +1 -1
- package/dist/web/client/_app/immutable/assets/0.bo32IKJI.css +0 -1
- package/dist/web/client/_app/immutable/assets/0.bo32IKJI.css.br +0 -0
- package/dist/web/client/_app/immutable/assets/0.bo32IKJI.css.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/BpzfNVdV.js +0 -1
- package/dist/web/client/_app/immutable/chunks/BpzfNVdV.js.br +0 -1
- package/dist/web/client/_app/immutable/chunks/BpzfNVdV.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/CM_W2Y6b.js +0 -1
- package/dist/web/client/_app/immutable/chunks/CM_W2Y6b.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/CM_W2Y6b.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/CkYrZ5uP.js +0 -1
- package/dist/web/client/_app/immutable/chunks/CkYrZ5uP.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/CkYrZ5uP.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/DhpCfsq_.js +0 -2
- package/dist/web/client/_app/immutable/chunks/DhpCfsq_.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/DhpCfsq_.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/JuVRPOYA.js +0 -1
- package/dist/web/client/_app/immutable/chunks/JuVRPOYA.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/JuVRPOYA.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/qEz027d4.js +0 -1
- package/dist/web/client/_app/immutable/chunks/qEz027d4.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/qEz027d4.js.gz +0 -0
- package/dist/web/client/_app/immutable/entry/app.B3ErwcNl.js +0 -2
- package/dist/web/client/_app/immutable/entry/app.B3ErwcNl.js.br +0 -0
- package/dist/web/client/_app/immutable/entry/app.B3ErwcNl.js.gz +0 -0
- package/dist/web/client/_app/immutable/entry/start.DfAnAPV3.js +0 -1
- package/dist/web/client/_app/immutable/entry/start.DfAnAPV3.js.br +0 -2
- package/dist/web/client/_app/immutable/entry/start.DfAnAPV3.js.gz +0 -0
- package/dist/web/client/_app/immutable/nodes/0.0G4u1RwN.js +0 -1
- package/dist/web/client/_app/immutable/nodes/0.0G4u1RwN.js.br +0 -0
- package/dist/web/client/_app/immutable/nodes/0.0G4u1RwN.js.gz +0 -0
- package/dist/web/client/_app/immutable/nodes/1.BTCUCPE9.js +0 -1
- package/dist/web/client/_app/immutable/nodes/1.BTCUCPE9.js.br +0 -0
- package/dist/web/client/_app/immutable/nodes/1.BTCUCPE9.js.gz +0 -0
- package/dist/web/client/_app/immutable/nodes/2.rvNN8qKE.js +0 -69
- package/dist/web/client/_app/immutable/nodes/2.rvNN8qKE.js.br +0 -0
- package/dist/web/client/_app/immutable/nodes/2.rvNN8qKE.js.gz +0 -0
- package/dist/web/server/chunks/2-CXKmp7vO.js +0 -9
- package/dist/web/server/chunks/_layout.svelte-g4K2eFdi.js.map +0 -1
- package/dist/web/server/chunks/_page.svelte-Bu5w4fE4.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-zkRNh3d2.js.map +0 -1
- package/dist/web/server/chunks/session-BAE596_s.js.map +0 -1
|
@@ -3,7 +3,264 @@ import * as fs from 'node:fs/promises';
|
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import * as os from 'node:os';
|
|
5
5
|
|
|
6
|
-
const getSessionsDir = () => path.join(os.homedir(), ".claude", "projects");
|
|
6
|
+
const getSessionsDir$1 = () => path.join(os.homedir(), ".claude", "projects");
|
|
7
|
+
const getTodosDir = () => path.join(os.homedir(), ".claude", "todos");
|
|
8
|
+
const findLinkedAgents$1 = (projectName, sessionId) => Effect.gen(function* () {
|
|
9
|
+
const projectPath = path.join(getSessionsDir$1(), projectName);
|
|
10
|
+
const files = yield* Effect.tryPromise(() => fs.readdir(projectPath));
|
|
11
|
+
const agentFiles = files.filter((f) => f.startsWith("agent-") && f.endsWith(".jsonl"));
|
|
12
|
+
const linkedAgents = [];
|
|
13
|
+
for (const agentFile of agentFiles) {
|
|
14
|
+
const filePath = path.join(projectPath, agentFile);
|
|
15
|
+
const content = yield* Effect.tryPromise(() => fs.readFile(filePath, "utf-8"));
|
|
16
|
+
const firstLine = content.split("\n")[0];
|
|
17
|
+
if (firstLine) {
|
|
18
|
+
try {
|
|
19
|
+
const parsed = JSON.parse(firstLine);
|
|
20
|
+
if (parsed.sessionId === sessionId) {
|
|
21
|
+
linkedAgents.push(agentFile.replace(".jsonl", ""));
|
|
22
|
+
}
|
|
23
|
+
} catch {
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return linkedAgents;
|
|
28
|
+
});
|
|
29
|
+
const findOrphanAgents$1 = (projectName) => Effect.gen(function* () {
|
|
30
|
+
const projectPath = path.join(getSessionsDir$1(), projectName);
|
|
31
|
+
const files = yield* Effect.tryPromise(() => fs.readdir(projectPath));
|
|
32
|
+
const sessionIds = new Set(
|
|
33
|
+
files.filter((f) => !f.startsWith("agent-") && f.endsWith(".jsonl")).map((f) => f.replace(".jsonl", ""))
|
|
34
|
+
);
|
|
35
|
+
const agentFiles = files.filter((f) => f.startsWith("agent-") && f.endsWith(".jsonl"));
|
|
36
|
+
const orphanAgents = [];
|
|
37
|
+
for (const agentFile of agentFiles) {
|
|
38
|
+
const filePath = path.join(projectPath, agentFile);
|
|
39
|
+
const content = yield* Effect.tryPromise(() => fs.readFile(filePath, "utf-8"));
|
|
40
|
+
const firstLine = content.split("\n")[0];
|
|
41
|
+
if (firstLine) {
|
|
42
|
+
try {
|
|
43
|
+
const parsed = JSON.parse(firstLine);
|
|
44
|
+
if (parsed.sessionId && !sessionIds.has(parsed.sessionId)) {
|
|
45
|
+
orphanAgents.push({
|
|
46
|
+
agentId: agentFile.replace(".jsonl", ""),
|
|
47
|
+
sessionId: parsed.sessionId
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return orphanAgents;
|
|
55
|
+
});
|
|
56
|
+
const deleteOrphanAgents$1 = (projectName) => Effect.gen(function* () {
|
|
57
|
+
const projectPath = path.join(getSessionsDir$1(), projectName);
|
|
58
|
+
const orphans = yield* findOrphanAgents$1(projectName);
|
|
59
|
+
const backupDir = path.join(projectPath, ".bak");
|
|
60
|
+
yield* Effect.tryPromise(() => fs.mkdir(backupDir, { recursive: true }));
|
|
61
|
+
const deletedAgents = [];
|
|
62
|
+
for (const orphan of orphans) {
|
|
63
|
+
const agentPath = path.join(projectPath, `${orphan.agentId}.jsonl`);
|
|
64
|
+
const agentBackupPath = path.join(backupDir, `${orphan.agentId}.jsonl`);
|
|
65
|
+
yield* Effect.tryPromise(() => fs.rename(agentPath, agentBackupPath));
|
|
66
|
+
deletedAgents.push(orphan.agentId);
|
|
67
|
+
}
|
|
68
|
+
return { success: true, deletedAgents, count: deletedAgents.length };
|
|
69
|
+
});
|
|
70
|
+
const findLinkedTodos = (sessionId, agentIds) => Effect.gen(function* () {
|
|
71
|
+
const todosDir = getTodosDir();
|
|
72
|
+
const exists = yield* Effect.tryPromise(
|
|
73
|
+
() => fs.access(todosDir).then(() => true).catch(() => false)
|
|
74
|
+
);
|
|
75
|
+
if (!exists) {
|
|
76
|
+
return {
|
|
77
|
+
sessionId,
|
|
78
|
+
sessionTodos: [],
|
|
79
|
+
agentTodos: [],
|
|
80
|
+
hasTodos: false
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const sessionTodoPath = path.join(todosDir, `${sessionId}.json`);
|
|
84
|
+
let sessionTodos = [];
|
|
85
|
+
const sessionTodoExists = yield* Effect.tryPromise(
|
|
86
|
+
() => fs.access(sessionTodoPath).then(() => true).catch(() => false)
|
|
87
|
+
);
|
|
88
|
+
if (sessionTodoExists) {
|
|
89
|
+
const content = yield* Effect.tryPromise(() => fs.readFile(sessionTodoPath, "utf-8"));
|
|
90
|
+
try {
|
|
91
|
+
sessionTodos = JSON.parse(content);
|
|
92
|
+
} catch {
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const agentTodos = [];
|
|
96
|
+
for (const agentId of agentIds) {
|
|
97
|
+
const shortAgentId = agentId.replace("agent-", "");
|
|
98
|
+
const agentTodoPath = path.join(todosDir, `${sessionId}-agent-${shortAgentId}.json`);
|
|
99
|
+
const agentTodoExists = yield* Effect.tryPromise(
|
|
100
|
+
() => fs.access(agentTodoPath).then(() => true).catch(() => false)
|
|
101
|
+
);
|
|
102
|
+
if (agentTodoExists) {
|
|
103
|
+
const content = yield* Effect.tryPromise(() => fs.readFile(agentTodoPath, "utf-8"));
|
|
104
|
+
try {
|
|
105
|
+
const todos = JSON.parse(content);
|
|
106
|
+
agentTodos.push({ agentId, todos });
|
|
107
|
+
} catch {
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const hasTodos = sessionTodos.length > 0 || agentTodos.some((at) => at.todos.length > 0);
|
|
112
|
+
return {
|
|
113
|
+
sessionId,
|
|
114
|
+
sessionTodos,
|
|
115
|
+
agentTodos,
|
|
116
|
+
hasTodos
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
const sessionHasTodos$1 = (sessionId, agentIds) => Effect.gen(function* () {
|
|
120
|
+
const todosDir = getTodosDir();
|
|
121
|
+
const exists = yield* Effect.tryPromise(
|
|
122
|
+
() => fs.access(todosDir).then(() => true).catch(() => false)
|
|
123
|
+
);
|
|
124
|
+
if (!exists) return false;
|
|
125
|
+
const sessionTodoPath = path.join(todosDir, `${sessionId}.json`);
|
|
126
|
+
const sessionTodoExists = yield* Effect.tryPromise(
|
|
127
|
+
() => fs.access(sessionTodoPath).then(() => true).catch(() => false)
|
|
128
|
+
);
|
|
129
|
+
if (sessionTodoExists) {
|
|
130
|
+
const content = yield* Effect.tryPromise(() => fs.readFile(sessionTodoPath, "utf-8"));
|
|
131
|
+
try {
|
|
132
|
+
const todos = JSON.parse(content);
|
|
133
|
+
if (todos.length > 0) return true;
|
|
134
|
+
} catch {
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
for (const agentId of agentIds) {
|
|
138
|
+
const shortAgentId = agentId.replace("agent-", "");
|
|
139
|
+
const agentTodoPath = path.join(todosDir, `${sessionId}-agent-${shortAgentId}.json`);
|
|
140
|
+
const agentTodoExists = yield* Effect.tryPromise(
|
|
141
|
+
() => fs.access(agentTodoPath).then(() => true).catch(() => false)
|
|
142
|
+
);
|
|
143
|
+
if (agentTodoExists) {
|
|
144
|
+
const content = yield* Effect.tryPromise(() => fs.readFile(agentTodoPath, "utf-8"));
|
|
145
|
+
try {
|
|
146
|
+
const todos = JSON.parse(content);
|
|
147
|
+
if (todos.length > 0) return true;
|
|
148
|
+
} catch {
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
});
|
|
154
|
+
const deleteLinkedTodos$1 = (sessionId, agentIds) => Effect.gen(function* () {
|
|
155
|
+
const todosDir = getTodosDir();
|
|
156
|
+
const exists = yield* Effect.tryPromise(
|
|
157
|
+
() => fs.access(todosDir).then(() => true).catch(() => false)
|
|
158
|
+
);
|
|
159
|
+
if (!exists) return { deletedCount: 0 };
|
|
160
|
+
const backupDir = path.join(todosDir, ".bak");
|
|
161
|
+
yield* Effect.tryPromise(() => fs.mkdir(backupDir, { recursive: true }));
|
|
162
|
+
let deletedCount = 0;
|
|
163
|
+
const sessionTodoPath = path.join(todosDir, `${sessionId}.json`);
|
|
164
|
+
const sessionTodoExists = yield* Effect.tryPromise(
|
|
165
|
+
() => fs.access(sessionTodoPath).then(() => true).catch(() => false)
|
|
166
|
+
);
|
|
167
|
+
if (sessionTodoExists) {
|
|
168
|
+
const backupPath = path.join(backupDir, `${sessionId}.json`);
|
|
169
|
+
yield* Effect.tryPromise(() => fs.rename(sessionTodoPath, backupPath));
|
|
170
|
+
deletedCount++;
|
|
171
|
+
}
|
|
172
|
+
for (const agentId of agentIds) {
|
|
173
|
+
const shortAgentId = agentId.replace("agent-", "");
|
|
174
|
+
const agentTodoPath = path.join(todosDir, `${sessionId}-agent-${shortAgentId}.json`);
|
|
175
|
+
const agentTodoExists = yield* Effect.tryPromise(
|
|
176
|
+
() => fs.access(agentTodoPath).then(() => true).catch(() => false)
|
|
177
|
+
);
|
|
178
|
+
if (agentTodoExists) {
|
|
179
|
+
const backupPath = path.join(backupDir, `${sessionId}-agent-${shortAgentId}.json`);
|
|
180
|
+
yield* Effect.tryPromise(() => fs.rename(agentTodoPath, backupPath));
|
|
181
|
+
deletedCount++;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return { deletedCount };
|
|
185
|
+
});
|
|
186
|
+
const findOrphanTodos$1 = () => Effect.gen(function* () {
|
|
187
|
+
const todosDir = getTodosDir();
|
|
188
|
+
const sessionsDir = getSessionsDir$1();
|
|
189
|
+
const [todosExists, sessionsExists] = yield* Effect.all([
|
|
190
|
+
Effect.tryPromise(
|
|
191
|
+
() => fs.access(todosDir).then(() => true).catch(() => false)
|
|
192
|
+
),
|
|
193
|
+
Effect.tryPromise(
|
|
194
|
+
() => fs.access(sessionsDir).then(() => true).catch(() => false)
|
|
195
|
+
)
|
|
196
|
+
]);
|
|
197
|
+
if (!todosExists || !sessionsExists) return [];
|
|
198
|
+
const todoFiles = yield* Effect.tryPromise(() => fs.readdir(todosDir));
|
|
199
|
+
const jsonFiles = todoFiles.filter((f) => f.endsWith(".json"));
|
|
200
|
+
const validSessionIds = /* @__PURE__ */ new Set();
|
|
201
|
+
const projectEntries = yield* Effect.tryPromise(
|
|
202
|
+
() => fs.readdir(sessionsDir, { withFileTypes: true })
|
|
203
|
+
);
|
|
204
|
+
for (const entry of projectEntries) {
|
|
205
|
+
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
206
|
+
const projectPath = path.join(sessionsDir, entry.name);
|
|
207
|
+
const files = yield* Effect.tryPromise(() => fs.readdir(projectPath));
|
|
208
|
+
for (const f of files) {
|
|
209
|
+
if (f.endsWith(".jsonl") && !f.startsWith("agent-")) {
|
|
210
|
+
validSessionIds.add(f.replace(".jsonl", ""));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const orphans = [];
|
|
215
|
+
for (const todoFile of jsonFiles) {
|
|
216
|
+
const match = todoFile.match(/^([a-f0-9-]+)(?:-agent-[a-f0-9]+)?\.json$/);
|
|
217
|
+
if (match) {
|
|
218
|
+
const sessionId = match[1];
|
|
219
|
+
if (!validSessionIds.has(sessionId)) {
|
|
220
|
+
orphans.push(todoFile);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return orphans;
|
|
225
|
+
});
|
|
226
|
+
const deleteOrphanTodos$1 = () => Effect.gen(function* () {
|
|
227
|
+
const todosDir = getTodosDir();
|
|
228
|
+
const orphans = yield* findOrphanTodos$1();
|
|
229
|
+
if (orphans.length === 0) return { success: true, deletedCount: 0 };
|
|
230
|
+
const backupDir = path.join(todosDir, ".bak");
|
|
231
|
+
yield* Effect.tryPromise(() => fs.mkdir(backupDir, { recursive: true }));
|
|
232
|
+
let deletedCount = 0;
|
|
233
|
+
for (const orphan of orphans) {
|
|
234
|
+
const filePath = path.join(todosDir, orphan);
|
|
235
|
+
const backupPath = path.join(backupDir, orphan);
|
|
236
|
+
yield* Effect.tryPromise(() => fs.rename(filePath, backupPath));
|
|
237
|
+
deletedCount++;
|
|
238
|
+
}
|
|
239
|
+
return { success: true, deletedCount };
|
|
240
|
+
});
|
|
241
|
+
const shared = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
242
|
+
__proto__: null,
|
|
243
|
+
deleteLinkedTodos: deleteLinkedTodos$1,
|
|
244
|
+
deleteOrphanAgents: deleteOrphanAgents$1,
|
|
245
|
+
deleteOrphanTodos: deleteOrphanTodos$1,
|
|
246
|
+
findLinkedAgents: findLinkedAgents$1,
|
|
247
|
+
findLinkedTodos,
|
|
248
|
+
findOrphanAgents: findOrphanAgents$1,
|
|
249
|
+
findOrphanTodos: findOrphanTodos$1,
|
|
250
|
+
getSessionsDir: getSessionsDir$1,
|
|
251
|
+
getTodosDir,
|
|
252
|
+
sessionHasTodos: sessionHasTodos$1
|
|
253
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
254
|
+
const {
|
|
255
|
+
getSessionsDir,
|
|
256
|
+
findLinkedAgents,
|
|
257
|
+
findOrphanAgents,
|
|
258
|
+
deleteOrphanAgents,
|
|
259
|
+
sessionHasTodos,
|
|
260
|
+
deleteLinkedTodos,
|
|
261
|
+
findOrphanTodos,
|
|
262
|
+
deleteOrphanTodos
|
|
263
|
+
} = shared;
|
|
7
264
|
const extractTextContent = (message) => {
|
|
8
265
|
if (!message) return "";
|
|
9
266
|
const content = message.content;
|
|
@@ -71,6 +328,7 @@ const listSessions = (projectName) => Effect.gen(function* () {
|
|
|
71
328
|
const userAssistantMessages = messages.filter(
|
|
72
329
|
(m) => m.type === "user" || m.type === "assistant"
|
|
73
330
|
);
|
|
331
|
+
const hasSummary = messages.some((m) => m.type === "summary");
|
|
74
332
|
const firstMessage = userAssistantMessages[0];
|
|
75
333
|
const lastMessage = userAssistantMessages[userAssistantMessages.length - 1];
|
|
76
334
|
const title = pipe(
|
|
@@ -80,13 +338,14 @@ const listSessions = (projectName) => Effect.gen(function* () {
|
|
|
80
338
|
const text = extractTextContent(m.message);
|
|
81
339
|
return extractTitle(text);
|
|
82
340
|
}),
|
|
83
|
-
Option.getOrElse(() => `Session ${sessionId.slice(0, 8)}`)
|
|
341
|
+
Option.getOrElse(() => hasSummary ? "[Summary Only]" : `Session ${sessionId.slice(0, 8)}`)
|
|
84
342
|
);
|
|
85
343
|
return {
|
|
86
344
|
id: sessionId,
|
|
87
345
|
projectName,
|
|
88
346
|
title,
|
|
89
|
-
|
|
347
|
+
// If session has summary but no user/assistant messages, count as 1
|
|
348
|
+
messageCount: userAssistantMessages.length > 0 ? userAssistantMessages.length : hasSummary ? 1 : 0,
|
|
90
349
|
createdAt: firstMessage?.timestamp,
|
|
91
350
|
updatedAt: lastMessage?.timestamp
|
|
92
351
|
};
|
|
@@ -108,17 +367,42 @@ const readSession = (projectName, sessionId) => Effect.gen(function* () {
|
|
|
108
367
|
});
|
|
109
368
|
const deleteSession = (projectName, sessionId) => Effect.gen(function* () {
|
|
110
369
|
const sessionsDir = getSessionsDir();
|
|
111
|
-
const
|
|
370
|
+
const projectPath = path.join(sessionsDir, projectName);
|
|
371
|
+
const filePath = path.join(projectPath, `${sessionId}.jsonl`);
|
|
372
|
+
const linkedAgents = yield* findLinkedAgents(projectName, sessionId);
|
|
112
373
|
const stat = yield* Effect.tryPromise(() => fs.stat(filePath));
|
|
113
374
|
if (stat.size === 0) {
|
|
114
375
|
yield* Effect.tryPromise(() => fs.unlink(filePath));
|
|
115
|
-
|
|
376
|
+
const agentBackupDir2 = path.join(projectPath, ".bak");
|
|
377
|
+
yield* Effect.tryPromise(() => fs.mkdir(agentBackupDir2, { recursive: true }));
|
|
378
|
+
for (const agentId of linkedAgents) {
|
|
379
|
+
const agentPath = path.join(projectPath, `${agentId}.jsonl`);
|
|
380
|
+
const agentBackupPath = path.join(agentBackupDir2, `${agentId}.jsonl`);
|
|
381
|
+
yield* Effect.tryPromise(() => fs.rename(agentPath, agentBackupPath).catch(() => {
|
|
382
|
+
}));
|
|
383
|
+
}
|
|
384
|
+
yield* deleteLinkedTodos(sessionId, linkedAgents);
|
|
385
|
+
return { success: true, deletedAgents: linkedAgents.length };
|
|
116
386
|
}
|
|
117
387
|
const backupDir = path.join(sessionsDir, ".bak");
|
|
118
388
|
yield* Effect.tryPromise(() => fs.mkdir(backupDir, { recursive: true }));
|
|
389
|
+
const agentBackupDir = path.join(projectPath, ".bak");
|
|
390
|
+
yield* Effect.tryPromise(() => fs.mkdir(agentBackupDir, { recursive: true }));
|
|
391
|
+
for (const agentId of linkedAgents) {
|
|
392
|
+
const agentPath = path.join(projectPath, `${agentId}.jsonl`);
|
|
393
|
+
const agentBackupPath = path.join(agentBackupDir, `${agentId}.jsonl`);
|
|
394
|
+
yield* Effect.tryPromise(() => fs.rename(agentPath, agentBackupPath).catch(() => {
|
|
395
|
+
}));
|
|
396
|
+
}
|
|
397
|
+
const todosResult = yield* deleteLinkedTodos(sessionId, linkedAgents);
|
|
119
398
|
const backupPath = path.join(backupDir, `${projectName}_${sessionId}.jsonl`);
|
|
120
399
|
yield* Effect.tryPromise(() => fs.rename(filePath, backupPath));
|
|
121
|
-
return {
|
|
400
|
+
return {
|
|
401
|
+
success: true,
|
|
402
|
+
backupPath,
|
|
403
|
+
deletedAgents: linkedAgents.length,
|
|
404
|
+
deletedTodos: todosResult.deletedCount
|
|
405
|
+
};
|
|
122
406
|
});
|
|
123
407
|
const renameSession = (projectName, sessionId, newTitle) => Effect.gen(function* () {
|
|
124
408
|
const filePath = path.join(getSessionsDir(), projectName, `${sessionId}.jsonl`);
|
|
@@ -193,6 +477,8 @@ const deleteMessage = (projectName, sessionId, messageUuid) => Effect.gen(functi
|
|
|
193
477
|
const previewCleanup = (projectName) => Effect.gen(function* () {
|
|
194
478
|
const projects = yield* listProjects;
|
|
195
479
|
const targetProjects = projectName ? projects.filter((p) => p.name === projectName) : projects;
|
|
480
|
+
const orphanTodos = yield* findOrphanTodos();
|
|
481
|
+
const orphanTodoCount = orphanTodos.length;
|
|
196
482
|
const results = yield* Effect.all(
|
|
197
483
|
targetProjects.map(
|
|
198
484
|
(project) => Effect.gen(function* () {
|
|
@@ -201,15 +487,34 @@ const previewCleanup = (projectName) => Effect.gen(function* () {
|
|
|
201
487
|
const invalidSessions = sessions.filter(
|
|
202
488
|
(s) => s.title?.includes("Invalid API key") || s.title?.includes("API key")
|
|
203
489
|
);
|
|
490
|
+
let emptyWithTodosCount = 0;
|
|
491
|
+
for (const session of emptySessions) {
|
|
492
|
+
const linkedAgents = yield* findLinkedAgents(project.name, session.id);
|
|
493
|
+
const hasTodos = yield* sessionHasTodos(session.id, linkedAgents);
|
|
494
|
+
if (hasTodos) {
|
|
495
|
+
emptyWithTodosCount++;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
const orphanAgents = yield* findOrphanAgents(project.name);
|
|
204
499
|
return {
|
|
205
500
|
project: project.name,
|
|
206
501
|
emptySessions,
|
|
207
|
-
invalidSessions
|
|
502
|
+
invalidSessions,
|
|
503
|
+
emptyWithTodosCount,
|
|
504
|
+
orphanAgentCount: orphanAgents.length,
|
|
505
|
+
orphanTodoCount
|
|
506
|
+
// Include global orphan todo count in first project only
|
|
208
507
|
};
|
|
209
508
|
})
|
|
210
509
|
),
|
|
211
510
|
{ concurrency: 5 }
|
|
212
511
|
);
|
|
512
|
+
if (results.length > 0) {
|
|
513
|
+
results[0] = { ...results[0], orphanTodoCount };
|
|
514
|
+
for (let i = 1; i < results.length; i++) {
|
|
515
|
+
results[i] = { ...results[i], orphanTodoCount: 0 };
|
|
516
|
+
}
|
|
517
|
+
}
|
|
213
518
|
return results;
|
|
214
519
|
});
|
|
215
520
|
const isInvalidApiKeyMessage = (msg) => {
|
|
@@ -232,7 +537,9 @@ const cleanInvalidMessages = (projectName, sessionId) => Effect.gen(function* ()
|
|
|
232
537
|
const userAssistantCount = messages.filter(
|
|
233
538
|
(m) => m.type === "user" || m.type === "assistant"
|
|
234
539
|
).length;
|
|
235
|
-
|
|
540
|
+
const hasSummary2 = messages.some((m) => m.type === "summary");
|
|
541
|
+
const remainingCount2 = userAssistantCount > 0 ? userAssistantCount : hasSummary2 ? 1 : 0;
|
|
542
|
+
return { removedCount: 0, remainingCount: remainingCount2 };
|
|
236
543
|
}
|
|
237
544
|
const filtered = [];
|
|
238
545
|
let lastValidUuid = null;
|
|
@@ -252,7 +559,9 @@ const cleanInvalidMessages = (projectName, sessionId) => Effect.gen(function* ()
|
|
|
252
559
|
const remainingUserAssistant = filtered.filter(
|
|
253
560
|
(m) => m.type === "user" || m.type === "assistant"
|
|
254
561
|
).length;
|
|
255
|
-
|
|
562
|
+
const hasSummary = filtered.some((m) => m.type === "summary");
|
|
563
|
+
const remainingCount = remainingUserAssistant > 0 ? remainingUserAssistant : hasSummary ? 1 : 0;
|
|
564
|
+
return { removedCount: invalidIndices.length, remainingCount };
|
|
256
565
|
});
|
|
257
566
|
const getSessionFiles = (projectName, sessionId) => Effect.gen(function* () {
|
|
258
567
|
const messages = yield* readSession(projectName, sessionId);
|
|
@@ -306,6 +615,39 @@ const getSessionFiles = (projectName, sessionId) => Effect.gen(function* () {
|
|
|
306
615
|
totalChanges: fileChanges.length
|
|
307
616
|
};
|
|
308
617
|
});
|
|
618
|
+
const moveSession = (sourceProject, sessionId, targetProject) => Effect.gen(function* () {
|
|
619
|
+
const sessionsDir = getSessionsDir();
|
|
620
|
+
const sourcePath = path.join(sessionsDir, sourceProject);
|
|
621
|
+
const targetPath = path.join(sessionsDir, targetProject);
|
|
622
|
+
const sourceFile = path.join(sourcePath, `${sessionId}.jsonl`);
|
|
623
|
+
const targetFile = path.join(targetPath, `${sessionId}.jsonl`);
|
|
624
|
+
const sourceExists = yield* Effect.tryPromise(
|
|
625
|
+
() => fs.access(sourceFile).then(() => true).catch(() => false)
|
|
626
|
+
);
|
|
627
|
+
if (!sourceExists) {
|
|
628
|
+
return { success: false, error: "Source session not found" };
|
|
629
|
+
}
|
|
630
|
+
const targetExists = yield* Effect.tryPromise(
|
|
631
|
+
() => fs.access(targetFile).then(() => true).catch(() => false)
|
|
632
|
+
);
|
|
633
|
+
if (targetExists) {
|
|
634
|
+
return { success: false, error: "Session already exists in target project" };
|
|
635
|
+
}
|
|
636
|
+
yield* Effect.tryPromise(() => fs.mkdir(targetPath, { recursive: true }));
|
|
637
|
+
const linkedAgents = yield* findLinkedAgents(sourceProject, sessionId);
|
|
638
|
+
yield* Effect.tryPromise(() => fs.rename(sourceFile, targetFile));
|
|
639
|
+
for (const agentId of linkedAgents) {
|
|
640
|
+
const sourceAgentFile = path.join(sourcePath, `${agentId}.jsonl`);
|
|
641
|
+
const targetAgentFile = path.join(targetPath, `${agentId}.jsonl`);
|
|
642
|
+
const agentExists = yield* Effect.tryPromise(
|
|
643
|
+
() => fs.access(sourceAgentFile).then(() => true).catch(() => false)
|
|
644
|
+
);
|
|
645
|
+
if (agentExists) {
|
|
646
|
+
yield* Effect.tryPromise(() => fs.rename(sourceAgentFile, targetAgentFile));
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return { success: true };
|
|
650
|
+
});
|
|
309
651
|
const splitSession = (projectName, sessionId, splitAtMessageUuid) => Effect.gen(function* () {
|
|
310
652
|
const projectPath = path.join(getSessionsDir(), projectName);
|
|
311
653
|
const filePath = path.join(projectPath, `${sessionId}.jsonl`);
|
|
@@ -365,11 +707,19 @@ const splitSession = (projectName, sessionId, splitAtMessageUuid) => Effect.gen(
|
|
|
365
707
|
};
|
|
366
708
|
});
|
|
367
709
|
const clearSessions = (options) => Effect.gen(function* () {
|
|
368
|
-
const {
|
|
710
|
+
const {
|
|
711
|
+
projectName,
|
|
712
|
+
clearEmpty = true,
|
|
713
|
+
skipWithTodos = true,
|
|
714
|
+
clearOrphanAgents = false,
|
|
715
|
+
clearOrphanTodos = false
|
|
716
|
+
} = options;
|
|
369
717
|
const projects = yield* listProjects;
|
|
370
718
|
const targetProjects = projectName ? projects.filter((p) => p.name === projectName) : projects;
|
|
371
719
|
let deletedSessionCount = 0;
|
|
372
720
|
let removedMessageCount = 0;
|
|
721
|
+
let deletedOrphanAgentCount = 0;
|
|
722
|
+
let deletedOrphanTodoCount = 0;
|
|
373
723
|
const sessionsToDelete = [];
|
|
374
724
|
for (const project of targetProjects) {
|
|
375
725
|
const projectPath = path.join(getSessionsDir(), project.name);
|
|
@@ -393,6 +743,11 @@ const clearSessions = (options) => Effect.gen(function* () {
|
|
|
393
743
|
(s) => s.project === project.name && s.sessionId === session.id
|
|
394
744
|
);
|
|
395
745
|
if (!alreadyMarked) {
|
|
746
|
+
if (skipWithTodos) {
|
|
747
|
+
const linkedAgents = yield* findLinkedAgents(project.name, session.id);
|
|
748
|
+
const hasTodos = yield* sessionHasTodos(session.id, linkedAgents);
|
|
749
|
+
if (hasTodos) continue;
|
|
750
|
+
}
|
|
396
751
|
sessionsToDelete.push({ project: project.name, sessionId: session.id });
|
|
397
752
|
}
|
|
398
753
|
}
|
|
@@ -403,12 +758,24 @@ const clearSessions = (options) => Effect.gen(function* () {
|
|
|
403
758
|
yield* deleteSession(project, sessionId);
|
|
404
759
|
deletedSessionCount++;
|
|
405
760
|
}
|
|
761
|
+
if (clearOrphanAgents) {
|
|
762
|
+
for (const project of targetProjects) {
|
|
763
|
+
const result = yield* deleteOrphanAgents(project.name);
|
|
764
|
+
deletedOrphanAgentCount += result.count;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
if (clearOrphanTodos) {
|
|
768
|
+
const result = yield* deleteOrphanTodos();
|
|
769
|
+
deletedOrphanTodoCount = result.deletedCount;
|
|
770
|
+
}
|
|
406
771
|
return {
|
|
407
772
|
success: true,
|
|
408
773
|
deletedCount: deletedSessionCount,
|
|
409
|
-
removedMessageCount
|
|
774
|
+
removedMessageCount,
|
|
775
|
+
deletedOrphanAgentCount,
|
|
776
|
+
deletedOrphanTodoCount
|
|
410
777
|
};
|
|
411
778
|
});
|
|
412
779
|
|
|
413
|
-
export { listSessions as a, deleteSession as b, clearSessions as c, deleteMessage as d, renameSession as e, getSessionFiles as g, listProjects as l, previewCleanup as p, readSession as r, splitSession as s, updateCustomTitle as u };
|
|
414
|
-
//# sourceMappingURL=session-
|
|
780
|
+
export { listSessions as a, deleteSession as b, clearSessions as c, deleteMessage as d, renameSession as e, getSessionFiles as g, listProjects as l, moveSession as m, previewCleanup as p, readSession as r, splitSession as s, updateCustomTitle as u };
|
|
781
|
+
//# sourceMappingURL=session-DmOGNZUD.js.map
|