refactor: remove stale import understanding surfaces
This commit is contained in:
@@ -24,8 +24,6 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
private @Nullable JSONObject currentDraft;
|
||||
private @Nullable JSONObject currentResolution;
|
||||
private @Nullable JSONObject currentReviewTask;
|
||||
private @Nullable JSONArray currentUnderstandingTasks;
|
||||
private @Nullable JSONArray currentProjectUnderstandings;
|
||||
private final LinkedHashSet<String> selectedCandidateIds = new LinkedHashSet<>();
|
||||
private final Runnable reviewPollRunnable = this::reload;
|
||||
|
||||
@@ -55,9 +53,7 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
runOnUiThread(() -> applyPayload(
|
||||
response.json.optJSONObject("draft"),
|
||||
response.json.optJSONObject("resolution"),
|
||||
response.json.optJSONObject("reviewTask"),
|
||||
response.json.optJSONArray("understandingTasks"),
|
||||
response.json.optJSONArray("projectUnderstandings")
|
||||
response.json.optJSONObject("reviewTask")
|
||||
));
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> {
|
||||
@@ -71,15 +67,11 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
private void applyPayload(
|
||||
@Nullable JSONObject draft,
|
||||
@Nullable JSONObject resolution,
|
||||
@Nullable JSONObject reviewTask,
|
||||
@Nullable JSONArray understandingTasks,
|
||||
@Nullable JSONArray projectUnderstandings
|
||||
@Nullable JSONObject reviewTask
|
||||
) {
|
||||
currentDraft = draft;
|
||||
currentResolution = resolution;
|
||||
currentReviewTask = reviewTask;
|
||||
currentUnderstandingTasks = understandingTasks;
|
||||
currentProjectUnderstandings = projectUnderstandings;
|
||||
selectedCandidateIds.clear();
|
||||
JSONArray selected = draft == null ? null : draft.optJSONArray("selectedCandidateIds");
|
||||
if (selected != null) {
|
||||
@@ -117,8 +109,6 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
JSONObject draft = currentDraft;
|
||||
JSONObject resolution = currentResolution;
|
||||
JSONObject reviewTask = currentReviewTask;
|
||||
JSONArray understandingTasks = currentUnderstandingTasks;
|
||||
JSONArray projectUnderstandings = currentProjectUnderstandings;
|
||||
contentLayout.removeCallbacks(reviewPollRunnable);
|
||||
replaceContent();
|
||||
appendContent(BossUi.buildSoftPanel(
|
||||
@@ -237,40 +227,6 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
));
|
||||
}
|
||||
|
||||
if (understandingTasks != null && understandingTasks.length() > 0) {
|
||||
int completedCount = 0;
|
||||
for (int i = 0; i < understandingTasks.length(); i++) {
|
||||
JSONObject task = understandingTasks.optJSONObject(i);
|
||||
if (task != null && "completed".equals(task.optString("status", ""))) {
|
||||
completedCount += 1;
|
||||
}
|
||||
}
|
||||
appendContent(BossUi.buildCard(
|
||||
this,
|
||||
"项目理解",
|
||||
completedCount == understandingTasks.length()
|
||||
? "主 Agent 已经拿到活跃线程的项目目标、进度和技术架构。"
|
||||
: "主 Agent 正在向活跃线程追问项目目标、进度和技术架构。",
|
||||
"已完成 " + completedCount + " / " + understandingTasks.length()
|
||||
));
|
||||
}
|
||||
|
||||
if (projectUnderstandings != null) {
|
||||
for (int i = 0; i < projectUnderstandings.length(); i++) {
|
||||
JSONObject understanding = projectUnderstandings.optJSONObject(i);
|
||||
if (understanding == null) continue;
|
||||
appendContent(BossUi.buildCard(
|
||||
this,
|
||||
understanding.optString("threadDisplayName", "项目理解"),
|
||||
"目标:" + understanding.optString("projectGoal", "未提供")
|
||||
+ "\n进度:" + understanding.optString("currentProgress", "未提供")
|
||||
+ "\n架构:" + understanding.optString("technicalArchitecture", "未提供"),
|
||||
"阻塞:" + understanding.optString("currentBlockers", "无")
|
||||
+ " · 下一步:" + understanding.optString("recommendedNextStep", "继续联调")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
JSONArray appliedProjectNames = draft.optJSONArray("appliedProjectNames");
|
||||
if (appliedProjectNames != null && appliedProjectNames.length() > 0) {
|
||||
appendContent(BossUi.buildCard(
|
||||
@@ -417,16 +373,14 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
reviewResponse.json.optJSONObject("resolution"),
|
||||
reviewResponse.json.optJSONObject("reviewTask") != null
|
||||
? reviewResponse.json.optJSONObject("reviewTask")
|
||||
: reviewResponse.json.optJSONObject("task"),
|
||||
reviewResponse.json.optJSONArray("understandingTasks"),
|
||||
reviewResponse.json.optJSONArray("projectUnderstandings")
|
||||
: reviewResponse.json.optJSONObject("task")
|
||||
);
|
||||
});
|
||||
} catch (Exception error) {
|
||||
final JSONObject fallbackDraft = selectedDraft;
|
||||
runOnUiThread(() -> {
|
||||
if (fallbackDraft != null) {
|
||||
applyPayload(fallbackDraft, null, null, null, null);
|
||||
applyPayload(fallbackDraft, null, null);
|
||||
} else {
|
||||
setRefreshing(false);
|
||||
}
|
||||
@@ -450,7 +404,7 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
}
|
||||
runOnUiThread(() -> {
|
||||
showMessage("已清空当前勾选");
|
||||
applyPayload(response.json.optJSONObject("draft"), null, null, null, null);
|
||||
applyPayload(response.json.optJSONObject("draft"), null, null);
|
||||
});
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> {
|
||||
@@ -478,9 +432,7 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
applyPayload(
|
||||
response.json.optJSONObject("draft"),
|
||||
response.json.optJSONObject("resolution"),
|
||||
null,
|
||||
null,
|
||||
response.json.optJSONArray("projectUnderstandings")
|
||||
null
|
||||
);
|
||||
});
|
||||
} catch (Exception error) {
|
||||
|
||||
@@ -37,9 +37,7 @@ public class DeviceImportDraftActivityTest {
|
||||
"applyPayload",
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildPendingDraft()),
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, null),
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, null),
|
||||
ReflectionHelpers.ClassParameter.from(JSONArray.class, null),
|
||||
ReflectionHelpers.ClassParameter.from(JSONArray.class, null)
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, null)
|
||||
);
|
||||
|
||||
View content = activity.findViewById(R.id.screen_content);
|
||||
@@ -66,9 +64,7 @@ public class DeviceImportDraftActivityTest {
|
||||
"applyPayload",
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildAppliedDraft()),
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildAppliedResolution()),
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, null),
|
||||
ReflectionHelpers.ClassParameter.from(JSONArray.class, null),
|
||||
ReflectionHelpers.ClassParameter.from(JSONArray.class, null)
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, null)
|
||||
);
|
||||
|
||||
View content = activity.findViewById(R.id.screen_content);
|
||||
@@ -80,7 +76,7 @@ public class DeviceImportDraftActivityTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void renderCurrentStateShowsQueuedReviewTaskCopy() throws Exception {
|
||||
public void renderCurrentStateShowsQueuedReviewTaskCopyWithoutProjectUnderstandingSection() throws Exception {
|
||||
TestDeviceImportDraftActivity activity = Robolectric
|
||||
.buildActivity(
|
||||
TestDeviceImportDraftActivity.class,
|
||||
@@ -96,18 +92,15 @@ public class DeviceImportDraftActivityTest {
|
||||
"applyPayload",
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildPendingResolutionDraft()),
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, null),
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildQueuedReviewTask()),
|
||||
ReflectionHelpers.ClassParameter.from(JSONArray.class, buildUnderstandingTasks()),
|
||||
ReflectionHelpers.ClassParameter.from(JSONArray.class, buildProjectUnderstandings())
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildQueuedReviewTask())
|
||||
);
|
||||
|
||||
View content = activity.findViewById(R.id.screen_content);
|
||||
assertTrue(viewTreeContainsText(content, "主 Agent 审核中"));
|
||||
assertTrue(viewTreeContainsText(content, "审核任务"));
|
||||
assertTrue(viewTreeContainsText(content, "状态:queued"));
|
||||
assertTrue(viewTreeContainsText(content, "项目理解"));
|
||||
assertTrue(viewTreeContainsText(content, "北区试产线回归"));
|
||||
assertTrue(viewTreeContainsText(content, "树莓派二代接入与联调"));
|
||||
assertFalse(viewTreeContainsText(content, "项目理解"));
|
||||
assertFalse(viewTreeContainsText(content, "树莓派二代接入与联调"));
|
||||
}
|
||||
|
||||
private static JSONObject buildPendingDraft() throws Exception {
|
||||
@@ -209,27 +202,6 @@ public class DeviceImportDraftActivityTest {
|
||||
.put("status", "queued");
|
||||
}
|
||||
|
||||
private static JSONArray buildUnderstandingTasks() throws Exception {
|
||||
return new JSONArray()
|
||||
.put(new JSONObject()
|
||||
.put("taskId", "mastertask-understanding-1")
|
||||
.put("candidateId", "candidate-1")
|
||||
.put("threadDisplayName", "北区试产线回归")
|
||||
.put("status", "completed"));
|
||||
}
|
||||
|
||||
private static JSONArray buildProjectUnderstandings() throws Exception {
|
||||
return new JSONArray()
|
||||
.put(new JSONObject()
|
||||
.put("candidateId", "candidate-1")
|
||||
.put("threadDisplayName", "北区试产线回归")
|
||||
.put("projectGoal", "完成树莓派二代接入与联调")
|
||||
.put("currentProgress", "正在核对接线和控制链路")
|
||||
.put("technicalArchitecture", "Next.js 控制台 + local-agent + Codex 线程")
|
||||
.put("currentBlockers", "串口稳定性待验证")
|
||||
.put("recommendedNextStep", "先确认串口日志"));
|
||||
}
|
||||
|
||||
private static boolean viewTreeContainsText(View root, String expectedText) {
|
||||
if (root instanceof TextView) {
|
||||
CharSequence text = ((TextView) root).getText();
|
||||
|
||||
@@ -7332,55 +7332,7 @@ export async function getLatestDeviceImportDraft(deviceId: string) {
|
||||
item.deviceImportDraftId === draft.draftId,
|
||||
) ?? null
|
||||
: null;
|
||||
const understandingTasks = draft
|
||||
? listDeviceImportUnderstandingTasks(state, draft.draftId)
|
||||
: [];
|
||||
const projectUnderstandings = draft
|
||||
? deriveDeviceImportProjectUnderstandings(state, draft.draftId)
|
||||
: [];
|
||||
return { draft, resolution, reviewTask, understandingTasks, projectUnderstandings };
|
||||
}
|
||||
|
||||
function listDeviceImportUnderstandingTasks(state: BossState, draftId: string) {
|
||||
const latestByCandidate = new Map<string, MasterAgentTask>();
|
||||
for (const task of state.masterAgentTasks) {
|
||||
if (
|
||||
task.taskType !== "conversation_reply" ||
|
||||
task.deviceImportDraftId !== draftId ||
|
||||
!task.deviceImportCandidateId
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const existing = latestByCandidate.get(task.deviceImportCandidateId);
|
||||
if (!existing || existing.requestedAt < task.requestedAt) {
|
||||
latestByCandidate.set(task.deviceImportCandidateId, task);
|
||||
}
|
||||
}
|
||||
return [...latestByCandidate.values()].map((task) => ({
|
||||
taskId: task.taskId,
|
||||
candidateId: task.deviceImportCandidateId ?? "",
|
||||
threadDisplayName: task.targetThreadDisplayName ?? "",
|
||||
folderName: task.deviceImportCandidateFolderName ?? "",
|
||||
status: task.status,
|
||||
updatedAt: task.completedAt ?? task.claimedAt ?? task.requestedAt,
|
||||
}));
|
||||
}
|
||||
|
||||
function parseDeviceImportUnderstandingReply(
|
||||
task: Pick<MasterAgentTask, "replyBody" | "deviceImportCandidateId" | "targetThreadDisplayName" | "deviceImportCandidateFolderName" | "taskId" | "completedAt" | "requestedAt">,
|
||||
): DeviceImportProjectUnderstanding | null {
|
||||
const understanding = parseStructuredProjectUnderstandingReply(task);
|
||||
const candidateId = task.deviceImportCandidateId?.trim();
|
||||
if (!candidateId || !understanding) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
candidateId,
|
||||
threadDisplayName: task.targetThreadDisplayName?.trim() || "未命名线程",
|
||||
folderName: task.deviceImportCandidateFolderName?.trim() || "",
|
||||
...understanding,
|
||||
};
|
||||
return { draft, resolution, reviewTask };
|
||||
}
|
||||
|
||||
function parseStructuredProjectUnderstandingReply(
|
||||
@@ -7429,29 +7381,6 @@ function parseStructuredProjectUnderstandingReply(
|
||||
};
|
||||
}
|
||||
|
||||
function deriveDeviceImportProjectUnderstandings(state: BossState, draftId: string) {
|
||||
const latestByCandidate = new Map<string, DeviceImportProjectUnderstanding>();
|
||||
for (const task of state.masterAgentTasks) {
|
||||
if (
|
||||
task.taskType !== "conversation_reply" ||
|
||||
task.deviceImportDraftId !== draftId ||
|
||||
task.status !== "completed" ||
|
||||
!task.deviceImportCandidateId
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const understanding = parseDeviceImportUnderstandingReply(task);
|
||||
if (!understanding) {
|
||||
continue;
|
||||
}
|
||||
const existing = latestByCandidate.get(understanding.candidateId);
|
||||
if (!existing || existing.updatedAt < understanding.updatedAt) {
|
||||
latestByCandidate.set(understanding.candidateId, understanding);
|
||||
}
|
||||
}
|
||||
return [...latestByCandidate.values()];
|
||||
}
|
||||
|
||||
function applyProjectUnderstandingSnapshotInState(
|
||||
state: BossState,
|
||||
input: {
|
||||
@@ -8085,9 +8014,6 @@ function applyDeviceImportResolutionInState(
|
||||
const selectedCandidates = draft.candidates.filter((candidate) =>
|
||||
draft.selectedCandidateIds.includes(candidate.candidateId),
|
||||
);
|
||||
const understandingsByCandidate = new Map(
|
||||
deriveDeviceImportProjectUnderstandings(state, draft.draftId).map((item) => [item.candidateId, item] as const),
|
||||
);
|
||||
const importedProjects: Project[] = [];
|
||||
for (const item of resolution.items) {
|
||||
const candidate = draft.candidates.find((entry) => entry.candidateId === item.candidateId);
|
||||
@@ -8132,25 +8058,6 @@ function applyDeviceImportResolutionInState(
|
||||
targetProject.preview = `已导入 ${candidate.threadDisplayName}`;
|
||||
targetProject.updatedAt = nowIso();
|
||||
targetProject.lastMessageAt = targetProject.updatedAt;
|
||||
const understanding = understandingsByCandidate.get(candidate.candidateId);
|
||||
if (understanding) {
|
||||
applyProjectUnderstandingSnapshotInState(state, {
|
||||
projectId: targetProject.id,
|
||||
account: device.account,
|
||||
snapshot: {
|
||||
projectGoal: understanding.projectGoal,
|
||||
currentProgress: understanding.currentProgress,
|
||||
technicalArchitecture: understanding.technicalArchitecture,
|
||||
currentBlockers: understanding.currentBlockers,
|
||||
recommendedNextStep: understanding.recommendedNextStep,
|
||||
sourceTaskId: understanding.sourceTaskId,
|
||||
updatedAt: understanding.updatedAt,
|
||||
sourceKind: "device_import",
|
||||
},
|
||||
sourceMessageId: understanding.sourceTaskId,
|
||||
sourceKind: "device_import",
|
||||
});
|
||||
}
|
||||
importedProjects.push({ ...targetProject });
|
||||
}
|
||||
|
||||
|
||||
@@ -1795,7 +1795,6 @@ export async function queueDeviceImportResolutionTask(params: {
|
||||
const selectedCandidates = draft.candidates.filter((candidate) =>
|
||||
draft.selectedCandidateIds.includes(candidate.candidateId),
|
||||
);
|
||||
const understandingTasks: Array<Awaited<ReturnType<typeof queueMasterAgentTask>>> = [];
|
||||
const task = await queueMasterAgentTask({
|
||||
projectId: "master-agent",
|
||||
taskType: "device_import_resolution",
|
||||
@@ -1836,13 +1835,6 @@ export async function queueDeviceImportResolutionTask(params: {
|
||||
deviceImportDraftId: task.deviceImportDraftId,
|
||||
},
|
||||
draft: latest.draft ?? undefined,
|
||||
understandingTasks: understandingTasks.map((item) => ({
|
||||
taskId: item.taskId,
|
||||
taskType: item.taskType,
|
||||
status: item.status,
|
||||
candidateId: item.deviceImportCandidateId,
|
||||
threadDisplayName: item.targetThreadDisplayName,
|
||||
})),
|
||||
...(latest.resolution ? { resolution: latest.resolution } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user