devrage 0.5.6 → 0.5.7

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/dist/cli.js CHANGED
@@ -825,6 +825,97 @@ import { existsSync as existsSync2 } from "node:fs";
825
825
  import { readdir as readdir5 } from "node:fs/promises";
826
826
  import { homedir as homedir5 } from "node:os";
827
827
  import { join as join5 } from "node:path";
828
+
829
+ // src/adapters/sqlite.ts
830
+ async function openReadonlySqliteDatabase(dbPath) {
831
+ const requestedDriver = process.env["DEVRAGE_SQLITE_DRIVER"];
832
+ if (requestedDriver) {
833
+ const loader = driverLoader(requestedDriver);
834
+ if (!loader) {
835
+ return null;
836
+ }
837
+ try {
838
+ return await loader(dbPath);
839
+ } catch {
840
+ return null;
841
+ }
842
+ }
843
+ const loaders = isBunRuntime() ? [openWithBunSqlite, openWithNodeSqlite, openWithBetterSqlite3] : [openWithNodeSqlite, openWithBetterSqlite3];
844
+ for (const loader of loaders) {
845
+ try {
846
+ return await loader(dbPath);
847
+ } catch {
848
+ continue;
849
+ }
850
+ }
851
+ return null;
852
+ }
853
+ function driverLoader(driver) {
854
+ switch (driver) {
855
+ case "bun":
856
+ case "bun:sqlite":
857
+ return openWithBunSqlite;
858
+ case "node":
859
+ case "node:sqlite":
860
+ return openWithNodeSqlite;
861
+ case "better-sqlite3":
862
+ return openWithBetterSqlite3;
863
+ default:
864
+ return null;
865
+ }
866
+ }
867
+ function isBunRuntime() {
868
+ return Boolean(process.versions["bun"]);
869
+ }
870
+ async function openWithBunSqlite(dbPath) {
871
+ const specifier = "bun:sqlite";
872
+ const sqlite = await import(specifier);
873
+ const db = new sqlite.Database(dbPath, { readonly: true, create: false });
874
+ return {
875
+ prepare(sql) {
876
+ const prepare = db.prepare ?? db.query;
877
+ return prepare.call(db, sql);
878
+ },
879
+ close() {
880
+ db.close();
881
+ }
882
+ };
883
+ }
884
+ async function openWithNodeSqlite(dbPath) {
885
+ const sqlite = await importNodeSqlite();
886
+ return new sqlite.DatabaseSync(dbPath, { open: true, readOnly: true, timeout: 5e3 });
887
+ }
888
+ async function openWithBetterSqlite3(dbPath) {
889
+ const BetterSqlite3 = await import("better-sqlite3");
890
+ const Ctor = BetterSqlite3.default ?? BetterSqlite3;
891
+ return new Ctor(dbPath, {
892
+ readonly: true,
893
+ fileMustExist: true
894
+ });
895
+ }
896
+ async function importNodeSqlite() {
897
+ const originalEmitWarning = process.emitWarning;
898
+ process.emitWarning = ((warning, ...args) => {
899
+ const message = typeof warning === "string" ? warning : warning.message;
900
+ const type = typeof args[0] === "string" ? args[0] : void 0;
901
+ if (message === "SQLite is an experimental feature and might change at any time" && type === "ExperimentalWarning") {
902
+ return;
903
+ }
904
+ originalEmitWarning(warning, ...args);
905
+ });
906
+ try {
907
+ const specifier = "node:sqlite";
908
+ const sqlite = await import(specifier);
909
+ if (typeof sqlite.DatabaseSync !== "function") {
910
+ throw new Error("node:sqlite DatabaseSync is unavailable");
911
+ }
912
+ return sqlite;
913
+ } finally {
914
+ process.emitWarning = originalEmitWarning;
915
+ }
916
+ }
917
+
918
+ // src/adapters/cursor.ts
828
919
  var CANDIDATE_KEY_PREFIXES = [
829
920
  "bubbleId:",
830
921
  "composerData:",
@@ -978,16 +1069,7 @@ async function* parseCursorUsageStore(store, options) {
978
1069
  }
979
1070
  }
980
1071
  async function openCursorDb(dbPath) {
981
- try {
982
- const BetterSqlite3 = await import("better-sqlite3");
983
- const Ctor = BetterSqlite3.default ?? BetterSqlite3;
984
- return new Ctor(
985
- dbPath,
986
- { readonly: true }
987
- );
988
- } catch {
989
- return null;
990
- }
1072
+ return openReadonlySqliteDatabase(dbPath);
991
1073
  }
