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 全部接满”

View File

@@ -0,0 +1,36 @@
# Android chat status row spec
## Goal
Surface `conversationTasks` and `executionWarnings` as a single compact status row under each Android chat bubble so owners can see backend work without stacking multiple cards, while keeping realtime patches minimal.
## Motivation
- The current Android chat preview renders separate warning cards below every message and keeps an expensive list of `executionWarnings` separately, which duplicates the tap area and height of the chat list.
- The Web page already summarizes tasks and warnings inline: we should match that on Android while keeping real-time patches restrictive, only rejiggering views for the affected message.
- Requirements from the user: group warnings per message, deduplicate statuses, update only affected message on realtime patches, no web/backend changes.
## Architecture
1. Extend `BossUi.buildMessageBubble` (or its wrapper) to accept a reusable compact status row view that can show a grouped warning count and task status.
2. When building a message view in `ProjectDetailActivity.buildMessageView`, gather all conversation task summaries and execution warnings that match the message ID. Deduplicate them by warning ID or Task ID and render them inside the status row.
3. Create helper methods to compute a `StatusRowView` (a `LinearLayout`) that displays:
- If there is an active `conversationTask`, show a row with the backend status label and session/task info.
- If there are warnings, show badge summaries with title and summary text but limit to one line (maybe ellipsized) and collapse duplicates by grouping warnings that share the same title+summary pair.
4. `buildMessageView` will add the status row view directly under the existing bubble but before any other attachments.
5. The realtime warning patch logic already replaces a specific `messageId` view; ensure it reconstructs the same minimal status row and only rerenders when the status content changes. To do that, we may need to compute a canonical string for the combined task/warnings and store/compare to avoid redundant replacements.
## Implementation details
- Introduce new helper methods in `ProjectDetailActivity`:
- `private LinearLayout buildStatusRow(JSONObject message, List<ConversationTaskSummary> tasks, JSONArray warnings)`
- `private boolean hasStatusChangesForMessage(...)` to allow realtime patch to compare old vs new statuses without rerender unless necessary.
- `BossUi` may need a new method such as `public static LinearLayout buildMessageStatusRow(Context context, String label, String detail, int tintColor)` to standardize the UI.
- Update `ProjectDetailActivity.appendContent(buildMessageView(message))` loops to clear prior warning cards and add the new status row once.
- Keep logic around `findExecutionWarningForMessage` but adjust to return grouped data instead of each warning separately.
- Update `currentRenderedProjectPayload` handling to consider the grouped warning/task text, ensuring `hasSameExecutionWarningForMessage` returns `true` when summaries and counts match.
## Testing approach (TDD)
1. Add a new or expand existing Android tests that read `ProjectDetailActivity.java` source to assert the presence of status row construction, grouped warnings, and realtime patch logic (e.g., `tests/android-chat-incremental-realtime-append.test.ts` and `tests/android-chat-local-realtime-patch.test.ts`).
2. Write a failing test first that expects a new helper like `buildMessageStatusRow` or `getStatusTextForMessage` to exist and to be used under each message.
3. Update tests referencing warning cards to expect the new inline status row and ensure patch logic still references the helper to rerender targeted messages only when necessary.
4. Manually run `npm test android-chat-incremental-realtime-append.test.ts` and `npm test android-chat-local-realtime-patch.test.ts` after implementing.
## Validation
- After receiving user approval on this spec, proceed with the implementation plan using TDD. Use test file names to focus runs, and keep the Android changes confined to `ProjectDetailActivity.java`, `BossUi.java`, and the corresponding tests.

View File

