@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
@@ -385,7 +385,6 @@ function callOpenApiSchema(params) {
385
385
  return validationErrorResponse('REQUEST_VALIDATION_FAILED', requestValidation.errors);
386
386
  }
387
387
  const response = createDirectToolResponse();
388
- logger.info(`Calling OpenAPI tool "${toolName}" with direct handler`);
389
388
  const lang = acceptLanguage !== null && acceptLanguage !== void 0 ? acceptLanguage : "en";
390
389
  const tr = (msg, category, trParams, pluralizationNumber) => adminforth.tr(msg, category, lang, trParams, pluralizationNumber);
391
390
  const output = yield withToolHandlerTimeout((handlerAbortSignal) => schema.handler({
@@ -432,6 +431,12 @@ function callOpenApiSchema(params) {
432
431
  function stringifyToolOutput(output) {
433
432
  return YAML.stringify(output === undefined ? EMPTY_HANDLER_RESPONSE_ERROR : output);
434
433
  }
434
+ function attachDurationMs(output, durationMs) {
435
+ if (output !== null && typeof output === 'object' && !Array.isArray(output)) {
436
+ return Object.assign(Object.assign({}, output), { durationMs });
437
+ }
438
+ return { result: output, durationMs };
439
+ }
435
440
  export function prepareApiBasedTools(adminforth, hiddenResourceIds = []) {
436
441
  const apiBasedTools = {};
437
442
  const openApiSchemas = adminforth.openApi.registeredSchemas;
@@ -443,19 +448,18 @@ export function prepareApiBasedTools(adminforth, hiddenResourceIds = []) {
443
448
  openApiSchemasByToolName.set(toolName, schema);
444
449
  }
445
450
  }
446
- logger.info(`AdminForth Agent OpenAPI APIs: ${formatLogNameList(adminforth.openApi.registeredSchemas.map((schema) => openApiSchemaPathToToolName(schema.path, adminforth)))}`);
447
- logger.info(`AdminForth Agent OpenAPI tools connected: ${formatLogNameList([...openApiSchemasByToolName.keys()])}`);
448
451
  for (const [toolName, schema] of openApiSchemasByToolName.entries()) {
449
452
  apiBasedTools[toolName] = {
450
453
  description: schema.description,
451
454
  input_schema: schema.request_schema,
452
455
  agent: schema.agent,
453
456
  call: (...args_1) => __awaiter(this, [...args_1], void 0, function* ({ adminUser, adminuser, abortSignal, inputs, userTimeZone, acceptLanguage } = {}) {
457
+ const startedAt = Date.now();
454
458
  if (isHiddenResourceCall(hiddenResourceIdSet, inputs)) {
455
- return stringifyToolOutput({
459
+ return stringifyToolOutput(attachDurationMs({
456
460
  error: 'RESOURCE_NOT_AVAILABLE',
457
461
  message: 'This resource is not available to the agent.',
458
- });
462
+ }, Date.now() - startedAt));
459
463
  }
460
464
  const output = yield callOpenApiSchema({
461
465
  adminforth,
@@ -475,7 +479,7 @@ export function prepareApiBasedTools(adminforth, hiddenResourceIds = []) {
475
479
  toolName,
476
480
  userTimeZone,
477
481
  });
478
- return stringifyToolOutput(processedOutput);
482
+ return stringifyToolOutput(attachDurationMs(processedOutput, Date.now() - startedAt));
479
483
  }),
480
484
  };
481
485
  }
@@ -1,4 +1,4 @@
1
- import type { ApiBasedTool } from "../../apiBasedTools.js";
1
+ import type { ApiBasedTool } from "./apiBasedTools.js";
2
2
  export declare function createApiTool(toolName: string, apiBasedTool: ApiBasedTool): import("langchain").DynamicStructuredTool<Record<string, unknown> | {
3
3
  readonly type: "object";
4
4
  readonly properties: {};
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { tool } from "langchain";
11
11
  import { z } from "zod";
12
- import { listSkillManifests, loadSkillMarkdown, } from "../skills/registry.js";
12
+ import { listSkillManifests, loadSkillMarkdown, } from "./skills/registry.js";
13
13
  const fetchSkillSchema = z.object({
14
14
  skillName: z
15
15
  .string()
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import type { ApiBasedTool } from "../../apiBasedTools.js";
2
+ import type { ApiBasedTool } from "./apiBasedTools.js";
3
3
  export declare function createFetchToolSchemaTool(apiBasedTools: Record<string, ApiBasedTool>): Promise<import("langchain").DynamicStructuredTool<z.ZodObject<{
4
4
  toolName: z.ZodString;
5
5
  }, z.core.$strip>, {
@@ -1,4 +1,4 @@
1
1
  import type { ClientTool } from "@langchain/core/tools";
2
- import type { ApiBasedTool } from "../../apiBasedTools.js";
2
+ import type { ApiBasedTool } from "./apiBasedTools.js";
3
3
  export declare const ALWAYS_AVAILABLE_API_TOOL_NAMES: readonly ["get_resource"];
4
4
  export declare function createAgentTools(customComponentsDir: string, apiBasedTools: Record<string, ApiBasedTool>, pluginCustomFolderPaths?: string[]): Promise<ClientTool[]>;
@@ -17,8 +17,8 @@ export declare function createNavigateUserTool(): import("langchain").DynamicStr
17
17
  sort: z.ZodOptional<z.ZodObject<{
18
18
  column: z.ZodString;
19
19
  direction: z.ZodEnum<{
20
- asc: "asc";
21
20
  desc: "desc";
21
+ asc: "asc";
22
22
  }>;
23
23
  }, z.core.$strip>>;
24
24
  query: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
@@ -34,7 +34,7 @@ export declare function createNavigateUserTool(): import("langchain").DynamicStr
34
34
  }[] | undefined;
35
35
  sort?: {
36
36
  column: string;
37
- direction: "asc" | "desc";
37
+ direction: "desc" | "asc";
38
38
  } | undefined;
39
39
  query?: Record<string, string | number | boolean> | undefined;
40
40
  }, {
@@ -49,7 +49,7 @@ export declare function createNavigateUserTool(): import("langchain").DynamicStr
49
49
  }[] | undefined;
50
50
  sort?: {
51
51
  column: string;
52
- direction: "asc" | "desc";
52
+ direction: "desc" | "asc";
53
53
  } | undefined;
54
54
  query?: Record<string, string | number | boolean> | undefined;
55
55
  }, string, unknown, "navigate_user">;
@@ -1,6 +1,6 @@
1
1
  import type { ChatSurfaceAdapter, ChatSurfaceEventSink, ChatSurfaceIncomingMessage, IAdminForth } from "adminforth";
2
- import type { HandleSpeechTurnInput, HandleTurnInput, RunAndPersistAgentResponseInput, RunAndPersistAgentResponseResult } from "../agentTurnService.js";
3
- import type { PluginOptions } from "../types.js";
2
+ import type { HandleSpeechTurnInput, HandleTurnInput, RunAndPersistAgentResponseInput, RunAndPersistAgentResponseResult } from "../../domain/turnTypes.js";
3
+ import type { PluginOptions } from "../../types.js";
4
4
  export type SessionTurn = {
5
5
  prompt: string;
6
6
  response: string;
@@ -0,0 +1 @@
1
+ export {};
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { z } from "zod";
11
- import { createSseEventEmitter } from "../surfaces/web-sse/createSseEventEmitter.js";
11
+ import { createSseEventEmitter } from "../sse/sseWriter.js";
12
12
  const currentPageContextSchema = z.object({
13
13
  path: z.string(),
14
14
  fullPath: z.string(),
@@ -77,7 +77,7 @@ export function setupCoreEndpoints(ctx, server) {
77
77
  method: 'POST',
78
78
  path: `/agent/response`,
79
79
  request_schema: agentResponseBodySchema,
80
- handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, _raw_express_res, abortSignal }) {
80
+ handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, _raw_express_res, abortSignal }) {
81
81
  var _b;
82
82
  const data = body;
83
83
  const emit = createSseEventEmitter(_raw_express_res, {
@@ -103,7 +103,7 @@ export function setupCoreEndpoints(ctx, server) {
103
103
  method: 'POST',
104
104
  path: `/agent/approval`,
105
105
  request_schema: agentApprovalBodySchema,
106
- handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, _raw_express_res, abortSignal }) {
106
+ handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, _raw_express_res, abortSignal }) {
107
107
  const data = body;
108
108
  const emit = createSseEventEmitter(_raw_express_res, {
109
109
  vercelAiUiMessageStream: true,
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { Filters, Sorts } from "adminforth";
11
11
  import { randomUUID } from "crypto";
12
12
  import { z } from "zod";
13
- import { AGENT_SYSTEM_TURN_PROMPT } from "../sessionStore.js";
13
+ import { AGENT_SYSTEM_TURN_PROMPT } from "../../persistence/sessionStore.js";
14
14
  const addSystemMessageBodySchema = z.object({
15
15
  sessionId: z.string(),
16
16
  systemMessage: z.string(),
@@ -54,11 +54,13 @@ export function setupSessionEndpoints(ctx, server) {
54
54
  const sessionId = data.sessionId;
55
55
  const session = yield ctx.adminforth.resource(ctx.options.sessionResource.resourceId).get([Filters.EQ(ctx.options.sessionResource.idField, sessionId)]);
56
56
  if (!session) {
57
+ response.setStatus(404, 'Session not found');
57
58
  return {
58
59
  error: 'Session not found'
59
60
  };
60
61
  }
61
62
  if (session[ctx.options.sessionResource.askerIdField] !== userId) {
63
+ response.setStatus(403, 'Unauthorized');
62
64
  return {
63
65
  error: 'Unauthorized'
64
66
  };
@@ -129,11 +131,13 @@ export function setupSessionEndpoints(ctx, server) {
129
131
  const userId = adminUser.pk;
130
132
  const session = yield ctx.adminforth.resource(ctx.options.sessionResource.resourceId).get([Filters.EQ(ctx.options.sessionResource.idField, sessionId)]);
131
133
  if (!session) {
134
+ response.setStatus(404, 'Session not found');
132
135
  return {
133
136
  error: 'Session not found'
134
137
  };
135
138
  }
136
139
  if (session[ctx.options.sessionResource.askerIdField] !== userId) {
140
+ response.setStatus(403, 'Unauthorized');
137
141
  return {
138
142
  error: 'Unauthorized'
139
143
  };
@@ -154,11 +158,13 @@ export function setupSessionEndpoints(ctx, server) {
154
158
  const data = body;
155
159
  const session = yield ctx.adminforth.resource(ctx.options.sessionResource.resourceId).get([Filters.EQ(ctx.options.sessionResource.idField, data.sessionId)]);
156
160
  if (!session) {
161
+ response.setStatus(404, 'Session not found');
157
162
  return {
158
163
  error: 'Session not found'
159
164
  };
160
165
  }
161
166
  if (session[ctx.options.sessionResource.askerIdField] !== adminUser.pk) {
167
+ response.setStatus(403, 'Unauthorized');
162
168
  return {
163
169
  error: 'Unauthorized'
164
170
  };
@@ -0,0 +1,29 @@
1
+ import type { AgentEventEmitter } from "../../domain/agentEvents.js";
2
+ type AgentEventStreamResponse = {
3
+ writeHead: (statusCode: number, headers: Record<string, string>) => void;
4
+ write: (chunk: string) => unknown;
5
+ end: () => unknown;
6
+ writableEnded: boolean;
7
+ destroyed: boolean;
8
+ };
9
+ type AgentEventStreamOptions = {
10
+ vercelAiUiMessageStream?: boolean;
11
+ closeActiveBlockOnToolStart?: boolean;
12
+ };
13
+ /**
14
+ * Maps the internal {@link AgentEvent} vocabulary onto the two Server-Sent-Events
15
+ * wire dialects the frontend consumes. Both dialects are HARD external contracts —
16
+ * do not change frame names/shapes without updating the corresponding consumer:
17
+ *
18
+ * - `vercelAiUiMessageStream: true` (used by `/agent/response` and `/agent/approval`):
19
+ * the Vercel AI SDK message-stream v1 format (`start`, `text-start`/`text-delta`/
20
+ * `text-end`, `reasoning-*`, `data-*` parts, `error` with `errorText`, `finish`,
21
+ * `[DONE]`). Consumed by `DefaultChatTransport` and the manual approval parser in
22
+ * `custom/composables/agentStore/useAgentChat.ts`.
23
+ * - default (used by `/agent/speech-response`): bare event names
24
+ * (`transcript`, `speech-response`, `audio-start`/`audio-delta`/`audio-done`,
25
+ * `open-page`, `error`) plus the Vercel-shaped `data-tool-call`. Consumed by
26
+ * `custom/composables/useAgentAudio.ts`.
27
+ */
28
+ export declare function createSseEventEmitter(res: AgentEventStreamResponse, options?: AgentEventStreamOptions): AgentEventEmitter;
29
+ export {};
@@ -185,6 +185,21 @@ function createAgentEventStream(res, options = {}) {
185
185
  };
186
186
  return stream;
187
187
  }
188
+ /**
189
+ * Maps the internal {@link AgentEvent} vocabulary onto the two Server-Sent-Events
190
+ * wire dialects the frontend consumes. Both dialects are HARD external contracts —
191
+ * do not change frame names/shapes without updating the corresponding consumer:
192
+ *
193
+ * - `vercelAiUiMessageStream: true` (used by `/agent/response` and `/agent/approval`):
194
+ * the Vercel AI SDK message-stream v1 format (`start`, `text-start`/`text-delta`/
195
+ * `text-end`, `reasoning-*`, `data-*` parts, `error` with `errorText`, `finish`,
196
+ * `[DONE]`). Consumed by `DefaultChatTransport` and the manual approval parser in
197
+ * `custom/composables/agentStore/useAgentChat.ts`.
198
+ * - default (used by `/agent/speech-response`): bare event names
199
+ * (`transcript`, `speech-response`, `audio-start`/`audio-delta`/`audio-done`,
200
+ * `open-page`, `error`) plus the Vercel-shaped `data-tool-call`. Consumed by
201
+ * `custom/composables/useAgentAudio.ts`.
202
+ */
188
203
  export function createSseEventEmitter(res, options = {}) {
189
204
  const stream = createAgentEventStream(res, options);
190
205
  return (event) => __awaiter(this, void 0, void 0, function* () {
@@ -1,7 +1,7 @@
1
1
  import type { ChatSurfaceAdapter, ChatSurfaceEventSink, ChatSurfaceIncomingMessage, IAdminForth } from "adminforth";
2
- import type { HandleTurnInput, RunAndPersistAgentResponseInput, RunAndPersistAgentResponseResult } from "./agentTurnService.js";
3
- import type { AgentSessionStore } from "./sessionStore.js";
4
- import type { PluginOptions } from "./types.js";
2
+ import type { HandleTurnInput, RunAndPersistAgentResponseInput, RunAndPersistAgentResponseResult } from "../../domain/turnTypes.js";
3
+ import type { AgentSessionStore } from "../../persistence/sessionStore.js";
4
+ import type { PluginOptions } from "../../types.js";
5
5
  export declare class ChatSurfaceService {
6
6
  private getAdminforth;
7
7
  private options;
@@ -8,8 +8,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { Filters, logger } from "adminforth";
11
- import { getErrorMessage, isAbortError } from "./errors.js";
12
- import { sanitizeSpeechText } from "./sanitizeSpeechText.js";
11
+ import { getErrorMessage, isAbortError } from "../../shared/errors.js";
12
+ import { sanitizeSpeechText } from "../../shared/sanitizeSpeechText.js";
13
13
  export class ChatSurfaceService {
14
14
  constructor(getAdminforth, options, sessionStore, handleTurn, runAndPersistAgentResponse) {
15
15
  this.getAdminforth = getAdminforth;
@@ -35,9 +35,11 @@ export class ChatSurfaceService {
35
35
  return;
36
36
  }
37
37
  if (event.type === "error") {
38
+ // Full error detail is logged server-side (see runAndPersistAgentResponse);
39
+ // external chat users receive a generic message to avoid leaking internals.
38
40
  yield sink.emit({
39
41
  type: "error",
40
- message: event.error,
42
+ message: "Agent response failed. Check server logs for details.",
41
43
  });
42
44
  }
43
45
  });
@@ -122,7 +124,7 @@ export class ChatSurfaceService {
122
124
  logger.error(`Agent ${incoming.surface} surface speech synthesis failed:\n${getErrorMessage(error)}`);
123
125
  yield sink.emit({
124
126
  type: "error",
125
- message: getErrorMessage(error),
127
+ message: "Speech synthesis failed. Check server logs for details.",
126
128
  });
127
129
  }
128
130
  });
@@ -165,7 +167,7 @@ export class ChatSurfaceService {
165
167
  if (agentResponse.failed) {
166
168
  yield sink.emit({
167
169
  type: "error",
168
- message: agentResponse.text,
170
+ message: "Agent response failed. Check server logs for details.",
169
171
  });
170
172
  }
171
173
  return agentResponse;
@@ -1,4 +1,4 @@
1
- import type { RunAndPersistAgentResponseInput, RunAndPersistAgentResponseResult, SpeechAgentTurnInput } from "../turn/turnTypes.js";
1
+ import type { RunAndPersistAgentResponseInput, RunAndPersistAgentResponseResult, SpeechAgentTurnInput } from "../../domain/turnTypes.js";
2
2
  export declare class SpeechTurnService {
3
3
  private readonly runAndPersistAgentResponse;
4
4
  constructor(runAndPersistAgentResponse: (input: RunAndPersistAgentResponseInput) => Promise<RunAndPersistAgentResponseResult>);
@@ -8,8 +8,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { logger } from "adminforth";
11
- import { getErrorMessage, isAbortError } from "../../errors.js";
12
- import { sanitizeSpeechText } from "../../sanitizeSpeechText.js";
11
+ import { getErrorMessage, isAbortError } from "../../shared/errors.js";
12
+ import { sanitizeSpeechText } from "../../shared/sanitizeSpeechText.js";
13
13
  export class SpeechTurnService {
14
14
  constructor(runAndPersistAgentResponse) {
15
15
  this.runAndPersistAgentResponse = runAndPersistAgentResponse;
package/dist/types.d.ts CHANGED
@@ -1,10 +1,15 @@
1
1
  import { type PluginsCommonOptions, type AdminUser, type HttpExtra, type AudioAdapter, type ChatSurfaceAdapter } from "adminforth";
2
- import type { AgentModeCompletionAdapter } from "./agent/simpleAgent.js";
2
+ import type { AgentModeCompletionAdapter } from "./application/ports.js";
3
3
  interface ISessionResource {
4
4
  resourceId: string;
5
5
  idField: string;
6
6
  titleField: string;
7
- turnsField: string;
7
+ /**
8
+ * @deprecated Not used by the plugin — session turns are looked up via
9
+ * `turnResource.sessionIdField`. Kept optional for backward compatibility;
10
+ * will be removed in a future major version.
11
+ */
12
+ turnsField?: string;
8
13
  askerIdField: string;
9
14
  createdAtField: string;
10
15
  }
@@ -69,8 +74,9 @@ export interface PluginOptions extends PluginsCommonOptions {
69
74
  */
70
75
  systemPrompt?: string;
71
76
  /**
72
- * Response generation level.
73
- * Default is low
77
+ * @deprecated Not applied — reasoning effort is configured on the completion
78
+ * adapter (e.g. `extraRequestBodyParameters.reasoning.effort`), not here.
79
+ * Kept for backward compatibility; will be removed in a future major version.
74
80
  */
75
81
  reasoning?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh";
76
82
  /**
package/package.json CHANGED
@@ -1,15 +1,21 @@
1
1
  {
2
2
  "name": "@adminforth/agent",
3
- "version": "2.0.9",
3
+ "version": "2.1.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
7
+ "files": [
8
+ "dist",
9
+ "README.md",
10
+ "LICENSE"
11
+ ],
7
12
  "homepage": "https://adminforth.dev/docs/tutorial/Plugins/agent/",
8
13
  "publishConfig": {
9
14
  "access": "public"
10
15
  },
11
16
  "scripts": {
12
- "build": "tsc && rsync -av --exclude 'node_modules' custom dist/"
17
+ "build": "tsc && rsync -av --exclude 'node_modules' custom dist/",
18
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand"
13
19
  },
14
20
  "keywords": [
15
21
  "adminforth",
@@ -24,10 +30,13 @@
24
30
  "license": "MIT",
25
31
  "description": "AI agent plugin for AdminForth with tool-based workflows and persistent chat sessions",
26
32
  "devDependencies": {
33
+ "@types/jest": "^30.0.0",
27
34
  "@types/node": "latest",
28
35
  "adminforth": "^3.8.2",
36
+ "jest": "^30.3.0",
29
37
  "semantic-release": "^24.2.1",
30
38
  "semantic-release-slack-bot": "^4.0.2",
39
+ "ts-jest": "^29.4.6",
31
40
  "typescript": "^5.7.3"
32
41
  },
33
42
  "dependencies": {
@@ -1,13 +0,0 @@
1
-
2
- #!/bin/bash
3
-
4
- # write npm run output both to console and to build.log
5
- npm run build 2>&1 | tee build.log
6
- build_status=${PIPESTATUS[0]}
7
-
8
- # if exist status from the npm run build is not 0
9
- # then exit with the status code from the npm run build
10
- if [ $build_status -ne 0 ]; then
11
- echo "Build failed. Exiting with status code $build_status"
12
- exit $build_status
13
- fi
@@ -1,46 +0,0 @@
1
- #!/bin/sh
2
-
3
- set -x
4
-
5
- COMMIT_SHORT_SHA=$(echo $CI_COMMIT_SHA | cut -c1-8)
6
-
7
- STATUS=${1}
8
-
9
-
10
- if [ "$STATUS" = "success" ]; then
11
- MESSAGE="Did a build without issues on \`$CI_REPO_NAME/$CI_COMMIT_BRANCH\`. Commit: _${CI_COMMIT_MESSAGE}_ (<$CI_COMMIT_URL|$COMMIT_SHORT_SHA>)"
12
-
13
- curl -s -X POST -H "Content-Type: application/json" -d '{
14
- "username": "'"$CI_COMMIT_AUTHOR"'",
15
- "icon_url": "'"$CI_COMMIT_AUTHOR_AVATAR"'",
16
- "attachments": [
17
- {
18
- "mrkdwn_in": ["text", "pretext"],
19
- "color": "#36a64f",
20
- "text": "'"$MESSAGE"'"
21
- }
22
- ]
23
- }' "$DEVELOPERS_SLACK_WEBHOOK"
24
- exit 0
25
- fi
26
- export BUILD_LOG=$(cat ./build.log)
27
-
28
- BUILD_LOG=$(echo $BUILD_LOG | sed 's/"/\\"/g')
29
-
30
- MESSAGE="Broke \`$CI_REPO_NAME/$CI_COMMIT_BRANCH\` with commit _${CI_COMMIT_MESSAGE}_ (<$CI_COMMIT_URL|$COMMIT_SHORT_SHA>)"
31
- CODE_BLOCK="\`\`\`$BUILD_LOG\n\`\`\`"
32
-
33
- echo "Sending slack message to developers $MESSAGE"
34
- # Send the message
35
- curl -sS -X POST -H "Content-Type: application/json" -d '{
36
- "username": "'"$CI_COMMIT_AUTHOR"'",
37
- "icon_url": "'"$CI_COMMIT_AUTHOR_AVATAR"'",
38
- "attachments": [
39
- {
40
- "mrkdwn_in": ["text", "pretext"],
41
- "color": "#8A1C12",
42
- "text": "'"$CODE_BLOCK"'",
43
- "pretext": "'"$MESSAGE"'"
44
- }
45
- ]
46
- }' "$DEVELOPERS_SLACK_WEBHOOK" 2>&1
@@ -1,57 +0,0 @@
1
- clone:
2
- git:
3
- image: woodpeckerci/plugin-git
4
- settings:
5
- partial: false
6
- depth: 5
7
-
8
- steps:
9
- init-secrets:
10
- when:
11
- - event: push
12
- image: infisical/cli
13
- environment:
14
- INFISICAL_TOKEN:
15
- from_secret: VAULT_TOKEN
16
- commands:
17
- - infisical export --domain https://vault.devforth.io/api --format=dotenv-export --env="prod" > /woodpecker/deploy.vault.env
18
-
19
- build:
20
- image: devforth/node20-pnpm:latest
21
- when:
22
- - event: push
23
- commands:
24
- - apt update && apt install -y rsync
25
- - . /woodpecker/deploy.vault.env
26
- - pnpm install
27
- - /bin/bash ./.woodpecker/buildRelease.sh
28
- - npm audit signatures
29
-
30
- release:
31
- image: devforth/node20-pnpm:latest
32
- when:
33
- - event:
34
- - push
35
- branch:
36
- - main
37
- commands:
38
- - . /woodpecker/deploy.vault.env
39
- - pnpm exec semantic-release
40
-
41
- slack-on-failure:
42
- image: curlimages/curl
43
- when:
44
- - event: push
45
- status: [failure]
46
- commands:
47
- - . /woodpecker/deploy.vault.env
48
- - /bin/sh ./.woodpecker/buildSlackNotify.sh failure
49
-
50
- slack-on-success:
51
- image: curlimages/curl
52
- when:
53
- - event: push
54
- status: [success]
55
- commands:
56
- - . /woodpecker/deploy.vault.env
57
- - /bin/sh ./.woodpecker/buildSlackNotify.sh success