@adminforth/agent 1.44.2 → 1.45.1
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/agentTurnService.ts +526 -0
- package/build.log +3 -2
- package/chatSurfaceService.ts +189 -0
- package/custom/ChatSurfaceSettings.vue +125 -0
- package/custom/incremark_code_renderers/incremarkRenderer.ts +5 -5
- package/dist/agentTurnService.d.ts +70 -0
- package/dist/agentTurnService.js +453 -0
- package/dist/chatSurfaceService.d.ts +29 -0
- package/dist/chatSurfaceService.js +142 -0
- package/dist/custom/ChatSurfaceSettings.vue +125 -0
- package/dist/custom/incremark_code_renderers/incremarkRenderer.ts +5 -5
- package/dist/endpoints/chatSurfaces.d.ts +3 -0
- package/dist/endpoints/chatSurfaces.js +91 -0
- package/dist/endpoints/context.d.ts +30 -0
- package/dist/endpoints/context.js +1 -0
- package/dist/endpoints/core.d.ts +3 -0
- package/dist/endpoints/core.js +106 -0
- package/dist/endpoints/sessions.d.ts +3 -0
- package/dist/endpoints/sessions.js +177 -0
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +9 -0
- package/dist/index.d.ts +5 -42
- package/dist/index.js +50 -808
- package/dist/sessionStore.d.ts +19 -0
- package/dist/sessionStore.js +83 -0
- package/dist/types.d.ts +4 -0
- package/endpoints/chatSurfaces.ts +93 -0
- package/endpoints/context.ts +66 -0
- package/endpoints/core.ts +113 -0
- package/endpoints/sessions.ts +183 -0
- package/errors.ts +10 -0
- package/index.ts +60 -907
- package/package.json +2 -2
- package/sessionStore.ts +94 -0
- package/types.ts +5 -0
- package/agentResponseEvents.ts +0 -1
- package/dist/agentResponseEvents.d.ts +0 -1
- package/dist/agentResponseEvents.js +0 -1
package/dist/index.js
CHANGED
|
@@ -7,64 +7,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
|
|
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
|
-
import { AdminForthPlugin, logger, Filters, Sorts } from "adminforth";
|
|
18
|
-
import { randomUUID } from 'crypto';
|
|
19
|
-
import { HumanMessage, SystemMessage } from "langchain";
|
|
10
|
+
import { AdminForthPlugin } from "adminforth";
|
|
20
11
|
import { MemorySaver } from "@langchain/langgraph";
|
|
21
|
-
import { z } from "zod";
|
|
22
|
-
import { createAgentChatModel, callAgent } from "./agent/simpleAgent.js";
|
|
23
12
|
import { AdminForthCheckpointSaver } from "./agent/checkpointer.js";
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
message: z.string(),
|
|
32
|
-
sessionId: z.string(),
|
|
33
|
-
mode: z.string().nullish(),
|
|
34
|
-
timeZone: z.string().optional(),
|
|
35
|
-
currentPage: z.custom().optional(),
|
|
36
|
-
}).strict();
|
|
37
|
-
const agentSpeechResponseBodySchema = agentResponseBodySchema.omit({ message: true });
|
|
38
|
-
const addSystemMessageBodySchema = z.object({
|
|
39
|
-
sessionId: z.string(),
|
|
40
|
-
systemMessage: z.string(),
|
|
41
|
-
}).strict();
|
|
42
|
-
const getSessionsBodySchema = z.object({
|
|
43
|
-
limit: z.number().optional(),
|
|
44
|
-
}).strict();
|
|
45
|
-
const sessionIdBodySchema = z.object({
|
|
46
|
-
sessionId: z.string(),
|
|
47
|
-
}).strict();
|
|
48
|
-
const createSessionBodySchema = z.object({
|
|
49
|
-
triggerMessage: z.string().optional(),
|
|
50
|
-
}).strict();
|
|
51
|
-
const VEGA_LITE_FENCE_START = "```vega-lite";
|
|
52
|
-
const COMPLETE_VEGA_LITE_BLOCK_RE = /```vega-lite[\s\S]*?```/;
|
|
53
|
-
function isAbortError(error) {
|
|
54
|
-
return (error instanceof DOMException && error.name === "AbortError") || (typeof error === "object" &&
|
|
55
|
-
error !== null &&
|
|
56
|
-
"name" in error &&
|
|
57
|
-
(error.name === "AbortError" || error.name === "APIUserAbortError"));
|
|
58
|
-
}
|
|
59
|
-
function getErrorMessage(error) {
|
|
60
|
-
return error instanceof Error ? error.message : String(error);
|
|
61
|
-
}
|
|
62
|
-
function requireAdminUser(adminUser) {
|
|
63
|
-
if (!adminUser) {
|
|
64
|
-
throw new Error("AdminForth Agent endpoint requires an authenticated admin user");
|
|
65
|
-
}
|
|
66
|
-
return adminUser;
|
|
67
|
-
}
|
|
13
|
+
import { appendCustomSystemPrompt, buildAgentSystemPrompt, DEFAULT_AGENT_SYSTEM_PROMPT } from "./agent/systemPrompt.js";
|
|
14
|
+
import { setupCoreEndpoints } from "./endpoints/core.js";
|
|
15
|
+
import { setupSessionEndpoints } from "./endpoints/sessions.js";
|
|
16
|
+
import { setupChatSurfaceEndpoints } from "./endpoints/chatSurfaces.js";
|
|
17
|
+
import { AgentSessionStore } from "./sessionStore.js";
|
|
18
|
+
import { ChatSurfaceService } from "./chatSurfaceService.js";
|
|
19
|
+
import { AgentTurnService } from "./agentTurnService.js";
|
|
68
20
|
export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
69
21
|
parseBody(schema, body, response) {
|
|
70
22
|
const parsed = schema.safeParse(body !== null && body !== void 0 ? body : {});
|
|
@@ -74,57 +26,6 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
74
26
|
}
|
|
75
27
|
return parsed.data;
|
|
76
28
|
}
|
|
77
|
-
createNewTurn(sessionId, prompt, response) {
|
|
78
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
79
|
-
const turnId = randomUUID();
|
|
80
|
-
const turnRecord = {
|
|
81
|
-
[this.options.turnResource.idField]: turnId,
|
|
82
|
-
[this.options.turnResource.sessionIdField]: sessionId,
|
|
83
|
-
[this.options.turnResource.promptField]: prompt,
|
|
84
|
-
[this.options.turnResource.responseField]: response || "not_finished",
|
|
85
|
-
};
|
|
86
|
-
const newTurn = yield this.adminforth.resource(this.options.turnResource.resourceId).create(turnRecord);
|
|
87
|
-
return newTurn.createdRecord[this.options.turnResource.idField];
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
getSessionTurns(sessionId) {
|
|
91
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
-
const turns = yield this.adminforth.resource(this.options.turnResource.resourceId).list([Filters.EQ(this.options.turnResource.sessionIdField, sessionId)], undefined, undefined, [Sorts.ASC(this.options.turnResource.createdAtField)]);
|
|
93
|
-
return turns.map(turn => ({
|
|
94
|
-
prompt: turn[this.options.turnResource.promptField],
|
|
95
|
-
response: turn[this.options.turnResource.responseField],
|
|
96
|
-
}));
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
getPreviousUserMessages(sessionId) {
|
|
100
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
-
const turns = yield this.adminforth.resource(this.options.turnResource.resourceId).list([Filters.EQ(this.options.turnResource.sessionIdField, sessionId)], 2, undefined, [Sorts.DESC(this.options.turnResource.createdAtField)]);
|
|
102
|
-
return turns
|
|
103
|
-
.reverse()
|
|
104
|
-
.map((turn) => ({
|
|
105
|
-
text: turn[this.options.turnResource.promptField],
|
|
106
|
-
}));
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
getChatSurfaceSessionId(incoming) {
|
|
110
|
-
return `${incoming.surface}:${incoming.externalConversationId}`;
|
|
111
|
-
}
|
|
112
|
-
getOrCreateChatSurfaceSession(incoming, adminUser) {
|
|
113
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
114
|
-
const sessionId = this.getChatSurfaceSessionId(incoming);
|
|
115
|
-
const sessionResource = this.adminforth.resource(this.options.sessionResource.resourceId);
|
|
116
|
-
const session = yield sessionResource.get([Filters.EQ(this.options.sessionResource.idField, sessionId)]);
|
|
117
|
-
if (session) {
|
|
118
|
-
return sessionId;
|
|
119
|
-
}
|
|
120
|
-
yield sessionResource.create({
|
|
121
|
-
[this.options.sessionResource.idField]: sessionId,
|
|
122
|
-
[this.options.sessionResource.titleField]: incoming.prompt.slice(0, 40) || "New Session",
|
|
123
|
-
[this.options.sessionResource.askerIdField]: adminUser.pk,
|
|
124
|
-
});
|
|
125
|
-
return sessionId;
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
29
|
getCheckpointer() {
|
|
129
30
|
if (this.checkpointer)
|
|
130
31
|
return this.checkpointer;
|
|
@@ -144,7 +45,19 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
144
45
|
constructor(options) {
|
|
145
46
|
super(options, import.meta.url);
|
|
146
47
|
this.checkpointer = null;
|
|
48
|
+
this.chatSurfaceSettingsPageRegistered = false;
|
|
147
49
|
this.options = options;
|
|
50
|
+
this.sessionStore = new AgentSessionStore(() => this.adminforth, this.options);
|
|
51
|
+
this.agentTurnService = new AgentTurnService({
|
|
52
|
+
getAdminforth: () => this.adminforth,
|
|
53
|
+
getPluginInstanceId: () => this.pluginInstanceId,
|
|
54
|
+
options: this.options,
|
|
55
|
+
sessionStore: this.sessionStore,
|
|
56
|
+
getCheckpointer: this.getCheckpointer.bind(this),
|
|
57
|
+
getInternalAgentResourceIds: this.getInternalAgentResourceIds.bind(this),
|
|
58
|
+
getAgentSystemPrompt: () => this.agentSystemPromptPromise,
|
|
59
|
+
});
|
|
60
|
+
this.chatSurfaceService = new ChatSurfaceService(() => this.adminforth, this.options, this.sessionStore, this.agentTurnService.handleTurn.bind(this.agentTurnService));
|
|
148
61
|
this.agentSystemPromptPromise = Promise.resolve(appendCustomSystemPrompt(DEFAULT_AGENT_SYSTEM_PROMPT, this.options.systemPrompt));
|
|
149
62
|
this.shouldHaveSingleInstancePerWholeApp = () => false;
|
|
150
63
|
}
|
|
@@ -171,6 +84,19 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
171
84
|
hasAudioAdapter: Boolean(this.options.audioAdapter),
|
|
172
85
|
}
|
|
173
86
|
});
|
|
87
|
+
if (this.chatSurfaceService.getConnectActionAdapters().length && !this.chatSurfaceSettingsPageRegistered) {
|
|
88
|
+
if (!this.adminforth.config.auth.userMenuSettingsPages) {
|
|
89
|
+
this.adminforth.config.auth.userMenuSettingsPages = [];
|
|
90
|
+
}
|
|
91
|
+
this.adminforth.config.auth.userMenuSettingsPages.push({
|
|
92
|
+
icon: "flowbite:link-outline",
|
|
93
|
+
pageLabel: "Chat Surfaces",
|
|
94
|
+
slug: "chat-surfaces",
|
|
95
|
+
component: this.componentPath("ChatSurfaceSettings.vue"),
|
|
96
|
+
isVisible: () => true,
|
|
97
|
+
});
|
|
98
|
+
this.chatSurfaceSettingsPageRegistered = true;
|
|
99
|
+
}
|
|
174
100
|
if (!this.adminforth.config.customization.customHeadItems) {
|
|
175
101
|
this.adminforth.config.customization.customHeadItems = [];
|
|
176
102
|
}
|
|
@@ -202,707 +128,23 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
202
128
|
instanceUniqueRepresentation(pluginOptions) {
|
|
203
129
|
return `single`;
|
|
204
130
|
}
|
|
205
|
-
runAgentTurn(input) {
|
|
206
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
207
|
-
var _a, e_1, _b, _c;
|
|
208
|
-
var _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
209
|
-
let fullResponse = "";
|
|
210
|
-
let bufferedTextDelta = "";
|
|
211
|
-
let isRenderingVegaLite = false;
|
|
212
|
-
const maxTokens = (_d = this.options.maxTokens) !== null && _d !== void 0 ? _d : 1000;
|
|
213
|
-
const selectedMode = (_e = this.options.modes.find((mode) => mode.name === input.modeName)) !== null && _e !== void 0 ? _e : this.options.modes[0];
|
|
214
|
-
const [primaryModelSpec, summaryModelSpec] = yield Promise.all([
|
|
215
|
-
createAgentChatModel({
|
|
216
|
-
adapter: selectedMode.completionAdapter,
|
|
217
|
-
maxTokens,
|
|
218
|
-
purpose: "primary",
|
|
219
|
-
}),
|
|
220
|
-
createAgentChatModel({
|
|
221
|
-
adapter: selectedMode.completionAdapter,
|
|
222
|
-
maxTokens,
|
|
223
|
-
purpose: "summary",
|
|
224
|
-
}),
|
|
225
|
-
]);
|
|
226
|
-
const model = primaryModelSpec.model;
|
|
227
|
-
const summaryModel = summaryModelSpec.model;
|
|
228
|
-
const modelMiddleware = primaryModelSpec.middleware;
|
|
229
|
-
const userLanguage = yield detectUserLanguage(selectedMode.completionAdapter, input.prompt, input.previousUserMessages)
|
|
230
|
-
.catch((error) => {
|
|
231
|
-
var _a;
|
|
232
|
-
if (((_a = input.abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) || isAbortError(error)) {
|
|
233
|
-
throw error;
|
|
234
|
-
}
|
|
235
|
-
logger.warn(`Failed to detect user language: ${getErrorMessage(error)}`);
|
|
236
|
-
return null;
|
|
237
|
-
});
|
|
238
|
-
const systemPrompt = buildAgentTurnSystemPrompt({
|
|
239
|
-
agentSystemPrompt: yield this.agentSystemPromptPromise,
|
|
240
|
-
adminUser: input.adminUser,
|
|
241
|
-
usernameField: this.adminforth.config.auth.usernameField,
|
|
242
|
-
userLanguage,
|
|
243
|
-
});
|
|
244
|
-
const apiBasedTools = buildApiBasedTools(this.adminforth, this.getInternalAgentResourceIds());
|
|
245
|
-
const stream = yield callAgent({
|
|
246
|
-
name: `adminforth-agent-${this.pluginInstanceId}`,
|
|
247
|
-
model,
|
|
248
|
-
summaryModel,
|
|
249
|
-
modelMiddleware,
|
|
250
|
-
checkpointer: this.getCheckpointer(),
|
|
251
|
-
messages: [
|
|
252
|
-
new SystemMessage(systemPrompt),
|
|
253
|
-
new HumanMessage(input.prompt),
|
|
254
|
-
],
|
|
255
|
-
adminUser: input.adminUser,
|
|
256
|
-
adminforth: this.adminforth,
|
|
257
|
-
apiBasedTools,
|
|
258
|
-
customComponentsDir: (_f = this.adminforth.config.customization.customComponentsDir) !== null && _f !== void 0 ? _f : "custom",
|
|
259
|
-
sessionId: input.sessionId,
|
|
260
|
-
turnId: input.turnId,
|
|
261
|
-
currentPage: input.currentPage,
|
|
262
|
-
userTimeZone: input.userTimeZone,
|
|
263
|
-
abortSignal: input.abortSignal,
|
|
264
|
-
emitToolCallEvent: (event) => {
|
|
265
|
-
var _a;
|
|
266
|
-
input.sequenceDebugCollector.handleToolCallEvent(event);
|
|
267
|
-
void ((_a = input.emit) === null || _a === void 0 ? void 0 : _a.call(input, {
|
|
268
|
-
type: "tool-call",
|
|
269
|
-
data: event,
|
|
270
|
-
}));
|
|
271
|
-
},
|
|
272
|
-
sequenceDebugSink: input.sequenceDebugCollector,
|
|
273
|
-
});
|
|
274
|
-
try {
|
|
275
|
-
for (var _p = true, _q = __asyncValues(stream), _r; _r = yield _q.next(), _a = _r.done, !_a; _p = true) {
|
|
276
|
-
_c = _r.value;
|
|
277
|
-
_p = false;
|
|
278
|
-
const rawChunk = _c;
|
|
279
|
-
if ((_g = input.abortSignal) === null || _g === void 0 ? void 0 : _g.aborted) {
|
|
280
|
-
throw new DOMException("This operation was aborted", "AbortError");
|
|
281
|
-
}
|
|
282
|
-
const [token, metadata] = rawChunk;
|
|
283
|
-
const nodeName = typeof (metadata === null || metadata === void 0 ? void 0 : metadata.langgraph_node) === "string"
|
|
284
|
-
? metadata.langgraph_node
|
|
285
|
-
: "";
|
|
286
|
-
if (nodeName && !["model", "model_request"].includes(nodeName)) {
|
|
287
|
-
continue;
|
|
288
|
-
}
|
|
289
|
-
const blocks = Array.isArray(token === null || token === void 0 ? void 0 : token.contentBlocks)
|
|
290
|
-
? token.contentBlocks
|
|
291
|
-
: Array.isArray(token === null || token === void 0 ? void 0 : token.content)
|
|
292
|
-
? token.content
|
|
293
|
-
: [];
|
|
294
|
-
const reasoningDelta = blocks
|
|
295
|
-
.filter((b) => (b === null || b === void 0 ? void 0 : b.type) === "reasoning")
|
|
296
|
-
.map((b) => { var _a; return String((_a = b.reasoning) !== null && _a !== void 0 ? _a : ""); })
|
|
297
|
-
.join("");
|
|
298
|
-
const textDelta = blocks
|
|
299
|
-
.filter((b) => (b === null || b === void 0 ? void 0 : b.type) === "text")
|
|
300
|
-
.map((b) => { var _a; return String((_a = b.text) !== null && _a !== void 0 ? _a : ""); })
|
|
301
|
-
.join("");
|
|
302
|
-
if (reasoningDelta) {
|
|
303
|
-
yield ((_h = input.emit) === null || _h === void 0 ? void 0 : _h.call(input, {
|
|
304
|
-
type: "reasoning-delta",
|
|
305
|
-
delta: reasoningDelta,
|
|
306
|
-
}));
|
|
307
|
-
}
|
|
308
|
-
if (textDelta) {
|
|
309
|
-
fullResponse += textDelta;
|
|
310
|
-
bufferedTextDelta += textDelta;
|
|
311
|
-
if (bufferedTextDelta.includes(VEGA_LITE_FENCE_START) &&
|
|
312
|
-
!COMPLETE_VEGA_LITE_BLOCK_RE.test(bufferedTextDelta)) {
|
|
313
|
-
if (!isRenderingVegaLite) {
|
|
314
|
-
isRenderingVegaLite = true;
|
|
315
|
-
yield ((_j = input.emit) === null || _j === void 0 ? void 0 : _j.call(input, {
|
|
316
|
-
type: "rendering",
|
|
317
|
-
phase: "start",
|
|
318
|
-
label: "Rendering...",
|
|
319
|
-
}));
|
|
320
|
-
}
|
|
321
|
-
continue;
|
|
322
|
-
}
|
|
323
|
-
if (isRenderingVegaLite) {
|
|
324
|
-
isRenderingVegaLite = false;
|
|
325
|
-
yield ((_k = input.emit) === null || _k === void 0 ? void 0 : _k.call(input, {
|
|
326
|
-
type: "rendering",
|
|
327
|
-
phase: "end",
|
|
328
|
-
label: "Rendering...",
|
|
329
|
-
}));
|
|
330
|
-
}
|
|
331
|
-
const streamableLength = bufferedTextDelta.includes(VEGA_LITE_FENCE_START)
|
|
332
|
-
? bufferedTextDelta.length
|
|
333
|
-
: bufferedTextDelta.length - getPartialVegaLiteFenceStartLength(bufferedTextDelta);
|
|
334
|
-
if (!streamableLength) {
|
|
335
|
-
continue;
|
|
336
|
-
}
|
|
337
|
-
yield ((_l = input.emit) === null || _l === void 0 ? void 0 : _l.call(input, {
|
|
338
|
-
type: "text-delta",
|
|
339
|
-
delta: bufferedTextDelta.slice(0, streamableLength),
|
|
340
|
-
}));
|
|
341
|
-
bufferedTextDelta = bufferedTextDelta.slice(streamableLength);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
346
|
-
finally {
|
|
347
|
-
try {
|
|
348
|
-
if (!_p && !_a && (_b = _q.return)) yield _b.call(_q);
|
|
349
|
-
}
|
|
350
|
-
finally { if (e_1) throw e_1.error; }
|
|
351
|
-
}
|
|
352
|
-
if (isRenderingVegaLite) {
|
|
353
|
-
yield ((_m = input.emit) === null || _m === void 0 ? void 0 : _m.call(input, {
|
|
354
|
-
type: "rendering",
|
|
355
|
-
phase: "end",
|
|
356
|
-
label: "Rendering...",
|
|
357
|
-
}));
|
|
358
|
-
}
|
|
359
|
-
if (bufferedTextDelta) {
|
|
360
|
-
yield ((_o = input.emit) === null || _o === void 0 ? void 0 : _o.call(input, {
|
|
361
|
-
type: "text-delta",
|
|
362
|
-
delta: bufferedTextDelta,
|
|
363
|
-
}));
|
|
364
|
-
}
|
|
365
|
-
return {
|
|
366
|
-
text: fullResponse,
|
|
367
|
-
};
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
runAndPersistAgentResponse(input) {
|
|
371
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
372
|
-
var _a;
|
|
373
|
-
const previousUserMessages = yield this.getPreviousUserMessages(input.sessionId);
|
|
374
|
-
const turnId = yield this.createNewTurn(input.sessionId, input.prompt);
|
|
375
|
-
yield this.adminforth.resource(this.options.sessionResource.resourceId).update(input.sessionId, {
|
|
376
|
-
[this.options.sessionResource.createdAtField]: new Date().toISOString(),
|
|
377
|
-
});
|
|
378
|
-
const sequenceDebugCollector = createSequenceDebugCollector();
|
|
379
|
-
let fullResponse = "";
|
|
380
|
-
let aborted = false;
|
|
381
|
-
let failed = false;
|
|
382
|
-
try {
|
|
383
|
-
const agentResponse = yield this.runAgentTurn({
|
|
384
|
-
prompt: input.prompt,
|
|
385
|
-
sessionId: input.sessionId,
|
|
386
|
-
turnId,
|
|
387
|
-
previousUserMessages,
|
|
388
|
-
modeName: input.modeName,
|
|
389
|
-
userTimeZone: input.userTimeZone,
|
|
390
|
-
currentPage: input.currentPage,
|
|
391
|
-
abortSignal: input.abortSignal,
|
|
392
|
-
adminUser: input.adminUser,
|
|
393
|
-
sequenceDebugCollector,
|
|
394
|
-
emit: input.emit,
|
|
395
|
-
});
|
|
396
|
-
fullResponse = agentResponse.text;
|
|
397
|
-
}
|
|
398
|
-
catch (error) {
|
|
399
|
-
if (((_a = input.abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) || isAbortError(error)) {
|
|
400
|
-
aborted = true;
|
|
401
|
-
logger.info(input.abortLogMessage);
|
|
402
|
-
}
|
|
403
|
-
else {
|
|
404
|
-
failed = true;
|
|
405
|
-
fullResponse = getErrorMessage(error);
|
|
406
|
-
logger.error(`${input.failureLogMessage}:\n${fullResponse}`);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
sequenceDebugCollector.flush();
|
|
410
|
-
const turnUpdates = {
|
|
411
|
-
[this.options.turnResource.responseField]: fullResponse,
|
|
412
|
-
};
|
|
413
|
-
if (this.options.turnResource.debugField) {
|
|
414
|
-
turnUpdates[this.options.turnResource.debugField] = sequenceDebugCollector.getHistory();
|
|
415
|
-
}
|
|
416
|
-
yield this.adminforth.resource(this.options.turnResource.resourceId).update(turnId, turnUpdates);
|
|
417
|
-
return {
|
|
418
|
-
text: fullResponse,
|
|
419
|
-
turnId,
|
|
420
|
-
aborted,
|
|
421
|
-
failed,
|
|
422
|
-
};
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
handleTurn(input) {
|
|
426
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
427
|
-
var _a, _b;
|
|
428
|
-
yield input.emit({
|
|
429
|
-
type: "turn-started",
|
|
430
|
-
messageId: randomUUID(),
|
|
431
|
-
});
|
|
432
|
-
const agentResponse = yield this.runAndPersistAgentResponse({
|
|
433
|
-
prompt: input.prompt,
|
|
434
|
-
sessionId: input.sessionId,
|
|
435
|
-
modeName: input.modeName,
|
|
436
|
-
userTimeZone: input.userTimeZone,
|
|
437
|
-
currentPage: input.currentPage,
|
|
438
|
-
abortSignal: input.abortSignal,
|
|
439
|
-
adminUser: input.adminUser,
|
|
440
|
-
emit: input.emit,
|
|
441
|
-
failureLogMessage: (_a = input.failureLogMessage) !== null && _a !== void 0 ? _a : "Agent response failed",
|
|
442
|
-
abortLogMessage: (_b = input.abortLogMessage) !== null && _b !== void 0 ? _b : "Agent response aborted",
|
|
443
|
-
});
|
|
444
|
-
if (agentResponse.failed) {
|
|
445
|
-
yield input.emit({
|
|
446
|
-
type: "error",
|
|
447
|
-
error: agentResponse.text,
|
|
448
|
-
});
|
|
449
|
-
}
|
|
450
|
-
else if (!agentResponse.aborted) {
|
|
451
|
-
yield input.emit({
|
|
452
|
-
type: "response",
|
|
453
|
-
text: agentResponse.text,
|
|
454
|
-
sessionId: input.sessionId,
|
|
455
|
-
turnId: agentResponse.turnId,
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
|
-
yield input.emit({
|
|
459
|
-
type: "finish",
|
|
460
|
-
});
|
|
461
|
-
return agentResponse;
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
createChatSurfaceEventEmitter(sink) {
|
|
465
|
-
return (event) => __awaiter(this, void 0, void 0, function* () {
|
|
466
|
-
if (event.type === "text-delta") {
|
|
467
|
-
yield sink.emit({
|
|
468
|
-
type: "text_delta",
|
|
469
|
-
delta: event.delta,
|
|
470
|
-
});
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
if (event.type === "response") {
|
|
474
|
-
yield sink.emit({
|
|
475
|
-
type: "done",
|
|
476
|
-
text: event.text,
|
|
477
|
-
});
|
|
478
|
-
return;
|
|
479
|
-
}
|
|
480
|
-
if (event.type === "error") {
|
|
481
|
-
yield sink.emit({
|
|
482
|
-
type: "error",
|
|
483
|
-
message: event.error,
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
|
-
handleChatSurfaceMessage(adapter, incoming, sink) {
|
|
489
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
490
|
-
var _a;
|
|
491
|
-
const adminUser = yield adapter.resolveAdminUser({
|
|
492
|
-
adminforth: this.adminforth,
|
|
493
|
-
incoming,
|
|
494
|
-
});
|
|
495
|
-
if (!adminUser) {
|
|
496
|
-
yield sink.emit({
|
|
497
|
-
type: "error",
|
|
498
|
-
message: "This chat account is not authorized to use AdminForth Agent.",
|
|
499
|
-
});
|
|
500
|
-
return;
|
|
501
|
-
}
|
|
502
|
-
yield this.handleTurn({
|
|
503
|
-
prompt: incoming.prompt,
|
|
504
|
-
sessionId: yield this.getOrCreateChatSurfaceSession(incoming, adminUser),
|
|
505
|
-
modeName: incoming.modeName,
|
|
506
|
-
userTimeZone: (_a = incoming.userTimeZone) !== null && _a !== void 0 ? _a : "UTC",
|
|
507
|
-
adminUser,
|
|
508
|
-
emit: this.createChatSurfaceEventEmitter(sink),
|
|
509
|
-
failureLogMessage: `Agent ${incoming.surface} surface response failed`,
|
|
510
|
-
abortLogMessage: `Agent ${incoming.surface} surface response aborted`,
|
|
511
|
-
});
|
|
512
|
-
});
|
|
513
|
-
}
|
|
514
131
|
setupEndpoints(server) {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
return { ok: true };
|
|
533
|
-
const sink = yield adapter.createEventSink(surfaceContext, incoming);
|
|
534
|
-
try {
|
|
535
|
-
yield this.handleChatSurfaceMessage(adapter, incoming, sink);
|
|
536
|
-
}
|
|
537
|
-
finally {
|
|
538
|
-
yield ((_a = sink.close) === null || _a === void 0 ? void 0 : _a.call(sink));
|
|
539
|
-
}
|
|
540
|
-
return { ok: true };
|
|
541
|
-
}),
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
server.endpoint({
|
|
545
|
-
method: 'POST',
|
|
546
|
-
path: `/agent/get-placeholder-messages`,
|
|
547
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ headers, adminUser }) {
|
|
548
|
-
const currentAdminUser = requireAdminUser(adminUser);
|
|
549
|
-
if (!this.options.placeholderMessages) {
|
|
550
|
-
return {
|
|
551
|
-
messages: [],
|
|
552
|
-
};
|
|
553
|
-
}
|
|
554
|
-
const messages = yield this.options.placeholderMessages({
|
|
555
|
-
adminUser: currentAdminUser,
|
|
556
|
-
headers,
|
|
557
|
-
});
|
|
558
|
-
return {
|
|
559
|
-
messages,
|
|
560
|
-
};
|
|
561
|
-
})
|
|
562
|
-
});
|
|
563
|
-
server.endpoint({
|
|
564
|
-
method: 'POST',
|
|
565
|
-
path: `/agent/response`,
|
|
566
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, _raw_express_res, abortSignal }) {
|
|
567
|
-
var _b;
|
|
568
|
-
const currentAdminUser = requireAdminUser(adminUser);
|
|
569
|
-
const data = this.parseBody(agentResponseBodySchema, body, response);
|
|
570
|
-
if (!data)
|
|
571
|
-
return;
|
|
572
|
-
const emit = createSseEventEmitter(_raw_express_res, {
|
|
573
|
-
vercelAiUiMessageStream: true,
|
|
574
|
-
closeActiveBlockOnToolStart: true,
|
|
575
|
-
});
|
|
576
|
-
yield this.handleTurn({
|
|
577
|
-
prompt: data.message,
|
|
578
|
-
sessionId: data.sessionId,
|
|
579
|
-
modeName: data.mode,
|
|
580
|
-
userTimeZone: (_b = data.timeZone) !== null && _b !== void 0 ? _b : 'UTC',
|
|
581
|
-
currentPage: data.currentPage,
|
|
582
|
-
abortSignal,
|
|
583
|
-
adminUser: currentAdminUser,
|
|
584
|
-
emit,
|
|
585
|
-
failureLogMessage: "Agent response streaming failed",
|
|
586
|
-
abortLogMessage: "Agent response streaming aborted by the client",
|
|
587
|
-
});
|
|
588
|
-
return null;
|
|
589
|
-
})
|
|
590
|
-
});
|
|
591
|
-
server.endpoint({
|
|
592
|
-
method: 'POST',
|
|
593
|
-
path: `/agent/speech-response`,
|
|
594
|
-
target: 'upload',
|
|
595
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, _raw_express_req, _raw_express_res, abortSignal }) {
|
|
596
|
-
var _b;
|
|
597
|
-
const currentAdminUser = requireAdminUser(adminUser);
|
|
598
|
-
const req = _raw_express_req;
|
|
599
|
-
const audioAdapter = this.options.audioAdapter;
|
|
600
|
-
if (!audioAdapter) {
|
|
601
|
-
response.setStatus(400, "Audio adapter is not configured for AdminForth Agent");
|
|
602
|
-
return { error: "Audio adapter is not configured for AdminForth Agent" };
|
|
603
|
-
}
|
|
604
|
-
const data = this.parseBody(agentSpeechResponseBodySchema, body, response);
|
|
605
|
-
if (!data)
|
|
606
|
-
return;
|
|
607
|
-
if (!req.file) {
|
|
608
|
-
response.setStatus(400, "Audio file is required");
|
|
609
|
-
return { error: "Audio file is required" };
|
|
610
|
-
}
|
|
611
|
-
const emit = createSseEventEmitter(_raw_express_res);
|
|
612
|
-
let transcription;
|
|
613
|
-
try {
|
|
614
|
-
transcription = yield audioAdapter.transcribe({
|
|
615
|
-
buffer: req.file.buffer,
|
|
616
|
-
filename: req.file.originalname,
|
|
617
|
-
mimeType: req.file.mimetype,
|
|
618
|
-
language: "auto",
|
|
619
|
-
abortSignal,
|
|
620
|
-
});
|
|
621
|
-
}
|
|
622
|
-
catch (error) {
|
|
623
|
-
if (abortSignal.aborted || isAbortError(error)) {
|
|
624
|
-
logger.info("Agent speech transcription aborted by the client");
|
|
625
|
-
yield emit({ type: "finish" });
|
|
626
|
-
return null;
|
|
627
|
-
}
|
|
628
|
-
logger.error(`Agent speech transcription failed:\n${getErrorMessage(error)}`);
|
|
629
|
-
yield emit({
|
|
630
|
-
type: "error",
|
|
631
|
-
error: "Speech transcription failed. Check server logs for details.",
|
|
632
|
-
});
|
|
633
|
-
yield emit({ type: "finish" });
|
|
634
|
-
return null;
|
|
635
|
-
}
|
|
636
|
-
if (abortSignal.aborted) {
|
|
637
|
-
yield emit({ type: "finish" });
|
|
638
|
-
return null;
|
|
639
|
-
}
|
|
640
|
-
const prompt = transcription.text;
|
|
641
|
-
if (!prompt) {
|
|
642
|
-
yield emit({
|
|
643
|
-
type: "error",
|
|
644
|
-
error: "Speech transcription is empty",
|
|
645
|
-
});
|
|
646
|
-
yield emit({ type: "finish" });
|
|
647
|
-
return null;
|
|
648
|
-
}
|
|
649
|
-
yield emit({
|
|
650
|
-
type: "transcript",
|
|
651
|
-
text: transcription.text,
|
|
652
|
-
language: transcription.language,
|
|
653
|
-
});
|
|
654
|
-
const sessionId = data.sessionId;
|
|
655
|
-
const currentPage = data.currentPage;
|
|
656
|
-
const agentResponse = yield this.runAndPersistAgentResponse({
|
|
657
|
-
prompt,
|
|
658
|
-
sessionId,
|
|
659
|
-
modeName: data.mode,
|
|
660
|
-
userTimeZone: (_b = data.timeZone) !== null && _b !== void 0 ? _b : 'UTC',
|
|
661
|
-
currentPage,
|
|
662
|
-
abortSignal,
|
|
663
|
-
adminUser: currentAdminUser,
|
|
664
|
-
emit: (event) => __awaiter(this, void 0, void 0, function* () {
|
|
665
|
-
if (event.type === "tool-call") {
|
|
666
|
-
yield emit(event);
|
|
667
|
-
}
|
|
668
|
-
}),
|
|
669
|
-
failureLogMessage: "Agent speech response failed",
|
|
670
|
-
abortLogMessage: "Agent speech response aborted by the client",
|
|
671
|
-
});
|
|
672
|
-
if (agentResponse.aborted) {
|
|
673
|
-
yield emit({ type: "finish" });
|
|
674
|
-
return null;
|
|
675
|
-
}
|
|
676
|
-
if (agentResponse.failed) {
|
|
677
|
-
yield emit({
|
|
678
|
-
type: "error",
|
|
679
|
-
error: agentResponse.text,
|
|
680
|
-
});
|
|
681
|
-
yield emit({ type: "finish" });
|
|
682
|
-
return null;
|
|
683
|
-
}
|
|
684
|
-
try {
|
|
685
|
-
yield emit({
|
|
686
|
-
type: "speech-response",
|
|
687
|
-
transcript: {
|
|
688
|
-
text: transcription.text,
|
|
689
|
-
language: transcription.language,
|
|
690
|
-
},
|
|
691
|
-
response: {
|
|
692
|
-
text: agentResponse.text,
|
|
693
|
-
},
|
|
694
|
-
sessionId,
|
|
695
|
-
turnId: agentResponse.turnId,
|
|
696
|
-
});
|
|
697
|
-
const speech = yield audioAdapter.synthesize({
|
|
698
|
-
text: sanitizeSpeechText(agentResponse.text),
|
|
699
|
-
stream: true,
|
|
700
|
-
streamFormat: "audio",
|
|
701
|
-
format: "pcm",
|
|
702
|
-
abortSignal,
|
|
703
|
-
});
|
|
704
|
-
yield emit({
|
|
705
|
-
type: "audio-start",
|
|
706
|
-
mimeType: speech.mimeType,
|
|
707
|
-
format: speech.format,
|
|
708
|
-
sampleRate: 24000,
|
|
709
|
-
channelCount: 1,
|
|
710
|
-
bitsPerSample: 16,
|
|
711
|
-
});
|
|
712
|
-
const reader = speech.audioStream.getReader();
|
|
713
|
-
const cancelAudioStream = () => {
|
|
714
|
-
void reader.cancel().catch(() => undefined);
|
|
715
|
-
};
|
|
716
|
-
try {
|
|
717
|
-
abortSignal.addEventListener("abort", cancelAudioStream, { once: true });
|
|
718
|
-
while (true) {
|
|
719
|
-
if (abortSignal.aborted) {
|
|
720
|
-
yield reader.cancel().catch(() => undefined);
|
|
721
|
-
break;
|
|
722
|
-
}
|
|
723
|
-
const { value, done } = yield reader.read();
|
|
724
|
-
if (done) {
|
|
725
|
-
break;
|
|
726
|
-
}
|
|
727
|
-
if (abortSignal.aborted) {
|
|
728
|
-
break;
|
|
729
|
-
}
|
|
730
|
-
yield emit({
|
|
731
|
-
type: "audio-delta",
|
|
732
|
-
value,
|
|
733
|
-
});
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
finally {
|
|
737
|
-
abortSignal.removeEventListener("abort", cancelAudioStream);
|
|
738
|
-
reader.releaseLock();
|
|
739
|
-
}
|
|
740
|
-
yield emit({ type: "audio-done" });
|
|
741
|
-
yield emit({ type: "finish" });
|
|
742
|
-
return null;
|
|
743
|
-
}
|
|
744
|
-
catch (error) {
|
|
745
|
-
if (abortSignal.aborted || isAbortError(error)) {
|
|
746
|
-
logger.info("Agent speech audio streaming aborted by the client");
|
|
747
|
-
}
|
|
748
|
-
else {
|
|
749
|
-
logger.error(`Agent speech audio streaming failed:\n${error}`);
|
|
750
|
-
yield emit({
|
|
751
|
-
type: "error",
|
|
752
|
-
error: getErrorMessage(error),
|
|
753
|
-
});
|
|
754
|
-
}
|
|
755
|
-
yield emit({ type: "finish" });
|
|
756
|
-
return null;
|
|
757
|
-
}
|
|
758
|
-
})
|
|
759
|
-
});
|
|
760
|
-
server.endpoint({
|
|
761
|
-
method: 'POST',
|
|
762
|
-
path: `/agent/get-sessions`,
|
|
763
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
|
|
764
|
-
var _b;
|
|
765
|
-
const currentAdminUser = requireAdminUser(adminUser);
|
|
766
|
-
const data = this.parseBody(getSessionsBodySchema, body, response);
|
|
767
|
-
if (!data)
|
|
768
|
-
return;
|
|
769
|
-
const userId = currentAdminUser.pk;
|
|
770
|
-
const limit = (_b = data.limit) !== null && _b !== void 0 ? _b : 20;
|
|
771
|
-
const sessions = yield this.adminforth.resource(this.options.sessionResource.resourceId).list([Filters.EQ(this.options.sessionResource.askerIdField, userId)], limit, undefined, [Sorts.DESC(this.options.sessionResource.createdAtField)]);
|
|
772
|
-
return {
|
|
773
|
-
sessions: sessions.map((session) => ({
|
|
774
|
-
sessionId: session[this.options.sessionResource.idField],
|
|
775
|
-
title: session[this.options.sessionResource.titleField],
|
|
776
|
-
timestamp: session[this.options.sessionResource.createdAtField],
|
|
777
|
-
})),
|
|
778
|
-
};
|
|
779
|
-
})
|
|
780
|
-
});
|
|
781
|
-
server.endpoint({
|
|
782
|
-
method: 'POST',
|
|
783
|
-
path: `/agent/get-session-info`,
|
|
784
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
|
|
785
|
-
const currentAdminUser = requireAdminUser(adminUser);
|
|
786
|
-
const parsedBody = sessionIdBodySchema.safeParse(body);
|
|
787
|
-
if (!parsedBody.success) {
|
|
788
|
-
response.setStatus(422, parsedBody.error.message);
|
|
789
|
-
return;
|
|
790
|
-
}
|
|
791
|
-
const userId = currentAdminUser.pk;
|
|
792
|
-
const sessionId = parsedBody.data.sessionId;
|
|
793
|
-
const session = yield this.adminforth.resource(this.options.sessionResource.resourceId).get([Filters.EQ(this.options.sessionResource.idField, sessionId)]);
|
|
794
|
-
if (!session) {
|
|
795
|
-
return {
|
|
796
|
-
error: 'Session not found'
|
|
797
|
-
};
|
|
798
|
-
}
|
|
799
|
-
if (session[this.options.sessionResource.askerIdField] !== userId) {
|
|
800
|
-
return {
|
|
801
|
-
error: 'Unauthorized'
|
|
802
|
-
};
|
|
803
|
-
}
|
|
804
|
-
const turns = yield this.getSessionTurns(sessionId);
|
|
805
|
-
return {
|
|
806
|
-
session: {
|
|
807
|
-
sessionId,
|
|
808
|
-
title: session[this.options.sessionResource.titleField],
|
|
809
|
-
timestamp: session[this.options.sessionResource.createdAtField],
|
|
810
|
-
messages: turns.flatMap(turn => {
|
|
811
|
-
const messages = [];
|
|
812
|
-
if (turn.prompt) {
|
|
813
|
-
messages.push({
|
|
814
|
-
text: turn.prompt,
|
|
815
|
-
role: 'user',
|
|
816
|
-
});
|
|
817
|
-
}
|
|
818
|
-
if (turn.response && turn.response !== "not_finished") {
|
|
819
|
-
messages.push({
|
|
820
|
-
text: turn.response,
|
|
821
|
-
role: 'assistant',
|
|
822
|
-
});
|
|
823
|
-
}
|
|
824
|
-
return messages;
|
|
825
|
-
}),
|
|
826
|
-
},
|
|
827
|
-
};
|
|
828
|
-
})
|
|
829
|
-
});
|
|
830
|
-
server.endpoint({
|
|
831
|
-
method: 'POST',
|
|
832
|
-
path: `/agent/create-session`,
|
|
833
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
|
|
834
|
-
const currentAdminUser = requireAdminUser(adminUser);
|
|
835
|
-
const data = this.parseBody(createSessionBodySchema, body, response);
|
|
836
|
-
if (!data)
|
|
837
|
-
return;
|
|
838
|
-
const triggerMessage = data.triggerMessage;
|
|
839
|
-
const userId = currentAdminUser.pk;
|
|
840
|
-
const title = (triggerMessage === null || triggerMessage === void 0 ? void 0 : triggerMessage.slice(0, 40)) || "New Session";
|
|
841
|
-
const newSession = {
|
|
842
|
-
[this.options.sessionResource.idField]: randomUUID(),
|
|
843
|
-
[this.options.sessionResource.titleField]: title,
|
|
844
|
-
[this.options.sessionResource.askerIdField]: userId,
|
|
845
|
-
};
|
|
846
|
-
yield this.adminforth.resource(this.options.sessionResource.resourceId).create(newSession);
|
|
847
|
-
return {
|
|
848
|
-
sessionId: newSession[this.options.sessionResource.idField],
|
|
849
|
-
title: newSession[this.options.sessionResource.titleField],
|
|
850
|
-
timestamp: newSession[this.options.sessionResource.createdAtField],
|
|
851
|
-
messages: []
|
|
852
|
-
};
|
|
853
|
-
})
|
|
854
|
-
});
|
|
855
|
-
server.endpoint({
|
|
856
|
-
method: 'POST',
|
|
857
|
-
path: `/agent/delete-session`,
|
|
858
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
|
|
859
|
-
const currentAdminUser = requireAdminUser(adminUser);
|
|
860
|
-
const data = this.parseBody(sessionIdBodySchema, body, response);
|
|
861
|
-
if (!data)
|
|
862
|
-
return;
|
|
863
|
-
const sessionId = data.sessionId;
|
|
864
|
-
const userId = currentAdminUser.pk;
|
|
865
|
-
const session = yield this.adminforth.resource(this.options.sessionResource.resourceId).get([Filters.EQ(this.options.sessionResource.idField, sessionId)]);
|
|
866
|
-
if (!session) {
|
|
867
|
-
return {
|
|
868
|
-
error: 'Session not found'
|
|
869
|
-
};
|
|
870
|
-
}
|
|
871
|
-
if (session[this.options.sessionResource.askerIdField] !== userId) {
|
|
872
|
-
return {
|
|
873
|
-
error: 'Unauthorized'
|
|
874
|
-
};
|
|
875
|
-
}
|
|
876
|
-
yield this.adminforth.resource(this.options.sessionResource.resourceId).delete(sessionId);
|
|
877
|
-
const turns = yield this.adminforth.resource(this.options.turnResource.resourceId).list([Filters.EQ(this.options.turnResource.sessionIdField, sessionId)]);
|
|
878
|
-
for (const turn of turns) {
|
|
879
|
-
yield this.adminforth.resource(this.options.turnResource.resourceId).delete(turn[this.options.turnResource.idField]);
|
|
880
|
-
}
|
|
881
|
-
return {
|
|
882
|
-
ok: true
|
|
883
|
-
};
|
|
884
|
-
})
|
|
885
|
-
}),
|
|
886
|
-
server.endpoint({
|
|
887
|
-
method: 'POST',
|
|
888
|
-
path: `/agent/add-system-message-to-turns`,
|
|
889
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, response }) {
|
|
890
|
-
const data = this.parseBody(addSystemMessageBodySchema, body, response);
|
|
891
|
-
if (!data)
|
|
892
|
-
return;
|
|
893
|
-
yield this.createNewTurn(data.sessionId, data.systemMessage);
|
|
894
|
-
return {
|
|
895
|
-
ok: true
|
|
896
|
-
};
|
|
897
|
-
})
|
|
898
|
-
});
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
function getPartialVegaLiteFenceStartLength(text) {
|
|
902
|
-
for (let length = Math.min(text.length, VEGA_LITE_FENCE_START.length - 1); length > 0; length -= 1) {
|
|
903
|
-
if (VEGA_LITE_FENCE_START.startsWith(text.slice(-length))) {
|
|
904
|
-
return length;
|
|
905
|
-
}
|
|
132
|
+
const endpointContext = {
|
|
133
|
+
adminforth: this.adminforth,
|
|
134
|
+
options: this.options,
|
|
135
|
+
parseBody: this.parseBody.bind(this),
|
|
136
|
+
handleTurn: this.agentTurnService.handleTurn.bind(this.agentTurnService),
|
|
137
|
+
handleSpeechTurn: this.agentTurnService.handleSpeechTurn.bind(this.agentTurnService),
|
|
138
|
+
runAndPersistAgentResponse: this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService),
|
|
139
|
+
getSessionTurns: this.sessionStore.getSessionTurns.bind(this.sessionStore),
|
|
140
|
+
createNewTurn: this.sessionStore.createNewTurn.bind(this.sessionStore),
|
|
141
|
+
createSystemTurn: this.sessionStore.createSystemTurn.bind(this.sessionStore),
|
|
142
|
+
getChatSurfaceConnectActionAdapters: this.chatSurfaceService.getConnectActionAdapters.bind(this.chatSurfaceService),
|
|
143
|
+
createChatSurfaceLinkToken: this.chatSurfaceService.createLinkToken.bind(this.chatSurfaceService),
|
|
144
|
+
handleChatSurfaceMessage: this.chatSurfaceService.handleMessage.bind(this.chatSurfaceService),
|
|
145
|
+
};
|
|
146
|
+
setupCoreEndpoints(endpointContext, server);
|
|
147
|
+
setupSessionEndpoints(endpointContext, server);
|
|
148
|
+
setupChatSurfaceEndpoints(endpointContext, server);
|
|
906
149
|
}
|
|
907
|
-
return 0;
|
|
908
150
|
}
|