@molroo-io/sdk 0.6.2 → 0.7.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 (252) hide show
  1. package/README.md +100 -194
  2. package/dist/cjs/api-client.d.ts +2 -12
  3. package/dist/cjs/api-client.d.ts.map +1 -1
  4. package/dist/cjs/api-client.js +4 -42
  5. package/dist/cjs/errors.d.ts +1 -16
  6. package/dist/cjs/errors.d.ts.map +1 -1
  7. package/dist/cjs/errors.js +2 -18
  8. package/dist/cjs/events/types.d.ts +14 -21
  9. package/dist/cjs/events/types.d.ts.map +1 -1
  10. package/dist/cjs/events/types.js +0 -11
  11. package/dist/cjs/index.d.ts +26 -48
  12. package/dist/cjs/index.d.ts.map +1 -1
  13. package/dist/cjs/index.js +29 -52
  14. package/dist/cjs/llm/resolve.d.ts +4 -22
  15. package/dist/cjs/llm/resolve.d.ts.map +1 -1
  16. package/dist/cjs/llm/resolve.js +19 -7
  17. package/dist/cjs/llm/vercel-ai/adapter.d.ts +4 -10
  18. package/dist/cjs/llm/vercel-ai/adapter.d.ts.map +1 -1
  19. package/dist/cjs/llm/vercel-ai/adapter.js +6 -152
  20. package/dist/cjs/llm/vercel-ai/config.d.ts +8 -5
  21. package/dist/cjs/llm/vercel-ai/config.d.ts.map +1 -1
  22. package/dist/cjs/memory/in-memory.d.ts +14 -37
  23. package/dist/cjs/memory/in-memory.d.ts.map +1 -1
  24. package/dist/cjs/memory/in-memory.js +22 -85
  25. package/dist/cjs/memory/recall.d.ts +10 -21
  26. package/dist/cjs/memory/recall.d.ts.map +1 -1
  27. package/dist/cjs/memory/recall.js +12 -91
  28. package/dist/cjs/memory/types.d.ts +46 -186
  29. package/dist/cjs/memory/types.d.ts.map +1 -1
  30. package/dist/cjs/memory/types.js +0 -10
  31. package/dist/cjs/persona/chat-orchestrator.d.ts +46 -0
  32. package/dist/cjs/persona/chat-orchestrator.d.ts.map +1 -0
  33. package/dist/cjs/persona/chat-orchestrator.js +240 -0
  34. package/dist/cjs/persona/event-emitter.d.ts +7 -0
  35. package/dist/cjs/persona/event-emitter.d.ts.map +1 -0
  36. package/dist/cjs/persona/event-emitter.js +53 -0
  37. package/dist/cjs/persona/memory-pipeline.d.ts +26 -0
  38. package/dist/cjs/persona/memory-pipeline.d.ts.map +1 -0
  39. package/dist/cjs/persona/memory-pipeline.js +69 -0
  40. package/dist/cjs/persona.d.ts +56 -187
  41. package/dist/cjs/persona.d.ts.map +1 -1
  42. package/dist/cjs/persona.js +62 -638
  43. package/dist/cjs/shared/appraisal.d.ts +26 -0
  44. package/dist/cjs/shared/appraisal.d.ts.map +1 -0
  45. package/dist/cjs/shared/appraisal.js +45 -0
  46. package/dist/cjs/shared/client-factory.d.ts +23 -0
  47. package/dist/cjs/shared/client-factory.d.ts.map +1 -0
  48. package/dist/cjs/shared/client-factory.js +48 -0
  49. package/dist/cjs/shared/errors.d.ts +21 -0
  50. package/dist/cjs/shared/errors.d.ts.map +1 -0
  51. package/dist/cjs/shared/errors.js +29 -0
  52. package/dist/cjs/world/client.d.ts +2 -9
  53. package/dist/cjs/world/client.d.ts.map +1 -1
  54. package/dist/cjs/world/client.js +7 -34
  55. package/dist/cjs/world/errors.d.ts +1 -8
  56. package/dist/cjs/world/errors.d.ts.map +1 -1
  57. package/dist/cjs/world/errors.js +2 -12
  58. package/dist/cjs/world/index.d.ts +2 -2
  59. package/dist/cjs/world/index.d.ts.map +1 -1
  60. package/dist/cjs/world/types.d.ts +6 -4
  61. package/dist/cjs/world/types.d.ts.map +1 -1
  62. package/dist/cjs/world/world-domain.d.ts.map +1 -1
  63. package/dist/cjs/world/world-domain.js +4 -32
  64. package/dist/cjs/world/world-persona.d.ts +7 -5
  65. package/dist/cjs/world/world-persona.d.ts.map +1 -1
  66. package/dist/cjs/world/world-persona.js +2 -17
  67. package/dist/cjs/world/world.d.ts +28 -5
  68. package/dist/cjs/world/world.d.ts.map +1 -1
  69. package/dist/cjs/world/world.js +13 -11
  70. package/dist/esm/api-client.d.ts +2 -12
  71. package/dist/esm/api-client.d.ts.map +1 -1
  72. package/dist/esm/api-client.js +3 -38
  73. package/dist/esm/errors.d.ts +1 -16
  74. package/dist/esm/errors.d.ts.map +1 -1
  75. package/dist/esm/errors.js +1 -17
  76. package/dist/esm/events/types.d.ts +14 -21
  77. package/dist/esm/events/types.d.ts.map +1 -1
  78. package/dist/esm/events/types.js +0 -11
  79. package/dist/esm/index.d.ts +26 -48
  80. package/dist/esm/index.d.ts.map +1 -1
  81. package/dist/esm/index.js +25 -38
  82. package/dist/esm/llm/resolve.d.ts +4 -22
  83. package/dist/esm/llm/resolve.d.ts.map +1 -1
  84. package/dist/esm/llm/resolve.js +20 -8
  85. package/dist/esm/llm/vercel-ai/adapter.d.ts +4 -10
  86. package/dist/esm/llm/vercel-ai/adapter.d.ts.map +1 -1
  87. package/dist/esm/llm/vercel-ai/adapter.js +6 -119
  88. package/dist/esm/llm/vercel-ai/config.d.ts +8 -5
  89. package/dist/esm/llm/vercel-ai/config.d.ts.map +1 -1
  90. package/dist/esm/memory/in-memory.d.ts +14 -37
  91. package/dist/esm/memory/in-memory.d.ts.map +1 -1
  92. package/dist/esm/memory/in-memory.js +20 -83
  93. package/dist/esm/memory/recall.d.ts +10 -21
  94. package/dist/esm/memory/recall.d.ts.map +1 -1
  95. package/dist/esm/memory/recall.js +12 -91
  96. package/dist/esm/memory/types.d.ts +46 -186
  97. package/dist/esm/memory/types.d.ts.map +1 -1
  98. package/dist/esm/memory/types.js +1 -9
  99. package/dist/esm/persona/chat-orchestrator.d.ts +46 -0
  100. package/dist/esm/persona/chat-orchestrator.d.ts.map +1 -0
  101. package/dist/esm/persona/chat-orchestrator.js +204 -0
  102. package/dist/esm/persona/event-emitter.d.ts +7 -0
  103. package/dist/esm/persona/event-emitter.d.ts.map +1 -0
  104. package/dist/esm/persona/event-emitter.js +50 -0
  105. package/dist/esm/persona/memory-pipeline.d.ts +26 -0
  106. package/dist/esm/persona/memory-pipeline.d.ts.map +1 -0
  107. package/dist/esm/persona/memory-pipeline.js +65 -0
  108. package/dist/esm/persona.d.ts +56 -187
  109. package/dist/esm/persona.d.ts.map +1 -1
  110. package/dist/esm/persona.js +62 -638
  111. package/dist/esm/shared/appraisal.d.ts +26 -0
  112. package/dist/esm/shared/appraisal.d.ts.map +1 -0
  113. package/dist/esm/shared/appraisal.js +40 -0
  114. package/dist/esm/shared/client-factory.d.ts +23 -0
  115. package/dist/esm/shared/client-factory.d.ts.map +1 -0
  116. package/dist/esm/shared/client-factory.js +41 -0
  117. package/dist/esm/shared/errors.d.ts +21 -0
  118. package/dist/esm/shared/errors.d.ts.map +1 -0
  119. package/dist/esm/shared/errors.js +24 -0
  120. package/dist/esm/world/client.d.ts +2 -9
  121. package/dist/esm/world/client.d.ts.map +1 -1
  122. package/dist/esm/world/client.js +6 -30
  123. package/dist/esm/world/errors.d.ts +1 -8
  124. package/dist/esm/world/errors.d.ts.map +1 -1
  125. package/dist/esm/world/errors.js +1 -11
  126. package/dist/esm/world/index.d.ts +2 -2
  127. package/dist/esm/world/index.d.ts.map +1 -1
  128. package/dist/esm/world/types.d.ts +6 -4
  129. package/dist/esm/world/types.d.ts.map +1 -1
  130. package/dist/esm/world/world-domain.d.ts.map +1 -1
  131. package/dist/esm/world/world-domain.js +4 -32
  132. package/dist/esm/world/world-persona.d.ts +7 -5
  133. package/dist/esm/world/world-persona.d.ts.map +1 -1
  134. package/dist/esm/world/world-persona.js +2 -17
  135. package/dist/esm/world/world.d.ts +28 -5
  136. package/dist/esm/world/world.d.ts.map +1 -1
  137. package/dist/esm/world/world.js +13 -11
  138. package/package.json +4 -101
  139. package/dist/cjs/embedding/cloudflare.d.ts +0 -15
  140. package/dist/cjs/embedding/cloudflare.d.ts.map +0 -1
  141. package/dist/cjs/embedding/cloudflare.js +0 -16
  142. package/dist/cjs/embedding/cohere.d.ts +0 -8
  143. package/dist/cjs/embedding/cohere.d.ts.map +0 -1
  144. package/dist/cjs/embedding/cohere.js +0 -31
  145. package/dist/cjs/embedding/index.d.ts +0 -9
  146. package/dist/cjs/embedding/index.d.ts.map +0 -1
  147. package/dist/cjs/embedding/index.js +0 -11
  148. package/dist/cjs/embedding/local.d.ts +0 -6
  149. package/dist/cjs/embedding/local.d.ts.map +0 -1
  150. package/dist/cjs/embedding/local.js +0 -28
  151. package/dist/cjs/embedding/openai.d.ts +0 -9
  152. package/dist/cjs/embedding/openai.d.ts.map +0 -1
  153. package/dist/cjs/embedding/openai.js +0 -26
  154. package/dist/cjs/events/console.d.ts +0 -25
  155. package/dist/cjs/events/console.d.ts.map +0 -1
  156. package/dist/cjs/events/console.js +0 -41
  157. package/dist/cjs/events/webhook.d.ts +0 -30
  158. package/dist/cjs/events/webhook.d.ts.map +0 -1
  159. package/dist/cjs/events/webhook.js +0 -79
  160. package/dist/cjs/memory/cloudflare/index.d.ts +0 -3
  161. package/dist/cjs/memory/cloudflare/index.d.ts.map +0 -1
  162. package/dist/cjs/memory/cloudflare/index.js +0 -5
  163. package/dist/cjs/memory/cloudflare/vectorize.d.ts +0 -62
  164. package/dist/cjs/memory/cloudflare/vectorize.d.ts.map +0 -1
  165. package/dist/cjs/memory/cloudflare/vectorize.js +0 -55
  166. package/dist/cjs/memory/in-memory-semantic.d.ts +0 -16
  167. package/dist/cjs/memory/in-memory-semantic.d.ts.map +0 -1
  168. package/dist/cjs/memory/in-memory-semantic.js +0 -57
  169. package/dist/cjs/memory/pinecone/index.d.ts +0 -7
  170. package/dist/cjs/memory/pinecone/index.d.ts.map +0 -1
  171. package/dist/cjs/memory/pinecone/index.js +0 -8
  172. package/dist/cjs/memory/pinecone/memory-adapter.d.ts +0 -62
  173. package/dist/cjs/memory/pinecone/memory-adapter.d.ts.map +0 -1
  174. package/dist/cjs/memory/pinecone/memory-adapter.js +0 -220
  175. package/dist/cjs/memory/pinecone/semantic.d.ts +0 -44
  176. package/dist/cjs/memory/pinecone/semantic.d.ts.map +0 -1
  177. package/dist/cjs/memory/pinecone/semantic.js +0 -90
  178. package/dist/cjs/memory/sqlite/index.d.ts +0 -3
  179. package/dist/cjs/memory/sqlite/index.d.ts.map +0 -1
  180. package/dist/cjs/memory/sqlite/index.js +0 -5
  181. package/dist/cjs/memory/sqlite/memory-adapter.d.ts +0 -58
  182. package/dist/cjs/memory/sqlite/memory-adapter.d.ts.map +0 -1
  183. package/dist/cjs/memory/sqlite/memory-adapter.js +0 -336
  184. package/dist/cjs/memory/sqlite/schema.d.ts +0 -4
  185. package/dist/cjs/memory/sqlite/schema.d.ts.map +0 -1
  186. package/dist/cjs/memory/sqlite/schema.js +0 -91
  187. package/dist/cjs/memory/supabase/index.d.ts +0 -7
  188. package/dist/cjs/memory/supabase/index.d.ts.map +0 -1
  189. package/dist/cjs/memory/supabase/index.js +0 -8
  190. package/dist/cjs/memory/supabase/memory-adapter.d.ts +0 -67
  191. package/dist/cjs/memory/supabase/memory-adapter.d.ts.map +0 -1
  192. package/dist/cjs/memory/supabase/memory-adapter.js +0 -335
  193. package/dist/cjs/memory/supabase/semantic.d.ts +0 -44
  194. package/dist/cjs/memory/supabase/semantic.d.ts.map +0 -1
  195. package/dist/cjs/memory/supabase/semantic.js +0 -72
  196. package/dist/esm/embedding/cloudflare.d.ts +0 -15
  197. package/dist/esm/embedding/cloudflare.d.ts.map +0 -1
  198. package/dist/esm/embedding/cloudflare.js +0 -13
  199. package/dist/esm/embedding/cohere.d.ts +0 -8
  200. package/dist/esm/embedding/cohere.d.ts.map +0 -1
  201. package/dist/esm/embedding/cohere.js +0 -28
  202. package/dist/esm/embedding/index.d.ts +0 -9
  203. package/dist/esm/embedding/index.d.ts.map +0 -1
  204. package/dist/esm/embedding/index.js +0 -4
  205. package/dist/esm/embedding/local.d.ts +0 -6
  206. package/dist/esm/embedding/local.d.ts.map +0 -1
  207. package/dist/esm/embedding/local.js +0 -25
  208. package/dist/esm/embedding/openai.d.ts +0 -9
  209. package/dist/esm/embedding/openai.d.ts.map +0 -1
  210. package/dist/esm/embedding/openai.js +0 -23
  211. package/dist/esm/events/console.d.ts +0 -25
  212. package/dist/esm/events/console.d.ts.map +0 -1
  213. package/dist/esm/events/console.js +0 -37
  214. package/dist/esm/events/webhook.d.ts +0 -30
  215. package/dist/esm/events/webhook.d.ts.map +0 -1
  216. package/dist/esm/events/webhook.js +0 -75
  217. package/dist/esm/memory/cloudflare/index.d.ts +0 -3
  218. package/dist/esm/memory/cloudflare/index.d.ts.map +0 -1
  219. package/dist/esm/memory/cloudflare/index.js +0 -1
  220. package/dist/esm/memory/cloudflare/vectorize.d.ts +0 -62
  221. package/dist/esm/memory/cloudflare/vectorize.d.ts.map +0 -1
  222. package/dist/esm/memory/cloudflare/vectorize.js +0 -51
  223. package/dist/esm/memory/in-memory-semantic.d.ts +0 -16
  224. package/dist/esm/memory/in-memory-semantic.d.ts.map +0 -1
  225. package/dist/esm/memory/in-memory-semantic.js +0 -53
  226. package/dist/esm/memory/pinecone/index.d.ts +0 -7
  227. package/dist/esm/memory/pinecone/index.d.ts.map +0 -1
  228. package/dist/esm/memory/pinecone/index.js +0 -3
  229. package/dist/esm/memory/pinecone/memory-adapter.d.ts +0 -62
  230. package/dist/esm/memory/pinecone/memory-adapter.d.ts.map +0 -1
  231. package/dist/esm/memory/pinecone/memory-adapter.js +0 -216
  232. package/dist/esm/memory/pinecone/semantic.d.ts +0 -44
  233. package/dist/esm/memory/pinecone/semantic.d.ts.map +0 -1
  234. package/dist/esm/memory/pinecone/semantic.js +0 -86
  235. package/dist/esm/memory/sqlite/index.d.ts +0 -3
  236. package/dist/esm/memory/sqlite/index.d.ts.map +0 -1
  237. package/dist/esm/memory/sqlite/index.js +0 -1
  238. package/dist/esm/memory/sqlite/memory-adapter.d.ts +0 -58
  239. package/dist/esm/memory/sqlite/memory-adapter.d.ts.map +0 -1
  240. package/dist/esm/memory/sqlite/memory-adapter.js +0 -296
  241. package/dist/esm/memory/sqlite/schema.d.ts +0 -4
  242. package/dist/esm/memory/sqlite/schema.d.ts.map +0 -1
  243. package/dist/esm/memory/sqlite/schema.js +0 -86
  244. package/dist/esm/memory/supabase/index.d.ts +0 -7
  245. package/dist/esm/memory/supabase/index.d.ts.map +0 -1
  246. package/dist/esm/memory/supabase/index.js +0 -3
  247. package/dist/esm/memory/supabase/memory-adapter.d.ts +0 -67
  248. package/dist/esm/memory/supabase/memory-adapter.d.ts.map +0 -1
  249. package/dist/esm/memory/supabase/memory-adapter.js +0 -331
  250. package/dist/esm/memory/supabase/semantic.d.ts +0 -44
  251. package/dist/esm/memory/supabase/semantic.d.ts.map +0 -1
  252. package/dist/esm/memory/supabase/semantic.js +0 -68
