wolbarg 0.5.5 → 0.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/README.md +73 -292
- package/dist/cli.js +515 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +532 -116
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +145 -8
- package/dist/index.d.ts +145 -8
- package/dist/index.js +518 -119
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import fs6 from "node:fs";
|
|
2
|
-
import path7 from "node:path";
|
|
1
|
+
import fs6, { existsSync, readFileSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import path7, { isAbsolute, resolve, dirname, join } from "node:path";
|
|
3
3
|
import { createHash } from 'crypto';
|
|
4
4
|
import fs from 'fs/promises';
|
|
5
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
5
6
|
import { DatabaseSync } from "node:sqlite";
|
|
6
7
|
import * as sqliteVec from 'sqlite-vec';
|
|
7
|
-
import { AsyncLocalStorage } from 'async_hooks';
|
|
8
8
|
import { EventEmitter } from 'events';
|
|
9
9
|
|
|
10
10
|
// src/core/wolbarg.ts
|
|
@@ -445,8 +445,8 @@ var AsyncMutex = class {
|
|
|
445
445
|
*/
|
|
446
446
|
async runExclusive(fn) {
|
|
447
447
|
let release;
|
|
448
|
-
const next = new Promise((
|
|
449
|
-
release =
|
|
448
|
+
const next = new Promise((resolve3) => {
|
|
449
|
+
release = resolve3;
|
|
450
450
|
});
|
|
451
451
|
const previous = this.chain;
|
|
452
452
|
this.chain = previous.then(() => next);
|
|
@@ -2238,19 +2238,35 @@ var DEFAULT_CONCURRENCY = {
|
|
|
2238
2238
|
maxRetries: 5,
|
|
2239
2239
|
baseBackoffMs: 50,
|
|
2240
2240
|
maxBackoffMs: 2e3,
|
|
2241
|
-
lockTimeoutMs: 5e3
|
|
2241
|
+
lockTimeoutMs: 5e3,
|
|
2242
|
+
lockDeadlineMs: 3e4
|
|
2243
|
+
};
|
|
2244
|
+
var MULTI_PROCESS_CONCURRENCY = {
|
|
2245
|
+
maxRetries: 12,
|
|
2246
|
+
baseBackoffMs: 40,
|
|
2247
|
+
maxBackoffMs: 3e3,
|
|
2248
|
+
lockTimeoutMs: 15e3,
|
|
2249
|
+
lockDeadlineMs: 9e4
|
|
2242
2250
|
};
|
|
2243
2251
|
function resolveConcurrencyConfig(input) {
|
|
2252
|
+
const base = input?.multiProcess ? MULTI_PROCESS_CONCURRENCY : DEFAULT_CONCURRENCY;
|
|
2253
|
+
const maxRetries = input?.maxRetries ?? base.maxRetries;
|
|
2254
|
+
const baseBackoffMs = input?.baseBackoffMs ?? base.baseBackoffMs;
|
|
2255
|
+
const maxBackoffMs = input?.maxBackoffMs ?? base.maxBackoffMs;
|
|
2256
|
+
const lockTimeoutMs = input?.lockTimeoutMs ?? base.lockTimeoutMs;
|
|
2257
|
+
const lockDeadlineMs = input?.lockDeadlineMs ?? Math.max(base.lockDeadlineMs, lockTimeoutMs * (maxRetries + 1));
|
|
2244
2258
|
const resolved = {
|
|
2245
|
-
maxRetries
|
|
2246
|
-
baseBackoffMs
|
|
2247
|
-
maxBackoffMs
|
|
2248
|
-
lockTimeoutMs
|
|
2259
|
+
maxRetries,
|
|
2260
|
+
baseBackoffMs,
|
|
2261
|
+
maxBackoffMs,
|
|
2262
|
+
lockTimeoutMs,
|
|
2263
|
+
lockDeadlineMs
|
|
2249
2264
|
};
|
|
2250
2265
|
assertPositiveInt(resolved.maxRetries, "concurrency.maxRetries");
|
|
2251
2266
|
assertPositiveNumber(resolved.baseBackoffMs, "concurrency.baseBackoffMs");
|
|
2252
2267
|
assertPositiveNumber(resolved.maxBackoffMs, "concurrency.maxBackoffMs");
|
|
2253
2268
|
assertPositiveInt(resolved.lockTimeoutMs, "concurrency.lockTimeoutMs");
|
|
2269
|
+
assertPositiveInt(resolved.lockDeadlineMs, "concurrency.lockDeadlineMs");
|
|
2254
2270
|
if (resolved.maxBackoffMs < resolved.baseBackoffMs) {
|
|
2255
2271
|
throw new ConfigurationError(
|
|
2256
2272
|
"concurrency.maxBackoffMs must be >= concurrency.baseBackoffMs"
|
|
@@ -2276,19 +2292,25 @@ function isSqliteBusyError(error) {
|
|
|
2276
2292
|
return lower.includes("database is locked") || lower.includes("sqlite_busy") || lower.includes("busy");
|
|
2277
2293
|
}
|
|
2278
2294
|
function sleep(ms) {
|
|
2279
|
-
return new Promise((
|
|
2295
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
2280
2296
|
}
|
|
2281
2297
|
function backoffDelay(attempt, config) {
|
|
2282
2298
|
const exp = Math.min(
|
|
2283
2299
|
config.maxBackoffMs,
|
|
2284
2300
|
config.baseBackoffMs * 2 ** attempt
|
|
2285
2301
|
);
|
|
2286
|
-
|
|
2287
|
-
|
|
2302
|
+
return Math.random() * exp;
|
|
2303
|
+
}
|
|
2304
|
+
function deadlineExceeded(startedAt, config) {
|
|
2305
|
+
return performance.now() - startedAt >= config.lockDeadlineMs;
|
|
2288
2306
|
}
|
|
2289
2307
|
async function withImmediateTransaction(db, config, fn, onRetry) {
|
|
2290
2308
|
let lastError;
|
|
2309
|
+
const startedAt = performance.now();
|
|
2291
2310
|
for (let attempt = 0; attempt <= config.maxRetries; attempt += 1) {
|
|
2311
|
+
if (attempt > 0 && deadlineExceeded(startedAt, config)) {
|
|
2312
|
+
break;
|
|
2313
|
+
}
|
|
2292
2314
|
try {
|
|
2293
2315
|
db.exec("BEGIN IMMEDIATE");
|
|
2294
2316
|
try {
|
|
@@ -2308,7 +2330,7 @@ async function withImmediateTransaction(db, config, fn, onRetry) {
|
|
|
2308
2330
|
if (!isBusy) {
|
|
2309
2331
|
throw error;
|
|
2310
2332
|
}
|
|
2311
|
-
if (attempt >= config.maxRetries) {
|
|
2333
|
+
if (attempt >= config.maxRetries || deadlineExceeded(startedAt, config)) {
|
|
2312
2334
|
break;
|
|
2313
2335
|
}
|
|
2314
2336
|
const delay = backoffDelay(attempt, config);
|
|
@@ -2321,7 +2343,7 @@ async function withImmediateTransaction(db, config, fn, onRetry) {
|
|
|
2321
2343
|
{
|
|
2322
2344
|
cause: lastError instanceof Error ? lastError : void 0,
|
|
2323
2345
|
reason: "SQLITE_BUSY exhausted retries",
|
|
2324
|
-
suggestion: "Increase concurrency.maxRetries
|
|
2346
|
+
suggestion: "Increase concurrency.maxRetries / concurrency.lockDeadlineMs, set concurrency.multiProcess: true for shared-file writers, or use the Postgres backend."
|
|
2325
2347
|
}
|
|
2326
2348
|
);
|
|
2327
2349
|
}
|
|
@@ -2379,6 +2401,20 @@ var SqliteStorageProvider = class _SqliteStorageProvider {
|
|
|
2379
2401
|
transactionDepth = 0;
|
|
2380
2402
|
/** Incrementing counter for deterministic savepoint names. */
|
|
2381
2403
|
savepointCounter = 0;
|
|
2404
|
+
/**
|
|
2405
|
+
* Serializes top-level write transactions on the single SQLite connection.
|
|
2406
|
+
* SQLite is single-writer; serializing in-process avoids SQLITE_BUSY churn
|
|
2407
|
+
* AND prevents interleaved BEGIN/SAVEPOINT state corruption when many async
|
|
2408
|
+
* callers share one connection (see "no such savepoint" class of bugs).
|
|
2409
|
+
*/
|
|
2410
|
+
writeMutex = new AsyncMutex();
|
|
2411
|
+
/**
|
|
2412
|
+
* Async-context flag: true while executing inside a top-level write
|
|
2413
|
+
* transaction held by this provider. Used so writes issued from within an
|
|
2414
|
+
* ambient transaction (e.g. compress()) join that ACID unit, WITHOUT
|
|
2415
|
+
* mistaking the coalescer's own flush window for an ambient transaction.
|
|
2416
|
+
*/
|
|
2417
|
+
txContext = new AsyncLocalStorage();
|
|
2382
2418
|
/** Hot in-process ANN for blob backend (sqlite-vec unavailable platforms). */
|
|
2383
2419
|
memoryIndex = null;
|
|
2384
2420
|
memoryIndexDirty = false;
|
|
@@ -2421,62 +2457,85 @@ var SqliteStorageProvider = class _SqliteStorageProvider {
|
|
|
2421
2457
|
}
|
|
2422
2458
|
/** Open the database, run migrations, and prepare statements. */
|
|
2423
2459
|
async open() {
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
this.sqliteVecLoaded = this.tryLoadSqliteVec(db);
|
|
2444
|
-
this.runMigrations(db);
|
|
2445
|
-
this.statements = this.prepareStatements(db);
|
|
2446
|
-
const backend = this.readMetaString(META_KEYS.vectorBackend);
|
|
2447
|
-
const dims = this.readMetaNumber(META_KEYS.embeddingDimensions);
|
|
2448
|
-
if (backend) {
|
|
2449
|
-
this.vectorBackend = backend;
|
|
2450
|
-
} else if (this.sqliteVecLoaded) {
|
|
2451
|
-
this.vectorBackend = "sqlite-vec";
|
|
2452
|
-
} else {
|
|
2453
|
-
if (!warnedSqliteVecFallback) {
|
|
2454
|
-
warnedSqliteVecFallback = true;
|
|
2455
|
-
warnLogger.warn(
|
|
2456
|
-
"sqlite-vec unavailable on this platform; using blob ANN fallback."
|
|
2460
|
+
const startedAt = performance.now();
|
|
2461
|
+
let attempt = 0;
|
|
2462
|
+
for (; ; ) {
|
|
2463
|
+
try {
|
|
2464
|
+
this.openOnce();
|
|
2465
|
+
return;
|
|
2466
|
+
} catch (error) {
|
|
2467
|
+
try {
|
|
2468
|
+
this.db?.close();
|
|
2469
|
+
} catch {
|
|
2470
|
+
}
|
|
2471
|
+
this.db = null;
|
|
2472
|
+
this.statements = null;
|
|
2473
|
+
const busy = isSqliteBusyError(error);
|
|
2474
|
+
const exhausted = attempt >= this.concurrency.maxRetries || performance.now() - startedAt >= this.concurrency.lockDeadlineMs;
|
|
2475
|
+
if (!busy || exhausted) {
|
|
2476
|
+
throw new InitializationError(
|
|
2477
|
+
`Failed to open SQLite database: ${this.describe(error)}`,
|
|
2478
|
+
{ cause: error instanceof Error ? error : void 0 }
|
|
2457
2479
|
);
|
|
2458
2480
|
}
|
|
2459
|
-
|
|
2481
|
+
const base = Math.min(
|
|
2482
|
+
this.concurrency.maxBackoffMs,
|
|
2483
|
+
this.concurrency.baseBackoffMs * 2 ** attempt
|
|
2484
|
+
);
|
|
2485
|
+
const delay = Math.random() * base;
|
|
2486
|
+
this.retryLog?.(
|
|
2487
|
+
`SQLITE_BUSY during open attempt=${attempt + 1} backoffMs=${Math.round(delay)}`
|
|
2488
|
+
);
|
|
2489
|
+
attempt += 1;
|
|
2490
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
2460
2491
|
}
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
/** Single open attempt — connect, apply pragmas, migrate, prepare. */
|
|
2495
|
+
openOnce() {
|
|
2496
|
+
const dbPath = this.resolvePath(this.connectionString);
|
|
2497
|
+
this.resolvedPath = dbPath;
|
|
2498
|
+
if (dbPath !== ":memory:") {
|
|
2499
|
+
fs6.mkdirSync(path7.dirname(dbPath), { recursive: true });
|
|
2500
|
+
}
|
|
2501
|
+
const db = new DatabaseSync(dbPath, { allowExtension: true });
|
|
2502
|
+
this.db = db;
|
|
2503
|
+
db.exec(`PRAGMA busy_timeout = ${this.concurrency.lockTimeoutMs};`);
|
|
2504
|
+
db.exec("PRAGMA journal_mode = WAL;");
|
|
2505
|
+
db.exec(`
|
|
2506
|
+
PRAGMA synchronous = NORMAL;
|
|
2507
|
+
PRAGMA foreign_keys = ON;
|
|
2508
|
+
PRAGMA temp_store = MEMORY;
|
|
2509
|
+
PRAGMA cache_size = -32768;
|
|
2510
|
+
PRAGMA mmap_size = 134217728;
|
|
2511
|
+
PRAGMA wal_autocheckpoint = 2000;
|
|
2512
|
+
PRAGMA recursive_triggers = OFF;
|
|
2513
|
+
`);
|
|
2514
|
+
this.sqliteVecLoaded = this.tryLoadSqliteVec(db);
|
|
2515
|
+
this.runMigrations(db);
|
|
2516
|
+
this.statements = this.prepareStatements(db);
|
|
2517
|
+
const backend = this.readMetaString(META_KEYS.vectorBackend);
|
|
2518
|
+
const dims = this.readMetaNumber(META_KEYS.embeddingDimensions);
|
|
2519
|
+
if (backend) {
|
|
2520
|
+
this.vectorBackend = backend;
|
|
2521
|
+
} else if (this.sqliteVecLoaded) {
|
|
2522
|
+
this.vectorBackend = "sqlite-vec";
|
|
2523
|
+
} else {
|
|
2524
|
+
if (!warnedSqliteVecFallback) {
|
|
2525
|
+
warnedSqliteVecFallback = true;
|
|
2526
|
+
warnLogger.warn(
|
|
2527
|
+
"sqlite-vec unavailable on this platform; using blob ANN fallback."
|
|
2528
|
+
);
|
|
2468
2529
|
}
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2530
|
+
this.vectorBackend = "blob";
|
|
2531
|
+
}
|
|
2532
|
+
if (dims !== null) {
|
|
2533
|
+
this.vectorDimensions = dims;
|
|
2534
|
+
this.ensureVectorStorage(dims);
|
|
2535
|
+
this.reprepareVectorStatements();
|
|
2536
|
+
if (this.vectorBackend === "blob") {
|
|
2537
|
+
this.memoryIndexDirty = true;
|
|
2473
2538
|
}
|
|
2474
|
-
this.db = null;
|
|
2475
|
-
this.statements = null;
|
|
2476
|
-
throw new InitializationError(
|
|
2477
|
-
`Failed to open SQLite database: ${this.describe(error)}`,
|
|
2478
|
-
{ cause: error instanceof Error ? error : void 0 }
|
|
2479
|
-
);
|
|
2480
2539
|
}
|
|
2481
2540
|
}
|
|
2482
2541
|
/** Drain pending inserts, optimize, and close the SQLite connection. */
|
|
@@ -2549,8 +2608,11 @@ var SqliteStorageProvider = class _SqliteStorageProvider {
|
|
|
2549
2608
|
/** Insert a single memory row (coalesced under concurrent writers). */
|
|
2550
2609
|
async insertMemory(input) {
|
|
2551
2610
|
this.requireVectorReady();
|
|
2552
|
-
|
|
2553
|
-
this.
|
|
2611
|
+
if (this.txContext.getStore() === true) {
|
|
2612
|
+
return this.insertMemoryImmediate(input);
|
|
2613
|
+
}
|
|
2614
|
+
return new Promise((resolve3, reject) => {
|
|
2615
|
+
this.insertQueue.push({ input, resolve: resolve3, reject });
|
|
2554
2616
|
if (this.insertQueue.length >= INSERT_COALESCE_THRESHOLD) {
|
|
2555
2617
|
this.insertFlushScheduled = false;
|
|
2556
2618
|
void this.flushInsertQueue();
|
|
@@ -2845,7 +2907,8 @@ var SqliteStorageProvider = class _SqliteStorageProvider {
|
|
|
2845
2907
|
const stmts = this.requireStatements();
|
|
2846
2908
|
const archived = [];
|
|
2847
2909
|
return this.withTransaction(() => {
|
|
2848
|
-
|
|
2910
|
+
const orderedIds = [...new Set(ids)].sort();
|
|
2911
|
+
for (const id of orderedIds) {
|
|
2849
2912
|
const existing = stmts.getMemoryById.get(id, organization);
|
|
2850
2913
|
const result = stmts.archiveMemory.run(
|
|
2851
2914
|
compressedIntoId,
|
|
@@ -2986,7 +3049,7 @@ var SqliteStorageProvider = class _SqliteStorageProvider {
|
|
|
2986
3049
|
}
|
|
2987
3050
|
async withTransaction(fn) {
|
|
2988
3051
|
const db = this.requireDb();
|
|
2989
|
-
if (this.
|
|
3052
|
+
if (this.txContext.getStore() === true) {
|
|
2990
3053
|
const savepointName = `wolbarg_sp_${this.savepointCounter++}`;
|
|
2991
3054
|
db.exec(`SAVEPOINT ${savepointName}`);
|
|
2992
3055
|
try {
|
|
@@ -3004,21 +3067,26 @@ var SqliteStorageProvider = class _SqliteStorageProvider {
|
|
|
3004
3067
|
this.transactionDepth -= 1;
|
|
3005
3068
|
}
|
|
3006
3069
|
}
|
|
3007
|
-
this.
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3070
|
+
return this.writeMutex.runExclusive(
|
|
3071
|
+
() => this.txContext.run(true, async () => {
|
|
3072
|
+
this.transactionDepth = 1;
|
|
3073
|
+
this.savepointCounter = 0;
|
|
3074
|
+
try {
|
|
3075
|
+
return await withImmediateTransaction(
|
|
3076
|
+
db,
|
|
3077
|
+
this.concurrency,
|
|
3078
|
+
fn,
|
|
3079
|
+
(attempt, delayMs) => {
|
|
3080
|
+
this.retryLog?.(
|
|
3081
|
+
`SQLITE_BUSY retry attempt=${attempt} backoffMs=${Math.round(delayMs)}`
|
|
3082
|
+
);
|
|
3083
|
+
}
|
|
3016
3084
|
);
|
|
3085
|
+
} finally {
|
|
3086
|
+
this.transactionDepth = 0;
|
|
3017
3087
|
}
|
|
3018
|
-
)
|
|
3019
|
-
|
|
3020
|
-
this.transactionDepth = 0;
|
|
3021
|
-
}
|
|
3088
|
+
})
|
|
3089
|
+
);
|
|
3022
3090
|
}
|
|
3023
3091
|
// ─── internals ───────────────────────────────────────────────────────────
|
|
3024
3092
|
tryLoadSqliteVec(db) {
|
|
@@ -4185,8 +4253,20 @@ function createPostgresListenerFromPool(pool, onError) {
|
|
|
4185
4253
|
}
|
|
4186
4254
|
|
|
4187
4255
|
// src/storage/providers/postgres.ts
|
|
4188
|
-
var txStore = new AsyncLocalStorage();
|
|
4189
4256
|
var warnLogger2 = new WolbargLogger("warn");
|
|
4257
|
+
function isRetriablePgTxError(error) {
|
|
4258
|
+
const code = error && typeof error === "object" && "code" in error ? String(error.code ?? "") : "";
|
|
4259
|
+
if (code === "40P01" || code === "40001") {
|
|
4260
|
+
return true;
|
|
4261
|
+
}
|
|
4262
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
4263
|
+
return /deadlock detected|could not serialize access/i.test(msg);
|
|
4264
|
+
}
|
|
4265
|
+
function pgTxBackoffMs(attempt) {
|
|
4266
|
+
const base = 25 * 2 ** attempt;
|
|
4267
|
+
const jitter = Math.random() * 25;
|
|
4268
|
+
return Math.min(1e3, base + jitter);
|
|
4269
|
+
}
|
|
4190
4270
|
var warnedPgvectorFallback = false;
|
|
4191
4271
|
var warnedFtsKeywordSearch2 = false;
|
|
4192
4272
|
var warnedHnswSoftFail = false;
|
|
@@ -4231,7 +4311,11 @@ function withPoolStartupOptions(connectionString, durableWrites) {
|
|
|
4231
4311
|
"-c jit=off",
|
|
4232
4312
|
// Bake HNSW search GUCs into the connection — avoids per-recall set_config.
|
|
4233
4313
|
"-c hnsw.ef_search=40",
|
|
4234
|
-
"-c hnsw.iterative_scan=relaxed_order"
|
|
4314
|
+
"-c hnsw.iterative_scan=relaxed_order",
|
|
4315
|
+
// Bound waits so lock storms cannot hang agents indefinitely.
|
|
4316
|
+
"-c statement_timeout=30000",
|
|
4317
|
+
"-c lock_timeout=10000",
|
|
4318
|
+
"-c idle_in_transaction_session_timeout=60000"
|
|
4235
4319
|
];
|
|
4236
4320
|
if (!durableWrites) {
|
|
4237
4321
|
flags.unshift("-c synchronous_commit=off");
|
|
@@ -4312,6 +4396,8 @@ var PostgresStorageProvider = class _PostgresStorageProvider {
|
|
|
4312
4396
|
insertFlushScheduled = false;
|
|
4313
4397
|
insertFlushTimer = null;
|
|
4314
4398
|
insertFlushInFlight = 0;
|
|
4399
|
+
/** Per-provider TX context — never share across PostgresStorageProvider instances. */
|
|
4400
|
+
txStore = new AsyncLocalStorage();
|
|
4315
4401
|
/**
|
|
4316
4402
|
* @param options - Connection string, pool size, and durability flags.
|
|
4317
4403
|
*/
|
|
@@ -4611,8 +4697,11 @@ var PostgresStorageProvider = class _PostgresStorageProvider {
|
|
|
4611
4697
|
/** Insert a single memory row (coalesced under concurrent writers). */
|
|
4612
4698
|
async insertMemory(input) {
|
|
4613
4699
|
this.requireVectorReady();
|
|
4614
|
-
|
|
4615
|
-
this.
|
|
4700
|
+
if (this.txStore.getStore()) {
|
|
4701
|
+
return this.insertMemoryImmediate(input);
|
|
4702
|
+
}
|
|
4703
|
+
return new Promise((resolve3, reject) => {
|
|
4704
|
+
this.insertQueue.push({ input, resolve: resolve3, reject });
|
|
4616
4705
|
if (this.insertQueue.length >= COALESCE_FLUSH_THRESHOLD) {
|
|
4617
4706
|
this.clearInsertFlushTimer();
|
|
4618
4707
|
void this.flushInsertQueue();
|
|
@@ -4847,10 +4936,18 @@ var PostgresStorageProvider = class _PostgresStorageProvider {
|
|
|
4847
4936
|
/** Update memory content, metadata, embedding, and content hash. */
|
|
4848
4937
|
async updateMemory(input) {
|
|
4849
4938
|
return this.withTransaction(async () => {
|
|
4850
|
-
const
|
|
4851
|
-
|
|
4939
|
+
const locked = await this.query(
|
|
4940
|
+
`SELECT id, organization, agent, content_text, metadata_json,
|
|
4941
|
+
archived::int AS archived, compressed_into, content_hash, created_at, updated_at
|
|
4942
|
+
FROM memories
|
|
4943
|
+
WHERE id = $1 AND organization = $2
|
|
4944
|
+
FOR UPDATE`,
|
|
4945
|
+
[input.id, input.organization]
|
|
4946
|
+
);
|
|
4947
|
+
if (locked.rows.length === 0) {
|
|
4852
4948
|
return null;
|
|
4853
4949
|
}
|
|
4950
|
+
const existing = this.mapRow(locked.rows[0]);
|
|
4854
4951
|
const contentHash = input.contentHash !== void 0 ? input.contentHash : input.contentText !== void 0 ? hashMemoryContent(input.contentText) : existing.content_hash ?? null;
|
|
4855
4952
|
await this.query(
|
|
4856
4953
|
`UPDATE memories SET
|
|
@@ -5168,23 +5265,38 @@ var PostgresStorageProvider = class _PostgresStorageProvider {
|
|
|
5168
5265
|
if (ids.length === 0) {
|
|
5169
5266
|
return [];
|
|
5170
5267
|
}
|
|
5268
|
+
const orderedIds = [...new Set(ids)].sort();
|
|
5269
|
+
await this.query(
|
|
5270
|
+
`SELECT id FROM memories
|
|
5271
|
+
WHERE organization = $1 AND archived = false AND id = ANY($2::text[])
|
|
5272
|
+
ORDER BY id
|
|
5273
|
+
FOR UPDATE`,
|
|
5274
|
+
[organization, orderedIds]
|
|
5275
|
+
);
|
|
5171
5276
|
const result = await this.query(
|
|
5172
5277
|
`UPDATE memories
|
|
5173
5278
|
SET archived = true, compressed_into = $1, updated_at = $2
|
|
5174
5279
|
WHERE organization = $3 AND archived = false AND id = ANY($4::text[])
|
|
5175
5280
|
RETURNING id`,
|
|
5176
|
-
[compressedIntoId, archivedAt, organization,
|
|
5281
|
+
[compressedIntoId, archivedAt, organization, orderedIds]
|
|
5177
5282
|
);
|
|
5178
5283
|
const archived = result.rows.map((r) => String(r.id));
|
|
5179
5284
|
if (archived.length === 0) {
|
|
5180
5285
|
return [];
|
|
5181
5286
|
}
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5287
|
+
if (this.hasPgvector) {
|
|
5288
|
+
await this.query(
|
|
5289
|
+
`UPDATE memory_embeddings
|
|
5290
|
+
SET archived = true
|
|
5291
|
+
WHERE memory_id = ANY($1::text[])`,
|
|
5292
|
+
[archived]
|
|
5293
|
+
);
|
|
5294
|
+
} else {
|
|
5295
|
+
await this.query(
|
|
5296
|
+
`DELETE FROM memory_embeddings_blob WHERE memory_id = ANY($1::text[])`,
|
|
5297
|
+
[archived]
|
|
5298
|
+
);
|
|
5299
|
+
}
|
|
5188
5300
|
const histIds = [];
|
|
5189
5301
|
const memIds = [];
|
|
5190
5302
|
const types = [];
|
|
@@ -5287,27 +5399,40 @@ var PostgresStorageProvider = class _PostgresStorageProvider {
|
|
|
5287
5399
|
return Number(result.rows[0]?.size ?? 0);
|
|
5288
5400
|
}
|
|
5289
5401
|
async withTransaction(fn) {
|
|
5290
|
-
const existing = txStore.getStore();
|
|
5402
|
+
const existing = this.txStore.getStore();
|
|
5291
5403
|
if (existing) {
|
|
5292
5404
|
return fn();
|
|
5293
5405
|
}
|
|
5294
|
-
const
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
const
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5406
|
+
const maxAttempts = 5;
|
|
5407
|
+
let lastError;
|
|
5408
|
+
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
5409
|
+
const client = await this.requirePool().connect();
|
|
5410
|
+
try {
|
|
5411
|
+
await client.query("BEGIN");
|
|
5412
|
+
const result = await this.txStore.run(client, fn);
|
|
5413
|
+
await client.query("COMMIT");
|
|
5414
|
+
return result;
|
|
5415
|
+
} catch (error) {
|
|
5416
|
+
await client.query("ROLLBACK").catch(() => void 0);
|
|
5417
|
+
lastError = error;
|
|
5418
|
+
if (isRetriablePgTxError(error) && attempt < maxAttempts - 1) {
|
|
5419
|
+
await new Promise((r) => setTimeout(r, pgTxBackoffMs(attempt)));
|
|
5420
|
+
continue;
|
|
5421
|
+
}
|
|
5422
|
+
if (error instanceof DatabaseError || error instanceof InitializationError) {
|
|
5423
|
+
throw error;
|
|
5424
|
+
}
|
|
5425
|
+
throw new DatabaseError(`Transaction failed: ${this.describe(error)}`, {
|
|
5426
|
+
cause: error instanceof Error ? error : void 0
|
|
5427
|
+
});
|
|
5428
|
+
} finally {
|
|
5429
|
+
client.release();
|
|
5304
5430
|
}
|
|
5305
|
-
throw new DatabaseError(`Transaction failed: ${this.describe(error)}`, {
|
|
5306
|
-
cause: error instanceof Error ? error : void 0
|
|
5307
|
-
});
|
|
5308
|
-
} finally {
|
|
5309
|
-
client.release();
|
|
5310
5431
|
}
|
|
5432
|
+
throw new DatabaseError(
|
|
5433
|
+
`Transaction failed after retries: ${this.describe(lastError)}`,
|
|
5434
|
+
{ cause: lastError instanceof Error ? lastError : void 0 }
|
|
5435
|
+
);
|
|
5311
5436
|
}
|
|
5312
5437
|
async runMigrations() {
|
|
5313
5438
|
await this.query(`
|
|
@@ -5535,13 +5660,13 @@ var PostgresStorageProvider = class _PostgresStorageProvider {
|
|
|
5535
5660
|
await this.query(`DELETE FROM memory_embeddings_blob WHERE memory_id = $1`, [memoryId]).catch(() => void 0);
|
|
5536
5661
|
}
|
|
5537
5662
|
async query(text, params) {
|
|
5538
|
-
const tx = txStore.getStore();
|
|
5663
|
+
const tx = this.txStore.getStore();
|
|
5539
5664
|
const target = tx ?? this.requirePool();
|
|
5540
5665
|
return target.query(text, params);
|
|
5541
5666
|
}
|
|
5542
5667
|
/** Named prepared statement — parse/plan cached per pool connection. */
|
|
5543
5668
|
async queryNamed(name, text, params) {
|
|
5544
|
-
const tx = txStore.getStore();
|
|
5669
|
+
const tx = this.txStore.getStore();
|
|
5545
5670
|
const target = tx ?? this.requirePool();
|
|
5546
5671
|
return target.query({ name, text, values: params });
|
|
5547
5672
|
}
|
|
@@ -5627,7 +5752,7 @@ function createDatabaseProvider(config) {
|
|
|
5627
5752
|
}
|
|
5628
5753
|
|
|
5629
5754
|
// src/version.ts
|
|
5630
|
-
var SDK_VERSION = "0.5.
|
|
5755
|
+
var SDK_VERSION = "0.5.6";
|
|
5631
5756
|
|
|
5632
5757
|
// src/memory/transfer.ts
|
|
5633
5758
|
var warnedMissingExportManifest = false;
|
|
@@ -9583,12 +9708,18 @@ var Wolbarg = class {
|
|
|
9583
9708
|
createdAt: timestamp,
|
|
9584
9709
|
updatedAt: timestamp
|
|
9585
9710
|
});
|
|
9711
|
+
const sourceIds = [...records.map((r) => r.id)].sort();
|
|
9586
9712
|
const archivedIds = await storage.archiveMemories(
|
|
9587
|
-
|
|
9713
|
+
sourceIds,
|
|
9588
9714
|
organization,
|
|
9589
9715
|
summaryId,
|
|
9590
9716
|
timestamp
|
|
9591
9717
|
);
|
|
9718
|
+
if (archivedIds.length < 2) {
|
|
9719
|
+
throw new ValidationError(
|
|
9720
|
+
"compress lost a concurrency race: fewer than 2 source memories remained active"
|
|
9721
|
+
);
|
|
9722
|
+
}
|
|
9592
9723
|
return {
|
|
9593
9724
|
summary: toMemoryRecord(summaryRow),
|
|
9594
9725
|
archivedIds
|
|
@@ -10600,8 +10731,11 @@ var meta = {
|
|
|
10600
10731
|
};
|
|
10601
10732
|
|
|
10602
10733
|
// src/factories/index.ts
|
|
10603
|
-
function sqlite(connectionString) {
|
|
10604
|
-
return new SqliteStorageProvider({
|
|
10734
|
+
function sqlite(connectionString, options) {
|
|
10735
|
+
return new SqliteStorageProvider({
|
|
10736
|
+
connectionString,
|
|
10737
|
+
concurrency: options?.concurrency
|
|
10738
|
+
});
|
|
10605
10739
|
}
|
|
10606
10740
|
function sqliteConfig(connectionString) {
|
|
10607
10741
|
return {
|
|
@@ -11118,6 +11252,271 @@ function percentile(sorted, p) {
|
|
|
11118
11252
|
return sorted[idx];
|
|
11119
11253
|
}
|
|
11120
11254
|
|
|
11121
|
-
|
|
11255
|
+
// src/config/providers.ts
|
|
11256
|
+
var EMBEDDING_PROVIDER_PRESETS = [
|
|
11257
|
+
{
|
|
11258
|
+
id: "openai",
|
|
11259
|
+
label: "OpenAI",
|
|
11260
|
+
defaultBaseUrl: "https://api.openai.com/v1",
|
|
11261
|
+
defaultModel: "text-embedding-3-small",
|
|
11262
|
+
apiKeyEnv: "OPENAI_API_KEY"
|
|
11263
|
+
},
|
|
11264
|
+
{
|
|
11265
|
+
id: "ollama",
|
|
11266
|
+
label: "Ollama (local)",
|
|
11267
|
+
defaultBaseUrl: "http://127.0.0.1:11434/v1",
|
|
11268
|
+
defaultModel: "nomic-embed-text",
|
|
11269
|
+
apiKeyEnv: "OLLAMA_API_KEY",
|
|
11270
|
+
apiKeyHint: "Any non-empty value works locally (e.g. ollama)"
|
|
11271
|
+
},
|
|
11272
|
+
{
|
|
11273
|
+
id: "openrouter",
|
|
11274
|
+
label: "OpenRouter",
|
|
11275
|
+
defaultBaseUrl: "https://openrouter.ai/api/v1",
|
|
11276
|
+
defaultModel: "openai/text-embedding-3-small",
|
|
11277
|
+
apiKeyEnv: "OPENROUTER_API_KEY"
|
|
11278
|
+
},
|
|
11279
|
+
{
|
|
11280
|
+
id: "lmstudio",
|
|
11281
|
+
label: "LM Studio (local)",
|
|
11282
|
+
defaultBaseUrl: "http://127.0.0.1:1234/v1",
|
|
11283
|
+
defaultModel: "text-embedding-nomic-embed-text-v1.5",
|
|
11284
|
+
apiKeyEnv: "LM_STUDIO_API_KEY",
|
|
11285
|
+
apiKeyHint: "Often unused locally \u2014 any non-empty value is fine"
|
|
11286
|
+
},
|
|
11287
|
+
{
|
|
11288
|
+
id: "gemini",
|
|
11289
|
+
label: "Google Gemini",
|
|
11290
|
+
defaultBaseUrl: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
11291
|
+
defaultModel: "text-embedding-004",
|
|
11292
|
+
apiKeyEnv: "GEMINI_API_KEY"
|
|
11293
|
+
},
|
|
11294
|
+
{
|
|
11295
|
+
id: "together",
|
|
11296
|
+
label: "Together AI",
|
|
11297
|
+
defaultBaseUrl: "https://api.together.xyz/v1",
|
|
11298
|
+
defaultModel: "togethercomputer/m2-bert-80M-8k-retrieval",
|
|
11299
|
+
apiKeyEnv: "TOGETHER_API_KEY"
|
|
11300
|
+
},
|
|
11301
|
+
{
|
|
11302
|
+
id: "vllm",
|
|
11303
|
+
label: "vLLM (local/server)",
|
|
11304
|
+
defaultBaseUrl: "http://127.0.0.1:8000/v1",
|
|
11305
|
+
defaultModel: "text-embedding-ada-002",
|
|
11306
|
+
apiKeyEnv: "VLLM_API_KEY",
|
|
11307
|
+
apiKeyHint: "Only if your server requires auth"
|
|
11308
|
+
},
|
|
11309
|
+
{
|
|
11310
|
+
id: "custom",
|
|
11311
|
+
label: "Custom OpenAI-compatible",
|
|
11312
|
+
defaultBaseUrl: "https://api.openai.com/v1",
|
|
11313
|
+
defaultModel: "text-embedding-3-small",
|
|
11314
|
+
apiKeyEnv: "WOLBARG_EMBEDDING_API_KEY"
|
|
11315
|
+
}
|
|
11316
|
+
];
|
|
11317
|
+
function getEmbeddingProviderPreset(id) {
|
|
11318
|
+
return EMBEDDING_PROVIDER_PRESETS.find((p) => p.id === id);
|
|
11319
|
+
}
|
|
11320
|
+
var DEFAULT_SQLITE_DB_PATH = ".wolbarg/shared-memory/memory.db";
|
|
11321
|
+
var DEFAULT_ORGANIZATION = "default";
|
|
11322
|
+
var DEFAULT_CONFIG_PATH = ".wolbarg/config.json";
|
|
11323
|
+
var DEFAULT_ENV_PATH = ".wolbarg/.env";
|
|
11324
|
+
function defaultProjectConfig() {
|
|
11325
|
+
return {
|
|
11326
|
+
version: 1,
|
|
11327
|
+
organization: DEFAULT_ORGANIZATION,
|
|
11328
|
+
database: {
|
|
11329
|
+
provider: "sqlite",
|
|
11330
|
+
url: DEFAULT_SQLITE_DB_PATH
|
|
11331
|
+
},
|
|
11332
|
+
paths: {
|
|
11333
|
+
config: DEFAULT_CONFIG_PATH
|
|
11334
|
+
}
|
|
11335
|
+
};
|
|
11336
|
+
}
|
|
11337
|
+
function resolveConfigPath(cwd = process.cwd(), configPath) {
|
|
11338
|
+
const rel = configPath ?? DEFAULT_CONFIG_PATH;
|
|
11339
|
+
return isAbsolute(rel) ? rel : resolve(cwd, rel);
|
|
11340
|
+
}
|
|
11341
|
+
function resolveEnvPath(cwd = process.cwd(), envPath) {
|
|
11342
|
+
const rel = envPath ?? DEFAULT_ENV_PATH;
|
|
11343
|
+
return isAbsolute(rel) ? rel : resolve(cwd, rel);
|
|
11344
|
+
}
|
|
11345
|
+
function loadProjectConfig(cwd = process.cwd(), configPath) {
|
|
11346
|
+
const full = resolveConfigPath(cwd, configPath);
|
|
11347
|
+
if (!existsSync(full)) return null;
|
|
11348
|
+
const raw = JSON.parse(readFileSync(full, "utf8"));
|
|
11349
|
+
if (!raw || raw.version !== 1 || !raw.database?.url) {
|
|
11350
|
+
throw new Error(`Invalid Wolbarg config at ${full}`);
|
|
11351
|
+
}
|
|
11352
|
+
return raw;
|
|
11353
|
+
}
|
|
11354
|
+
function saveProjectConfig(config, options = {}) {
|
|
11355
|
+
const cwd = options.cwd ?? process.cwd();
|
|
11356
|
+
const configPath = resolveConfigPath(cwd, options.configPath);
|
|
11357
|
+
const dir = dirname(configPath);
|
|
11358
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
11359
|
+
if (existsSync(configPath) && options.overwrite === false) {
|
|
11360
|
+
throw new Error(`Config already exists: ${configPath} (pass --force to overwrite)`);
|
|
11361
|
+
}
|
|
11362
|
+
const toWrite = {
|
|
11363
|
+
...config,
|
|
11364
|
+
paths: {
|
|
11365
|
+
config: options.configPath ?? DEFAULT_CONFIG_PATH,
|
|
11366
|
+
...options.envPath || options.apiKey ? { env: options.envPath ?? DEFAULT_ENV_PATH } : config.paths?.env ? { env: config.paths.env } : {}
|
|
11367
|
+
}
|
|
11368
|
+
};
|
|
11369
|
+
writeFileSync(configPath, `${JSON.stringify(toWrite, null, 2)}
|
|
11370
|
+
`, "utf8");
|
|
11371
|
+
let envPath;
|
|
11372
|
+
if (options.apiKey && config.embedding?.apiKeyEnv) {
|
|
11373
|
+
envPath = resolveEnvPath(cwd, options.envPath);
|
|
11374
|
+
ensureParent(envPath);
|
|
11375
|
+
upsertEnvVar(envPath, config.embedding.apiKeyEnv, options.apiKey);
|
|
11376
|
+
ensureGitignore(cwd, [DEFAULT_ENV_PATH, ".env"]);
|
|
11377
|
+
}
|
|
11378
|
+
if (config.database.provider === "sqlite" && !config.database.url.includes("://")) {
|
|
11379
|
+
const dbPath = isAbsolute(config.database.url) ? config.database.url : resolve(cwd, config.database.url);
|
|
11380
|
+
ensureParent(dbPath);
|
|
11381
|
+
}
|
|
11382
|
+
return { configPath, envPath };
|
|
11383
|
+
}
|
|
11384
|
+
function ensureParent(filePath) {
|
|
11385
|
+
const dir = dirname(filePath);
|
|
11386
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
11387
|
+
}
|
|
11388
|
+
function upsertEnvVar(envPath, key, value) {
|
|
11389
|
+
ensureParent(envPath);
|
|
11390
|
+
let text = existsSync(envPath) ? readFileSync(envPath, "utf8") : "";
|
|
11391
|
+
const line = `${key}=${shellQuoteEnv(value)}`;
|
|
11392
|
+
const re = new RegExp(`^${escapeRegExp(key)}=.*$`, "m");
|
|
11393
|
+
if (re.test(text)) {
|
|
11394
|
+
text = text.replace(re, line);
|
|
11395
|
+
} else {
|
|
11396
|
+
if (text && !text.endsWith("\n")) text += "\n";
|
|
11397
|
+
text += `${line}
|
|
11398
|
+
`;
|
|
11399
|
+
}
|
|
11400
|
+
writeFileSync(envPath, text, "utf8");
|
|
11401
|
+
}
|
|
11402
|
+
function shellQuoteEnv(value) {
|
|
11403
|
+
if (/[\s#"']/.test(value)) {
|
|
11404
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
11405
|
+
}
|
|
11406
|
+
return value;
|
|
11407
|
+
}
|
|
11408
|
+
function escapeRegExp(s) {
|
|
11409
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11410
|
+
}
|
|
11411
|
+
function ensureGitignore(cwd, entries) {
|
|
11412
|
+
const gi = join(cwd, ".gitignore");
|
|
11413
|
+
let text = existsSync(gi) ? readFileSync(gi, "utf8") : "";
|
|
11414
|
+
let changed = false;
|
|
11415
|
+
for (const entry of entries) {
|
|
11416
|
+
if (text.split(/\r?\n/).some((l) => l.trim() === entry)) continue;
|
|
11417
|
+
if (text && !text.endsWith("\n")) text += "\n";
|
|
11418
|
+
text += `${entry}
|
|
11419
|
+
`;
|
|
11420
|
+
changed = true;
|
|
11421
|
+
}
|
|
11422
|
+
if (changed) writeFileSync(gi, text, "utf8");
|
|
11423
|
+
}
|
|
11424
|
+
function resolveEmbeddingApiKey(config, env = process.env) {
|
|
11425
|
+
const name = config.embedding?.apiKeyEnv;
|
|
11426
|
+
if (!name) return "";
|
|
11427
|
+
return env[name] ?? "";
|
|
11428
|
+
}
|
|
11429
|
+
function assertEmbeddingPreset(provider) {
|
|
11430
|
+
const preset = getEmbeddingProviderPreset(provider);
|
|
11431
|
+
if (!preset) {
|
|
11432
|
+
throw new Error(
|
|
11433
|
+
`Unknown embedding provider "${provider}". Choose one of: ${[
|
|
11434
|
+
"openai",
|
|
11435
|
+
"ollama",
|
|
11436
|
+
"openrouter",
|
|
11437
|
+
"lmstudio",
|
|
11438
|
+
"gemini",
|
|
11439
|
+
"together",
|
|
11440
|
+
"vllm",
|
|
11441
|
+
"custom"
|
|
11442
|
+
].join(", ")}`
|
|
11443
|
+
);
|
|
11444
|
+
}
|
|
11445
|
+
return preset.id;
|
|
11446
|
+
}
|
|
11447
|
+
function applyEnvFile(envPath, base = {}) {
|
|
11448
|
+
const out = { ...base };
|
|
11449
|
+
if (!existsSync(envPath)) return out;
|
|
11450
|
+
const text = readFileSync(envPath, "utf8");
|
|
11451
|
+
for (const rawLine of text.split(/\r?\n/)) {
|
|
11452
|
+
const line = rawLine.trim();
|
|
11453
|
+
if (!line || line.startsWith("#")) continue;
|
|
11454
|
+
const eq = line.indexOf("=");
|
|
11455
|
+
if (eq <= 0) continue;
|
|
11456
|
+
const key = line.slice(0, eq).trim();
|
|
11457
|
+
let value = line.slice(eq + 1).trim();
|
|
11458
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
11459
|
+
value = value.slice(1, -1);
|
|
11460
|
+
}
|
|
11461
|
+
if (out[key] === void 0) out[key] = value;
|
|
11462
|
+
}
|
|
11463
|
+
return out;
|
|
11464
|
+
}
|
|
11465
|
+
function projectConfigToWolbargOptions(config, env = process.env) {
|
|
11466
|
+
if (!config.embedding) {
|
|
11467
|
+
throw new Error(
|
|
11468
|
+
"Project config has no embedding section. Re-run `wolbarg init` and configure an embedding provider, or pass embedding explicitly to wolbarg()."
|
|
11469
|
+
);
|
|
11470
|
+
}
|
|
11471
|
+
const apiKey = resolveEmbeddingApiKey(config, env);
|
|
11472
|
+
if (!apiKey) {
|
|
11473
|
+
throw new Error(
|
|
11474
|
+
`Missing API key. Set ${config.embedding.apiKeyEnv} in the environment or in .wolbarg/.env (from wolbarg init).`
|
|
11475
|
+
);
|
|
11476
|
+
}
|
|
11477
|
+
const dbUrl = config.database.url;
|
|
11478
|
+
return {
|
|
11479
|
+
organization: config.organization,
|
|
11480
|
+
database: {
|
|
11481
|
+
provider: config.database.provider,
|
|
11482
|
+
url: dbUrl,
|
|
11483
|
+
connectionString: dbUrl
|
|
11484
|
+
},
|
|
11485
|
+
embedding: {
|
|
11486
|
+
baseUrl: config.embedding.baseUrl,
|
|
11487
|
+
apiKey,
|
|
11488
|
+
model: config.embedding.model
|
|
11489
|
+
}
|
|
11490
|
+
};
|
|
11491
|
+
}
|
|
11492
|
+
function createWolbargFromProjectConfig(options = {}) {
|
|
11493
|
+
const cwd = options.cwd ?? process.cwd();
|
|
11494
|
+
const config = loadProjectConfig(cwd, options.configPath);
|
|
11495
|
+
if (!config) {
|
|
11496
|
+
throw new Error(
|
|
11497
|
+
`No Wolbarg config found. Run \`wolbarg init\` in ${cwd} (expected .wolbarg/config.json).`
|
|
11498
|
+
);
|
|
11499
|
+
}
|
|
11500
|
+
let env = options.env ?? { ...process.env };
|
|
11501
|
+
if (options.loadEnvFile !== false) {
|
|
11502
|
+
const envFile = resolveEnvPath(
|
|
11503
|
+
cwd,
|
|
11504
|
+
config.paths?.env ?? DEFAULT_ENV_PATH
|
|
11505
|
+
);
|
|
11506
|
+
env = applyEnvFile(envFile, env);
|
|
11507
|
+
}
|
|
11508
|
+
if (options.organization) {
|
|
11509
|
+
config.organization = options.organization;
|
|
11510
|
+
}
|
|
11511
|
+
if (config.database.provider === "sqlite" && !config.database.url.includes("://") && !isAbsolute(config.database.url)) {
|
|
11512
|
+
config.database = {
|
|
11513
|
+
...config.database,
|
|
11514
|
+
url: resolve(cwd, config.database.url)
|
|
11515
|
+
};
|
|
11516
|
+
}
|
|
11517
|
+
return wolbarg(projectConfigToWolbargOptions(config, env));
|
|
11518
|
+
}
|
|
11519
|
+
|
|
11520
|
+
export { CompressionError, ConfigurationError, DEFAULT_CONFIG_PATH, DEFAULT_ENV_PATH, DEFAULT_ORGANIZATION, DEFAULT_SQLITE_DB_PATH, DatabaseError, EMBEDDING_PROVIDER_PRESETS, EmbeddingError, FixedChunkingStrategy, GraphCheckpointNotSupportedError, HeadingChunkingStrategy, InitializationError, LlmCompressionProvider, MarkdownChunkingStrategy, MemoryNotFoundError, Neo4jGraphProvider, NoopTelemetryProvider, ParagraphChunkingStrategy, PostgresStorageProvider, ProviderNotConfiguredError, SDK_VERSION, SentenceChunkingStrategy, SqliteCheckpointProvider, SqliteDatabaseProvider, SqliteEventDatabase, SqliteGraphProvider, SqliteStorageProvider, SqliteTelemetryProvider, StorageLockedError, TelemetryEmitter, ValidationError, Wolbarg, WolbargError, WolbargLogger, applyEnvFile, assertEmbeddingPreset, bgeReranker, bm25, cohereReranker, createChunkingStrategy, createCompressionProvider, createDatabaseProvider, createEmbeddingProvider, createLlmProvider, createStorageProvider, createTelemetryProvider, createWolbarg, createWolbargFromProjectConfig, crossEncoder, defaultProjectConfig, geminiEmbedding, geminiVision, getEmbeddingProviderPreset, jinaReranker, lmStudioEmbedding, loadProjectConfig, meta, neo4jGraph, ollamaEmbedding, ollamaLlm, openRouterEmbedding, openRouterLlm, openaiCompatibleEmbedding, openaiCompatibleLlm, openaiEmbedding, openaiLlm, openaiReranker, openaiVision, postgres, postgresConfig, projectConfigToWolbargOptions, resolveConfigPath, resolveEmbeddingApiKey, resolveEnvPath, runBenchmark, saveProjectConfig, sqlite, sqliteCheckpoint, sqliteConfig, sqliteGraph, sqliteTelemetry, summarizeBenchmark, tesseract, togetherEmbedding, upsertEnvVar, vllmEmbedding, wolbarg, wrapOperationError };
|
|
11122
11521
|
//# sourceMappingURL=index.js.map
|
|
11123
11522
|
//# sourceMappingURL=index.js.map
|