You've already forked agentic-coding-workflow
bugfix
This commit is contained in:
+171
-3
@@ -21,9 +21,14 @@ type AgentKindAdminDTO struct {
|
||||
ClientType string `json:"client_type"`
|
||||
// MCPServers 明文返回(admin only,编辑所需);条目可能含 header/env 密钥。
|
||||
MCPServers []McpServerSpec `json:"mcp_servers"`
|
||||
CreatedBy uuid.UUID `json:"created_by"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
// 成本核算:model 价格来源 + 默认预算上限(均可空)。
|
||||
ModelID *string `json:"model_id"`
|
||||
MaxCostUSD *float64 `json:"max_cost_usd"`
|
||||
MaxTokens *int64 `json:"max_tokens"`
|
||||
MaxWallClockSeconds *int32 `json:"max_wall_clock_seconds"`
|
||||
CreatedBy uuid.UUID `json:"created_by"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
// AgentKindPublicDTO 是普通用户视图,不暴露 binary_path / args / env_keys。
|
||||
@@ -46,6 +51,11 @@ type CreateAgentKindReq struct {
|
||||
ToolAllowlist []string `json:"tool_allowlist"`
|
||||
ClientType string `json:"client_type"`
|
||||
MCPServers []McpServerSpec `json:"mcp_servers"`
|
||||
// 成本核算:model_id 为字符串 UUID(空/缺省 = 不设置);预算上限均可选。
|
||||
ModelID *string `json:"model_id"`
|
||||
MaxCostUSD *float64 `json:"max_cost_usd"`
|
||||
MaxTokens *int64 `json:"max_tokens"`
|
||||
MaxWallClockSeconds *int32 `json:"max_wall_clock_seconds"`
|
||||
}
|
||||
|
||||
type UpdateAgentKindReq struct {
|
||||
@@ -58,6 +68,12 @@ type UpdateAgentKindReq struct {
|
||||
ToolAllowlist []string `json:"tool_allowlist,omitempty"`
|
||||
ClientType *string `json:"client_type,omitempty"`
|
||||
MCPServers []McpServerSpec `json:"mcp_servers,omitempty"` // nil = 不改;非 nil(含空)= 替换
|
||||
// 成本核算三态:字段存在(非 nil)= 设置;缺省(nil)= 不改。
|
||||
// ModelID 空串 = 清空;预算上限值 <=0 = 清空。
|
||||
ModelID *string `json:"model_id,omitempty"`
|
||||
MaxCostUSD *float64 `json:"max_cost_usd,omitempty"`
|
||||
MaxTokens *int64 `json:"max_tokens,omitempty"`
|
||||
MaxWallClockSeconds *int32 `json:"max_wall_clock_seconds,omitempty"`
|
||||
}
|
||||
|
||||
// ConfigFileDTO 是 AgentKind 配置文件的对外视图(admin only,content 明文)。
|
||||
@@ -133,6 +149,15 @@ type SessionDTO struct {
|
||||
LastError *string `json:"last_error"`
|
||||
StartedAt string `json:"started_at"`
|
||||
EndedAt *string `json:"ended_at"`
|
||||
// 成本核算:运行时累计 + 有效预算上限 + 终止原因。
|
||||
PromptTokens int64 `json:"prompt_tokens"`
|
||||
CompletionTokens int64 `json:"completion_tokens"`
|
||||
ThinkingTokens int64 `json:"thinking_tokens"`
|
||||
TotalCostUSD float64 `json:"total_cost_usd"`
|
||||
BudgetMaxCostUSD *float64 `json:"budget_max_cost_usd"`
|
||||
BudgetMaxTokens *int64 `json:"budget_max_tokens"`
|
||||
BudgetMaxWallClockSeconds *int32 `json:"budget_max_wall_clock_seconds"`
|
||||
TerminatedReason *string `json:"terminated_reason"`
|
||||
}
|
||||
|
||||
func sessionToDTO(s *Session) SessionDTO {
|
||||
@@ -167,5 +192,148 @@ func sessionToDTO(s *Session) SessionDTO {
|
||||
LastError: s.LastError,
|
||||
StartedAt: s.StartedAt.UTC().Format("2006-01-02T15:04:05Z"),
|
||||
EndedAt: ended,
|
||||
|
||||
PromptTokens: s.PromptTokens,
|
||||
CompletionTokens: s.CompletionTokens,
|
||||
ThinkingTokens: s.ThinkingTokens,
|
||||
TotalCostUSD: s.TotalCostUSD,
|
||||
BudgetMaxCostUSD: s.BudgetMaxCostUSD,
|
||||
BudgetMaxTokens: s.BudgetMaxTokens,
|
||||
BudgetMaxWallClockSeconds: s.BudgetMaxWallClockSeconds,
|
||||
TerminatedReason: s.TerminatedReason,
|
||||
}
|
||||
}
|
||||
|
||||
// SessionUsageDTO 是单条 per-turn 账目的对外视图。
|
||||
type SessionUsageDTO struct {
|
||||
ID int64 `json:"id"`
|
||||
ModelID *string `json:"model_id"`
|
||||
PromptTokens int64 `json:"prompt_tokens"`
|
||||
CompletionTokens int64 `json:"completion_tokens"`
|
||||
ThinkingTokens int64 `json:"thinking_tokens"`
|
||||
CostUSD float64 `json:"cost_usd"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
|
||||
// SessionUsageResponse 是 GET /sessions/{id}/usage 的响应:会话累计 + 最近账目。
|
||||
type SessionUsageResponse struct {
|
||||
SessionID string `json:"session_id"`
|
||||
PromptTokens int64 `json:"prompt_tokens"`
|
||||
CompletionTokens int64 `json:"completion_tokens"`
|
||||
ThinkingTokens int64 `json:"thinking_tokens"`
|
||||
TotalCostUSD float64 `json:"total_cost_usd"`
|
||||
BudgetMaxCostUSD *float64 `json:"budget_max_cost_usd"`
|
||||
BudgetMaxTokens *int64 `json:"budget_max_tokens"`
|
||||
Recent []SessionUsageDTO `json:"recent"`
|
||||
}
|
||||
|
||||
// AcpUsageItem 是 admin ACP 用量聚合的一行(镜像 chat AdminUsageItem)。
|
||||
type AcpUsageItem struct {
|
||||
Key string `json:"key"`
|
||||
PromptTokens int64 `json:"prompt_tokens"`
|
||||
CompletionTokens int64 `json:"completion_tokens"`
|
||||
ThinkingTokens int64 `json:"thinking_tokens"`
|
||||
CostUSD float64 `json:"cost_usd"`
|
||||
}
|
||||
|
||||
// AcpUsageResponse 包裹分组用量项。
|
||||
type AcpUsageResponse struct {
|
||||
Items []AcpUsageItem `json:"items"`
|
||||
}
|
||||
|
||||
// ===== run-history dashboard DTO =====
|
||||
|
||||
// DashboardResponse 是 GET /api/v1/acp/dashboard 的响应:总览 + 按天序列。
|
||||
type DashboardResponse struct {
|
||||
From string `json:"from"`
|
||||
To string `json:"to"`
|
||||
Rollup SessionRollupDTO `json:"rollup"`
|
||||
ByDay []SessionDayDTO `json:"by_day"`
|
||||
}
|
||||
|
||||
// SessionRollupDTO 是会话总览(计数 + 成功率 + 成本 + 平均时长)。
|
||||
type SessionRollupDTO struct {
|
||||
Total int64 `json:"total"`
|
||||
Succeeded int64 `json:"succeeded"`
|
||||
Crashed int64 `json:"crashed"`
|
||||
Active int64 `json:"active"`
|
||||
SuccessRate float64 `json:"success_rate"`
|
||||
TotalCostUSD float64 `json:"total_cost_usd"`
|
||||
TotalTokens int64 `json:"total_tokens"`
|
||||
AvgDurationSeconds float64 `json:"avg_duration_seconds"`
|
||||
}
|
||||
|
||||
// SessionDayDTO 是按天的时间序列一行。
|
||||
type SessionDayDTO struct {
|
||||
Day string `json:"day"`
|
||||
Total int64 `json:"total"`
|
||||
Succeeded int64 `json:"succeeded"`
|
||||
Crashed int64 `json:"crashed"`
|
||||
TotalCostUSD float64 `json:"total_cost_usd"`
|
||||
}
|
||||
|
||||
// SessionTimelineDTO 是单会话事件时间线一行(按 method/kind 分桶)。
|
||||
type SessionTimelineDTO struct {
|
||||
Direction string `json:"direction"`
|
||||
Kind string `json:"kind"`
|
||||
Method string `json:"method"`
|
||||
EventCount int64 `json:"event_count"`
|
||||
FirstAt string `json:"first_at"`
|
||||
LastAt string `json:"last_at"`
|
||||
}
|
||||
|
||||
func dashboardToResponse(r *DashboardResult) DashboardResponse {
|
||||
resp := DashboardResponse{
|
||||
From: r.From.UTC().Format(time.RFC3339),
|
||||
To: r.To.UTC().Format(time.RFC3339),
|
||||
Rollup: SessionRollupDTO{
|
||||
Total: r.Rollup.Total,
|
||||
Succeeded: r.Rollup.Succeeded,
|
||||
Crashed: r.Rollup.Crashed,
|
||||
Active: r.Rollup.Active,
|
||||
SuccessRate: r.Rollup.SuccessRate(),
|
||||
TotalCostUSD: r.Rollup.TotalCostUSD,
|
||||
TotalTokens: r.Rollup.TotalTokens,
|
||||
AvgDurationSeconds: r.Rollup.AvgDurationSeconds,
|
||||
},
|
||||
ByDay: make([]SessionDayDTO, 0, len(r.ByDay)),
|
||||
}
|
||||
for _, d := range r.ByDay {
|
||||
resp.ByDay = append(resp.ByDay, SessionDayDTO{
|
||||
Day: d.Day.UTC().Format(time.RFC3339),
|
||||
Total: d.Total,
|
||||
Succeeded: d.Succeeded,
|
||||
Crashed: d.Crashed,
|
||||
TotalCostUSD: d.TotalCostUSD,
|
||||
})
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func sessionTimelineToDTO(b SessionTimelineBucket) SessionTimelineDTO {
|
||||
return SessionTimelineDTO{
|
||||
Direction: b.Direction,
|
||||
Kind: b.RPCKind,
|
||||
Method: b.Method,
|
||||
EventCount: b.EventCount,
|
||||
FirstAt: b.FirstAt.UTC().Format(time.RFC3339),
|
||||
LastAt: b.LastAt.UTC().Format(time.RFC3339),
|
||||
}
|
||||
}
|
||||
|
||||
func sessionUsageToDTO(r *SessionUsageRecord) SessionUsageDTO {
|
||||
var modelID *string
|
||||
if r.ModelID != nil {
|
||||
v := r.ModelID.String()
|
||||
modelID = &v
|
||||
}
|
||||
return SessionUsageDTO{
|
||||
ID: r.ID,
|
||||
ModelID: modelID,
|
||||
PromptTokens: r.PromptTokens,
|
||||
CompletionTokens: r.CompletionTokens,
|
||||
ThinkingTokens: r.ThinkingTokens,
|
||||
CostUSD: r.CostUSD,
|
||||
CreatedAt: r.CreatedAt.UTC().Format(time.RFC3339),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user