@claude-sessions/core 0.4.0 → 0.4.2-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 CHANGED
@@ -1,5 +1,5 @@
1
- import { M as MessagePayload, a as Message, P as Project, S as SummaryInfo, T as TodoItem, b as MoveSessionResult, A as AgentInfo, c as SessionSortOptions, C as CompressSessionOptions, d as SummarizeSessionOptions, e as ConversationLine, f as SearchResult, F as FileChange, g as SessionsIndex, h as SessionIndexEntry } from './types-BdPaAnP8.js';
2
- export { o as CleanupPreview, n as ClearSessionsResult, v as CompressSessionResult, i as ContentItem, D as DeleteSessionResult, w as ProjectKnowledge, q as ProjectTreeData, R as RenameSessionResult, r as ResumeSessionOptions, s as ResumeSessionResult, u as SessionAnalysis, l as SessionFilesSummary, j as SessionMeta, y as SessionSortField, z as SessionSortOrder, k as SessionTodos, p as SessionTreeData, m as SplitSessionResult, x as SummarizeSessionResult, t as ToolUsageStats } from './types-BdPaAnP8.js';
1
+ import { P as Project, M as MessagePayload$1, a as Message, S as SummaryInfo, b as SessionTodos, c as MoveSessionResult, A as AgentInfo, d as SessionSortOptions, e as ProjectTreeData, C as CompressSessionOptions, f as SummarizeSessionOptions, g as ConversationLine, h as SearchResult, F as FileChange, i as SessionsIndex, j as SessionIndexEntry } from './types-mWa378iC.js';
2
+ export { p as CleanupPreview, o as ClearSessionsResult, v as CompressSessionResult, k as ContentItem, D as DeleteSessionResult, w as ProjectKnowledge, R as RenameSessionResult, r as ResumeSessionOptions, s as ResumeSessionResult, u as SessionAnalysis, m as SessionFilesSummary, l as SessionMeta, y as SessionSortField, z as SessionSortOrder, q as SessionTreeData, n as SplitSessionResult, x as SummarizeSessionResult, T as TodoItem, t as ToolUsageStats } from './types-mWa378iC.js';
3
3
  import * as effect_Cause from 'effect/Cause';
4
4
  import { Effect } from 'effect';
5
5
 
@@ -59,16 +59,37 @@ declare const folderNameToPath: (folderName: string) => string;
59
59
  declare const findProjectByWorkspacePath: (workspacePath: string, projectNames: string[], sessionsDir?: string, fileSystem?: FileSystem, logger?: Logger$1) => string | null;
60
60
 
61
61
  /**
62
- * Utility functions for message processing
62
+ * Project-level utilities
63
63
  */
64
64
 
65
- declare const extractTextContent: (message: MessagePayload | undefined) => 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[];
76
+
77
+ declare const extractTextContent: (message: MessagePayload$1 | undefined) => string;
78
+ /**
79
+ * Parse command message content (e.g., slash commands like /commit)
80
+ * Returns the command name and message extracted from XML tags
81
+ */
82
+ declare const parseCommandMessage: (content?: string) => {
83
+ name: string;
84
+ message: string;
85
+ };
66
86
  declare const extractTitle: (text: string) => string;
67
87
  declare const isInvalidApiKeyMessage: (msg: Message) => boolean;
68
88
  declare const isContinuationSummary: (msg: Message) => boolean;
69
89
  /**
70
90
  * Get display title with fallback logic
71
91
  * Priority: customTitle > currentSummary (truncated) > title > fallback
92
+ * Also handles slash command format in title
72
93
  */
73
94
  declare const getDisplayTitle: (customTitle: string | undefined, currentSummary: string | undefined, title: string | undefined, maxLength?: number, fallback?: string) => string;
74
95
  /**
@@ -77,31 +98,28 @@ declare const getDisplayTitle: (customTitle: string | undefined, currentSummary:
77
98
  */
78
99
  declare const maskHomePath: (text: string, homeDir: string) => string;
79
100
  /**
80
- * Get session sort timestamp based on official Claude Code extension behavior
81
- *
82
- * CRITICAL ARCHITECTURE:
83
- * - Summary records have `leafUuid` but NO timestamp in the summary record itself
84
- * - `leafUuid` points to a message in ANOTHER session (cross-session reference)
85
- * - The timestamp for sorting must come from the TARGET message's timestamp
86
- * - Official extension uses leafUuid's target message timestamp for sorting/display
87
- *
88
- * Priority: summaries[0].timestamp (leafUuid-based) > createdAt
101
+ * Get sort timestamp for session (Unix timestamp ms)
102
+ * Priority: summaries[0].timestamp > createdAt > 0
89
103
  */
