@framers/agentos 0.1.6 → 0.1.8

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 (287) hide show
  1. package/README.md +19 -0
  2. package/dist/api/AgentOS.d.ts +12 -0
  3. package/dist/api/AgentOS.d.ts.map +1 -1
  4. package/dist/api/AgentOS.js +100 -2
  5. package/dist/api/AgentOS.js.map +1 -1
  6. package/dist/api/AgentOSOrchestrator.d.ts +45 -0
  7. package/dist/api/AgentOSOrchestrator.d.ts.map +1 -1
  8. package/dist/api/AgentOSOrchestrator.js +470 -6
  9. package/dist/api/AgentOSOrchestrator.js.map +1 -1
  10. package/dist/api/types/AgentOSInput.d.ts +8 -0
  11. package/dist/api/types/AgentOSInput.d.ts.map +1 -1
  12. package/dist/api/types/AgentOSResponse.d.ts +22 -2
  13. package/dist/api/types/AgentOSResponse.d.ts.map +1 -1
  14. package/dist/api/types/AgentOSResponse.js +1 -0
  15. package/dist/api/types/AgentOSResponse.js.map +1 -1
  16. package/dist/channels/ChannelRouter.d.ts +150 -0
  17. package/dist/channels/ChannelRouter.d.ts.map +1 -0
  18. package/dist/channels/ChannelRouter.js +309 -0
  19. package/dist/channels/ChannelRouter.js.map +1 -0
  20. package/dist/channels/IChannelAdapter.d.ts +113 -0
  21. package/dist/channels/IChannelAdapter.d.ts.map +1 -0
  22. package/dist/channels/IChannelAdapter.js +17 -0
  23. package/dist/channels/IChannelAdapter.js.map +1 -0
  24. package/dist/channels/index.d.ts +9 -0
  25. package/dist/channels/index.d.ts.map +1 -0
  26. package/dist/channels/index.js +7 -0
  27. package/dist/channels/index.js.map +1 -0
  28. package/dist/channels/types.d.ts +257 -0
  29. package/dist/channels/types.d.ts.map +1 -0
  30. package/dist/channels/types.js +12 -0
  31. package/dist/channels/types.js.map +1 -0
  32. package/dist/cognitive_substrate/GMI.d.ts +139 -0
  33. package/dist/cognitive_substrate/GMI.d.ts.map +1 -1
  34. package/dist/cognitive_substrate/GMI.js +680 -14
  35. package/dist/cognitive_substrate/GMI.js.map +1 -1
  36. package/dist/cognitive_substrate/GMIEvent.d.ts +151 -0
  37. package/dist/cognitive_substrate/GMIEvent.d.ts.map +1 -0
  38. package/dist/cognitive_substrate/GMIEvent.js +79 -0
  39. package/dist/cognitive_substrate/GMIEvent.js.map +1 -0
  40. package/dist/cognitive_substrate/IGMI.d.ts +22 -0
  41. package/dist/cognitive_substrate/IGMI.d.ts.map +1 -1
  42. package/dist/cognitive_substrate/IGMI.js.map +1 -1
  43. package/dist/cognitive_substrate/personas/IPersonaDefinition.d.ts +92 -0
  44. package/dist/cognitive_substrate/personas/IPersonaDefinition.d.ts.map +1 -1
  45. package/dist/cognitive_substrate/personas/PersonaLoader.d.ts.map +1 -1
  46. package/dist/cognitive_substrate/personas/PersonaLoader.js +21 -0
  47. package/dist/cognitive_substrate/personas/PersonaLoader.js.map +1 -1
  48. package/dist/cognitive_substrate/personas/metaprompt_presets.d.ts +86 -0
  49. package/dist/cognitive_substrate/personas/metaprompt_presets.d.ts.map +1 -0
  50. package/dist/cognitive_substrate/personas/metaprompt_presets.js +457 -0
  51. package/dist/cognitive_substrate/personas/metaprompt_presets.js.map +1 -0
  52. package/dist/config/RetrievalAugmentorConfiguration.d.ts +21 -0
  53. package/dist/config/RetrievalAugmentorConfiguration.d.ts.map +1 -1
  54. package/dist/config/RetrievalAugmentorConfiguration.js.map +1 -1
  55. package/dist/config/VectorStoreConfiguration.d.ts +2 -1
  56. package/dist/config/VectorStoreConfiguration.d.ts.map +1 -1
  57. package/dist/config/VectorStoreConfiguration.js.map +1 -1
  58. package/dist/config/extension-secrets.json +360 -0
  59. package/dist/core/agents/AgentCore.d.ts +8 -0
  60. package/dist/core/agents/AgentCore.d.ts.map +1 -1
  61. package/dist/core/agents/AgentCore.js.map +1 -1
  62. package/dist/core/conversation/ConversationManager.d.ts.map +1 -1
  63. package/dist/core/conversation/ConversationManager.js +2 -4
  64. package/dist/core/conversation/ConversationManager.js.map +1 -1
  65. package/dist/core/conversation/ILongTermMemoryRetriever.d.ts +30 -0
  66. package/dist/core/conversation/ILongTermMemoryRetriever.d.ts.map +1 -0
  67. package/dist/core/conversation/ILongTermMemoryRetriever.js +2 -0
  68. package/dist/core/conversation/ILongTermMemoryRetriever.js.map +1 -0
  69. package/dist/core/conversation/IRollingSummaryMemorySink.d.ts +44 -0
  70. package/dist/core/conversation/IRollingSummaryMemorySink.d.ts.map +1 -0
  71. package/dist/core/conversation/IRollingSummaryMemorySink.js +9 -0
  72. package/dist/core/conversation/IRollingSummaryMemorySink.js.map +1 -0
  73. package/dist/core/conversation/LongTermMemoryPolicy.d.ts +53 -0
  74. package/dist/core/conversation/LongTermMemoryPolicy.d.ts.map +1 -0
  75. package/dist/core/conversation/LongTermMemoryPolicy.js +84 -0
  76. package/dist/core/conversation/LongTermMemoryPolicy.js.map +1 -0
  77. package/dist/core/conversation/RollingSummaryCompactor.d.ts +61 -0
  78. package/dist/core/conversation/RollingSummaryCompactor.d.ts.map +1 -0
  79. package/dist/core/conversation/RollingSummaryCompactor.js +255 -0
  80. package/dist/core/conversation/RollingSummaryCompactor.js.map +1 -0
  81. package/dist/core/llm/PromptEngine.d.ts.map +1 -1
  82. package/dist/core/llm/PromptEngine.js +10 -1
  83. package/dist/core/llm/PromptEngine.js.map +1 -1
  84. package/dist/core/orchestration/AgentOrchestrator.d.ts +40 -0
  85. package/dist/core/orchestration/AgentOrchestrator.d.ts.map +1 -1
  86. package/dist/core/orchestration/AgentOrchestrator.js +324 -2
  87. package/dist/core/orchestration/AgentOrchestrator.js.map +1 -1
  88. package/dist/core/prompting/PromptProfileRouter.d.ts +74 -0
  89. package/dist/core/prompting/PromptProfileRouter.d.ts.map +1 -0
  90. package/dist/core/prompting/PromptProfileRouter.js +270 -0
  91. package/dist/core/prompting/PromptProfileRouter.js.map +1 -0
  92. package/dist/core/provenance/anchoring/AnchorManager.d.ts +86 -0
  93. package/dist/core/provenance/anchoring/AnchorManager.d.ts.map +1 -0
  94. package/dist/core/provenance/anchoring/AnchorManager.js +244 -0
  95. package/dist/core/provenance/anchoring/AnchorManager.js.map +1 -0
  96. package/dist/core/provenance/anchoring/providers/CompositeAnchorProvider.d.ts +20 -0
  97. package/dist/core/provenance/anchoring/providers/CompositeAnchorProvider.d.ts.map +1 -0
  98. package/dist/core/provenance/anchoring/providers/CompositeAnchorProvider.js +62 -0
  99. package/dist/core/provenance/anchoring/providers/CompositeAnchorProvider.js.map +1 -0
  100. package/dist/core/provenance/anchoring/providers/NoneProvider.d.ts +15 -0
  101. package/dist/core/provenance/anchoring/providers/NoneProvider.d.ts.map +1 -0
  102. package/dist/core/provenance/anchoring/providers/NoneProvider.js +21 -0
  103. package/dist/core/provenance/anchoring/providers/NoneProvider.js.map +1 -0
  104. package/dist/core/provenance/anchoring/providers/createAnchorProvider.d.ts +38 -0
  105. package/dist/core/provenance/anchoring/providers/createAnchorProvider.d.ts.map +1 -0
  106. package/dist/core/provenance/anchoring/providers/createAnchorProvider.js +67 -0
  107. package/dist/core/provenance/anchoring/providers/createAnchorProvider.js.map +1 -0
  108. package/dist/core/provenance/anchoring/providers/index.d.ts +12 -0
  109. package/dist/core/provenance/anchoring/providers/index.d.ts.map +1 -0
  110. package/dist/core/provenance/anchoring/providers/index.js +12 -0
  111. package/dist/core/provenance/anchoring/providers/index.js.map +1 -0
  112. package/dist/core/provenance/config/PolicyProfiles.d.ts +60 -0
  113. package/dist/core/provenance/config/PolicyProfiles.d.ts.map +1 -0
  114. package/dist/core/provenance/config/PolicyProfiles.js +144 -0
  115. package/dist/core/provenance/config/PolicyProfiles.js.map +1 -0
  116. package/dist/core/provenance/crypto/AgentKeyManager.d.ts +48 -0
  117. package/dist/core/provenance/crypto/AgentKeyManager.d.ts.map +1 -0
  118. package/dist/core/provenance/crypto/AgentKeyManager.js +162 -0
  119. package/dist/core/provenance/crypto/AgentKeyManager.js.map +1 -0
  120. package/dist/core/provenance/crypto/HashChain.d.ts +58 -0
  121. package/dist/core/provenance/crypto/HashChain.d.ts.map +1 -0
  122. package/dist/core/provenance/crypto/HashChain.js +86 -0
  123. package/dist/core/provenance/crypto/HashChain.js.map +1 -0
  124. package/dist/core/provenance/crypto/MerkleTree.d.ts +41 -0
  125. package/dist/core/provenance/crypto/MerkleTree.d.ts.map +1 -0
  126. package/dist/core/provenance/crypto/MerkleTree.js +86 -0
  127. package/dist/core/provenance/crypto/MerkleTree.js.map +1 -0
  128. package/dist/core/provenance/enforcement/AutonomyGuard.d.ts +37 -0
  129. package/dist/core/provenance/enforcement/AutonomyGuard.d.ts.map +1 -0
  130. package/dist/core/provenance/enforcement/AutonomyGuard.js +120 -0
  131. package/dist/core/provenance/enforcement/AutonomyGuard.js.map +1 -0
  132. package/dist/core/provenance/enforcement/ProvenanceStorageHooks.d.ts +43 -0
  133. package/dist/core/provenance/enforcement/ProvenanceStorageHooks.d.ts.map +1 -0
  134. package/dist/core/provenance/enforcement/ProvenanceStorageHooks.js +193 -0
  135. package/dist/core/provenance/enforcement/ProvenanceStorageHooks.js.map +1 -0
  136. package/dist/core/provenance/enforcement/RevisionManager.d.ts +41 -0
  137. package/dist/core/provenance/enforcement/RevisionManager.d.ts.map +1 -0
  138. package/dist/core/provenance/enforcement/RevisionManager.js +105 -0
  139. package/dist/core/provenance/enforcement/RevisionManager.js.map +1 -0
  140. package/dist/core/provenance/enforcement/TombstoneManager.d.ts +47 -0
  141. package/dist/core/provenance/enforcement/TombstoneManager.d.ts.map +1 -0
  142. package/dist/core/provenance/enforcement/TombstoneManager.js +121 -0
  143. package/dist/core/provenance/enforcement/TombstoneManager.js.map +1 -0
  144. package/dist/core/provenance/index.d.ts +34 -0
  145. package/dist/core/provenance/index.d.ts.map +1 -0
  146. package/dist/core/provenance/index.js +39 -0
  147. package/dist/core/provenance/index.js.map +1 -0
  148. package/dist/core/provenance/ledger/EventTypes.d.ts +123 -0
  149. package/dist/core/provenance/ledger/EventTypes.d.ts.map +1 -0
  150. package/dist/core/provenance/ledger/EventTypes.js +9 -0
  151. package/dist/core/provenance/ledger/EventTypes.js.map +1 -0
  152. package/dist/core/provenance/ledger/SignedEventLedger.d.ts +75 -0
  153. package/dist/core/provenance/ledger/SignedEventLedger.d.ts.map +1 -0
  154. package/dist/core/provenance/ledger/SignedEventLedger.js +210 -0
  155. package/dist/core/provenance/ledger/SignedEventLedger.js.map +1 -0
  156. package/dist/core/provenance/schema/provenance-schema.d.ts +17 -0
  157. package/dist/core/provenance/schema/provenance-schema.d.ts.map +1 -0
  158. package/dist/core/provenance/schema/provenance-schema.js +104 -0
  159. package/dist/core/provenance/schema/provenance-schema.js.map +1 -0
  160. package/dist/core/provenance/types.d.ts +261 -0
  161. package/dist/core/provenance/types.d.ts.map +1 -0
  162. package/dist/core/provenance/types.js +21 -0
  163. package/dist/core/provenance/types.js.map +1 -0
  164. package/dist/core/provenance/verification/BundleExporter.d.ts +50 -0
  165. package/dist/core/provenance/verification/BundleExporter.d.ts.map +1 -0
  166. package/dist/core/provenance/verification/BundleExporter.js +240 -0
  167. package/dist/core/provenance/verification/BundleExporter.js.map +1 -0
  168. package/dist/core/provenance/verification/ChainVerifier.d.ts +39 -0
  169. package/dist/core/provenance/verification/ChainVerifier.d.ts.map +1 -0
  170. package/dist/core/provenance/verification/ChainVerifier.js +204 -0
  171. package/dist/core/provenance/verification/ChainVerifier.js.map +1 -0
  172. package/dist/core/provenance/verification/ConversationVerifier.d.ts +56 -0
  173. package/dist/core/provenance/verification/ConversationVerifier.d.ts.map +1 -0
  174. package/dist/core/provenance/verification/ConversationVerifier.js +109 -0
  175. package/dist/core/provenance/verification/ConversationVerifier.js.map +1 -0
  176. package/dist/extensions/ExtensionManager.d.ts +8 -0
  177. package/dist/extensions/ExtensionManager.d.ts.map +1 -1
  178. package/dist/extensions/ExtensionManager.js +58 -3
  179. package/dist/extensions/ExtensionManager.js.map +1 -1
  180. package/dist/extensions/MessagingChannelPayload.d.ts +39 -0
  181. package/dist/extensions/MessagingChannelPayload.d.ts.map +1 -0
  182. package/dist/extensions/MessagingChannelPayload.js +12 -0
  183. package/dist/extensions/MessagingChannelPayload.js.map +1 -0
  184. package/dist/extensions/manifest.d.ts +3 -1
  185. package/dist/extensions/manifest.d.ts.map +1 -1
  186. package/dist/extensions/packs/provenance-pack.d.ts +66 -0
  187. package/dist/extensions/packs/provenance-pack.d.ts.map +1 -0
  188. package/dist/extensions/packs/provenance-pack.js +162 -0
  189. package/dist/extensions/packs/provenance-pack.js.map +1 -0
  190. package/dist/extensions/types.d.ts +23 -0
  191. package/dist/extensions/types.d.ts.map +1 -1
  192. package/dist/extensions/types.js +4 -0
  193. package/dist/extensions/types.js.map +1 -1
  194. package/dist/index.d.ts +8 -0
  195. package/dist/index.d.ts.map +1 -1
  196. package/dist/index.js +12 -0
  197. package/dist/index.js.map +1 -1
  198. package/dist/rag/IRetrievalAugmentor.d.ts +22 -1
  199. package/dist/rag/IRetrievalAugmentor.d.ts.map +1 -1
  200. package/dist/rag/RetrievalAugmentor.d.ts +37 -0
  201. package/dist/rag/RetrievalAugmentor.d.ts.map +1 -1
  202. package/dist/rag/RetrievalAugmentor.js +82 -6
  203. package/dist/rag/RetrievalAugmentor.js.map +1 -1
  204. package/dist/rag/VectorStoreManager.d.ts.map +1 -1
  205. package/dist/rag/VectorStoreManager.js +5 -0
  206. package/dist/rag/VectorStoreManager.js.map +1 -1
  207. package/dist/rag/graphrag/GraphRAGEngine.d.ts +100 -0
  208. package/dist/rag/graphrag/GraphRAGEngine.d.ts.map +1 -0
  209. package/dist/rag/graphrag/GraphRAGEngine.js +1146 -0
  210. package/dist/rag/graphrag/GraphRAGEngine.js.map +1 -0
  211. package/dist/rag/graphrag/IGraphRAG.d.ts +198 -0
  212. package/dist/rag/graphrag/IGraphRAG.d.ts.map +1 -0
  213. package/dist/rag/graphrag/IGraphRAG.js +11 -0
  214. package/dist/rag/graphrag/IGraphRAG.js.map +1 -0
  215. package/dist/rag/graphrag/index.d.ts +12 -0
  216. package/dist/rag/graphrag/index.d.ts.map +1 -0
  217. package/dist/rag/graphrag/index.js +11 -0
  218. package/dist/rag/graphrag/index.js.map +1 -0
  219. package/dist/rag/implementations/vector_stores/HnswlibVectorStore.d.ts +72 -0
  220. package/dist/rag/implementations/vector_stores/HnswlibVectorStore.d.ts.map +1 -0
  221. package/dist/rag/implementations/vector_stores/HnswlibVectorStore.js +463 -0
  222. package/dist/rag/implementations/vector_stores/HnswlibVectorStore.js.map +1 -0
  223. package/dist/rag/implementations/vector_stores/index.d.ts +1 -0
  224. package/dist/rag/implementations/vector_stores/index.d.ts.map +1 -1
  225. package/dist/rag/implementations/vector_stores/index.js +2 -0
  226. package/dist/rag/implementations/vector_stores/index.js.map +1 -1
  227. package/dist/rag/index.d.ts +3 -0
  228. package/dist/rag/index.d.ts.map +1 -1
  229. package/dist/rag/index.js +5 -0
  230. package/dist/rag/index.js.map +1 -1
  231. package/dist/rag/reranking/IRerankerService.d.ts +163 -0
  232. package/dist/rag/reranking/IRerankerService.d.ts.map +1 -0
  233. package/dist/rag/reranking/IRerankerService.js +9 -0
  234. package/dist/rag/reranking/IRerankerService.js.map +1 -0
  235. package/dist/rag/reranking/RerankerService.d.ts +107 -0
  236. package/dist/rag/reranking/RerankerService.d.ts.map +1 -0
  237. package/dist/rag/reranking/RerankerService.js +194 -0
  238. package/dist/rag/reranking/RerankerService.js.map +1 -0
  239. package/dist/rag/reranking/index.d.ts +55 -0
  240. package/dist/rag/reranking/index.d.ts.map +1 -0
  241. package/dist/rag/reranking/index.js +56 -0
  242. package/dist/rag/reranking/index.js.map +1 -0
  243. package/dist/rag/reranking/providers/CohereReranker.d.ts +66 -0
  244. package/dist/rag/reranking/providers/CohereReranker.d.ts.map +1 -0
  245. package/dist/rag/reranking/providers/CohereReranker.js +141 -0
  246. package/dist/rag/reranking/providers/CohereReranker.js.map +1 -0
  247. package/dist/rag/reranking/providers/LocalCrossEncoderReranker.d.ts +105 -0
  248. package/dist/rag/reranking/providers/LocalCrossEncoderReranker.d.ts.map +1 -0
  249. package/dist/rag/reranking/providers/LocalCrossEncoderReranker.js +214 -0
  250. package/dist/rag/reranking/providers/LocalCrossEncoderReranker.js.map +1 -0
  251. package/dist/rag/reranking/providers/index.d.ts +7 -0
  252. package/dist/rag/reranking/providers/index.d.ts.map +1 -0
  253. package/dist/rag/reranking/providers/index.js +7 -0
  254. package/dist/rag/reranking/providers/index.js.map +1 -0
  255. package/dist/rag/reranking/tests/index.d.ts +6 -0
  256. package/dist/rag/reranking/tests/index.d.ts.map +1 -0
  257. package/dist/rag/reranking/tests/index.js +11 -0
  258. package/dist/rag/reranking/tests/index.js.map +1 -0
  259. package/dist/types/optionalDependencies.d.ts +5 -0
  260. package/dist/types/optionalDependencies.d.ts.map +1 -0
  261. package/dist/types/optionalDependencies.js +4 -0
  262. package/dist/types/optionalDependencies.js.map +1 -0
  263. package/dist/voice/CallManager.d.ts +116 -0
  264. package/dist/voice/CallManager.d.ts.map +1 -0
  265. package/dist/voice/CallManager.js +426 -0
  266. package/dist/voice/CallManager.js.map +1 -0
  267. package/dist/voice/IVoiceCallProvider.d.ts +137 -0
  268. package/dist/voice/IVoiceCallProvider.d.ts.map +1 -0
  269. package/dist/voice/IVoiceCallProvider.js +11 -0
  270. package/dist/voice/IVoiceCallProvider.js.map +1 -0
  271. package/dist/voice/index.d.ts +10 -0
  272. package/dist/voice/index.d.ts.map +1 -0
  273. package/dist/voice/index.js +8 -0
  274. package/dist/voice/index.js.map +1 -0
  275. package/dist/voice/providers/mock.d.ts +74 -0
  276. package/dist/voice/providers/mock.d.ts.map +1 -0
  277. package/dist/voice/providers/mock.js +199 -0
  278. package/dist/voice/providers/mock.js.map +1 -0
  279. package/dist/voice/telephony-audio.d.ts +42 -0
  280. package/dist/voice/telephony-audio.d.ts.map +1 -0
  281. package/dist/voice/telephony-audio.js +150 -0
  282. package/dist/voice/telephony-audio.js.map +1 -0
  283. package/dist/voice/types.d.ts +260 -0
  284. package/dist/voice/types.d.ts.map +1 -0
  285. package/dist/voice/types.js +36 -0
  286. package/dist/voice/types.js.map +1 -0
  287. package/package.json +22 -6
