@adminforth/agent 2.0.9 → 2.1.0

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 (187) hide show
  1. package/README.md +333 -10
  2. package/dist/application/ports.d.ts +66 -0
  3. package/dist/application/runTurnUseCase.d.ts +68 -0
  4. package/dist/application/runTurnUseCase.js +358 -0
  5. package/dist/{agentEvents.d.ts → domain/agentEvents.d.ts} +1 -1
  6. package/dist/{agent → domain}/systemPrompt.js +1 -1
  7. package/dist/{agent/turn → domain}/turnTypes.d.ts +41 -37
  8. package/dist/{agent/turn/VegaLiteStreamBuffer.d.ts → domain/vegaLiteStreamBuffer.d.ts} +1 -1
  9. package/dist/index.d.ts +3 -2
  10. package/dist/index.js +40 -35
  11. package/dist/{agent/runtime/AgentContext.d.ts → llm/agentContext.d.ts} +3 -3
  12. package/dist/{agent/simpleAgent.d.ts → llm/agentModels.d.ts} +18 -16
  13. package/dist/llm/agentModels.js +65 -0
  14. package/dist/{agent/runtime/AgentRuntime.d.ts → llm/agentRuntime.d.ts} +11 -2
  15. package/dist/{agent/runtime/AgentRuntime.js → llm/agentRuntime.js} +38 -6
  16. package/dist/llm/langGraphLlm.d.ts +25 -0
  17. package/dist/llm/langGraphLlm.js +54 -0
  18. package/dist/{agent/middleware/apiBasedTools.d.ts → llm/middleware/apiToolsMiddleware.d.ts} +1 -1
  19. package/dist/{agent/middleware/apiBasedTools.js → llm/middleware/apiToolsMiddleware.js} +8 -14
  20. package/dist/{agent → llm}/middleware/sequenceDebug.d.ts +1 -1
  21. package/dist/{agent/models/AgentModelFactory.d.ts → llm/modelFactory.d.ts} +1 -1
  22. package/dist/{agent/models/AgentModelFactory.js → llm/modelFactory.js} +1 -1
  23. package/dist/llm/streamAdapter.d.ts +18 -0
  24. package/dist/llm/streamAdapter.js +117 -0
  25. package/dist/{sessionStore.d.ts → persistence/sessionStore.d.ts} +12 -2
  26. package/dist/{sessionStore.js → persistence/sessionStore.js} +33 -0
  27. package/dist/{agent/tools/AgentToolProvider.d.ts → tools/agentToolProvider.d.ts} +1 -1
  28. package/dist/{agent/tools/AgentToolProvider.js → tools/agentToolProvider.js} +1 -1
  29. package/dist/{apiBasedTools.js → tools/apiBasedTools.js} +10 -6
  30. package/dist/{agent/tools → tools}/apiTool.d.ts +1 -1
  31. package/dist/{agent/tools → tools}/fetchSkill.js +1 -1
  32. package/dist/{agent/tools → tools}/fetchToolSchema.d.ts +1 -1
  33. package/dist/{agent/tools → tools}/index.d.ts +1 -1
  34. package/dist/{agent/tools → tools}/navigateUser.d.ts +3 -3
  35. package/dist/{endpoints → transport/http}/context.d.ts +2 -2
  36. package/dist/transport/http/context.js +1 -0
  37. package/dist/{endpoints/core.js → transport/http/coreEndpoints.js} +3 -3
  38. package/dist/{endpoints/sessions.js → transport/http/sessionEndpoints.js} +7 -1
  39. package/dist/transport/sse/sseWriter.d.ts +29 -0
  40. package/dist/{surfaces/web-sse/createSseEventEmitter.js → transport/sse/sseWriter.js} +15 -0
  41. package/dist/{chatSurfaceService.d.ts → transport/surfaces/chatSurfaceService.d.ts} +3 -3
  42. package/dist/{chatSurfaceService.js → transport/surfaces/chatSurfaceService.js} +7 -5
  43. package/dist/{agent/speech/SpeechTurnService.d.ts → transport/surfaces/speechTurnService.d.ts} +1 -1
  44. package/dist/{agent/speech/SpeechTurnService.js → transport/surfaces/speechTurnService.js} +2 -2
  45. package/dist/types.d.ts +10 -4
  46. package/package.json +11 -2
  47. package/.woodpecker/buildRelease.sh +0 -13
  48. package/.woodpecker/buildSlackNotify.sh +0 -46
  49. package/.woodpecker/release.yml +0 -57
  50. package/agent/checkpointer.ts +0 -329
  51. package/agent/languageDetect.ts +0 -92
  52. package/agent/middleware/apiBasedTools.ts +0 -174
  53. package/agent/middleware/openAiResponsesContinuation.ts +0 -92
  54. package/agent/middleware/sequenceDebug.ts +0 -429
  55. package/agent/models/AgentModeResolver.ts +0 -9
  56. package/agent/models/AgentModelFactory.ts +0 -28
  57. package/agent/runtime/AgentContext.ts +0 -30
  58. package/agent/runtime/AgentRuntime.ts +0 -89
  59. package/agent/simpleAgent.ts +0 -199
  60. package/agent/skills/registry.ts +0 -162
  61. package/agent/speech/SpeechTurnService.ts +0 -179
  62. package/agent/systemPrompt.ts +0 -133
  63. package/agent/toolCallEvents.ts +0 -135
  64. package/agent/tools/AgentToolProvider.ts +0 -28
  65. package/agent/tools/apiTool.ts +0 -66
  66. package/agent/tools/fetchSkill.ts +0 -68
  67. package/agent/tools/fetchToolSchema.ts +0 -47
  68. package/agent/tools/getUserLocation.ts +0 -45
  69. package/agent/tools/index.ts +0 -31
  70. package/agent/tools/navigateUser.ts +0 -210
  71. package/agent/turn/TurnContextBuilder.ts +0 -36
  72. package/agent/turn/TurnLifecycleService.ts +0 -47
  73. package/agent/turn/TurnPersistenceService.ts +0 -33
  74. package/agent/turn/TurnPromptBuilder.ts +0 -51
  75. package/agent/turn/TurnStreamConsumer.ts +0 -69
  76. package/agent/turn/VegaLiteStreamBuffer.ts +0 -90
  77. package/agent/turn/turnTypes.ts +0 -100
  78. package/agentEvents.ts +0 -75
  79. package/agentTurnService.ts +0 -314
  80. package/apiBasedTools.ts +0 -702
  81. package/build.log +0 -67
  82. package/chatSurfaceService.ts +0 -319
  83. package/custom/ChatFooter.vue +0 -173
  84. package/custom/ChatHeader.vue +0 -78
  85. package/custom/ChatSurface.vue +0 -160
  86. package/custom/CustomAutoScrollContainer.vue +0 -164
  87. package/custom/SessionsHistory.vue +0 -88
  88. package/custom/chat.ts +0 -82
  89. package/custom/composables/agentAudio/utils.ts +0 -220
  90. package/custom/composables/agentStore/constants.ts +0 -19
  91. package/custom/composables/agentStore/pageContext.ts +0 -8
  92. package/custom/composables/agentStore/useAgentChat.ts +0 -241
  93. package/custom/composables/agentStore/useAgentPlaceholder.ts +0 -142
  94. package/custom/composables/agentStore/useAgentSessions.ts +0 -350
  95. package/custom/composables/useAgentAudio.ts +0 -272
  96. package/custom/composables/useAgentStore.ts +0 -510
  97. package/custom/composables/useAgentTransitions.ts +0 -58
  98. package/custom/conversation_area/ConversationArea.vue +0 -301
  99. package/custom/conversation_area/MessageRenderer.vue +0 -49
  100. package/custom/conversation_area/ProcessingTimeline.vue +0 -286
  101. package/custom/conversation_area/ReasoningRenderer.vue +0 -79
  102. package/custom/conversation_area/SystemMessageRenderer.vue +0 -28
  103. package/custom/conversation_area/TextRenderer.vue +0 -182
  104. package/custom/conversation_area/ThreeDotsAnimation.vue +0 -35
  105. package/custom/conversation_area/ToolApprovalRenderer.vue +0 -98
  106. package/custom/conversation_area/ToolRenderer.vue +0 -178
  107. package/custom/conversation_area/ToolsGroup.vue +0 -59
  108. package/custom/env.d.ts +0 -7
  109. package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +0 -393
  110. package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +0 -285
  111. package/custom/incremark_code_renderers/incremarkRenderer.ts +0 -653
  112. package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +0 -118
  113. package/custom/package.json +0 -30
  114. package/custom/pnpm-lock.yaml +0 -2394
  115. package/custom/public/agentAudio/agent-processing.mp3 +0 -0
  116. package/custom/skills/analyze_data/SKILL.md +0 -25
  117. package/custom/skills/charts/SKILL.md +0 -193
  118. package/custom/skills/fetch_data/SKILL.md +0 -31
  119. package/custom/skills/mutate_data/SKILL.md +0 -121
  120. package/custom/speech_recognition_frontend/AudioLines.vue +0 -43
  121. package/custom/speech_recognition_frontend/MicrophoneButon.vue +0 -185
  122. package/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +0 -22
  123. package/custom/speech_recognition_frontend/voiceActivityDetection.ts +0 -62
  124. package/custom/tsconfig.json +0 -15
  125. package/custom/types.ts +0 -108
  126. package/custom/utils.ts +0 -38
  127. package/dist/agent/middleware/openAiResponsesContinuation.d.ts +0 -1
  128. package/dist/agent/middleware/openAiResponsesContinuation.js +0 -66
  129. package/dist/agent/models/AgentModeResolver.d.ts +0 -9
  130. package/dist/agent/models/AgentModeResolver.js +0 -9
  131. package/dist/agent/simpleAgent.js +0 -118
  132. package/dist/agent/turn/TurnContextBuilder.d.ts +0 -14
  133. package/dist/agent/turn/TurnContextBuilder.js +0 -31
  134. package/dist/agent/turn/TurnLifecycleService.d.ts +0 -24
  135. package/dist/agent/turn/TurnLifecycleService.js +0 -47
  136. package/dist/agent/turn/TurnPersistenceService.d.ts +0 -13
  137. package/dist/agent/turn/TurnPersistenceService.js +0 -35
  138. package/dist/agent/turn/TurnPromptBuilder.d.ts +0 -19
  139. package/dist/agent/turn/TurnPromptBuilder.js +0 -43
  140. package/dist/agent/turn/TurnStreamConsumer.d.ts +0 -11
  141. package/dist/agent/turn/TurnStreamConsumer.js +0 -84
  142. package/dist/agentTurnService.d.ts +0 -24
  143. package/dist/agentTurnService.js +0 -269
  144. package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +0 -14
  145. package/endpoints/chatSurfaces.ts +0 -66
  146. package/endpoints/context.ts +0 -52
  147. package/endpoints/core.ts +0 -181
  148. package/endpoints/sessions.ts +0 -183
  149. package/errors.ts +0 -10
  150. package/index.ts +0 -192
  151. package/pnpm-workspace.yaml +0 -4
  152. package/sanitizeSpeechText.ts +0 -32
  153. package/sessionStore.ts +0 -105
  154. package/surfaces/web-sse/createSseEventEmitter.ts +0 -311
  155. package/tsconfig.json +0 -14
  156. package/types.ts +0 -127
  157. /package/dist/{agent/turn/turnTypes.js → application/ports.js} +0 -0
  158. /package/dist/{agentEvents.js → domain/agentEvents.js} +0 -0
  159. /package/dist/{agent → domain}/languageDetect.d.ts +0 -0
  160. /package/dist/{agent → domain}/languageDetect.js +0 -0
  161. /package/dist/{agent → domain}/systemPrompt.d.ts +0 -0
  162. /package/dist/{agent → domain}/toolCallEvents.d.ts +0 -0
  163. /package/dist/{agent → domain}/toolCallEvents.js +0 -0
  164. /package/dist/{endpoints/context.js → domain/turnTypes.js} +0 -0
  165. /package/dist/{agent/turn/VegaLiteStreamBuffer.js → domain/vegaLiteStreamBuffer.js} +0 -0
  166. /package/dist/{agent/runtime/AgentContext.js → llm/agentContext.js} +0 -0
  167. /package/dist/{agent → llm}/middleware/sequenceDebug.js +0 -0
  168. /package/dist/{agent/checkpointer.d.ts → persistence/checkpointStore.d.ts} +0 -0
  169. /package/dist/{agent/checkpointer.js → persistence/checkpointStore.js} +0 -0
  170. /package/dist/{errors.d.ts → shared/errors.d.ts} +0 -0
  171. /package/dist/{errors.js → shared/errors.js} +0 -0
  172. /package/dist/{sanitizeSpeechText.d.ts → shared/sanitizeSpeechText.d.ts} +0 -0
  173. /package/dist/{sanitizeSpeechText.js → shared/sanitizeSpeechText.js} +0 -0
  174. /package/dist/{apiBasedTools.d.ts → tools/apiBasedTools.d.ts} +0 -0
  175. /package/dist/{agent/tools → tools}/apiTool.js +0 -0
  176. /package/dist/{agent/tools → tools}/fetchSkill.d.ts +0 -0
  177. /package/dist/{agent/tools → tools}/fetchToolSchema.js +0 -0
  178. /package/dist/{agent/tools → tools}/getUserLocation.d.ts +0 -0
  179. /package/dist/{agent/tools → tools}/getUserLocation.js +0 -0
  180. /package/dist/{agent/tools → tools}/index.js +0 -0
  181. /package/dist/{agent/tools → tools}/navigateUser.js +0 -0
  182. /package/dist/{agent → tools}/skills/registry.d.ts +0 -0
  183. /package/dist/{agent → tools}/skills/registry.js +0 -0
  184. /package/dist/{endpoints/chatSurfaces.d.ts → transport/http/chatSurfaceEndpoints.d.ts} +0 -0
  185. /package/dist/{endpoints/chatSurfaces.js → transport/http/chatSurfaceEndpoints.js} +0 -0
  186. /package/dist/{endpoints/core.d.ts → transport/http/coreEndpoints.d.ts} +0 -0
  187. /package/dist/{endpoints/sessions.d.ts → transport/http/sessionEndpoints.d.ts} +0 -0
