fix: harden production chat runtime

This commit is contained in:
kris
2026-03-31 20:20:07 +08:00
parent ec7081f6cc
commit 02fcc56332
12 changed files with 310 additions and 11 deletions

View File

@@ -36,8 +36,8 @@ android {
applicationId "com.hyzq.boss"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 19
versionName "2.5.6"
versionCode 20
versionName "2.5.7"
buildConfigField "String", "BOSS_API_BASE_URL", "\"https://boss.hyzq.net\""
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

View File

@@ -852,7 +852,7 @@ public class ProjectDetailActivity extends BossScreenActivity {
ProjectChatUiState.ReplyWaitSpec waitSpec =
ProjectChatUiState.resolveReplyWaitAfterDispatchConfirm(response.json);
runOnUiThread(() -> {
projectApprovalState = "approval_required".equals(projectCollaborationMode) ? "approved" : "not_required";
applyDispatchPlanActionResponse(response.json);
if (waitSpec.shouldWait) {
startReplyWait(
waitSpec,
@@ -887,9 +887,8 @@ public class ProjectDetailActivity extends BossScreenActivity {
throw new IllegalStateException(response.message());
}
runOnUiThread(() -> {
currentPendingDispatchPlan = null;
composerSending = false;
projectApprovalState = "rejected";
applyDispatchPlanActionResponse(response.json);
updateComposerSendButtonState();
showMessage("已拒绝主 Agent 推荐");
reload(true);
@@ -1935,6 +1934,24 @@ public class ProjectDetailActivity extends BossScreenActivity {
}
}
private void applyDispatchPlanActionResponse(@Nullable JSONObject response) {
if (response == null) {
return;
}
JSONObject collaborationGate = response.optJSONObject("collaborationGate");
if (collaborationGate != null) {
projectCollaborationMode = collaborationGate.optString("collaborationMode", projectCollaborationMode);
projectApprovalState = collaborationGate.optString("approvalState", projectApprovalState);
}
JSONObject plan = response.optJSONObject("plan");
if (plan != null) {
String status = plan.optString("status", "");
if (!"pending_user_confirmation".equals(status)) {
currentPendingDispatchPlan = null;
}
}
}
private List<String> collectMessageIds(@Nullable JSONArray messages) {
ArrayList<String> ids = new ArrayList<>();
if (messages == null) {

View File

@@ -353,6 +353,45 @@ public class ProjectDetailActivityUiTest {
assertEquals("group-1", nextIntent.getStringExtra(GroupInfoActivity.EXTRA_PROJECT_ID));
}
@Test
public void applyDispatchPlanActionResponseClearsPendingPlanAndTracksApprovalState() throws Exception {
Intent intent = new Intent()
.putExtra(ProjectDetailActivity.EXTRA_PROJECT_ID, "group-1")
.putExtra(ProjectDetailActivity.EXTRA_PROJECT_NAME, "巡检协作群");
TestProjectDetailActivity activity = Robolectric
.buildActivity(TestProjectDetailActivity.class, intent)
.setup()
.get();
ReflectionHelpers.setField(activity, "projectCollaborationMode", "approval_required");
ReflectionHelpers.setField(activity, "projectApprovalState", "pending_user");
ReflectionHelpers.setField(
activity,
"currentPendingDispatchPlan",
new JSONObject().put("planId", "dispatch-plan-1").put("status", "pending_user_confirmation")
);
JSONObject response = new JSONObject()
.put("plan", new JSONObject()
.put("planId", "dispatch-plan-1")
.put("status", "dispatched"))
.put("collaborationGate", new JSONObject()
.put("isGroup", true)
.put("collaborationMode", "approval_required")
.put("requiresMasterAgentApproval", true)
.put("approvalState", "approved"));
ReflectionHelpers.callInstanceMethod(
activity,
"applyDispatchPlanActionResponse",
ReflectionHelpers.ClassParameter.from(JSONObject.class, response)
);
assertEquals("approval_required", ReflectionHelpers.getField(activity, "projectCollaborationMode"));
assertEquals("approved", ReflectionHelpers.getField(activity, "projectApprovalState"));
assertEquals(null, ReflectionHelpers.getField(activity, "currentPendingDispatchPlan"));
}
private static JSONObject buildGroupProjectPayload() throws Exception {
JSONObject threadMeta = new JSONObject()
.put("threadId", "group-thread-3")