@ai-setting/roy-agent-core 1.5.89 → 1.5.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/env/agent/index.js +3 -3
  2. package/dist/env/event-source/index.js +8 -4
  3. package/dist/env/index.js +9 -9
  4. package/dist/env/llm/index.js +4 -2
  5. package/dist/env/session/index.js +3 -3
  6. package/dist/env/session/storage/index.js +2 -2
  7. package/dist/env/task/plugins/index.js +1 -1
  8. package/dist/env/workflow/engine/index.js +2 -2
  9. package/dist/env/workflow/index.js +3 -3
  10. package/dist/env/workflow/nodes/index.js +1 -1
  11. package/dist/index.js +119 -14
  12. package/dist/shared/@ai-setting/{roy-agent-core-r0m0at3x.js → roy-agent-core-0r4ndyn9.js} +119 -7
  13. package/dist/shared/@ai-setting/{roy-agent-core-fvfc7f6v.js → roy-agent-core-2c8eraxq.js} +62 -8
  14. package/dist/shared/@ai-setting/{roy-agent-core-h2d1s8yd.js → roy-agent-core-5ykms33a.js} +1 -1
  15. package/dist/shared/@ai-setting/{roy-agent-core-fgpnv7dt.js → roy-agent-core-8zjntsbb.js} +71 -28
  16. package/dist/shared/@ai-setting/{roy-agent-core-vneyghpg.js → roy-agent-core-ddq5hcp5.js} +1 -1
  17. package/dist/shared/@ai-setting/{roy-agent-core-qhhxx2x2.js → roy-agent-core-ds5f75pg.js} +2 -1
  18. package/dist/shared/@ai-setting/{roy-agent-core-3f6k060j.js → roy-agent-core-j0107ww1.js} +1 -1
  19. package/dist/shared/@ai-setting/{roy-agent-core-2q7cshpm.js → roy-agent-core-m683wd1n.js} +283 -15
  20. package/dist/shared/@ai-setting/{roy-agent-core-qbq3jgrn.js → roy-agent-core-rkz8r2sx.js} +1 -1
  21. package/dist/shared/@ai-setting/{roy-agent-core-c1j7ev4e.js → roy-agent-core-txwf64pd.js} +70 -0
  22. package/dist/shared/@ai-setting/{roy-agent-core-m3dkyprg.js → roy-agent-core-w0kb72ve.js} +7 -2
  23. package/dist/shared/@ai-setting/{roy-agent-core-hc20420t.js → roy-agent-core-z240ts1r.js} +27 -3
  24. package/dist/shared/@ai-setting/{roy-agent-core-q7sqeax6.js → roy-agent-core-zky9jse4.js} +163 -3
  25. package/package.json +1 -1
  26. /package/dist/shared/@ai-setting/{roy-agent-core-4f3976cd.js → roy-agent-core-k5hxvaf0.js} +0 -0
@@ -1,10 +1,27 @@
1
1
  import {
2
2
  SessionMessageConverter
3
- } from "./roy-agent-core-c1j7ev4e.js";
3
+ } from "./roy-agent-core-txwf64pd.js";
4
+ import {
5
+ createLogger,
6
+ init_logger
7
+ } from "./roy-agent-core-shme7set.js";
4
8
  import {
5
9
  __require
6
10
  } from "./roy-agent-core-fs0mn2jk.js";
7
11
 
12
+ // src/env/session/session-store.ts
13
+ class BaseSessionStore {
14
+ async addMessages(sessionId, messages) {
15
+ if (messages.length === 0)
16
+ return [];
17
+ const ids = [];
18
+ for (const msg of messages) {
19
+ ids.push(await this.addMessage(sessionId, msg));
20
+ }
21
+ return ids;
22
+ }
23
+ }
24
+
8
25
  // src/env/session/storage/memory.ts
9
26
  import { randomUUID } from "crypto";
