loki-mode 5.7.2 → 5.7.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.
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Task Routes
3
+ *
4
+ * REST endpoints for task management.
5
+ */
6
+
7
+ import { cliBridge } from "../services/cli-bridge.ts";
8
+ import type { Task } from "../types/api.ts";
9
+ import {
10
+ LokiApiError,
11
+ ErrorCodes,
12
+ successResponse,
13
+ } from "../middleware/error.ts";
14
+
15
+ /**
16
+ * GET /api/sessions/:id/tasks - List tasks for a session
17
+ */
18
+ export async function listTasks(
19
+ _req: Request,
20
+ sessionId: string
21
+ ): Promise<Response> {
22
+ const session = await cliBridge.getSession(sessionId);
23
+
24
+ if (!session) {
25
+ throw new LokiApiError(
26
+ `Session not found: ${sessionId}`,
27
+ ErrorCodes.SESSION_NOT_FOUND
28
+ );
29
+ }
30
+
31
+ const tasks = await cliBridge.getTasks(sessionId);
32
+
33
+ // Parse query parameters for filtering
34
+ const url = new URL(_req.url);
35
+ const status = url.searchParams.get("status");
36
+ const limit = parseInt(url.searchParams.get("limit") || "100", 10);
37
+ const offset = parseInt(url.searchParams.get("offset") || "0", 10);
38
+
39
+ let filteredTasks = tasks;
40
+
41
+ // Filter by status
42
+ if (status) {
43
+ filteredTasks = tasks.filter((t) => t.status === status);
44
+ }
45
+
46
+ // Paginate
47
+ const paginatedTasks = filteredTasks.slice(offset, offset + limit);
48
+
49
+ return successResponse({
50
+ tasks: paginatedTasks,
51
+ pagination: {
52
+ total: filteredTasks.length,
53
+ limit,
54
+ offset,
55
+ hasMore: offset + limit < filteredTasks.length,
56
+ },
57
+ summary: {
58
+ pending: tasks.filter((t) => t.status === "pending").length,
59
+ running: tasks.filter((t) => t.status === "running").length,
60
+ completed: tasks.filter((t) => t.status === "completed").length,
61
+ failed: tasks.filter((t) => t.status === "failed").length,
62
+ },
63
+ });
64
+ }
65
+
66
+ /**
67
+ * GET /api/sessions/:sessionId/tasks/:taskId - Get a specific task
68
+ */
69
+ export async function getTask(
70
+ _req: Request,
71
+ sessionId: string,
72
+ taskId: string
73
+ ): Promise<Response> {
74
+ const session = await cliBridge.getSession(sessionId);
75
+
76
+ if (!session) {
77
+ throw new LokiApiError(
78
+ `Session not found: ${sessionId}`,
79
+ ErrorCodes.SESSION_NOT_FOUND
80
+ );
81
+ }
82
+
83
+ const tasks = await cliBridge.getTasks(sessionId);
84
+ const task = tasks.find((t) => t.id === taskId);
85
+
86
+ if (!task) {
87
+ throw new LokiApiError(
88
+ `Task not found: ${taskId}`,
89
+ ErrorCodes.NOT_FOUND
90
+ );
91
+ }
92
+
93
+ return successResponse({ task });
94
+ }
95
+
96
+ /**
97
+ * GET /api/tasks - List all tasks across sessions
98
+ */
99
+ export async function listAllTasks(req: Request): Promise<Response> {
100
+ const sessions = await cliBridge.listSessions();
101
+ const allTasks: Task[] = [];
102
+
103
+ for (const session of sessions) {
104
+ const tasks = await cliBridge.getTasks(session.id);
105
+ allTasks.push(...tasks);
106
+ }
107
+
108
+ // Parse query parameters
109
+ const url = new URL(req.url);
110
+ const status = url.searchParams.get("status");
111
+ const limit = parseInt(url.searchParams.get("limit") || "100", 10);
112
+ const offset = parseInt(url.searchParams.get("offset") || "0", 10);
113
+
114
+ let filteredTasks = allTasks;
115
+
116
+ if (status) {
117
+ filteredTasks = allTasks.filter((t) => t.status === status);
118
+ }
119
+
120
+ // Sort by creation time (newest first)
121
+ filteredTasks.sort(
122
+ (a, b) =>
123
+ new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
124
+ );
125
+
126
+ const paginatedTasks = filteredTasks.slice(offset, offset + limit);
127
+
128
+ return successResponse({
129
+ tasks: paginatedTasks,
130
+ pagination: {
131
+ total: filteredTasks.length,
132
+ limit,
133
+ offset,
134
+ hasMore: offset + limit < filteredTasks.length,
135
+ },
136
+ });
137
+ }
138
+
139
+ /**
140
+ * GET /api/tasks/active - Get currently running tasks
141
+ */
142
+ export async function getActiveTasks(_req: Request): Promise<Response> {
143
+ const sessions = await cliBridge.listSessions();
144
+ const activeTasks: Task[] = [];
145
+
146
+ for (const session of sessions) {
147
+ if (session.status === "running") {
148
+ const tasks = await cliBridge.getTasks(session.id);
149
+ activeTasks.push(...tasks.filter((t) => t.status === "running"));
150
+ }
151
+ }
152
+
153
+ return successResponse({
154
+ tasks: activeTasks,
155
+ count: activeTasks.length,
156
+ });
157
+ }
158
+
159
+ /**
160
+ * GET /api/tasks/queue - Get queued tasks
161
+ */
162
+ export async function getQueuedTasks(_req: Request): Promise<Response> {
163
+ const sessions = await cliBridge.listSessions();
164
+ const queuedTasks: Task[] = [];
165
+
166
+ for (const session of sessions) {
167
+ if (session.status === "running") {
168
+ const tasks = await cliBridge.getTasks(session.id);
169
+ queuedTasks.push(
170
+ ...tasks.filter((t) => t.status === "pending" || t.status === "queued")
171
+ );
172
+ }
173
+ }
174
+
175
+ // Sort by priority
176
+ queuedTasks.sort((a, b) => b.priority - a.priority);
177
+
178
+ return successResponse({
179
+ tasks: queuedTasks,
180
+ count: queuedTasks.length,
181
+ });
182
+ }