feat: add claw backend adapter

This commit is contained in:
kris
2026-04-03 01:36:29 +08:00
parent 8daaea01fd
commit 39b576cc42
23 changed files with 1212 additions and 23 deletions

View File

@@ -4,8 +4,11 @@ import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.TextUtils;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.Nullable;
@@ -13,6 +16,8 @@ import androidx.annotation.Nullable;
import org.json.JSONObject;
public class MasterAgentPromptActivity extends BossScreenActivity {
private static final String[] BACKEND_OVERRIDE_VALUES = {"", "claw-runtime"};
private static final String[] BACKEND_OVERRIDE_LABELS = {"默认", "Claw Runtime"};
public static final String EXTRA_PROJECT_ID = "project_id";
public static final String EXTRA_PROJECT_NAME = "project_name";
@@ -25,8 +30,10 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
private @Nullable String adminPromptText;
private @Nullable String userPromptText;
private @Nullable String projectPromptOverrideText;
private @Nullable String backendOverrideText;
private EditText userPromptInput;
private EditText projectPromptInput;
private Spinner backendSpinner;
private TextView previewTextView;
@Override
@@ -78,6 +85,7 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
"projectPromptOverride",
projectControls == null ? "" : projectControls.optString("promptOverride", "")
);
backendOverrideText = projectControls == null ? "" : projectControls.optString("backendOverride", "");
replaceContent();
appendContent(BossUi.buildSimpleProfileHeader(
@@ -115,6 +123,27 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
projectPromptInput
));
backendSpinner = new Spinner(this);
backendSpinner.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, BACKEND_OVERRIDE_LABELS));
backendSpinner.setSelection(indexOfBackendOverride(backendOverrideText));
backendSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, android.view.View view, int position, long id) {
refreshPreview();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
refreshPreview();
}
});
appendContent(BossUi.buildFormCell(
this,
"执行后端",
"默认沿用 Boss 当前主链;需要时可显式切到 Claw Runtime。",
backendSpinner
));
previewTextView = new TextView(this);
previewTextView.setText(buildPreviewText());
previewTextView.setTextSize(14);
@@ -172,6 +201,12 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
if (!TextUtils.isEmpty(projectText)) {
builder.append("【当前对话提示词】\n").append(projectText).append("\n\n");
}
String backendValue = backendSpinner == null
? (backendOverrideText == null ? "" : backendOverrideText)
: BACKEND_OVERRIDE_VALUES[backendSpinner.getSelectedItemPosition()];
if (!TextUtils.isEmpty(backendValue)) {
builder.append("【执行后端】\n").append(backendValue).append("\n\n");
}
if (builder.length() == 0) {
return "当前没有任何提示词内容。";
}
@@ -185,12 +220,16 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
}
final String userContent = userPromptInput == null ? "" : userPromptInput.getText().toString();
final String promptOverride = projectPromptInput == null ? "" : projectPromptInput.getText().toString();
final String backendOverride = backendSpinner == null
? ""
: BACKEND_OVERRIDE_VALUES[backendSpinner.getSelectedItemPosition()];
setRefreshing(true);
executor.execute(() -> {
try {
JSONObject payload = new JSONObject();
payload.put("userPromptContent", userContent);
payload.put("promptOverride", promptOverride);
payload.put("backendOverride", TextUtils.isEmpty(backendOverride) ? JSONObject.NULL : backendOverride);
BossApiClient.ApiResponse response = apiClient.updateMasterAgentPromptProfile(projectId, payload);
if (!response.ok()) {
throw new IllegalStateException(response.message());
@@ -215,4 +254,16 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
headerActionButton.setAlpha(contentLoaded ? 1f : 0.45f);
}
}
private int indexOfBackendOverride(@Nullable String value) {
if (TextUtils.isEmpty(value)) {
return 0;
}
for (int index = 0; index < BACKEND_OVERRIDE_VALUES.length; index += 1) {
if (value.equals(BACKEND_OVERRIDE_VALUES[index])) {
return index;
}
}
return 0;
}
}

View File

@@ -6,6 +6,7 @@ import static org.junit.Assert.assertTrue;
import android.content.Intent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Spinner;
import android.widget.EditText;
import android.widget.TextView;
@@ -51,7 +52,9 @@ public class MasterAgentPromptActivityTest {
JSONObject payload = new JSONObject()
.put("promptPolicy", new JSONObject().put("globalPrompt", "全局主提示词"))
.put("userPrompt", new JSONObject().put("content", "用户私有主提示词"))
.put("projectControls", new JSONObject().put("promptOverride", "当前对话提示词"));
.put("projectControls", new JSONObject()
.put("promptOverride", "当前对话提示词")
.put("backendOverride", "claw-runtime"));
ReflectionHelpers.callInstanceMethod(
activity,
@@ -64,6 +67,7 @@ public class MasterAgentPromptActivityTest {
assertTrue(viewTreeContainsText(content, "全局主提示词"));
assertTrue(viewTreeContainsText(content, "用户私有主提示词"));
assertTrue(viewTreeContainsText(content, "当前对话提示词"));
assertTrue(viewTreeContainsText(content, "执行后端"));
assertTrue(viewTreeContainsText(content, "合成预览"));
}
@@ -91,7 +95,9 @@ public class MasterAgentPromptActivityTest {
JSONObject payload = new JSONObject()
.put("promptPolicy", new JSONObject().put("globalPrompt", "全局主提示词"))
.put("userPrompt", new JSONObject().put("content", "用户私有主提示词"))
.put("projectControls", new JSONObject().put("promptOverride", "当前对话提示词"));
.put("projectControls", new JSONObject()
.put("promptOverride", "当前对话提示词")
.put("backendOverride", "claw-runtime"));
ReflectionHelpers.callInstanceMethod(
activity,
@@ -101,14 +107,16 @@ public class MasterAgentPromptActivityTest {
EditText userInput = ReflectionHelpers.getField(activity, "userPromptInput");
EditText conversationInput = ReflectionHelpers.getField(activity, "projectPromptInput");
Spinner backendSpinner = ReflectionHelpers.getField(activity, "backendSpinner");
userInput.setText("更新后的用户提示词");
conversationInput.setText("更新后的对话提示词");
backendSpinner.setSelection(0);
ReflectionHelpers.callInstanceMethod(activity, "savePromptProfile");
org.robolectric.Shadows.shadowOf(android.os.Looper.getMainLooper()).idle();
assertEquals(
"{\"userPromptContent\":\"更新后的用户提示词\",\"promptOverride\":\"更新后的对话提示词\"}",
"{\"userPromptContent\":\"更新后的用户提示词\",\"promptOverride\":\"更新后的对话提示词\",\"backendOverride\":null}",
((ScriptedBossApiClient) ReflectionHelpers.getField(activity, "apiClient")).connection.requestBody()
);
}
@@ -128,7 +136,9 @@ public class MasterAgentPromptActivityTest {
JSONObject payload = new JSONObject()
.put("promptPolicy", new JSONObject().put("globalPrompt", "全局主提示词"))
.put("userPrompt", new JSONObject().put("content", "用户私有主提示词"))
.put("projectControls", new JSONObject().put("promptOverride", "当前对话提示词"));
.put("projectControls", new JSONObject()
.put("promptOverride", "当前对话提示词")
.put("backendOverride", "claw-runtime"));
ReflectionHelpers.callInstanceMethod(
activity,