@@ -35,116 +35,58 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.MolrooPersona = void 0;
37
37
  const resolve_1 = require("./llm/resolve");
38
- const types_1 = require("./memory/types");
39
- const recall_1 = require("./memory/recall");
40
38
  const errors_1 = require("./errors");
41
39
  const api_client_1 = require("./api-client");
42
- /** Clamp appraisal values to engine-valid ranges after LLM generation. */
43
- function clampAppraisal(a) {
44
- const c = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
45
- return {
46
- goal_relevance: c(a.goal_relevance, -1, 1),
47
- goal_congruence: c(a.goal_congruence, -1, 1),
48
- expectedness: c(a.expectedness, 0, 1),
49
- controllability: c(a.controllability, 0, 1),
50
- agency: c(a.agency, -1, 1),
51
- norm_compatibility: c(a.norm_compatibility, -1, 1),
52
- internal_standards: c(a.internal_standards ?? 0, -1, 1),
53
- adjustment_potential: c(a.adjustment_potential ?? 0.5, 0, 1),
54
- urgency: c(a.urgency ?? 0.5, 0, 1),
55
- };
56
- }
57
- /** Build a system prompt section describing the interlocutor. */
58
- function buildInterlocutorBlock(ctx) {
59
- const parts = [`## About ${ctx.name}`];
60
- if (ctx.description)
61
- parts.push(ctx.description);
62
- if (ctx.extensions) {
63
- for (const [title, content] of Object.entries(ctx.extensions)) {
64
- parts.push(`### ${title}`);
65
- parts.push(content);
66
- }
67
- }
68
- return parts.join('\n');
69
- }
40
+ const memory_pipeline_1 = require("./persona/memory-pipeline");
41
+ const chat_orchestrator_1 = require("./persona/chat-orchestrator");
42
+ // ── SDK Persona Types ──
43
+ const DEFAULT_BASE_URL = 'https://api.molroo.io';
70
44
  // ── MolrooPersona ──
