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