@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/dist/index.js CHANGED
@@ -7,26 +7,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { AdminForthPlugin } from "adminforth";
10
+ import { AdminForthPlugin, logger } from "adminforth";
11
11
  import { MemorySaver } from "@langchain/langgraph";
12
- import { AdminForthCheckpointSaver } from "./agent/checkpointer.js";
13
- import { appendCustomSystemPrompt, buildAgentSystemPrompt, DEFAULT_AGENT_SYSTEM_PROMPT } from "./agent/systemPrompt.js";
14
- import { setupCoreEndpoints } from "./endpoints/core.js";
15
- import { setupSessionEndpoints } from "./endpoints/sessions.js";
16
- import { setupChatSurfaceEndpoints } from "./endpoints/chatSurfaces.js";
17
- import { AgentSessionStore } from "./sessionStore.js";
18
- import { ChatSurfaceService } from "./chatSurfaceService.js";
19
- import { AgentTurnService } from "./agentTurnService.js";
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";
12
+ import { AdminForthCheckpointSaver } from "./persistence/checkpointStore.js";
13
+ import { appendCustomSystemPrompt, buildAgentSystemPrompt, DEFAULT_AGENT_SYSTEM_PROMPT } from "./domain/systemPrompt.js";
14
+ import { setupCoreEndpoints } from "./transport/http/coreEndpoints.js";
15
+ import { setupSessionEndpoints } from "./transport/http/sessionEndpoints.js";
16
+ import { setupChatSurfaceEndpoints } from "./transport/http/chatSurfaceEndpoints.js";
17
+ import { AgentSessionStore } from "./persistence/sessionStore.js";
18
+ import { ChatSurfaceService } from "./transport/surfaces/chatSurfaceService.js";
19
+ import { RunTurnUseCase } from "./application/runTurnUseCase.js";
20
+ import { createSequenceDebugCollector } from "./llm/middleware/sequenceDebug.js";
21
+ import { LangGraphLlm } from "./llm/langGraphLlm.js";
22
+ import { AgentModelFactory } from "./llm/modelFactory.js";
23
+ import { AgentRuntime } from "./llm/agentRuntime.js";
24
+ import { SpeechTurnService } from "./transport/surfaces/speechTurnService.js";
25
+ import { AgentToolProvider } from "./tools/agentToolProvider.js";
26
+ import { SteerBuffer } from "./domain/steerBuffer.js";
30
27
  export default class AdminForthAgentPlugin extends AdminForthPlugin {
31
28
  getCheckpointer() {
32
29
  if (this.checkpointer)
@@ -44,6 +41,18 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
44
41
  (_a = this.options.checkpointResource) === null || _a === void 0 ? void 0 : _a.resourceId,
45
42
  ].filter((resourceId) => Boolean(resourceId));
46
43
  }
