diff --git a/docs/content-services/services/search-ai.service.md b/docs/content-services/services/search-ai.service.md index c3ee98037e..4d7c07214f 100644 --- a/docs/content-services/services/search-ai.service.md +++ b/docs/content-services/services/search-ai.service.md @@ -24,6 +24,9 @@ Manages search AI in Content Services. Get an answer to specific question. - _questionId:_ `string` - The ID of the question to get an answer for. - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`AiAnswerEntry`](../../../lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md#aianswerentry)`>` - AiAnswerEntry object containing the answer. +- **getConfig**(): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`KnowledgeRetrievalConfigEntry`](../../../lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md#knowledgeretrievalconfigentry)`>`
+ Get the knowledge retrieval configuration. + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`KnowledgeRetrievalConfigEntry`](../../../lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md#knowledgeretrievalconfigentry)`>` - KnowledgeRetrievalConfigEntry object containing the configuration. - **checkSearchAvailability**(selectedNodesState: `SelectionState`, maxSelectedNodes: `number`): `string`
Check if using of search is possible (if all conditions are met). - _selectedNodesState:_ `SelectionState` - information about selected nodes. diff --git a/lib/content-services/src/lib/search-ai/services/search-ai.service.spec.ts b/lib/content-services/src/lib/search-ai/services/search-ai.service.spec.ts index cbbc92ecd0..5e67fbbf15 100644 --- a/lib/content-services/src/lib/search-ai/services/search-ai.service.spec.ts +++ b/lib/content-services/src/lib/search-ai/services/search-ai.service.spec.ts @@ -16,7 +16,7 @@ */ import { TestBed } from '@angular/core/testing'; -import { AiAnswerEntry, Node, QuestionModel, QuestionRequest } from '@alfresco/js-api'; +import { AiAnswerEntry, KnowledgeRetrievalConfigEntry, Node, QuestionModel, QuestionRequest } from '@alfresco/js-api'; import { ContentTestingModule } from '../../testing/content.testing.module'; import { SearchAiService } from './search-ai.service'; import { SearchAiInputState } from '../models/search-ai-input-state'; @@ -79,6 +79,23 @@ describe('SearchAiService', () => { }); }); + describe('getConfig', () => { + it('should load knowledge retrieval configuration', (done) => { + const config: KnowledgeRetrievalConfigEntry = { + entry: { + knowledgeRetrievalUrl: 'https://some-url' + } + }; + spyOn(service.searchAiApi, 'getConfig').and.returnValue(Promise.resolve(config)); + + service.getConfig().subscribe((configResponse) => { + expect(configResponse).toBe(config); + expect(service.searchAiApi.getConfig).toHaveBeenCalled(); + done(); + }); + }); + }); + describe('updateSearchAiInputState', () => { it('should trigger toggleSearchAiInput$', () => { const state: SearchAiInputState = { diff --git a/lib/content-services/src/lib/search-ai/services/search-ai.service.ts b/lib/content-services/src/lib/search-ai/services/search-ai.service.ts index 2336d6d6d0..b10dd27a4e 100644 --- a/lib/content-services/src/lib/search-ai/services/search-ai.service.ts +++ b/lib/content-services/src/lib/search-ai/services/search-ai.service.ts @@ -16,7 +16,7 @@ */ import { Injectable } from '@angular/core'; -import { AiAnswerEntry, QuestionModel, QuestionRequest, SearchAiApi } from '@alfresco/js-api'; +import { AiAnswerEntry, KnowledgeRetrievalConfigEntry, QuestionModel, QuestionRequest, SearchAiApi } from '@alfresco/js-api'; import { AlfrescoApiService } from '@alfresco/adf-core'; import { BehaviorSubject, from, Observable } from 'rxjs'; import { SelectionState } from '@alfresco/adf-extensions'; @@ -70,6 +70,15 @@ export class SearchAiService { return from(this.searchAiApi.getAnswer(questionId)); } + /** + * Get the knowledge retrieval configuration. + * + * @returns KnowledgeRetrievalConfigEntry object containing the configuration. + */ + getConfig(): Observable { + return from(this.searchAiApi.getConfig()); + } + /** * Check if using of search is possible (if all conditions are met). * diff --git a/lib/js-api/src/api/content-rest-api/api/search-ai.api.ts b/lib/js-api/src/api/content-rest-api/api/search-ai.api.ts index 5ec2edda40..1ee3c6c389 100644 --- a/lib/js-api/src/api/content-rest-api/api/search-ai.api.ts +++ b/lib/js-api/src/api/content-rest-api/api/search-ai.api.ts @@ -15,10 +15,8 @@ * limitations under the License. */ -import { QuestionModel } from '../model/questionModel'; +import { QuestionModel, QuestionRequest, AiAnswerEntry, KnowledgeRetrievalConfigEntry } from '../model'; import { BaseApi } from '../../hxi-connector-api/api/base.api'; -import { QuestionRequest } from '../model/questionRequest'; -import { AiAnswerEntry } from '../model'; /** * Search AI API. @@ -52,4 +50,15 @@ export class SearchAiApi extends BaseApi { path: `questions/${questionId}/answers/-default-` }); } + + /** + * Get the knowledge retrieval configuration. + * + * @returns KnowledgeRetrievalConfigEntry object containing the configuration. + */ + getConfig(): Promise { + return this.get({ + path: '/config/-default-' + }); + } } diff --git a/lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md b/lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md index 07175ea6c0..74e2597a80 100644 --- a/lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md +++ b/lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md @@ -1,9 +1,10 @@ # SearchAiApi -| Method | HTTP request | Description | -|-------------------------|----------------------------|-------------------------------------| -| [ask](#ask) | **GET** /questions | Ask a question to the AI. | -| [getAnswer](#getAnswer) | **GET** /answers/-default- | Get an answer to specific question. | +| Method | HTTP request | Description | +|-------------------------|----------------------------|--------------------------------------------| +| [ask](#ask) | **GET** /questions | Ask a question to the AI. | +| [getAnswer](#getAnswer) | **GET** /answers/-default- | Get an answer to specific question. | +| [getConfig](#getConfig) | **GET** /config/-default- | Get the knowledge retrieval configuration. | ## ask @@ -97,6 +98,33 @@ searchAiApi.getAnswer('some question id').then((answer) => { **Return type**: [AiAnswerEntry](#AiAnswerEntry) +## getConfig + +Get the knowledge retrieval configuration. For example: + +```json +{ + "entry": { + "knowledgeRetrievalUrl": "https://some-url" + } +} +``` + +**Example** + +```javascript +import { AlfrescoApi, AgentsApi } from '@alfresco/js-api'; + +const alfrescoApi = new AlfrescoApi(/*..*/); +const searchAiApi = new SearchAiApi(alfrescoApi); + +searchAiApi.getConfig().then((answer) => { + console.log('API called successfully. Returned data: ', answer.entry.knowledgeRetrievalUrl); +}); +``` + +**Return type**: [KnowledgeRetrievalConfigEntry](#KnowledgeRetrievalConfigEntry) + # Models ## AiAnswerEntry @@ -153,3 +181,19 @@ searchAiApi.getAnswer('some question id').then((answer) => { | **question** | string | | **nodeIds** | string[] | | **agentId** | string | + +## KnowledgeRetrievalConfigEntry + +**Properties** + +| Name | Type | +|-------|-------------------------------------------------------| +| entry | [KnowledgeRetrievalConfig](#KnowledgeRetrievalConfig) | + +## KnowledgeRetrievalConfig + +**Properties** + +| Name | Type | +|-----------------------|--------| +| knowledgeRetrievalUrl | string | diff --git a/lib/js-api/src/api/content-rest-api/model/index.ts b/lib/js-api/src/api/content-rest-api/model/index.ts index 5ebb4ba8ee..3df2aa5863 100644 --- a/lib/js-api/src/api/content-rest-api/model/index.ts +++ b/lib/js-api/src/api/content-rest-api/model/index.ts @@ -99,6 +99,8 @@ export * from './groupMemberPagingList'; export * from './groupMembershipBodyCreate'; export * from './groupPaging'; export * from './groupPagingList'; +export * from './knowledgeRetrievalConfig'; +export * from './knowledgeRetrievalConfigEntry'; export * from './modelError'; export * from './networkQuota'; export * from './node'; diff --git a/lib/js-api/src/api/content-rest-api/model/knowledgeRetrievalConfig.ts b/lib/js-api/src/api/content-rest-api/model/knowledgeRetrievalConfig.ts new file mode 100644 index 0000000000..b92011f2e2 --- /dev/null +++ b/lib/js-api/src/api/content-rest-api/model/knowledgeRetrievalConfig.ts @@ -0,0 +1,20 @@ +/*! + * @license + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface KnowledgeRetrievalConfig { + knowledgeRetrievalUrl: string; +} diff --git a/lib/js-api/src/api/content-rest-api/model/knowledgeRetrievalConfigEntry.ts b/lib/js-api/src/api/content-rest-api/model/knowledgeRetrievalConfigEntry.ts new file mode 100644 index 0000000000..c01b52600b --- /dev/null +++ b/lib/js-api/src/api/content-rest-api/model/knowledgeRetrievalConfigEntry.ts @@ -0,0 +1,22 @@ +/*! + * @license + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { KnowledgeRetrievalConfig } from './knowledgeRetrievalConfig'; + +export interface KnowledgeRetrievalConfigEntry { + entry: KnowledgeRetrievalConfig; +} diff --git a/lib/js-api/test/content-services/searchAiApi.spec.ts b/lib/js-api/test/content-services/searchAiApi.spec.ts index 7806662dba..40c57c87a6 100644 --- a/lib/js-api/test/content-services/searchAiApi.spec.ts +++ b/lib/js-api/test/content-services/searchAiApi.spec.ts @@ -44,27 +44,17 @@ describe('SearchAiApi', () => { { question: 'some question 1', nodeIds: ['some node id 1'], - agentId: 'some id 1' - }, - { - question: 'some question 2', - nodeIds: ['some node id 2', 'some node id 3'], - agentId: 'some id 2' + agentId: 'id1' } ]) .then((questions) => { - assert.deepStrictEqual(questions, [ - { - questionId: 'some id 1', - question: 'some question 1', - restrictionQuery: 'some node id 1' - }, - { - questionId: 'some id 2', - question: 'some question 2', - restrictionQuery: 'some node id 2,some node id 3' + assert.deepStrictEqual(questions, { + questionId: 'some id 1', + question: 'some question 1', + restrictionQuery: { + nodesIds: ['some node id 1'] } - ]); + }); done(); }); }); @@ -91,4 +81,19 @@ describe('SearchAiApi', () => { }); }); }); + + describe('getConfig', () => { + it('should load knowledge retrieval configuration', (done) => { + searchAiMock.mockGetConfig200Response(); + + searchAiApi.getConfig().then((config) => { + assert.deepStrictEqual(config, { + entry: { + knowledgeRetrievalUrl: 'https://some-url' + } + }); + done(); + }); + }); + }); }); diff --git a/lib/js-api/test/mockObjects/content-services/search-ai.mock.ts b/lib/js-api/test/mockObjects/content-services/search-ai.mock.ts index 4462248bc2..f0dcbce15a 100644 --- a/lib/js-api/test/mockObjects/content-services/search-ai.mock.ts +++ b/lib/js-api/test/mockObjects/content-services/search-ai.mock.ts @@ -21,68 +21,49 @@ import nock from 'nock'; export class SearchAiMock extends BaseMock { mockGetAsk200Response(): void { nock(this.host, { encodedQueryParams: true }) - .get('/alfresco/api/-default-/private/hxi/versions/1/questions', [ + .post('/alfresco/api/-default-/private/hxi/versions/1/agents/id1/questions', [ { question: 'some question 1', - restrictionQuery: 'some node id 1' - }, - { - question: 'some question 2', - restrictionQuery: 'some node id 2,some node id 3' + restrictionQuery: { + nodesIds: ['some node id 1'] + } } ]) - .reply(200, [ - { + .reply(200, { + entry: { question: 'some question 1', questionId: 'some id 1', - restrictionQuery: 'some node id 1' - }, - { - question: 'some question 2', - questionId: 'some id 2', - restrictionQuery: 'some node id 2,some node id 3' + restrictionQuery: { + nodesIds: ['some node id 1'] + } } - ]); + }); } mockGetAnswer200Response(): void { nock(this.host, { encodedQueryParams: true }) - .get('/alfresco/api/-default-/private/hxi/versions/1/answers/-default-?questionId=id1') + .get('/alfresco/api/-default-/private/hxi/versions/1/questions/id1/answers/-default-') .reply(200, { - list: { - pagination: { - count: 2, - hasMoreItems: false, - skipCount: 0, - maxItems: 100 - }, - entries: [ + entry: { + answer: 'Some answer 1', + questionId: 'some id 1', + references: [ { - entry: { - answer: 'Some answer 1', - questionId: 'some id 1', - references: [ - { - referenceId: 'some reference id 1', - referenceText: 'some reference text 1' - } - ] - } - }, - { - entry: { - answer: 'Some answer 2', - questionId: 'some id 2', - references: [ - { - referenceId: 'some reference id 2', - referenceText: 'some reference text 2' - } - ] - } + referenceId: 'some reference id 1', + referenceText: 'some reference text 1' } ] } }); } + + mockGetConfig200Response(): void { + nock(this.host, { encodedQueryParams: true }) + .get('/alfresco/api/-default-/private/hxi/versions/1/config/-default-') + .reply(200, { + entry: { + knowledgeRetrievalUrl: 'https://some-url' + } + }); + } }