@@ -18,6 +18,7 @@ import { GMIOutputChunkType, GMIPrimeState, GMIMood, ReasoningEntryType, GMIInte
18
18
  import { RagMemoryCategory } from '../rag/IRetrievalAugmentor.js';
19
19
  import { createConversationMessage, MessageRole } from '../core/conversation/ConversationMessage.js';
20
20
  import { GMIError, GMIErrorCode, createGMIErrorFromError } from '../utils/errors.js';
21
+ import { GMIEventType, createGMIEvent } from './GMIEvent.js';
21
22
  const DEFAULT_MAX_CONVERSATION_HISTORY_TURNS = 20;
22
23
  const DEFAULT_SELF_REFLECTION_INTERVAL_TURNS = 5;
23
24
  const MAX_REASONING_TRACE_ENTRIES = 500; // Limit trace size in memory
@@ -35,6 +36,10 @@ export class GMI {
35
36
  */
36
37
  constructor(gmiId) {
37
38
  this.isInitialized = false; // Maintained as per user-provided GMI.ts
39
+ // Sentiment & Event Tracking
40
+ this.pendingGMIEvents = new Set();
41
+ this.eventHistory = []; // Last 20 events for debugging
42
+ this.metaPromptTriggerCounters = new Map();
38
43
  this.gmiId = gmiId || `gmi-${uuidv4()}`;
39
44
  this.creationTimestamp = new Date();
40
45
  this.state = GMIPrimeState.IDLE;
@@ -401,10 +406,25 @@ export class GMI {
401
406
  await this.workingMemory.set('currentUserContext', this.currentUserContext);
402
407
  }
403
408
  this.updateConversationHistory(turnInput);
409
+ // Analyze sentiment of user input only when sentiment tracking is enabled
410
+ if (this.activePersona.sentimentTracking?.enabled) {
411
+ const lastMsg = this.conversationHistory.length > 0
412
+ ? this.conversationHistory[this.conversationHistory.length - 1]
413
+ : null;
414
+ if (lastMsg?.role === 'user' && lastMsg?.content) {
415
+ const userInputText = typeof lastMsg.content === 'string'
416
+ ? lastMsg.content
417
+ : JSON.stringify(lastMsg.content);
418
+ await this.analyzeTurnSentiment(turnId, userInputText);
419
+ }
420
+ }
404
421
  let safetyBreak = 0;
405
422
  main_processing_loop: while (safetyBreak < 5) {
406
423
  safetyBreak++;
407
424
  let augmentedContextFromRAG = "";
425
+ const injectedLongTermMemoryContext = typeof turnInput.metadata?.longTermMemoryContext === 'string'
426
+ ? turnInput.metadata.longTermMemoryContext.trim()
427
+ : "";
408
428
  const lastMessage = this.conversationHistory.length > 0 ? this.conversationHistory[this.conversationHistory.length - 1] : null;
409
429
  const isUserInitiatedTurn = lastMessage?.role === 'user';
410
430
  if (this.retrievalAugmentor && this.activePersona.memoryConfig?.ragConfig?.enabled && isUserInitiatedTurn && lastMessage?.content) {
@@ -429,11 +449,33 @@ export class GMI {
429
449
  : typeof this.activePersona.baseSystemPrompt === 'string'
430
450
  ? [{ content: this.activePersona.baseSystemPrompt, priority: 1 }]
431
451
  : [];
452
+ const systemPrompts = [...baseSystemPrompts];
453
+ const rollingSummaryText = typeof turnInput.metadata?.rollingSummary?.text === 'string'
454
+ ? turnInput.metadata.rollingSummary.text.trim()
455
+ : '';
456
+ if (rollingSummaryText) {
457
+ systemPrompts.push({
458
+ content: `Rolling Memory Summary (compressed)\n${rollingSummaryText}`,
459
+ priority: 50,
460
+ });
461
+ }
462
+ const promptProfileInstructions = typeof turnInput.metadata?.promptProfile?.systemInstructions === 'string'
463
+ ? turnInput.metadata.promptProfile.systemInstructions.trim()
464
+ : '';
465
+ if (promptProfileInstructions) {
466
+ systemPrompts.push({
467
+ content: promptProfileInstructions,
468
+ priority: 60,
469
+ });
470
+ }
471
+ const durableHistoryForPrompt = Array.isArray(turnInput.metadata?.conversationHistoryForPrompt) && turnInput.metadata?.conversationHistoryForPrompt.length > 0
472
+ ? turnInput.metadata?.conversationHistoryForPrompt
473
+ : null;
432
474
  const promptComponents = {
433
- systemPrompts: baseSystemPrompts,
434
- conversationHistory: this.buildConversationHistoryForPrompt(),
475
+ systemPrompts,
476
+ conversationHistory: durableHistoryForPrompt ?? this.buildConversationHistoryForPrompt(),
435
477
  userInput: isUserInitiatedTurn && typeof lastMessage?.content === 'string' ? lastMessage.content : null,
436
- retrievedContext: augmentedContextFromRAG,
478
+ retrievedContext: [augmentedContextFromRAG, injectedLongTermMemoryContext].filter(Boolean).join("\n\n---\n\n"),
437
479
  // tools: this.activePersona.embeddedTools, // If ITool[] and PromptComponents.tools takes ITool[]
438
480
  };
439
481
  const preferredModelIdFromInput = turnInput.metadata?.options?.preferredModelId;
@@ -552,17 +594,8 @@ export class GMI {
552
594
  break main_processing_loop; // Break if no tool calls
553
595
  }
554
596
  await this.performPostTurnIngestion(typeof turnInput.content === 'string' ? turnInput.content : JSON.stringify(turnInput.content), aggregatedResponseText);
555
- this.turnsSinceLastReflection++;
556
- const reflectionMetaPrompt = this.activePersona.metaPrompts?.find(mp => mp.id === 'gmi_self_trait_adjustment');
557
- if (reflectionMetaPrompt?.trigger?.type === 'turn_interval' &&
558
- this.turnsSinceLastReflection >= (reflectionMetaPrompt.trigger.intervalTurns || this.selfReflectionIntervalTurns)) {
559
- this.addTraceEntry(ReasoningEntryType.SELF_REFLECTION_TRIGGERED, `Interval reached.`);
560
- this._triggerAndProcessSelfReflection().catch(err => {
561
- console.error(`GMI (ID: ${this.gmiId}): Background self-reflection error:`, err);
562
- this.addTraceEntry(ReasoningEntryType.ERROR, "Self-reflection background process failed.", { error: err.message });
563
- });
564
- this.turnsSinceLastReflection = 0;
565
- }
597
+ // Check and trigger all metaprompts (turn_interval, event_based, manual)
598
+ await this.checkAndTriggerMetaprompts(turnId);
566
599
  // Prepare the final GMIOutput for the generator's return value
567
600
  const finalTurnOutput = {
568
601
  isFinal: true,
@@ -735,6 +768,639 @@ export class GMI {
735
768
  console.error(`GMI (ID: ${this.gmiId}): RAG Ingestion Error - ${gmiError.message}`, gmiError.details);
736
769
  }
737
770
  }
771
+ /**
772
+ * Analyzes sentiment of user input and updates sentiment history.
773
+ * Triggers event detection based on sentiment patterns.
774
+ *
775
+ * @param turnId - Current turn identifier
776
+ * @param userInput - User's input text
777
+ * @private
778
+ */
779
+ async analyzeTurnSentiment(turnId, userInput) {
780
+ // Skip if input is not a string or is empty
781
+ if (!userInput || typeof userInput !== 'string') {
782
+ return;
783
+ }
784
+ try {
785
+ // Analyze sentiment using configurable method from sentimentTracking config
786
+ const stConfig = this.activePersona.sentimentTracking;
787
+ const sentimentResult = await this.utilityAI.analyzeSentiment(userInput, {
788
+ method: stConfig?.method || 'lexicon_based',
789
+ modelId: stConfig?.modelId || this.activePersona.defaultModelId,
790
+ providerId: stConfig?.providerId || this.activePersona.defaultProviderId,
791
+ language: this.currentUserContext.language || 'en',
792
+ });
793
+ // Update UserContext with current sentiment
794
+ this.currentUserContext.currentSentiment = sentimentResult.polarity;
795
+ await this.workingMemory.set('currentUserContext', this.currentUserContext);
796
+ // Get or initialize sentiment history
797
+ let sentimentHistory = await this.workingMemory.get('gmi_sentiment_history');
798
+ if (!sentimentHistory) {
799
+ sentimentHistory = {
800
+ trends: [],
801
+ consecutiveFrustration: 0,
802
+ consecutiveConfusion: 0,
803
+ consecutiveSatisfaction: 0,
804
+ };
805
+ }
806
+ // Add to sentiment trends
807
+ const trend = {
808
+ turnId,
809
+ timestamp: new Date(),
810
+ score: sentimentResult.score,
811
+ polarity: sentimentResult.polarity,
812
+ intensity: sentimentResult.intensity || 0,
813
+ context: userInput.substring(0, 100), // First 100 chars
814
+ };
815
+ sentimentHistory.trends.push(trend);
816
+ // Keep only last N trends (configurable sliding window)
817
+ const historyWindow = stConfig?.historyWindow || 10;
818
+ if (sentimentHistory.trends.length > historyWindow) {
819
+ sentimentHistory.trends.shift();
820
+ }
821
+ // Update consecutive counters based on configurable thresholds
822
+ const frustrationThreshold = stConfig?.frustrationThreshold ?? -0.3;
823
+ const satisfactionThreshold = stConfig?.satisfactionThreshold ?? 0.3;
824
+ if (sentimentResult.score < frustrationThreshold) {
825
+ // Negative sentiment
826
+ sentimentHistory.consecutiveFrustration++;
827
+ sentimentHistory.consecutiveConfusion = 0;
828
+ sentimentHistory.consecutiveSatisfaction = 0;
829
+ }
830
+ else if (sentimentResult.score > satisfactionThreshold) {
831
+ // Positive sentiment
832
+ sentimentHistory.consecutiveSatisfaction++;
833
+ sentimentHistory.consecutiveFrustration = 0;
834
+ sentimentHistory.consecutiveConfusion = 0;
835
+ }
836
+ else {
837
+ // Neutral sentiment (or close to it)
838
+ sentimentHistory.consecutiveConfusion++;
839
+ sentimentHistory.consecutiveFrustration = 0;
840
+ sentimentHistory.consecutiveSatisfaction = 0;
841
+ }
842
+ sentimentHistory.lastAnalyzedTurnId = turnId;
843
+ // Store updated sentiment history
844
+ await this.workingMemory.set('gmi_sentiment_history', sentimentHistory);
845
+ this.addTraceEntry(ReasoningEntryType.DEBUG, 'Turn sentiment analyzed', {
846
+ sentiment: {
847
+ score: sentimentResult.score,
848
+ polarity: sentimentResult.polarity,
849
+ intensity: sentimentResult.intensity,
850
+ },
851
+ consecutiveCounters: {
852
+ frustration: sentimentHistory.consecutiveFrustration,
853
+ confusion: sentimentHistory.consecutiveConfusion,
854
+ satisfaction: sentimentHistory.consecutiveSatisfaction,
855
+ },
856
+ });
857
+ // Detect and emit events based on sentiment patterns
858
+ await this.detectAndEmitEvents(turnId, userInput, sentimentResult, sentimentHistory);
859
+ }
860
+ catch (error) {
861
+ // Don't fail the turn if sentiment analysis fails - log and continue
862
+ console.error(`GMI (ID: ${this.gmiId}): Sentiment analysis error:`, error);
863
+ this.addTraceEntry(ReasoningEntryType.WARNING, 'Sentiment analysis failed', { error: error.message });
864
+ }
865
+ }
866
+ /**
867
+ * Detects emotional patterns and emits appropriate GMI events.
868
+ *
869
+ * @param turnId - Current turn identifier
870
+ * @param userInput - User's input text
871
+ * @param sentimentResult - Sentiment analysis result
872
+ * @param sentimentHistory - Historical sentiment data
873
+ * @private
874
+ */
875
+ async detectAndEmitEvents(turnId, userInput, sentimentResult, sentimentHistory) {
876
+ // Read configurable thresholds
877
+ const stConfig = this.activePersona.sentimentTracking;
878
+ const frustThreshold = stConfig?.frustrationThreshold ?? -0.3;
879
+ const satisThreshold = stConfig?.satisfactionThreshold ?? 0.3;
880
+ const consecutiveRequired = stConfig?.consecutiveTurnsForTrigger ?? 2;
881
+ // Frustration detection
882
+ if ((sentimentResult.score < frustThreshold && (sentimentResult.intensity || 0) > 0.6) ||
883
+ sentimentHistory.consecutiveFrustration >= consecutiveRequired) {
884
+ this.emitEvent(createGMIEvent(GMIEventType.USER_FRUSTRATED, turnId, sentimentHistory.consecutiveFrustration >= 2 ? 'high' : 'medium', {
885
+ sentimentScore: sentimentResult.score,
886
+ sentimentPolarity: sentimentResult.polarity,
887
+ sentimentIntensity: sentimentResult.intensity,
888
+ consecutiveTurns: sentimentHistory.consecutiveFrustration,
889
+ triggeredBy: 'sentiment',
890
+ }));
891
+ }
892
+ // Confusion detection (keyword-based + sentiment)
893
+ const confusionKeywords = [
894
+ 'confused',
895
+ "don't understand",
896
+ "dont understand",
897
+ 'unclear',
898
+ 'what do you mean',
899
+ 'explain',
900
+ 'clarify',
901
+ 'huh',
902
+ '??',
903
+ "doesn't make sense",
904
+ "doesnt make sense",
905
+ 'not sure',
906
+ ];
907
+ const lowerInput = userInput.toLowerCase();
908
+ const hasConfusionKeyword = confusionKeywords.some((keyword) => lowerInput.includes(keyword));
909
+ const triggerKeywords = hasConfusionKeyword
910
+ ? confusionKeywords.filter((keyword) => lowerInput.includes(keyword))
911
+ : [];
912
+ if (hasConfusionKeyword ||
913
+ (sentimentResult.polarity === 'neutral' &&
914
+ sentimentResult.negativeTokens &&
915
+ sentimentResult.negativeTokens.length > 2)) {
916
+ this.emitEvent(createGMIEvent(GMIEventType.USER_CONFUSED, turnId, sentimentHistory.consecutiveConfusion >= 2 ? 'high' : 'medium', {
917
+ triggeredBy: hasConfusionKeyword ? 'keyword' : 'sentiment',
918
+ consecutiveTurns: sentimentHistory.consecutiveConfusion,
919
+ evidencePreview: userInput.substring(0, 100),
920
+ triggerKeywords: hasConfusionKeyword ? triggerKeywords : undefined,
921
+ }));
922
+ }
923
+ // Satisfaction detection
924
+ if ((sentimentResult.score > satisThreshold && (sentimentResult.intensity || 0) > 0.5) ||
925
+ sentimentHistory.consecutiveSatisfaction >= (consecutiveRequired + 1)) {
926
+ this.emitEvent(createGMIEvent(GMIEventType.USER_SATISFIED, turnId, 'low', {
927
+ sentimentScore: sentimentResult.score,
928
+ sentimentPolarity: sentimentResult.polarity,
929
+ sentimentIntensity: sentimentResult.intensity,
930
+ consecutiveTurns: sentimentHistory.consecutiveSatisfaction,
931
+ triggeredBy: 'sentiment',
932
+ }));
933
+ }
934
+ // Error threshold detection (check reasoning trace for recent errors)
935
+ const recentErrors = this.reasoningTrace.entries
936
+ .slice(-10)
937
+ .filter((entry) => entry.type === ReasoningEntryType.ERROR);
938
+ if (recentErrors.length >= 2) {
939
+ this.emitEvent(createGMIEvent(GMIEventType.ERROR_THRESHOLD_EXCEEDED, turnId, 'high', {
940
+ triggeredBy: 'error',
941
+ errorCount: recentErrors.length,
942
+ consecutiveTurns: recentErrors.length,
943
+ }));
944
+ }
945
+ // Low engagement detection (consecutive neutral with short responses)
946
+ const recentUserMessages = this.conversationHistory
947
+ .slice(-5)
948
+ .filter((msg) => msg.role === 'user');
949
+ const avgLength = recentUserMessages.length > 0
950
+ ? recentUserMessages.reduce((sum, msg) => sum + String(msg.content).length, 0) / recentUserMessages.length
951
+ : 0;
952
+ if (sentimentHistory.consecutiveConfusion >= 4 && avgLength < 50) {
953
+ this.emitEvent(createGMIEvent(GMIEventType.LOW_ENGAGEMENT, turnId, 'medium', {
954
+ triggeredBy: 'pattern',
955
+ consecutiveTurns: sentimentHistory.consecutiveConfusion,
956
+ evidencePreview: `Avg response length: ${avgLength.toFixed(0)} chars`,
957
+ }));
958
+ }
959
+ }
960
+ /**
961
+ * Emits a GMI event and stores it in event history.
962
+ *
963
+ * @param event - The event to emit
964
+ * @private
965
+ */
966
+ emitEvent(event) {
967
+ // Add to pending events (will be consumed by trigger checking)
968
+ this.pendingGMIEvents.add(event.eventType);
969
+ // Add to event history for debugging (circular buffer, max 20)
970
+ this.eventHistory.push(event);
971
+ if (this.eventHistory.length > 20) {
972
+ this.eventHistory.shift();
973
+ }
974
+ this.addTraceEntry(ReasoningEntryType.DEBUG, `GMI Event Emitted: ${event.eventType}`, {
975
+ event: {
976
+ eventType: event.eventType,
977
+ turnId: event.turnId,
978
+ severity: event.severity,
979
+ metadata: event.metadata,
980
+ },
981
+ });
982
+ }
983
+ /**
984
+ * Checks all metaprompt triggers (turn_interval, event_based, manual) and executes triggered ones.
985
+ *
986
+ * @param turnId - Current turn identifier
987
+ * @private
988
+ */
989
+ async checkAndTriggerMetaprompts(turnId) {
990
+ if (!this.activePersona.metaPrompts || this.activePersona.metaPrompts.length === 0) {
991
+ return;
992
+ }
993
+ const triggeredMetaPrompts = [];
994
+ for (const metaPrompt of this.activePersona.metaPrompts) {
995
+ if (!metaPrompt.trigger)
996
+ continue;
997
+ if (metaPrompt.trigger.type === 'turn_interval') {
998
+ // Existing turn_interval logic
999
+ const counter = await this.getMetapromptTurnCounter(metaPrompt.id);
1000
+ if (counter >= metaPrompt.trigger.intervalTurns) {
1001
+ triggeredMetaPrompts.push(metaPrompt);
1002
+ await this.resetMetapromptTurnCounter(metaPrompt.id);
1003
+ }
1004
+ else {
1005
+ await this.incrementMetapromptTurnCounter(metaPrompt.id);
1006
+ }
1007
+ }
1008
+ else if (metaPrompt.trigger.type === 'event_based') {
1009
+ // NEW: Event-based trigger checking
1010
+ const eventName = metaPrompt.trigger.eventName;
1011
+ if (this.pendingGMIEvents.has(eventName)) {
1012
+ triggeredMetaPrompts.push(metaPrompt);
1013
+ // Consume the event (remove from pending)
1014
+ this.pendingGMIEvents.delete(eventName);
1015
+ }
1016
+ }
1017
+ else if (metaPrompt.trigger.type === 'manual') {
1018
+ // NEW: Manual trigger checking
1019
+ // Check for manual trigger flag in working memory
1020
+ const manualFlag = await this.workingMemory.get(`manual_trigger_${metaPrompt.id}`);
1021
+ if (manualFlag) {
1022
+ triggeredMetaPrompts.push(metaPrompt);
1023
+ // Clear the flag
1024
+ await this.workingMemory.delete(`manual_trigger_${metaPrompt.id}`);
1025
+ }
1026
+ }
1027
+ }
1028
+ if (triggeredMetaPrompts.length > 0) {
1029
+ this.addTraceEntry(ReasoningEntryType.SELF_REFLECTION_TRIGGERED, `${triggeredMetaPrompts.length} metaprompt(s) triggered`, { ids: triggeredMetaPrompts.map((m) => m.id), turnId });
1030
+ // Execute metaprompts (background task, don't block turn)
1031
+ this.executeMetaprompts(triggeredMetaPrompts).catch((err) => {
1032
+ console.error(`GMI (ID: ${this.gmiId}): Metaprompt execution error:`, err);
1033
+ this.addTraceEntry(ReasoningEntryType.ERROR, 'Metaprompt execution failed', { error: err.message });
1034
+ });
1035
+ }
1036
+ }
1037
+ /**
1038
+ * Gets the turn counter for a specific metaprompt.
1039
+ *
1040
+ * @param metapromptId - Metaprompt identifier
1041
+ * @returns Current counter value
1042
+ * @private
1043
+ */
1044
+ async getMetapromptTurnCounter(metapromptId) {
1045
+ const counter = this.metaPromptTriggerCounters.get(metapromptId);
1046
+ if (counter !== undefined) {
1047
+ return counter;
1048
+ }
1049
+ // Try loading from working memory (for persistence across GMI instances)
1050
+ const storedCounter = await this.workingMemory.get(`metaprompt_turn_counter_${metapromptId}`);
1051
+ return storedCounter || 0;
1052
+ }
1053
+ /**
1054
+ * Increments the turn counter for a specific metaprompt.
1055
+ *
1056
+ * @param metapromptId - Metaprompt identifier
1057
+ * @private
1058
+ */
1059
+ async incrementMetapromptTurnCounter(metapromptId) {
1060
+ const current = await this.getMetapromptTurnCounter(metapromptId);
1061
+ const newValue = current + 1;
1062
+ this.metaPromptTriggerCounters.set(metapromptId, newValue);
1063
+ await this.workingMemory.set(`metaprompt_turn_counter_${metapromptId}`, newValue);
1064
+ }
1065
+ /**
1066
+ * Resets the turn counter for a specific metaprompt to zero.
1067
+ *
1068
+ * @param metapromptId - Metaprompt identifier
1069
+ * @private
1070
+ */
1071
+ async resetMetapromptTurnCounter(metapromptId) {
1072
+ this.metaPromptTriggerCounters.set(metapromptId, 0);
1073
+ await this.workingMemory.set(`metaprompt_turn_counter_${metapromptId}`, 0);
1074
+ }
1075
+ /**
1076
+ * Executes multiple metaprompts in parallel or sequence.
1077
+ * Replaces the single-metaprompt _triggerAndProcessSelfReflection().
1078
+ *
1079
+ * @param metaPrompts - Array of metaprompts to execute
1080
+ * @private
1081
+ */
1082
+ async executeMetaprompts(metaPrompts) {
1083
+ if (metaPrompts.length === 0)
1084
+ return;
1085
+ const previousState = this.state;
1086
+ this.state = GMIPrimeState.REFLECTING;
1087
+ this.addTraceEntry(ReasoningEntryType.SELF_REFLECTION_START, `Executing ${metaPrompts.length} metaprompt(s)`, { ids: metaPrompts.map((m) => m.id) });
1088
+ try {
1089
+ // Execute metaprompts in parallel using Promise.allSettled
1090
+ // This allows all to run even if some fail
1091
+ const results = await Promise.allSettled(metaPrompts.map((mp) => this.executeMetapromptHandler(mp)));
1092
+ // Log any failures
1093
+ results.forEach((result, idx) => {
1094
+ if (result.status === 'rejected') {
1095
+ this.addTraceEntry(ReasoningEntryType.ERROR, `Metaprompt '${metaPrompts[idx].id}' failed: ${result.reason}`, { error: result.reason });
1096
+ }
1097
+ });
1098
+ }
1099
+ catch (error) {
1100
+ const gmiError = createGMIErrorFromError(error, GMIErrorCode.GMI_PROCESSING_ERROR, undefined, 'Error during metaprompt execution');
1101
+ this.addTraceEntry(ReasoningEntryType.ERROR, gmiError.message, gmiError.toPlainObject());
1102
+ }
1103
+ finally {
1104
+ // Restore state
1105
+ const disallowedStates = new Set([
1106
+ GMIPrimeState.IDLE,
1107
+ GMIPrimeState.INITIALIZING,
1108
+ ]);
1109
+ this.state = disallowedStates.has(previousState)
1110
+ ? GMIPrimeState.READY
1111
+ : previousState;
1112
+ this.addTraceEntry(ReasoningEntryType.SELF_REFLECTION_COMPLETE, 'Metaprompt execution cycle complete');
1113
+ }
1114
+ }
1115
+ /**
1116
+ * Routes a metaprompt to its appropriate handler based on ID.
1117
+ *
1118
+ * @param metaPrompt - Metaprompt definition to execute
1119
+ * @private
1120
+ */
1121
+ async executeMetapromptHandler(metaPrompt) {
1122
+ // Handler routing map
1123
+ switch (metaPrompt.id) {
1124
+ case 'gmi_self_trait_adjustment':
1125
+ return this.handleTraitAdjustment(metaPrompt);
1126
+ case 'gmi_frustration_recovery':
1127
+ return this.handleFrustrationRecovery(metaPrompt);
1128
+ case 'gmi_confusion_clarification':
1129
+ return this.handleConfusionClarification(metaPrompt);
1130
+ case 'gmi_satisfaction_reinforcement':
1131
+ return this.handleSatisfactionReinforcement(metaPrompt);
1132
+ case 'gmi_error_recovery':
1133
+ return this.handleErrorRecovery(metaPrompt);
1134
+ case 'gmi_engagement_boost':
1135
+ return this.handleEngagementBoost(metaPrompt);
1136
+ default:
1137
+ // Generic handler for custom metaprompts
1138
+ return this.handleGenericMetaprompt(metaPrompt);
1139
+ }
1140
+ }
1141
+ /**
1142
+ * Handler for trait adjustment metaprompt (existing self-reflection logic).
1143
+ *
1144
+ * @param metaPrompt - Metaprompt definition
1145
+ * @private
1146
+ */
1147
+ async handleTraitAdjustment(metaPrompt) {
1148
+ // Gather evidence for self-reflection
1149
+ const evidenceHistory = this.conversationHistory.slice(-10);
1150
+ const evidenceTrace = this.reasoningTrace.entries.slice(-20);
1151
+ const evidence = {
1152
+ recentHistory: evidenceHistory,
1153
+ recentReasoning: evidenceTrace,
1154
+ currentMood: this.currentGmiMood,
1155
+ userContext: this.currentUserContext,
1156
+ taskContext: this.currentTaskContext,
1157
+ };
1158
+ const variables = {
1159
+ evidence: JSON.stringify(evidence).substring(0, 4000), // Limit size
1160
+ current_mood: this.currentGmiMood,
1161
+ user_skill: this.currentUserContext.skillLevel || 'unknown',
1162
+ task_complexity: this.currentTaskContext.complexity || 'unknown',
1163
+ };
1164
+ const response = await this.executeMetapromptWithVariables(metaPrompt, variables);
1165
+ await this.applyMetapromptUpdates(response, metaPrompt.id);
1166
+ }
1167
+ /**
1168
+ * Handler for frustration recovery metaprompt.
1169
+ *
1170
+ * @param metaPrompt - Metaprompt definition
1171
+ * @private
1172
+ */
1173
+ async handleFrustrationRecovery(metaPrompt) {
1174
+ const sentimentHistory = await this.workingMemory.get('gmi_sentiment_history');
1175
+ const recentErrors = this.reasoningTrace.entries
1176
+ .slice(-10)
1177
+ .filter((e) => e.type === ReasoningEntryType.ERROR);
1178
+ const variables = {
1179
+ current_sentiment: this.currentUserContext.currentSentiment || 'negative',
1180
+ sentiment_score: (sentimentHistory?.trends[sentimentHistory.trends.length - 1]?.score || -0.5).toString(),
1181
+ consecutive_frustration: (sentimentHistory?.consecutiveFrustration || 1).toString(),
1182
+ recent_conversation: JSON.stringify(this.conversationHistory.slice(-5)),
1183
+ recent_errors: JSON.stringify(recentErrors.map((e) => e.message)),
1184
+ current_mood: this.currentGmiMood,
1185
+ user_skill: this.currentUserContext.skillLevel || 'unknown',
1186
+ task_complexity: this.currentTaskContext.complexity || 'unknown',
1187
+ };
1188
+ const response = await this.executeMetapromptWithVariables(metaPrompt, variables);
1189
+ await this.applyMetapromptUpdates(response, metaPrompt.id);
1190
+ }
1191
+ /**
1192
+ * Handler for confusion clarification metaprompt.
1193
+ *
1194
+ * @param metaPrompt - Metaprompt definition
1195
+ * @private
1196
+ */
1197
+ async handleConfusionClarification(metaPrompt) {
1198
+ const sentimentHistory = await this.workingMemory.get('gmi_sentiment_history');
1199
+ // Get the last event for confusion keywords
1200
+ const lastConfusionEvent = this.eventHistory
1201
+ .slice()
1202
+ .reverse()
1203
+ .find((e) => e.eventType === GMIEventType.USER_CONFUSED);
1204
+ const variables = {
1205
+ current_sentiment: this.currentUserContext.currentSentiment || 'neutral',
1206
+ consecutive_confusion: (sentimentHistory?.consecutiveConfusion || 1).toString(),
1207
+ recent_conversation: JSON.stringify(this.conversationHistory.slice(-5)),
1208
+ confusion_keywords: lastConfusionEvent?.metadata.triggerKeywords
1209
+ ? JSON.stringify(lastConfusionEvent.metadata.triggerKeywords)
1210
+ : '[]',
1211
+ current_mood: this.currentGmiMood,
1212
+ user_skill: this.currentUserContext.skillLevel || 'unknown',
1213
+ task_complexity: this.currentTaskContext.complexity || 'unknown',
1214
+ };
1215
+ const response = await this.executeMetapromptWithVariables(metaPrompt, variables);
1216
+ await this.applyMetapromptUpdates(response, metaPrompt.id);
1217
+ }
1218
+ /**
1219
+ * Handler for satisfaction reinforcement metaprompt.
1220
+ *
1221
+ * @param metaPrompt - Metaprompt definition
1222
+ * @private
1223
+ */
1224
+ async handleSatisfactionReinforcement(metaPrompt) {
1225
+ const sentimentHistory = await this.workingMemory.get('gmi_sentiment_history');
1226
+ const variables = {
1227
+ current_sentiment: this.currentUserContext.currentSentiment || 'positive',
1228
+ sentiment_score: (sentimentHistory?.trends[sentimentHistory.trends.length - 1]?.score || 0.5).toString(),
1229
+ consecutive_satisfaction: (sentimentHistory?.consecutiveSatisfaction || 1).toString(),
1230
+ recent_conversation: JSON.stringify(this.conversationHistory.slice(-5)),
1231
+ current_mood: this.currentGmiMood,
1232
+ user_skill: this.currentUserContext.skillLevel || 'unknown',
1233
+ task_complexity: this.currentTaskContext.complexity || 'unknown',
1234
+ };
1235
+ const response = await this.executeMetapromptWithVariables(metaPrompt, variables);
1236
+ await this.applyMetapromptUpdates(response, metaPrompt.id);
1237
+ }
1238
+ /**
1239
+ * Handler for error recovery metaprompt.
1240
+ *
1241
+ * @param metaPrompt - Metaprompt definition
1242
+ * @private
1243
+ */
1244
+ async handleErrorRecovery(metaPrompt) {
1245
+ const recentErrors = this.reasoningTrace.entries
1246
+ .slice(-10)
1247
+ .filter((e) => e.type === ReasoningEntryType.ERROR);
1248
+ const variables = {
1249
+ recent_errors: JSON.stringify(recentErrors.map((e) => ({ message: e.message, details: e.details }))),
1250
+ recent_conversation: JSON.stringify(this.conversationHistory.slice(-5)),
1251
+ current_mood: this.currentGmiMood,
1252
+ user_skill: this.currentUserContext.skillLevel || 'unknown',
1253
+ task_complexity: this.currentTaskContext.complexity || 'unknown',
1254
+ };
1255
+ const response = await this.executeMetapromptWithVariables(metaPrompt, variables);
1256
+ await this.applyMetapromptUpdates(response, metaPrompt.id);
1257
+ }
1258
+ /**
1259
+ * Handler for engagement boost metaprompt.
1260
+ *
1261
+ * @param metaPrompt - Metaprompt definition
1262
+ * @private
1263
+ */
1264
+ async handleEngagementBoost(metaPrompt) {
1265
+ const sentimentHistory = await this.workingMemory.get('gmi_sentiment_history');
1266
+ const variables = {
1267
+ consecutive_neutral: (sentimentHistory?.consecutiveConfusion || 4).toString(),
1268
+ recent_conversation: JSON.stringify(this.conversationHistory.slice(-5)),
1269
+ current_mood: this.currentGmiMood,
1270
+ user_skill: this.currentUserContext.skillLevel || 'unknown',
1271
+ task_complexity: this.currentTaskContext.complexity || 'unknown',
1272
+ };
1273
+ const response = await this.executeMetapromptWithVariables(metaPrompt, variables);
1274
+ await this.applyMetapromptUpdates(response, metaPrompt.id);
1275
+ }
1276
+ /**
1277
+ * Generic handler for custom metaprompts not in the preset list.
1278
+ *
1279
+ * @param metaPrompt - Metaprompt definition
1280
+ * @private
1281
+ */
1282
+ async handleGenericMetaprompt(metaPrompt) {
1283
+ // Generic handler that provides all available context
1284
+ const variables = {
1285
+ recent_conversation: JSON.stringify(this.conversationHistory.slice(-5)),
1286
+ recent_reasoning: JSON.stringify(this.reasoningTrace.entries.slice(-10)),
1287
+ current_mood: this.currentGmiMood,
1288
+ user_skill: this.currentUserContext.skillLevel || 'unknown',
1289
+ task_complexity: this.currentTaskContext.complexity || 'unknown',
1290
+ current_sentiment: this.currentUserContext.currentSentiment || 'neutral',
1291
+ };
1292
+ const response = await this.executeMetapromptWithVariables(metaPrompt, variables);
1293
+ await this.applyMetapromptUpdates(response, metaPrompt.id);
1294
+ }
1295
+ /**
1296
+ * Executes a metaprompt with variable substitution.
1297
+ *
1298
+ * @param metaPrompt - Metaprompt definition
1299
+ * @param variables - Variables to substitute in the template
1300
+ * @returns Parsed JSON response from LLM
1301
+ * @private
1302
+ */
1303
+ async executeMetapromptWithVariables(metaPrompt, variables) {
1304
+ // Extract template
1305
+ let template;
1306
+ if (typeof metaPrompt.promptTemplate === 'string') {
1307
+ template = metaPrompt.promptTemplate;
1308
+ }
1309
+ else {
1310
+ template = metaPrompt.promptTemplate.template;
1311
+ }
1312
+ // Substitute variables
1313
+ let finalPrompt = template;
1314
+ for (const [key, value] of Object.entries(variables)) {
1315
+ finalPrompt = finalPrompt.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), value);
1316
+ }
1317
+ // Get model and provider info
1318
+ const modelId = metaPrompt.modelId || this.activePersona.defaultModelId;
1319
+ const providerId = metaPrompt.providerId || this.activePersona.defaultProviderId;
1320
+ if (!modelId || !providerId) {
1321
+ throw new GMIError('No model or provider specified for metaprompt', GMIErrorCode.CONFIGURATION_ERROR);
1322
+ }
1323
+ // Call LLM
1324
+ this.addTraceEntry(ReasoningEntryType.DEBUG, `Executing metaprompt '${metaPrompt.id}'`, { modelId, providerId });
1325
+ const completionOptions = {
1326
+ temperature: metaPrompt.temperature ?? 0.3,
1327
+ maxTokens: metaPrompt.maxOutputTokens ?? 512,
1328
+ responseFormat: { type: 'json_object' },
1329
+ };
1330
+ const provider = this.llmProviderManager.getProvider(providerId);
1331
+ if (!provider) {
1332
+ throw new GMIError(`Provider '${providerId}' not found for metaprompt '${metaPrompt.id}'.`, GMIErrorCode.LLM_PROVIDER_UNAVAILABLE);
1333
+ }
1334
+ const result = await provider.generateCompletion(modelId, [{ role: 'user', content: finalPrompt }], completionOptions);
1335
+ const responseContent = result.choices?.[0]?.message?.content;
1336
+ if (!responseContent || typeof responseContent !== 'string') {
1337
+ throw new GMIError(`Metaprompt '${metaPrompt.id}' returned no valid content.`, GMIErrorCode.LLM_PROVIDER_ERROR, { response: result });
1338
+ }
1339
+ // Parse JSON with LLM-based recovery
1340
+ const parseOptions = {
1341
+ attemptFixWithLLM: true,
1342
+ llmModelIdForFix: modelId,
1343
+ llmProviderIdForFix: providerId,
1344
+ };
1345
+ const parsedResponse = await this.utilityAI.parseJsonSafe(responseContent, parseOptions);
1346
+ return parsedResponse;
1347
+ }
1348
+ /**
1349
+ * Applies metaprompt updates to GMI state (mood, user skill, task complexity, memory).
1350
+ *
1351
+ * @param updates - Parsed updates from metaprompt response
1352
+ * @param metapromptId - ID of the metaprompt that generated these updates
1353
+ * @private
1354
+ */
1355
+ async applyMetapromptUpdates(updates, metapromptId) {
1356
+ if (!updates)
1357
+ return;
1358
+ let stateChanged = false;
1359
+ // Mood update
1360
+ if (updates.updatedGmiMood && this.currentGmiMood !== updates.updatedGmiMood) {
1361
+ // Validate that the mood is a valid GMIMood value
1362
+ const validMoods = Object.values(GMIMood);
1363
+ if (validMoods.includes(updates.updatedGmiMood.toUpperCase())) {
1364
+ this.currentGmiMood = updates.updatedGmiMood.toUpperCase();
1365
+ await this.workingMemory.set('currentGmiMood', this.currentGmiMood);
1366
+ stateChanged = true;
1367
+ }
1368
+ }
1369
+ // User skill level update
1370
+ if (updates.updatedUserSkillLevel &&
1371
+ this.currentUserContext.skillLevel !== updates.updatedUserSkillLevel) {
1372
+ this.currentUserContext.skillLevel = updates.updatedUserSkillLevel;
1373
+ await this.workingMemory.set('currentUserContext', this.currentUserContext);
1374
+ stateChanged = true;
1375
+ }
1376
+ // Task complexity update
1377
+ if (updates.updatedTaskComplexity &&
1378
+ this.currentTaskContext.complexity !== updates.updatedTaskComplexity) {
1379
+ this.currentTaskContext.complexity = updates.updatedTaskComplexity;
1380
+ await this.workingMemory.set('currentTaskContext', this.currentTaskContext);
1381
+ stateChanged = true;
1382
+ }
1383
+ // Memory imprints
1384
+ if (updates.newMemoryImprints && Array.isArray(updates.newMemoryImprints)) {
1385
+ for (const imprint of updates.newMemoryImprints) {
1386
+ if (imprint.key) {
1387
+ await this.workingMemory.set(imprint.key, imprint.value);
1388
+ }
1389
+ }
1390
+ if (updates.newMemoryImprints.length > 0) {
1391
+ stateChanged = true;
1392
+ }
1393
+ }
1394
+ // Log state change
1395
+ if (stateChanged) {
1396
+ this.addTraceEntry(ReasoningEntryType.STATE_CHANGE, `GMI state updated by metaprompt '${metapromptId}'`, {
1397
+ newMood: this.currentGmiMood,
1398
+ newUserSkill: this.currentUserContext.skillLevel,
1399
+ newTaskComplexity: this.currentTaskContext.complexity,
1400
+ rationale: updates.adjustmentRationale || updates.recoveryStrategy || updates.clarificationStrategy || updates.engagementStrategy || updates.mitigationStrategy,
1401
+ });
1402
+ }
1403
+ }
738
1404
  /** @inheritdoc */
739
1405
  async _triggerAndProcessSelfReflection() {
740
1406
  // ... (GMI.ts code for _triggerAndProcessSelfReflection provided by user, with my error fixes)