@claude-sessions/core 0.4.8-beta.0 → 0.4.8-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +27 -9
- package/dist/index.js +100 -31
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/{types-CsXAWb1Q.d.ts → types-CoLRUgPk.d.ts} +5 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as Project, M as MessagePayload$1, a as Message, T as TitleDisplayMode, S as SummaryInfo, b as
|
|
2
|
-
export {
|
|
1
|
+
import { P as Project, M as MessagePayload$1, a as Message, T as TitleDisplayMode, S as SummaryInfo, b as SessionSortField, c as SessionTodos, d as MoveSessionResult, A as AgentInfo, e as SessionSortOptions, f as ProjectTreeData, C as CompressSessionOptions, g as SummarizeSessionOptions, h as ConversationLine, i as SearchResult, F as FileChange, j as SessionsIndex, k as SessionIndexEntry } from './types-CoLRUgPk.js';
|
|
2
|
+
export { r as CleanupPreview, q as ClearSessionsResult, x as CompressSessionResult, l as ContentItem, D as DeleteSessionResult, y as ProjectKnowledge, R as RenameSessionResult, t as ResumeSessionOptions, u as ResumeSessionResult, w as SessionAnalysis, o as SessionFilesSummary, m as SessionMeta, B as SessionSortOrder, s as SessionTreeData, p as SplitSessionResult, z as SummarizeSessionResult, n as TodoItem, v as ToolUsageStats } from './types-CoLRUgPk.js';
|
|
3
3
|
import * as effect_Cause from 'effect/Cause';
|
|
4
4
|
import { Effect } from 'effect';
|
|
5
5
|
|
|
@@ -71,7 +71,8 @@ declare const findProjectByWorkspacePath: (workspacePath: string, projectNames:
|
|
|
71
71
|
* Sort projects with priority:
|
|
72
72
|
* 1. Current project (if specified)
|
|
73
73
|
* 2. Current user's home directory subpaths
|
|
74
|
-
* 3.
|
|
74
|
+
* 3. Most recently modified first (by newest session file mtime)
|
|
75
|
+
* 4. Alphabetically by displayName as tiebreaker
|
|
75
76
|
*/
|
|
76
77
|
declare const sortProjects: (projects: Project[], options?: {
|
|
77
78
|
currentProjectName?: string | null;
|
|
@@ -126,13 +127,28 @@ declare function getDisplayTitle(customTitle: string | undefined, currentSummary
|
|
|
126
127
|
*/
|
|
127
128
|
declare const maskHomePath: (text: string, homeDir: string) => string;
|
|
128
129
|
/**
|
|
129
|
-
* Get sort timestamp for session (Unix timestamp ms)
|
|
130
|
-
* Priority: summaries[0].timestamp > createdAt > 0
|
|
130
|
+
* Get summary-based sort timestamp for session (Unix timestamp ms)
|
|
131
|
+
* Used for 'summary' sort field. Priority: summaries[0].timestamp > createdAt > 0
|
|
131
132
|
*/
|
|
133
|
+
declare const getSummarySortTimestamp: (session: {
|
|
134
|
+
summaries?: SummaryInfo[];
|
|
135
|
+
createdAt?: string;
|
|
136
|
+
}) => number;
|
|
137
|
+
/** @deprecated Use getSummarySortTimestamp instead */
|
|
132
138
|
declare const getSessionSortTimestamp: (session: {
|
|
133
139
|
summaries?: SummaryInfo[];
|
|
134
140
|
createdAt?: string;
|
|
135
141
|
}) => number;
|
|
142
|
+
/**
|
|
143
|
+
* Get display-ready sort timestamp based on active sort field.
|
|
144
|
+
* Returns the timestamp matching what the user sees as the sort order.
|
|
145
|
+
*/
|
|
146
|
+
declare const getDisplaySortTimestamp: (session: {
|
|
147
|
+
summaries?: SummaryInfo[];
|
|
148
|
+
createdAt?: string;
|
|
149
|
+
updatedAt?: string;
|
|
150
|
+
fileMtime?: number;
|
|
151
|
+
}, sortField: SessionSortField) => number;
|
|
136
152
|
/**
|
|
137
153
|
* Try to parse a single JSON line, returning null on failure with optional warning log
|
|
138
154
|
* Use this when you want to skip invalid lines instead of throwing
|
|
@@ -503,6 +519,7 @@ declare const previewCleanup: (projectName?: string) => Effect.Effect<{
|
|
|
503
519
|
emptyWithTodosCount: number;
|
|
504
520
|
orphanAgentCount: number;
|
|
505
521
|
orphanTodoCount: number;
|
|
522
|
+
isStale: boolean;
|
|
506
523
|
}[], effect_Cause.UnknownException, never>;
|
|
507
524
|
declare const clearSessions: (options: {
|
|
508
525
|
projectName?: string;
|
|
@@ -511,12 +528,15 @@ declare const clearSessions: (options: {
|
|
|
511
528
|
skipWithTodos?: boolean;
|
|
512
529
|
clearOrphanAgents?: boolean;
|
|
513
530
|
clearOrphanTodos?: boolean;
|
|
531
|
+
clearStale?: boolean;
|
|
532
|
+
staleProjects?: string[];
|
|
514
533
|
}) => Effect.Effect<{
|
|
515
534
|
success: true;
|
|
516
535
|
deletedCount: number;
|
|
517
536
|
removedMessageCount: number;
|
|
518
537
|
deletedOrphanAgentCount: number;
|
|
519
538
|
deletedOrphanTodoCount: number;
|
|
539
|
+
deletedStaleProjectCount: number;
|
|
520
540
|
}, effect_Cause.UnknownException, never>;
|
|
521
541
|
|
|
522
542
|
declare const searchSessions: (query: string, options?: {
|
|
@@ -593,9 +613,7 @@ declare function validateChain(messages: readonly GenericMessage[]): ValidationR
|
|
|
593
613
|
errors: ChainError[];
|
|
594
614
|
};
|
|
595
615
|
/**
|
|
596
|
-
* Validate for unwanted
|
|
597
|
-
*
|
|
598
|
-
* Only 'Stop' hookEvent is treated as an error (should be removed)
|
|
616
|
+
* Validate for unwanted cleanup artifacts that should not remain in sessions.
|
|
599
617
|
*/
|
|
600
618
|
declare function validateProgressMessages(messages: readonly GenericMessage[]): ValidationResult & {
|
|
601
619
|
errors: ProgressError[];
|
|
@@ -690,4 +708,4 @@ declare const getLogger: () => Logger;
|
|
|
690
708
|
*/
|
|
691
709
|
declare const createLogger: (namespace: string) => Logger;
|
|
692
710
|
|
|
693
|
-
export { AgentInfo, type ChainError, CompressSessionOptions, ConversationLine, type DisplayTitleOptions, FileChange, type GenericMessage, type Logger, Message, MessagePayload$1 as MessagePayload, MoveSessionResult, type ProgressError, Project, ProjectTreeData, SearchResult, SessionIndexEntry, SessionSortOptions, SessionTodos, SessionsIndex, SummarizeSessionOptions, SummaryInfo, TREE_ICONS, TitleDisplayMode, type ToolUseResultError, type TreeItemType, type ValidationResult, analyzeSession, autoRepairChain, canMoveSession, clearSessions, compressSession, createLogger, deleteLinkedTodos, deleteMessage, deleteMessageWithChainRepair, deleteOrphanAgents, deleteOrphanTodos, deleteSession, expandHomePath, extractProjectKnowledge, extractTextContent, extractTitle, findLinkedAgents, findLinkedTodos, findOrphanAgents, findOrphanTodos, findProjectByWorkspacePath, folderNameToDisplayPath, folderNameToPath, formatRelativeTime, generateTreeNodeId, getCachePath, getDisplayTitle, getIndexEntryDisplayTitle, getLogger, getRealPathFromSession, getSessionFiles, getSessionSortTimestamp, getSessionTooltip, getSessionsDir, getTodoIcon, getTodosDir, getTotalTodoCount, hasSessionsIndex, isContinuationSummary, isInvalidApiKeyMessage, listProjects, listSessions, loadAgentMessages, loadProjectTreeData, loadSessionTreeData, loadSessionsIndex, maskHomePath, moveSession, parseCommandMessage, parseJsonlLines, parseTreeNodeId, pathToFolderName, previewCleanup, readJsonlFile, readSession, renameSession, repairChain, repairParentUuidChain, restoreMessage, searchSessions, sessionHasSubItems, sessionHasTodos, setLogger, sortIndexEntriesByModified, sortProjects, splitSession, summarizeSession, tryParseJsonLine, updateSessionSummary, validateChain, validateProgressMessages, validateToolUseResult };
|
|
711
|
+
export { AgentInfo, type ChainError, CompressSessionOptions, ConversationLine, type DisplayTitleOptions, FileChange, type GenericMessage, type Logger, Message, MessagePayload$1 as MessagePayload, MoveSessionResult, type ProgressError, Project, ProjectTreeData, SearchResult, SessionIndexEntry, SessionSortField, SessionSortOptions, SessionTodos, SessionsIndex, SummarizeSessionOptions, SummaryInfo, TREE_ICONS, TitleDisplayMode, type ToolUseResultError, type TreeItemType, type ValidationResult, analyzeSession, autoRepairChain, canMoveSession, clearSessions, compressSession, createLogger, deleteLinkedTodos, deleteMessage, deleteMessageWithChainRepair, deleteOrphanAgents, deleteOrphanTodos, deleteSession, expandHomePath, extractProjectKnowledge, extractTextContent, extractTitle, findLinkedAgents, findLinkedTodos, findOrphanAgents, findOrphanTodos, findProjectByWorkspacePath, folderNameToDisplayPath, folderNameToPath, formatRelativeTime, generateTreeNodeId, getCachePath, getDisplaySortTimestamp, getDisplayTitle, getIndexEntryDisplayTitle, getLogger, getRealPathFromSession, getSessionFiles, getSessionSortTimestamp, getSessionTooltip, getSessionsDir, getSummarySortTimestamp, getTodoIcon, getTodosDir, getTotalTodoCount, hasSessionsIndex, isContinuationSummary, isInvalidApiKeyMessage, listProjects, listSessions, loadAgentMessages, loadProjectTreeData, loadSessionTreeData, loadSessionsIndex, maskHomePath, moveSession, parseCommandMessage, parseJsonlLines, parseTreeNodeId, pathToFolderName, previewCleanup, readJsonlFile, readSession, renameSession, repairChain, repairParentUuidChain, restoreMessage, searchSessions, sessionHasSubItems, sessionHasTodos, setLogger, sortIndexEntriesByModified, sortProjects, splitSession, summarizeSession, tryParseJsonLine, updateSessionSummary, validateChain, validateProgressMessages, validateToolUseResult };
|
package/dist/index.js
CHANGED
|
@@ -163,10 +163,27 @@ var maskHomePath = (text, homeDir) => {
|
|
|
163
163
|
const regex = new RegExp(`${escapedHome}(?=[/\\\\]|$)`, "g");
|
|
164
164
|
return text.replace(regex, "~");
|
|
165
165
|
};
|
|
166
|
-
var
|
|
166
|
+
var getSummarySortTimestamp = (session) => {
|
|
167
167
|
const timestampStr = session.summaries?.[0]?.timestamp ?? session.createdAt;
|
|
168
168
|
return timestampStr ? new Date(timestampStr).getTime() : 0;
|
|
169
169
|
};
|
|
170
|
+
var getSessionSortTimestamp = getSummarySortTimestamp;
|
|
171
|
+
var getDisplaySortTimestamp = (session, sortField) => {
|
|
172
|
+
switch (sortField) {
|
|
173
|
+
case "updated": {
|
|
174
|
+
if (session.updatedAt) return new Date(session.updatedAt).getTime();
|
|
175
|
+
return getSummarySortTimestamp(session);
|
|
176
|
+
}
|
|
177
|
+
case "created": {
|
|
178
|
+
if (session.createdAt) return new Date(session.createdAt).getTime();
|
|
179
|
+
return getSummarySortTimestamp(session);
|
|
180
|
+
}
|
|
181
|
+
case "modified":
|
|
182
|
+
return session.fileMtime ?? getSummarySortTimestamp(session);
|
|
183
|
+
default:
|
|
184
|
+
return getSummarySortTimestamp(session);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
170
187
|
var tryParseJsonLine = (line, lineNumber, filePath) => {
|
|
171
188
|
try {
|
|
172
189
|
return JSON.parse(line);
|
|
@@ -410,6 +427,9 @@ var sortProjects = (projects, options = {}) => {
|
|
|
410
427
|
if (aIsUserHome && !bIsUserHome) return -1;
|
|
411
428
|
if (!aIsUserHome && bIsUserHome) return 1;
|
|
412
429
|
}
|
|
430
|
+
const aMtime = a.lastModified ?? 0;
|
|
431
|
+
const bMtime = b.lastModified ?? 0;
|
|
432
|
+
if (aMtime !== bMtime) return bMtime - aMtime;
|
|
413
433
|
return a.displayName.localeCompare(b.displayName);
|
|
414
434
|
});
|
|
415
435
|
};
|
|
@@ -519,8 +539,8 @@ var findOrphanAgentsWithPaths = (projectName) => Effect2.gen(function* () {
|
|
|
519
539
|
}
|
|
520
540
|
for (const entry of files) {
|
|
521
541
|
const entryPath = path2.join(projectPath, entry);
|
|
522
|
-
const
|
|
523
|
-
if (
|
|
542
|
+
const stat6 = yield* Effect2.tryPromise(() => fs3.stat(entryPath).catch(() => null));
|
|
543
|
+
if (stat6?.isDirectory() && !entry.startsWith(".")) {
|
|
524
544
|
const subagentsPath = path2.join(entryPath, "subagents");
|
|
525
545
|
const subagentsExists = yield* Effect2.tryPromise(
|
|
526
546
|
() => fs3.stat(subagentsPath).then(() => true).catch(() => false)
|
|
@@ -838,11 +858,24 @@ var listProjects = Effect4.gen(function* () {
|
|
|
838
858
|
const files = yield* Effect4.tryPromise(() => fs5.readdir(projectPath));
|
|
839
859
|
const sessionFiles = files.filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
|
|
840
860
|
const displayName = yield* Effect4.tryPromise(() => folderNameToPath(entry.name));
|
|
861
|
+
let lastModified = 0;
|
|
862
|
+
if (sessionFiles.length > 0) {
|
|
863
|
+
const stats = yield* Effect4.all(
|
|
864
|
+
sessionFiles.map(
|
|
865
|
+
(f) => Effect4.tryPromise(
|
|
866
|
+
() => fs5.stat(path4.join(projectPath, f)).then((s) => s.mtimeMs)
|
|
867
|
+
).pipe(Effect4.orElseSucceed(() => 0))
|
|
868
|
+
),
|
|
869
|
+
{ concurrency: 20 }
|
|
870
|
+
);
|
|
871
|
+
lastModified = stats.reduce((max, value) => value > max ? value : max, 0);
|
|
872
|
+
}
|
|
841
873
|
return {
|
|
842
874
|
name: entry.name,
|
|
843
875
|
displayName,
|
|
844
876
|
path: projectPath,
|
|
845
|
-
sessionCount: sessionFiles.length
|
|
877
|
+
sessionCount: sessionFiles.length,
|
|
878
|
+
lastModified
|
|
846
879
|
};
|
|
847
880
|
})
|
|
848
881
|
),
|
|
@@ -917,19 +950,7 @@ function validateProgressMessages(messages) {
|
|
|
917
950
|
const errors = [];
|
|
918
951
|
for (let i = 0; i < messages.length; i++) {
|
|
919
952
|
const msg = messages[i];
|
|
920
|
-
if (msg.type === "
|
|
921
|
-
const progressMsg = msg;
|
|
922
|
-
const hookEvent = progressMsg.hookEvent ?? progressMsg.data?.hookEvent;
|
|
923
|
-
const hookName = progressMsg.hookName ?? progressMsg.data?.hookName;
|
|
924
|
-
if (hookEvent === "Stop") {
|
|
925
|
-
errors.push({
|
|
926
|
-
type: "unwanted_progress",
|
|
927
|
-
line: i + 1,
|
|
928
|
-
hookEvent,
|
|
929
|
-
hookName
|
|
930
|
-
});
|
|
931
|
-
}
|
|
932
|
-
} else if (msg.type === "saved_hook_context") {
|
|
953
|
+
if (msg.type === "saved_hook_context") {
|
|
933
954
|
errors.push({
|
|
934
955
|
type: "unwanted_progress",
|
|
935
956
|
line: i + 1,
|
|
@@ -1219,8 +1240,8 @@ var deleteSession = (projectName, sessionId) => Effect5.gen(function* () {
|
|
|
1219
1240
|
const projectPath = path5.join(sessionsDir, projectName);
|
|
1220
1241
|
const filePath = path5.join(projectPath, `${sessionId}.jsonl`);
|
|
1221
1242
|
const linkedAgents = yield* findLinkedAgents(projectName, sessionId);
|
|
1222
|
-
const
|
|
1223
|
-
if (
|
|
1243
|
+
const stat6 = yield* Effect5.tryPromise(() => fs6.stat(filePath));
|
|
1244
|
+
if (stat6.size === 0) {
|
|
1224
1245
|
yield* Effect5.tryPromise(() => fs6.unlink(filePath));
|
|
1225
1246
|
const agentBackupDir2 = path5.join(projectPath, ".bak");
|
|
1226
1247
|
yield* Effect5.tryPromise(() => fs6.mkdir(agentBackupDir2, { recursive: true }));
|
|
@@ -1610,7 +1631,7 @@ var loadSessionTreeDataInternal = (projectName, sessionId, summariesByTargetSess
|
|
|
1610
1631
|
}
|
|
1611
1632
|
const todos = yield* findLinkedTodos(sessionId, linkedAgentIds);
|
|
1612
1633
|
const createdAt = firstMessage?.timestamp ?? void 0;
|
|
1613
|
-
const sortTimestamp =
|
|
1634
|
+
const sortTimestamp = getSummarySortTimestamp({ summaries, createdAt });
|
|
1614
1635
|
return {
|
|
1615
1636
|
id: sessionId,
|
|
1616
1637
|
projectName,
|
|
@@ -1709,12 +1730,16 @@ var buildProjectTreeResult = (project, sessions, sort) => {
|
|
|
1709
1730
|
if (isErrorSessionTitle(s.currentSummary)) return false;
|
|
1710
1731
|
return true;
|
|
1711
1732
|
});
|
|
1733
|
+
const displaySessions = filteredSessions.map((s) => ({
|
|
1734
|
+
...s,
|
|
1735
|
+
sortTimestamp: getDisplaySortTimestamp(s, sort.field)
|
|
1736
|
+
}));
|
|
1712
1737
|
return {
|
|
1713
1738
|
name: project.name,
|
|
1714
1739
|
displayName: project.displayName,
|
|
1715
1740
|
path: project.path,
|
|
1716
|
-
sessionCount:
|
|
1717
|
-
sessions:
|
|
1741
|
+
sessionCount: displaySessions.length,
|
|
1742
|
+
sessions: displaySessions
|
|
1718
1743
|
};
|
|
1719
1744
|
};
|
|
1720
1745
|
var buildTreeCache = (globalUuidMap, allSummaries, sessions, fileMtimes) => {
|
|
@@ -1741,7 +1766,7 @@ var updateSessionSummaries = (cached, summariesByTargetSession) => {
|
|
|
1741
1766
|
const oldJson = JSON.stringify(cached.summaries);
|
|
1742
1767
|
const newJson = JSON.stringify(newSummaries);
|
|
1743
1768
|
if (oldJson === newJson) return cached;
|
|
1744
|
-
const newSortTimestamp =
|
|
1769
|
+
const newSortTimestamp = getSummarySortTimestamp({
|
|
1745
1770
|
summaries: newSummaries,
|
|
1746
1771
|
createdAt: cached.createdAt
|
|
1747
1772
|
});
|
|
@@ -1770,8 +1795,8 @@ var loadProjectTreeData = (projectName, sortOptions) => Effect6.gen(function* ()
|
|
|
1770
1795
|
(file) => Effect6.gen(function* () {
|
|
1771
1796
|
const filePath = path7.join(projectPath, file);
|
|
1772
1797
|
try {
|
|
1773
|
-
const
|
|
1774
|
-
fileMtimes.set(file.replace(".jsonl", ""),
|
|
1798
|
+
const stat6 = yield* Effect6.tryPromise(() => fs8.stat(filePath));
|
|
1799
|
+
fileMtimes.set(file.replace(".jsonl", ""), stat6.mtimeMs);
|
|
1775
1800
|
} catch {
|
|
1776
1801
|
}
|
|
1777
1802
|
})
|
|
@@ -2027,9 +2052,12 @@ var compressSession = (projectName, sessionId, options = {}) => Effect7.gen(func
|
|
|
2027
2052
|
const messagesToRemove = [];
|
|
2028
2053
|
const filteredMessages = messages.filter((msg, idx) => {
|
|
2029
2054
|
if (msg.type === "progress") {
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2055
|
+
const hookEvent = (typeof msg.hookEvent === "string" ? msg.hookEvent : void 0) ?? (typeof msg.data === "object" && msg.data !== null && "hookEvent" in msg.data ? msg.data.hookEvent : void 0);
|
|
2056
|
+
if (hookEvent !== "Stop") {
|
|
2057
|
+
removedProgress++;
|
|
2058
|
+
messagesToRemove.push(msg);
|
|
2059
|
+
return false;
|
|
2060
|
+
}
|
|
2033
2061
|
}
|
|
2034
2062
|
if (msg.type === "custom-title") {
|
|
2035
2063
|
if (customTitleIndices.length > 1 && idx !== customTitleIndices[customTitleIndices.length - 1]) {
|
|
@@ -2216,6 +2244,7 @@ var summarizeSession = (projectName, sessionId, options = {}) => Effect7.gen(fun
|
|
|
2216
2244
|
import { Effect as Effect8 } from "effect";
|
|
2217
2245
|
import * as fs10 from "fs/promises";
|
|
2218
2246
|
import * as path9 from "path";
|
|
2247
|
+
import * as os2 from "os";
|
|
2219
2248
|
var cleanInvalidMessages = (projectName, sessionId) => Effect8.gen(function* () {
|
|
2220
2249
|
const filePath = path9.join(getSessionsDir(), projectName, `${sessionId}.jsonl`);
|
|
2221
2250
|
const content = yield* Effect8.tryPromise(() => fs10.readFile(filePath, "utf-8"));
|
|
@@ -2263,9 +2292,32 @@ var previewCleanup = (projectName) => Effect8.gen(function* () {
|
|
|
2263
2292
|
const targetProjects = projectName ? projects.filter((p) => p.name === projectName) : projects;
|
|
2264
2293
|
const orphanTodos = yield* findOrphanTodos();
|
|
2265
2294
|
const orphanTodoCount = orphanTodos.length;
|
|
2295
|
+
const homeDir = os2.homedir();
|
|
2296
|
+
const staleSet = /* @__PURE__ */ new Set();
|
|
2297
|
+
yield* Effect8.all(
|
|
2298
|
+
targetProjects.map(
|
|
2299
|
+
(project) => Effect8.tryPromise(async () => {
|
|
2300
|
+
const displayPath = await folderNameToPath(project.name);
|
|
2301
|
+
const absPath = expandHomePath(displayPath, homeDir);
|
|
2302
|
+
try {
|
|
2303
|
+
const stats = await fs10.stat(absPath);
|
|
2304
|
+
if (!stats.isDirectory()) {
|
|
2305
|
+
staleSet.add(project.name);
|
|
2306
|
+
}
|
|
2307
|
+
} catch (error) {
|
|
2308
|
+
const err = error;
|
|
2309
|
+
if (err.code === "ENOENT") {
|
|
2310
|
+
staleSet.add(project.name);
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
})
|
|
2314
|
+
),
|
|
2315
|
+
{ concurrency: 10 }
|
|
2316
|
+
);
|
|
2266
2317
|
const results = yield* Effect8.all(
|
|
2267
2318
|
targetProjects.map(
|
|
2268
2319
|
(project) => Effect8.gen(function* () {
|
|
2320
|
+
const isStale = staleSet.has(project.name);
|
|
2269
2321
|
const sessions = yield* listSessions(project.name);
|
|
2270
2322
|
const emptySessions = sessions.filter((s) => s.messageCount === 0);
|
|
2271
2323
|
const invalidSessions = sessions.filter(
|
|
@@ -2286,8 +2338,9 @@ var previewCleanup = (projectName) => Effect8.gen(function* () {
|
|
|
2286
2338
|
invalidSessions,
|
|
2287
2339
|
emptyWithTodosCount,
|
|
2288
2340
|
orphanAgentCount: orphanAgents.length,
|
|
2289
|
-
orphanTodoCount: 0
|
|
2341
|
+
orphanTodoCount: 0,
|
|
2290
2342
|
// Will set for first project only
|
|
2343
|
+
isStale
|
|
2291
2344
|
};
|
|
2292
2345
|
})
|
|
2293
2346
|
),
|
|
@@ -2305,7 +2358,9 @@ var clearSessions = (options) => Effect8.gen(function* () {
|
|
|
2305
2358
|
clearInvalid = true,
|
|
2306
2359
|
skipWithTodos = true,
|
|
2307
2360
|
clearOrphanAgents = true,
|
|
2308
|
-
clearOrphanTodos = false
|
|
2361
|
+
clearOrphanTodos = false,
|
|
2362
|
+
clearStale = false,
|
|
2363
|
+
staleProjects = []
|
|
2309
2364
|
} = options;
|
|
2310
2365
|
const projects = yield* listProjects;
|
|
2311
2366
|
const targetProjects = projectName ? projects.filter((p) => p.name === projectName) : projects;
|
|
@@ -2363,12 +2418,24 @@ var clearSessions = (options) => Effect8.gen(function* () {
|
|
|
2363
2418
|
const result = yield* deleteOrphanTodos();
|
|
2364
2419
|
deletedOrphanTodoCount = result.deletedCount;
|
|
2365
2420
|
}
|
|
2421
|
+
let deletedStaleProjectCount = 0;
|
|
2422
|
+
if (clearStale && staleProjects.length > 0) {
|
|
2423
|
+
const sessionsDir = getSessionsDir();
|
|
2424
|
+
for (const staleProjectName of staleProjects) {
|
|
2425
|
+
const projectSessionsPath = path9.join(sessionsDir, staleProjectName);
|
|
2426
|
+
const deleted = yield* Effect8.tryPromise(
|
|
2427
|
+
() => fs10.rm(projectSessionsPath, { recursive: true, force: true }).then(() => true)
|
|
2428
|
+
).pipe(Effect8.orElse(() => Effect8.succeed(false)));
|
|
2429
|
+
if (deleted) deletedStaleProjectCount++;
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2366
2432
|
return {
|
|
2367
2433
|
success: true,
|
|
2368
2434
|
deletedCount: deletedSessionCount,
|
|
2369
2435
|
removedMessageCount,
|
|
2370
2436
|
deletedOrphanAgentCount,
|
|
2371
|
-
deletedOrphanTodoCount
|
|
2437
|
+
deletedOrphanTodoCount,
|
|
2438
|
+
deletedStaleProjectCount
|
|
2372
2439
|
};
|
|
2373
2440
|
});
|
|
2374
2441
|
|
|
@@ -2595,6 +2662,7 @@ export {
|
|
|
2595
2662
|
formatRelativeTime,
|
|
2596
2663
|
generateTreeNodeId,
|
|
2597
2664
|
getCachePath,
|
|
2665
|
+
getDisplaySortTimestamp,
|
|
2598
2666
|
getDisplayTitle,
|
|
2599
2667
|
getIndexEntryDisplayTitle,
|
|
2600
2668
|
getLogger,
|
|
@@ -2603,6 +2671,7 @@ export {
|
|
|
2603
2671
|
getSessionSortTimestamp,
|
|
2604
2672
|
getSessionTooltip,
|
|
2605
2673
|
getSessionsDir,
|
|
2674
|
+
getSummarySortTimestamp,
|
|
2606
2675
|
getTodoIcon,
|
|
2607
2676
|
getTodosDir,
|
|
2608
2677
|
getTotalTodoCount,
|