44
+ getAgentSystemPrompt() {
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ if (!this.agentSystemPrompt) {
47
+ const systemPrompt = yield buildAgentSystemPrompt(this.adminforth, this.getInternalAgentResourceIds()).catch((err) => {
48
+ logger.error(`Failed to build agent system prompt, falling back to default: ${err instanceof Error ? err.message : String(err)}`);
49
+ return DEFAULT_AGENT_SYSTEM_PROMPT;
50
+ });
51
+ this.agentSystemPrompt = appendCustomSystemPrompt(systemPrompt, this.options.systemPrompt);
52
+ }
53
+ return this.agentSystemPrompt;
54
+ });
55
+ }
47
56
  constructor(options) {
48
57
  var _a;
49
58
  super(options, import.meta.url);
@@ -52,28 +61,28 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
52
61
  this.checkpointer = null;
53
62
  this.options = options;
54
63
  this.sessionStore = new AgentSessionStore(() => this.adminforth, this.options);
64
+ this.steerBuffer = new SteerBuffer();
55
65
  const toolProvider = new AgentToolProvider(() => this.adminforth, this.getInternalAgentResourceIds.bind(this));
56
66
  const runtime = new AgentRuntime({
57
67
  name: `adminforth-agent-${this.pluginInstanceId}`,
58
68
  getAdminforth: () => this.adminforth,
59
69
  getCheckpointer: this.getCheckpointer.bind(this),
60
70
  toolProvider,
71
+ steerBuffer: this.steerBuffer,
61
72
  });
62
- const persistence = new TurnPersistenceService(() => this.adminforth, this.options);
63
- this.agentTurnService = new AgentTurnService(new TurnLifecycleService(this.sessionStore, persistence, this.options), new TurnContextBuilder(() => this.adminforth), new AgentModeResolver(this.options), new AgentModelFactory((_a = this.options.maxTokens) !== null && _a !== void 0 ? _a : 1000), new TurnPromptBuilder({
73
+ const llm = new LangGraphLlm(runtime, new AgentModelFactory((_a = this.options.maxTokens) !== null && _a !== void 0 ? _a : 1000));
74
+ this.runTurnUseCase = new RunTurnUseCase({
75
+ llm,
76
+ sessions: this.sessionStore,
77
+ steerBuffer: this.steerBuffer,
78
+ modes: this.options.modes,
64
79
  getAdminforth: () => this.adminforth,
65
- getAgentSystemPrompt: () => __awaiter(this, void 0, void 0, function* () {
66
- if (!this.agentSystemPrompt) {
67
- const systemPrompt = yield buildAgentSystemPrompt(this.adminforth, this.getInternalAgentResourceIds()).catch((err) => {
68
- return DEFAULT_AGENT_SYSTEM_PROMPT;
69
- });
70
- this.agentSystemPrompt = appendCustomSystemPrompt(systemPrompt, this.options.systemPrompt);
71
- }
72
- return this.agentSystemPrompt;
73
- }),
74
- }), runtime, new TurnStreamConsumer());
75
- this.speechTurnService = new SpeechTurnService(this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService));
76
- this.chatSurfaceService = new ChatSurfaceService(() => this.adminforth, this.options, this.sessionStore, this.agentTurnService.handleTurn.bind(this.agentTurnService), this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService));
80
+ getAgentSystemPrompt: this.getAgentSystemPrompt.bind(this),
81
+ hasPersistentCheckpointer: Boolean(this.options.checkpointResource),
82
+ createDebugSink: createSequenceDebugCollector,
83
+ });
84
+ this.speechTurnService = new SpeechTurnService(this.runTurnUseCase.runAndPersistAgentResponse.bind(this.runTurnUseCase));
85
+ this.chatSurfaceService = new ChatSurfaceService(() => this.adminforth, this.options, this.sessionStore, this.runTurnUseCase.handleTurn.bind(this.runTurnUseCase), this.runTurnUseCase.runAndPersistAgentResponse.bind(this.runTurnUseCase));
77
86
  this.agentSystemPromptPromise = Promise.resolve(appendCustomSystemPrompt(DEFAULT_AGENT_SYSTEM_PROMPT, this.options.systemPrompt));
78
87
  this.shouldHaveSingleInstancePerWholeApp = () => false;
79
88
  }
@@ -139,12 +148,17 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
139
148
  const endpointContext = {
140
149
  adminforth: this.adminforth,
141
150
  options: this.options,
142
- handleTurn: this.agentTurnService.handleTurn.bind(this.agentTurnService),
151
+ handleTurn: this.runTurnUseCase.handleTurn.bind(this.runTurnUseCase),
143
152
  handleSpeechTurn: this.speechTurnService.handle.bind(this.speechTurnService),
144
- runAndPersistAgentResponse: this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService),
153
+ steer: ({ sessionId, message }) => {
154
+ const { id } = this.steerBuffer.add(sessionId, message);
155
+ return { id, queued: this.steerBuffer.size(sessionId) };
156
+ },
157
+ runAndPersistAgentResponse: this.runTurnUseCase.runAndPersistAgentResponse.bind(this.runTurnUseCase),
145
158
  getSessionTurns: this.sessionStore.getSessionTurns.bind(this.sessionStore),
146
159
  createNewTurn: this.sessionStore.createNewTurn.bind(this.sessionStore),
147
160
  createSystemTurn: this.sessionStore.createSystemTurn.bind(this.sessionStore),
161
+ appendSteerToCurrentTurn: this.sessionStore.appendSteerToCurrentTurn.bind(this.sessionStore),
148
162
  handleChatSurfaceMessage: this.chatSurfaceService.handleMessage.bind(this.chatSurfaceService),
149
163
  };
150
164
  setupCoreEndpoints(endpointContext, server);
@@ -1,9 +1,9 @@
1
1
  import type { AdminUser } from "adminforth";
2
2
  import { z } from "zod";
3
- import type { AgentEventEmitter } from "../../agentEvents.js";
4
- import type { SequenceDebugCollector } from "../middleware/sequenceDebug.js";
3
+ import type { AgentEventEmitter } from "../domain/agentEvents.js";
4
+ import type { SequenceDebugCollector } from "./middleware/sequenceDebug.js";
5
5
  import type { CurrentPageContext } from "../tools/getUserLocation.js";
