@claude-sessions/core 0.3.1 → 0.3.3

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 CHANGED
@@ -1,231 +1,8 @@
1
+ import { M as MessagePayload, a as Message, P as Project, T as TodoItem, F as FileChange, b as MoveSessionResult, S as SearchResult, c as SummaryInfo, A as AgentInfo } from './types-C2fzbmg9.js';
2
+ export { i as CleanupPreview, h as ClearSessionsResult, C as ContentItem, D as DeleteSessionResult, k as ProjectTreeData, R as RenameSessionResult, l as ResumeSessionOptions, m as ResumeSessionResult, f as SessionFilesSummary, d as SessionMeta, e as SessionTodos, j as SessionTreeData, g as SplitSessionResult } from './types-C2fzbmg9.js';
1
3
  import * as effect_Cause from 'effect/Cause';
2
4
  import { Effect } from 'effect';
3
5
 
4
- /**
5
- * Core types for Claude Code session management
6
- */
7
- /**
8
- * Base interface for objects with a type discriminator.
9
- * Used as a foundation for message and content types.
10
- */
11
- interface TypedObject {
12
- type: string;
13
- }
14
- /**
15
- * Text content block in a message.
16
- * @see https://docs.anthropic.com/en/api/messages
17
- */
18
- interface TextContent {
19
- type: 'text';
20
- text: string;
21
- }
22
- /**
23
- * Tool result content returned after tool execution.
24
- * Contains the output from a tool_use request.
25
- */
26
- interface ToolResultContent {
27
- type: 'tool_result';
28
- tool_use_id: string;
29
- content: string;
30
- is_error?: boolean;
31
- }
32
- /**
33
- * Tool use request from the assistant.
34
- * Represents a function call with input parameters.
35
- */
36
- interface ToolUseContent {
37
- type: 'tool_use';
38
- id: string;
39
- name: string;
40
- input: unknown;
41
- }
42
- /**
43
- * Union type for all message content blocks.
44
- * Includes known types and a fallback for unknown content types.
45
- */
46
- type ContentItem = TextContent | ToolResultContent | ToolUseContent | {
47
- type: string;
48
- text?: string;
49
- name?: string;
50
- input?: unknown;
51
- content?: string;
52
- };
53
- /**
54
- * Message payload containing role and content.
55
- * Matches Anthropic API message structure.
56
- */
57
- interface MessagePayload {
58
- role?: string;
59
- content?: ContentItem[] | string;
60
- model?: string;
61
- }
62
- /**
63
- * A single message in a Claude Code session.
64
- * Stored as a line in a JSONL session file.
65
- */
66
- interface Message extends TypedObject {
67
- /** Unique identifier for this message */
68
- uuid: string;
69
- /** Parent message UUID for conversation threading */
70
- parentUuid?: string | null;
71
- /** Session ID this message belongs to */
72
- sessionId?: string;
73
- /** Timestamp in ISO format */
74
- timestamp?: string;
75
- /** Message content (nested payload structure) */
76
- message?: MessagePayload;
77
- /** Direct content (alternative to message.content) */
78
- content?: ContentItem[] | string;
79
- /** User-defined custom title for this message */
80
- customTitle?: string;
81
- /** Summary text for summary-type messages */
82
- summary?: string;
83
- /** Flag indicating this is a context continuation summary */
84
- isCompactSummary?: boolean;
85
- /** Tool use result text (for tool_result messages) */
86
- toolUseResult?: string;
87
- }
88
- /** Basic metadata for a session, used in listings and summaries */
89
- interface SessionMeta {
90
- id: string;
91
- projectName: string;
92
- title?: string;
93
- messageCount: number;
94
- createdAt?: string;
95
- updatedAt?: string;
96
- }
97
- /** Project directory information */
98
- interface Project {
99
- name: string;
100
- displayName: string;
101
- path: string;
102
- sessionCount: number;
103
- }
104
- /** A single todo item from TodoWrite tool */
105
- interface TodoItem {
106
- content: string;
107
- status: 'pending' | 'in_progress' | 'completed';
108
- /** Active form text shown during execution */
109
- activeForm?: string;
110
- }
111
- /** Aggregated todos for a session including agent todos */
112
- interface SessionTodos {
113
- sessionId: string;
114
- sessionTodos: TodoItem[];
115
- agentTodos: {
116
- agentId: string;
117
- todos: TodoItem[];
118
- }[];
119
- hasTodos: boolean;
120
- }
121
- /** A file modification recorded during a session */
122
- interface FileChange {
123
- path: string;
124
- action: 'created' | 'modified' | 'deleted';
125
- timestamp?: string;
126
- messageUuid?: string;
127
- }
128
- /** Summary of all file changes in a session */
129
- interface SessionFilesSummary {
130
- sessionId: string;
131
- projectName: string;
132
- files: FileChange[];
133
- totalChanges: number;
134
- }
135
- /** Result of deleting a session */
136
- interface DeleteSessionResult {
137
- success: boolean;
138
- backupPath?: string;
139
- deletedAgents: number;
140
- deletedTodos?: number;
141
- }
142
- /** Result of renaming a session */
143
- interface RenameSessionResult {
144
- success: boolean;
145
- error?: string;
146
- }
147
- /** Result of splitting a session at a message */
148
- interface SplitSessionResult {
149
- success: boolean;
150
- newSessionId?: string;
151
- newSessionPath?: string;
152
- movedMessageCount?: number;
153
- duplicatedSummary?: boolean;
154
- error?: string;
155
- }
156
- /** Result of moving a session to another project */
157
- interface MoveSessionResult {
158
- success: boolean;
159
- error?: string;
160
- }
161
- /** Result of clearing empty/invalid sessions */
162
- interface ClearSessionsResult {
163
- success: boolean;
164
- deletedCount: number;
165
- removedMessageCount?: number;
166
- deletedOrphanAgentCount?: number;
167
- deletedOrphanTodoCount?: number;
168
- }
169
- /** Preview of sessions that would be cleaned up */
170
- interface CleanupPreview {
171
- project: string;
172
- emptySessions: SessionMeta[];
173
- invalidSessions: SessionMeta[];
174
- emptyWithTodosCount?: number;
175
- orphanAgentCount?: number;
176
- orphanTodoCount?: number;
177
- }
178
- /** A search result matching a session or message */
179
- interface SearchResult {
180
- sessionId: string;
181
- projectName: string;
182
- title: string;
183
- matchType: 'title' | 'content';
184
- snippet?: string;
185
- messageUuid?: string;
186
- timestamp?: string;
187
- }
188
- /** Summary extracted from a session for display */
189
- interface SummaryInfo {
190
- summary: string;
191
- leafUuid?: string;
192
- timestamp?: string;
193
- }
194
- /** Agent information for tree display */
195
- interface AgentInfo {
196
- id: string;
197
- name?: string;
198
- messageCount: number;
199
- }
200
- /** Full session data for tree view rendering */
201
- interface SessionTreeData {
202
- id: string;
203
- projectName: string;
204
- /** First user message title */
205
- title: string;
206
- /** User-set custom title */
207
- customTitle?: string;
208
- /** Current (first) summary text for display/tooltip */
209
- currentSummary?: string;
210
- messageCount: number;
211
- createdAt?: string;
212
- updatedAt?: string;
213
- /** All summaries in reverse order (newest first) */
214
- summaries: SummaryInfo[];
215
- agents: AgentInfo[];
216
- todos: SessionTodos;
217
- /** UUID of last compact_boundary message */
218
- lastCompactBoundaryUuid?: string;
219
- }
220
- /** Project with all sessions for tree view */
221
- interface ProjectTreeData {
222
- name: string;
223
- displayName: string;
224
- path: string;
225
- sessionCount: number;
226
- sessions: SessionTreeData[];
227
- }
228
-
229
6
  interface Logger$1 {
230
7
  debug: (msg: string) => void;
231
8
  warn: (msg: string) => void;
@@ -280,6 +57,22 @@ declare const isContinuationSummary: (msg: Message) => boolean;
280
57
  * Priority: customTitle > currentSummary (truncated) > title > fallback
281
58
  */
282
59
  declare const getDisplayTitle: (customTitle: string | undefined, currentSummary: string | undefined, title: string | undefined, maxLength?: number, fallback?: string) => string;
60
+ /**
61
+ * Mask home directory path with ~
62
+ * Only masks the specified homeDir, not other users' paths
63
+ */
64
+ declare const maskHomePath: (text: string, homeDir: string) => string;
65
+ /**
66
+ * Sort projects with priority:
67
+ * 1. Current project (if specified)
68
+ * 2. Current user's home directory subpaths
69
+ * 3. Others (alphabetically by displayName)
70
+ */
71
+ declare const sortProjects: (projects: Project[], options?: {
72
+ currentProjectName?: string | null;
73
+ homeDir?: string;
74
+ filterEmpty?: boolean;
75
+ }) => Project[];
283
76
 
284
77
  declare const findLinkedAgents: (projectName: string, sessionId: string) => Effect.Effect<string[], effect_Cause.UnknownException, never>;
285
78
  declare const findOrphanAgents: (projectName: string) => Effect.Effect<{
@@ -507,4 +300,4 @@ declare const getLogger: () => Logger;
507
300
  */
508
301
  declare const createLogger: (namespace: string) => Logger;
509
302
 
510
- export { type AgentInfo, type CleanupPreview, type ClearSessionsResult, type ContentItem, type DeleteSessionResult, type FileChange, type Logger, type Message, type MessagePayload, type MoveSessionResult, type Project, type ProjectTreeData, type RenameSessionResult, type SearchResult, type SessionFilesSummary, type SessionMeta, type SessionTodos, type SessionTreeData, type SplitSessionResult, type SummaryInfo, type TodoItem, clearSessions, createLogger, deleteLinkedTodos, deleteMessage, deleteOrphanAgents, deleteOrphanTodos, deleteSession, displayPathToFolderName, extractTextContent, extractTitle, findLinkedAgents, findLinkedTodos, findOrphanAgents, findOrphanTodos, folderNameToDisplayPath, folderNameToPath, getDisplayTitle, getLogger, getRealPathFromSession, getSessionFiles, getSessionsDir, getTodosDir, isContinuationSummary, isInvalidApiKeyMessage, listProjects, listSessions, loadAgentMessages, loadProjectTreeData, loadSessionTreeData, moveSession, pathToFolderName, previewCleanup, readSession, renameSession, restoreMessage, searchSessions, sessionHasTodos, setLogger, splitSession, updateSessionSummary };
303
+ export { AgentInfo, FileChange, type Logger, Message, MessagePayload, MoveSessionResult, Project, SearchResult, SummaryInfo, TodoItem, clearSessions, createLogger, deleteLinkedTodos, deleteMessage, deleteOrphanAgents, deleteOrphanTodos, deleteSession, displayPathToFolderName, extractTextContent, extractTitle, findLinkedAgents, findLinkedTodos, findOrphanAgents, findOrphanTodos, folderNameToDisplayPath, folderNameToPath, getDisplayTitle, getLogger, getRealPathFromSession, getSessionFiles, getSessionsDir, getTodosDir, isContinuationSummary, isInvalidApiKeyMessage, listProjects, listSessions, loadAgentMessages, loadProjectTreeData, loadSessionTreeData, maskHomePath, moveSession, pathToFolderName, previewCleanup, readSession, renameSession, restoreMessage, searchSessions, sessionHasTodos, setLogger, sortProjects, splitSession, updateSessionSummary };
package/dist/index.js CHANGED
@@ -186,22 +186,56 @@ var getDisplayTitle = (customTitle, currentSummary, title, maxLength = 60, fallb
186
186
  if (title && title !== "Untitled") return title;
187
187
  return fallback;
188
188
  };
189
+ var replaceMessageContent = (msg, text) => ({
190
+ ...msg,
191
+ message: {
192
+ ...msg.message,
193
+ content: [{ type: "text", text }]
194
+ },
195
+ toolUseResult: void 0
196
+ });
189
197
  var cleanupSplitFirstMessage = (msg) => {
190
198
  const toolUseResult = msg.toolUseResult;
191
199
  if (!toolUseResult) return msg;
192
- const rejectionMarker = "The user provided the following reason for the rejection:";
193
- const rejectionIndex = toolUseResult.indexOf(rejectionMarker);
194
- if (rejectionIndex === -1) return msg;
195
- const text = toolUseResult.slice(rejectionIndex + rejectionMarker.length).trim();
196
- if (!text) return msg;
197
- return {
198
- ...msg,
199
- message: {
200
- ...msg.message,
201
- content: [{ type: "text", text }]
202
- },
203
- toolUseResult: void 0
204
- };
200
+ if (typeof toolUseResult === "object" && "answers" in toolUseResult) {
201
+ const answers = toolUseResult.answers;
202
+ const qaText = Object.entries(answers).map(([q, a]) => `Q: ${q}
203
+ A: ${a}`).join("\n\n");
204
+ return replaceMessageContent(msg, qaText);
205
+ }
206
+ if (typeof toolUseResult === "string") {
207
+ const rejectionMarker = "The user provided the following reason for the rejection:";
208
+ const rejectionIndex = toolUseResult.indexOf(rejectionMarker);
209
+ if (rejectionIndex === -1) return msg;
210
+ const text = toolUseResult.slice(rejectionIndex + rejectionMarker.length).trim();
211
+ if (!text) return msg;
212
+ return replaceMessageContent(msg, text);
213
+ }
214
+ return msg;
215
+ };
216
+ var maskHomePath = (text, homeDir) => {
217
+ if (!homeDir) return text;
218
+ const escapedHome = homeDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
219
+ const regex = new RegExp(`${escapedHome}(?=[/\\\\]|$)`, "g");
220
+ return text.replace(regex, "~");
221
+ };
222
+ var sortProjects = (projects, options = {}) => {
223
+ const { currentProjectName, homeDir, filterEmpty = true } = options;
224
+ const filtered = filterEmpty ? projects.filter((p) => p.sessionCount > 0) : projects;
225
+ const homeDirPrefix = homeDir ? pathToFolderName(homeDir) : null;
226
+ return filtered.sort((a, b) => {
227
+ if (currentProjectName) {
228
+ if (a.name === currentProjectName) return -1;
229
+ if (b.name === currentProjectName) return 1;
230
+ }
231
+ if (homeDirPrefix) {
232
+ const aIsUserHome = a.name.startsWith(homeDirPrefix);
233
+ const bIsUserHome = b.name.startsWith(homeDirPrefix);
234
+ if (aIsUserHome && !bIsUserHome) return -1;
235
+ if (!aIsUserHome && bIsUserHome) return 1;
236
+ }
237
+ return a.displayName.localeCompare(b.displayName);
238
+ });
205
239
  };
206
240
 
207
241
  // src/agents.ts
@@ -847,36 +881,40 @@ var splitSession = (projectName, sessionId, splitAtMessageUuid) => Effect3.gen(f
847
881
  const summaryMessage = summaryMessages.length > 0 ? summaryMessages[summaryMessages.length - 1] : null;
848
882
  const splitMessage = allMessages[splitIndex];
849
883
  const shouldDuplicate = isContinuationSummary(splitMessage);
850
- let remainingMessages;
851
- const movedMessages = allMessages.slice(splitIndex);
884
+ let keptMessages = allMessages.slice(splitIndex);
885
+ let movedMessages;
852
886
  if (shouldDuplicate) {
853
887
  const duplicatedMessage = {
854
888
  ...splitMessage,
855
889
  uuid: crypto.randomUUID(),
856
- sessionId
857
- // Keep original session ID
890
+ sessionId: newSessionId
858
891
  };
859
- remainingMessages = [...allMessages.slice(0, splitIndex), duplicatedMessage];
892
+ movedMessages = [...allMessages.slice(0, splitIndex), duplicatedMessage];
860
893
  } else {
861
- remainingMessages = allMessages.slice(0, splitIndex);
894
+ movedMessages = allMessages.slice(0, splitIndex);
862
895
  }
863
- const updatedMovedMessages = movedMessages.map((msg, index) => {
864
- let updated = { ...msg, sessionId: newSessionId };
896
+ keptMessages = keptMessages.map((msg, index) => {
897
+ let updated = { ...msg };
865
898
  if (index === 0) {
866
899
  updated.parentUuid = null;
867
900
  updated = cleanupSplitFirstMessage(updated);
868
901
  }
869
902
  return updated;
870
903
  });
904
+ const updatedMovedMessages = movedMessages.map((msg) => ({
905
+ ...msg,
906
+ sessionId: newSessionId
907
+ }));
871
908
  if (summaryMessage) {
872
909
  const clonedSummary = {
873
910
  ...summaryMessage,
911
+ sessionId: newSessionId,
874
912
  leafUuid: updatedMovedMessages[0]?.uuid ?? null
875
913
  };
876
914
  updatedMovedMessages.unshift(clonedSummary);
877
915
  }
878
- const remainingContent = remainingMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
879
- yield* Effect3.tryPromise(() => fs4.writeFile(filePath, remainingContent, "utf-8"));
916
+ const keptContent = keptMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
917
+ yield* Effect3.tryPromise(() => fs4.writeFile(filePath, keptContent, "utf-8"));
880
918
  const newFilePath = path4.join(projectPath, `${newSessionId}.jsonl`);
881
919
  const newContent = updatedMovedMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
882
920
  yield* Effect3.tryPromise(() => fs4.writeFile(newFilePath, newContent, "utf-8"));
@@ -1382,6 +1420,7 @@ export {
1382
1420
  loadAgentMessages,
1383
1421
  loadProjectTreeData,
1384
1422
  loadSessionTreeData,
1423
+ maskHomePath,
1385
1424
  moveSession,
1386
1425
  pathToFolderName,
1387
1426
  previewCleanup,
@@ -1391,6 +1430,7 @@ export {
1391
1430
  searchSessions,
1392
1431
  sessionHasTodos,
1393
1432
  setLogger,
1433
+ sortProjects,
1394
1434
  splitSession,
1395
1435
  updateSessionSummary
1396
1436
  };