90
104
  declare const getSessionSortTimestamp: (session: {
91
105
  summaries?: SummaryInfo[];
92
106
  createdAt?: string;
93
- }) => string | undefined;
107
+ }) => number;
94
108
  /**
95
- * Sort projects with priority:
96
- * 1. Current project (if specified)
97
- * 2. Current user's home directory subpaths
98
- * 3. Others (alphabetically by displayName)
109
+ * Try to parse a single JSON line, returning null on failure with optional warning log
110
+ * Use this when you want to skip invalid lines instead of throwing
99
111
  */
100
- declare const sortProjects: (projects: Project[], options?: {
101
- currentProjectName?: string | null;
102
- homeDir?: string;
103
- filterEmpty?: boolean;
104
- }) => Project[];
112
+ declare const tryParseJsonLine: <T = Record<string, unknown>>(line: string, lineNumber: number, filePath?: string) => T | null;
113
+ /**
114
+ * Parse JSONL lines with detailed error messages including file path and line number
115
+ * @throws Error with "Failed to parse line X in /path/to/file: original error"
116
+ */
117
+ declare const parseJsonlLines: <T = Record<string, unknown>>(lines: string[], filePath: string) => T[];
118
+ /**
119
+ * Read and parse JSONL file (Effect wrapper)
120
+ * Combines file reading and JSONL parsing with proper error messages
121
+ */
122
+ declare const readJsonlFile: <T = Record<string, unknown>>(filePath: string) => Effect.Effect<T[], effect_Cause.UnknownException, never>;
105
123
 
106
124
  declare const findLinkedAgents: (projectName: string, sessionId: string) => Effect.Effect<string[], effect_Cause.UnknownException, never>;
