feat: complete chat routing and openai onboarding
This commit is contained in:
@@ -327,6 +327,15 @@ export interface DeviceImportCandidate {
|
||||
suggestedImport: boolean;
|
||||
}
|
||||
|
||||
export function isDispatchableThreadProject(project: Project) {
|
||||
return (
|
||||
project.id !== "master-agent" &&
|
||||
!project.isGroup &&
|
||||
Boolean(project.threadMeta.codexThreadRef?.trim()) &&
|
||||
project.deviceIds.length > 0
|
||||
);
|
||||
}
|
||||
|
||||
export interface DeviceImportDraft {
|
||||
draftId: string;
|
||||
deviceId: string;
|
||||
@@ -521,6 +530,8 @@ export interface MasterAgentTask {
|
||||
targetProjectId?: string;
|
||||
targetThreadId?: string;
|
||||
targetThreadDisplayName?: string;
|
||||
targetCodexThreadRef?: string;
|
||||
targetCodexFolderRef?: string;
|
||||
deviceImportDraftId?: string;
|
||||
status: MasterAgentTaskStatus;
|
||||
requestedAt: string;
|
||||
@@ -3812,7 +3823,10 @@ export async function saveAiAccount(payload: {
|
||||
const existing = payload.accountId
|
||||
? state.aiAccounts.find((item) => item.accountId === payload.accountId)
|
||||
: null;
|
||||
const accountId = existing?.accountId ?? `ai-${slugify(`${payload.label}-${payload.displayName}`)}`;
|
||||
const accountId =
|
||||
existing?.accountId ??
|
||||
payload.accountId?.trim() ??
|
||||
`ai-${slugify(`${payload.label}-${payload.displayName}`)}`;
|
||||
const next: AiAccount = normalizeAiAccount({
|
||||
accountId,
|
||||
label: payload.label.trim() || aiRoleLabel(payload.role),
|
||||
@@ -3989,6 +4003,8 @@ export async function queueMasterAgentTask(payload: {
|
||||
targetProjectId?: string;
|
||||
targetThreadId?: string;
|
||||
targetThreadDisplayName?: string;
|
||||
targetCodexThreadRef?: string;
|
||||
targetCodexFolderRef?: string;
|
||||
}) {
|
||||
const task = await mutateState((state) => {
|
||||
const task: MasterAgentTask = {
|
||||
@@ -4014,6 +4030,8 @@ export async function queueMasterAgentTask(payload: {
|
||||
targetProjectId: payload.targetProjectId,
|
||||
targetThreadId: payload.targetThreadId,
|
||||
targetThreadDisplayName: payload.targetThreadDisplayName,
|
||||
targetCodexThreadRef: payload.targetCodexThreadRef,
|
||||
targetCodexFolderRef: payload.targetCodexFolderRef,
|
||||
status: "queued",
|
||||
requestedAt: nowIso(),
|
||||
};
|
||||
@@ -4281,6 +4299,8 @@ function ensureDispatchExecutionTaskInState(
|
||||
existing.targetProjectId = existing.targetProjectId ?? execution.targetProjectId;
|
||||
existing.targetThreadId = existing.targetThreadId ?? execution.targetThreadId;
|
||||
existing.targetThreadDisplayName = existing.targetThreadDisplayName ?? target.threadDisplayName;
|
||||
existing.targetCodexThreadRef = existing.targetCodexThreadRef ?? target.codexThreadRef;
|
||||
existing.targetCodexFolderRef = existing.targetCodexFolderRef ?? target.codexFolderRef;
|
||||
existing.executionPrompt =
|
||||
existing.executionPrompt ||
|
||||
buildDispatchExecutionPrompt({
|
||||
@@ -4311,6 +4331,8 @@ function ensureDispatchExecutionTaskInState(
|
||||
targetProjectId: execution.targetProjectId,
|
||||
targetThreadId: execution.targetThreadId,
|
||||
targetThreadDisplayName: target.threadDisplayName,
|
||||
targetCodexThreadRef: target.codexThreadRef,
|
||||
targetCodexFolderRef: target.codexFolderRef,
|
||||
status: "queued",
|
||||
requestedAt: nowIso(),
|
||||
};
|
||||
@@ -4790,17 +4812,48 @@ export async function completeMasterAgentTask(payload: {
|
||||
masterSummary: payload.replyBody?.trim(),
|
||||
});
|
||||
} else if (!attachmentProjectId && payload.status === "completed" && task.replyBody) {
|
||||
pushProjectLedgerMessage(state, task.projectId, {
|
||||
sender: "master",
|
||||
senderLabel: task.accountLabel ? `主 Agent · ${task.accountLabel}` : "主 Agent",
|
||||
body: task.replyBody,
|
||||
kind: "text",
|
||||
});
|
||||
const isThreadConversationReply =
|
||||
task.taskType === "conversation_reply" &&
|
||||
task.projectId !== "master-agent" &&
|
||||
Boolean(task.targetProjectId && task.targetThreadId);
|
||||
if (isThreadConversationReply) {
|
||||
const threadProject = state.projects.find(
|
||||
(item) => item.id === (task.targetProjectId ?? task.projectId),
|
||||
);
|
||||
const device = state.devices.find((item) => item.id === payload.deviceId);
|
||||
pushProjectLedgerMessage(state, threadProject?.id ?? task.projectId, {
|
||||
sender: "device",
|
||||
senderLabel:
|
||||
task.targetThreadDisplayName?.trim() ||
|
||||
threadProject?.threadMeta.threadDisplayName ||
|
||||
device?.name ||
|
||||
"线程",
|
||||
body: task.replyBody,
|
||||
kind: "text",
|
||||
});
|
||||
} else {
|
||||
pushProjectLedgerMessage(state, task.projectId, {
|
||||
sender: "master",
|
||||
senderLabel: task.accountLabel ? `主 Agent · ${task.accountLabel}` : "主 Agent",
|
||||
body: task.replyBody,
|
||||
kind: "text",
|
||||
});
|
||||
}
|
||||
} else if (!attachmentProjectId && payload.status === "failed") {
|
||||
const isThreadConversationReply =
|
||||
task.taskType === "conversation_reply" &&
|
||||
task.projectId !== "master-agent" &&
|
||||
Boolean(task.targetProjectId && task.targetThreadId);
|
||||
pushProjectLedgerMessage(state, task.projectId, {
|
||||
sender: "ops",
|
||||
senderLabel: task.accountLabel ? `主 Agent Relay · ${task.accountLabel}` : "主 Agent Relay",
|
||||
body: `Master Codex Node 执行失败:${task.errorMessage ?? "UNKNOWN_ERROR"}`,
|
||||
senderLabel: isThreadConversationReply
|
||||
? "线程执行失败"
|
||||
: task.accountLabel
|
||||
? `主 Agent Relay · ${task.accountLabel}`
|
||||
: "主 Agent Relay",
|
||||
body: isThreadConversationReply
|
||||
? `${task.targetThreadDisplayName ?? "当前线程"} 执行失败:${task.errorMessage ?? "UNKNOWN_ERROR"}`
|
||||
: `Master Codex Node 执行失败:${task.errorMessage ?? "UNKNOWN_ERROR"}`,
|
||||
kind: "text",
|
||||
});
|
||||
}
|
||||
@@ -6233,6 +6286,9 @@ function createGroupChatFromProjectIds(
|
||||
if (!memberProject) {
|
||||
throw new Error("GROUP_CHAT_MEMBER_NOT_FOUND");
|
||||
}
|
||||
if (!isDispatchableThreadProject(memberProject)) {
|
||||
throw new Error("GROUP_CHAT_MEMBER_NOT_THREAD");
|
||||
}
|
||||
memberProjects.push(memberProject);
|
||||
}
|
||||
if (memberProjects.length < 2) {
|
||||
|
||||
Reference in New Issue
Block a user