@magmamath/students-features 0.2.13 → 0.2.15

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 (56) hide show
  1. package/dist/commonjs/features/chatbot/helpers.js +8 -1
  2. package/dist/commonjs/features/chatbot/helpers.js.map +1 -1
  3. package/dist/commonjs/features/chatbot/model/api.js +3 -7
  4. package/dist/commonjs/features/chatbot/model/api.js.map +1 -1
  5. package/dist/commonjs/features/chatbot/model/model.js +4 -1
  6. package/dist/commonjs/features/chatbot/model/model.js.map +1 -1
  7. package/dist/commonjs/features/chatbot/model/t2s.js +10 -15
  8. package/dist/commonjs/features/chatbot/model/t2s.js.map +1 -1
  9. package/dist/commonjs/features/chatbot/types/model.types.js.map +1 -1
  10. package/dist/commonjs/features/feedback/types.js.map +1 -1
  11. package/dist/module/features/chatbot/helpers.js +5 -0
  12. package/dist/module/features/chatbot/helpers.js.map +1 -1
  13. package/dist/module/features/chatbot/model/api.js +3 -7
  14. package/dist/module/features/chatbot/model/api.js.map +1 -1
  15. package/dist/module/features/chatbot/model/model.js +5 -2
  16. package/dist/module/features/chatbot/model/model.js.map +1 -1
  17. package/dist/module/features/chatbot/model/t2s.js +8 -13
  18. package/dist/module/features/chatbot/model/t2s.js.map +1 -1
  19. package/dist/module/features/chatbot/types/model.types.js.map +1 -1
  20. package/dist/module/features/feedback/types.js.map +1 -1
  21. package/dist/typescript/commonjs/features/chatbot/helpers.d.ts +1 -0
  22. package/dist/typescript/commonjs/features/chatbot/helpers.d.ts.map +1 -1
  23. package/dist/typescript/commonjs/features/chatbot/model/api.d.ts +2 -3
  24. package/dist/typescript/commonjs/features/chatbot/model/api.d.ts.map +1 -1
  25. package/dist/typescript/commonjs/features/chatbot/model/model.d.ts +3 -3
  26. package/dist/typescript/commonjs/features/chatbot/model/model.d.ts.map +1 -1
  27. package/dist/typescript/commonjs/features/chatbot/model/t2s.d.ts +10 -4
  28. package/dist/typescript/commonjs/features/chatbot/model/t2s.d.ts.map +1 -1
  29. package/dist/typescript/commonjs/features/chatbot/types/api.types.d.ts +4 -0
  30. package/dist/typescript/commonjs/features/chatbot/types/api.types.d.ts.map +1 -1
  31. package/dist/typescript/commonjs/features/chatbot/types/model.types.d.ts +2 -2
  32. package/dist/typescript/commonjs/features/chatbot/types/model.types.d.ts.map +1 -1
  33. package/dist/typescript/commonjs/features/feedback/types.d.ts +1 -0
  34. package/dist/typescript/commonjs/features/feedback/types.d.ts.map +1 -1
  35. package/dist/typescript/module/features/chatbot/helpers.d.ts +1 -0
  36. package/dist/typescript/module/features/chatbot/helpers.d.ts.map +1 -1
  37. package/dist/typescript/module/features/chatbot/model/api.d.ts +2 -3
  38. package/dist/typescript/module/features/chatbot/model/api.d.ts.map +1 -1
  39. package/dist/typescript/module/features/chatbot/model/model.d.ts +3 -3
  40. package/dist/typescript/module/features/chatbot/model/model.d.ts.map +1 -1
  41. package/dist/typescript/module/features/chatbot/model/t2s.d.ts +10 -4
  42. package/dist/typescript/module/features/chatbot/model/t2s.d.ts.map +1 -1
  43. package/dist/typescript/module/features/chatbot/types/api.types.d.ts +4 -0
  44. package/dist/typescript/module/features/chatbot/types/api.types.d.ts.map +1 -1
  45. package/dist/typescript/module/features/chatbot/types/model.types.d.ts +2 -2
  46. package/dist/typescript/module/features/chatbot/types/model.types.d.ts.map +1 -1
  47. package/dist/typescript/module/features/feedback/types.d.ts +1 -0
  48. package/dist/typescript/module/features/feedback/types.d.ts.map +1 -1
  49. package/package.json +1 -1
  50. package/src/features/chatbot/helpers.ts +16 -1
  51. package/src/features/chatbot/model/api.ts +5 -17
  52. package/src/features/chatbot/model/model.ts +243 -252
  53. package/src/features/chatbot/model/t2s.ts +90 -92
  54. package/src/features/chatbot/types/api.types.ts +5 -0
  55. package/src/features/chatbot/types/model.types.ts +44 -43
  56. package/src/features/feedback/types.ts +1 -0
