@adminforth/agent 2.0.9 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/README.md +333 -10
  2. package/dist/application/ports.d.ts +66 -0
  3. package/dist/application/runTurnUseCase.d.ts +68 -0
  4. package/dist/application/runTurnUseCase.js +358 -0
  5. package/dist/{agentEvents.d.ts → domain/agentEvents.d.ts} +1 -1
  6. package/dist/{agent → domain}/systemPrompt.js +1 -1
  7. package/dist/{agent/turn → domain}/turnTypes.d.ts +41 -37
  8. package/dist/{agent/turn/VegaLiteStreamBuffer.d.ts → domain/vegaLiteStreamBuffer.d.ts} +1 -1
  9. package/dist/index.d.ts +3 -2
  10. package/dist/index.js +40 -35
  11. package/dist/{agent/runtime/AgentContext.d.ts → llm/agentContext.d.ts} +3 -3
  12. package/dist/{agent/simpleAgent.d.ts → llm/agentModels.d.ts} +18 -16
  13. package/dist/llm/agentModels.js +65 -0
  14. package/dist/{agent/runtime/AgentRuntime.d.ts → llm/agentRuntime.d.ts} +11 -2
  15. package/dist/{agent/runtime/AgentRuntime.js → llm/agentRuntime.js} +38 -6
  16. package/dist/llm/langGraphLlm.d.ts +25 -0
  17. package/dist/llm/langGraphLlm.js +54 -0
  18. package/dist/{agent/middleware/apiBasedTools.d.ts → llm/middleware/apiToolsMiddleware.d.ts} +1 -1
  19. package/dist/{agent/middleware/apiBasedTools.js → llm/middleware/apiToolsMiddleware.js} +8 -14
  20. package/dist/{agent → llm}/middleware/sequenceDebug.d.ts +1 -1
  21. package/dist/{agent/models/AgentModelFactory.d.ts → llm/modelFactory.d.ts} +1 -1
  22. package/dist/{agent/models/AgentModelFactory.js → llm/modelFactory.js} +1 -1
  23. package/dist/llm/streamAdapter.d.ts +18 -0
  24. package/dist/llm/streamAdapter.js +117 -0
  25. package/dist/{sessionStore.d.ts → persistence/sessionStore.d.ts} +12 -2
  26. package/dist/{sessionStore.js → persistence/sessionStore.js} +33 -0
  27. package/dist/{agent/tools/AgentToolProvider.d.ts → tools/agentToolProvider.d.ts} +1 -1
  28. package/dist/{agent/tools/AgentToolProvider.js → tools/agentToolProvider.js} +1 -1
  29. package/dist/{apiBasedTools.js → tools/apiBasedTools.js} +10 -6
  30. package/dist/{agent/tools → tools}/apiTool.d.ts +1 -1
  31. package/dist/{agent/tools → tools}/fetchSkill.js +1 -1
  32. package/dist/{agent/tools → tools}/fetchToolSchema.d.ts +1 -1
  33. package/dist/{agent/tools → tools}/index.d.ts +1 -1
  34. package/dist/{agent/tools → tools}/navigateUser.d.ts +3 -3
  35. package/dist/{endpoints → transport/http}/context.d.ts +2 -2
  36. package/dist/transport/http/context.js +1 -0
  37. package/dist/{endpoints/core.js → transport/http/coreEndpoints.js} +3 -3
  38. package/dist/{endpoints/sessions.js → transport/http/sessionEndpoints.js} +7 -1
  39. package/dist/transport/sse/sseWriter.d.ts +29 -0
  40. package/dist/{surfaces/web-sse/createSseEventEmitter.js → transport/sse/sseWriter.js} +15 -0
  41. package/dist/{chatSurfaceService.d.ts → transport/surfaces/chatSurfaceService.d.ts} +3 -3
  42. package/dist/{chatSurfaceService.js → transport/surfaces/chatSurfaceService.js} +7 -5
  43. package/dist/{agent/speech/SpeechTurnService.d.ts → transport/surfaces/speechTurnService.d.ts} +1 -1
  44. package/dist/{agent/speech/SpeechTurnService.js → transport/surfaces/speechTurnService.js} +2 -2
  45. package/dist/types.d.ts +10 -4
  46. package/package.json +11 -2
  47. package/.woodpecker/buildRelease.sh +0 -13
  48. package/.woodpecker/buildSlackNotify.sh +0 -46
  49. package/.woodpecker/release.yml +0 -57
  50. package/agent/checkpointer.ts +0 -329
  51. package/agent/languageDetect.ts +0 -92
  52. package/agent/middleware/apiBasedTools.ts +0 -174
  53. package/agent/middleware/openAiResponsesContinuation.ts +0 -92
  54. package/agent/middleware/sequenceDebug.ts +0 -429
  55. package/agent/models/AgentModeResolver.ts +0 -9
  56. package/agent/models/AgentModelFactory.ts +0 -28
  57. package/agent/runtime/AgentContext.ts +0 -30
  58. package/agent/runtime/AgentRuntime.ts +0 -89
  59. package/agent/simpleAgent.ts +0 -199
  60. package/agent/skills/registry.ts +0 -162
  61. package/agent/speech/SpeechTurnService.ts +0 -179
  62. package/agent/systemPrompt.ts +0 -133
  63. package/agent/toolCallEvents.ts +0 -135
  64. package/agent/tools/AgentToolProvider.ts +0 -28
  65. package/agent/tools/apiTool.ts +0 -66
  66. package/agent/tools/fetchSkill.ts +0 -68
  67. package/agent/tools/fetchToolSchema.ts +0 -47
  68. package/agent/tools/getUserLocation.ts +0 -45
  69. package/agent/tools/index.ts +0 -31
  70. package/agent/tools/navigateUser.ts +0 -210
  71. package/agent/turn/TurnContextBuilder.ts +0 -36
  72. package/agent/turn/TurnLifecycleService.ts +0 -47
  73. package/agent/turn/TurnPersistenceService.ts +0 -33
  74. package/agent/turn/TurnPromptBuilder.ts +0 -51
  75. package/agent/turn/TurnStreamConsumer.ts +0 -69
  76. package/agent/turn/VegaLiteStreamBuffer.ts +0 -90
  77. package/agent/turn/turnTypes.ts +0 -100
  78. package/agentEvents.ts +0 -75
  79. package/agentTurnService.ts +0 -314
  80. package/apiBasedTools.ts +0 -702
  81. package/build.log +0 -67
  82. package/chatSurfaceService.ts +0 -319
  83. package/custom/ChatFooter.vue +0 -173
  84. package/custom/ChatHeader.vue +0 -78
  85. package/custom/ChatSurface.vue +0 -160
  86. package/custom/CustomAutoScrollContainer.vue +0 -164
  87. package/custom/SessionsHistory.vue +0 -88
  88. package/custom/chat.ts +0 -82
  89. package/custom/composables/agentAudio/utils.ts +0 -220
  90. package/custom/composables/agentStore/constants.ts +0 -19
  91. package/custom/composables/agentStore/pageContext.ts +0 -8
  92. package/custom/composables/agentStore/useAgentChat.ts +0 -241
  93. package/custom/composables/agentStore/useAgentPlaceholder.ts +0 -142
  94. package/custom/composables/agentStore/useAgentSessions.ts +0 -350
  95. package/custom/composables/useAgentAudio.ts +0 -272
  96. package/custom/composables/useAgentStore.ts +0 -510
  97. package/custom/composables/useAgentTransitions.ts +0 -58
  98. package/custom/conversation_area/ConversationArea.vue +0 -301
  99. package/custom/conversation_area/MessageRenderer.vue +0 -49
  100. package/custom/conversation_area/ProcessingTimeline.vue +0 -286
  101. package/custom/conversation_area/ReasoningRenderer.vue +0 -79
  102. package/custom/conversation_area/SystemMessageRenderer.vue +0 -28
  103. package/custom/conversation_area/TextRenderer.vue +0 -182
  104. package/custom/conversation_area/ThreeDotsAnimation.vue +0 -35
  105. package/custom/conversation_area/ToolApprovalRenderer.vue +0 -98
  106. package/custom/conversation_area/ToolRenderer.vue +0 -178
  107. package/custom/conversation_area/ToolsGroup.vue +0 -59
  108. package/custom/env.d.ts +0 -7
  109. package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +0 -393
  110. package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +0 -285
  111. package/custom/incremark_code_renderers/incremarkRenderer.ts +0 -653
  112. package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +0 -118
  113. package/custom/package.json +0 -30
  114. package/custom/pnpm-lock.yaml +0 -2394
  115. package/custom/public/agentAudio/agent-processing.mp3 +0 -0
  116. package/custom/skills/analyze_data/SKILL.md +0 -25
  117. package/custom/skills/charts/SKILL.md +0 -193
  118. package/custom/skills/fetch_data/SKILL.md +0 -31
  119. package/custom/skills/mutate_data/SKILL.md +0 -121
  120. package/custom/speech_recognition_frontend/AudioLines.vue +0 -43
  121. package/custom/speech_recognition_frontend/MicrophoneButon.vue +0 -185
  122. package/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +0 -22
  123. package/custom/speech_recognition_frontend/voiceActivityDetection.ts +0 -62
  124. package/custom/tsconfig.json +0 -15
  125. package/custom/types.ts +0 -108
  126. package/custom/utils.ts +0 -38
  127. package/dist/agent/middleware/openAiResponsesContinuation.d.ts +0 -1
  128. package/dist/agent/middleware/openAiResponsesContinuation.js +0 -66
  129. package/dist/agent/models/AgentModeResolver.d.ts +0 -9
  130. package/dist/agent/models/AgentModeResolver.js +0 -9
  131. package/dist/agent/simpleAgent.js +0 -118
  132. package/dist/agent/turn/TurnContextBuilder.d.ts +0 -14
  133. package/dist/agent/turn/TurnContextBuilder.js +0 -31
  134. package/dist/agent/turn/TurnLifecycleService.d.ts +0 -24
  135. package/dist/agent/turn/TurnLifecycleService.js +0 -47
  136. package/dist/agent/turn/TurnPersistenceService.d.ts +0 -13
  137. package/dist/agent/turn/TurnPersistenceService.js +0 -35
  138. package/dist/agent/turn/TurnPromptBuilder.d.ts +0 -19
  139. package/dist/agent/turn/TurnPromptBuilder.js +0 -43
  140. package/dist/agent/turn/TurnStreamConsumer.d.ts +0 -11
  141. package/dist/agent/turn/TurnStreamConsumer.js +0 -84
  142. package/dist/agentTurnService.d.ts +0 -24
  143. package/dist/agentTurnService.js +0 -269
  144. package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +0 -14
  145. package/endpoints/chatSurfaces.ts +0 -66
  146. package/endpoints/context.ts +0 -52
  147. package/endpoints/core.ts +0 -181
  148. package/endpoints/sessions.ts +0 -183
  149. package/errors.ts +0 -10
  150. package/index.ts +0 -192
  151. package/pnpm-workspace.yaml +0 -4
  152. package/sanitizeSpeechText.ts +0 -32
  153. package/sessionStore.ts +0 -105
  154. package/surfaces/web-sse/createSseEventEmitter.ts +0 -311
  155. package/tsconfig.json +0 -14
  156. package/types.ts +0 -127
  157. /package/dist/{agent/turn/turnTypes.js → application/ports.js} +0 -0
  158. /package/dist/{agentEvents.js → domain/agentEvents.js} +0 -0
  159. /package/dist/{agent → domain}/languageDetect.d.ts +0 -0
  160. /package/dist/{agent → domain}/languageDetect.js +0 -0
  161. /package/dist/{agent → domain}/systemPrompt.d.ts +0 -0
  162. /package/dist/{agent → domain}/toolCallEvents.d.ts +0 -0
  163. /package/dist/{agent → domain}/toolCallEvents.js +0 -0
  164. /package/dist/{endpoints/context.js → domain/turnTypes.js} +0 -0
  165. /package/dist/{agent/turn/VegaLiteStreamBuffer.js → domain/vegaLiteStreamBuffer.js} +0 -0
  166. /package/dist/{agent/runtime/AgentContext.js → llm/agentContext.js} +0 -0
  167. /package/dist/{agent → llm}/middleware/sequenceDebug.js +0 -0
  168. /package/dist/{agent/checkpointer.d.ts → persistence/checkpointStore.d.ts} +0 -0
  169. /package/dist/{agent/checkpointer.js → persistence/checkpointStore.js} +0 -0
  170. /package/dist/{errors.d.ts → shared/errors.d.ts} +0 -0
  171. /package/dist/{errors.js → shared/errors.js} +0 -0
  172. /package/dist/{sanitizeSpeechText.d.ts → shared/sanitizeSpeechText.d.ts} +0 -0
  173. /package/dist/{sanitizeSpeechText.js → shared/sanitizeSpeechText.js} +0 -0
  174. /package/dist/{apiBasedTools.d.ts → tools/apiBasedTools.d.ts} +0 -0
  175. /package/dist/{agent/tools → tools}/apiTool.js +0 -0
  176. /package/dist/{agent/tools → tools}/fetchSkill.d.ts +0 -0
  177. /package/dist/{agent/tools → tools}/fetchToolSchema.js +0 -0
  178. /package/dist/{agent/tools → tools}/getUserLocation.d.ts +0 -0
  179. /package/dist/{agent/tools → tools}/getUserLocation.js +0 -0
  180. /package/dist/{agent/tools → tools}/index.js +0 -0
  181. /package/dist/{agent/tools → tools}/navigateUser.js +0 -0
  182. /package/dist/{agent → tools}/skills/registry.d.ts +0 -0
  183. /package/dist/{agent → tools}/skills/registry.js +0 -0
  184. /package/dist/{endpoints/chatSurfaces.d.ts → transport/http/chatSurfaceEndpoints.d.ts} +0 -0
  185. /package/dist/{endpoints/chatSurfaces.js → transport/http/chatSurfaceEndpoints.js} +0 -0
  186. /package/dist/{endpoints/core.d.ts → transport/http/coreEndpoints.d.ts} +0 -0
  187. /package/dist/{endpoints/sessions.d.ts → transport/http/sessionEndpoints.d.ts} +0 -0