6
- import type { AgentTurnContext } from "../turn/turnTypes.js";
6
+ import type { AgentTurnContext } from "../domain/turnTypes.js";
7
7
  export declare const contextSchema: z.ZodObject<{
8
8
  adminUser: z.ZodCustom<AdminUser, AdminUser>;
9
9
  userTimeZone: z.ZodString;
@@ -2,22 +2,26 @@ import type { BaseChatModel } from "@langchain/core/language_models/chat_models"
2
2
  import { type CompletionAdapter } from "adminforth";
3
3
  import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
4
4
  import type { LLMResult } from "@langchain/core/outputs";
5
+ import type { Messages, Command } from "@langchain/langgraph";
5
6
  import { createSequenceDebugMiddleware } from "./middleware/sequenceDebug.js";
7
+ import type { AgentModelPurpose } from "../application/ports.js";
8
+ import type { AgentTurnContext, AgentTurnObservability } from "../domain/turnTypes.js";
9
+ export type { AgentModeCompletionAdapter, AgentModelPurpose } from "../application/ports.js";
6
10
  export type AgentChatModel = BaseChatModel<any, any>;
7
- export type AgentModelPurpose = "primary" | "summary";
8
- export type AgentModeCompletionAdapter = CompletionAdapter & {
9
- getLangChainAgentSpec(params: {
10
- maxTokens: number;
11
- purpose: AgentModelPurpose;
12
- }): Promise<{
13
- model: unknown;
14
- middleware?: unknown[];
15
- }> | {
16
- model: unknown;
17
- middleware?: unknown[];
18
- };
19
- };
20
11
  export type AgentMiddleware = ReturnType<typeof createSequenceDebugMiddleware>;
12
+ export type AgentTurnModels = {
13
+ model: AgentChatModel;
14
+ summaryModel: AgentChatModel;
15
+ modelMiddleware?: AgentMiddleware[];
16
+ };
17
+ export type AgentRuntimeRunInput = {
18
+ models: AgentTurnModels;
19
+ input: {
20
+ messages: Messages;
21
+ } | Command;
22
+ context: AgentTurnContext;
23
+ observability: AgentTurnObservability;
24
+ };
21
25
  type AgentChatModelSpec = {
22
26
  model: AgentChatModel;
23
27
  middleware: AgentMiddleware[];
@@ -27,8 +31,7 @@ declare class AgentLlmMetricsLogger extends BaseCallbackHandler {
27
31
  lc_prefer_streaming: boolean;
28
32
  private readonly pendingRuns;
29
33
  handleLLMStart(_llm: unknown, _prompts: string[], runId: string): Promise<void>;
30
- handleLLMNewToken(_token: string, _chunk: unknown, runId: string): Promise<void>;
31
- handleLLMEnd(output: LLMResult, runId: string): Promise<void>;
34
+ handleLLMEnd(_output: LLMResult, runId: string): Promise<void>;
32
35
  handleLLMError(_error: unknown, runId: string): Promise<void>;
33
36
  }
34
37
  export declare function createAgentLlmMetricsLogger(): AgentLlmMetricsLogger;
@@ -37,4 +40,3 @@ export declare function createAgentChatModel(params: {
37
40
  maxTokens: number;
38
41
  purpose: AgentModelPurpose;
39
42
  }): Promise<AgentChatModelSpec>;
40
- export {};
@@ -0,0 +1,65 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
11
+ function isLangChainAgentCompletionAdapter(adapter) {
12
+ return typeof adapter
13
+ .getLangChainAgentSpec === "function";
14
+ }
15
+ function getAgentChatModelSpec(params) {
16
+ return __awaiter(this, void 0, void 0, function* () {
17
+ var _a;
18
+ const spec = yield params.adapter.getLangChainAgentSpec({
19
+ maxTokens: params.maxTokens,
20
+ purpose: params.purpose,
21
+ });
22
+ return {
23
+ model: spec.model,
24
+ middleware: ((_a = spec.middleware) !== null && _a !== void 0 ? _a : []),
25
+ };
26
+ });
27
+ }
28
+ class AgentLlmMetricsLogger extends BaseCallbackHandler {
29
+ constructor() {
30
+ super(...arguments);
31
+ this.name = "AgentLlmMetricsLogger";
32
+ this.lc_prefer_streaming = true;
33
+ this.pendingRuns = new Map();
34
+ }
35
+ handleLLMStart(_llm, _prompts, runId) {
36
+ return __awaiter(this, void 0, void 0, function* () {
37
+ this.pendingRuns.set(runId, { startedAt: Date.now() });
38
+ });
39
+ }
40
+ handleLLMEnd(_output, runId) {
41
+ return __awaiter(this, void 0, void 0, function* () {
42
+ this.pendingRuns.delete(runId);
43
+ });
44
+ }
45
+ handleLLMError(_error, runId) {
46
+ return __awaiter(this, void 0, void 0, function* () {
47
+ this.pendingRuns.delete(runId);
48
+ });
49
+ }
50
+ }
51
+ export function createAgentLlmMetricsLogger() {
52
+ return new AgentLlmMetricsLogger();
53
+ }
54
+ export function createAgentChatModel(params) {
55
+ return __awaiter(this, void 0, void 0, function* () {
56
+ if (!isLangChainAgentCompletionAdapter(params.adapter)) {
57
+ throw new Error("AdminForth Agent requires completionAdapter to implement getLangChainAgentSpec({ maxTokens, purpose }).");
58
+ }
59
+ return yield getAgentChatModelSpec({
60
+ adapter: params.adapter,
61
+ maxTokens: params.maxTokens,
62
+ purpose: params.purpose,
63
+ });
64
+ });
65
+ }
@@ -1,15 +1,27 @@
1
1
  import type { IAdminForth } from "adminforth";
2
2
  import type { BaseCheckpointSaver } from "@langchain/langgraph";
3
- import type { AgentToolProvider } from "../tools/AgentToolProvider.js";
4
- import type { AgentRuntimeRunInput } from "../turn/turnTypes.js";
3
+ import type { SteerBuffer } from "../domain/steerBuffer.js";
4
+ import type { AgentToolProvider } from "../tools/agentToolProvider.js";
5
+ import type { AgentRuntimeRunInput, AgentTurnModels } from "./agentModels.js";
5
6
  export type AgentRuntimeOptions = {
6
7
  name: string;
7
8
  getAdminforth: () => IAdminForth;
8
9
  getCheckpointer: () => BaseCheckpointSaver;
9
10
  toolProvider: AgentToolProvider;
11
+ /** Per-session buffer of mid-turn steering instructions drained by the steer middleware. */
12
+ steerBuffer: SteerBuffer;
10
13
  };
11
14
  export declare class AgentRuntime {
12
15
  private readonly options;
13
16
  constructor(options: AgentRuntimeOptions);
14
17
  stream(input: AgentRuntimeRunInput): Promise<import("@langchain/core/utils/stream").IterableReadableStream<["messages", [import("langchain").BaseMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>, import("@langchain/core/messages").MessageType>, Record<string, any>]] | ["updates", Record<string, Omit<import("langchain").BuiltInState<import("@langchain/core/messages").MessageStructure<import("langchain").ToolsToMessageToolSet<readonly (import("@langchain/core/tools").ClientTool | import("@langchain/core/tools").ServerTool)[]>>>, "jumpTo">>]>>;
18
+ /**
19
+ * Read the pending human-in-the-loop interrupts persisted for a thread from the
20
+ * checkpointer. Builds a minimal agent (model + checkpointer + HITL middleware) and
21
+ * queries its state — no model call is made. Returns raw LangGraph interrupt objects.
22
+ */
23
+ getPendingInterrupts(input: {
24
+ models: AgentTurnModels;
25
+ sessionId: string;
26
+ }): Promise<unknown[]>;
15
27
  }
@@ -8,10 +8,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { createAgent, summarizationMiddleware, humanInTheLoopMiddleware } from "langchain";
11
- import { createApiBasedToolsMiddleware } from "../middleware/apiBasedTools.js";
12
- import { createSequenceDebugMiddleware } from "../middleware/sequenceDebug.js";
13
- import { createAgentLlmMetricsLogger } from "../simpleAgent.js";
14
- import { contextSchema, toLangchainAgentContext } from "./AgentContext.js";
11
+ import { createApiBasedToolsMiddleware } from "./middleware/apiToolsMiddleware.js";
12
+ import { createSequenceDebugMiddleware } from "./middleware/sequenceDebug.js";
13
+ import { createSteerMiddleware } from "./middleware/steerMiddleware.js";
14
+ import { createAgentLlmMetricsLogger } from "./agentModels.js";
15
+ import { contextSchema, toLangchainAgentContext } from "./agentContext.js";
15
16
  function createHumanInTheLoopInterrupts(apiBasedTools) {
16
17
  return Object.fromEntries(Object.entries(apiBasedTools)
17
18
  .filter(([, apiBasedTool]) => { var _a; return ((_a = apiBasedTool.agent) === null || _a === void 0 ? void 0 : _a.isDangerous) === true; })
@@ -33,12 +34,17 @@ export class AgentRuntime {
33
34
  const tools = yield this.options.toolProvider.getTools(apiBasedTools);
34
35
  const adminforth = this.options.getAdminforth();
35
36
  const apiBasedToolsMiddleware = createApiBasedToolsMiddleware(apiBasedTools, adminforth);
36
- const sequenceDebugMiddleware = createSequenceDebugMiddleware(input.observability.sequenceDebugSink);
37
+ // The domain exposes only the narrow DebugSink; the concrete collector (with the
38
+ // model-call hooks the debug middleware needs) is an llm-layer detail.
39
+ const sequenceDebugSink = input.observability.sequenceDebugSink;
40
+ const sequenceDebugMiddleware = createSequenceDebugMiddleware(sequenceDebugSink);
37
41
  const hitlMiddleware = humanInTheLoopMiddleware({
38
42
  interruptOn: createHumanInTheLoopInterrupts(apiBasedTools),
39
43
  descriptionPrefix: "Tool execution pending approval",
40
44
  });
45
+ const steerMiddleware = createSteerMiddleware(this.options.steerBuffer);
41
46
  const middleware = [
47
+ steerMiddleware,
42
48
  apiBasedToolsMiddleware,
43
49
  hitlMiddleware,
44
50
  ...((_a = input.models.modelMiddleware) !== null && _a !== void 0 ? _a : []),
@@ -65,8 +71,37 @@ export class AgentRuntime {
65
71
  configurable: {
66
72
  thread_id: input.context.sessionId,
67
73
  },
68
- context: toLangchainAgentContext(Object.assign(Object.assign({}, input.context), { adminBaseUrl: adminforth.config.baseUrlSlashed, emit: input.observability.emit, sequenceDebugSink: input.observability.sequenceDebugSink })),
74
+ context: toLangchainAgentContext(Object.assign(Object.assign({}, input.context), { adminBaseUrl: adminforth.config.baseUrlSlashed, emit: input.observability.emit, sequenceDebugSink })),
69
75
  });
70
76
  });
71
77
  }
78
+ /**
79
+ * Read the pending human-in-the-loop interrupts persisted for a thread from the
80
+ * checkpointer. Builds a minimal agent (model + checkpointer + HITL middleware) and
81
+ * queries its state — no model call is made. Returns raw LangGraph interrupt objects.
82
+ */
83
+ getPendingInterrupts(input) {
84
+ return __awaiter(this, void 0, void 0, function* () {
85
+ const apiBasedTools = this.options.toolProvider.getApiBasedTools();
86
+ const tools = yield this.options.toolProvider.getTools(apiBasedTools);
87
+ const agent = createAgent({
88
+ name: this.options.name,
89
+ model: input.models.model,
90
+ checkpointer: this.options.getCheckpointer(),
91
+ tools,
92
+ contextSchema,
93
+ middleware: [
94
+ humanInTheLoopMiddleware({
95
+ interruptOn: createHumanInTheLoopInterrupts(apiBasedTools),
96
+ descriptionPrefix: "Tool execution pending approval",
97
+ }),
98
+ ],
99
+ });
100
+ const state = yield agent.getState({
101
+ configurable: { thread_id: input.sessionId },
102
+ });
103
+ const tasks = Array.isArray(state === null || state === void 0 ? void 0 : state.tasks) ? state.tasks : [];
104
+ return tasks.flatMap((task) => (Array.isArray(task === null || task === void 0 ? void 0 : task.interrupts) ? task.interrupts : []));
105
+ });
106
+ }
72
107
  }
@@ -0,0 +1,25 @@
1
+ import type { AgentRuntime } from "./agentRuntime.js";
2
+ import type { AgentModelFactory } from "./modelFactory.js";
3
+ import { type PreviousUserMessage } from "../domain/languageDetect.js";
4
+ import type { AgentModeCompletionAdapter, LlmPort, LlmStreamInput } from "../application/ports.js";
5
+ import type { PendingInterrupt } from "../domain/turnTypes.js";
6
+ /**
7
+ * LangChain/LangGraph implementation of {@link LlmPort}. This is the single
8
+ * place that knows about the agent graph, model construction, and the raw
9
+ * stream shape; the application layer talks only to the port.
10
+ */
11
+ export declare class LangGraphLlm implements LlmPort {
12
+ private readonly runtime;
13
+ private readonly modelFactory;
14
+ constructor(runtime: AgentRuntime, modelFactory: AgentModelFactory);
15
+ streamTurn(input: LlmStreamInput): Promise<AsyncGenerator<import("../domain/turnTypes.js").AgentStreamChunk, any, any>>;
16
+ detectLanguage(input: {
17
+ completionAdapter: AgentModeCompletionAdapter;
18
+ prompt: string;
19
+ previousUserMessages: PreviousUserMessage[];
20
+ }): Promise<import("../domain/languageDetect.js").DetectedLanguage | null>;
21
+ getPendingInterrupts(input: {
22
+ completionAdapter: AgentModeCompletionAdapter;
23
+ sessionId: string;
24
+ }): Promise<PendingInterrupt[]>;
25
+ }
@@ -0,0 +1,54 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { Command } from "@langchain/langgraph";
11
+ import { HumanMessage, SystemMessage } from "langchain";
12
+ import { detectUserLanguage } from "../domain/languageDetect.js";
13
+ import { adaptRawStream, normalizeInterrupts } from "./streamAdapter.js";
14
+ function toLangchainMessages(messages) {
15
+ return messages.map((message) => message.role === "system"
16
+ ? new SystemMessage(message.content)
17
+ : new HumanMessage(message.content));
18
+ }
19
+ /**
20
+ * LangChain/LangGraph implementation of {@link LlmPort}. This is the single
21
+ * place that knows about the agent graph, model construction, and the raw
22
+ * stream shape; the application layer talks only to the port.
23
+ */
24
+ export class LangGraphLlm {
25
+ constructor(runtime, modelFactory) {
26
+ this.runtime = runtime;
27
+ this.modelFactory = modelFactory;
28
+ }
29
+ streamTurn(input) {
30
+ return __awaiter(this, void 0, void 0, function* () {
31
+ const models = yield this.modelFactory.create(input.completionAdapter);
32
+ const runtimeInput = "resume" in input.input
33
+ ? new Command({ resume: input.input.resume })
34
+ : { messages: toLangchainMessages(input.input.messages) };
35
+ const rawStream = yield this.runtime.stream({
36
+ models,
37
+ input: runtimeInput,
38
+ context: input.context,
39
+ observability: input.observability,
40
+ });
41
+ return adaptRawStream(rawStream);
42
+ });
43
+ }
44
+ detectLanguage(input) {
45
+ return detectUserLanguage(input.completionAdapter, input.prompt, input.previousUserMessages);
46
+ }
47
+ getPendingInterrupts(input) {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ const models = yield this.modelFactory.create(input.completionAdapter);
50
+ const raw = yield this.runtime.getPendingInterrupts({ models, sessionId: input.sessionId });
51
+ return normalizeInterrupts(raw);
52
+ });
53
+ }
54
+ }
@@ -1,3 +1,3 @@
1
1
  import { type IAdminForth } from "adminforth";
