copilot working as a conversation

This commit is contained in:
Dan Percic 2024-11-05 21:58:07 +02:00
parent ff8009167b
commit 306b524dee
3 changed files with 50 additions and 18 deletions

View File

@ -12,23 +12,20 @@
</div>
<div class="header-wrapper flex mt-8">
<div class="heading-xl flex-1" id="dossierDetailsDossierName">Copilot</div>
<div class="heading-xl flex-1">Copilot</div>
<ng-container *ngTemplateOutlet="collapsible; context: { action: 'collapse', tooltip: ('copilot' | translate) }"></ng-container>
</div>
<div class="mt-24">
@for (comment of responses$ | async; track comment) {
@for (comment of conversation(); track comment) {
<div class="comment">
<div class="comment-details-wrapper">
<div [matTooltipPosition]="'above'" [matTooltip]="comment.date | date: 'exactDate'" class="small-label">
{{ comment.date | date: 'sophisticatedDate' }}
</div>
<!-- <div class="comment-actions">-->
<!-- </div>-->
</div>
<div>{{ comment.text }}</div>
<pre class="text-auto">{{ comment.text }}</pre>
</div>
}

View File

@ -84,7 +84,7 @@ ngx-monaco-editor {
.right-container {
display: flex;
width: 375px;
width: 750px;
min-width: 375px;
padding: 16px 24px 16px 24px;
@ -96,3 +96,7 @@ ngx-monaco-editor {
width: 100%;
}
}
.text-auto {
text-wrap: auto;
}

View File

@ -1,5 +1,5 @@
import { AsyncPipe, NgIf, NgTemplateOutlet } from '@angular/common';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, inject, input, OnInit, signal } from '@angular/core';
import { NgIf, NgTemplateOutlet } from '@angular/common';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, inject, input, OnInit, signal, viewChild } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { FormsModule } from '@angular/forms';
import { MatIcon } from '@angular/material/icon';
@ -17,8 +17,8 @@ import { CopilotService } from '@services/copilot.service';
import { EditorThemeService } from '@services/editor-theme.service';
import { PermissionsService } from '@services/permissions.service';
import { DatePipe } from '@shared/pipes/date.pipe';
import { BehaviorSubject, firstValueFrom } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import { firstValueFrom } from 'rxjs';
import { map } from 'rxjs/operators';
import { RulesService } from '../../../services/rules.service';
import { rulesScreenTranslations } from '../../../translations/rules-screen-translations';
import ICodeEditor = monaco.editor.ICodeEditor;
@ -38,6 +38,21 @@ interface UploadResponse {
deprecatedWarnings: SyntaxError[];
}
export const SentenceTypes = {
question: 'question',
answer: 'answer',
} as const;
export type SentenceType = keyof typeof SentenceTypes;
interface Sentence {
text: string | null;
date: string;
type: SentenceType;
}
const endingSentence: Sentence = { text: null, date: new Date().toISOString(), type: SentenceTypes.answer };
const RULE_VALIDATION_TIMEOUT = 2000;
@Component({
@ -52,7 +67,6 @@ const RULE_VALIDATION_TIMEOUT = 2000;
IconButtonComponent,
NgIf,
TranslateModule,
AsyncPipe,
NgTemplateOutlet,
CircleButtonComponent,
DatePipe,
@ -68,11 +82,13 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv
#ruleValidationTimeout: number = null;
readonly #copilotService = inject(CopilotService);
readonly #currentUser = getCurrentUser();
readonly #conversation = signal<Sentence[]>([endingSentence]);
protected readonly collapsed = signal(true);
protected readonly IqserTooltipPositions = IqserTooltipPositions;
readonly dossierTemplateId = input.required<string>();
readonly translations = rulesScreenTranslations;
readonly iconButtonTypes = IconButtonTypes;
readonly inputWithAction = viewChild(InputWithActionComponent);
readonly editorOptions: IStandaloneEditorConstructionOptions = {
theme: 'vs',
language: 'java',
@ -87,7 +103,7 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv
readonly type = input.required<IRules['ruleFileType']>();
readonly numberOfErrors = computed(() => this.#errors().filter(e => !e.warning).length);
readonly numberOfWarnings = computed(() => this.#errors().filter(e => e.warning).length);
readonly responses$ = new BehaviorSubject<{ text: string; date: string }[]>([]);
readonly conversation = computed(() => this.#conversation().filter(r => !!r.text));
constructor(
readonly permissionsService: PermissionsService,
@ -104,11 +120,18 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv
.pipe(
takeUntilDestroyed(),
map(res => res?.token),
filter(Boolean),
)
.subscribe(response => {
console.log('WS response: ' + response);
this.responses$.next([...this.responses$.value, { text: response, date: new Date().toISOString() }]);
.subscribe(token => {
console.log('WS token: ' + token);
if (token === null) {
console.log(this.#conversation());
this.#conversation.update(responses => [...responses, { ...endingSentence }]);
return;
}
this.#conversation.update(responses => {
const last = responses.pop();
return [...responses, { ...last, text: (last.text ?? '') + token }];
});
});
this.#copilotService.send('manageradmin');
@ -135,7 +158,15 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv
}
add(question: string) {
console.log(question);
this.#conversation.update(responses => {
const last = responses.pop();
last.text = question;
last.type = SentenceTypes.question;
last.date = new Date().toISOString();
return [...responses, last, { ...endingSentence }];
});
console.log(this.#conversation());
this.inputWithAction().reset();
this.#copilotService.send(question);
}