@adminforth/agent 2.0.10 → 2.2.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 (201) hide show
  1. package/README.md +333 -10
  2. package/dist/application/ports.d.ts +66 -0
  3. package/dist/application/runTurnUseCase.d.ts +71 -0
  4. package/dist/application/runTurnUseCase.js +364 -0
  5. package/dist/custom/ChatFooter.vue +58 -30
  6. package/dist/custom/SteerDebugPanel.vue +45 -0
  7. package/dist/custom/SteerQueue.vue +54 -0
  8. package/dist/custom/composables/agentStore/constants.ts +1 -0
  9. package/dist/custom/composables/agentStore/useAgentSessions.ts +35 -16
  10. package/dist/custom/composables/agentStore/useAgentSteerQueue.ts +114 -0
  11. package/dist/custom/composables/useAgentStore.ts +46 -1
  12. package/dist/custom/conversation_area/MessageRenderer.vue +7 -1
  13. package/dist/custom/speech_recognition_frontend/AudioLines.vue +1 -1
  14. package/dist/custom/speech_recognition_frontend/MicrophoneButon.vue +3 -3
  15. package/dist/{agentEvents.d.ts → domain/agentEvents.d.ts} +5 -1
  16. package/dist/domain/steerBuffer.d.ts +33 -0
  17. package/dist/domain/steerBuffer.js +51 -0
  18. package/dist/{agent → domain}/systemPrompt.js +1 -1
  19. package/dist/{agent/turn → domain}/turnTypes.d.ts +41 -37
  20. package/dist/{agent/turn/VegaLiteStreamBuffer.d.ts → domain/vegaLiteStreamBuffer.d.ts} +1 -1
  21. package/dist/index.d.ts +4 -2
  22. package/dist/index.js +49 -35
  23. package/dist/{agent/runtime/AgentContext.d.ts → llm/agentContext.d.ts} +3 -3
  24. package/dist/{agent/simpleAgent.d.ts → llm/agentModels.d.ts} +18 -16
  25. package/dist/llm/agentModels.js +65 -0
  26. package/dist/{agent/runtime/AgentRuntime.d.ts → llm/agentRuntime.d.ts} +14 -2
  27. package/dist/{agent/runtime/AgentRuntime.js → llm/agentRuntime.js} +41 -6
  28. package/dist/llm/langGraphLlm.d.ts +25 -0
  29. package/dist/llm/langGraphLlm.js +54 -0
  30. package/dist/{agent/middleware/apiBasedTools.d.ts → llm/middleware/apiToolsMiddleware.d.ts} +1 -1
  31. package/dist/{agent/middleware/apiBasedTools.js → llm/middleware/apiToolsMiddleware.js} +8 -14
  32. package/dist/{agent → llm}/middleware/sequenceDebug.d.ts +1 -1
  33. package/dist/llm/middleware/steerMiddleware.d.ts +21 -0
  34. package/dist/llm/middleware/steerMiddleware.js +50 -0
  35. package/dist/{agent/models/AgentModelFactory.d.ts → llm/modelFactory.d.ts} +1 -1
  36. package/dist/{agent/models/AgentModelFactory.js → llm/modelFactory.js} +1 -1
  37. package/dist/llm/streamAdapter.d.ts +18 -0
  38. package/dist/llm/streamAdapter.js +117 -0
  39. package/dist/{sessionStore.d.ts → persistence/sessionStore.d.ts} +19 -2
  40. package/dist/{sessionStore.js → persistence/sessionStore.js} +53 -0
  41. package/dist/{agent/tools/AgentToolProvider.d.ts → tools/agentToolProvider.d.ts} +1 -1
  42. package/dist/{agent/tools/AgentToolProvider.js → tools/agentToolProvider.js} +1 -1
  43. package/dist/{apiBasedTools.js → tools/apiBasedTools.js} +0 -3
  44. package/dist/{agent/tools → tools}/apiTool.d.ts +1 -1
  45. package/dist/{agent/tools → tools}/fetchSkill.js +1 -1
  46. package/dist/{agent/tools → tools}/fetchToolSchema.d.ts +1 -1
  47. package/dist/{agent/tools → tools}/index.d.ts +1 -1
  48. package/dist/{agent/tools → tools}/navigateUser.d.ts +3 -3
  49. package/dist/{endpoints → transport/http}/context.d.ts +12 -4
  50. package/dist/transport/http/context.js +1 -0
  51. package/dist/{endpoints/core.js → transport/http/coreEndpoints.js} +23 -3
  52. package/dist/{endpoints/sessions.js → transport/http/sessionEndpoints.js} +36 -1
  53. package/dist/transport/sse/sseWriter.d.ts +29 -0
  54. package/dist/{surfaces/web-sse/createSseEventEmitter.js → transport/sse/sseWriter.js} +27 -0
  55. package/dist/{chatSurfaceService.d.ts → transport/surfaces/chatSurfaceService.d.ts} +3 -3
  56. package/dist/{chatSurfaceService.js → transport/surfaces/chatSurfaceService.js} +7 -5
  57. package/dist/{agent/speech/SpeechTurnService.d.ts → transport/surfaces/speechTurnService.d.ts} +1 -1
  58. package/dist/{agent/speech/SpeechTurnService.js → transport/surfaces/speechTurnService.js} +2 -2
  59. package/dist/types.d.ts +10 -4
  60. package/package.json +11 -2
  61. package/.woodpecker/buildRelease.sh +0 -13
  62. package/.woodpecker/buildSlackNotify.sh +0 -46
  63. package/.woodpecker/release.yml +0 -57
  64. package/agent/checkpointer.ts +0 -329
  65. package/agent/languageDetect.ts +0 -92
  66. package/agent/middleware/apiBasedTools.ts +0 -174
  67. package/agent/middleware/openAiResponsesContinuation.ts +0 -92
  68. package/agent/middleware/sequenceDebug.ts +0 -429
  69. package/agent/models/AgentModeResolver.ts +0 -9
  70. package/agent/models/AgentModelFactory.ts +0 -28
  71. package/agent/runtime/AgentContext.ts +0 -30
  72. package/agent/runtime/AgentRuntime.ts +0 -89
  73. package/agent/simpleAgent.ts +0 -199
  74. package/agent/skills/registry.ts +0 -162
  75. package/agent/speech/SpeechTurnService.ts +0 -179
  76. package/agent/systemPrompt.ts +0 -133
  77. package/agent/toolCallEvents.ts +0 -135
  78. package/agent/tools/AgentToolProvider.ts +0 -28
  79. package/agent/tools/apiTool.ts +0 -66
  80. package/agent/tools/fetchSkill.ts +0 -68
  81. package/agent/tools/fetchToolSchema.ts +0 -47
  82. package/agent/tools/getUserLocation.ts +0 -45
  83. package/agent/tools/index.ts +0 -31
  84. package/agent/tools/navigateUser.ts +0 -210
  85. package/agent/turn/TurnContextBuilder.ts +0 -36
  86. package/agent/turn/TurnLifecycleService.ts +0 -47
  87. package/agent/turn/TurnPersistenceService.ts +0 -33
  88. package/agent/turn/TurnPromptBuilder.ts +0 -51
  89. package/agent/turn/TurnStreamConsumer.ts +0 -69
  90. package/agent/turn/VegaLiteStreamBuffer.ts +0 -90
  91. package/agent/turn/turnTypes.ts +0 -100
  92. package/agentEvents.ts +0 -75
  93. package/agentTurnService.ts +0 -314
  94. package/apiBasedTools.ts +0 -712
  95. package/build.log +0 -67
  96. package/chatSurfaceService.ts +0 -319
  97. package/custom/ChatFooter.vue +0 -173
  98. package/custom/ChatHeader.vue +0 -78
  99. package/custom/ChatSurface.vue +0 -160
  100. package/custom/CustomAutoScrollContainer.vue +0 -164
  101. package/custom/SessionsHistory.vue +0 -88
  102. package/custom/chat.ts +0 -82
  103. package/custom/composables/agentAudio/utils.ts +0 -220
  104. package/custom/composables/agentStore/constants.ts +0 -19
  105. package/custom/composables/agentStore/pageContext.ts +0 -8
  106. package/custom/composables/agentStore/useAgentChat.ts +0 -241
  107. package/custom/composables/agentStore/useAgentPlaceholder.ts +0 -142
  108. package/custom/composables/agentStore/useAgentSessions.ts +0 -350
  109. package/custom/composables/useAgentAudio.ts +0 -272
  110. package/custom/composables/useAgentStore.ts +0 -510
  111. package/custom/composables/useAgentTransitions.ts +0 -58
  112. package/custom/conversation_area/ConversationArea.vue +0 -301
  113. package/custom/conversation_area/MessageRenderer.vue +0 -49
  114. package/custom/conversation_area/ProcessingTimeline.vue +0 -286
  115. package/custom/conversation_area/ReasoningRenderer.vue +0 -79
  116. package/custom/conversation_area/SystemMessageRenderer.vue +0 -28
  117. package/custom/conversation_area/TextRenderer.vue +0 -182
  118. package/custom/conversation_area/ThreeDotsAnimation.vue +0 -35
  119. package/custom/conversation_area/ToolApprovalRenderer.vue +0 -98
  120. package/custom/conversation_area/ToolRenderer.vue +0 -178
  121. package/custom/conversation_area/ToolsGroup.vue +0 -59
  122. package/custom/env.d.ts +0 -7
  123. package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +0 -393
  124. package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +0 -285
  125. package/custom/incremark_code_renderers/incremarkRenderer.ts +0 -653
  126. package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +0 -118
  127. package/custom/package.json +0 -30
  128. package/custom/pnpm-lock.yaml +0 -2394
  129. package/custom/public/agentAudio/agent-processing.mp3 +0 -0
  130. package/custom/skills/analyze_data/SKILL.md +0 -25
  131. package/custom/skills/charts/SKILL.md +0 -193
  132. package/custom/skills/fetch_data/SKILL.md +0 -31
  133. package/custom/skills/mutate_data/SKILL.md +0 -121
  134. package/custom/speech_recognition_frontend/AudioLines.vue +0 -43
  135. package/custom/speech_recognition_frontend/MicrophoneButon.vue +0 -185
  136. package/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +0 -22
  137. package/custom/speech_recognition_frontend/voiceActivityDetection.ts +0 -62
  138. package/custom/tsconfig.json +0 -15
  139. package/custom/types.ts +0 -108
  140. package/custom/utils.ts +0 -38
  141. package/dist/agent/middleware/openAiResponsesContinuation.d.ts +0 -1
  142. package/dist/agent/middleware/openAiResponsesContinuation.js +0 -66
  143. package/dist/agent/models/AgentModeResolver.d.ts +0 -9
  144. package/dist/agent/models/AgentModeResolver.js +0 -9
  145. package/dist/agent/simpleAgent.js +0 -118
  146. package/dist/agent/turn/TurnContextBuilder.d.ts +0 -14
  147. package/dist/agent/turn/TurnContextBuilder.js +0 -31
  148. package/dist/agent/turn/TurnLifecycleService.d.ts +0 -24
  149. package/dist/agent/turn/TurnLifecycleService.js +0 -47
  150. package/dist/agent/turn/TurnPersistenceService.d.ts +0 -13
  151. package/dist/agent/turn/TurnPersistenceService.js +0 -35
  152. package/dist/agent/turn/TurnPromptBuilder.d.ts +0 -19
  153. package/dist/agent/turn/TurnPromptBuilder.js +0 -43
  154. package/dist/agent/turn/TurnStreamConsumer.d.ts +0 -11
  155. package/dist/agent/turn/TurnStreamConsumer.js +0 -84
  156. package/dist/agentTurnService.d.ts +0 -24
  157. package/dist/agentTurnService.js +0 -269
  158. package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +0 -14
  159. package/endpoints/chatSurfaces.ts +0 -66
  160. package/endpoints/context.ts +0 -52
  161. package/endpoints/core.ts +0 -181
  162. package/endpoints/sessions.ts +0 -183
  163. package/errors.ts +0 -10
  164. package/index.ts +0 -192
  165. package/pnpm-workspace.yaml +0 -4
  166. package/sanitizeSpeechText.ts +0 -32
  167. package/sessionStore.ts +0 -105
  168. package/surfaces/web-sse/createSseEventEmitter.ts +0 -311
  169. package/tsconfig.json +0 -14
  170. package/types.ts +0 -127
  171. /package/dist/{agent/turn/turnTypes.js → application/ports.js} +0 -0
  172. /package/dist/{agentEvents.js → domain/agentEvents.js} +0 -0
  173. /package/dist/{agent → domain}/languageDetect.d.ts +0 -0
  174. /package/dist/{agent → domain}/languageDetect.js +0 -0
  175. /package/dist/{agent → domain}/systemPrompt.d.ts +0 -0
  176. /package/dist/{agent → domain}/toolCallEvents.d.ts +0 -0
  177. /package/dist/{agent → domain}/toolCallEvents.js +0 -0
  178. /package/dist/{endpoints/context.js → domain/turnTypes.js} +0 -0
  179. /package/dist/{agent/turn/VegaLiteStreamBuffer.js → domain/vegaLiteStreamBuffer.js} +0 -0
  180. /package/dist/{agent/runtime/AgentContext.js → llm/agentContext.js} +0 -0
  181. /package/dist/{agent → llm}/middleware/sequenceDebug.js +0 -0
  182. /package/dist/{agent/checkpointer.d.ts → persistence/checkpointStore.d.ts} +0 -0
  183. /package/dist/{agent/checkpointer.js → persistence/checkpointStore.js} +0 -0
  184. /package/dist/{errors.d.ts → shared/errors.d.ts} +0 -0
  185. /package/dist/{errors.js → shared/errors.js} +0 -0
  186. /package/dist/{sanitizeSpeechText.d.ts → shared/sanitizeSpeechText.d.ts} +0 -0
  187. /package/dist/{sanitizeSpeechText.js → shared/sanitizeSpeechText.js} +0 -0
  188. /package/dist/{apiBasedTools.d.ts → tools/apiBasedTools.d.ts} +0 -0
  189. /package/dist/{agent/tools → tools}/apiTool.js +0 -0
  190. /package/dist/{agent/tools → tools}/fetchSkill.d.ts +0 -0
  191. /package/dist/{agent/tools → tools}/fetchToolSchema.js +0 -0
  192. /package/dist/{agent/tools → tools}/getUserLocation.d.ts +0 -0
  193. /package/dist/{agent/tools → tools}/getUserLocation.js +0 -0
  194. /package/dist/{agent/tools → tools}/index.js +0 -0
  195. /package/dist/{agent/tools → tools}/navigateUser.js +0 -0
  196. /package/dist/{agent → tools}/skills/registry.d.ts +0 -0
  197. /package/dist/{agent → tools}/skills/registry.js +0 -0
  198. /package/dist/{endpoints/chatSurfaces.d.ts → transport/http/chatSurfaceEndpoints.d.ts} +0 -0
  199. /package/dist/{endpoints/chatSurfaces.js → transport/http/chatSurfaceEndpoints.js} +0 -0
  200. /package/dist/{endpoints/core.d.ts → transport/http/coreEndpoints.d.ts} +0 -0
  201. /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
- }