@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,220 +0,0 @@
1
-
2
- const ctx = new AudioContext();
3
- let standbySource: AudioBufferSourceNode | null = null;
4
- let isAudioUnlocked = false;
5
-
6
- const DEFAULT_PCM_SAMPLE_RATE = 24000;
7
- const DEFAULT_PCM_CHANNEL_COUNT = 1;
8
- const DEFAULT_PCM_BITS_PER_SAMPLE = 16;
9
-
10
- export type ChatResponseAudioPlayback = {
11
- nextStartTime: number;
12
- activeSources: Set<AudioBufferSourceNode>;
13
- pendingSourceCount: number;
14
- pendingPcmBytes: Uint8Array;
15
- isDone: boolean;
16
- isStopped: boolean;
17
- sampleRate: number;
18
- channelCount: number;
19
- bitsPerSample: number;
20
- onEnded?: () => void;
21
- };
22
-
23
- export async function unlockAudio() {
24
- if (isAudioUnlocked) {
25
- return;
26
- }
27
- console.log('Unlocking audio context by playing silent audio');
28
- await ctx.resume();
29
-
30
- const buffer = ctx.createBuffer(1, 1, 22050);
31
- const source = ctx.createBufferSource();
32
-
33
- source.buffer = buffer;
34
- source.connect(ctx.destination);
35
- source.start(0);
36
- isAudioUnlocked = true;
37
- console.log('Audio context unlocked');
38
- }
39
-
40
- export async function startStandByAudio() {
41
- const standByAudio = new URL(
42
- '../../public/agentAudio/agent-processing.mp3',
43
- import.meta.url
44
- ).href;
45
- const response = await fetch(standByAudio);
46
- console.log('status', response.status);
47
- console.log('content-type', response.headers.get('content-type'));
48
- console.log('response', response);
49
-
50
- const arrayBuffer = await response.arrayBuffer();
51
- const audioBuffer = await ctx.decodeAudioData(arrayBuffer);
52
-
53
- const source = ctx.createBufferSource();
54
- standbySource = source;
55
-
56
- source.buffer = audioBuffer;
57
- source.connect(ctx.destination);
58
- console.log('Playing standby audio');
59
- source.start();
60
- }
61
-
62
- export function createChatResponseAudioPlayback(options: {
63
- sampleRate?: number;
64
- channelCount?: number;
65
- bitsPerSample?: number;
66
- onEnded?: () => void;
67
- } = {}): ChatResponseAudioPlayback {
68
- return {
69
- nextStartTime: ctx.currentTime,
70
- activeSources: new Set(),
71
- pendingSourceCount: 0,
72
- pendingPcmBytes: new Uint8Array(0),
73
- isDone: false,
74
- isStopped: false,
75
- sampleRate: options.sampleRate ?? DEFAULT_PCM_SAMPLE_RATE,
76
- channelCount: options.channelCount ?? DEFAULT_PCM_CHANNEL_COUNT,
77
- bitsPerSample: options.bitsPerSample ?? DEFAULT_PCM_BITS_PER_SAMPLE,
78
- onEnded: options.onEnded,
79
- };
80
- }
81
-
82
- export function playChatResponseCurrentChunks({
83
- playback,
84
- chunks,
85
- }: {
86
- playback: ChatResponseAudioPlayback;
87
- chunks: ArrayBuffer[];
88
- }) {
89
- console.log('Playing chat response audio chunks:', chunks.length);
90
- void ctx.resume().catch(() => undefined);
91
-
92
- for (const chunk of chunks) {
93
- if (playback.isStopped || !chunk.byteLength) {
94
- continue;
95
- }
96
-
97
- const pcmBytes = concatUint8Arrays(playback.pendingPcmBytes, new Uint8Array(chunk));
98
- const bytesPerFrame = playback.channelCount * (playback.bitsPerSample / 8);
99
- const alignedByteLength = pcmBytes.byteLength - (pcmBytes.byteLength % bytesPerFrame);
100
-
101
- playback.pendingPcmBytes = pcmBytes.slice(alignedByteLength);
102
-
103
- if (!alignedByteLength) {
104
- continue;
105
- }
106
-
107
- const audioBuffer = createAudioBufferFromPcmChunk(
108
- playback,
109
- pcmBytes.subarray(0, alignedByteLength)
110
- );
111
- const source = ctx.createBufferSource();
112
- const startTime = Math.max(playback.nextStartTime, ctx.currentTime);
113
-
114
- source.buffer = audioBuffer;
115
- source.connect(ctx.destination);
116
-
117
- playback.activeSources.add(source);
118
- playback.pendingSourceCount += 1;
119
- playback.nextStartTime = startTime + audioBuffer.duration;
120
-
121
- source.addEventListener(
122
- 'ended',
123
- () => {
124
- playback.activeSources.delete(source);
125
- playback.pendingSourceCount = Math.max(0, playback.pendingSourceCount - 1);
126
-
127
- if (!playback.isStopped && playback.isDone && playback.pendingSourceCount === 0) {
128
- playback.onEnded?.();
129
- }
130
- },
131
- { once: true }
132
- );
133
-
134
- source.start(startTime);
135
- }
136
- }
137
-
138
- export function finishChatResponseAudio(playback: ChatResponseAudioPlayback | null) {
139
- if (!playback || playback.isStopped) {
140
- return;
141
- }
142
- console.log('Finishing chat response audio playback');
143
- playback.isDone = true;
144
-
145
- if (playback.pendingSourceCount === 0) {
146
- playback.onEnded?.();
147
- }
148
- }
149
-
150
- export function stopChatResponseAudio(playback: ChatResponseAudioPlayback | null) {
151
- if (!playback || playback.isStopped) {
152
- return;
153
- }
154
- console.log('Stopping chat response audio playback');
155
- playback.isStopped = true;
156
-
157
- for (const source of playback.activeSources) {
158
- source.stop();
159
- }
160
-
161
- playback.activeSources.clear();
162
- playback.pendingSourceCount = 0;
163
- playback.pendingPcmBytes = new Uint8Array(0);
164
- playback.nextStartTime = ctx.currentTime;
165
- }
166
-
167
- function createAudioBufferFromPcmChunk(
168
- playback: ChatResponseAudioPlayback,
169
- chunk: Uint8Array
170
- ) {
171
- if (playback.bitsPerSample !== DEFAULT_PCM_BITS_PER_SAMPLE) {
172
- throw new Error(`Unsupported PCM bit depth: ${playback.bitsPerSample}`);
173
- }
174
-
175
- const bytesPerSample = playback.bitsPerSample / 8;
176
- const frameCount = chunk.byteLength / playback.channelCount / bytesPerSample;
177
- const audioBuffer = ctx.createBuffer(
178
- playback.channelCount,
179
- frameCount,
180
- playback.sampleRate
181
- );
182
- const pcm = new DataView(chunk.buffer, chunk.byteOffset, chunk.byteLength);
183
- const channelData = Array.from(
184
- { length: playback.channelCount },
185
- (_, channelIndex) => audioBuffer.getChannelData(channelIndex)
186
- );
187
-
188
- for (let frameIndex = 0; frameIndex < frameCount; frameIndex += 1) {
189
- for (let channelIndex = 0; channelIndex < playback.channelCount; channelIndex += 1) {
190
- const sampleOffset =
191
- (frameIndex * playback.channelCount + channelIndex) * bytesPerSample;
192
- const sample = pcm.getInt16(sampleOffset, true) / 32768;
193
-
194
- channelData[channelIndex][frameIndex] = sample;
195
- }
196
- }
197
-
198
- return audioBuffer;
199
- }
200
-
201
- function concatUint8Arrays(left: Uint8Array, right: Uint8Array) {
202
- if (!left.byteLength) {
203
- return right;
204
- }
205
-
206
- const combined = new Uint8Array(left.byteLength + right.byteLength);
207
-
208
- combined.set(left, 0);
209
- combined.set(right, left.byteLength);
210
-
211
- return combined;
212
- }
213
-
214
- export function endStandByAudio() {
215
- if (standbySource) {
216
- console.log('Ending standby audio');
217
- standbySource.stop();
218
- standbySource = null;
219
- }
220
- }
@@ -1,19 +0,0 @@
1
- export type AgentMode = {
2
- name: string;
3
- };
4
-
5
- export const DEFAULT_CHAT_WIDTH = 30;
6
- export const MAX_WIDTH = 60;
7
- export const MIN_WIDTH = 25;
8
-
9
- export const DEFAULT_TEXTAREA_PLACEHOLDER = 'Type a message...';
10
- export const PLACEHOLDER_TYPING_DELAY_MS = 60;
11
- export const PLACEHOLDER_DELETING_DELAY_MS = 35;
12
- export const PLACEHOLDER_HOLD_DELAY_MS = 3000;
13
- export const PRE_SESSION_ID = 'pre-session';
14
-
15
- export enum RESERVED_SYSTEM_MESSAGE_CONTENT {
16
- START_AUDIO_CHAT = 'START_AUDIO_CHAT',
17
- END_AUDIO_CHAT = 'END_AUDIO_CHAT',
18
- AGENT_RESPONSE_ABORTED = 'AGENT_RESPONSE_ABORTED'
19
- }
@@ -1,8 +0,0 @@
1
- export function getCurrentPageContext() {
2
- return {
3
- path: window.location.pathname,
4
- fullPath: `${window.location.pathname}${window.location.search}${window.location.hash}`,
5
- title: document.title,
6
- url: window.location.href,
7
- };
8
- }
@@ -1,241 +0,0 @@
1
- import { DefaultChatTransport } from 'ai';
2
- import { shallowRef, type Ref } from 'vue';
3
- import { Chat } from '../../chat';
4
- import { getCurrentPageContext } from './pageContext';
5
- // const { DefaultChatTransport } = await import('ai');
6
-
7
- type AgentImportMeta = ImportMeta & {
8
- env: {
9
- VITE_ADMINFORTH_PUBLIC_PATH?: string;
10
- };
11
- };
12
-
13
- type CreateAgentChatManagerOptions = {
14
- lastMessage: Ref<string>;
15
- activeModeName: Ref<string | null>;
16
- onOpenPage: (targetPath: string) => void;
17
- onToolApprovalRequest: (sessionId: string, interrupt: unknown) => void;
18
- };
19
-
20
- export function createAgentChatManager({
21
- lastMessage,
22
- activeModeName,
23
- onOpenPage,
24
- onToolApprovalRequest,
25
- }: CreateAgentChatManagerOptions) {
26
- const chats = new Map<string, Chat<any>>();
27
- const currentChat = shallowRef<Chat<any> | null>();
28
- const agentApiBase = `${(import.meta as AgentImportMeta).env.VITE_ADMINFORTH_PUBLIC_PATH || ''}/adminapi/v1/agent`;
29
-
30
- function replaceLastMessage(message: any) {
31
- const chat = currentChat.value;
32
-
33
- if (!chat) {
34
- return;
35
- }
36
-
37
- chat.messages.splice(chat.messages.length - 1, 1, message);
38
- }
39
-
40
- function getOrCreateAssistantMessage() {
41
- const chat = currentChat.value;
42
- const lastChatMessage = chat?.lastMessage;
43
-
44
- if (lastChatMessage?.role === 'assistant') {
45
- return lastChatMessage;
46
- }
47
-
48
- const assistantMessage = {
49
- role: 'assistant',
50
- parts: [],
51
- };
52
-
53
- chat?.messages.push(assistantMessage);
54
- return assistantMessage;
55
- }
56
-
57
- function appendTextDelta(delta: string) {
58
- const assistantMessage = getOrCreateAssistantMessage();
59
- const lastPart = assistantMessage.parts.at(-1);
60
-
61
- if (lastPart?.type === 'text') {
62
- lastPart.text = `${lastPart.text ?? ''}${delta}`;
63
- lastPart.state = 'streaming';
64
- } else {
65
- assistantMessage.parts.push({
66
- type: 'text',
67
- text: delta,
68
- state: 'streaming',
69
- });
70
- }
71
-
72
- replaceLastMessage(assistantMessage);
73
- }
74
-
75
- function finishTextPart() {
76
- const assistantMessage = currentChat.value?.lastMessage;
77
- const lastPart = assistantMessage?.parts.at(-1);
78
-
79
- if (assistantMessage?.role === 'assistant' && lastPart?.type === 'text') {
80
- lastPart.state = 'done';
81
- replaceLastMessage(assistantMessage);
82
- }
83
- }
84
-
85
- function appendDataPart(type: string, data: unknown) {
86
- const assistantMessage = getOrCreateAssistantMessage();
87
-
88
- assistantMessage.parts.push({ type, data });
89
- replaceLastMessage(assistantMessage);
90
- }
91
-
92
- function handleRealtimeChatData(dataPart: any) {
93
- if (dataPart?.type === 'data-open-page' && typeof dataPart.data?.targetPath === 'string') {
94
- onOpenPage(dataPart.data.targetPath);
95
- return;
96
- }
97
-
98
- if (dataPart?.type === 'data-interrupt' && typeof dataPart.data?.sessionId === 'string') {
99
- onToolApprovalRequest(dataPart.data.sessionId, dataPart.data.interrupt);
100
- }
101
- }
102
-
103
- function handleManualApprovalStreamPart(dataPart: any) {
104
- if (dataPart?.type === 'text-delta' && typeof dataPart.delta === 'string') {
105
- appendTextDelta(dataPart.delta);
106
- return;
107
- }
108
-
109
- if (dataPart?.type === 'text-end') {
110
- finishTextPart();
111
- return;
112
- }
113
-
114
- if (dataPart?.type === 'data-tool-call') {
115
- appendDataPart('data-tool-call', dataPart.data);
116
- return;
117
- }
118
-
119
- if (dataPart?.type === 'data-rendering') {
120
- appendDataPart('data-rendering', dataPart.data);
121
- return;
122
- }
123
-
124
- if (dataPart?.type === 'data-open-page' && typeof dataPart.data?.targetPath === 'string') {
125
- onOpenPage(dataPart.data.targetPath);
126
- return;
127
- }
128
-
129
- if (dataPart?.type === 'data-interrupt' && typeof dataPart.data?.sessionId === 'string') {
130
- onToolApprovalRequest(dataPart.data.sessionId, dataPart.data.interrupt);
131
- }
132
- }
133
-
134
- async function consumeAgentStream(response: Response) {
135
- const reader = response.body?.getReader();
136
-
137
- if (!reader) {
138
- return;
139
- }
140
-
141
- const decoder = new TextDecoder();
142
- let buffer = '';
143
-
144
- while (true) {
145
- const { value, done } = await reader.read();
146
-
147
- if (done) {
148
- break;
149
- }
150
-
151
- buffer += decoder.decode(value, { stream: true });
152
- const events = buffer.split('\n\n');
153
- buffer = events.pop() ?? '';
154
-
155
- for (const event of events) {
156
- const data = event
157
- .split('\n')
158
- .filter(line => line.startsWith('data:'))
159
- .map(line => line.slice(5).trim())
160
- .join('\n');
161
-
162
- if (!data || data === '[DONE]') {
163
- continue;
164
- }
165
-
166
- handleManualApprovalStreamPart(JSON.parse(data));
167
- }
168
- }
169
- }
170
-
171
- function setCurrentChat(sessionId: string) {
172
- if (chats.has(sessionId)) {
173
- currentChat.value = chats.get(sessionId) || null;
174
- } else {
175
- const newChat = new Chat({
176
- transport: new DefaultChatTransport({
177
- api: `${agentApiBase}/response`,
178
- credentials: 'include',
179
- prepareSendMessagesRequest({ messages }: any) {
180
- const message = lastMessage.value;
181
- const body = {
182
- message,
183
- sessionId,
184
- timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
185
- mode: activeModeName.value,
186
- currentPage: getCurrentPageContext(),
187
- };
188
-
189
- return {
190
- headers: {
191
- Accept: 'text/event-stream',
192
- 'x-vercel-ai-ui-message-stream': 'v1',
193
- },
194
- body
195
- };
196
- }
197
- }),
198
- onError(error: unknown) {
199
- console.error('Chat error:', error);
200
- appendTextDelta(`Error: ${error instanceof Error ? error.message : String(error)}`);
201
- },
202
- onData: handleRealtimeChatData,
203
- });
204
- chats.set(sessionId, newChat);
205
- currentChat.value = newChat;
206
- }
207
- }
208
-
209
- function abortCurrentChatRequest() {
210
- currentChat.value?.stop();
211
- }
212
-
213
- async function submitToolApproval(sessionId: string, decision: 'approve' | 'reject') {
214
- const response = await fetch(`${agentApiBase}/approval`, {
215
- method: 'POST',
216
- credentials: 'include',
217
- headers: {
218
- Accept: 'text/event-stream',
219
- 'Content-Type': 'application/json',
220
- 'x-vercel-ai-ui-message-stream': 'v1',
221
- },
222
- body: JSON.stringify({
223
- sessionId,
224
- decision,
225
- }),
226
- });
227
-
228
- if (!response.ok) {
229
- throw new Error(`Agent approval failed with status ${response.status}`);
230
- }
231
-
232
- await consumeAgentStream(response);
233
- }
234
-
235
- return {
236
- currentChat,
237
- setCurrentChat,
238
- abortCurrentChatRequest,
239
- submitToolApproval,
240
- };
241
- }
@@ -1,142 +0,0 @@
1
- import { ref, watch, type Ref } from 'vue';
2
- import { callAdminForthApi } from '@/utils';
3
- import {
4
- DEFAULT_TEXTAREA_PLACEHOLDER,
5
- PLACEHOLDER_DELETING_DELAY_MS,
6
- PLACEHOLDER_HOLD_DELAY_MS,
7
- PLACEHOLDER_TYPING_DELAY_MS,
8
- } from './constants';
9
-
10
- type CreateAgentPlaceholderControllerOptions = {
11
- userMessageInput: Ref<unknown>;
12
- };
13
-
14
- export function createAgentPlaceholderController({
15
- userMessageInput,
16
- }: CreateAgentPlaceholderControllerOptions) {
17
- const userMessagePlaceholder = ref(DEFAULT_TEXTAREA_PLACEHOLDER);
18
- const placeholderMessages = ref<string[]>([]);
19
- const hasTypedMessageInPageSession = ref(false);
20
-
21
- let placeholderAnimationTimer: ReturnType<typeof setTimeout> | null = null;
22
-
23
- function clearPlaceholderAnimationTimer() {
24
- if (placeholderAnimationTimer !== null) {
25
- clearTimeout(placeholderAnimationTimer);
26
- placeholderAnimationTimer = null;
27
- }
28
- }
29
-
30
- function resetPlaceholder() {
31
- clearPlaceholderAnimationTimer();
32
- userMessagePlaceholder.value = DEFAULT_TEXTAREA_PLACEHOLDER;
33
- }
34
-
35
- function stopPlaceholderAnimation() {
36
- resetPlaceholder();
37
- }
38
-
39
- function startPlaceholderAnimation(messages: string[]) {
40
- clearPlaceholderAnimationTimer();
41
-
42
- if (!messages.length) {
43
- userMessagePlaceholder.value = DEFAULT_TEXTAREA_PLACEHOLDER;
44
- return;
45
- }
46
-
47
- let messageIndex = 0;
48
- let visibleLength = 0;
49
- let isDeleting = false;
50
-
51
- const animate = () => {
52
- const currentMessage = messages[messageIndex];
53
-
54
- if (!currentMessage) {
55
- resetPlaceholder();
56
- return;
57
- }
58
-
59
- if (!isDeleting) {
60
- visibleLength += 1;
61
- userMessagePlaceholder.value = currentMessage.slice(0, visibleLength);
62
-
63
- if (visibleLength >= currentMessage.length) {
64
- isDeleting = true;
65
- placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_HOLD_DELAY_MS);
66
- return;
67
- }
68
-
69
- placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_TYPING_DELAY_MS);
70
- return;
71
- }
72
-
73
- visibleLength -= 1;
74
- userMessagePlaceholder.value = currentMessage.slice(0, Math.max(visibleLength, 0));
75
-
76
- if (visibleLength <= 0) {
77
- isDeleting = false;
78
- messageIndex = (messageIndex + 1) % messages.length;
79
- placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_TYPING_DELAY_MS);
80
- return;
81
- }
82
-
83
- placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_DELETING_DELAY_MS);
84
- };
85
-
86
- animate();
87
- }
88
-
89
- async function fetchPlaceholderMessages() {
90
- if (hasTypedMessageInPageSession.value) {
91
- stopPlaceholderAnimation();
92
- return;
93
- }
94
-
95
- try {
96
- const res = await callAdminForthApi({
97
- method: 'POST',
98
- path: '/agent/get-placeholder-messages',
99
- });
100
-
101
- if (res.error) {
102
- console.error('Error fetching placeholder messages:', res.error);
103
- placeholderMessages.value = [];
104
- resetPlaceholder();
105
- return;
106
- }
107
-
108
- placeholderMessages.value = Array.isArray(res.messages)
109
- ? res.messages.filter((message: unknown): message is string => typeof message === 'string' && message.length > 0)
110
- : [];
111
-
112
- if (!placeholderMessages.value.length) {
113
- resetPlaceholder();
114
- return;
115
- }
116
-
117
- startPlaceholderAnimation(placeholderMessages.value);
118
- } catch (error) {
119
- console.error('Error fetching placeholder messages', error);
120
- placeholderMessages.value = [];
121
- resetPlaceholder();
122
- }
123
- }
124
-
125
- watch(userMessageInput, (newVal: unknown) => {
126
- if (hasTypedMessageInPageSession.value) {
127
- return;
128
- }
129
-
130
- if (typeof newVal === 'string' && newVal.trim() !== '') {
131
- hasTypedMessageInPageSession.value = true;
132
- stopPlaceholderAnimation();
133
- }
134
- });
135
-
136
- return {
137
- userMessagePlaceholder,
138
- hasTypedMessageInPageSession,
139
- fetchPlaceholderMessages,
140
- stopPlaceholderAnimation,
141
- };
142
- }