@adminforth/agent 2.0.10 → 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} +0 -3
  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 -712
  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
package/build.log DELETED
@@ -1,67 +0,0 @@
1
-
2
- > @adminforth/agent@1.0.1 build
3
- > tsc && rsync -av --exclude 'node_modules' custom dist/
4
-
5
- sending incremental file list
6
- custom/
7
- custom/ChatFooter.vue
8
- custom/ChatHeader.vue
9
- custom/ChatSurface.vue
10
- custom/CustomAutoScrollContainer.vue
11
- custom/SessionsHistory.vue
12
- custom/chat.ts
13
- custom/env.d.ts
14
- custom/package.json
15
- custom/pnpm-lock.yaml
16
- custom/tsconfig.json
17
- custom/types.ts
18
- custom/utils.ts
19
- custom/composables/
20
- custom/composables/useAgentAudio.ts
21
- custom/composables/useAgentStore.ts
22
- custom/composables/useAgentTransitions.ts
23
- custom/composables/agentAudio/
24
- custom/composables/agentAudio/utils.ts
25
- custom/composables/agentStore/
26
- custom/composables/agentStore/constants.ts
27
- custom/composables/agentStore/pageContext.ts
28
- custom/composables/agentStore/useAgentChat.ts
29
- custom/composables/agentStore/useAgentPlaceholder.ts
30
- custom/composables/agentStore/useAgentSessions.ts
31
- custom/conversation_area/
32
- custom/conversation_area/ConversationArea.vue
33
- custom/conversation_area/MessageRenderer.vue
34
- custom/conversation_area/ProcessingTimeline.vue
35
- custom/conversation_area/ReasoningRenderer.vue
36
- custom/conversation_area/SystemMessageRenderer.vue
37
- custom/conversation_area/TextRenderer.vue
38
- custom/conversation_area/ThreeDotsAnimation.vue
39
- custom/conversation_area/ToolApprovalRenderer.vue
40
- custom/conversation_area/ToolRenderer.vue
41
- custom/conversation_area/ToolsGroup.vue
42
- custom/incremark_code_renderers/
43
- custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue
44
- custom/incremark_code_renderers/incremarkCodeHighlight.ts
45
- custom/incremark_code_renderers/incremarkRenderer.ts
46
- custom/incremark_code_renderers/renderIncremarkMarkdown.ts
47
- custom/public/
48
- custom/public/agentAudio/
49
- custom/public/agentAudio/agent-processing.mp3
50
- custom/skills/
51
- custom/skills/analyze_data/
52
- custom/skills/analyze_data/SKILL.md
53
- custom/skills/charts/
54
- custom/skills/charts/SKILL.md
55
- custom/skills/fetch_data/
56
- custom/skills/fetch_data/SKILL.md
57
- custom/skills/mutate_data/
58
- custom/skills/mutate_data/SKILL.md
59
- custom/speech_recognition_frontend/
60
- custom/speech_recognition_frontend/AudioLines.vue
61
- custom/speech_recognition_frontend/MicrophoneButon.vue
62
- custom/speech_recognition_frontend/voiceActivityDetection.ts
63
- custom/speech_recognition_frontend/types/
64
- custom/speech_recognition_frontend/types/voice-activity-detection.d.ts
65
-
66
- sent 1,682,452 bytes received 940 bytes 3,366,784.00 bytes/sec
67
- total size is 1,678,191 speedup is 1.00
@@ -1,319 +0,0 @@
1
- import type {
2
- AdminUser,
3
- ChatSurfaceAdapter,
4
- ChatSurfaceEventSink,
5
- ChatSurfaceIncomingMessage,
6
- IAdminForth,
7
- } from "adminforth";
8
- import { Filters, logger } from "adminforth";
9
- import type { AgentEventEmitter } from "./agentEvents.js";
10
- import type {
11
- HandleTurnInput,
12
- RunAndPersistAgentResponseInput,
13
- RunAndPersistAgentResponseResult,
14
- } from "./agentTurnService.js";
15
- import { getErrorMessage, isAbortError } from "./errors.js";
16
- import type { AgentSessionStore } from "./sessionStore.js";
17
- import { sanitizeSpeechText } from "./sanitizeSpeechText.js";
18
- import type { PluginOptions } from "./types.js";
19
-
20
- type ChatSurfaceIncomingMessageWithAudio = ChatSurfaceIncomingMessage & {
21
- audio?: {
22
- buffer: Buffer;
23
- filename: string;
24
- mimeType: string;
25
- };
26
- };
27
-
28
- type ChatSurfaceEventSinkWithAudio = ChatSurfaceEventSink & {
29
- emit(event: Parameters<ChatSurfaceEventSink["emit"]>[0] | {
30
- type: "audio";
31
- audio: Buffer;
32
- filename: string;
33
- mimeType: string;
34
- }): void | Promise<void>;
35
- };
36
-
37
- export class ChatSurfaceService {
38
- constructor(
39
- private getAdminforth: () => IAdminForth,
40
- private options: PluginOptions,
41
- private sessionStore: AgentSessionStore,
42
- private handleTurn: (input: HandleTurnInput) => Promise<unknown>,
43
- private runAndPersistAgentResponse: (
44
- input: RunAndPersistAgentResponseInput,
45
- ) => Promise<RunAndPersistAgentResponseResult>,
46
- ) {}
47
-
48
- private createEventEmitter(sink: ChatSurfaceEventSink): AgentEventEmitter {
49
- return async (event) => {
50
- if (event.type === "text-delta") {
51
- await sink.emit({
52
- type: "text_delta",
53
- delta: event.delta,
54
- });
55
- return;
56
- }
57
-
58
- if (event.type === "response") {
59
- await sink.emit({
60
- type: "done",
61
- text: event.text,
62
- });
63
- return;
64
- }
65
-
66
- if (event.type === "error") {
67
- await sink.emit({
68
- type: "error",
69
- message: event.error,
70
- });
71
- }
72
- };
73
- }
74
-
75
- private async handleLink(
76
- incoming: ChatSurfaceIncomingMessage,
77
- sink: ChatSurfaceEventSink,
78
- ) {
79
- if (incoming.metadata?.isStartCommand !== true) {
80
- return false;
81
- }
82
-
83
- await sink.emit({
84
- type: "done",
85
- text: `Open AdminForth and connect your ${incoming.surface} account from Connected Accounts settings.`,
86
- });
87
- return true;
88
- }
89
-
90
- private async handleAudioMessage(
91
- incoming: ChatSurfaceIncomingMessageWithAudio,
92
- sink: ChatSurfaceEventSinkWithAudio,
93
- adminUser: AdminUser,
94
- ) {
95
- const audioAdapter = this.options.audioAdapter;
96
- if (!audioAdapter) {
97
- await sink.emit({
98
- type: "error",
99
- message: "Audio adapter is not configured for AdminForth Agent.",
100
- });
101
- return;
102
- }
103
-
104
- let transcription;
105
-
106
- try {
107
- transcription = await audioAdapter.transcribe({
108
- buffer: incoming.audio!.buffer,
109
- filename: incoming.audio!.filename,
110
- mimeType: incoming.audio!.mimeType,
111
- language: "auto",
112
- });
113
- } catch (error) {
114
- if (isAbortError(error)) {
115
- logger.info(`Agent ${incoming.surface} surface speech transcription aborted`);
116
- return;
117
- }
118
-
119
- logger.error(`Agent ${incoming.surface} surface speech transcription failed:\n${getErrorMessage(error)}`);
120
- await sink.emit({
121
- type: "error",
122
- message: "Speech transcription failed. Check server logs for details.",
123
- });
124
- return;
125
- }
126
-
127
- if (!transcription.text) {
128
- await sink.emit({
129
- type: "error",
130
- message: "Speech transcription is empty",
131
- });
132
- return;
133
- }
134
-
135
- const agentResponse = await this.handleAgentSurfaceResponse(
136
- incoming,
137
- sink,
138
- adminUser,
139
- transcription.text,
140
- { emitDone: false },
141
- );
142
-
143
- if (!agentResponse || agentResponse.aborted || agentResponse.failed) {
144
- return;
145
- }
146
-
147
- await sink.emit({
148
- type: "done",
149
- text: agentResponse.text,
150
- });
151
-
152
- try {
153
- const speech = await audioAdapter.synthesize({
154
- text: sanitizeSpeechText(agentResponse.text),
155
- stream: false,
156
- format: "opus",
157
- });
158
-
159
- await sink.emit({
160
- type: "audio",
161
- audio: speech.audio,
162
- filename: "agent-response.ogg",
163
- mimeType: speech.mimeType,
164
- });
165
- } catch (error) {
166
- if (isAbortError(error)) {
167
- logger.info(`Agent ${incoming.surface} surface speech synthesis aborted`);
168
- return;
169
- }
170
-
171
- logger.error(`Agent ${incoming.surface} surface speech synthesis failed:\n${getErrorMessage(error)}`);
172
- await sink.emit({
173
- type: "error",
174
- message: getErrorMessage(error),
175
- });
176
- }
177
- }
178
-
179
- private async handleAgentSurfaceResponse(
180
- incoming: ChatSurfaceIncomingMessage,
181
- sink: ChatSurfaceEventSink,
182
- adminUser: AdminUser,
183
- prompt: string,
184
- options?: { emitDone?: boolean },
185
- ) {
186
- const emitDone = options?.emitDone ?? true;
187
- const adminPublicOrigin = typeof incoming.metadata?.adminPublicOrigin === "string"
188
- ? incoming.metadata.adminPublicOrigin
189
- : undefined;
190
- const sessionId = await this.sessionStore.getOrCreateChatSurfaceSession(
191
- { ...incoming, prompt },
192
- adminUser,
193
- );
194
-
195
- if (emitDone) {
196
- await this.handleTurn({
197
- prompt,
198
- sessionId,
199
- modeName: incoming.modeName,
200
- userTimeZone: incoming.userTimeZone ?? "UTC",
201
- chatSurface: incoming.surface,
202
- adminPublicOrigin,
203
- adminUser,
204
- emit: this.createEventEmitter(sink),
205
- failureLogMessage: `Agent ${incoming.surface} surface response failed`,
206
- abortLogMessage: `Agent ${incoming.surface} surface response aborted`,
207
- });
208
- return null;
209
- }
210
-
211
- const agentResponse = await this.runAndPersistAgentResponse({
212
- prompt,
213
- sessionId,
214
- modeName: incoming.modeName,
215
- userTimeZone: incoming.userTimeZone ?? "UTC",
216
- chatSurface: incoming.surface,
217
- adminPublicOrigin,
218
- adminUser,
219
- emit: this.createEventEmitter(sink),
220
- failureLogMessage: `Agent ${incoming.surface} surface response failed`,
221
- abortLogMessage: `Agent ${incoming.surface} surface response aborted`,
222
- });
223
-
224
- if (agentResponse.failed) {
225
- await sink.emit({
226
- type: "error",
227
- message: agentResponse.text,
228
- });
229
- }
230
-
231
- return agentResponse;
232
- }
233
-
234
- private async getAdminUserRecordForChatSurface(
235
- adapter: ChatSurfaceAdapter,
236
- incoming: ChatSurfaceIncomingMessage,
237
- ) {
238
- const adminforth = this.getAdminforth();
239
- const authResourceId = adminforth.config.auth!.usersResourceId!;
240
- const externalIdentityResource = this.options.chatExternalIdentityResource;
241
- if (!externalIdentityResource) {
242
- return null;
243
- }
244
-
245
- const surfaceIdentityConfig = externalIdentityResource.surfaces[adapter.name];
246
- if (!surfaceIdentityConfig) {
247
- return null;
248
- }
249
-
250
- const providerField = externalIdentityResource.providerField ?? 'provider';
251
- const subjectField = externalIdentityResource.subjectField ?? 'subject';
252
- const adminUserIdField = externalIdentityResource.adminUserIdField ?? 'adminUserId';
253
- const externalUserIdField = externalIdentityResource.externalUserIdField ?? 'externalUserId';
254
- const identityFilters = [
255
- Filters.EQ(providerField, surfaceIdentityConfig.provider),
256
- Filters.EQ(externalUserIdField, incoming.externalUserId),
257
- ];
258
- const identities = await adminforth.resource(externalIdentityResource.resourceId).list(identityFilters);
259
- const identity = identities.find((identity) => {
260
- if (String(identity[externalUserIdField]) === incoming.externalUserId) {
261
- return true;
262
- }
263
-
264
- if (String(identity[subjectField]) === incoming.externalUserId) {
265
- return true;
266
- }
267
-
268
- return false;
269
- });
270
-
271
- if (!identity) {
272
- return null;
273
- }
274
-
275
- const authResource = adminforth.config.resources.find((resource) => resource.resourceId === authResourceId)!;
276
- const primaryKeyField = authResource.columns.find((column) => column.primaryKey)!.name!;
277
- return adminforth.resource(authResourceId).get([
278
- Filters.EQ(primaryKeyField, identity[adminUserIdField]),
279
- ]);
280
- }
281
-
282
- async handleMessage(
283
- adapter: ChatSurfaceAdapter,
284
- incoming: ChatSurfaceIncomingMessage,
285
- sink: ChatSurfaceEventSink,
286
- ) {
287
- if (await this.handleLink(incoming, sink)) {
288
- return;
289
- }
290
-
291
- const adminforth = this.getAdminforth();
292
- const authResourceId = adminforth.config.auth!.usersResourceId!;
293
- const authResource = adminforth.config.resources.find((resource) => resource.resourceId === authResourceId)!;
294
- const primaryKeyField = authResource.columns.find((column) => column.primaryKey)!.name!;
295
- const adminUserRecord = await this.getAdminUserRecordForChatSurface(adapter, incoming);
296
-
297
- if (!adminUserRecord) {
298
- await sink.emit({
299
- type: "error",
300
- message: "This chat account is not authorized to use AdminForth Agent.",
301
- });
302
- return;
303
- }
304
-
305
- const adminUser = {
306
- pk: adminUserRecord[primaryKeyField],
307
- username: adminUserRecord[adminforth.config.auth!.usernameField],
308
- dbUser: adminUserRecord,
309
- };
310
-
311
- const incomingWithAudio = incoming as ChatSurfaceIncomingMessageWithAudio;
312
- if (incomingWithAudio.audio) {
313
- await this.handleAudioMessage(incomingWithAudio, sink as ChatSurfaceEventSinkWithAudio, adminUser);
314
- return;
315
- }
316
-
317
- await this.handleAgentSurfaceResponse(incoming, sink, adminUser, incoming.prompt);
318
- }
319
- }
@@ -1,173 +0,0 @@
1
- <template>
2
- <div
3
- ref="promptInput"
4
- class="w-full mb-2 flex items-center justify-center px-2 bg-transparent relative translate-x-[-50%] left-1/2"
5
- :style="{
6
- maxWidth: agentStore.isFullScreen ? remToPx(agentStore.MAX_WIDTH)+'px' : '100%',
7
- transition: `transform ${agentTransitions.TRANSITION_DURATION}ms ease-in-out`
8
- }"
9
- >
10
- <div
11
- class="w-full border rounded-lg pb-8"
12
- :class="agentStore.isAudioChatMode ? 'border-none mt-8' : 'border dark:bg-gray-700'"
13
- >
14
- <textarea
15
- v-if="!agentStore.isAudioChatMode"
16
- v-model="agentStore.userMessageInput"
17
- ref="textInput"
18
- @input="autoResize"
19
- :class="[
20
- 'min-h-12 px-4 pt-4 rounded-xl w-full resize-none overflow-hidden text-lightInputText dark:text-darkInputText rounded-md bg-transparent text-sm bg-gray-50 dark:bg-gray-700 dark:border-gray-600 focus:outline-none',
21
- { '!text-base': coreStore.isIos }
22
- ]"
23
- :placeholder="agentStore.hasPendingToolApproval ? 'Approve or reject the pending action to continue' : agentStore.userMessagePlaceholder"
24
- :disabled="agentStore.isMessageInputBlocked"
25
- @keydown.enter.exact.prevent="sendMessage"
26
- />
27
- <div
28
- v-if="agentStore.availableModes.length > 1"
29
- ref="modeMenu"
30
- class="absolute bottom-2 left-4"
31
- >
32
- <button
33
- aria-label="Select mode"
34
- class="flex px-2 py-1 items-center text-sm justify-center
35
- rounded-md bg-white text-lightListTableHeadingText
36
- transition-colors duration-200 hover:bg-gray-100
37
- dark:text-darkListTableHeadingText dark:bg-gray-700 dark:hover:bg-gray-800"
38
- :class="isModeMenuOpen ? 'bg-gray-100 dark:bg-gray-700' : ''"
39
- title="Select mode"
40
- type="button"
41
- @click="toggleModeMenu"
42
- >
43
- {{ agentStore.activeModeName }}
44
- <IconAngleDownOutline
45
- class="w-4 h-4 ml-1 transition-transform duration-200"
46
- :class="isModeMenuOpen ? '!rotate-180' : '!rotate-0'"
47
- />
48
- </button>
49
-
50
- <div
51
- v-if="isModeMenuOpen"
52
- class="absolute bottom-full left-0 mb-2 min-w-40 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg dark:border-gray-600 dark:bg-gray-800"
53
- >
54
- <button
55
- v-for="mode in agentStore.availableModes"
56
- :key="mode.name"
57
- class="block w-full px-3 py-2 text-left text-sm text-lightInputText transition-colors duration-150 hover:bg-gray-100 dark:text-darkInputText dark:hover:bg-gray-700"
58
- :class="mode.name === agentStore.activeModeName ? 'bg-gray-100 dark:bg-gray-700' : ''"
59
- type="button"
60
- @click="selectMode(mode.name)"
61
- >
62
- {{ mode.name }}
63
- </button>
64
- </div>
65
- </div>
66
- <MicrophoneButton
67
- v-if="props.meta.hasAudioAdapter"
68
- />
69
- <template v-if="!agentStore.isAudioChatMode">
70
- <Button
71
- v-if="!agentStore.isResponseInProgress"
72
- class="absolute right-4 bottom-2 !p-0 h-9 w-9 transition-opacity duration-200"
73
- @click="sendMessage"
74
- :disabled="!agentStore.trimmedUserMessage || agentStore.isMessageInputBlocked"
75
- >
76
- <IconArrowUpOutline
77
- class="w-8 h-8 p-1
78
- text-white"
79
- />
80
- </Button>
81
- <Button
82
- v-else
83
- class="absolute right-4 bottom-2 !p-0 h-9 w-9"
84
- @click="stopCurrentRequest"
85
- >
86
- <div
87
- class="w-3 h-3 bg-white rounded-sm"
88
- />
89
- </Button>
90
- </template>
91
- </div>
92
- </div>
93
- </template>
94
-
95
- <script setup lang="ts">
96
- import { IconArrowUpOutline, IconAngleDownOutline } from '@iconify-prerendered/vue-flowbite';
97
- import { useTemplateRef, onMounted, ref, onUnmounted } from 'vue';
98
- import { onClickOutside } from '@vueuse/core'
99
- import { useAgentStore } from './composables/useAgentStore';
100
- import { useAgentTransitions } from './composables/useAgentTransitions';
101
- import { Button } from '@/afcl';
102
- import { useCoreStore } from '@/stores/core';
103
- import { remToPx } from './utils';
104
- import MicrophoneButton from './speech_recognition_frontend/MicrophoneButon.vue';
105
-
106
- const props = defineProps<{
107
- meta: {
108
- pluginInstanceId: string;
109
- modes: Array<{
110
- name: string;
111
- }>;
112
- defaultModeName: string | null;
113
- stickByDefault: boolean;
114
- hasAudioAdapter: boolean;
115
- }
116
- adminUser: any
117
- conversationAreaRef: any
118
- }>();
119
-
120
- const textInput = useTemplateRef('textInput');
121
- const modeMenu = useTemplateRef('modeMenu');
122
- const agentStore = useAgentStore();
123
- const agentTransitions = useAgentTransitions();
124
- const coreStore = useCoreStore();
125
- const isModeMenuOpen = ref(false);
126
-
127
- onClickOutside(modeMenu as any, () => { isModeMenuOpen.value = false; });
128
-
129
- onMounted(async () => {
130
- agentStore.setAvailableModes(props.meta.modes, props.meta.defaultModeName);
131
- agentStore.setCurrentGenerationModeFromLocalStorage();
132
- agentStore.regisrerTextInput(textInput.value);
133
- textInput.value?.focus();
134
- });
135
-
136
- function autoResize() {
137
- const el = textInput.value
138
- if (!el) return
139
-
140
- el.style.height = 'auto'
141
- //max-w-48
142
- const maxHeight = 192
143
- if (el.scrollHeight > maxHeight) {
144
- el.style.height = maxHeight + 'px'
145
- el.style.overflowY = 'auto'
146
- } else {
147
- el.style.height = el.scrollHeight + 'px'
148
- el.style.overflowY = 'hidden'
149
- }
150
- }
151
-
152
- function toggleModeMenu() {
153
- isModeMenuOpen.value = !isModeMenuOpen.value;
154
- }
155
-
156
- function selectMode(modeName: string) {
157
- agentStore.setActiveMode(modeName);
158
- isModeMenuOpen.value = false;
159
- }
160
-
161
- async function sendMessage() {
162
- if (agentStore.isAudioChatMode) return;
163
- isModeMenuOpen.value = false;
164
- await agentStore.sendMessage();
165
- autoResize();
166
- props.conversationAreaRef?.handleSendMessage();
167
- }
168
-
169
- function stopCurrentRequest() {
170
- agentStore.abortCurrentChatRequestAndAddSystemMessage();
171
- }
172
-
173
- </script>
@@ -1,78 +0,0 @@
1
- <template>
2
- <div
3
- ref="headerRef"
4
- class="flex items-center justify-between h-14 border-b border-gray-200 dark:border-gray-700"
5
- >
6
- <div
7
- class="flex items-center"
8
- >
9
- <IconBarsOutline
10
- class="m-2 w-8 h-8 p-1 cursor-pointer hover:scale-110 rounded transition-colors duration-200
11
- text-lightNavbarIcons hover:text-lightNavbarIcons/80 hover:bg-lightNavbarIcons/20
12
- dark:text-darkNavbarIcons hover:text-darkNavbarIcons/80 hover:bg-darkNavbarIcons/20 "
13
- :class="agentStore.isSessionHistoryOpen ?
14
- 'bg-lightNavbarIcons/20 text-lightNavbarIcons/80 dark:bg-darkNavbarIcons/20 dark:text-darkNavbarIcons/80' :
15
- ''"
16
- @click="agentStore.setSessionHistoryOpen(!agentStore.isSessionHistoryOpen)"
17
- />
18
- <IconOpenSidebarSolid
19
- v-if="!agentStore.isTeleportedToBody && !coreStore.isMobile && !agentStore.isFullScreen"
20
- class="m-2 w-8 h-8 p-1 cursor-pointer hover:scale-110 rounded transition-colors duration-200
21
- text-lightNavbarIcons hover:text-lightNavbarIcons/80 hover:bg-lightNavbarIcons/20
22
- dark:text-darkNavbarIcons hover:text-darkNavbarIcons/80 hover:bg-darkNavbarIcons/20 "
23
- @click="agentStore.setIsTeleportedToBody(true)"
24
- />
25
- <IconCloseSidebarSolid
26
- v-else-if="!coreStore.isMobile && !agentStore.isFullScreen"
27
- class="m-2 w-8 h-8 p-1 cursor-pointer hover:scale-110 rounded transition-colors duration-200
28
- text-lightNavbarIcons hover:text-lightNavbarIcons/80 bg-lightNavbarIcons/20
29
- dark:bg-darkNavbarIcons/20 dark:text-darkNavbarIcons/80 hover:text-darkNavbarIcons/80 hover:bg-darkNavbarIcons/20 "
30
- @click="agentStore.setIsTeleportedToBody(false)"
31
- />
32
- <IconArrowsPointingOut
33
- v-if="!agentStore.isFullScreen && !coreStore.isMobile"
34
- class="m-2 w-8 h-8 p-1 cursor-pointer hover:scale-110 rounded transition-colors duration-200
35
- text-lightNavbarIcons hover:text-lightNavbarIcons/80 hover:bg-lightNavbarIcons/20
36
- dark:text-darkNavbarIcons hover:text-darkNavbarIcons/80 hover:bg-darkNavbarIcons/20 "
37
- @click="agentStore.setFullScreen(true)"
38
- />
39
- <IconArrowsPointingIn
40
- v-else-if="!coreStore.isMobile"
41
- class="m-2 w-8 h-8 p-1 cursor-pointer hover:scale-110 rounded transition-colors duration-200
42
- text-lightNavbarIcons hover:text-lightNavbarIcons/80 hover:bg-lightNavbarIcons/20
43
- dark:text-darkNavbarIcons hover:text-darkNavbarIcons/80 hover:bg-darkNavbarIcons/20 "
44
- :class="agentStore.isFullScreen ?
45
- 'bg-lightNavbarIcons/20 text-lightNavbarIcons/80 dark:bg-darkNavbarIcons/20 dark:text-darkNavbarIcons/80' :
46
- ''"
47
- @click="agentStore.setFullScreen(false)"
48
- />
49
- </div>
50
- <div class="flex items-center justify-center">
51
- <Button
52
- @click="agentStore.createPreSession(); agentStore.setSessionHistoryOpen(false); agentStore.focusTextInput();"
53
- class="!py-1 !px-2 rounded-3xl text-gray-800 dark:text-gray-200 max-w-64 mr-2"
54
- >
55
- <IconPlusOutline class="w-5 h-5" />
56
- {{ $t('New chat') }}
57
- </Button>
58
- <IconCloseOutline
59
- class="m-2 w-8 h-8 p-1 cursor-pointer hover:scale-110 rounded transition-colors duration-200
60
- text-lightNavbarIcons hover:text-lightNavbarIcons/80 hover:bg-lightNavbarIcons/20
61
- dark:text-darkNavbarIcons hover:text-darkNavbarIcons/80 hover:bg-darkNavbarIcons/20 "
62
- @click="agentStore.setIsChatOpen(false)"
63
- />
64
- </div>
65
- </div>
66
- </template>
67
-
68
-
69
- <script setup>
70
- import { IconArrowsPointingOut, IconArrowsPointingIn } from '@iconify-prerendered/vue-heroicons';
71
- import { IconCloseOutline, IconBarsOutline, IconCloseSidebarSolid, IconOpenSidebarSolid, IconPlusOutline } from '@iconify-prerendered/vue-flowbite';
72
- import { useAgentStore } from './composables/useAgentStore';
73
- import { useCoreStore } from '@/stores/core';
74
- import { Button } from '@/afcl';
75
-
76
- const agentStore = useAgentStore();
77
- const coreStore = useCoreStore();
78
- </script>