feat(workflow): implement workflow system with steps terminology (#102)
This commit is contained in:
@@ -7,12 +7,14 @@ export function registerTaskSessionHandlers(store: StoreApi<AppState>): WsHandle
|
||||
return {
|
||||
'session.state_changed': (message) => {
|
||||
const payload = message.payload;
|
||||
if (!payload?.task_id || !payload?.new_state) {
|
||||
if (!payload?.task_id) {
|
||||
return;
|
||||
}
|
||||
const taskId = payload.task_id;
|
||||
const newState = payload.new_state as TaskSessionState;
|
||||
const newState = payload.new_state as TaskSessionState | undefined;
|
||||
const sessionId = payload.session_id;
|
||||
const reviewStatus = payload.review_status as string | undefined;
|
||||
const workflowStepId = payload.workflow_step_id as string | undefined;
|
||||
|
||||
// Also update or create the session object if we have the session ID
|
||||
if (sessionId) {
|
||||
@@ -20,16 +22,21 @@ export function registerTaskSessionHandlers(store: StoreApi<AppState>): WsHandle
|
||||
const agentProfileId = payload.agent_profile_id;
|
||||
const agentProfileSnapshot = payload.agent_profile_snapshot as Record<string, unknown> | undefined;
|
||||
|
||||
// Build the update object with all possible fields
|
||||
const sessionUpdate: Record<string, unknown> = {};
|
||||
if (newState) sessionUpdate.state = newState;
|
||||
if (reviewStatus !== undefined) sessionUpdate.review_status = reviewStatus;
|
||||
if (workflowStepId !== undefined) sessionUpdate.workflow_step_id = workflowStepId;
|
||||
if (agentProfileSnapshot) sessionUpdate.agent_profile_snapshot = agentProfileSnapshot;
|
||||
|
||||
if (existingSession) {
|
||||
// Update existing session - preserve all existing fields, but update snapshot if provided
|
||||
// Update existing session - preserve all existing fields
|
||||
store.getState().setTaskSession({
|
||||
...existingSession,
|
||||
state: newState,
|
||||
...(agentProfileSnapshot ? { agent_profile_snapshot: agentProfileSnapshot } : {}),
|
||||
...sessionUpdate,
|
||||
});
|
||||
} else {
|
||||
// Create partial session object
|
||||
// Include agent_profile_id and agent_profile_snapshot from the payload if provided
|
||||
} else if (newState) {
|
||||
// Create partial session object only if we have a state
|
||||
store.getState().setTaskSession({
|
||||
id: sessionId,
|
||||
task_id: taskId,
|
||||
@@ -37,14 +44,14 @@ export function registerTaskSessionHandlers(store: StoreApi<AppState>): WsHandle
|
||||
started_at: '',
|
||||
updated_at: '',
|
||||
...(agentProfileId ? { agent_profile_id: agentProfileId } : {}),
|
||||
...(agentProfileSnapshot ? { agent_profile_snapshot: agentProfileSnapshot } : {}),
|
||||
...sessionUpdate,
|
||||
});
|
||||
}
|
||||
|
||||
const sessionsByTask = store.getState().taskSessionsByTask.itemsByTaskId[taskId];
|
||||
if (sessionsByTask) {
|
||||
const hasSession = sessionsByTask.some((session) => session.id === sessionId);
|
||||
if (!hasSession) {
|
||||
if (!hasSession && newState) {
|
||||
store.getState().setTaskSessionsForTask(taskId, [...sessionsByTask, {
|
||||
id: sessionId,
|
||||
task_id: taskId,
|
||||
@@ -52,12 +59,12 @@ export function registerTaskSessionHandlers(store: StoreApi<AppState>): WsHandle
|
||||
started_at: '',
|
||||
updated_at: '',
|
||||
...(agentProfileId ? { agent_profile_id: agentProfileId } : {}),
|
||||
...(agentProfileSnapshot ? { agent_profile_snapshot: agentProfileSnapshot } : {}),
|
||||
...sessionUpdate,
|
||||
}]);
|
||||
} else {
|
||||
} else if (hasSession) {
|
||||
const nextSessions = sessionsByTask.map((session) =>
|
||||
session.id === sessionId
|
||||
? { ...session, state: newState, ...(agentProfileSnapshot ? { agent_profile_snapshot: agentProfileSnapshot } : {}) }
|
||||
? { ...session, ...sessionUpdate }
|
||||
: session
|
||||
);
|
||||
store.getState().setTaskSessionsForTask(taskId, nextSessions);
|
||||
|
||||
@@ -53,7 +53,7 @@ export function registerBoardsHandlers(store: StoreApi<AppState>): WsHandlers {
|
||||
},
|
||||
kanban:
|
||||
state.kanban.boardId === message.payload.id
|
||||
? { boardId: nextActiveId, columns: [], tasks: [] }
|
||||
? { boardId: nextActiveId, steps: [], tasks: [] }
|
||||
: state.kanban,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
import type { StoreApi } from 'zustand';
|
||||
import type { AppState } from '@/lib/state/store';
|
||||
import type { WsHandlers } from '@/lib/ws/handlers/types';
|
||||
|
||||
export function registerColumnsHandlers(store: StoreApi<AppState>): WsHandlers {
|
||||
return {
|
||||
'column.created': (message) => {
|
||||
store.setState((state) => {
|
||||
if (state.kanban.boardId !== message.payload.board_id) {
|
||||
return state;
|
||||
}
|
||||
const nextColumns = [
|
||||
...state.kanban.columns,
|
||||
{
|
||||
id: message.payload.id,
|
||||
title: message.payload.name,
|
||||
color: message.payload.color,
|
||||
position: message.payload.position,
|
||||
},
|
||||
].sort((a, b) => (a.position ?? 0) - (b.position ?? 0));
|
||||
return {
|
||||
...state,
|
||||
kanban: {
|
||||
...state.kanban,
|
||||
columns: nextColumns,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
'column.updated': (message) => {
|
||||
store.setState((state) => {
|
||||
if (state.kanban.boardId !== message.payload.board_id) {
|
||||
return state;
|
||||
}
|
||||
const exists = state.kanban.columns.some((column) => column.id === message.payload.id);
|
||||
const updatedColumns = exists
|
||||
? state.kanban.columns.map((column) =>
|
||||
column.id === message.payload.id
|
||||
? {
|
||||
...column,
|
||||
title: message.payload.name,
|
||||
color: message.payload.color,
|
||||
position: message.payload.position,
|
||||
}
|
||||
: column
|
||||
)
|
||||
: [
|
||||
...state.kanban.columns,
|
||||
{
|
||||
id: message.payload.id,
|
||||
title: message.payload.name,
|
||||
color: message.payload.color,
|
||||
position: message.payload.position,
|
||||
},
|
||||
];
|
||||
const nextColumns = updatedColumns.sort((a, b) => (a.position ?? 0) - (b.position ?? 0));
|
||||
return {
|
||||
...state,
|
||||
kanban: {
|
||||
...state.kanban,
|
||||
columns: nextColumns,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
'column.deleted': (message) => {
|
||||
store.setState((state) => {
|
||||
if (state.kanban.boardId !== message.payload.board_id) {
|
||||
return state;
|
||||
}
|
||||
const nextColumns = state.kanban.columns.filter((column) => column.id !== message.payload.id);
|
||||
return {
|
||||
...state,
|
||||
kanban: {
|
||||
...state.kanban,
|
||||
columns: nextColumns,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -9,15 +9,16 @@ export function registerKanbanHandlers(store: StoreApi<AppState>): WsHandlers {
|
||||
...state,
|
||||
kanban: {
|
||||
boardId: message.payload.boardId,
|
||||
columns: message.payload.columns.map((column, index) => ({
|
||||
id: column.id,
|
||||
title: column.title,
|
||||
color: column.color ?? 'bg-neutral-400',
|
||||
position: column.position ?? index,
|
||||
steps: message.payload.steps.map((step, index) => ({
|
||||
id: step.id,
|
||||
title: step.title,
|
||||
color: step.color ?? 'bg-neutral-400',
|
||||
position: step.position ?? index,
|
||||
autoStartAgent: step.autoStartAgent ?? false,
|
||||
})),
|
||||
tasks: message.payload.tasks.map((task) => ({
|
||||
id: task.id,
|
||||
columnId: task.columnId,
|
||||
workflowStepId: task.workflowStepId,
|
||||
title: task.title,
|
||||
description: task.description,
|
||||
position: task.position ?? 0,
|
||||
|
||||
@@ -13,7 +13,7 @@ export function registerTasksHandlers(store: StoreApi<AppState>): WsHandlers {
|
||||
const existingTask = state.kanban.tasks.find((task) => task.id === message.payload.task_id);
|
||||
const nextTask = {
|
||||
id: message.payload.task_id,
|
||||
columnId: message.payload.column_id,
|
||||
workflowStepId: message.payload.workflow_step_id,
|
||||
title: message.payload.title,
|
||||
description: message.payload.description,
|
||||
position: message.payload.position ?? 0,
|
||||
@@ -39,7 +39,7 @@ export function registerTasksHandlers(store: StoreApi<AppState>): WsHandlers {
|
||||
const existingTask = state.kanban.tasks.find((task) => task.id === message.payload.task_id);
|
||||
const nextTask = {
|
||||
id: message.payload.task_id,
|
||||
columnId: message.payload.column_id,
|
||||
workflowStepId: message.payload.workflow_step_id,
|
||||
title: message.payload.title,
|
||||
description: message.payload.description,
|
||||
position: message.payload.position ?? 0,
|
||||
@@ -74,7 +74,7 @@ export function registerTasksHandlers(store: StoreApi<AppState>): WsHandlers {
|
||||
const existingTask = state.kanban.tasks.find((t) => t.id === message.payload.task_id);
|
||||
const nextTask = {
|
||||
id: message.payload.task_id,
|
||||
columnId: message.payload.column_id,
|
||||
workflowStepId: message.payload.workflow_step_id,
|
||||
title: message.payload.title,
|
||||
description: message.payload.description,
|
||||
position: message.payload.position ?? 0,
|
||||
|
||||
@@ -68,7 +68,7 @@ export function registerWorkspacesHandlers(store: StoreApi<AppState>): WsHandler
|
||||
activeId,
|
||||
},
|
||||
boards: clearBoards ? { items: [], activeId: null } : state.boards,
|
||||
kanban: clearBoards ? { boardId: null, columns: [], tasks: [] } : state.kanban,
|
||||
kanban: clearBoards ? { boardId: null, steps: [], tasks: [] } : state.kanban,
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { AppState } from '@/lib/state/store';
|
||||
import { registerAgentsHandlers } from '@/lib/ws/handlers/agents';
|
||||
import { registerTaskSessionHandlers } from '@/lib/ws/handlers/agent-session';
|
||||
import { registerBoardsHandlers } from '@/lib/ws/handlers/boards';
|
||||
import { registerColumnsHandlers } from '@/lib/ws/handlers/columns';
|
||||
|
||||
import { registerMessagesHandlers } from '@/lib/ws/handlers/messages';
|
||||
import { registerNotificationsHandlers } from '@/lib/ws/handlers/notifications';
|
||||
import { registerDiffsHandlers } from '@/lib/ws/handlers/diffs';
|
||||
@@ -23,7 +23,7 @@ export function registerWsHandlers(store: StoreApi<AppState>) {
|
||||
...registerKanbanHandlers(store),
|
||||
...registerTasksHandlers(store),
|
||||
...registerBoardsHandlers(store),
|
||||
...registerColumnsHandlers(store),
|
||||
|
||||
...registerWorkspacesHandlers(store),
|
||||
...registerExecutorsHandlers(store),
|
||||
...registerEnvironmentsHandlers(store),
|
||||
|
||||
Reference in New Issue
Block a user