feat: gate claw runtime selection by availability
This commit is contained in:
@@ -15,9 +15,10 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
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";
|
||||
|
||||
@@ -31,6 +32,9 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
|
||||
private @Nullable String userPromptText;
|
||||
private @Nullable String projectPromptOverrideText;
|
||||
private @Nullable String backendOverrideText;
|
||||
private boolean clawSelectable;
|
||||
private @Nullable String clawReasonLabel;
|
||||
private final List<String> backendOverrideValues = new ArrayList<>();
|
||||
private EditText userPromptInput;
|
||||
private EditText projectPromptInput;
|
||||
private Spinner backendSpinner;
|
||||
@@ -79,6 +83,7 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
|
||||
promptPolicy = payload.optJSONObject("promptPolicy");
|
||||
userPrompt = payload.optJSONObject("userPrompt");
|
||||
projectControls = payload.optJSONObject("projectControls");
|
||||
JSONObject clawAvailability = payload.optJSONObject("clawAvailability");
|
||||
adminPromptText = promptPolicy == null ? null : promptPolicy.optString("globalPrompt", "");
|
||||
userPromptText = userPrompt == null ? "" : userPrompt.optString("content", "");
|
||||
projectPromptOverrideText = payload.optString(
|
||||
@@ -86,6 +91,8 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
|
||||
projectControls == null ? "" : projectControls.optString("promptOverride", "")
|
||||
);
|
||||
backendOverrideText = projectControls == null ? "" : projectControls.optString("backendOverride", "");
|
||||
clawSelectable = clawAvailability != null && clawAvailability.optBoolean("selectable", false);
|
||||
clawReasonLabel = clawAvailability == null ? "" : clawAvailability.optString("reasonLabel", "");
|
||||
|
||||
replaceContent();
|
||||
appendContent(BossUi.buildSimpleProfileHeader(
|
||||
@@ -123,8 +130,17 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
|
||||
projectPromptInput
|
||||
));
|
||||
|
||||
backendOverrideValues.clear();
|
||||
List<String> backendLabels = new ArrayList<>();
|
||||
backendOverrideValues.add("");
|
||||
backendLabels.add("默认");
|
||||
if (clawSelectable) {
|
||||
backendOverrideValues.add("claw-runtime");
|
||||
backendLabels.add("Claw Runtime");
|
||||
}
|
||||
|
||||
backendSpinner = new Spinner(this);
|
||||
backendSpinner.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, BACKEND_OVERRIDE_LABELS));
|
||||
backendSpinner.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, backendLabels));
|
||||
backendSpinner.setSelection(indexOfBackendOverride(backendOverrideText));
|
||||
backendSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
@@ -143,6 +159,16 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
|
||||
"默认沿用 Boss 当前主链;需要时可显式切到 Claw Runtime。",
|
||||
backendSpinner
|
||||
));
|
||||
if (!clawSelectable) {
|
||||
appendContent(BossUi.buildSoftPanel(
|
||||
this,
|
||||
"Claw Runtime 当前不可用",
|
||||
TextUtils.isEmpty(clawReasonLabel) ? "当前环境未满足 Claw Runtime 的启动条件。" : clawReasonLabel,
|
||||
TextUtils.equals(backendOverrideText, "claw-runtime")
|
||||
? "当前对话之前保存过 Claw Runtime,运行时会自动回退到默认后端。"
|
||||
: "恢复可用后,执行后端下拉框会重新出现 Claw Runtime。"
|
||||
));
|
||||
}
|
||||
|
||||
previewTextView = new TextView(this);
|
||||
previewTextView.setText(buildPreviewText());
|
||||
@@ -203,9 +229,11 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
|
||||
}
|
||||
String backendValue = backendSpinner == null
|
||||
? (backendOverrideText == null ? "" : backendOverrideText)
|
||||
: BACKEND_OVERRIDE_VALUES[backendSpinner.getSelectedItemPosition()];
|
||||
: backendOverrideValues.get(backendSpinner.getSelectedItemPosition());
|
||||
if (!TextUtils.isEmpty(backendValue)) {
|
||||
builder.append("【执行后端】\n").append(backendValue).append("\n\n");
|
||||
} else if (TextUtils.equals(backendOverrideText, "claw-runtime") && !clawSelectable) {
|
||||
builder.append("【执行后端】\n默认(Claw Runtime 当前不可用,运行时会自动回退)\n\n");
|
||||
}
|
||||
if (builder.length() == 0) {
|
||||
return "当前没有任何提示词内容。";
|
||||
@@ -222,7 +250,7 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
|
||||
final String promptOverride = projectPromptInput == null ? "" : projectPromptInput.getText().toString();
|
||||
final String backendOverride = backendSpinner == null
|
||||
? ""
|
||||
: BACKEND_OVERRIDE_VALUES[backendSpinner.getSelectedItemPosition()];
|
||||
: backendOverrideValues.get(backendSpinner.getSelectedItemPosition());
|
||||
setRefreshing(true);
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
@@ -259,8 +287,8 @@ public class MasterAgentPromptActivity extends BossScreenActivity {
|
||||
if (TextUtils.isEmpty(value)) {
|
||||
return 0;
|
||||
}
|
||||
for (int index = 0; index < BACKEND_OVERRIDE_VALUES.length; index += 1) {
|
||||
if (value.equals(BACKEND_OVERRIDE_VALUES[index])) {
|
||||
for (int index = 0; index < backendOverrideValues.size(); index += 1) {
|
||||
if (value.equals(backendOverrideValues.get(index))) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,6 +156,43 @@ public class MasterAgentPromptActivityTest {
|
||||
assertTrue(viewTreeContainsText(content, "新的当前对话提示词"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void renderPromptProfileShowsClawUnavailableHintWhenBackendCannotBeSelected() throws Exception {
|
||||
TestMasterAgentPromptActivity activity = Robolectric
|
||||
.buildActivity(
|
||||
TestMasterAgentPromptActivity.class,
|
||||
new Intent()
|
||||
.putExtra(MasterAgentPromptActivity.EXTRA_PROJECT_ID, "master-agent")
|
||||
.putExtra(MasterAgentPromptActivity.EXTRA_PROJECT_NAME, "主 Agent")
|
||||
)
|
||||
.setup()
|
||||
.get();
|
||||
|
||||
JSONObject payload = new JSONObject()
|
||||
.put("promptPolicy", new JSONObject().put("globalPrompt", "全局主提示词"))
|
||||
.put("userPrompt", new JSONObject().put("content", "用户私有主提示词"))
|
||||
.put("projectControls", new JSONObject()
|
||||
.put("promptOverride", "当前对话提示词")
|
||||
.put("backendOverride", "claw-runtime"))
|
||||
.put("clawAvailability", new JSONObject()
|
||||
.put("status", "misconfigured")
|
||||
.put("selectable", false)
|
||||
.put("reason", "script_not_found")
|
||||
.put("reasonLabel", "未检测到有效的 Claw 启动脚本,将自动回退到默认后端。"));
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"renderPromptProfile",
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, payload)
|
||||
);
|
||||
|
||||
Spinner backendSpinner = ReflectionHelpers.getField(activity, "backendSpinner");
|
||||
assertEquals(1, backendSpinner.getAdapter().getCount());
|
||||
View content = activity.findViewById(R.id.screen_content);
|
||||
assertTrue(viewTreeContainsText(content, "Claw Runtime 当前不可用"));
|
||||
assertTrue(viewTreeContainsText(content, "未检测到有效的 Claw 启动脚本"));
|
||||
}
|
||||
|
||||
private static boolean viewTreeContainsText(View root, String expectedText) {
|
||||
if (root instanceof TextView) {
|
||||
CharSequence text = ((TextView) root).getText();
|
||||
|
||||
Reference in New Issue
Block a user