diff --git a/README.md b/README.md index 70cfb51..8cb45b6 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ Android APK: - 当前三条聊天主链都已接入真实等待链路:`主 Agent 单聊 / 普通线程单聊 / 群聊确认下发` 当前都会返回任务信息,原生 Android 会保持等待直到收到真实回写或明确超时提示 - 当前 `我的 > AI 账号` 已补 `登录 OpenAI 平台账号` 与 `绑定 Master Codex Node` 两条显式入口;OpenAI API 登录成功后会立即设为当前主控 - 当前 `登录 OpenAI 平台账号` 已升级成浏览器辅助登录流:会先进入原生引导页,再自动打开 `OpenAI Platform` 登录页;用户登录后可直接跳到 `API Keys` 页面,回 APP 粘贴 key 完成接入 +- 当前 `OpenAiOnboardingActivity` 在登录成功后会直接给出 `测试主 Agent 对话` 入口,可一键跳到 `master-agent` 聊天页 - 当前主控若还是 `Master Codex Node`,但节点离线或执行立即失败,主 Agent 会优先尝试已配置的 `OpenAI API` 备用账号,避免聊天直接掉成失败日志 - 当前群资料页已经支持“修复群成员”:如果历史脏群里混入了 `master-agent` 或失效线程引用,前台会明确提示并允许重新选择真实线程成员,修复后会正式写回群成员账本 - 当前原生聊天页也会直接提示“修复群成员”:当群里存在失效线程或不可下发成员时,`ProjectDetailActivity` 会在消息流上方直接给出 `去修复` 入口,并跳到群资料页完成修复 diff --git a/android/app/src/main/java/com/hyzq/boss/OpenAiOnboardingActivity.java b/android/app/src/main/java/com/hyzq/boss/OpenAiOnboardingActivity.java index f795941..70c7797 100644 --- a/android/app/src/main/java/com/hyzq/boss/OpenAiOnboardingActivity.java +++ b/android/app/src/main/java/com/hyzq/boss/OpenAiOnboardingActivity.java @@ -179,9 +179,8 @@ public class OpenAiOnboardingActivity extends BossScreenActivity { BossApiClient.ApiResponse response = apiClient.onboardOpenAiApiAccount(payload); if (!response.ok()) throw new IllegalStateException(response.message()); runOnUiThread(() -> { - showMessage("OpenAI 平台账号已登录,并设为当前主控。"); setResult(RESULT_OK); - finish(); + showPostLoginActions(); }); } catch (Exception error) { runOnUiThread(() -> { @@ -194,4 +193,26 @@ public class OpenAiOnboardingActivity extends BossScreenActivity { } }); } + + private void showPostLoginActions() { + new AlertDialog.Builder(this) + .setTitle("OpenAI 平台账号已登录") + .setMessage("已经设为当前主控。现在就可以直接测试主 Agent 对话。") + .setPositiveButton("测试主 Agent 对话", (dialog, which) -> openMasterAgentConversation()) + .setNegativeButton("稍后再说", (dialog, which) -> finish()) + .setOnDismissListener(dialog -> { + if (!isFinishing()) { + finish(); + } + }) + .show(); + } + + private void openMasterAgentConversation() { + Intent intent = new Intent(this, ProjectDetailActivity.class); + intent.putExtra(ProjectDetailActivity.EXTRA_PROJECT_ID, "master-agent"); + intent.putExtra(ProjectDetailActivity.EXTRA_PROJECT_NAME, "主 Agent"); + startActivity(intent); + finish(); + } } diff --git a/android/app/src/test/java/com/hyzq/boss/OpenAiOnboardingActivityTest.java b/android/app/src/test/java/com/hyzq/boss/OpenAiOnboardingActivityTest.java index faa2bd0..99e608e 100644 --- a/android/app/src/test/java/com/hyzq/boss/OpenAiOnboardingActivityTest.java +++ b/android/app/src/test/java/com/hyzq/boss/OpenAiOnboardingActivityTest.java @@ -5,16 +5,22 @@ import static org.junit.Assert.assertNotNull; import android.content.Intent; import android.net.Uri; +import android.os.Looper; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import androidx.appcompat.app.AlertDialog; + import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; +import org.robolectric.shadows.ShadowDialog; import org.robolectric.annotation.Config; +import org.robolectric.Shadows; import org.robolectric.shadows.ShadowActivity; +import org.robolectric.util.ReflectionHelpers; @RunWith(RobolectricTestRunner.class) @Config(sdk = 34) @@ -56,6 +62,28 @@ public class OpenAiOnboardingActivityTest { assertEquals(Uri.parse("https://platform.openai.com/api-keys"), nextIntent.getData()); } + @Test + public void successActionsDialogCanOpenMasterAgentConversation() { + OpenAiOnboardingActivity activity = Robolectric + .buildActivity(OpenAiOnboardingActivity.class) + .setup() + .get(); + + ReflectionHelpers.callInstanceMethod(activity, "showPostLoginActions"); + + AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog(); + assertNotNull(dialog); + dialog.getButton(AlertDialog.BUTTON_POSITIVE).performClick(); + Shadows.shadowOf(Looper.getMainLooper()).idle(); + + ShadowActivity shadowActivity = Shadows.shadowOf(activity); + Intent nextIntent = shadowActivity.getNextStartedActivity(); + assertNotNull(nextIntent); + assertEquals(ProjectDetailActivity.class.getName(), nextIntent.getComponent().getClassName()); + assertEquals("master-agent", nextIntent.getStringExtra(ProjectDetailActivity.EXTRA_PROJECT_ID)); + assertEquals("主 Agent", nextIntent.getStringExtra(ProjectDetailActivity.EXTRA_PROJECT_NAME)); + } + private static View findClickableViewContainingText(View root, String expectedText) { if (root == null) { return null; diff --git a/docs/architecture/api_and_service_inventory_cn.md b/docs/architecture/api_and_service_inventory_cn.md index a75b87a..0d2b417 100644 --- a/docs/architecture/api_and_service_inventory_cn.md +++ b/docs/architecture/api_and_service_inventory_cn.md @@ -77,6 +77,7 @@ - 会先自动打开 `OpenAI Platform` 登录页 - 支持继续打开 `API Keys` 页面 - 回 APP 后可直接粘贴 key,并设为当前主控 + - 登录成功后会直接给出 `测试主 Agent 对话` 入口 - 当前登录:临时免验证,点击登录直接创建最高管理员会话 - 当前会话恢复:`SharedPreferences` 中保存 `boss_session / restore_token / account` diff --git a/docs/architecture/current_runtime_and_deploy_status_cn.md b/docs/architecture/current_runtime_and_deploy_status_cn.md index d052d6b..2143054 100644 --- a/docs/architecture/current_runtime_and_deploy_status_cn.md +++ b/docs/architecture/current_runtime_and_deploy_status_cn.md @@ -108,6 +108,7 @@ cd /Users/kris/code/boss - 当前 Web 群聊详情页也已补上待确认推荐的刷新恢复:服务端会在页面渲染时读取最近一条 `pending_user_confirmation` 的 dispatch plan,聊天输入区会继续显示“等待你确认主 Agent 推荐”,不再因刷新丢失确认入口 - 当前 `AI 账号` 页面已分成两条显式接入链:`登录 OpenAI 平台账号(API Key)` 和 `绑定 Master Codex Node`;OpenAI API 登录成功后会立即切成当前主控 - 当前 `登录 OpenAI 平台账号` 已升级成浏览器辅助登录流:原生 Android 会先进入 `OpenAiOnboardingActivity`,自动打开 `OpenAI Platform` 登录页;用户登录后可直接跳到 `API Keys` 页面,回 APP 粘贴 key 完成接入 +- 当前 `OpenAiOnboardingActivity` 在登录成功后会直接弹出 `测试主 Agent 对话`,可一键进入 `master-agent` 聊天页验证主控链路 - 当前如果主控身份还是 `Master Codex Node`,但该节点离线或执行立即失败,主 Agent 会优先尝试已配置的 `OpenAI API` 备用账号,不再把失败日志直接原样回给用户 - 当前设备导入主链也已补上第一轮后端闭环:`heartbeat` 可上报真实项目候选,服务端会生成 `deviceImportDraft`;用户可提交勾选结果、生成导入决议,再把选中的线程真正落成聊天窗口 - Web 与原生 Android 当前都已补上“新设备导入草稿 -> 勾选 -> 决议预览 -> 应用导入”的前台流程;已绑定生产设备继续保留 heartbeat 自动导入主链 diff --git a/public/downloads/boss-android-latest.apk b/public/downloads/boss-android-latest.apk index 4fcb713..81ba9cc 100644 Binary files a/public/downloads/boss-android-latest.apk and b/public/downloads/boss-android-latest.apk differ diff --git a/public/downloads/boss-android-latest.json b/public/downloads/boss-android-latest.json index 788a8d4..4662c43 100644 --- a/public/downloads/boss-android-latest.json +++ b/public/downloads/boss-android-latest.json @@ -1,9 +1,9 @@ { "fileName": "boss-android-v2.5.5-release.apk", "urlPath": "/api/v1/user/ota/package", - "sizeBytes": 3107985, - "updatedAt": "2026-03-30T20:31:07Z", - "sha256": "61127ae868995d367616192200667b48b980dd39623c37ab2f776a5edc2700e6", + "sizeBytes": 3108637, + "updatedAt": "2026-03-30T20:41:16Z", + "sha256": "43dde41b42b2bbc4256256edb3059803b3f9959da4e546b1d9c7addeafa03350", "versionName": "2.5.5", "versionCode": 18, "buildFlavor": "release" diff --git a/public/downloads/boss-android-v2.5.5-release.apk b/public/downloads/boss-android-v2.5.5-release.apk index 4fcb713..81ba9cc 100644 Binary files a/public/downloads/boss-android-v2.5.5-release.apk and b/public/downloads/boss-android-v2.5.5-release.apk differ