From a21dc4d6a0273bd6cb775a8a17d32d1a9f423764 Mon Sep 17 00:00:00 2001
From: jacekpluta <73617938+jacekpluta@users.noreply.github.com>
Date: Tue, 3 Sep 2024 09:29:32 +0200
Subject: [PATCH] [ACS-8399] Integrate all changes with backend (#10163)
---
.../services/agent.service.md | 3 +-
.../services/search-ai.service.md | 4 +-
.../lib/agent/services/agent.service.spec.ts | 3 +-
.../src/lib/agent/services/agent.service.ts | 58 ++-----------------
.../services/search-ai.service.spec.ts | 8 +--
.../search-ai/services/search-ai.service.ts | 53 ++---------------
.../api/content-rest-api/api/search-ai.api.ts | 18 +++---
.../api/content-rest-api/docs/SearchAiApi.md | 22 +++++--
.../content-rest-api/model/questionModel.ts | 6 +-
.../content-rest-api/model/questionRequest.ts | 1 +
.../model/restrictionQuery.ts | 20 +++++++
11 files changed, 66 insertions(+), 130 deletions(-)
create mode 100644 lib/js-api/src/api/content-rest-api/model/restrictionQuery.ts
diff --git a/docs/content-services/services/agent.service.md b/docs/content-services/services/agent.service.md
index c92ddf9cca..5a7afa0e06 100644
--- a/docs/content-services/services/agent.service.md
+++ b/docs/content-services/services/agent.service.md
@@ -13,9 +13,8 @@ Manages agents in Content Services.
### Methods
-- **getAgents**(mocked?: `boolean`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`AgentPaging`](../../../lib/js-api/src/api/content-rest-api/docs/AgentsApi.md#agentpaging)`>`
+- **getAgents**(): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`AgentPaging`](../../../lib/js-api/src/api/content-rest-api/docs/AgentsApi.md#agentpaging)`>`
Gets all agents.
- - _mocked:_ `boolean` - (Optional) Temporary parameter to mock agents. Should be removed when backend implemented. True by default.
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`AgentPaging`](../../../lib/js-api/src/api/content-rest-api/docs/AgentsApi.md#agentpaging)`>` - AgentPaging object containing the agents.
## Details
diff --git a/docs/content-services/services/search-ai.service.md b/docs/content-services/services/search-ai.service.md
index e1be562d0f..524d6235e0 100644
--- a/docs/content-services/services/search-ai.service.md
+++ b/docs/content-services/services/search-ai.service.md
@@ -19,12 +19,10 @@ Manages search AI in Content Services.
- **ask**(question: [`QuestionRequest`](../../../lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md#questionrequest)): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`QuestionModel`](../../../lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md#questionmodel)`>`
Ask a question to the AI.
- _question:_ [`QuestionRequest`](../../../lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md#questionrequest) - The question to ask.
- - _mocked:_ `boolean` - (Optional) temporary parameter to mock returned information about question. Should be removed when backend implemented. True by default.
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`QuestionModel`](../../../lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md#questionmodel)`>` - QuestionModel object containing information about questions.
-- **getAnswer**(questionId: `string`, mocked?: `boolean`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`AiAnswerPaging`](../../../lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md#aianswerpaging)`>`
+- **getAnswer**(questionId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`AiAnswerPaging`](../../../lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md#aianswerpaging)`>`
Get an answer to specific question.
- _questionId:_ `string` - The ID of the question to get an answer for.
- - _mocked:_ `boolean` - (Optional) temporary parameter to mock answer on question. Should be removed when backend implemented. True by default.
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`AiAnswerPaging`](../../../lib/js-api/src/api/content-rest-api/docs/SearchAiApi.md#aianswerpaging)`>` - AiAnswerPaging object containing the answer.
- **checkSearchAvailability**(selectedNodesState: `SelectionState`, maxSelectedNodes: `number`): `string`
Check if using of search is possible (if all conditions are met).
diff --git a/lib/content-services/src/lib/agent/services/agent.service.spec.ts b/lib/content-services/src/lib/agent/services/agent.service.spec.ts
index 69cea0dae0..78e9361e8e 100644
--- a/lib/content-services/src/lib/agent/services/agent.service.spec.ts
+++ b/lib/content-services/src/lib/agent/services/agent.service.spec.ts
@@ -45,7 +45,7 @@ const agentPagingObjectMock: AgentPaging = {
}
};
-const avatarAgentMock = 'https://res.cloudinary.com/hyld/image/upload/f_auto,c_fill,g_auto,w_1400,h_730/v1/h2/hero/blue-shirt-woman';
+const avatarAgentMock = '';
const agentWithAvatarListMock: AgentWithAvatar[] = [
{
@@ -71,7 +71,6 @@ describe('AgentService', () => {
agentService = TestBed.inject(AgentService);
apiService = TestBed.inject(AlfrescoApiService);
agentsApi = new AgentsApi(apiService.getInstance());
- agentService.mocked = false;
spyOn(agentsApi, 'getAgentAvatar').and.returnValue(Promise.resolve(avatarAgentMock));
spyOn(agentService.agentsApi, 'getAgentAvatar').and.returnValue(Promise.resolve(avatarAgentMock));
diff --git a/lib/content-services/src/lib/agent/services/agent.service.ts b/lib/content-services/src/lib/agent/services/agent.service.ts
index 887420a23e..a0de4f6f6b 100644
--- a/lib/content-services/src/lib/agent/services/agent.service.ts
+++ b/lib/content-services/src/lib/agent/services/agent.service.ts
@@ -16,7 +16,7 @@
*/
import { Injectable } from '@angular/core';
-import { AgentPaging, AgentsApi, AgentWithAvatar } from '@alfresco/js-api';
+import { AgentsApi, AgentWithAvatar } from '@alfresco/js-api';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { BehaviorSubject, forkJoin, from, Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
@@ -26,7 +26,6 @@ import { switchMap } from 'rxjs/operators';
})
export class AgentService {
private _agentsApi: AgentsApi;
- private _mocked = true;
private agents = new BehaviorSubject([]);
get agentsApi(): AgentsApi {
@@ -34,10 +33,6 @@ export class AgentService {
return this._agentsApi;
}
- set mocked(mocked: boolean) {
- this._mocked = mocked;
- }
-
agents$ = this.agents.asObservable();
constructor(private apiService: AlfrescoApiService) {}
@@ -53,12 +48,13 @@ export class AgentService {
if (agentsList.length) {
return of(agentsList);
}
- return this.getMockedAgents().pipe(
+ return from(this.agentsApi.getAgents()).pipe(
switchMap((paging) => {
const agents = paging.list.entries.map((agentEntry) => agentEntry.entry);
- return forkJoin([of(agents), ...agents.map((agent) => this.getAgentAvatar(agent.id))]);
+ // TODO: fetch avatars https://hyland.atlassian.net/browse/ACS-8695
+ return forkJoin({ agents: of(agents), avatars: forkJoin(agents.map(() => of(``))) });
}),
- switchMap(([agents, ...avatars]: [AgentWithAvatar[], string]) => {
+ switchMap(({ agents, avatars }) => {
const agentsWithAvatar = agents.map((agent, index) => ({ ...agent, avatar: avatars[index] }));
this.agents.next(agentsWithAvatar);
return of(agentsWithAvatar);
@@ -68,46 +64,6 @@ export class AgentService {
);
}
- /**
- * Gets all agents.
- *
- * @returns AgentPaging object containing the agents.
- */
- private getMockedAgents(): Observable {
- return this._mocked
- ? of({
- list: {
- entries: [
- {
- entry: {
- id: '1',
- name: 'HR Agent',
- description:
- 'Your Claims Doc Agent streamlines the extraction, analysis, and management of data from insurance claims documents.'
- }
- },
- {
- entry: {
- id: '2',
- name: 'Policy Agent',
- description:
- 'Your Claims Doc Agent streamlines the extraction, analysis, and management of data from insurance claims documents.'
- }
- },
- {
- entry: {
- id: '3',
- name: 'Rules & Rates Agent',
- description:
- 'Your Claims Doc Agent streamlines the extraction, analysis, and management of data from insurance claims documents.'
- }
- }
- ]
- }
- })
- : from(this.agentsApi.getAgents());
- }
-
/**
* Gets agent avatar by agent id.
*
@@ -115,8 +71,6 @@ export class AgentService {
* @returns string with an image.
*/
getAgentAvatar(agentId: string): Observable {
- return this._mocked
- ? of('https://res.cloudinary.com/hyld/image/upload/f_auto,c_fill,g_auto,w_1400,h_730/v1/h2/hero/blue-shirt-woman')
- : from(this._agentsApi.getAgentAvatar(agentId));
+ return from(this._agentsApi.getAgentAvatar(agentId));
}
}
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 61258c8d03..a45dddab53 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
@@ -30,7 +30,6 @@ describe('SearchAiService', () => {
imports: [ContentTestingModule]
});
service = TestBed.inject(SearchAiService);
- service.mocked = false;
});
describe('ask', () => {
@@ -38,12 +37,13 @@ describe('SearchAiService', () => {
const question: QuestionModel = {
question: 'some question',
questionId: 'some id',
- restrictionQuery: 'node id1,node id 2'
+ restrictionQuery: { nodesIds: ['nodeId1', 'nodeId2'] }
};
- spyOn(service.searchAiApi, 'ask').and.returnValue(Promise.resolve([question]));
+ spyOn(service.searchAiApi, 'ask').and.returnValue(Promise.resolve(question));
const questionRequest: QuestionRequest = {
question: 'some question',
- nodeIds: ['node id1', 'node id 2']
+ nodeIds: ['nodeId1', 'nodeId2'],
+ agentId: 'some id'
};
service.ask(questionRequest).subscribe((questionResponse) => {
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 bb750d2f58..e98878c1f0 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
@@ -18,8 +18,7 @@
import { Injectable } from '@angular/core';
import { AiAnswerPaging, QuestionModel, QuestionRequest, SearchAiApi } from '@alfresco/js-api';
import { AlfrescoApiService } from '@alfresco/adf-core';
-import { BehaviorSubject, from, Observable, of } from 'rxjs';
-import { map } from 'rxjs/operators';
+import { BehaviorSubject, from, Observable } from 'rxjs';
import { SelectionState } from '@alfresco/adf-extensions';
import { TranslateService } from '@ngx-translate/core';
import { SearchAiInputState } from '../models/search-ai-input-state';
@@ -32,23 +31,15 @@ export class SearchAiService {
active: false
});
private _searchAiApi: SearchAiApi;
- private _mocked = true;
get searchAiApi(): SearchAiApi {
this._searchAiApi = this._searchAiApi ?? new SearchAiApi(this.apiService.getInstance());
return this._searchAiApi;
}
- set mocked(mocked: boolean) {
- this._mocked = mocked;
- }
-
toggleSearchAiInput$ = this.toggleSearchAiInput.asObservable();
- constructor(
- private apiService: AlfrescoApiService,
- private translateService: TranslateService
- ) {}
+ constructor(private apiService: AlfrescoApiService, private translateService: TranslateService) {}
/**
* Update the state of the search AI input.
@@ -66,13 +57,7 @@ export class SearchAiService {
* @returns QuestionModel object containing information about questions.
*/
ask(question: QuestionRequest): Observable {
- return this._mocked
- ? of({
- question: 'Some question',
- questionId: 'some id',
- restrictionQuery: 'Some restriction query'
- })
- : from(this.searchAiApi.ask([question])).pipe(map((questions) => questions[0]));
+ return from(this.searchAiApi.ask([question]));
}
/**
@@ -82,37 +67,7 @@ export class SearchAiService {
* @returns AiAnswerPaging object containing the answer.
*/
getAnswer(questionId: string): Observable {
- return this._mocked
- ? of({
- list: {
- pagination: {
- count: 1,
- hasMoreItems: false,
- totalItems: 1,
- skipCount: 0,
- maxItems: 100
- },
- entries: [
- {
- entry: {
- answer: 'Some answer',
- questionId: 'some id',
- references: [
- {
- referenceId: '45a84919-d654-4669-a849-19d6548669e9',
- referenceText: 'some type'
- },
- {
- referenceId: '45a84919-d654-4669-a849-19d6548669e9',
- referenceText: 'some type'
- }
- ]
- }
- }
- ]
- }
- })
- : from(this.searchAiApi.getAnswer(questionId));
+ return from(this.searchAiApi.getAnswer(questionId));
}
/**
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 745b8b6490..3a0d2529ae 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
@@ -27,17 +27,18 @@ export class SearchAiApi extends BaseApi {
/**
* Ask a question to the AI.
*
- * @param questions The questions to ask.
+ * @param questions QuestionRequest array containing questions to ask.
* @returns QuestionModel object containing information about questions.
*/
- ask(questions: QuestionRequest[]): Promise {
- return this.get({
- path: 'questions',
+ ask(questions: QuestionRequest[]): Promise {
+ const agentId = questions[0].agentId;
+ return this.post({
+ path: `agents/${agentId}/questions`,
bodyParam: questions.map((questionRequest) => ({
question: questionRequest.question,
- restrictionQuery: questionRequest.nodeIds.join(',')
+ restrictionQuery: { nodesIds: questionRequest.nodeIds }
}))
- });
+ }).then((response) => response.entry);
}
/**
@@ -48,10 +49,7 @@ export class SearchAiApi extends BaseApi {
*/
getAnswer(questionId: string): Promise {
return this.get({
- path: 'answers',
- queryParams: {
- questionId
- }
+ path: `questions/${questionId}/answers`
});
}
}
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 fd1d7801f3..96e49ef423 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
@@ -30,7 +30,8 @@ const searchAiApi = new SearchAiApi(alfrescoApi);
searchAiApi.ask([{
question: 'Some question',
- restrictionQuery: 'Some restriction query'
+ restrictionQuery: 'Some restriction query',
+ agentId: 'Some agent id'
}]).then((questionInformation) => {
console.log('API called successfully. Returned data: ' + questionInformation);
});
@@ -146,11 +147,19 @@ searchAiApi.getAnswer('some question id').then((answer) => {
**Properties**
-| Name | Type |
-|----------------------|--------|
-| **question** | string |
-| **questionId** | string |
-| **restrictionQuery** | string |
+| Name | Type |
+|----------------------|------------------|
+| **question** | string |
+| **questionId** | string |
+| **restrictionQuery** | RestrictionQuery |
+
+## RestrictionQuery
+
+**Properties**
+
+| Name | Type |
+|--------------|----------|
+| **nodesIds** | string[] |
## QuestionRequest
@@ -160,3 +169,4 @@ searchAiApi.getAnswer('some question id').then((answer) => {
|--------------|----------|
| **question** | string |
| **nodeIds** | string[] |
+| **agentId** | string |
diff --git a/lib/js-api/src/api/content-rest-api/model/questionModel.ts b/lib/js-api/src/api/content-rest-api/model/questionModel.ts
index 4e88c36c7c..17b994ef44 100644
--- a/lib/js-api/src/api/content-rest-api/model/questionModel.ts
+++ b/lib/js-api/src/api/content-rest-api/model/questionModel.ts
@@ -15,8 +15,10 @@
* limitations under the License.
*/
+import { RestrictionQuery } from './restrictionQuery';
+
export interface QuestionModel {
- question: string;
questionId: string;
- restrictionQuery: string;
+ question: string;
+ restrictionQuery: RestrictionQuery;
}
diff --git a/lib/js-api/src/api/content-rest-api/model/questionRequest.ts b/lib/js-api/src/api/content-rest-api/model/questionRequest.ts
index d2bd6332bd..2eaabfac7a 100644
--- a/lib/js-api/src/api/content-rest-api/model/questionRequest.ts
+++ b/lib/js-api/src/api/content-rest-api/model/questionRequest.ts
@@ -18,4 +18,5 @@
export interface QuestionRequest {
question: string;
nodeIds: string[];
+ agentId: string;
}
diff --git a/lib/js-api/src/api/content-rest-api/model/restrictionQuery.ts b/lib/js-api/src/api/content-rest-api/model/restrictionQuery.ts
new file mode 100644
index 0000000000..05d5186bcc
--- /dev/null
+++ b/lib/js-api/src/api/content-rest-api/model/restrictionQuery.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 RestrictionQuery {
+ nodesIds: string[];
+}