2
- import { type ApiBasedTool } from "../../apiBasedTools.js";
2
+ import { type ApiBasedTool } from "../../tools/apiBasedTools.js";
3
3
  export declare function createApiBasedToolsMiddleware(apiBasedTools: Record<string, ApiBasedTool>, adminforth: IAdminForth): import("langchain").AgentMiddleware<undefined, undefined, unknown, readonly (import("@langchain/core/tools").ClientTool | import("@langchain/core/tools").ServerTool)[]>;
@@ -11,11 +11,11 @@ import { ToolMessage } from "@langchain/core/messages";
11
11
  import { isGraphInterrupt } from "@langchain/langgraph";
12
12
  import { createMiddleware } from "langchain";
13
13
  import { logger } from "adminforth";
14
- import { formatApiBasedToolCall, } from "../../apiBasedTools.js";
15
- import { createToolCallTracker, } from "../toolCallEvents.js";
16
- import { ALWAYS_AVAILABLE_API_TOOL_NAMES } from "../tools/index.js";
17
- import { createApiTool } from "../tools/apiTool.js";
18
- import { isAbortError } from "../../errors.js";
14
+ import { formatApiBasedToolCall, } from "../../tools/apiBasedTools.js";
15
+ import { createToolCallTracker, } from "../../domain/toolCallEvents.js";
16
+ import { ALWAYS_AVAILABLE_API_TOOL_NAMES } from "../../tools/index.js";
17
+ import { createApiTool } from "../../tools/apiTool.js";
18
+ import { isAbortError } from "../../shared/errors.js";
19
19
  function getEnabledApiToolNames(messages) {
20
20
  const enabledToolNames = new Set();
21
21
  for (const message of messages) {
@@ -58,15 +58,13 @@ export function createApiBasedToolsMiddleware(apiBasedTools, adminforth) {
58
58
  .filter((toolName) => !alwaysAvailableApiToolNames.has(toolName))
59
59
  .map((toolName) => dynamicTools[toolName]);
60
60
  const availableTools = [...request.tools, ...tools];
61
- logger.info(`AdminForth Agent callable tools: ${availableTools.map((tool) => tool.name).join(", ")}`);
62
61
  return handler(Object.assign(Object.assign({}, request), { tools: availableTools }));
63
62
  });
64
63
  },
