fmode-ng 0.0.75 → 0.0.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/esm2022/lib/aigc/agent/fm-agent-task/fm-agent-task.component.mjs +10 -0
  2. package/esm2022/lib/aigc/agent/index.mjs +1 -1
  3. package/esm2022/lib/aigc/chat/chat-list/chat-list.component.mjs +1 -1
  4. package/esm2022/lib/aigc/chat/chat-modal-input/modal-input.component.mjs +1 -1
  5. package/esm2022/lib/aigc/service-fmai/service-chat/chat-class.mjs +1 -1
  6. package/esm2022/lib/aigc/voice/stream.player.mjs +1 -1
  7. package/esm2022/lib/aigc/voice/tts/fmode-tts-class.mjs +1 -1
  8. package/esm2022/lib/core/agent/chat/completion/fmode-completion.mjs +10 -0
  9. package/esm2022/lib/core/agent/chat/completion/index.mjs +10 -0
  10. package/esm2022/lib/core/agent/chat/fmode-chat.mjs +10 -0
  11. package/esm2022/lib/core/agent/chat/index.mjs +10 -0
  12. package/esm2022/lib/core/agent/chat/interface.mjs +10 -0
  13. package/esm2022/lib/core/agent/index.mjs +10 -0
  14. package/esm2022/lib/core/agent/prompt/agent.prompt.mjs +10 -0
  15. package/esm2022/lib/core/agent/prompt/index.mjs +10 -0
  16. package/esm2022/lib/core/agent/prompt/prompt-util.mjs +10 -0
  17. package/esm2022/lib/core/agent/story/agent.story.mjs +10 -0
  18. package/esm2022/lib/core/agent/story/index.mjs +10 -0
  19. package/esm2022/lib/core/agent/task/agent.task.mjs +10 -0
  20. package/esm2022/lib/core/agent/task/index.mjs +10 -0
  21. package/esm2022/lib/core/voice/tts/index.mjs +10 -0
  22. package/esm2022/lib/storage/service-upload/nova-upload.service.mjs +1 -1
  23. package/esm2022/lib/user/login/auth.service.mjs +1 -1
  24. package/esm2022/lib/user/login/login.component.mjs +1 -1
  25. package/esm2022/lib/user/modal-user-login/modal-user-login.component.mjs +1 -1
  26. package/fesm2022/fmode-ng.mjs +1 -1
  27. package/fesm2022/fmode-ng.mjs.map +1 -1
  28. package/lib/aigc/agent/fm-agent-task/fm-agent-task.component.d.ts +34 -0
  29. package/lib/aigc/agent/index.d.ts +2 -1
  30. package/lib/aigc/chat/chat-list/chat-list.component.d.ts +3 -2
  31. package/lib/aigc/chat/chat-message-card/comp-message-card.component.d.ts +2 -1
  32. package/lib/aigc/chat/chat-modal-input/modal-input.component.d.ts +6 -4
  33. package/lib/aigc/chat/chat-panel/chat-panel.component.d.ts +2 -1
  34. package/lib/aigc/service-fmai/service-chat/chat-class.d.ts +1 -199
  35. package/lib/aigc/voice/stream.player.d.ts +1 -1
  36. package/lib/core/agent/chat/completion/fmode-completion.d.ts +29 -0
  37. package/lib/core/agent/chat/completion/index.d.ts +1 -0
  38. package/lib/core/agent/chat/fmode-chat.d.ts +137 -0
  39. package/lib/core/agent/chat/index.d.ts +3 -0
  40. package/lib/core/agent/chat/interface.d.ts +35 -0
  41. package/lib/core/agent/index.d.ts +4 -0
  42. package/lib/{aigc/agent → core/agent/prompt}/agent.prompt.d.ts +1 -4
  43. package/lib/core/agent/prompt/index.d.ts +1 -0
  44. package/lib/core/agent/prompt/prompt-util.d.ts +3 -0
  45. package/lib/core/agent/story/agent.story.d.ts +12 -0
  46. package/lib/core/agent/story/index.d.ts +1 -0
  47. package/lib/core/agent/task/agent.task.d.ts +51 -0
  48. package/lib/core/agent/task/index.d.ts +1 -0
  49. package/lib/core/voice/tts/index.d.ts +1 -0
  50. package/lib/storage/service-upload/nova-upload.service.d.ts +5 -1
  51. package/lib/user/login/auth.service.d.ts +10 -1
  52. package/lib/user/login/login.component.d.ts +9 -3
  53. package/lib/user/modal-user-login/modal-user-login.component.d.ts +9 -4
  54. package/package.json +2 -2
  55. package/esm2022/lib/aigc/agent/agent.prompt.mjs +0 -10
@@ -0,0 +1,10 @@
1
+
2
+ /**
3
+ * @copyright © 未来飞马 © 未来全栈 www.fmode.cn
4
+ * 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
5
+ * 保留所有权利 All Rights Reserved.
6
+ * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/aigc/agent/fm-agent-task/fm-agent-task.component.mjs
7
+ */
8
+ import{CommonModule}from"@angular/common";import{Component,Inject,ViewChild}from"@angular/core";import{FormsModule}from"@angular/forms";import{MatButtonModule}from"@angular/material/button";import{MatDialogModule,MatDialogRef,MAT_DIALOG_DATA}from"@angular/material/dialog";import{MatFormFieldModule}from"@angular/material/form-field";import{MatInputModule}from"@angular/material/input";import{MatProgressBarModule}from"@angular/material/progress-bar";import{MatStepper,MatStepperModule}from"@angular/material/stepper";import*as i0 from"@angular/core";import*as i1 from"@angular/material/dialog";import*as i2 from"@angular/common";import*as i3 from"@angular/material/button";import*as i4 from"@angular/material/stepper";import*as i5 from"@angular/material/progress-bar";export class FmAgentTaskComponent{constructor(t,e){this.dialogRef=t,this.data=e,this.enabledClose=!1,this.currentStepIndex=0,this.hasError=!1,console.log(this.data?.stepsList)}ngOnInit(){this.startTask()}async startTask(t){if(t&&(this.currentStepIndex=t),this.data.stepsList){for(;this.currentStepIndex<this.data.stepsList?.length;this.currentStepIndex++){let t=this.data.stepsList?.[this.currentStepIndex];if(console.log("this.currentStepIndex",this.currentStepIndex),t?.simulatorProgress(),t.parentComp=this,t.parentIndex=Number(this.currentStepIndex.toFixed(0)),t?.limitStart)break;if(t?.handle){let e=await(t?.handle());if(t.cancelAll){this.dialogRef.close();break}if(0==e)break;t.error||(t.progressSub$?.unsubscribe(),t.progress=1,this.stepper?.next())}}let t=!1;this.data?.stepsList.forEach(((e,o)=>{e?.error&&(t=!0,this.hasError=!0)})),t||(this.enabledClose=!0)}}onNoClick(){this.dialogRef.close()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmAgentTaskComponent,deps:[{token:i1.MatDialogRef},{token:MAT_DIALOG_DATA}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmAgentTaskComponent,isStandalone:!0,selector:"fm-agent-task",viewQueries:[{propertyName:"stepper",first:!0,predicate:MatStepper,descendants:!0}],ngImport:i0,template:'\n<h2 mat-dialog-title *ngIf="!enabledClose">AI生成中</h2>\n<h2 mat-dialog-title *ngIf="enabledClose">任务已完成</h2>\n<mat-dialog-content>\n \n <mat-stepper #stepper orientation="vertical">\n <mat-step *ngFor="let step of data?.stepsList; let index=index;">\n <ng-template matStepLabel>{{step?.title}}</ng-template>\n <ng-template matStepContent>\n <p *ngIf="step?.message">{{step?.message}}</p>\n <p *ngFor="let log of step?.logList">{{log}}</p>\n <button *ngIf="step?.error" mat-button color="warn">{{step?.error}}</button>\n <mat-progress-bar *ngIf="step?.progress!=1&&!step?.limitStart" [color]="step?.error?\'warn\':\'primary\'"\n [mode]="(step?.progress || 1)>=100?\'indeterminate\':\'buffer\'" [value]="step?.progress" [bufferValue]="(step?.progress || 0) + 10"></mat-progress-bar>\n\n\n\n \x3c!-- 自定义按钮区域 --\x3e\n <ng-container *ngFor="let button of step?.buttons">\n <button *ngIf="button.isShow&&button.isShow()" mat-raised-button [color]="button?.color||\'primary\'" (click)="button?.handle()">{{button?.name}}</button>\n </ng-container>\n\n <button mat-button color="warn" *ngIf="step?.restartButtonShow" (click)="startTask(index)">重试</button>\n \x3c!-- 非首项:上一步 --\x3e\n <button mat-button matStepperPrevious *ngIf="index!=0">上一步</button>\n \x3c!-- 非末项:下一步 --\x3e\n <button mat-button matStepperNext *ngIf="(index+1!=data?.stepsList?.length)&&!step?.error">下一步</button>\n </ng-template>\n </mat-step>\n\n </mat-stepper>\n \n \n</mat-dialog-content>\n<mat-dialog-actions [align]="\'end\'" style="display: flex;justify-content: center;">\n \x3c!-- <button mat-button (click)="onNoClick()">No Thanks</button> --\x3e\n <button style="font-size: 20px;" *ngIf="hasError" mat-button color="warn" [mat-dialog-close]="false" cdkFocusInitial>取消</button>\n <button style="font-size: 20px;" *ngIf="enabledClose" mat-button color="primary" [mat-dialog-close]="true" cdkFocusInitial>完成</button>\n</mat-dialog-actions>\n\n',styles:["h2{text-align:center;background-color:#6e23ce}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:MatDialogModule},{kind:"directive",type:i1.MatDialogClose,selector:"[mat-dialog-close], [matDialogClose]",inputs:["aria-label","type","mat-dialog-close","matDialogClose"],exportAs:["matDialogClose"]},{kind:"directive",type:i1.MatDialogTitle,selector:"[mat-dialog-title], [matDialogTitle]",inputs:["id"],exportAs:["matDialogTitle"]},{kind:"directive",type:i1.MatDialogActions,selector:"[mat-dialog-actions], mat-dialog-actions, [matDialogActions]",inputs:["align"]},{kind:"directive",type:i1.MatDialogContent,selector:"[mat-dialog-content], mat-dialog-content, [matDialogContent]"},{kind:"ngmodule",type:MatFormFieldModule},{kind:"ngmodule",type:MatInputModule},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:MatStepperModule},{kind:"component",type:i4.MatStep,selector:"mat-step",inputs:["color"],exportAs:["matStep"]},{kind:"directive",type:i4.MatStepLabel,selector:"[matStepLabel]"},{kind:"component",type:i4.MatStepper,selector:"mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]",inputs:["disableRipple","color","labelPosition","headerPosition","animationDuration"],outputs:["animationDone"],exportAs:["matStepper","matVerticalStepper","matHorizontalStepper"]},{kind:"directive",type:i4.MatStepperNext,selector:"button[matStepperNext]"},{kind:"directive",type:i4.MatStepperPrevious,selector:"button[matStepperPrevious]"},{kind:"directive",type:i4.MatStepContent,selector:"ng-template[matStepContent]"},{kind:"ngmodule",type:MatProgressBarModule},{kind:"component",type:i5.MatProgressBar,selector:"mat-progress-bar",inputs:["color","value","bufferValue","mode"],outputs:["animationEnd"],exportAs:["matProgressBar"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmAgentTaskComponent,decorators:[{type:Component,args:[{selector:"fm-agent-task",standalone:!0,imports:[CommonModule,FormsModule,MatDialogModule,MatFormFieldModule,MatInputModule,MatButtonModule,MatStepperModule,MatProgressBarModule],template:'\n<h2 mat-dialog-title *ngIf="!enabledClose">AI生成中</h2>\n<h2 mat-dialog-title *ngIf="enabledClose">任务已完成</h2>\n<mat-dialog-content>\n \n <mat-stepper #stepper orientation="vertical">\n <mat-step *ngFor="let step of data?.stepsList; let index=index;">\n <ng-template matStepLabel>{{step?.title}}</ng-template>\n <ng-template matStepContent>\n <p *ngIf="step?.message">{{step?.message}}</p>\n <p *ngFor="let log of step?.logList">{{log}}</p>\n <button *ngIf="step?.error" mat-button color="warn">{{step?.error}}</button>\n <mat-progress-bar *ngIf="step?.progress!=1&&!step?.limitStart" [color]="step?.error?\'warn\':\'primary\'"\n [mode]="(step?.progress || 1)>=100?\'indeterminate\':\'buffer\'" [value]="step?.progress" [bufferValue]="(step?.progress || 0) + 10"></mat-progress-bar>\n\n\n\n \x3c!-- 自定义按钮区域 --\x3e\n <ng-container *ngFor="let button of step?.buttons">\n <button *ngIf="button.isShow&&button.isShow()" mat-raised-button [color]="button?.color||\'primary\'" (click)="button?.handle()">{{button?.name}}</button>\n </ng-container>\n\n <button mat-button color="warn" *ngIf="step?.restartButtonShow" (click)="startTask(index)">重试</button>\n \x3c!-- 非首项:上一步 --\x3e\n <button mat-button matStepperPrevious *ngIf="index!=0">上一步</button>\n \x3c!-- 非末项:下一步 --\x3e\n <button mat-button matStepperNext *ngIf="(index+1!=data?.stepsList?.length)&&!step?.error">下一步</button>\n </ng-template>\n </mat-step>\n\n </mat-stepper>\n \n \n</mat-dialog-content>\n<mat-dialog-actions [align]="\'end\'" style="display: flex;justify-content: center;">\n \x3c!-- <button mat-button (click)="onNoClick()">No Thanks</button> --\x3e\n <button style="font-size: 20px;" *ngIf="hasError" mat-button color="warn" [mat-dialog-close]="false" cdkFocusInitial>取消</button>\n <button style="font-size: 20px;" *ngIf="enabledClose" mat-button color="primary" [mat-dialog-close]="true" cdkFocusInitial>完成</button>\n</mat-dialog-actions>\n\n',styles:["h2{text-align:center;background-color:#6e23ce}\n"]}]}],ctorParameters:()=>[{type:i1.MatDialogRef},{type:void 0,decorators:[{type:Inject,args:[MAT_DIALOG_DATA]}]}],propDecorators:{stepper:[{type:ViewChild,args:[MatStepper]}]}});
9
+ var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9haWdjL2FnZW50L2ZtLWFnZW50LXRhc2svZm0tYWdlbnQtdGFzay5jb21wb25lbnQubWpz`
10
+
@@ -5,6 +5,6 @@
5
5
  * 保留所有权利 All Rights Reserved.
6
6
  * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/aigc/agent/index.mjs
7
7
  */
8
- export*from"./agent.prompt";
8
+ export*from"../../core/agent";export*from"./fm-agent-task/fm-agent-task.component";
9
9
  var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9haWdjL2FnZW50L2luZGV4Lm1qcw==`
10
10
 
@@ -5,6 +5,6 @@
5
5
  * 保留所有权利 All Rights Reserved.
6
6
  * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/aigc/chat/chat-list/chat-list.component.mjs
7
7
  */