107
125
  declare const findOrphanAgents: (projectName: string) => Effect.Effect<{
@@ -121,15 +139,7 @@ declare const deleteOrphanAgents: (projectName: string) => Effect.Effect<{
121
139
  declare const loadAgentMessages: (projectName: string, _sessionId: string, // Reserved for future validation
122
140
  agentId: string) => Effect.Effect<Message[], effect_Cause.UnknownException, never>;
123
141
 
124
- declare const findLinkedTodos: (sessionId: string, agentIds?: string[]) => Effect.Effect<{
125
- sessionId: string;
126
- sessionTodos: TodoItem[];
127
- agentTodos: {
128
- agentId: string;
129
- todos: TodoItem[];
130
- }[];
131
- hasTodos: boolean;
132
- }, effect_Cause.UnknownException, never>;
142
+ declare const findLinkedTodos: (sessionId: string, agentIds?: string[]) => Effect.Effect<SessionTodos, effect_Cause.UnknownException, never>;
133
143
  declare const sessionHasTodos: (sessionId: string, agentIds?: string[]) => Effect.Effect<boolean, effect_Cause.UnknownException, never>;
134
144
  declare const deleteLinkedTodos: (sessionId: string, agentIds: string[]) => Effect.Effect<{
135
145
  deletedCount: number;
@@ -156,7 +166,7 @@ declare const listSessions: (projectName: string) => Effect.Effect<{
156
166
  updatedAt: string | undefined;
157
167
  }[], effect_Cause.UnknownException, never>;
158
168
  declare const readSession: (projectName: string, sessionId: string) => Effect.Effect<Message[], effect_Cause.UnknownException, never>;
159
- declare const deleteMessage: (projectName: string, sessionId: string, messageUuid: string) => Effect.Effect<{
169
+ declare const deleteMessage: (projectName: string, sessionId: string, messageUuid: string, targetType?: "file-history-snapshot" | "summary") => Effect.Effect<{
160
170
  success: boolean;
161
171
  error: string;
162
172
  deletedMessage?: undefined;
@@ -217,48 +227,13 @@ declare const loadSessionTreeData: (projectName: string, sessionId: string) => E
217
227
  createdAt: string;
218
228
  updatedAt: string;
219
229
  fileMtime: number | undefined;
230
+ sortTimestamp: number;
220
231
  summaries: SummaryInfo[];
221
232
  agents: AgentInfo[];
222
- todos: {
223
- sessionId: string;
224
- sessionTodos: TodoItem[];
225
- agentTodos: {
226
- agentId: string;
227
- todos: TodoItem[];
228
- }[];
229
- hasTodos: boolean;
230
- };
233
+ todos: SessionTodos;
231
234
  lastCompactBoundaryUuid: string | undefined;
232
235
  }, effect_Cause.UnknownException, never>;
233
- declare const loadProjectTreeData: (projectName: string, sortOptions?: SessionSortOptions) => Effect.Effect<{
234
- name: string;
235
- displayName: string;
236
- path: string;
237
- sessionCount: number;
238
- sessions: {
239
- id: string;
240
- projectName: string;
241
- title: string;
242
- customTitle: string | undefined;
243
- currentSummary: string;
244
- messageCount: number;
245
- createdAt: string;
246
- updatedAt: string;
247
- fileMtime: number | undefined;
248
- summaries: SummaryInfo[];
249
- agents: AgentInfo[];
250
- todos: {
251
- sessionId: string;
252
- sessionTodos: TodoItem[];
253
- agentTodos: {
254
- agentId: string;
255
- todos: TodoItem[];
256
- }[];
257
- hasTodos: boolean;
258
- };
259
- lastCompactBoundaryUuid: string | undefined;
260
- }[];
261
- } | null, effect_Cause.UnknownException, never>;
236
+ declare const loadProjectTreeData: (projectName: string, sortOptions?: SessionSortOptions) => Effect.Effect<ProjectTreeData | null, effect_Cause.UnknownException, never>;
262
237
 
263
238
  declare const analyzeSession: (projectName: string, sessionId: string) => Effect.Effect<{
264
239
  sessionId: string;
@@ -364,7 +339,13 @@ declare const clearSessions: (options: {
364
339
  declare const searchSessions: (query: string, options?: {
365
340
  projectName?: string;
366
341
  searchContent?: boolean;
367
- }) => Effect.Effect<SearchResult[], effect_Cause.UnknownException, never>;
342
+ }) => Effect.Effect<(SearchResult | {
343
+ sessionId: string;
344
+ projectName: string;
345
+ title: string;
346
+ matchType: "title";
347
+ timestamp: string | undefined;
348
+ })[], effect_Cause.UnknownException, never>;
368
349
 
369
350
  declare const getSessionFiles: (projectName: string, sessionId: string) => Effect.Effect<{
370
351
  sessionId: string;
@@ -373,6 +354,75 @@ declare const getSessionFiles: (projectName: string, sessionId: string) => Effec
373
354
  totalChanges: number;
374
355
  }, effect_Cause.UnknownException, never>;
375
356
 
357
+ /**
358
+ * Session message chain validation utilities
359
+ *
360
+ * Validates:
361
+ * 1. parentUuid chain integrity (skip file-history-snapshot)
362
+ * 2. tool_use_id / tool_result matching
363
+ */
364
+ interface ChainError {
365
+ type: 'broken_chain' | 'orphan_parent';
366
+ uuid: string;
367
+ line: number;
368
+ parentUuid: string | null;
369
+ expectedParent?: string;
370
+ }
371
+ interface ToolUseResultError {
372
+ type: 'orphan_tool_result';
373
+ uuid: string;
374
+ line: number;
375
+ toolUseId: string;
376
+ }
377
+ interface ValidationResult {
378
+ valid: boolean;
379
+ errors: (ChainError | ToolUseResultError)[];
380
+ }
381
+ interface MessagePayload {
382
+ role?: string;
383
+ content?: unknown;
384
+ }
385
+ interface GenericMessage {
386
+ type?: string;
387
+ uuid?: string;
388
+ parentUuid?: string | null;
389
+ message?: MessagePayload;
390
+ messageId?: string;
391
+ }
392
+ /**
393
+ * Validate parentUuid chain for messages
394
+ *
395
+ * Rules:
396
+ * - Skip file-history-snapshot type (has no uuid, uses messageId instead)
397
+ * - Skip messages without uuid
398
+ * - First message can have null parentUuid
399
+ * - Subsequent messages must have valid parentUuid pointing to existing uuid
400
+ */
401
+ declare function validateChain(messages: readonly GenericMessage[]): ValidationResult;
402
+ /**
403
+ * Validate tool_use_id / tool_result matching
404
+ *
405
+ * Rules:
406
+ * - All tool_result blocks must have a corresponding tool_use block in the session
407
+ * - tool_use blocks are collected from all messages (not just previous)
408
+ */
409
+ declare function validateToolUseResult(messages: readonly GenericMessage[]): ValidationResult;
410
+ /**
411
+ * Delete a message and repair the parentUuid chain
412
+ *
413
+ * This is a pure function for client-side use (without file I/O)
414
+ * Server-side deleteMessage in crud.ts uses similar logic with file operations
415
+ *
416
+ * @param messages - Array of messages (will be mutated)
417
+ * @param targetId - uuid, messageId, or leafUuid of message to delete
418
+ * @param targetType - Optional: 'file-history-snapshot' or 'summary' to disambiguate collisions
419
+ * @returns Object with deleted message and messages to also delete (orphan tool_results)
420
+ */
421
+ declare function deleteMessageWithChainRepair<T extends GenericMessage>(messages: T[], targetId: string, targetType?: 'file-history-snapshot' | 'summary'): {
422
+ deleted: T | null;
423
+ alsoDeleted: T[];
424
+ };
425
+
376
426
  /**
377
427
  * Load sessions-index.json for a project
378
428
  * Returns null if the file doesn't exist
@@ -426,4 +476,4 @@ declare const getLogger: () => Logger;
426
476
  */
427
477
  declare const createLogger: (namespace: string) => Logger;
428
478
 
429
- export { AgentInfo, CompressSessionOptions, ConversationLine, FileChange, type Logger, Message, MessagePayload, MoveSessionResult, Project, SearchResult, SessionIndexEntry, SessionSortOptions, SessionsIndex, SummarizeSessionOptions, SummaryInfo, TodoItem, analyzeSession, clearSessions, compressSession, createLogger, deleteLinkedTodos, deleteMessage, deleteOrphanAgents, deleteOrphanTodos, deleteSession, displayPathToFolderName, extractProjectKnowledge, extractTextContent, extractTitle, findLinkedAgents, findLinkedTodos, findOrphanAgents, findOrphanTodos, findProjectByWorkspacePath, folderNameToDisplayPath, folderNameToPath, getDisplayTitle, getIndexEntryDisplayTitle, getLogger, getRealPathFromSession, getSessionFiles, getSessionSortTimestamp, getSessionsDir, getTodosDir, hasSessionsIndex, isContinuationSummary, isInvalidApiKeyMessage, listProjects, listSessions, loadAgentMessages, loadProjectTreeData, loadSessionTreeData, loadSessionsIndex, maskHomePath, moveSession, pathToFolderName, previewCleanup, readSession, renameSession, restoreMessage, searchSessions, sessionHasTodos, setLogger, sortIndexEntriesByModified, sortProjects, splitSession, summarizeSession, updateSessionSummary };
479
+ export { AgentInfo, type ChainError, CompressSessionOptions, ConversationLine, FileChange, type Logger, Message, MessagePayload$1 as MessagePayload, MoveSessionResult, Project, ProjectTreeData, SearchResult, SessionIndexEntry, SessionSortOptions, SessionTodos, SessionsIndex, SummarizeSessionOptions, SummaryInfo, type ToolUseResultError, type ValidationResult, analyzeSession, clearSessions, compressSession, createLogger, deleteLinkedTodos, deleteMessage, deleteMessageWithChainRepair, deleteOrphanAgents, deleteOrphanTodos, deleteSession, displayPathToFolderName, extractProjectKnowledge, extractTextContent, extractTitle, findLinkedAgents, findLinkedTodos, findOrphanAgents, findOrphanTodos, findProjectByWorkspacePath, folderNameToDisplayPath, folderNameToPath, getDisplayTitle, getIndexEntryDisplayTitle, getLogger, getRealPathFromSession, getSessionFiles, getSessionSortTimestamp, getSessionsDir, getTodosDir, hasSessionsIndex, isContinuationSummary, isInvalidApiKeyMessage, listProjects, listSessions, loadAgentMessages, loadProjectTreeData, loadSessionTreeData, loadSessionsIndex, maskHomePath, moveSession, parseCommandMessage, parseJsonlLines, pathToFolderName, previewCleanup, readJsonlFile, readSession, renameSession, restoreMessage, searchSessions, sessionHasTodos, setLogger, sortIndexEntriesByModified, sortProjects, splitSession, summarizeSession, tryParseJsonLine, updateSessionSummary, validateChain, validateToolUseResult };