feat: adapt codex app-server protocol updates
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user