@adminforth/agent 1.50.1 → 1.51.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/agent/middleware/apiBasedTools.ts +13 -3
- package/agent/models/AgentModeResolver.ts +9 -0
- package/agent/models/AgentModelFactory.ts +28 -0
- package/agent/runtime/AgentContext.ts +30 -0
- package/agent/runtime/AgentRuntime.ts +68 -0
- package/agent/simpleAgent.ts +2 -129
- package/agent/speech/SpeechTurnService.ts +179 -0
- package/agent/tools/AgentToolProvider.ts +28 -0
- package/agent/tools/navigateUser.ts +2 -2
- package/agent/turn/TurnContextBuilder.ts +36 -0
- package/agent/turn/TurnLifecycleService.ts +29 -0
- package/agent/turn/TurnPersistenceService.ts +33 -0
- package/agent/turn/TurnPromptBuilder.ts +51 -0
- package/agent/turn/TurnStreamConsumer.ts +61 -0
- package/agent/turn/VegaLiteStreamBuffer.ts +90 -0
- package/agent/turn/turnTypes.ts +92 -0
- package/agentTurnService.ts +88 -461
- package/build.log +1 -1
- package/dist/agent/middleware/apiBasedTools.js +9 -2
- package/dist/agent/models/AgentModeResolver.d.ts +9 -0
- package/dist/agent/models/AgentModeResolver.js +9 -0
- package/dist/agent/models/AgentModelFactory.d.ts +7 -0
- package/dist/agent/models/AgentModelFactory.js +36 -0
- package/dist/agent/runtime/AgentContext.d.ts +28 -0
- package/dist/agent/runtime/AgentContext.js +17 -0
- package/dist/agent/runtime/AgentRuntime.d.ts +15 -0
- package/dist/agent/runtime/AgentRuntime.js +57 -0
- package/dist/agent/simpleAgent.d.ts +15 -45
- package/dist/agent/simpleAgent.js +1 -67
- package/dist/agent/speech/SpeechTurnService.d.ts +6 -0
- package/dist/agent/speech/SpeechTurnService.js +168 -0
- package/dist/agent/tools/AgentToolProvider.d.ts +9 -0
- package/dist/agent/tools/AgentToolProvider.js +27 -0
- package/dist/agent/tools/navigateUser.js +1 -1
- package/dist/agent/turn/TurnContextBuilder.d.ts +14 -0
- package/dist/agent/turn/TurnContextBuilder.js +31 -0
- package/dist/agent/turn/TurnLifecycleService.d.ts +17 -0
- package/dist/agent/turn/TurnLifecycleService.js +31 -0
- package/dist/agent/turn/TurnPersistenceService.d.ts +13 -0
- package/dist/agent/turn/TurnPersistenceService.js +35 -0
- package/dist/agent/turn/TurnPromptBuilder.d.ts +19 -0
- package/dist/agent/turn/TurnPromptBuilder.js +43 -0
- package/dist/agent/turn/TurnStreamConsumer.d.ts +10 -0
- package/dist/agent/turn/TurnStreamConsumer.js +78 -0
- package/dist/agent/turn/VegaLiteStreamBuffer.d.ts +7 -0
- package/dist/agent/turn/VegaLiteStreamBuffer.js +87 -0
- package/dist/agent/turn/turnTypes.d.ts +81 -0
- package/dist/agent/turn/turnTypes.js +1 -0
- package/dist/agentTurnService.d.ts +20 -69
- package/dist/agentTurnService.js +60 -373
- package/dist/index.d.ts +1 -0
- package/dist/index.js +22 -7
- package/index.ts +35 -7
- package/package.json +1 -1
package/dist/agentTurnService.js
CHANGED
|
@@ -7,231 +7,79 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
11
|
-
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
12
|
-
var m = o[Symbol.asyncIterator], i;
|
|
13
|
-
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
14
|
-
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
15
|
-
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
16
|
-
};
|
|
17
10
|
import { logger } from "adminforth";
|
|
18
11
|
import { randomUUID } from "crypto";
|
|
19
|
-
import { HumanMessage, SystemMessage } from "langchain";
|
|
20
|
-
import { createAgentChatModel, callAgent } from "./agent/simpleAgent.js";
|
|
21
12
|
import { createSequenceDebugCollector } from "./agent/middleware/sequenceDebug.js";
|
|
22
|
-
import {
|
|
23
|
-
import { prepareApiBasedTools as buildApiBasedTools } from "./apiBasedTools.js";
|
|
24
|
-
import { buildAgentTurnSystemPrompt } from "./agent/systemPrompt.js";
|
|
25
|
-
import { isAbortError, getErrorMessage } from "./errors.js";
|
|
26
|
-
import { sanitizeSpeechText } from "./sanitizeSpeechText.js";
|
|
27
|
-
const VEGA_LITE_FENCE_START = "```vega-lite";
|
|
28
|
-
const COMPLETE_VEGA_LITE_BLOCK_RE = /```vega-lite[\s\S]*?```/;
|
|
13
|
+
import { getErrorMessage, isAbortError } from "./errors.js";
|
|
29
14
|
export class AgentTurnService {
|
|
30
|
-
constructor(
|
|
31
|
-
this.
|
|
15
|
+
constructor(lifecycle, contextBuilder, modeResolver, modelFactory, promptBuilder, runtime, streamConsumer) {
|
|
16
|
+
this.lifecycle = lifecycle;
|
|
17
|
+
this.contextBuilder = contextBuilder;
|
|
18
|
+
this.modeResolver = modeResolver;
|
|
19
|
+
this.modelFactory = modelFactory;
|
|
20
|
+
this.promptBuilder = promptBuilder;
|
|
21
|
+
this.runtime = runtime;
|
|
22
|
+
this.streamConsumer = streamConsumer;
|
|
23
|
+
}
|
|
24
|
+
prepareTurn(input) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
const sequenceDebugCollector = createSequenceDebugCollector();
|
|
27
|
+
const { turnId, previousUserMessages } = yield this.lifecycle.start(input);
|
|
28
|
+
const context = yield this.contextBuilder.build({
|
|
29
|
+
base: input,
|
|
30
|
+
turnId,
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
prompt: input.prompt,
|
|
34
|
+
sessionId: input.sessionId,
|
|
35
|
+
turnId,
|
|
36
|
+
previousUserMessages,
|
|
37
|
+
modeName: input.modeName,
|
|
38
|
+
context,
|
|
39
|
+
observability: {
|
|
40
|
+
emit: undefined,
|
|
41
|
+
sequenceDebugSink: sequenceDebugCollector,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
});
|
|
32
45
|
}
|
|
33
46
|
runAgentTurn(input) {
|
|
34
47
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
createAgentChatModel({
|
|
46
|
-
adapter: selectedMode.completionAdapter,
|
|
47
|
-
maxTokens,
|
|
48
|
-
purpose: "primary",
|
|
49
|
-
}),
|
|
50
|
-
createAgentChatModel({
|
|
51
|
-
adapter: selectedMode.completionAdapter,
|
|
52
|
-
maxTokens,
|
|
53
|
-
purpose: "summary",
|
|
48
|
+
const selectedMode = this.modeResolver.resolve(input.modeName);
|
|
49
|
+
const [models, messages] = yield Promise.all([
|
|
50
|
+
this.modelFactory.create(selectedMode.completionAdapter),
|
|
51
|
+
this.promptBuilder.build({
|
|
52
|
+
prompt: input.prompt,
|
|
53
|
+
previousUserMessages: input.previousUserMessages,
|
|
54
|
+
adminUser: input.context.adminUser,
|
|
55
|
+
completionAdapter: selectedMode.completionAdapter,
|
|
56
|
+
chatSurface: input.context.chatSurface,
|
|
57
|
+
abortSignal: input.context.abortSignal,
|
|
54
58
|
}),
|
|
55
59
|
]);
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
.
|
|
61
|
-
var _a;
|
|
62
|
-
if (((_a = input.abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) || isAbortError(error)) {
|
|
63
|
-
throw error;
|
|
64
|
-
}
|
|
65
|
-
logger.warn(`Failed to detect user language: ${getErrorMessage(error)}`);
|
|
66
|
-
return null;
|
|
60
|
+
const stream = yield this.runtime.stream({
|
|
61
|
+
models,
|
|
62
|
+
messages,
|
|
63
|
+
context: input.context,
|
|
64
|
+
observability: input.observability,
|
|
67
65
|
});
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
userLanguage,
|
|
73
|
-
chatSurface: input.chatSurface,
|
|
66
|
+
return this.streamConsumer.consume({
|
|
67
|
+
stream: stream,
|
|
68
|
+
abortSignal: input.context.abortSignal,
|
|
69
|
+
emit: input.observability.emit,
|
|
74
70
|
});
|
|
75
|
-
const apiBasedTools = buildApiBasedTools(adminforth, this.serviceOptions.getInternalAgentResourceIds());
|
|
76
|
-
const stream = yield callAgent({
|
|
77
|
-
name: `adminforth-agent-${this.serviceOptions.getPluginInstanceId()}`,
|
|
78
|
-
model,
|
|
79
|
-
summaryModel,
|
|
80
|
-
modelMiddleware,
|
|
81
|
-
checkpointer: this.serviceOptions.getCheckpointer(),
|
|
82
|
-
messages: [
|
|
83
|
-
new SystemMessage(systemPrompt),
|
|
84
|
-
new HumanMessage(input.prompt),
|
|
85
|
-
],
|
|
86
|
-
adminUser: input.adminUser,
|
|
87
|
-
adminforth,
|
|
88
|
-
apiBasedTools,
|
|
89
|
-
customComponentsDir: (_f = adminforth.config.customization.customComponentsDir) !== null && _f !== void 0 ? _f : "custom",
|
|
90
|
-
pluginCustomFolderPaths: adminforth.activatedPlugins.map((plugin) => plugin.customFolderPath),
|
|
91
|
-
sessionId: input.sessionId,
|
|
92
|
-
turnId: input.turnId,
|
|
93
|
-
currentPage: input.currentPage,
|
|
94
|
-
chatSurface: input.chatSurface,
|
|
95
|
-
adminPublicOrigin: input.adminPublicOrigin,
|
|
96
|
-
userTimeZone: input.userTimeZone,
|
|
97
|
-
abortSignal: input.abortSignal,
|
|
98
|
-
emitToolCallEvent: (event) => {
|
|
99
|
-
var _a;
|
|
100
|
-
input.sequenceDebugCollector.handleToolCallEvent(event);
|
|
101
|
-
void ((_a = input.emit) === null || _a === void 0 ? void 0 : _a.call(input, {
|
|
102
|
-
type: "tool-call",
|
|
103
|
-
data: event,
|
|
104
|
-
}));
|
|
105
|
-
},
|
|
106
|
-
emitAgentEvent: input.emit,
|
|
107
|
-
sequenceDebugSink: input.sequenceDebugCollector,
|
|
108
|
-
});
|
|
109
|
-
try {
|
|
110
|
-
for (var _p = true, _q = __asyncValues(stream), _r; _r = yield _q.next(), _a = _r.done, !_a; _p = true) {
|
|
111
|
-
_c = _r.value;
|
|
112
|
-
_p = false;
|
|
113
|
-
const rawChunk = _c;
|
|
114
|
-
if ((_g = input.abortSignal) === null || _g === void 0 ? void 0 : _g.aborted) {
|
|
115
|
-
throw new DOMException("This operation was aborted", "AbortError");
|
|
116
|
-
}
|
|
117
|
-
const [token, metadata] = rawChunk;
|
|
118
|
-
const nodeName = typeof (metadata === null || metadata === void 0 ? void 0 : metadata.langgraph_node) === "string"
|
|
119
|
-
? metadata.langgraph_node
|
|
120
|
-
: "";
|
|
121
|
-
if (nodeName && !["model", "model_request"].includes(nodeName)) {
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
const blocks = Array.isArray(token === null || token === void 0 ? void 0 : token.contentBlocks)
|
|
125
|
-
? token.contentBlocks
|
|
126
|
-
: Array.isArray(token === null || token === void 0 ? void 0 : token.content)
|
|
127
|
-
? token.content
|
|
128
|
-
: [];
|
|
129
|
-
const reasoningDelta = blocks
|
|
130
|
-
.filter((b) => (b === null || b === void 0 ? void 0 : b.type) === "reasoning")
|
|
131
|
-
.map((b) => { var _a; return String((_a = b.reasoning) !== null && _a !== void 0 ? _a : ""); })
|
|
132
|
-
.join("");
|
|
133
|
-
const textDelta = blocks
|
|
134
|
-
.filter((b) => (b === null || b === void 0 ? void 0 : b.type) === "text")
|
|
135
|
-
.map((b) => { var _a; return String((_a = b.text) !== null && _a !== void 0 ? _a : ""); })
|
|
136
|
-
.join("");
|
|
137
|
-
if (reasoningDelta) {
|
|
138
|
-
yield ((_h = input.emit) === null || _h === void 0 ? void 0 : _h.call(input, {
|
|
139
|
-
type: "reasoning-delta",
|
|
140
|
-
delta: reasoningDelta,
|
|
141
|
-
}));
|
|
142
|
-
}
|
|
143
|
-
if (textDelta) {
|
|
144
|
-
fullResponse += textDelta;
|
|
145
|
-
bufferedTextDelta += textDelta;
|
|
146
|
-
if (bufferedTextDelta.includes(VEGA_LITE_FENCE_START) &&
|
|
147
|
-
!COMPLETE_VEGA_LITE_BLOCK_RE.test(bufferedTextDelta)) {
|
|
148
|
-
if (!isRenderingVegaLite) {
|
|
149
|
-
isRenderingVegaLite = true;
|
|
150
|
-
yield ((_j = input.emit) === null || _j === void 0 ? void 0 : _j.call(input, {
|
|
151
|
-
type: "rendering",
|
|
152
|
-
phase: "start",
|
|
153
|
-
label: "Rendering...",
|
|
154
|
-
}));
|
|
155
|
-
}
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
if (isRenderingVegaLite) {
|
|
159
|
-
isRenderingVegaLite = false;
|
|
160
|
-
yield ((_k = input.emit) === null || _k === void 0 ? void 0 : _k.call(input, {
|
|
161
|
-
type: "rendering",
|
|
162
|
-
phase: "end",
|
|
163
|
-
label: "Rendering...",
|
|
164
|
-
}));
|
|
165
|
-
}
|
|
166
|
-
const streamableLength = bufferedTextDelta.includes(VEGA_LITE_FENCE_START)
|
|
167
|
-
? bufferedTextDelta.length
|
|
168
|
-
: bufferedTextDelta.length - getPartialVegaLiteFenceStartLength(bufferedTextDelta);
|
|
169
|
-
if (!streamableLength) {
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
172
|
-
yield ((_l = input.emit) === null || _l === void 0 ? void 0 : _l.call(input, {
|
|
173
|
-
type: "text-delta",
|
|
174
|
-
delta: bufferedTextDelta.slice(0, streamableLength),
|
|
175
|
-
}));
|
|
176
|
-
bufferedTextDelta = bufferedTextDelta.slice(streamableLength);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
181
|
-
finally {
|
|
182
|
-
try {
|
|
183
|
-
if (!_p && !_a && (_b = _q.return)) yield _b.call(_q);
|
|
184
|
-
}
|
|
185
|
-
finally { if (e_1) throw e_1.error; }
|
|
186
|
-
}
|
|
187
|
-
if (isRenderingVegaLite) {
|
|
188
|
-
yield ((_m = input.emit) === null || _m === void 0 ? void 0 : _m.call(input, {
|
|
189
|
-
type: "rendering",
|
|
190
|
-
phase: "end",
|
|
191
|
-
label: "Rendering...",
|
|
192
|
-
}));
|
|
193
|
-
}
|
|
194
|
-
if (bufferedTextDelta) {
|
|
195
|
-
yield ((_o = input.emit) === null || _o === void 0 ? void 0 : _o.call(input, {
|
|
196
|
-
type: "text-delta",
|
|
197
|
-
delta: bufferedTextDelta,
|
|
198
|
-
}));
|
|
199
|
-
}
|
|
200
|
-
return {
|
|
201
|
-
text: fullResponse,
|
|
202
|
-
};
|
|
203
71
|
});
|
|
204
72
|
}
|
|
205
73
|
runAndPersistAgentResponse(input) {
|
|
206
74
|
return __awaiter(this, void 0, void 0, function* () {
|
|
207
75
|
var _a;
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
const previousUserMessages = yield this.serviceOptions.sessionStore.getPreviousUserMessages(input.sessionId);
|
|
211
|
-
const turnId = yield this.serviceOptions.sessionStore.createNewTurn(input.sessionId, input.prompt);
|
|
212
|
-
yield adminforth.resource(options.sessionResource.resourceId).update(input.sessionId, {
|
|
213
|
-
[options.sessionResource.createdAtField]: new Date().toISOString(),
|
|
214
|
-
});
|
|
215
|
-
const sequenceDebugCollector = createSequenceDebugCollector();
|
|
76
|
+
const preparedTurn = yield this.prepareTurn(input);
|
|
77
|
+
preparedTurn.observability.emit = input.emit;
|
|
216
78
|
let fullResponse = "";
|
|
217
79
|
let aborted = false;
|
|
218
80
|
let failed = false;
|
|
219
81
|
try {
|
|
220
|
-
const agentResponse = yield this.runAgentTurn(
|
|
221
|
-
prompt: input.prompt,
|
|
222
|
-
sessionId: input.sessionId,
|
|
223
|
-
turnId,
|
|
224
|
-
previousUserMessages,
|
|
225
|
-
modeName: input.modeName,
|
|
226
|
-
userTimeZone: input.userTimeZone,
|
|
227
|
-
currentPage: input.currentPage,
|
|
228
|
-
chatSurface: input.chatSurface,
|
|
229
|
-
adminPublicOrigin: input.adminPublicOrigin,
|
|
230
|
-
abortSignal: input.abortSignal,
|
|
231
|
-
adminUser: input.adminUser,
|
|
232
|
-
sequenceDebugCollector,
|
|
233
|
-
emit: input.emit,
|
|
234
|
-
});
|
|
82
|
+
const agentResponse = yield this.runAgentTurn(preparedTurn);
|
|
235
83
|
fullResponse = agentResponse.text;
|
|
236
84
|
}
|
|
237
85
|
catch (error) {
|
|
@@ -245,17 +93,15 @@ export class AgentTurnService {
|
|
|
245
93
|
logger.error(`${input.failureLogMessage}:\n${fullResponse}`);
|
|
246
94
|
}
|
|
247
95
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}
|
|
255
|
-
yield adminforth.resource(options.turnResource.resourceId).update(turnId, turnUpdates);
|
|
96
|
+
preparedTurn.observability.sequenceDebugSink.flush();
|
|
97
|
+
yield this.lifecycle.finish({
|
|
98
|
+
turnId: preparedTurn.turnId,
|
|
99
|
+
responseText: fullResponse,
|
|
100
|
+
debugHistory: preparedTurn.observability.sequenceDebugSink.getHistory(),
|
|
101
|
+
});
|
|
256
102
|
return {
|
|
257
103
|
text: fullResponse,
|
|
258
|
-
turnId,
|
|
104
|
+
turnId: preparedTurn.turnId,
|
|
259
105
|
aborted,
|
|
260
106
|
failed,
|
|
261
107
|
};
|
|
@@ -302,163 +148,4 @@ export class AgentTurnService {
|
|
|
302
148
|
return agentResponse;
|
|
303
149
|
});
|
|
304
150
|
}
|
|
305
|
-
handleSpeechTurn(input) {
|
|
306
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
307
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
308
|
-
let transcription;
|
|
309
|
-
try {
|
|
310
|
-
transcription = yield input.audioAdapter.transcribe({
|
|
311
|
-
buffer: input.audio.buffer,
|
|
312
|
-
filename: input.audio.filename,
|
|
313
|
-
mimeType: input.audio.mimeType,
|
|
314
|
-
language: "auto",
|
|
315
|
-
abortSignal: input.abortSignal,
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
catch (error) {
|
|
319
|
-
if (((_a = input.abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) || isAbortError(error)) {
|
|
320
|
-
logger.info("Agent speech transcription aborted by the client");
|
|
321
|
-
yield input.emit({ type: "finish" });
|
|
322
|
-
return null;
|
|
323
|
-
}
|
|
324
|
-
logger.error(`Agent speech transcription failed:\n${getErrorMessage(error)}`);
|
|
325
|
-
yield input.emit({
|
|
326
|
-
type: "error",
|
|
327
|
-
error: "Speech transcription failed. Check server logs for details.",
|
|
328
|
-
});
|
|
329
|
-
yield input.emit({ type: "finish" });
|
|
330
|
-
return null;
|
|
331
|
-
}
|
|
332
|
-
if ((_b = input.abortSignal) === null || _b === void 0 ? void 0 : _b.aborted) {
|
|
333
|
-
yield input.emit({ type: "finish" });
|
|
334
|
-
return null;
|
|
335
|
-
}
|
|
336
|
-
const prompt = transcription.text;
|
|
337
|
-
if (!prompt) {
|
|
338
|
-
yield input.emit({
|
|
339
|
-
type: "error",
|
|
340
|
-
error: "Speech transcription is empty",
|
|
341
|
-
});
|
|
342
|
-
yield input.emit({ type: "finish" });
|
|
343
|
-
return null;
|
|
344
|
-
}
|
|
345
|
-
yield input.emit({
|
|
346
|
-
type: "transcript",
|
|
347
|
-
text: transcription.text,
|
|
348
|
-
language: transcription.language,
|
|
349
|
-
});
|
|
350
|
-
const agentResponse = yield this.runAndPersistAgentResponse({
|
|
351
|
-
prompt,
|
|
352
|
-
sessionId: input.sessionId,
|
|
353
|
-
modeName: input.modeName,
|
|
354
|
-
userTimeZone: input.userTimeZone,
|
|
355
|
-
currentPage: input.currentPage,
|
|
356
|
-
chatSurface: input.chatSurface,
|
|
357
|
-
adminPublicOrigin: input.adminPublicOrigin,
|
|
358
|
-
abortSignal: input.abortSignal,
|
|
359
|
-
adminUser: input.adminUser,
|
|
360
|
-
emit: (event) => __awaiter(this, void 0, void 0, function* () {
|
|
361
|
-
if (event.type === "tool-call") {
|
|
362
|
-
yield input.emit(event);
|
|
363
|
-
}
|
|
364
|
-
}),
|
|
365
|
-
failureLogMessage: (_c = input.failureLogMessage) !== null && _c !== void 0 ? _c : "Agent speech response failed",
|
|
366
|
-
abortLogMessage: (_d = input.abortLogMessage) !== null && _d !== void 0 ? _d : "Agent speech response aborted by the client",
|
|
367
|
-
});
|
|
368
|
-
if (agentResponse.aborted) {
|
|
369
|
-
yield input.emit({ type: "finish" });
|
|
370
|
-
return agentResponse;
|
|
371
|
-
}
|
|
372
|
-
if (agentResponse.failed) {
|
|
373
|
-
yield input.emit({
|
|
374
|
-
type: "error",
|
|
375
|
-
error: agentResponse.text,
|
|
376
|
-
});
|
|
377
|
-
yield input.emit({ type: "finish" });
|
|
378
|
-
return agentResponse;
|
|
379
|
-
}
|
|
380
|
-
try {
|
|
381
|
-
yield input.emit({
|
|
382
|
-
type: "speech-response",
|
|
383
|
-
transcript: {
|
|
384
|
-
text: transcription.text,
|
|
385
|
-
language: transcription.language,
|
|
386
|
-
},
|
|
387
|
-
response: {
|
|
388
|
-
text: agentResponse.text,
|
|
389
|
-
},
|
|
390
|
-
sessionId: input.sessionId,
|
|
391
|
-
turnId: agentResponse.turnId,
|
|
392
|
-
});
|
|
393
|
-
const speech = yield input.audioAdapter.synthesize({
|
|
394
|
-
text: sanitizeSpeechText(agentResponse.text),
|
|
395
|
-
stream: true,
|
|
396
|
-
streamFormat: "audio",
|
|
397
|
-
format: "pcm",
|
|
398
|
-
abortSignal: input.abortSignal,
|
|
399
|
-
});
|
|
400
|
-
yield input.emit({
|
|
401
|
-
type: "audio-start",
|
|
402
|
-
mimeType: speech.mimeType,
|
|
403
|
-
format: speech.format,
|
|
404
|
-
sampleRate: 24000,
|
|
405
|
-
channelCount: 1,
|
|
406
|
-
bitsPerSample: 16,
|
|
407
|
-
});
|
|
408
|
-
const reader = speech.audioStream.getReader();
|
|
409
|
-
const cancelAudioStream = () => {
|
|
410
|
-
void reader.cancel().catch(() => undefined);
|
|
411
|
-
};
|
|
412
|
-
try {
|
|
413
|
-
(_e = input.abortSignal) === null || _e === void 0 ? void 0 : _e.addEventListener("abort", cancelAudioStream, { once: true });
|
|
414
|
-
while (true) {
|
|
415
|
-
if ((_f = input.abortSignal) === null || _f === void 0 ? void 0 : _f.aborted) {
|
|
416
|
-
yield reader.cancel().catch(() => undefined);
|
|
417
|
-
break;
|
|
418
|
-
}
|
|
419
|
-
const { value, done } = yield reader.read();
|
|
420
|
-
if (done) {
|
|
421
|
-
break;
|
|
422
|
-
}
|
|
423
|
-
if ((_g = input.abortSignal) === null || _g === void 0 ? void 0 : _g.aborted) {
|
|
424
|
-
break;
|
|
425
|
-
}
|
|
426
|
-
yield input.emit({
|
|
427
|
-
type: "audio-delta",
|
|
428
|
-
value,
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
finally {
|
|
433
|
-
(_h = input.abortSignal) === null || _h === void 0 ? void 0 : _h.removeEventListener("abort", cancelAudioStream);
|
|
434
|
-
reader.releaseLock();
|
|
435
|
-
}
|
|
436
|
-
yield input.emit({ type: "audio-done" });
|
|
437
|
-
yield input.emit({ type: "finish" });
|
|
438
|
-
return agentResponse;
|
|
439
|
-
}
|
|
440
|
-
catch (error) {
|
|
441
|
-
if (((_j = input.abortSignal) === null || _j === void 0 ? void 0 : _j.aborted) || isAbortError(error)) {
|
|
442
|
-
logger.info("Agent speech audio streaming aborted by the client");
|
|
443
|
-
}
|
|
444
|
-
else {
|
|
445
|
-
logger.error(`Agent speech audio streaming failed:\n${getErrorMessage(error)}`);
|
|
446
|
-
yield input.emit({
|
|
447
|
-
type: "error",
|
|
448
|
-
error: getErrorMessage(error),
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
yield input.emit({ type: "finish" });
|
|
452
|
-
return agentResponse;
|
|
453
|
-
}
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
function getPartialVegaLiteFenceStartLength(text) {
|
|
458
|
-
for (let length = Math.min(text.length, VEGA_LITE_FENCE_START.length - 1); length > 0; length -= 1) {
|
|
459
|
-
if (VEGA_LITE_FENCE_START.startsWith(text.slice(-length))) {
|
|
460
|
-
return length;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
return 0;
|
|
464
151
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -17,6 +17,16 @@ import { setupChatSurfaceEndpoints } from "./endpoints/chatSurfaces.js";
|
|
|
17
17
|
import { AgentSessionStore } from "./sessionStore.js";
|
|
18
18
|
import { ChatSurfaceService } from "./chatSurfaceService.js";
|
|
19
19
|
import { AgentTurnService } from "./agentTurnService.js";
|
|
20
|
+
import { AgentModelFactory } from "./agent/models/AgentModelFactory.js";
|
|
21
|
+
import { AgentModeResolver } from "./agent/models/AgentModeResolver.js";
|
|
22
|
+
import { AgentRuntime } from "./agent/runtime/AgentRuntime.js";
|
|
23
|
+
import { SpeechTurnService } from "./agent/speech/SpeechTurnService.js";
|
|
24
|
+
import { AgentToolProvider } from "./agent/tools/AgentToolProvider.js";
|
|
25
|
+
import { TurnContextBuilder } from "./agent/turn/TurnContextBuilder.js";
|
|
26
|
+
import { TurnLifecycleService } from "./agent/turn/TurnLifecycleService.js";
|
|
27
|
+
import { TurnPersistenceService } from "./agent/turn/TurnPersistenceService.js";
|
|
28
|
+
import { TurnPromptBuilder } from "./agent/turn/TurnPromptBuilder.js";
|
|
29
|
+
import { TurnStreamConsumer } from "./agent/turn/TurnStreamConsumer.js";
|
|
20
30
|
export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
21
31
|
parseBody(schema, body, response) {
|
|
22
32
|
const parsed = schema.safeParse(body !== null && body !== void 0 ? body : {});
|
|
@@ -43,19 +53,24 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
43
53
|
].filter((resourceId) => Boolean(resourceId));
|
|
44
54
|
}
|
|
45
55
|
constructor(options) {
|
|
56
|
+
var _a;
|
|
46
57
|
super(options, import.meta.url);
|
|
47
58
|
this.checkpointer = null;
|
|
48
59
|
this.options = options;
|
|
49
60
|
this.sessionStore = new AgentSessionStore(() => this.adminforth, this.options);
|
|
50
|
-
|
|
61
|
+
const toolProvider = new AgentToolProvider(() => this.adminforth, this.getInternalAgentResourceIds.bind(this));
|
|
62
|
+
const runtime = new AgentRuntime({
|
|
63
|
+
name: `adminforth-agent-${this.pluginInstanceId}`,
|
|
51
64
|
getAdminforth: () => this.adminforth,
|
|
52
|
-
getPluginInstanceId: () => this.pluginInstanceId,
|
|
53
|
-
options: this.options,
|
|
54
|
-
sessionStore: this.sessionStore,
|
|
55
65
|
getCheckpointer: this.getCheckpointer.bind(this),
|
|
56
|
-
|
|
57
|
-
getAgentSystemPrompt: () => this.agentSystemPromptPromise,
|
|
66
|
+
toolProvider,
|
|
58
67
|
});
|
|
68
|
+
const persistence = new TurnPersistenceService(() => this.adminforth, this.options);
|
|
69
|
+
this.agentTurnService = new AgentTurnService(new TurnLifecycleService(this.sessionStore, persistence), new TurnContextBuilder(() => this.adminforth), new AgentModeResolver(this.options), new AgentModelFactory((_a = this.options.maxTokens) !== null && _a !== void 0 ? _a : 1000), new TurnPromptBuilder({
|
|
70
|
+
getAdminforth: () => this.adminforth,
|
|
71
|
+
getAgentSystemPrompt: () => this.agentSystemPromptPromise,
|
|
72
|
+
}), runtime, new TurnStreamConsumer());
|
|
73
|
+
this.speechTurnService = new SpeechTurnService(this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService));
|
|
59
74
|
this.chatSurfaceService = new ChatSurfaceService(() => this.adminforth, this.options, this.sessionStore, this.agentTurnService.handleTurn.bind(this.agentTurnService), this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService));
|
|
60
75
|
this.agentSystemPromptPromise = Promise.resolve(appendCustomSystemPrompt(DEFAULT_AGENT_SYSTEM_PROMPT, this.options.systemPrompt));
|
|
61
76
|
this.shouldHaveSingleInstancePerWholeApp = () => false;
|
|
@@ -120,7 +135,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
120
135
|
options: this.options,
|
|
121
136
|
parseBody: this.parseBody.bind(this),
|
|
122
137
|
handleTurn: this.agentTurnService.handleTurn.bind(this.agentTurnService),
|
|
123
|
-
handleSpeechTurn: this.
|
|
138
|
+
handleSpeechTurn: this.speechTurnService.handle.bind(this.speechTurnService),
|
|
124
139
|
runAndPersistAgentResponse: this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService),
|
|
125
140
|
getSessionTurns: this.sessionStore.getSessionTurns.bind(this.sessionStore),
|
|
126
141
|
createNewTurn: this.sessionStore.createNewTurn.bind(this.sessionStore),
|
package/index.ts
CHANGED
|
@@ -18,6 +18,16 @@ import type { AgentEndpointsContext } from "./endpoints/context.js";
|
|
|
18
18
|
import { AgentSessionStore } from "./sessionStore.js";
|
|
19
19
|
import { ChatSurfaceService } from "./chatSurfaceService.js";
|
|
20
20
|
import { AgentTurnService } from "./agentTurnService.js";
|
|
21
|
+
import { AgentModelFactory } from "./agent/models/AgentModelFactory.js";
|
|
22
|
+
import { AgentModeResolver } from "./agent/models/AgentModeResolver.js";
|
|
23
|
+
import { AgentRuntime } from "./agent/runtime/AgentRuntime.js";
|
|
24
|
+
import { SpeechTurnService } from "./agent/speech/SpeechTurnService.js";
|
|
25
|
+
import { AgentToolProvider } from "./agent/tools/AgentToolProvider.js";
|
|
26
|
+
import { TurnContextBuilder } from "./agent/turn/TurnContextBuilder.js";
|
|
27
|
+
import { TurnLifecycleService } from "./agent/turn/TurnLifecycleService.js";
|
|
28
|
+
import { TurnPersistenceService } from "./agent/turn/TurnPersistenceService.js";
|
|
29
|
+
import { TurnPromptBuilder } from "./agent/turn/TurnPromptBuilder.js";
|
|
30
|
+
import { TurnStreamConsumer } from "./agent/turn/TurnStreamConsumer.js";
|
|
21
31
|
|
|
22
32
|
export type { AgentEvent, AgentEventEmitter } from "./agentEvents.js";
|
|
23
33
|
|
|
@@ -27,6 +37,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
27
37
|
private checkpointer: BaseCheckpointSaver | null = null;
|
|
28
38
|
private sessionStore: AgentSessionStore;
|
|
29
39
|
private agentTurnService: AgentTurnService;
|
|
40
|
+
private speechTurnService: SpeechTurnService;
|
|
30
41
|
private chatSurfaceService: ChatSurfaceService;
|
|
31
42
|
private parseBody<T>(
|
|
32
43
|
schema: z.ZodType<T>,
|
|
@@ -62,15 +73,32 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
62
73
|
super(options, import.meta.url);
|
|
63
74
|
this.options = options;
|
|
64
75
|
this.sessionStore = new AgentSessionStore(() => this.adminforth, this.options);
|
|
65
|
-
|
|
76
|
+
const toolProvider = new AgentToolProvider(
|
|
77
|
+
() => this.adminforth,
|
|
78
|
+
this.getInternalAgentResourceIds.bind(this),
|
|
79
|
+
);
|
|
80
|
+
const runtime = new AgentRuntime({
|
|
81
|
+
name: `adminforth-agent-${this.pluginInstanceId}`,
|
|
66
82
|
getAdminforth: () => this.adminforth,
|
|
67
|
-
getPluginInstanceId: () => this.pluginInstanceId,
|
|
68
|
-
options: this.options,
|
|
69
|
-
sessionStore: this.sessionStore,
|
|
70
83
|
getCheckpointer: this.getCheckpointer.bind(this),
|
|
71
|
-
|
|
72
|
-
getAgentSystemPrompt: () => this.agentSystemPromptPromise,
|
|
84
|
+
toolProvider,
|
|
73
85
|
});
|
|
86
|
+
const persistence = new TurnPersistenceService(() => this.adminforth, this.options);
|
|
87
|
+
this.agentTurnService = new AgentTurnService(
|
|
88
|
+
new TurnLifecycleService(this.sessionStore, persistence),
|
|
89
|
+
new TurnContextBuilder(() => this.adminforth),
|
|
90
|
+
new AgentModeResolver(this.options),
|
|
91
|
+
new AgentModelFactory(this.options.maxTokens ?? 1000),
|
|
92
|
+
new TurnPromptBuilder({
|
|
93
|
+
getAdminforth: () => this.adminforth,
|
|
94
|
+
getAgentSystemPrompt: () => this.agentSystemPromptPromise,
|
|
95
|
+
}),
|
|
96
|
+
runtime,
|
|
97
|
+
new TurnStreamConsumer(),
|
|
98
|
+
);
|
|
99
|
+
this.speechTurnService = new SpeechTurnService(
|
|
100
|
+
this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService),
|
|
101
|
+
);
|
|
74
102
|
this.chatSurfaceService = new ChatSurfaceService(
|
|
75
103
|
() => this.adminforth,
|
|
76
104
|
this.options,
|
|
@@ -146,7 +174,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
146
174
|
options: this.options,
|
|
147
175
|
parseBody: this.parseBody.bind(this),
|
|
148
176
|
handleTurn: this.agentTurnService.handleTurn.bind(this.agentTurnService),
|
|
149
|
-
handleSpeechTurn: this.
|
|
177
|
+
handleSpeechTurn: this.speechTurnService.handle.bind(this.speechTurnService),
|
|
150
178
|
runAndPersistAgentResponse: this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService),
|
|
151
179
|
getSessionTurns: this.sessionStore.getSessionTurns.bind(this.sessionStore),
|
|
152
180
|
createNewTurn: this.sessionStore.createNewTurn.bind(this.sessionStore),
|