claude-sessions 0.1.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/LICENSE +661 -0
- package/README.md +140 -0
- package/data/model-pricing.json +113 -0
- package/dist/cost-calculator.d.ts +49 -0
- package/dist/cost-calculator.d.ts.map +1 -0
- package/dist/cost-calculator.js +429 -0
- package/dist/cost-calculator.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/dist/projects-service.d.ts +106 -0
- package/dist/projects-service.d.ts.map +1 -0
- package/dist/projects-service.js +317 -0
- package/dist/projects-service.js.map +1 -0
- package/dist/session-cache-store.d.ts +48 -0
- package/dist/session-cache-store.d.ts.map +1 -0
- package/dist/session-cache-store.js +231 -0
- package/dist/session-cache-store.js.map +1 -0
- package/dist/session-cache.d.ts +266 -0
- package/dist/session-cache.d.ts.map +1 -0
- package/dist/session-cache.js +1294 -0
- package/dist/session-cache.js.map +1 -0
- package/dist/session-parser.d.ts +265 -0
- package/dist/session-parser.d.ts.map +1 -0
- package/dist/session-parser.js +555 -0
- package/dist/session-parser.js.map +1 -0
- package/dist/session-reader.d.ts +87 -0
- package/dist/session-reader.d.ts.map +1 -0
- package/dist/session-reader.js +279 -0
- package/dist/session-reader.js.map +1 -0
- package/dist/tasks-service.d.ts +100 -0
- package/dist/tasks-service.d.ts.map +1 -0
- package/dist/tasks-service.js +290 -0
- package/dist/tasks-service.js.map +1 -0
- package/dist/teams-service.d.ts +30 -0
- package/dist/teams-service.d.ts.map +1 -0
- package/dist/teams-service.js +85 -0
- package/dist/teams-service.js.map +1 -0
- package/dist/types.d.ts +87 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/path-utils.d.ts +80 -0
- package/dist/utils/path-utils.d.ts.map +1 -0
- package/dist/utils/path-utils.js +355 -0
- package/dist/utils/path-utils.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Session Reader
|
|
4
|
+
*
|
|
5
|
+
* Read-only access to session files in ~/.claude/projects/.
|
|
6
|
+
* Provides low-level JSONL file discovery and reading.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.SessionReader = void 0;
|
|
43
|
+
exports.createSessionReader = createSessionReader;
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const os = __importStar(require("os"));
|
|
47
|
+
const readline = __importStar(require("readline"));
|
|
48
|
+
const path_utils_1 = require("./utils/path-utils");
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// SessionReader Implementation
|
|
51
|
+
// ============================================================================
|
|
52
|
+
/**
|
|
53
|
+
* Read-only access to session files.
|
|
54
|
+
*
|
|
55
|
+
* Sessions are stored in ~/.claude/projects/{projectKey}/ as JSONL files.
|
|
56
|
+
* This class provides methods to:
|
|
57
|
+
* - List sessions and projects
|
|
58
|
+
* - Read session data (messages, tool uses, etc.)
|
|
59
|
+
* - Access conversation history
|
|
60
|
+
* - Read subagent session files
|
|
61
|
+
*/
|
|
62
|
+
class SessionReader {
|
|
63
|
+
configDir;
|
|
64
|
+
defaultCwd;
|
|
65
|
+
constructor(config) {
|
|
66
|
+
this.configDir = config?.configDir || path.join(os.homedir(), '.claude');
|
|
67
|
+
this.defaultCwd = config?.defaultCwd;
|
|
68
|
+
}
|
|
69
|
+
getProjectsDir() {
|
|
70
|
+
return path.join(this.configDir, 'projects');
|
|
71
|
+
}
|
|
72
|
+
cwdToProjectKey(cwd) {
|
|
73
|
+
return cwd.replace(/[:\\/]/g, '-');
|
|
74
|
+
}
|
|
75
|
+
getProjectDir(cwd) {
|
|
76
|
+
const workingDir = cwd || this.defaultCwd || process.cwd();
|
|
77
|
+
const projectKey = this.cwdToProjectKey(workingDir);
|
|
78
|
+
return path.join(this.getProjectsDir(), projectKey);
|
|
79
|
+
}
|
|
80
|
+
getSessionFilePath(sessionId, cwd) {
|
|
81
|
+
return path.join(this.getProjectDir(cwd), `${sessionId}.jsonl`);
|
|
82
|
+
}
|
|
83
|
+
listSessions(cwd) {
|
|
84
|
+
const projectDir = this.getProjectDir(cwd);
|
|
85
|
+
if (!fs.existsSync(projectDir)) {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
const sessions = [];
|
|
89
|
+
const files = fs.readdirSync(projectDir);
|
|
90
|
+
for (const file of files) {
|
|
91
|
+
if (!file.endsWith('.jsonl') || file.startsWith('agent-')) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const sessionId = file.replace('.jsonl', '');
|
|
95
|
+
const filePath = path.join(projectDir, file);
|
|
96
|
+
const stats = fs.statSync(filePath);
|
|
97
|
+
sessions.push({
|
|
98
|
+
sessionId,
|
|
99
|
+
projectPath: cwd || this.defaultCwd || process.cwd(),
|
|
100
|
+
projectKey: this.cwdToProjectKey(cwd || this.defaultCwd || process.cwd()),
|
|
101
|
+
lastModified: stats.mtime,
|
|
102
|
+
sizeBytes: stats.size,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
sessions.sort((a, b) => b.lastModified.getTime() - a.lastModified.getTime());
|
|
106
|
+
return sessions;
|
|
107
|
+
}
|
|
108
|
+
listSessionsWithDetails(cwd) {
|
|
109
|
+
const summaries = this.listSessions(cwd);
|
|
110
|
+
const detailed = [];
|
|
111
|
+
for (const summary of summaries) {
|
|
112
|
+
const info = { ...summary };
|
|
113
|
+
try {
|
|
114
|
+
const filePath = this.getSessionFilePath(summary.sessionId, cwd);
|
|
115
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
116
|
+
const lines = content.trim().split('\n');
|
|
117
|
+
if (lines.length > 0) {
|
|
118
|
+
try {
|
|
119
|
+
const firstLine = JSON.parse(lines[0]);
|
|
120
|
+
if (firstLine.type === 'system' && firstLine.subtype === 'init') {
|
|
121
|
+
info.model = firstLine.model;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// Ignore parse errors
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
const lastLine = JSON.parse(lines[lines.length - 1]);
|
|
129
|
+
if (lastLine.type === 'result') {
|
|
130
|
+
info.numTurns = lastLine.num_turns;
|
|
131
|
+
info.totalCostUsd = lastLine.total_cost_usd;
|
|
132
|
+
info.durationMs = lastLine.duration_ms;
|
|
133
|
+
info.status = lastLine.is_error ? 'error' : 'completed';
|
|
134
|
+
info.result = lastLine.result;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
info.status = 'active';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Ignore parse errors
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// Ignore read errors
|
|
147
|
+
}
|
|
148
|
+
detailed.push(info);
|
|
149
|
+
}
|
|
150
|
+
return detailed;
|
|
151
|
+
}
|
|
152
|
+
listProjects() {
|
|
153
|
+
const projectsDir = this.getProjectsDir();
|
|
154
|
+
if (!fs.existsSync(projectsDir)) {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
const projects = [];
|
|
158
|
+
const entries = fs.readdirSync(projectsDir, { withFileTypes: true });
|
|
159
|
+
for (const entry of entries) {
|
|
160
|
+
if (!entry.isDirectory())
|
|
161
|
+
continue;
|
|
162
|
+
const projectDir = path.join(projectsDir, entry.name);
|
|
163
|
+
const files = fs.readdirSync(projectDir).filter(f => f.endsWith('.jsonl') && !f.startsWith('agent-'));
|
|
164
|
+
if (files.length === 0)
|
|
165
|
+
continue;
|
|
166
|
+
let lastActivity = new Date(0);
|
|
167
|
+
for (const file of files) {
|
|
168
|
+
const stats = fs.statSync(path.join(projectDir, file));
|
|
169
|
+
if (stats.mtime > lastActivity) {
|
|
170
|
+
lastActivity = stats.mtime;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
projects.push({
|
|
174
|
+
key: entry.name,
|
|
175
|
+
path: (0, path_utils_1.decodePath)(entry.name),
|
|
176
|
+
sessionCount: files.length,
|
|
177
|
+
lastActivity,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
projects.sort((a, b) => b.lastActivity.getTime() - a.lastActivity.getTime());
|
|
181
|
+
return projects;
|
|
182
|
+
}
|
|
183
|
+
sessionExists(sessionId, cwd) {
|
|
184
|
+
const filePath = this.getSessionFilePath(sessionId, cwd);
|
|
185
|
+
return fs.existsSync(filePath);
|
|
186
|
+
}
|
|
187
|
+
listSubagentFiles(sessionId, cwd) {
|
|
188
|
+
const projectDir = this.getProjectDir(cwd);
|
|
189
|
+
if (!fs.existsSync(projectDir)) {
|
|
190
|
+
return [];
|
|
191
|
+
}
|
|
192
|
+
const files = [];
|
|
193
|
+
const addAgentFile = (filePath, parentSessionId) => {
|
|
194
|
+
const fileName = path.basename(filePath);
|
|
195
|
+
const match = fileName.match(/^agent-(.+)\.jsonl$/);
|
|
196
|
+
if (!match)
|
|
197
|
+
return;
|
|
198
|
+
const agentId = match[1];
|
|
199
|
+
try {
|
|
200
|
+
const stats = fs.statSync(filePath);
|
|
201
|
+
files.push({
|
|
202
|
+
agentId,
|
|
203
|
+
sessionId: parentSessionId,
|
|
204
|
+
filePath,
|
|
205
|
+
lastModified: stats.mtime,
|
|
206
|
+
sizeBytes: stats.size,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// Ignore files we can't stat
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
const entries = fs.readdirSync(projectDir);
|
|
214
|
+
for (const file of entries) {
|
|
215
|
+
if (file.startsWith('agent-') && file.endsWith('.jsonl')) {
|
|
216
|
+
addAgentFile(path.join(projectDir, file), sessionId || 'unknown');
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
for (const entry of entries) {
|
|
220
|
+
const entryPath = path.join(projectDir, entry);
|
|
221
|
+
const subagentsDir = path.join(entryPath, 'subagents');
|
|
222
|
+
if (sessionId && entry !== sessionId)
|
|
223
|
+
continue;
|
|
224
|
+
if (fs.existsSync(subagentsDir) && fs.statSync(subagentsDir).isDirectory()) {
|
|
225
|
+
const subagentFiles = fs.readdirSync(subagentsDir);
|
|
226
|
+
for (const file of subagentFiles) {
|
|
227
|
+
if (file.startsWith('agent-') && file.endsWith('.jsonl')) {
|
|
228
|
+
addAgentFile(path.join(subagentsDir, file), entry);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
files.sort((a, b) => b.lastModified.getTime() - a.lastModified.getTime());
|
|
234
|
+
return files;
|
|
235
|
+
}
|
|
236
|
+
async readSessionLines(sessionId, cwd) {
|
|
237
|
+
const filePath = this.getSessionFilePath(sessionId, cwd);
|
|
238
|
+
if (!fs.existsSync(filePath)) {
|
|
239
|
+
return [];
|
|
240
|
+
}
|
|
241
|
+
const lines = [];
|
|
242
|
+
const fileStream = fs.createReadStream(filePath);
|
|
243
|
+
const rl = readline.createInterface({
|
|
244
|
+
input: fileStream,
|
|
245
|
+
crlfDelay: Infinity,
|
|
246
|
+
});
|
|
247
|
+
for await (const line of rl) {
|
|
248
|
+
if (line.trim()) {
|
|
249
|
+
lines.push(line);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return lines;
|
|
253
|
+
}
|
|
254
|
+
async readSessionLinesFrom(sessionId, fromLineIndex, cwd, limit) {
|
|
255
|
+
const allLines = await this.readSessionLines(sessionId, cwd);
|
|
256
|
+
const totalLines = allLines.length;
|
|
257
|
+
let lines = allLines.slice(fromLineIndex);
|
|
258
|
+
if (limit && limit > 0) {
|
|
259
|
+
lines = lines.slice(0, limit);
|
|
260
|
+
}
|
|
261
|
+
return { lines, totalLines };
|
|
262
|
+
}
|
|
263
|
+
parseJsonlLine(line) {
|
|
264
|
+
try {
|
|
265
|
+
return JSON.parse(line);
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
exports.SessionReader = SessionReader;
|
|
273
|
+
// ============================================================================
|
|
274
|
+
// Factory Function
|
|
275
|
+
// ============================================================================
|
|
276
|
+
function createSessionReader(config) {
|
|
277
|
+
return new SessionReader(config);
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=session-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-reader.js","sourceRoot":"","sources":["../src/session-reader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Tasks Service
|
|
3
|
+
*
|
|
4
|
+
* Reads Claude Code task files from ~/.claude/tasks/
|
|
5
|
+
* Each task list is a directory containing individual task JSON files.
|
|
6
|
+
*/
|
|
7
|
+
export interface Task {
|
|
8
|
+
id: string;
|
|
9
|
+
subject: string;
|
|
10
|
+
description: string;
|
|
11
|
+
activeForm?: string;
|
|
12
|
+
status: 'pending' | 'in_progress' | 'completed' | 'deleted';
|
|
13
|
+
blocks: string[];
|
|
14
|
+
blockedBy: string[];
|
|
15
|
+
owner?: string;
|
|
16
|
+
metadata?: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
export interface SessionInfo {
|
|
19
|
+
sessionId: string;
|
|
20
|
+
projectPath: string;
|
|
21
|
+
projectKey: string;
|
|
22
|
+
filePath: string;
|
|
23
|
+
exists: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface TaskList {
|
|
26
|
+
listId: string;
|
|
27
|
+
tasks: Task[];
|
|
28
|
+
taskCount: number;
|
|
29
|
+
path: string;
|
|
30
|
+
sessionInfo?: SessionInfo;
|
|
31
|
+
}
|
|
32
|
+
export interface TaskListSummary {
|
|
33
|
+
listId: string;
|
|
34
|
+
taskCount: number;
|
|
35
|
+
pendingCount: number;
|
|
36
|
+
inProgressCount: number;
|
|
37
|
+
completedCount: number;
|
|
38
|
+
lastModified: Date;
|
|
39
|
+
sessionInfo?: SessionInfo;
|
|
40
|
+
}
|
|
41
|
+
export interface CreateTaskInput {
|
|
42
|
+
subject: string;
|
|
43
|
+
description?: string;
|
|
44
|
+
activeForm?: string;
|
|
45
|
+
status?: 'pending' | 'in_progress' | 'completed';
|
|
46
|
+
blocks?: string[];
|
|
47
|
+
blockedBy?: string[];
|
|
48
|
+
owner?: string;
|
|
49
|
+
metadata?: Record<string, unknown>;
|
|
50
|
+
}
|
|
51
|
+
export interface UpdateTaskInput {
|
|
52
|
+
subject?: string;
|
|
53
|
+
description?: string;
|
|
54
|
+
activeForm?: string;
|
|
55
|
+
status?: 'pending' | 'in_progress' | 'completed';
|
|
56
|
+
blocks?: string[];
|
|
57
|
+
blockedBy?: string[];
|
|
58
|
+
addBlocks?: string[];
|
|
59
|
+
addBlockedBy?: string[];
|
|
60
|
+
owner?: string;
|
|
61
|
+
metadata?: Record<string, unknown>;
|
|
62
|
+
}
|
|
63
|
+
export declare class TasksService {
|
|
64
|
+
private tasksDir;
|
|
65
|
+
private _sessionInfoCache;
|
|
66
|
+
private _taskListCache;
|
|
67
|
+
private _taskListCacheDirty;
|
|
68
|
+
constructor(tasksDir?: string);
|
|
69
|
+
invalidateCache(): void;
|
|
70
|
+
invalidateSessionInfoCache(): void;
|
|
71
|
+
getTasksDir(): string;
|
|
72
|
+
isSessionIdFormat(id: string): boolean;
|
|
73
|
+
findSessionById(sessionId: string): SessionInfo | null;
|
|
74
|
+
getSessionInfo(listId: string): SessionInfo | null;
|
|
75
|
+
listTaskLists(): Promise<TaskListSummary[]>;
|
|
76
|
+
encodeProjectPath(projectPath: string): string;
|
|
77
|
+
getTaskListsForProject(projectPath: string): Promise<TaskListSummary[]>;
|
|
78
|
+
getTaskList(listId: string): Promise<TaskList | null>;
|
|
79
|
+
getTask(listId: string, taskId: string): Promise<Task | null>;
|
|
80
|
+
getReadyTasks(listId: string): Promise<Task[]>;
|
|
81
|
+
getAllTasksFlat(): Promise<Array<Task & {
|
|
82
|
+
sessionId: string;
|
|
83
|
+
projectPath?: string;
|
|
84
|
+
projectName?: string;
|
|
85
|
+
}>>;
|
|
86
|
+
getDependencyGraph(listId: string): Promise<{
|
|
87
|
+
nodes: Array<{
|
|
88
|
+
id: string;
|
|
89
|
+
subject: string;
|
|
90
|
+
status: string;
|
|
91
|
+
}>;
|
|
92
|
+
edges: Array<{
|
|
93
|
+
from: string;
|
|
94
|
+
to: string;
|
|
95
|
+
}>;
|
|
96
|
+
}>;
|
|
97
|
+
private readTasksFromDir;
|
|
98
|
+
}
|
|
99
|
+
export declare function createTasksService(tasksDir?: string): TasksService;
|
|
100
|
+
//# sourceMappingURL=tasks-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks-service.d.ts","sourceRoot":"","sources":["../src/tasks-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Claude Code Tasks Service
|
|
4
|
+
*
|
|
5
|
+
* Reads Claude Code task files from ~/.claude/tasks/
|
|
6
|
+
* Each task list is a directory containing individual task JSON files.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.TasksService = void 0;
|
|
43
|
+
exports.createTasksService = createTasksService;
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const os_1 = require("os");
|
|
47
|
+
const path_utils_1 = require("./utils/path-utils");
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// Service Implementation
|
|
50
|
+
// ============================================================================
|
|
51
|
+
class TasksService {
|
|
52
|
+
tasksDir;
|
|
53
|
+
// Cache: sessionId → SessionInfo (avoids scanning 30 project dirs per lookup)
|
|
54
|
+
_sessionInfoCache = new Map();
|
|
55
|
+
// Cache: listTaskLists() result, invalidated on file changes
|
|
56
|
+
_taskListCache = null;
|
|
57
|
+
_taskListCacheDirty = true;
|
|
58
|
+
constructor(tasksDir) {
|
|
59
|
+
this.tasksDir = tasksDir || path.join((0, os_1.homedir)(), '.claude', 'tasks');
|
|
60
|
+
}
|
|
61
|
+
invalidateCache() {
|
|
62
|
+
this._taskListCache = null;
|
|
63
|
+
this._taskListCacheDirty = true;
|
|
64
|
+
}
|
|
65
|
+
invalidateSessionInfoCache() {
|
|
66
|
+
this._sessionInfoCache.clear();
|
|
67
|
+
}
|
|
68
|
+
getTasksDir() {
|
|
69
|
+
return this.tasksDir;
|
|
70
|
+
}
|
|
71
|
+
isSessionIdFormat(id) {
|
|
72
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
73
|
+
return uuidRegex.test(id);
|
|
74
|
+
}
|
|
75
|
+
findSessionById(sessionId) {
|
|
76
|
+
if (!this.isSessionIdFormat(sessionId)) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
if (this._sessionInfoCache.has(sessionId)) {
|
|
80
|
+
return this._sessionInfoCache.get(sessionId) || null;
|
|
81
|
+
}
|
|
82
|
+
const projectsDir = path.join((0, os_1.homedir)(), '.claude', 'projects');
|
|
83
|
+
if (!fs.existsSync(projectsDir)) {
|
|
84
|
+
this._sessionInfoCache.set(sessionId, null);
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const dirs = fs.readdirSync(projectsDir, { withFileTypes: true })
|
|
89
|
+
.filter(d => d.isDirectory());
|
|
90
|
+
for (const dir of dirs) {
|
|
91
|
+
const sessionFile = path.join(projectsDir, dir.name, `${sessionId}.jsonl`);
|
|
92
|
+
if (fs.existsSync(sessionFile)) {
|
|
93
|
+
const projectPath = '/' + dir.name.replace(/^-/, '').replace(/-/g, '/');
|
|
94
|
+
const info = {
|
|
95
|
+
sessionId,
|
|
96
|
+
projectPath,
|
|
97
|
+
projectKey: dir.name,
|
|
98
|
+
filePath: sessionFile,
|
|
99
|
+
exists: true,
|
|
100
|
+
};
|
|
101
|
+
this._sessionInfoCache.set(sessionId, info);
|
|
102
|
+
return info;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// Ignore errors
|
|
108
|
+
}
|
|
109
|
+
this._sessionInfoCache.set(sessionId, null);
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
getSessionInfo(listId) {
|
|
113
|
+
return this.findSessionById(listId);
|
|
114
|
+
}
|
|
115
|
+
async listTaskLists() {
|
|
116
|
+
if (!this._taskListCacheDirty && this._taskListCache) {
|
|
117
|
+
return this._taskListCache;
|
|
118
|
+
}
|
|
119
|
+
if (!fs.existsSync(this.tasksDir)) {
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
const entries = fs.readdirSync(this.tasksDir, { withFileTypes: true });
|
|
123
|
+
const summaries = [];
|
|
124
|
+
for (const entry of entries) {
|
|
125
|
+
if (entry.isDirectory()) {
|
|
126
|
+
const listPath = path.join(this.tasksDir, entry.name);
|
|
127
|
+
const tasks = await this.readTasksFromDir(listPath);
|
|
128
|
+
const stat = fs.statSync(listPath);
|
|
129
|
+
const sessionInfo = this.getSessionInfo(entry.name);
|
|
130
|
+
summaries.push({
|
|
131
|
+
listId: entry.name,
|
|
132
|
+
taskCount: tasks.length,
|
|
133
|
+
pendingCount: tasks.filter(t => t.status === 'pending').length,
|
|
134
|
+
inProgressCount: tasks.filter(t => t.status === 'in_progress').length,
|
|
135
|
+
completedCount: tasks.filter(t => t.status === 'completed').length,
|
|
136
|
+
lastModified: stat.mtime,
|
|
137
|
+
sessionInfo: sessionInfo || undefined,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const result = summaries.sort((a, b) => b.lastModified.getTime() - a.lastModified.getTime());
|
|
142
|
+
this._taskListCache = result;
|
|
143
|
+
this._taskListCacheDirty = false;
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
encodeProjectPath(projectPath) {
|
|
147
|
+
const normalized = projectPath.replace(/[\\/]+$/, '');
|
|
148
|
+
return (0, path_utils_1.legacyEncodeProjectPath)(normalized);
|
|
149
|
+
}
|
|
150
|
+
async getTaskListsForProject(projectPath) {
|
|
151
|
+
const allLists = await this.listTaskLists();
|
|
152
|
+
const targetProjectKey = this.encodeProjectPath(projectPath);
|
|
153
|
+
return allLists.filter(list => {
|
|
154
|
+
if (!list.sessionInfo)
|
|
155
|
+
return false;
|
|
156
|
+
return list.sessionInfo.projectKey === targetProjectKey;
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
async getTaskList(listId) {
|
|
160
|
+
const listPath = path.join(this.tasksDir, listId);
|
|
161
|
+
if (!fs.existsSync(listPath)) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
const tasks = await this.readTasksFromDir(listPath);
|
|
165
|
+
const sessionInfo = this.getSessionInfo(listId);
|
|
166
|
+
return {
|
|
167
|
+
listId,
|
|
168
|
+
tasks,
|
|
169
|
+
taskCount: tasks.length,
|
|
170
|
+
path: listPath,
|
|
171
|
+
sessionInfo: sessionInfo || undefined,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
async getTask(listId, taskId) {
|
|
175
|
+
const taskPath = path.join(this.tasksDir, listId, `${taskId}.json`);
|
|
176
|
+
if (fs.existsSync(taskPath)) {
|
|
177
|
+
try {
|
|
178
|
+
const content = fs.readFileSync(taskPath, 'utf-8');
|
|
179
|
+
return JSON.parse(content);
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
// Fall through
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const taskList = await this.getTaskList(listId);
|
|
186
|
+
return taskList?.tasks.find(t => t.id === taskId) || null;
|
|
187
|
+
}
|
|
188
|
+
async getReadyTasks(listId) {
|
|
189
|
+
const taskList = await this.getTaskList(listId);
|
|
190
|
+
if (!taskList)
|
|
191
|
+
return [];
|
|
192
|
+
const completedIds = new Set(taskList.tasks
|
|
193
|
+
.filter(t => t.status === 'completed')
|
|
194
|
+
.map(t => t.id));
|
|
195
|
+
return taskList.tasks.filter(task => {
|
|
196
|
+
if (task.status === 'completed')
|
|
197
|
+
return false;
|
|
198
|
+
return task.blockedBy.every(id => completedIds.has(id));
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
async getAllTasksFlat() {
|
|
202
|
+
if (!fs.existsSync(this.tasksDir)) {
|
|
203
|
+
return [];
|
|
204
|
+
}
|
|
205
|
+
const entries = fs.readdirSync(this.tasksDir, { withFileTypes: true });
|
|
206
|
+
const allTasks = [];
|
|
207
|
+
for (const entry of entries) {
|
|
208
|
+
if (!entry.isDirectory())
|
|
209
|
+
continue;
|
|
210
|
+
const listId = entry.name;
|
|
211
|
+
const listPath = path.join(this.tasksDir, listId);
|
|
212
|
+
const rawTasks = await this.readTasksFromDir(listPath);
|
|
213
|
+
const tasks = rawTasks.filter(t => t.status !== 'deleted');
|
|
214
|
+
if (tasks.length === 0)
|
|
215
|
+
continue;
|
|
216
|
+
const sessionInfo = this.getSessionInfo(listId);
|
|
217
|
+
const projectPath = sessionInfo?.projectPath;
|
|
218
|
+
const projectName = projectPath ? path.basename(projectPath) : undefined;
|
|
219
|
+
for (const task of tasks) {
|
|
220
|
+
allTasks.push({
|
|
221
|
+
...task,
|
|
222
|
+
sessionId: listId,
|
|
223
|
+
projectPath,
|
|
224
|
+
projectName,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return allTasks;
|
|
229
|
+
}
|
|
230
|
+
async getDependencyGraph(listId) {
|
|
231
|
+
const taskList = await this.getTaskList(listId);
|
|
232
|
+
if (!taskList) {
|
|
233
|
+
return { nodes: [], edges: [] };
|
|
234
|
+
}
|
|
235
|
+
const nodes = taskList.tasks.map(t => ({
|
|
236
|
+
id: t.id,
|
|
237
|
+
subject: t.subject,
|
|
238
|
+
status: t.status,
|
|
239
|
+
}));
|
|
240
|
+
const edges = [];
|
|
241
|
+
const edgeSet = new Set();
|
|
242
|
+
for (const task of taskList.tasks) {
|
|
243
|
+
for (const blockedId of task.blocks) {
|
|
244
|
+
const key = `${task.id}->${blockedId}`;
|
|
245
|
+
if (!edgeSet.has(key)) {
|
|
246
|
+
edgeSet.add(key);
|
|
247
|
+
edges.push({ from: task.id, to: blockedId });
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
for (const blockerId of task.blockedBy) {
|
|
251
|
+
const key = `${blockerId}->${task.id}`;
|
|
252
|
+
if (!edgeSet.has(key)) {
|
|
253
|
+
edgeSet.add(key);
|
|
254
|
+
edges.push({ from: blockerId, to: task.id });
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return { nodes, edges };
|
|
259
|
+
}
|
|
260
|
+
async readTasksFromDir(dirPath) {
|
|
261
|
+
if (!fs.existsSync(dirPath)) {
|
|
262
|
+
return [];
|
|
263
|
+
}
|
|
264
|
+
const files = fs.readdirSync(dirPath).filter(f => f.endsWith('.json'));
|
|
265
|
+
const tasks = [];
|
|
266
|
+
for (const file of files) {
|
|
267
|
+
try {
|
|
268
|
+
const content = fs.readFileSync(path.join(dirPath, file), 'utf-8');
|
|
269
|
+
const task = JSON.parse(content);
|
|
270
|
+
tasks.push(task);
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
// Skip invalid files
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return tasks.sort((a, b) => {
|
|
277
|
+
const aNum = parseInt(a.id, 10);
|
|
278
|
+
const bNum = parseInt(b.id, 10);
|
|
279
|
+
if (isNaN(aNum) || isNaN(bNum)) {
|
|
280
|
+
return a.id.localeCompare(b.id);
|
|
281
|
+
}
|
|
282
|
+
return aNum - bNum;
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
exports.TasksService = TasksService;
|
|
287
|
+
function createTasksService(tasksDir) {
|
|
288
|
+
return new TasksService(tasksDir);
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=tasks-service.js.map
|