65
64
  wrapToolCall(request, handler) {
66
65
  return __awaiter(this, void 0, void 0, function* () {
67
- var _a, _b, _c;
66
+ var _a, _b;
68
67
  const startedAt = Date.now();
69
- const toolInput = JSON.stringify((_a = request.toolCall.args) !== null && _a !== void 0 ? _a : {});
70
68
  if (!request.toolCall.id) {
71
69
  throw new Error(`Tool call "${request.toolCall.name}" has no id.`);
72
70
  }
@@ -79,7 +77,7 @@ export function createApiBasedToolsMiddleware(apiBasedTools, adminforth) {
79
77
  data: event,
80
78
  }));
81
79
  };
82
- const toolArgs = ((_b = request.toolCall.args) !== null && _b !== void 0 ? _b : {});
80
+ const toolArgs = ((_a = request.toolCall.args) !== null && _a !== void 0 ? _a : {});
83
81
  let toolInfo;
84
82
  if (request.toolCall.name === "fetch_skill") {
85
83
  toolInfo = `Load ${toolArgs.skillName.split("_").join(" ")} skill`;
@@ -105,7 +103,6 @@ export function createApiBasedToolsMiddleware(apiBasedTools, adminforth) {
105
103
  startedAt,
106
104
  });
107
105
  toolCallTracker.start();
