@plur-ai/core 0.9.5 → 0.9.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/dist/index.d.ts CHANGED
@@ -2252,6 +2252,16 @@ declare class Plur {
2252
2252
  * freshness and closes the race. See issue #25.
2253
2253
  */
2254
2254
  private _writeEngrams;
2255
+ /**
2256
+ * Resolve a remote store for a write scope. Returns the RemoteStore driver
2257
+ * if the engram's scope matches a registered remote entry, else null.
2258
+ *
2259
+ * Match rule (pilot scope): exact-match `entry.scope === engramScope`. We
2260
+ * intentionally don't do prefix-match yet — agents that want to write to a
2261
+ * narrower scope than they registered must explicitly register the narrower
2262
+ * scope. Keeps routing predictable and prevents accidental cross-team writes.
2263
+ */
2264
+ private _resolveRemoteStoreForScope;
2255
2265
  /** Find which store owns an engram by ID. For namespaced IDs, strips prefix to find in store. */
2256
2266
  private _findEngramStore;
2257
2267
  /** Content hash fast-path dedup. */
package/dist/index.js CHANGED
@@ -283,10 +283,31 @@ var PlurConfigSchema = z.object({
283
283
  // src/config.ts
284
284
  function loadConfig(configPath) {
285
285
  if (!existsSync3(configPath)) return PlurConfigSchema.parse({});
286
+ let raw;
286
287
  try {
287
- const raw = yaml.load(readFileSync(configPath, "utf8"));
288
- return PlurConfigSchema.parse(raw ?? {});
289
- } catch {
288
+ raw = yaml.load(readFileSync(configPath, "utf8")) ?? {};
289
+ } catch (err) {
290
+ logger.warning(`[plur:config] cannot parse YAML at ${configPath}: ${err.message} \u2014 falling back to defaults`);
291
+ return PlurConfigSchema.parse({});
292
+ }
293
+ if (Array.isArray(raw.stores)) {
294
+ const validStores = [];
295
+ for (let i = 0; i < raw.stores.length; i++) {
296
+ const entry = raw.stores[i];
297
+ const parsed = StoreEntrySchema.safeParse(entry);
298
+ if (parsed.success) {
299
+ validStores.push(entry);
300
+ } else {
301
+ const label = entry?.scope ?? entry?.url ?? entry?.path ?? `index ${i}`;
302
+ logger.warning(`[plur:config] dropping invalid stores[${i}] (${label}) from ${configPath}: ${parsed.error.issues.map((it) => it.message).join("; ")}`);
303
+ }
304
+ }
305
+ raw.stores = validStores;
306
+ }
307
+ try {
308
+ return PlurConfigSchema.parse(raw);
309
+ } catch (err) {
310
+ logger.warning(`[plur:config] top-level config invalid at ${configPath}: ${err.message} \u2014 falling back to defaults`);
290
311
  return PlurConfigSchema.parse({});
291
312
  }
292
313
  }
@@ -3442,6 +3463,31 @@ var Plur = class {
3442
3463
  saveEngrams(path3, engrams);
3443
3464
  this._engramCache.delete(path3);
3444
3465
  }
3466
+ /**
3467
+ * Resolve a remote store for a write scope. Returns the RemoteStore driver
3468
+ * if the engram's scope matches a registered remote entry, else null.
3469
+ *
3470
+ * Match rule (pilot scope): exact-match `entry.scope === engramScope`. We
3471
+ * intentionally don't do prefix-match yet — agents that want to write to a
3472
+ * narrower scope than they registered must explicitly register the narrower
3473
+ * scope. Keeps routing predictable and prevents accidental cross-team writes.
3474
+ */
3475
+ _resolveRemoteStoreForScope(scope) {
3476
+ const stores = this.config.stores ?? [];
3477
+ for (const entry of stores) {
3478
+ if (!entry.url) continue;
3479
+ if (entry.readonly === true) continue;
3480
+ if (entry.scope !== scope) continue;
3481
+ const key = `${entry.url}::${entry.scope}`;
3482
+ let driver = this._remoteStores.get(key);
3483
+ if (!driver) {
3484
+ driver = new RemoteStore(entry.url, entry.token ?? "", entry.scope);
3485
+ this._remoteStores.set(key, driver);
3486
+ }
3487
+ return driver;
3488
+ }
3489
+ return null;
3490
+ }
3445
3491
  /** Find which store owns an engram by ID. For namespaced IDs, strips prefix to find in store. */
3446
3492
  _findEngramStore(id) {
3447
3493
  const primaryEngrams = this._loadCached(this.paths.engrams);
@@ -3572,6 +3618,19 @@ var Plur = class {
3572
3618
  } : void 0,
3573
3619
  pinned: context?.pinned === true ? true : void 0
3574
3620
  };
3621
+ const remoteDriver = this._resolveRemoteStoreForScope(scope);
3622
+ if (remoteDriver) {
3623
+ void remoteDriver.append(engram).catch((err) => {
3624
+ logger.error(`[plur:learn] remote append failed for ${engram.id} (scope=${scope}): ${err.message}`);
3625
+ });
3626
+ appendHistory(this.paths.root, {
3627
+ event: "engram_created",
3628
+ engram_id: engram.id,
3629
+ timestamp: now,
3630
+ data: { type: engram.type, scope: engram.scope, source: engram.source, routed_to: "remote" }
3631
+ });
3632
+ return engram;
3633
+ }
3575
3634
  engrams.push(engram);
3576
3635
  this._writeEngrams(this.paths.engrams, engrams);
3577
3636
  this._syncIndex();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plur-ai/core",
3
- "version": "0.9.5",
3
+ "version": "0.9.7",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",