@@ -0,0 +1,271 @@
# Boss `HermesBackendAdapter` 最小接入设计
## 1. 背景
Boss 现在已经有一层稳定的执行底座:
- `ExecutionBackend`
- `ExecutionBackendSelector`
- `PromptAssembler`
- `PermissionPolicy`
- `RemoteRuntimeAdapter`
并且已经接过两个外部项目:
- `ClawBackendAdapter` 负责单次执行候选
- `OmxTeamBackendAdapter` 负责编排候选
`hermes-agent` 的最新上游形态更像“重型 agent runner”而不是 Boss 的产品层替代物。它的价值主要集中在:
- 成熟的单次 agent loop
- CLI / Gateway / ACP 多入口
- 丰富的 toolset 体系
- 内建 skills / memory / session / search / delegation
结论不是“把 Hermes 整体搬进 Boss”而是把它当成新的**执行后端候选**接进 Boss 现有底座。
---
## 2. 第一批目标
第一批只做一件事:
> 在不改变 Boss 当前生产主链默认行为的前提下,为 `master-agent` 新增一个默认关闭、可显式启用的 `hermes-runtime`。
用户能在 Boss 现有的主 Agent 对话控制里选择 `Hermes Runtime`,然后让当前 `master-agent` 的回复通过 Hermes CLI 完成。
这批做完后Boss 获得的是:
- 一个新的可选执行后端
- 一个可继续升级的 Hermes 适配点
- 对现有 `claw-runtime` / API / Master Codex Node 主链零破坏
---
## 3. 明确不做
这一批明确不做:
- 不把 Hermes 的 gateway、Telegram、Discord、Slack、WhatsApp、Signal 接进 Boss
- 不把 Hermes 的 Honcho memory 直接并入 Boss 的 `threadStatusDocuments / threadProgressEvents`
- 不让 Boss 前台直接理解 Hermes 的 sessions、slash commands、toolsets 内部结构
- 不接 Hermes 的多平台消息收发
- 不接 Hermes 的 cron / ACP / editor integration
- 不改 Boss 群聊编排链路
- 不把 Hermes 当成新的 OrchestrationBackend
这一批的定位非常明确:**只加一个执行后端,不加一个新产品子系统。**
---
## 4. 为什么 Hermes 值得接
### 4.1 对主 Agent 的意义
对 Boss 的主 Agent 来说Hermes 的参考价值主要有三层:
1. **成熟的一次性 agent loop**
- `hermes chat -q ... -Q` 已经提供了可脚本化的单次非交互执行入口。
- 这正好适合 Boss 当前 `ExecutionBackend` 的“单次请求 -> 单次结果”契约。
2. **比 Claw 更完整的 agent runtime**
- Hermes 不只是命令封装,而是完整的 agent runner、tool registry、toolsets、skills、memory、delegation 体系。
- 这意味着它对复杂任务的“自己调工具完成”的能力更强,适合作为 Boss 主 Agent 的增强执行候选。
3. **未来跨端能力的扩展面更大**
- Hermes 天然有 CLI / Gateway / ACP 三个入口。
- 这对 Boss 未来做“同一 agent 内核,挂不同入口”很有参考价值,但第一批先不展开。
### 4.2 对 Boss 整体业务流程的意义
Hermes 对 Boss 的真正价值不在 UI而在**执行层的替换与对照实验**
- 同一条 Boss 产品链
- 同一组项目、线程、审批、导入、群聊数据
- 不同执行后端并行存在
这样 Boss 可以把“产品层稳定”与“执行层可替换”真正做实。
---
## 5. 第一批接入方案
### 5.1 接入位置
Hermes 第一批接在:
- `src/lib/execution/backends/`
- `ExecutionBackendSelector`
- `master-agent` 对话控制
不接:
- `OrchestrationBackend`
- `local-agent` dispatch_execution
- Android 独立配置页
### 5.2 运行方式
Boss 不直接 import Hermes Python 代码,也不把 Hermes vendoring 进仓库。
Boss 通过外部命令调用 Hermes
```text
<configured command> <configured prefix args> chat -q "<executionPrompt>" -Q --source tool
```
按需追加:
- `-m <model>`
- `-t <toolsets>`
- `-s <skills>`
这样做的原因:
- 上游升级成本最低
- Boss 与 Hermes 保持进程边界
- 可以像 `claw-runtime` 一样通过命令 / workdir / args 做显式配置
- 出问题时可直接回退,不污染主链
### 5.3 输入输出契约
Boss -> Hermes
- `executionPrompt`
- `modelOverride`
- `reasoningEffortOverride`(第一批只透传给 Boss 自身记录,不强行映射到 Hermes CLI 参数)
- 可选 `toolsets`
- 可选 `skills`
Hermes -> Boss
- `stdout` 主体内容作为最终回复
- quiet mode 末尾的 `session_id: ...` 只做解析,不写回会话正文
如果 Hermes 非零退出、超时、输出为空或结构不可解析,统一转成:
- `ExecutionImmediateFailedResult`
---
## 6. 配置设计
新增环境变量:
- `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`
设计约束:
- 默认关闭
- `enabled=true` 时若未显式设置 `BOSS_HERMES_COMMAND`,默认尝试 `hermes`
- 可执行入口不存在、工作目录不存在、前置脚本不存在时,前台不允许选择
---
## 7. Boss 内部改动点
### 7.1 新增文件
- `src/lib/execution/backends/hermes-config.ts`
- `src/lib/execution/backends/hermes-runner.ts`
- `src/lib/execution/backends/hermes-backend.ts`
- `scripts/hermes-runtime-smoke.mjs`
### 7.2 修改文件
- `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`
### 7.3 测试
新增或扩展:
- `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`
---
## 8. 关键取舍
### 8.1 第一批不做 session 级复用
Hermes quiet mode 会回 `session_id`,但 Boss 第一批不把它纳入正式状态模型。
原因:
- Boss 现有 `ExecutionImmediateResult` 没有 session 归档职责
- 当前目标是先把“后端切换可用”做通
- 先引入 session 绑定会把 `thread/session` 关联、恢复、清理都一起带进来,范围会失控
第一批策略:
- 解析但不持久化 `session_id`
- 先跑通 stateless one-shot backend
### 8.2 第一批不把 Boss PermissionPolicy 动态映射成 Hermes toolsets
Hermes 的 toolsets 很强,但 Boss 现在没有现成的“工具级权限 -> Hermes CLI 参数”双向映射层。
第一批策略:
- 只支持静态环境变量指定 `toolsets` / `skills`
- Boss 自己仍保留顶层产品审批与后端选择权
这样虽然不够极致,但风险最小。
### 8.3 第一批只开放给 `master-agent`
这是刻意收口,不是能力缺陷。
原因:
- 当前 Boss 的后端 override UI 只在主 Agent 对话控制里成熟
- `dispatch_execution` 牵涉群聊编排与设备执行链,接 Hermes 会把范围扩大到第二批
- 先让主 Agent 对话用起来,收益最大、回归面最小
---
## 9. 验收标准
满足以下条件才算第一批完成:
1. 未启用 `BOSS_HERMES_*`Boss 行为与当前完全一致
2. 启用且配置正确后,`master-agent` 对话控制中可选择 `Hermes Runtime`
3. 选择 `Hermes Runtime` 后,主 Agent 单次回复能通过 Hermes CLI 返回结果
4. Hermes 不可用时,保存接口会拒绝选择,并返回明确原因
5. 历史保存了 `hermes-runtime` 但当前不可用时,运行时会自动回退到默认后端,并给出人类可读说明
6. `npm run build`
7. `npm run lint`(当前需排除仓库外来大文件噪音后)
8. 相关测试通过
---
## 10. 第二批预留方向
第一批完成后,再考虑第二批:
- Hermes session 级复用与 Boss 项目线程关联
- Boss 权限策略到 Hermes toolsets 的映射
- `thread_reply` 正式挂接
- Android 主 Agent 设置页显示 Hermes 可用性
- `dispatch_execution` 是否引入 Hermes 作为编排前执行候选
第一批的成功标准不是“把 Hermes 接满”,而是:
> 让 Boss 在现有产品层完全不变的情况下,稳定多出一个可选择、可回退、可继续升级的重型 agent 执行后端。

