murashit_codex-panel/src/features/chat/app-server/mappers/message-stream/task-progress.ts
2026-06-23 11:59:18 +09:00

44 lines
1.5 KiB
TypeScript

import type { ExecutionState, MessageStreamItem } from "../../../domain/message-stream/items";
import {
executionStateFromStatus,
RUNNING_EXECUTION_STATE,
type ExecutionStateByStatus,
} from "../../../domain/message-stream/execution-state";
const TASK_STATES = {
pending: RUNNING_EXECUTION_STATE,
inProgress: RUNNING_EXECUTION_STATE,
completed: "completed",
} as const satisfies ExecutionStateByStatus;
type TaskStepStatus = "pending" | "inProgress" | "completed";
interface TaskPlanStep {
step: string;
status: TaskStepStatus;
}
function taskProgressExecutionState(status: string): ExecutionState {
return executionStateFromStatus(status, TASK_STATES);
}
export function taskProgressMessageStreamItem(
turnId: string,
explanation: string | null,
plan: readonly TaskPlanStep[],
): MessageStreamItem {
const trimmedExplanation = explanation?.trim();
const status = plan.some((step) => step.status === "inProgress" || step.status === "pending") ? "inProgress" : "completed";
return {
id: `plan-progress-${turnId}`,
kind: "taskProgress",
role: "tool",
turnId,
sourceItemId: `plan-progress-${turnId}`,
provenance: { source: "appServer", channel: "notification", event: "taskProgress", sourceItemId: `plan-progress-${turnId}` },
explanation: trimmedExplanation !== undefined && trimmedExplanation.length > 0 ? trimmedExplanation : null,
steps: plan.map((step) => ({ step: step.step, status: step.status })),
status,
executionState: taskProgressExecutionState(status),
};
}