@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.
Files changed (54) hide show
  1. package/agent/middleware/apiBasedTools.ts +13 -3
  2. package/agent/models/AgentModeResolver.ts +9 -0
  3. package/agent/models/AgentModelFactory.ts +28 -0
  4. package/agent/runtime/AgentContext.ts +30 -0
  5. package/agent/runtime/AgentRuntime.ts +68 -0
  6. package/agent/simpleAgent.ts +2 -129
  7. package/agent/speech/SpeechTurnService.ts +179 -0
  8. package/agent/tools/AgentToolProvider.ts +28 -0
  9. package/agent/tools/navigateUser.ts +2 -2
  10. package/agent/turn/TurnContextBuilder.ts +36 -0
  11. package/agent/turn/TurnLifecycleService.ts +29 -0
  12. package/agent/turn/TurnPersistenceService.ts +33 -0
  13. package/agent/turn/TurnPromptBuilder.ts +51 -0
  14. package/agent/turn/TurnStreamConsumer.ts +61 -0
  15. package/agent/turn/VegaLiteStreamBuffer.ts +90 -0
  16. package/agent/turn/turnTypes.ts +92 -0
  17. package/agentTurnService.ts +88 -461
  18. package/build.log +1 -1
  19. package/dist/agent/middleware/apiBasedTools.js +9 -2
  20. package/dist/agent/models/AgentModeResolver.d.ts +9 -0
  21. package/dist/agent/models/AgentModeResolver.js +9 -0
  22. package/dist/agent/models/AgentModelFactory.d.ts +7 -0
  23. package/dist/agent/models/AgentModelFactory.js +36 -0
  24. package/dist/agent/runtime/AgentContext.d.ts +28 -0
  25. package/dist/agent/runtime/AgentContext.js +17 -0
  26. package/dist/agent/runtime/AgentRuntime.d.ts +15 -0
  27. package/dist/agent/runtime/AgentRuntime.js +57 -0
  28. package/dist/agent/simpleAgent.d.ts +15 -45
  29. package/dist/agent/simpleAgent.js +1 -67
  30. package/dist/agent/speech/SpeechTurnService.d.ts +6 -0
  31. package/dist/agent/speech/SpeechTurnService.js +168 -0
  32. package/dist/agent/tools/AgentToolProvider.d.ts +9 -0
  33. package/dist/agent/tools/AgentToolProvider.js +27 -0
  34. package/dist/agent/tools/navigateUser.js +1 -1
  35. package/dist/agent/turn/TurnContextBuilder.d.ts +14 -0
  36. package/dist/agent/turn/TurnContextBuilder.js +31 -0
  37. package/dist/agent/turn/TurnLifecycleService.d.ts +17 -0
  38. package/dist/agent/turn/TurnLifecycleService.js +31 -0
  39. package/dist/agent/turn/TurnPersistenceService.d.ts +13 -0
  40. package/dist/agent/turn/TurnPersistenceService.js +35 -0
  41. package/dist/agent/turn/TurnPromptBuilder.d.ts +19 -0
  42. package/dist/agent/turn/TurnPromptBuilder.js +43 -0
  43. package/dist/agent/turn/TurnStreamConsumer.d.ts +10 -0
  44. package/dist/agent/turn/TurnStreamConsumer.js +78 -0
  45. package/dist/agent/turn/VegaLiteStreamBuffer.d.ts +7 -0
  46. package/dist/agent/turn/VegaLiteStreamBuffer.js +87 -0
  47. package/dist/agent/turn/turnTypes.d.ts +81 -0
  48. package/dist/agent/turn/turnTypes.js +1 -0
  49. package/dist/agentTurnService.d.ts +20 -69
  50. package/dist/agentTurnService.js +60 -373
  51. package/dist/index.d.ts +1 -0
  52. package/dist/index.js +22 -7
  53. package/index.ts +35 -7
  54. package/package.json +1 -1
@@ -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 { detectUserLanguage } from "./agent/languageDetect.js";
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(serviceOptions) {
31
- this.serviceOptions = serviceOptions;
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
- var _a, e_1, _b, _c;
36
- var _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
37
- const adminforth = this.serviceOptions.getAdminforth();
38
- const options = this.serviceOptions.options;
39
- let fullResponse = "";
40
- let bufferedTextDelta = "";
41
- let isRenderingVegaLite = false;
42
- const maxTokens = (_d = options.maxTokens) !== null && _d !== void 0 ? _d : 1000;
43
- const selectedMode = (_e = options.modes.find((mode) => mode.name === input.modeName)) !== null && _e !== void 0 ? _e : options.modes[0];
44
- const [primaryModelSpec, summaryModelSpec] = yield Promise.all([
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 model = primaryModelSpec.model;
57
- const summaryModel = summaryModelSpec.model;
58
- const modelMiddleware = primaryModelSpec.middleware;
59
- const userLanguage = yield detectUserLanguage(selectedMode.completionAdapter, input.prompt, input.previousUserMessages)
60
- .catch((error) => {
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
- const systemPrompt = buildAgentTurnSystemPrompt({
69
- agentSystemPrompt: yield this.serviceOptions.getAgentSystemPrompt(),
70
- adminUser: input.adminUser,
71
- usernameField: adminforth.config.auth.usernameField,
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 adminforth = this.serviceOptions.getAdminforth();
209
- const options = this.serviceOptions.options;
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
- sequenceDebugCollector.flush();
249
- const turnUpdates = {
250
- [options.turnResource.responseField]: fullResponse,
251
- };
252
- if (options.turnResource.debugField) {
253
- turnUpdates[options.turnResource.debugField] = sequenceDebugCollector.getHistory();
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
@@ -8,6 +8,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
8
8
  private checkpointer;
9
9
  private sessionStore;
10
10
  private agentTurnService;
11
+ private speechTurnService;
11
12
  private chatSurfaceService;
12
13
  private parseBody;
13
14
  private getCheckpointer;
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
- this.agentTurnService = new AgentTurnService({
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
- getInternalAgentResourceIds: this.getInternalAgentResourceIds.bind(this),
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.agentTurnService.handleSpeechTurn.bind(this.agentTurnService),
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
- this.agentTurnService = new AgentTurnService({
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
- getInternalAgentResourceIds: this.getInternalAgentResourceIds.bind(this),
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.agentTurnService.handleSpeechTurn.bind(this.agentTurnService),
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),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/agent",
3
- "version": "1.50.1",
3
+ "version": "1.51.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",