feat(workbench): integrate operational workflows and map state
This commit is contained in:
@@ -2,6 +2,7 @@ import { env } from "@/shared/config/env";
|
||||
import type { AccessTokenProvider } from "@/shared/auth/keycloak-auth";
|
||||
|
||||
export type AgentRunStatus = "running" | "completed" | "error" | "aborted";
|
||||
export type AgentSessionPurpose = "ordinary_chat" | "task_execution" | "task_collaboration";
|
||||
|
||||
export type AgentEventTriggerContext = {
|
||||
schema_version: "agent-trigger@1";
|
||||
@@ -51,9 +52,12 @@ export type AgentChatSession = {
|
||||
created?: boolean;
|
||||
event_duplicate?: boolean;
|
||||
trigger_id?: string;
|
||||
purpose?: AgentSessionPurpose;
|
||||
task_id?: string;
|
||||
};
|
||||
|
||||
export type AgentChatSessionSummary = {
|
||||
trigger?: { subjectId: string; workflow: "water_quality_complaint"; occurredAt: string };
|
||||
id: string;
|
||||
title: string;
|
||||
createdAt: number;
|
||||
@@ -62,6 +66,8 @@ export type AgentChatSessionSummary = {
|
||||
parentSessionId?: string;
|
||||
isStreaming?: boolean;
|
||||
runStatus?: AgentRunStatus;
|
||||
purpose: AgentSessionPurpose;
|
||||
taskId?: string;
|
||||
};
|
||||
|
||||
export type AgentLoadedChatSession = AgentChatSessionSummary & {
|
||||
@@ -71,6 +77,7 @@ export type AgentLoadedChatSession = AgentChatSessionSummary & {
|
||||
};
|
||||
|
||||
export type AgentSessionStreamDataEventType =
|
||||
| "execution_plan"
|
||||
| "token"
|
||||
| "progress"
|
||||
| "todo_update"
|
||||
@@ -90,6 +97,7 @@ export type AgentSessionStreamDataEventType =
|
||||
export type AgentSessionStreamEvent =
|
||||
| {
|
||||
type: "state";
|
||||
executionPlans?: unknown[];
|
||||
sessionId: string;
|
||||
messages: unknown[];
|
||||
isStreaming: boolean;
|
||||
@@ -103,7 +111,8 @@ export type AgentSessionStreamEvent =
|
||||
|
||||
export type AgentApiClient = {
|
||||
createSession: (options?: { triggerContext?: AgentEventTriggerContext }) => Promise<AgentChatSession>;
|
||||
listSessions: () => Promise<AgentChatSessionSummary[]>;
|
||||
listSessions: (options?: { purpose?: AgentSessionPurpose; taskId?: string }) => Promise<AgentChatSessionSummary[]>;
|
||||
createTaskCollaborationSession: (taskId: string) => Promise<AgentChatSession>;
|
||||
loadSession: (sessionId: string) => Promise<AgentLoadedChatSession | null>;
|
||||
streamSession: (
|
||||
sessionId: string,
|
||||
@@ -184,11 +193,23 @@ export function createAgentApiClient(
|
||||
});
|
||||
},
|
||||
|
||||
async listSessions() {
|
||||
const payload = await requestJson<{ sessions?: unknown[] }>("/sessions");
|
||||
async listSessions(listOptions) {
|
||||
const params = new URLSearchParams();
|
||||
if (listOptions?.purpose) params.set("purpose", listOptions.purpose);
|
||||
if (listOptions?.taskId) params.set("task_id", listOptions.taskId);
|
||||
const payload = await requestJson<{ sessions?: unknown[] }>(
|
||||
`/sessions${params.size ? `?${params.toString()}` : ""}`
|
||||
);
|
||||
return (payload.sessions ?? []).map(toSessionSummary).filter(isPresent).sort(compareSessionSummaries);
|
||||
},
|
||||
|
||||
async createTaskCollaborationSession(taskId) {
|
||||
return requestJson<AgentChatSession>(
|
||||
`/task/${encodeURIComponent(taskId)}/collaboration/session`,
|
||||
{ method: "POST" }
|
||||
);
|
||||
},
|
||||
|
||||
async getFrontendActionRegistry() {
|
||||
return requestJson<unknown>("/frontend-action-registry");
|
||||
},
|
||||
@@ -432,6 +453,10 @@ function readRunStatus(value: unknown): AgentRunStatus | undefined {
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function readSessionPurpose(value: unknown): AgentSessionPurpose {
|
||||
return value === "task_execution" || value === "task_collaboration" ? value : "ordinary_chat";
|
||||
}
|
||||
|
||||
function toSessionSummary(value: unknown): AgentChatSessionSummary | null {
|
||||
if (!isRecord(value)) {
|
||||
return null;
|
||||
@@ -450,7 +475,14 @@ function toSessionSummary(value: unknown): AgentChatSessionSummary | null {
|
||||
status: typeof value.status === "string" ? value.status : undefined,
|
||||
parentSessionId: typeof value.parent_session_id === "string" ? value.parent_session_id : undefined,
|
||||
isStreaming: typeof value.is_streaming === "boolean" ? value.is_streaming : undefined,
|
||||
runStatus: readRunStatus(value.run_status)
|
||||
runStatus: readRunStatus(value.run_status),
|
||||
purpose: readSessionPurpose(value.purpose),
|
||||
taskId: typeof value.task_id === "string" ? value.task_id : undefined,
|
||||
trigger: isRecord(value.trigger) && value.trigger.workflow === "water_quality_complaint" &&
|
||||
typeof value.trigger.subject_id === "string" && typeof value.trigger.occurred_at === "string" &&
|
||||
Number.isFinite(Date.parse(value.trigger.occurred_at))
|
||||
? { subjectId: value.trigger.subject_id, workflow: "water_quality_complaint", occurredAt: value.trigger.occurred_at }
|
||||
: undefined
|
||||
};
|
||||
}
|
||||
|
||||
@@ -530,6 +562,7 @@ function emitSessionSseEvent(
|
||||
const sessionId = typeof data.session_id === "string" ? data.session_id : "";
|
||||
onEvent({
|
||||
type: "state",
|
||||
executionPlans: Array.isArray(data.execution_plans) ? data.execution_plans : undefined,
|
||||
sessionId,
|
||||
messages: Array.isArray(data.messages) ? data.messages : [],
|
||||
isStreaming: data.is_streaming === true,
|
||||
@@ -554,6 +587,7 @@ function isSessionStreamDataEventType(value: string): value is AgentSessionStrea
|
||||
value === "token" ||
|
||||
value === "progress" ||
|
||||
value === "todo_update" ||
|
||||
value === "execution_plan" ||
|
||||
value === "permission_request" ||
|
||||
value === "permission_response" ||
|
||||
value === "question_request" ||
|
||||
|
||||
Reference in New Issue
Block a user