108
- logger.info(`Invoking tool "${request.toolCall.name}" with input: ${toolInput}`);
109
106
  try {
110
107
  const result = getEnabledApiToolNames(request.state.messages).has(request.toolCall.name)
111
108
  ? yield handler(Object.assign(Object.assign({}, request), { tool: dynamicTools[request.toolCall.name] }))
@@ -120,7 +117,7 @@ export function createApiBasedToolsMiddleware(apiBasedTools, adminforth) {
120
117
  throw error;
121
118
  }
122
119
  const message = error instanceof Error ? error.message : String(error);
123
- logger.error(`Error calling tool "${request.toolCall.name}": ${error instanceof Error ? (_c = error.stack) !== null && _c !== void 0 ? _c : error.message : String(error)}`);
120
+ logger.error(`Error calling tool "${request.toolCall.name}": ${error instanceof Error ? (_b = error.stack) !== null && _b !== void 0 ? _b : error.message : String(error)}`);
124
121
  toolCallTracker.finishError(`Error: ${message}`);
125
122
  return new ToolMessage({
126
123
  name: request.toolCall.name,
@@ -129,9 +126,6 @@ export function createApiBasedToolsMiddleware(apiBasedTools, adminforth) {
129
126
  content: `Error: ${message}`,
130
127
  });
131
128
  }
132
- finally {
133
- logger.info(`Tool "${request.toolCall.name}" finished in ${Date.now() - startedAt}ms`);
134
- }
135
129
  });