View File

@@ -0,0 +1,101 @@
# 主 Agent Fast Path 设计
更新时间:`2026-04-16`
## 1. 背景
主 Agent 当前同时承担两类请求:
- 需要深度理解、规划、协调的慢路径问题
- 只需要读取本地状态、快速执行配置变更的快路径问题
在原实现里,只有少量模型切换命令会本地直答。大量高频问题,例如“你现在是什么大模型”“当前后端是什么”,仍会落入主推理链,导致:
- 回复延迟明显偏高
- 消耗不必要的 token
- 用户需要记忆更机械的命令句式
## 2. 设计目标
- 把“状态查询 / 配置操作 / 枚举类问题”从主推理链中剥离出来
- 对高频确定性问题提供本地直答,不进入异步队列
- 保持自然语言容错,不要求用户输入完全标准化命令
- 为后续继续扩展快路径意图提供统一入口
## 3. 方案
### 3.1 Fast Path Router
`src/lib/boss-master-agent.ts` 中新增主 Agent 快路径路由层:
- 统一先构造 `MasterAgentFastIntentContext`
- 上下文内聚合:
- 当前登录用户作用域下的 `agentControls`
- 可见模型列表
- 可用模型列表
- 当前聊天意图的实际模型策略
- 深度任务意图的实际模型策略
- 当前 runtime 主控来源
- `replyToMasterAgentUserMessage()` 在进入主链前先尝试 `tryHandleMasterAgentFastIntent()`
### 3.2 第一批接入意图
- 模型列表查询
- 例:“有哪些模型可以用”
- 模型切换
- 例:“把快模型切到 gpt5.4mini”
- 当前模型状态查询
- 例:“你现在是什么大模型”
- 例:“当前主模型是什么”
- 例:“快模型是什么”
- 例:“强模型是什么”
- 当前后端状态查询
- 例:“当前后端是什么”
### 3.3 自然语言归一化
模型名解析新增轻量归一化:
- 忽略 `- / _ / 空格 / .`
- 兼容 `gpt5.4``gpt 5.4``gpt_5_4`
- 仍然会回落到系统当前可选模型列表做映射
## 4. 展示规则
主 Agent 快路径回复的发送者名称改成:
- `主Agent·<当前模型名>`
Android 主 Agent 会话页顶部标题同步显示:
- `主Agent·<当前模型名>`
如果当前拿不到显式模型,则退回:
- `主Agent`
## 5. 当前收益
- “查状态 / 查配置 / 改模型”这一类问题能直接秒回
- 主 Agent 不再因为低价值查询进入慢路径
- 用户不用死记标准句式
- 后续扩展更多快路径意图时,只需要继续往 router 中追加 handler
## 6. 后续扩展建议
下一批适合继续接入 Fast Path 的问题:
- 当前绑定设备 / 在线设备查询
- 当前会话 / 当前线程运行状态查询
- GUI / CLI 默认执行模式查询
- 当前接管开关状态查询
- 最近活跃项目 / 最近活跃线程查询
## 7. 验证基线
本次落地至少要求以下验证通过:
- `npx tsx --test tests/master-agent-message-queue.test.ts tests/master-agent-chat-controls.test.ts`
- `npm run build`
- `./gradlew :app:compileDebugJavaWithJavac :app:assembleDebug`
- 真机安装并验证主 Agent 名称与模型查询行为