feat: 接入起卦后端流程并完善积分扣减链路
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
# Divination Run Protocol (Frontend <-> Backend)
|
||||
|
||||
This document defines the structured contract for divination run input, backend hexagram derivation, and run event output.
|
||||
|
||||
Protocol verification status:
|
||||
|
||||
- Backend route source: `backend/src/v1/agent/router.py`
|
||||
- Backend derivation source: `backend/src/core/divination/derivation.py`
|
||||
- Runtime payload schema source: `backend/src/schemas/domain/divination.py`
|
||||
|
||||
## Compatibility strategy
|
||||
|
||||
- Current strategy: additive evolution only.
|
||||
- Existing required fields cannot be removed or renamed without migration notes.
|
||||
- Canonical divination terminology values must remain Chinese.
|
||||
|
||||
## Route overview
|
||||
|
||||
- Submit run: `POST /api/v1/agent/runs`
|
||||
- Stream events: `GET /api/v1/agent/runs/{threadId}/events?runId=...`
|
||||
|
||||
## Run request contract
|
||||
|
||||
`RunAgentInput` uses AG-UI shape. This protocol constrains two sections:
|
||||
|
||||
1) `messages[0].content` (question text)
|
||||
2) `forwardedProps.divinationPayload` (structured divination input)
|
||||
|
||||
### Required request shape
|
||||
|
||||
```json
|
||||
{
|
||||
"threadId": "uuid",
|
||||
"runId": "run_20260403_xxx",
|
||||
"state": {},
|
||||
"messages": [
|
||||
{
|
||||
"id": "msg_run_20260403_xxx_user_0",
|
||||
"role": "user",
|
||||
"content": "我最近换工作是否合适?"
|
||||
}
|
||||
],
|
||||
"tools": [],
|
||||
"context": [],
|
||||
"forwardedProps": {
|
||||
"runtime_mode": "chat",
|
||||
"client_time": {
|
||||
"device_timezone": "Asia/Shanghai",
|
||||
"client_now_iso": "2026-04-03T20:30:00+08:00",
|
||||
"client_epoch_ms": 1775219400000
|
||||
},
|
||||
"divinationPayload": {
|
||||
"divinationMethod": "手动起卦",
|
||||
"questionType": "事业",
|
||||
"question": "我最近换工作是否合适?",
|
||||
"divinationTimeIso": "2026-04-03T20:30:00+08:00",
|
||||
"yaoLines": [
|
||||
"少阳",
|
||||
"少阴",
|
||||
"老阳",
|
||||
"少阴",
|
||||
"少阳",
|
||||
"老阴"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### AG-UI required base fields
|
||||
|
||||
- `state`: required object, frontend sends `{}` by default.
|
||||
- `messages[0].id`: required string id for user message.
|
||||
- `tools`: required array, frontend sends empty array when no tools requested.
|
||||
- `context`: required array, frontend sends empty array when no extra context.
|
||||
|
||||
### `divinationPayload` strict rules
|
||||
|
||||
- `divinationMethod`: enum, allowed values `手动起卦 | 自动起卦`
|
||||
- `questionType`: non-empty string, recommended Chinese category labels
|
||||
- `question`: non-empty string
|
||||
- `divinationTimeIso`: RFC3339 datetime with timezone offset
|
||||
- `yaoLines`: exactly 6 items, order is `初爻 -> 上爻`
|
||||
- `yaoLines` item enum: `少阳 | 少阴 | 老阳 | 老阴`
|
||||
- Additional fields are forbidden.
|
||||
|
||||
## Event output contract
|
||||
|
||||
During run streaming, backend emits standard AG-UI lifecycle events and two divination-relevant payload events:
|
||||
|
||||
### 1) `DIVINATION_DERIVED`
|
||||
|
||||
- Emitted once after backend derives hexagram data.
|
||||
- Payload field: `divination` (strict object).
|
||||
|
||||
`divination` object:
|
||||
|
||||
```json
|
||||
{
|
||||
"question": "我最近换工作是否合适?",
|
||||
"questionType": "事业",
|
||||
"divinationMethod": "手动起卦",
|
||||
"divinationTime": "2026年04月03日 20:30",
|
||||
"binaryCode": "101001",
|
||||
"changedBinaryCode": "100001",
|
||||
"guaName": "山火贲",
|
||||
"upperName": "艮",
|
||||
"lowerName": "离",
|
||||
"targetGuaName": "山雷颐",
|
||||
"worldPosition": 1,
|
||||
"responsePosition": 4,
|
||||
"hasChangingYao": true,
|
||||
"ganzhi": {
|
||||
"yearGanZhi": "丙午",
|
||||
"monthGanZhi": "壬辰",
|
||||
"dayGanZhi": "辛亥",
|
||||
"timeGanZhi": "乙巳",
|
||||
"yearKongWang": "子丑",
|
||||
"monthKongWang": "午未",
|
||||
"dayKongWang": "寅卯",
|
||||
"timeKongWang": "戌亥",
|
||||
"yueJian": "辰土",
|
||||
"riChen": "亥水",
|
||||
"yuePo": "戌土",
|
||||
"riChong": "巳火"
|
||||
},
|
||||
"wuXingStatuses": {
|
||||
"木": "囚",
|
||||
"火": "休",
|
||||
"土": "旺",
|
||||
"金": "相",
|
||||
"水": "死"
|
||||
},
|
||||
"yaoInfoList": [
|
||||
{
|
||||
"position": 1,
|
||||
"spiritName": "虎",
|
||||
"relationName": "官鬼",
|
||||
"tiganName": "卯",
|
||||
"elementName": "木",
|
||||
"isYang": true,
|
||||
"isChanging": false,
|
||||
"specialMark": "世"
|
||||
}
|
||||
],
|
||||
"targetYaoInfoList": [],
|
||||
"fushenPositions": [2],
|
||||
"fushenInfoList": [
|
||||
{
|
||||
"position": 2,
|
||||
"relationName": "父母",
|
||||
"tiganName": "午",
|
||||
"elementName": "火"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 2) `TEXT_MESSAGE_END`
|
||||
|
||||
- Standard final answer event.
|
||||
- Existing fields remain canonical: `sign_level`, `summary`, `conclusion`, `focus_points`, `advice`, `keywords`, `answer`.
|
||||
|
||||
Frontend should combine:
|
||||
|
||||
- structural divination data from `DIVINATION_DERIVED`
|
||||
- interpretation text from `TEXT_MESSAGE_END`
|
||||
|
||||
## Error contract linkage
|
||||
|
||||
- All errors use RFC7807 with extension `code` and optional `params`.
|
||||
- Error code registry source: `docs/protocols/common/http-error-codes.md`.
|
||||
Reference in New Issue
Block a user