@plur-ai/core 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -265,10 +265,10 @@ declare const EngramSchema: z.ZodObject<{
265
265
  }, "strip", z.ZodTypeAny, {
266
266
  type: "behavioral" | "architectural" | "procedural" | "terminological";
267
267
  status: "active" | "dormant" | "retired" | "candidate";
268
+ scope: string;
268
269
  id: string;
269
270
  version: number;
270
271
  consolidated: boolean;
271
- scope: string;
272
272
  visibility: "private" | "public" | "template";
273
273
  statement: string;
274
274
  derivation_count: number;
@@ -359,8 +359,8 @@ declare const EngramSchema: z.ZodObject<{
359
359
  }, {
360
360
  type: "behavioral" | "architectural" | "procedural" | "terminological";
361
361
  status: "active" | "dormant" | "retired" | "candidate";
362
- id: string;
363
362
  scope: string;
363
+ id: string;
364
364
  statement: string;
365
365
  version?: number | undefined;
366
366
  consolidated?: boolean | undefined;
@@ -595,6 +595,23 @@ declare const EpisodeSchema: z.ZodObject<{
595
595
  }>;
596
596
  type Episode = z.infer<typeof EpisodeSchema>;
597
597
 
598
+ declare const StoreEntrySchema: z.ZodObject<{
599
+ path: z.ZodString;
600
+ scope: z.ZodString;
601
+ shared: z.ZodDefault<z.ZodBoolean>;
602
+ readonly: z.ZodDefault<z.ZodBoolean>;
603
+ }, "strip", z.ZodTypeAny, {
604
+ path: string;
605
+ scope: string;
606
+ shared: boolean;
607
+ readonly: boolean;
608
+ }, {
609
+ path: string;
610
+ scope: string;
611
+ shared?: boolean | undefined;
612
+ readonly?: boolean | undefined;
613
+ }>;
614
+ type StoreEntry = z.infer<typeof StoreEntrySchema>;
598
615
  declare const PlurConfigSchema: z.ZodObject<{
599
616
  auto_learn: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
600
617
  auto_capture: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
@@ -617,6 +634,22 @@ declare const PlurConfigSchema: z.ZodObject<{
617
634
  }>>>;
618
635
  allow_secrets: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
619
636
  index: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
637
+ stores: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
638
+ path: z.ZodString;
639
+ scope: z.ZodString;
640
+ shared: z.ZodDefault<z.ZodBoolean>;
641
+ readonly: z.ZodDefault<z.ZodBoolean>;
642
+ }, "strip", z.ZodTypeAny, {
643
+ path: string;
644
+ scope: string;
645
+ shared: boolean;
646
+ readonly: boolean;
647
+ }, {
648
+ path: string;
649
+ scope: string;
650
+ shared?: boolean | undefined;
651
+ readonly?: boolean | undefined;
652
+ }>, "many">>>;
620
653
  }, "strip", z.ZodTypeAny, {
621
654
  auto_learn?: boolean | undefined;
622
655
  auto_capture?: boolean | undefined;
@@ -631,6 +664,12 @@ declare const PlurConfigSchema: z.ZodObject<{
631
664
  } | undefined;
632
665
  allow_secrets?: boolean | undefined;
633
666
  index?: boolean | undefined;
667
+ stores?: {
668
+ path: string;
669
+ scope: string;
670
+ shared: boolean;
671
+ readonly: boolean;
672
+ }[] | undefined;
634
673
  }, {
635
674
  auto_learn?: boolean | undefined;
636
675
  auto_capture?: boolean | undefined;
@@ -645,6 +684,12 @@ declare const PlurConfigSchema: z.ZodObject<{
645
684
  } | undefined;
646
685
  allow_secrets?: boolean | undefined;
647
686
  index?: boolean | undefined;
687
+ stores?: {
688
+ path: string;
689
+ scope: string;
690
+ shared?: boolean | undefined;
691
+ readonly?: boolean | undefined;
692
+ }[] | undefined;
648
693
  }>;
649
694
  type PlurConfig = z.infer<typeof PlurConfigSchema>;
650
695
 
@@ -653,6 +698,20 @@ interface LearnContext {
653
698
  scope?: string;
654
699
  domain?: string;
655
700
  source?: string;
701
+ tags?: string[];
702
+ rationale?: string;
703
+ visibility?: 'private' | 'public' | 'template';
704
+ knowledge_anchors?: Array<{
705
+ path: string;
706
+ relevance?: string;
707
+ snippet?: string;
708
+ }>;
709
+ dual_coding?: {
710
+ example?: string;
711
+ analogy?: string;
712
+ };
713
+ abstract?: string | null;
714
+ derived_from?: string | null;
656
715
  }
657
716
  /**
658
717
  * Function that calls an LLM. Model-agnostic — consumer provides this.
@@ -680,6 +739,7 @@ interface InjectionResult {
680
739
  consider: string;
681
740
  count: number;
682
741
  tokens_used: number;
742
+ injected_ids: string[];
683
743
  }
684
744
  interface CaptureContext {
685
745
  agent?: string;
@@ -1268,6 +1328,8 @@ declare class Plur {
1268
1328
  recallExpanded(query: string, options: RecallOptions & {
1269
1329
  llm: LlmFunction;
1270
1330
  }): Promise<Engram[]>;
1331
+ /** Get a single engram by ID, regardless of status. Returns null if not found. */
1332
+ getById(id: string): Engram | null;
1271
1333
  /** List all active engrams, optionally filtered by scope/domain. No search — returns all matches. */
1272
1334
  list(options?: {
1273
1335
  scope?: string;
@@ -1283,7 +1345,7 @@ declare class Plur {
1283
1345
  /** Scored injection with embedding boost when available. Falls back to BM25 if embeddings not installed. */
1284
1346
  injectHybrid(task: string, options?: InjectOptions): Promise<InjectionResult>;
1285
1347
  private _formatInjection;
1286
- /** Update feedback_signals and adjust retrieval_strength. */
1348
+ /** Update feedback_signals and adjust retrieval_strength. Searches packs if not found in personal engrams. */
1287
1349
  feedback(id: string, signal: 'positive' | 'negative' | 'neutral'): void;
1288
1350
  /** Save extracted meta-engrams to the engram store. Skips IDs that already exist. */
1289
1351
  saveMetaEngrams(metas: Engram[]): {
@@ -1303,6 +1365,8 @@ declare class Plur {
1303
1365
  reindex(): void;
1304
1366
  /** Sync SQLite index after YAML write (no-op if index disabled) */
1305
1367
  private _syncIndex;
1368
+ /** Search packs for an engram by ID and apply feedback, writing back to the pack's engrams.yaml. */
1369
+ private _feedbackPack;
1306
1370
  /** Capture an episodic memory. */
1307
1371
  capture(summary: string, context?: CaptureContext): Episode;
1308
1372
  /** Query the episode timeline. */
@@ -1332,6 +1396,19 @@ declare class Plur {
1332
1396
  syncStatus(): SyncStatus;
1333
1397
  /** Return system health info. */
1334
1398
  status(): StatusResult;
1399
+ /** Register an additional engram store. */
1400
+ addStore(storePath: string, scope: string, options?: {
1401
+ shared?: boolean;
1402
+ readonly?: boolean;
1403
+ }): void;
1404
+ /** List all configured stores. */
1405
+ listStores(): Array<{
1406
+ path: string;
1407
+ scope: string;
1408
+ shared: boolean;
1409
+ readonly: boolean;
1410
+ engram_count: number;
1411
+ }>;
1335
1412
  }
1336
1413
 
1337
- export { type AlignmentResult, type Association, type CaptureContext, type DomainCoverage, DomainCoverageSchema, type Engram, type EngramCluster, type Episode, type EvidenceEntry, EvidenceEntrySchema, type ExtractOptions, type ExtractionResult, type Falsification, FalsificationSchema, type HierarchyPosition, HierarchyPositionSchema, IndexedStorage, type IngestCandidate, type IngestOptions, type InjectOptions, type InjectionResult, type KnowledgeAnchor, type LearnContext, type LlmFunction, type MemberAlignment, type MetaConfidence, MetaConfidenceSchema, type MetaField, MetaFieldSchema, PLATITUDE_PATTERNS, type PackManifest, Plur, type PlurConfig, type PlurPaths, type RecallOptions, type RelationalAnalysis, type RelationalTriple, SessionBreadcrumbs, type StatusResult, type StructuralTemplate, StructuralTemplateSchema, type SyncResult, type SyncStatus, type TimelineQuery, type TypedRole, type ValidationResult, type VersionCheckResult, alignCluster, analyzeStructure, checkForUpdate, classifyPolarity, clearVersionCache, clusterByStructure, computeConfidence, computeMetaConfidence, confidenceBand, detectPlurStorage, detectSecrets, engramSearchText, extractMetaEngrams, formulateMetaEngram, generateGuardrails, getCachedUpdateCheck, isPlatitude, organizeHierarchy, tokenSimilarity, validateMetaEngram };
1414
+ export { type AlignmentResult, type Association, type CaptureContext, type DomainCoverage, DomainCoverageSchema, type Engram, type EngramCluster, type Episode, type EvidenceEntry, EvidenceEntrySchema, type ExtractOptions, type ExtractionResult, type Falsification, FalsificationSchema, type HierarchyPosition, HierarchyPositionSchema, IndexedStorage, type IngestCandidate, type IngestOptions, type InjectOptions, type InjectionResult, type KnowledgeAnchor, type LearnContext, type LlmFunction, type MemberAlignment, type MetaConfidence, MetaConfidenceSchema, type MetaField, MetaFieldSchema, PLATITUDE_PATTERNS, type PackManifest, Plur, type PlurConfig, type PlurPaths, type RecallOptions, type RelationalAnalysis, type RelationalTriple, SessionBreadcrumbs, type StatusResult, type StoreEntry, type StructuralTemplate, StructuralTemplateSchema, type SyncResult, type SyncStatus, type TimelineQuery, type TypedRole, type ValidationResult, type VersionCheckResult, alignCluster, analyzeStructure, checkForUpdate, classifyPolarity, clearVersionCache, clusterByStructure, computeConfidence, computeMetaConfidence, confidenceBand, detectPlurStorage, detectSecrets, engramSearchText, extractMetaEngrams, formulateMetaEngram, generateGuardrails, getCachedUpdateCheck, isPlatitude, organizeHierarchy, tokenSimilarity, validateMetaEngram };
package/dist/index.js CHANGED
@@ -11,6 +11,10 @@ import {
11
11
  } from "./chunk-KMVQYBNP.js";
12
12
  import "./chunk-2ZDO52B4.js";
13
13
 
14
+ // src/index.ts
15
+ import * as fs3 from "fs";
16
+ import yaml5 from "js-yaml";
17
+
14
18
  // src/storage.ts
15
19
  import { existsSync, mkdirSync } from "fs";
16
20
  import { join } from "path";
@@ -433,6 +437,12 @@ import yaml2 from "js-yaml";
433
437
 
434
438
  // src/schemas/config.ts
435
439
  import { z as z3 } from "zod";
440
+ var StoreEntrySchema = z3.object({
441
+ path: z3.string(),
442
+ scope: z3.string(),
443
+ shared: z3.boolean().default(false),
444
+ readonly: z3.boolean().default(false)
445
+ });
436
446
  var PlurConfigSchema = z3.object({
437
447
  auto_learn: z3.boolean().default(true),
438
448
  auto_capture: z3.boolean().default(true),
@@ -446,7 +456,8 @@ var PlurConfigSchema = z3.object({
446
456
  co_access: z3.boolean().default(true)
447
457
  }).default({}),
448
458
  allow_secrets: z3.boolean().default(false),
449
- index: z3.boolean().default(false)
459
+ index: z3.boolean().default(false),
460
+ stores: z3.array(StoreEntrySchema).default([])
450
461
  }).partial();
451
462
 
452
463
  // src/config.ts
@@ -1996,8 +2007,9 @@ var Plur = class {
1996
2007
  consolidated: false,
1997
2008
  type: context?.type ?? "behavioral",
1998
2009
  scope,
1999
- visibility: "private",
2010
+ visibility: context?.visibility ?? "private",
2000
2011
  statement,
2012
+ rationale: context?.rationale,
2001
2013
  source: context?.source,
2002
2014
  domain: context?.domain,
2003
2015
  activation: {
@@ -2007,13 +2019,18 @@ var Plur = class {
2007
2019
  last_accessed: now.slice(0, 10)
2008
2020
  },
2009
2021
  feedback_signals: { positive: 0, negative: 0, neutral: 0 },
2010
- knowledge_anchors: [],
2022
+ knowledge_anchors: (context?.knowledge_anchors ?? []).map((a) => ({
2023
+ path: a.path,
2024
+ relevance: a.relevance ?? "supporting",
2025
+ snippet: a.snippet
2026
+ })),
2011
2027
  associations: [],
2012
2028
  derivation_count: 1,
2013
- tags: [],
2029
+ tags: context?.tags ?? [],
2014
2030
  pack: null,
2015
- abstract: null,
2016
- derived_from: null,
2031
+ abstract: context?.abstract ?? null,
2032
+ derived_from: context?.derived_from ?? null,
2033
+ dual_coding: context?.dual_coding,
2017
2034
  polarity: null,
2018
2035
  relations: conflictIds.length > 0 ? {
2019
2036
  broader: [],
@@ -2074,6 +2091,11 @@ var Plur = class {
2074
2091
  this._reactivateResults(results);
2075
2092
  return results;
2076
2093
  }
2094
+ /** Get a single engram by ID, regardless of status. Returns null if not found. */
2095
+ getById(id) {
2096
+ const engrams = loadEngrams(this.paths.engrams);
2097
+ return engrams.find((e) => e.id === id) ?? null;
2098
+ }
2077
2099
  /** List all active engrams, optionally filtered by scope/domain. No search — returns all matches. */
2078
2100
  list(options) {
2079
2101
  return this._filterEngrams(options);
@@ -2211,20 +2233,26 @@ var Plur = class {
2211
2233
  const considerStr = formatEngrams(result.consider);
2212
2234
  const count = result.directives.length + result.constraints.length + result.consider.length;
2213
2235
  const tokensUsed = result.tokens_used.directives + result.tokens_used.consider;
2236
+ const injected_ids = [
2237
+ ...result.directives.map((e) => e.id),
2238
+ ...result.constraints.map((e) => e.id),
2239
+ ...result.consider.map((e) => e.id)
2240
+ ];
2214
2241
  return {
2215
2242
  directives: directivesStr,
2216
2243
  constraints: constraintsStr,
2217
2244
  consider: considerStr,
2218
2245
  count,
2219
- tokens_used: tokensUsed
2246
+ tokens_used: tokensUsed,
2247
+ injected_ids
2220
2248
  };
2221
2249
  }
2222
- /** Update feedback_signals and adjust retrieval_strength. */
2250
+ /** Update feedback_signals and adjust retrieval_strength. Searches packs if not found in personal engrams. */
2223
2251
  feedback(id, signal) {
2224
- withLock(this.paths.engrams, () => {
2252
+ const found = withLock(this.paths.engrams, () => {
2225
2253
  const engrams = loadEngrams(this.paths.engrams);
2226
2254
  const engram = engrams.find((e) => e.id === id);
2227
- if (!engram) throw new Error(`Engram not found: ${id}`);
2255
+ if (!engram) return false;
2228
2256
  if (!engram.feedback_signals) {
2229
2257
  engram.feedback_signals = { positive: 0, negative: 0, neutral: 0 };
2230
2258
  }
@@ -2236,7 +2264,10 @@ var Plur = class {
2236
2264
  }
2237
2265
  saveEngrams(this.paths.engrams, engrams);
2238
2266
  this._syncIndex();
2267
+ return true;
2239
2268
  });
2269
+ if (found) return;
2270
+ this._feedbackPack(id, signal);
2240
2271
  }
2241
2272
  /** Save extracted meta-engrams to the engram store. Skips IDs that already exist. */
2242
2273
  saveMetaEngrams(metas) {
@@ -2312,6 +2343,31 @@ var Plur = class {
2312
2343
  this.indexedStorage.syncFromYaml();
2313
2344
  }
2314
2345
  }
2346
+ /** Search packs for an engram by ID and apply feedback, writing back to the pack's engrams.yaml. */
2347
+ _feedbackPack(id, signal) {
2348
+ if (!fs3.existsSync(this.paths.packs)) throw new Error(`Engram not found: ${id}`);
2349
+ for (const entry of fs3.readdirSync(this.paths.packs)) {
2350
+ const packDir = `${this.paths.packs}/${entry}`;
2351
+ if (!fs3.statSync(packDir).isDirectory()) continue;
2352
+ const engramsPath = `${packDir}/engrams.yaml`;
2353
+ if (!fs3.existsSync(engramsPath)) continue;
2354
+ const engrams = loadEngrams(engramsPath);
2355
+ const engram = engrams.find((e) => e.id === id);
2356
+ if (!engram) continue;
2357
+ if (!engram.feedback_signals) {
2358
+ engram.feedback_signals = { positive: 0, negative: 0, neutral: 0 };
2359
+ }
2360
+ engram.feedback_signals[signal] += 1;
2361
+ if (signal === "positive") {
2362
+ engram.activation.retrieval_strength = Math.min(1, engram.activation.retrieval_strength + 0.05);
2363
+ } else if (signal === "negative") {
2364
+ engram.activation.retrieval_strength = Math.max(0, engram.activation.retrieval_strength - 0.1);
2365
+ }
2366
+ saveEngrams(engramsPath, engrams);
2367
+ return;
2368
+ }
2369
+ throw new Error(`Engram not found: ${id}`);
2370
+ }
2315
2371
  /** Capture an episodic memory. */
2316
2372
  capture(summary, context) {
2317
2373
  return captureEpisode(this.paths.episodes, summary, context);
@@ -2385,6 +2441,47 @@ var Plur = class {
2385
2441
  config: this.config
2386
2442
  };
2387
2443
  }
2444
+ /** Register an additional engram store. */
2445
+ addStore(storePath, scope, options) {
2446
+ const config = loadConfig(this.paths.config);
2447
+ const existing = config.stores?.find((s) => s.path === storePath);
2448
+ if (existing) return;
2449
+ const stores = [...config.stores ?? [], {
2450
+ path: storePath,
2451
+ scope,
2452
+ shared: options?.shared ?? false,
2453
+ readonly: options?.readonly ?? false
2454
+ }];
2455
+ let configData = {};
2456
+ try {
2457
+ const raw = fs3.readFileSync(this.paths.config, "utf8");
2458
+ if (raw) configData = yaml5.load(raw) ?? {};
2459
+ } catch {
2460
+ }
2461
+ configData.stores = stores;
2462
+ fs3.writeFileSync(this.paths.config, yaml5.dump(configData, { lineWidth: 120, noRefs: true }));
2463
+ this.config = loadConfig(this.paths.config);
2464
+ }
2465
+ /** List all configured stores. */
2466
+ listStores() {
2467
+ const stores = this.config.stores ?? [];
2468
+ const primary = {
2469
+ path: this.paths.engrams,
2470
+ scope: "global",
2471
+ shared: false,
2472
+ readonly: false,
2473
+ engram_count: loadEngrams(this.paths.engrams).filter((e) => e.status !== "retired").length
2474
+ };
2475
+ const additional = stores.map((s) => {
2476
+ let count = 0;
2477
+ try {
2478
+ count = loadEngrams(s.path).filter((e) => e.status !== "retired").length;
2479
+ } catch {
2480
+ }
2481
+ return { ...s, engram_count: count };
2482
+ });
2483
+ return [primary, ...additional];
2484
+ }
2388
2485
  };
2389
2486
  export {
2390
2487
  DomainCoverageSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plur-ai/core",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",