@@ -1,107 +1,105 @@
1
- import { ChatbotModel } from './model'
2
- import { restore, createEvent } from 'effector'
1
+ import { restore, createEvent, Store } from 'effector'
3
2
  import { AUDIO_CONFIG, DEFAULT_VOICE } from '../constants'
4
3
  import { AudioProvider, AudioStatus, PlayTextToSpeechProps } from '../types/t2s.types'
4
+ import { ChatbotAPI } from './api'
5
5
 
6
- export class ChatTextToSpeech {
7
- private readonly model: ChatbotModel
8
- private readonly audioCache: Record<string, string> = {}
9
- private audioProvider: AudioProvider | null = null
6
+ type ChatTextToSpeechModelProps = {
7
+ $isOpen: Store<boolean>
8
+ api: ChatbotAPI
9
+ }
10
10
 
11
- readonly setCurrentPlayingId = createEvent<string | null>()
12
- readonly $currentPlayingId = restore(this.setCurrentPlayingId, null)
13
- readonly setStatus = createEvent<AudioStatus>()
14
- readonly $status = restore(this.setStatus, AudioStatus.STOPPED)
11
+ export class ChatTextToSpeechModel {
12
+ private readonly api: ChatbotAPI
13
+ private readonly audioCache: Record<string, string> = {}
14
+ private audioProvider: AudioProvider | null = null
15
+
16
+ readonly setCurrentPlayingId = createEvent<string | null>()
17
+ readonly $currentPlayingId = restore(this.setCurrentPlayingId, null)
18
+ readonly setStatus = createEvent<AudioStatus>()
19
+ readonly $status = restore(this.setStatus, AudioStatus.STOPPED)
20
+
21
+ constructor({ $isOpen, api }: ChatTextToSpeechModelProps) {
22
+ this.api = api
23
+
24
+ $isOpen.updates.watch(isOpen => {
25
+ if (!isOpen) this.reset()
26
+ })
27
+ }
28
+
29
+ public setAudioProvider(audioProvider: AudioProvider) {
30
+ this.audioProvider = audioProvider
31
+ }
32
+
33
+ private getCacheKey = (messageId: string, isTranslated: boolean) => {
34
+ return `${messageId}-${isTranslated ? 'translated' : 'original'}`
35
+ }
36
+
37
+ async play({ text, messageId, isTranslated, config }: PlayTextToSpeechProps) {
38
+ if (!this.audioProvider) throw new Error('Audio provider is not set. Use setAudioProvider.')
39
+
40
+ try {
41
+ const status = this.$status.getState()
42
+ const playingId = this.$currentPlayingId.getState()
43
+ const isPlaying = status === AudioStatus.PLAYING
44
+ const isPaused = status === AudioStatus.PAUSED
45
+ const isCurrentMessage = messageId === playingId
46
+
47
+ if (isPlaying && isCurrentMessage) {
48
+ this.audioProvider.pause()
49
+ this.setStatus(AudioStatus.PAUSED)
50
+ return
51
+ }
52
+
53
+ if (isPaused && isCurrentMessage) {
54
+ this.audioProvider.resume()
55
+ this.setStatus(AudioStatus.PLAYING)
56
+ return
57
+ }
58
+
59
+ if (messageId && !isCurrentMessage) {
60
+ this.audioProvider.stop()
61
+ }
15
62
 
16
- constructor(chatbotModel: ChatbotModel) {
17
- this.model = chatbotModel
63
+ const cacheKey = this.getCacheKey(messageId, isTranslated)
64
+ let audioPath = this.audioCache[cacheKey]
65
+ this.setCurrentPlayingId(messageId)
18
66
 
19
- this.model.$isOpen.updates.watch((isOpen) => {
20
- if (!isOpen) this.reset()
67
+ if (!audioPath) {
68
+ const response = await this.api.textToSpeechTextFx({
69
+ input: { text },
70
+ voice: config?.voice ?? DEFAULT_VOICE,
71
+ audioConfig: config?.audioConfig ?? AUDIO_CONFIG,
21
72
  })
22
- }
23
73
 
24
- public setAudioProvider(audioProvider: AudioProvider) {
25
- this.audioProvider = audioProvider
26
- }
27
-
28
- private getCacheKey = (messageId: string, isTranslated: boolean) => {
29
- return `${messageId}-${isTranslated ? 'translated' : 'original'}`
30
- }
31
-
32
- async play({ text, messageId, isTranslated, config }: PlayTextToSpeechProps) {
33
- if (!this.audioProvider) throw new Error('Audio provider is not set. Use setAudioProvider.')
34
-
35
- try {
36
- const status = this.$status.getState()
37
- const playingId = this.$currentPlayingId.getState()
38
- const isPlaying = status === AudioStatus.PLAYING
39
- const isPaused = status === AudioStatus.PAUSED
40
- const isCurrentMessage = messageId === playingId
41
-
42
- if (isPlaying && isCurrentMessage) {
43
- this.audioProvider.pause()
44
- this.setStatus(AudioStatus.PAUSED)
45
- return
46
- }
47
-
48
- if (isPaused && isCurrentMessage) {
49
- this.audioProvider.resume()
50
- this.setStatus(AudioStatus.PLAYING)
51
- return
52
- }
53
-
54
- if (messageId && !isCurrentMessage) {
55
- this.audioProvider.stop()
56
- }
57
-
58
- const cacheKey = this.getCacheKey(messageId, isTranslated)
59
- let audioPath = this.audioCache[cacheKey]
60
- this.setCurrentPlayingId(messageId)
61
-
62
- if (!audioPath) {
63
- const response = await this.model.api.textToSpeechTextFx({
64
- input: { text },
65
- voice: config?.voice ?? DEFAULT_VOICE,
66
- audioConfig: config?.audioConfig ?? AUDIO_CONFIG,
67
- })
68
-
69
- // Response might be different type based on provided AUDIO_CONFIG
70
- if (typeof response === 'string') {
71
- audioPath = `data:audio/mpeg;base64,${response}`
72
- } else {
73
- audioPath = response?.audioContent ?? ''
74
- }
75
-
76
- this.audioCache[cacheKey] = audioPath
77
- }
78
-
79
- this.setStatus(AudioStatus.PLAYING)
80
- await this.audioProvider.play(audioPath, () => {
81
- this.setStatus(AudioStatus.STOPPED)
82
- this.setCurrentPlayingId(null)
83
- })
84
- } catch (error) {
85
- this.reset()
86
- console.error('Error playing text-to-speech: ', error)
74
+ // Response might be different type based on provided AUDIO_CONFIG
75
+ if (typeof response === 'string') {
76
+ audioPath = `data:audio/mpeg;base64,${response}`
77
+ } else {
78
+ audioPath = response?.audioContent ?? ''
87
79
  }
88
- }
89
-
90
- public stop() {
91
- if (!this.audioProvider) throw new Error('Audio provider is not set. Use setAudioProvider.')
92
- this.audioProvider.stop()
93
- }
94
80
 
95
- // reset should also do stop(), add watcher to model to not write it in repos
96
- // chatbotModel.$isOpen.updates.watch((isOpen) => {
97
- // if (!isOpen) {
98
- // chatbotModel.t2s.stop();
99
- // chatbotModel.t2s.reset();
100
- // }
81
+ this.audioCache[cacheKey] = audioPath
82
+ }
101
83
 
102
- public reset() {
103
- this.stop()
84
+ this.setStatus(AudioStatus.PLAYING)
85
+ await this.audioProvider.play(audioPath, () => {
104
86
  this.setStatus(AudioStatus.STOPPED)
105
87
  this.setCurrentPlayingId(null)
88
+ })
89
+ } catch (error) {
90
+ this.reset()
91
+ console.error('Error playing text-to-speech: ', error)
106
92
  }
93
+ }
94
+
95
+ public stop() {
96
+ if (!this.audioProvider) throw new Error('Audio provider is not set. Use setAudioProvider.')
97
+ this.audioProvider.stop()
98
+ }
99
+
100
+ public reset() {
101
+ this.stop()
102
+ this.setStatus(AudioStatus.STOPPED)
103
+ this.setCurrentPlayingId(null)
104
+ }
107
105
  }
@@ -4,6 +4,11 @@ export type ChatAnswer = {
4
4
  translatedText?: string
5
5
  }
6
6
 
7
+ export type GetAlternativesPayload = {
8
+ municipalityId: string
9
+ assignmentClassGrade: number
10
+ } | void
11
+
7
12
  export type GetAlternativesResponse = {
8
13
  chatAccess?: boolean
9
14
  options: {
@@ -1,27 +1,28 @@
1
1
  import type { Store } from 'effector'
2
2
  import {
3
- GetAlternativesResponse,
4
- PostMessagePayload,
5
- PostMessageResponse,
6
- GoogleTranslatePayload,
7
- GoogleTranslateResponse,
8
- GoogleText2SpeechPayload,
9
- GoogleText2SpeechResponse,
10
- ChatAnswer,
3
+ GetAlternativesResponse,
4
+ PostMessagePayload,
5
+ PostMessageResponse,
6
+ GoogleTranslatePayload,
7
+ GoogleTranslateResponse,
8
+ GoogleText2SpeechPayload,
9
+ GoogleText2SpeechResponse,
10
+ ChatAnswer,
11
+ GetAlternativesPayload,
11
12
  } from './api.types'
12
13
 
13
14
  export type ConversationMessage = {
14
- id: string
15
- message: string
16
- threadId: string
17
- options: ChatAnswer[]
18
- isOwnMessage: boolean
19
- translatedMessage?: string
15
+ id: string
16
+ message: string
17
+ threadId: string
18
+ options: ChatAnswer[]
19
+ isOwnMessage: boolean
20
+ translatedMessage?: string
20
21
  }
21
22
 
22
23
  export type EntityIds = {
23
- entityId: string
24
- fieldId: string
24
+ entityId: string
25
+ fieldId: string
25
26
  }
26
27
 
27
28
  export type ChatMessagesModel = EntityIds & { messages: ConversationMessage[] }
@@ -29,45 +30,45 @@ export type ThreadIdsModel = EntityIds & { threadId: string }
29
30
  export type AvailableChatsModel = EntityIds & { isAvailable: boolean }
30
31
 
31
32
  export type ChatbotModelProps = {
32
- credits: {
33
- $assignmentId: Store<string>
34
- $exerciseId: Store<string>
35
- },
36
- api: {
37
- getAlternatives: (props: void) => Promise<GetAlternativesResponse>
38
- postMessage: (props: PostMessagePayload) => Promise<PostMessageResponse>
39
- postTranslateText: (props: GoogleTranslatePayload) => Promise<GoogleTranslateResponse>
40
- postTextToSpeech: (props: GoogleText2SpeechPayload) => Promise<GoogleText2SpeechResponse>
41
- }
42
- messages: {
43
- error: ConversationMessage,
44
- start: ConversationMessage
45
- }
33
+ credits: {
34
+ $assignmentId: Store<string>
35
+ $exerciseId: Store<string>
36
+ }
37
+ api: {
38
+ getAlternatives: (props: GetAlternativesPayload) => Promise<GetAlternativesResponse>
39
+ postMessage: (props: PostMessagePayload) => Promise<PostMessageResponse>
40
+ postTranslateText: (props: GoogleTranslatePayload) => Promise<GoogleTranslateResponse>
41
+ postTextToSpeech: (props: GoogleText2SpeechPayload) => Promise<GoogleText2SpeechResponse>
42
+ }
43
+ messages: {
44
+ error: ConversationMessage
45
+ start: ConversationMessage
46
+ }
46
47
  }
47
48
 
48
49
  export type SendHelpParams = {
49
- payload: PostMessagePayload
50
- message: string
51
- translationTargetLanguage: string
52
- translatedMessage?: string
50
+ payload: PostMessagePayload
51
+ message: string
52
+ translationTargetLanguage: string
53
+ translatedMessage?: string
53
54
  }
54
55
 
55
56
  export type SendHelpProps = SendHelpParams & {
56
- assignmentId: string
57
- exerciseId: string
58
- messages: Record<string, Record<string, { messages: ConversationMessage[] }>>
59
- isTranslated: boolean
57
+ assignmentId: string
58
+ exerciseId: string
59
+ messages: Record<string, Record<string, { messages: ConversationMessage[] }>>
60
+ isTranslated: boolean
60
61
  }
61
62
 
62
63
  export type SetHintMessageProps = EntityIds & ConversationMessage
63
64
 
64
65
  export enum MessageVariant {
65
- SENT = 'sent',
66
- RECEIVED = 'received',
66
+ SENT = 'sent',
67
+ RECEIVED = 'received',
67
68
  }
68
69
 
69
70
  export type ChatbotRenderer = {
70
- message: string
71
- variant: MessageVariant
72
- withTextToSpeech: boolean
71
+ message: string
72
+ variant: MessageVariant
73
+ withTextToSpeech: boolean
73
74
  }
@@ -2,6 +2,7 @@ import { EMPTY_COMMENT_ID } from './constants'
2
2
 
3
3
  export type GetCommentsPayload = {
4
4
  id: string
5
+ userId: string
5
6
  }
6
7
 
7
8
  export type GetCommentsResponse = {