@grackle-ai/server 0.24.1 → 0.26.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/dist/compute-task-status.d.ts +27 -0
- package/dist/compute-task-status.d.ts.map +1 -0
- package/dist/compute-task-status.js +93 -0
- package/dist/compute-task-status.js.map +1 -0
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +62 -14
- package/dist/db.js.map +1 -1
- package/dist/event-processor.d.ts +15 -1
- package/dist/event-processor.d.ts.map +1 -1
- package/dist/event-processor.js +164 -99
- package/dist/event-processor.js.map +1 -1
- package/dist/github-import.d.ts +1 -1
- package/dist/github-import.d.ts.map +1 -1
- package/dist/github-import.js +4 -5
- package/dist/github-import.js.map +1 -1
- package/dist/grpc-service.d.ts.map +1 -1
- package/dist/grpc-service.js +112 -72
- package/dist/grpc-service.js.map +1 -1
- package/dist/processor-registry.d.ts +25 -0
- package/dist/processor-registry.d.ts.map +1 -0
- package/dist/processor-registry.js +58 -0
- package/dist/processor-registry.js.map +1 -0
- package/dist/schema.d.ts +19 -57
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +1 -3
- package/dist/schema.js.map +1 -1
- package/dist/session-store.d.ts +9 -1
- package/dist/session-store.d.ts.map +1 -1
- package/dist/session-store.js +46 -2
- package/dist/session-store.js.map +1 -1
- package/dist/task-store.d.ts +6 -7
- package/dist/task-store.d.ts.map +1 -1
- package/dist/task-store.js +6 -28
- package/dist/task-store.js.map +1 -1
- package/dist/ws-bridge.d.ts.map +1 -1
- package/dist/ws-bridge.js +138 -104
- package/dist/ws-bridge.js.map +1 -1
- package/package.json +4 -4
package/dist/task-store.js
CHANGED
|
@@ -5,7 +5,7 @@ import { MAX_TASK_DEPTH } from "@grackle-ai/common";
|
|
|
5
5
|
import { safeParseJsonArray } from "./json-helpers.js";
|
|
6
6
|
import { slugify } from "./utils/slugify.js";
|
|
7
7
|
/** Insert a new task with auto-generated branch name and sort order. */
|
|
8
|
-
export function createTask(id, projectId, title, description,
|
|
8
|
+
export function createTask(id, projectId, title, description, dependsOn, projectSlug, parentTaskId = "", canDecompose) {
|
|
9
9
|
let depth = 0;
|
|
10
10
|
let branch;
|
|
11
11
|
if (parentTaskId) {
|
|
@@ -41,13 +41,11 @@ export function createTask(id, projectId, title, description, environmentId, dep
|
|
|
41
41
|
title,
|
|
42
42
|
description,
|
|
43
43
|
branch,
|
|
44
|
-
environmentId,
|
|
45
44
|
dependsOn: depsJson,
|
|
46
45
|
sortOrder,
|
|
47
46
|
parentTaskId,
|
|
48
47
|
depth,
|
|
49
48
|
canDecompose: resolvedCanDecompose,
|
|
50
|
-
personaId,
|
|
51
49
|
})
|
|
52
50
|
.run();
|
|
53
51
|
}
|
|
@@ -65,16 +63,14 @@ export function listTasks(projectId) {
|
|
|
65
63
|
.all();
|
|
66
64
|
}
|
|
67
65
|
/** Update multiple task fields at once. */
|
|
68
|
-
export function updateTask(id, title, description, status,
|
|
66
|
+
export function updateTask(id, title, description, status, dependsOn, reviewNotes) {
|
|
69
67
|
db.update(tasks)
|
|
70
68
|
.set({
|
|
71
69
|
title,
|
|
72
70
|
description,
|
|
73
71
|
status,
|
|
74
|
-
environmentId,
|
|
75
72
|
dependsOn: JSON.stringify(dependsOn),
|
|
76
73
|
reviewNotes,
|
|
77
|
-
personaId,
|
|
78
74
|
updatedAt: sql `datetime('now')`,
|
|
79
75
|
})
|
|
80
76
|
.where(eq(tasks.id, id))
|
|
@@ -100,28 +96,10 @@ export function updateTaskStatus(id, status) {
|
|
|
100
96
|
.where(eq(tasks.id, id))
|
|
101
97
|
.run();
|
|
102
98
|
}
|
|
103
|
-
/**
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
sessionId,
|
|
108
|
-
updatedAt: sql `datetime('now')`,
|
|
109
|
-
})
|
|
110
|
-
.where(eq(tasks.id, id))
|
|
111
|
-
.run();
|
|
112
|
-
}
|
|
113
|
-
/** Mark a task as in_progress with a started_at timestamp. */
|
|
114
|
-
export function markTaskStarted(id) {
|
|
115
|
-
db.update(tasks)
|
|
116
|
-
.set({
|
|
117
|
-
status: "in_progress",
|
|
118
|
-
startedAt: sql `datetime('now')`,
|
|
119
|
-
updatedAt: sql `datetime('now')`,
|
|
120
|
-
})
|
|
121
|
-
.where(eq(tasks.id, id))
|
|
122
|
-
.run();
|
|
123
|
-
}
|
|
124
|
-
/** Mark a task as completed (review, done, or failed) with a completed_at timestamp. */
|
|
99
|
+
/**
|
|
100
|
+
* Mark a task as completed with a completed_at timestamp.
|
|
101
|
+
* Used only for human-authoritative status transitions (approve → "done").
|
|
102
|
+
*/
|
|
125
103
|
export function markTaskCompleted(id, status) {
|
|
126
104
|
db.update(tasks)
|
|
127
105
|
.set({
|
package/dist/task-store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-store.js","sourceRoot":"","sources":["../src/task-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,KAAK,EAAgB,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAI7C,wEAAwE;AACxE,MAAM,UAAU,UAAU,CACxB,EAAU,EACV,SAAiB,EACjB,KAAa,EACb,WAAmB,EACnB,
|
|
1
|
+
{"version":3,"file":"task-store.js","sourceRoot":"","sources":["../src/task-store.ts"],"names":[],"mappings":"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"}
|
package/dist/ws-bridge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws-bridge.d.ts","sourceRoot":"","sources":["../src/ws-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAa,MAAM,IAAI,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"ws-bridge.d.ts","sourceRoot":"","sources":["../src/ws-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAa,MAAM,IAAI,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAC;AAmDtD,wGAAwG;AACxG,wBAAgB,cAAc,CAC5B,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GACvC,eAAe,CAuCjB"}
|
package/dist/ws-bridge.js
CHANGED
|
@@ -21,8 +21,10 @@ import { logger } from "./logger.js";
|
|
|
21
21
|
import { buildTaskSystemContext } from "./utils/system-context.js";
|
|
22
22
|
import { slugify } from "./utils/slugify.js";
|
|
23
23
|
import { processEventStream } from "./event-processor.js";
|
|
24
|
+
import * as processorRegistry from "./processor-registry.js";
|
|
24
25
|
import { broadcast, setWssInstance } from "./ws-broadcast.js";
|
|
25
26
|
import { buildMcpServersJson } from "./grpc-service.js";
|
|
27
|
+
import { computeTaskStatus } from "./compute-task-status.js";
|
|
26
28
|
import { exec } from "./utils/exec.js";
|
|
27
29
|
const GH_CODESPACE_LIST_TIMEOUT_MS = 30_000;
|
|
28
30
|
const GH_CODESPACE_CREATE_TIMEOUT_MS = 300_000;
|
|
@@ -190,7 +192,7 @@ async function startTaskSession(ws, task, options) {
|
|
|
190
192
|
logger.warn({ taskId: task.id }, "startTaskSession failed: project not found");
|
|
191
193
|
return `Project not found: ${task.projectId}`;
|
|
192
194
|
}
|
|
193
|
-
const environmentId =
|
|
195
|
+
const environmentId = options?.environmentId || project.defaultEnvironmentId;
|
|
194
196
|
const env = envRegistry.getEnvironment(environmentId);
|
|
195
197
|
if (!env) {
|
|
196
198
|
logger.warn({ taskId: task.id, environmentId }, "startTaskSession failed: environment not found");
|
|
@@ -203,7 +205,7 @@ async function startTaskSession(ws, task, options) {
|
|
|
203
205
|
return undefined;
|
|
204
206
|
}
|
|
205
207
|
// Resolve persona
|
|
206
|
-
const resolvedPersonaId = options?.personaId ||
|
|
208
|
+
const resolvedPersonaId = options?.personaId || "";
|
|
207
209
|
const persona = resolvedPersonaId
|
|
208
210
|
? personaStore.getPersona(resolvedPersonaId)
|
|
209
211
|
: undefined;
|
|
@@ -226,9 +228,7 @@ async function startTaskSession(ws, task, options) {
|
|
|
226
228
|
if (persona) {
|
|
227
229
|
systemContext = persona.systemPrompt + "\n\n" + systemContext;
|
|
228
230
|
}
|
|
229
|
-
sessionStore.createSession(sessionId, environmentId, runtime, freshTask.title, model, logPath, freshTask.id);
|
|
230
|
-
taskStore.setTaskSession(freshTask.id, sessionId);
|
|
231
|
-
taskStore.markTaskStarted(freshTask.id);
|
|
231
|
+
sessionStore.createSession(sessionId, environmentId, runtime, freshTask.title, model, logPath, freshTask.id, resolvedPersonaId);
|
|
232
232
|
broadcast({
|
|
233
233
|
type: "task_started",
|
|
234
234
|
payload: {
|
|
@@ -274,22 +274,6 @@ async function startTaskSession(ws, task, options) {
|
|
|
274
274
|
logPath,
|
|
275
275
|
projectId: freshTask.projectId,
|
|
276
276
|
taskId: freshTask.id,
|
|
277
|
-
onComplete: () => {
|
|
278
|
-
const t = taskStore.getTask(freshTask.id);
|
|
279
|
-
if (t && (t.status === "in_progress" || t.status === "waiting_input")) {
|
|
280
|
-
const sess = sessionStore.getSession(sessionId);
|
|
281
|
-
if (sess?.status === "completed") {
|
|
282
|
-
taskStore.markTaskCompleted(freshTask.id, "review");
|
|
283
|
-
}
|
|
284
|
-
else if (sess?.status === "failed") {
|
|
285
|
-
taskStore.markTaskCompleted(freshTask.id, "failed");
|
|
286
|
-
}
|
|
287
|
-
broadcast({
|
|
288
|
-
type: "task_updated",
|
|
289
|
-
payload: { taskId: freshTask.id, projectId: freshTask.projectId },
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
},
|
|
293
277
|
});
|
|
294
278
|
return undefined;
|
|
295
279
|
}
|
|
@@ -546,11 +530,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
546
530
|
await conn.client.kill(create(powerline.SessionIdSchema, { id: sessionId }));
|
|
547
531
|
}
|
|
548
532
|
catch (err) {
|
|
549
|
-
|
|
550
|
-
type: "error",
|
|
551
|
-
payload: { message: `Kill failed: ${err}` },
|
|
552
|
-
});
|
|
553
|
-
return;
|
|
533
|
+
logger.warn({ sessionId, err }, "PowerLine kill failed — marking session killed anyway");
|
|
554
534
|
}
|
|
555
535
|
}
|
|
556
536
|
sessionStore.updateSession(sessionId, "killed");
|
|
@@ -561,6 +541,13 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
561
541
|
content: "killed",
|
|
562
542
|
raw: "",
|
|
563
543
|
}));
|
|
544
|
+
// Broadcast task_updated so frontend re-fetches computed status
|
|
545
|
+
if (session.taskId) {
|
|
546
|
+
const task = taskStore.getTask(session.taskId);
|
|
547
|
+
if (task) {
|
|
548
|
+
broadcast({ type: "task_updated", payload: { taskId: task.id, projectId: task.projectId } });
|
|
549
|
+
}
|
|
550
|
+
}
|
|
564
551
|
break;
|
|
565
552
|
}
|
|
566
553
|
// ─── Projects ──────────────────────────────────────────
|
|
@@ -749,29 +736,40 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
749
736
|
return;
|
|
750
737
|
const rows = taskStore.listTasks(projectId);
|
|
751
738
|
const childIdsMap = taskStore.buildChildIdsMap(rows);
|
|
739
|
+
// Batch-fetch sessions for all tasks and group by taskId
|
|
740
|
+
const taskIds = rows.map((r) => r.id);
|
|
741
|
+
const allSessions = sessionStore.listSessionsByTaskIds(taskIds);
|
|
742
|
+
const sessionsByTask = new Map();
|
|
743
|
+
for (const s of allSessions) {
|
|
744
|
+
const arr = sessionsByTask.get(s.taskId) ?? [];
|
|
745
|
+
arr.push(s);
|
|
746
|
+
sessionsByTask.set(s.taskId, arr);
|
|
747
|
+
}
|
|
752
748
|
sendWs(ws, {
|
|
753
749
|
type: "tasks",
|
|
754
750
|
payload: {
|
|
755
751
|
projectId,
|
|
756
|
-
tasks: rows.map((r) =>
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
752
|
+
tasks: rows.map((r) => {
|
|
753
|
+
const taskSessions = sessionsByTask.get(r.id) ?? [];
|
|
754
|
+
const computed = computeTaskStatus(r.status, taskSessions);
|
|
755
|
+
return {
|
|
756
|
+
id: r.id,
|
|
757
|
+
projectId: r.projectId,
|
|
758
|
+
title: r.title,
|
|
759
|
+
description: r.description,
|
|
760
|
+
status: computed.status,
|
|
761
|
+
branch: r.branch,
|
|
762
|
+
latestSessionId: computed.latestSessionId,
|
|
763
|
+
dependsOn: safeParseJsonArray(r.dependsOn),
|
|
764
|
+
reviewNotes: r.reviewNotes,
|
|
765
|
+
sortOrder: r.sortOrder,
|
|
766
|
+
createdAt: r.createdAt,
|
|
767
|
+
parentTaskId: r.parentTaskId,
|
|
768
|
+
depth: r.depth,
|
|
769
|
+
childTaskIds: childIdsMap.get(r.id) ?? [],
|
|
770
|
+
canDecompose: r.canDecompose,
|
|
771
|
+
};
|
|
772
|
+
}),
|
|
775
773
|
},
|
|
776
774
|
});
|
|
777
775
|
break;
|
|
@@ -797,19 +795,8 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
797
795
|
const parentTaskId = msg.payload?.parentTaskId || "";
|
|
798
796
|
const rawCanDecompose = msg.payload?.canDecompose;
|
|
799
797
|
const canDecompose = typeof rawCanDecompose === "boolean" ? rawCanDecompose : undefined;
|
|
800
|
-
// Resolve environment: explicit > parent task's env > project default
|
|
801
|
-
let resolvedEnvId = msg.payload?.environmentId || "";
|
|
802
|
-
if (!resolvedEnvId && parentTaskId) {
|
|
803
|
-
const parentTask = taskStore.getTask(parentTaskId);
|
|
804
|
-
if (parentTask?.environmentId) {
|
|
805
|
-
resolvedEnvId = parentTask.environmentId;
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
if (!resolvedEnvId) {
|
|
809
|
-
resolvedEnvId = project.defaultEnvironmentId;
|
|
810
|
-
}
|
|
811
798
|
const id = uuid().slice(0, 8);
|
|
812
|
-
taskStore.createTask(id, projectId, title, msg.payload?.description || "",
|
|
799
|
+
taskStore.createTask(id, projectId, title, msg.payload?.description || "", msg.payload?.dependsOn || [], slugify(project.name), parentTaskId, canDecompose);
|
|
813
800
|
const row = taskStore.getTask(id);
|
|
814
801
|
broadcast({
|
|
815
802
|
type: "task_created",
|
|
@@ -832,7 +819,45 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
832
819
|
sendWs(ws, { type: "error", payload: { message: `Task not found: ${updateTaskId}` } });
|
|
833
820
|
return;
|
|
834
821
|
}
|
|
835
|
-
//
|
|
822
|
+
// Late-bind: associate a running session with this task
|
|
823
|
+
const lateBindSessionId = typeof msg.payload?.sessionId === "string" ? msg.payload.sessionId : "";
|
|
824
|
+
if (lateBindSessionId) {
|
|
825
|
+
const session = sessionStore.getSession(lateBindSessionId);
|
|
826
|
+
if (!session) {
|
|
827
|
+
sendWs(ws, { type: "error", payload: { message: `Session not found: ${lateBindSessionId}` } });
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
const terminalStatuses = ["completed", "failed", "killed"];
|
|
831
|
+
if (terminalStatuses.includes(session.status)) {
|
|
832
|
+
sendWs(ws, {
|
|
833
|
+
type: "error",
|
|
834
|
+
payload: { message: `Cannot bind terminal session ${lateBindSessionId} (status: ${session.status})` },
|
|
835
|
+
});
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
// Verify the processor exists before mutating DB state to avoid partial updates
|
|
839
|
+
if (!processorRegistry.get(lateBindSessionId)) {
|
|
840
|
+
sendWs(ws, {
|
|
841
|
+
type: "error",
|
|
842
|
+
payload: { message: `No active event processor for session ${lateBindSessionId}` },
|
|
843
|
+
});
|
|
844
|
+
return;
|
|
845
|
+
}
|
|
846
|
+
sessionStore.setSessionTask(lateBindSessionId, updateTaskId);
|
|
847
|
+
try {
|
|
848
|
+
processorRegistry.lateBind(lateBindSessionId, updateTaskId, existingTask.projectId);
|
|
849
|
+
}
|
|
850
|
+
catch (err) {
|
|
851
|
+
sendWs(ws, { type: "error", payload: { message: String(err) } });
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
broadcast({
|
|
855
|
+
type: "task_started",
|
|
856
|
+
payload: { taskId: updateTaskId, sessionId: lateBindSessionId, projectId: existingTask.projectId },
|
|
857
|
+
});
|
|
858
|
+
break;
|
|
859
|
+
}
|
|
860
|
+
// Only allow editing pending/assigned tasks (non-late-bind path)
|
|
836
861
|
if (!["pending", "assigned"].includes(existingTask.status)) {
|
|
837
862
|
sendWs(ws, {
|
|
838
863
|
type: "error",
|
|
@@ -854,13 +879,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
854
879
|
.filter((d) => d !== updateTaskId)),
|
|
855
880
|
]
|
|
856
881
|
: safeParseJsonArray(existingTask.dependsOn);
|
|
857
|
-
|
|
858
|
-
? msg.payload.environmentId
|
|
859
|
-
: existingTask.environmentId;
|
|
860
|
-
const updatedPersonaId = typeof msg.payload?.personaId === "string"
|
|
861
|
-
? msg.payload.personaId
|
|
862
|
-
: existingTask.personaId;
|
|
863
|
-
taskStore.updateTask(updateTaskId, updatedTitle, updatedDescription, existingTask.status, updatedEnvironmentId, updatedDependsOn, existingTask.reviewNotes, updatedPersonaId);
|
|
882
|
+
taskStore.updateTask(updateTaskId, updatedTitle, updatedDescription, existingTask.status, updatedDependsOn, existingTask.reviewNotes);
|
|
864
883
|
const updatedRow = taskStore.getTask(updateTaskId);
|
|
865
884
|
broadcast({
|
|
866
885
|
type: "task_updated",
|
|
@@ -886,14 +905,18 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
886
905
|
});
|
|
887
906
|
return;
|
|
888
907
|
}
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
908
|
+
{
|
|
909
|
+
const taskSessions = sessionStore.listSessionsForTask(taskId);
|
|
910
|
+
const { status: effectiveStatus } = computeTaskStatus(task.status, taskSessions);
|
|
911
|
+
if (!["pending", "assigned", "failed"].includes(effectiveStatus)) {
|
|
912
|
+
sendWs(ws, {
|
|
913
|
+
type: "error",
|
|
914
|
+
payload: {
|
|
915
|
+
message: `Task cannot be started (status: ${effectiveStatus})`,
|
|
916
|
+
},
|
|
917
|
+
});
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
897
920
|
}
|
|
898
921
|
if (!taskStore.areDependenciesMet(taskId)) {
|
|
899
922
|
sendWs(ws, {
|
|
@@ -905,7 +928,8 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
905
928
|
const startError = await startTaskSession(ws, task, {
|
|
906
929
|
runtime: msg.payload?.runtime,
|
|
907
930
|
model: msg.payload?.model,
|
|
908
|
-
personaId: msg.payload?.personaId ||
|
|
931
|
+
personaId: msg.payload?.personaId || undefined,
|
|
932
|
+
environmentId: msg.payload?.environmentId || undefined,
|
|
909
933
|
});
|
|
910
934
|
if (startError) {
|
|
911
935
|
sendWs(ws, { type: "error", payload: { message: startError } });
|
|
@@ -936,22 +960,27 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
936
960
|
const task = taskStore.getTask(taskId);
|
|
937
961
|
if (!task)
|
|
938
962
|
return;
|
|
939
|
-
|
|
963
|
+
// Use computed status (derived from session history) since the stored
|
|
964
|
+
// status is never explicitly set to "review".
|
|
965
|
+
const taskSessions = sessionStore.listSessionsByTaskIds([taskId]);
|
|
966
|
+
const { status: effectiveStatus } = computeTaskStatus(task.status, taskSessions);
|
|
967
|
+
if (effectiveStatus !== "review") {
|
|
940
968
|
sendWs(ws, {
|
|
941
969
|
type: "error",
|
|
942
970
|
payload: {
|
|
943
|
-
message: `Task cannot be rejected (status: ${
|
|
971
|
+
message: `Task cannot be rejected (status: ${effectiveStatus})`,
|
|
944
972
|
},
|
|
945
973
|
});
|
|
946
974
|
return;
|
|
947
975
|
}
|
|
948
976
|
// Preserve runtime/model from the previous session so the retry
|
|
949
977
|
// doesn't unexpectedly switch runtimes/models.
|
|
950
|
-
const previousSession = task.
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
//
|
|
954
|
-
|
|
978
|
+
const previousSession = sessionStore.getLatestSessionForTask(task.id);
|
|
979
|
+
// Store review notes and reset status to "pending" so computeTaskStatus
|
|
980
|
+
// can derive the effective status from the new retry session. We use
|
|
981
|
+
// "pending" rather than "assigned" because rejection + retry is an
|
|
982
|
+
// automated flow — "assigned" implies deliberate human assignment.
|
|
983
|
+
taskStore.updateTask(task.id, task.title, task.description, "pending", safeParseJsonArray(task.dependsOn), reviewNotes);
|
|
955
984
|
broadcast({
|
|
956
985
|
type: "task_rejected",
|
|
957
986
|
payload: { taskId, projectId: task.projectId },
|
|
@@ -962,9 +991,17 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
962
991
|
const retryError = await startTaskSession(ws, freshTask, {
|
|
963
992
|
runtime: previousSession?.runtime,
|
|
964
993
|
model: previousSession?.model,
|
|
994
|
+
environmentId: previousSession?.environmentId,
|
|
995
|
+
personaId: previousSession?.personaId,
|
|
965
996
|
});
|
|
966
997
|
if (retryError) {
|
|
967
|
-
|
|
998
|
+
// Retry failed — set status to "assigned" so the user can retry manually.
|
|
999
|
+
logger.warn({ taskId, error: retryError }, "Auto-retry after rejection failed — task set to assigned");
|
|
1000
|
+
taskStore.updateTask(freshTask.id, freshTask.title, freshTask.description, "assigned", safeParseJsonArray(freshTask.dependsOn), freshTask.reviewNotes);
|
|
1001
|
+
broadcast({
|
|
1002
|
+
type: "task_updated",
|
|
1003
|
+
payload: { taskId, projectId: freshTask.projectId },
|
|
1004
|
+
});
|
|
968
1005
|
}
|
|
969
1006
|
}
|
|
970
1007
|
break;
|
|
@@ -988,28 +1025,26 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
988
1025
|
});
|
|
989
1026
|
return;
|
|
990
1027
|
}
|
|
991
|
-
// Kill active
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
logger.warn({ taskId, sessionId: deletedTask.sessionId, err }, "Failed to kill session during task deletion");
|
|
1002
|
-
}
|
|
1028
|
+
// Kill all active sessions before deleting the task
|
|
1029
|
+
const activeSessions = sessionStore.getActiveSessionsForTask(taskId);
|
|
1030
|
+
for (const activeSession of activeSessions) {
|
|
1031
|
+
const conn = adapterManager.getConnection(activeSession.environmentId);
|
|
1032
|
+
if (conn) {
|
|
1033
|
+
try {
|
|
1034
|
+
await conn.client.kill(create(powerline.SessionIdSchema, { id: activeSession.id }));
|
|
1035
|
+
}
|
|
1036
|
+
catch (err) {
|
|
1037
|
+
logger.warn({ taskId, sessionId: activeSession.id, err }, "Failed to kill session during task deletion");
|
|
1003
1038
|
}
|
|
1004
|
-
sessionStore.updateSession(deletedTask.sessionId, "killed");
|
|
1005
|
-
streamHub.publish(create(grackle.SessionEventSchema, {
|
|
1006
|
-
sessionId: deletedTask.sessionId,
|
|
1007
|
-
type: grackle.EventType.STATUS,
|
|
1008
|
-
timestamp: new Date().toISOString(),
|
|
1009
|
-
content: "killed",
|
|
1010
|
-
raw: "",
|
|
1011
|
-
}));
|
|
1012
1039
|
}
|
|
1040
|
+
sessionStore.updateSession(activeSession.id, "killed");
|
|
1041
|
+
streamHub.publish(create(grackle.SessionEventSchema, {
|
|
1042
|
+
sessionId: activeSession.id,
|
|
1043
|
+
type: grackle.EventType.STATUS,
|
|
1044
|
+
timestamp: new Date().toISOString(),
|
|
1045
|
+
content: "killed",
|
|
1046
|
+
raw: "",
|
|
1047
|
+
}));
|
|
1013
1048
|
}
|
|
1014
1049
|
const changes = taskStore.deleteTask(taskId);
|
|
1015
1050
|
if (changes === 0) {
|
|
@@ -1098,8 +1133,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
1098
1133
|
});
|
|
1099
1134
|
return;
|
|
1100
1135
|
}
|
|
1101
|
-
const environmentId = task.
|
|
1102
|
-
projectStore.getProject(task.projectId)?.defaultEnvironmentId;
|
|
1136
|
+
const environmentId = projectStore.getProject(task.projectId)?.defaultEnvironmentId;
|
|
1103
1137
|
if (!environmentId) {
|
|
1104
1138
|
sendWs(ws, {
|
|
1105
1139
|
type: "task_diff",
|