Integrate master agent runtime orchestration updates

This commit is contained in:
kris
2026-04-16 04:41:46 +08:00
parent e0c0ea1814
commit 39be49630f
81 changed files with 9283 additions and 448 deletions

View File

@@ -0,0 +1,112 @@
# Android Chat Status Row Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Render `conversationTasks` and `executionWarnings` as a compact inline status row beneath each message on the Android chat page, dedupe grouped warnings per message, and keep realtime patches scoped to the affected message.
**Architecture:** Add a reusable status-row builder in `BossUi` and wire `ProjectDetailActivity.buildMessageView` to compute grouped tasks/warnings, append the status row under each bubble, and compare a fingerprint during realtime patches so only impacted views re-render.
**Tech Stack:** Android/Java UI (`ProjectDetailActivity.java`, `BossUi.java`) and Node-powered source-verification tests (`tests/android-chat-incremental-realtime-append.test.ts`, `tests/android-chat-local-realtime-patch.test.ts`).
---
### Task 1: Fail on missing inline status row in realtime append test
**Files:**
- Modify: `tests/android-chat-incremental-realtime-append.test.ts`
- Test: `npm test tests/android-chat-incremental-realtime-append.test.ts`
- [ ] **Step 1: Write the failing test**
```ts
assert.match(
source,
/wrapper\.addView\(BossUi\.buildMessageStatusRow\(/,
"expected every message bubble to append BossUi.buildMessageStatusRow",
);
assert.match(
source,
/List<JSONObject> messageWarnings = collectMessageWarnings\(projectMessagesPayload, messageId\);/,
"expected the new status row builder to source grouped warnings per message",
);
assert.match(
source,
/String statusFingerprint = buildStatusFingerprint\(messageId, projectMessagesPayload\);/,
"expected realtime patches to compute a fingerprint before replacing a message view",
);
```
- [ ] **Step 2: Run it to prove failure**
Run: `npm test tests/android-chat-incremental-realtime-append.test.ts`
Expected: FAIL because `BossUi.buildMessageStatusRow` and the new helper functions do not yet exist.
- [ ] **Step 3: Re-run after implementation to confirm success**
Run: `npm test tests/android-chat-incremental-realtime-append.test.ts`
Expected: PASS.
### Task 2: Fail on missing helper signatures in realtime patch test
**Files:**
- Modify: `tests/android-chat-local-realtime-patch.test.ts`
- Test: `npm test tests/android-chat-local-realtime-patch.test.ts`
- [ ] **Step 1: Write the failing test**
```ts
assert.match(
source,
/LinearLayout statusRow = buildMessageStatusRow\(this, message, conversationTask, messageWarnings\);/,
"expected buildMessageStatusRow to be invoked when each message is rendered",
);
assert.match(
source,
/List<JSONObject> buildMessageWarnings\(JSONObject payload, String messageId\);/,
"expected a helper that returns grouped warnings keyed by message id",
);
assert.match(
source,
/if \(!TextUtils\.equals\(currentFingerprint, nextFingerprint\)\) \{ replaceMessageViewById\(/,
"expected realtime patch to compare status fingerprint before rerendering",
);
```
- [ ] **Step 2: Run it to prove failure**
Run: `npm test tests/android-chat-local-realtime-patch.test.ts`
Expected: FAIL because helper signatures and fingerprint comparisons are missing.
- [ ] **Step 3: Re-run after implementation to confirm success**
Run: `npm test tests/android-chat-local-realtime-patch.test.ts`
Expected: PASS.
### Task 3: Add BossUi helper for compact status row
**Files:**
- Modify: `android/app/src/main/java/com/hyzq/boss/BossUi.java`
- Test: `npm test tests/android-chat-incremental-realtime-append.test.ts`
- Test: `npm test tests/android-chat-local-realtime-patch.test.ts`
- [ ] **Step 1: Implement `buildMessageStatusRow`**
Add a method that accepts `(Context context, String statusLabel, String detailText, boolean outgoing)` and returns a horizontal `LinearLayout` with spaced pills and body text, using rounded background colors and `TextView` ellipsizing. Keep it compact (max height) and re-usable for both warnings and conversation task summaries.
- [ ] **Step 2: Run targeted tests**
Run: `npm test tests/android-chat-incremental-realtime-append.test.ts tests/android-chat-local-realtime-patch.test.ts`
Expected: PASS after the helper is referenced by `ProjectDetailActivity`.
### Task 4: Wire ProjectDetailActivity to the new status row
**Files:**
- Modify: `android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java`
- Test: `npm test tests/android-chat-incremental-realtime-append.test.ts`
- Test: `npm test tests/android-chat-local-realtime-patch.test.ts`
- [ ] **Step 1: Add helper methods for grouped warnings/tasks and fingerprinting**
Implement `List<JSONObject> collectMessageWarnings(JSONObject payload, String messageId)`, `@Nullable JSONObject findConversationTask(String messageId)`, and `private String buildStatusFingerprint(String messageId, JSONObject payload)` that concatenates task/w warning summaries so the realtime patch can detect status changes without re-rendering unchanged rows.
- [ ] **Step 2: Update `buildMessageView` to append a status row**
Inside `buildMessageView`, compute `List<JSONObject> messageWarnings` and `JSONObject messageTask`, then call `BossUi.buildMessageStatusRow(this, description, detail, outgoing)` and add it directly beneath the bubble instead of the previous warning card logic. Use the grouped data to deduplicate identical warnings (e.g., map by `warningId` or `title+summary`).
- [ ] **Step 3: Update realtime patch logic**
In `tryPatchRealtimeExecutionWarnings`, compute `String currentFingerprint = buildStatusFingerprint(messageId, currentRenderedProjectPayload)` and `String nextFingerprint = buildStatusFingerprint(messageId, projectMessagesPayload)`; only call `replaceMessageViewById` when they differ. Ensure `currentRenderedProjectPayload` is updated once per patch and that `renderNearBottom`/`setRefreshing` behavior stays the same.
- [ ] **Step 4: Run regression tests**
Run: `npm test tests/android-chat-incremental-realtime-append.test.ts tests/android-chat-local-realtime-patch.test.ts`
Expected: PASS.
### Task 5: Final verification
**Files:**
- Test: all above tests
- [ ] **Step 1: Run the two test files together**
Run: `npm test tests/android-chat-incremental-realtime-append.test.ts tests/android-chat-local-realtime-patch.test.ts`
Expected: PASS with no additional failures.

