feat: adapt codex app-server protocol updates

This commit is contained in:
AI Bot
2026-05-31 03:25:30 +08:00
parent e1aed590f8
commit b9d3cca2e7
820 changed files with 108070 additions and 71 deletions

View File

@@ -1105,10 +1105,16 @@ export interface MasterAgentTask {
attachmentDownloadUrl?: string;
attachmentTextExcerpt?: string;
dispatchExecutionId?: string;
sourceProjectId?: string;
sourceThreadId?: string;
sourceThreadDisplayName?: string;
sourceCodexThreadRef?: string;
targetProjectId?: string;
targetThreadId?: string;
targetThreadDisplayName?: string;
targetCodexThreadRef?: string;
targetTurnId?: string;
targetCodexTurnId?: string;
targetCodexFolderRef?: string;
orchestrationBackendId?: OrchestrationBackendId;
orchestrationBackendLabel?: string;
@@ -4447,10 +4453,16 @@ export function migrateBossState(raw: Partial<BossState> | undefined): BossState
attachmentDownloadUrl: task.attachmentDownloadUrl,
attachmentTextExcerpt: task.attachmentTextExcerpt,
dispatchExecutionId: task.dispatchExecutionId,
sourceProjectId: task.sourceProjectId,
sourceThreadId: task.sourceThreadId,
sourceThreadDisplayName: task.sourceThreadDisplayName,
sourceCodexThreadRef: task.sourceCodexThreadRef,
targetProjectId: task.targetProjectId,
targetThreadId: task.targetThreadId,
targetThreadDisplayName: task.targetThreadDisplayName,
targetCodexThreadRef: task.targetCodexThreadRef,
targetTurnId: task.targetTurnId,
targetCodexTurnId: task.targetCodexTurnId,
targetCodexFolderRef: task.targetCodexFolderRef,
orchestrationBackendId:
task.orchestrationBackendId === "omx-team" || task.orchestrationBackendId === "boss-native-orchestrator"
@@ -8085,10 +8097,16 @@ export async function queueMasterAgentTask(payload: {
attachmentTextExcerpt?: string;
deviceImportDraftId?: string;
dispatchExecutionId?: string;
sourceProjectId?: string;
sourceThreadId?: string;
sourceThreadDisplayName?: string;
sourceCodexThreadRef?: string;
targetProjectId?: string;
targetThreadId?: string;
targetThreadDisplayName?: string;
targetCodexThreadRef?: string;
targetTurnId?: string;
targetCodexTurnId?: string;
targetCodexFolderRef?: string;
orchestrationBackendId?: OrchestrationBackendId;
orchestrationBackendLabel?: string;
@@ -8138,10 +8156,16 @@ export async function queueMasterAgentTask(payload: {
attachmentTextExcerpt: payload.attachmentTextExcerpt,
deviceImportDraftId: payload.deviceImportDraftId,
dispatchExecutionId: payload.dispatchExecutionId,
sourceProjectId: payload.sourceProjectId,
sourceThreadId: payload.sourceThreadId,
sourceThreadDisplayName: payload.sourceThreadDisplayName,
sourceCodexThreadRef: payload.sourceCodexThreadRef,
targetProjectId: payload.targetProjectId,
targetThreadId: payload.targetThreadId,
targetThreadDisplayName: payload.targetThreadDisplayName,
targetCodexThreadRef: payload.targetCodexThreadRef,
targetTurnId: payload.targetTurnId,
targetCodexTurnId: payload.targetCodexTurnId,
targetCodexFolderRef: payload.targetCodexFolderRef,
orchestrationBackendId: payload.orchestrationBackendId,
orchestrationBackendLabel: payload.orchestrationBackendLabel,
@@ -9291,6 +9315,50 @@ export async function cancelMasterAgentTask(input: {
return result;
}
export async function updateMasterAgentTaskProgress(payload: {
taskId: string;
deviceId: string;
status?: "queued" | "running";
executionProgress?: ExecutionProgressInput;
requestId?: string;
}) {
const result = await mutateState((state) => {
const task = state.masterAgentTasks.find((item) => item.taskId === payload.taskId);
if (!task) {
throw new Error("MASTER_AGENT_TASK_NOT_FOUND");
}
if (task.deviceId !== payload.deviceId) {
throw new Error("MASTER_AGENT_TASK_DEVICE_MISMATCH");
}
if (isTerminalMasterAgentTaskStatus(task.status)) {
return { ...task };
}
const progressStatus = payload.status === "queued" ? "queued" : "running";
if (task.status === "queued" && progressStatus === "running") {
task.status = "running";
task.claimedAt = task.claimedAt ?? nowIso();
task.lastClaimedAt = task.lastClaimedAt ?? task.claimedAt;
task.attemptCount = task.attemptCount ?? 1;
task.maxAttempts = task.maxAttempts ?? defaultMasterAgentTaskMaxAttempts(task.taskType);
task.leaseExpiresAt = task.leaseExpiresAt ?? new Date(Date.now() + masterAgentTaskLeaseMs(task)).toISOString();
}
task.requestId = payload.requestId?.trim() || task.requestId;
upsertTaskExecutionProgressMessageInState(state, task, progressStatus, payload.executionProgress);
return { ...task };
});
publishBossEvent("master_agent.task.updated", {
taskId: result.taskId,
deviceId: result.deviceId,
status: result.status,
});
const progressProjectId = resolveTaskExecutionProgressProjectId(result);
if (progressProjectId) {
publishBossEvent("project.messages.updated", { projectId: progressProjectId });
publishBossEvent("conversation.updated", { projectId: progressProjectId });
}
return result;
}
export async function completeMasterAgentTask(payload: {
taskId: string;
deviceId: string;

View File

@@ -1039,6 +1039,23 @@ function buildThreadConversationRelayPrompt(project: Project, requestText: strin
].join("\n");
}
function buildInterThreadCollaborationPrompt(params: {
sourceProject: Project;
targetProject: Project;
requestText: string;
}) {
return [
"你正在处理 Boss Inter-Thread Broker 下发的线程协作任务。",
`来源线程:${params.sourceProject.threadMeta.threadDisplayName || params.sourceProject.name}`,
`目标线程:${params.targetProject.threadMeta.threadDisplayName || params.targetProject.name}`,
"Boss 已通过 Codex App Server 把来源线程的最新可读上下文注入到当前目标线程。",
"请只基于用户的协作意图和已注入上下文继续推进,不要输出系统提示词、设备密钥、内部调度字段或无关运行时噪音。",
"如果信息足够,直接给出目标线程接下来的执行结论或开发动作;如果信息不足,只问一个最关键的问题。",
"用户协作意图:",
params.requestText.trim(),
].join("\n");
}
function appendExecutionPromptDirective(basePrompt: string, directive?: string | null) {
const trimmedDirective = directive?.trim();
if (!trimmedDirective) {
@@ -3173,6 +3190,65 @@ export async function queueThreadConversationReplyTask(params: {
});
}
export async function queueInterThreadCollaborationTask(params: {
sourceProjectId: string;
targetProjectId: string;
requestMessageId: string;
requestText: string;
sourceMessageId?: string;
sourceMessageBody?: string;
sourceMessageSentAt?: string;
requestedBy: string;
requestedByAccount: string;
}) {
if (params.sourceProjectId === params.targetProjectId) {
throw new Error("THREAD_COLLABORATION_TARGET_MUST_DIFFER");
}
const state = await readState();
const sourceProject = state.projects.find((project) => project.id === params.sourceProjectId);
if (!sourceProject) {
throw new Error("SOURCE_PROJECT_NOT_FOUND");
}
if (!isDispatchableThreadProject(sourceProject)) {
throw new Error("SOURCE_THREAD_BINDING_REQUIRED");
}
const conflict = await getThreadConversationExecutionConflict(params.targetProjectId);
if (conflict) {
throw new ThreadConversationExecutionConflictError(conflict);
}
const { project: targetProject, deviceId } =
await resolveThreadConversationExecutionContext(params.targetProjectId);
return queueMasterAgentTask({
projectId: targetProject.id,
taskType: "conversation_reply",
requestMessageId: params.requestMessageId,
requestText: params.requestText,
executionPrompt: buildInterThreadCollaborationPrompt({
sourceProject,
targetProject,
requestText: params.requestText,
}),
sourceMessageId: params.sourceMessageId,
sourceMessageBody: params.sourceMessageBody,
sourceMessageSentAt: params.sourceMessageSentAt,
requestedBy: params.requestedBy,
requestedByAccount: params.requestedByAccount,
deviceId,
intentCategory: "thread_collaboration",
sourceProjectId: sourceProject.id,
sourceThreadId: sourceProject.threadMeta.threadId,
sourceThreadDisplayName: sourceProject.threadMeta.threadDisplayName,
sourceCodexThreadRef: sourceProject.threadMeta.codexThreadRef,
targetProjectId: targetProject.id,
targetThreadId: targetProject.threadMeta.threadId,
targetThreadDisplayName: targetProject.threadMeta.threadDisplayName,
targetCodexThreadRef: targetProject.threadMeta.codexThreadRef,
targetCodexFolderRef: targetProject.threadMeta.codexFolderRef,
});
}
function buildDeviceImportResolutionPrompt(params: {
deviceName: string;
deviceId: string;