@hasna/brains 0.0.1 → 0.0.2

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/index.js CHANGED
@@ -2062,771 +2062,6 @@ var require_commander = __commonJS((exports) => {
2062
2062
  exports.InvalidOptionArgumentError = InvalidArgumentError;
2063
2063
  });
2064
2064
 
2065
- // node_modules/better-sqlite3/lib/util.js
2066
- var require_util = __commonJS((exports) => {
2067
- exports.getBooleanOption = (options, key) => {
2068
- let value = false;
2069
- if (key in options && typeof (value = options[key]) !== "boolean") {
2070
- throw new TypeError(`Expected the "${key}" option to be a boolean`);
2071
- }
2072
- return value;
2073
- };
2074
- exports.cppdb = Symbol();
2075
- exports.inspect = Symbol.for("nodejs.util.inspect.custom");
2076
- });
2077
-
2078
- // node_modules/better-sqlite3/lib/sqlite-error.js
2079
- var require_sqlite_error = __commonJS((exports, module) => {
2080
- var descriptor = { value: "SqliteError", writable: true, enumerable: false, configurable: true };
2081
- function SqliteError(message, code) {
2082
- if (new.target !== SqliteError) {
2083
- return new SqliteError(message, code);
2084
- }
2085
- if (typeof code !== "string") {
2086
- throw new TypeError("Expected second argument to be a string");
2087
- }
2088
- Error.call(this, message);
2089
- descriptor.value = "" + message;
2090
- Object.defineProperty(this, "message", descriptor);
2091
- Error.captureStackTrace(this, SqliteError);
2092
- this.code = code;
2093
- }
2094
- Object.setPrototypeOf(SqliteError, Error);
2095
- Object.setPrototypeOf(SqliteError.prototype, Error.prototype);
2096
- Object.defineProperty(SqliteError.prototype, "name", descriptor);
2097
- module.exports = SqliteError;
2098
- });
2099
-
2100
- // node_modules/file-uri-to-path/index.js
2101
- var require_file_uri_to_path = __commonJS((exports, module) => {
2102
- var sep = __require("path").sep || "/";
2103
- module.exports = fileUriToPath;
2104
- function fileUriToPath(uri) {
2105
- if (typeof uri != "string" || uri.length <= 7 || uri.substring(0, 7) != "file://") {
2106
- throw new TypeError("must pass in a file:// URI to convert to a file path");
2107
- }
2108
- var rest = decodeURI(uri.substring(7));
2109
- var firstSlash = rest.indexOf("/");
2110
- var host = rest.substring(0, firstSlash);
2111
- var path = rest.substring(firstSlash + 1);
2112
- if (host == "localhost")
2113
- host = "";
2114
- if (host) {
2115
- host = sep + sep + host;
2116
- }
2117
- path = path.replace(/^(.+)\|/, "$1:");
2118
- if (sep == "\\") {
2119
- path = path.replace(/\//g, "\\");
2120
- }
2121
- if (/^.+\:/.test(path)) {} else {
2122
- path = sep + path;
2123
- }
2124
- return host + path;
2125
- }
2126
- });
2127
-
2128
- // node_modules/bindings/bindings.js
2129
- var require_bindings = __commonJS((exports, module) => {
2130
- var __filename = "/Users/hasna/Workspace/hasna/opensource/opensourcedev/open-brains/node_modules/bindings/bindings.js";
2131
- var fs = __require("fs");
2132
- var path = __require("path");
2133
- var fileURLToPath = require_file_uri_to_path();
2134
- var join = path.join;
2135
- var dirname = path.dirname;
2136
- var exists2 = fs.accessSync && function(path2) {
2137
- try {
2138
- fs.accessSync(path2);
2139
- } catch (e) {
2140
- return false;
2141
- }
2142
- return true;
2143
- } || fs.existsSync || path.existsSync;
2144
- var defaults = {
2145
- arrow: process.env.NODE_BINDINGS_ARROW || " \u2192 ",
2146
- compiled: process.env.NODE_BINDINGS_COMPILED_DIR || "compiled",
2147
- platform: process.platform,
2148
- arch: process.arch,
2149
- nodePreGyp: "node-v" + process.versions.modules + "-" + process.platform + "-" + process.arch,
2150
- version: process.versions.node,
2151
- bindings: "bindings.node",
2152
- try: [
2153
- ["module_root", "build", "bindings"],
2154
- ["module_root", "build", "Debug", "bindings"],
2155
- ["module_root", "build", "Release", "bindings"],
2156
- ["module_root", "out", "Debug", "bindings"],
2157
- ["module_root", "Debug", "bindings"],
2158
- ["module_root", "out", "Release", "bindings"],
2159
- ["module_root", "Release", "bindings"],
2160
- ["module_root", "build", "default", "bindings"],
2161
- ["module_root", "compiled", "version", "platform", "arch", "bindings"],
2162
- ["module_root", "addon-build", "release", "install-root", "bindings"],
2163
- ["module_root", "addon-build", "debug", "install-root", "bindings"],
2164
- ["module_root", "addon-build", "default", "install-root", "bindings"],
2165
- ["module_root", "lib", "binding", "nodePreGyp", "bindings"]
2166
- ]
2167
- };
2168
- function bindings(opts) {
2169
- if (typeof opts == "string") {
2170
- opts = { bindings: opts };
2171
- } else if (!opts) {
2172
- opts = {};
2173
- }
2174
- Object.keys(defaults).map(function(i2) {
2175
- if (!(i2 in opts))
2176
- opts[i2] = defaults[i2];
2177
- });
2178
- if (!opts.module_root) {
2179
- opts.module_root = exports.getRoot(exports.getFileName());
2180
- }
2181
- if (path.extname(opts.bindings) != ".node") {
2182
- opts.bindings += ".node";
2183
- }
2184
- var requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
2185
- var tries = [], i = 0, l = opts.try.length, n, b, err;
2186
- for (;i < l; i++) {
2187
- n = join.apply(null, opts.try[i].map(function(p) {
2188
- return opts[p] || p;
2189
- }));
2190
- tries.push(n);
2191
- try {
2192
- b = opts.path ? requireFunc.resolve(n) : requireFunc(n);
2193
- if (!opts.path) {
2194
- b.path = n;
2195
- }
2196
- return b;
2197
- } catch (e) {
2198
- if (e.code !== "MODULE_NOT_FOUND" && e.code !== "QUALIFIED_PATH_RESOLUTION_FAILED" && !/not find/i.test(e.message)) {
2199
- throw e;
2200
- }
2201
- }
2202
- }
2203
- err = new Error(`Could not locate the bindings file. Tried:
2204
- ` + tries.map(function(a) {
2205
- return opts.arrow + a;
2206
- }).join(`
2207
- `));
2208
- err.tries = tries;
2209
- throw err;
2210
- }
2211
- module.exports = exports = bindings;
2212
- exports.getFileName = function getFileName(calling_file) {
2213
- var { prepareStackTrace: origPST, stackTraceLimit: origSTL } = Error, dummy = {}, fileName;
2214
- Error.stackTraceLimit = 10;
2215
- Error.prepareStackTrace = function(e, st) {
2216
- for (var i = 0, l = st.length;i < l; i++) {
2217
- fileName = st[i].getFileName();
2218
- if (fileName !== __filename) {
2219
- if (calling_file) {
2220
- if (fileName !== calling_file) {
2221
- return;
2222
- }
2223
- } else {
2224
- return;
2225
- }
2226
- }
2227
- }
2228
- };
2229
- Error.captureStackTrace(dummy);
2230
- dummy.stack;
2231
- Error.prepareStackTrace = origPST;
2232
- Error.stackTraceLimit = origSTL;
2233
- var fileSchema = "file://";
2234
- if (fileName.indexOf(fileSchema) === 0) {
2235
- fileName = fileURLToPath(fileName);
2236
- }
2237
- return fileName;
2238
- };
2239
- exports.getRoot = function getRoot(file) {
2240
- var dir = dirname(file), prev;
2241
- while (true) {
2242
- if (dir === ".") {
2243
- dir = process.cwd();
2244
- }
2245
- if (exists2(join(dir, "package.json")) || exists2(join(dir, "node_modules"))) {
2246
- return dir;
2247
- }
2248
- if (prev === dir) {
2249
- throw new Error('Could not find module root given file: "' + file + '". Do you have a `package.json` file? ');
2250
- }
2251
- prev = dir;
2252
- dir = join(dir, "..");
2253
- }
2254
- };
2255
- });
2256
-
2257
- // node_modules/better-sqlite3/lib/methods/wrappers.js
2258
- var require_wrappers = __commonJS((exports) => {
2259
- var { cppdb } = require_util();
2260
- exports.prepare = function prepare(sql2) {
2261
- return this[cppdb].prepare(sql2, this, false);
2262
- };
2263
- exports.exec = function exec(sql2) {
2264
- this[cppdb].exec(sql2);
2265
- return this;
2266
- };
2267
- exports.close = function close() {
2268
- this[cppdb].close();
2269
- return this;
2270
- };
2271
- exports.loadExtension = function loadExtension(...args) {
2272
- this[cppdb].loadExtension(...args);
2273
- return this;
2274
- };
2275
- exports.defaultSafeIntegers = function defaultSafeIntegers(...args) {
2276
- this[cppdb].defaultSafeIntegers(...args);
2277
- return this;
2278
- };
2279
- exports.unsafeMode = function unsafeMode(...args) {
2280
- this[cppdb].unsafeMode(...args);
2281
- return this;
2282
- };
2283
- exports.getters = {
2284
- name: {
2285
- get: function name() {
2286
- return this[cppdb].name;
2287
- },
2288
- enumerable: true
2289
- },
2290
- open: {
2291
- get: function open() {
2292
- return this[cppdb].open;
2293
- },
2294
- enumerable: true
2295
- },
2296
- inTransaction: {
2297
- get: function inTransaction() {
2298
- return this[cppdb].inTransaction;
2299
- },
2300
- enumerable: true
2301
- },
2302
- readonly: {
2303
- get: function readonly() {
2304
- return this[cppdb].readonly;
2305
- },
2306
- enumerable: true
2307
- },
2308
- memory: {
2309
- get: function memory() {
2310
- return this[cppdb].memory;
2311
- },
2312
- enumerable: true
2313
- }
2314
- };
2315
- });
2316
-
2317
- // node_modules/better-sqlite3/lib/methods/transaction.js
2318
- var require_transaction = __commonJS((exports, module) => {
2319
- var { cppdb } = require_util();
2320
- var controllers = new WeakMap;
2321
- module.exports = function transaction(fn) {
2322
- if (typeof fn !== "function")
2323
- throw new TypeError("Expected first argument to be a function");
2324
- const db = this[cppdb];
2325
- const controller = getController(db, this);
2326
- const { apply } = Function.prototype;
2327
- const properties = {
2328
- default: { value: wrapTransaction(apply, fn, db, controller.default) },
2329
- deferred: { value: wrapTransaction(apply, fn, db, controller.deferred) },
2330
- immediate: { value: wrapTransaction(apply, fn, db, controller.immediate) },
2331
- exclusive: { value: wrapTransaction(apply, fn, db, controller.exclusive) },
2332
- database: { value: this, enumerable: true }
2333
- };
2334
- Object.defineProperties(properties.default.value, properties);
2335
- Object.defineProperties(properties.deferred.value, properties);
2336
- Object.defineProperties(properties.immediate.value, properties);
2337
- Object.defineProperties(properties.exclusive.value, properties);
2338
- return properties.default.value;
2339
- };
2340
- var getController = (db, self) => {
2341
- let controller = controllers.get(db);
2342
- if (!controller) {
2343
- const shared = {
2344
- commit: db.prepare("COMMIT", self, false),
2345
- rollback: db.prepare("ROLLBACK", self, false),
2346
- savepoint: db.prepare("SAVEPOINT `\t_bs3.\t`", self, false),
2347
- release: db.prepare("RELEASE `\t_bs3.\t`", self, false),
2348
- rollbackTo: db.prepare("ROLLBACK TO `\t_bs3.\t`", self, false)
2349
- };
2350
- controllers.set(db, controller = {
2351
- default: Object.assign({ begin: db.prepare("BEGIN", self, false) }, shared),
2352
- deferred: Object.assign({ begin: db.prepare("BEGIN DEFERRED", self, false) }, shared),
2353
- immediate: Object.assign({ begin: db.prepare("BEGIN IMMEDIATE", self, false) }, shared),
2354
- exclusive: Object.assign({ begin: db.prepare("BEGIN EXCLUSIVE", self, false) }, shared)
2355
- });
2356
- }
2357
- return controller;
2358
- };
2359
- var wrapTransaction = (apply, fn, db, { begin, commit, rollback, savepoint, release, rollbackTo }) => function sqliteTransaction() {
2360
- let before, after, undo;
2361
- if (db.inTransaction) {
2362
- before = savepoint;
2363
- after = release;
2364
- undo = rollbackTo;
2365
- } else {
2366
- before = begin;
2367
- after = commit;
2368
- undo = rollback;
2369
- }
2370
- before.run();
2371
- try {
2372
- const result = apply.call(fn, this, arguments);
2373
- if (result && typeof result.then === "function") {
2374
- throw new TypeError("Transaction function cannot return a promise");
2375
- }
2376
- after.run();
2377
- return result;
2378
- } catch (ex) {
2379
- if (db.inTransaction) {
2380
- undo.run();
2381
- if (undo !== rollback)
2382
- after.run();
2383
- }
2384
- throw ex;
2385
- }
2386
- };
2387
- });
2388
-
2389
- // node_modules/better-sqlite3/lib/methods/pragma.js
2390
- var require_pragma = __commonJS((exports, module) => {
2391
- var { getBooleanOption, cppdb } = require_util();
2392
- module.exports = function pragma(source, options) {
2393
- if (options == null)
2394
- options = {};
2395
- if (typeof source !== "string")
2396
- throw new TypeError("Expected first argument to be a string");
2397
- if (typeof options !== "object")
2398
- throw new TypeError("Expected second argument to be an options object");
2399
- const simple = getBooleanOption(options, "simple");
2400
- const stmt = this[cppdb].prepare(`PRAGMA ${source}`, this, true);
2401
- return simple ? stmt.pluck().get() : stmt.all();
2402
- };
2403
- });
2404
-
2405
- // node_modules/better-sqlite3/lib/methods/backup.js
2406
- var require_backup = __commonJS((exports, module) => {
2407
- var fs = __require("fs");
2408
- var path = __require("path");
2409
- var { promisify } = __require("util");
2410
- var { cppdb } = require_util();
2411
- var fsAccess = promisify(fs.access);
2412
- module.exports = async function backup(filename, options) {
2413
- if (options == null)
2414
- options = {};
2415
- if (typeof filename !== "string")
2416
- throw new TypeError("Expected first argument to be a string");
2417
- if (typeof options !== "object")
2418
- throw new TypeError("Expected second argument to be an options object");
2419
- filename = filename.trim();
2420
- const attachedName = "attached" in options ? options.attached : "main";
2421
- const handler = "progress" in options ? options.progress : null;
2422
- if (!filename)
2423
- throw new TypeError("Backup filename cannot be an empty string");
2424
- if (filename === ":memory:")
2425
- throw new TypeError('Invalid backup filename ":memory:"');
2426
- if (typeof attachedName !== "string")
2427
- throw new TypeError('Expected the "attached" option to be a string');
2428
- if (!attachedName)
2429
- throw new TypeError('The "attached" option cannot be an empty string');
2430
- if (handler != null && typeof handler !== "function")
2431
- throw new TypeError('Expected the "progress" option to be a function');
2432
- await fsAccess(path.dirname(filename)).catch(() => {
2433
- throw new TypeError("Cannot save backup because the directory does not exist");
2434
- });
2435
- const isNewFile = await fsAccess(filename).then(() => false, () => true);
2436
- return runBackup(this[cppdb].backup(this, attachedName, filename, isNewFile), handler || null);
2437
- };
2438
- var runBackup = (backup, handler) => {
2439
- let rate = 0;
2440
- let useDefault = true;
2441
- return new Promise((resolve, reject) => {
2442
- setImmediate(function step() {
2443
- try {
2444
- const progress = backup.transfer(rate);
2445
- if (!progress.remainingPages) {
2446
- backup.close();
2447
- resolve(progress);
2448
- return;
2449
- }
2450
- if (useDefault) {
2451
- useDefault = false;
2452
- rate = 100;
2453
- }
2454
- if (handler) {
2455
- const ret = handler(progress);
2456
- if (ret !== undefined) {
2457
- if (typeof ret === "number" && ret === ret)
2458
- rate = Math.max(0, Math.min(2147483647, Math.round(ret)));
2459
- else
2460
- throw new TypeError("Expected progress callback to return a number or undefined");
2461
- }
2462
- }
2463
- setImmediate(step);
2464
- } catch (err) {
2465
- backup.close();
2466
- reject(err);
2467
- }
2468
- });
2469
- });
2470
- };
2471
- });
2472
-
2473
- // node_modules/better-sqlite3/lib/methods/serialize.js
2474
- var require_serialize = __commonJS((exports, module) => {
2475
- var { cppdb } = require_util();
2476
- module.exports = function serialize(options) {
2477
- if (options == null)
2478
- options = {};
2479
- if (typeof options !== "object")
2480
- throw new TypeError("Expected first argument to be an options object");
2481
- const attachedName = "attached" in options ? options.attached : "main";
2482
- if (typeof attachedName !== "string")
2483
- throw new TypeError('Expected the "attached" option to be a string');
2484
- if (!attachedName)
2485
- throw new TypeError('The "attached" option cannot be an empty string');
2486
- return this[cppdb].serialize(attachedName);
2487
- };
2488
- });
2489
-
2490
- // node_modules/better-sqlite3/lib/methods/function.js
2491
- var require_function = __commonJS((exports, module) => {
2492
- var { getBooleanOption, cppdb } = require_util();
2493
- module.exports = function defineFunction(name, options, fn) {
2494
- if (options == null)
2495
- options = {};
2496
- if (typeof options === "function") {
2497
- fn = options;
2498
- options = {};
2499
- }
2500
- if (typeof name !== "string")
2501
- throw new TypeError("Expected first argument to be a string");
2502
- if (typeof fn !== "function")
2503
- throw new TypeError("Expected last argument to be a function");
2504
- if (typeof options !== "object")
2505
- throw new TypeError("Expected second argument to be an options object");
2506
- if (!name)
2507
- throw new TypeError("User-defined function name cannot be an empty string");
2508
- const safeIntegers = "safeIntegers" in options ? +getBooleanOption(options, "safeIntegers") : 2;
2509
- const deterministic = getBooleanOption(options, "deterministic");
2510
- const directOnly = getBooleanOption(options, "directOnly");
2511
- const varargs = getBooleanOption(options, "varargs");
2512
- let argCount = -1;
2513
- if (!varargs) {
2514
- argCount = fn.length;
2515
- if (!Number.isInteger(argCount) || argCount < 0)
2516
- throw new TypeError("Expected function.length to be a positive integer");
2517
- if (argCount > 100)
2518
- throw new RangeError("User-defined functions cannot have more than 100 arguments");
2519
- }
2520
- this[cppdb].function(fn, name, argCount, safeIntegers, deterministic, directOnly);
2521
- return this;
2522
- };
2523
- });
2524
-
2525
- // node_modules/better-sqlite3/lib/methods/aggregate.js
2526
- var require_aggregate = __commonJS((exports, module) => {
2527
- var { getBooleanOption, cppdb } = require_util();
2528
- module.exports = function defineAggregate(name, options) {
2529
- if (typeof name !== "string")
2530
- throw new TypeError("Expected first argument to be a string");
2531
- if (typeof options !== "object" || options === null)
2532
- throw new TypeError("Expected second argument to be an options object");
2533
- if (!name)
2534
- throw new TypeError("User-defined function name cannot be an empty string");
2535
- const start = "start" in options ? options.start : null;
2536
- const step = getFunctionOption(options, "step", true);
2537
- const inverse = getFunctionOption(options, "inverse", false);
2538
- const result = getFunctionOption(options, "result", false);
2539
- const safeIntegers = "safeIntegers" in options ? +getBooleanOption(options, "safeIntegers") : 2;
2540
- const deterministic = getBooleanOption(options, "deterministic");
2541
- const directOnly = getBooleanOption(options, "directOnly");
2542
- const varargs = getBooleanOption(options, "varargs");
2543
- let argCount = -1;
2544
- if (!varargs) {
2545
- argCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);
2546
- if (argCount > 0)
2547
- argCount -= 1;
2548
- if (argCount > 100)
2549
- throw new RangeError("User-defined functions cannot have more than 100 arguments");
2550
- }
2551
- this[cppdb].aggregate(start, step, inverse, result, name, argCount, safeIntegers, deterministic, directOnly);
2552
- return this;
2553
- };
2554
- var getFunctionOption = (options, key, required) => {
2555
- const value = key in options ? options[key] : null;
2556
- if (typeof value === "function")
2557
- return value;
2558
- if (value != null)
2559
- throw new TypeError(`Expected the "${key}" option to be a function`);
2560
- if (required)
2561
- throw new TypeError(`Missing required option "${key}"`);
2562
- return null;
2563
- };
2564
- var getLength = ({ length }) => {
2565
- if (Number.isInteger(length) && length >= 0)
2566
- return length;
2567
- throw new TypeError("Expected function.length to be a positive integer");
2568
- };
2569
- });
2570
-
2571
- // node_modules/better-sqlite3/lib/methods/table.js
2572
- var require_table = __commonJS((exports, module) => {
2573
- var { cppdb } = require_util();
2574
- module.exports = function defineTable(name, factory) {
2575
- if (typeof name !== "string")
2576
- throw new TypeError("Expected first argument to be a string");
2577
- if (!name)
2578
- throw new TypeError("Virtual table module name cannot be an empty string");
2579
- let eponymous = false;
2580
- if (typeof factory === "object" && factory !== null) {
2581
- eponymous = true;
2582
- factory = defer(parseTableDefinition(factory, "used", name));
2583
- } else {
2584
- if (typeof factory !== "function")
2585
- throw new TypeError("Expected second argument to be a function or a table definition object");
2586
- factory = wrapFactory(factory);
2587
- }
2588
- this[cppdb].table(factory, name, eponymous);
2589
- return this;
2590
- };
2591
- function wrapFactory(factory) {
2592
- return function virtualTableFactory(moduleName, databaseName, tableName, ...args) {
2593
- const thisObject = {
2594
- module: moduleName,
2595
- database: databaseName,
2596
- table: tableName
2597
- };
2598
- const def = apply.call(factory, thisObject, args);
2599
- if (typeof def !== "object" || def === null) {
2600
- throw new TypeError(`Virtual table module "${moduleName}" did not return a table definition object`);
2601
- }
2602
- return parseTableDefinition(def, "returned", moduleName);
2603
- };
2604
- }
2605
- function parseTableDefinition(def, verb, moduleName) {
2606
- if (!hasOwnProperty.call(def, "rows")) {
2607
- throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "rows" property`);
2608
- }
2609
- if (!hasOwnProperty.call(def, "columns")) {
2610
- throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "columns" property`);
2611
- }
2612
- const rows = def.rows;
2613
- if (typeof rows !== "function" || Object.getPrototypeOf(rows) !== GeneratorFunctionPrototype) {
2614
- throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "rows" property (should be a generator function)`);
2615
- }
2616
- let columns = def.columns;
2617
- if (!Array.isArray(columns) || !(columns = [...columns]).every((x) => typeof x === "string")) {
2618
- throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "columns" property (should be an array of strings)`);
2619
- }
2620
- if (columns.length !== new Set(columns).size) {
2621
- throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate column names`);
2622
- }
2623
- if (!columns.length) {
2624
- throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with zero columns`);
2625
- }
2626
- let parameters;
2627
- if (hasOwnProperty.call(def, "parameters")) {
2628
- parameters = def.parameters;
2629
- if (!Array.isArray(parameters) || !(parameters = [...parameters]).every((x) => typeof x === "string")) {
2630
- throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "parameters" property (should be an array of strings)`);
2631
- }
2632
- } else {
2633
- parameters = inferParameters(rows);
2634
- }
2635
- if (parameters.length !== new Set(parameters).size) {
2636
- throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate parameter names`);
2637
- }
2638
- if (parameters.length > 32) {
2639
- throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with more than the maximum number of 32 parameters`);
2640
- }
2641
- for (const parameter of parameters) {
2642
- if (columns.includes(parameter)) {
2643
- throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with column "${parameter}" which was ambiguously defined as both a column and parameter`);
2644
- }
2645
- }
2646
- let safeIntegers = 2;
2647
- if (hasOwnProperty.call(def, "safeIntegers")) {
2648
- const bool = def.safeIntegers;
2649
- if (typeof bool !== "boolean") {
2650
- throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "safeIntegers" property (should be a boolean)`);
2651
- }
2652
- safeIntegers = +bool;
2653
- }
2654
- let directOnly = false;
2655
- if (hasOwnProperty.call(def, "directOnly")) {
2656
- directOnly = def.directOnly;
2657
- if (typeof directOnly !== "boolean") {
2658
- throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "directOnly" property (should be a boolean)`);
2659
- }
2660
- }
2661
- const columnDefinitions = [
2662
- ...parameters.map(identifier).map((str) => `${str} HIDDEN`),
2663
- ...columns.map(identifier)
2664
- ];
2665
- return [
2666
- `CREATE TABLE x(${columnDefinitions.join(", ")});`,
2667
- wrapGenerator(rows, new Map(columns.map((x, i) => [x, parameters.length + i])), moduleName),
2668
- parameters,
2669
- safeIntegers,
2670
- directOnly
2671
- ];
2672
- }
2673
- function wrapGenerator(generator, columnMap, moduleName) {
2674
- return function* virtualTable(...args) {
2675
- const output = args.map((x) => Buffer.isBuffer(x) ? Buffer.from(x) : x);
2676
- for (let i = 0;i < columnMap.size; ++i) {
2677
- output.push(null);
2678
- }
2679
- for (const row of generator(...args)) {
2680
- if (Array.isArray(row)) {
2681
- extractRowArray(row, output, columnMap.size, moduleName);
2682
- yield output;
2683
- } else if (typeof row === "object" && row !== null) {
2684
- extractRowObject(row, output, columnMap, moduleName);
2685
- yield output;
2686
- } else {
2687
- throw new TypeError(`Virtual table module "${moduleName}" yielded something that isn't a valid row object`);
2688
- }
2689
- }
2690
- };
2691
- }
2692
- function extractRowArray(row, output, columnCount, moduleName) {
2693
- if (row.length !== columnCount) {
2694
- throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an incorrect number of columns`);
2695
- }
2696
- const offset = output.length - columnCount;
2697
- for (let i = 0;i < columnCount; ++i) {
2698
- output[i + offset] = row[i];
2699
- }
2700
- }
2701
- function extractRowObject(row, output, columnMap, moduleName) {
2702
- let count = 0;
2703
- for (const key of Object.keys(row)) {
2704
- const index = columnMap.get(key);
2705
- if (index === undefined) {
2706
- throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an undeclared column "${key}"`);
2707
- }
2708
- output[index] = row[key];
2709
- count += 1;
2710
- }
2711
- if (count !== columnMap.size) {
2712
- throw new TypeError(`Virtual table module "${moduleName}" yielded a row with missing columns`);
2713
- }
2714
- }
2715
- function inferParameters({ length }) {
2716
- if (!Number.isInteger(length) || length < 0) {
2717
- throw new TypeError("Expected function.length to be a positive integer");
2718
- }
2719
- const params = [];
2720
- for (let i = 0;i < length; ++i) {
2721
- params.push(`$${i + 1}`);
2722
- }
2723
- return params;
2724
- }
2725
- var { hasOwnProperty } = Object.prototype;
2726
- var { apply } = Function.prototype;
2727
- var GeneratorFunctionPrototype = Object.getPrototypeOf(function* () {});
2728
- var identifier = (str) => `"${str.replace(/"/g, '""')}"`;
2729
- var defer = (x) => () => x;
2730
- });
2731
-
2732
- // node_modules/better-sqlite3/lib/methods/inspect.js
2733
- var require_inspect = __commonJS((exports, module) => {
2734
- var DatabaseInspection = function Database() {};
2735
- module.exports = function inspect(depth, opts) {
2736
- return Object.assign(new DatabaseInspection, this);
2737
- };
2738
- });
2739
-
2740
- // node_modules/better-sqlite3/lib/database.js
2741
- var require_database = __commonJS((exports, module) => {
2742
- var fs = __require("fs");
2743
- var path = __require("path");
2744
- var util = require_util();
2745
- var SqliteError = require_sqlite_error();
2746
- var DEFAULT_ADDON;
2747
- function Database(filenameGiven, options) {
2748
- if (new.target == null) {
2749
- return new Database(filenameGiven, options);
2750
- }
2751
- let buffer;
2752
- if (Buffer.isBuffer(filenameGiven)) {
2753
- buffer = filenameGiven;
2754
- filenameGiven = ":memory:";
2755
- }
2756
- if (filenameGiven == null)
2757
- filenameGiven = "";
2758
- if (options == null)
2759
- options = {};
2760
- if (typeof filenameGiven !== "string")
2761
- throw new TypeError("Expected first argument to be a string");
2762
- if (typeof options !== "object")
2763
- throw new TypeError("Expected second argument to be an options object");
2764
- if ("readOnly" in options)
2765
- throw new TypeError('Misspelled option "readOnly" should be "readonly"');
2766
- if ("memory" in options)
2767
- throw new TypeError('Option "memory" was removed in v7.0.0 (use ":memory:" filename instead)');
2768
- const filename = filenameGiven.trim();
2769
- const anonymous = filename === "" || filename === ":memory:";
2770
- const readonly = util.getBooleanOption(options, "readonly");
2771
- const fileMustExist = util.getBooleanOption(options, "fileMustExist");
2772
- const timeout = "timeout" in options ? options.timeout : 5000;
2773
- const verbose = "verbose" in options ? options.verbose : null;
2774
- const nativeBinding = "nativeBinding" in options ? options.nativeBinding : null;
2775
- if (readonly && anonymous && !buffer)
2776
- throw new TypeError("In-memory/temporary databases cannot be readonly");
2777
- if (!Number.isInteger(timeout) || timeout < 0)
2778
- throw new TypeError('Expected the "timeout" option to be a positive integer');
2779
- if (timeout > 2147483647)
2780
- throw new RangeError('Option "timeout" cannot be greater than 2147483647');
2781
- if (verbose != null && typeof verbose !== "function")
2782
- throw new TypeError('Expected the "verbose" option to be a function');
2783
- if (nativeBinding != null && typeof nativeBinding !== "string" && typeof nativeBinding !== "object")
2784
- throw new TypeError('Expected the "nativeBinding" option to be a string or addon object');
2785
- let addon;
2786
- if (nativeBinding == null) {
2787
- addon = DEFAULT_ADDON || (DEFAULT_ADDON = require_bindings()("better_sqlite3.node"));
2788
- } else if (typeof nativeBinding === "string") {
2789
- const requireFunc = typeof __non_webpack_require__ === "function" ? __non_webpack_require__ : __require;
2790
- addon = requireFunc(path.resolve(nativeBinding).replace(/(\.node)?$/, ".node"));
2791
- } else {
2792
- addon = nativeBinding;
2793
- }
2794
- if (!addon.isInitialized) {
2795
- addon.setErrorConstructor(SqliteError);
2796
- addon.isInitialized = true;
2797
- }
2798
- if (!anonymous && !fs.existsSync(path.dirname(filename))) {
2799
- throw new TypeError("Cannot open database because the directory does not exist");
2800
- }
2801
- Object.defineProperties(this, {
2802
- [util.cppdb]: { value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null) },
2803
- ...wrappers.getters
2804
- });
2805
- }
2806
- var wrappers = require_wrappers();
2807
- Database.prototype.prepare = wrappers.prepare;
2808
- Database.prototype.transaction = require_transaction();
2809
- Database.prototype.pragma = require_pragma();
2810
- Database.prototype.backup = require_backup();
2811
- Database.prototype.serialize = require_serialize();
2812
- Database.prototype.function = require_function();
2813
- Database.prototype.aggregate = require_aggregate();
2814
- Database.prototype.table = require_table();
2815
- Database.prototype.loadExtension = wrappers.loadExtension;
2816
- Database.prototype.exec = wrappers.exec;
2817
- Database.prototype.close = wrappers.close;
2818
- Database.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers;
2819
- Database.prototype.unsafeMode = wrappers.unsafeMode;
2820
- Database.prototype[util.inspect] = require_inspect();
2821
- module.exports = Database;
2822
- });
2823
-
2824
- // node_modules/better-sqlite3/lib/index.js
2825
- var require_lib = __commonJS((exports, module) => {
2826
- module.exports = require_database();
2827
- module.exports.SqliteError = require_sqlite_error();
2828
- });
2829
-
2830
2065
  // node_modules/commander/esm.mjs
