@adminforth/agent 2.0.10 → 2.2.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 (201) hide show
  1. package/README.md +333 -10
  2. package/dist/application/ports.d.ts +66 -0
  3. package/dist/application/runTurnUseCase.d.ts +71 -0
  4. package/dist/application/runTurnUseCase.js +364 -0
  5. package/dist/custom/ChatFooter.vue +58 -30
  6. package/dist/custom/SteerDebugPanel.vue +45 -0
  7. package/dist/custom/SteerQueue.vue +54 -0
  8. package/dist/custom/composables/agentStore/constants.ts +1 -0
  9. package/dist/custom/composables/agentStore/useAgentSessions.ts +35 -16
  10. package/dist/custom/composables/agentStore/useAgentSteerQueue.ts +114 -0
  11. package/dist/custom/composables/useAgentStore.ts +46 -1
  12. package/dist/custom/conversation_area/MessageRenderer.vue +7 -1
  13. package/dist/custom/speech_recognition_frontend/AudioLines.vue +1 -1
  14. package/dist/custom/speech_recognition_frontend/MicrophoneButon.vue +3 -3
  15. package/dist/{agentEvents.d.ts → domain/agentEvents.d.ts} +5 -1
  16. package/dist/domain/steerBuffer.d.ts +33 -0
  17. package/dist/domain/steerBuffer.js +51 -0
  18. package/dist/{agent → domain}/systemPrompt.js +1 -1
  19. package/dist/{agent/turn → domain}/turnTypes.d.ts +41 -37
  20. package/dist/{agent/turn/VegaLiteStreamBuffer.d.ts → domain/vegaLiteStreamBuffer.d.ts} +1 -1
  21. package/dist/index.d.ts +4 -2
  22. package/dist/index.js +49 -35
  23. package/dist/{agent/runtime/AgentContext.d.ts → llm/agentContext.d.ts} +3 -3
  24. package/dist/{agent/simpleAgent.d.ts → llm/agentModels.d.ts} +18 -16
  25. package/dist/llm/agentModels.js +65 -0
  26. package/dist/{agent/runtime/AgentRuntime.d.ts → llm/agentRuntime.d.ts} +14 -2
  27. package/dist/{agent/runtime/AgentRuntime.js → llm/agentRuntime.js} +41 -6
  28. package/dist/llm/langGraphLlm.d.ts +25 -0
  29. package/dist/llm/langGraphLlm.js +54 -0
  30. package/dist/{agent/middleware/apiBasedTools.d.ts → llm/middleware/apiToolsMiddleware.d.ts} +1 -1
  31. package/dist/{agent/middleware/apiBasedTools.js → llm/middleware/apiToolsMiddleware.js} +8 -14
  32. package/dist/{agent → llm}/middleware/sequenceDebug.d.ts +1 -1
  33. package/dist/llm/middleware/steerMiddleware.d.ts +21 -0
  34. package/dist/llm/middleware/steerMiddleware.js +50 -0
  35. package/dist/{agent/models/AgentModelFactory.d.ts → llm/modelFactory.d.ts} +1 -1
  36. package/dist/{agent/models/AgentModelFactory.js → llm/modelFactory.js} +1 -1
  37. package/dist/llm/streamAdapter.d.ts +18 -0
  38. package/dist/llm/streamAdapter.js +117 -0
  39. package/dist/{sessionStore.d.ts → persistence/sessionStore.d.ts} +19 -2
  40. package/dist/{sessionStore.js → persistence/sessionStore.js} +53 -0
  41. package/dist/{agent/tools/AgentToolProvider.d.ts → tools/agentToolProvider.d.ts} +1 -1
  42. package/dist/{agent/tools/AgentToolProvider.js → tools/agentToolProvider.js} +1 -1
  43. package/dist/{apiBasedTools.js → tools/apiBasedTools.js} +0 -3
  44. package/dist/{agent/tools → tools}/apiTool.d.ts +1 -1
  45. package/dist/{agent/tools → tools}/fetchSkill.js +1 -1
  46. package/dist/{agent/tools → tools}/fetchToolSchema.d.ts +1 -1
  47. package/dist/{agent/tools → tools}/index.d.ts +1 -1
  48. package/dist/{agent/tools → tools}/navigateUser.d.ts +3 -3
  49. package/dist/{endpoints → transport/http}/context.d.ts +12 -4
  50. package/dist/transport/http/context.js +1 -0
  51. package/dist/{endpoints/core.js → transport/http/coreEndpoints.js} +23 -3
  52. package/dist/{endpoints/sessions.js → transport/http/sessionEndpoints.js} +36 -1
  53. package/dist/transport/sse/sseWriter.d.ts +29 -0
  54. package/dist/{surfaces/web-sse/createSseEventEmitter.js → transport/sse/sseWriter.js} +27 -0
  55. package/dist/{chatSurfaceService.d.ts → transport/surfaces/chatSurfaceService.d.ts} +3 -3
  56. package/dist/{chatSurfaceService.js → transport/surfaces/chatSurfaceService.js} +7 -5
  57. package/dist/{agent/speech/SpeechTurnService.d.ts → transport/surfaces/speechTurnService.d.ts} +1 -1
  58. package/dist/{agent/speech/SpeechTurnService.js → transport/surfaces/speechTurnService.js} +2 -2
  59. package/dist/types.d.ts +10 -4
  60. package/package.json +11 -2
  61. package/.woodpecker/buildRelease.sh +0 -13
  62. package/.woodpecker/buildSlackNotify.sh +0 -46
  63. package/.woodpecker/release.yml +0 -57
  64. package/agent/checkpointer.ts +0 -329
  65. package/agent/languageDetect.ts +0 -92
  66. package/agent/middleware/apiBasedTools.ts +0 -174
  67. package/agent/middleware/openAiResponsesContinuation.ts +0 -92
  68. package/agent/middleware/sequenceDebug.ts +0 -429
  69. package/agent/models/AgentModeResolver.ts +0 -9
  70. package/agent/models/AgentModelFactory.ts +0 -28
  71. package/agent/runtime/AgentContext.ts +0 -30
  72. package/agent/runtime/AgentRuntime.ts +0 -89
  73. package/agent/simpleAgent.ts +0 -199
  74. package/agent/skills/registry.ts +0 -162
  75. package/agent/speech/SpeechTurnService.ts +0 -179
  76. package/agent/systemPrompt.ts +0 -133
  77. package/agent/toolCallEvents.ts +0 -135
  78. package/agent/tools/AgentToolProvider.ts +0 -28
  79. package/agent/tools/apiTool.ts +0 -66
  80. package/agent/tools/fetchSkill.ts +0 -68
  81. package/agent/tools/fetchToolSchema.ts +0 -47
  82. package/agent/tools/getUserLocation.ts +0 -45
  83. package/agent/tools/index.ts +0 -31
  84. package/agent/tools/navigateUser.ts +0 -210
  85. package/agent/turn/TurnContextBuilder.ts +0 -36
  86. package/agent/turn/TurnLifecycleService.ts +0 -47
  87. package/agent/turn/TurnPersistenceService.ts +0 -33
  88. package/agent/turn/TurnPromptBuilder.ts +0 -51
  89. package/agent/turn/TurnStreamConsumer.ts +0 -69
  90. package/agent/turn/VegaLiteStreamBuffer.ts +0 -90
  91. package/agent/turn/turnTypes.ts +0 -100
  92. package/agentEvents.ts +0 -75
  93. package/agentTurnService.ts +0 -314
  94. package/apiBasedTools.ts +0 -712
  95. package/build.log +0 -67
  96. package/chatSurfaceService.ts +0 -319
  97. package/custom/ChatFooter.vue +0 -173
  98. package/custom/ChatHeader.vue +0 -78
  99. package/custom/ChatSurface.vue +0 -160
  100. package/custom/CustomAutoScrollContainer.vue +0 -164
  101. package/custom/SessionsHistory.vue +0 -88
  102. package/custom/chat.ts +0 -82
  103. package/custom/composables/agentAudio/utils.ts +0 -220
  104. package/custom/composables/agentStore/constants.ts +0 -19
  105. package/custom/composables/agentStore/pageContext.ts +0 -8
  106. package/custom/composables/agentStore/useAgentChat.ts +0 -241
  107. package/custom/composables/agentStore/useAgentPlaceholder.ts +0 -142
  108. package/custom/composables/agentStore/useAgentSessions.ts +0 -350
  109. package/custom/composables/useAgentAudio.ts +0 -272
  110. package/custom/composables/useAgentStore.ts +0 -510
  111. package/custom/composables/useAgentTransitions.ts +0 -58
  112. package/custom/conversation_area/ConversationArea.vue +0 -301
  113. package/custom/conversation_area/MessageRenderer.vue +0 -49
  114. package/custom/conversation_area/ProcessingTimeline.vue +0 -286
  115. package/custom/conversation_area/ReasoningRenderer.vue +0 -79
  116. package/custom/conversation_area/SystemMessageRenderer.vue +0 -28
  117. package/custom/conversation_area/TextRenderer.vue +0 -182
  118. package/custom/conversation_area/ThreeDotsAnimation.vue +0 -35
  119. package/custom/conversation_area/ToolApprovalRenderer.vue +0 -98
  120. package/custom/conversation_area/ToolRenderer.vue +0 -178
  121. package/custom/conversation_area/ToolsGroup.vue +0 -59
  122. package/custom/env.d.ts +0 -7
  123. package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +0 -393
  124. package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +0 -285
  125. package/custom/incremark_code_renderers/incremarkRenderer.ts +0 -653
  126. package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +0 -118
  127. package/custom/package.json +0 -30
  128. package/custom/pnpm-lock.yaml +0 -2394
  129. package/custom/public/agentAudio/agent-processing.mp3 +0 -0
  130. package/custom/skills/analyze_data/SKILL.md +0 -25
  131. package/custom/skills/charts/SKILL.md +0 -193
  132. package/custom/skills/fetch_data/SKILL.md +0 -31
  133. package/custom/skills/mutate_data/SKILL.md +0 -121
  134. package/custom/speech_recognition_frontend/AudioLines.vue +0 -43
  135. package/custom/speech_recognition_frontend/MicrophoneButon.vue +0 -185
  136. package/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +0 -22
  137. package/custom/speech_recognition_frontend/voiceActivityDetection.ts +0 -62
  138. package/custom/tsconfig.json +0 -15
  139. package/custom/types.ts +0 -108
  140. package/custom/utils.ts +0 -38
  141. package/dist/agent/middleware/openAiResponsesContinuation.d.ts +0 -1
  142. package/dist/agent/middleware/openAiResponsesContinuation.js +0 -66
  143. package/dist/agent/models/AgentModeResolver.d.ts +0 -9
  144. package/dist/agent/models/AgentModeResolver.js +0 -9
  145. package/dist/agent/simpleAgent.js +0 -118
  146. package/dist/agent/turn/TurnContextBuilder.d.ts +0 -14
  147. package/dist/agent/turn/TurnContextBuilder.js +0 -31
  148. package/dist/agent/turn/TurnLifecycleService.d.ts +0 -24
  149. package/dist/agent/turn/TurnLifecycleService.js +0 -47
  150. package/dist/agent/turn/TurnPersistenceService.d.ts +0 -13
  151. package/dist/agent/turn/TurnPersistenceService.js +0 -35
  152. package/dist/agent/turn/TurnPromptBuilder.d.ts +0 -19
  153. package/dist/agent/turn/TurnPromptBuilder.js +0 -43
  154. package/dist/agent/turn/TurnStreamConsumer.d.ts +0 -11
  155. package/dist/agent/turn/TurnStreamConsumer.js +0 -84
  156. package/dist/agentTurnService.d.ts +0 -24
  157. package/dist/agentTurnService.js +0 -269
  158. package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +0 -14
  159. package/endpoints/chatSurfaces.ts +0 -66
  160. package/endpoints/context.ts +0 -52
  161. package/endpoints/core.ts +0 -181
  162. package/endpoints/sessions.ts +0 -183
  163. package/errors.ts +0 -10
  164. package/index.ts +0 -192
  165. package/pnpm-workspace.yaml +0 -4
  166. package/sanitizeSpeechText.ts +0 -32
  167. package/sessionStore.ts +0 -105
  168. package/surfaces/web-sse/createSseEventEmitter.ts +0 -311
  169. package/tsconfig.json +0 -14
  170. package/types.ts +0 -127
  171. /package/dist/{agent/turn/turnTypes.js → application/ports.js} +0 -0
  172. /package/dist/{agentEvents.js → domain/agentEvents.js} +0 -0
  173. /package/dist/{agent → domain}/languageDetect.d.ts +0 -0
  174. /package/dist/{agent → domain}/languageDetect.js +0 -0
  175. /package/dist/{agent → domain}/systemPrompt.d.ts +0 -0
  176. /package/dist/{agent → domain}/toolCallEvents.d.ts +0 -0
  177. /package/dist/{agent → domain}/toolCallEvents.js +0 -0
  178. /package/dist/{endpoints/context.js → domain/turnTypes.js} +0 -0
  179. /package/dist/{agent/turn/VegaLiteStreamBuffer.js → domain/vegaLiteStreamBuffer.js} +0 -0
  180. /package/dist/{agent/runtime/AgentContext.js → llm/agentContext.js} +0 -0
  181. /package/dist/{agent → llm}/middleware/sequenceDebug.js +0 -0
  182. /package/dist/{agent/checkpointer.d.ts → persistence/checkpointStore.d.ts} +0 -0
  183. /package/dist/{agent/checkpointer.js → persistence/checkpointStore.js} +0 -0
  184. /package/dist/{errors.d.ts → shared/errors.d.ts} +0 -0
  185. /package/dist/{errors.js → shared/errors.js} +0 -0
  186. /package/dist/{sanitizeSpeechText.d.ts → shared/sanitizeSpeechText.d.ts} +0 -0
  187. /package/dist/{sanitizeSpeechText.js → shared/sanitizeSpeechText.js} +0 -0
  188. /package/dist/{apiBasedTools.d.ts → tools/apiBasedTools.d.ts} +0 -0
  189. /package/dist/{agent/tools → tools}/apiTool.js +0 -0
  190. /package/dist/{agent/tools → tools}/fetchSkill.d.ts +0 -0
  191. /package/dist/{agent/tools → tools}/fetchToolSchema.js +0 -0
  192. /package/dist/{agent/tools → tools}/getUserLocation.d.ts +0 -0
  193. /package/dist/{agent/tools → tools}/getUserLocation.js +0 -0
  194. /package/dist/{agent/tools → tools}/index.js +0 -0
  195. /package/dist/{agent/tools → tools}/navigateUser.js +0 -0
  196. /package/dist/{agent → tools}/skills/registry.d.ts +0 -0
  197. /package/dist/{agent → tools}/skills/registry.js +0 -0
  198. /package/dist/{endpoints/chatSurfaces.d.ts → transport/http/chatSurfaceEndpoints.d.ts} +0 -0
  199. /package/dist/{endpoints/chatSurfaces.js → transport/http/chatSurfaceEndpoints.js} +0 -0
  200. /package/dist/{endpoints/core.d.ts → transport/http/coreEndpoints.d.ts} +0 -0
  201. /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
- });