Skip to content

Commit

Permalink
Merge pull request #31 from xpert-ai/develop
Browse files Browse the repository at this point in the history
Relase v3.0.14
  • Loading branch information
tiven-w authored Jan 24, 2025
2 parents 99b889a + 84e297d commit a3c8098
Show file tree
Hide file tree
Showing 44 changed files with 394 additions and 205 deletions.
46 changes: 20 additions & 26 deletions apps/cloud/src/app/@core/interceptors/language.interceptor.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { Store } from './../services/store.service';
import { TranslateService } from '@ngx-translate/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { TranslateService } from '@ngx-translate/core'
import { Observable } from 'rxjs'
import { Store } from './../services/store.service'

@Injectable()
export class LanguageInterceptor implements HttpInterceptor {
constructor(private store: Store, private translate: TranslateService) {}
constructor(
private store: Store,
private translate: TranslateService
) {}

intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const language =
this.store && this.store.preferredLanguage
? this.store.preferredLanguage
: this.translate.getBrowserLang();
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const language =
this.store && this.store.preferredLanguage ? this.store.preferredLanguage : this.translate.getBrowserLang()

request = request.clone({
setHeaders: {
Language: language
}
});
request = request.clone({
setHeaders: {
Language: language,
'Time-Zone': Intl.DateTimeFormat().resolvedOptions().timeZone
}
})

return next.handle(request);
}
return next.handle(request)
}
}
22 changes: 22 additions & 0 deletions apps/cloud/src/app/@core/providers/date.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Pipe, PipeTransform } from '@angular/core'
import { format } from 'date-fns/format'
import { formatRelative } from 'date-fns/formatRelative'
import { getDateLocale } from '../types'
import { injectLanguage } from './translate'
Expand All @@ -11,3 +13,23 @@ export function injectFormatRelative() {
})
}
}

@Pipe({ name: 'format', standalone: true })
export class DateFormatPipe implements PipeTransform {
readonly lang = injectLanguage()

transform(value: any, pattern?: string): string | null {
return format(value, pattern || 'yyyy-MM-dd', {
locale: getDateLocale(this.lang())
})
}
}