992
1074
  function readStateRows(db) {
993
1075
  const rows = [];
@@ -1048,6 +1130,12 @@ function decodeStateValue(value) {
1048
1130
  if (Buffer.isBuffer(value)) {
1049
1131
  return value.toString("utf-8");
1050
1132
  }
1133
+ if (value instanceof Uint8Array) {
1134
+ return Buffer.from(value).toString("utf-8");
1135
+ }
1136
+ if (ArrayBuffer.isView(value)) {
1137
+ return Buffer.from(value.buffer, value.byteOffset, value.byteLength).toString("utf-8");
1138
+ }
1051
1139
  return null;
1052
1140
  }
1053
1141
  function extractCursorMessages(root, rowKey) {
@@ -1410,17 +1498,11 @@ async function openOpencodeDb() {
1410
1498
  if (!dbPath) {
1411
1499
  return null;
1412
1500
  }
1413
- try {
1414
- const BetterSqlite3 = await import("better-sqlite3");
1415
- const Ctor = BetterSqlite3.default ?? BetterSqlite3;
1416
- return new Ctor(
1417
- dbPath,
1418
- { readonly: true }
1419
- );
1420
- } catch {
1421
- console.warn("devrage: better-sqlite3 not available, skipping OpenCode sessions");
1422
- return null;
1501
+ const db = await openReadonlySqliteDatabase(dbPath);
1502
+ if (!db) {
1503
+ console.warn("devrage: SQLite support not available, skipping OpenCode sessions");
1423
1504
  }
1505
+ return db;
1424
1506
  }
1425
1507
  function* queryUserMessages(db, options) {
1426
1508
  let query = `
@@ -1763,16 +1845,7 @@ function resolveHomePath(value) {
1763
1845
  return isAbsolute(value) ? value : resolve(value);
1764
1846
  }
1765
1847
  async function openT3Db(dbPath) {
1766
- try {
1767
- const BetterSqlite3 = await import("better-sqlite3");
1768
- const Ctor = BetterSqlite3.default ?? BetterSqlite3;
1769
- return new Ctor(
1770
- dbPath,
1771
- { readonly: true, fileMustExist: true }
1772
- );
1773
- } catch {
1774
- return null;
1775
- }
1848
+ return openReadonlySqliteDatabase(dbPath);
1776
1849
  }
1777
1850
  function* queryUserMessages2(db, location, options) {
1778
1851
  if (!hasColumns(db, "projection_thread_messages", ["thread_id", "role", "text", "created_at"])) {
@@ -2190,21 +2263,10 @@ async function* parseAgentThreads(dbDir, _options) {
2190
2263
  if (dbFiles.length === 0) {
2191
2264
  return;
2192
2265
  }
2193
- let Database;
2194
- try {
2195
- const mod = await import("better-sqlite3");
2196
- Database = mod.default ?? mod;
2197
- } catch {
2198
- return;
2199
- }
2200
2266
  for (const dbFile of dbFiles) {
2201
2267
  const dbPath = join9(dbDir, dbFile);
2202
- let db;
2203
- try {
2204
- db = new Database(dbPath, {
2205
- readonly: true
2206
- });
2207
- } catch {
2268
+ const db = await openReadonlySqliteDatabase(dbPath);
2269
+ if (!db) {
2208
2270
  continue;
2209
2271
  }
2210
2272
  try {
@@ -2214,14 +2276,12 @@ async function* parseAgentThreads(dbDir, _options) {
2214
2276
  (t) => t === "messages" || t === "thread_messages" || t.includes("message")
2215
2277
  );
2216
2278
  if (!msgTable) {
2217
- db.close();
2218
2279
  continue;
2219
2280
  }
2220
2281
  const columns = db.prepare(`PRAGMA table_info("${msgTable}")`).all();
2221
2282
  const colNames = columns.map((c2) => c2.name);
2222
2283
  const hasRole = colNames.includes("role");
2223
2284
  if (!hasRole) {
2224
- db.close();
2225
2285
  continue;
2226
2286
  }
2227
2287
  const contentCol = colNames.includes("content") ? "content" : colNames.includes("body") ? "body" : "text";
@@ -3667,7 +3727,7 @@ async function main() {
3667
3727
  process.exit(0);
3668
3728
  }
3669
3729
  if (command === "--version") {
3670
- console.log("0.5.6");
3730
+ console.log("0.5.7");
3671
3731
  process.exit(0);
3672
3732
  }
3673
3733
  const parsed = parseCommand(args);