diff --git a/doc/api/chat.md b/doc/api/chat.md index a15b3b5c5fe21e13d1e07194a645be727d8d4372..0c0b49880e06d101a991f35dac1f47db499ffd96 100644 --- a/doc/api/chat.md +++ b/doc/api/chat.md @@ -23,14 +23,15 @@ Requests to this endpoint are proxied to the Supported attributes: -| Attribute | Type | Required | Description | -|--------------------------|---------|----------|-------------------------------------------------------------------------| -| `content` | string | Yes | Question sent to Chat. | -| `resource_type` | string | No | Type of resource that is sent with Chat question. | -| `resource_id` | string | No | ID of the resource. | -| `referer_url` | string | No | Referer URL. | -| `client_subscription_id` | string | No | Client Subscription ID. | -| `with_clean_history` | boolean | No | Indicates if we need to reset the history before and after the request. | +| Attribute | Type | Required | Description | +|--------------------------|-----------------|----------|-------------------------------------------------------------------------| +| `content` | string | Yes | Question sent to Chat. | +| `resource_type` | string | No | Type of resource that is sent with Chat question. | +| `resource_id` | string, integer | No | ID of the resource. Can be a resource ID (integer) or a commit hash (string). | +| `referer_url` | string | No | Referer URL. | +| `client_subscription_id` | string | No | Client Subscription ID. | +| `with_clean_history` | boolean | No | Indicates if we need to reset the history before and after the request. | +| `project_id` | integer | No | Project ID. Required if `resource_type` is a commit. | Example request: diff --git a/ee/lib/api/chat.rb b/ee/lib/api/chat.rb index bf42c781e53a3f223a50d91a981ba6bb62c21903..3fa05a0b3b5cb256f07106554e17ea80c136a853 100644 --- a/ee/lib/api/chat.rb +++ b/ee/lib/api/chat.rb @@ -8,7 +8,7 @@ class Chat < ::API::Base allow_access_with_scope :ai_features - AVAILABLE_RESOURCES = %w[issue epic group project merge_request].freeze + AVAILABLE_RESOURCES = %w[issue epic group project merge_request commit].freeze before do authenticate! @@ -24,10 +24,16 @@ def user_allowed?(resource) def find_resource(parameters) return current_user unless parameters[:resource_type] && parameters[:resource_id] + return commit_object(parameters) if parameters[:resource_type] == 'commit' object = parameters[:resource_type].camelize.safe_constantize object.find(parameters[:resource_id]) end + + def commit_object(parameters) + project = ::Project.find(parameters[:project_id]) + project.commit_by(oid: parameters[:resource_id]) + end end namespace 'chat' do @@ -35,11 +41,14 @@ def find_resource(parameters) params do requires :content, type: String, limit: 1000, desc: 'Prompt from user' optional :resource_type, type: String, limit: 100, values: AVAILABLE_RESOURCES, desc: 'Resource type' - optional :resource_id, type: Integer, desc: 'ID of resource.' + optional :resource_id, types: [String, Integer], + desc: 'ID of resource. Can be a resource ID (integer) or a commit hash (string).' optional :referer_url, type: String, limit: 1000, desc: 'Referer URL' optional :client_subscription_id, type: String, limit: 500, desc: 'Client Subscription ID' optional :with_clean_history, type: Boolean, desc: 'Indicates if we need to reset the history before and after the request' + optional :project_id, type: Integer, + desc: 'Project ID. Required if resource_type is a commit.' optional :current_file, type: Hash do optional :file_name, type: String, limit: 1000, desc: 'The name of the current file' optional :content_above_cursor, type: String, diff --git a/ee/spec/requests/api/chat_spec.rb b/ee/spec/requests/api/chat_spec.rb index 349c16e85be77a67a7992ce68dc01d52950e5eea..3c8d9750a52a46cb138b5e758501618ed86974d3 100644 --- a/ee/spec/requests/api/chat_spec.rb +++ b/ee/spec/requests/api/chat_spec.rb @@ -17,6 +17,7 @@ let_it_be(:project) { create(:project, :repository, group: group) } let_it_be(:issue) { create(:issue, project: project) } let_it_be(:merge_request) { create(:merge_request, source_project: project) } + let_it_be(:commit) { project.commit } let(:current_user) { nil } let(:headers) { {} } @@ -256,6 +257,22 @@ end end + context 'with a commit' do + let!(:resource) { commit } + let(:params) do + { content: content, resource_type: "commit", resource_id: resource.id, project_id: resource.project.id } + end + + it 'sends resource to the chat' do + expect(chat_message).to receive(:save!) + expect(Gitlab::Llm::ChatMessage).to receive(:new).with(chat_message_params).and_return(chat_message) + expect(Llm::Internal::CompletionService).to receive(:new).with(chat_message, options).and_return(chat) + expect(chat).to receive(:execute) + + post_api + end + end + context 'without resource' do let(:params) { { content: content } } let(:resource) { current_user }