@Pipe({ name: 'relative', standalone: true })
export class DateRelativePipe implements PipeTransform {
readonly _formatRelative = injectFormatRelative()

transform(value: Date | string): string | null {
return this._formatRelative(value)
}
}
3 changes: 2 additions & 1 deletion apps/cloud/src/app/@core/services/fetch-event-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export function injectFetchEventSource<T extends BodyInit | null>() {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
'Organization-Id': `${organization.id}`,
Language: lang()
Language: lang(),
'Time-Zone': Intl.DateTimeFormat().resolvedOptions().timeZone
},
body: data,
openWhenHidden: true,
Expand Down
2 changes: 1 addition & 1 deletion apps/cloud/src/app/@core/services/xpert.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ export class XpertService extends XpertWorkspaceBaseCrudService<IXpert> {

chatApp(name: string, request: TChatRequest, options: TChatOptions) {
return this.fetchEventSource(
this.apiBaseUrl + `/${name}/chat-app`,
this.baseUrl + this.apiBaseUrl + `/${name}/chat-app`,
JSON.stringify({
request,
options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</div>

<div class="grow flex flex-col rounded-b-2xl overflow-y-auto">
<div class="flex-1 relative overflow-x-hidden px-3">
<div class="flex-1 relative overflow-x-hidden px-3 pt-4">
@if (parameters()?.length) {
<xpert-parameters-card class="w-full" [parameters]="parameters()" />
}
Expand Down
169 changes: 101 additions & 68 deletions apps/cloud/src/app/@shared/chat/preview/preview.component.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,49 @@
import { Clipboard } from '@angular/cdk/clipboard'
import { TextFieldModule } from '@angular/cdk/text-field'
import { CommonModule } from '@angular/common'
import { booleanAttribute, Component, computed, DestroyRef, effect, inject, input, model, output, signal } from '@angular/core'
import {
booleanAttribute,
Component,
computed,
DestroyRef,
effect,
inject,
input,
model,
output,
signal
} from '@angular/core'
import { toObservable } from '@angular/core/rxjs-interop'
import { FormsModule } from '@angular/forms'
import { MatTooltipModule } from '@angular/material/tooltip'
import { appendMessageContent, stringifyMessageContent } from '@metad/copilot'
import { nonBlank } from '@metad/core'
import { TranslateModule } from '@ngx-translate/core'
import {
ChatConversationService,
ChatMessageEventTypeEnum,
ChatMessageFeedbackRatingEnum,
ChatMessageFeedbackService,
ChatMessageTypeEnum,
getErrorMessage,
IChatConversation,
IChatMessage,
IChatMessageFeedback,
IXpert,
ToastrService,
ToolCall,
TXpertParameter,
uuid,
XpertAgentExecutionService,
XpertAgentExecutionStatusEnum,
XpertService,
uuid,
ChatMessageTypeEnum,
ChatMessageEventTypeEnum,
IXpert,
XpertService
} from 'apps/cloud/src/app/@core'
import { EmojiAvatarComponent } from 'apps/cloud/src/app/@shared/avatar'
import { ToolCallConfirmComponent, XpertParametersCardComponent } from 'apps/cloud/src/app/@shared/xpert'
import { MarkdownModule } from 'ngx-markdown'
import { derivedAsync } from 'ngxtension/derived-async'
import { map, of, Subscription } from 'rxjs'
import { map, of, Subscription, switchMap } from 'rxjs'
import { XpertPreviewAiMessageComponent } from './ai-message/message.component'
import { nonBlank } from '@metad/core'
import { MatTooltipModule } from '@angular/material/tooltip'

@Component({
standalone: true,
Expand Down Expand Up @@ -80,15 +93,14 @@ export class ChatConversationPreviewComponent {
readonly chatStop = output<void>()

// States
readonly conversation = derivedAsync(() => {
return this.conversationId()
? this.conversationService.getOneById(this.conversationId(), { relations: ['messages', 'xpert', 'xpert.agent', 'xpert.agents'] })
: of(null)
})
readonly conversation = signal<IChatConversation>(null)

readonly feedbacks = signal<Record<string, IChatMessageFeedback>>({})
readonly #feedbacks = derivedAsync(() => {
return this.conversationId() ? this.messageFeedbackService.getMyAll({ where: { conversationId: this.conversationId(), } })
.pipe(map(({items}) => items))
return this.conversationId()
? this.messageFeedbackService
.getMyAll({ where: { conversationId: this.conversationId() } })
.pipe(map(({ items }) => items))
: of(null)
})
readonly envriments = signal(false)
Expand Down Expand Up @@ -125,27 +137,41 @@ export class ChatConversationPreviewComponent {
return this._messages() as IChatMessage[]
})

private chatSubscription: Subscription
constructor() {
effect(() => {
// console.log(this.starters())
})
effect(() => {
if (this.conversation()) {
this._messages.set(this.conversation().messages)
private convSub = toObservable(this.conversationId)
.pipe(
switchMap((id) =>
id
? this.conversationService.getOneById(this.conversationId(), {
relations: ['messages', 'xpert', 'xpert.agent', 'xpert.agents']
})
: of(null)
)
)
.subscribe((conv) => {
this.conversation.set(conv)
if (conv) {
this._messages.set(conv.messages)
if (!this.xpert()) {
this.xpert.set(this.conversation().xpert)
this.xpert.set(conv.xpert)
}
}
}, { allowSignalWrites: true })
effect(() => {
if (this.#feedbacks()) {
this.feedbacks.set(this.#feedbacks().reduce((acc, curr) => {
acc[curr.messageId] = curr
return acc
}, {}))
}
}, { allowSignalWrites: true })
})

private chatSubscription: Subscription
constructor() {
effect(
() => {
if (this.#feedbacks()) {
this.feedbacks.set(
this.#feedbacks().reduce((acc, curr) => {
acc[curr.messageId] = curr
return acc
}, {})
)
}
},
{ allowSignalWrites: true }
)
}

chat(options?: { input?: string; confirm?: boolean; reject?: boolean }) {
Expand Down Expand Up @@ -209,19 +235,30 @@ export class ChatConversationPreviewComponent {
}
} else if (event.type === ChatMessageTypeEnum.EVENT) {
this.chatEvent.emit(event)
// processEvents(event, this.executionService)
if (event.event === ChatMessageEventTypeEnum.ON_MESSAGE_START) {
this.currentMessage.update((state) => ({
...state,
...event.data
}))
}
if (event.event === ChatMessageEventTypeEnum.ON_AGENT_END) {
this.currentMessage.update((message) => ({
...message,
executionId: event.data.id,
status: event.data.status
}))
switch (event.event) {
case ChatMessageEventTypeEnum.ON_CONVERSATION_START:
case ChatMessageEventTypeEnum.ON_CONVERSATION_END: {
this.conversation.update((state) => ({
...(state ?? {}),
...event.data
}))
break
}
case ChatMessageEventTypeEnum.ON_MESSAGE_START: {
this.currentMessage.update((state) => ({
...state,
...event.data
}))
break
}
case ChatMessageEventTypeEnum.ON_AGENT_END: {
this.currentMessage.update((message) => ({
...message,
executionId: event.data.id,
status: event.data.status
}))
break
}
}
}
}
Expand Down Expand Up @@ -259,12 +296,10 @@ export class ChatConversationPreviewComponent {
}

appendMessage(message: Partial<IChatMessage>) {
this._messages.update(
(state) => {
const messages = state?.filter((_) => _.id !== message.id)
return [...(messages ?? []), message as IChatMessage]
}
)
this._messages.update((state) => {
const messages = state?.filter((_) => _.id !== message.id)
return [...(messages ?? []), message as IChatMessage]
})
}

copy(message: IChatMessage) {
Expand Down Expand Up @@ -304,7 +339,7 @@ export class ChatConversationPreviewComponent {
...(state ?? {}),
[message.id]: feedback
}))
this.#toastr.success('PAC.Messages.UpdatedSuccessfully', {Default: 'Updated successfully'})
this.#toastr.success('PAC.Messages.UpdatedSuccessfully', { Default: 'Updated successfully' })
},
error: (error) => {
this.#toastr.error(getErrorMessage(error))
Expand All @@ -313,20 +348,18 @@ export class ChatConversationPreviewComponent {
}

cancelFeedback(message: Partial<IChatMessage>, id: string) {
this.messageFeedbackService
.delete(id)
.subscribe({
next: () => {
this.feedbacks.update((state) => ({
...(state ?? {}),
[message.id]: null
}))
this.#toastr.success('PAC.Messages.UpdatedSuccessfully', {Default: 'Updated successfully'})
},
error: (error) => {
this.#toastr.error(getErrorMessage(error))
}
})
this.messageFeedbackService.delete(id).subscribe({
next: () => {
this.feedbacks.update((state) => ({
...(state ?? {}),
[message.id]: null
}))
this.#toastr.success('PAC.Messages.UpdatedSuccessfully', { Default: 'Updated successfully' })
},
error: (error) => {
this.#toastr.error(getErrorMessage(error))
}
})
}

getFeedback(id: string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
<div class="flex">
<div class="shrink-0 w-[104px] px-2 py-[5px] text-gray-500 text-sm leading-[18px] truncate">{{ 'PAC.Xpert.StartTime' | translate: {Default: 'Start Time'} }}</div>
<div class="grow px-2 py-[5px] text-gray-900 text-sm leading-[18px]">
<span>{{ execution().createdAt | date}}</span>
<span>{{ execution().createdAt | relative}}</span>
</div>
</div>
<div class="flex">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Clipboard } from '@angular/cdk/clipboard'
import { CommonModule } from '@angular/common'
import { Component, inject, input, signal, WritableSignal } from '@angular/core'
import { TranslateModule } from '@ngx-translate/core'
import { IXpertAgentExecution } from '../../../@core'
import { DateRelativePipe, IXpertAgentExecution } from '../../../@core'
import { UserPipe } from '../../pipes'
import { XpertAgentExecutionLogComponent } from '../execution-log/execution.component'
import { XpertAgentExecutionStatusComponent } from '../execution-status/execution.component'
Expand All @@ -13,6 +13,7 @@ import { XpertAgentExecutionStatusComponent } from '../execution-status/executio
CommonModule,
TranslateModule,
UserPipe,
DateRelativePipe,
XpertAgentExecutionStatusComponent,
XpertAgentExecutionLogComponent
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@
@for (execution of executions(); track execution.id) {
<button cdkMenuItem class="ngm-cdk-menu-item shrink-0 px-2 py-1 max-w-full flex justify-between items-start text-sm"
(click)="openExecution(execution)">
{{execution.updatedAt | date: 'medium'}}
{{execution.updatedAt | relative}}
<span class="px-1 rounded-md border-light text-xs">{{execution.elapsedTime | number}}ms</span>
</button>
} @empty {
Expand Down
Loading

0 comments on commit a3c8098

Please sign in to comment.