feat: summarize codex stream progress events
This commit is contained in:
@@ -1679,6 +1679,49 @@ public final class BossUi {
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject streamEvents = progress == null ? null : progress.optJSONObject("streamEvents");
|
||||
if (streamEvents != null) {
|
||||
int agentDeltaCount = streamEvents.optInt("agentDeltaCount", 0);
|
||||
int planDeltaCount = streamEvents.optInt("planDeltaCount", 0);
|
||||
int reasoningDeltaCount = streamEvents.optInt("reasoningDeltaCount", 0);
|
||||
int toolProgressCount = streamEvents.optInt("toolProgressCount", 0);
|
||||
int commandOutputChunkCount = streamEvents.optInt("commandOutputChunkCount", 0);
|
||||
int terminalInteractionCount = streamEvents.optInt("terminalInteractionCount", 0);
|
||||
int fileOutputChunkCount = streamEvents.optInt("fileOutputChunkCount", 0);
|
||||
boolean hasStreamEvents = agentDeltaCount > 0 || planDeltaCount > 0 || reasoningDeltaCount > 0 ||
|
||||
toolProgressCount > 0 || commandOutputChunkCount > 0 || terminalInteractionCount > 0 ||
|
||||
fileOutputChunkCount > 0;
|
||||
if (hasStreamEvents) {
|
||||
card.addView(divider(context));
|
||||
card.addView(sectionTitle(context, "流式增量"));
|
||||
String status = streamEvents.optString("status", "").trim();
|
||||
if (!TextUtils.isEmpty(status)) {
|
||||
card.addView(detailRow(context, "◇", "状态 " + status, "", false));
|
||||
}
|
||||
if (agentDeltaCount > 0) {
|
||||
card.addView(detailRow(context, "", "回复片段 " + agentDeltaCount, "", false, true));
|
||||
}
|
||||
if (planDeltaCount > 0) {
|
||||
card.addView(detailRow(context, "", "计划片段 " + planDeltaCount, "", false, true));
|
||||
}
|
||||
if (reasoningDeltaCount > 0) {
|
||||
card.addView(detailRow(context, "", "思考片段 " + reasoningDeltaCount, "", false, true));
|
||||
}
|
||||
if (toolProgressCount > 0) {
|
||||
card.addView(detailRow(context, "", "工具进度 " + toolProgressCount, "", false, true));
|
||||
}
|
||||
if (commandOutputChunkCount > 0) {
|
||||
card.addView(detailRow(context, "", "命令输出片段 " + commandOutputChunkCount, "", false, true));
|
||||
}
|
||||
if (terminalInteractionCount > 0) {
|
||||
card.addView(detailRow(context, "", "终端交互 " + terminalInteractionCount, "", false, true));
|
||||
}
|
||||
if (fileOutputChunkCount > 0) {
|
||||
card.addView(detailRow(context, "", "文件输出片段 " + fileOutputChunkCount, "", false, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSONArray warnings = progress == null ? null : progress.optJSONArray("warnings");
|
||||
if (warnings != null && warnings.length() > 0) {
|
||||
card.addView(divider(context));
|
||||
|
||||
@@ -1234,6 +1234,58 @@ public class ProjectDetailActivityUiTest {
|
||||
assertFalse(viewTreeContainsText(messageView, "sk-secret-should-not-render"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executionProgressMessageRendersCodexStreamEventsSection() throws Exception {
|
||||
Intent intent = new Intent()
|
||||
.putExtra(ProjectDetailActivity.EXTRA_PROJECT_ID, "stream-events")
|
||||
.putExtra(ProjectDetailActivity.EXTRA_PROJECT_NAME, "Boss开发主线程");
|
||||
TestProjectDetailActivity activity = Robolectric
|
||||
.buildActivity(TestProjectDetailActivity.class, intent)
|
||||
.setup()
|
||||
.get();
|
||||
|
||||
JSONObject message = new JSONObject()
|
||||
.put("id", "progress-stream-events-1")
|
||||
.put("sender", "master")
|
||||
.put("senderLabel", "主 Agent")
|
||||
.put("body", "执行进度")
|
||||
.put("kind", "execution_progress")
|
||||
.put("sentAt", "2026-06-03T11:20:00+08:00")
|
||||
.put("executionProgress", new JSONObject()
|
||||
.put("status", "running")
|
||||
.put("steps", new JSONArray()
|
||||
.put(new JSONObject().put("text", "接收 Codex 流式事件").put("status", "running")))
|
||||
.put("streamEvents", new JSONObject()
|
||||
.put("status", "streaming")
|
||||
.put("agentDeltaCount", 2)
|
||||
.put("planDeltaCount", 1)
|
||||
.put("reasoningDeltaCount", 3)
|
||||
.put("toolProgressCount", 1)
|
||||
.put("commandOutputChunkCount", 4)
|
||||
.put("terminalInteractionCount", 1)
|
||||
.put("fileOutputChunkCount", 1)
|
||||
.put("delta", "secret delta should-not-render")
|
||||
.put("output", "secret output should-not-render")
|
||||
.put("content", "secret content should-not-render")));
|
||||
|
||||
View messageView = ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"buildMessageView",
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, message)
|
||||
);
|
||||
|
||||
assertTrue(viewTreeContainsText(messageView, "流式增量"));
|
||||
assertTrue(viewTreeContainsText(messageView, "状态 streaming"));
|
||||
assertTrue(viewTreeContainsText(messageView, "回复片段 2"));
|
||||
assertTrue(viewTreeContainsText(messageView, "计划片段 1"));
|
||||
assertTrue(viewTreeContainsText(messageView, "思考片段 3"));
|
||||
assertTrue(viewTreeContainsText(messageView, "工具进度 1"));
|
||||
assertTrue(viewTreeContainsText(messageView, "命令输出片段 4"));
|
||||
assertTrue(viewTreeContainsText(messageView, "终端交互 1"));
|
||||
assertTrue(viewTreeContainsText(messageView, "文件输出片段 1"));
|
||||
assertFalse(viewTreeContainsText(messageView, "should-not-render"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executionProgressMessageRendersCodexToolActivitySection() throws Exception {
|
||||
Intent intent = new Intent()
|
||||
|
||||
Reference in New Issue
Block a user