@plur-ai/core 0.9.4 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +91 -12
- package/dist/index.js +211 -11
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -635,19 +635,45 @@ declare const EpisodeSchema: z.ZodObject<{
|
|
|
635
635
|
}>;
|
|
636
636
|
type Episode = z.infer<typeof EpisodeSchema>;
|
|
637
637
|
|
|
638
|
-
|
|
639
|
-
|
|
638
|
+
/**
|
|
639
|
+
* A store can be either:
|
|
640
|
+
* - filesystem (path) — historical default; YAML or SQLite
|
|
641
|
+
* - remote (url + token) — speaks to a PLUR Enterprise server over HTTP
|
|
642
|
+
* Exactly one of path/url must be present.
|
|
643
|
+
*/
|
|
644
|
+
declare const StoreEntrySchema: z.ZodEffects<z.ZodObject<{
|
|
645
|
+
path: z.ZodOptional<z.ZodString>;
|
|
646
|
+
url: z.ZodOptional<z.ZodString>;
|
|
647
|
+
token: z.ZodOptional<z.ZodString>;
|
|
640
648
|
scope: z.ZodString;
|
|
641
649
|
shared: z.ZodDefault<z.ZodBoolean>;
|
|
642
650
|
readonly: z.ZodDefault<z.ZodBoolean>;
|
|
643
651
|
}, "strip", z.ZodTypeAny, {
|
|
644
|
-
path: string;
|
|
645
652
|
scope: string;
|
|
646
653
|
shared: boolean;
|
|
647
654
|
readonly: boolean;
|
|
655
|
+
path?: string | undefined;
|
|
656
|
+
url?: string | undefined;
|
|
657
|
+
token?: string | undefined;
|
|
658
|
+
}, {
|
|
659
|
+
scope: string;
|
|
660
|
+
path?: string | undefined;
|
|
661
|
+
url?: string | undefined;
|
|
662
|
+
token?: string | undefined;
|
|
663
|
+
shared?: boolean | undefined;
|
|
664
|
+
readonly?: boolean | undefined;
|
|
665
|
+
}>, {
|
|
666
|
+
scope: string;
|
|
667
|
+
shared: boolean;
|
|
668
|
+
readonly: boolean;
|
|
669
|
+
path?: string | undefined;
|
|
670
|
+
url?: string | undefined;
|
|
671
|
+
token?: string | undefined;
|
|
648
672
|
}, {
|
|
649
|
-
path: string;
|
|
650
673
|
scope: string;
|
|
674
|
+
path?: string | undefined;
|
|
675
|
+
url?: string | undefined;
|
|
676
|
+
token?: string | undefined;
|
|
651
677
|
shared?: boolean | undefined;
|
|
652
678
|
readonly?: boolean | undefined;
|
|
653
679
|
}>;
|
|
@@ -705,19 +731,39 @@ declare const PlurConfigSchema: z.ZodObject<{
|
|
|
705
731
|
}, {
|
|
706
732
|
enabled?: boolean | undefined;
|
|
707
733
|
}>>>;
|
|
708
|
-
stores: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
709
|
-
path: z.ZodString
|
|
734
|
+
stores: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodEffects<z.ZodObject<{
|
|
735
|
+
path: z.ZodOptional<z.ZodString>;
|
|
736
|
+
url: z.ZodOptional<z.ZodString>;
|
|
737
|
+
token: z.ZodOptional<z.ZodString>;
|
|
710
738
|
scope: z.ZodString;
|
|
711
739
|
shared: z.ZodDefault<z.ZodBoolean>;
|
|
712
740
|
readonly: z.ZodDefault<z.ZodBoolean>;
|
|
713
741
|
}, "strip", z.ZodTypeAny, {
|
|
714
|
-
path: string;
|
|
715
742
|
scope: string;
|
|
716
743
|
shared: boolean;
|
|
717
744
|
readonly: boolean;
|
|
745
|
+
path?: string | undefined;
|
|
746
|
+
url?: string | undefined;
|
|
747
|
+
token?: string | undefined;
|
|
748
|
+
}, {
|
|
749
|
+
scope: string;
|
|
750
|
+
path?: string | undefined;
|
|
751
|
+
url?: string | undefined;
|
|
752
|
+
token?: string | undefined;
|
|
753
|
+
shared?: boolean | undefined;
|
|
754
|
+
readonly?: boolean | undefined;
|
|
755
|
+
}>, {
|
|
756
|
+
scope: string;
|
|
757
|
+
shared: boolean;
|
|
758
|
+
readonly: boolean;
|
|
759
|
+
path?: string | undefined;
|
|
760
|
+
url?: string | undefined;
|
|
761
|
+
token?: string | undefined;
|
|
718
762
|
}, {
|
|
719
|
-
path: string;
|
|
720
763
|
scope: string;
|
|
764
|
+
path?: string | undefined;
|
|
765
|
+
url?: string | undefined;
|
|
766
|
+
token?: string | undefined;
|
|
721
767
|
shared?: boolean | undefined;
|
|
722
768
|
readonly?: boolean | undefined;
|
|
723
769
|
}>, "many">>>;
|
|
@@ -778,10 +824,12 @@ declare const PlurConfigSchema: z.ZodObject<{
|
|
|
778
824
|
enabled?: boolean | undefined;
|
|
779
825
|
} | undefined;
|
|
780
826
|
stores?: {
|
|
781
|
-
path: string;
|
|
782
827
|
scope: string;
|
|
783
828
|
shared: boolean;
|
|
784
829
|
readonly: boolean;
|
|
830
|
+
path?: string | undefined;
|
|
831
|
+
url?: string | undefined;
|
|
832
|
+
token?: string | undefined;
|
|
785
833
|
}[] | undefined;
|
|
786
834
|
profile?: {
|
|
787
835
|
enabled?: boolean | undefined;
|
|
@@ -821,8 +869,10 @@ declare const PlurConfigSchema: z.ZodObject<{
|
|
|
821
869
|
enabled?: boolean | undefined;
|
|
822
870
|
} | undefined;
|
|
823
871
|
stores?: {
|
|
824
|
-
path: string;
|
|
825
872
|
scope: string;
|
|
873
|
+
path?: string | undefined;
|
|
874
|
+
url?: string | undefined;
|
|
875
|
+
token?: string | undefined;
|
|
826
876
|
shared?: boolean | undefined;
|
|
827
877
|
readonly?: boolean | undefined;
|
|
828
878
|
}[] | undefined;
|
|
@@ -2175,6 +2225,21 @@ declare class Plur {
|
|
|
2175
2225
|
private _loadAllEngrams;
|
|
2176
2226
|
/** Load engrams from a path with mtime-based caching */
|
|
2177
2227
|
private _loadCached;
|
|
2228
|
+
/**
|
|
2229
|
+
* Per-instance pool of RemoteStore drivers, keyed by url+scope.
|
|
2230
|
+
* RemoteStore holds its own internal TTL cache so repeated load()
|
|
2231
|
+
* within ttlMs returns the same array without a network call.
|
|
2232
|
+
*
|
|
2233
|
+
* Note `_loadAllEngrams` is sync but RemoteStore.load() is async.
|
|
2234
|
+
* We bridge that by returning whatever's in the driver's cache
|
|
2235
|
+
* synchronously and triggering a background refresh on cache miss.
|
|
2236
|
+
* The first call after server start returns [] for that store; the
|
|
2237
|
+
* call after the first refresh sees the data. For our pilot this
|
|
2238
|
+
* is acceptable — recall is expected to be tried more than once
|
|
2239
|
+
* in any real session.
|
|
2240
|
+
*/
|
|
2241
|
+
private _remoteStores;
|
|
2242
|
+
private _loadRemoteCached;
|
|
2178
2243
|
/**
|
|
2179
2244
|
* Write engrams to disk and invalidate the cache for that path.
|
|
2180
2245
|
*
|
|
@@ -2350,10 +2415,23 @@ declare class Plur {
|
|
|
2350
2415
|
}>;
|
|
2351
2416
|
/** Return system health info. */
|
|
2352
2417
|
status(): StatusResult;
|
|
2353
|
-
/**
|
|
2418
|
+
/**
|
|
2419
|
+
* Register an additional engram store.
|
|
2420
|
+
*
|
|
2421
|
+
* Two shapes — exactly one of `pathOrUrl` semantics applies:
|
|
2422
|
+
* - filesystem (default): pass a path. `options.url` undefined.
|
|
2423
|
+
* - remote (PLUR Enterprise / any compatible REST API):
|
|
2424
|
+
* pass any string for the first arg (it goes into a slot we
|
|
2425
|
+
* never read), set `options.url` + `options.token`.
|
|
2426
|
+
*
|
|
2427
|
+
* Backwards compatible: existing call sites that pass a filesystem
|
|
2428
|
+
* path keep working.
|
|
2429
|
+
*/
|
|
2354
2430
|
addStore(storePath: string, scope: string, options?: {
|
|
2355
2431
|
shared?: boolean;
|
|
2356
2432
|
readonly?: boolean;
|
|
2433
|
+
url?: string;
|
|
2434
|
+
token?: string;
|
|
2357
2435
|
}): void;
|
|
2358
2436
|
/**
|
|
2359
2437
|
* Auto-discover .plur/engrams.yaml in CWD and parent dirs (up to git root).
|
|
@@ -2366,7 +2444,8 @@ declare class Plur {
|
|
|
2366
2444
|
}>;
|
|
2367
2445
|
/** List all configured stores. */
|
|
2368
2446
|
listStores(): Array<{
|
|
2369
|
-
path
|
|
2447
|
+
path?: string;
|
|
2448
|
+
url?: string;
|
|
2370
2449
|
scope: string;
|
|
2371
2450
|
shared: boolean;
|
|
2372
2451
|
readonly: boolean;
|
package/dist/index.js
CHANGED
|
@@ -177,6 +177,7 @@ var IndexedStorage = class {
|
|
|
177
177
|
allSyncedIds.add(e.id);
|
|
178
178
|
}
|
|
179
179
|
for (const store of this.stores) {
|
|
180
|
+
if (!store.path) continue;
|
|
180
181
|
validSources.add(store.path);
|
|
181
182
|
const storeEngrams = loadEngrams(store.path);
|
|
182
183
|
const prefix = storePrefix(store.scope);
|
|
@@ -223,11 +224,17 @@ import yaml from "js-yaml";
|
|
|
223
224
|
// src/schemas/config.ts
|
|
224
225
|
import { z } from "zod";
|
|
225
226
|
var StoreEntrySchema = z.object({
|
|
226
|
-
path: z.string(),
|
|
227
|
+
path: z.string().optional(),
|
|
228
|
+
url: z.string().url().optional(),
|
|
229
|
+
token: z.string().optional(),
|
|
230
|
+
// Bearer for remote stores; ignored for path
|
|
227
231
|
scope: z.string(),
|
|
228
232
|
shared: z.boolean().default(false),
|
|
229
233
|
readonly: z.boolean().default(false)
|
|
230
|
-
})
|
|
234
|
+
}).refine(
|
|
235
|
+
(s) => Boolean(s.path) !== Boolean(s.url),
|
|
236
|
+
{ message: "StoreEntry requires exactly one of path or url" }
|
|
237
|
+
);
|
|
231
238
|
var LlmTierConfigSchema = z.object({
|
|
232
239
|
dedup_tier: z.enum(["fast", "balanced", "thorough"]).default("fast"),
|
|
233
240
|
profile_tier: z.enum(["fast", "balanced", "thorough"]).default("balanced"),
|
|
@@ -1516,6 +1523,137 @@ function computePackHash(packDir) {
|
|
|
1516
1523
|
return hash.digest("hex");
|
|
1517
1524
|
}
|
|
1518
1525
|
|
|
1526
|
+
// src/store/remote-store.ts
|
|
1527
|
+
var RemoteStore = class {
|
|
1528
|
+
constructor(url, token, scope, opts = {}) {
|
|
1529
|
+
this.url = url;
|
|
1530
|
+
this.token = token;
|
|
1531
|
+
this.scope = scope;
|
|
1532
|
+
this.opts = opts;
|
|
1533
|
+
}
|
|
1534
|
+
cache = null;
|
|
1535
|
+
inFlight = null;
|
|
1536
|
+
get apiBase() {
|
|
1537
|
+
return this.url.replace(/\/sse\/?$/, "").replace(/\/$/, "") + "/api/v1";
|
|
1538
|
+
}
|
|
1539
|
+
get ttlMs() {
|
|
1540
|
+
return this.opts.ttlMs ?? 6e4;
|
|
1541
|
+
}
|
|
1542
|
+
headers(extra = {}) {
|
|
1543
|
+
return {
|
|
1544
|
+
Authorization: `Bearer ${this.token}`,
|
|
1545
|
+
Accept: "application/json",
|
|
1546
|
+
...extra
|
|
1547
|
+
};
|
|
1548
|
+
}
|
|
1549
|
+
/**
|
|
1550
|
+
* Load all engrams visible to this token at this scope. Cached up to
|
|
1551
|
+
* ttlMs; in-flight calls deduplicate to avoid thundering-herd on
|
|
1552
|
+
* the remote when 5 things ask for engrams at once.
|
|
1553
|
+
*/
|
|
1554
|
+
async load() {
|
|
1555
|
+
const now = Date.now();
|
|
1556
|
+
if (this.cache && now - this.cache.ts < this.ttlMs) return this.cache.engrams;
|
|
1557
|
+
if (this.inFlight) return this.inFlight;
|
|
1558
|
+
this.inFlight = (async () => {
|
|
1559
|
+
try {
|
|
1560
|
+
const all = [];
|
|
1561
|
+
let offset = 0;
|
|
1562
|
+
const limit = 200;
|
|
1563
|
+
const maxPages = 50;
|
|
1564
|
+
for (let i = 0; i < maxPages; i++) {
|
|
1565
|
+
const u = `${this.apiBase}/engrams?scope=${encodeURIComponent(this.scope)}&limit=${limit}&offset=${offset}`;
|
|
1566
|
+
const r = await fetch(u, { headers: this.headers() });
|
|
1567
|
+
if (!r.ok) {
|
|
1568
|
+
if (r.status >= 500) console.error(`[plur:remote-store] ${this.url} returned ${r.status} loading scope ${this.scope}`);
|
|
1569
|
+
break;
|
|
1570
|
+
}
|
|
1571
|
+
const body = await r.json();
|
|
1572
|
+
for (const row of body.rows) {
|
|
1573
|
+
const d = row.data ?? {};
|
|
1574
|
+
all.push({
|
|
1575
|
+
id: row.id,
|
|
1576
|
+
scope: row.scope,
|
|
1577
|
+
status: row.status,
|
|
1578
|
+
...d
|
|
1579
|
+
});
|
|
1580
|
+
}
|
|
1581
|
+
if (all.length >= body.total_count || body.rows.length < limit) break;
|
|
1582
|
+
offset += limit;
|
|
1583
|
+
}
|
|
1584
|
+
this.cache = { ts: Date.now(), engrams: all };
|
|
1585
|
+
return all;
|
|
1586
|
+
} catch (err) {
|
|
1587
|
+
console.error(`[plur:remote-store] ${this.url} load failed: ${err.message}`);
|
|
1588
|
+
return this.cache?.engrams ?? [];
|
|
1589
|
+
} finally {
|
|
1590
|
+
this.inFlight = null;
|
|
1591
|
+
}
|
|
1592
|
+
})();
|
|
1593
|
+
return this.inFlight;
|
|
1594
|
+
}
|
|
1595
|
+
/**
|
|
1596
|
+
* Append a single engram to the remote store. POST /api/v1/engrams
|
|
1597
|
+
* carries statement + scope + domain + type — the server handles
|
|
1598
|
+
* ID assignment, content_hash, status.
|
|
1599
|
+
*/
|
|
1600
|
+
async append(engram) {
|
|
1601
|
+
const body = JSON.stringify({
|
|
1602
|
+
statement: engram.statement,
|
|
1603
|
+
scope: engram.scope,
|
|
1604
|
+
domain: engram.domain,
|
|
1605
|
+
type: engram.type
|
|
1606
|
+
});
|
|
1607
|
+
const r = await fetch(`${this.apiBase}/engrams`, {
|
|
1608
|
+
method: "POST",
|
|
1609
|
+
headers: this.headers({ "Content-Type": "application/json" }),
|
|
1610
|
+
body
|
|
1611
|
+
});
|
|
1612
|
+
if (!r.ok) {
|
|
1613
|
+
const text = await r.text().catch(() => "");
|
|
1614
|
+
throw new Error(`Remote store append failed: ${r.status} ${text}`);
|
|
1615
|
+
}
|
|
1616
|
+
this.cache = null;
|
|
1617
|
+
}
|
|
1618
|
+
/**
|
|
1619
|
+
* `save(all)` — used by migrations to bulk-replace. Not supported
|
|
1620
|
+
* on remote: the server keeps an audit trail and we don't want a
|
|
1621
|
+
* single client to be able to nuke + replace the whole store. Throws.
|
|
1622
|
+
*/
|
|
1623
|
+
async save(_engrams) {
|
|
1624
|
+
throw new Error("Remote store does not support bulk save() \u2014 use append()/remove() per engram");
|
|
1625
|
+
}
|
|
1626
|
+
async getById(id) {
|
|
1627
|
+
try {
|
|
1628
|
+
const r = await fetch(`${this.apiBase}/engrams/${encodeURIComponent(id)}`, { headers: this.headers() });
|
|
1629
|
+
if (r.status === 404) return null;
|
|
1630
|
+
if (!r.ok) return null;
|
|
1631
|
+
const row = await r.json();
|
|
1632
|
+
return { id: row.id, scope: row.scope, status: row.status, ...row.data ?? {} };
|
|
1633
|
+
} catch {
|
|
1634
|
+
return null;
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
/** Remove → DELETE /api/v1/engrams/:id (server soft-retires). */
|
|
1638
|
+
async remove(id) {
|
|
1639
|
+
const r = await fetch(`${this.apiBase}/engrams/${encodeURIComponent(id)}`, {
|
|
1640
|
+
method: "DELETE",
|
|
1641
|
+
headers: this.headers()
|
|
1642
|
+
});
|
|
1643
|
+
if (!r.ok) return false;
|
|
1644
|
+
this.cache = null;
|
|
1645
|
+
return true;
|
|
1646
|
+
}
|
|
1647
|
+
async count(filter) {
|
|
1648
|
+
const all = await this.load();
|
|
1649
|
+
if (filter?.status) return all.filter((e) => e.status === filter.status).length;
|
|
1650
|
+
return all.length;
|
|
1651
|
+
}
|
|
1652
|
+
async close() {
|
|
1653
|
+
this.cache = null;
|
|
1654
|
+
}
|
|
1655
|
+
};
|
|
1656
|
+
|
|
1519
1657
|
// src/meta/sanitize.ts
|
|
1520
1658
|
function sanitizeForPrompt(text) {
|
|
1521
1659
|
return text.replace(/```/g, "~~~").replace(/\n{3,}/g, "\n\n").replace(/^(system|assistant|user):/gim, "$1 -").slice(0, 2e3);
|
|
@@ -3220,7 +3358,7 @@ var Plur = class {
|
|
|
3220
3358
|
const stores = this.config.stores ?? [];
|
|
3221
3359
|
const all = [...primary];
|
|
3222
3360
|
for (const store of stores) {
|
|
3223
|
-
const storeEngrams = this._loadCached(store.path);
|
|
3361
|
+
const storeEngrams = store.url ? this._loadRemoteCached(store) : this._loadCached(store.path);
|
|
3224
3362
|
const prefix = storePrefix(store.scope);
|
|
3225
3363
|
for (const e of storeEngrams) {
|
|
3226
3364
|
if (e.scope !== "global" && e.scope !== store.scope && !e.scope.startsWith(store.scope)) {
|
|
@@ -3263,6 +3401,32 @@ var Plur = class {
|
|
|
3263
3401
|
this._engramCache.set(path3, { mtime, engrams });
|
|
3264
3402
|
return engrams;
|
|
3265
3403
|
}
|
|
3404
|
+
/**
|
|
3405
|
+
* Per-instance pool of RemoteStore drivers, keyed by url+scope.
|
|
3406
|
+
* RemoteStore holds its own internal TTL cache so repeated load()
|
|
3407
|
+
* within ttlMs returns the same array without a network call.
|
|
3408
|
+
*
|
|
3409
|
+
* Note `_loadAllEngrams` is sync but RemoteStore.load() is async.
|
|
3410
|
+
* We bridge that by returning whatever's in the driver's cache
|
|
3411
|
+
* synchronously and triggering a background refresh on cache miss.
|
|
3412
|
+
* The first call after server start returns [] for that store; the
|
|
3413
|
+
* call after the first refresh sees the data. For our pilot this
|
|
3414
|
+
* is acceptable — recall is expected to be tried more than once
|
|
3415
|
+
* in any real session.
|
|
3416
|
+
*/
|
|
3417
|
+
_remoteStores = /* @__PURE__ */ new Map();
|
|
3418
|
+
_loadRemoteCached(store) {
|
|
3419
|
+
const key = `${store.url}::${store.scope}`;
|
|
3420
|
+
let driver = this._remoteStores.get(key);
|
|
3421
|
+
if (!driver) {
|
|
3422
|
+
driver = new RemoteStore(store.url, store.token ?? "", store.scope);
|
|
3423
|
+
this._remoteStores.set(key, driver);
|
|
3424
|
+
}
|
|
3425
|
+
const cached = driver.cache;
|
|
3426
|
+
void driver.load().catch(() => {
|
|
3427
|
+
});
|
|
3428
|
+
return cached?.engrams ?? [];
|
|
3429
|
+
}
|
|
3266
3430
|
/**
|
|
3267
3431
|
* Write engrams to disk and invalidate the cache for that path.
|
|
3268
3432
|
*
|
|
@@ -3286,6 +3450,7 @@ var Plur = class {
|
|
|
3286
3450
|
}
|
|
3287
3451
|
const stores = this.config.stores ?? [];
|
|
3288
3452
|
for (const store of stores) {
|
|
3453
|
+
if (!store.path) continue;
|
|
3289
3454
|
const prefix = storePrefix(store.scope);
|
|
3290
3455
|
const nsPattern = new RegExp(`^(ENG|ABS|META)-${prefix}-`);
|
|
3291
3456
|
if (nsPattern.test(id)) {
|
|
@@ -4130,17 +4295,38 @@ Generate an improved version of the procedure that prevents this failure. Return
|
|
|
4130
4295
|
versioned_engram_count: versionedCount
|
|
4131
4296
|
};
|
|
4132
4297
|
}
|
|
4133
|
-
/**
|
|
4298
|
+
/**
|
|
4299
|
+
* Register an additional engram store.
|
|
4300
|
+
*
|
|
4301
|
+
* Two shapes — exactly one of `pathOrUrl` semantics applies:
|
|
4302
|
+
* - filesystem (default): pass a path. `options.url` undefined.
|
|
4303
|
+
* - remote (PLUR Enterprise / any compatible REST API):
|
|
4304
|
+
* pass any string for the first arg (it goes into a slot we
|
|
4305
|
+
* never read), set `options.url` + `options.token`.
|
|
4306
|
+
*
|
|
4307
|
+
* Backwards compatible: existing call sites that pass a filesystem
|
|
4308
|
+
* path keep working.
|
|
4309
|
+
*/
|
|
4134
4310
|
addStore(storePath, scope, options) {
|
|
4135
4311
|
const config = loadConfig(this.paths.config);
|
|
4136
|
-
const
|
|
4312
|
+
const isRemote = Boolean(options?.url);
|
|
4313
|
+
const dedupKey = isRemote ? options.url : storePath;
|
|
4314
|
+
const existing = config.stores?.find((s) => isRemote ? s.url === dedupKey : s.path === dedupKey);
|
|
4137
4315
|
if (existing) return;
|
|
4138
|
-
const
|
|
4316
|
+
const newEntry = isRemote ? {
|
|
4317
|
+
url: options.url,
|
|
4318
|
+
token: options.token,
|
|
4319
|
+
scope,
|
|
4320
|
+
shared: options?.shared ?? true,
|
|
4321
|
+
// remote stores are shared by definition
|
|
4322
|
+
readonly: options?.readonly ?? false
|
|
4323
|
+
} : {
|
|
4139
4324
|
path: storePath,
|
|
4140
4325
|
scope,
|
|
4141
4326
|
shared: options?.shared ?? false,
|
|
4142
4327
|
readonly: options?.readonly ?? false
|
|
4143
|
-
}
|
|
4328
|
+
};
|
|
4329
|
+
const stores = [...config.stores ?? [], newEntry];
|
|
4144
4330
|
let configData = {};
|
|
4145
4331
|
try {
|
|
4146
4332
|
const raw = fs4.readFileSync(this.paths.config, "utf8");
|
|
@@ -4208,11 +4394,25 @@ Generate an improved version of the procedure that prevents this failure. Return
|
|
|
4208
4394
|
};
|
|
4209
4395
|
const additional = stores.map((s) => {
|
|
4210
4396
|
let count = 0;
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4397
|
+
if (s.url) {
|
|
4398
|
+
try {
|
|
4399
|
+
count = this._loadRemoteCached(s).filter((e) => e.status !== "retired").length;
|
|
4400
|
+
} catch {
|
|
4401
|
+
}
|
|
4402
|
+
} else if (s.path) {
|
|
4403
|
+
try {
|
|
4404
|
+
count = this._loadCached(s.path).filter((e) => e.status !== "retired").length;
|
|
4405
|
+
} catch {
|
|
4406
|
+
}
|
|
4214
4407
|
}
|
|
4215
|
-
return {
|
|
4408
|
+
return {
|
|
4409
|
+
path: s.path,
|
|
4410
|
+
url: s.url,
|
|
4411
|
+
scope: s.scope,
|
|
4412
|
+
shared: s.shared,
|
|
4413
|
+
readonly: s.readonly,
|
|
4414
|
+
engram_count: count
|
|
4415
|
+
};
|
|
4216
4416
|
});
|
|
4217
4417
|
return [primary, ...additional];
|
|
4218
4418
|
}
|