71
45
  /**
72
46
  * SDK client for interacting with a standalone molroo persona instance.
73
47
  *
74
- * @example
75
- * ```typescript
76
- * // Single adapter (recommended)
77
- * const persona = await MolrooPersona.create(
78
- * { baseUrl: 'https://api.molroo.io', apiKey: 'key', llm,
79
- * memory: new SqliteMemoryAdapter({ dbPath: './memory.db' }) },
80
- * { identity: { name: 'Sera' }, personality: { O: 0.8, C: 0.6, E: 0.7 } },
81
- * );
82
- *
83
- * // Split adapters (advanced)
84
- * const persona = await MolrooPersona.create(
85
- * { baseUrl: 'https://api.molroo.io', apiKey: 'key', llm,
86
- * memory: { episodes: episodeStore, semantic: vectorStore, embedding: embedProvider } },
87
- * { identity: { name: 'Sera' }, personality: { O: 0.8, C: 0.6, E: 0.7 } },
88
- * );
89
- * ```
48
+ * @deprecated Use {@link Molroo} from './world/world' instead.
90
49
  */
91
50
  class MolrooPersona {
92
51
  constructor(config) {
93
- this.client = (0, api_client_1.createApiClient)(config.baseUrl, config.apiKey);
52
+ const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
53
+ this.client = (0, api_client_1.createApiClient)(baseUrl, config.apiKey);
94
54
  this._personaId = config.personaId || '';
95
55
  this.llm = config.llm ?? null;
96
56
  this.engineLlm = config.engineLlm ?? null;
97
57
  this.events = config.events ?? null;
98
- // Memory infrastructure
99
- if (config.memory) {
100
- if ((0, types_1.isMemoryConfig)(config.memory)) {
101
- // Split adapter path (MemoryConfig)
102
- this.memoryAdapter = null;
103
- this.episodeStore = config.memory.episodes;
104
- this.semanticStore = config.memory.semantic ?? null;
105
- this.embeddingProvider = config.memory.embedding ?? null;
106
- this.memoryRecallConfig = config.memory.recall;
107
- }
108
- else {
109
- // Single adapter path (MemoryAdapter)
110
- this.memoryAdapter = config.memory;
111
- this.episodeStore = null;
112
- this.semanticStore = null;
113
- this.embeddingProvider = null;
114
- this.memoryRecallConfig = config.recall;
115
- }
116
- }
117
- else {
118
- this.memoryAdapter = null;
119
- this.episodeStore = null;
120
- this.semanticStore = null;
121
- this.embeddingProvider = null;
122
- this.memoryRecallConfig = undefined;
123
- }
58
+ this.memoryAdapter = config.memory ?? null;
59
+ this.memoryRecallConfig = config.recall;
124
60
  }
125
61
  // ── Properties ──
126
- /** Unique identifier for this persona instance. */
127
62
  get id() {
128
63
  return this._personaId;
129
64
  }
130
- /** Unique identifier for this persona instance (alias for {@link id}). */
131
65
  get personaId() {
132
66
  return this._personaId;
133
67
  }
134
- // ── Static Factory Methods ──
68
+ static async create(config, input) {
69
+ // Handle description string (auto-generate via LLM)
70
+ if (typeof input === 'string') {
71
+ if (!config.llm) {
72
+ throw new errors_1.MolrooApiError('LLM adapter is required when using description string. ' +
73
+ 'Provide llm option or use explicit PersonaConfigData.', 'LLM_REQUIRED', 400);
74
+ }
75
+ const { generatePersona } = await Promise.resolve().then(() => __importStar(require('./generate/persona')));
76
+ const llm = await (0, resolve_1.resolveLLM)(config.llm);
77
+ const personaConfig = await generatePersona(llm, input);
78
+ return MolrooPersona.createWithConfig(config, personaConfig);
79
+ }
80
+ // Handle explicit PersonaConfigData
81
+ return MolrooPersona.createWithConfig(config, input);
82
+ }
135
83
  /**
136
- * Create a new persona on the molroo API and return a connected instance.
137
- *
138
- * @param config - API connection config and optional LLM adapter.
139
- * Accepts a full {@link LLMAdapter} or a shorthand config object:
140
- * ```typescript
141
- * llm: { provider: 'openai', apiKey: '...' }
142
- * ```
143
- * @param personaConfig - Persona identity, personality, and goals.
144
- * @returns A connected MolrooPersona instance.
84
+ * Internal implementation for creating persona with resolved config.
85
+ * @internal
145
86
  */
146
- static async create(config, personaConfig) {
147
- const client = (0, api_client_1.createApiClient)(config.baseUrl, config.apiKey);
87
+ static async createWithConfig(config, personaConfig) {
88
+ const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
89
+ const client = (0, api_client_1.createApiClient)(baseUrl, config.apiKey);
148
90
  const { data } = await client.POST('/personas', {
149
91
  body: { config: personaConfig },
150
92
  headers: { 'Idempotency-Key': crypto.randomUUID() },
@@ -154,75 +96,34 @@ class MolrooPersona {
154
96
  config.engineLlm ? (0, resolve_1.resolveLLM)(config.engineLlm) : undefined,
155
97
  ]);
156
98
  const result = (0, api_client_1.unwrap)(data);
157
- const persona = new MolrooPersona({ ...config, llm, engineLlm, personaId: result.personaId });
158
- return persona;
99
+ return new MolrooPersona({ ...config, llm, engineLlm, personaId: result.personaId });
159
100
  }
160
101
  /**
161
- * Generate a persona from a natural-language description, then create it on the API.
162
- *
163
- * Combines {@link generatePersona} + {@link MolrooPersona.create} in one step.
164
- *
165
- * @param config - API connection config and optional LLM adapter.
166
- * @param description - Natural-language description of the persona to generate.
167
- * @returns A connected MolrooPersona instance with a generated config.
168
- *
169
- * @example
170
- * ```typescript
171
- * const sera = await MolrooPersona.generate(
172
- * { baseUrl: 'https://api.molroo.io', apiKey: 'mk_live_...', llm: { provider: 'openai', apiKey: '...' } },
173
- * 'A warm and friendly barista named Sera who loves coffee and people.',
174
- * );
175
- * ```
102
+ * Generate a persona from description and create it.
103
+ * @deprecated Use `create(config, description)` instead.
176
104
  */
177
105
  static async generate(config, description) {
178
- const { generatePersona } = await Promise.resolve().then(() => __importStar(require('./generate/persona')));
179
- const llm = await (0, resolve_1.resolveLLM)(config.llm);
180
- const personaConfig = await generatePersona(llm, description);
181
- return MolrooPersona.create(config, personaConfig);
106
+ return MolrooPersona.create(config, description);
182
107
  }
183
- /**
184
- * Connect to an existing persona by ID.
185
- *
186
- * Verifies the persona exists and fetches its configuration.
187
- *
188
- * @param config - API connection config and optional LLM adapter.
189
- * Accepts a full {@link LLMAdapter} or a shorthand config object:
190
- * ```typescript
191
- * llm: { provider: 'openai', apiKey: '...' }
192
- * ```
193
- * @param personaId - The ID of the persona to connect to.
194
- * @returns A connected MolrooPersona instance.
195
- */
196
108
  static async connect(config, personaId) {
197
109
  const [llm, engineLlm] = await Promise.all([
198
110
  config.llm ? (0, resolve_1.resolveLLM)(config.llm) : undefined,
199
111
  config.engineLlm ? (0, resolve_1.resolveLLM)(config.engineLlm) : undefined,
200
112
  ]);
113
+ const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
201
114
  const persona = new MolrooPersona({ ...config, llm, engineLlm, personaId });
202
- // Verify persona exists
203
115
  await persona.client.GET('/personas/{id}', {
204
116
  params: { path: { id: personaId } },
205
117
  });
206
118
  return persona;
207
119
  }
208
- /**
209
- * List all personas for the authenticated tenant.
210
- *
211
- * @param config - API connection config (baseUrl + apiKey).
212
- * @returns List of persona summaries with optional pagination cursor.
213
- */
214
120
  static async listPersonas(config) {
215
- const client = (0, api_client_1.createApiClient)(config.baseUrl, config.apiKey);
121
+ const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
122
+ const client = (0, api_client_1.createApiClient)(baseUrl, config.apiKey);
216
123
  const { data } = await client.GET('/personas');
217
124
  return (0, api_client_1.unwrap)(data);
218
125
  }
219
126
  // ── Runtime ──
220
- /**
221
- * Send a message to the persona and get an emotion-processed response.
222
- *
223
- * Internally converts the SDK-friendly options into the API wire format
224
- * (`{ event: PerceiveEvent, context?: PerceiveContext }`).
225
- */
226
127
  async perceive(message, options) {
227
128
  const eventType = options?.type ?? 'chat_message';
228
129
  const sourceName = typeof options?.from === 'string'
@@ -247,196 +148,32 @@ class MolrooPersona {
247
148
  body: { event, context },
248
149
  });
249
150
  const response = (0, api_client_1.unwrap)(data);
250
- // Save episode to memory (unless caller opts out)
251
- if (!options?.skipMemory && response.memoryEpisode) {
252
- // Tag episode with event type so recall can distinguish chat vs events
151
+ if (!options?.skipMemory && response.memoryEpisode && this.memoryAdapter) {
253
152
  if (!response.memoryEpisode.type) {
254
153
  response.memoryEpisode.type = eventType;
255
154
  }
256
- this.postPerceivePipeline(response);
155
+ (0, memory_pipeline_1.postPerceive)(this.memoryPipelineDeps, response);
257
156
  }
258
157
  return response;
259
158
  }
260
- /**
261
- * Fire a non-chat event and process through the emotion engine.
262
- *
263
- * Unlike chat(), this does not involve LLM generation — it directly
264
- * sends an event to the perceive endpoint with a required appraisal vector.
265
- * The resulting episode is saved to memory and can be recalled during chat().
266
- *
267
- * @param type - Event type identifier (e.g. 'attack', 'gift', 'rest').
268
- * @param description - Human-readable event description (used as message context).
269
- * @param options - Must include `appraisal`. Optionally `from`, `stimulus`, `payload`.
270
- * @returns Emotion engine response.
271
- *
272
- * @example
273
- * ```typescript
274
- * await persona.event('attack', 'goblin attacks with sword', {
275
- * from: 'goblin',
276
- * appraisal: {
277
- * goal_relevance: 0.8,
278
- * goal_congruence: -0.9,
279
- * expectedness: 0.3,
280
- * controllability: 0.4,
281
- * agency: -0.6,
282
- * norm_compatibility: -0.5,
283
- * },
284
- * });
285
- * ```
286
- */
287
159
  async event(type, description, options) {
288
160
  return this.perceive(description, { ...options, type });
289
161
  }
290
- /**
291
- * High-level chat: getState → LLM generate → perceive with appraisal.
292
- *
293
- * 1. Calls `getPromptContext()` for the server-assembled system prompt
294
- * 2. Recalls episodic + semantic memories from client-side stores
295
- * 3. Sends to LLM adapter for text generation + appraisal
296
- * 4. Sends the appraisal to the API via `perceive()` for emotion computation
297
- * 5. Runs post-chat pipeline (episode save, reflection, events)
298
- *
299
- * Requires {@link LLMAdapter}. Without one, use {@link perceive} directly
300
- * for emotion-only interaction.
301
- */
302
162
  async chat(message, options) {
303
- const fromOption = options?.from ?? 'user';
304
- const from = typeof fromOption === 'string' ? fromOption : fromOption.name;
305
- const interlocutor = typeof fromOption === 'object' ? fromOption : null;
306
163
  const llm = this.requireLLM();
307
- // 1. Fetch server-assembled system prompt
308
- const ctx = await this.getPromptContext(options?.consumerSuffix, from);
309
- let systemPrompt = ctx.systemPrompt;
310
- const hasTools = (ctx.tools?.length ?? 0) > 0;
311
- // 2. Recall memories (episodic + semantic + reflections)
312
- const recalled = await (0, recall_1.recallMemories)(message, {
164
+ const deps = {
165
+ personaId: this._personaId,
166
+ llm,
167
+ engineLlm: this.engineLlm,
313
168
  memoryAdapter: this.memoryAdapter,
314
- episodeStore: this.episodeStore,
315
- semanticStore: this.semanticStore,
316
- embeddingProvider: this.embeddingProvider,
317
- config: this.memoryRecallConfig,
318
- sourceEntity: from,
319
- reflectionEntity: this._personaId,
320
- });
321
- if (interlocutor) {
322
- systemPrompt += '\n\n' + buildInterlocutorBlock(interlocutor);
323
- }
324
- const memoryBlock = (0, recall_1.buildMemoryBlock)(recalled.episodic, recalled.semantic, recalled.reflections);
325
- if (memoryBlock) {
326
- systemPrompt += '\n\n' + memoryBlock;
327
- }
328
- // 3. LLM Generate (SDK side, user's API key)
329
- const messages = [];
330
- if (options?.history) {
331
- messages.push(...options.history.map(h => ({ role: h.role, content: h.content })));
332
- }
333
- messages.push({ role: 'user', content: message });
334
- let responseText;
335
- let appraisal;
336
- let earlyPerceiveResponse;
337
- // Split mode: engineLlm handles appraisal, primary llm handles response text
338
- if (this.engineLlm && this.engineLlm !== llm) {
339
- const { AppraisalVectorSchema } = await Promise.resolve().then(() => __importStar(require('./llm/schema')));
340
- const appraisalInstruction = [
341
- '',
342
- '## Appraisal Task',
343
- "Evaluate how RECEIVING the user's message affects this persona emotionally.",
344
- 'The event you are appraising is the message itself arriving — not the described situation.',
345
- "When the user shares their own experience (e.g. loss, success), appraise through the persona's relational goals: caring about the speaker makes their suffering relevant and incongruent.",
346
- "Rate each dimension from the persona's subjective perspective.",
347
- 'An insult should produce negative goal_congruence and norm_compatibility.',
348
- 'A compliment should produce positive values. Neutral small talk should be near zero.',
349
- ].join('\n');
350
- // 3a. engineLlm → appraisal (based on prior emotional state)
351
- // Only send last few messages for appraisal context (full history is wasteful)
352
- const appraisalMessages = messages.length <= 5 ? messages : messages.slice(-5);
353
- const { object: appraisalResult } = await this.engineLlm.generateObject({
354
- system: systemPrompt + appraisalInstruction,
355
- messages: appraisalMessages,
356
- schema: AppraisalVectorSchema,
357
- });
358
- appraisal = clampAppraisal(appraisalResult);
359
- // 3b. perceive with user message → engine updates emotion before response generation
360
- earlyPerceiveResponse = await this.perceive(message, {
361
- from,
362
- appraisal,
363
- priorEpisodes: recalled.episodic.length > 0 ? recalled.episodic : undefined,
364
- skipMemory: true, // chat() runs its own postChatPipeline
365
- });
366
- // 3c. Fetch updated prompt reflecting new emotional state
367
- let updatedPrompt = systemPrompt;
368
- try {
369
- const updatedCtx = await this.getPromptContext(options?.consumerSuffix, from);
370
- updatedPrompt = updatedCtx.systemPrompt;
371
- if (interlocutor) {
372
- updatedPrompt += '\n\n' + buildInterlocutorBlock(interlocutor);
373
- }
374
- if (memoryBlock) {
375
- updatedPrompt += '\n\n' + memoryBlock;
376
- }
377
- }
378
- catch {
379
- // Use original prompt if updated fetch fails
380
- }
381
- // 3d. primary llm → response (with updated emotional state in prompt)
382
- const { text } = await llm.generateText({
383
- system: updatedPrompt,
384
- messages,
385
- });
386
- responseText = text;
387
- }
388
- else if (hasTools) {
389
- // Combined mode with tool-use: LLM can request memory searches
390
- const result = await this.generateWithToolLoop(llm, systemPrompt, messages, options?.onToolCall);
391
- responseText = result.text;
392
- appraisal = clampAppraisal(result.appraisal);
393
- }
394
- else {
395
- // Combined mode (default): single LLM call for response + appraisal
396
- const { LLMResponseSchema } = await Promise.resolve().then(() => __importStar(require('./llm/schema')));
397
- const { object: llmResult } = await llm.generateObject({
398
- system: systemPrompt,
399
- messages,
400
- schema: LLMResponseSchema,
401
- });
402
- responseText = llmResult.response;
403
- appraisal = clampAppraisal(llmResult.appraisal ?? {
404
- goal_relevance: 0,
405
- goal_congruence: 0,
406
- expectedness: 0.5,
407
- controllability: 0.5,
408
- agency: 0,
409
- norm_compatibility: 0,
410
- internal_standards: 0,
411
- adjustment_potential: 0.5,
412
- urgency: 0.5,
413
- });
414
- }
415
- // 4. Send to API for emotion processing (skip if already done in split mode)
416
- let response;
417
- if (earlyPerceiveResponse) {
418
- response = earlyPerceiveResponse;
419
- }
420
- else {
421
- response = await this.perceive(responseText, {
422
- from,
423
- appraisal,
424
- priorEpisodes: recalled.episodic.length > 0 ? recalled.episodic : undefined,
425
- skipMemory: true, // chat() runs its own postChatPipeline
426
- });
427
- }
428
- // Inject LLM-generated text
429
- response.text = responseText;
430
- // 5. Post-chat pipeline (fire-and-forget: episode save, reflection, events)
431
- this.postChatPipeline(response);
432
- return { text: responseText, response };
169
+ memoryRecallConfig: this.memoryRecallConfig,
170
+ events: this.events,
171
+ getPromptContext: (suffix, source) => this.getPromptContext(suffix, source),
172
+ perceive: (msg, opts) => this.perceive(msg, opts),
173
+ searchMemory: (query) => this.searchMemory(query),
174
+ };
175
+ return (0, chat_orchestrator_1.chat)(deps, message, options);
433
176
  }
434
- /**
435
- * Advance persona time by the specified number of seconds.
436
- *
437
- * @param seconds - Number of seconds to advance.
438
- * @returns Any pending events that were processed.
439
- */
440
177
  async tick(seconds) {
441
178
  const { data } = await this.client.POST('/personas/{id}/tick', {
442
179
  params: { path: { id: this._personaId } },
@@ -444,11 +181,6 @@ class MolrooPersona {
444
181
  });
445
182
  return (0, api_client_1.unwrap)(data);
446
183
  }
447
- /**
448
- * Directly set the persona's emotion state in VAD space.
449
- *
450
- * @param vad - Partial VAD values to set (V: -1..1, A: 0..1, D: -1..1).
451
- */
452
184
  async setEmotion(vad) {
453
185
  await this.client.POST('/personas/{id}/emotion', {
454
186
  params: { path: { id: this._personaId } },
@@ -456,33 +188,18 @@ class MolrooPersona {
456
188
  });
457
189
  }
458
190
  // ── State ──
459
- /**
460
- * Get the current emotional and psychological state of the persona.
461
- *
462
- * @returns Current emotion, mood, somatic, and narrative state.
463
- */
464
191
  async getState() {
465
192
  const { data } = await this.client.GET('/personas/{id}/state', {
466
193
  params: { path: { id: this._personaId } },
467
194
  });
468
195
  return (0, api_client_1.unwrap)(data);
469
196
  }
470
- /**
471
- * Get a full snapshot of the persona's internal state.
472
- *
473
- * @returns Complete persona snapshot for backup/restore.
474
- */
475
197
  async getSnapshot() {
476
198
  const { data } = await this.client.GET('/personas/{id}/snapshot', {
477
199
  params: { path: { id: this._personaId } },
478
200
  });
479
201
  return (0, api_client_1.unwrap)(data);
480
202
  }
481
- /**
482
- * Restore the persona's internal state from a snapshot.
483
- *
484
- * @param snapshot - The snapshot to restore.
485
- */
486
203
  async putSnapshot(snapshot) {
487
204
  await this.client.PUT('/personas/{id}/snapshot', {
488
205
  params: { path: { id: this._personaId } },
@@ -490,11 +207,6 @@ class MolrooPersona {
490
207
  });
491
208
  }
492
209
  // ── Config ──
493
- /**
494
- * Patch the persona's configuration (identity, personality, goals).
495
- *
496
- * @param updates - Configuration updates to apply.
497
- */
498
210
  async patch(updates) {
499
211
  await this.client.PATCH('/personas/{id}', {
500
212
  params: { path: { id: this._personaId } },
@@ -502,7 +214,6 @@ class MolrooPersona {
502
214
  });
503
215
  }
504
216
  // ── Lifecycle ──
505
- /** Soft-delete this persona. Can be restored with {@link restore}. */
506
217
  async destroy() {
507
218
  if (this._personaId) {
508
219
  await this.client.DELETE('/personas/{id}', {
@@ -510,7 +221,6 @@ class MolrooPersona {
510
221
  });
511
222
  }
512
223
  }
513
- /** Restore a previously soft-deleted persona. */
514
224
  async restore() {
515
225
  if (this._personaId) {
516
226
  await this.client.POST('/personas/{id}/restore', {
@@ -518,216 +228,7 @@ class MolrooPersona {
518
228
  });
519
229
  }
520
230
  }
521
- // ── Private Helpers ──
522
- /** Whether memory is available (either single adapter or split stores). */
523
- get hasMemory() {
524
- return this.memoryAdapter !== null || this.episodeStore !== null;
525
- }
526
- // ── Post-Chat Pipeline (fire-and-forget) ──
527
- /**
528
- * Lightweight pipeline for perceive()-only interactions (non-chat events).
529
- * Saves the episode and emits events, but skips LLM reflection.
530
- */
531
- postPerceivePipeline(response) {
532
- if (!response.memoryEpisode)
533
- return;
534
- if (this.memoryAdapter) {
535
- // Single adapter path — adapter handles semantic indexing internally
536
- this.memoryAdapter.saveEpisode(response.memoryEpisode).catch(() => { });
537
- }
538
- else if (this.episodeStore) {
539
- // Split adapter path
540
- this.episodeStore.saveEpisode(response.memoryEpisode).catch(() => { });
541
- if (this.semanticStore && this.embeddingProvider && response.memoryEpisode.context) {
542
- const ep = response.memoryEpisode;
543
- this.embeddingProvider
544
- .embed((0, recall_1.stripMetaTags)(ep.context))
545
- .then((embedding) => {
546
- this.semanticStore.index({
547
- id: ep.id,
548
- embedding,
549
- metadata: {
550
- type: 'episode',
551
- sourceEntity: ep.sourceEntity,
552
- timestamp: ep.timestamp,
553
- importance: ep.importance,
554
- episodeType: ep.type,
555
- },
556
- });
557
- })
558
- .catch(() => { });
559
- }
560
- }
561
- // Event emission
562
- if (this.events) {
563
- this.emitResponseEvents(response, Date.now()).catch(() => { });
564
- }
565
- }
566
- postChatPipeline(response) {
567
- const now = Date.now();
568
- if (this.memoryAdapter) {
569
- // Single adapter path — adapter handles semantic indexing internally
570
- if (response.memoryEpisode) {
571
- this.memoryAdapter.saveEpisode(response.memoryEpisode).catch(() => { });
572
- }
573
- // Reflection generation
574
- if ((this.engineLlm || this.llm) && response.reflectionPrompt) {
575
- this.handleReflection(response.reflectionPrompt, response.emotion.vad).catch(() => { });
576
- }
577
- }
578
- else {
579
- // Split adapter path
580
- // 1. Episode storage + semantic indexing
581
- if (this.episodeStore && response.memoryEpisode) {
582
- this.episodeStore.saveEpisode(response.memoryEpisode).catch(() => { });
583
- if (this.semanticStore && this.embeddingProvider && response.memoryEpisode.context) {
584
- const ep = response.memoryEpisode;
585
- this.embeddingProvider
586
- .embed((0, recall_1.stripMetaTags)(ep.context))
587
- .then((embedding) => {
588
- this.semanticStore.index({
589
- id: ep.id,
590
- embedding,
591
- metadata: {
592
- type: 'episode',
593
- sourceEntity: ep.sourceEntity,
594
- timestamp: ep.timestamp,
595
- importance: ep.importance,
596
- episodeType: ep.type,
597
- },
598
- });
599
- })
600
- .catch(() => { });
601
- }
602
- }
603
- // 2. Reflection generation (requires LLM + episodeStore)
604
- if (this.episodeStore && (this.engineLlm || this.llm) && response.reflectionPrompt) {
605
- this.handleReflection(response.reflectionPrompt, response.emotion.vad).catch(() => { });
606
- }
607
- }
608
- // 3. Event emission
609
- if (this.events) {
610
- this.emitResponseEvents(response, now).catch(() => { });
611
- }
612
- }
613
- async handleReflection(prompt, emotionVad) {
614
- const reflectionLlm = this.engineLlm ?? this.llm;
615
- if (!reflectionLlm)
616
- return;
617
- if (!this.memoryAdapter && !this.episodeStore)
618
- return;
619
- const { text } = await reflectionLlm.generateText({
620
- system: prompt.system,
621
- messages: [{ role: 'user', content: prompt.user }],
622
- });
623
- const reflection = {
624
- id: `ref-${Date.now()}`,
625
- timestamp: Date.now(),
626
- sourceEntity: this._personaId,
627
- content: text,
628
- trigger: 'interaction',
629
- emotionSnapshot: emotionVad ?? { V: 0, A: 0, D: 0 },
630
- };
631
- if (this.memoryAdapter) {
632
- // Single adapter path — save reflection if supported
633
- if (this.memoryAdapter.saveReflection) {
634
- await this.memoryAdapter.saveReflection(reflection);
635
- }
636
- }
637
- else if (this.episodeStore) {
638
- // Split adapter path
639
- await this.episodeStore.saveReflection(reflection);
640
- if (this.semanticStore && this.embeddingProvider) {
641
- try {
642
- const embedding = await this.embeddingProvider.embed(text);
643
- await this.semanticStore.index({
644
- id: reflection.id,
645
- embedding,
646
- metadata: {
647
- type: 'reflection',
648
- sourceEntity: this._personaId,
649
- timestamp: reflection.timestamp,
650
- },
651
- });
652
- }
653
- catch {
654
- // semantic indexing is optional
655
- }
656
- }
657
- }
658
- await this.events?.emit({
659
- type: 'reflection_generated',
660
- personaId: this._personaId,
661
- timestamp: Date.now(),
662
- payload: { trigger: 'interaction' },
663
- });
664
- }
665
- async emitResponseEvents(response, now) {
666
- if (!this.events)
667
- return;
668
- const batch = [];
669
- if (response.emotion) {
670
- batch.push({
671
- type: 'emotion_changed',
672
- personaId: this._personaId,
673
- timestamp: now,
674
- payload: {
675
- vad: response.emotion.vad,
676
- primary: response.emotion.discrete.primary,
677
- intensity: response.emotion.discrete.intensity,
678
- },
679
- });
680
- }
681
- if (response.socialUpdates?.length) {
682
- batch.push({
683
- type: 'relationship_changed',
684
- personaId: this._personaId,
685
- timestamp: now,
686
- payload: { updates: response.socialUpdates },
687
- });
688
- }
689
- if (response.memoryEpisode) {
690
- batch.push({
691
- type: 'memory_consolidated',
692
- personaId: this._personaId,
693
- timestamp: now,
694
- payload: { episodeId: response.memoryEpisode.id },
695
- });
696
- }
697
- if (response.stageTransition) {
698
- batch.push({ type: 'stage_transition', personaId: this._personaId, timestamp: now, payload: {} });
699
- }
700
- if (response.maskExposure) {
701
- batch.push({ type: 'mask_exposure', personaId: this._personaId, timestamp: now, payload: response.maskExposure });
702
- }
703
- if (response.goalChanges) {
704
- batch.push({ type: 'goal_changed', personaId: this._personaId, timestamp: now, payload: response.goalChanges });
705
- }
706
- if (batch.length === 0)
707
- return;
708
- if (this.events.emitBatch) {
709
- await this.events.emitBatch(batch);
710
- }
711
- else {
712
- for (const event of batch) {
713
- await this.events.emit(event);
714
- }
715
- }
716
- }
717
- buildAppraisalHint(appraisal) {
718
- return [
719
- '## Emotional Evaluation (already computed — embody this, do not describe it)',
720
- `Goal relevance: ${appraisal.goal_relevance.toFixed(2)}, congruence: ${appraisal.goal_congruence.toFixed(2)}`,
721
- `Expectedness: ${appraisal.expectedness.toFixed(2)}, controllability: ${appraisal.controllability.toFixed(2)}`,
722
- `Agency: ${appraisal.agency.toFixed(2)}, norm compatibility: ${appraisal.norm_compatibility.toFixed(2)}`,
723
- ].join('\n');
724
- }
725
- requireLLM() {
726
- if (!this.llm) {
727
- throw new errors_1.MolrooApiError('LLM adapter is required for chat(). Provide llm option, or use perceive() directly.', 'LLM_NOT_CONFIGURED', 400);
728
- }
729
- return this.llm;
730
- }
231
+ // ── Prompt / Memory ──
731
232
  async getPromptContext(consumerSuffix, sourceEntity) {
732
233
  const { data } = await this.client.POST('/personas/{id}/prompt-context', {
733
234
  params: { path: { id: this._personaId } },
@@ -738,10 +239,6 @@ class MolrooPersona {
738
239
  });
739
240
  return (0, api_client_1.unwrap)(data);
740
241
  }
741
- /**
742
- * Search persona's episodic memory via the API.
743
- * Used internally by the tool-use loop.
744
- */
745
242
  async searchMemory(query, options) {
746
243
  const { data } = await this.client.POST('/personas/{id}/memory/search', {
747
244
  params: { path: { id: this._personaId } },
@@ -754,94 +251,21 @@ class MolrooPersona {
754
251
  const result = (0, api_client_1.unwrap)(data);
755
252
  return result.episodes;
756
253
  }
757
- /**
758
- * LLM generation loop with tool-use support for standalone persona.
759
- * Uses LLMResponseWithToolsSchema which allows the LLM to request
760
- * memory searches via the search_memory field. Capped at 3 iterations.
761
- */
762
- async generateWithToolLoop(llm, system, messages, onToolCall) {
763
- const MAX_TOOL_ITERATIONS = 3;
764
- const { LLMResponseWithToolsSchema, LLMResponseSchema } = await Promise.resolve().then(() => __importStar(require('./llm/schema')));
765
- let currentSystem = system;
766
- for (let iteration = 0; iteration < MAX_TOOL_ITERATIONS; iteration++) {
767
- const { object: llmResult } = await llm.generateObject({
768
- system: currentSystem,
769
- messages,
770
- schema: LLMResponseWithToolsSchema,
771
- });
772
- // If no tool call requested, return the response
773
- if (!llmResult.search_memory) {
774
- const text = llmResult.response;
775
- const appraisal = llmResult.appraisal ?? {
776
- goal_relevance: 0,
777
- goal_congruence: 0,
778
- expectedness: 0.5,
779
- controllability: 0.5,
780
- agency: 0,
781
- norm_compatibility: 0,
782
- internal_standards: 0,
783
- adjustment_potential: 0.5,
784
- urgency: 0.5,
785
- };
786
- return { text, appraisal };
787
- }
788
- // Execute memory search tool call
789
- const query = llmResult.search_memory;
790
- let episodes = [];
791
- try {
792
- episodes = await this.searchMemory(query);
793
- }
794
- catch {
795
- // Memory search failed — continue without results
796
- }
797
- // Notify callback if provided
798
- if (onToolCall) {
799
- onToolCall({
800
- name: 'search_memory',
801
- args: { query },
802
- result: episodes,
803
- });
804
- }
805
- // Inject memory search results into system prompt for next iteration
806
- const resultBlock = episodes.length > 0
807
- ? `\n\n## Memory Search Results (query: "${query}")\n${episodes.map(ep => {
808
- const ts = ep.timestamp ? new Date(ep.timestamp).toISOString() : 'unknown';
809
- const source = ep.sourceEntity ?? 'unknown';
810
- const context = ep.context ?? 'no context';
811
- return `- [${ts}] ${source}: ${context}`;
812
- }).join('\n')}`
813
- : `\n\n## Memory Search Results (query: "${query}")\nNo matching memories found.`;
814
- currentSystem = currentSystem + resultBlock;
815
- }
816
- // Exhausted tool iterations — make a final call without tool schema
817
- const { object: finalResult } = await llm.generateObject({
818
- system: currentSystem,
819
- messages,
820
- schema: LLMResponseSchema,
821
- });
822
- const text = finalResult.response;
823
- const appraisal = finalResult.appraisal ?? {
824
- goal_relevance: 0,
825
- goal_congruence: 0,
826
- expectedness: 0.5,
827
- controllability: 0.5,
828
- agency: 0,
829
- norm_compatibility: 0,
830
- internal_standards: 0,
831
- adjustment_potential: 0.5,
832
- urgency: 0.5,
254
+ // ── Private ──
255
+ get memoryPipelineDeps() {
256
+ return {
257
+ personaId: this._personaId,
258
+ memoryAdapter: this.memoryAdapter,
259
+ events: this.events,
260
+ llm: this.llm,
261
+ engineLlm: this.engineLlm,
833
262
  };
834
- return { text, appraisal };
835
263
  }
836
- buildContextBlock(state, from) {
837
- const parts = [];
838
- if (from) {
839
- parts.push(`Speaking with: ${from}.`);
840
- }
841
- if (state.narrative) {
842
- parts.push(`Narrative tone: ${state.narrative.tone.toFixed(2)}, agency: ${state.narrative.agency.toFixed(2)}`);
264
+ requireLLM() {
265
+ if (!this.llm) {
266
+ throw new errors_1.MolrooApiError('LLM adapter is required for chat(). Provide llm option, or use perceive() directly.', 'LLM_NOT_CONFIGURED', 400);
843
267
  }
844
- return parts.join('\n');
268
+ return this.llm;
845
269
  }
846
270
  }
847
271
  exports.MolrooPersona = MolrooPersona;