feat(trade): Enhance trade processing and context handling in customer service

- Introduced `pending_trade` handling in the chat API to manage trade requests more effectively.
- Updated the `submit_trade_api` to allow advisors to access customer trades based on assigned roles.
- Added new methods in `GatewayRepository` for managing core holdings during trade subscriptions and redemptions.
- Implemented context-aware trade dialogue management in the customer service layer to improve user experience during multi-turn interactions.
- Enhanced the tool service to support trade actions and suitability checks, ensuring accurate processing of user requests.

This update significantly improves the trade interaction flow, providing a more robust and user-friendly experience for customers engaging in trading activities.
This commit is contained in:
2026-09-13 17:45:04 +08:00
parent b04af6e701
commit 647c07062e
57 changed files with 5419 additions and 244 deletions
+70 -13
View File
@@ -24,6 +24,39 @@ $Root = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
$Web = Join-Path $Root "web"
Set-Location $Root
function Invoke-DockerText {
param([Parameter(ValueFromRemainingArguments)][string[]]$Args)
if (-not (Get-Command docker -ErrorAction SilentlyContinue)) { return $null }
$prevEa = $ErrorActionPreference
$ErrorActionPreference = "SilentlyContinue"
try {
$lines = & docker @Args 2>&1 | Where-Object { $_ -is [string] }
if ($LASTEXITCODE -ne 0) { return $null }
$line = $lines | Select-Object -First 1
if (-not $line) { return $null }
return "$line".Trim()
} catch {
return $null
} finally {
$ErrorActionPreference = $prevEa
}
}
function Invoke-DockerOk {
param([Parameter(ValueFromRemainingArguments)][string[]]$Args)
if (-not (Get-Command docker -ErrorAction SilentlyContinue)) { return $false }
$prevEa = $ErrorActionPreference
$ErrorActionPreference = "SilentlyContinue"
try {
& docker @Args 2>&1 | Out-Null
return ($LASTEXITCODE -eq 0)
} catch {
return $false
} finally {
$ErrorActionPreference = $prevEa
}
}
function Get-ListenerPids([int[]]$Ports) {
$pids = @()
foreach ($port in $Ports) {
@@ -86,6 +119,26 @@ function Stop-AllBackendOnPort8000 {
Start-Sleep -Milliseconds 400
}
function Test-RedisDevReady {
try {
$ready = Invoke-RestMethod -Uri "http://127.0.0.1:8000/api/ready" -TimeoutSec 4 -ErrorAction Stop
if ($ready.checks.redis -eq $true) { return $true }
} catch {
# 后端尚未起来时走端口探测
}
$listen6380 = Get-NetTCPConnection -LocalPort 6380 -State Listen -ErrorAction SilentlyContinue
return [bool]$listen6380
}
function Write-RedisDevReminder {
Write-Host ""
Write-Host "[WARN] Redis 未就绪(推荐 Docker jinrong-redis @ 127.0.0.1:6380)。" -ForegroundColor Yellow
Write-Host " 影响:客户助手会话窗口、交易多轮抽槽、问数 D-06 缓存、JWT 吊销列表等(fail-open 时可能静默降级)。" -ForegroundColor Yellow
Write-Host " 不影响:交易中心直连 simulate、持仓/流水/看板(走 MySQL Core)。" -ForegroundColor DarkGray
Write-Host " 请先打开 Docker Desktop,再执行: .\scripts\dev\start-redis.ps1" -ForegroundColor Yellow
Write-Host " 自检: http://127.0.0.1:8000/api/ready (checks.redis 应为 true)" -ForegroundColor DarkGray
}
function Stop-AllViteDev {
$webEsc = [regex]::Escape($Web)
Get-CimInstance Win32_Process -Filter "Name='node.exe'" -ErrorAction SilentlyContinue |
@@ -124,25 +177,19 @@ function Get-DockerBackendName {
if ($DockerContainer -ne "") {
return $DockerContainer
}
if (-not (Get-Command docker -ErrorAction SilentlyContinue)) {
return $null
}
$name = docker ps --filter "publish=8000" --format "{{.Names}}" 2>$null | Select-Object -First 1
$name = Invoke-DockerText ps --filter "publish=8000" --format "{{.Names}}"
if (-not $name) { return $null }
$name = $name.Trim()
# 仅把 JinRong 自有容器当后端;其它项目(如 stu-system-app)占 8000 时走本机 uvicorn
if ($name -match '^jinrong') { return $name }
return $null
}
function Stop-ForeignPort8000Container {
if (-not (Get-Command docker -ErrorAction SilentlyContinue)) { return }
$name = docker ps --filter "publish=8000" --format "{{.Names}}" 2>$null | Select-Object -First 1
$name = Invoke-DockerText ps --filter "publish=8000" --format "{{.Names}}"
if (-not $name) { return }
$name = $name.Trim()
if ($name -match '^jinrong') { return }
Write-Host "[WARN] 容器 '$name' 占用 8000 且非 JinRong 后端,将 stop 以便加载本仓库 uvicorn(行情 nav/history 等路由)" -ForegroundColor Yellow
docker stop $name | Out-Null
Invoke-DockerOk stop $name | Out-Null
}
function Test-HttpOk([string]$Url, [int]$TimeoutSec = 12) {
@@ -184,7 +231,10 @@ if (-not $SkipBackend) {
if ($useDocker) {
Write-Host "重启后端 Docker: $container (8000) ..." -ForegroundColor Cyan
docker restart $container | Out-Null
if (-not (Invoke-DockerOk restart $container)) {
Write-Error "docker restart $container 失败(Docker Desktop 是否已启动?)"
exit 1
}
$deadline = (Get-Date).AddSeconds(45)
while ((Get-Date) -lt $deadline) {
if (Test-HealthOk) { break }
@@ -197,9 +247,9 @@ if (-not $SkipBackend) {
}
} else {
Stop-AllBackendOnPort8000
$foreign = docker ps --filter "publish=8000" --format "{{.Names}}" 2>$null | Select-Object -First 1
if ($foreign -and ($foreign.Trim() -notmatch '^jinrong')) {
Write-Host "[WARN] 8000 仍被 Docker 容器 '$($foreign.Trim())' 占用;脚本已尝试 stop,若仍存在请手动 docker stop" -ForegroundColor Yellow
$foreign = Invoke-DockerText ps --filter "publish=8000" --format "{{.Names}}"
if ($foreign -and ($foreign -notmatch '^jinrong')) {
Write-Host "[WARN] 8000 仍被 Docker 容器 '$foreign' 占用;脚本已尝试 stop,若仍存在请手动 docker stop 或启动 Docker Desktop" -ForegroundColor Yellow
}
if (-not (Wait-Port8000Clear)) {
Write-Host "[WARN] 8000 仍被占用。将列出监听进程 — 请关掉所有「uvicorn」PowerShell 窗口后重跑本脚本。" -ForegroundColor Yellow
@@ -248,4 +298,11 @@ if (-not $SkipFrontend) {
}
}
if (-not (Test-RedisDevReady)) {
Write-RedisDevReminder
} else {
Write-Host "Redis 自检: 6380 / api/ready checks.redis = OK" -ForegroundColor Green
}
Write-Host "`n完成。后端 Swagger: http://127.0.0.1:8000/docs" -ForegroundColor DarkGray
Write-Host "提示: 本脚本不启动 Redis;需要时先 .\scripts\dev\start-redis.ps1(见脚本头部 NOTES)" -ForegroundColor DarkGray