2831
2066
  var import__ = __toESM(require_commander(), 1);
2832
2067
  var {
@@ -4201,12 +3436,12 @@ function mapRelationalRow(tablesConfig, tableConfig, row, buildQueryResultSelect
4201
3436
 
4202
3437
  // src/cli/index.ts
4203
3438
  import { randomUUID } from "crypto";
4204
- import { readFileSync as readFileSync2, existsSync, mkdirSync as mkdirSync2, writeFileSync } from "fs";
4205
- import { join as join2 } from "path";
4206
- import { homedir as homedir2 } from "os";
3439
+ import { readFileSync as readFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, writeFileSync } from "fs";
3440
+ import { join as join6 } from "path";
3441
+ import { homedir as homedir6 } from "os";
4207
3442
 
4208
- // node_modules/drizzle-orm/better-sqlite3/driver.js
4209
- var import_better_sqlite3 = __toESM(require_lib(), 1);
3443
+ // node_modules/drizzle-orm/bun-sqlite/driver.js
3444
+ import { Database } from "bun:sqlite";
4210
3445
 
4211
3446
  // node_modules/drizzle-orm/selection-proxy.js
4212
3447
  class SelectionProxyHandler {
@@ -6334,32 +5569,39 @@ class SQLiteTransaction extends BaseSQLiteDatabase {
6334
5569
  }
6335
5570
  }
6336
5571
 
6337
- // node_modules/drizzle-orm/better-sqlite3/session.js
6338
- class BetterSQLiteSession extends SQLiteSession {
5572
+ // node_modules/drizzle-orm/bun-sqlite/session.js
5573
+ class SQLiteBunSession extends SQLiteSession {
6339
5574
  constructor(client, dialect, schema, options = {}) {
6340
5575
  super(dialect);
6341
5576
  this.client = client;
6342
5577
  this.schema = schema;
6343
5578
  this.logger = options.logger ?? new NoopLogger;
6344
5579
  }
6345
- static [entityKind] = "BetterSQLiteSession";
5580
+ static [entityKind] = "SQLiteBunSession";
6346
5581
  logger;
5582
+ exec(query) {
5583
+ this.client.exec(query);
5584
+ }
6347
5585
  prepareQuery(query, fields, executeMethod, isResponseInArrayMode, customResultMapper) {
6348
5586
  const stmt = this.client.prepare(query.sql);
6349
5587
  return new PreparedQuery(stmt, query, this.logger, fields, executeMethod, isResponseInArrayMode, customResultMapper);
6350
5588
  }
6351
5589
  transaction(transaction, config = {}) {
6352
- const tx = new BetterSQLiteTransaction("sync", this.dialect, this, this.schema);
6353
- const nativeTx = this.client.transaction(transaction);
6354
- return nativeTx[config.behavior ?? "deferred"](tx);
5590
+ const tx = new SQLiteBunTransaction("sync", this.dialect, this, this.schema);
5591
+ let result;
5592
+ const nativeTx = this.client.transaction(() => {
5593
+ result = transaction(tx);
5594
+ });
5595
+ nativeTx[config.behavior ?? "deferred"]();
5596
+ return result;
6355
5597
  }
6356
5598
  }
6357
5599
 
6358
- class BetterSQLiteTransaction extends SQLiteTransaction {
6359
- static [entityKind] = "BetterSQLiteTransaction";
5600
+ class SQLiteBunTransaction extends SQLiteTransaction {
5601
+ static [entityKind] = "SQLiteBunTransaction";
6360
5602
  transaction(transaction) {
6361
5603
  const savepointName = `sp${this.nestedIndex}`;
6362
- const tx = new BetterSQLiteTransaction("sync", this.dialect, this.session, this.schema, this.nestedIndex + 1);
5604
+ const tx = new SQLiteBunTransaction("sync", this.dialect, this.session, this.schema, this.nestedIndex + 1);
6363
5605
  this.session.run(sql.raw(`savepoint ${savepointName}`));
6364
5606
  try {
6365
5607
  const result = transaction(tx);
@@ -6381,14 +5623,14 @@ class PreparedQuery extends SQLitePreparedQuery {
6381
5623
  this._isResponseInArrayMode = _isResponseInArrayMode;
6382
5624
  this.customResultMapper = customResultMapper;
6383
5625
  }
6384
- static [entityKind] = "BetterSQLitePreparedQuery";
5626
+ static [entityKind] = "SQLiteBunPreparedQuery";
6385
5627
  run(placeholderValues) {
6386
5628
  const params = fillPlaceholders(this.query.params, placeholderValues ?? {});
6387
5629
  this.logger.logQuery(this.query.sql, params);
6388
5630
  return this.stmt.run(...params);
6389
5631
  }
6390
5632
  all(placeholderValues) {
6391
- const { fields, joinsNotNullableMap, query, logger, stmt, customResultMapper } = this;
5633
+ const { fields, query, logger, joinsNotNullableMap, stmt, customResultMapper } = this;
6392
5634
  if (!fields && !customResultMapper) {
6393
5635
  const params = fillPlaceholders(query.params, placeholderValues ?? {});
6394
5636
  logger.logQuery(query.sql, params);
@@ -6403,14 +5645,14 @@ class PreparedQuery extends SQLitePreparedQuery {
6403
5645
  get(placeholderValues) {
6404
5646
  const params = fillPlaceholders(this.query.params, placeholderValues ?? {});
6405
5647
  this.logger.logQuery(this.query.sql, params);
6406
- const { fields, stmt, joinsNotNullableMap, customResultMapper } = this;
6407
- if (!fields && !customResultMapper) {
6408
- return stmt.get(...params);
6409
- }
6410
- const row = stmt.raw().get(...params);
5648
+ const row = this.stmt.values(...params)[0];
6411
5649
  if (!row) {
6412
5650
  return;
6413
5651
  }
5652
+ const { fields, joinsNotNullableMap, customResultMapper } = this;
5653
+ if (!fields && !customResultMapper) {
5654
+ return row;
5655
+ }
6414
5656
  if (customResultMapper) {
6415
5657
  return customResultMapper([row]);
6416
5658
  }
@@ -6419,16 +5661,16 @@ class PreparedQuery extends SQLitePreparedQuery {
6419
5661
  values(placeholderValues) {
6420
5662
  const params = fillPlaceholders(this.query.params, placeholderValues ?? {});
6421
5663
  this.logger.logQuery(this.query.sql, params);
6422
- return this.stmt.raw().all(...params);
5664
+ return this.stmt.values(...params);
6423
5665
  }
6424
5666
  isResponseInArrayMode() {
6425
5667
  return this._isResponseInArrayMode;
6426
5668
  }
6427
5669
  }
6428
5670
 
6429
- // node_modules/drizzle-orm/better-sqlite3/driver.js
6430
- class BetterSQLite3Database extends BaseSQLiteDatabase {
6431
- static [entityKind] = "BetterSQLite3Database";
5671
+ // node_modules/drizzle-orm/bun-sqlite/driver.js
5672
+ class BunSQLiteDatabase extends BaseSQLiteDatabase {
5673
+ static [entityKind] = "BunSQLiteDatabase";
6432
5674
  }
6433
5675
  function construct(client, config = {}) {
6434
5676
  const dialect = new SQLiteSyncDialect({ casing: config.casing });
@@ -6447,14 +5689,14 @@ function construct(client, config = {}) {
6447
5689
  tableNamesMap: tablesConfig.tableNamesMap
6448
5690
  };
6449
5691
  }
6450
- const session = new BetterSQLiteSession(client, dialect, schema, { logger });
6451
- const db = new BetterSQLite3Database("sync", dialect, session, schema);
5692
+ const session = new SQLiteBunSession(client, dialect, schema, { logger });
5693
+ const db = new BunSQLiteDatabase("sync", dialect, session, schema);
6452
5694
  db.$client = client;
6453
5695
  return db;
6454
5696
  }
6455
5697
  function drizzle(...params) {
6456
5698
  if (params[0] === undefined || typeof params[0] === "string") {
6457
- const instance = params[0] === undefined ? new import_better_sqlite3.default : new import_better_sqlite3.default(params[0]);
5699
+ const instance = params[0] === undefined ? new Database : new Database(params[0]);
6458
5700
  return construct(instance, params[1]);
6459
5701
  }
6460
5702
  if (isConfig(params[0])) {
@@ -6462,11 +5704,12 @@ function drizzle(...params) {
6462
5704
  if (client)
6463
5705
  return construct(client, drizzleConfig);
6464
5706
  if (typeof connection === "object") {
6465
- const { source, ...options } = connection;
6466
- const instance2 = new import_better_sqlite3.default(source, options);
5707
+ const { source, ...opts } = connection;
5708
+ const options = Object.values(opts).filter((v) => v !== undefined).length ? opts : undefined;
5709
+ const instance2 = new Database(source, options);
6467
5710
  return construct(instance2, drizzleConfig);
6468
5711
  }
6469
- const instance = new import_better_sqlite3.default(connection);
5712
+ const instance = new Database(connection);
6470
5713
  return construct(instance, drizzleConfig);
6471
5714
  }
6472
5715
  return construct(params[0], params[1]);
@@ -6479,7 +5722,7 @@ function drizzle(...params) {
6479
5722
  })(drizzle || (drizzle = {}));
6480
5723
 
6481
5724
  // src/db/index.ts
6482
- var import_better_sqlite33 = __toESM(require_lib(), 1);
5725
+ import { Database as Database2 } from "bun:sqlite";
6483
5726
  import { mkdirSync } from "fs";
6484
5727
  import { dirname, join } from "path";
6485
5728
  import { homedir } from "os";
@@ -6500,6 +5743,10 @@ var fineTunedModels = sqliteTable("fine_tuned_models", {
6500
5743
  enum: ["pending", "running", "succeeded", "failed", "cancelled"]
6501
5744
  }).notNull().default("pending"),
6502
5745
  fineTuneJobId: text("fine_tune_job_id"),
5746
+ displayName: text("display_name"),
5747
+ description: text("description"),
5748
+ collection: text("collection"),
5749
+ tags: text("tags"),
6503
5750
  createdAt: integer("created_at").notNull(),
6504
5751
  updatedAt: integer("updated_at").notNull()
6505
5752
  });
@@ -6538,6 +5785,10 @@ function createTables(sqlite) {
6538
5785
  provider TEXT NOT NULL,
6539
5786
  status TEXT NOT NULL DEFAULT 'pending',
6540
5787
  fine_tune_job_id TEXT,
5788
+ display_name TEXT,
5789
+ description TEXT,
5790
+ collection TEXT,
5791
+ tags TEXT,
6541
5792
  created_at INTEGER NOT NULL,
6542
5793
  updated_at INTEGER NOT NULL
6543
5794
  );
@@ -6566,9 +5817,9 @@ function createTables(sqlite) {
6566
5817
  function getDb(dbPath) {
6567
5818
  const resolvedPath = dbPath ?? DEFAULT_DB_PATH;
6568
5819
  ensureDir(resolvedPath);
6569
- const sqlite = new import_better_sqlite33.default(resolvedPath);
6570
- sqlite.pragma("journal_mode = WAL");
6571
- sqlite.pragma("foreign_keys = ON");
5820
+ const sqlite = new Database2(resolvedPath);
5821
+ sqlite.run("PRAGMA journal_mode = WAL");
5822
+ sqlite.run("PRAGMA foreign_keys = ON");
6572
5823
  createTables(sqlite);
6573
5824
  return drizzle(sqlite, { schema: exports_schema });
6574
5825
  }
@@ -12256,6 +11507,352 @@ function printInfo(message) {
12256
11507
  console.log(chalk.dim(" " + message));
12257
11508
  }
12258
11509
 
11510
+ // src/lib/gatherers/todos.ts
11511
+ import { Database as Database3 } from "bun:sqlite";
11512
+ import { homedir as homedir2 } from "os";
11513
+ import { join as join2 } from "path";
11514
+ var SYSTEM_PROMPT = "You are a task management assistant that helps users create, update, search, and manage tasks and projects.";
11515
+ function taskToCreateExample(task) {
11516
+ const userMsg = `Create a task: ${task.title}${task.description ? `
11517
+
11518
+ Description: ${task.description}` : ""}`;
11519
+ const taskDetails = {
11520
+ id: task.short_id ?? task.id,
11521
+ title: task.title,
11522
+ description: task.description ?? "",
11523
+ status: task.status,
11524
+ priority: task.priority,
11525
+ tags: JSON.parse(task.tags ?? "[]"),
11526
+ created_at: task.created_at
11527
+ };
11528
+ return {
11529
+ messages: [
11530
+ { role: "system", content: SYSTEM_PROMPT },
11531
+ { role: "user", content: userMsg },
11532
+ { role: "assistant", content: `Created task: ${JSON.stringify(taskDetails, null, 2)}` }
11533
+ ]
11534
+ };
11535
+ }
11536
+ function taskToStatusUpdateExample(task) {
11537
+ if (!task.completed_at && task.status === "pending")
11538
+ return null;
11539
+ const id = task.short_id ?? task.id;
11540
+ return {
11541
+ messages: [
11542
+ { role: "system", content: SYSTEM_PROMPT },
11543
+ { role: "user", content: `Mark task ${id} as ${task.status}` },
11544
+ { role: "assistant", content: `Task ${id} has been updated to status: ${task.status}. ${task.completed_at ? `Completed at: ${task.completed_at}` : ""}`.trim() }
11545
+ ]
11546
+ };
11547
+ }
11548
+ function taskToSearchExample(tasks, query) {
11549
+ const matched = tasks.filter((t) => t.title.toLowerCase().includes(query.toLowerCase())).slice(0, 5);
11550
+ return {
11551
+ messages: [
11552
+ { role: "system", content: SYSTEM_PROMPT },
11553
+ { role: "user", content: `Search tasks for: "${query}"` },
11554
+ {
11555
+ role: "assistant",
11556
+ content: matched.length > 0 ? `Found ${matched.length} task(s):
11557
+ ${matched.map((t) => `- [${t.short_id ?? t.id}] ${t.title} (${t.status})`).join(`
11558
+ `)}` : `No tasks found matching "${query}".`
11559
+ }
11560
+ ]
11561
+ };
11562
+ }
11563
+ async function gatherFromTodos(options = {}) {
11564
+ const dbPath = join2(homedir2(), ".todos", "todos.db");
11565
+ const db = new Database3(dbPath, { readonly: true, create: false });
11566
+ try {
11567
+ let query = "SELECT * FROM tasks WHERE 1=1";
11568
+ const params = [];
11569
+ if (options.since) {
11570
+ query += " AND created_at >= ?";
11571
+ params.push(options.since.toISOString());
11572
+ }
11573
+ query += " ORDER BY created_at DESC";
11574
+ if (options.limit) {
11575
+ query += " LIMIT ?";
11576
+ params.push(options.limit * 2);
11577
+ }
11578
+ const tasks = db.query(query).all(...params);
11579
+ const examples = [];
11580
+ for (const task of tasks) {
11581
+ examples.push(taskToCreateExample(task));
11582
+ const statusEx = taskToStatusUpdateExample(task);
11583
+ if (statusEx)
11584
+ examples.push(statusEx);
11585
+ }
11586
+ const searchTerms = ["urgent", "fix", "implement", "create", "update", "review"];
11587
+ for (const term of searchTerms) {
11588
+ examples.push(taskToSearchExample(tasks, term));
11589
+ }
11590
+ const finalExamples = options.limit ? examples.slice(0, options.limit) : examples;
11591
+ return {
11592
+ source: "todos",
11593
+ examples: finalExamples,
11594
+ count: finalExamples.length
11595
+ };
11596
+ } finally {
11597
+ db.close();
11598
+ }
11599
+ }
11600
+
11601
+ // src/lib/gatherers/mementos.ts
11602
+ import { Database as Database4 } from "bun:sqlite";
11603
+ import { homedir as homedir3 } from "os";
11604
+ import { join as join3 } from "path";
11605
+ var SYSTEM_PROMPT2 = "You are an AI assistant with persistent memory. You can remember and recall information across sessions to provide better, more personalized assistance.";
11606
+ function memoryToRecallExample(memory) {
11607
+ return {
11608
+ messages: [
11609
+ { role: "system", content: SYSTEM_PROMPT2 },
11610
+ { role: "user", content: `What do you remember about "${memory.key}"?` },
11611
+ {
11612
+ role: "assistant",
11613
+ content: memory.summary ? `${memory.value}
11614
+
11615
+ Summary: ${memory.summary}` : memory.value
11616
+ }
11617
+ ]
11618
+ };
11619
+ }
11620
+ function memoryToSaveExample(memory) {
11621
+ const tags = JSON.parse(memory.tags ?? "[]");
11622
+ return {
11623
+ messages: [
11624
+ { role: "system", content: SYSTEM_PROMPT2 },
11625
+ {
11626
+ role: "user",
11627
+ content: `Remember this for me: ${memory.key} = ${memory.value}${tags.length ? ` (tags: ${tags.join(", ")})` : ""}`
11628
+ },
11629
+ {
11630
+ role: "assistant",
11631
+ content: `Saved to memory: "${memory.key}" with ${memory.category} category, importance ${memory.importance}/10, scope: ${memory.scope}.`
11632
+ }
11633
+ ]
11634
+ };
11635
+ }
11636
+ function memoryToSearchExample(memories, category) {
11637
+ const matched = memories.filter((m) => m.category === category && m.status === "active").slice(0, 5);
11638
+ return {
11639
+ messages: [
11640
+ { role: "system", content: SYSTEM_PROMPT2 },
11641
+ { role: "user", content: `What ${category} memories do you have?` },
11642
+ {
11643
+ role: "assistant",
11644
+ content: matched.length > 0 ? `Here are my ${category} memories:
11645
+ ${matched.map((m) => `- ${m.key}: ${m.value.slice(0, 120)}${m.value.length > 120 ? "..." : ""}`).join(`
11646
+ `)}` : `I don't have any ${category} memories stored yet.`
11647
+ }
11648
+ ]
11649
+ };
11650
+ }
11651
+ async function gatherFromMementos(options = {}) {
11652
+ const dbPath = join3(homedir3(), ".mementos", "mementos.db");
11653
+ const db = new Database4(dbPath, { readonly: true, create: false });
11654
+ try {
11655
+ let query = "SELECT * FROM memories WHERE status = 'active'";
11656
+ const params = [];
11657
+ if (options.since) {
11658
+ query += " AND created_at >= ?";
11659
+ params.push(options.since.toISOString());
11660
+ }
11661
+ query += " ORDER BY importance DESC, created_at DESC";
11662
+ if (options.limit) {
11663
+ query += " LIMIT ?";
11664
+ params.push(options.limit * 3);
11665
+ }
11666
+ const memories = db.query(query).all(...params);
11667
+ const examples = [];
11668
+ for (const memory of memories) {
11669
+ examples.push(memoryToRecallExample(memory));
11670
+ examples.push(memoryToSaveExample(memory));
11671
+ }
11672
+ const categories = [...new Set(memories.map((m) => m.category))];
11673
+ for (const category of categories) {
11674
+ examples.push(memoryToSearchExample(memories, category));
11675
+ }
11676
+ const finalExamples = options.limit ? examples.slice(0, options.limit) : examples;
11677
+ return {
11678
+ source: "mementos",
11679
+ examples: finalExamples,
11680
+ count: finalExamples.length
11681
+ };
11682
+ } finally {
11683
+ db.close();
11684
+ }
11685
+ }
11686
+
11687
+ // src/lib/gatherers/conversations.ts
11688
+ import { Database as Database5 } from "bun:sqlite";
11689
+ import { homedir as homedir4 } from "os";
11690
+ import { join as join4 } from "path";
11691
+ var SYSTEM_PROMPT3 = "You are a helpful AI assistant participating in multi-agent conversations. You communicate clearly and collaboratively with other agents and users.";
11692
+ function windowToExample(window2) {
11693
+ if (window2.length < 2)
11694
+ return null;
11695
+ const messages = [
11696
+ { role: "system", content: SYSTEM_PROMPT3 }
11697
+ ];
11698
+ for (let i = 0;i < window2.length - 1; i++) {
11699
+ const msg = window2[i];
11700
+ if (!msg)
11701
+ continue;
11702
+ const role = i % 2 === 0 ? "user" : "assistant";
11703
+ messages.push({
11704
+ role,
11705
+ content: `[${msg.from_agent} \u2192 ${msg.to_agent ?? msg.space ?? "all"}]: ${msg.content}`
11706
+ });
11707
+ }
11708
+ const last = window2[window2.length - 1];
11709
+ if (!last)
11710
+ return null;
11711
+ messages.push({
11712
+ role: "assistant",
11713
+ content: `[${last.from_agent} \u2192 ${last.to_agent ?? last.space ?? "all"}]: ${last.content}`
11714
+ });
11715
+ return { messages };
11716
+ }
11717
+ async function gatherFromConversations(options = {}) {
11718
+ const dbPath = join4(homedir4(), ".conversations", "messages.db");
11719
+ const db = new Database5(dbPath, { readonly: true, create: false });
11720
+ try {
11721
+ let query = "SELECT * FROM messages WHERE 1=1";
11722
+ const params = [];
11723
+ if (options.since) {
11724
+ query += " AND created_at >= ?";
11725
+ params.push(options.since.toISOString());
11726
+ }
11727
+ query += " ORDER BY session_id, created_at ASC";
11728
+ const allMessages = db.query(query).all(...params);
11729
+ const sessions = new Map;
11730
+ for (const msg of allMessages) {
11731
+ const msgs = sessions.get(msg.session_id) ?? [];
11732
+ msgs.push(msg);
11733
+ sessions.set(msg.session_id, msgs);
11734
+ }
11735
+ const examples = [];
11736
+ const windowSize = 4;
11737
+ for (const [, sessionMsgs] of sessions) {
11738
+ if (sessionMsgs.length < 2)
11739
+ continue;
11740
+ for (let start = 0;start <= sessionMsgs.length - 2; start++) {
11741
+ const end = Math.min(start + windowSize, sessionMsgs.length);
11742
+ const window2 = sessionMsgs.slice(start, end);
11743
+ const example = windowToExample(window2);
11744
+ if (example)
11745
+ examples.push(example);
11746
+ }
11747
+ }
11748
+ const finalExamples = options.limit ? examples.slice(0, options.limit) : examples;
11749
+ return {
11750
+ source: "conversations",
11751
+ examples: finalExamples,
11752
+ count: finalExamples.length
11753
+ };
11754
+ } finally {
11755
+ db.close();
11756
+ }
11757
+ }
11758
+
11759
+ // src/lib/gatherers/sessions.ts
11760
+ import { readdir, readFile, stat } from "fs/promises";
11761
+ import { existsSync } from "fs";
11762
+ import { join as join5 } from "path";
11763
+ import { homedir as homedir5 } from "os";
11764
+ var SYSTEM_PROMPT4 = "You are Claude Code, an AI assistant built by Anthropic that helps developers with coding, architecture, debugging, and software engineering tasks.";
11765
+ function extractText(content) {
11766
+ if (typeof content === "string")
11767
+ return content;
11768
+ return content.filter((c) => c.type === "text" && c.text).map((c) => c.text).join(`
11769
+ `).trim();
11770
+ }
11771
+ async function gatherFromSessions(options = {}) {
11772
+ const { limit: limit2 = 1000 } = options;
11773
+ const examples = [];
11774
+ const claudeDir = join5(homedir5(), ".claude", "projects");
11775
+ if (!existsSync(claudeDir)) {
11776
+ return { source: "sessions", examples: [], count: 0 };
11777
+ }
11778
+ const projectDirs = await readdir(claudeDir).catch(() => []);
11779
+ for (const projectDir of projectDirs) {
11780
+ if (examples.length >= limit2)
11781
+ break;
11782
+ const projectPath = join5(claudeDir, projectDir);
11783
+ const files = await readdir(projectPath).catch(() => []);
11784
+ for (const file of files) {
11785
+ if (examples.length >= limit2)
11786
+ break;
11787
+ if (!file.endsWith(".jsonl"))
11788
+ continue;
11789
+ const filePath = join5(projectPath, file);
11790
+ if (options.since) {
11791
+ const fileStat = await stat(filePath).catch(() => null);
11792
+ if (fileStat && fileStat.mtime < options.since)
11793
+ continue;
11794
+ }
11795
+ const content = await readFile(filePath, "utf-8").catch(() => "");
11796
+ if (!content.trim())
11797
+ continue;
11798
+ const lines = content.trim().split(`
11799
+ `);
11800
+ const turns = [];
11801
+ for (const line of lines) {
11802
+ try {
11803
+ const entry = JSON.parse(line);
11804
+ if ((entry.type === "user" || entry.type === "human") && entry.message?.content) {
11805
+ const text2 = extractText(entry.message.content);
11806
+ if (text2.trim())
11807
+ turns.push({ role: "user", content: text2.trim() });
11808
+ } else if (entry.type === "assistant" && entry.message?.content) {
11809
+ const text2 = extractText(entry.message.content);
11810
+ if (text2.trim())
11811
+ turns.push({ role: "assistant", content: text2.trim() });
11812
+ }
11813
+ } catch {}
11814
+ }
11815
+ const windowSize = 6;
11816
+ for (let start = 0;start < turns.length - 1 && examples.length < limit2; start++) {
11817
+ const window2 = turns.slice(start, start + windowSize);
11818
+ if (!window2[0] || window2[0].role !== "user")
11819
+ continue;
11820
+ const lastAssistantIdx = window2.map((t) => t.role).lastIndexOf("assistant");
11821
+ if (lastAssistantIdx < 1)
11822
+ continue;
11823
+ const usedTurns = window2.slice(0, lastAssistantIdx + 1);
11824
+ examples.push({
11825
+ messages: [
11826
+ { role: "system", content: SYSTEM_PROMPT4 },
11827
+ ...usedTurns
11828
+ ]
11829
+ });
11830
+ }
11831
+ }
11832
+ }
11833
+ return { source: "sessions", examples, count: examples.length };
11834
+ }
11835
+ // src/lib/gatherers/index.ts
11836
+ var ALL_SOURCES = ["todos", "mementos", "conversations", "sessions"];
11837
+ async function gatherAll(sources, options = {}) {
11838
+ const targets = sources.includes("all") ? [...ALL_SOURCES] : sources;
11839
+ const results = await Promise.allSettled(targets.map((source) => {
11840
+ switch (source) {
11841
+ case "todos":
11842
+ return gatherFromTodos(options);
11843
+ case "mementos":
11844
+ return gatherFromMementos(options);
11845
+ case "conversations":
11846
+ return gatherFromConversations(options);
11847
+ case "sessions":
11848
+ return gatherFromSessions(options);
11849
+ default:
11850
+ return Promise.resolve({ source, examples: [], count: 0 });
11851
+ }
11852
+ }));
11853
+ return results.filter((r) => r.status === "fulfilled").map((r) => r.value);
11854
+ }
11855
+
12259
11856
  // src/cli/index.ts
12260
11857
  var program2 = new Command;
12261
11858
  program2.name("brains").description("Fine-tuned model tracker and trainer").version("0.0.1");
@@ -12268,7 +11865,14 @@ modelsCmd.command("list").description("List all tracked fine-tuned models").acti
12268
11865
  printInfo("No models tracked yet. Use 'brains finetune start' to train one.");
12269
11866
  return;
12270
11867
  }
12271
- printTable(["ID", "Name", "Provider", "Status", "Base Model"], models.map((m) => [m.id, m.name, m.provider, printStatus(m.status), m.baseModel]));
11868
+ printTable(["ID", "Display Name", "Provider", "Status", "Collection", "Base Model"], models.map((m) => [
11869
+ m.id,
11870
+ m.displayName ?? m.name,
11871
+ m.provider,
11872
+ printStatus(m.status),
11873
+ m.collection ?? "",
11874
+ m.baseModel
11875
+ ]));
12272
11876
  } catch (err) {
12273
11877
  printError(err instanceof Error ? err.message : String(err));
12274
11878
  process.exit(1);
@@ -12283,8 +11887,13 @@ modelsCmd.command("show <id>").description("Show details of a specific model").a
12283
11887
  process.exit(1);
12284
11888
  }
12285
11889
  console.log();
11890
+ const tagsList = model.tags ? JSON.parse(model.tags).join(", ") : "(none)";
12286
11891
  console.log(` ID: ${model.id}`);
12287
11892
  console.log(` Name: ${model.name}`);
11893
+ console.log(` Display Name: ${model.displayName ?? "(none)"}`);
11894
+ console.log(` Description: ${model.description ?? "(none)"}`);
11895
+ console.log(` Collection: ${model.collection ?? "(none)"}`);
11896
+ console.log(` Tags: ${tagsList}`);
12288
11897
  console.log(` Provider: ${model.provider}`);
12289
11898
  console.log(` Status: ${printStatus(model.status)}`);
12290
11899
  console.log(` Base Model: ${model.baseModel}`);
@@ -12297,6 +11906,72 @@ modelsCmd.command("show <id>").description("Show details of a specific model").a
12297
11906
  process.exit(1);
12298
11907
  }
12299
11908
  });
11909
+ modelsCmd.command("rename <id> <displayName>").description("Set the display name of a model").action(async (id, displayName) => {
11910
+ try {
11911
+ const db = getDb();
11912
+ await db.update(fineTunedModels).set({ displayName, updatedAt: Date.now() }).where(eq(fineTunedModels.id, id));
11913
+ printSuccess(`Display name set to "${displayName}"`);
11914
+ } catch (err) {
11915
+ printError(err instanceof Error ? err.message : String(err));
11916
+ process.exit(1);
11917
+ }
11918
+ });
11919
+ modelsCmd.command("describe <id> <description>").description("Set the description of a model").action(async (id, description) => {
11920
+ try {
11921
+ const db = getDb();
11922
+ await db.update(fineTunedModels).set({ description, updatedAt: Date.now() }).where(eq(fineTunedModels.id, id));
11923
+ printSuccess(`Description updated.`);
11924
+ } catch (err) {
11925
+ printError(err instanceof Error ? err.message : String(err));
11926
+ process.exit(1);
11927
+ }
11928
+ });
11929
+ modelsCmd.command("tag <id> <tag>").description("Add a tag to a model").action(async (id, tag) => {
11930
+ try {
11931
+ const db = getDb();
11932
+ const [model] = await db.select().from(fineTunedModels).where(eq(fineTunedModels.id, id));
11933
+ if (!model) {
11934
+ printError(`Model not found: ${id}`);
11935
+ process.exit(1);
11936
+ }
11937
+ const existing = model.tags ? JSON.parse(model.tags) : [];
11938
+ if (!existing.includes(tag)) {
11939
+ existing.push(tag);
11940
+ }
11941
+ await db.update(fineTunedModels).set({ tags: JSON.stringify(existing), updatedAt: Date.now() }).where(eq(fineTunedModels.id, id));
11942
+ printSuccess(`Tag "${tag}" added. Tags: ${existing.join(", ")}`);
11943
+ } catch (err) {
11944
+ printError(err instanceof Error ? err.message : String(err));
11945
+ process.exit(1);
11946
+ }
11947
+ });
11948
+ modelsCmd.command("untag <id> <tag>").description("Remove a tag from a model").action(async (id, tag) => {
11949
+ try {
11950
+ const db = getDb();
11951
+ const [model] = await db.select().from(fineTunedModels).where(eq(fineTunedModels.id, id));
11952
+ if (!model) {
11953
+ printError(`Model not found: ${id}`);
11954
+ process.exit(1);
11955
+ }
11956
+ const existing = model.tags ? JSON.parse(model.tags) : [];
11957
+ const updated = existing.filter((t) => t !== tag);
11958
+ await db.update(fineTunedModels).set({ tags: JSON.stringify(updated), updatedAt: Date.now() }).where(eq(fineTunedModels.id, id));
11959
+ printSuccess(`Tag "${tag}" removed. Tags: ${updated.join(", ") || "(none)"}`);
11960
+ } catch (err) {
11961
+ printError(err instanceof Error ? err.message : String(err));
11962
+ process.exit(1);
11963
+ }
11964
+ });
11965
+ modelsCmd.command("collection <id> <collectionName>").description("Set the collection of a model").action(async (id, collectionName) => {
11966
+ try {
11967
+ const db = getDb();
11968
+ await db.update(fineTunedModels).set({ collection: collectionName, updatedAt: Date.now() }).where(eq(fineTunedModels.id, id));
11969
+ printSuccess(`Collection set to "${collectionName}"`);
11970
+ } catch (err) {
11971
+ printError(err instanceof Error ? err.message : String(err));
11972
+ process.exit(1);
11973
+ }
11974
+ });
12300
11975
  var finetuneCmd = program2.command("finetune").description("Manage fine-tuning jobs");
12301
11976
  finetuneCmd.command("start").description("Start a fine-tuning job").requiredOption("--provider <provider>", "Provider to use (openai|thinker-labs)").requiredOption("--base-model <model>", "Base model to fine-tune (e.g. gpt-4o-mini-2024-07-18)").requiredOption("--dataset <path>", "Path to the JSONL training dataset").requiredOption("--name <name>", "Human-readable name for this fine-tuned model").action(async (opts) => {
12302
11977
  try {
@@ -12304,7 +11979,7 @@ finetuneCmd.command("start").description("Start a fine-tuning job").requiredOpti
12304
11979
  printError(`Unknown provider: ${opts.provider}. Use 'openai' or 'thinker-labs'.`);
12305
11980
  process.exit(1);
12306
11981
  }
12307
- if (!existsSync(opts.dataset)) {
11982
+ if (!existsSync2(opts.dataset)) {
12308
11983
  printError(`Dataset file not found: ${opts.dataset}`);
12309
11984
  process.exit(1);
12310
11985
  }
@@ -12411,7 +12086,7 @@ finetuneCmd.command("list").description("List all fine-tuning jobs").option("--p
12411
12086
  process.exit(1);
12412
12087
  }
12413
12088
  });
12414
- var DEFAULT_DATASETS_DIR = join2(homedir2(), ".brains", "datasets");
12089
+ var DEFAULT_DATASETS_DIR = join6(homedir6(), ".brains", "datasets");
12415
12090
  var dataCmd = program2.command("data").description("Manage training datasets");
12416
12091
  dataCmd.command("gather").description("Gather training data from agent memory sources").option("--source <source>", "Data source: todos|mementos|conversations|sessions|all", "all").option("--output <dir>", "Output directory", DEFAULT_DATASETS_DIR).option("--limit <n>", "Maximum number of examples to gather", "500").action(async (opts) => {
12417
12092
  const validSources = ["todos", "mementos", "conversations", "sessions", "all"];
@@ -12427,43 +12102,32 @@ dataCmd.command("gather").description("Gather training data from agent memory so
12427
12102
  try {
12428
12103
  mkdirSync2(opts.output, { recursive: true });
12429
12104
  const sources = opts.source === "all" ? ["todos", "mementos", "conversations", "sessions"] : [opts.source];
12430
- let totalExamples = 0;
12431
12105
  const now = Date.now();
12432
12106
  const db = getDb();
12433
- for (const source of sources) {
12434
- printInfo(`Gathering from ${source} \u2026`);
12435
- try {
12436
- const gathererPath = new URL(`../lib/gatherers/${source}.js`, import.meta.url);
12437
- const mod = await import(gathererPath.pathname).catch(() => null);
12438
- if (!mod || typeof mod.gather !== "function") {
12439
- printInfo(` No gatherer found for source '${source}', skipping.`);
12440
- continue;
12441
- }
12442
- const result = await mod.gather({ limit: limit2, outputDir: opts.output });
12443
- const count = result?.count ?? 0;
12444
- const examples = result?.examples ?? [];
12445
- totalExamples += count;
12446
- if (count === 0) {
12447
- printInfo(` No examples gathered from ${source}.`);
12448
- continue;
12449
- }
12450
- const fileName = `${source}-${now}.jsonl`;
12451
- const filePath = join2(opts.output, fileName);
12452
- writeFileSync(filePath, examples.map((e) => JSON.stringify(e)).join(`
12107
+ const results = await gatherAll(sources, { limit: limit2 });
12108
+ let totalExamples = 0;
12109
+ for (const result of results) {
12110
+ const { source, examples, count } = result;
12111
+ printInfo(`Gathered from ${source} \u2026`);
12112
+ if (count === 0) {
12113
+ printInfo(` No examples gathered from ${source}.`);
12114
+ continue;
12115
+ }
12116
+ totalExamples += count;
12117
+ const fileName = `${source}-${now}.jsonl`;
12118
+ const filePath = join6(opts.output, fileName);
12119
+ writeFileSync(filePath, examples.map((e) => JSON.stringify(e)).join(`
12453
12120
  `) + `
12454
12121
  `, "utf8");
12455
- const datasetId = randomUUID();
12456
- await db.insert(trainingDatasets).values({
12457
- id: datasetId,
12458
- source,
12459
- filePath,
12460
- exampleCount: count,
12461
- createdAt: now
12462
- });
12463
- printSuccess(` ${count} examples \u2192 ${filePath}`);
12464
- } catch (innerErr) {
12465
- printError(` Failed to gather from ${source}: ${innerErr instanceof Error ? innerErr.message : String(innerErr)}`);
12466
- }
12122
+ const datasetId = randomUUID();
12123
+ await db.insert(trainingDatasets).values({
12124
+ id: datasetId,
12125
+ source,
12126
+ filePath,
12127
+ exampleCount: count,
12128
+ createdAt: now
12129
+ });
12130
+ printSuccess(` ${count} examples \u2192 ${filePath}`);
12467
12131
  }
12468
12132
  console.log();
12469
12133
  printSuccess(`Total examples gathered: ${totalExamples}`);
@@ -12473,7 +12137,7 @@ dataCmd.command("gather").description("Gather training data from agent memory so
12473
12137
  }
12474
12138
  });
12475
12139
  dataCmd.command("preview <file>").description("Preview a JSONL training file").option("-n, --count <n>", "Number of examples to show", "5").action((file, opts) => {
12476
- if (!existsSync(file)) {
12140
+ if (!existsSync2(file)) {
12477
12141
  printError(`File not found: ${file}`);
12478
12142
  process.exit(1);
12479
12143
  }
@@ -12528,4 +12192,59 @@ dataCmd.command("list").description("List all gathered datasets").action(async (
12528
12192
  process.exit(1);
12529
12193
  }
12530
12194
  });
12195
+ var collectionsCmd = program2.command("collections").description("Manage model collections");
12196
+ collectionsCmd.action(async () => {
12197
+ await listCollections();
12198
+ });
12199
+ async function listCollections() {
12200
+ try {
12201
+ const db = getDb();
12202
+ const rows = await db.select({
12203
+ collection: fineTunedModels.collection,
12204
+ count: sql`count(*)`.as("count"),
12205
+ names: sql`group_concat(coalesce(${fineTunedModels.displayName}, ${fineTunedModels.name}), ', ')`.as("names")
12206
+ }).from(fineTunedModels).groupBy(fineTunedModels.collection);
12207
+ if (rows.length === 0) {
12208
+ printInfo("No collections found. Set a collection with 'brains models set-collection'.");
12209
+ return;
12210
+ }
12211
+ printTable(["Collection", "Model Count", "Models"], rows.map((r) => [
12212
+ r.collection ?? "(none)",
12213
+ String(r.count),
12214
+ r.names ?? ""
12215
+ ]));
12216
+ } catch (err) {
12217
+ printError(err instanceof Error ? err.message : String(err));
12218
+ process.exit(1);
12219
+ }
12220
+ }
12221
+ collectionsCmd.command("list").description("List all collections with model counts").action(async () => {
12222
+ await listCollections();
12223
+ });
12224
+ collectionsCmd.command("show <name>").description("List all models in a collection").action(async (name) => {
12225
+ try {
12226
+ const db = getDb();
12227
+ const models = await db.select().from(fineTunedModels).where(eq(fineTunedModels.collection, name));
12228
+ if (models.length === 0) {
12229
+ printInfo(`No models found in collection '${name}'.`);
12230
+ return;
12231
+ }
12232
+ printTable(["ID", "Name", "Provider", "Status", "Base Model"], models.map((m) => [m.id, m.name, m.provider, printStatus(m.status), m.baseModel]));
12233
+ } catch (err) {
12234
+ printError(err instanceof Error ? err.message : String(err));
12235
+ process.exit(1);
12236
+ }
12237
+ });
12238
+ collectionsCmd.command("rename <oldName> <newName>").description("Rename a collection across all models").action(async (oldName, newName) => {
12239
+ try {
12240
+ const db = getDb();
12241
+ const affected = await db.select({ id: fineTunedModels.id }).from(fineTunedModels).where(eq(fineTunedModels.collection, oldName));
12242
+ const count = affected.length;
12243
+ await db.update(fineTunedModels).set({ collection: newName, updatedAt: Date.now() }).where(eq(fineTunedModels.collection, oldName));
12244
+ printSuccess(`Renamed collection '${oldName}' \u2192 '${newName}' (${count} models updated)`);
12245
+ } catch (err) {
12246
+ printError(err instanceof Error ? err.message : String(err));
12247
+ process.exit(1);
12248
+ }
12249
+ });
12531
12250
  program2.parse();