View File

@@ -0,0 +1,318 @@
# Hermes Backend MVP Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 为 Boss 新增一个默认关闭、可显式启用的 `hermes-runtime`,让 `master-agent` 可通过 Hermes CLI 返回回复。
**Architecture:** 复用现有 `claw-runtime` 的接入形态,在 `src/lib/execution/backends/` 下新增 Hermes 配置、runner 与 backend adapter再把 selector、主 Agent 路由与前台控制接上。第一批只开放给 `master-agent`,不碰群聊编排和 Android 独立设置页。
**Tech Stack:** Next.js App Router, TypeScript, Node child_process, Node test runner
---
### Task 1: 补 Hermes 后端底座测试
**Files:**
- Create: `tests/hermes-backend-config.test.ts`
- Create: `tests/hermes-runner.test.ts`
- Create: `tests/hermes-backend.test.ts`
- Modify: `tests/execution-backend-selector.test.ts`
- [ ] **Step 1: 写配置与 selector 的失败测试**
```ts
test("Hermes backend 默认关闭且 selector 不会主动选中", () => {
const backends = listExecutionBackendChoices({
primary: { provider: "master_codex_node", status: "ready" },
backups: [{ provider: "openai_api", status: "ready" }],
requestKind: "master_agent_reply",
});
assert.deepEqual(backends.map((item) => item.backendId), [
"master-codex-node",
"openai-api",
]);
});
```
- [ ] **Step 2: 写 runner 参数拼装失败测试**
```ts
test("Hermes runner 会拼 chat -q -Q --source tool 与可选模型参数", async () => {
const result = await runHermesCommandForTesting({
config: {
enabled: true,
command: process.execPath,
args: [scriptPath],
timeoutMs: 30_000,
defaultModel: "gpt-5.4",
sourceTag: "tool",
},
payload: {
executionPrompt: "请输出链路正常",
model: "gpt-5.5",
},
});
assert.equal(result.status, "completed");
assert.equal(result.output, "Hermes smoke completed");
});
```
- [ ] **Step 3: 跑测试确认当前失败**
Run:
```bash
npx tsx --test tests/hermes-backend-config.test.ts tests/hermes-runner.test.ts tests/hermes-backend.test.ts tests/execution-backend-selector.test.ts
```
Expected:
- FAIL提示 Hermes 相关模块不存在或 selector 还不认识 `hermes-runtime`
---
### Task 2: 实现 Hermes config / runner / backend
**Files:**
- Create: `src/lib/execution/backends/hermes-config.ts`
- Create: `src/lib/execution/backends/hermes-runner.ts`
- Create: `src/lib/execution/backends/hermes-backend.ts`
- Create: `scripts/hermes-runtime-smoke.mjs`
- [ ] **Step 1: 实现 Hermes 配置读取与可用性检查**
实现点:
- `BOSS_HERMES_ENABLED`
- `BOSS_HERMES_COMMAND`
- `BOSS_HERMES_ARGS`
- `BOSS_HERMES_WORKDIR`
- `BOSS_HERMES_TIMEOUT_MS`
- `BOSS_HERMES_DEFAULT_MODEL`
- `BOSS_HERMES_TOOLSETS`
- `BOSS_HERMES_SKILLS`
- [ ] **Step 2: 实现 runner**
固定执行形态:
```text
<command> <prefix args> chat -q <executionPrompt> -Q --source tool
```
可选追加:
- `-m <model>`
- `-t <toolsets>`
- `-s <skills>`
解析 quiet 模式结尾的:
```text
session_id: xxx
```
但只把正文回给 Boss。
- [ ] **Step 3: 实现 backend adapter**
能力保持与 Claw 一致:
- backendId: `hermes-runtime`
- 仅支持 `master_agent_reply` / `thread_reply`
- `describe()` 返回稳定描述
- [ ] **Step 4: 跑测试确认转绿**
Run:
```bash
npx tsx --test tests/hermes-backend-config.test.ts tests/hermes-runner.test.ts tests/hermes-backend.test.ts tests/execution-backend-selector.test.ts
```
Expected:
- PASS
---
### Task 3: 把 Hermes 接入 selector 与主 Agent 控制面
**Files:**
- Modify: `src/lib/execution/backend-selector.ts`
- Modify: `src/lib/boss-data.ts`
- Modify: `src/app/api/v1/projects/[projectId]/agent-controls/route.ts`
- Modify: `src/app/api/v1/projects/[projectId]/prompt-profile/route.ts`
- Modify: `src/app/me/master-agent/page.tsx`
- Modify: `src/components/master-agent-prompt-memory-client.tsx`
- Modify: `tests/master-agent-chat-controls.test.ts`
- [ ] **Step 1: 扩展 `backendOverride` 合法值**
把:
```ts
backendOverride?: "claw-runtime";
```
扩为:
```ts
backendOverride?: "claw-runtime" | "hermes-runtime";
```
并同步更新 `parseBackendOverride()`
- [ ] **Step 2: 扩展路由校验**
保存 `agent-controls` / `prompt-profile` 时:
- 允许 `hermes-runtime`
- 若 Hermes 当前不可选,直接返回 400 和原因
- [ ] **Step 3: 扩展 Web 控制面**
主 Agent 提示词页的执行后端下拉新增:
- `Hermes Runtime`
并显示 Hermes 的可用性提示。
- [ ] **Step 4: 跑控制面测试**
Run:
```bash
npx tsx --test tests/master-agent-chat-controls.test.ts
```
Expected:
- PASS`backendOverride: "hermes-runtime"` 可读写
---
### Task 4: 接上 `boss-master-agent` 执行链
**Files:**
- Modify: `src/lib/boss-master-agent.ts`
- Modify: `tests/master-agent-message-queue.test.ts`
- [ ] **Step 1: 写 Hermes 主 Agent 执行失败测试**
新增与 Claw 对齐的测试:
- 显式选择 `hermes-runtime`
- Hermes 返回结果后能写回主 Agent 会话
- 不可用时会回退或返回明确失败
- [ ] **Step 2: 实现 `replyViaHermesBackend` 与 `enqueueHermesMasterAgentReply`**
保持与 Claw 同一层级:
- 同步模式直接执行并回写
- enqueue 模式先排任务,再异步执行 Hermes
- Hermes 失败时按当前主链回退到 API / Master Node
- [ ] **Step 3: 在 selector 结果里接入 Hermes 分支**
在:
- `replyToMasterAgentUserMessage()`
里新增:
- `selectedBackend.backendId === HERMES_BACKEND_ID`
对应处理。
- [ ] **Step 4: 跑消息链路测试**
Run:
```bash
npx tsx --test tests/master-agent-message-queue.test.ts
```
Expected:
- PASS`master-agent` 显式选 Hermes 时会通过 Hermes 返回
---
### Task 5: 全量验证与文档收口
**Files:**
- Modify: `docs/architecture/current_runtime_and_deploy_status_cn.md`
- Modify: `docs/architecture/api_and_service_inventory_cn.md`
- [ ] **Step 1: 更新运行时文档**
补充:
- `HermesBackendAdapter` 已最小接入
- 默认关闭
- 当前只对 `master-agent` 开放
- [ ] **Step 2: 运行相关测试**
Run:
```bash
npx tsx --test tests/hermes-backend-config.test.ts tests/hermes-runner.test.ts tests/hermes-backend.test.ts tests/execution-backend-selector.test.ts tests/master-agent-chat-controls.test.ts tests/master-agent-message-queue.test.ts
```
Expected:
- PASS
- [ ] **Step 3: 运行基础验证**
Run:
```bash
npm run build
npm run lint
```
Expected:
- `build` PASS
- `lint` 若失败,只能是仓库已知外来大文件噪音,不能是本批新增文件
- [ ] **Step 4: 提交**
```bash
git add docs/superpowers/specs/2026-04-14-hermes-backend-mvp-design.md \
docs/superpowers/plans/2026-04-14-hermes-backend-mvp.md \
src/lib/execution/backends/hermes-config.ts \
src/lib/execution/backends/hermes-runner.ts \
src/lib/execution/backends/hermes-backend.ts \
src/lib/execution/backend-selector.ts \
src/lib/boss-data.ts \
src/lib/boss-master-agent.ts \
src/app/api/v1/projects/[projectId]/agent-controls/route.ts \
src/app/api/v1/projects/[projectId]/prompt-profile/route.ts \
src/app/me/master-agent/page.tsx \
src/components/master-agent-prompt-memory-client.tsx \
scripts/hermes-runtime-smoke.mjs \
tests/hermes-backend-config.test.ts \
tests/hermes-runner.test.ts \
tests/hermes-backend.test.ts \
tests/execution-backend-selector.test.ts \
tests/master-agent-chat-controls.test.ts \
tests/master-agent-message-queue.test.ts \
docs/architecture/current_runtime_and_deploy_status_cn.md \
docs/architecture/api_and_service_inventory_cn.md
git commit -m "feat: add hermes runtime backend for master agent"
```
---
## Self-Review
- 这份计划只覆盖 `master-agent`没有把群聊编排、Android 独立配置页和 Hermes session 持久化一起卷进来
- 所有代码改动都围绕现有 `claw-runtime` 接入形态做最小差异实现
- 第一批验收点是“能选、能跑、能回退”,不是“把 Hermes 全部接满”