@nomad-e/bluma-cli 0.26.0 → 0.26.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.
Files changed (2) hide show
  1. package/dist/main.js +84 -106
  2. package/package.json +1 -3
package/dist/main.js CHANGED
@@ -2616,17 +2616,22 @@ var init_CtxInspectTool = __esm({
2616
2616
  import path32 from "path";
2617
2617
  import { mkdirSync as mkdirSync3 } from "fs";
2618
2618
  import { promises as fs27 } from "fs";
2619
- import { createRequire } from "module";
2620
- function loadSqlite() {
2621
- const nodeRequire = createRequire(import.meta.url);
2622
- return nodeRequire("better-sqlite3");
2623
- }
2624
- function getSessionDbPath(appDir = getPreferredAppDir()) {
2625
- return path32.join(appDir, BLUMA_SESSION_DB_FILE);
2619
+ function getSessionIndexPath(appDir = getPreferredAppDir()) {
2620
+ return path32.join(appDir, SESSION_INDEX_FILE);
2626
2621
  }
2627
2622
  function normalizeRelativePath(relativePath) {
2628
2623
  return relativePath.split(path32.sep).join("/");
2629
2624
  }
2625
+ function emptyStore() {
2626
+ return { version: 1, sessions: {} };
2627
+ }
2628
+ async function persistStore(store2, appDir) {
2629
+ mkdirSync3(appDir, { recursive: true });
2630
+ const filePath = getSessionIndexPath(appDir);
2631
+ const tmp = `${filePath}.${Date.now()}.tmp`;
2632
+ await fs27.writeFile(tmp, JSON.stringify(store2, null, 2), "utf-8");
2633
+ await fs27.rename(tmp, filePath);
2634
+ }
2630
2635
  async function walkSessionJsonFiles(dir, onFile) {
2631
2636
  let entries;
2632
2637
  try {
@@ -2707,22 +2712,30 @@ async function readSessionMetaFromJson(absPath) {
2707
2712
  }
2708
2713
  }
2709
2714
  }
2710
- async function runMigrationV1(db, appDir) {
2715
+ function upsertIntoStore(store2, row) {
2716
+ const rel = normalizeRelativePath(row.relativePath);
2717
+ const existing = store2.sessions[row.sessionId];
2718
+ if (!existing) {
2719
+ store2.sessions[row.sessionId] = {
2720
+ relativePath: rel,
2721
+ createdAt: row.createdAt,
2722
+ updatedAt: row.updatedAt,
2723
+ preview: row.preview
2724
+ };
2725
+ return;
2726
+ }
2727
+ const existingMs = Date.parse(existing.updatedAt);
2728
+ const incomingMs = Date.parse(row.updatedAt);
2729
+ const incomingIsNewer = Number.isFinite(incomingMs) && incomingMs >= (Number.isFinite(existingMs) ? existingMs : 0);
2730
+ store2.sessions[row.sessionId] = {
2731
+ relativePath: incomingIsNewer ? rel : existing.relativePath,
2732
+ createdAt: existing.createdAt || row.createdAt,
2733
+ updatedAt: incomingIsNewer ? row.updatedAt : existing.updatedAt,
2734
+ preview: incomingIsNewer ? row.preview : existing.preview
2735
+ };
2736
+ }
2737
+ async function migrateLegacyIndex(store2, appDir) {
2711
2738
  const jsonl = await loadJsonlEntries(appDir);
2712
- const upsert = db.prepare(`
2713
- INSERT INTO agent_sessions (session_id, relative_path, created_at, updated_at, preview)
2714
- VALUES (@sessionId, @relativePath, @createdAt, @updatedAt, @preview)
2715
- ON CONFLICT(session_id) DO UPDATE SET
2716
- relative_path = excluded.relative_path,
2717
- updated_at = CASE
2718
- WHEN excluded.updated_at > agent_sessions.updated_at THEN excluded.updated_at
2719
- ELSE agent_sessions.updated_at
2720
- END,
2721
- preview = CASE
2722
- WHEN excluded.updated_at > agent_sessions.updated_at THEN excluded.preview
2723
- ELSE agent_sessions.preview
2724
- END
2725
- `);
2726
2739
  const insertFromPath = async (sessionId, absPath, jsonlUpdatedAt) => {
2727
2740
  let rel;
2728
2741
  try {
@@ -2732,7 +2745,7 @@ async function runMigrationV1(db, appDir) {
2732
2745
  }
2733
2746
  const meta = await readSessionMetaFromJson(absPath);
2734
2747
  const updatedAt = jsonlUpdatedAt && Date.parse(jsonlUpdatedAt) > Date.parse(meta.updatedAt) ? jsonlUpdatedAt : meta.updatedAt;
2735
- upsert.run({
2748
+ upsertIntoStore(store2, {
2736
2749
  sessionId,
2737
2750
  relativePath: rel,
2738
2751
  createdAt: meta.createdAt,
@@ -2746,7 +2759,7 @@ async function runMigrationV1(db, appDir) {
2746
2759
  await fs27.access(full);
2747
2760
  await insertFromPath(sessionId, full, entry.updatedAt);
2748
2761
  } catch {
2749
- upsert.run({
2762
+ upsertIntoStore(store2, {
2750
2763
  sessionId,
2751
2764
  relativePath: entry.relativePath,
2752
2765
  createdAt: entry.updatedAt,
@@ -2756,109 +2769,74 @@ async function runMigrationV1(db, appDir) {
2756
2769
  }
2757
2770
  }
2758
2771
  const sessionsRoot = path32.join(appDir, "sessions");
2759
- const existing = db.prepare("SELECT session_id FROM agent_sessions").all();
2760
- const seen = new Set(existing.map((r) => r.session_id));
2761
2772
  await walkSessionJsonFiles(sessionsRoot, async (absPath) => {
2762
2773
  const sessionId = path32.basename(absPath, ".json");
2763
- if (!sessionId || seen.has(sessionId)) return;
2764
- seen.add(sessionId);
2774
+ if (!sessionId || store2.sessions[sessionId]) return;
2765
2775
  await insertFromPath(sessionId, absPath);
2766
2776
  });
2767
- db.pragma(`user_version = ${SCHEMA_VERSION}`);
2768
- }
2769
- function applySchema(db) {
2770
- db.exec(`
2771
- CREATE TABLE IF NOT EXISTS agent_sessions (
2772
- session_id TEXT PRIMARY KEY NOT NULL,
2773
- relative_path TEXT NOT NULL,
2774
- created_at TEXT NOT NULL,
2775
- updated_at TEXT NOT NULL,
2776
- preview TEXT NOT NULL DEFAULT '(no messages)'
2777
- );
2778
- CREATE INDEX IF NOT EXISTS idx_agent_sessions_updated
2779
- ON agent_sessions(updated_at DESC);
2780
- `);
2777
+ }
2778
+ async function loadStoreFromDisk(appDir) {
2779
+ try {
2780
+ const raw = await fs27.readFile(getSessionIndexPath(appDir), "utf-8");
2781
+ const parsed = JSON.parse(raw);
2782
+ if (parsed.version === 1 && parsed.sessions && typeof parsed.sessions === "object") {
2783
+ return { version: 1, sessions: { ...parsed.sessions } };
2784
+ }
2785
+ } catch {
2786
+ }
2787
+ return emptyStore();
2781
2788
  }
2782
2789
  async function ensureSessionIndexDb(appDir = getPreferredAppDir()) {
2783
- if (dbInstance && dbAppDir === appDir) {
2784
- return dbInstance;
2790
+ if (storeCache && storeAppDir === appDir) {
2791
+ return;
2785
2792
  }
2786
- if (!migratePromise || dbAppDir !== appDir) {
2787
- migratePromise = (async () => {
2788
- if (dbInstance) {
2789
- try {
2790
- dbInstance.close();
2791
- } catch {
2793
+ if (!loadPromise || storeAppDir !== appDir) {
2794
+ loadPromise = (async () => {
2795
+ const store2 = await loadStoreFromDisk(appDir);
2796
+ if (Object.keys(store2.sessions).length === 0) {
2797
+ await migrateLegacyIndex(store2, appDir);
2798
+ if (Object.keys(store2.sessions).length > 0) {
2799
+ await persistStore(store2, appDir);
2792
2800
  }
2793
- dbInstance = null;
2794
2801
  }
2795
- const BetterSqlite3 = loadSqlite();
2796
- const dbPath = getSessionDbPath(appDir);
2797
- mkdirSync3(path32.dirname(dbPath), { recursive: true });
2798
- const db = new BetterSqlite3(dbPath);
2799
- db.pragma("journal_mode = WAL");
2800
- applySchema(db);
2801
- const version = db.pragma("user_version", { simple: true });
2802
- if (version < SCHEMA_VERSION) {
2803
- await runMigrationV1(db, appDir);
2804
- }
2805
- dbInstance = db;
2806
- dbAppDir = appDir;
2802
+ storeCache = store2;
2803
+ storeAppDir = appDir;
2807
2804
  })();
2808
2805
  }
2809
- await migratePromise;
2810
- return dbInstance;
2806
+ await loadPromise;
2811
2807
  }
2812
2808
  async function upsertSessionIndexRow(row, appDir = getPreferredAppDir()) {
2813
- const db = await ensureSessionIndexDb(appDir);
2814
- const stmt = db.prepare(`
2815
- INSERT INTO agent_sessions (session_id, relative_path, created_at, updated_at, preview)
2816
- VALUES (@sessionId, @relativePath, @createdAt, @updatedAt, @preview)
2817
- ON CONFLICT(session_id) DO UPDATE SET
2818
- relative_path = excluded.relative_path,
2819
- updated_at = excluded.updated_at,
2820
- preview = excluded.preview
2821
- `);
2822
- stmt.run({
2823
- sessionId: row.sessionId,
2824
- relativePath: normalizeRelativePath(row.relativePath),
2825
- createdAt: row.createdAt,
2826
- updatedAt: row.updatedAt,
2827
- preview: row.preview
2828
- });
2809
+ await ensureSessionIndexDb(appDir);
2810
+ const store2 = storeCache;
2811
+ upsertIntoStore(store2, row);
2812
+ await persistStore(store2, appDir);
2829
2813
  }
2830
2814
  async function getSessionPathFromIndex(sessionId, appDir = getPreferredAppDir()) {
2831
- const db = await ensureSessionIndexDb(appDir);
2832
- const row = db.prepare("SELECT relative_path FROM agent_sessions WHERE session_id = ?").get(sessionId);
2833
- return row?.relative_path?.replace(/\//g, path32.sep) ?? null;
2815
+ await ensureSessionIndexDb(appDir);
2816
+ const entry = storeCache?.sessions[sessionId];
2817
+ return entry?.relativePath?.replace(/\//g, path32.sep) ?? null;
2834
2818
  }
2835
2819
  async function listSessionsFromIndex(limit = 50, appDir = getPreferredAppDir()) {
2836
- const db = await ensureSessionIndexDb(appDir);
2837
- const rows = db.prepare(
2838
- `SELECT session_id, relative_path, created_at, updated_at, preview
2839
- FROM agent_sessions
2840
- ORDER BY updated_at DESC
2841
- LIMIT ?`
2842
- ).all(limit);
2843
- return rows.map((r) => ({
2844
- sessionId: r.session_id,
2845
- relativePath: r.relative_path.replace(/\//g, path32.sep),
2846
- createdAt: r.created_at,
2847
- updatedAt: r.updated_at,
2848
- preview: r.preview
2849
- }));
2820
+ await ensureSessionIndexDb(appDir);
2821
+ const sessions = storeCache?.sessions ?? {};
2822
+ return Object.entries(sessions).map(([sessionId, row]) => ({
2823
+ sessionId,
2824
+ relativePath: row.relativePath.replace(/\//g, path32.sep),
2825
+ createdAt: row.createdAt,
2826
+ updatedAt: row.updatedAt,
2827
+ preview: row.preview
2828
+ })).sort((a, b) => Date.parse(b.updatedAt) - Date.parse(a.updatedAt)).slice(0, limit);
2850
2829
  }
2851
- var AGENT_SESSION_PATHS_JSONL, BLUMA_SESSION_DB_FILE, SCHEMA_VERSION, dbInstance, dbAppDir, migratePromise;
2830
+ var AGENT_SESSION_PATHS_JSONL, SESSION_INDEX_FILE, storeCache, storeAppDir, loadPromise;
2852
2831
  var init_session_index_db = __esm({
2853
2832
  "src/app/agent/session_manager/session_index_db.ts"() {
2854
2833
  "use strict";
2855
2834
  init_bluma_app_dir();
2856
2835
  AGENT_SESSION_PATHS_JSONL = "agent_session_paths.jsonl";
2857
- BLUMA_SESSION_DB_FILE = "bluma.sqlite";
2858
- SCHEMA_VERSION = 1;
2859
- dbInstance = null;
2860
- dbAppDir = null;
2861
- migratePromise = null;
2836
+ SESSION_INDEX_FILE = "session_index.json";
2837
+ storeCache = null;
2838
+ storeAppDir = null;
2839
+ loadPromise = null;
2862
2840
  }
2863
2841
  });
2864
2842
 
@@ -39031,7 +39009,7 @@ import { promisify as promisify2 } from "util";
39031
39009
 
39032
39010
  // src/app/utils/clipboardNative.ts
39033
39011
  import { existsSync as existsSync7 } from "fs";
39034
- import { createRequire as createRequire2 } from "module";
39012
+ import { createRequire } from "module";
39035
39013
  import { dirname as dirname4, join as join13 } from "path";
39036
39014
  import { fileURLToPath as fileURLToPath6 } from "url";
39037
39015
  var __dirname;
@@ -39079,7 +39057,7 @@ function getNativeModule() {
39079
39057
  throw loadError;
39080
39058
  }
39081
39059
  try {
39082
- const require2 = createRequire2(import.meta.url);
39060
+ const require2 = createRequire(import.meta.url);
39083
39061
  const mod = require2(nativePath);
39084
39062
  nativeModule = mod;
39085
39063
  return nativeModule;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nomad-e/bluma-cli",
3
- "version": "0.26.0",
3
+ "version": "0.26.1",
4
4
  "description": "BluMa independent agent for automation and advanced software engineering.",
5
5
  "author": "Alex Fonseca",
6
6
  "license": "Apache-2.0",
@@ -11,7 +11,6 @@
11
11
  "@babel/preset-env": "^7.28.0",
12
12
  "@babel/preset-react": "^7.27.1",
13
13
  "@babel/preset-typescript": "^7.27.1",
14
- "@types/better-sqlite3": "^7.6.13",
15
14
  "@types/diff": "^7.0.2",
16
15
  "@types/glob": "^8.1.0",
17
16
  "@types/jest": "^30.0.0",
@@ -75,7 +74,6 @@
75
74
  "@types/react-dom": "^19.2.3",
76
75
  "auto-bind": "^5.0.1",
77
76
  "axios": "^1.16.0",
78
- "better-sqlite3": "^11.10.0",
79
77
  "bidi-js": "^1.0.3",
80
78
  "chalk": "^5.5.0",
81
79
  "class-variance-authority": "^0.7.1",