refactor: unify AI capabilities and workspace integration

This commit is contained in:
yuxuanhui
2026-09-08 19:28:44 +08:00
parent 3d26827b49
commit b604e6050e
23 changed files with 1821 additions and 805 deletions
+145
View File
@@ -0,0 +1,145 @@
"""Domain-owned AI capabilities; caller owns authorization and transactions."""
from pydantic import Field
from ..schemas import AlphaFilters, BulkInput, BulkUpdate, Contract, ResearchInput, ResearchUpdate
from .capabilities import Capability, EmptyArgs
class SearchArgs(Contract):
filters: AlphaFilters = Field(default_factory=AlphaFilters)
class AlphaArgs(Contract):
alpha_id: str = Field(min_length=1, max_length=100, pattern=r"^[A-Za-z0-9_-]+$")
class ResearchArgs(AlphaArgs):
changes: ResearchInput
async def search(ctx, args):
data = await ctx.business.search_alphas(args.filters)
return {**data, "filters": args.filters.model_dump(mode="json")}
async def pnl(ctx, args):
data = await ctx.business.get_alpha_pnl(args.alpha_id)
points = data.pop("points")
return {
**data,
"alpha_id": args.alpha_id,
"count": len(points),
"first": points[0] if points else None,
"last": points[-1] if points else None,
"null_count": sum(p["value"] is None for p in points),
}
async def research_preview(ctx, ids, changes):
"""Fix before/after values and versions using the same validation as execution."""
targets, versions = [], {}
for alpha_id in ids:
before = (await ctx.business.get_alpha(alpha_id))["research"]
after = {**before, **changes(before)}
ResearchInput.model_validate({k: after[k] for k in ("note", "tags", "favorite", "state")})
targets.append({"alpha_id": alpha_id, "before": before, "after": after})
versions[alpha_id] = before["version"]
return {"targets": targets, "versions": versions}
async def preview_research(ctx, args):
return await research_preview(
ctx, [args.alpha_id], lambda before: args.changes.model_dump(exclude_unset=True)
)
async def preview_bulk(ctx, args):
return await research_preview(
ctx,
args.alpha_ids,
lambda before: {
"tags": sorted((set(before["tags"]) | set(args.add_tags)) - set(args.remove_tags)),
**({"state": args.state} if args.state else {}),
},
)
async def update_research(ctx, args, preview):
return await ctx.business.update_research(
args.alpha_id,
ResearchUpdate(
**args.changes.model_dump(exclude_unset=True), version=preview["versions"][args.alpha_id]
),
)
async def update_bulk(ctx, args, preview):
return await ctx.business.bulk_update_research(
BulkUpdate(**args.model_dump(), versions=preview["versions"])
)
INSTRUCTIONS = "缺失指标保持未知;Turnover 0.15 表示15%。陈述依据、Alpha ID 和数据时间,区分当前页与全部结果。\n只传需要修改的研究字段。批量操作固定ID,最多100个。不要自行扩大选中范围。"
CAPABILITIES = (
Capability(
name="search_alphas",
schema=SearchArgs,
description="按明确筛选条件查询本地 Alpha。Turnover 0.15 表示 15%;支持分页,禁止把当前页当作全部结果。",
label="查询 Alpha",
renderer="alpha",
effect="query",
handler=search,
),
Capability(
name="get_alpha_facets",
schema=EmptyArgs,
description="获取可用地区、类型、状态、标签与本地 Alpha 总数。",
label="查询筛选选项",
renderer="alpha",
effect="query",
handler=lambda ctx, args: ctx.business.get_alpha_facets(),
),
Capability(
name="get_alpha",
schema=AlphaArgs,
description="读取指定 Alpha 的表达式、指标、已有检查和本地研究记录。",
label="读取 Alpha",
renderer="alpha",
effect="query",
handler=lambda ctx, args: ctx.business.get_alpha(args.alpha_id),
),
Capability(
name="get_alpha_pnl",
schema=AlphaArgs,
description="读取指定 Alpha 的 PnL 缓存摘要。缺失缓存时说明情况,不自动刷新。",
label="读取 PnL 缓存",
renderer="alpha",
effect="query",
handler=pnl,
),
Capability(
name="update_research",
schema=ResearchArgs,
description="提出指定 Alpha 的本地研究记录修改。仅传要修改的字段,等待用户在界面确认。",
label="修改研究记录",
renderer="alpha",
effect="confirm",
preview=preview_research,
execute=update_research,
refresh=("alphas",),
),
Capability(
name="bulk_update_research",
schema=BulkInput,
description="提出固定 1–100 个 Alpha 的批量标签或研究状态修改,等待用户确认。",
label="批量修改研究记录",
renderer="alpha",
effect="confirm",
preview=preview_bulk,
execute=update_bulk,
refresh=("alphas",),
),
)