package acp import ( "encoding/json" "time" "github.com/google/uuid" ) // AgentKindAdminDTO 是 admin 视图的完整字段。EnvKeys 仅返回 key 列表(不返回值)。 type AgentKindAdminDTO struct { ID uuid.UUID `json:"id"` Name string `json:"name"` DisplayName string `json:"display_name"` Description string `json:"description"` BinaryPath string `json:"binary_path"` Args []string `json:"args"` EnvKeys []string `json:"env_keys"` Enabled bool `json:"enabled"` ToolAllowlist []string `json:"tool_allowlist"` 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"` } // AgentKindPublicDTO 是普通用户视图,不暴露 binary_path / args / env_keys。 type AgentKindPublicDTO struct { ID uuid.UUID `json:"id"` Name string `json:"name"` DisplayName string `json:"display_name"` Enabled bool `json:"enabled"` } // CreateAgentKindReq / UpdateAgentKindReq 是 HTTP 请求体。 type CreateAgentKindReq struct { Name string `json:"name"` DisplayName string `json:"display_name"` Description string `json:"description"` BinaryPath string `json:"binary_path"` Args []string `json:"args"` Env map[string]string `json:"env"` Enabled *bool `json:"enabled"` ToolAllowlist []string `json:"tool_allowlist"` ClientType string `json:"client_type"` MCPServers []McpServerSpec `json:"mcp_servers"` } type UpdateAgentKindReq struct { DisplayName *string `json:"display_name,omitempty"` Description *string `json:"description,omitempty"` BinaryPath *string `json:"binary_path,omitempty"` Args []string `json:"args,omitempty"` Env map[string]string `json:"env,omitempty"` Enabled *bool `json:"enabled,omitempty"` ToolAllowlist []string `json:"tool_allowlist,omitempty"` ClientType *string `json:"client_type,omitempty"` MCPServers []McpServerSpec `json:"mcp_servers,omitempty"` // nil = 不改;非 nil(含空)= 替换 } // ConfigFileDTO 是 AgentKind 配置文件的对外视图(admin only,content 明文)。 type ConfigFileDTO struct { RelPath string `json:"rel_path"` Content string `json:"content"` UpdatedAt string `json:"updated_at"` } // UpsertConfigFileReq 是 PUT config-files 请求体。 type UpsertConfigFileReq struct { RelPath string `json:"rel_path"` Content string `json:"content"` } func configFileToDTO(f *ConfigFileContent) ConfigFileDTO { return ConfigFileDTO{ RelPath: f.RelPath, Content: f.Content, UpdatedAt: f.UpdatedAt.UTC().Format("2006-01-02T15:04:05Z"), } } // PermissionRequestDTO 是权限请求的对外视图。 type PermissionRequestDTO struct { ID string `json:"id"` SessionID string `json:"session_id"` ToolName string `json:"tool_name"` ToolCall json.RawMessage `json:"tool_call"` Options json.RawMessage `json:"options"` Status string `json:"status"` CreatedAt string `json:"created_at"` } func permissionRequestToDTO(p *PermissionRequest) PermissionRequestDTO { return PermissionRequestDTO{ ID: p.ID.String(), SessionID: p.SessionID.String(), ToolName: p.ToolName, ToolCall: json.RawMessage(p.ToolCall), Options: json.RawMessage(p.Options), Status: string(p.Status), CreatedAt: p.CreatedAt.Format(time.RFC3339), } } // CreateSessionReq is the request body for POST /api/v1/acp/sessions. type CreateSessionReq struct { WorkspaceID string `json:"workspace_id"` AgentKindID string `json:"agent_kind_id"` Branch *string `json:"branch,omitempty"` IssueNumber *int `json:"issue_number,omitempty"` RequirementNumber *int `json:"requirement_number,omitempty"` InitialPrompt *string `json:"initial_prompt,omitempty"` } // SessionDTO is the response shape for sessions. type SessionDTO struct { ID string `json:"id"` WorkspaceID string `json:"workspace_id"` ProjectID string `json:"project_id"` AgentKindID string `json:"agent_kind_id"` UserID string `json:"user_id"` IssueID *string `json:"issue_id"` RequirementID *string `json:"requirement_id"` AgentSessionID *string `json:"agent_session_id"` Branch string `json:"branch"` CwdPath string `json:"cwd_path"` IsMainWorktree bool `json:"is_main_worktree"` Status string `json:"status"` PID *int32 `json:"pid"` ExitCode *int32 `json:"exit_code"` LastError *string `json:"last_error"` StartedAt string `json:"started_at"` EndedAt *string `json:"ended_at"` } func sessionToDTO(s *Session) SessionDTO { var issueID, reqID, ended *string if s.IssueID != nil { v := s.IssueID.String() issueID = &v } if s.RequirementID != nil { v := s.RequirementID.String() reqID = &v } if s.EndedAt != nil { v := s.EndedAt.UTC().Format("2006-01-02T15:04:05Z") ended = &v } return SessionDTO{ ID: s.ID.String(), WorkspaceID: s.WorkspaceID.String(), ProjectID: s.ProjectID.String(), AgentKindID: s.AgentKindID.String(), UserID: s.UserID.String(), IssueID: issueID, RequirementID: reqID, AgentSessionID: s.AgentSessionID, Branch: s.Branch, CwdPath: s.CwdPath, IsMainWorktree: s.IsMainWorktree, Status: string(s.Status), PID: s.PID, ExitCode: s.ExitCode, LastError: s.LastError, StartedAt: s.StartedAt.UTC().Format("2006-01-02T15:04:05Z"), EndedAt: ended, } }