10
27
  function generateSessionId() {
@@ -14,7 +31,7 @@ function generateMessageId() {
14
31
  return `msg_${randomUUID()}`;
15
32
  }
16
33
 
17
- class MemorySessionStore {
34
+ class MemorySessionStore extends BaseSessionStore {
18
35
  sessions = new Map;
19
36
  messages = new Map;
20
37
  checkpoints = new Map;
@@ -138,6 +155,40 @@ class MemorySessionStore {
138
155
  session.updatedAt = Date.now();
139
156
  return msg.id;
140
157
  }
158
+ async addMessages(sessionId, messages) {
159
+ if (messages.length === 0) {
160
+ return [];
161
+ }
162
+ const session = this.sessions.get(sessionId);
163
+ if (!session) {
164
+ throw new Error(`Session not found: ${sessionId}`);
165
+ }
166
+ const sessionMessages = this.messages.get(sessionId) ?? [];
167
+ const ids = [];
168
+ const now = Date.now();
169
+ for (const message of messages) {
170
+ const rawMessage = {
171
+ sessionID: sessionId,
172
+ role: message.role,
173
+ content: message.content,
174
+ parts: message.parts,
175
+ metadata: message.metadata
176
+ };
177
+ const msg = this.messageConverter.migrateMessage(rawMessage);
178
+ msg.id = generateMessageId();
179
+ msg.timestamp = now;
180
+ sessionMessages.push(msg);
181
+ ids.push(msg.id);
182
+ }
183
+ this.messages.set(sessionId, sessionMessages);
184
+ session.messageCount = sessionMessages.filter((m) => !m.isArchived).length;
185
+ session.metadata = {
186
+ ...session.metadata,
187
+ messageCount: session.messageCount
188
+ };
189
+ session.updatedAt = now;
190
+ return ids;
191
+ }
141
192
  async updateMessage(sessionId, messageId, updates) {
142
193
  const sessionMessages = this.messages.get(sessionId);
143
194
  if (!sessionMessages) {
@@ -371,6 +422,8 @@ class MemorySessionStore {
371
422
  // src/env/session/storage/sqlite.ts
372
423
  import { join } from "path";
373
424
  import { randomUUID as randomUUID2 } from "crypto";
425
+ init_logger();
426
+ var logger = createLogger("session:storage:sqlite");
374
427
  function getDatabaseClass() {
375
428
  if (typeof Bun !== "undefined") {
376
429
  const { Database } = __require("bun:sqlite");
@@ -379,6 +432,17 @@ function getDatabaseClass() {
379
432
  return __require("better-sqlite3");
380
433
  }
381
434
  }
435
+ function isSqliteBusyError(err) {
436
+ if (err == null)
437
+ return false;
438
+ const e = err;
439
+ if (typeof e.code === "string" && /^SQLITE_(BUSY|LOCKED)$/i.test(e.code))
440
+ return true;
441
+ if (typeof e.errno === "number" && (e.errno === 5 || e.errno === 6))
442
+ return true;
443
+ const msg = e.message ?? "";
444
+ return /SQLiteError:\s+(database is locked|database table is locked)/i.test(msg);
445
+ }
382
446
  function createCompatibleDatabase(path) {
383
447
  const Database = getDatabaseClass();
384
448
  const db = new Database(path);
@@ -407,7 +471,7 @@ function getDefaultSessionDbPath() {
407
471
  return join(getDefaultDataDir(), "roy-agent", "sessions.db");
408
472
  }
409
473
 
410
- class SQLiteSessionStore {
474
+ class SQLiteSessionStore extends BaseSessionStore {
411
475
  db = null;
412
476
  dbPath;
413
477
  initialized = false;
@@ -416,6 +480,7 @@ class SQLiteSessionStore {
416
480
  checkpointsCache = new Map;
417
481
  messageConverter = new SessionMessageConverter;
418
482
  constructor(dbPath) {
483
+ super();
419
484
  this.dbPath = dbPath || getDefaultSessionDbPath();
420
485
  }
421
486
  async initialize() {
@@ -430,6 +495,10 @@ class SQLiteSessionStore {
430
495
  }
431
496
  }
432
497
  this.db = createCompatibleDatabase(this.dbPath);
498
+ this.applyPragma("PRAGMA journal_mode = WAL");
499
+ this.applyPragma("PRAGMA busy_timeout = 5000");
500
+ this.applyPragma("PRAGMA synchronous = NORMAL");
501
+ this.applyPragma("PRAGMA wal_autocheckpoint = 1000");
433
502
  this.db.run(`
434
503
  CREATE TABLE IF NOT EXISTS session (
435
504
  id TEXT PRIMARY KEY,
@@ -611,6 +680,90 @@ class SQLiteSessionStore {
611
680
  this.sessionsCache.set(sessionId, session);
612
681
  return msg.id;
613
682
  }
683
+ async addMessages(sessionId, messages) {
684
+ if (messages.length === 0) {
685
+ return [];
686
+ }
687
+ const BATCH_BACKOFFS_MS = [50, 100, 200];
688
+ let lastError = undefined;
689
+ for (let attempt = 0;attempt <= BATCH_BACKOFFS_MS.length; attempt++) {
690
+ try {
691
+ return await this.addMessagesOnce(sessionId, messages);
692
+ } catch (err) {
693
+ if (!isSqliteBusyError(err) || attempt === BATCH_BACKOFFS_MS.length) {
694
+ this.messagesCache.delete(sessionId);
695
+ this.sessionsCache.delete(sessionId);
696
+ lastError = err;
697
+ if (!isSqliteBusyError(err))
698
+ throw err;
699
+ break;
700
+ }
701
+ await new Promise((resolve) => setTimeout(resolve, BATCH_BACKOFFS_MS[attempt]));
702
+ }
703
+ }
704
+ throw lastError;
705
+ }
706
+ async addMessagesOnce(sessionId, messages) {
707
+ await this.initialize();
708
+ const session = await this.get(sessionId);
709
+ if (!session) {
710
+ throw new Error(`Session not found: ${sessionId}`);
711
+ }
712
+ const now = Date.now();
713
+ const ids = [];
714
+ const insertStmt = this.db.prepare(`
715
+ INSERT INTO message (id, session_id, role, content, timestamp, parts, metadata)
716
+ VALUES (?, ?, ?, ?, ?, ?, ?)
717
+ `);
718
+ const sessionUpdateStmt = this.db.prepare(`
719
+ UPDATE session SET message_count = ?, metadata = ?, updated_at = ? WHERE id = ?
720
+ `);
721
+ this.db.run("BEGIN");
722
+ try {
723
+ for (const message of messages) {
724
+ const id = generateMessageId2();
725
+ ids.push(id);
726
+ insertStmt.run(id, sessionId, message.role, message.content, now, message.parts ? JSON.stringify(message.parts) : null, message.metadata ? JSON.stringify(message.metadata) : null);
727
+ }
728
+ const countResult = this.db.prepare("SELECT COUNT(*) as count FROM message WHERE session_id = ? AND is_archived = 0").get(sessionId);
729
+ const newCount = countResult?.count ?? 0;
730
+ session.messageCount = newCount;
731
+ session.updatedAt = now;
732
+ session.metadata = {
733
+ ...session.metadata ?? {},
734
+ messageCount: newCount
735
+ };
736
+ sessionUpdateStmt.run(newCount, JSON.stringify(session.metadata), now, sessionId);
737
+ this.db.run("COMMIT");
738
+ } catch (err) {
739
+ try {
740
+ this.db.run("ROLLBACK");
741
+ } catch {}
742
+ throw err;
743
+ }
744
+ try {
745
+ const cached = this.messagesCache.get(sessionId) ?? [];
746
+ for (let i = 0;i < messages.length; i++) {
747
+ const message = messages[i];
748
+ cached.push({
749
+ id: ids[i],
750
+ sessionID: sessionId,
751
+ role: message.role,
752
+ content: message.content,
753
+ timestamp: now,
754
+ parts: message.parts,
755
+ metadata: message.metadata
756
+ });
757
+ }
758
+ this.messagesCache.set(sessionId, cached);
759
+ this.sessionsCache.set(sessionId, session);
760
+ } catch (cacheErr) {
761
+ logger.warn(`[SQLiteSessionStore] cache update failed after commit; invalidating: ${cacheErr}`);
762
+ this.messagesCache.delete(sessionId);
763
+ this.sessionsCache.delete(sessionId);
764
+ }
765
+ return ids;
766
+ }
614
767
  async updateMessage(sessionId, messageId, updates) {
615
768
  await this.initialize();
616
769
  const row = this.db.prepare("SELECT id FROM message WHERE id = ? AND session_id = ?").get(messageId, sessionId);
@@ -679,6 +832,13 @@ class SQLiteSessionStore {
679
832
  const rows = this.db.prepare(sql).all(...params);
680
833
  return rows.map((row) => this.rowToMessage(row));
681
834
  }
835
+ applyPragma(pragmaSql) {
836
+ this.db.run(pragmaSql);
837
+ const readback = this.db.prepare(pragmaSql.split("=")[0].trim()).get();
838
+ const key = Object.keys(readback ?? {})[0];
839
+ const actual = key ? readback[key] : undefined;
840
+ logger.info(`[SQLiteSessionStore] Applied ${pragmaSql} → ${actual}`);
841
+ }
682
842
  async getMessageCount(sessionId, includeArchived = false) {
683
843
  await this.initialize();
684
844
  let sql = "SELECT COUNT(*) as count FROM message WHERE session_id = ?";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-setting/roy-agent-core",
3
- "version": "1.5.89",
3
+ "version": "1.5.90",
4
4
  "type": "module",
5
5
  "description": "Core SDK for roy-agent - Environment, Components, Tools, Sessions, Tasks",
6
6
  "main": "./dist/index.js",