@adminforth/agent 2.0.9 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +333 -10
- package/dist/application/ports.d.ts +66 -0
- package/dist/application/runTurnUseCase.d.ts +68 -0
- package/dist/application/runTurnUseCase.js +358 -0
- package/dist/{agentEvents.d.ts → domain/agentEvents.d.ts} +1 -1
- package/dist/{agent → domain}/systemPrompt.js +1 -1
- package/dist/{agent/turn → domain}/turnTypes.d.ts +41 -37
- package/dist/{agent/turn/VegaLiteStreamBuffer.d.ts → domain/vegaLiteStreamBuffer.d.ts} +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +40 -35
- package/dist/{agent/runtime/AgentContext.d.ts → llm/agentContext.d.ts} +3 -3
- package/dist/{agent/simpleAgent.d.ts → llm/agentModels.d.ts} +18 -16
- package/dist/llm/agentModels.js +65 -0
- package/dist/{agent/runtime/AgentRuntime.d.ts → llm/agentRuntime.d.ts} +11 -2
- package/dist/{agent/runtime/AgentRuntime.js → llm/agentRuntime.js} +38 -6
- package/dist/llm/langGraphLlm.d.ts +25 -0
- package/dist/llm/langGraphLlm.js +54 -0
- package/dist/{agent/middleware/apiBasedTools.d.ts → llm/middleware/apiToolsMiddleware.d.ts} +1 -1
- package/dist/{agent/middleware/apiBasedTools.js → llm/middleware/apiToolsMiddleware.js} +8 -14
- package/dist/{agent → llm}/middleware/sequenceDebug.d.ts +1 -1
- package/dist/{agent/models/AgentModelFactory.d.ts → llm/modelFactory.d.ts} +1 -1
- package/dist/{agent/models/AgentModelFactory.js → llm/modelFactory.js} +1 -1
- package/dist/llm/streamAdapter.d.ts +18 -0
- package/dist/llm/streamAdapter.js +117 -0
- package/dist/{sessionStore.d.ts → persistence/sessionStore.d.ts} +12 -2
- package/dist/{sessionStore.js → persistence/sessionStore.js} +33 -0
- package/dist/{agent/tools/AgentToolProvider.d.ts → tools/agentToolProvider.d.ts} +1 -1
- package/dist/{agent/tools/AgentToolProvider.js → tools/agentToolProvider.js} +1 -1
- package/dist/{apiBasedTools.js → tools/apiBasedTools.js} +10 -6
- package/dist/{agent/tools → tools}/apiTool.d.ts +1 -1
- package/dist/{agent/tools → tools}/fetchSkill.js +1 -1
- package/dist/{agent/tools → tools}/fetchToolSchema.d.ts +1 -1
- package/dist/{agent/tools → tools}/index.d.ts +1 -1
- package/dist/{agent/tools → tools}/navigateUser.d.ts +3 -3
- package/dist/{endpoints → transport/http}/context.d.ts +2 -2
- package/dist/transport/http/context.js +1 -0
- package/dist/{endpoints/core.js → transport/http/coreEndpoints.js} +3 -3
- package/dist/{endpoints/sessions.js → transport/http/sessionEndpoints.js} +7 -1
- package/dist/transport/sse/sseWriter.d.ts +29 -0
- package/dist/{surfaces/web-sse/createSseEventEmitter.js → transport/sse/sseWriter.js} +15 -0
- package/dist/{chatSurfaceService.d.ts → transport/surfaces/chatSurfaceService.d.ts} +3 -3
- package/dist/{chatSurfaceService.js → transport/surfaces/chatSurfaceService.js} +7 -5
- package/dist/{agent/speech/SpeechTurnService.d.ts → transport/surfaces/speechTurnService.d.ts} +1 -1
- package/dist/{agent/speech/SpeechTurnService.js → transport/surfaces/speechTurnService.js} +2 -2
- package/dist/types.d.ts +10 -4
- package/package.json +11 -2
- package/.woodpecker/buildRelease.sh +0 -13
- package/.woodpecker/buildSlackNotify.sh +0 -46
- package/.woodpecker/release.yml +0 -57
- package/agent/checkpointer.ts +0 -329
- package/agent/languageDetect.ts +0 -92
- package/agent/middleware/apiBasedTools.ts +0 -174
- package/agent/middleware/openAiResponsesContinuation.ts +0 -92
- package/agent/middleware/sequenceDebug.ts +0 -429
- package/agent/models/AgentModeResolver.ts +0 -9
- package/agent/models/AgentModelFactory.ts +0 -28
- package/agent/runtime/AgentContext.ts +0 -30
- package/agent/runtime/AgentRuntime.ts +0 -89
- package/agent/simpleAgent.ts +0 -199
- package/agent/skills/registry.ts +0 -162
- package/agent/speech/SpeechTurnService.ts +0 -179
- package/agent/systemPrompt.ts +0 -133
- package/agent/toolCallEvents.ts +0 -135
- package/agent/tools/AgentToolProvider.ts +0 -28
- package/agent/tools/apiTool.ts +0 -66
- package/agent/tools/fetchSkill.ts +0 -68
- package/agent/tools/fetchToolSchema.ts +0 -47
- package/agent/tools/getUserLocation.ts +0 -45
- package/agent/tools/index.ts +0 -31
- package/agent/tools/navigateUser.ts +0 -210
- package/agent/turn/TurnContextBuilder.ts +0 -36
- package/agent/turn/TurnLifecycleService.ts +0 -47
- package/agent/turn/TurnPersistenceService.ts +0 -33
- package/agent/turn/TurnPromptBuilder.ts +0 -51
- package/agent/turn/TurnStreamConsumer.ts +0 -69
- package/agent/turn/VegaLiteStreamBuffer.ts +0 -90
- package/agent/turn/turnTypes.ts +0 -100
- package/agentEvents.ts +0 -75
- package/agentTurnService.ts +0 -314
- package/apiBasedTools.ts +0 -702
- package/build.log +0 -67
- package/chatSurfaceService.ts +0 -319
- package/custom/ChatFooter.vue +0 -173
- package/custom/ChatHeader.vue +0 -78
- package/custom/ChatSurface.vue +0 -160
- package/custom/CustomAutoScrollContainer.vue +0 -164
- package/custom/SessionsHistory.vue +0 -88
- package/custom/chat.ts +0 -82
- package/custom/composables/agentAudio/utils.ts +0 -220
- package/custom/composables/agentStore/constants.ts +0 -19
- package/custom/composables/agentStore/pageContext.ts +0 -8
- package/custom/composables/agentStore/useAgentChat.ts +0 -241
- package/custom/composables/agentStore/useAgentPlaceholder.ts +0 -142
- package/custom/composables/agentStore/useAgentSessions.ts +0 -350
- package/custom/composables/useAgentAudio.ts +0 -272
- package/custom/composables/useAgentStore.ts +0 -510
- package/custom/composables/useAgentTransitions.ts +0 -58
- package/custom/conversation_area/ConversationArea.vue +0 -301
- package/custom/conversation_area/MessageRenderer.vue +0 -49
- package/custom/conversation_area/ProcessingTimeline.vue +0 -286
- package/custom/conversation_area/ReasoningRenderer.vue +0 -79
- package/custom/conversation_area/SystemMessageRenderer.vue +0 -28
- package/custom/conversation_area/TextRenderer.vue +0 -182
- package/custom/conversation_area/ThreeDotsAnimation.vue +0 -35
- package/custom/conversation_area/ToolApprovalRenderer.vue +0 -98
- package/custom/conversation_area/ToolRenderer.vue +0 -178
- package/custom/conversation_area/ToolsGroup.vue +0 -59
- package/custom/env.d.ts +0 -7
- package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +0 -393
- package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +0 -285
- package/custom/incremark_code_renderers/incremarkRenderer.ts +0 -653
- package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +0 -118
- package/custom/package.json +0 -30
- package/custom/pnpm-lock.yaml +0 -2394
- package/custom/public/agentAudio/agent-processing.mp3 +0 -0
- package/custom/skills/analyze_data/SKILL.md +0 -25
- package/custom/skills/charts/SKILL.md +0 -193
- package/custom/skills/fetch_data/SKILL.md +0 -31
- package/custom/skills/mutate_data/SKILL.md +0 -121
- package/custom/speech_recognition_frontend/AudioLines.vue +0 -43
- package/custom/speech_recognition_frontend/MicrophoneButon.vue +0 -185
- package/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +0 -22
- package/custom/speech_recognition_frontend/voiceActivityDetection.ts +0 -62
- package/custom/tsconfig.json +0 -15
- package/custom/types.ts +0 -108
- package/custom/utils.ts +0 -38
- package/dist/agent/middleware/openAiResponsesContinuation.d.ts +0 -1
- package/dist/agent/middleware/openAiResponsesContinuation.js +0 -66
- package/dist/agent/models/AgentModeResolver.d.ts +0 -9
- package/dist/agent/models/AgentModeResolver.js +0 -9
- package/dist/agent/simpleAgent.js +0 -118
- package/dist/agent/turn/TurnContextBuilder.d.ts +0 -14
- package/dist/agent/turn/TurnContextBuilder.js +0 -31
- package/dist/agent/turn/TurnLifecycleService.d.ts +0 -24
- package/dist/agent/turn/TurnLifecycleService.js +0 -47
- package/dist/agent/turn/TurnPersistenceService.d.ts +0 -13
- package/dist/agent/turn/TurnPersistenceService.js +0 -35
- package/dist/agent/turn/TurnPromptBuilder.d.ts +0 -19
- package/dist/agent/turn/TurnPromptBuilder.js +0 -43
- package/dist/agent/turn/TurnStreamConsumer.d.ts +0 -11
- package/dist/agent/turn/TurnStreamConsumer.js +0 -84
- package/dist/agentTurnService.d.ts +0 -24
- package/dist/agentTurnService.js +0 -269
- package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +0 -14
- package/endpoints/chatSurfaces.ts +0 -66
- package/endpoints/context.ts +0 -52
- package/endpoints/core.ts +0 -181
- package/endpoints/sessions.ts +0 -183
- package/errors.ts +0 -10
- package/index.ts +0 -192
- package/pnpm-workspace.yaml +0 -4
- package/sanitizeSpeechText.ts +0 -32
- package/sessionStore.ts +0 -105
- package/surfaces/web-sse/createSseEventEmitter.ts +0 -311
- package/tsconfig.json +0 -14
- package/types.ts +0 -127
- /package/dist/{agent/turn/turnTypes.js → application/ports.js} +0 -0
- /package/dist/{agentEvents.js → domain/agentEvents.js} +0 -0
- /package/dist/{agent → domain}/languageDetect.d.ts +0 -0
- /package/dist/{agent → domain}/languageDetect.js +0 -0
- /package/dist/{agent → domain}/systemPrompt.d.ts +0 -0
- /package/dist/{agent → domain}/toolCallEvents.d.ts +0 -0
- /package/dist/{agent → domain}/toolCallEvents.js +0 -0
- /package/dist/{endpoints/context.js → domain/turnTypes.js} +0 -0
- /package/dist/{agent/turn/VegaLiteStreamBuffer.js → domain/vegaLiteStreamBuffer.js} +0 -0
- /package/dist/{agent/runtime/AgentContext.js → llm/agentContext.js} +0 -0
- /package/dist/{agent → llm}/middleware/sequenceDebug.js +0 -0
- /package/dist/{agent/checkpointer.d.ts → persistence/checkpointStore.d.ts} +0 -0
- /package/dist/{agent/checkpointer.js → persistence/checkpointStore.js} +0 -0
- /package/dist/{errors.d.ts → shared/errors.d.ts} +0 -0
- /package/dist/{errors.js → shared/errors.js} +0 -0
- /package/dist/{sanitizeSpeechText.d.ts → shared/sanitizeSpeechText.d.ts} +0 -0
- /package/dist/{sanitizeSpeechText.js → shared/sanitizeSpeechText.js} +0 -0
- /package/dist/{apiBasedTools.d.ts → tools/apiBasedTools.d.ts} +0 -0
- /package/dist/{agent/tools → tools}/apiTool.js +0 -0
- /package/dist/{agent/tools → tools}/fetchSkill.d.ts +0 -0
- /package/dist/{agent/tools → tools}/fetchToolSchema.js +0 -0
- /package/dist/{agent/tools → tools}/getUserLocation.d.ts +0 -0
- /package/dist/{agent/tools → tools}/getUserLocation.js +0 -0
- /package/dist/{agent/tools → tools}/index.js +0 -0
- /package/dist/{agent/tools → tools}/navigateUser.js +0 -0
- /package/dist/{agent → tools}/skills/registry.d.ts +0 -0
- /package/dist/{agent → tools}/skills/registry.js +0 -0
- /package/dist/{endpoints/chatSurfaces.d.ts → transport/http/chatSurfaceEndpoints.d.ts} +0 -0
- /package/dist/{endpoints/chatSurfaces.js → transport/http/chatSurfaceEndpoints.js} +0 -0
- /package/dist/{endpoints/core.d.ts → transport/http/coreEndpoints.d.ts} +0 -0
- /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,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
|
-
}
|