refactor: remove stale import understanding surfaces

This commit is contained in:
kris
2026-04-05 07:53:03 +08:00
parent 50d5327afd
commit 28f692706b
4 changed files with 13 additions and 190 deletions

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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 });
}

View File

@@ -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 } : {}),
};
}