@plur-ai/core 0.9.1 → 0.9.3
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.
|
@@ -101,7 +101,11 @@ function searchEngrams(engrams, query, limit = 20) {
|
|
|
101
101
|
if (queryTokens.length === 0) return [];
|
|
102
102
|
const idfWeights = computeIdf(engrams, queryTokens);
|
|
103
103
|
const avgDocLength = engrams.length > 0 ? engrams.reduce((sum, e) => sum + ftsTokenize(engramSearchText(e)).length, 0) / engrams.length : 0;
|
|
104
|
-
|
|
104
|
+
let scored = engrams.map((e) => ({ engram: e, score: ftsScore(e, queryTokens, idfWeights, avgDocLength) })).filter((r) => r.score > 0);
|
|
105
|
+
if (scored.length === 0) {
|
|
106
|
+
scored = engrams.map((e) => ({ engram: e, score: ftsScore(e, queryTokens, void 0, avgDocLength) })).filter((r) => r.score > 0);
|
|
107
|
+
}
|
|
108
|
+
return scored.sort((a, b) => b.score - a.score).slice(0, limit).map((r) => r.engram);
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
// src/embeddings.ts
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
ftsScore,
|
|
7
7
|
ftsTokenize,
|
|
8
8
|
searchEngrams
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-IGGMRXAB.js";
|
|
10
10
|
import {
|
|
11
11
|
EngramSchemaPassthrough,
|
|
12
12
|
appendHistory,
|
|
@@ -33,12 +33,12 @@ import {
|
|
|
33
33
|
sync,
|
|
34
34
|
withLock
|
|
35
35
|
} from "./chunk-PRK3B7WR.js";
|
|
36
|
-
import
|
|
37
|
-
__require
|
|
38
|
-
} from "./chunk-2ZDO52B4.js";
|
|
36
|
+
import "./chunk-2ZDO52B4.js";
|
|
39
37
|
|
|
40
38
|
// src/index.ts
|
|
41
39
|
import * as fs4 from "fs";
|
|
40
|
+
import * as os from "os";
|
|
41
|
+
import * as path3 from "path";
|
|
42
42
|
import yaml6 from "js-yaml";
|
|
43
43
|
|
|
44
44
|
// src/storage.ts
|
|
@@ -772,8 +772,8 @@ function generateEpisodeId() {
|
|
|
772
772
|
const rand = Math.random().toString(36).slice(2, 6);
|
|
773
773
|
return `EP-${ts}-${rand}`;
|
|
774
774
|
}
|
|
775
|
-
function captureEpisode(
|
|
776
|
-
const episodes = loadEpisodes(
|
|
775
|
+
function captureEpisode(path4, summary, context) {
|
|
776
|
+
const episodes = loadEpisodes(path4);
|
|
777
777
|
const episode = {
|
|
778
778
|
id: generateEpisodeId(),
|
|
779
779
|
summary,
|
|
@@ -784,11 +784,11 @@ function captureEpisode(path3, summary, context) {
|
|
|
784
784
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
785
785
|
};
|
|
786
786
|
episodes.push(episode);
|
|
787
|
-
atomicWrite(
|
|
787
|
+
atomicWrite(path4, yaml2.dump(episodes, { lineWidth: 120, noRefs: true }));
|
|
788
788
|
return episode;
|
|
789
789
|
}
|
|
790
|
-
function queryTimeline(
|
|
791
|
-
let episodes = loadEpisodes(
|
|
790
|
+
function queryTimeline(path4, query) {
|
|
791
|
+
let episodes = loadEpisodes(path4);
|
|
792
792
|
if (query?.since) episodes = episodes.filter((e) => new Date(e.timestamp) >= query.since);
|
|
793
793
|
if (query?.until) episodes = episodes.filter((e) => new Date(e.timestamp) <= query.until);
|
|
794
794
|
if (query?.agent) episodes = episodes.filter((e) => e.agent === query.agent);
|
|
@@ -799,10 +799,10 @@ function queryTimeline(path3, query) {
|
|
|
799
799
|
}
|
|
800
800
|
return episodes;
|
|
801
801
|
}
|
|
802
|
-
function loadEpisodes(
|
|
803
|
-
if (!existsSync4(
|
|
802
|
+
function loadEpisodes(path4) {
|
|
803
|
+
if (!existsSync4(path4)) return [];
|
|
804
804
|
try {
|
|
805
|
-
const raw = yaml2.load(readFileSync2(
|
|
805
|
+
const raw = yaml2.load(readFileSync2(path4, "utf8"));
|
|
806
806
|
return Array.isArray(raw) ? raw : [];
|
|
807
807
|
} catch {
|
|
808
808
|
return [];
|
|
@@ -1585,7 +1585,7 @@ async function computeSimilarityMatrix(templates) {
|
|
|
1585
1585
|
const n = templates.length;
|
|
1586
1586
|
const matrix = Array.from({ length: n }, () => Array(n).fill(0));
|
|
1587
1587
|
try {
|
|
1588
|
-
const { embed, cosineSimilarity } = await import("./embeddings-
|
|
1588
|
+
const { embed, cosineSimilarity } = await import("./embeddings-ZRT6IRPA.js");
|
|
1589
1589
|
const embeddings = [];
|
|
1590
1590
|
for (const t of templates) {
|
|
1591
1591
|
embeddings.push(await embed(t));
|
|
@@ -2966,6 +2966,10 @@ var Plur = class {
|
|
|
2966
2966
|
constructor(options) {
|
|
2967
2967
|
this.paths = detectPlurStorage(options?.path);
|
|
2968
2968
|
this.config = loadConfig(this.paths.config);
|
|
2969
|
+
this.autoDiscoverStores();
|
|
2970
|
+
if (this.config.stores?.length !== loadConfig(this.paths.config).stores?.length) {
|
|
2971
|
+
this.config = loadConfig(this.paths.config);
|
|
2972
|
+
}
|
|
2969
2973
|
if (this.config.index) {
|
|
2970
2974
|
this.indexedStorage = new IndexedStorage(this.paths.engrams, this.paths.db, this.config.stores);
|
|
2971
2975
|
}
|
|
@@ -3010,17 +3014,17 @@ var Plur = class {
|
|
|
3010
3014
|
return all;
|
|
3011
3015
|
}
|
|
3012
3016
|
/** Load engrams from a path with mtime-based caching */
|
|
3013
|
-
_loadCached(
|
|
3017
|
+
_loadCached(path4) {
|
|
3014
3018
|
let mtime;
|
|
3015
3019
|
try {
|
|
3016
|
-
mtime = fs4.statSync(
|
|
3020
|
+
mtime = fs4.statSync(path4, { bigint: true }).mtimeNs;
|
|
3017
3021
|
} catch {
|
|
3018
3022
|
return [];
|
|
3019
3023
|
}
|
|
3020
|
-
const cached = this._engramCache.get(
|
|
3024
|
+
const cached = this._engramCache.get(path4);
|
|
3021
3025
|
if (cached && cached.mtime === mtime) return cached.engrams;
|
|
3022
|
-
const engrams = loadEngrams(
|
|
3023
|
-
this._engramCache.set(
|
|
3026
|
+
const engrams = loadEngrams(path4);
|
|
3027
|
+
this._engramCache.set(path4, { mtime, engrams });
|
|
3024
3028
|
return engrams;
|
|
3025
3029
|
}
|
|
3026
3030
|
/**
|
|
@@ -3034,9 +3038,9 @@ var Plur = class {
|
|
|
3034
3038
|
* invalidation on write removes the filesystem as a source of cache
|
|
3035
3039
|
* freshness and closes the race. See issue #25.
|
|
3036
3040
|
*/
|
|
3037
|
-
_writeEngrams(
|
|
3038
|
-
saveEngrams(
|
|
3039
|
-
this._engramCache.delete(
|
|
3041
|
+
_writeEngrams(path4, engrams) {
|
|
3042
|
+
saveEngrams(path4, engrams);
|
|
3043
|
+
this._engramCache.delete(path4);
|
|
3040
3044
|
}
|
|
3041
3045
|
/** Find which store owns an engram by ID. For namespaced IDs, strips prefix to find in store. */
|
|
3042
3046
|
_findEngramStore(id) {
|
|
@@ -3197,12 +3201,12 @@ var Plur = class {
|
|
|
3197
3201
|
}
|
|
3198
3202
|
/** Async learn with LLM-driven deduplication (Ideas 1+2+19). */
|
|
3199
3203
|
async learnAsync(statement, context) {
|
|
3200
|
-
const { learnAsync: learnAsyncImpl } = await import("./learn-async-
|
|
3204
|
+
const { learnAsync: learnAsyncImpl } = await import("./learn-async-R5KZ5EWF.js");
|
|
3201
3205
|
return learnAsyncImpl(this._learnAsyncDeps(), statement, context);
|
|
3202
3206
|
}
|
|
3203
3207
|
/** Batch learn with LLM dedup. */
|
|
3204
3208
|
async learnBatch(statements, llm) {
|
|
3205
|
-
const { learnBatch: learnBatchImpl } = await import("./learn-async-
|
|
3209
|
+
const { learnBatch: learnBatchImpl } = await import("./learn-async-R5KZ5EWF.js");
|
|
3206
3210
|
return learnBatchImpl(this._learnAsyncDeps(), statements, llm);
|
|
3207
3211
|
}
|
|
3208
3212
|
/**
|
|
@@ -3871,21 +3875,20 @@ Generate an improved version of the procedure that prevents this failure. Return
|
|
|
3871
3875
|
autoDiscoverStores(cwd) {
|
|
3872
3876
|
const startDir = cwd || process.cwd();
|
|
3873
3877
|
const discovered = [];
|
|
3874
|
-
const os = __require("os");
|
|
3875
3878
|
const tmpDir = os.tmpdir();
|
|
3876
3879
|
if (this.paths.root.startsWith(tmpDir) || this.paths.root.startsWith("/tmp/")) {
|
|
3877
3880
|
return discovered;
|
|
3878
3881
|
}
|
|
3879
3882
|
const knownPaths = new Set((this.config.stores ?? []).map((s) => s.path));
|
|
3880
|
-
const primaryDir =
|
|
3883
|
+
const primaryDir = path3.dirname(this.paths.engrams);
|
|
3881
3884
|
let dir = startDir;
|
|
3882
|
-
const { join: join5, dirname:
|
|
3885
|
+
const { join: join5, dirname: dirname3, basename: basename2 } = path3;
|
|
3883
3886
|
const visited = /* @__PURE__ */ new Set();
|
|
3884
3887
|
while (dir && !visited.has(dir)) {
|
|
3885
3888
|
visited.add(dir);
|
|
3886
3889
|
const candidate = join5(dir, ".plur", "engrams.yaml");
|
|
3887
3890
|
if (join5(dir, ".plur") === primaryDir) {
|
|
3888
|
-
dir =
|
|
3891
|
+
dir = dirname3(dir);
|
|
3889
3892
|
continue;
|
|
3890
3893
|
}
|
|
3891
3894
|
if (fs4.existsSync(candidate) && !knownPaths.has(candidate)) {
|
|
@@ -3904,7 +3907,7 @@ Generate an improved version of the procedure that prevents this failure. Return
|
|
|
3904
3907
|
logger.info(`Auto-discovered project store: ${candidate} (${scope})`);
|
|
3905
3908
|
}
|
|
3906
3909
|
if (fs4.existsSync(join5(dir, ".git"))) break;
|
|
3907
|
-
const parent =
|
|
3910
|
+
const parent = dirname3(dir);
|
|
3908
3911
|
if (parent === dir) break;
|
|
3909
3912
|
dir = parent;
|
|
3910
3913
|
}
|
|
@@ -135,6 +135,9 @@ async function learnAsync(deps, statement, context) {
|
|
|
135
135
|
} catch {
|
|
136
136
|
candidates = deps.recall(statement, { limit: 5 });
|
|
137
137
|
}
|
|
138
|
+
if (candidates.length === 0) {
|
|
139
|
+
candidates = deps.recall(statement, { limit: 5 });
|
|
140
|
+
}
|
|
138
141
|
candidates = candidates.filter((c) => c.status === "active");
|
|
139
142
|
if (candidates.length === 0) {
|
|
140
143
|
return { engram: deps.learn(statement, context), decision: "ADD" };
|