morpheus-cli 0.2.7 → 0.3.1

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.
@@ -27,6 +27,8 @@ export async function migrateConfigFile() {
27
27
  }
28
28
  // Migrate memory.limit to llm.context_window
29
29
  await migrateContextWindow();
30
+ // Migrate santi -> sati
31
+ await migrateSantiToSati();
30
32
  }
31
33
  /**
32
34
  * Migrates memory.limit to llm.context_window
@@ -78,3 +80,41 @@ async function migrateContextWindow() {
78
80
  });
79
81
  }
80
82
  }
83
+ /**
84
+ * Migrates santi config section to sati
85
+ * Fixes typo in previous versions
86
+ */
87
+ async function migrateSantiToSati() {
88
+ const display = DisplayManager.getInstance();
89
+ const configPath = PATHS.config;
90
+ try {
91
+ // Check if config file exists
92
+ if (!await fs.pathExists(configPath)) {
93
+ return;
94
+ }
95
+ // Read current config
96
+ const configContent = await fs.readFile(configPath, 'utf8');
97
+ const config = yaml.load(configContent);
98
+ // Check if migration is needed
99
+ if (config?.santi !== undefined && config?.sati === undefined) {
100
+ // Create backup before migration
101
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
102
+ const backupPath = `${configPath}.backup-${timestamp}`;
103
+ await fs.copy(configPath, backupPath);
104
+ display.log(`Created config backup: ${backupPath}`, { source: 'Migration', level: 'info' });
105
+ // Perform migration
106
+ config.sati = config.santi;
107
+ delete config.santi;
108
+ // Write migrated config
109
+ const migratedYaml = yaml.dump(config);
110
+ await fs.writeFile(configPath, migratedYaml, 'utf8');
111
+ display.log('Migrated santi → sati in configuration', { source: 'Migration', level: 'info' });
112
+ }
113
+ }
114
+ catch (error) {
115
+ display.log(`Config migration (santi->sati) failed: ${error.message}`, {
116
+ source: 'Migration',
117
+ level: 'warning'
118
+ });
119
+ }
120
+ }
@@ -37,7 +37,7 @@ export class Oracle {
37
37
  const contextWindow = this.config.llm?.context_window ?? this.config.memory?.limit ?? 100;
38
38
  this.display.log(`Using context window: ${contextWindow} messages`, { source: 'Oracle' });
39
39
  this.history = new SQLiteChatMessageHistory({
40
- sessionId: "default",
40
+ sessionId: '', // Let the history manage session IDs internally
41
41
  databasePath: this.databasePath,
42
42
  limit: contextWindow,
43
43
  });
@@ -245,6 +245,74 @@ You maintain intent until resolution.
245
245
  }
246
246
  return await this.history.getMessages();
247
247
  }
