@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.
- package/README.md +100 -194
- package/dist/cjs/api-client.d.ts +2 -12
- package/dist/cjs/api-client.d.ts.map +1 -1
- package/dist/cjs/api-client.js +4 -42
- package/dist/cjs/errors.d.ts +1 -16
- package/dist/cjs/errors.d.ts.map +1 -1
- package/dist/cjs/errors.js +2 -18
- package/dist/cjs/events/types.d.ts +14 -21
- package/dist/cjs/events/types.d.ts.map +1 -1
- package/dist/cjs/events/types.js +0 -11
- package/dist/cjs/index.d.ts +26 -48
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +29 -52
- package/dist/cjs/llm/resolve.d.ts +4 -22
- package/dist/cjs/llm/resolve.d.ts.map +1 -1
- package/dist/cjs/llm/resolve.js +19 -7
- package/dist/cjs/llm/vercel-ai/adapter.d.ts +4 -10
- package/dist/cjs/llm/vercel-ai/adapter.d.ts.map +1 -1
- package/dist/cjs/llm/vercel-ai/adapter.js +6 -152
- package/dist/cjs/llm/vercel-ai/config.d.ts +8 -5
- package/dist/cjs/llm/vercel-ai/config.d.ts.map +1 -1
- package/dist/cjs/memory/in-memory.d.ts +14 -37
- package/dist/cjs/memory/in-memory.d.ts.map +1 -1
- package/dist/cjs/memory/in-memory.js +22 -85
- package/dist/cjs/memory/recall.d.ts +10 -21
- package/dist/cjs/memory/recall.d.ts.map +1 -1
- package/dist/cjs/memory/recall.js +12 -91
- package/dist/cjs/memory/types.d.ts +46 -186
- package/dist/cjs/memory/types.d.ts.map +1 -1
- package/dist/cjs/memory/types.js +0 -10
- package/dist/cjs/persona/chat-orchestrator.d.ts +46 -0
- package/dist/cjs/persona/chat-orchestrator.d.ts.map +1 -0
- package/dist/cjs/persona/chat-orchestrator.js +240 -0
- package/dist/cjs/persona/event-emitter.d.ts +7 -0
- package/dist/cjs/persona/event-emitter.d.ts.map +1 -0
- package/dist/cjs/persona/event-emitter.js +53 -0
- package/dist/cjs/persona/memory-pipeline.d.ts +26 -0
- package/dist/cjs/persona/memory-pipeline.d.ts.map +1 -0
- package/dist/cjs/persona/memory-pipeline.js +69 -0
- package/dist/cjs/persona.d.ts +56 -187
- package/dist/cjs/persona.d.ts.map +1 -1
- package/dist/cjs/persona.js +62 -638
- package/dist/cjs/shared/appraisal.d.ts +26 -0
- package/dist/cjs/shared/appraisal.d.ts.map +1 -0
- package/dist/cjs/shared/appraisal.js +45 -0
- package/dist/cjs/shared/client-factory.d.ts +23 -0
- package/dist/cjs/shared/client-factory.d.ts.map +1 -0
- package/dist/cjs/shared/client-factory.js +48 -0
- package/dist/cjs/shared/errors.d.ts +21 -0
- package/dist/cjs/shared/errors.d.ts.map +1 -0
- package/dist/cjs/shared/errors.js +29 -0
- package/dist/cjs/world/client.d.ts +2 -9
- package/dist/cjs/world/client.d.ts.map +1 -1
- package/dist/cjs/world/client.js +7 -34
- package/dist/cjs/world/errors.d.ts +1 -8
- package/dist/cjs/world/errors.d.ts.map +1 -1
- package/dist/cjs/world/errors.js +2 -12
- package/dist/cjs/world/index.d.ts +2 -2
- package/dist/cjs/world/index.d.ts.map +1 -1
- package/dist/cjs/world/types.d.ts +6 -4
- package/dist/cjs/world/types.d.ts.map +1 -1
- package/dist/cjs/world/world-domain.d.ts.map +1 -1
- package/dist/cjs/world/world-domain.js +4 -32
- package/dist/cjs/world/world-persona.d.ts +7 -5
- package/dist/cjs/world/world-persona.d.ts.map +1 -1
- package/dist/cjs/world/world-persona.js +2 -17
- package/dist/cjs/world/world.d.ts +28 -5
- package/dist/cjs/world/world.d.ts.map +1 -1
- package/dist/cjs/world/world.js +13 -11
- package/dist/esm/api-client.d.ts +2 -12
- package/dist/esm/api-client.d.ts.map +1 -1
- package/dist/esm/api-client.js +3 -38
- package/dist/esm/errors.d.ts +1 -16
- package/dist/esm/errors.d.ts.map +1 -1
- package/dist/esm/errors.js +1 -17
- package/dist/esm/events/types.d.ts +14 -21
- package/dist/esm/events/types.d.ts.map +1 -1
- package/dist/esm/events/types.js +0 -11
- package/dist/esm/index.d.ts +26 -48
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +25 -38
- package/dist/esm/llm/resolve.d.ts +4 -22
- package/dist/esm/llm/resolve.d.ts.map +1 -1
- package/dist/esm/llm/resolve.js +20 -8
- package/dist/esm/llm/vercel-ai/adapter.d.ts +4 -10
- package/dist/esm/llm/vercel-ai/adapter.d.ts.map +1 -1
- package/dist/esm/llm/vercel-ai/adapter.js +6 -119
- package/dist/esm/llm/vercel-ai/config.d.ts +8 -5
- package/dist/esm/llm/vercel-ai/config.d.ts.map +1 -1
- package/dist/esm/memory/in-memory.d.ts +14 -37
- package/dist/esm/memory/in-memory.d.ts.map +1 -1
- package/dist/esm/memory/in-memory.js +20 -83
- package/dist/esm/memory/recall.d.ts +10 -21
- package/dist/esm/memory/recall.d.ts.map +1 -1
- package/dist/esm/memory/recall.js +12 -91
- package/dist/esm/memory/types.d.ts +46 -186
- package/dist/esm/memory/types.d.ts.map +1 -1
- package/dist/esm/memory/types.js +1 -9
- package/dist/esm/persona/chat-orchestrator.d.ts +46 -0
- package/dist/esm/persona/chat-orchestrator.d.ts.map +1 -0
- package/dist/esm/persona/chat-orchestrator.js +204 -0
- package/dist/esm/persona/event-emitter.d.ts +7 -0
- package/dist/esm/persona/event-emitter.d.ts.map +1 -0
- package/dist/esm/persona/event-emitter.js +50 -0
- package/dist/esm/persona/memory-pipeline.d.ts +26 -0
- package/dist/esm/persona/memory-pipeline.d.ts.map +1 -0
- package/dist/esm/persona/memory-pipeline.js +65 -0
- package/dist/esm/persona.d.ts +56 -187
- package/dist/esm/persona.d.ts.map +1 -1
- package/dist/esm/persona.js +62 -638
- package/dist/esm/shared/appraisal.d.ts +26 -0
- package/dist/esm/shared/appraisal.d.ts.map +1 -0
- package/dist/esm/shared/appraisal.js +40 -0
- package/dist/esm/shared/client-factory.d.ts +23 -0
- package/dist/esm/shared/client-factory.d.ts.map +1 -0
- package/dist/esm/shared/client-factory.js +41 -0
- package/dist/esm/shared/errors.d.ts +21 -0
- package/dist/esm/shared/errors.d.ts.map +1 -0
- package/dist/esm/shared/errors.js +24 -0
- package/dist/esm/world/client.d.ts +2 -9
- package/dist/esm/world/client.d.ts.map +1 -1
- package/dist/esm/world/client.js +6 -30
- package/dist/esm/world/errors.d.ts +1 -8
- package/dist/esm/world/errors.d.ts.map +1 -1
- package/dist/esm/world/errors.js +1 -11
- package/dist/esm/world/index.d.ts +2 -2
- package/dist/esm/world/index.d.ts.map +1 -1
- package/dist/esm/world/types.d.ts +6 -4
- package/dist/esm/world/types.d.ts.map +1 -1
- package/dist/esm/world/world-domain.d.ts.map +1 -1
- package/dist/esm/world/world-domain.js +4 -32
- package/dist/esm/world/world-persona.d.ts +7 -5
- package/dist/esm/world/world-persona.d.ts.map +1 -1
- package/dist/esm/world/world-persona.js +2 -17
- package/dist/esm/world/world.d.ts +28 -5
- package/dist/esm/world/world.d.ts.map +1 -1
- package/dist/esm/world/world.js +13 -11
- package/package.json +4 -101
- package/dist/cjs/embedding/cloudflare.d.ts +0 -15
- package/dist/cjs/embedding/cloudflare.d.ts.map +0 -1
- package/dist/cjs/embedding/cloudflare.js +0 -16
- package/dist/cjs/embedding/cohere.d.ts +0 -8
- package/dist/cjs/embedding/cohere.d.ts.map +0 -1
- package/dist/cjs/embedding/cohere.js +0 -31
- package/dist/cjs/embedding/index.d.ts +0 -9
- package/dist/cjs/embedding/index.d.ts.map +0 -1
- package/dist/cjs/embedding/index.js +0 -11
- package/dist/cjs/embedding/local.d.ts +0 -6
- package/dist/cjs/embedding/local.d.ts.map +0 -1
- package/dist/cjs/embedding/local.js +0 -28
- package/dist/cjs/embedding/openai.d.ts +0 -9
- package/dist/cjs/embedding/openai.d.ts.map +0 -1
- package/dist/cjs/embedding/openai.js +0 -26
- package/dist/cjs/events/console.d.ts +0 -25
- package/dist/cjs/events/console.d.ts.map +0 -1
- package/dist/cjs/events/console.js +0 -41
- package/dist/cjs/events/webhook.d.ts +0 -30
- package/dist/cjs/events/webhook.d.ts.map +0 -1
- package/dist/cjs/events/webhook.js +0 -79
- package/dist/cjs/memory/cloudflare/index.d.ts +0 -3
- package/dist/cjs/memory/cloudflare/index.d.ts.map +0 -1
- package/dist/cjs/memory/cloudflare/index.js +0 -5
- package/dist/cjs/memory/cloudflare/vectorize.d.ts +0 -62
- package/dist/cjs/memory/cloudflare/vectorize.d.ts.map +0 -1
- package/dist/cjs/memory/cloudflare/vectorize.js +0 -55
- package/dist/cjs/memory/in-memory-semantic.d.ts +0 -16
- package/dist/cjs/memory/in-memory-semantic.d.ts.map +0 -1
- package/dist/cjs/memory/in-memory-semantic.js +0 -57
- package/dist/cjs/memory/pinecone/index.d.ts +0 -7
- package/dist/cjs/memory/pinecone/index.d.ts.map +0 -1
- package/dist/cjs/memory/pinecone/index.js +0 -8
- package/dist/cjs/memory/pinecone/memory-adapter.d.ts +0 -62
- package/dist/cjs/memory/pinecone/memory-adapter.d.ts.map +0 -1
- package/dist/cjs/memory/pinecone/memory-adapter.js +0 -220
- package/dist/cjs/memory/pinecone/semantic.d.ts +0 -44
- package/dist/cjs/memory/pinecone/semantic.d.ts.map +0 -1
- package/dist/cjs/memory/pinecone/semantic.js +0 -90
- package/dist/cjs/memory/sqlite/index.d.ts +0 -3
- package/dist/cjs/memory/sqlite/index.d.ts.map +0 -1
- package/dist/cjs/memory/sqlite/index.js +0 -5
- package/dist/cjs/memory/sqlite/memory-adapter.d.ts +0 -58
- package/dist/cjs/memory/sqlite/memory-adapter.d.ts.map +0 -1
- package/dist/cjs/memory/sqlite/memory-adapter.js +0 -336
- package/dist/cjs/memory/sqlite/schema.d.ts +0 -4
- package/dist/cjs/memory/sqlite/schema.d.ts.map +0 -1
- package/dist/cjs/memory/sqlite/schema.js +0 -91
- package/dist/cjs/memory/supabase/index.d.ts +0 -7
- package/dist/cjs/memory/supabase/index.d.ts.map +0 -1
- package/dist/cjs/memory/supabase/index.js +0 -8
- package/dist/cjs/memory/supabase/memory-adapter.d.ts +0 -67
- package/dist/cjs/memory/supabase/memory-adapter.d.ts.map +0 -1
- package/dist/cjs/memory/supabase/memory-adapter.js +0 -335
- package/dist/cjs/memory/supabase/semantic.d.ts +0 -44
- package/dist/cjs/memory/supabase/semantic.d.ts.map +0 -1
- package/dist/cjs/memory/supabase/semantic.js +0 -72
- package/dist/esm/embedding/cloudflare.d.ts +0 -15
- package/dist/esm/embedding/cloudflare.d.ts.map +0 -1
- package/dist/esm/embedding/cloudflare.js +0 -13
- package/dist/esm/embedding/cohere.d.ts +0 -8
- package/dist/esm/embedding/cohere.d.ts.map +0 -1
- package/dist/esm/embedding/cohere.js +0 -28
- package/dist/esm/embedding/index.d.ts +0 -9
- package/dist/esm/embedding/index.d.ts.map +0 -1
- package/dist/esm/embedding/index.js +0 -4
- package/dist/esm/embedding/local.d.ts +0 -6
- package/dist/esm/embedding/local.d.ts.map +0 -1
- package/dist/esm/embedding/local.js +0 -25
- package/dist/esm/embedding/openai.d.ts +0 -9
- package/dist/esm/embedding/openai.d.ts.map +0 -1
- package/dist/esm/embedding/openai.js +0 -23
- package/dist/esm/events/console.d.ts +0 -25
- package/dist/esm/events/console.d.ts.map +0 -1
- package/dist/esm/events/console.js +0 -37
- package/dist/esm/events/webhook.d.ts +0 -30
- package/dist/esm/events/webhook.d.ts.map +0 -1
- package/dist/esm/events/webhook.js +0 -75
- package/dist/esm/memory/cloudflare/index.d.ts +0 -3
- package/dist/esm/memory/cloudflare/index.d.ts.map +0 -1
- package/dist/esm/memory/cloudflare/index.js +0 -1
- package/dist/esm/memory/cloudflare/vectorize.d.ts +0 -62
- package/dist/esm/memory/cloudflare/vectorize.d.ts.map +0 -1
- package/dist/esm/memory/cloudflare/vectorize.js +0 -51
- package/dist/esm/memory/in-memory-semantic.d.ts +0 -16
- package/dist/esm/memory/in-memory-semantic.d.ts.map +0 -1
- package/dist/esm/memory/in-memory-semantic.js +0 -53
- package/dist/esm/memory/pinecone/index.d.ts +0 -7
- package/dist/esm/memory/pinecone/index.d.ts.map +0 -1
- package/dist/esm/memory/pinecone/index.js +0 -3
- package/dist/esm/memory/pinecone/memory-adapter.d.ts +0 -62
- package/dist/esm/memory/pinecone/memory-adapter.d.ts.map +0 -1
- package/dist/esm/memory/pinecone/memory-adapter.js +0 -216
- package/dist/esm/memory/pinecone/semantic.d.ts +0 -44
- package/dist/esm/memory/pinecone/semantic.d.ts.map +0 -1
- package/dist/esm/memory/pinecone/semantic.js +0 -86
- package/dist/esm/memory/sqlite/index.d.ts +0 -3
- package/dist/esm/memory/sqlite/index.d.ts.map +0 -1
- package/dist/esm/memory/sqlite/index.js +0 -1
- package/dist/esm/memory/sqlite/memory-adapter.d.ts +0 -58
- package/dist/esm/memory/sqlite/memory-adapter.d.ts.map +0 -1
- package/dist/esm/memory/sqlite/memory-adapter.js +0 -296
- package/dist/esm/memory/sqlite/schema.d.ts +0 -4
- package/dist/esm/memory/sqlite/schema.d.ts.map +0 -1
- package/dist/esm/memory/sqlite/schema.js +0 -86
- package/dist/esm/memory/supabase/index.d.ts +0 -7
- package/dist/esm/memory/supabase/index.d.ts.map +0 -1
- package/dist/esm/memory/supabase/index.js +0 -3
- package/dist/esm/memory/supabase/memory-adapter.d.ts +0 -67
- package/dist/esm/memory/supabase/memory-adapter.d.ts.map +0 -1
- package/dist/esm/memory/supabase/memory-adapter.js +0 -331
- package/dist/esm/memory/supabase/semantic.d.ts +0 -44
- package/dist/esm/memory/supabase/semantic.d.ts.map +0 -1
- package/dist/esm/memory/supabase/semantic.js +0 -68
package/dist/cjs/persona.js
CHANGED
|
@@ -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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
* @
|
|
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
|
-
|
|
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
|
-
|
|
99
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
|
147
|
-
const
|
|
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
|
-
|
|
158
|
-
return persona;
|
|
99
|
+
return new MolrooPersona({ ...config, llm, engineLlm, personaId: result.personaId });
|
|
159
100
|
}
|
|
160
101
|
/**
|
|
161
|
-
* Generate a persona from
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
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
|
-
// ──
|
|
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
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
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
|
-
|
|
837
|
-
|
|
838
|
-
|
|
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
|
|
268
|
+
return this.llm;
|
|
845
269
|
}
|
|
846
270
|
}
|
|
847
271
|
exports.MolrooPersona = MolrooPersona;
|