8
- import{CommonModule}from"@angular/common";import{Component,Input}from"@angular/core";import{AlertController,IonAvatar,IonButton,IonIcon,IonItem,IonLabel,IonList,IonNote,IonText,NavController}from"@ionic/angular/standalone";import{ChatService}from"../../service-fmai/service-chat/chat.service";import*as i0 from"@angular/core";import*as i1 from"../../service-fmai/service-chat/chat.service";import*as i2 from"@ionic/angular/standalone";import*as i3 from"@angular/common";export class ChatListComponent{constructor(t,e,n){this.chatServ=t,this.alertCtrl=e,this.navCtrl=n,this.chatList=[],this.onItemClick=(t,e)=>{e.stopPropagation(),this.goSession(t)},this.avatar="https://ionicframework.com/docs/img/demos/avatar.svg",this.isPreventGo=!1,this.chatServ.getChatSession().then((()=>{}))}async goSession(t){if(!this.isPreventGo)if(t?.rid||t?.sid)this.chatServ.restoreChatPanel(t);else{(await this.alertCtrl.create({header:"注意",subHeader:"请您选择右侧角色",message:"开始对话",buttons:[{role:"ok",text:"知道了",handler:()=>{}}]})).present(),this.navCtrl.navigateRoot("/chat/pro/mask")}}async presentEditTitle(t,e,n){n.stopPropagation(),this.isPreventGo=!0,setTimeout((()=>{this.isPreventGo=!1}),500),n.preventDefault();const i=await this.alertCtrl.create({header:"修改会话标题",subHeader:"",message:"",buttons:[{text:"取消",role:"cancel",handler:()=>{}},{text:"确定",role:"confirm",handler:n=>{e.title=n.title,t?.set("title",n.title),t?.save()}}],inputs:[{placeholder:"会话标题",name:"title",value:e?.title||""}]});await i.present()}async presentDeleteTItle(t,e,n){n.stopPropagation(),this.isPreventGo=!0,setTimeout((()=>{this.isPreventGo=!1}),500),n.preventDefault();const i=await this.alertCtrl.create({header:"确认删除?",subHeader:"",message:"",buttons:[{text:"取消",role:"cancel",handler:()=>{}},{text:"确定",role:"confirm",handler:()=>{e.isHidden=!0,t?.set("isDeleted",!0),t?.save()}}]});await i.present()}truncateString(t){return t&&t.length>10?t.slice(0,10)+"...":t}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatListComponent,deps:[{token:i1.ChatService},{token:i2.AlertController},{token:i2.NavController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ChatListComponent,isStandalone:!0,selector:"app-chat-list",inputs:{onItemClick:"onItemClick"},providers:[],ngImport:i0,template:'<ion-list>\n <ng-container *ngFor="let chat of (chatServ?.chatList || chatList)">\n <ion-item [button]="true" detail="false" *ngIf="!chat?.isHidden" (click)="onItemClick(chat,$event)">\n <div class="unread-indicator-wrapper" slot="start">\n <div class="unread-indicator"></div>\n </div>\n <ion-label>\n <div style="display: flex;justify-content: space-between; align-items: center;">\n <div style="display: flex; flex-direction: row;align-items: center;">\n <strong style="display: flex;align-items: center;">\n <ion-avatar style="margin-right: 10px;">\n <img [src]="chat?.thumb||avatar" />\n </ion-avatar>\n <p style="max-width: 7rem;white-space: nowrap;">{{truncateString(chat?.title)}}</p>\n </strong>\n\n <ion-icon (click)="presentEditTitle(chat?.session,chat,$event)" name="brush-sharp" style="margin-left: 1rem;"></ion-icon>\n <ion-icon (click)="presentDeleteTItle(chat?.session,chat,$event)" name="trash-sharp" style="margin-left: 0.5rem;"></ion-icon>\n \n </div>\n <div class="metadata-end-wrapper" slot="end">\n <ion-note color="medium">{{chat?.latest | date:"HH:mm"}}</ion-note>\n <ion-icon color="medium" name="chevron-forward"></ion-icon>\n </div>\n </div>\n <ion-text></ion-text><br />\n <ion-note color="medium" class="ion-text-wrap">\n {{chat?.message}}\n </ion-note>\n </ion-label>\n </ion-item>\n </ng-container>\n </ion-list>',styles:["ion-icon{color:#fff}ion-list{margin:3px}ion-list ion-item{--inner-padding-bottom:0px;--inner-padding-end:0px;--inner-padding-start:0px;--inner-padding-to:0px;--padding-bottom:0px;--padding-end:0px;--padding-start:0px;--padding-to:0px}ion-list ul{width:100%;list-style-type:none;padding:0;margin:0 0 10px;display:flex;flex-wrap:wrap;background-color:#fff;border-radius:10px}ion-list ul .active__{position:relative;padding:5px 15px;font-size:18px;font-weight:700;color:#535353;transition:.3s}ion-list ul .active{color:#2d8af7;background-color:#f2f4ff;border-radius:10px}ion-list ul li{flex:1 1 auto}ion-list ul li div{cursor:pointer;text-align:center}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i3.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i3.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i3.DatePipe,name:"date"},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonNote,selector:"ion-note",inputs:["color","mode"]},{kind:"component",type:IonAvatar,selector:"ion-avatar"},{kind:"component",type:IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:IonText,selector:"ion-text",inputs:["color","mode"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatListComponent,decorators:[{type:Component,args:[{selector:"app-chat-list",imports:[CommonModule,IonIcon,IonList,IonLabel,IonNote,IonButton,IonAvatar,IonItem,IonText],providers:[],standalone:!0,template:'<ion-list>\n <ng-container *ngFor="let chat of (chatServ?.chatList || chatList)">\n <ion-item [button]="true" detail="false" *ngIf="!chat?.isHidden" (click)="onItemClick(chat,$event)">\n <div class="unread-indicator-wrapper" slot="start">\n <div class="unread-indicator"></div>\n </div>\n <ion-label>\n <div style="display: flex;justify-content: space-between; align-items: center;">\n <div style="display: flex; flex-direction: row;align-items: center;">\n <strong style="display: flex;align-items: center;">\n <ion-avatar style="margin-right: 10px;">\n <img [src]="chat?.thumb||avatar" />\n </ion-avatar>\n <p style="max-width: 7rem;white-space: nowrap;">{{truncateString(chat?.title)}}</p>\n </strong>\n\n <ion-icon (click)="presentEditTitle(chat?.session,chat,$event)" name="brush-sharp" style="margin-left: 1rem;"></ion-icon>\n <ion-icon (click)="presentDeleteTItle(chat?.session,chat,$event)" name="trash-sharp" style="margin-left: 0.5rem;"></ion-icon>\n \n </div>\n <div class="metadata-end-wrapper" slot="end">\n <ion-note color="medium">{{chat?.latest | date:"HH:mm"}}</ion-note>\n <ion-icon color="medium" name="chevron-forward"></ion-icon>\n </div>\n </div>\n <ion-text></ion-text><br />\n <ion-note color="medium" class="ion-text-wrap">\n {{chat?.message}}\n </ion-note>\n </ion-label>\n </ion-item>\n </ng-container>\n </ion-list>',styles:["ion-icon{color:#fff}ion-list{margin:3px}ion-list ion-item{--inner-padding-bottom:0px;--inner-padding-end:0px;--inner-padding-start:0px;--inner-padding-to:0px;--padding-bottom:0px;--padding-end:0px;--padding-start:0px;--padding-to:0px}ion-list ul{width:100%;list-style-type:none;padding:0;margin:0 0 10px;display:flex;flex-wrap:wrap;background-color:#fff;border-radius:10px}ion-list ul .active__{position:relative;padding:5px 15px;font-size:18px;font-weight:700;color:#535353;transition:.3s}ion-list ul .active{color:#2d8af7;background-color:#f2f4ff;border-radius:10px}ion-list ul li{flex:1 1 auto}ion-list ul li div{cursor:pointer;text-align:center}\n"]}]}],ctorParameters:()=>[{type:i1.ChatService},{type:i2.AlertController},{type:i2.NavController}],propDecorators:{onItemClick:[{type:Input}]}});
8
+ import{CommonModule}from"@angular/common";import{Component,Input}from"@angular/core";import{AlertController,IonAvatar,IonButton,IonIcon,IonItem,IonLabel,IonList,IonNote,IonText,ModalController,NavController}from"@ionic/angular/standalone";import{ChatService}from"../../service-fmai/service-chat/chat.service";import{openChatPanelModal}from"../chat-panel/chat-panel.component";import*as i0 from"@angular/core";import*as i1 from"../../service-fmai/service-chat/chat.service";import*as i2 from"@ionic/angular/standalone";import*as i3 from"@angular/common";export class ChatListComponent{constructor(t,e,n,i){this.chatServ=t,this.alertCtrl=e,this.navCtrl=n,this.modalCtrl=i,this.chatList=[],this.onItemClick=(t,e)=>{e.stopPropagation(),this.goSession(t)},this.avatar="https://ionicframework.com/docs/img/demos/avatar.svg",this.isPreventGo=!1,this.chatServ.getChatSession().then((()=>{}))}async goSession(t){if(!this.isPreventGo)if(t?.rid||t?.sid){if(document.body.clientWidth<700){let e={roleId:t?.rid,chatId:t?.sid};return console.log("openChatPanelModal"),void openChatPanelModal(this.modalCtrl,e)}this.chatServ.restoreChatPanel(t)}else{(await this.alertCtrl.create({header:"注意",subHeader:"请您选择右侧角色",message:"开始对话",buttons:[{role:"ok",text:"知道了",handler:()=>{}}]})).present(),this.navCtrl.navigateRoot("/chat/pro/mask")}}async presentEditTitle(t,e,n){n.stopPropagation(),this.isPreventGo=!0,setTimeout((()=>{this.isPreventGo=!1}),500),n.preventDefault();const i=await this.alertCtrl.create({header:"修改会话标题",subHeader:"",message:"",buttons:[{text:"取消",role:"cancel",handler:()=>{}},{text:"确定",role:"confirm",handler:n=>{e.title=n.title,t?.set("title",n.title),t?.save()}}],inputs:[{placeholder:"会话标题",name:"title",value:e?.title||""}]});await i.present()}async presentDeleteTItle(t,e,n){n.stopPropagation(),this.isPreventGo=!0,setTimeout((()=>{this.isPreventGo=!1}),500),n.preventDefault();const i=await this.alertCtrl.create({header:"确认删除?",subHeader:"",message:"",buttons:[{text:"取消",role:"cancel",handler:()=>{}},{text:"确定",role:"confirm",handler:()=>{e.isHidden=!0,t?.set("isDeleted",!0),t?.save()}}]});await i.present()}truncateString(t){return t&&t.length>10?t.slice(0,10)+"...":t}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatListComponent,deps:[{token:i1.ChatService},{token:i2.AlertController},{token:i2.NavController},{token:i2.ModalController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ChatListComponent,isStandalone:!0,selector:"app-chat-list",inputs:{onItemClick:"onItemClick"},providers:[],ngImport:i0,template:'<ion-list>\n <ng-container *ngFor="let chat of (chatServ?.chatList || chatList)">\n <ion-item [button]="true" detail="false" *ngIf="!chat?.isHidden" (click)="onItemClick(chat,$event)">\n <div class="unread-indicator-wrapper" slot="start">\n <div class="unread-indicator"></div>\n </div>\n <ion-label>\n <div style="display: flex;justify-content: space-between; align-items: center;">\n <div style="display: flex; flex-direction: row;align-items: center;">\n <strong style="display: flex;align-items: center;">\n <ion-avatar style="margin-right: 10px;">\n <img [src]="chat?.thumb||avatar" />\n </ion-avatar>\n <p style="max-width: 7rem;white-space: nowrap;">{{truncateString(chat?.title)}}</p>\n </strong>\n\n <ion-icon (click)="presentEditTitle(chat?.session,chat,$event)" name="brush-sharp" style="color:#777777;margin-left: 1rem;"></ion-icon>\n <ion-icon (click)="presentDeleteTItle(chat?.session,chat,$event)" name="trash-sharp" style="color:#777777;margin-left: 0.5rem;"></ion-icon>\n \n </div>\n <div class="metadata-end-wrapper" slot="end">\n <ion-note color="medium">{{chat?.latest | date:"HH:mm"}}</ion-note>\n <ion-icon color="medium" name="chevron-forward"></ion-icon>\n </div>\n </div>\n <ion-text></ion-text><br />\n <ion-note color="medium" class="ion-text-wrap">\n {{chat?.message}}\n </ion-note>\n </ion-label>\n </ion-item>\n </ng-container>\n </ion-list>',styles:["ion-icon{color:#fff}ion-list{margin:3px}ion-list ion-item{--inner-padding-bottom:0px;--inner-padding-end:0px;--inner-padding-start:0px;--inner-padding-to:0px;--padding-bottom:0px;--padding-end:0px;--padding-start:0px;--padding-to:0px}ion-list ul{width:100%;list-style-type:none;padding:0;margin:0 0 10px;display:flex;flex-wrap:wrap;background-color:#fff;border-radius:10px}ion-list ul .active__{position:relative;padding:5px 15px;font-size:18px;font-weight:700;color:#535353;transition:.3s}ion-list ul .active{color:#2d8af7;background-color:#f2f4ff;border-radius:10px}ion-list ul li{flex:1 1 auto}ion-list ul li div{cursor:pointer;text-align:center}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i3.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i3.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i3.DatePipe,name:"date"},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonNote,selector:"ion-note",inputs:["color","mode"]},{kind:"component",type:IonAvatar,selector:"ion-avatar"},{kind:"component",type:IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:IonText,selector:"ion-text",inputs:["color","mode"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatListComponent,decorators:[{type:Component,args:[{selector:"app-chat-list",imports:[CommonModule,IonIcon,IonList,IonLabel,IonNote,IonButton,IonAvatar,IonItem,IonText],providers:[],standalone:!0,template:'<ion-list>\n <ng-container *ngFor="let chat of (chatServ?.chatList || chatList)">\n <ion-item [button]="true" detail="false" *ngIf="!chat?.isHidden" (click)="onItemClick(chat,$event)">\n <div class="unread-indicator-wrapper" slot="start">\n <div class="unread-indicator"></div>\n </div>\n <ion-label>\n <div style="display: flex;justify-content: space-between; align-items: center;">\n <div style="display: flex; flex-direction: row;align-items: center;">\n <strong style="display: flex;align-items: center;">\n <ion-avatar style="margin-right: 10px;">\n <img [src]="chat?.thumb||avatar" />\n </ion-avatar>\n <p style="max-width: 7rem;white-space: nowrap;">{{truncateString(chat?.title)}}</p>\n </strong>\n\n <ion-icon (click)="presentEditTitle(chat?.session,chat,$event)" name="brush-sharp" style="color:#777777;margin-left: 1rem;"></ion-icon>\n <ion-icon (click)="presentDeleteTItle(chat?.session,chat,$event)" name="trash-sharp" style="color:#777777;margin-left: 0.5rem;"></ion-icon>\n \n </div>\n <div class="metadata-end-wrapper" slot="end">\n <ion-note color="medium">{{chat?.latest | date:"HH:mm"}}</ion-note>\n <ion-icon color="medium" name="chevron-forward"></ion-icon>\n </div>\n </div>\n <ion-text></ion-text><br />\n <ion-note color="medium" class="ion-text-wrap">\n {{chat?.message}}\n </ion-note>\n </ion-label>\n </ion-item>\n </ng-container>\n </ion-list>',styles:["ion-icon{color:#fff}ion-list{margin:3px}ion-list ion-item{--inner-padding-bottom:0px;--inner-padding-end:0px;--inner-padding-start:0px;--inner-padding-to:0px;--padding-bottom:0px;--padding-end:0px;--padding-start:0px;--padding-to:0px}ion-list ul{width:100%;list-style-type:none;padding:0;margin:0 0 10px;display:flex;flex-wrap:wrap;background-color:#fff;border-radius:10px}ion-list ul .active__{position:relative;padding:5px 15px;font-size:18px;font-weight:700;color:#535353;transition:.3s}ion-list ul .active{color:#2d8af7;background-color:#f2f4ff;border-radius:10px}ion-list ul li{flex:1 1 auto}ion-list ul li div{cursor:pointer;text-align:center}\n"]}]}],ctorParameters:()=>[{type:i1.ChatService},{type:i2.AlertController},{type:i2.NavController},{type:i2.ModalController}],propDecorators:{onItemClick:[{type:Input}]}});
9
9
  var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9haWdjL2NoYXQvY2hhdC1saXN0L2NoYXQtbGlzdC5jb21wb25lbnQubWpz`
10
10
 
@@ -5,6 +5,6 @@
5
5
  * 保留所有权利 All Rights Reserved.
6
6
  * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/aigc/chat/chat-modal-input/modal-input.component.mjs
7
7
  */
8
- import{Component,Input,ViewChild}from"@angular/core";import{ActivatedRoute,Router,RouterModule}from"@angular/router";import{AlertController,NavController,ToastController}from"@ionic/angular";import{FmodeChat}from"../../service-fmai/service-chat";import{ChatService}from"../../service-fmai/service-chat";import Parse from"parse";import{NzMessageService}from"ng-zorro-antd/message";import{ImagineService}from"../../service-fmai/service-imagine/imagine.service";import{IonButton,IonContent,IonIcon,IonInput,IonItem,IonList,IonModal,IonPopover,IonTextarea,IonToolbar,ModalController}from"@ionic/angular/standalone";import{CommonModule}from"@angular/common";import{FormsModule,ReactiveFormsModule}from"@angular/forms";import{ModalAudioMessageComponent}from"./modal-audio-message/modal-audio-message.component";import{FmChatMessageCard}from"../chat-message-card/comp-message-card.component";import{addIcons}from"ionicons";import{imageOutline,chevronBackOutline,ellipsisHorizontalOutline,chevronDownOutline,chatboxEllipsesOutline,micOutline,paperPlaneOutline,shareSocialOutline,settingsOutline,alertOutline,colorWandOutline,peopleOutline}from"ionicons/icons/index.mjs";import*as i0 from"@angular/core";import*as i1 from"@ionic/angular";import*as i2 from"@ionic/angular/standalone";import*as i3 from"@angular/router";import*as i4 from"../../service-fmai/service-imagine/imagine.service";import*as i5 from"../../service-fmai/service-chat";import*as i6 from"ng-zorro-antd/message";import*as i7 from"@angular/common";import*as i8 from"@angular/forms";addIcons({colorWandOutline:colorWandOutline,peopleOutline:peopleOutline,alertOutline:alertOutline,imageOutline:imageOutline,chevronBackOutline:chevronBackOutline,ellipsisHorizontalOutline:ellipsisHorizontalOutline,chevronDownOutline:chevronDownOutline,chatboxEllipsesOutline:chatboxEllipsesOutline,micOutline:micOutline,paperPlaneOutline:paperPlaneOutline,shareSocialOutline:shareSocialOutline,settingsOutline:settingsOutline});export class FmChatModalInput{closeAudio(){this.audioComp?.cancel(),this.isAudioModal=!1}async startTalk(){let e,n=document.body.clientHeight||960;this.audioModalHeightPoint=Number((165/n).toFixed(2)),this.chat.stopPlayingVoice(),e=await this.modalCtrl.create({component:ModalAudioMessageComponent,componentProps:{chat:this.chat,modal:e,onBreakPointSet:()=>{e?.setCurrentBreakpoint(this.audioModalHeightPoint)}},breakpoints:[this.audioModalHeightPoint],initialBreakpoint:this.audioModalHeightPoint}),e.present()}constructor(e,n,t,o,i,a,s,r,l){this.toastCtrl=e,this.alertCtrl=n,this.modalCtrl=t,this.navCtrl=o,this.router=i,this.imagineServ=a,this.chatServ=s,this.route=r,this.messages=l,this.errorText="",this.isAudioModal=!1,this.audioModalHeightPoint=.35,this.isShare=!1,this.user=Parse.User.current()}ngOnInit(){this.loadModel();let e=this;this.chat.focusUserInput=()=>{e.chat.isVoiceInputMode=!1,e.userInputComp.setFocus()}}async loadModel(){let e=this.chat?.role?.get("model");await this.chat.loadModelList(e)}async setMessageImage(){let e=await this.imagineServ.getimg();this.chat.userImage=e,console.log(this.chat?.userImage)}onInputFocus(){this.chat.isTexting=!0,this.chat.scrollToBottom&&this.chat.scrollToBottom()}onKeyDown(e){e.ctrlKey&&"Enter"===e.key&&(console.log("Ctrl+Enter 被按下"),this.sendMessage())}async sendMessage(){if(!this.chat.userInput){return this.errorText="内容不能为空",void(await this.toastCtrl.create({message:this.errorText,position:"top",icon:"alert",color:"warning-circle",duration:1e3})).present()}this.chat?.sendMessage(this.chat?.userInput,this.chat?.userImage,(e=>{}),{onSSMLComplete:e=>{console.log(e)}}),this.chat.userInput="",this.chat.userImage=""}async checkBalance(){if(!this.chat?.currentModel?.get("payLimit"))return!0;let e=await this.account.getBilling();if(e?.credit?.balance<10){return(await this.alertCtrl.create({header:"注意",subHeader:"您的余额不足,请充值后解锁高级模型",buttons:[{role:"cancel",text:"取消"},{role:"destructive",text:"充值",handler:()=>{this.router.navigateByUrl("/account/billing")}}]})).present(),!1}return!0}async getChatShare(){this.user=Parse.User.current();let e=new Parse.Query("ChatShare");e.equalTo("user",Parse.User.current().id),e.equalTo("session",this.chat?.sessionId);await e.first()}async toggleChatShare(){let e=new Parse.Query("ChatShare");e.equalTo("user",Parse.User.current().id),e.equalTo("role",this.chat?.role.id),e.equalTo("session",this.chat?.sessionId),e.select("objectId");let n=await e.first();if(n?.id)n.set("messageList",this.chat?.messageList);else{n=new(Parse.Object.extend("ChatShare")),n.set("user",{__type:"Pointer",className:"_User",objectId:Parse.User.current()?.id}),n.set("session",{__type:"Pointer",className:"ChatSession",objectId:this.chat?.sessionId}),n.set("role",{__type:"Pointer",className:"AvatarRole",objectId:this.chat?.role.id}),n.set("company",{__type:"Pointer",className:"Company",objectId:"E4KpGvTEto"}),n.set("messageList",this.chat?.messageList)}await n.save(),this.getChatShare()}chatShareSuccessMessage(){this.messages.success("分享成功")}showShare(){this.isShare=!0}handleOkShare(){this.toggleChatShare(),this.chatShareSuccessMessage(),this.isShare=!1}handleCancelShare(){this.isShare=!1}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatModalInput,deps:[{token:i1.ToastController},{token:i1.AlertController},{token:i2.ModalController},{token:i1.NavController},{token:i3.Router},{token:i4.ImagineService},{token:i5.ChatService},{token:i3.ActivatedRoute},{token:i6.NzMessageService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:FmChatModalInput,isStandalone:!0,selector:"fm-chat-modal-input",inputs:{chat:"chat",message:"message",role:"role"},viewQueries:[{propertyName:"audioComp",first:!0,predicate:ModalAudioMessageComponent,descendants:!0},{propertyName:"userInputComp",first:!0,predicate:["userInput"],descendants:!0}],ngImport:i0,template:'<ion-toolbar>\n <ion-item class="button-item" lines="none">\n \x3c!-- 设置 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="settings-outline"></ion-icon> \n </ion-button> --\x3e\n <ng-container *ngFor="let button of chat?.leftButtons">\n <ion-button style="--padding-start:10px;--padding-end:10px;"\n shape="round" *ngIf="button.show()" fill="outline" [title]="button?.title" slot="start" (click)="button.onClick()">\n <ion-icon [name]="button?.icon" [slot]="button?.showTitle?\'start\':\'icon-only\'"></ion-icon>\n {{button?.showTitle&&button?.title}}\n </ion-button>\n </ng-container>\n\n <ng-container *ngFor="let button of chat?.role?.get(\'buttons\')">\n <ion-button shape="round" (click)="chatServ.doButtonAction(button)" fill="outline" slot="start">\n {{button?.name}}\n </ion-button>\n </ng-container>\n\n \x3c!--分享按钮--\x3e\n @if(!chat?.hideShare){\n <ion-button shape="round" *ngIf="chat?.messageList?.length>1" (click)="showShare()" fill="outline" title="分享" slot="end">\n <ion-icon name="share-social-outline"></ion-icon>\n </ion-button>\n }\n \x3c!-- <button nz-button *ngIf="chat?.messageList?.length>1"\n nzType="primary" title="分享" (click)="showShare()" style="width: 31.188px;height: 22px;box-shadow: none;background: #fff;border: 1px solid #4588ff;border-radius: 5px;"> <span class="iconfont icon-fenxiang" style="color: #4588ff;"></span></button>\n --\x3e\n <ion-modal [isOpen]="isShare">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="handleCancelShare()">取消</ion-button>\n </ion-buttons>\n <ion-title>对话分享</ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="handleOkShare()">分享</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n <ng-container *ngFor="let message of chat?.messageList;let index=index;">\n \x3c!-- 内容格式化区域 --\x3e\n <fm-chat-message-card [chat]="chat" *ngIf="!message?.hidden" [index]="index" [message]="message" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n\n <div *ngIf="false" class="popup-content">\n <div *ngFor="let message of chat?.messageList">\n \x3c!-- 头像 --\x3e\n <div class="item-row user" *ngIf="message?.role!=\'system\'">\n <div>\n <img class="avatar" *ngIf="message?.role!=\'user\'" [src]="(chat?.role?.get(\'avatar\') || chat?.role?.get(\'thumb\') || \'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png\')+\'?\'+\'x-image-process=image/resize,m_fixed,w_100\'+\'&imageView2/1/w/32/h/32\'" >\n \x3c!-- <nz-avatar *ngIf="message?.role!=\'user\'" [nzSrc]="(chat?.role?.get(\'avatar\') || chat?.role?.get(\'thumb\') || \'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png\')+\'?\'+\'x-image-process=image/resize,m_fixed,w_100\'+\'&imageView2/1/w/32/h/32\'"></nz-avatar> --\x3e\n </div>\n <div class="user-question">\n <app-comp-user-avatar [user]="user" *ngIf="message?.role==\'user\'"></app-comp-user-avatar>\n </div>\n </div>\n \x3c!-- 内容 --\x3e\n <div class="message-wrapper">\n <div class="message-content-user">\n <div class="user-message" *ngIf="message?.role === \'user\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-role">\n <div class="role-message" *ngIf="message?.role !== \'user\' && message?.role !== \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-system">\n <div class="system-message" *ngIf="message?.role === \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n </div>\n <div class="chat-time" *ngIf="message?.createdAt" [ngClass]="{\'role-time\': message?.role !== \'user\'}">\n <span>{{message?.createdAt | date:"dd/MM/yyyy, HH/mm/ss a"}}</span>\n </div>\n </div>\n </div> \n </ion-content>\n </ng-template>\n </ion-modal>\n\n \x3c!-- 图片 --\x3e\n <ion-button shape="round" *ngIf="chat?.currentModel?.get(\'config\')?.imageEnabled" fill="outline" slot="end" (click)="setMessageImage()">\n <ion-icon name="image-outline"></ion-icon>\n </ion-button>\n \x3c!-- 模型 --\x3e\n @if(!chat?.hideModalSelect){\n <ion-button shape="round" fill="outline" slot="end" id="model-button">\n <ion-icon name="chevron-down-outline"></ion-icon>\n {{chat?.currentModel?.get&&chat?.currentModel?.get("name")||"飞码4.0"}}\n </ion-button>\n <ion-popover trigger="model-button" [dismissOnSelect]="true">\n <ng-template>\n <ion-content>\n <ion-list>\n <ng-container *ngFor="let model of chat.modelList">\n <ion-item (click)="chat.currentModel = model" [button]="true" [detail]="false">\n {{model?.get("name")}}\n <ion-note slot="end">{{model?.get("credit")}}/k</ion-note>\n </ion-item>\n </ng-container>\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n }\n\n </ion-item>\n\n <ion-item class="input-item" lines="none">\n \x3c!-- 语音消息输入 --\x3e\n <ng-container *ngIf="chat?.isVoiceInputMode">\n \x3c!-- 切换文本输入 --\x3e\n <ion-button class="btn-input-change" color="primary" (click)="chat.isVoiceInputMode=false" shape="round" size="large">\n <ion-icon name="chatbox-ellipses-outline" slot="icon-only"></ion-icon>\n </ion-button>\n \n <div class="btn-voice-start" (click)="startTalk()">\n <span>\n 点击讲话\n </span> \n </div>\n </ng-container>\n\n \x3c!-- 文本消息输入 --\x3e\n <ng-container *ngIf="!chat?.isVoiceInputMode">\n \x3c!-- 切换语音输入 --\x3e\n <ion-button [style.display]="chat.isTexting?\'none\':\'flex\'" class="btn-input-change" color="primary" *ngIf="chat?.role?.get(\'voiceConfig\')" (click)="chat.isVoiceInputMode=true" shape="round" size="large">\n <ion-icon name="mic-outline" slot="icon-only"></ion-icon>\n </ion-button>\n\n \x3c!-- 文本输入区域 --\x3e\n <ion-textarea\n #userInput\n *ngIf="chat" (keydown)="onKeyDown($event)"\n [errorText]="errorText"\n [(ngModel)]="chat.userInput"\n (ionFocus)="onInputFocus()"\n (ionBlur)="chat.isTexting=false"\n [autoGrow]="true" shape="round" fill="outline"\n label="Ctrl + Enter 发送消息" placeholder="请输入您的提示词"\n labelPlacement="floating"></ion-textarea>\n \n \x3c!-- 文本发送按钮 --\x3e\n <ion-button color="primary" shape="round" size="large" (click)="sendMessage()">\n <ion-icon name="paper-plane-outline" slot="icon-only"></ion-icon>\n </ion-button>\n </ng-container>\n </ion-item>\n</ion-toolbar>\n\n\n\x3c!-- 语音消息输入:弹出区域 --\x3e\n\x3c!-- <ion-modal #audioModal [isOpen]="isAudioModal" (willDismiss)="closeAudio()" [initialBreakpoint]="audioModalHeightPoint" [breakpoints]="[0, audioModalHeightPoint]">\n <ng-template>\n <fm-modal-audio-message #audioComp *ngIf="isAudioModal" [chat]="chat" [modal]="audioModal"></fm-modal-audio-message>\n </ng-template>\n</ion-modal> --\x3e',styles:['@charset "UTF-8";:host-context(body.dark) .btn-voice-start{background-color:#222428;color:#fff}:host-context(body.dark) ion-textarea{background-color:#222428;color:#fff}ion-toolbar{--background:none}ion-toolbar .button-item{--inner-padding-start:5px;--inner-padding-end:0px;--padding-start:5px;--padding-end:0px}ion-toolbar ion-item{--background:transparent}.avatar{border-radius:50%;width:32px;height:32px;object-fit:cover}ion-textarea.custom{--background: #373737;--color: #fff;--padding-end: 10px;--padding-start: 10px;--placeholder-color: #ddd;--placeholder-opacity: .8}ion-textarea.custom textarea{width:calc(100% - 95px)}ion-textarea.custom ion-button{position:absolute;right:0}.input-item{display:flex;min-height:77px;align-items:center;border:none;--inner-padding-start:0px;--inner-padding-end:0px;--padding-start:0px;--padding-end:0px}.input-item ion-textarea{background-color:#fff;max-height:400px;padding:0 5px;margin:0 5px;border-radius:20px;overflow-y:auto}.input-item .btn-voice-start{display:flex;flex:1;justify-content:center;align-items:center;font-weight:700;background:#fff;border-radius:20px;min-height:50px}ion-textarea{transition:width .5s ease}ion-textarea:hover .btn-input-change,ion-textarea:focus-within .btn-input-change{display:none}.input-item:hover ion-textarea,.input-item:focus-within ion-textarea{border-color:var(--logo-color-primary)}::ng-deep .ant-modal-body{max-height:600px;overflow-y:auto}::ng-deep .ant-modal-footer{display:flex;justify-content:space-around}::ng-deep .ant-btn{width:40%}.popup-content{position:relative}.popup-content .message-content-user{display:flex;justify-content:flex-end}.popup-content .message-content-role{display:flex;justify-content:flex-start}.popup-content .message-content-system{display:flex;justify-content:center}.popup-content .user-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#e7f8ff}.popup-content .role-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#f6f6f6}.popup-content .user-question{margin-bottom:5px;display:flex;justify-content:flex-end}.popup-content .chat-time{margin-bottom:10px;display:flex;justify-content:flex-end;font-size:14px;color:#a3a3a3}.popup-content .role-time{justify-content:flex-start}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i7.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:i7.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i7.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i7.DatePipe,name:"date"},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i8.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i8.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"ngmodule",type:RouterModule},{kind:"component",type:IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:IonButton,selector:"ion-button",inputs:["buttonType","color","disabled","download","expand","fill","form","href","mode","rel","routerAnimation","routerDirection","shape","size","strong","target","type"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:IonModal,selector:"ion-modal"},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonTextarea,selector:"ion-textarea",inputs:["autoGrow","autocapitalize","autofocus","clearOnEdit","color","cols","counter","counterFormatter","debounce","disabled","enterkeyhint","errorText","fill","helperText","inputmode","label","labelPlacement","maxlength","minlength","mode","name","placeholder","readonly","required","rows","shape","spellcheck","value","wrap"]},{kind:"component",type:IonPopover,selector:"ion-popover"},{kind:"component",type:IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:FmChatMessageCard,selector:"fm-chat-message-card",inputs:["index","message","role","chat"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatModalInput,decorators:[{type:Component,args:[{selector:"fm-chat-modal-input",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,RouterModule,IonToolbar,IonItem,IonButton,IonList,IonModal,IonInput,IonIcon,IonTextarea,IonPopover,IonContent,FmChatMessageCard,ModalAudioMessageComponent],template:'<ion-toolbar>\n <ion-item class="button-item" lines="none">\n \x3c!-- 设置 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="settings-outline"></ion-icon> \n </ion-button> --\x3e\n <ng-container *ngFor="let button of chat?.leftButtons">\n <ion-button style="--padding-start:10px;--padding-end:10px;"\n shape="round" *ngIf="button.show()" fill="outline" [title]="button?.title" slot="start" (click)="button.onClick()">\n <ion-icon [name]="button?.icon" [slot]="button?.showTitle?\'start\':\'icon-only\'"></ion-icon>\n {{button?.showTitle&&button?.title}}\n </ion-button>\n </ng-container>\n\n <ng-container *ngFor="let button of chat?.role?.get(\'buttons\')">\n <ion-button shape="round" (click)="chatServ.doButtonAction(button)" fill="outline" slot="start">\n {{button?.name}}\n </ion-button>\n </ng-container>\n\n \x3c!--分享按钮--\x3e\n @if(!chat?.hideShare){\n <ion-button shape="round" *ngIf="chat?.messageList?.length>1" (click)="showShare()" fill="outline" title="分享" slot="end">\n <ion-icon name="share-social-outline"></ion-icon>\n </ion-button>\n }\n \x3c!-- <button nz-button *ngIf="chat?.messageList?.length>1"\n nzType="primary" title="分享" (click)="showShare()" style="width: 31.188px;height: 22px;box-shadow: none;background: #fff;border: 1px solid #4588ff;border-radius: 5px;"> <span class="iconfont icon-fenxiang" style="color: #4588ff;"></span></button>\n --\x3e\n <ion-modal [isOpen]="isShare">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="handleCancelShare()">取消</ion-button>\n </ion-buttons>\n <ion-title>对话分享</ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="handleOkShare()">分享</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n <ng-container *ngFor="let message of chat?.messageList;let index=index;">\n \x3c!-- 内容格式化区域 --\x3e\n <fm-chat-message-card [chat]="chat" *ngIf="!message?.hidden" [index]="index" [message]="message" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n\n <div *ngIf="false" class="popup-content">\n <div *ngFor="let message of chat?.messageList">\n \x3c!-- 头像 --\x3e\n <div class="item-row user" *ngIf="message?.role!=\'system\'">\n <div>\n <img class="avatar" *ngIf="message?.role!=\'user\'" [src]="(chat?.role?.get(\'avatar\') || chat?.role?.get(\'thumb\') || \'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png\')+\'?\'+\'x-image-process=image/resize,m_fixed,w_100\'+\'&imageView2/1/w/32/h/32\'" >\n \x3c!-- <nz-avatar *ngIf="message?.role!=\'user\'" [nzSrc]="(chat?.role?.get(\'avatar\') || chat?.role?.get(\'thumb\') || \'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png\')+\'?\'+\'x-image-process=image/resize,m_fixed,w_100\'+\'&imageView2/1/w/32/h/32\'"></nz-avatar> --\x3e\n </div>\n <div class="user-question">\n <app-comp-user-avatar [user]="user" *ngIf="message?.role==\'user\'"></app-comp-user-avatar>\n </div>\n </div>\n \x3c!-- 内容 --\x3e\n <div class="message-wrapper">\n <div class="message-content-user">\n <div class="user-message" *ngIf="message?.role === \'user\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-role">\n <div class="role-message" *ngIf="message?.role !== \'user\' && message?.role !== \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-system">\n <div class="system-message" *ngIf="message?.role === \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n </div>\n <div class="chat-time" *ngIf="message?.createdAt" [ngClass]="{\'role-time\': message?.role !== \'user\'}">\n <span>{{message?.createdAt | date:"dd/MM/yyyy, HH/mm/ss a"}}</span>\n </div>\n </div>\n </div> \n </ion-content>\n </ng-template>\n </ion-modal>\n\n \x3c!-- 图片 --\x3e\n <ion-button shape="round" *ngIf="chat?.currentModel?.get(\'config\')?.imageEnabled" fill="outline" slot="end" (click)="setMessageImage()">\n <ion-icon name="image-outline"></ion-icon>\n </ion-button>\n \x3c!-- 模型 --\x3e\n @if(!chat?.hideModalSelect){\n <ion-button shape="round" fill="outline" slot="end" id="model-button">\n <ion-icon name="chevron-down-outline"></ion-icon>\n {{chat?.currentModel?.get&&chat?.currentModel?.get("name")||"飞码4.0"}}\n </ion-button>\n <ion-popover trigger="model-button" [dismissOnSelect]="true">\n <ng-template>\n <ion-content>\n <ion-list>\n <ng-container *ngFor="let model of chat.modelList">\n <ion-item (click)="chat.currentModel = model" [button]="true" [detail]="false">\n {{model?.get("name")}}\n <ion-note slot="end">{{model?.get("credit")}}/k</ion-note>\n </ion-item>\n </ng-container>\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n }\n\n </ion-item>\n\n <ion-item class="input-item" lines="none">\n \x3c!-- 语音消息输入 --\x3e\n <ng-container *ngIf="chat?.isVoiceInputMode">\n \x3c!-- 切换文本输入 --\x3e\n <ion-button class="btn-input-change" color="primary" (click)="chat.isVoiceInputMode=false" shape="round" size="large">\n <ion-icon name="chatbox-ellipses-outline" slot="icon-only"></ion-icon>\n </ion-button>\n \n <div class="btn-voice-start" (click)="startTalk()">\n <span>\n 点击讲话\n </span> \n </div>\n </ng-container>\n\n \x3c!-- 文本消息输入 --\x3e\n <ng-container *ngIf="!chat?.isVoiceInputMode">\n \x3c!-- 切换语音输入 --\x3e\n <ion-button [style.display]="chat.isTexting?\'none\':\'flex\'" class="btn-input-change" color="primary" *ngIf="chat?.role?.get(\'voiceConfig\')" (click)="chat.isVoiceInputMode=true" shape="round" size="large">\n <ion-icon name="mic-outline" slot="icon-only"></ion-icon>\n </ion-button>\n\n \x3c!-- 文本输入区域 --\x3e\n <ion-textarea\n #userInput\n *ngIf="chat" (keydown)="onKeyDown($event)"\n [errorText]="errorText"\n [(ngModel)]="chat.userInput"\n (ionFocus)="onInputFocus()"\n (ionBlur)="chat.isTexting=false"\n [autoGrow]="true" shape="round" fill="outline"\n label="Ctrl + Enter 发送消息" placeholder="请输入您的提示词"\n labelPlacement="floating"></ion-textarea>\n \n \x3c!-- 文本发送按钮 --\x3e\n <ion-button color="primary" shape="round" size="large" (click)="sendMessage()">\n <ion-icon name="paper-plane-outline" slot="icon-only"></ion-icon>\n </ion-button>\n </ng-container>\n </ion-item>\n</ion-toolbar>\n\n\n\x3c!-- 语音消息输入:弹出区域 --\x3e\n\x3c!-- <ion-modal #audioModal [isOpen]="isAudioModal" (willDismiss)="closeAudio()" [initialBreakpoint]="audioModalHeightPoint" [breakpoints]="[0, audioModalHeightPoint]">\n <ng-template>\n <fm-modal-audio-message #audioComp *ngIf="isAudioModal" [chat]="chat" [modal]="audioModal"></fm-modal-audio-message>\n </ng-template>\n</ion-modal> --\x3e',styles:['@charset "UTF-8";:host-context(body.dark) .btn-voice-start{background-color:#222428;color:#fff}:host-context(body.dark) ion-textarea{background-color:#222428;color:#fff}ion-toolbar{--background:none}ion-toolbar .button-item{--inner-padding-start:5px;--inner-padding-end:0px;--padding-start:5px;--padding-end:0px}ion-toolbar ion-item{--background:transparent}.avatar{border-radius:50%;width:32px;height:32px;object-fit:cover}ion-textarea.custom{--background: #373737;--color: #fff;--padding-end: 10px;--padding-start: 10px;--placeholder-color: #ddd;--placeholder-opacity: .8}ion-textarea.custom textarea{width:calc(100% - 95px)}ion-textarea.custom ion-button{position:absolute;right:0}.input-item{display:flex;min-height:77px;align-items:center;border:none;--inner-padding-start:0px;--inner-padding-end:0px;--padding-start:0px;--padding-end:0px}.input-item ion-textarea{background-color:#fff;max-height:400px;padding:0 5px;margin:0 5px;border-radius:20px;overflow-y:auto}.input-item .btn-voice-start{display:flex;flex:1;justify-content:center;align-items:center;font-weight:700;background:#fff;border-radius:20px;min-height:50px}ion-textarea{transition:width .5s ease}ion-textarea:hover .btn-input-change,ion-textarea:focus-within .btn-input-change{display:none}.input-item:hover ion-textarea,.input-item:focus-within ion-textarea{border-color:var(--logo-color-primary)}::ng-deep .ant-modal-body{max-height:600px;overflow-y:auto}::ng-deep .ant-modal-footer{display:flex;justify-content:space-around}::ng-deep .ant-btn{width:40%}.popup-content{position:relative}.popup-content .message-content-user{display:flex;justify-content:flex-end}.popup-content .message-content-role{display:flex;justify-content:flex-start}.popup-content .message-content-system{display:flex;justify-content:center}.popup-content .user-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#e7f8ff}.popup-content .role-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#f6f6f6}.popup-content .user-question{margin-bottom:5px;display:flex;justify-content:flex-end}.popup-content .chat-time{margin-bottom:10px;display:flex;justify-content:flex-end;font-size:14px;color:#a3a3a3}.popup-content .role-time{justify-content:flex-start}\n']}]}],ctorParameters:()=>[{type:i1.ToastController},{type:i1.AlertController},{type:i2.ModalController},{type:i1.NavController},{type:i3.Router},{type:i4.ImagineService},{type:i5.ChatService},{type:i3.ActivatedRoute},{type:i6.NzMessageService}],propDecorators:{audioComp:[{type:ViewChild,args:[ModalAudioMessageComponent]}],userInputComp:[{type:ViewChild,args:["userInput"]}],chat:[{type:Input}],message:[{type:Input}],role:[{type:Input}]}});
8
+ import{Component,Input,ViewChild}from"@angular/core";import{ActivatedRoute,Router,RouterModule}from"@angular/router";import{AlertController,NavController,ToastController}from"@ionic/angular";import{FmodeChat}from"../../service-fmai/service-chat";import{ChatService}from"../../service-fmai/service-chat";import Parse from"parse";import{NzMessageService}from"ng-zorro-antd/message";import{ImagineService}from"../../service-fmai/service-imagine/imagine.service";import{IonButton,IonContent,IonIcon,IonInput,IonItem,IonList,IonModal,IonPopover,IonTextarea,IonToolbar,ModalController}from"@ionic/angular/standalone";import{CommonModule}from"@angular/common";import{FormsModule,ReactiveFormsModule}from"@angular/forms";import{ModalAudioMessageComponent}from"./modal-audio-message/modal-audio-message.component";import{FmChatMessageCard}from"../chat-message-card/comp-message-card.component";import{addIcons}from"ionicons";import{imageOutline,chevronBackOutline,ellipsisHorizontalOutline,chevronDownOutline,chatboxEllipsesOutline,micOutline,paperPlaneOutline,shareSocialOutline,settingsOutline,alertOutline,colorWandOutline,peopleOutline}from"ionicons/icons/index.mjs";import{AccountService}from"../../../user/account/account.service";import*as i0 from"@angular/core";import*as i1 from"@ionic/angular";import*as i2 from"@ionic/angular/standalone";import*as i3 from"@angular/router";import*as i4 from"../../service-fmai/service-imagine/imagine.service";import*as i5 from"../../service-fmai/service-chat";import*as i6 from"../../../user/account/account.service";import*as i7 from"ng-zorro-antd/message";import*as i8 from"@angular/common";import*as i9 from"@angular/forms";addIcons({colorWandOutline:colorWandOutline,peopleOutline:peopleOutline,alertOutline:alertOutline,imageOutline:imageOutline,chevronBackOutline:chevronBackOutline,ellipsisHorizontalOutline:ellipsisHorizontalOutline,chevronDownOutline:chevronDownOutline,chatboxEllipsesOutline:chatboxEllipsesOutline,micOutline:micOutline,paperPlaneOutline:paperPlaneOutline,shareSocialOutline:shareSocialOutline,settingsOutline:settingsOutline});export class FmChatModalInput{closeAudio(){this.audioComp?.cancel(),this.isAudioModal=!1}async startTalk(){let e,n=document.body.clientHeight||960;this.audioModalHeightPoint=Number((165/n).toFixed(2)),this.chat.stopPlayingVoice(),e=await this.modalCtrl.create({component:ModalAudioMessageComponent,componentProps:{chat:this.chat,modal:e,onBreakPointSet:()=>{e?.setCurrentBreakpoint(this.audioModalHeightPoint)}},breakpoints:[this.audioModalHeightPoint],initialBreakpoint:this.audioModalHeightPoint}),e.present()}constructor(e,n,t,o,i,a,s,r,l,c){this.toastCtrl=e,this.alertCtrl=n,this.modalCtrl=t,this.navCtrl=o,this.router=i,this.imagineServ=a,this.chatServ=s,this.account=r,this.route=l,this.messages=c,this.errorText="",this.isAudioModal=!1,this.audioModalHeightPoint=.35,this.isShare=!1,this.user=Parse.User.current()}ngOnInit(){this.loadModel();let e=this;this.chat.focusUserInput=()=>{e.chat.isVoiceInputMode=!1,e.userInputComp.setFocus()}}async loadModel(){let e=this.chat?.role?.get("model");await this.chat.loadModelList(e)}async setMessageImage(){let e=await this.imagineServ.getimg();this.chat.userImage=e,console.log(this.chat?.userImage)}onInputFocus(){this.chat.isTexting=!0,this.chat.scrollToBottom&&this.chat.scrollToBottom()}onKeyDown(e){e.ctrlKey&&"Enter"===e.key&&(console.log("Ctrl+Enter 被按下"),this.sendMessage())}async sendMessage(){if(!await this.checkBalance())return!1;if(!this.chat.userInput){return this.errorText="内容不能为空",void(await this.toastCtrl.create({message:this.errorText,position:"top",icon:"alert",color:"warning-circle",duration:1e3})).present()}this.chat?.sendMessage(this.chat?.userInput,this.chat?.userImage,(e=>{}),{onSSMLComplete:e=>{console.log(e)}}),this.chat.userInput="",this.chat.userImage=""}async checkBalance(){let e=await this.account.getBilling();if(e?.credit?.balance>=10&&(this.chat.isDirect=!0),!this.chat?.currentModel?.get("payLimit"))return!0;if(e?.credit?.balance<10){return(await this.alertCtrl.create({header:"注意",subHeader:"您的余额不足,请充值后解锁高级模型",buttons:[{role:"cancel",text:"取消"},{role:"destructive",text:"充值",handler:()=>{this.router.navigateByUrl("/account/billing")}}]})).present(),!1}return!0}async getChatShare(){this.user=Parse.User.current();let e=new Parse.Query("ChatShare");e.equalTo("user",Parse.User.current().id),e.equalTo("session",this.chat?.sessionId);await e.first()}async toggleChatShare(){let e=new Parse.Query("ChatShare");e.equalTo("user",Parse.User.current().id),e.equalTo("role",this.chat?.role.id),e.equalTo("session",this.chat?.sessionId),e.select("objectId");let n=await e.first();if(n?.id)n.set("messageList",this.chat?.messageList);else{n=new(Parse.Object.extend("ChatShare")),n.set("user",{__type:"Pointer",className:"_User",objectId:Parse.User.current()?.id}),n.set("session",{__type:"Pointer",className:"ChatSession",objectId:this.chat?.sessionId}),n.set("role",{__type:"Pointer",className:"AvatarRole",objectId:this.chat?.role.id}),n.set("company",{__type:"Pointer",className:"Company",objectId:"E4KpGvTEto"}),n.set("messageList",this.chat?.messageList)}await n.save(),this.getChatShare()}chatShareSuccessMessage(){this.messages.success("分享成功")}showShare(){this.isShare=!0}handleOkShare(){this.toggleChatShare(),this.chatShareSuccessMessage(),this.isShare=!1}handleCancelShare(){this.isShare=!1}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatModalInput,deps:[{token:i1.ToastController},{token:i1.AlertController},{token:i2.ModalController},{token:i1.NavController},{token:i3.Router},{token:i4.ImagineService},{token:i5.ChatService},{token:i6.AccountService},{token:i3.ActivatedRoute},{token:i7.NzMessageService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:FmChatModalInput,isStandalone:!0,selector:"fm-chat-modal-input",inputs:{chat:"chat",message:"message",role:"role"},viewQueries:[{propertyName:"audioComp",first:!0,predicate:ModalAudioMessageComponent,descendants:!0},{propertyName:"userInputComp",first:!0,predicate:["userInput"],descendants:!0}],ngImport:i0,template:'<ion-toolbar>\n <ion-item class="button-item" lines="none">\n \x3c!-- 设置 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="settings-outline"></ion-icon> \n </ion-button> --\x3e\n <ng-container *ngFor="let button of chat?.leftButtons">\n <ion-button style="--padding-start:10px;--padding-end:10px;"\n shape="round" *ngIf="button.show()" fill="outline" [title]="button?.title" slot="start" (click)="button.onClick()">\n <ion-icon [name]="button?.icon" [slot]="button?.showTitle?\'start\':\'icon-only\'"></ion-icon>\n {{button?.showTitle&&button?.title}}\n </ion-button>\n </ng-container>\n\n <ng-container *ngFor="let button of chat?.role?.get(\'buttons\')">\n <ion-button shape="round" (click)="chatServ.doButtonAction(button)" fill="outline" slot="start">\n {{button?.name}}\n </ion-button>\n </ng-container>\n\n \x3c!--分享按钮--\x3e\n @if(!chat?.hideShare){\n <ion-button shape="round" *ngIf="chat?.messageList?.length>1" (click)="showShare()" fill="outline" title="分享" slot="end">\n <ion-icon name="share-social-outline"></ion-icon>\n </ion-button>\n }\n \x3c!-- <button nz-button *ngIf="chat?.messageList?.length>1"\n nzType="primary" title="分享" (click)="showShare()" style="width: 31.188px;height: 22px;box-shadow: none;background: #fff;border: 1px solid #4588ff;border-radius: 5px;"> <span class="iconfont icon-fenxiang" style="color: #4588ff;"></span></button>\n --\x3e\n <ion-modal [isOpen]="isShare">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="handleCancelShare()">取消</ion-button>\n </ion-buttons>\n <ion-title>对话分享</ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="handleOkShare()">分享</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n <ng-container *ngFor="let message of chat?.messageList;let index=index;">\n \x3c!-- 内容格式化区域 --\x3e\n <fm-chat-message-card [chat]="chat" *ngIf="!message?.hidden" [index]="index" [message]="message" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n\n <div *ngIf="false" class="popup-content">\n <div *ngFor="let message of chat?.messageList">\n \x3c!-- 头像 --\x3e\n <div class="item-row user" *ngIf="message?.role!=\'system\'">\n <div>\n <img class="avatar" *ngIf="message?.role!=\'user\'" [src]="(chat?.role?.get(\'avatar\') || chat?.role?.get(\'thumb\') || \'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png\')+\'?\'+\'x-image-process=image/resize,m_fixed,w_100\'+\'&imageView2/1/w/32/h/32\'" >\n \x3c!-- <nz-avatar *ngIf="message?.role!=\'user\'" [nzSrc]="(chat?.role?.get(\'avatar\') || chat?.role?.get(\'thumb\') || \'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png\')+\'?\'+\'x-image-process=image/resize,m_fixed,w_100\'+\'&imageView2/1/w/32/h/32\'"></nz-avatar> --\x3e\n </div>\n <div class="user-question">\n <app-comp-user-avatar [user]="user" *ngIf="message?.role==\'user\'"></app-comp-user-avatar>\n </div>\n </div>\n \x3c!-- 内容 --\x3e\n <div class="message-wrapper">\n <div class="message-content-user">\n <div class="user-message" *ngIf="message?.role === \'user\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-role">\n <div class="role-message" *ngIf="message?.role !== \'user\' && message?.role !== \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-system">\n <div class="system-message" *ngIf="message?.role === \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n </div>\n <div class="chat-time" *ngIf="message?.createdAt" [ngClass]="{\'role-time\': message?.role !== \'user\'}">\n <span>{{message?.createdAt | date:"dd/MM/yyyy, HH/mm/ss a"}}</span>\n </div>\n </div>\n </div> \n </ion-content>\n </ng-template>\n </ion-modal>\n\n \x3c!-- 图片 --\x3e\n <ion-button shape="round" *ngIf="chat?.currentModel?.get(\'config\')?.imageEnabled" fill="outline" slot="end" (click)="setMessageImage()">\n <ion-icon name="image-outline"></ion-icon>\n </ion-button>\n \x3c!-- 模型 --\x3e\n @if(!chat?.hideModalSelect){\n <ion-button shape="round" fill="outline" slot="end" id="model-button">\n <ion-icon name="chevron-down-outline"></ion-icon>\n {{chat?.currentModel?.get&&chat?.currentModel?.get("name")||"Fmode-C1.0-128k"}}\n </ion-button>\n <ion-popover trigger="model-button" [dismissOnSelect]="true">\n <ng-template>\n <ion-content>\n <ion-list>\n <ng-container *ngFor="let model of chat.modelList">\n <ion-item (click)="chat.currentModel = model" [button]="true" [detail]="false">\n {{model?.get("name")}}\n <ion-note slot="end">{{model?.get("credit")}}/k</ion-note>\n </ion-item>\n </ng-container>\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n }\n\n </ion-item>\n\n <ion-item class="input-item" lines="none">\n \x3c!-- 语音消息输入 --\x3e\n <ng-container *ngIf="chat?.isVoiceInputMode">\n \x3c!-- 切换文本输入 --\x3e\n <ion-button class="btn-input-change" color="primary" (click)="chat.isVoiceInputMode=false" shape="round" size="large">\n <ion-icon name="chatbox-ellipses-outline" slot="icon-only"></ion-icon>\n </ion-button>\n \n <div class="btn-voice-start" (click)="startTalk()">\n <span>\n 点击讲话\n </span> \n </div>\n </ng-container>\n\n \x3c!-- 文本消息输入 --\x3e\n <ng-container *ngIf="!chat?.isVoiceInputMode">\n \x3c!-- 切换语音输入 --\x3e\n <ion-button [style.display]="chat.isTexting?\'none\':\'flex\'" class="btn-input-change" color="primary" *ngIf="chat?.role?.get(\'voiceConfig\')" (click)="chat.isVoiceInputMode=true" shape="round" size="large">\n <ion-icon name="mic-outline" slot="icon-only"></ion-icon>\n </ion-button>\n\n \x3c!-- 文本输入区域 --\x3e\n <ion-textarea\n #userInput\n *ngIf="chat" (keydown)="onKeyDown($event)"\n [errorText]="errorText"\n [(ngModel)]="chat.userInput"\n (ionFocus)="onInputFocus()"\n (ionBlur)="chat.isTexting=false"\n [autoGrow]="true" shape="round" fill="outline"\n label="Ctrl + Enter 发送消息" placeholder="请输入您的提示词"\n labelPlacement="floating"></ion-textarea>\n \n \x3c!-- 文本发送按钮 --\x3e\n <ion-button color="primary" shape="round" size="large" (click)="sendMessage()">\n <ion-icon name="paper-plane-outline" slot="icon-only"></ion-icon>\n </ion-button>\n </ng-container>\n </ion-item>\n</ion-toolbar>\n\n\n\x3c!-- 语音消息输入:弹出区域 --\x3e\n\x3c!-- <ion-modal #audioModal [isOpen]="isAudioModal" (willDismiss)="closeAudio()" [initialBreakpoint]="audioModalHeightPoint" [breakpoints]="[0, audioModalHeightPoint]">\n <ng-template>\n <fm-modal-audio-message #audioComp *ngIf="isAudioModal" [chat]="chat" [modal]="audioModal"></fm-modal-audio-message>\n </ng-template>\n</ion-modal> --\x3e',styles:['@charset "UTF-8";:host-context(body.dark) .btn-voice-start{background-color:#222428;color:#fff}:host-context(body.dark) ion-textarea{background-color:#222428;color:#fff}ion-toolbar{--background:none}ion-toolbar .button-item{--inner-padding-start:5px;--inner-padding-end:0px;--padding-start:5px;--padding-end:0px}ion-toolbar ion-item{--background:transparent}.avatar{border-radius:50%;width:32px;height:32px;object-fit:cover}ion-textarea.custom{--background: #373737;--color: #fff;--padding-end: 10px;--padding-start: 10px;--placeholder-color: #ddd;--placeholder-opacity: .8}ion-textarea.custom textarea{width:calc(100% - 95px)}ion-textarea.custom ion-button{position:absolute;right:0}.input-item{display:flex;min-height:77px;align-items:center;border:none;--inner-padding-start:0px;--inner-padding-end:0px;--padding-start:0px;--padding-end:0px}.input-item ion-textarea{background-color:#fff;max-height:400px;padding:0 5px;margin:0 5px;border-radius:20px;overflow-y:auto}.input-item .btn-voice-start{display:flex;flex:1;justify-content:center;align-items:center;font-weight:700;background:#fff;border-radius:20px;min-height:50px}ion-textarea{transition:width .5s ease}ion-textarea:hover .btn-input-change,ion-textarea:focus-within .btn-input-change{display:none}.input-item:hover ion-textarea,.input-item:focus-within ion-textarea{border-color:var(--logo-color-primary)}::ng-deep .ant-modal-body{max-height:600px;overflow-y:auto}::ng-deep .ant-modal-footer{display:flex;justify-content:space-around}::ng-deep .ant-btn{width:40%}.popup-content{position:relative}.popup-content .message-content-user{display:flex;justify-content:flex-end}.popup-content .message-content-role{display:flex;justify-content:flex-start}.popup-content .message-content-system{display:flex;justify-content:center}.popup-content .user-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#e7f8ff}.popup-content .role-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#f6f6f6}.popup-content .user-question{margin-bottom:5px;display:flex;justify-content:flex-end}.popup-content .chat-time{margin-bottom:10px;display:flex;justify-content:flex-end;font-size:14px;color:#a3a3a3}.popup-content .role-time{justify-content:flex-start}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i8.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:i8.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i8.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i8.DatePipe,name:"date"},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i9.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i9.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"ngmodule",type:RouterModule},{kind:"component",type:IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:IonButton,selector:"ion-button",inputs:["buttonType","color","disabled","download","expand","fill","form","href","mode","rel","routerAnimation","routerDirection","shape","size","strong","target","type"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:IonModal,selector:"ion-modal"},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonTextarea,selector:"ion-textarea",inputs:["autoGrow","autocapitalize","autofocus","clearOnEdit","color","cols","counter","counterFormatter","debounce","disabled","enterkeyhint","errorText","fill","helperText","inputmode","label","labelPlacement","maxlength","minlength","mode","name","placeholder","readonly","required","rows","shape","spellcheck","value","wrap"]},{kind:"component",type:IonPopover,selector:"ion-popover"},{kind:"component",type:IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:FmChatMessageCard,selector:"fm-chat-message-card",inputs:["index","message","role","chat"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatModalInput,decorators:[{type:Component,args:[{selector:"fm-chat-modal-input",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,RouterModule,IonToolbar,IonItem,IonButton,IonList,IonModal,IonInput,IonIcon,IonTextarea,IonPopover,IonContent,FmChatMessageCard,ModalAudioMessageComponent],template:'<ion-toolbar>\n <ion-item class="button-item" lines="none">\n \x3c!-- 设置 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="settings-outline"></ion-icon> \n </ion-button> --\x3e\n <ng-container *ngFor="let button of chat?.leftButtons">\n <ion-button style="--padding-start:10px;--padding-end:10px;"\n shape="round" *ngIf="button.show()" fill="outline" [title]="button?.title" slot="start" (click)="button.onClick()">\n <ion-icon [name]="button?.icon" [slot]="button?.showTitle?\'start\':\'icon-only\'"></ion-icon>\n {{button?.showTitle&&button?.title}}\n </ion-button>\n </ng-container>\n\n <ng-container *ngFor="let button of chat?.role?.get(\'buttons\')">\n <ion-button shape="round" (click)="chatServ.doButtonAction(button)" fill="outline" slot="start">\n {{button?.name}}\n </ion-button>\n </ng-container>\n\n \x3c!--分享按钮--\x3e\n @if(!chat?.hideShare){\n <ion-button shape="round" *ngIf="chat?.messageList?.length>1" (click)="showShare()" fill="outline" title="分享" slot="end">\n <ion-icon name="share-social-outline"></ion-icon>\n </ion-button>\n }\n \x3c!-- <button nz-button *ngIf="chat?.messageList?.length>1"\n nzType="primary" title="分享" (click)="showShare()" style="width: 31.188px;height: 22px;box-shadow: none;background: #fff;border: 1px solid #4588ff;border-radius: 5px;"> <span class="iconfont icon-fenxiang" style="color: #4588ff;"></span></button>\n --\x3e\n <ion-modal [isOpen]="isShare">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="handleCancelShare()">取消</ion-button>\n </ion-buttons>\n <ion-title>对话分享</ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="handleOkShare()">分享</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n <ng-container *ngFor="let message of chat?.messageList;let index=index;">\n \x3c!-- 内容格式化区域 --\x3e\n <fm-chat-message-card [chat]="chat" *ngIf="!message?.hidden" [index]="index" [message]="message" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n\n <div *ngIf="false" class="popup-content">\n <div *ngFor="let message of chat?.messageList">\n \x3c!-- 头像 --\x3e\n <div class="item-row user" *ngIf="message?.role!=\'system\'">\n <div>\n <img class="avatar" *ngIf="message?.role!=\'user\'" [src]="(chat?.role?.get(\'avatar\') || chat?.role?.get(\'thumb\') || \'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png\')+\'?\'+\'x-image-process=image/resize,m_fixed,w_100\'+\'&imageView2/1/w/32/h/32\'" >\n \x3c!-- <nz-avatar *ngIf="message?.role!=\'user\'" [nzSrc]="(chat?.role?.get(\'avatar\') || chat?.role?.get(\'thumb\') || \'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png\')+\'?\'+\'x-image-process=image/resize,m_fixed,w_100\'+\'&imageView2/1/w/32/h/32\'"></nz-avatar> --\x3e\n </div>\n <div class="user-question">\n <app-comp-user-avatar [user]="user" *ngIf="message?.role==\'user\'"></app-comp-user-avatar>\n </div>\n </div>\n \x3c!-- 内容 --\x3e\n <div class="message-wrapper">\n <div class="message-content-user">\n <div class="user-message" *ngIf="message?.role === \'user\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-role">\n <div class="role-message" *ngIf="message?.role !== \'user\' && message?.role !== \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-system">\n <div class="system-message" *ngIf="message?.role === \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n </div>\n <div class="chat-time" *ngIf="message?.createdAt" [ngClass]="{\'role-time\': message?.role !== \'user\'}">\n <span>{{message?.createdAt | date:"dd/MM/yyyy, HH/mm/ss a"}}</span>\n </div>\n </div>\n </div> \n </ion-content>\n </ng-template>\n </ion-modal>\n\n \x3c!-- 图片 --\x3e\n <ion-button shape="round" *ngIf="chat?.currentModel?.get(\'config\')?.imageEnabled" fill="outline" slot="end" (click)="setMessageImage()">\n <ion-icon name="image-outline"></ion-icon>\n </ion-button>\n \x3c!-- 模型 --\x3e\n @if(!chat?.hideModalSelect){\n <ion-button shape="round" fill="outline" slot="end" id="model-button">\n <ion-icon name="chevron-down-outline"></ion-icon>\n {{chat?.currentModel?.get&&chat?.currentModel?.get("name")||"Fmode-C1.0-128k"}}\n </ion-button>\n <ion-popover trigger="model-button" [dismissOnSelect]="true">\n <ng-template>\n <ion-content>\n <ion-list>\n <ng-container *ngFor="let model of chat.modelList">\n <ion-item (click)="chat.currentModel = model" [button]="true" [detail]="false">\n {{model?.get("name")}}\n <ion-note slot="end">{{model?.get("credit")}}/k</ion-note>\n </ion-item>\n </ng-container>\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n }\n\n </ion-item>\n\n <ion-item class="input-item" lines="none">\n \x3c!-- 语音消息输入 --\x3e\n <ng-container *ngIf="chat?.isVoiceInputMode">\n \x3c!-- 切换文本输入 --\x3e\n <ion-button class="btn-input-change" color="primary" (click)="chat.isVoiceInputMode=false" shape="round" size="large">\n <ion-icon name="chatbox-ellipses-outline" slot="icon-only"></ion-icon>\n </ion-button>\n \n <div class="btn-voice-start" (click)="startTalk()">\n <span>\n 点击讲话\n </span> \n </div>\n </ng-container>\n\n \x3c!-- 文本消息输入 --\x3e\n <ng-container *ngIf="!chat?.isVoiceInputMode">\n \x3c!-- 切换语音输入 --\x3e\n <ion-button [style.display]="chat.isTexting?\'none\':\'flex\'" class="btn-input-change" color="primary" *ngIf="chat?.role?.get(\'voiceConfig\')" (click)="chat.isVoiceInputMode=true" shape="round" size="large">\n <ion-icon name="mic-outline" slot="icon-only"></ion-icon>\n </ion-button>\n\n \x3c!-- 文本输入区域 --\x3e\n <ion-textarea\n #userInput\n *ngIf="chat" (keydown)="onKeyDown($event)"\n [errorText]="errorText"\n [(ngModel)]="chat.userInput"\n (ionFocus)="onInputFocus()"\n (ionBlur)="chat.isTexting=false"\n [autoGrow]="true" shape="round" fill="outline"\n label="Ctrl + Enter 发送消息" placeholder="请输入您的提示词"\n labelPlacement="floating"></ion-textarea>\n \n \x3c!-- 文本发送按钮 --\x3e\n <ion-button color="primary" shape="round" size="large" (click)="sendMessage()">\n <ion-icon name="paper-plane-outline" slot="icon-only"></ion-icon>\n </ion-button>\n </ng-container>\n </ion-item>\n</ion-toolbar>\n\n\n\x3c!-- 语音消息输入:弹出区域 --\x3e\n\x3c!-- <ion-modal #audioModal [isOpen]="isAudioModal" (willDismiss)="closeAudio()" [initialBreakpoint]="audioModalHeightPoint" [breakpoints]="[0, audioModalHeightPoint]">\n <ng-template>\n <fm-modal-audio-message #audioComp *ngIf="isAudioModal" [chat]="chat" [modal]="audioModal"></fm-modal-audio-message>\n </ng-template>\n</ion-modal> --\x3e',styles:['@charset "UTF-8";:host-context(body.dark) .btn-voice-start{background-color:#222428;color:#fff}:host-context(body.dark) ion-textarea{background-color:#222428;color:#fff}ion-toolbar{--background:none}ion-toolbar .button-item{--inner-padding-start:5px;--inner-padding-end:0px;--padding-start:5px;--padding-end:0px}ion-toolbar ion-item{--background:transparent}.avatar{border-radius:50%;width:32px;height:32px;object-fit:cover}ion-textarea.custom{--background: #373737;--color: #fff;--padding-end: 10px;--padding-start: 10px;--placeholder-color: #ddd;--placeholder-opacity: .8}ion-textarea.custom textarea{width:calc(100% - 95px)}ion-textarea.custom ion-button{position:absolute;right:0}.input-item{display:flex;min-height:77px;align-items:center;border:none;--inner-padding-start:0px;--inner-padding-end:0px;--padding-start:0px;--padding-end:0px}.input-item ion-textarea{background-color:#fff;max-height:400px;padding:0 5px;margin:0 5px;border-radius:20px;overflow-y:auto}.input-item .btn-voice-start{display:flex;flex:1;justify-content:center;align-items:center;font-weight:700;background:#fff;border-radius:20px;min-height:50px}ion-textarea{transition:width .5s ease}ion-textarea:hover .btn-input-change,ion-textarea:focus-within .btn-input-change{display:none}.input-item:hover ion-textarea,.input-item:focus-within ion-textarea{border-color:var(--logo-color-primary)}::ng-deep .ant-modal-body{max-height:600px;overflow-y:auto}::ng-deep .ant-modal-footer{display:flex;justify-content:space-around}::ng-deep .ant-btn{width:40%}.popup-content{position:relative}.popup-content .message-content-user{display:flex;justify-content:flex-end}.popup-content .message-content-role{display:flex;justify-content:flex-start}.popup-content .message-content-system{display:flex;justify-content:center}.popup-content .user-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#e7f8ff}.popup-content .role-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#f6f6f6}.popup-content .user-question{margin-bottom:5px;display:flex;justify-content:flex-end}.popup-content .chat-time{margin-bottom:10px;display:flex;justify-content:flex-end;font-size:14px;color:#a3a3a3}.popup-content .role-time{justify-content:flex-start}\n']}]}],ctorParameters:()=>[{type:i1.ToastController},{type:i1.AlertController},{type:i2.ModalController},{type:i1.NavController},{type:i3.Router},{type:i4.ImagineService},{type:i5.ChatService},{type:i6.AccountService},{type:i3.ActivatedRoute},{type:i7.NzMessageService}],propDecorators:{audioComp:[{type:ViewChild,args:[ModalAudioMessageComponent]}],userInputComp:[{type:ViewChild,args:["userInput"]}],chat:[{type:Input}],message:[{type:Input}],role:[{type:Input}]}});
9
9
  var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9haWdjL2NoYXQvY2hhdC1tb2RhbC1pbnB1dC9tb2RhbC1pbnB1dC5jb21wb25lbnQubWpz`
10
10
 
@@ -5,6 +5,6 @@
5
5
  * 保留所有权利 All Rights Reserved.
6
6
  * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/aigc/service-fmai/service-chat/chat-class.mjs
7
7
  */
8
- import{bufferTime,concatMap,Observable,delay,finalize}from"rxjs";import Parse from"parse";import{AgentPrompt}from"../../agent";import{FmodeTTS}from"../../voice/tts";import{PromptTemplate}from"@langchain/core/prompts";const API_BASE="https://server.fmode.cn/api/apig/aigc/gpt",agentPrompt=new AgentPrompt,PromptTplTalkSSMLOutputCode="talk-ssml-output-tpl",PromptTplTalkTextSSMLCode="talk-text-ssml-tpl";export function getMessageContentText(t){let e="";return"string"==typeof t&&(e=t),"object"==typeof t&&(e=t?.find((t=>t?.text))?.text||""),e}export function getMessageImageUrl(t){return"object"==typeof t?t?.find((t=>t?.image_url))?.image_url?.url||"":null}export class FmodeChat{async loadModelList(t){if(this.modelList?.length)return;let e=new Parse.Query("ChatModel");e.notEqualTo("isDeleted",!0),e.equalTo("isEnabled",!0),e.addAscending("index"),this.modelList=await e.find(),this.currentModel=t||this.modelList?.find((t=>"fmode-4.5-128k"==t.get("code")))}showAvatar(){this.avatarConfig=this.role?.get("avatarConfig"),this.avatarConfig&&(this.isAvatarShow=!0,this.avatarConfig?.image&&(this.avatarConfig.image.waiting=this.avatarConfig.image.waiting||this.role?.get("thumb")||this.role?.get("avatar"),this.avatarMode="image"),this.avatarConfig?.video&&(this.avatarConfig.video.waiting=this.avatarConfig.video.waiting,this.avatarMode="video"))}scrollToBottom(t){t=t||this.scrollComp,t?.nativeElement?.scrollHeight&&(t.nativeElement.scrollTop=t.nativeElement.scrollHeight)}constructor(t,e,s,i,o,n,a){this.ChatSession=Parse.Object.extend("ChatSession"),this.messageList=[{role:"system",content:"系统提示:AI仅供参考"}],this.latestAIResponse="",this.userInput="",this.userImage="",this.isDirect=!1,this.mode="page",this.hideShare=!1,this.hideModalSelect=!1,this.hideInputPreview=!1,this.isAvatarShow=!1,this.avatarMode="",this.isPromptModalOpen=!1,this.isPromptMessageAreaShow=!0,this.promptList=[],this.focusUserInput=()=>{},this.leftButtons=[{title:"灵感",icon:"color-wand-outline",onClick:()=>{this.isPromptModalOpen=!0},show:()=>this?.promptList?.length},{title:"角色",icon:"people-outline",onClick:()=>{this.navCtrl?.navigateRoot("/chat/pro/mask")},show:()=>!0},{title:"呼叫",icon:"call-outline",onClick:()=>{this.chatServ?.callRole(this.role)},show:()=>this?.role?.get("voiceConfig")}],this.isVoiceInputMode=!1,this.isTexting=!1,this.isTalkMode=!1,this.SSMLRoleVoice="zh-CN-XiaoxiaoNeural",this.playAnimation=t=>{console.log(t)},this.welcome=async()=>{let t=this.messageList?.filter((t=>"assistant"==t?.role));if(t?.length)return;let e=Parse.User.current(),s=await this.loadSelf("Person","userVerify"),i=await this.loadSelf("Profile","user"),o=e?.get("nickname")||i?.get("name")||e?.get("realname")||e?.get("name"),n=s?.get("name")||s?.get("userVefiry")?.get("realname")||s?.get("userVefiry")?.get("nickname");s?.get("userVerify")?.id==e?.id&&(n="您");let a=this.role.get("voiceConfig")?.welcome?.prompt;if(this.role.get("voiceConfig")?.welcome?.promptList?.length){let t=this.role.get("voiceConfig")?.welcome?.promptList;a=t[Math.floor(Math.random()*t.length)]}if(!a)return;let r=await PromptTemplate.fromTemplate(a,{templateFormat:"mustache"}).format({name:o,userName:o,personName:n,timeOfDay:this.getTimeOfDay()}),l=await this.getVoiceByContentText(r),h={role:"assistant",voice:l,content:r,complete:!0};this.voiceMap[l?.id],this.playChatVoice(this.voiceMap[l?.id]),this.messageList.push(h)},this.self={},this.voiceMap={},this.VoiceTTSMap={},this.chatServ=i,this.role=e,this.sessionId=t,this.navCtrl=o,this.ncloud=n,this.uploadServ=a,s?.id&&(this.chatSession=s,this.messageList=this.chatSession.get("messageList"),this.sessionId=s?.id),this.role?.id&&(this.voiceConfig=this.role?.get("voiceConfig"),this.voiceConfig?.autoTalk&&(this.isTalkMode=!0,this.isDirect=!0))}getTimeOfDay(){const t=(new Date).getHours();return t>=5&&t<12?"早上":t>=12&&t<14?"中午":t>=14&&t<18?"下午":"晚上"}async loadSelf(t,e){if(this.self[t])return this.self[t];let s=Parse.User.current(),i=new Parse.Query(t);return i.include(e),i.equalTo(e,s?.id),this.self[t]=await i.first(),this.self[t]}async loadTalkSystemPrompt(t){if(!this.isTalkMode)return;if(!t)return;"男"==t?.get("gender")?this.SSMLRoleVoice="zh-CN-YunyeNeural":this.SSMLRoleVoice="zh-CN-XiaoxiaoNeural",this.SSMLRoleVoice=t?.get("voiceConfig")?.voice||this.SSMLRoleVoice;let e=await agentPrompt.getFormatTpl("talk-ssml-output-tpl",{SSMLRoleVoice:this.SSMLRoleVoice}),s=t.get("prompt")||"请你扮演飞码AI的人工智能专家。";s+=e;let i={role:"user",content:s,hidden:!0},o=this.messageList?.map((t=>t?.content)).join();if(o.indexOf(s)>-1)return;let n=this.messageList?.findIndex((t=>"system"==t?.role)),a=n+1;this.messageList.splice(a,0,i)}loadRolePrompt(){let t=this.role?.get("prompt"),e={role:"user",content:t,hidden:!0};if(!t)return;let s=this.messageList?.map((t=>t?.content)).join();if(s.indexOf(t)>-1)return;let i=this.messageList?.findIndex((t=>"system"==t?.role)),o=i+1;this.messageList.splice(o,0,e)}async sendMessage(t="FmodeAiTest测试问题",e,s,i,o){if(this.scrollToBottom&&this.scrollToBottom(),this.isPromptMessageAreaShow=!1,this.loadRolePrompt(),e){let s={role:"user",content:[{type:"image_url",image_url:{url:e}},{type:"text",text:t}],complete:!0,createdAt:new Date};o&&(s.voice={id:o?.id}),this.messageList.push({role:"user",content:[{type:"image_url",image_url:{url:e}},{type:"text",text:t}],complete:!0,createdAt:new Date})}else{let e={role:"user",content:t,complete:!0,createdAt:new Date};o&&(e.voice={id:o?.id,duration:o?.duration}),this.messageList.push(e)}let n=new FmodeChatCompletion(this.fixMessageList(this.messageList),{model:this.currentModel?.get("code")||"fmode-4.5-128k"});if(this.onUserSend){if(!await this.onUserSend(this,this.messageList[this.messageList?.length-1]))return}this.userInput="",this.userImage="";let a=this.isDirect||!1;this.isTalkMode&&(a=!0);let r=n.sendCompletion({isDirect:a,onComplete:s||null}).pipe(finalize((async()=>{if(this.isTalkMode){let t=this.messageList[n.indexOfList]?.content,e=await this.getVoiceByContentText(t,i);i?.onSSMLComplete&&i?.onSSMLComplete(e),this.messageList[n.indexOfList].voice=e,this.playChatVoice(this.voiceMap[e?.id])}this.messageList[n.indexOfList].complete=!0}))).subscribe((t=>{this.messageList[n.indexOfList]=t,this.latestAIResponse=this.getContentText(t?.content);let e=this.chatSession?.get("messageList")?.length;this.messageList?.length>e&&this.saveChatSession(),t?.complete&&(this.onMessage&&this.onMessage(this,this.messageList[this.messageList?.length-1]),this.saveChatSession(),r.unsubscribe()),this.scrollToBottom&&this.scrollToBottom()}))}getVoiceByContentText(t,e,s=!1){let i=this.getContentText(t),o=new(Parse.Object.extend("ChatVoice")),n="";return this.SSMLRoleVoice=this.role?.get("voiceConfig")?.voice||this.SSMLRoleVoice,new Promise((async(t,e)=>{let resolveChatVoice=async()=>{o.set("content",i),o.set("ssml",n),o.set("role","assistant");let e=localStorage.getItem("company");e&&o.set("company",{__type:"Pointer",className:"Company",objectId:e}),Parse.User.current()?.id&&o.set("user",Parse.User.current().toPointer()),this.chatSession?.id&&o.set("session",this.chatSession?.toPointer()),o=await o.save(),this.voiceMap[o?.id]=o,t({id:o?.id})};if(0==s&&(n=`<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="zh-CN"><voice name="${this.SSMLRoleVoice}">${i}</voice></speak>`,resolveChatVoice()),1==s){let t=await agentPrompt.getFormatTpl("talk-text-ssml-tpl",{content:i,SSMLRoleVoice:this.SSMLRoleVoice});new FmodeChatCompletion(this.fixMessageList([{role:"user",content:t}]),{model:this.currentModel?.get("code")||"fmode-4.5-128k"}).sendCompletion({isDirect:!0}).subscribe((async t=>{t?.complete&&(n=this.getContentText(t?.content),resolveChatVoice())}))}}))}getContentText(t){return"string"==typeof t?t:t?.[0]?.text||""}async initTTS(){let t=await this.ncloud.apig("voice/tts/token",{company:localStorage.getItem("company")});if(console.log(t),t?.token){return new FmodeTTS(t,this.uploadServ)}return null}stopPlayingVoice(){Object.values(this.VoiceTTSMap).forEach((t=>{t?.isPlaying&&t?.stop()}))}async playChatVoice(t,e){let s=await this.initTTS();if(s){try{this.playAnimation("talking"),s.speakAsync(t?.get("ssml"),t,{onStart:t=>{e?.onStart&&e?.onStart(t)},onLoaded:t=>{e?.onLoaded&&e?.onLoaded(t)},onStop:()=>{e?.onStop&&e?.onStop(),this.playAnimation("waiting")}})}catch(t){console.error(t)}return this.VoiceTTSMap[t.id]=s,s}return null}async saveChatSession(){if("new"==this.sessionId&&(this.chatSession=new this.ChatSession),this.chatSession.set("title",this.genTitle()),this.chatSession.set("role",this.role?.toPointer()),this.chatSession.set("messageList",this.messageList),this.chatSession.set("user",Parse.User.current()?.toPointer()),this.chatSession=await this.chatSession.save(),this.onChatSaved&&this.onChatSaved(this),this.sessionId=this.chatSession?.id,this.sessionId){let t=`${window.location.origin}/chat/pro/chat/${this.sessionId}`;window.location?.pathname?.indexOf("chat/session")>-1&&(t=`${window.location.origin}/chat/session/chat/${this.sessionId}`),"modal"==this.mode&&(t=window.location.href),t=this.getInviteUrl(t),window.history.replaceState(null,null,t+window.location.search);let e={sid:this.chatSession?.id,rid:this.role?.id,name:this.role?.get("name"),message:this.chatSession?.get("messageList")?.[this.chatSession?.get("messageList")?.length-1]?.content?.slice(0,20),latest:this.chatSession?.createdAt};this.chatServ&&!this.chatServ?.chatList?.length&&(this.chatServ.chatList=[]);let s=this.chatServ?.chatList?.find((t=>t?.sid==e?.sid));s>-1?this.chatServ.chatList[s]=e:this.chatServ?.chatList.unshift(e)}}getInviteUrl(t){let e=new URL(t),s=Parse.User?.current()?.id;return e.searchParams.set("invite",s),e.href}genTitle(){if(this.title)return this.title;let t=this.messageList.find((t=>"user"==t.role))?.content;return"string"==typeof t&&(this.title=t?.slice(0,15)||""),"object"==typeof t&&(this.title=t?.find((t=>t?.text))?.text||""),this.title}fixMessageList(t){return t.map((t=>({role:t.role,content:t.content})))}nowStr(){let t=new Date;return`${t.getFullYear()}/${t.getMonth()+1}/${t.getDate()} ${t.getHours()}:${t.getMinutes()}:${t.getSeconds()}`}}export class FmodeChatCompletion{constructor(t,e){this.content="",this.contentBuffer=[],this.isCompleted=!1,this.indexOfList=Number(t.length),this.messages=t,this.model=e?.model||"fmode-4.5-128k"}sendCompletion(t={}){t.intTime=t?.intTime||50,t.isDirect=t?.isDirect||!1,t?.isDirect&&(t.intTime=1);let e={messages:this.messages,stream:!0,model:this.model,temperature:.5,presence_penalty:0,frequency_penalty:0};return new Observable((s=>{let i=RequestFmodeChatApi("/v1/chat/completions",e).subscribe((e=>{let o=String(e);if("data: [DONE]"==o&&(this.isCompleted=!0,t?.isDirect&&this.isCompleted&&(s.next({role:"assistant",content:this.content,complete:!0,createdAt:new Date}),i.unsubscribe(),t?.onComplete&&t.onComplete({role:"assistant",content:this.content,complete:!0,createdAt:new Date}),s.complete())),o.indexOf("data: {")>-1){let e=chunkToJson(o),n=e?.choices?.[0]?.delta?.content||"";this.contentBuffer.push(n),t?.isDirect&&(this.content+=n||"",this.isCompleted||s.next({role:"assistant",cid:e?.id,content:this.content,createdAt:new Date})),t?.isDirect||this.contentPusher||(this.contentPusher=setInterval((()=>{this.isCompleted&&0==this.contentBuffer?.length&&(s.next({role:"assistant",cid:e?.id,content:this.content,complete:!0,createdAt:new Date}),i.unsubscribe(),clearInterval(this.contentPusher),s.complete()),this.contentBuffer?.length>=0&&(this.contentBuffer?.length>0&&(this.content+=this.contentBuffer.shift()),s.next({role:"assistant",cid:e?.id,content:this.content,createdAt:new Date}))}),t?.intTime))}}))})).pipe(bufferTime(100),concatMap((t=>t)),delay(200))}}function chunkToJson(t){let e;try{e=JSON.parse(t.replaceAll("data: ",""))}catch(t){console.error(t)}return e||{}}function RequestFmodeChatApi(t,e,s="POST"){return new Observable((i=>{let o=API_BASE+t,n=`Bearer ${Parse.User.current()?.getSessionToken()||localStorage.getItem("FMODE_AI_TOKEN")}`;return e.token=n,e&&(e=JSON.stringify(e)),fetch(o,{headers:{"Content-Type":"text/plain; charset=utf-8","Cache-Control":"no-cache"},body:e||null,method:s,credentials:"omit",mode:"cors"}).then((t=>{let e="";{let s=t.body?.getReader();const o=new TextDecoder;let n=new ReadableStream({start(t){!function read(){s.read().then((({done:e,value:s})=>{if(e)return t.close(),void i.complete();t.enqueue(s),read()}))}()}}).getReader();n.read().then((function processStream({done:t,value:s}){if(t)return;!function processData(t){let s=(e+t).split("\n");if(s?.length>1){for(let t=0;t<s.length-1;t++){let e=s[t];i.next(e)}e=s[s.length-1]}}(o.decode(s)),n.read().then(processStream)}))}})).catch((t=>i.error(t))),()=>{}}))}function JsonToFormData(t){const e=new FormData;return function appendFormData(t,s=""){Array.isArray(t)?t.forEach(((t,e)=>{appendFormData(t,`${s}[${e}]`)})):"object"==typeof t&&null!==t?Object.keys(t).forEach((e=>{const i=s?`${s}.${e}`:e;appendFormData(t[e],i)})):e.append(s,t)}(t),e}
8
+ export*from"../../../core/agent/chat";
9
9
  var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9haWdjL3NlcnZpY2UtZm1haS9zZXJ2aWNlLWNoYXQvY2hhdC1jbGFzcy5tanM=`
10
10
 
@@ -5,6 +5,6 @@
5
5
  * 保留所有权利 All Rights Reserved.
6
6
  * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/aigc/voice/stream.player.mjs
7
7
  */
8
- import{PushAudioOutputStreamCallback}from"microsoft-cognitiveservices-speech-sdk";import{Subject}from"rxjs";import{bufferWhen,filter,takeUntil}from"rxjs/operators";export class FmPushAudioOutputStreamCallback extends PushAudioOutputStreamCallback{constructor(){super(),this.audioDataSubject=new Subject,this.playedSubject=new Subject,this.isPlaying=!1,this.isClosed=!1,this.audioBufferQueue=[],this.maxBufferSize=10,this.writeCount=0,this.audioContext=new(window.AudioContext||window.webkitAudioContext),this.audioDataSubject.pipe(bufferWhen((()=>this.playedSubject)),takeUntil(this.audioDataSubject.pipe(filter((()=>this.isClosed))))).subscribe((t=>{this.playAudio(t)}))}async write(t){this.writeCount++,10==this.writeCount&&this.playedSubject.next(!0),this.audioDataSubject.next(t)}async playAudio(t){this.isPlaying=!0;const e=this.mergeArrayBuffers(t);let i;try{i=await this.audioContext.decodeAudioData(e)}catch(t){}if(i){const t=this.audioContext.createBufferSource();t.buffer=i,t.connect(this.audioContext.destination),t.start(),await new Promise((e=>{t.onended=e})),this.playedSubject.next(!0)}this.isPlaying=!1}mergeArrayBuffers(t){const e=t.reduce(((t,e)=>t+e.byteLength),0),i=new Uint8Array(e);let s=0;for(const e of t){const t=new Uint8Array(e);i.set(t,s),s+=t.length}return i.buffer}async stop(){this.isClosed=!0,this.audioDataSubject&&this.audioDataSubject.unsubscribe(),this.playedSubject&&this.playedSubject.unsubscribe(),this.audioContext&&this.audioContext.close()}async close(){console.log("close 数据加载完成"),this.isClosed=!0}}
8
+ import{PushAudioOutputStreamCallback}from"microsoft-cognitiveservices-speech-sdk/distrib/lib/src/sdk/Audio/PushAudioOutputStreamCallback";import{Subject}from"rxjs";import{bufferWhen,filter,takeUntil}from"rxjs/operators";export class FmPushAudioOutputStreamCallback extends PushAudioOutputStreamCallback{constructor(){super(),this.audioDataSubject=new Subject,this.playedSubject=new Subject,this.isPlaying=!1,this.isClosed=!1,this.audioBufferQueue=[],this.maxBufferSize=10,this.writeCount=0,this.audioContext=new(window.AudioContext||window.webkitAudioContext),this.audioDataSubject.pipe(bufferWhen((()=>this.playedSubject)),takeUntil(this.audioDataSubject.pipe(filter((()=>this.isClosed))))).subscribe((t=>{this.playAudio(t)}))}async write(t){this.writeCount++,10==this.writeCount&&this.playedSubject.next(!0),this.audioDataSubject.next(t)}async playAudio(t){this.isPlaying=!0;const e=this.mergeArrayBuffers(t);let i;try{i=await this.audioContext.decodeAudioData(e)}catch(t){}if(i){const t=this.audioContext.createBufferSource();t.buffer=i,t.connect(this.audioContext.destination),t.start(),await new Promise((e=>{t.onended=e})),this.playedSubject.next(!0)}this.isPlaying=!1}mergeArrayBuffers(t){const e=t.reduce(((t,e)=>t+e.byteLength),0),i=new Uint8Array(e);let s=0;for(const e of t){const t=new Uint8Array(e);i.set(t,s),s+=t.length}return i.buffer}async stop(){this.isClosed=!0,this.audioDataSubject&&this.audioDataSubject.unsubscribe(),this.playedSubject&&this.playedSubject.unsubscribe(),this.audioContext&&this.audioContext.close()}async close(){console.log("close 数据加载完成"),this.isClosed=!0}}
9
9
  var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9haWdjL3ZvaWNlL3N0cmVhbS5wbGF5ZXIubWpz`
10
10
 
@@ -5,6 +5,6 @@
5
5
  * 保留所有权利 All Rights Reserved.
6
6
  * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/aigc/voice/tts/fmode-tts-class.mjs
7
7
  */
8
- import{SpeechSynthesizer}from"microsoft-cognitiveservices-speech-sdk";import{SpeechConfig}from"microsoft-cognitiveservices-speech-sdk";import{ResultReason}from"microsoft-cognitiveservices-speech-sdk";import{AudioConfig}from"microsoft-cognitiveservices-speech-sdk";import Parse from"parse";import{AudioPlayer}from"../audio.player";import{FmPushAudioOutputStreamCallback}from"../stream.player";export class FmodeTTS{stop(){this.audioPlayer&&this.audioPlayer?.stop(),this.audioStream&&this.audioStream?.stop()}constructor(e,t){this.isPlaying=!1,this.uploadServ=t,this.subscriptionKey=e?.subscriptionKey,this.authorizationToken=e?.token,this.region=e?.region,this.subscriptionKey&&(this.speechConfig=SpeechConfig.fromSubscription(this.subscriptionKey,this.region)),this.authorizationToken&&(this.speechConfig=SpeechConfig.fromAuthorizationToken(this.authorizationToken,this.region)),this.audioStream=new FmPushAudioOutputStreamCallback,this.audioConfig=AudioConfig.fromStreamOutput(this.audioStream),this.synthesizer=new SpeechSynthesizer(this.speechConfig,this.audioConfig),this.audioPlayer=AudioPlayer.getInstance()}extractTextFromXML(e){const t=/>([^<]+)</g;let o,i=[];for(;null!==(o=t.exec(e));){const e=o[1].trim();e&&i.push(e)}return i.join(" ")}extractSSMLContent(e){var t=e.match(/<speak.*?<\/speak>/s);return t?t[0]:e}async speakAsync(e,t,o){if(!t){let o=Parse.Object.extend("ChatVoice");(t=new o).set("ssml",e),t.set("content",this.extractTextFromXML(e));let i=localStorage.getItem("company");i&&t.set("company",{__type:"Pointer",className:"Company",objectId:i}),Parse.User.current()?.id&&t.set("user",Parse.User.current().toPointer())}if(!t?.get("voiceFile")){let o=[];t?.get("content")&&o.push({content:t?.get("content")}),e&&o.push({ssml:e});let i=Parse.Query.fromJSON("ChatVoice",{include:"voiceFile",where:{$or:o}}),s=await i.first();t.set("voiceFile",s?.get("voiceFile"))}return t?.get("voiceFile")?(this.playAudioData(t?.get("voiceFile")?.get("url"),t,o),t):(e=this.extractSSMLContent(e),this.isPlaying=!0,new Promise(((i,s)=>{const n=Date.now();let a="speakTextAsync";e?.indexOf("<")>-1&&(a="speakSsmlAsync"),e=this.fixMarkdownChar(e),this.eventMap?.onSpeakBefore&&this.eventMap?.onSpeakBefore(),this.synthesizer[a](e,(e=>{if(console.log(e),e.reason===ResultReason.SynthesizingAudioStarted&&(this.isPlaying=!0),e.reason===ResultReason.SynthesizingAudioCompleted){this.eventMap?.onAudioCompleted&&this.eventMap?.onAudioCompleted();const s=Date.now();let a=e?.audioData;t.set("duration",Number(e?.audioDuration)/1e4),this.playAudioData(a,t,o),console.log(`Audio synthesis finished. Duration: ${s-n} ms`),setTimeout((()=>{this.isPlaying=!1,o?.onStop()&&o?.onStop()}),2e3),i(t)}else s(`Speech synthesis failed. Reason: ${e.errorDetails}`)}),(e=>{s(`Error occurred during synthesis: ${e}`)}))})))}onBreak(e){}fixMarkdownChar(e){return e.replaceAll("*","")}async playAudioData(e,t,o){let i;if(console.log("audioData",e),!(e?.indexOf&&e?.indexOf("http")>=-1)){let o=new Blob([e],{type:"audio/wav"});return i=URL.createObjectURL(o),void this.uploadAndSaveVoice(o,t)}i=e;let s=this.audioPlayer;o?.onStart&&o?.onStart(t),this.isPlaying=!0,s.setAudioEvent("onloadeddata",(()=>{let e=1e3*s.duration;console.log("duration",e),t?.get("duration")||(t?.set("duration",e),t?.save()),o?.onLoaded&&o?.onLoaded(s)})),console.log("event setting"),s.setAudioEvent("onabort",(()=>{this.isPlaying=!1,o?.onStop&&o?.onStop()})),s.setAudioEvent("onerror",(()=>{this.isPlaying=!1,o?.onStop&&o?.onStop()})),s.setAudioEvent("onpause",(()=>{this.isPlaying=!1,o?.onStop&&o?.onStop()})),s.setAudioEvent("onended",(()=>{this.isPlaying=!1,o?.onStop&&o?.onStop()})),s.setAudioEvent("onclose",(()=>{this.isPlaying=!1,o?.onStop&&o?.onStop()})),console.log("playAudio",i);let playAudio=()=>{s.play(i).then((()=>{})).catch((()=>{setTimeout((()=>{console.log("playAudio"),playAudio()}),200)}))};playAudio()}async uploadAndSaveVoice(e,t){if(console.log("blob",e),this.uploadServ){let o=t?.id||this.uploadServ?.genMd5(t?.get("content")||t?.get("ssml")),i=new Date,s=o+i.getFullYear()+(i.getMonth()+1)+i.getDate()+i.getHours()+i.getMinutes()+i.getSeconds()+".wav",n=new File([e],s,{type:"audio/wav"}),a=await this.uploadServ.upload(n,(e=>{console.log(e)})),r={__type:"Pointer",className:"Attachment",objectId:a?.id};return r?.objectId&&(t.set("voiceFile",r),t=await t.save()),a?.url}return null}}
8
+ import{SpeechSynthesizer}from"microsoft-cognitiveservices-speech-sdk/distrib/browser/microsoft.cognitiveservices.speech.sdk.bundle-min";import{SpeechConfig}from"microsoft-cognitiveservices-speech-sdk/distrib/browser/microsoft.cognitiveservices.speech.sdk.bundle-min";import{ResultReason}from"microsoft-cognitiveservices-speech-sdk/distrib/browser/microsoft.cognitiveservices.speech.sdk.bundle-min";import{AudioConfig}from"microsoft-cognitiveservices-speech-sdk/distrib/browser/microsoft.cognitiveservices.speech.sdk.bundle-min";import Parse from"parse";import{AudioPlayer}from"../audio.player";import{FmPushAudioOutputStreamCallback}from"../stream.player";export class FmodeTTS{stop(){this.audioPlayer&&this.audioPlayer?.stop(),this.audioStream&&this.audioStream?.stop()}constructor(e,t){this.isPlaying=!1,this.uploadServ=t,this.subscriptionKey=e?.subscriptionKey,this.authorizationToken=e?.token,this.region=e?.region,this.subscriptionKey&&(this.speechConfig=SpeechConfig.fromSubscription(this.subscriptionKey,this.region)),this.authorizationToken&&(this.speechConfig=SpeechConfig.fromAuthorizationToken(this.authorizationToken,this.region)),this.audioStream=new FmPushAudioOutputStreamCallback,this.audioConfig=AudioConfig.fromStreamOutput(this.audioStream),this.synthesizer=new SpeechSynthesizer(this.speechConfig,this.audioConfig),this.audioPlayer=AudioPlayer.getInstance()}extractTextFromXML(e){const t=/>([^<]+)</g;let o,i=[];for(;null!==(o=t.exec(e));){const e=o[1].trim();e&&i.push(e)}return i.join(" ")}extractSSMLContent(e){var t=e.match(/<speak.*?<\/speak>/s);return t?t[0]:e}async speakAsync(e,t,o){if(!t){let o=Parse.Object.extend("ChatVoice");(t=new o).set("ssml",e),t.set("content",this.extractTextFromXML(e));let i=localStorage.getItem("company");i&&t.set("company",{__type:"Pointer",className:"Company",objectId:i}),Parse.User.current()?.id&&t.set("user",Parse.User.current().toPointer())}if(!t?.get("voiceFile")){let o=[];t?.get("content")&&o.push({content:t?.get("content")}),e&&o.push({ssml:e});let i=Parse.Query.fromJSON("ChatVoice",{include:"voiceFile",where:{$or:o}}),s=await i.first();t.set("voiceFile",s?.get("voiceFile"))}return t?.get("voiceFile")?(this.playAudioData(t?.get("voiceFile")?.get("url"),t,o),t):(e=this.extractSSMLContent(e),this.isPlaying=!0,new Promise(((i,s)=>{const n=Date.now();let r="speakTextAsync";e?.indexOf("<")>-1&&(r="speakSsmlAsync"),e=this.fixMarkdownChar(e),this.eventMap?.onSpeakBefore&&this.eventMap?.onSpeakBefore(),this.synthesizer[r](e,(e=>{if(console.log(e),e.reason===ResultReason.SynthesizingAudioStarted&&(this.isPlaying=!0),e.reason===ResultReason.SynthesizingAudioCompleted){this.eventMap?.onAudioCompleted&&this.eventMap?.onAudioCompleted();const s=Date.now();let r=e?.audioData;t.set("duration",Number(e?.audioDuration)/1e4),this.playAudioData(r,t,o),console.log(`Audio synthesis finished. Duration: ${s-n} ms`),setTimeout((()=>{this.isPlaying=!1,o?.onStop()&&o?.onStop()}),2e3),i(t)}else s(`Speech synthesis failed. Reason: ${e.errorDetails}`)}),(e=>{s(`Error occurred during synthesis: ${e}`)}))})))}onBreak(e){}fixMarkdownChar(e){return e.replaceAll("*","")}async playAudioData(e,t,o){let i;if(console.log("audioData",e),!(e?.indexOf&&e?.indexOf("http")>=-1)){let o=new Blob([e],{type:"audio/wav"});return i=URL.createObjectURL(o),void this.uploadAndSaveVoice(o,t)}i=e;let s=this.audioPlayer;o?.onStart&&o?.onStart(t),this.isPlaying=!0,s.setAudioEvent("onloadeddata",(()=>{let e=1e3*s.duration;console.log("duration",e),t?.get("duration")||(t?.set("duration",e),t?.save()),o?.onLoaded&&o?.onLoaded(s)})),console.log("event setting"),s.setAudioEvent("onabort",(()=>{this.isPlaying=!1,o?.onStop&&o?.onStop()})),s.setAudioEvent("onerror",(()=>{this.isPlaying=!1,o?.onStop&&o?.onStop()})),s.setAudioEvent("onpause",(()=>{this.isPlaying=!1,o?.onStop&&o?.onStop()})),s.setAudioEvent("onended",(()=>{this.isPlaying=!1,o?.onStop&&o?.onStop()})),s.setAudioEvent("onclose",(()=>{this.isPlaying=!1,o?.onStop&&o?.onStop()})),console.log("playAudio",i);let playAudio=()=>{s.play(i).then((()=>{})).catch((()=>{setTimeout((()=>{console.log("playAudio"),playAudio()}),200)}))};playAudio()}async uploadAndSaveVoice(e,t){if(console.log("blob",e),this.uploadServ){let o=t?.id||this.uploadServ?.genMd5(t?.get("content")||t?.get("ssml")),i=new Date,s=o+i.getFullYear()+(i.getMonth()+1)+i.getDate()+i.getHours()+i.getMinutes()+i.getSeconds()+".wav",n=new File([e],s,{type:"audio/wav"}),r=await this.uploadServ.upload(n,(e=>{console.log(e)})),a={__type:"Pointer",className:"Attachment",objectId:r?.id};return a?.objectId&&(t.set("voiceFile",a),t=await t.save()),r?.url}return null}}
9
9
  var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9haWdjL3ZvaWNlL3R0cy9mbW9kZS10dHMtY2xhc3MubWpz`
10
10
 
@@ -0,0 +1,10 @@
1
+
2
+ /**
3
+ * @copyright © 未来飞马 © 未来全栈 www.fmode.cn
4
+ * 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
5
+ * 保留所有权利 All Rights Reserved.
6
+ * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/core/agent/chat/completion/fmode-completion.mjs
7
+ */
8
+ import{bufferTime,concatMap,delay,Observable}from"rxjs";const API_BASE="https://server.fmode.cn/api/apig/aigc/gpt";import Parse from"parse";export class FmodeChatCompletion{constructor(e,t){this.content="",this.contentBuffer=[],this.isCompleted=!1,this.indexOfList=Number(e.length),this.messages=e,this.model=t?.model||"fmode-4.5-128k"}sendCompletion(e={}){e.intTime=e?.intTime||50,e.isDirect=e?.isDirect||!1,e?.isDirect&&(e.intTime=1);let t={messages:this.messages,stream:!0,model:this.model,temperature:.5,presence_penalty:0,frequency_penalty:0};return new Observable((n=>{let s=RequestFmodeChatApi("/v1/chat/completions",t).subscribe((t=>{let o,r=String(t);try{o=chunkToJson(r)}catch(e){}if(("data: [DONE]"==r||o?.created&&o?.choices?.[0]?.finish_reason)&&(this.isCompleted=!0,e?.isDirect&&this.isCompleted&&(n.next({role:"assistant",content:this.content,complete:!0,createdAt:new Date}),s.unsubscribe(),e?.onComplete&&e.onComplete({role:"assistant",content:this.content,complete:!0,createdAt:new Date}),n.complete())),r.indexOf("data: {")>-1){let t=o?.choices?.[0]?.delta?.content||"";this.contentBuffer.push(t),e?.isDirect&&(this.content+=t||"",this.isCompleted||n.next({role:"assistant",cid:o?.id,content:this.content,createdAt:new Date})),e?.isDirect||this.contentPusher||(this.contentPusher=setInterval((()=>{this.isCompleted&&0==this.contentBuffer?.length&&(n.next({role:"assistant",cid:o?.id,content:this.content,complete:!0,createdAt:new Date}),s.unsubscribe(),clearInterval(this.contentPusher),n.complete()),this.contentBuffer?.length>=0&&(this.contentBuffer?.length>0&&(this.content+=this.contentBuffer.shift()),n.next({role:"assistant",cid:o?.id,content:this.content,createdAt:new Date}))}),e?.intTime))}}))})).pipe(bufferTime(100),concatMap((e=>e)),delay(200))}}function chunkToJson(e){let t;try{t=JSON.parse(e.replaceAll("data: ",""))}catch(e){}return t||{}}function RequestFmodeChatApi(e,t,n="POST"){return new Observable((s=>{let o=API_BASE+e,r=`Bearer ${Parse.User.current()?.getSessionToken()||localStorage.getItem("FMODE_AI_TOKEN")}`;return t.token=r,t&&(t=JSON.stringify(t)),fetch(o,{headers:{"Content-Type":"text/plain; charset=utf-8","Cache-Control":"no-cache"},body:t||null,method:n,credentials:"omit",mode:"cors"}).then((e=>{let t="";{let n=e.body?.getReader();const o=new TextDecoder;let r=new ReadableStream({start(e){!function read(){n.read().then((({done:t,value:n})=>{if(t)return e.close(),void s.complete();e.enqueue(n),read()}))}()}}).getReader();r.read().then((function processStream(e){let{done:n,value:a}=e;n||(!function processData(e){let n=(t+e).split("\n");if(n?.length>1){for(let e=0;e<n.length-1;e++){let t=n[e];s.next(t)}t=n[n.length-1]}}(o.decode(a)),r.read().then(processStream))}))}})).catch((e=>s.error(e))),()=>{}}))}function JsonToFormData(e){const t=new FormData;return function appendFormData(e,n=""){Array.isArray(e)?e.forEach(((e,t)=>{appendFormData(e,`${n}[${t}]`)})):"object"==typeof e&&null!==e?Object.keys(e).forEach((t=>{const s=n?`${n}.${t}`:t;appendFormData(e[t],s)})):t.append(n,e)}(e),t}
9
+ var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9jb3JlL2FnZW50L2NoYXQvY29tcGxldGlvbi9mbW9kZS1jb21wbGV0aW9uLm1qcw==`
10
+
@@ -0,0 +1,10 @@
1
+
2
+ /**
3
+ * @copyright © 未来飞马 © 未来全栈 www.fmode.cn
4
+ * 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
5
+ * 保留所有权利 All Rights Reserved.
6
+ * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/core/agent/chat/completion/index.mjs
7
+ */
8
+ export*from"./fmode-completion";
9
+ var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9jb3JlL2FnZW50L2NoYXQvY29tcGxldGlvbi9pbmRleC5tanM=`
10
+
@@ -0,0 +1,10 @@
1
+
2
+ /**
3
+ * @copyright © 未来飞马 © 未来全栈 www.fmode.cn
4
+ * 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
5
+ * 保留所有权利 All Rights Reserved.
6
+ * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/core/agent/chat/fmode-chat.mjs
7
+ */
8
+ import{finalize}from"rxjs";import Parse from"parse";import{FmodeTTS}from"../../voice/tts";import{PromptTemplate}from"@langchain/core/prompts";import{getFormatTpl}from"../prompt/prompt-util";import{FmodeChatCompletion}from"./completion";const PromptTplTalkSSMLOutputCode="talk-ssml-output-tpl",PromptTplTalkTextSSMLCode="talk-text-ssml-tpl";export function getMessageContentText(t){let e="";return"string"==typeof t&&(e=t),"object"==typeof t&&(e=t?.find((t=>t?.text))?.text||""),e}export function getMessageImageUrl(t){return"object"==typeof t?t?.find((t=>t?.image_url))?.image_url?.url||"":null}export class FmodeChat{async loadModelList(t){if(this.modelList?.length)return;let e=new Parse.Query("ChatModel");e.notEqualTo("isDeleted",!0),e.equalTo("isEnabled",!0),e.addAscending("index"),this.modelList=await e.find(),this.currentModel=t||this.modelList?.find((t=>"fmode-4.5-128k"==t.get("code")))}showAvatar(){this.avatarConfig=this.role?.get("avatarConfig"),this.avatarConfig&&(this.isAvatarShow=!0,this.avatarConfig?.image&&(this.avatarConfig.image.waiting=this.avatarConfig.image.waiting||this.role?.get("thumb")||this.role?.get("avatar"),this.avatarMode="image"),this.avatarConfig?.video&&(this.avatarConfig.video.waiting=this.avatarConfig.video.waiting,this.avatarMode="video"))}scrollToBottom(t){t=t||this.scrollComp,t?.nativeElement?.scrollHeight&&(t.nativeElement.scrollTop=t.nativeElement.scrollHeight)}constructor(t,e,s,i,o,a,n){this.ChatSession=Parse.Object.extend("ChatSession"),this.messageList=[{role:"system",content:"系统提示:AI仅供参考"}],this.latestAIResponse="",this.userInput="",this.userImage="",this.isDirect=!1,this.mode="page",this.hideShare=!1,this.hideModalSelect=!1,this.hideInputPreview=!1,this.isAvatarShow=!1,this.avatarMode="",this.isPromptModalOpen=!1,this.isPromptMessageAreaShow=!0,this.promptList=[],this.focusUserInput=()=>{},this.leftButtons=[{title:"灵感",icon:"color-wand-outline",onClick:()=>{this.isPromptModalOpen=!0},show:()=>this?.promptList?.length},{title:"角色",icon:"people-outline",onClick:()=>{this.navCtrl?.navigateRoot("/chat/pro/mask")},show:()=>!0},{title:"呼叫",icon:"call-outline",onClick:()=>{this.chatServ?.callRole(this.role)},show:()=>this?.role?.get("voiceConfig")}],this.isVoiceInputMode=!1,this.isTexting=!1,this.isTalkMode=!1,this.SSMLRoleVoice="zh-CN-XiaoxiaoNeural",this.playAnimation=t=>{console.log(t)},this.welcome=async()=>{let t=this.messageList?.filter((t=>"assistant"==t?.role));if(t?.length)return;let e=Parse.User.current(),s=await this.loadSelf("Person","userVerify"),i=await this.loadSelf("Profile","user"),o=e?.get("nickname")||i?.get("name")||e?.get("realname")||e?.get("name"),a=s?.get("name")||s?.get("userVefiry")?.get("realname")||s?.get("userVefiry")?.get("nickname");s?.get("userVerify")?.id==e?.id&&(a="您");let n=this.role.get("voiceConfig")?.welcome?.prompt;if(this.role.get("voiceConfig")?.welcome?.promptList?.length){let t=this.role.get("voiceConfig")?.welcome?.promptList;n=t[Math.floor(Math.random()*t.length)]}if(!n)return;let r=await PromptTemplate.fromTemplate(n,{templateFormat:"mustache"}).format({name:o,userName:o,personName:a,timeOfDay:this.getTimeOfDay()}),l=await this.getVoiceByContentText(r),h={role:"assistant",voice:l,content:r,complete:!0};this.voiceMap[l?.id],this.playChatVoice(this.voiceMap[l?.id]),this.messageList.push(h)},this.self={},this.voiceMap={},this.VoiceTTSMap={},this.chatServ=i,this.role=e,this.sessionId=t,this.navCtrl=o,this.ncloud=a,this.uploadServ=n,s?.id&&(this.chatSession=s,this.messageList=this.chatSession.get("messageList"),this.sessionId=s?.id),this.role?.id&&(this.voiceConfig=this.role?.get("voiceConfig"),this.voiceConfig?.autoTalk&&(this.isTalkMode=!0,this.isDirect=!0))}getTimeOfDay(){const t=(new Date).getHours();return t>=5&&t<12?"早上":t>=12&&t<14?"中午":t>=14&&t<18?"下午":"晚上"}async loadSelf(t,e){if(this.self[t])return this.self[t];let s=Parse.User.current(),i=new Parse.Query(t);return i.include(e),i.equalTo(e,s?.id),this.self[t]=await i.first(),this.self[t]}async loadTalkSystemPrompt(t){if(!this.isTalkMode)return;if(!t)return;"男"==t?.get("gender")?this.SSMLRoleVoice="zh-CN-YunyeNeural":this.SSMLRoleVoice="zh-CN-XiaoxiaoNeural",this.SSMLRoleVoice=t?.get("voiceConfig")?.voice||this.SSMLRoleVoice;let e=await getFormatTpl("talk-ssml-output-tpl",{SSMLRoleVoice:this.SSMLRoleVoice}),s=t.get("prompt")||"请你扮演飞码AI的人工智能专家。";s+=e;let i={role:"user",content:s,hidden:!0},o=this.messageList?.map((t=>t?.content)).join();if(o.indexOf(s)>-1)return;let a=this.messageList?.findIndex((t=>"system"==t?.role)),n=a+1;this.messageList.splice(n,0,i)}loadRolePrompt(){let t=this.role?.get("prompt"),e={role:"user",content:t,hidden:!0};if(!t)return;let s=this.messageList?.map((t=>t?.content)).join();if(s.indexOf(t)>-1)return;let i=this.messageList?.findIndex((t=>"system"==t?.role)),o=i+1;this.messageList.splice(o,0,e)}async sendMessage(t="FmodeAiTest测试问题",e,s,i,o){if(this.scrollToBottom&&this.scrollToBottom(),this.isPromptMessageAreaShow=!1,this.loadRolePrompt(),e){let s={role:"user",content:[{type:"image_url",image_url:{url:e}},{type:"text",text:t}],complete:!0,createdAt:new Date};o&&(s.voice={id:o?.id}),this.messageList.push({role:"user",content:[{type:"image_url",image_url:{url:e}},{type:"text",text:t}],complete:!0,createdAt:new Date})}else{let e={role:"user",content:t,complete:!0,createdAt:new Date};o&&(e.voice={id:o?.id,duration:o?.duration}),this.messageList.push(e)}let a=new FmodeChatCompletion(this.fixMessageList(this.messageList),{model:this.currentModel?.get("code")||"fmode-4.5-128k"});if(this.onUserSend){if(!await this.onUserSend(this,this.messageList[this.messageList?.length-1]))return}this.userInput="",this.userImage="";let n=this.isDirect||!1;this.isTalkMode&&(n=!0);let r=a.sendCompletion({isDirect:n,onComplete:s||null}).pipe(finalize((async()=>{if(this.isTalkMode){let t=this.messageList[a.indexOfList]?.content,e=await this.getVoiceByContentText(t,i);i?.onSSMLComplete&&i?.onSSMLComplete(e),this.messageList[a.indexOfList].voice=e,this.playChatVoice(this.voiceMap[e?.id])}this.messageList[a.indexOfList].complete=!0}))).subscribe((t=>{this.messageList[a.indexOfList]=t,this.latestAIResponse=this.getContentText(t?.content);let e=this.chatSession?.get("messageList")?.length;this.messageList?.length>e&&this.saveChatSession(),t?.complete&&(this.onMessage&&this.onMessage(this,this.messageList[this.messageList?.length-1]),this.saveChatSession(),r.unsubscribe()),this.scrollToBottom&&this.scrollToBottom()}))}getVoiceByContentText(t,e,s=!1){let i=this.getContentText(t),o=new(Parse.Object.extend("ChatVoice")),a="";return this.SSMLRoleVoice=this.role?.get("voiceConfig")?.voice||this.SSMLRoleVoice,new Promise((async(t,e)=>{let resolveChatVoice=async()=>{o.set("content",i),o.set("ssml",a),o.set("role","assistant");let e=localStorage.getItem("company");e&&o.set("company",{__type:"Pointer",className:"Company",objectId:e}),Parse.User.current()?.id&&o.set("user",Parse.User.current().toPointer()),this.chatSession?.id&&o.set("session",this.chatSession?.toPointer()),o=await o.save(),this.voiceMap[o?.id]=o,t({id:o?.id})};if(0==s&&(a=`<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="zh-CN"><voice name="${this.SSMLRoleVoice}">${i}</voice></speak>`,resolveChatVoice()),1==s){let t=await getFormatTpl("talk-text-ssml-tpl",{content:i,SSMLRoleVoice:this.SSMLRoleVoice});new FmodeChatCompletion(this.fixMessageList([{role:"user",content:t}]),{model:this.currentModel?.get("code")||"fmode-4.5-128k"}).sendCompletion({isDirect:!0}).subscribe((async t=>{t?.complete&&(a=this.getContentText(t?.content),resolveChatVoice())}))}}))}getContentText(t){return"string"==typeof t?t:t?.[0]?.text||""}async initTTS(){let t=await this.ncloud.apig("voice/tts/token",{company:localStorage.getItem("company")});if(t?.token){return new FmodeTTS(t,this.uploadServ)}return null}stopPlayingVoice(){Object.values(this.VoiceTTSMap).forEach((t=>{t?.isPlaying&&t?.stop()}))}async playChatVoice(t,e){let s=await this.initTTS();if(s){try{this.playAnimation("talking"),s.speakAsync(t?.get("ssml"),t,{onStart:t=>{e?.onStart&&e?.onStart(t)},onLoaded:t=>{e?.onLoaded&&e?.onLoaded(t)},onStop:()=>{e?.onStop&&e?.onStop(),this.playAnimation("waiting")}})}catch(t){}return this.VoiceTTSMap[t.id]=s,s}return null}async saveChatSession(){if("new"==this.sessionId&&(this.chatSession=new this.ChatSession),this.chatSession.set("title",this.genTitle()),this.chatSession.set("role",this.role?.toPointer()),this.chatSession.set("messageList",this.messageList),this.chatSession.set("user",Parse.User.current()?.toPointer()),this.chatSession=await this.chatSession.save(),this.onChatSaved&&this.onChatSaved(this),this.sessionId=this.chatSession?.id,this.sessionId){let t=`${window.location.origin}/chat/pro/chat/${this.sessionId}`;window.location?.pathname?.indexOf("chat/session")>-1&&(t=`${window.location.origin}/chat/session/chat/${this.sessionId}`),"modal"==this.mode&&(t=window.location.href),t=this.getInviteUrl(t),window.history.replaceState(null,null,t+window.location.search);let e={sid:this.chatSession?.id,rid:this.role?.id,name:this.role?.get("name"),message:this.chatSession?.get("messageList")?.[this.chatSession?.get("messageList")?.length-1]?.content?.slice(0,20),latest:this.chatSession?.createdAt};this.chatServ&&!this.chatServ?.chatList?.length&&(this.chatServ.chatList=[]);let s=this.chatServ?.chatList?.find((t=>t?.sid==e?.sid));s>-1?this.chatServ.chatList[s]=e:this.chatServ?.chatList.unshift(e)}}getInviteUrl(t){let e=new URL(t),s=Parse.User?.current()?.id;return e.searchParams.set("invite",s),e.href}genTitle(){if(this.title)return this.title;let t=this.messageList.find((t=>"user"==t.role))?.content;return"string"==typeof t&&(this.title=t?.slice(0,15)||""),"object"==typeof t&&(this.title=t?.find((t=>t?.text))?.text||""),this.title}fixMessageList(t){return t.map((t=>({role:t.role,content:t.content})))}nowStr(){let t=new Date;return`${t.getFullYear()}/${t.getMonth()+1}/${t.getDate()} ${t.getHours()}:${t.getMinutes()}:${t.getSeconds()}`}}
9
+ var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9jb3JlL2FnZW50L2NoYXQvZm1vZGUtY2hhdC5tanM=`
10
+
@@ -0,0 +1,10 @@
1
+
2
+ /**
3
+ * @copyright © 未来飞马 © 未来全栈 www.fmode.cn
4
+ * 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
5
+ * 保留所有权利 All Rights Reserved.
6
+ * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/core/agent/chat/index.mjs
7
+ */
8
+ export*from"./fmode-chat";export*from"./interface";export*from"./completion/fmode-completion";
9
+ var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9jb3JlL2FnZW50L2NoYXQvaW5kZXgubWpz`
10
+
@@ -0,0 +1,10 @@
1
+
2
+ /**
3
+ * @copyright © 未来飞马 © 未来全栈 www.fmode.cn
4
+ * 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
5
+ * 保留所有权利 All Rights Reserved.
6
+ * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/core/agent/chat/interface.mjs
7
+ */
8
+ export{};
9
+ var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9jb3JlL2FnZW50L2NoYXQvaW50ZXJmYWNlLm1qcw==`
10
+
@@ -0,0 +1,10 @@
1
+
2
+ /**
3
+ * @copyright © 未来飞马 © 未来全栈 www.fmode.cn
4
+ * 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
5
+ * 保留所有权利 All Rights Reserved.
6
+ * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/core/agent/index.mjs
7
+ */
8
+ export*from"./prompt";export*from"./story";export*from"./task";export*from"./chat";
9
+ var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9jb3JlL2FnZW50L2luZGV4Lm1qcw==`
10
+
@@ -0,0 +1,10 @@
1
+
2
+ /**
3
+ * @copyright © 未来飞马 © 未来全栈 www.fmode.cn
4
+ * 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
5
+ * 保留所有权利 All Rights Reserved.
6
+ * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/core/agent/prompt/agent.prompt.mjs
7
+ */
8
+ import{FmodeChatCompletion}from"../chat";import{finalize}from"rxjs";export class AgentPrompt{constructor(){}jsonCompletion(e,t){let o,r=new FmodeChatCompletion([{role:"user",content:e}]);return r.model=t||"fmode-4.0-cn-256k",r.sendCompletion({isDirect:!0,onComplete:e=>{console.log("finalMessage",e);e?.content;e.complete=!0}}).pipe(finalize((()=>{let e;console.log(o);try{o.json=this.extractAndParseJson(e)}catch(e){}o.complete=!0})))}extractAndParseJson(e){let t=e.indexOf("{");if(-1===t)return{};let o=0,r=t;for(let n=t;n<e.length;n++)if("{"===e[n]?o++:"}"===e[n]&&o--,0===o){r=n;break}if(0!==o)return{};const n=e.slice(t,r+1);try{return JSON.parse(n)}catch(e){return console.error("Failed to parse JSON:",e),{}}}extractMarkdownToMultiArray(e){let t=e.split("\n"),o=[],r=o,n=[o];for(let e of t){if(!e.trim())continue;if(e.startsWith("#")){let t=e.replace(/^#+\s*/,"");r.push([t]);continue}let t=e.search(/\S/)/2,o=e.trim().replace(/^-+\s*/,"");for(;t<n.length-1;)n.pop();for(;t>n.length-1;){let e=[];n[n.length-1].push(e),n.push(e)}r=n[n.length-1],r.push(o)}return o}getTokens(e){return e=e||"",2*e?.length}}
9
+ var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9jb3JlL2FnZW50L3Byb21wdC9hZ2VudC5wcm9tcHQubWpz`
10
+
@@ -0,0 +1,10 @@
1
+
2
+ /**
3
+ * @copyright © 未来飞马 © 未来全栈 www.fmode.cn
4
+ * 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
5
+ * 保留所有权利 All Rights Reserved.
6
+ * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/core/agent/prompt/index.mjs
7
+ */
8
+ export*from"./agent.prompt";
9
+ var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9jb3JlL2FnZW50L3Byb21wdC9pbmRleC5tanM=`
10
+
@@ -0,0 +1,10 @@
1
+
2
+ /**
3
+ * @copyright © 未来飞马 © 未来全栈 www.fmode.cn
4
+ * 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
5
+ * 保留所有权利 All Rights Reserved.
6
+ * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/core/agent/prompt/prompt-util.mjs
7
+ */
8
+ import{PromptTemplate}from"@langchain/core/prompts";import Parse from"parse";export async function getFormatTpl(t,e){let r=await getPromptTpl(t);return await r.format(e)}export async function getPromptTpl(t){let e=new Parse.Query("PromptTemplate");e.equalTo("code",t);let r=await e.first();return PromptTemplate.fromTemplate(r?.get("template"),{templateFormat:"mustache"})}
9
+ var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9jb3JlL2FnZW50L3Byb21wdC9wcm9tcHQtdXRpbC5tanM=`
10
+
@@ -0,0 +1,10 @@
1
+
2
+ /**
3
+ * @copyright © 未来飞马 © 未来全栈 www.fmode.cn
4
+ * 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
5
+ * 保留所有权利 All Rights Reserved.
6
+ * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/core/agent/story/agent.story.mjs
7
+ */
8
+ import Parse from"parse";export class AgentStory{constructor(t,s,e){this.Story=Parse.Object.extend("Story"),this.Document=Parse.Object.extend("Document"),this.docsList=[],this.story?.id||(this.story=t),this.story?.id||t?.id||(this.story=new this.Story),s?.id&&this.story?.set("person",s?.toPointer()),e?.id&&this.story?.set("book",e),this.story?.get("user")?.id||this.story?.set("user",Parse.User.current()?.toPointer())}async setAttachment(t){let s=new Parse.Query("Attachment"),e=await s.get(t?.id);return this.story?.set("attach",e),this.story?.set("type","document"),this.story=await(this.story?.save()),this.story?.set("attach",e),e}async loadSlipt(t){let s=await fetch("https://server.fmode.cn/api/aiagent/indexes/loader",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:t?.get("url"),md5:t?.get("md5")})}),e=await s.json(),o=e?.data;return console.log(o),console.log(o?.split),o?.split?.length&&(this.docsList=o?.split?.map((t=>{let s=t,e=new this.Document;return e.set({pageContent:s.pageContent,metadata:s.metadata}),e}))),this.docsList}}
9
+ var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9jb3JlL2FnZW50L3N0b3J5L2FnZW50LnN0b3J5Lm1qcw==`
10
+