136
130
  },
137
131
  });
@@ -1,4 +1,4 @@
1
- import type { ToolCallEvent } from "../toolCallEvents.js";
1
+ import type { ToolCallEvent } from "../../domain/toolCallEvents.js";
2
2
  export type SequenceDebugResultType = "tool_calls" | "final_text";
3
3
  type SequenceDebugToolCall = {
4
4
  toolCallId: string;
@@ -0,0 +1,21 @@
1
+ import { z } from "zod";
2
+ import type { AgentEventEmitter } from "../../domain/agentEvents.js";
3
+ import type { SteerBuffer } from "../../domain/steerBuffer.js";
4
+ /**
5
+ * `beforeModel` middleware that folds user "steering" instructions into a running
6
+ * turn. Before every model call in the agent loop it drains the per-session
7
+ * {@link SteerBuffer}; any buffered steers are appended to the conversation as
8
+ * user messages (so the model sees them on the very next call) and a
9
+ * `steer-applied` event is emitted on the turn's already-open SSE stream so the
10
+ * frontend knows the steer was actually consumed (not just received/queued).
11
+ *
12
+ * Placed first in the middleware array so the injected messages are present for
13
+ * every downstream `beforeModel` hook (e.g. summarization) and the model itself.
14
+ */
15
+ export declare function createSteerMiddleware(steerBuffer: SteerBuffer): import("langchain").AgentMiddleware<undefined, z.ZodObject<{
16
+ sessionId: z.ZodString;
17
+ emit: z.ZodOptional<z.ZodCustom<AgentEventEmitter, AgentEventEmitter>>;
18
+ }, z.core.$strip>, {
19
+ sessionId: string;
20
+ emit?: AgentEventEmitter | undefined;
21
+ }, readonly (import("@langchain/core/tools").ClientTool | import("@langchain/core/tools").ServerTool)[]>;
@@ -0,0 +1,50 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { HumanMessage } from "langchain";
11
+ import { createMiddleware } from "langchain";
12
+ import { z } from "zod";
13
+ const steerContextSchema = z.object({
14
+ sessionId: z.string(),
15
+ emit: z.custom().optional(),
16
+ });
17
+ /**
18
+ * `beforeModel` middleware that folds user "steering" instructions into a running
19
+ * turn. Before every model call in the agent loop it drains the per-session
20
+ * {@link SteerBuffer}; any buffered steers are appended to the conversation as
21
+ * user messages (so the model sees them on the very next call) and a
22
+ * `steer-applied` event is emitted on the turn's already-open SSE stream so the
23
+ * frontend knows the steer was actually consumed (not just received/queued).
24
+ *
25
+ * Placed first in the middleware array so the injected messages are present for
26
+ * every downstream `beforeModel` hook (e.g. summarization) and the model itself.
27
+ */
28
+ export function createSteerMiddleware(steerBuffer) {
29
+ return createMiddleware({
30
+ name: "SteerMiddleware",
31
+ contextSchema: steerContextSchema,
32
+ beforeModel(_state, runtime) {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ const { sessionId, emit } = runtime.context;
35
+ const steers = steerBuffer.drain(sessionId);
36
+ if (steers.length === 0) {
37
+ return;
38
+ }
39
+ void (emit === null || emit === void 0 ? void 0 : emit({
40
+ type: "steer-applied",
41
+ count: steers.length,
42
+ ids: steers.map((steer) => steer.id),
43
+ }));
44
+ return {
45
+ messages: steers.map((steer) => new HumanMessage(`[User steering — new instruction sent mid-turn, take it into account from now on]\n${steer.text}`)),
46
+ };
47
+ });
48
+ },
49
+ });
50
+ }
@@ -1,5 +1,5 @@
1
1
  import type { CompletionAdapter } from "adminforth";
