docs: add main agent runtime flow spec
This commit is contained in:
480
docs/superpowers/plans/2026-03-29-main-agent-runtime-flow.md
Normal file
480
docs/superpowers/plans/2026-03-29-main-agent-runtime-flow.md
Normal file
@@ -0,0 +1,480 @@
|
||||
# Main Agent Runtime Flow 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:** Add the first production-ready main-agent run layer so StoryForge can create confirmable runs, display runtime progress in the floating OneLiner window, and unify “handoff to main agent” actions.
|
||||
|
||||
**Architecture:** Keep existing `OneLiner session/message` as the conversation layer, add `agent_runs` plus `agent_run_events` inside `oneliner_features.py` as a separate runtime layer, then extend the existing floating OneLiner UI to render a run header area above the chat stream and wire selected page actions into run creation.
|
||||
|
||||
**Tech Stack:** FastAPI, SQLite, existing StoryForge Web V4 vanilla JS, Node test runner, Python unittest
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Save docs for the runtime flow
|
||||
|
||||
**Files:**
|
||||
- Create: `docs/superpowers/specs/2026-03-29-main-agent-runtime-flow-design.md`
|
||||
- Create: `docs/superpowers/plans/2026-03-29-main-agent-runtime-flow.md`
|
||||
|
||||
- [ ] **Step 1: Save the approved design**
|
||||
|
||||
Write the runtime flow design into the spec file above.
|
||||
|
||||
- [ ] **Step 2: Save this implementation plan**
|
||||
|
||||
Write this plan file and keep it committed with the implementation.
|
||||
|
||||
- [ ] **Step 3: Commit docs checkpoint**
|
||||
|
||||
```bash
|
||||
git add docs/superpowers/specs/2026-03-29-main-agent-runtime-flow-design.md docs/superpowers/plans/2026-03-29-main-agent-runtime-flow.md
|
||||
git commit -m "docs: add main agent runtime flow spec"
|
||||
```
|
||||
|
||||
### Task 2: Add failing backend tests for the run layer
|
||||
|
||||
**Files:**
|
||||
- Modify: `tests/test_main_agent_governance.py`
|
||||
|
||||
- [ ] **Step 1: Write the failing test for run creation**
|
||||
|
||||
Add a test that creates a run through `POST /v2/oneliner/runs` and asserts:
|
||||
|
||||
```python
|
||||
response = self.client.post(
|
||||
"/v2/oneliner/runs",
|
||||
headers=self.ctx["member_headers"],
|
||||
json={
|
||||
"project_id": self.ctx["project_id"],
|
||||
"source_screen": "dashboard",
|
||||
"source_action_key": "homepage-primary-action",
|
||||
"title": "跟进重点账号",
|
||||
"summary": "先由主 Agent 评估优先级",
|
||||
"intent_key": "track_account",
|
||||
"platform": "douyin",
|
||||
"platform_scope": "single_platform",
|
||||
"plan_request": {
|
||||
"goal": "跟进重点账号",
|
||||
"steps": ["读取当前项目上下文", "检查重点账号变化", "决定下一步"]
|
||||
},
|
||||
},
|
||||
)
|
||||
payload = response.json()
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
self.assertEqual(payload["run_status"], "needs_confirmation")
|
||||
self.assertEqual(payload["source_screen"], "dashboard")
|
||||
self.assertEqual(payload["platform"], "douyin")
|
||||
self.assertTrue(payload["plan"]["steps"])
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Write the failing test for confirm flow**
|
||||
|
||||
Add a test that confirms a run and asserts:
|
||||
|
||||
```python
|
||||
confirm = self.client.post(
|
||||
f"/v2/oneliner/runs/{run_id}/confirm",
|
||||
headers=self.ctx["member_headers"],
|
||||
json={"reason": "user confirmed"},
|
||||
)
|
||||
payload = confirm.json()
|
||||
self.assertEqual(confirm.status_code, 200, confirm.text)
|
||||
self.assertIn(payload["run_status"], {"queued", "running"})
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Write the failing test for projectless governance snapshot**
|
||||
|
||||
Add a test that creates a run for an approved user with no project id and verifies no default project is auto-created while the run still stores a blank governance snapshot.
|
||||
|
||||
- [ ] **Step 4: Run the backend tests and confirm they fail**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
python3 -m unittest tests.test_main_agent_governance -v
|
||||
```
|
||||
|
||||
Expected: FAIL because the run tables and endpoints do not exist yet.
|
||||
|
||||
### Task 3: Add backend run schema and payload helpers
|
||||
|
||||
**Files:**
|
||||
- Modify: `collector-service/app/oneliner_features.py`
|
||||
|
||||
- [ ] **Step 1: Add the new tables**
|
||||
|
||||
Add schema creation for:
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS agent_runs (
|
||||
id TEXT PRIMARY KEY,
|
||||
session_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
project_id TEXT NOT NULL DEFAULT '',
|
||||
source_type TEXT NOT NULL,
|
||||
source_screen TEXT NOT NULL,
|
||||
source_action_key TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
summary TEXT NOT NULL DEFAULT '',
|
||||
intent_key TEXT NOT NULL DEFAULT '',
|
||||
platform TEXT NOT NULL DEFAULT '',
|
||||
platform_scope TEXT NOT NULL DEFAULT 'single_platform',
|
||||
delivery_mode TEXT NOT NULL DEFAULT 'hybrid',
|
||||
run_status TEXT NOT NULL,
|
||||
scheduling_mode TEXT NOT NULL DEFAULT 'queued',
|
||||
active_executor_key TEXT NOT NULL DEFAULT '',
|
||||
plan_json TEXT NOT NULL DEFAULT '{}',
|
||||
result_json TEXT NOT NULL DEFAULT '{}',
|
||||
status_summary TEXT NOT NULL DEFAULT '',
|
||||
needs_user_input INTEGER NOT NULL DEFAULT 0,
|
||||
blocked_reason TEXT NOT NULL DEFAULT '',
|
||||
active_admin_override_notice_json TEXT NOT NULL DEFAULT '{}',
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
started_at TEXT NOT NULL DEFAULT '',
|
||||
finished_at TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS agent_run_events (
|
||||
id TEXT PRIMARY KEY,
|
||||
run_id TEXT NOT NULL,
|
||||
event_type TEXT NOT NULL,
|
||||
summary TEXT NOT NULL DEFAULT '',
|
||||
details_json TEXT NOT NULL DEFAULT '{}',
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add helper payload builders**
|
||||
|
||||
Implement focused helpers for:
|
||||
|
||||
```python
|
||||
def _agent_run_payload(row: dict[str, Any]) -> dict[str, Any]:
|
||||
...
|
||||
|
||||
def _agent_run_event_payload(row: dict[str, Any]) -> dict[str, Any]:
|
||||
...
|
||||
|
||||
def _list_agent_run_events(run_id: str) -> list[dict[str, Any]]:
|
||||
...
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Add governance snapshot helper**
|
||||
|
||||
Add a helper that returns:
|
||||
|
||||
```python
|
||||
{
|
||||
"project_id": project_id,
|
||||
"platform": platform,
|
||||
"effective_policy": ...,
|
||||
"layers": ...,
|
||||
"active_admin_override_notice": ...,
|
||||
}
|
||||
```
|
||||
|
||||
for use at run creation time.
|
||||
|
||||
- [ ] **Step 4: Run backend tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
python3 -m unittest tests.test_main_agent_governance -v
|
||||
```
|
||||
|
||||
Expected: tests still fail, but schema-related failures move forward.
|
||||
|
||||
### Task 4: Add backend run endpoints and state transitions
|
||||
|
||||
**Files:**
|
||||
- Modify: `collector-service/app/oneliner_features.py`
|
||||
- Test: `tests/test_main_agent_governance.py`
|
||||
|
||||
- [ ] **Step 1: Add request models**
|
||||
|
||||
Add minimal request models for:
|
||||
|
||||
```python
|
||||
class AgentRunCreateRequest(BaseModel):
|
||||
project_id: str = ""
|
||||
source_screen: str
|
||||
source_action_key: str
|
||||
title: str
|
||||
summary: str = ""
|
||||
intent_key: str = ""
|
||||
platform: str = ""
|
||||
platform_scope: str = "single_platform"
|
||||
plan_request: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
class AgentRunConfirmRequest(BaseModel):
|
||||
reason: str = ""
|
||||
|
||||
class AgentRunCancelRequest(BaseModel):
|
||||
reason: str = ""
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add `POST /v2/oneliner/runs`**
|
||||
|
||||
Create a run that:
|
||||
- resolves or creates the current session via the existing OneLiner session helper
|
||||
- stores `run_status = "needs_confirmation"`
|
||||
- snapshots current governance
|
||||
- logs `run.created`
|
||||
|
||||
- [ ] **Step 3: Add read endpoints**
|
||||
|
||||
Implement:
|
||||
|
||||
```python
|
||||
@app.get("/v2/oneliner/runs")
|
||||
@app.get("/v2/oneliner/runs/{run_id}")
|
||||
@app.get("/v2/oneliner/runs/{run_id}/events")
|
||||
```
|
||||
|
||||
The list endpoint should return the latest 20 runs for the current user and project, newest first.
|
||||
|
||||
- [ ] **Step 4: Add confirm and cancel endpoints**
|
||||
|
||||
Implement:
|
||||
|
||||
```python
|
||||
@app.post("/v2/oneliner/runs/{run_id}/confirm")
|
||||
@app.post("/v2/oneliner/runs/{run_id}/cancel")
|
||||
```
|
||||
|
||||
Confirm should:
|
||||
- move `needs_confirmation -> queued`
|
||||
- set `status_summary = "等待主 Agent 执行"` or `"主 Agent 正在执行"`
|
||||
- create `run.confirmed`
|
||||
- for the first version, immediately promote to `running` when no other active run exists for that user/project
|
||||
|
||||
Cancel should:
|
||||
- move `needs_confirmation -> cancelled` or `queued -> cancelled`
|
||||
- create `run.cancelled`
|
||||
|
||||
- [ ] **Step 5: Add one backend test for event sequencing**
|
||||
|
||||
Assert that creation + confirm writes at least:
|
||||
- `run.created`
|
||||
- `run.confirmed`
|
||||
- one of `run.queued` / `run.started`
|
||||
|
||||
- [ ] **Step 6: Re-run backend tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
python3 -m unittest tests.test_main_agent_governance -v
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
### Task 5: Add failing frontend tests for the floating runtime header
|
||||
|
||||
**Files:**
|
||||
- Modify: `web/storyforge-web-v4/tests/workbench-pages.test.mjs`
|
||||
|
||||
- [ ] **Step 1: Add a failing test for the run header**
|
||||
|
||||
Assert the OneLiner UI now includes a dedicated runtime header zone:
|
||||
|
||||
```javascript
|
||||
const source = extractBetween(APP, "function ensureOneLinerUi()", "function renderOneLinerSessionTabs()");
|
||||
assert.match(source, /data-role="oneliner-runs"/);
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add a failing test for the run list loader**
|
||||
|
||||
Assert the app state loader hits the new endpoints:
|
||||
|
||||
```javascript
|
||||
const source = extractBetween(APP, "async function loadAgentControlSurfaces(projectId = \"\")", "async function loadOneLinerMessages(sessionId)");
|
||||
assert.match(source, /\/v2\/oneliner\/runs/);
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Add a failing test for the handoff entrypoint**
|
||||
|
||||
Assert the click handler routes a main-agent handoff to a dedicated action instead of only opening the chat:
|
||||
|
||||
```javascript
|
||||
const actions = extractBetween(APP, "document.addEventListener(\"click\", async (event) => {", "document.addEventListener(\"submit\", async (event) => {");
|
||||
assert.match(actions, /handoff-to-main-agent/);
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Run the frontend tests and confirm failure**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
node --test web/storyforge-web-v4/tests/workbench-pages.test.mjs
|
||||
```
|
||||
|
||||
Expected: FAIL on missing run UI and handoff actions.
|
||||
|
||||
### Task 6: Extend app state and OneLiner UI with the runtime header
|
||||
|
||||
**Files:**
|
||||
- Modify: `web/storyforge-web-v4/assets/app.js`
|
||||
- Modify: `web/storyforge-web-v4/assets/styles.css`
|
||||
- Test: `web/storyforge-web-v4/tests/workbench-pages.test.mjs`
|
||||
|
||||
- [ ] **Step 1: Extend app state**
|
||||
|
||||
Add state fields:
|
||||
|
||||
```javascript
|
||||
onelinerRuns: [],
|
||||
selectedOnelinerRunId: "",
|
||||
onelinerRunEvents: [],
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Render the runtime header area**
|
||||
|
||||
Inside `ensureOneLinerUi()`, add a dedicated block:
|
||||
|
||||
```html
|
||||
<div class="oneliner-runs" data-role="oneliner-runs"></div>
|
||||
```
|
||||
|
||||
above the message list.
|
||||
|
||||
- [ ] **Step 3: Add render helpers**
|
||||
|
||||
Implement focused helpers:
|
||||
|
||||
```javascript
|
||||
function pickPrimaryRun(runs) { ... }
|
||||
function renderOneLinerRunSummary(primaryRun, runs) { ... }
|
||||
function renderOneLinerRunEventChips(primaryRunEvents) { ... }
|
||||
```
|
||||
|
||||
Behavior:
|
||||
- prefer `needs_confirmation`
|
||||
- then `blocked`
|
||||
- then `running`
|
||||
- then latest `done`
|
||||
|
||||
- [ ] **Step 4: Add CSS for the runtime header**
|
||||
|
||||
Add styles for:
|
||||
- `.oneliner-runs`
|
||||
- `.oneliner-run-card`
|
||||
- `.oneliner-run-title`
|
||||
- `.oneliner-run-summary`
|
||||
|
||||
Keep the current OneLiner visual language. Do not redesign the shell.
|
||||
|
||||
- [ ] **Step 5: Re-run frontend tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
node --test web/storyforge-web-v4/tests/workbench-pages.test.mjs
|
||||
node --check web/storyforge-web-v4/assets/app.js
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
### Task 7: Wire run loading, confirmation, and page handoff
|
||||
|
||||
**Files:**
|
||||
- Modify: `web/storyforge-web-v4/assets/app.js`
|
||||
- Test: `web/storyforge-web-v4/tests/workbench-pages.test.mjs`
|
||||
|
||||
- [ ] **Step 1: Load runs into app state**
|
||||
|
||||
Extend `loadAgentControlSurfaces(projectId)` to fetch:
|
||||
|
||||
```javascript
|
||||
storyforgeFetch(`/v2/oneliner/runs?project_id=${encodeURIComponent(normalizedProjectId)}`)
|
||||
```
|
||||
|
||||
and store it in `appState.onelinerRuns`.
|
||||
|
||||
- [ ] **Step 2: Add API helpers**
|
||||
|
||||
Implement:
|
||||
|
||||
```javascript
|
||||
async function createMainAgentRun(input) { ... }
|
||||
async function confirmMainAgentRun(runId, reason = "") { ... }
|
||||
async function cancelMainAgentRun(runId, reason = "") { ... }
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Add the dedicated handoff action**
|
||||
|
||||
In the click handler, add:
|
||||
|
||||
```javascript
|
||||
if (name === "handoff-to-main-agent") {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
This action should:
|
||||
- create a `needs_confirmation` run
|
||||
- refresh run state
|
||||
- open the OneLiner panel
|
||||
|
||||
- [ ] **Step 4: Replace the first batch of entrypoints**
|
||||
|
||||
Update these buttons to use `handoff-to-main-agent`:
|
||||
- homepage primary action handoff
|
||||
- homepage secondary action handoff
|
||||
- strategy page `交给 OneLiner 调整`
|
||||
- agent governance handoff tags
|
||||
|
||||
- [ ] **Step 5: Add confirmation controls in the run header**
|
||||
|
||||
For `needs_confirmation` runs, show:
|
||||
- `确认执行`
|
||||
- `取消`
|
||||
|
||||
For `running/queued/blocked/done`, show compact status only.
|
||||
|
||||
- [ ] **Step 6: Re-run frontend tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
node --test web/storyforge-web-v4/tests/workbench-pages.test.mjs
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
### Task 8: Full verification, deploy, and publish
|
||||
|
||||
**Files:**
|
||||
- Modify only files already touched above
|
||||
|
||||
- [ ] **Step 1: Run full verification**
|
||||
|
||||
```bash
|
||||
python3 -m unittest tests.test_main_agent_governance tests.test_platform_contracts tests.test_production_baseline -v
|
||||
node --test web/storyforge-web-v4/tests/dashboard-home.test.mjs web/storyforge-web-v4/tests/workbench-pages.test.mjs
|
||||
python3 -m compileall collector-service/app tests
|
||||
git diff --check
|
||||
bash scripts/check_repo_baseline.sh
|
||||
```
|
||||
|
||||
Expected: all pass.
|
||||
|
||||
- [ ] **Step 2: Deploy to NAS**
|
||||
|
||||
```bash
|
||||
STORYFORGE_FNOS_COLLECTOR_DEPLOY_MODE=remote_build bash /Users/kris/code/StoryForge-gitea/scripts/deploy_fnos_storyforge_collector.sh
|
||||
bash /Users/kris/code/StoryForge-gitea/scripts/deploy_fnos_storyforge_web.sh
|
||||
bash /Users/kris/code/StoryForge-gitea/scripts/smoke_fnos_storyforge_lan.sh
|
||||
```
|
||||
|
||||
Expected: web, collector, cutvideo tunnel, compat smoke all pass.
|
||||
|
||||
- [ ] **Step 3: Commit and push**
|
||||
|
||||
```bash
|
||||
git add collector-service/app/oneliner_features.py tests/test_main_agent_governance.py web/storyforge-web-v4/assets/app.js web/storyforge-web-v4/assets/styles.css web/storyforge-web-v4/tests/workbench-pages.test.mjs docs/superpowers/specs/2026-03-29-main-agent-runtime-flow-design.md docs/superpowers/plans/2026-03-29-main-agent-runtime-flow.md
|
||||
git commit -m "feat: add main agent runtime flow"
|
||||
git push gitea codex/storyforge-live-orchestrator-sync-20260323
|
||||
```
|
||||
@@ -0,0 +1,354 @@
|
||||
# StoryForge 主 Agent 运行层与悬浮工作流设计
|
||||
|
||||
- 日期:2026-03-29
|
||||
- 状态:已确认,直接进入实现
|
||||
- 范围:`collector-service`、`web/storyforge-web-v4`
|
||||
|
||||
## 1. 背景
|
||||
|
||||
当前仓库已经有两类能力:
|
||||
|
||||
- `OneLiner session/message`
|
||||
- 承担用户与主 Agent 的对话历史
|
||||
- `execution_card`
|
||||
- 能在单条消息里附带执行建议、下一步、证据和管理员覆盖提示
|
||||
|
||||
但这些能力还不足以支撑“主 Agent 是全站统一工作入口”的产品目标。当前缺口主要有:
|
||||
|
||||
- 页面里的“交给主 Agent”还没有统一承接链路。
|
||||
- 用户确认执行、后台运行、阻塞等待、近期进度都还没有独立的运行单元。
|
||||
- 右下角悬浮主 Agent 目前还是“聊天面板”,还不是“聊天 + 任务运行中心”。
|
||||
- 多任务并行/排队、最小化后状态感知、最近待确认任务都没有统一模型。
|
||||
|
||||
如果继续把执行请求直接塞进聊天消息,会导致:
|
||||
|
||||
- 聊天和任务状态纠缠
|
||||
- 运行中/待确认/阻塞/完成难以跟踪
|
||||
- 页面动作无法统一接入
|
||||
- 后续审计、商业化和管理员治理会越来越难做
|
||||
|
||||
## 2. 目标
|
||||
|
||||
- 在现有 `OneLiner session/message` 之外,新增独立的 `agent run` 运行层。
|
||||
- 所有页面里的“交给主 Agent”统一先创建一个 `needs_confirmation` 的 run。
|
||||
- 右下角悬浮主 Agent 继续作为唯一入口,但内部升级为:
|
||||
- 顶部执行区
|
||||
- 下方聊天流
|
||||
- 用户确认后,run 才进入真正执行。
|
||||
- 主 Agent 自己判断 run 是并行还是排队。
|
||||
- 悬浮按钮最小化后仍可看到:
|
||||
- 状态点
|
||||
- 当前任务数
|
||||
- 一行极短状态摘要
|
||||
- 当存在管理员覆盖时,确认卡和运行卡需要显式提示。
|
||||
|
||||
## 3. 非目标
|
||||
|
||||
- 本轮不重做整套视觉风格。
|
||||
- 本轮不把所有前端按钮都改成真正自动化执行。
|
||||
- 本轮不实现复杂图形化编排器。
|
||||
- 本轮不引入新的任务基础设施或消息队列。
|
||||
- 本轮不替换现有 `OneLiner session/message`。
|
||||
|
||||
## 4. 总体方案
|
||||
|
||||
采用“双层结构”:
|
||||
|
||||
1. `OneLiner session/message`
|
||||
- 保留现有聊天历史与自然语言上下文
|
||||
|
||||
2. `agent run`
|
||||
- 新增专门的运行单元
|
||||
- 用于承接:
|
||||
- 页面动作升级为主 Agent 执行
|
||||
- 需要用户确认的执行计划
|
||||
- 后台运行状态
|
||||
- 阻塞等待和恢复
|
||||
- 最近一次执行结果
|
||||
|
||||
这两层通过 `session_id` 关联,但职责不同:
|
||||
|
||||
- `session/message` 负责“说了什么”
|
||||
- `agent run` 负责“当前在做什么”
|
||||
|
||||
## 5. 数据模型
|
||||
|
||||
### 5.1 新表
|
||||
|
||||
新增表:`agent_runs`
|
||||
|
||||
核心字段:
|
||||
|
||||
- `id`
|
||||
- `session_id`
|
||||
- `user_id`
|
||||
- `project_id`
|
||||
- `source_type`
|
||||
- `homepage_action`
|
||||
- `page_action`
|
||||
- `chat_request`
|
||||
- `system_followup`
|
||||
- `source_screen`
|
||||
- `source_action_key`
|
||||
- `title`
|
||||
- `summary`
|
||||
- `intent_key`
|
||||
- `platform`
|
||||
- `platform_scope`
|
||||
- `single_platform`
|
||||
- `all_platforms`
|
||||
- `delivery_mode`
|
||||
- `ui`
|
||||
- `oneliner`
|
||||
- `hybrid`
|
||||
- `run_status`
|
||||
- `needs_confirmation`
|
||||
- `queued`
|
||||
- `running`
|
||||
- `blocked`
|
||||
- `done`
|
||||
- `failed`
|
||||
- `cancelled`
|
||||
- `scheduling_mode`
|
||||
- `parallel`
|
||||
- `queued`
|
||||
- `active_executor_key`
|
||||
- `plan_json`
|
||||
- `result_json`
|
||||
- `status_summary`
|
||||
- `needs_user_input`
|
||||
- `blocked_reason`
|
||||
- `active_admin_override_notice_json`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
- `started_at`
|
||||
- `finished_at`
|
||||
|
||||
### 5.2 事件表
|
||||
|
||||
新增表:`agent_run_events`
|
||||
|
||||
核心字段:
|
||||
|
||||
- `id`
|
||||
- `run_id`
|
||||
- `event_type`
|
||||
- `run.created`
|
||||
- `run.confirmed`
|
||||
- `run.queued`
|
||||
- `run.started`
|
||||
- `run.progress`
|
||||
- `run.blocked`
|
||||
- `run.done`
|
||||
- `run.failed`
|
||||
- `run.cancelled`
|
||||
- `summary`
|
||||
- `details_json`
|
||||
- `created_at`
|
||||
|
||||
### 5.3 运行状态机
|
||||
|
||||
默认状态流转:
|
||||
|
||||
- `needs_confirmation -> queued -> running -> done`
|
||||
|
||||
异常流转:
|
||||
|
||||
- `needs_confirmation -> cancelled`
|
||||
- `running -> blocked`
|
||||
- `blocked -> running`
|
||||
- `running -> failed`
|
||||
- `queued -> cancelled`
|
||||
|
||||
## 6. 运行规则
|
||||
|
||||
### 6.1 页面动作进入主 Agent
|
||||
|
||||
所有页面中的“交给主 Agent”统一调用新入口:
|
||||
|
||||
- `POST /v2/oneliner/runs`
|
||||
|
||||
提交内容至少包含:
|
||||
|
||||
- `project_id`
|
||||
- `source_screen`
|
||||
- `source_action_key`
|
||||
- `title`
|
||||
- `summary`
|
||||
- `platform`
|
||||
- `platform_scope`
|
||||
- `intent_key`
|
||||
- `plan_request`
|
||||
|
||||
后端创建:
|
||||
|
||||
- 一个 `agent run`
|
||||
- 默认 `run_status = needs_confirmation`
|
||||
- 并把当时的:
|
||||
- 有效策略
|
||||
- 执行步骤
|
||||
- 平台 Agent 目标
|
||||
- 管理员覆盖提示
|
||||
写成 `plan_json`
|
||||
|
||||
### 6.2 确认卡
|
||||
|
||||
点击“交给主 Agent”后:
|
||||
|
||||
- 自动打开右下角悬浮窗口
|
||||
- 顶部优先展示最近一次 `needs_confirmation` 的 run
|
||||
|
||||
确认卡默认展示标准信息:
|
||||
|
||||
- 目标
|
||||
- 影响对象
|
||||
- 执行步骤
|
||||
- 会调用哪些平台 Agent
|
||||
- 可能影响什么
|
||||
|
||||
如果存在管理员覆盖,再额外展示一段简短提示:
|
||||
|
||||
- `当前存在管理员覆盖:xxx`
|
||||
|
||||
### 6.3 确认后执行
|
||||
|
||||
确认执行后:
|
||||
|
||||
- run 进入 `queued`
|
||||
- 主 Agent 根据当前运行情况决定:
|
||||
- 并行执行
|
||||
- 还是排队等待
|
||||
|
||||
如果可以直接执行:
|
||||
|
||||
- `queued -> running`
|
||||
|
||||
如果要等其他 run:
|
||||
|
||||
- 保持 `queued`
|
||||
- 更新 `status_summary`
|
||||
|
||||
### 6.4 最小化后的状态
|
||||
|
||||
悬浮按钮最小化时显示:
|
||||
|
||||
- 状态点
|
||||
- 空闲
|
||||
- 需确认
|
||||
- 运行中
|
||||
- 阻塞
|
||||
- 当前任务数
|
||||
- 一行极短状态摘要
|
||||
|
||||
摘要优先级:
|
||||
|
||||
1. 最近待确认任务
|
||||
2. 最近阻塞任务
|
||||
3. 当前运行中的任务
|
||||
4. 最近完成任务
|
||||
|
||||
## 7. 前端交互设计
|
||||
|
||||
### 7.1 悬浮窗口布局
|
||||
|
||||
保留现有 `OneLiner` 右下角入口,不新增第二入口。
|
||||
|
||||
窗口内部改成:
|
||||
|
||||
1. 顶部 `run` 区
|
||||
- 待确认卡 / 运行中卡 / 阻塞卡 / 完成卡
|
||||
|
||||
2. 中部聊天流
|
||||
- 保留现有 `session/message`
|
||||
|
||||
3. 底部输入区
|
||||
- 继续支持自然语言对话
|
||||
|
||||
### 7.2 顶部 run 区优先级
|
||||
|
||||
打开窗口后,顶部默认显示:
|
||||
|
||||
1. 最近一次需要用户确认的 run
|
||||
2. 若没有待确认,则显示最近一次阻塞 run
|
||||
3. 若没有阻塞,则显示当前运行中的 run
|
||||
4. 若都没有,则显示最近完成的 run
|
||||
|
||||
### 7.3 页面动作接入
|
||||
|
||||
第一版先接以下入口:
|
||||
|
||||
- 首页主动作中的 `交给主 Agent`
|
||||
- 首页次动作中的 `交给主 Agent`
|
||||
- `我的策略` 页的 `交给 OneLiner 调整`
|
||||
- `Agent` 页与策略治理相关的 `交给主 Agent`
|
||||
|
||||
其他页面先保留现有 `open-oneliner`,后续再逐步切到 run 创建入口。
|
||||
|
||||
## 8. 后端接口
|
||||
|
||||
### 8.1 运行层
|
||||
|
||||
- `POST /v2/oneliner/runs`
|
||||
- 创建一个待确认 run
|
||||
- `GET /v2/oneliner/runs`
|
||||
- 读取当前用户最近 run 列表
|
||||
- `GET /v2/oneliner/runs/{run_id}`
|
||||
- 读取单个 run 详情
|
||||
- `POST /v2/oneliner/runs/{run_id}/confirm`
|
||||
- 用户确认执行
|
||||
- `POST /v2/oneliner/runs/{run_id}/cancel`
|
||||
- 用户取消
|
||||
- `GET /v2/oneliner/runs/{run_id}/events`
|
||||
- 读取运行事件
|
||||
|
||||
### 8.2 会话层保持不变
|
||||
|
||||
保留现有:
|
||||
|
||||
- `POST /v2/oneliner/sessions/{session_id}/messages`
|
||||
- `POST /v2/oneliner/actions/execute`
|
||||
|
||||
第一版由 run 层在确认执行后,内部复用现有 `actions/execute` 或对话处理逻辑。
|
||||
|
||||
## 9. 与治理底座的关系
|
||||
|
||||
`agent run` 创建时会固化:
|
||||
|
||||
- 当前有效策略摘要
|
||||
- 当前叠加层
|
||||
- 当前管理员覆盖提示
|
||||
|
||||
这样可以确保:
|
||||
|
||||
- 用户看到的确认卡可解释
|
||||
- 运行中状态与当时策略一致
|
||||
- 后续审计可以回答“为什么这样执行”
|
||||
|
||||
## 10. 测试
|
||||
|
||||
### 10.1 后端
|
||||
|
||||
- run 创建测试
|
||||
- run 确认流转测试
|
||||
- run 阻塞/完成事件测试
|
||||
- run 创建时固化治理快照测试
|
||||
- run 列表优先级测试
|
||||
|
||||
### 10.2 前端
|
||||
|
||||
- 悬浮窗口包含 run 顶部区
|
||||
- 页面动作会创建待确认 run
|
||||
- 待确认 run 会优先展示
|
||||
- 最小化按钮显示状态点、数量、摘要
|
||||
- 管理员覆盖提示可见
|
||||
|
||||
## 11. 第一版验收标准
|
||||
|
||||
- 用户从首页点“交给主 Agent”,会打开悬浮窗口并看到标准确认卡。
|
||||
- 确认后,顶部 run 区能看到:
|
||||
- 运行状态
|
||||
- 极短状态摘要
|
||||
- 最新进度
|
||||
- 下方聊天流仍然正常工作。
|
||||
- 最小化后,右下角能看到当前任务状态。
|
||||
- 有管理员覆盖时,确认卡和运行卡都会明确提示。
|
||||
Reference in New Issue
Block a user