Integrate master agent runtime orchestration updates
This commit is contained in:
@@ -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.
|
||||
318
docs/superpowers/plans/2026-04-14-hermes-backend-mvp.md
Normal file
318
docs/superpowers/plans/2026-04-14-hermes-backend-mvp.md
Normal 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 全部接满”
|
||||
Reference in New Issue
Block a user