feat: streamline group dispatch reminders
This commit is contained in:
@@ -314,6 +314,7 @@ export interface Project {
|
||||
createdByAgent: boolean;
|
||||
collaborationMode: "development" | "approval_required";
|
||||
approvalState: "not_required" | "pending_agent" | "pending_user" | "approved" | "rejected";
|
||||
lightDispatchReminderEnabled?: boolean;
|
||||
orchestrationBackendOverride?: OrchestrationBackendOverride;
|
||||
agentControls?: ProjectAgentControls;
|
||||
unreadCount: number;
|
||||
@@ -371,7 +372,7 @@ export interface DispatchExecution {
|
||||
}
|
||||
|
||||
export function buildCollaborationGate(
|
||||
project?: Pick<Project, "isGroup" | "collaborationMode" | "approvalState">,
|
||||
project?: Pick<Project, "isGroup" | "collaborationMode" | "approvalState" | "lightDispatchReminderEnabled">,
|
||||
) {
|
||||
if (!project) {
|
||||
return {
|
||||
@@ -379,6 +380,7 @@ export function buildCollaborationGate(
|
||||
collaborationMode: "development" as const,
|
||||
requiresMasterAgentApproval: false,
|
||||
approvalState: "not_required" as const,
|
||||
lightDispatchReminderEnabled: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -387,6 +389,7 @@ export function buildCollaborationGate(
|
||||
collaborationMode: project.collaborationMode,
|
||||
requiresMasterAgentApproval: project.isGroup && project.collaborationMode === "approval_required",
|
||||
approvalState: project.approvalState,
|
||||
lightDispatchReminderEnabled: Boolean(project.lightDispatchReminderEnabled),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2783,6 +2786,7 @@ function normalizeProject(raw: Partial<Project>, fallback?: Project): Project {
|
||||
createdByAgent: raw.createdByAgent ?? false,
|
||||
collaborationMode: raw.collaborationMode ?? "development",
|
||||
approvalState: raw.approvalState ?? "not_required",
|
||||
lightDispatchReminderEnabled: raw.lightDispatchReminderEnabled ?? false,
|
||||
orchestrationBackendOverride: normalizeOrchestrationBackendOverride(raw.orchestrationBackendOverride),
|
||||
agentControls: normalizeProjectAgentControls(raw.agentControls),
|
||||
};
|
||||
@@ -3686,6 +3690,33 @@ export async function updateProjectOrchestrationBackendOverride(input: {
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateProjectLightDispatchReminder(input: {
|
||||
projectId: string;
|
||||
requestedBy: string;
|
||||
lightDispatchReminderEnabled: boolean;
|
||||
}) {
|
||||
return mutateStateIfChanged((state) => {
|
||||
const project = state.projects.find((item) => item.id === input.projectId);
|
||||
if (!project) {
|
||||
throw new Error("PROJECT_NOT_FOUND");
|
||||
}
|
||||
if (!project.isGroup) {
|
||||
throw new Error("PROJECT_NOT_GROUP_CHAT");
|
||||
}
|
||||
requireDispatchActorSession(state, input.requestedBy);
|
||||
|
||||
const nextValue = Boolean(input.lightDispatchReminderEnabled);
|
||||
if (Boolean(project.lightDispatchReminderEnabled) == nextValue) {
|
||||
return { result: project, changed: false };
|
||||
}
|
||||
|
||||
project.lightDispatchReminderEnabled = nextValue;
|
||||
project.updatedAt = nowIso();
|
||||
project.threadMeta.updatedAt = project.updatedAt;
|
||||
return { result: project, changed: true };
|
||||
});
|
||||
}
|
||||
|
||||
export async function hasPersistedProject(projectId: string) {
|
||||
const rawState = await loadPersistedStateRaw();
|
||||
return Array.isArray(rawState.projects) && rawState.projects.some((project) => project?.id === projectId);
|
||||
@@ -5559,6 +5590,7 @@ export async function confirmDispatchPlanAndCreateExecutions(input: {
|
||||
planId: string;
|
||||
confirmedBy: string;
|
||||
approvedTargetProjectIds: string[];
|
||||
rememberLightReminder?: boolean;
|
||||
}) {
|
||||
const result = await mutateState((state) => {
|
||||
const groupProjectId = input.groupProjectId.trim();
|
||||
@@ -5566,6 +5598,11 @@ export async function confirmDispatchPlanAndCreateExecutions(input: {
|
||||
const groupProject = state.projects.find((item) => item.id === groupProjectId);
|
||||
if (!groupProject) throw new Error("PROJECT_NOT_FOUND");
|
||||
if (!canOwnDispatchPlans(groupProject)) throw new Error("PROJECT_NOT_GROUP_CHAT");
|
||||
if (input.rememberLightReminder && !groupProject.lightDispatchReminderEnabled) {
|
||||
groupProject.lightDispatchReminderEnabled = true;
|
||||
groupProject.updatedAt = nowIso();
|
||||
groupProject.threadMeta.updatedAt = groupProject.updatedAt;
|
||||
}
|
||||
|
||||
const plan = applyDispatchPlanConfirmationInState(state, {
|
||||
planId: input.planId,
|
||||
|
||||
@@ -71,6 +71,29 @@ export function summarizeDispatchPlan(plan: DispatchPlanUiPayload | null | undef
|
||||
return `${summary}\n推荐线程:${titles.join("、")}`;
|
||||
}
|
||||
|
||||
export function summarizeDispatchPlanCompact(plan: DispatchPlanUiPayload | null | undefined) {
|
||||
if (!plan) {
|
||||
return "主 Agent 暂未生成推荐线程。";
|
||||
}
|
||||
const summary = plan.summary?.trim() || "主 Agent 已生成推荐线程。";
|
||||
const titles = (plan.targets ?? [])
|
||||
.map((target) => target.threadDisplayName?.trim() || "")
|
||||
.filter(Boolean);
|
||||
if (!titles.length) {
|
||||
return truncateDispatchSummary(summary);
|
||||
}
|
||||
return `推荐给:${titles.join("、")}\n${truncateDispatchSummary(summary)}`;
|
||||
}
|
||||
|
||||
export function summarizeDispatchPlanLightTitle(plan: DispatchPlanUiPayload | null | undefined) {
|
||||
const count = (plan?.targets ?? []).length;
|
||||
return count > 0 ? `主 Agent 已推荐 ${count} 个线程` : "主 Agent 已推荐线程";
|
||||
}
|
||||
|
||||
function truncateDispatchSummary(summary: string) {
|
||||
return summary.length > 32 ? `${summary.slice(0, 32)}…` : summary;
|
||||
}
|
||||
|
||||
export function extractApprovedTargetProjectIds(plan: DispatchPlanUiPayload | null | undefined) {
|
||||
return (plan?.targets ?? [])
|
||||
.map((target) => target.projectId?.trim() || "")
|
||||
|
||||
Reference in New Issue
Block a user