@learnrudi/cli 1.0.0 → 1.2.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/dist/index.cjs +625 -39
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -223,7 +223,7 @@ async function fetchIndex(options = {}) {
|
|
|
223
223
|
const response = await fetch(url, {
|
|
224
224
|
headers: {
|
|
225
225
|
"Accept": "application/json",
|
|
226
|
-
"User-Agent": "
|
|
226
|
+
"User-Agent": "rudi-cli/2.0"
|
|
227
227
|
}
|
|
228
228
|
});
|
|
229
229
|
if (!response.ok) {
|
|
@@ -401,7 +401,7 @@ async function downloadRuntime(runtime, version, destPath, options = {}) {
|
|
|
401
401
|
try {
|
|
402
402
|
const response = await fetch(url, {
|
|
403
403
|
headers: {
|
|
404
|
-
"User-Agent": "
|
|
404
|
+
"User-Agent": "rudi-cli/2.0",
|
|
405
405
|
"Accept": "application/octet-stream"
|
|
406
406
|
}
|
|
407
407
|
});
|
|
@@ -470,7 +470,7 @@ async function downloadTool(toolName, destPath, options = {}) {
|
|
|
470
470
|
try {
|
|
471
471
|
const response = await fetch(url, {
|
|
472
472
|
headers: {
|
|
473
|
-
"User-Agent": "
|
|
473
|
+
"User-Agent": "rudi-cli/2.0",
|
|
474
474
|
"Accept": "application/octet-stream"
|
|
475
475
|
}
|
|
476
476
|
});
|
|
@@ -522,7 +522,7 @@ async function downloadTool(toolName, destPath, options = {}) {
|
|
|
522
522
|
try {
|
|
523
523
|
const response = await fetch(upstreamUrl, {
|
|
524
524
|
headers: {
|
|
525
|
-
"User-Agent": "
|
|
525
|
+
"User-Agent": "rudi-cli/2.0",
|
|
526
526
|
"Accept": "application/octet-stream"
|
|
527
527
|
}
|
|
528
528
|
});
|
|
@@ -620,10 +620,10 @@ async function loadToolManifest(toolName) {
|
|
|
620
620
|
}
|
|
621
621
|
}
|
|
622
622
|
try {
|
|
623
|
-
const url = `https://raw.githubusercontent.com/
|
|
623
|
+
const url = `https://raw.githubusercontent.com/learn-rudi/registry/main/catalog/binaries/${toolName}.json`;
|
|
624
624
|
const response = await fetch(url, {
|
|
625
625
|
headers: {
|
|
626
|
-
"User-Agent": "
|
|
626
|
+
"User-Agent": "rudi-cli/2.0",
|
|
627
627
|
"Accept": "application/json"
|
|
628
628
|
}
|
|
629
629
|
});
|
|
@@ -683,13 +683,13 @@ var init_src2 = __esm({
|
|
|
683
683
|
import_path2 = __toESM(require("path"), 1);
|
|
684
684
|
import_crypto = __toESM(require("crypto"), 1);
|
|
685
685
|
init_src();
|
|
686
|
-
DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/
|
|
687
|
-
RUNTIMES_DOWNLOAD_BASE = "https://github.com/
|
|
686
|
+
DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/learn-rudi/registry/main/index.json";
|
|
687
|
+
RUNTIMES_DOWNLOAD_BASE = "https://github.com/learn-rudi/registry/releases/download";
|
|
688
688
|
CACHE_TTL = 24 * 60 * 60 * 1e3;
|
|
689
689
|
LOCAL_REGISTRY_PATHS = process.env.USE_LOCAL_REGISTRY === "true" ? [
|
|
690
690
|
import_path2.default.join(process.cwd(), "registry", "index.json"),
|
|
691
691
|
import_path2.default.join(process.cwd(), "..", "registry", "index.json"),
|
|
692
|
-
"/Users/hoff/dev/
|
|
692
|
+
"/Users/hoff/dev/RUDI/registry/index.json"
|
|
693
693
|
] : [];
|
|
694
694
|
PACKAGE_KINDS2 = ["stack", "prompt", "runtime", "binary", "agent"];
|
|
695
695
|
KIND_PLURALS = {
|
|
@@ -14830,6 +14830,9 @@ COMMANDS
|
|
|
14830
14830
|
db stats Show database statistics
|
|
14831
14831
|
db search <query> Search conversation history
|
|
14832
14832
|
|
|
14833
|
+
import sessions Import sessions from AI providers (claude, codex, gemini)
|
|
14834
|
+
import status Show import status for all providers
|
|
14835
|
+
|
|
14833
14836
|
logs [options] Query agent visibility logs
|
|
14834
14837
|
|
|
14835
14838
|
doctor Check system health and configuration
|
|
@@ -14958,10 +14961,47 @@ COMMANDS
|
|
|
14958
14961
|
stats Show usage statistics
|
|
14959
14962
|
search <query> Search conversation history
|
|
14960
14963
|
init Initialize or migrate database
|
|
14964
|
+
path Show database file path
|
|
14965
|
+
reset Delete all data (requires --force)
|
|
14966
|
+
vacuum Compact database and reclaim space
|
|
14967
|
+
backup [file] Create database backup
|
|
14968
|
+
prune [days] Delete sessions older than N days (default: 90)
|
|
14969
|
+
tables Show table row counts
|
|
14970
|
+
|
|
14971
|
+
OPTIONS
|
|
14972
|
+
--force Required for destructive operations
|
|
14973
|
+
--dry-run Preview without making changes
|
|
14974
|
+
--json Output as JSON
|
|
14961
14975
|
|
|
14962
14976
|
EXAMPLES
|
|
14963
14977
|
rudi db stats
|
|
14964
14978
|
rudi db search "authentication bug"
|
|
14979
|
+
rudi db reset --force
|
|
14980
|
+
rudi db vacuum
|
|
14981
|
+
rudi db backup ~/backups/rudi.db
|
|
14982
|
+
rudi db prune 30 --dry-run
|
|
14983
|
+
rudi db tables
|
|
14984
|
+
`,
|
|
14985
|
+
import: `
|
|
14986
|
+
rudi import - Import sessions from AI providers
|
|
14987
|
+
|
|
14988
|
+
USAGE
|
|
14989
|
+
rudi import <command> [options]
|
|
14990
|
+
|
|
14991
|
+
COMMANDS
|
|
14992
|
+
sessions [provider] Import sessions from provider (claude, codex, gemini, or all)
|
|
14993
|
+
status Show import status for all providers
|
|
14994
|
+
|
|
14995
|
+
OPTIONS
|
|
14996
|
+
--dry-run Show what would be imported without making changes
|
|
14997
|
+
--max-age=DAYS Only import sessions newer than N days
|
|
14998
|
+
--verbose Show detailed progress
|
|
14999
|
+
|
|
15000
|
+
EXAMPLES
|
|
15001
|
+
rudi import sessions Import from all providers
|
|
15002
|
+
rudi import sessions claude Import only Claude sessions
|
|
15003
|
+
rudi import sessions --dry-run Preview without importing
|
|
15004
|
+
rudi import status Check what's available to import
|
|
14965
15005
|
`,
|
|
14966
15006
|
doctor: `
|
|
14967
15007
|
rudi doctor - System health check
|
|
@@ -17214,6 +17254,10 @@ function promptSecret(prompt) {
|
|
|
17214
17254
|
});
|
|
17215
17255
|
}
|
|
17216
17256
|
|
|
17257
|
+
// src/commands/db.js
|
|
17258
|
+
var import_fs10 = require("fs");
|
|
17259
|
+
var import_path10 = require("path");
|
|
17260
|
+
|
|
17217
17261
|
// ../packages/db/src/index.js
|
|
17218
17262
|
var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
17219
17263
|
var import_path9 = __toESM(require("path"), 1);
|
|
@@ -17950,7 +17994,6 @@ function getToolsUsage(db3) {
|
|
|
17950
17994
|
}
|
|
17951
17995
|
|
|
17952
17996
|
// ../packages/db/src/index.js
|
|
17953
|
-
var PROMPT_STACK_HOME2 = PATHS.home;
|
|
17954
17997
|
var DB_PATH = PATHS.dbFile;
|
|
17955
17998
|
var db = null;
|
|
17956
17999
|
function getDb(options = {}) {
|
|
@@ -18013,6 +18056,21 @@ async function cmdDb(args, flags) {
|
|
|
18013
18056
|
case "path":
|
|
18014
18057
|
console.log(getDbPath());
|
|
18015
18058
|
break;
|
|
18059
|
+
case "reset":
|
|
18060
|
+
await dbReset(flags);
|
|
18061
|
+
break;
|
|
18062
|
+
case "vacuum":
|
|
18063
|
+
dbVacuum(flags);
|
|
18064
|
+
break;
|
|
18065
|
+
case "backup":
|
|
18066
|
+
dbBackup(args.slice(1), flags);
|
|
18067
|
+
break;
|
|
18068
|
+
case "prune":
|
|
18069
|
+
dbPrune(args.slice(1), flags);
|
|
18070
|
+
break;
|
|
18071
|
+
case "tables":
|
|
18072
|
+
dbTables(flags);
|
|
18073
|
+
break;
|
|
18016
18074
|
default:
|
|
18017
18075
|
console.log(`
|
|
18018
18076
|
rudi db - Database operations
|
|
@@ -18022,11 +18080,24 @@ COMMANDS
|
|
|
18022
18080
|
search <query> Search conversation history
|
|
18023
18081
|
init Initialize or migrate database
|
|
18024
18082
|
path Show database file path
|
|
18083
|
+
reset Delete all data (requires --force)
|
|
18084
|
+
vacuum Compact database and reclaim space
|
|
18085
|
+
backup [file] Create database backup
|
|
18086
|
+
prune [days] Delete sessions older than N days (default: 90)
|
|
18087
|
+
tables Show table row counts
|
|
18088
|
+
|
|
18089
|
+
OPTIONS
|
|
18090
|
+
--force Required for destructive operations
|
|
18091
|
+
--dry-run Preview without making changes
|
|
18025
18092
|
|
|
18026
18093
|
EXAMPLES
|
|
18027
18094
|
rudi db stats
|
|
18028
18095
|
rudi db search "authentication bug"
|
|
18029
18096
|
rudi db init
|
|
18097
|
+
rudi db reset --force
|
|
18098
|
+
rudi db vacuum
|
|
18099
|
+
rudi db backup ~/backups/rudi-backup.db
|
|
18100
|
+
rudi db prune 30 --dry-run
|
|
18030
18101
|
`);
|
|
18031
18102
|
}
|
|
18032
18103
|
}
|
|
@@ -18153,9 +18224,521 @@ function truncate(str, len) {
|
|
|
18153
18224
|
function stripHighlight(str) {
|
|
18154
18225
|
return str.replace(/>>>/g, "").replace(/<<</g, "");
|
|
18155
18226
|
}
|
|
18227
|
+
async function dbReset(flags) {
|
|
18228
|
+
if (!isDatabaseInitialized()) {
|
|
18229
|
+
console.log("Database not initialized.");
|
|
18230
|
+
return;
|
|
18231
|
+
}
|
|
18232
|
+
if (!flags.force) {
|
|
18233
|
+
console.error("This will delete ALL data from the database.");
|
|
18234
|
+
console.error("Use --force to confirm.");
|
|
18235
|
+
process.exit(1);
|
|
18236
|
+
}
|
|
18237
|
+
const db3 = getDb();
|
|
18238
|
+
const dbPath = getDbPath();
|
|
18239
|
+
const tables = ["sessions", "turns", "tool_calls", "projects"];
|
|
18240
|
+
const counts = {};
|
|
18241
|
+
for (const table of tables) {
|
|
18242
|
+
try {
|
|
18243
|
+
const row = db3.prepare(`SELECT COUNT(*) as count FROM ${table}`).get();
|
|
18244
|
+
counts[table] = row.count;
|
|
18245
|
+
} catch (e) {
|
|
18246
|
+
counts[table] = 0;
|
|
18247
|
+
}
|
|
18248
|
+
}
|
|
18249
|
+
console.log("Deleting all data...");
|
|
18250
|
+
console.log("\u2500".repeat(40));
|
|
18251
|
+
const deleteOrder = ["tool_calls", "turns", "sessions", "projects"];
|
|
18252
|
+
for (const table of deleteOrder) {
|
|
18253
|
+
try {
|
|
18254
|
+
db3.prepare(`DELETE FROM ${table}`).run();
|
|
18255
|
+
console.log(` ${table}: ${counts[table]} rows deleted`);
|
|
18256
|
+
} catch (e) {
|
|
18257
|
+
}
|
|
18258
|
+
}
|
|
18259
|
+
try {
|
|
18260
|
+
db3.prepare("DELETE FROM turns_fts").run();
|
|
18261
|
+
console.log(" turns_fts: cleared");
|
|
18262
|
+
} catch (e) {
|
|
18263
|
+
}
|
|
18264
|
+
console.log("\u2500".repeat(40));
|
|
18265
|
+
console.log("Database reset complete.");
|
|
18266
|
+
console.log(`Path: ${dbPath}`);
|
|
18267
|
+
}
|
|
18268
|
+
function dbVacuum(flags) {
|
|
18269
|
+
if (!isDatabaseInitialized()) {
|
|
18270
|
+
console.log("Database not initialized.");
|
|
18271
|
+
return;
|
|
18272
|
+
}
|
|
18273
|
+
const dbPath = getDbPath();
|
|
18274
|
+
const sizeBefore = getDbSize();
|
|
18275
|
+
console.log("Compacting database...");
|
|
18276
|
+
console.log(` Before: ${formatBytes(sizeBefore)}`);
|
|
18277
|
+
const db3 = getDb();
|
|
18278
|
+
db3.exec("VACUUM");
|
|
18279
|
+
const sizeAfter = getDbSize();
|
|
18280
|
+
const saved = sizeBefore - sizeAfter;
|
|
18281
|
+
console.log(` After: ${formatBytes(sizeAfter)}`);
|
|
18282
|
+
if (saved > 0) {
|
|
18283
|
+
console.log(` Saved: ${formatBytes(saved)} (${(saved / sizeBefore * 100).toFixed(1)}%)`);
|
|
18284
|
+
} else {
|
|
18285
|
+
console.log(" No space reclaimed.");
|
|
18286
|
+
}
|
|
18287
|
+
}
|
|
18288
|
+
function dbBackup(args, flags) {
|
|
18289
|
+
if (!isDatabaseInitialized()) {
|
|
18290
|
+
console.log("Database not initialized.");
|
|
18291
|
+
return;
|
|
18292
|
+
}
|
|
18293
|
+
const dbPath = getDbPath();
|
|
18294
|
+
let backupPath = args[0];
|
|
18295
|
+
if (!backupPath) {
|
|
18296
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
18297
|
+
backupPath = (0, import_path10.join)((0, import_path10.dirname)(dbPath), `rudi-backup-${timestamp}.db`);
|
|
18298
|
+
}
|
|
18299
|
+
if (backupPath.startsWith("~")) {
|
|
18300
|
+
backupPath = (0, import_path10.join)(process.env.HOME || "", backupPath.slice(1));
|
|
18301
|
+
}
|
|
18302
|
+
if ((0, import_fs10.existsSync)(backupPath) && !flags.force) {
|
|
18303
|
+
console.error(`Backup file already exists: ${backupPath}`);
|
|
18304
|
+
console.error("Use --force to overwrite.");
|
|
18305
|
+
process.exit(1);
|
|
18306
|
+
}
|
|
18307
|
+
console.log("Creating backup...");
|
|
18308
|
+
console.log(` Source: ${dbPath}`);
|
|
18309
|
+
console.log(` Dest: ${backupPath}`);
|
|
18310
|
+
try {
|
|
18311
|
+
const db3 = getDb();
|
|
18312
|
+
db3.exec("VACUUM INTO ?", [backupPath]);
|
|
18313
|
+
} catch (e) {
|
|
18314
|
+
(0, import_fs10.copyFileSync)(dbPath, backupPath);
|
|
18315
|
+
}
|
|
18316
|
+
const size = getDbSize();
|
|
18317
|
+
console.log(` Size: ${formatBytes(size)}`);
|
|
18318
|
+
console.log("Backup complete.");
|
|
18319
|
+
}
|
|
18320
|
+
function dbPrune(args, flags) {
|
|
18321
|
+
if (!isDatabaseInitialized()) {
|
|
18322
|
+
console.log("Database not initialized.");
|
|
18323
|
+
return;
|
|
18324
|
+
}
|
|
18325
|
+
const days = parseInt(args[0]) || 90;
|
|
18326
|
+
const dryRun = flags["dry-run"] || flags.dryRun;
|
|
18327
|
+
const cutoffDate = new Date(Date.now() - days * 24 * 60 * 60 * 1e3).toISOString();
|
|
18328
|
+
const db3 = getDb();
|
|
18329
|
+
const toDelete = db3.prepare(`
|
|
18330
|
+
SELECT COUNT(*) as count FROM sessions
|
|
18331
|
+
WHERE last_active_at < ? OR (last_active_at IS NULL AND created_at < ?)
|
|
18332
|
+
`).get(cutoffDate, cutoffDate);
|
|
18333
|
+
const total = db3.prepare("SELECT COUNT(*) as count FROM sessions").get();
|
|
18334
|
+
console.log(`Sessions older than ${days} days: ${toDelete.count}`);
|
|
18335
|
+
console.log(`Total sessions: ${total.count}`);
|
|
18336
|
+
console.log(`Cutoff date: ${cutoffDate.slice(0, 10)}`);
|
|
18337
|
+
if (toDelete.count === 0) {
|
|
18338
|
+
console.log("\nNo sessions to prune.");
|
|
18339
|
+
return;
|
|
18340
|
+
}
|
|
18341
|
+
if (dryRun) {
|
|
18342
|
+
console.log("\n(Dry run - no changes made)");
|
|
18343
|
+
return;
|
|
18344
|
+
}
|
|
18345
|
+
if (!flags.force) {
|
|
18346
|
+
console.error(`
|
|
18347
|
+
This will delete ${toDelete.count} sessions and their turns.`);
|
|
18348
|
+
console.error("Use --force to confirm, or --dry-run to preview.");
|
|
18349
|
+
process.exit(1);
|
|
18350
|
+
}
|
|
18351
|
+
console.log("\nDeleting old sessions...");
|
|
18352
|
+
const sessionIds = db3.prepare(`
|
|
18353
|
+
SELECT id FROM sessions
|
|
18354
|
+
WHERE last_active_at < ? OR (last_active_at IS NULL AND created_at < ?)
|
|
18355
|
+
`).all(cutoffDate, cutoffDate).map((r) => r.id);
|
|
18356
|
+
let turnsDeleted = 0;
|
|
18357
|
+
let toolCallsDeleted = 0;
|
|
18358
|
+
for (const sessionId of sessionIds) {
|
|
18359
|
+
const turnIds = db3.prepare("SELECT id FROM turns WHERE session_id = ?").all(sessionId).map((r) => r.id);
|
|
18360
|
+
for (const turnId of turnIds) {
|
|
18361
|
+
const result = db3.prepare("DELETE FROM tool_calls WHERE turn_id = ?").run(turnId);
|
|
18362
|
+
toolCallsDeleted += result.changes;
|
|
18363
|
+
}
|
|
18364
|
+
const turnResult = db3.prepare("DELETE FROM turns WHERE session_id = ?").run(sessionId);
|
|
18365
|
+
turnsDeleted += turnResult.changes;
|
|
18366
|
+
}
|
|
18367
|
+
const sessionResult = db3.prepare(`
|
|
18368
|
+
DELETE FROM sessions
|
|
18369
|
+
WHERE last_active_at < ? OR (last_active_at IS NULL AND created_at < ?)
|
|
18370
|
+
`).run(cutoffDate, cutoffDate);
|
|
18371
|
+
console.log(` Sessions deleted: ${sessionResult.changes}`);
|
|
18372
|
+
console.log(` Turns deleted: ${turnsDeleted}`);
|
|
18373
|
+
console.log(` Tool calls deleted: ${toolCallsDeleted}`);
|
|
18374
|
+
console.log('\nPrune complete. Run "rudi db vacuum" to reclaim disk space.');
|
|
18375
|
+
}
|
|
18376
|
+
function dbTables(flags) {
|
|
18377
|
+
if (!isDatabaseInitialized()) {
|
|
18378
|
+
console.log("Database not initialized.");
|
|
18379
|
+
return;
|
|
18380
|
+
}
|
|
18381
|
+
const db3 = getDb();
|
|
18382
|
+
const tables = db3.prepare(`
|
|
18383
|
+
SELECT name FROM sqlite_master
|
|
18384
|
+
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
18385
|
+
ORDER BY name
|
|
18386
|
+
`).all();
|
|
18387
|
+
if (flags.json) {
|
|
18388
|
+
const result = {};
|
|
18389
|
+
for (const { name } of tables) {
|
|
18390
|
+
try {
|
|
18391
|
+
const row = db3.prepare(`SELECT COUNT(*) as count FROM "${name}"`).get();
|
|
18392
|
+
result[name] = row.count;
|
|
18393
|
+
} catch (e) {
|
|
18394
|
+
result[name] = -1;
|
|
18395
|
+
}
|
|
18396
|
+
}
|
|
18397
|
+
console.log(JSON.stringify(result, null, 2));
|
|
18398
|
+
return;
|
|
18399
|
+
}
|
|
18400
|
+
console.log("\nDatabase Tables");
|
|
18401
|
+
console.log("\u2550".repeat(40));
|
|
18402
|
+
let totalRows = 0;
|
|
18403
|
+
for (const { name } of tables) {
|
|
18404
|
+
try {
|
|
18405
|
+
const row = db3.prepare(`SELECT COUNT(*) as count FROM "${name}"`).get();
|
|
18406
|
+
console.log(` ${name.padEnd(25)} ${row.count.toLocaleString().padStart(10)}`);
|
|
18407
|
+
totalRows += row.count;
|
|
18408
|
+
} catch (e) {
|
|
18409
|
+
console.log(` ${name.padEnd(25)} ${"error".padStart(10)}`);
|
|
18410
|
+
}
|
|
18411
|
+
}
|
|
18412
|
+
console.log("\u2500".repeat(40));
|
|
18413
|
+
console.log(` ${"Total".padEnd(25)} ${totalRows.toLocaleString().padStart(10)}`);
|
|
18414
|
+
console.log(`
|
|
18415
|
+
Size: ${formatBytes(getDbSize())}`);
|
|
18416
|
+
}
|
|
18417
|
+
|
|
18418
|
+
// src/commands/import.js
|
|
18419
|
+
var import_fs11 = require("fs");
|
|
18420
|
+
var import_path11 = require("path");
|
|
18421
|
+
var import_os3 = require("os");
|
|
18422
|
+
var import_crypto2 = require("crypto");
|
|
18423
|
+
var PROVIDERS = {
|
|
18424
|
+
claude: {
|
|
18425
|
+
name: "Claude Code",
|
|
18426
|
+
baseDir: (0, import_path11.join)((0, import_os3.homedir)(), ".claude", "projects"),
|
|
18427
|
+
pattern: /\.jsonl$/
|
|
18428
|
+
},
|
|
18429
|
+
codex: {
|
|
18430
|
+
name: "Codex",
|
|
18431
|
+
baseDir: (0, import_path11.join)((0, import_os3.homedir)(), ".codex", "sessions"),
|
|
18432
|
+
pattern: /\.jsonl$/
|
|
18433
|
+
},
|
|
18434
|
+
gemini: {
|
|
18435
|
+
name: "Gemini",
|
|
18436
|
+
baseDir: (0, import_path11.join)((0, import_os3.homedir)(), ".gemini", "sessions"),
|
|
18437
|
+
pattern: /\.jsonl$/
|
|
18438
|
+
}
|
|
18439
|
+
};
|
|
18440
|
+
async function cmdImport(args, flags) {
|
|
18441
|
+
const subcommand = args[0];
|
|
18442
|
+
switch (subcommand) {
|
|
18443
|
+
case "sessions":
|
|
18444
|
+
await importSessions(args.slice(1), flags);
|
|
18445
|
+
break;
|
|
18446
|
+
case "status":
|
|
18447
|
+
showImportStatus(flags);
|
|
18448
|
+
break;
|
|
18449
|
+
default:
|
|
18450
|
+
console.log(`
|
|
18451
|
+
rudi import - Import data from AI agent providers
|
|
18452
|
+
|
|
18453
|
+
COMMANDS
|
|
18454
|
+
sessions [provider] Import sessions from provider (claude, codex, gemini, or all)
|
|
18455
|
+
status Show import status for all providers
|
|
18456
|
+
|
|
18457
|
+
OPTIONS
|
|
18458
|
+
--dry-run Show what would be imported without making changes
|
|
18459
|
+
--max-age=DAYS Only import sessions newer than N days
|
|
18460
|
+
--verbose Show detailed progress
|
|
18461
|
+
|
|
18462
|
+
EXAMPLES
|
|
18463
|
+
rudi import sessions # Import from all providers
|
|
18464
|
+
rudi import sessions claude # Import only Claude sessions
|
|
18465
|
+
rudi import sessions --dry-run # Preview without importing
|
|
18466
|
+
rudi import status # Check what's available to import
|
|
18467
|
+
`);
|
|
18468
|
+
}
|
|
18469
|
+
}
|
|
18470
|
+
async function importSessions(args, flags) {
|
|
18471
|
+
const providerArg = args[0] || "all";
|
|
18472
|
+
const dryRun = flags["dry-run"] || flags.dryRun;
|
|
18473
|
+
const verbose = flags.verbose;
|
|
18474
|
+
const maxAgeDays = flags["max-age"] ? parseInt(flags["max-age"]) : null;
|
|
18475
|
+
if (!isDatabaseInitialized()) {
|
|
18476
|
+
console.log("Initializing database...");
|
|
18477
|
+
initSchema();
|
|
18478
|
+
}
|
|
18479
|
+
const db3 = getDb();
|
|
18480
|
+
const providers = providerArg === "all" ? Object.keys(PROVIDERS) : [providerArg];
|
|
18481
|
+
for (const p of providers) {
|
|
18482
|
+
if (!PROVIDERS[p]) {
|
|
18483
|
+
console.error(`Unknown provider: ${p}`);
|
|
18484
|
+
console.error(`Available: ${Object.keys(PROVIDERS).join(", ")}`);
|
|
18485
|
+
process.exit(1);
|
|
18486
|
+
}
|
|
18487
|
+
}
|
|
18488
|
+
console.log("\u2550".repeat(60));
|
|
18489
|
+
console.log("RUDI Session Import");
|
|
18490
|
+
console.log("\u2550".repeat(60));
|
|
18491
|
+
console.log(`Providers: ${providers.join(", ")}`);
|
|
18492
|
+
console.log(`Database: ${getDbPath()}`);
|
|
18493
|
+
console.log(`Max age: ${maxAgeDays ? `${maxAgeDays} days` : "all"}`);
|
|
18494
|
+
console.log(`Dry run: ${dryRun ? "yes" : "no"}`);
|
|
18495
|
+
console.log("\u2550".repeat(60));
|
|
18496
|
+
let totalImported = 0;
|
|
18497
|
+
let totalSkipped = 0;
|
|
18498
|
+
for (const providerKey of providers) {
|
|
18499
|
+
const provider = PROVIDERS[providerKey];
|
|
18500
|
+
console.log(`
|
|
18501
|
+
\u25B6 ${provider.name}`);
|
|
18502
|
+
console.log(` Source: ${provider.baseDir}`);
|
|
18503
|
+
if (!(0, import_fs11.existsSync)(provider.baseDir)) {
|
|
18504
|
+
console.log(` \u26A0 Directory not found, skipping`);
|
|
18505
|
+
continue;
|
|
18506
|
+
}
|
|
18507
|
+
const existingIds = /* @__PURE__ */ new Set();
|
|
18508
|
+
try {
|
|
18509
|
+
const rows = db3.prepare(
|
|
18510
|
+
"SELECT provider_session_id FROM sessions WHERE provider = ? AND provider_session_id IS NOT NULL"
|
|
18511
|
+
).all(providerKey);
|
|
18512
|
+
for (const row of rows) {
|
|
18513
|
+
existingIds.add(row.provider_session_id);
|
|
18514
|
+
}
|
|
18515
|
+
} catch (e) {
|
|
18516
|
+
}
|
|
18517
|
+
console.log(` Existing: ${existingIds.size} sessions`);
|
|
18518
|
+
const files = findSessionFiles(provider.baseDir, provider.pattern);
|
|
18519
|
+
console.log(` Found: ${files.length} session files`);
|
|
18520
|
+
const insertStmt = db3.prepare(`
|
|
18521
|
+
INSERT INTO sessions (
|
|
18522
|
+
id, provider, provider_session_id, project_id,
|
|
18523
|
+
origin, origin_imported_at, origin_native_file,
|
|
18524
|
+
title, snippet, status, model,
|
|
18525
|
+
inherit_project_prompt,
|
|
18526
|
+
cwd, dir_scope, native_storage_path,
|
|
18527
|
+
created_at, last_active_at,
|
|
18528
|
+
turn_count, total_cost, total_input_tokens, total_output_tokens, total_duration_ms,
|
|
18529
|
+
is_warmup, parent_session_id, agent_id, is_sidechain, session_type, version, user_type
|
|
18530
|
+
) VALUES (
|
|
18531
|
+
?, ?, ?, NULL,
|
|
18532
|
+
'provider-import', ?, ?,
|
|
18533
|
+
?, '', 'active', ?,
|
|
18534
|
+
1,
|
|
18535
|
+
?, 'project', ?,
|
|
18536
|
+
?, ?,
|
|
18537
|
+
0, 0, 0, 0, 0,
|
|
18538
|
+
0, ?, ?, ?, ?, '2.0.76', 'external'
|
|
18539
|
+
)
|
|
18540
|
+
`);
|
|
18541
|
+
let imported = 0;
|
|
18542
|
+
let skipped = { existing: 0, empty: 0, old: 0, error: 0 };
|
|
18543
|
+
const now = Date.now();
|
|
18544
|
+
const maxAgeMs = maxAgeDays ? maxAgeDays * 24 * 60 * 60 * 1e3 : null;
|
|
18545
|
+
for (const filepath of files) {
|
|
18546
|
+
const sessionId = (0, import_path11.basename)(filepath, ".jsonl");
|
|
18547
|
+
if (existingIds.has(sessionId)) {
|
|
18548
|
+
skipped.existing++;
|
|
18549
|
+
continue;
|
|
18550
|
+
}
|
|
18551
|
+
let stat;
|
|
18552
|
+
try {
|
|
18553
|
+
stat = (0, import_fs11.statSync)(filepath);
|
|
18554
|
+
} catch (e) {
|
|
18555
|
+
skipped.error++;
|
|
18556
|
+
continue;
|
|
18557
|
+
}
|
|
18558
|
+
if (stat.size === 0) {
|
|
18559
|
+
skipped.empty++;
|
|
18560
|
+
continue;
|
|
18561
|
+
}
|
|
18562
|
+
if (maxAgeMs && now - stat.mtimeMs > maxAgeMs) {
|
|
18563
|
+
skipped.old++;
|
|
18564
|
+
continue;
|
|
18565
|
+
}
|
|
18566
|
+
const session = parseSessionFile(filepath, providerKey);
|
|
18567
|
+
if (!session) {
|
|
18568
|
+
skipped.error++;
|
|
18569
|
+
continue;
|
|
18570
|
+
}
|
|
18571
|
+
if (dryRun) {
|
|
18572
|
+
if (verbose || imported < 5) {
|
|
18573
|
+
console.log(` [would import] ${sessionId}: ${session.title.slice(0, 40)}`);
|
|
18574
|
+
}
|
|
18575
|
+
imported++;
|
|
18576
|
+
continue;
|
|
18577
|
+
}
|
|
18578
|
+
try {
|
|
18579
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
18580
|
+
insertStmt.run(
|
|
18581
|
+
(0, import_crypto2.randomUUID)(),
|
|
18582
|
+
providerKey,
|
|
18583
|
+
sessionId,
|
|
18584
|
+
nowIso,
|
|
18585
|
+
filepath,
|
|
18586
|
+
session.title,
|
|
18587
|
+
session.model || "unknown",
|
|
18588
|
+
session.cwd,
|
|
18589
|
+
filepath,
|
|
18590
|
+
session.createdAt,
|
|
18591
|
+
session.lastActiveAt,
|
|
18592
|
+
session.parentSessionId,
|
|
18593
|
+
session.agentId,
|
|
18594
|
+
session.isAgent ? 1 : 0,
|
|
18595
|
+
session.sessionType
|
|
18596
|
+
);
|
|
18597
|
+
imported++;
|
|
18598
|
+
if (verbose) {
|
|
18599
|
+
console.log(` \u2713 ${sessionId}: ${session.title.slice(0, 40)}`);
|
|
18600
|
+
} else if (imported % 100 === 0) {
|
|
18601
|
+
console.log(` Imported ${imported}...`);
|
|
18602
|
+
}
|
|
18603
|
+
} catch (e) {
|
|
18604
|
+
skipped.error++;
|
|
18605
|
+
if (verbose) {
|
|
18606
|
+
console.log(` \u2717 ${sessionId}: ${e.message}`);
|
|
18607
|
+
}
|
|
18608
|
+
}
|
|
18609
|
+
}
|
|
18610
|
+
console.log(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
|
|
18611
|
+
console.log(` Imported: ${imported}`);
|
|
18612
|
+
console.log(` Skipped: ${skipped.existing} existing, ${skipped.empty} empty, ${skipped.old} old, ${skipped.error} errors`);
|
|
18613
|
+
totalImported += imported;
|
|
18614
|
+
totalSkipped += skipped.existing + skipped.empty + skipped.old + skipped.error;
|
|
18615
|
+
}
|
|
18616
|
+
console.log("\n" + "\u2550".repeat(60));
|
|
18617
|
+
console.log(`Total imported: ${totalImported}`);
|
|
18618
|
+
console.log(`Total skipped: ${totalSkipped}`);
|
|
18619
|
+
console.log("\u2550".repeat(60));
|
|
18620
|
+
if (dryRun) {
|
|
18621
|
+
console.log("\n(Dry run - no changes made)");
|
|
18622
|
+
}
|
|
18623
|
+
if (!dryRun && totalImported > 0) {
|
|
18624
|
+
const count = db3.prepare("SELECT COUNT(*) as count FROM sessions").get();
|
|
18625
|
+
console.log(`
|
|
18626
|
+
Total sessions in database: ${count.count}`);
|
|
18627
|
+
}
|
|
18628
|
+
}
|
|
18629
|
+
function showImportStatus(flags) {
|
|
18630
|
+
console.log("\u2550".repeat(60));
|
|
18631
|
+
console.log("Import Status");
|
|
18632
|
+
console.log("\u2550".repeat(60));
|
|
18633
|
+
if (!isDatabaseInitialized()) {
|
|
18634
|
+
console.log("\nDatabase: Not initialized");
|
|
18635
|
+
console.log("Run: rudi db init");
|
|
18636
|
+
} else {
|
|
18637
|
+
const db3 = getDb();
|
|
18638
|
+
const stats = db3.prepare(`
|
|
18639
|
+
SELECT provider, COUNT(*) as count
|
|
18640
|
+
FROM sessions
|
|
18641
|
+
WHERE status = 'active'
|
|
18642
|
+
GROUP BY provider
|
|
18643
|
+
`).all();
|
|
18644
|
+
console.log("\nDatabase sessions:");
|
|
18645
|
+
for (const row of stats) {
|
|
18646
|
+
console.log(` ${row.provider}: ${row.count}`);
|
|
18647
|
+
}
|
|
18648
|
+
}
|
|
18649
|
+
console.log("\nProvider directories:");
|
|
18650
|
+
for (const [key, provider] of Object.entries(PROVIDERS)) {
|
|
18651
|
+
const exists = (0, import_fs11.existsSync)(provider.baseDir);
|
|
18652
|
+
let count = 0;
|
|
18653
|
+
if (exists) {
|
|
18654
|
+
const files = findSessionFiles(provider.baseDir, provider.pattern);
|
|
18655
|
+
count = files.length;
|
|
18656
|
+
}
|
|
18657
|
+
console.log(` ${provider.name}:`);
|
|
18658
|
+
console.log(` Path: ${provider.baseDir}`);
|
|
18659
|
+
console.log(` Status: ${exists ? `${count} session files` : "not found"}`);
|
|
18660
|
+
}
|
|
18661
|
+
console.log("\n" + "\u2550".repeat(60));
|
|
18662
|
+
console.log("To import: rudi import sessions [provider]");
|
|
18663
|
+
}
|
|
18664
|
+
function findSessionFiles(dir, pattern, files = []) {
|
|
18665
|
+
if (!(0, import_fs11.existsSync)(dir)) return files;
|
|
18666
|
+
try {
|
|
18667
|
+
for (const entry of (0, import_fs11.readdirSync)(dir, { withFileTypes: true })) {
|
|
18668
|
+
const fullPath = (0, import_path11.join)(dir, entry.name);
|
|
18669
|
+
if (entry.isDirectory()) {
|
|
18670
|
+
findSessionFiles(fullPath, pattern, files);
|
|
18671
|
+
} else if (pattern.test(entry.name)) {
|
|
18672
|
+
files.push(fullPath);
|
|
18673
|
+
}
|
|
18674
|
+
}
|
|
18675
|
+
} catch (e) {
|
|
18676
|
+
}
|
|
18677
|
+
return files;
|
|
18678
|
+
}
|
|
18679
|
+
function parseSessionFile(filepath, provider) {
|
|
18680
|
+
try {
|
|
18681
|
+
const stat = (0, import_fs11.statSync)(filepath);
|
|
18682
|
+
const content = (0, import_fs11.readFileSync)(filepath, "utf-8");
|
|
18683
|
+
const lines = content.split("\n").filter((l) => l.trim());
|
|
18684
|
+
if (lines.length === 0) return null;
|
|
18685
|
+
const sessionId = (0, import_path11.basename)(filepath, ".jsonl");
|
|
18686
|
+
const isAgent = sessionId.startsWith("agent-");
|
|
18687
|
+
let title = null;
|
|
18688
|
+
let cwd = null;
|
|
18689
|
+
let createdAt = null;
|
|
18690
|
+
let model = null;
|
|
18691
|
+
let parentSessionId = null;
|
|
18692
|
+
let agentId = isAgent ? sessionId.replace("agent-", "") : null;
|
|
18693
|
+
for (const line of lines.slice(0, 50)) {
|
|
18694
|
+
try {
|
|
18695
|
+
const data = JSON.parse(line);
|
|
18696
|
+
if (!cwd && data.cwd) cwd = data.cwd;
|
|
18697
|
+
if (!createdAt && data.timestamp) createdAt = data.timestamp;
|
|
18698
|
+
if (!model && data.model) model = data.model;
|
|
18699
|
+
if (!parentSessionId && (data.parentSessionId || data.parentUuid)) {
|
|
18700
|
+
parentSessionId = data.parentSessionId || data.parentUuid;
|
|
18701
|
+
}
|
|
18702
|
+
if (!agentId && data.agentId) agentId = data.agentId;
|
|
18703
|
+
if (!title) {
|
|
18704
|
+
const msg = data.message?.content || data.userMessage || (data.type === "user" ? data.message?.content : null);
|
|
18705
|
+
if (msg && msg.length > 2) {
|
|
18706
|
+
title = msg.split("\n")[0].slice(0, 50).trim();
|
|
18707
|
+
}
|
|
18708
|
+
}
|
|
18709
|
+
} catch (e) {
|
|
18710
|
+
continue;
|
|
18711
|
+
}
|
|
18712
|
+
}
|
|
18713
|
+
if (!title || title.length < 3) {
|
|
18714
|
+
title = isAgent ? "Agent Session" : "Imported Session";
|
|
18715
|
+
}
|
|
18716
|
+
if (!cwd) {
|
|
18717
|
+
const parentDir = (0, import_path11.basename)((0, import_path11.dirname)(filepath));
|
|
18718
|
+
if (parentDir.startsWith("-")) {
|
|
18719
|
+
cwd = parentDir.replace(/-/g, "/").replace(/^\//, "/");
|
|
18720
|
+
} else {
|
|
18721
|
+
cwd = (0, import_os3.homedir)();
|
|
18722
|
+
}
|
|
18723
|
+
}
|
|
18724
|
+
return {
|
|
18725
|
+
title,
|
|
18726
|
+
cwd,
|
|
18727
|
+
createdAt: createdAt || stat.birthtime.toISOString(),
|
|
18728
|
+
lastActiveAt: stat.mtime.toISOString(),
|
|
18729
|
+
model,
|
|
18730
|
+
isAgent,
|
|
18731
|
+
agentId,
|
|
18732
|
+
parentSessionId,
|
|
18733
|
+
sessionType: isAgent ? "agent" : "main"
|
|
18734
|
+
};
|
|
18735
|
+
} catch (e) {
|
|
18736
|
+
return null;
|
|
18737
|
+
}
|
|
18738
|
+
}
|
|
18156
18739
|
|
|
18157
18740
|
// src/commands/doctor.js
|
|
18158
|
-
var
|
|
18741
|
+
var import_fs12 = __toESM(require("fs"), 1);
|
|
18159
18742
|
async function cmdDoctor(args, flags) {
|
|
18160
18743
|
console.log("RUDI Health Check");
|
|
18161
18744
|
console.log("\u2550".repeat(50));
|
|
@@ -18173,12 +18756,12 @@ async function cmdDoctor(args, flags) {
|
|
|
18173
18756
|
{ path: PATHS.cache, name: "Cache" }
|
|
18174
18757
|
];
|
|
18175
18758
|
for (const dir of dirs) {
|
|
18176
|
-
const exists =
|
|
18759
|
+
const exists = import_fs12.default.existsSync(dir.path);
|
|
18177
18760
|
const status = exists ? "\u2713" : "\u2717";
|
|
18178
18761
|
console.log(` ${status} ${dir.name}: ${dir.path}`);
|
|
18179
18762
|
if (!exists) {
|
|
18180
18763
|
issues.push(`Missing directory: ${dir.name}`);
|
|
18181
|
-
fixes.push(() =>
|
|
18764
|
+
fixes.push(() => import_fs12.default.mkdirSync(dir.path, { recursive: true }));
|
|
18182
18765
|
}
|
|
18183
18766
|
}
|
|
18184
18767
|
console.log("\n\u{1F4BE} Database");
|
|
@@ -18248,8 +18831,8 @@ async function cmdDoctor(args, flags) {
|
|
|
18248
18831
|
}
|
|
18249
18832
|
|
|
18250
18833
|
// src/commands/update.js
|
|
18251
|
-
var
|
|
18252
|
-
var
|
|
18834
|
+
var import_fs13 = __toESM(require("fs"), 1);
|
|
18835
|
+
var import_path12 = __toESM(require("path"), 1);
|
|
18253
18836
|
var import_child_process2 = require("child_process");
|
|
18254
18837
|
init_src();
|
|
18255
18838
|
init_src2();
|
|
@@ -18275,7 +18858,7 @@ async function cmdUpdate(args, flags) {
|
|
|
18275
18858
|
async function updatePackage(pkgId, flags) {
|
|
18276
18859
|
const [kind, name] = parsePackageId(pkgId);
|
|
18277
18860
|
const installPath = getPackagePath(pkgId);
|
|
18278
|
-
if (!
|
|
18861
|
+
if (!import_fs13.default.existsSync(installPath)) {
|
|
18279
18862
|
return { success: false, error: "Package not installed" };
|
|
18280
18863
|
}
|
|
18281
18864
|
const pkg = await getPackage(pkgId);
|
|
@@ -18298,7 +18881,7 @@ async function updatePackage(pkgId, flags) {
|
|
|
18298
18881
|
}
|
|
18299
18882
|
if (pkg.pipPackage) {
|
|
18300
18883
|
try {
|
|
18301
|
-
const venvPip =
|
|
18884
|
+
const venvPip = import_path12.default.join(installPath, "venv", "bin", "pip");
|
|
18302
18885
|
(0, import_child_process2.execSync)(`"${venvPip}" install --upgrade ${pkg.pipPackage}`, {
|
|
18303
18886
|
stdio: flags.verbose ? "inherit" : "pipe"
|
|
18304
18887
|
});
|
|
@@ -18315,7 +18898,7 @@ async function updatePackage(pkgId, flags) {
|
|
|
18315
18898
|
if (kind === "runtime" && !pkg.npmPackage && !pkg.pipPackage) {
|
|
18316
18899
|
try {
|
|
18317
18900
|
const { downloadRuntime: downloadRuntime2 } = await Promise.resolve().then(() => (init_src2(), src_exports));
|
|
18318
|
-
|
|
18901
|
+
import_fs13.default.rmSync(installPath, { recursive: true, force: true });
|
|
18319
18902
|
await downloadRuntime2(name, pkg.version || "latest", installPath, {
|
|
18320
18903
|
onProgress: (p) => {
|
|
18321
18904
|
if (flags.verbose) console.log(` ${p.phase}...`);
|
|
@@ -18335,8 +18918,8 @@ async function updateAll(flags) {
|
|
|
18335
18918
|
let failed = 0;
|
|
18336
18919
|
for (const kind of kinds) {
|
|
18337
18920
|
const dir = kind === "runtime" ? PATHS.runtimes : kind === "stack" ? PATHS.stacks : PATHS.prompts;
|
|
18338
|
-
if (!
|
|
18339
|
-
const entries =
|
|
18921
|
+
if (!import_fs13.default.existsSync(dir)) continue;
|
|
18922
|
+
const entries = import_fs13.default.readdirSync(dir, { withFileTypes: true });
|
|
18340
18923
|
for (const entry of entries) {
|
|
18341
18924
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
18342
18925
|
const pkgId = `${kind}:${entry.name}`;
|
|
@@ -18355,14 +18938,14 @@ Updated ${updated} package(s)${failed > 0 ? `, ${failed} failed` : ""}`);
|
|
|
18355
18938
|
}
|
|
18356
18939
|
function getInstalledVersion(installPath, npmPackage) {
|
|
18357
18940
|
try {
|
|
18358
|
-
const pkgJsonPath =
|
|
18359
|
-
if (
|
|
18360
|
-
const pkgJson = JSON.parse(
|
|
18941
|
+
const pkgJsonPath = import_path12.default.join(installPath, "node_modules", npmPackage.replace("@", "").split("/")[0], "package.json");
|
|
18942
|
+
if (import_fs13.default.existsSync(pkgJsonPath)) {
|
|
18943
|
+
const pkgJson = JSON.parse(import_fs13.default.readFileSync(pkgJsonPath, "utf-8"));
|
|
18361
18944
|
return pkgJson.version;
|
|
18362
18945
|
}
|
|
18363
|
-
const rootPkgPath =
|
|
18364
|
-
if (
|
|
18365
|
-
const rootPkg = JSON.parse(
|
|
18946
|
+
const rootPkgPath = import_path12.default.join(installPath, "package.json");
|
|
18947
|
+
if (import_fs13.default.existsSync(rootPkgPath)) {
|
|
18948
|
+
const rootPkg = JSON.parse(import_fs13.default.readFileSync(rootPkgPath, "utf-8"));
|
|
18366
18949
|
const dep = rootPkg.dependencies?.[npmPackage];
|
|
18367
18950
|
if (dep) return dep.replace(/[\^~]/, "");
|
|
18368
18951
|
}
|
|
@@ -18371,30 +18954,30 @@ function getInstalledVersion(installPath, npmPackage) {
|
|
|
18371
18954
|
return null;
|
|
18372
18955
|
}
|
|
18373
18956
|
function updateRuntimeMetadata(installPath, updates) {
|
|
18374
|
-
const metaPath =
|
|
18957
|
+
const metaPath = import_path12.default.join(installPath, "runtime.json");
|
|
18375
18958
|
try {
|
|
18376
18959
|
let meta = {};
|
|
18377
|
-
if (
|
|
18378
|
-
meta = JSON.parse(
|
|
18960
|
+
if (import_fs13.default.existsSync(metaPath)) {
|
|
18961
|
+
meta = JSON.parse(import_fs13.default.readFileSync(metaPath, "utf-8"));
|
|
18379
18962
|
}
|
|
18380
18963
|
meta = { ...meta, ...updates };
|
|
18381
|
-
|
|
18964
|
+
import_fs13.default.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
|
|
18382
18965
|
} catch {
|
|
18383
18966
|
}
|
|
18384
18967
|
}
|
|
18385
18968
|
|
|
18386
18969
|
// db/index.js
|
|
18387
18970
|
var import_better_sqlite32 = __toESM(require("better-sqlite3"), 1);
|
|
18388
|
-
var
|
|
18389
|
-
var
|
|
18390
|
-
var
|
|
18391
|
-
var
|
|
18392
|
-
var DB_PATH2 =
|
|
18971
|
+
var import_path13 = __toESM(require("path"), 1);
|
|
18972
|
+
var import_os4 = __toESM(require("os"), 1);
|
|
18973
|
+
var import_fs14 = __toESM(require("fs"), 1);
|
|
18974
|
+
var PROMPT_STACK_HOME = import_path13.default.join(import_os4.default.homedir(), ".prompt-stack");
|
|
18975
|
+
var DB_PATH2 = import_path13.default.join(PROMPT_STACK_HOME, "prompt-stack.db");
|
|
18393
18976
|
var db2 = null;
|
|
18394
18977
|
function getDb2(options = {}) {
|
|
18395
18978
|
if (!db2) {
|
|
18396
|
-
if (!
|
|
18397
|
-
|
|
18979
|
+
if (!import_fs14.default.existsSync(PROMPT_STACK_HOME)) {
|
|
18980
|
+
import_fs14.default.mkdirSync(PROMPT_STACK_HOME, { recursive: true });
|
|
18398
18981
|
}
|
|
18399
18982
|
db2 = new import_better_sqlite32.default(DB_PATH2, {
|
|
18400
18983
|
readonly: options.readonly || false
|
|
@@ -18552,7 +19135,7 @@ function getBeforeCrashLogs() {
|
|
|
18552
19135
|
}
|
|
18553
19136
|
|
|
18554
19137
|
// src/commands/logs.js
|
|
18555
|
-
var
|
|
19138
|
+
var import_fs15 = __toESM(require("fs"), 1);
|
|
18556
19139
|
function parseTimeAgo(str) {
|
|
18557
19140
|
const match = str.match(/^(\d+)([smhd])$/);
|
|
18558
19141
|
if (!match) return null;
|
|
@@ -18652,7 +19235,7 @@ function exportLogs(logs, filepath, format) {
|
|
|
18652
19235
|
});
|
|
18653
19236
|
content = JSON.stringify(formatted, null, 2);
|
|
18654
19237
|
}
|
|
18655
|
-
|
|
19238
|
+
import_fs15.default.writeFileSync(filepath, content, "utf-8");
|
|
18656
19239
|
return filepath;
|
|
18657
19240
|
}
|
|
18658
19241
|
function printStats(stats) {
|
|
@@ -19189,6 +19772,9 @@ async function main() {
|
|
|
19189
19772
|
case "database":
|
|
19190
19773
|
await cmdDb(args, flags);
|
|
19191
19774
|
break;
|
|
19775
|
+
case "import":
|
|
19776
|
+
await cmdImport(args, flags);
|
|
19777
|
+
break;
|
|
19192
19778
|
case "doctor":
|
|
19193
19779
|
case "check":
|
|
19194
19780
|
await cmdDoctor(args, flags);
|