@@ -1,350 +0,0 @@
1
- import type { ComputedRef, Ref, ShallowRef } from 'vue';
2
- import { callAdminForthApi } from '@/utils';
3
- import type { Chat } from '../../chat';
4
- import type { IAgentSession, ISessionsListItem, IPart } from '../../types';
5
- import { PRE_SESSION_ID } from './constants';
6
- import { i18nInstance } from '@/i18n';
7
-
8
- type AdminforthLike = {
9
- confirm(options: { title?: string; message?: string; yes?: string; no?: string; dangerous?: boolean }): Promise<boolean>;
10
- };
11
-
12
- type CreateAgentSessionManagerOptions = {
13
- activeSessionId: Ref<string | null>;
14
- currentSession: Ref<IAgentSession | null>;
15
- sessionList: Ref<ISessionsListItem[]>;
16
- sessions: Ref<Record<string, IAgentSession>>;
17
- currentChat: ShallowRef<Chat<any> | null | undefined>;
18
- trimmedUserMessage: ComputedRef<string>;
19
- isResponseInProgress: ComputedRef<boolean>;
20
- isMessageInputBlocked: ComputedRef<boolean>;
21
- userMessageInput: Ref<any>;
22
- lastMessage: Ref<string>;
23
- blockCloseOfChat: Ref<boolean>;
24
- adminforth: AdminforthLike;
25
- setCurrentChat: (sessionId: string) => void;
26
- };
27
-
28
- export function createAgentSessionManager({
29
- activeSessionId,
30
- currentSession,
31
- sessionList,
32
- sessions,
33
- currentChat,
34
- trimmedUserMessage,
35
- isResponseInProgress,
36
- isMessageInputBlocked,
37
- userMessageInput,
38
- lastMessage,
39
- blockCloseOfChat,
40
- adminforth,
41
- setCurrentChat,
42
- }: CreateAgentSessionManagerOptions) {
43
- function sortSessionsListByTimestamp(sessionsListToSort: ISessionsListItem[]) {
44
- return [...sessionsListToSort].sort((a: ISessionsListItem, b: ISessionsListItem) => b.timestamp.localeCompare(a.timestamp));
45
- }
46
-
47
- function t(key: string) {
48
- return i18nInstance?.global.t(key) ?? key;
49
- }
50
-
51
- function saveCurrentSessionInCache() {
52
- if (currentSession.value) {
53
- currentSession.value.messages = currentChat.value?.messages.map((m: any) => ({
54
- role: m.role,
55
- text: m.parts.map((p: IPart) => p.type === 'text' ? p.text : '').join(''),
56
- })) || [];
57
- sessions.value[currentSession.value.sessionId] = currentSession.value;
58
- }
59
- }
60
-
61
- async function fetchSession(sessionId: string) {
62
- try {
63
- const res = await callAdminForthApi({
64
- method: 'POST',
65
- path: '/agent/get-session-info',
66
- body: { sessionId },
67
- });
68
- if (res.error) {
69
- console.error('Error fetching session:', res.error);
70
- return;
71
- }
72
- sessions.value[sessionId] = res.session;
73
- setCurrentChat(sessionId);
74
- } catch (error) {
75
- console.error('Error fetching session', error);
76
- }
77
- }
78
-
79
- async function setActiveSession(sessionId: string) {
80
- activeSessionId.value = sessionId;
81
- saveCurrentSessionInCache();
82
- if (!sessions.value[sessionId]) {
83
- await fetchSession(sessionId);
84
- }
85
- currentSession.value = sessions.value[sessionId];
86
- setCurrentChat(sessionId);
87
- if (currentChat.value.messages.length === 0) {
88
- currentChat.value.messages = currentSession.value?.messages.map((m: any) => ({
89
- role: m.role,
90
- parts:[{
91
- type: 'text',
92
- text: m.text,
93
- state: 'done',
94
- }]
95
- }));
96
- }
97
- }
98
-
99
- async function deletePreSession() {
100
- sessionList.value = sessionList.value.filter((s: ISessionsListItem) => s.sessionId !== PRE_SESSION_ID);
101
- if (activeSessionId.value === PRE_SESSION_ID) {
102
- activeSessionId.value = null;
103
- currentSession.value = null;
104
- }
105
- }
106
-
107
- async function createNewSession(triggerMessage?: string) {
108
- try {
109
- const res = await callAdminForthApi({
110
- method: 'POST',
111
- path: '/agent/create-session',
112
- body: {
113
- triggerMessage
114
- },
115
- });
116
- if (res.error) {
117
- console.error('Error creating new session:', res.error);
118
- return;
119
- }
120
- deletePreSession();
121
- sessions.value[res.sessionId] = res;
122
- sessionList.value.unshift({
123
- sessionId: res.sessionId,
124
- title: res.title,
125
- timestamp: new Date().toISOString(),
126
- });
127
- setActiveSession(res.sessionId);
128
- } catch (error) {
129
- console.error('Error creating new session', error);
130
- }
131
- }
132
-
133
- async function sendMessage() {
134
- const message = trimmedUserMessage.value;
135
- if (!message || isMessageInputBlocked.value) {
136
- return;
137
- }
138
- if (!currentSession.value || currentSession.value.sessionId === PRE_SESSION_ID) {
139
- await createNewSession(message);
140
- }
141
- currentSession.value!.timestamp = new Date().toISOString();
142
- sessionList.value = sortSessionsListByTimestamp(sessionList.value.map((s: ISessionsListItem) => s.sessionId === currentSession.value?.sessionId ? {
143
- ...s,
144
- timestamp: currentSession.value?.timestamp || s.timestamp,
145
- } : s));
146
- lastMessage.value = message;
147
- currentChat.value?.sendMessage({
148
- text: message,
149
- });
150
- userMessageInput.value = '';
151
- }
152
-
153
- async function createPreSession() {
154
- saveCurrentSessionInCache();
155
- if (!sessionList.value.some((s: ISessionsListItem) => s.sessionId === PRE_SESSION_ID)) {
156
- sessionList.value.unshift({
157
- sessionId: PRE_SESSION_ID,
158
- title: 'New Session',
159
- timestamp: new Date().toISOString(),
160
- });
161
- }
162
-
163
- activeSessionId.value = PRE_SESSION_ID;
164
- currentSession.value = {
165
- sessionId: PRE_SESSION_ID,
166
- title: 'New Session',
167
- timestamp: new Date().toISOString(),
168
- messages: [],
169
- };
170
- sessions.value[PRE_SESSION_ID] = currentSession.value;
171
- setCurrentChat(PRE_SESSION_ID);
172
- }
173
-
174
- async function deleteSession(sessionId: string) {
175
- if (sessionId === PRE_SESSION_ID) {
176
- deletePreSession();
177
- return;
178
- }
179
- blockCloseOfChat.value = true;
180
- const isConfirmed = await adminforth.confirm({title: t('Are you sure, that you want to delete this session?'), message: t('This process is irreversible.'), yes: 'Yes', no: 'No', dangerous: true});
181
- blockCloseOfChat.value = false;
182
- if (!isConfirmed) {
183
- return;
184
- }
185
- try {
186
- const res = await callAdminForthApi({
187
- method: 'POST',
188
- path: '/agent/delete-session',
189
- body: { sessionId },
190
- });
191
- if (res.error) {
192
- console.error('Error deleting session:', res.error);
193
- return;
194
- }
195
- delete sessions.value[sessionId];
196
- sessionList.value = sessionList.value.filter((s: ISessionsListItem) => s.sessionId !== sessionId);
197
- if (activeSessionId.value === sessionId) {
198
- activeSessionId.value = null;
199
- currentSession.value = null;
200
- }
201
- } catch (error) {
202
- console.error('Error deleting session', error);
203
- }
204
- if(sessionId === activeSessionId.value) {
205
- activeSessionId.value = sessionList.value.length > 0 ? sessionList.value[0].sessionId : null;
206
- if (activeSessionId.value) {
207
- currentSession.value = sessions.value[activeSessionId.value] || null;
208
- } else {
209
- currentSession.value = null;
210
- }
211
- }
212
- createPreSession();
213
- }
214
-
215
- async function fetchSessionsList() {
216
- try {
217
- const res = await callAdminForthApi({
218
- method: 'POST',
219
- path: '/agent/get-sessions',
220
- body: {
221
- limit: 100,
222
- },
223
- });
224
- if (res.error) {
225
- console.error('Error fetching sessions list:', res.error);
226
- return;
227
- }
228
- sessionList.value = res.sessions;
229
- } catch (error) {
230
- console.error('Error fetching sessions list', error);
231
- }
232
- }
233
-
234
- function addDebugMessage(message: string) {
235
- const debugMessage = {
236
- role: 'assistant',
237
- parts: [{
238
- type: 'text',
239
- text: message,
240
- state: 'done',
241
- }]
242
- };
243
- currentChat.value?.messages.push(debugMessage);
244
- }
245
-
246
- async function addSystemMessage(message: string) {
247
- if (!currentSession.value || currentSession.value.sessionId === PRE_SESSION_ID) {
248
- await createNewSession('Audio chat');
249
- }
250
- const systemMessage = {
251
- role: 'system',
252
- parts: [{
253
- type: 'text',
254
- text: message,
255
- state: 'done',
256
- }]
257
- };
258
- currentChat.value?.messages.push(systemMessage);
259
- try {
260
- const res = await callAdminForthApi({
261
- method: 'POST',
262
- path: '/agent/add-system-message-to-turns',
263
- body: {
264
- sessionId: activeSessionId.value,
265
- systemMessage: message,
266
- },
267
- });
268
- } catch (error) {
269
- console.error('Error adding system message', error);
270
- }
271
- }
272
-
273
- function addAgentMessage(message: string) {
274
- const agentMessage = {
275
- role: 'assistant',
276
- parts: [{
277
- type: 'text',
278
- text: message,
279
- state: 'done',
280
- }]
281
- };
282
- currentChat.value?.messages.push(agentMessage);
283
- }
284
-
285
- function updateLastAgentMessage(message: string) {
286
- const lastMsg = currentChat.value?.lastMessage;
287
- if (lastMsg && lastMsg.role === 'assistant') {
288
- lastMsg.parts = [{
289
- type: 'text',
290
- text: message,
291
- state: 'done',
292
- }];
293
- currentChat.value?.messages.splice(currentChat.value.messages.length - 1, 1, lastMsg);
294
- } else {
295
- addAgentMessage(message);
296
- }
297
- }
298
-
299
- function addUserMessage(message: string) {
300
- const userMessage = {
301
- role: 'user',
302
- parts: [{
303
- type: 'text',
304
- text: message,
305
- state: 'done',
306
- }]
307
- };
308
- currentChat.value?.messages.push(userMessage);
309
- }
310
-
311
-
312
- function addDataToolCallMessage(data: any) {
313
- const lastMessage = currentChat.value?.lastMessage;
314
- if (lastMessage.role === 'assistant') {
315
- lastMessage.parts.push({
316
- type: 'data-tool-call',
317
- data,
318
- });
319
- currentChat.value?.messages.splice(currentChat.value.messages.length - 1, 1, lastMessage);
320
- } else {
321
- const toolCallMessage = {
322
- role: 'assistant',
323
- parts: [{
324
- type: 'data-tool-call',
325
- data,
326
- }]
327
- };
328
- currentChat.value?.messages.push(toolCallMessage);
329
- }
330
- }
331
-
332
- function setCurrentChatStatus(status: any) { // ChatStatus type
333
- (currentChat.value as any)?.setStatus({status});
334
- }
335
-
336
- return {
337
- sendMessage,
338
- createPreSession,
339
- setActiveSession,
340
- fetchSessionsList,
341
- deleteSession,
342
- addDebugMessage,
343
- addSystemMessage,
344
- addAgentMessage,
345
- addUserMessage,
346
- addDataToolCallMessage,
347
- setCurrentChatStatus,
348
- updateLastAgentMessage
349
- };
350
- }
@@ -1,272 +0,0 @@
1
- import adminforth from "@/adminforth";
2
- import { useAgentStore } from "./useAgentStore";
3
- import { defineStore } from 'pinia';
4
- import type { SpeechStreamEvent } from '../types';
5
- import { ref } from 'vue';
6
- import { getCurrentPageContext } from './agentStore/pageContext';
7
- import {
8
- createChatResponseAudioPlayback,
9
- endStandByAudio,
10
- finishChatResponseAudio,
11
- playChatResponseCurrentChunks,
12
- startStandByAudio,
13
- stopChatResponseAudio,
14
- unlockAudio,
15
- } from './agentAudio/utils';
16
- import type { ChatResponseAudioPlayback } from './agentAudio/utils';
17
-
18
- let isStandByAudioPlaying = false;
19
- async function playStandByAudio() {
20
- isStandByAudioPlaying = true;
21
- await startStandByAudio();
22
- }
23
-
24
- function stopStandByAudio() {
25
- endStandByAudio();
26
- isStandByAudioPlaying = false;
27
- }
28
-
29
- export const useAgentAudio = defineStore('agentAudio', () => {
30
- const agentStore = useAgentStore();
31
- const agentAudioMode = ref<'transcribing' | 'streaming' | 'fetchingAudio' | 'playingAgentResponse' | 'readyToRespond' >('readyToRespond');
32
- const isStreamingResponse = ref(false);
33
-
34
- let currentAbortController: AbortController | null = null;
35
- let currentStreamingAudio: ChatResponseAudioPlayback | null = null;
36
- let wasAudioResponseReceived = false;
37
-
38
- function stopGenerationAndAudio() {
39
- setAudioModeReadyToRespond();
40
- stopCurrentAudioPlayback();
41
- currentAbortController?.abort();
42
- }
43
-
44
- function setAudioModeReadyToRespond() {
45
- agentAudioMode.value = 'readyToRespond';
46
- }
47
-
48
- async function sendAudioToServerAndHandleResponse(blob: Blob) {
49
- currentAbortController = new AbortController();
50
- wasAudioResponseReceived = false;
51
- const formData = new FormData();
52
- formData.append('file', blob, 'user_prompt.wav');
53
- formData.append('sessionId', agentStore.activeSessionId);
54
- formData.append('mode', agentStore.activeModeName ?? '');
55
- formData.append('timeZone', Intl.DateTimeFormat().resolvedOptions().timeZone);
56
- formData.append('currentPage', JSON.stringify(getCurrentPageContext()));
57
- const fullPath = `${import.meta.env.VITE_ADMINFORTH_PUBLIC_PATH || ''}/adminapi/v1/agent/speech-response`;
58
- try {
59
- agentAudioMode.value = 'transcribing';
60
- console.log('Sending audio to server for transcription and response generation');
61
- const res = await fetch(fullPath, {
62
- method: 'POST',
63
- body: formData,
64
- headers: {
65
- Accept: 'text/event-stream',
66
- },
67
- signal: currentAbortController!.signal,
68
- });
69
- isStreamingResponse.value = true;
70
- if (res.ok) {
71
- agentAudioMode.value = 'streaming';
72
- await readSpeechResponseStream(res);
73
- } else {
74
- console.error('Failed to transcribe audio:', res.statusText);
75
- adminforth.alert({message: 'Failed to transcribe audio', variant: 'danger'});
76
- }
77
- } catch (error) {
78
- if (error instanceof DOMException && error.name === 'AbortError') {
79
- //
80
- } else {
81
- console.error('Error sending audio to server:', error);
82
- }
83
- } finally {
84
- isStreamingResponse.value = false;
85
- if (!wasAudioResponseReceived) {
86
- setAudioModeReadyToRespond();
87
- }
88
- }
89
- }
90
-
91
- async function readSpeechResponseStream(res: Response) {
92
- const reader = res.body?.getReader();
93
- if (!reader) {
94
- adminforth.alert({message: 'Speech response stream is not available', variant: 'danger'});
95
- return;
96
- }
97
-
98
- const decoder = new TextDecoder();
99
- let buffer = '';
100
-
101
- agentStore.setCurrentChatStatus('streaming');
102
- try {
103
- while (true) {
104
- const { value, done } = await reader.read();
105
-
106
- if (done) {
107
- break;
108
- }
109
-
110
- buffer += decoder.decode(value, { stream: true });
111
- const eventBlocks = buffer.split('\n\n');
112
- buffer = eventBlocks.pop() ?? '';
113
-
114
- for (const eventBlock of eventBlocks) {
115
- await handleSpeechStreamEvent(eventBlock);
116
- }
117
- }
118
-
119
- buffer += decoder.decode();
120
-
121
- if (buffer.trim()) {
122
- await handleSpeechStreamEvent(buffer);
123
- }
124
-
125
- finishAudioStream();
126
- } finally {
127
- reader.releaseLock();
128
- agentStore.setCurrentChatStatus('ready');
129
- }
130
- }
131
-
132
- async function handleSpeechStreamEvent(eventBlock: string) {
133
- if (currentAbortController?.signal.aborted) {
134
- return;
135
- }
136
- const data = eventBlock
137
- .split('\n')
138
- .filter((line) => line.startsWith('data:'))
139
- .map((line) => line.slice(5).trimStart())
140
- .join('\n');
141
- if (!data || data === '[DONE]') {
142
- return;
143
- }
144
-
145
- const event = JSON.parse(data) as SpeechStreamEvent;
146
- console.log('Received speech stream event type:', event.type);
147
-
148
- if (event.type === 'error') {
149
-
150
- return;
151
- }
152
-
153
- if (event.type === 'transcript') {
154
- agentStore.addUserMessage(event.data.text);
155
- agentStore.updateLastAgentMessage('');
156
- return;
157
- }
158
-
159
- if (event.type === 'speech-response') {
160
- stopStandByAudio();
161
- agentStore.setCurrentChatStatus('ready');
162
- agentStore.addAgentMessage(event.data.response.text);
163
- return;
164
- }
165
-
166
- if (event.type === 'audio-start') {
167
- wasAudioResponseReceived = true;
168
- isStreamingResponse.value = false;
169
- agentAudioMode.value = 'fetchingAudio';
170
- initializeAudioStream(event.data);
171
- agentAudioMode.value = 'playingAgentResponse';
172
- return;
173
- }
174
-
175
- if (event.type === 'audio-delta') {
176
- appendAudioChunk(event.data.base64);
177
- return;
178
- }
179
-
180
- if (event.type === 'audio-done') {
181
- finishAudioStream();
182
- return;
183
- }
184
-
185
- if (event.type === 'data-tool-call') {
186
- if (!isStandByAudioPlaying) {
187
- playStandByAudio();
188
- }
189
- agentStore.addDataToolCallMessage(event.data);
190
- return;
191
- }
192
-
193
- if (event.type === 'open-page') {
194
- agentStore.openAgentPage(event.data.targetPath);
195
- }
196
- }
197
-
198
- function initializeAudioStream(audioData: Extract<SpeechStreamEvent, { type: 'audio-start' }>['data']) {
199
- stopCurrentAudioPlayback();
200
- currentStreamingAudio = createChatResponseAudioPlayback({
201
- sampleRate: audioData.sampleRate,
202
- channelCount: audioData.channelCount,
203
- bitsPerSample: audioData.bitsPerSample,
204
- onEnded: handleAudioEnded,
205
- });
206
- }
207
-
208
- function appendAudioChunk(base64: string) {
209
- playChatResponseCurrentChunks({
210
- playback: currentStreamingAudio!,
211
- chunks: [base64ToArrayBuffer(base64)],
212
- });
213
- }
214
-
215
- function finishAudioStream() {
216
- finishChatResponseAudio(currentStreamingAudio);
217
- }
218
-
219
- function stopCurrentAudioPlayback(dontResetMode = false) {
220
- stopStandByAudio();
221
- stopChatResponseAudio(currentStreamingAudio);
222
- currentStreamingAudio = null;
223
- if (!dontResetMode) {
224
- setAudioModeReadyToRespond();
225
- }
226
- }
227
-
228
- function handleAudioEnded() {
229
- currentStreamingAudio = null;
230
- setAudioModeReadyToRespond();
231
- }
232
-
233
- function base64ToArrayBuffer(base64: string) {
234
- const binary = atob(base64);
235
- const bytes = new Uint8Array(binary.length);
236
-
237
- for (let i = 0; i < binary.length; i += 1) {
238
- bytes[i] = binary.charCodeAt(i);
239
- }
240
-
241
- return bytes.buffer;
242
- }
243
-
244
- function playBeep(freq = 800, duration = 0.05) {
245
- const ctx = new AudioContext();
246
- const osc = ctx.createOscillator();
247
- const gain = ctx.createGain();
248
-
249
- osc.frequency.value = freq;
250
- osc.type = 'sine';
251
-
252
- osc.connect(gain);
253
- gain.connect(ctx.destination);
254
-
255
- osc.start();
256
-
257
- gain.gain.setValueAtTime(1, ctx.currentTime);
258
- gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + duration);
259
-
260
- osc.stop(ctx.currentTime + duration);
261
- }
262
-
263
- return {
264
- sendAudioToServerAndHandleResponse,
265
- stopGenerationAndAudio,
266
- stopCurrentAudioPlayback,
267
- playBeep,
268
- agentAudioMode,
269
- unlockAudio,
270
- };
271
-
272
- });