package/endpoints/core.ts DELETED
@@ -1,181 +0,0 @@
1
- import type { IHttpServer } from "adminforth";
2
- import { z } from "zod";
3
- import { createSseEventEmitter } from "../surfaces/web-sse/createSseEventEmitter.js";
4
- import type { CurrentPageContext } from "../agent/tools/getUserLocation.js";
5
- import type { CoreEndpointsContext } from "./context.js";
6
-
7
- type MulterFile = {
8
- buffer: Buffer;
9
- originalname: string;
10
- mimetype: string;
11
- };
12
-
13
- type ExpressMulterRequest = { file?: MulterFile };
14
-
15
- const currentPageContextSchema = z.object({
16
- path: z.string(),
17
- fullPath: z.string(),
18
- title: z.string(),
19
- url: z.string(),
20
- }).strict() satisfies z.ZodType<CurrentPageContext>;
21
-
22
- const agentResponseBodySchema = z.object({
23
- message: z.string(),
24
- sessionId: z.string(),
25
- mode: z.string().nullish(),
26
- timeZone: z.string().optional(),
27
- currentPage: currentPageContextSchema.optional(),
28
- }).strict();
29
-
30
- const agentApprovalBodySchema = z.object({
31
- sessionId: z.string(),
32
- decision: z.enum(["approve", "reject"]),
33
- }).strict();
34
-
35
- // Sent as multipart/form-data (via multer), so every field arrives as a plain string on the wire.
36
- // `currentPage` is JSON.stringify'd by the client into a form field and must be parsed back into
37
- // an object. Zod -> JSON-Schema conversion cannot represent `.transform()` at all (it throws), so
38
- // `agentSpeechResponseShapeSchema` (plain strings, no transform) is what's passed as request_schema
39
- // for the AJV pre-check, while `agentSpeechResponseBodySchema` (with the transform) is used via an
40
- // inline safeParse in the handler to actually parse `currentPage` into an object.
41
- const agentSpeechResponseShapeSchema = z.object({
42
- sessionId: z.string(),
43
- mode: z.string().nullish(),
44
- timeZone: z.string().optional(),
45
- currentPage: z.string().optional(),
46
- }).strict();
47
-
48
- const agentSpeechResponseBodySchema = agentSpeechResponseShapeSchema.extend({
49
- currentPage: z.string().optional().transform((value, ctx) => {
50
- if (value === undefined) return undefined;
51
- try {
52
- return currentPageContextSchema.parse(JSON.parse(value));
53
- } catch (err) {
54
- ctx.addIssue({
55
- code: z.ZodIssueCode.custom,
56
- message: `currentPage must be a JSON-encoded object matching CurrentPageContext: ${err instanceof Error ? err.message : String(err)}`,
57
- });
58
- return z.NEVER;
59
- }
60
- }),
61
- });
62
-
63
- export function setupCoreEndpoints(ctx: CoreEndpointsContext, server: IHttpServer) {
64
- server.endpoint({
65
- method: 'POST',
66
- path: `/agent/get-placeholder-messages`,
67
- handler: async ({ headers, adminUser }) => {
68
- if (!ctx.options.placeholderMessages) {
69
- return {
70
- messages: [],
71
- };
72
- }
73
-
74
- const messages = await ctx.options.placeholderMessages({
75
- adminUser: adminUser!,
76
- headers,
77
- });
78
-
79
- return {
80
- messages,
81
- };
82
- }
83
- });
84
-
85
- server.endpoint({
86
- method: 'POST',
87
- path: `/agent/response`,
88
- request_schema: agentResponseBodySchema,
89
- handler: async ({ body, adminUser, response, _raw_express_res, abortSignal }) => {
90
- const data = body as z.infer<typeof agentResponseBodySchema>;
91
- const emit = createSseEventEmitter(_raw_express_res, {
92
- vercelAiUiMessageStream: true,
93
- closeActiveBlockOnToolStart: true,
94
- });
95
-
96
- await ctx.handleTurn({
97
- prompt: data.message,
98
- sessionId: data.sessionId,
99
- modeName: data.mode,
100
- userTimeZone: data.timeZone ?? 'UTC',
101
- currentPage: data.currentPage,
102
- abortSignal,
103
- adminUser: adminUser!,
104
- emit,
105
- failureLogMessage: "Agent response streaming failed",
106
- abortLogMessage: "Agent response streaming aborted by the client",
107
- });
108
- return null;
109
- }
110
- });
111
-
112
- server.endpoint({
113
- method: 'POST',
114
- path: `/agent/approval`,
115
- request_schema: agentApprovalBodySchema,
116
- handler: async ({ body, adminUser, response, _raw_express_res, abortSignal }) => {
117
- const data = body as z.infer<typeof agentApprovalBodySchema>;
118
- const emit = createSseEventEmitter(_raw_express_res, {
119
- vercelAiUiMessageStream: true,
120
- closeActiveBlockOnToolStart: true,
121
- });
122
-
123
- await ctx.handleTurn({
124
- prompt: "",
125
- sessionId: data.sessionId,
126
- approvalDecision: data.decision,
127
- abortSignal,
128
- adminUser: adminUser!,
129
- emit,
130
- failureLogMessage: "Agent approval response streaming failed",
131
- abortLogMessage: "Agent approval response streaming aborted by the client",
132
- });
133
- return null;
134
- }
135
- });
136
-
137
- server.endpoint({
138
- method: 'POST',
139
- path: `/agent/speech-response`,
140
- target: 'upload',
141
- request_schema: agentSpeechResponseShapeSchema,
142
- handler: async ({ body, adminUser, response, _raw_express_req, _raw_express_res, abortSignal }) => {
143
- const req = _raw_express_req as ExpressMulterRequest;
144
- const audioAdapter = ctx.options.audioAdapter;
145
- if (!audioAdapter) {
146
- response.setStatus(400, "Audio adapter is not configured for AdminForth Agent");
147
- return { error: "Audio adapter is not configured for AdminForth Agent" };
148
- }
149
- const parsed = agentSpeechResponseBodySchema.safeParse(body);
150
- if (!parsed.success) {
151
- response.setStatus(400, 'Request body validation failed');
152
- return { error: 'Request body validation failed', details: parsed.error.issues };
153
- }
154
- const data = parsed.data;
155
- if (!req.file) {
156
- response.setStatus(400, "Audio file is required");
157
- return { error: "Audio file is required" };
158
- }
159
- const emit = createSseEventEmitter(_raw_express_res);
160
-
161
- await ctx.handleSpeechTurn({
162
- audioAdapter,
163
- audio: {
164
- buffer: req.file.buffer,
165
- filename: req.file.originalname,
166
- mimeType: req.file.mimetype,
167
- },
168
- sessionId: data.sessionId,
169
- modeName: data.mode,
170
- userTimeZone: data.timeZone ?? 'UTC',
171
- currentPage: data.currentPage,
172
- abortSignal,
173
- adminUser: adminUser!,
174
- emit,
175
- failureLogMessage: "Agent speech response failed",
176
- abortLogMessage: "Agent speech response aborted by the client",
177
- });
178
- return null;
179
- }
180
- });
181
- }
@@ -1,183 +0,0 @@
1
- import type { IHttpServer } from "adminforth";
2
- import { Filters, Sorts } from "adminforth";
3
- import { randomUUID } from "crypto";
4
- import { z } from "zod";
5
- import { AGENT_SYSTEM_TURN_PROMPT } from "../sessionStore.js";
6
- import type { SessionEndpointsContext } from "./context.js";
7
-
8
- const addSystemMessageBodySchema = z.object({
9
- sessionId: z.string(),
10
- systemMessage: z.string(),
11
- }).strict();
12
-
13
- const getSessionsBodySchema = z.object({
14
- limit: z.number().int().min(1).max(100).optional(),
15
- }).strict();
16
-
17
- const sessionIdBodySchema = z.object({
18
- sessionId: z.string(),
19
- }).strict();
20
-
21
- const createSessionBodySchema = z.object({
22
- triggerMessage: z.string().optional(),
23
- }).strict();
24
-
25
- export function setupSessionEndpoints(ctx: SessionEndpointsContext, server: IHttpServer) {
26
- server.endpoint({
27
- method: 'POST',
28
- path: `/agent/get-sessions`,
29
- request_schema: getSessionsBodySchema,
30
- handler: async ({body, adminUser, response }) => {
31
- const data = body as z.infer<typeof getSessionsBodySchema>;
32
- const userId = adminUser!.pk;
33
- const limit = data.limit ?? 20;
34
- const sessions = await ctx.adminforth.resource(ctx.options.sessionResource.resourceId).list(
35
- [Filters.EQ(ctx.options.sessionResource.askerIdField, userId)], limit, undefined, [Sorts.DESC(ctx.options.sessionResource.createdAtField)]
36
- );
37
- return {
38
- sessions: sessions.map((session) => ({
39
- sessionId: session[ctx.options.sessionResource.idField],
40
- title: session[ctx.options.sessionResource.titleField],
41
- timestamp: session[ctx.options.sessionResource.createdAtField],
42
- })),
43
- };
44
- }
45
- });
46
-
47
- server.endpoint({
48
- method: 'POST',
49
- path: `/agent/get-session-info`,
50
- request_schema: sessionIdBodySchema,
51
- handler: async ({body, adminUser, response }) => {
52
- const data = body as z.infer<typeof sessionIdBodySchema>;
53
- const userId = adminUser!.pk;
54
- const sessionId = data.sessionId;
55
- const session = await ctx.adminforth.resource(ctx.options.sessionResource.resourceId).get(
56
- [Filters.EQ(ctx.options.sessionResource.idField, sessionId)]
57
- );
58
- if (!session) {
59
- return {
60
- error: 'Session not found'
61
- };
62
- }
63
- if (session[ctx.options.sessionResource.askerIdField] !== userId) {
64
- return {
65
- error: 'Unauthorized'
66
- };
67
- }
68
- const turns = await ctx.getSessionTurns(sessionId);
69
- return {
70
- session: {
71
- sessionId,
72
- title: session[ctx.options.sessionResource.titleField],
73
- timestamp: session[ctx.options.sessionResource.createdAtField],
74
- messages: turns.flatMap(turn => {
75
- const messages: Array<{ text: string; role: 'user' | 'assistant' | 'system' }> = [];
76
- if (turn.prompt === AGENT_SYSTEM_TURN_PROMPT) {
77
- messages.push({
78
- text: turn.response,
79
- role: 'system',
80
- });
81
- return messages;
82
- }
83
- if (turn.prompt) {
84
- messages.push({
85
- text: turn.prompt,
86
- role: 'user',
87
- });
88
- }
89
- if (turn.response && turn.response !== "not_finished") {
90
- messages.push({
91
- text: turn.response,
92
- role: 'assistant',
93
- });
94
- }
95
- return messages;
96
- }),
97
- },
98
- };
99
- }
100
- });
101
-
102
- server.endpoint({
103
- method: 'POST',
104
- path: `/agent/create-session`,
105
- request_schema: createSessionBodySchema,
106
- handler: async ({body, adminUser, response }) => {
107
- const data = body as z.infer<typeof createSessionBodySchema>;
108
- const triggerMessage = data.triggerMessage;
109
- const userId = adminUser!.pk;
110
- const title = triggerMessage?.slice(0, 40) || "New Session";
111
- const newSession = {
112
- [ctx.options.sessionResource.idField]: randomUUID(),
113
- [ctx.options.sessionResource.titleField]: title,
114
- [ctx.options.sessionResource.askerIdField]: userId,
115
- };
116
- const { createdRecord } = await ctx.adminforth.resource(ctx.options.sessionResource.resourceId).create(newSession);
117
- return {
118
- sessionId: createdRecord[ctx.options.sessionResource.idField],
119
- title: createdRecord[ctx.options.sessionResource.titleField],
120
- timestamp: createdRecord[ctx.options.sessionResource.createdAtField],
121
- messages: []
122
- };
123
- }
124
- });
125
-
126
- server.endpoint({
127
- method: 'POST',
128
- path: `/agent/delete-session`,
129
- request_schema: sessionIdBodySchema,
130
- handler: async ({body, adminUser, response }) => {
131
- const data = body as z.infer<typeof sessionIdBodySchema>;
132
- const sessionId = data.sessionId;
133
- const userId = adminUser!.pk;
134
- const session = await ctx.adminforth.resource(ctx.options.sessionResource.resourceId).get(
135
- [Filters.EQ(ctx.options.sessionResource.idField, sessionId)]
136
- );
137
- if (!session) {
138
- return {
139
- error: 'Session not found'
140
- };
141
- }
142
- if (session[ctx.options.sessionResource.askerIdField] !== userId) {
143
- return {
144
- error: 'Unauthorized'
145
- };
146
- }
147
- await ctx.adminforth.resource(ctx.options.sessionResource.resourceId).delete(sessionId);
148
- const turns = await ctx.adminforth.resource(ctx.options.turnResource.resourceId).list(
149
- [Filters.EQ(ctx.options.turnResource.sessionIdField, sessionId)]
150
- );
151
- await Promise.all(turns.map(turn => ctx.adminforth.resource(ctx.options.turnResource.resourceId).delete(turn[ctx.options.turnResource.idField])));
152
- return {
153
- ok: true
154
- };
155
- }
156
- });
157
-
158
- server.endpoint({
159
- method: 'POST',
160
- path: `/agent/add-system-message-to-turns`,
161
- request_schema: addSystemMessageBodySchema,
162
- handler: async ({body, adminUser, response }) => {
163
- const data = body as z.infer<typeof addSystemMessageBodySchema>;
164
- const session = await ctx.adminforth.resource(ctx.options.sessionResource.resourceId).get(
165
- [Filters.EQ(ctx.options.sessionResource.idField, data.sessionId)]
166
- );
167
- if (!session) {
168
- return {
169
- error: 'Session not found'
170
- };
171
- }
172
- if (session[ctx.options.sessionResource.askerIdField] !== adminUser!.pk) {
173
- return {
174
- error: 'Unauthorized'
175
- };
176
- }
177
- await ctx.createSystemTurn(data.sessionId, data.systemMessage);
178
- return {
179
- ok: true
180
- }
181
- }
182
- })
183
- }
package/errors.ts DELETED
@@ -1,10 +0,0 @@
1
- export function isAbortError(error: unknown): boolean {
2
- return typeof error === "object" &&
3
- error !== null &&
4
- "name" in error &&
5
- (error.name === "AbortError" || error.name === "APIUserAbortError");
6
- }
7
-
8
- export function getErrorMessage(error: unknown): string {
9
- return error instanceof Error ? error.message : String(error);
10
- }
package/index.ts DELETED
@@ -1,192 +0,0 @@
1
- import type {
2
- AdminForthResource,
3
- IAdminForth,
4
- IHttpServer,
5
- } from "adminforth";
6
-
7
- import { AdminForthPlugin } from "adminforth";
8
-
9
- import type { PluginOptions } from './types.js';
10
- import { MemorySaver, type BaseCheckpointSaver } from "@langchain/langgraph";
11
- import { AdminForthCheckpointSaver } from "./agent/checkpointer.js";
12
- import { appendCustomSystemPrompt, buildAgentSystemPrompt, DEFAULT_AGENT_SYSTEM_PROMPT} from "./agent/systemPrompt.js";
13
- import { setupCoreEndpoints } from "./endpoints/core.js";
14
- import { setupSessionEndpoints } from "./endpoints/sessions.js";
15
- import { setupChatSurfaceEndpoints } from "./endpoints/chatSurfaces.js";
16
- import type { AgentEndpointsContext } from "./endpoints/context.js";
17
- import { AgentSessionStore } from "./sessionStore.js";
18
- import { ChatSurfaceService } from "./chatSurfaceService.js";
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";
30
-
31
- export type { AgentEvent, AgentEventEmitter } from "./agentEvents.js";
32
-
33
- export default class AdminForthAgentPlugin extends AdminForthPlugin {
34
- options: PluginOptions;
35
- agentSystemPromptPromise: Promise<string>;
36
- pluginsScope: "resource" | "global" = "global";
37
- private agentSystemPrompt: string | null = null;
38
- private checkpointer: BaseCheckpointSaver | null = null;
39
- private sessionStore: AgentSessionStore;
40
- private agentTurnService: AgentTurnService;
41
- private speechTurnService: SpeechTurnService;
42
- private chatSurfaceService: ChatSurfaceService;
43
- private getCheckpointer() {
44
- if (this.checkpointer) return this.checkpointer;
45
-
46
- this.checkpointer = this.options.checkpointResource
47
- ? new AdminForthCheckpointSaver(this.adminforth, this.options)
48
- : new MemorySaver();
49
-
50
- return this.checkpointer;
51
- }
52
-
53
- private getInternalAgentResourceIds() {
54
- return [
55
- this.options.sessionResource.resourceId,
56
- this.options.turnResource.resourceId,
57
- this.options.checkpointResource?.resourceId,
58
- ].filter((resourceId): resourceId is string => Boolean(resourceId));
59
- }
60
-
61
- constructor(options: PluginOptions) {
62
- super(options, import.meta.url);
63
- this.options = options;
64
- this.sessionStore = new AgentSessionStore(() => this.adminforth, this.options);
65
- const toolProvider = new AgentToolProvider(
66
- () => this.adminforth,
67
- this.getInternalAgentResourceIds.bind(this),
68
- );
69
- const runtime = new AgentRuntime({
70
- name: `adminforth-agent-${this.pluginInstanceId}`,
71
- getAdminforth: () => this.adminforth,
72
- getCheckpointer: this.getCheckpointer.bind(this),
73
- toolProvider,
74
- });
75
- const persistence = new TurnPersistenceService(() => this.adminforth, this.options);
76
- this.agentTurnService = new AgentTurnService(
77
- new TurnLifecycleService(this.sessionStore, persistence, this.options),
78
- new TurnContextBuilder(() => this.adminforth),
79
- new AgentModeResolver(this.options),
80
- new AgentModelFactory(this.options.maxTokens ?? 1000),
81
- new TurnPromptBuilder({
82
- getAdminforth: () => this.adminforth,
83
- getAgentSystemPrompt: async () => {
84
- if (!this.agentSystemPrompt) {
85
- const systemPrompt = await buildAgentSystemPrompt(
86
- this.adminforth,
87
- this.getInternalAgentResourceIds(),
88
- ).catch((err) => {
89
- return DEFAULT_AGENT_SYSTEM_PROMPT;
90
- });
91
- this.agentSystemPrompt = appendCustomSystemPrompt(systemPrompt, this.options.systemPrompt);
92
- }
93
- return this.agentSystemPrompt;
94
- },
95
- }),
96
- runtime,
97
- new TurnStreamConsumer(),
98
- );
99
- this.speechTurnService = new SpeechTurnService(
100
- this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService),
101
- );
102
- this.chatSurfaceService = new ChatSurfaceService(
103
- () => this.adminforth,
104
- this.options,
105
- this.sessionStore,
106
- this.agentTurnService.handleTurn.bind(this.agentTurnService),
107
- this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService),
108
- );
109
- this.agentSystemPromptPromise = Promise.resolve(
110
- appendCustomSystemPrompt(DEFAULT_AGENT_SYSTEM_PROMPT, this.options.systemPrompt),
111
- );
112
- this.shouldHaveSingleInstancePerWholeApp = () => false;
113
- }
114
-
115
- async modifyGlobalConfig(adminforth: IAdminForth) {
116
- super.modifyGlobalConfig(adminforth);
117
- if (!this.options.modes?.length) {
118
- throw new Error("modes is required for AdminForthAgentPlugin");
119
- }
120
- if (!this.adminforth.config.customization.globalInjections.header) {
121
- this.adminforth.config.customization.globalInjections.header = [];
122
- }
123
- this.adminforth.config.customization.globalInjections.header.push({
124
- file: this.componentPath("ChatSurface.vue"),
125
- meta: {
126
- pluginInstanceId: this.pluginInstanceId,
127
- modes: this.options.modes.map((mode) => ({ name: mode.name })),
128
- defaultModeName: this.options.modes[0].name,
129
- stickByDefault: this.options.stickByDefault ?? false,
130
- hasAudioAdapter: Boolean(this.options.audioAdapter),
131
- }
132
- });
133
- if (!this.adminforth.config.customization.customHeadItems) {
134
- this.adminforth.config.customization.customHeadItems = [];
135
- }
136
- this.adminforth.config.customization.customHeadItems.push(
137
- {
138
- tagName: 'script',
139
- attributes: {
140
- src: 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/ort.wasm.min.js'
141
- }
142
- },
143
- {
144
- tagName: 'script',
145
- attributes: {
146
- src: 'https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.29/dist/bundle.min.js'
147
- },
148
- }
149
- );
150
- if (!this.options.sessionResource) {
151
- throw new Error("sessionResource is required for AdminForthAgentPlugin");
152
- }
153
- }
154
-
155
- validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
156
- this.options.audioAdapter?.validate();
157
- for (const chatSurfaceAdapter of this.options.chatSurfaceAdapters ?? []) {
158
- chatSurfaceAdapter.validate();
159
- }
160
- this.agentSystemPromptPromise = buildAgentSystemPrompt(
161
- adminforth,
162
- this.getInternalAgentResourceIds(),
163
- )
164
- .then((systemPrompt) => {
165
- const finalPrompt = appendCustomSystemPrompt(systemPrompt, this.options.systemPrompt);
166
- this.agentSystemPrompt = finalPrompt;
167
- return finalPrompt;
168
- });
169
- }
170
-
171
- instanceUniqueRepresentation(pluginOptions: any) : string {
172
- return `single`;
173
- }
174
-
175
- setupEndpoints(server: IHttpServer) {
176
- const endpointContext = {
177
- adminforth: this.adminforth,
178
- options: this.options,
179
- handleTurn: this.agentTurnService.handleTurn.bind(this.agentTurnService),
180
- handleSpeechTurn: this.speechTurnService.handle.bind(this.speechTurnService),
181
- runAndPersistAgentResponse: this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService),
182
- getSessionTurns: this.sessionStore.getSessionTurns.bind(this.sessionStore),
183
- createNewTurn: this.sessionStore.createNewTurn.bind(this.sessionStore),
184
- createSystemTurn: this.sessionStore.createSystemTurn.bind(this.sessionStore),
185
- handleChatSurfaceMessage: this.chatSurfaceService.handleMessage.bind(this.chatSurfaceService),
186
- } satisfies AgentEndpointsContext;
187
-
188
- setupCoreEndpoints(endpointContext, server);
189
- setupSessionEndpoints(endpointContext, server);
190
- setupChatSurfaceEndpoints(endpointContext, server);
191
- }
192
- }
@@ -1,4 +0,0 @@
1
- allowBuilds:
2
- adminforth: true
3
- minimumReleaseAgeExclude:
4
- - adminforth
@@ -1,32 +0,0 @@
1
- const URL_RE = /\b(?:https?:\/\/|www\.)[^\s<>()]+/gi;
2
- const MARKDOWN_LINK_RE = /\[([^\]]+)]\(([^)]+)\)/g;
3
- const MARKDOWN_IMAGE_RE = /!\[([^\]]*)]\(([^)]+)\)/g;
4
- const HTML_TAG_RE = /<[^>]+>/g;
5
- const CODE_FENCE_RE = /```[\s\S]*?```/g;
6
- const INLINE_CODE_RE = /`[^`]*`/g;
7
- const BRACKETED_META_RE = /\[(?:ref|link|url|source|sources?|debug|meta|data):[^\]]*]/gi;
8
- const MD_HEADING_LINE_RE = /^\s{0,3}#{1,6}\s+/gm;
9
- const MD_BLOCKQUOTE_RE = /^\s{0,3}>\s?/gm;
10
- const MD_HR_RE = /^\s{0,3}(-{3,}|\*{3,}|_{3,})\s*$/gm;
11
- const MD_LIST_MARKER_RE = /^\s{0,3}(?:[-*+]|\d+\.)\s+/gm;
12
- const MD_EMPHASIS_RE = /(\*\*|__)(.*?)\1/g;
13
- const MD_ITALIC_RE = /(^|[^\\])(?:\*|_)([^\s].*?)(?:\*|_)/g;
14
-
15
- export function sanitizeSpeechText(input: string): string {
16
- return input
17
- .replace(CODE_FENCE_RE, " ")
18
- .replace(MARKDOWN_IMAGE_RE, "$1")
19
- .replace(MARKDOWN_LINK_RE, "$1")
20
- .replace(URL_RE, " ")
21
- .replace(MD_HEADING_LINE_RE, "")
22
- .replace(MD_BLOCKQUOTE_RE, "")
23
- .replace(MD_HR_RE, " ")
24
- .replace(MD_LIST_MARKER_RE, "")
25
- .replace(MD_EMPHASIS_RE, "$2")
26
- .replace(MD_ITALIC_RE, "$1$2")
27
- .replace(HTML_TAG_RE, " ")
28
- .replace(INLINE_CODE_RE, " ")
29
- .replace(BRACKETED_META_RE, " ")
30
- .replace(/\s+/g, " ")
31
- .trim();
32
- }