agent-world 0.11.1 → 0.12.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 (267) hide show
  1. package/README.md +17 -7
  2. package/dist/cli/commands.d.ts +109 -0
  3. package/dist/cli/commands.js +2024 -0
  4. package/dist/cli/display.d.ts +124 -0
  5. package/dist/cli/display.js +381 -0
  6. package/dist/cli/hitl.d.ts +33 -0
  7. package/dist/cli/hitl.js +81 -0
  8. package/dist/cli/index.d.ts +2 -0
  9. package/dist/cli/stream.d.ts +41 -0
  10. package/dist/cli/stream.js +222 -0
  11. package/dist/core/activity-tracker.d.ts +16 -0
  12. package/dist/core/activity-tracker.d.ts.map +1 -0
  13. package/dist/core/activity-tracker.js +91 -0
  14. package/dist/core/activity-tracker.js.map +1 -0
  15. package/dist/core/ai-commands.d.ts +16 -0
  16. package/dist/core/ai-commands.d.ts.map +1 -0
  17. package/dist/core/ai-commands.js +24 -0
  18. package/dist/core/ai-commands.js.map +1 -0
  19. package/dist/core/ai-sdk-patch.d.ts +24 -0
  20. package/dist/core/ai-sdk-patch.d.ts.map +1 -0
  21. package/dist/core/ai-sdk-patch.js +169 -0
  22. package/dist/core/ai-sdk-patch.js.map +1 -0
  23. package/dist/core/anthropic-direct.d.ts +52 -0
  24. package/dist/core/anthropic-direct.d.ts.map +1 -0
  25. package/dist/core/anthropic-direct.js +301 -0
  26. package/dist/core/anthropic-direct.js.map +1 -0
  27. package/dist/core/approval-cache.d.ts +104 -0
  28. package/dist/core/approval-cache.d.ts.map +1 -0
  29. package/dist/core/approval-cache.js +150 -0
  30. package/dist/core/approval-cache.js.map +1 -0
  31. package/dist/core/chat-constants.d.ts +20 -0
  32. package/dist/core/chat-constants.d.ts.map +1 -0
  33. package/dist/core/chat-constants.js +22 -0
  34. package/dist/core/chat-constants.js.map +1 -0
  35. package/dist/core/create-agent-tool.d.ts +66 -0
  36. package/dist/core/create-agent-tool.d.ts.map +1 -0
  37. package/dist/core/create-agent-tool.js +212 -0
  38. package/dist/core/create-agent-tool.js.map +1 -0
  39. package/dist/core/events/approval-checker.d.ts +61 -0
  40. package/dist/core/events/approval-checker.d.ts.map +1 -0
  41. package/dist/core/events/approval-checker.js +226 -0
  42. package/dist/core/events/approval-checker.js.map +1 -0
  43. package/dist/core/events/index.d.ts +25 -0
  44. package/dist/core/events/index.d.ts.map +1 -0
  45. package/dist/core/events/index.js +30 -0
  46. package/dist/core/events/index.js.map +1 -0
  47. package/dist/core/events/memory-manager.d.ts +73 -0
  48. package/dist/core/events/memory-manager.d.ts.map +1 -0
  49. package/dist/core/events/memory-manager.js +1218 -0
  50. package/dist/core/events/memory-manager.js.map +1 -0
  51. package/dist/core/events/mention-logic.d.ts +39 -0
  52. package/dist/core/events/mention-logic.d.ts.map +1 -0
  53. package/dist/core/events/mention-logic.js +163 -0
  54. package/dist/core/events/mention-logic.js.map +1 -0
  55. package/dist/core/events/orchestrator.d.ts +69 -0
  56. package/dist/core/events/orchestrator.d.ts.map +1 -0
  57. package/dist/core/events/orchestrator.js +883 -0
  58. package/dist/core/events/orchestrator.js.map +1 -0
  59. package/dist/core/events/persistence.d.ts +41 -0
  60. package/dist/core/events/persistence.d.ts.map +1 -0
  61. package/dist/core/events/persistence.js +296 -0
  62. package/dist/core/events/persistence.js.map +1 -0
  63. package/dist/core/events/publishers.d.ts +81 -0
  64. package/dist/core/events/publishers.d.ts.map +1 -0
  65. package/dist/core/events/publishers.js +272 -0
  66. package/dist/core/events/publishers.js.map +1 -0
  67. package/dist/core/events/subscribers.d.ts +45 -0
  68. package/dist/core/events/subscribers.d.ts.map +1 -0
  69. package/dist/core/events/subscribers.js +288 -0
  70. package/dist/core/events/subscribers.js.map +1 -0
  71. package/dist/core/events/tool-bridge-logging.d.ts +28 -0
  72. package/dist/core/events/tool-bridge-logging.d.ts.map +1 -0
  73. package/dist/core/events/tool-bridge-logging.js +94 -0
  74. package/dist/core/events/tool-bridge-logging.js.map +1 -0
  75. package/dist/core/events-metadata.d.ts +72 -0
  76. package/dist/core/events-metadata.d.ts.map +1 -0
  77. package/dist/core/events-metadata.js +167 -0
  78. package/dist/core/events-metadata.js.map +1 -0
  79. package/dist/core/events.d.ts +186 -0
  80. package/dist/core/events.d.ts.map +1 -0
  81. package/dist/core/events.js +1248 -0
  82. package/dist/core/events.js.map +1 -0
  83. package/dist/core/export.d.ts +106 -0
  84. package/dist/core/export.d.ts.map +1 -0
  85. package/dist/core/export.js +705 -0
  86. package/dist/core/export.js.map +1 -0
  87. package/dist/core/file-tools.d.ts +114 -0
  88. package/dist/core/file-tools.d.ts.map +1 -0
  89. package/dist/core/file-tools.js +370 -0
  90. package/dist/core/file-tools.js.map +1 -0
  91. package/dist/core/google-direct.d.ts +58 -0
  92. package/dist/core/google-direct.d.ts.map +1 -0
  93. package/dist/core/google-direct.js +298 -0
  94. package/dist/core/google-direct.js.map +1 -0
  95. package/dist/core/hitl.d.ts +54 -0
  96. package/dist/core/hitl.d.ts.map +1 -0
  97. package/dist/core/hitl.js +153 -0
  98. package/dist/core/hitl.js.map +1 -0
  99. package/dist/core/index.d.ts +59 -0
  100. package/dist/core/index.d.ts.map +1 -0
  101. package/dist/core/index.js +70 -0
  102. package/dist/core/index.js.map +1 -0
  103. package/dist/core/llm-config.d.ts +128 -0
  104. package/dist/core/llm-config.d.ts.map +1 -0
  105. package/dist/core/llm-config.js +164 -0
  106. package/dist/core/llm-config.js.map +1 -0
  107. package/dist/core/llm-manager.d.ts +163 -0
  108. package/dist/core/llm-manager.d.ts.map +1 -0
  109. package/dist/core/llm-manager.js +669 -0
  110. package/dist/core/llm-manager.js.map +1 -0
  111. package/dist/core/load-skill-tool.d.ts +55 -0
  112. package/dist/core/load-skill-tool.d.ts.map +1 -0
  113. package/dist/core/load-skill-tool.js +468 -0
  114. package/dist/core/load-skill-tool.js.map +1 -0
  115. package/dist/core/logger.d.ts +88 -0
  116. package/dist/core/logger.d.ts.map +1 -0
  117. package/dist/core/logger.js +358 -0
  118. package/dist/core/logger.js.map +1 -0
  119. package/dist/core/managers.d.ts +131 -0
  120. package/dist/core/managers.d.ts.map +1 -0
  121. package/dist/core/managers.js +1223 -0
  122. package/dist/core/managers.js.map +1 -0
  123. package/dist/core/mcp-server-registry.d.ts +304 -0
  124. package/dist/core/mcp-server-registry.d.ts.map +1 -0
  125. package/dist/core/mcp-server-registry.js +1769 -0
  126. package/dist/core/mcp-server-registry.js.map +1 -0
  127. package/dist/core/mcp-tools.d.ts +56 -0
  128. package/dist/core/mcp-tools.d.ts.map +1 -0
  129. package/dist/core/mcp-tools.js +186 -0
  130. package/dist/core/mcp-tools.js.map +1 -0
  131. package/dist/core/message-prep.d.ts +81 -0
  132. package/dist/core/message-prep.d.ts.map +1 -0
  133. package/dist/core/message-prep.js +223 -0
  134. package/dist/core/message-prep.js.map +1 -0
  135. package/dist/core/message-processing-control.d.ts +54 -0
  136. package/dist/core/message-processing-control.d.ts.map +1 -0
  137. package/dist/core/message-processing-control.js +139 -0
  138. package/dist/core/message-processing-control.js.map +1 -0
  139. package/dist/core/openai-direct.d.ts +80 -0
  140. package/dist/core/openai-direct.d.ts.map +1 -0
  141. package/dist/core/openai-direct.js +374 -0
  142. package/dist/core/openai-direct.js.map +1 -0
  143. package/dist/core/shell-cmd-tool.d.ts +235 -0
  144. package/dist/core/shell-cmd-tool.d.ts.map +1 -0
  145. package/dist/core/shell-cmd-tool.js +1157 -0
  146. package/dist/core/shell-cmd-tool.js.map +1 -0
  147. package/dist/core/shell-process-registry.d.ts +88 -0
  148. package/dist/core/shell-process-registry.d.ts.map +1 -0
  149. package/dist/core/shell-process-registry.js +309 -0
  150. package/dist/core/shell-process-registry.js.map +1 -0
  151. package/dist/core/skill-registry.d.ts +75 -0
  152. package/dist/core/skill-registry.d.ts.map +1 -0
  153. package/dist/core/skill-registry.js +369 -0
  154. package/dist/core/skill-registry.js.map +1 -0
  155. package/dist/core/skill-script-runner.d.ts +89 -0
  156. package/dist/core/skill-script-runner.d.ts.map +1 -0
  157. package/dist/core/skill-script-runner.js +274 -0
  158. package/dist/core/skill-script-runner.js.map +1 -0
  159. package/dist/core/skill-selector.d.ts +65 -0
  160. package/dist/core/skill-selector.d.ts.map +1 -0
  161. package/dist/core/skill-selector.js +190 -0
  162. package/dist/core/skill-selector.js.map +1 -0
  163. package/dist/core/skill-settings.d.ts +20 -0
  164. package/dist/core/skill-settings.d.ts.map +1 -0
  165. package/dist/core/skill-settings.js +40 -0
  166. package/dist/core/skill-settings.js.map +1 -0
  167. package/dist/core/storage/agent-storage.d.ts +134 -0
  168. package/dist/core/storage/agent-storage.d.ts.map +1 -0
  169. package/dist/core/storage/agent-storage.js +498 -0
  170. package/dist/core/storage/agent-storage.js.map +1 -0
  171. package/dist/core/storage/eventStorage/fileEventStorage.d.ts +100 -0
  172. package/dist/core/storage/eventStorage/fileEventStorage.d.ts.map +1 -0
  173. package/dist/core/storage/eventStorage/fileEventStorage.js +494 -0
  174. package/dist/core/storage/eventStorage/fileEventStorage.js.map +1 -0
  175. package/dist/core/storage/eventStorage/index.d.ts +31 -0
  176. package/dist/core/storage/eventStorage/index.d.ts.map +1 -0
  177. package/dist/core/storage/eventStorage/index.js +31 -0
  178. package/dist/core/storage/eventStorage/index.js.map +1 -0
  179. package/dist/core/storage/eventStorage/memoryEventStorage.d.ts +87 -0
  180. package/dist/core/storage/eventStorage/memoryEventStorage.d.ts.map +1 -0
  181. package/dist/core/storage/eventStorage/memoryEventStorage.js +244 -0
  182. package/dist/core/storage/eventStorage/memoryEventStorage.js.map +1 -0
  183. package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts +45 -0
  184. package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts.map +1 -0
  185. package/dist/core/storage/eventStorage/sqliteEventStorage.js +301 -0
  186. package/dist/core/storage/eventStorage/sqliteEventStorage.js.map +1 -0
  187. package/dist/core/storage/eventStorage/types.d.ts +142 -0
  188. package/dist/core/storage/eventStorage/types.d.ts.map +1 -0
  189. package/dist/core/storage/eventStorage/types.js +43 -0
  190. package/dist/core/storage/eventStorage/types.js.map +1 -0
  191. package/dist/core/storage/eventStorage/validation.d.ts +30 -0
  192. package/dist/core/storage/eventStorage/validation.d.ts.map +1 -0
  193. package/dist/core/storage/eventStorage/validation.js +68 -0
  194. package/dist/core/storage/eventStorage/validation.js.map +1 -0
  195. package/dist/core/storage/legacy-migrations.d.ts +45 -0
  196. package/dist/core/storage/legacy-migrations.d.ts.map +1 -0
  197. package/dist/core/storage/legacy-migrations.js +295 -0
  198. package/dist/core/storage/legacy-migrations.js.map +1 -0
  199. package/dist/core/storage/memory-storage.d.ts +105 -0
  200. package/dist/core/storage/memory-storage.d.ts.map +1 -0
  201. package/dist/core/storage/memory-storage.js +415 -0
  202. package/dist/core/storage/memory-storage.js.map +1 -0
  203. package/dist/core/storage/migration-runner.d.ts +96 -0
  204. package/dist/core/storage/migration-runner.d.ts.map +1 -0
  205. package/dist/core/storage/migration-runner.js +306 -0
  206. package/dist/core/storage/migration-runner.js.map +1 -0
  207. package/dist/core/storage/queue-storage.d.ts +147 -0
  208. package/dist/core/storage/queue-storage.d.ts.map +1 -0
  209. package/dist/core/storage/queue-storage.js +290 -0
  210. package/dist/core/storage/queue-storage.js.map +1 -0
  211. package/dist/core/storage/skill-storage.d.ts +136 -0
  212. package/dist/core/storage/skill-storage.d.ts.map +1 -0
  213. package/dist/core/storage/skill-storage.js +474 -0
  214. package/dist/core/storage/skill-storage.js.map +1 -0
  215. package/dist/core/storage/sqlite-schema.d.ts +95 -0
  216. package/dist/core/storage/sqlite-schema.d.ts.map +1 -0
  217. package/dist/core/storage/sqlite-schema.js +156 -0
  218. package/dist/core/storage/sqlite-schema.js.map +1 -0
  219. package/dist/core/storage/sqlite-storage.d.ts +146 -0
  220. package/dist/core/storage/sqlite-storage.d.ts.map +1 -0
  221. package/dist/core/storage/sqlite-storage.js +709 -0
  222. package/dist/core/storage/sqlite-storage.js.map +1 -0
  223. package/dist/core/storage/storage-factory.d.ts +61 -0
  224. package/dist/core/storage/storage-factory.d.ts.map +1 -0
  225. package/dist/core/storage/storage-factory.js +794 -0
  226. package/dist/core/storage/storage-factory.js.map +1 -0
  227. package/dist/core/storage/validation.d.ts +36 -0
  228. package/dist/core/storage/validation.d.ts.map +1 -0
  229. package/dist/core/storage/validation.js +79 -0
  230. package/dist/core/storage/validation.js.map +1 -0
  231. package/dist/core/storage/world-storage.d.ts +114 -0
  232. package/dist/core/storage/world-storage.d.ts.map +1 -0
  233. package/dist/core/storage/world-storage.js +378 -0
  234. package/dist/core/storage/world-storage.js.map +1 -0
  235. package/dist/core/subscription.d.ts +43 -0
  236. package/dist/core/subscription.d.ts.map +1 -0
  237. package/dist/core/subscription.js +227 -0
  238. package/dist/core/subscription.js.map +1 -0
  239. package/dist/core/tool-utils.d.ts +80 -0
  240. package/dist/core/tool-utils.d.ts.map +1 -0
  241. package/dist/core/tool-utils.js +273 -0
  242. package/dist/core/tool-utils.js.map +1 -0
  243. package/dist/core/types.d.ts +595 -0
  244. package/dist/core/types.d.ts.map +1 -0
  245. package/dist/core/types.js +158 -0
  246. package/dist/core/types.js.map +1 -0
  247. package/dist/core/utils.d.ts +138 -0
  248. package/dist/core/utils.d.ts.map +1 -0
  249. package/dist/core/utils.js +478 -0
  250. package/dist/core/utils.js.map +1 -0
  251. package/dist/core/world-class.d.ts +43 -0
  252. package/dist/core/world-class.d.ts.map +1 -0
  253. package/dist/core/world-class.js +90 -0
  254. package/dist/core/world-class.js.map +1 -0
  255. package/dist/index.d.ts +18 -0
  256. package/dist/public/assets/agent-sprites-DJFgj-zP.png +0 -0
  257. package/dist/public/assets/border-KHK37r8y.svg +83 -0
  258. package/dist/public/assets/index-C9kPXL6G.css +1 -0
  259. package/dist/public/assets/index-DOQEHGWt.js +96 -0
  260. package/dist/public/index.html +21 -0
  261. package/dist/server/api.d.ts +2 -0
  262. package/dist/server/api.js +1124 -0
  263. package/dist/server/index.d.ts +29 -0
  264. package/dist/server/sse-handler.d.ts +62 -0
  265. package/dist/server/sse-handler.js +234 -0
  266. package/package.json +15 -3
  267. package/scripts/launch-electron.js +0 -58