2
- import type { AgentTurnModels } from "../turn/turnTypes.js";
2
+ import { type AgentTurnModels } from "./agentModels.js";
3
3
  export declare class AgentModelFactory {
4
4
  private readonly maxTokens;
5
5
  constructor(maxTokens: number);
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { createAgentChatModel } from "../simpleAgent.js";
10
+ import { createAgentChatModel } from "./agentModels.js";
11
11
  export class AgentModelFactory {
12
12
  constructor(maxTokens) {
13
13
  this.maxTokens = maxTokens;
@@ -0,0 +1,18 @@
1
+ import type { AgentStreamChunk, PendingInterrupt } from "../domain/turnTypes.js";
2
+ /**
3
+ * Normalize raw LangGraph interrupt object(s) into provider-agnostic descriptors.
4
+ * Kept in the llm layer so the LangGraph interrupt shape never reaches the app.
5
+ */
6
+ export declare function normalizeInterrupts(interrupt: unknown): PendingInterrupt[];
7
+ type RawStreamEntry = ["messages", [any, any]] | ["updates", Record<string, any>];
8
+ /**
9
+ * Convert one raw LangGraph stream entry into zero or more normalized chunks.
10
+ * Pure and synchronous so the parsing rules can be unit-tested in isolation.
11
+ */
12
+ export declare function parseRawStreamChunk(entry: RawStreamEntry): AgentStreamChunk[];
13
+ /**
14
+ * Adapt the raw LangGraph `["messages" | "updates", ...]` stream into a typed
15
+ * `AgentStreamChunk` stream for the application layer.
16
+ */
17
+ export declare function adaptRawStream(raw: AsyncIterable<RawStreamEntry>): AsyncGenerator<AgentStreamChunk>;
18
+ export {};