248
+ async createNewSession() {
249
+ if (!this.history) {
250
+ throw new Error("Message history not initialized. Call initialize() first.");
251
+ }
252
+ if (this.history instanceof SQLiteChatMessageHistory) {
253
+ await this.history.createNewSession();
254
+ this.display.log('Session rolled over successfully.', { source: 'Oracle' });
255
+ }
256
+ else {
257
+ throw new Error("Current history provider does not support session rollover.");
258
+ }
259
+ }
260
+ async setSessionId(sessionId) {
261
+ if (!this.history) {
262
+ throw new Error("Message history not initialized. Call initialize() first.");
263
+ }
264
+ // Check if the history provider supports switching sessions
265
+ // SQLiteChatMessageHistory does support it via constructor (new instance) or maybe we can add a method there too?
266
+ // Actually SQLiteChatMessageHistory has `switchSession(targetSessionId)` but that one logic is "pause current, activate target".
267
+ // For API usage, we might just want to *target* a session without necessarily changing the global "active" state regarding the Daemon?
268
+ //
269
+ // However, the user request implies this is "the" chat.
270
+ // If we use `switchSession` it pauses others. That seems correct for a single-user agent model.
271
+ //
272
+ // But `SQLiteChatMessageHistory` properties are `sessionId`.
273
+ // It seems `switchSession` in `sqlite.ts` updates the DB state.
274
+ // We also need to update the `sessionId` property of the `SQLiteChatMessageHistory` instance held by Oracle.
275
+ //
276
+ // Let's check `SQLiteChatMessageHistory` again.
277
+ // It has `sessionId` property.
278
+ // It does NOT have a method to just update `sessionId` property without DB side effects?
279
+ //
280
+ // Use `switchSession` from `sqlite.ts` is good for "Active/Paused" state management.
281
+ // But we also need the `history` instance to know it is now pointing to `sessionId`.
282
+ if (this.history instanceof SQLiteChatMessageHistory) {
283
+ // Logic:
284
+ // 1. If currently active session is different, switch.
285
+ // 2. Update internal sessionId.
286
+ // Actually `switchSession` in `sqlite.ts` takes `targetSessionId`.
287
+ // It updates the DB status.
288
+ // It DOES NOT seem to update `this.sessionId` of the instance?
289
+ // Wait, let me check `sqlite.ts` content from memory or view it again alongside.
290
+ //
291
+ // In `sqlite.ts`:
292
+ // public async switchSession(targetSessionId: string): Promise<void> { ... }
293
+ // It updates DB.
294
+ // It DOES NOT update `this.sessionId`.
295
+ //
296
+ // So we need to ensure `this.history` points to the new session.
297
+ // Since `SQLiteChatMessageHistory` might not allow changing `sessionId` publicly if it's protected/private...
298
+ // It is `private sessionId: string;`.
299
+ //
300
+ // So simple fix: Re-instantiate `this.history`?
301
+ // `this.history = new SQLiteChatMessageHistory({ sessionId: sessionId, ... })`
302
+ //
303
+ // This is safe and clean.
304
+ await this.history.switchSession(sessionId);
305
+ // Re-instantiate to point to new session
306
+ this.history = new SQLiteChatMessageHistory({
307
+ sessionId: sessionId,
308
+ databasePath: this.databasePath,
309
+ limit: this.config.llm?.context_window ?? 100
310
+ });
311
+ }
312
+ else {
313
+ throw new Error("Current history provider does not support session switching.");
314
+ }
315
+ }
248
316
  async clearMemory() {
249
317
  if (!this.history) {
250
318
  throw new Error("Message history not initialized. Call initialize() first.");
@@ -0,0 +1,21 @@
1
+ import { runSessionEmbeddingWorker } from './memory/session-embedding-worker.js';
2
+ import { DisplayManager } from './display.js';
3
+ const INTERVAL_MS = 60_000 * 5; // 5 minutos
4
+ export function startSessionEmbeddingScheduler() {
5
+ const display = DisplayManager.getInstance();
6
+ display.log('🕒 Scheduler de embeddings iniciado', { source: 'SessionEmbeddingScheduler' });
7
+ // roda imediatamente na inicialização
8
+ runSessionEmbeddingWorker().catch(console.error);
9
+ let isRunning = false;
10
+ setInterval(async () => {
11
+ if (isRunning)
12
+ return;
13
+ isRunning = true;
14
+ try {
15
+ await runSessionEmbeddingWorker();
16
+ }
17
+ finally {
18
+ isRunning = false;
19
+ }
20
+ }, INTERVAL_MS);
21
+ }
@@ -32,4 +32,12 @@ export const DEFAULT_CONFIG = {
32
32
  enabled: true,
33
33
  port: 3333,
34
34
  },
35
+ sati: {
36
+ provider: 'openai',
37
+ model: 'gpt-4',
38
+ temperature: 0.7,
39
+ context_window: 100,
40
+ memory_limit: 100,
41
+ enabled_archived_sessions: true,
42
+ }
35
43
  };