@@ -0,0 +1,669 @@
1
+ /**
2
+ * LLM Manager Module - Pure Orchestration Layer (LLM Provider Refactoring Phase 5)
3
+ *
4
+ * Features:
5
+ * - Browser-safe LLM integration using direct provider SDKs (OpenAI, Anthropic, Google)
6
+ * - Streaming responses with SSE events via World.eventEmitter specifically
7
+ * - Support for all major LLM providers (OpenAI, Anthropic, Google, Azure, XAI, OpenAI-Compatible, Ollama)
8
+ * - Agent activity tracking and token usage monitoring with automatic state persistence
9
+ * - Error handling with SSE error events via world's eventEmitter and timeout management
10
+ * - World-aware event publishing using world.eventEmitter for proper event isolation
11
+ * - Conversation history support with message preparation and context management
12
+ * - Global LLM call queue to ensure serialized execution (one LLM call at a time)
13
+ * - Configuration injection from external sources (CLI/server) for browser compatibility
14
+ * - Automatic MCP tool integration for worlds with mcpConfig
15
+ * - All providers return LLMResponse with unified structure
16
+ * - Granular function-based logging for detailed debugging control
17
+ *
18
+ * Core Functions:
19
+ * - streamAgentResponse: Streaming LLM calls with SSE events via world.eventEmitter (queued)
20
+ * - generateAgentResponse: Non-streaming LLM calls with automatic state management (queued)
21
+ * - loadLLMProvider: Provider loading logic using injected configuration
22
+ * - getLLMQueueStatus: Monitor queue status for debugging and administration
23
+ * - clearLLMQueue: Emergency queue clearing for administrative purposes
24
+ *
25
+ * Provider Support:
26
+ * - OpenAI: Direct OpenAI package integration (bypasses AI SDK bug)
27
+ * - Azure: Direct OpenAI package integration with Azure endpoints (bypasses AI SDK bug)
28
+ * - OpenAI-Compatible: Direct OpenAI package integration (bypasses AI SDK bug)
29
+ * - XAI: Direct OpenAI package integration with XAI endpoints (bypasses AI SDK bug)
30
+ * - Ollama: Direct OpenAI package integration with OpenAI-compatible endpoint (better function calling)
31
+ * - Anthropic: Direct Anthropic SDK integration (improved tool calling support)
32
+ * - Google: Direct Google Generative AI SDK integration (improved tool calling support)
33
+ *
34
+ * Granular Logging Categories:
35
+ * - llm.queue: Queue operations (add, process, complete, errors)
36
+ * - llm.streaming: Streaming response operations (start, chunks, finish, errors)
37
+ * - llm.generation: Non-streaming response operations (start, finish, errors)
38
+ * - llm.provider: Provider loading, configuration, and validation
39
+ * - llm.mcp: Comprehensive MCP tool integration and execution tracking
40
+ * - llm.util: Utility functions and helper operations
41
+ *
42
+ * Environment Variable Control:
43
+ * - LOG_LLM_QUEUE=debug: Enable queue operation debugging
44
+ * - LOG_LLM_STREAMING=debug: Enable streaming operation debugging
45
+ * - LOG_LLM_GENERATION=debug: Enable generation operation debugging
46
+ * - LOG_LLM_PROVIDER=debug: Enable provider operation debugging
47
+ * - LOG_LLM_MCP=debug: Enable comprehensive MCP tool debugging (consolidates all MCP logging)
48
+ * - LOG_LLM_UTIL=debug: Enable utility function debugging
49
+ *
50
+ * MCP Tool Logging Features (LOG_LLM_MCP=debug):
51
+ * - Tool call sequence tracking with unique sequence IDs
52
+ * - Tool execution performance metrics (duration in milliseconds)
53
+ * - Tool result content analysis (size, type, preview)
54
+ * - Tool call success/failure status with detailed error information
55
+ * - Tool call dependencies and parent-child relationships
56
+ * - Tool argument validation and presence checking
57
+ * - Streaming vs non-streaming execution path differentiation
58
+ * - Complete tool call lifecycle from start to completion
59
+ * - Server-side tool execution via direct MCP server registry calls
60
+ * - AI SDK tool conversion execution tracking
61
+ * - Tool result processing and content type identification
62
+ *
63
+ * LLM Queue Implementation:
64
+ * - Global singleton queue prevents concurrent LLM calls across all agents and worlds
65
+ * - FIFO (First In, First Out) processing ensures fair agent response ordering
66
+ * - Maximum queue size of 100 items prevents memory overflow issues
67
+ * - 15-minute timeout per LLM call supports long-running tool executions (configurable)
68
+ * - Warning logs at 50% timeout threshold for debugging long-running operations
69
+ * - Queue status monitoring available for debugging and performance analysis
70
+ * - Emergency clear function allows administrative queue reset when needed
71
+ * - Proper error handling with promise rejection for failed calls
72
+ * - Automatic queue processing with safety measures for edge cases
73
+ * - Timeout cleanup on promise resolution prevents resource leaks and Jest hanging
74
+ * - Configurable timeout via setProcessingTimeout() for different use cases
75
+ *
76
+ * Browser Safety Implementation:
77
+ * - Zero process.env dependencies for browser compatibility
78
+ * - Configuration injection via llm-config module
79
+ * - All provider settings supplied externally by CLI/server components
80
+ * - Type-safe configuration interfaces prevent runtime errors
81
+ * - Clear error messages when configuration is missing
82
+ *
83
+ * Implementation Details:
84
+ * - Uses direct OpenAI package for OpenAI providers to avoid AI SDK schema corruption bug
85
+ * - Uses direct Anthropic SDK for Anthropic provider to fix tool calling issues
86
+ * - Uses direct Google Generative AI SDK for Google provider to fix tool calling issues
87
+ * - Publishes SSE events via world.eventEmitter.emit('sse', event) for proper isolation
88
+ * - Updates agent activity metrics and LLM call counts automatically
89
+ * - Zero dependencies on Node.js environment variables or legacy event systems
90
+ * - Complete provider support with externally injected configuration
91
+ * - All events scoped to specific world instance preventing cross-world interference
92
+ * - Full LLM provider support with configuration validation and error handling
93
+ * - Timeout handling with configurable limits and proper error recovery
94
+ * - Queue-based serialization prevents API rate limits and resource conflicts
95
+ *
96
+ * Recent Changes:
97
+ * - 2026-02-13: Reclassified stop-triggered aborts as cancellation/info logs (not errors) in queue and non-streaming paths.
98
+ * - 2026-02-13: Added merged external+queue abort-signal support so chat stop requests can cancel follow-up continuation calls.
99
+ * - 2026-02-13: Added chat-scoped LLM cancellation controls so Electron stop requests can abort active and queued calls by `worldId` + `chatId`.
100
+ * - 2026-02-08: Removed stale manual tool-intervention terminology from internal comments
101
+ * - 2025-11-09: Phase 5 - Updated to expect LLMResponse from all providers
102
+ * - Removed old manual tool decision return type handling
103
+ * - All providers now return unified LLMResponse interface with type discriminator
104
+ * - Updated logging to handle LLMResponse structure (type, content, tool_calls)
105
+ * - Providers are now pure clients - no tool execution, only API calls
106
+ * - NO type checking for string vs object - always LLMResponse
107
+ * - Tool orchestration will be handled by events.ts (Phase 6)
108
+ * - Simplified tool usage guidance: minimal system prompt patch for tool availability
109
+ * - Increased LLM queue timeout from 2 minutes to 15 minutes for long-running tool executions
110
+ * - Replaced AI SDK with direct OpenAI, Anthropic, and Google integrations
111
+ * - Implemented granular function-based logging for detailed debugging control
112
+ * - Tool-specific guidance moved to individual tool descriptions (proper separation)
113
+ */
114
+ import { LLMProvider } from './types.js';
115
+ import { getMCPToolsForWorld } from './mcp-server-registry.js';
116
+ import { filterClientSideMessages } from './message-prep.js';
117
+ import { createClientForProvider, streamOpenAIResponse, generateOpenAIResponse } from './openai-direct.js';
118
+ import { createAnthropicClientForAgent, streamAnthropicResponse, generateAnthropicResponse } from './anthropic-direct.js';
119
+ import { createGoogleClientForAgent, streamGoogleResponse, generateGoogleResponse } from './google-direct.js';
120
+ import { generateId } from './utils.js';
121
+ import { createCategoryLogger } from './logger.js';
122
+ import { createStorageWithWrappers } from './storage/storage-factory.js';
123
+ // Granular function-specific loggers for detailed debugging control
124
+ const loggerQueue = createCategoryLogger('llm.queue');
125
+ const loggerStreaming = createCategoryLogger('llm.streaming');
126
+ const loggerGeneration = createCategoryLogger('llm.generation');
127
+ const loggerProvider = createCategoryLogger('llm.provider');
128
+ const loggerMCP = createCategoryLogger('llm.mcp');
129
+ const loggerUtil = createCategoryLogger('llm.util');
130
+ import { getLLMProviderConfig } from './llm-config.js';
131
+ // LLM Integration Utilities
132
+ function stripCustomFields(message) {
133
+ const { sender, chatId, ...llmMessage } = message;
134
+ loggerUtil.trace('Stripped custom fields from message', { originalFields: ['sender', 'chatId'], remainingKeys: Object.keys(llmMessage) });
135
+ return llmMessage;
136
+ }
137
+ function stripCustomFieldsFromMessages(messages) {
138
+ loggerUtil.debug(`Stripping custom fields from ${messages.length} messages`);
139
+ // First, filter out client-side tool request wrappers and orphaned tool results.
140
+ const filteredMessages = filterClientSideMessages(messages);
141
+ loggerUtil.debug(`Filtered to ${filteredMessages.length} messages (removed ${messages.length - filteredMessages.length} client-side messages)`);
142
+ // Then strip custom fields
143
+ return filteredMessages.map(stripCustomFields);
144
+ }
145
+ /**
146
+ * Append tool usage guidance to system message when tools are available
147
+ * Returns a new array with updated system message (doesn't mutate original)
148
+ */
149
+ function appendToolRulesToSystemMessage(messages, hasMCPTools) {
150
+ if (!hasMCPTools || messages.length === 0 || messages[0].role !== 'system') {
151
+ return messages;
152
+ }
153
+ const systemMessage = messages[0];
154
+ // Simple guidance: Only use tools when user explicitly requests an action
155
+ const toolRules = '\n\nYou have access to tools. Use them only when the user explicitly requests an action.';
156
+ return [
157
+ { ...systemMessage, content: systemMessage.content + toolRules },
158
+ ...messages.slice(1)
159
+ ];
160
+ }
161
+ // Storage wrapper for tool-execution follow-up handling
162
+ let storageWrappersPromise = null;
163
+ async function getStorageWrappers() {
164
+ if (!storageWrappersPromise) {
165
+ storageWrappersPromise = createStorageWithWrappers();
166
+ }
167
+ return storageWrappersPromise;
168
+ }
169
+ function normalizeChatId(chatId) {
170
+ if (chatId == null)
171
+ return '__none__';
172
+ return String(chatId);
173
+ }
174
+ class LLMQueue {
175
+ queue = [];
176
+ processing = false;
177
+ activeItem = null;
178
+ maxQueueSize = 100; // Prevent memory issues
179
+ processingTimeoutMs = 900000; // 15 minute max processing time per call (for long-running tools)
180
+ async add(agentId, worldId, chatId, task) {
181
+ // Prevent queue overflow
182
+ if (this.queue.length >= this.maxQueueSize) {
183
+ throw new Error(`LLM queue is full (${this.maxQueueSize} items). Please try again later.`);
184
+ }
185
+ loggerQueue.debug(`LLMQueue: Adding task for agent=${agentId}, world=${worldId}, chat=${normalizeChatId(chatId)}. Queue length before add: ${this.queue.length}`);
186
+ return new Promise((resolve, reject) => {
187
+ const queueItem = {
188
+ id: generateId(),
189
+ agentId,
190
+ worldId,
191
+ chatId,
192
+ abortController: new AbortController(),
193
+ canceled: false,
194
+ execute: task,
195
+ resolve,
196
+ reject
197
+ };
198
+ this.queue.push(queueItem);
199
+ this.processQueue();
200
+ });
201
+ }
202
+ async processQueue() {
203
+ if (this.processing || this.queue.length === 0) {
204
+ return;
205
+ }
206
+ this.processing = true;
207
+ loggerQueue.debug(`LLMQueue: Starting queue processing. Queue length: ${this.queue.length}`);
208
+ while (this.queue.length > 0) {
209
+ const item = this.queue.shift();
210
+ if (item.canceled) {
211
+ continue;
212
+ }
213
+ try {
214
+ this.activeItem = item;
215
+ const taskStartTime = Date.now();
216
+ loggerQueue.debug(`LLMQueue: Processing task for agent=${item.agentId}, world=${item.worldId}, chat=${normalizeChatId(item.chatId)}, queueItemId=${item.id}`);
217
+ // Add processing timeout to prevent stuck queue
218
+ const processPromise = item.execute(item.abortController.signal);
219
+ // Store timeout ID so we can cancel it if process completes first
220
+ let timeoutId;
221
+ let warningTimeoutId;
222
+ // Warn if processing takes more than 50% of timeout
223
+ const warningThreshold = this.processingTimeoutMs * 0.5;
224
+ warningTimeoutId = setTimeout(() => {
225
+ const elapsed = Date.now() - taskStartTime;
226
+ loggerQueue.warn(`LLM task is taking longer than expected`, {
227
+ agentId: item.agentId,
228
+ worldId: item.worldId,
229
+ elapsed,
230
+ timeoutMs: this.processingTimeoutMs,
231
+ percentComplete: Math.round((elapsed / this.processingTimeoutMs) * 100)
232
+ });
233
+ }, warningThreshold);
234
+ const timeoutPromise = new Promise((_, reject) => {
235
+ timeoutId = setTimeout(() => {
236
+ reject(new Error(`LLM call timeout after ${this.processingTimeoutMs}ms for agent ${item.agentId}`));
237
+ }, this.processingTimeoutMs);
238
+ });
239
+ const result = await Promise.race([processPromise, timeoutPromise]);
240
+ // Clear both timeouts to prevent Jest from hanging
241
+ clearTimeout(timeoutId);
242
+ clearTimeout(warningTimeoutId);
243
+ item.resolve(result);
244
+ loggerQueue.debug(`LLMQueue: Finished processing task for agent=${item.agentId}, world=${item.worldId}, queueItemId=${item.id}`);
245
+ }
246
+ catch (error) {
247
+ const wasCanceled = item.canceled || item.abortController.signal.aborted || isAbortError(error);
248
+ if (wasCanceled) {
249
+ loggerQueue.info('LLM queue call canceled', {
250
+ agentId: item.agentId,
251
+ worldId: item.worldId,
252
+ chatId: normalizeChatId(item.chatId),
253
+ queueItemId: item.id,
254
+ reason: error instanceof Error ? error.message : String(error)
255
+ });
256
+ }
257
+ else {
258
+ loggerQueue.error('LLM queue error', {
259
+ agentId: item.agentId,
260
+ worldId: item.worldId,
261
+ chatId: normalizeChatId(item.chatId),
262
+ queueItemId: item.id,
263
+ error: error instanceof Error ? error.message : error
264
+ });
265
+ }
266
+ item.reject(error);
267
+ }
268
+ finally {
269
+ this.activeItem = null;
270
+ }
271
+ }
272
+ this.processing = false;
273
+ loggerQueue.debug('LLMQueue: Queue processing complete.');
274
+ }
275
+ getQueueStatus() {
276
+ const next = this.queue[0];
277
+ return {
278
+ queueLength: this.queue.length,
279
+ processing: this.processing,
280
+ nextAgent: next?.agentId,
281
+ nextWorld: next?.worldId,
282
+ maxQueueSize: this.maxQueueSize
283
+ };
284
+ }
285
+ // Emergency method to clear stuck queue (for debugging/admin use)
286
+ clearQueue() {
287
+ const clearedCount = this.queue.length;
288
+ for (const item of this.queue) {
289
+ item.canceled = true;
290
+ item.abortController.abort();
291
+ item.reject(new Error('LLM queue item canceled by queue clear.'));
292
+ }
293
+ this.queue.length = 0;
294
+ loggerQueue.info('LLM queue cleared', { clearedCount });
295
+ return clearedCount;
296
+ }
297
+ cancelByChat(worldId, chatId) {
298
+ const targetChatId = normalizeChatId(chatId);
299
+ let canceledPending = 0;
300
+ let abortedActive = 0;
301
+ this.queue = this.queue.filter((item) => {
302
+ const matchesWorld = item.worldId === worldId;
303
+ const matchesChat = normalizeChatId(item.chatId) === targetChatId;
304
+ if (!matchesWorld || !matchesChat) {
305
+ return true;
306
+ }
307
+ item.canceled = true;
308
+ item.abortController.abort();
309
+ item.reject(new Error(`LLM call canceled for world '${worldId}' chat '${targetChatId}'.`));
310
+ canceledPending += 1;
311
+ return false;
312
+ });
313
+ if (this.activeItem) {
314
+ const matchesWorld = this.activeItem.worldId === worldId;
315
+ const matchesChat = normalizeChatId(this.activeItem.chatId) === targetChatId;
316
+ if (matchesWorld && matchesChat && !this.activeItem.abortController.signal.aborted) {
317
+ this.activeItem.abortController.abort();
318
+ abortedActive = 1;
319
+ }
320
+ }
321
+ return { canceledPending, abortedActive };
322
+ }
323
+ // Set processing timeout (useful for testing or adjusting for long-running operations)
324
+ setProcessingTimeout(timeoutMs) {
325
+ if (timeoutMs < 1000) {
326
+ throw new Error('Processing timeout must be at least 1000ms');
327
+ }
328
+ this.processingTimeoutMs = timeoutMs;
329
+ loggerQueue.info('LLM queue processing timeout updated', { timeoutMs });
330
+ }
331
+ // Get current processing timeout
332
+ getProcessingTimeout() {
333
+ return this.processingTimeoutMs;
334
+ }
335
+ }
336
+ // Global singleton queue instance
337
+ const llmQueue = new LLMQueue();
338
+ function isAbortError(error) {
339
+ if (!error)
340
+ return false;
341
+ if (error instanceof DOMException && error.name === 'AbortError')
342
+ return true;
343
+ if (error instanceof Error && error.name === 'AbortError')
344
+ return true;
345
+ const message = error instanceof Error ? error.message : String(error);
346
+ return message.toLowerCase().includes('abort');
347
+ }
348
+ function createCombinedAbortSignal(first, second) {
349
+ const signals = [first, second].filter((value) => Boolean(value));
350
+ if (signals.length === 0) {
351
+ return { signal: undefined, dispose: () => { } };
352
+ }
353
+ if (signals.length === 1) {
354
+ return { signal: signals[0], dispose: () => { } };
355
+ }
356
+ const controller = new AbortController();
357
+ const onAbort = () => {
358
+ if (!controller.signal.aborted) {
359
+ controller.abort();
360
+ }
361
+ };
362
+ for (const signal of signals) {
363
+ if (signal.aborted) {
364
+ controller.abort();
365
+ break;
366
+ }
367
+ signal.addEventListener('abort', onAbort);
368
+ }
369
+ const dispose = () => {
370
+ for (const signal of signals) {
371
+ signal.removeEventListener('abort', onAbort);
372
+ }
373
+ };
374
+ return { signal: controller.signal, dispose };
375
+ }
376
+ /**
377
+ * Streaming agent response with SSE events via world's eventEmitter (queued)
378
+ */
379
+ export async function streamAgentResponse(world, agent, messages, publishSSE, chatId = null, abortSignal) {
380
+ if (abortSignal?.aborted) {
381
+ throw new DOMException(`LLM call aborted before queue for agent ${agent.id}`, 'AbortError');
382
+ }
383
+ // Queue the LLM call to ensure serialized execution
384
+ return llmQueue.add(agent.id, world.id, chatId, async (queueAbortSignal) => {
385
+ const { signal: mergedAbortSignal, dispose } = createCombinedAbortSignal(queueAbortSignal, abortSignal);
386
+ try {
387
+ if (mergedAbortSignal?.aborted) {
388
+ throw new DOMException(`LLM call aborted before execution for agent ${agent.id}`, 'AbortError');
389
+ }
390
+ return await executeStreamAgentResponse(world, agent, messages, publishSSE, mergedAbortSignal);
391
+ }
392
+ finally {
393
+ dispose();
394
+ }
395
+ });
396
+ }
397
+ /**
398
+ * Internal streaming implementation (executed within queue)
399
+ */
400
+ async function executeStreamAgentResponse(world, agent, messages, publishSSE, abortSignal) {
401
+ const messageId = generateId();
402
+ try {
403
+ if (abortSignal?.aborted) {
404
+ throw new DOMException('LLM call aborted before start', 'AbortError');
405
+ }
406
+ // Publish SSE start event via world's eventEmitter
407
+ publishSSE(world, {
408
+ agentName: agent.id,
409
+ type: 'start',
410
+ messageId
411
+ });
412
+ loggerStreaming.debug(`LLM: Starting streaming response for agent=${agent.id}, world=${world.id}, messageId=${messageId}`);
413
+ // Convert messages for LLM (strip custom fields)
414
+ // Note: Client-side filtering already done by utils.ts prepareMessagesForLLM
415
+ let preparedMessages = stripCustomFieldsFromMessages(messages);
416
+ // Get MCP tools for this world
417
+ const mcpTools = await getMCPToolsForWorld(world.id);
418
+ const hasMCPTools = Object.keys(mcpTools).length > 0;
419
+ // Add tool usage instructions to system message when tools are available
420
+ preparedMessages = appendToolRulesToSystemMessage(preparedMessages, hasMCPTools);
421
+ if (hasMCPTools) {
422
+ loggerMCP.debug(`LLM: Including ${Object.keys(mcpTools).length} MCP tools for agent=${agent.id}, world=${world.id}`);
423
+ // Debug: Log complete tool definitions being sent to LLM
424
+ for (const [toolKey, toolDef] of Object.entries(mcpTools)) {
425
+ loggerMCP.debug(`LLM: Tool definition for ${toolKey}`, {
426
+ toolName: toolKey,
427
+ description: toolDef.description,
428
+ parameters: JSON.stringify(toolDef.parameters, null, 2),
429
+ hasExecuteFunction: typeof toolDef.execute === 'function'
430
+ });
431
+ }
432
+ }
433
+ // Use direct OpenAI integration for OpenAI providers
434
+ if (isOpenAIProvider(agent.provider)) {
435
+ const client = createOpenAIClientForAgent(agent);
436
+ const response = await streamOpenAIResponse(client, agent.model, preparedMessages, agent, mcpTools, world, (content) => publishSSE(world, { agentName: agent.id, type: 'chunk', content, messageId }), messageId, abortSignal);
437
+ // Emit end event after streaming completes
438
+ publishSSE(world, { agentName: agent.id, type: 'end', messageId });
439
+ return { response, messageId };
440
+ }
441
+ // Use direct Anthropic integration for Anthropic provider
442
+ if (isAnthropicProvider(agent.provider)) {
443
+ const client = createAnthropicClientForAgent(agent);
444
+ const response = await streamAnthropicResponse(client, agent.model, preparedMessages, agent, mcpTools, world, (content) => publishSSE(world, { agentName: agent.id, type: 'chunk', content, messageId }), messageId, abortSignal);
445
+ // Emit end event after streaming completes
446
+ publishSSE(world, { agentName: agent.id, type: 'end', messageId });
447
+ return { response, messageId };
448
+ }
449
+ // Use direct Google integration for Google provider
450
+ if (isGoogleProvider(agent.provider)) {
451
+ const client = createGoogleClientForAgent(agent);
452
+ const response = await streamGoogleResponse(client, agent.model, preparedMessages, agent, mcpTools, world, (content) => publishSSE(world, { agentName: agent.id, type: 'chunk', content, messageId }), messageId, abortSignal);
453
+ // Emit end event after streaming completes
454
+ publishSSE(world, { agentName: agent.id, type: 'end', messageId });
455
+ return { response, messageId };
456
+ }
457
+ // All providers now use direct integrations - no AI SDK needed
458
+ throw new Error(`Unsupported provider: ${agent.provider}. All providers should use direct integrations.`);
459
+ }
460
+ catch (error) {
461
+ if (isAbortError(error) || abortSignal?.aborted) {
462
+ publishSSE(world, {
463
+ agentName: agent.id,
464
+ type: 'end',
465
+ messageId
466
+ });
467
+ loggerStreaming.info(`LLM: Streaming response canceled for agent=${agent.id}, world=${world.id}, messageId=${messageId}`);
468
+ throw new Error(`LLM call canceled for agent ${agent.id}`);
469
+ }
470
+ // Publish SSE error event via world's eventEmitter
471
+ publishSSE(world, {
472
+ agentName: agent.id,
473
+ type: 'error',
474
+ error: error.message,
475
+ messageId
476
+ });
477
+ loggerStreaming.error(`LLM: Error during streaming response for agent=${agent.id}, world=${world.id}, messageId=${messageId}, error=${error.message}`);
478
+ throw error;
479
+ }
480
+ }
481
+ /**
482
+ * Non-streaming LLM call (queued)
483
+ */
484
+ export async function generateAgentResponse(world, agent, messages, _publishSSE, skipTools, chatId = null, abortSignal) {
485
+ if (abortSignal?.aborted) {
486
+ throw new DOMException(`LLM call aborted before queue for agent ${agent.id}`, 'AbortError');
487
+ }
488
+ // Queue the LLM call to ensure serialized execution
489
+ return llmQueue.add(agent.id, world.id, chatId, async (queueAbortSignal) => {
490
+ const { signal: mergedAbortSignal, dispose } = createCombinedAbortSignal(queueAbortSignal, abortSignal);
491
+ try {
492
+ if (mergedAbortSignal?.aborted) {
493
+ throw new DOMException(`LLM call aborted before execution for agent ${agent.id}`, 'AbortError');
494
+ }
495
+ return await executeGenerateAgentResponse(world, agent, messages, skipTools, mergedAbortSignal);
496
+ }
497
+ finally {
498
+ dispose();
499
+ }
500
+ });
501
+ }
502
+ /**
503
+ * Internal generation implementation (executed within queue)
504
+ */
505
+ async function executeGenerateAgentResponse(world, agent, messages, skipTools, abortSignal) {
506
+ if (abortSignal?.aborted) {
507
+ throw new DOMException('LLM call aborted before start', 'AbortError');
508
+ }
509
+ const messageId = generateId();
510
+ // Convert messages for LLM (strip custom fields)
511
+ // Note: Client-side filtering already done by utils.ts prepareMessagesForLLM
512
+ let preparedMessages = stripCustomFieldsFromMessages(messages);
513
+ // Get MCP tools for this world (skip if requested, e.g., for title generation)
514
+ const mcpTools = skipTools ? {} : await getMCPToolsForWorld(world.id);
515
+ const hasMCPTools = Object.keys(mcpTools).length > 0;
516
+ // Add tool usage instructions to system message when tools are available
517
+ preparedMessages = appendToolRulesToSystemMessage(preparedMessages, hasMCPTools);
518
+ if (hasMCPTools) {
519
+ loggerMCP.debug(`LLM: Including ${Object.keys(mcpTools).length} MCP tools for agent=${agent.id}, world=${world.id}`);
520
+ // Debug: Log complete tool definitions being sent to LLM
521
+ for (const [toolKey, toolDef] of Object.entries(mcpTools)) {
522
+ loggerMCP.debug(`LLM: Tool definition for ${toolKey}`, {
523
+ toolName: toolKey,
524
+ description: toolDef.description,
525
+ parameters: JSON.stringify(toolDef.parameters, null, 2),
526
+ hasExecuteFunction: typeof toolDef.execute === 'function'
527
+ });
528
+ }
529
+ }
530
+ loggerGeneration.debug(`LLM: Starting non-streaming response for agent=${agent.id}, world=${world.id}`, {
531
+ messageCount: preparedMessages.length,
532
+ allMessages: preparedMessages.map(m => ({
533
+ role: m.role,
534
+ hasContent: !!m.content,
535
+ contentPreview: m.content?.substring(0, 50),
536
+ hasToolCalls: !!m.tool_calls,
537
+ toolCallId: m.tool_call_id,
538
+ messageId: m.messageId,
539
+ agentId: m.agentId
540
+ }))
541
+ });
542
+ try {
543
+ // Use direct OpenAI integration for OpenAI providers
544
+ if (isOpenAIProvider(agent.provider)) {
545
+ const client = createOpenAIClientForAgent(agent);
546
+ const response = await generateOpenAIResponse(client, agent.model, preparedMessages, agent, mcpTools, world, abortSignal);
547
+ // Update agent activity and LLM call count
548
+ agent.lastActive = new Date();
549
+ agent.llmCallCount++;
550
+ agent.lastLLMCall = new Date();
551
+ loggerGeneration.debug(`LLM: Finished non-streaming OpenAI response for agent=${agent.id}, world=${world.id}`, {
552
+ responseType: response.type,
553
+ contentLength: response.content?.length || 0,
554
+ hasToolCalls: response.type === 'tool_calls',
555
+ toolCallCount: response.tool_calls?.length || 0,
556
+ messageId
557
+ });
558
+ return { response, messageId };
559
+ }
560
+ // Use direct Anthropic integration for Anthropic provider
561
+ if (isAnthropicProvider(agent.provider)) {
562
+ const client = createAnthropicClientForAgent(agent);
563
+ const response = await generateAnthropicResponse(client, agent.model, preparedMessages, agent, mcpTools, world, abortSignal);
564
+ // Update agent activity and LLM call count
565
+ agent.lastActive = new Date();
566
+ agent.llmCallCount++;
567
+ agent.lastLLMCall = new Date();
568
+ loggerGeneration.debug(`LLM: Finished non-streaming Anthropic response for agent=${agent.id}, world=${world.id}`, {
569
+ responseType: response.type,
570
+ contentLength: response.content?.length || 0,
571
+ hasToolCalls: response.type === 'tool_calls',
572
+ toolCallCount: response.tool_calls?.length || 0,
573
+ messageId
574
+ });
575
+ return { response, messageId };
576
+ }
577
+ // Use direct Google integration for Google provider
578
+ if (isGoogleProvider(agent.provider)) {
579
+ const client = createGoogleClientForAgent(agent);
580
+ const response = await generateGoogleResponse(client, agent.model, preparedMessages, agent, mcpTools, world, abortSignal);
581
+ // Update agent activity and LLM call count
582
+ agent.lastActive = new Date();
583
+ agent.llmCallCount++;
584
+ agent.lastLLMCall = new Date();
585
+ loggerGeneration.debug(`LLM: Finished non-streaming Google response for agent=${agent.id}, world=${world.id}`, {
586
+ responseType: response.type,
587
+ contentLength: response.content?.length || 0,
588
+ hasToolCalls: response.type === 'tool_calls',
589
+ toolCallCount: response.tool_calls?.length || 0,
590
+ messageId
591
+ });
592
+ return { response, messageId };
593
+ }
594
+ // All providers now use direct integrations - no AI SDK needed
595
+ throw new Error(`Provider ${agent.provider} should use direct integration, not AI SDK`);
596
+ }
597
+ catch (error) {
598
+ if (isAbortError(error) || abortSignal?.aborted) {
599
+ loggerGeneration.info(`LLM: Non-streaming response canceled for agent=${agent.id}, world=${world.id}, messageId=${messageId}`);
600
+ throw new Error(`LLM call canceled for agent ${agent.id}`);
601
+ }
602
+ loggerGeneration.error(`LLM: Error during non-streaming response for agent=${agent.id}, world=${world.id}, error=${error.message}`);
603
+ throw error;
604
+ }
605
+ }
606
+ /**
607
+ * Get current LLM queue status for monitoring and debugging
608
+ */
609
+ export function getLLMQueueStatus() {
610
+ return llmQueue.getQueueStatus();
611
+ }
612
+ /**
613
+ * Emergency function to clear the LLM queue (for debugging/admin use)
614
+ * Returns the number of items that were cleared
615
+ */
616
+ export function clearLLMQueue() {
617
+ return llmQueue.clearQueue();
618
+ }
619
+ /**
620
+ * Cancel active and pending LLM calls for a specific world/chat session.
621
+ */
622
+ export function cancelLLMCallsForChat(worldId, chatId) {
623
+ return llmQueue.cancelByChat(worldId, chatId);
624
+ }
625
+ /**
626
+ * Check if provider uses OpenAI package (direct integration)
627
+ */
628
+ function isOpenAIProvider(provider) {
629
+ return [
630
+ LLMProvider.OPENAI,
631
+ LLMProvider.AZURE,
632
+ LLMProvider.OPENAI_COMPATIBLE,
633
+ LLMProvider.XAI,
634
+ LLMProvider.OLLAMA // Added: Ollama now uses OpenAI-compatible endpoint
635
+ ].includes(provider);
636
+ }
637
+ /**
638
+ * Check if provider uses Anthropic direct integration
639
+ */
640
+ function isAnthropicProvider(provider) {
641
+ return provider === LLMProvider.ANTHROPIC;
642
+ }
643
+ /**
644
+ * Check if provider uses Google direct integration
645
+ */
646
+ function isGoogleProvider(provider) {
647
+ return provider === LLMProvider.GOOGLE;
648
+ }
649
+ /**
650
+ * Create OpenAI client for agent based on provider type
651
+ */
652
+ function createOpenAIClientForAgent(agent) {
653
+ const config = getLLMProviderConfig(agent.provider);
654
+ switch (agent.provider) {
655
+ case LLMProvider.OPENAI:
656
+ return createClientForProvider('openai', config);
657
+ case LLMProvider.AZURE:
658
+ return createClientForProvider('azure', config);
659
+ case LLMProvider.OPENAI_COMPATIBLE:
660
+ return createClientForProvider('openai-compatible', config);
661
+ case LLMProvider.XAI:
662
+ return createClientForProvider('xai', config);
663
+ case LLMProvider.OLLAMA:
664
+ return createClientForProvider('ollama', config);
665
+ default:
666
+ throw new Error(`Unsupported OpenAI provider: ${agent.provider}`);
667
+ }
668
+ }
669
+ //# sourceMappingURL=llm-manager.js.map