@voltro/cache 0.84.0 → 0.86.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.
@@ -1,6 +1,6 @@
1
1
  # Third-Party Notices — @voltro/cache
2
2
 
3
- This package depends on the open-source software listed below. Each is the
3
+ This package uses the open-source software listed below. Each is the
4
4
  property of its respective copyright holders and is used under the terms of
5
5
  its license. This file is provided for attribution; it grants no rights in
6
6
  @voltro/cache itself, which is proprietary (see LICENSE).
package/dist/Cache.js ADDED
@@ -0,0 +1,89 @@
1
+ import { CacheStore as e } from "./CacheStore.js";
2
+ import { Clock as t, Context as n, Deferred as r, Effect as i, HashMap as a, Layer as o, Metric as s, Option as c, SynchronizedRef as l } from "effect";
3
+ //#region src/Cache.ts
4
+ var u = (e) => typeof e == "object" && !!e && e._voltroSwr === 1, d = class d extends n.Service()("@voltro/Cache", { make: i.gen(function* () {
5
+ let n = yield* e, o = yield* l.make(a.empty()), d = s.counter("voltro_cache_hits"), f = s.counter("voltro_cache_misses"), p = (e, r, a) => {
6
+ let o = a.tags === void 0 ? {} : { tags: a.tags }, s = a.swrMs;
7
+ if (s !== void 0) {
8
+ let c = a.ttlMs ?? 0;
9
+ return t.currentTimeMillis.pipe(i.flatMap((t) => n.setWithTags(e, {
10
+ _voltroSwr: 1,
11
+ v: r,
12
+ freshUntil: t + c
13
+ }, {
14
+ ttlMs: c + s,
15
+ ...o
16
+ })));
17
+ }
18
+ let c = a.ttlMs === void 0 ? {} : { ttlMs: a.ttlMs };
19
+ return n.setWithTags(e, r, {
20
+ ...c,
21
+ ...o
22
+ });
23
+ }, m = (e, t, n) => n.pipe(i.tap((n) => p(e, n, t))), h = (e, t) => l.modifyEffect(o, (t) => {
24
+ let n = a.get(t, e);
25
+ return c.isSome(n) ? i.succeed([{
26
+ kind: "await",
27
+ deferred: n.value
28
+ }, t]) : r.make().pipe(i.map((n) => [{
29
+ kind: "own",
30
+ deferred: n
31
+ }, a.set(t, e, n)]));
32
+ }).pipe(i.flatMap((n) => {
33
+ if (n.kind === "await") return r.await(n.deferred);
34
+ let s = n.deferred;
35
+ return t.pipe(i.onExit((t) => r.done(s, t).pipe(i.andThen(l.update(o, (t) => a.remove(t, e))))));
36
+ })), g = (e, r, a) => n.get(e).pipe(i.flatMap((n) => {
37
+ if (c.isSome(n)) {
38
+ let o = n.value;
39
+ return u(o) ? s.update(d, 1).pipe(i.andThen(t.currentTimeMillis), i.flatMap((t) => {
40
+ if (t < o.freshUntil) return i.succeed(o.v);
41
+ let n = h(e, m(e, r, a)).pipe(i.catchCause(() => i.void));
42
+ return i.forkDetach(n).pipe(i.as(o.v));
43
+ })) : s.update(d, 1).pipe(i.as(o));
44
+ }
45
+ return s.update(f, 1).pipe(i.andThen(h(e, m(e, r, a))));
46
+ }));
47
+ return {
48
+ get: (e) => n.get(e),
49
+ set: (e, t, r) => n.set(e, t, r),
50
+ setWithTags: (e, t, r) => n.setWithTags(e, t, r),
51
+ put: (e, t, n) => p(e, n, t),
52
+ remove: n.remove,
53
+ has: n.has,
54
+ clear: n.clear,
55
+ invalidateTag: n.invalidateTag,
56
+ wrap: g,
57
+ partition: (e, t = {}) => {
58
+ let r = (t) => `${e}:${t}`, i = (e) => ({
59
+ ...t.ttlMs === void 0 ? {} : { ttlMs: t.ttlMs },
60
+ ...t.swrMs === void 0 ? {} : { swrMs: t.swrMs },
61
+ ...t.tags === void 0 ? {} : { tags: t.tags },
62
+ ...e
63
+ });
64
+ return {
65
+ get: (e) => n.get(r(e)),
66
+ set: (e, i, a) => n.set(r(e), i, a ?? (t.ttlMs === void 0 ? void 0 : { ttlMs: t.ttlMs })),
67
+ has: (e) => n.has(r(e)),
68
+ remove: (e) => n.remove(r(e)),
69
+ wrap: (e, t, n) => g(r(e), i(t), n),
70
+ invalidateTag: (e) => n.invalidateTag(e)
71
+ };
72
+ },
73
+ stats: () => i.all({
74
+ hits: s.value(d),
75
+ misses: s.value(f)
76
+ }).pipe(i.map(({ hits: e, misses: t }) => {
77
+ let n = Number(e.count), r = Number(t.count), i = n + r;
78
+ return {
79
+ hits: n,
80
+ misses: r,
81
+ hitRate: i === 0 ? 0 : n / i
82
+ };
83
+ }))
84
+ };
85
+ }) }) {
86
+ static layer = o.effect(d, d.make);
87
+ };
88
+ //#endregion
89
+ export { d as Cache };
@@ -0,0 +1,5 @@
1
+ import { Context as e } from "effect";
2
+ //#region src/CacheStore.ts
3
+ var t = class extends e.Service()("@voltro/CacheStore") {};
4
+ //#endregion
5
+ export { t as CacheStore };
@@ -0,0 +1,11 @@
1
+ //#region \0rolldown/runtime.js
2
+ var e = Object.defineProperty, t = (t, n) => {
3
+ let r = {};
4
+ for (var i in t) e(r, i, {
5
+ get: t[i],
6
+ enumerable: !0
7
+ });
8
+ return n || e(r, Symbol.toStringTag, { value: "Module" }), r;
9
+ };
10
+ //#endregion
11
+ export { t as __exportAll };
@@ -0,0 +1,114 @@
1
+ import { CacheStore as e } from "./CacheStore.js";
2
+ import { Clock as t, Effect as n, HashMap as r, HashSet as i, Layer as a, Option as o, Ref as s } from "effect";
3
+ //#region src/backendMemory.ts
4
+ var c = {
5
+ entries: r.empty(),
6
+ tagIndex: r.empty(),
7
+ seq: 0,
8
+ oldest: void 0,
9
+ newest: void 0
10
+ }, l = (e, t, n) => {
11
+ let a = e;
12
+ for (let e of n) {
13
+ let n = r.get(a, e);
14
+ if (o.isNone(n)) continue;
15
+ let s = i.remove(n.value, t);
16
+ a = i.size(s) === 0 ? r.remove(a, e) : r.set(a, e, s);
17
+ }
18
+ return a;
19
+ }, u = (e, t) => {
20
+ let n = r.get(e.entries, t);
21
+ if (o.isNone(n)) return e;
22
+ let { older: i, newer: a } = n.value, s = r.remove(e.entries, t);
23
+ if (i !== void 0) {
24
+ let e = r.get(s, i);
25
+ o.isSome(e) && (s = r.set(s, i, {
26
+ ...e.value,
27
+ newer: a
28
+ }));
29
+ }
30
+ if (a !== void 0) {
31
+ let e = r.get(s, a);
32
+ o.isSome(e) && (s = r.set(s, a, {
33
+ ...e.value,
34
+ older: i
35
+ }));
36
+ }
37
+ return {
38
+ entries: s,
39
+ tagIndex: l(e.tagIndex, t, n.value.tags),
40
+ seq: e.seq,
41
+ oldest: i === void 0 ? a : e.oldest,
42
+ newest: a === void 0 ? i : e.newest
43
+ };
44
+ }, d = (e, t, n) => {
45
+ let a = r.get(e, t), s = o.isSome(a) ? i.add(a.value, n) : i.make(n);
46
+ return r.set(e, t, s);
47
+ }, f = (e, t) => {
48
+ let n = r.size(e.entries) - t;
49
+ if (n <= 0) return e;
50
+ let i = e;
51
+ for (let e = 0; e < n; e++) {
52
+ let e = i.oldest;
53
+ if (e === void 0) break;
54
+ i = u(i, e);
55
+ }
56
+ return i;
57
+ }, p = (e, t, n, i, a, s) => {
58
+ let c = u(e, t), l = c.seq + 1, p = c.tagIndex;
59
+ for (let e of a) p = d(p, e, t);
60
+ let m = r.set(c.entries, t, {
61
+ value: n,
62
+ expiresAt: i,
63
+ tags: a,
64
+ seq: l,
65
+ older: c.newest,
66
+ newer: void 0
67
+ });
68
+ if (c.newest !== void 0) {
69
+ let e = r.get(m, c.newest);
70
+ o.isSome(e) && (m = r.set(m, c.newest, {
71
+ ...e.value,
72
+ newer: t
73
+ }));
74
+ }
75
+ let h = {
76
+ entries: m,
77
+ tagIndex: p,
78
+ seq: l,
79
+ oldest: c.oldest ?? t,
80
+ newest: t
81
+ };
82
+ return s === void 0 ? h : f(h, s);
83
+ }, m = (e, t) => t === void 0 ? Infinity : e + t, h = (e) => n.gen(function* () {
84
+ let i = yield* s.make(c), a = e.maxEntries, l = e.now === void 0 ? t.currentTimeMillis : n.sync(e.now);
85
+ return {
86
+ get: (e) => l.pipe(n.flatMap((t) => s.modify(i, (n) => {
87
+ let i = r.get(n.entries, e);
88
+ return o.isNone(i) ? [o.none(), n] : i.value.expiresAt <= t ? [o.none(), u(n, e)] : [o.some(i.value.value), n];
89
+ }))),
90
+ set: (e, t, r) => l.pipe(n.flatMap((n) => s.update(i, (i) => p(i, e, t, m(n, r?.ttlMs), [], a)))),
91
+ setWithTags: (e, t, r) => l.pipe(n.flatMap((n) => s.update(i, (i) => p(i, e, t, m(n, r.ttlMs), r.tags ?? [], a)))),
92
+ remove: (e) => l.pipe(n.flatMap((t) => s.modify(i, (n) => {
93
+ let i = r.get(n.entries, e);
94
+ return o.isNone(i) ? [!1, n] : [i.value.expiresAt > t, u(n, e)];
95
+ }))),
96
+ has: (e) => l.pipe(n.flatMap((t) => s.modify(i, (n) => {
97
+ let i = r.get(n.entries, e);
98
+ return o.isNone(i) ? [!1, n] : i.value.expiresAt <= t ? [!1, u(n, e)] : [!0, n];
99
+ }))),
100
+ clear: () => s.set(i, c),
101
+ invalidateTag: (e) => s.modify(i, (t) => {
102
+ let n = r.get(t.tagIndex, e);
103
+ if (o.isNone(n)) return [0, t];
104
+ let i = t, a = 0;
105
+ for (let e of n.value) i = u(i, e), a += 1;
106
+ return [a, {
107
+ ...i,
108
+ tagIndex: r.remove(i.tagIndex, e)
109
+ }];
110
+ })
111
+ };
112
+ }), g = (t = {}) => a.effect(e, h(t));
113
+ //#endregion
114
+ export { g as layerMemory };
@@ -0,0 +1,56 @@
1
+ import { CacheError as e } from "./errors.js";
2
+ import { CacheStore as t } from "./CacheStore.js";
3
+ import { Clock as n, Effect as r, Layer as i, Option as a } from "effect";
4
+ import { commandRetry as o, connect as s } from "@voltro/kv/connection";
5
+ //#region src/backendRedis.ts
6
+ var c = (t) => s({
7
+ url: t.url,
8
+ driver: t.driver,
9
+ ...t.token === void 0 ? {} : { token: t.token }
10
+ }).pipe(r.mapError((t) => new e({
11
+ operation: "connect",
12
+ key: "",
13
+ cause: String(t)
14
+ }))), l = "\nlocal NOEXP = 9000000000000000\nlocal ttl = tonumber(ARGV[1])\nlocal now = tonumber(ARGV[2])\nlocal score\nif ttl < 0 then score = NOEXP else score = now + ttl end\nredis.call('ZADD', KEYS[1], score, ARGV[3])\nlocal top = redis.call('ZREVRANGE', KEYS[1], 0, 0, 'WITHSCORES')\nlocal maxScore = tonumber(top[2])\nif maxScore >= NOEXP then\n redis.call('PERSIST', KEYS[1])\nelse\n local rem = maxScore - now\n if rem < 1 then rem = 1 end\n redis.call('PEXPIRE', KEYS[1], rem)\nend\nreturn 1\n", u = (t) => r.gen(function* () {
15
+ let i = yield* r.acquireRelease(c(t), (e) => r.promise(() => e.close().catch(() => void 0))), s = t.keyPrefix ?? "voltro:cache", u = (e) => `${s}:v:${e}`, d = (e) => `${s}:t:${e}`, f = (t, n, a) => r.tryPromise({
16
+ try: () => a(i),
17
+ catch: (r) => new e({
18
+ operation: t,
19
+ key: n,
20
+ cause: String(r)
21
+ })
22
+ }).pipe(r.retry(o)), p = (t, n) => r.try({
23
+ try: () => JSON.stringify(n),
24
+ catch: (n) => new e({
25
+ operation: "serialize",
26
+ key: t,
27
+ cause: String(n)
28
+ })
29
+ }), m = (t, n) => r.try({
30
+ try: () => a.some(JSON.parse(n)),
31
+ catch: (n) => new e({
32
+ operation: "deserialize",
33
+ key: t,
34
+ cause: String(n)
35
+ })
36
+ }), h = (e) => f("clear", "", (t) => t.scan(e, `${s}:*`, 200)).pipe(r.flatMap(({ cursor: e, keys: t }) => (t.length > 0 ? f("clear", "", (e) => e.del(t)) : r.succeed(0)).pipe(r.flatMap(() => e === "0" ? r.void : h(e))))), g = (e, t, n) => p(e, t).pipe(r.flatMap((t) => n !== void 0 && n > 0 ? f("set", e, (r) => r.psetex(u(e), Math.ceil(n), t)) : f("set", e, (n) => n.set(u(e), t))), r.asVoid);
37
+ return {
38
+ get: (e) => f("get", e, (t) => t.get(u(e))).pipe(r.flatMap((t) => t === null ? r.succeed(a.none()) : m(e, t))),
39
+ set: (e, t, n) => g(e, t, n?.ttlMs),
40
+ setWithTags: (e, t, i) => g(e, t, i.ttlMs).pipe(r.flatMap(() => {
41
+ let t = i.tags ?? [];
42
+ if (t.length === 0) return r.void;
43
+ let a = i.ttlMs !== void 0 && i.ttlMs > 0 ? Math.ceil(i.ttlMs) : -1;
44
+ return n.currentTimeMillis.pipe(r.flatMap((n) => r.forEach(t, (t) => f("setWithTags", e, (r) => r.eval(l, 1, d(t), a, n, e)), { discard: !0 })));
45
+ })),
46
+ remove: (e) => f("remove", e, (t) => t.del([u(e)])).pipe(r.map((e) => e > 0)),
47
+ has: (e) => f("has", e, (t) => t.exists(u(e))).pipe(r.map((e) => e > 0)),
48
+ clear: () => h("0"),
49
+ invalidateTag: (e) => f("invalidateTag", e, (t) => t.zrange(d(e))).pipe(r.flatMap((t) => f("invalidateTag", e, async (n) => {
50
+ let r = t.map(u), i = r.length > 0 ? await n.del(r) : 0;
51
+ return await n.del([d(e)]), i;
52
+ })))
53
+ };
54
+ }), d = (e) => i.effect(t, u(e));
55
+ //#endregion
56
+ export { d as layerRedis };
package/dist/errors.js ADDED
@@ -0,0 +1,9 @@
1
+ import { Schema as e } from "effect";
2
+ //#region src/errors.ts
3
+ var t = class extends e.TaggedError()("CacheError", {
4
+ operation: e.String,
5
+ key: e.String,
6
+ cause: e.String
7
+ }) {};
8
+ //#endregion
9
+ export { t as CacheError };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ConfigError } from 'effect';
1
+ import { Config } from 'effect';
2
2
  import { Context } from 'effect';
3
3
  import { Effect } from 'effect';
4
4
  import { Layer } from 'effect';
@@ -6,12 +6,42 @@ import { Option } from 'effect';
6
6
  import { Schema } from 'effect';
7
7
  import { Scope } from 'effect';
8
8
  import { Stream } from 'effect';
9
+ import { YieldableError } from 'effect/Cause';
9
10
 
10
11
  export declare class Cache extends Cache_base {
12
+ /** `Cache` over whatever `CacheStore` is provided. */
13
+ static readonly layer: Layer.Layer<Cache, never, CacheStore>;
11
14
  }
12
15
 
13
- declare const Cache_base: Effect.Service.Class<Cache, "@voltro/Cache", {
14
- readonly effect: Effect.Effect<{
16
+ declare const Cache_base: Context.ServiceClass<Cache, "@voltro/Cache", {
17
+ /** Read a typed value. `None` on miss/expiry. */
18
+ readonly get: <A = unknown>(key: string) => Effect.Effect<Option.Option<A>, CacheError>;
19
+ readonly set: <A>(key: string, value: A, options?: CacheSetOptions) => Effect.Effect<void, CacheError>;
20
+ readonly setWithTags: <A>(key: string, value: A, options: CacheSetWithTagsOptions) => Effect.Effect<void, CacheError>;
21
+ /** Write-through with the SAME storage shape `wrap` uses (incl. the
22
+ * SWR envelope) — so a value written here is read back identically
23
+ * by a later `wrap`. The dispatcher uses this to keep cached
24
+ * snapshots warm from its live recompute. */
25
+ readonly put: <A>(key: string, options: WrapOptions, value: A) => Effect.Effect<void, CacheError>;
26
+ readonly remove: (key: string) => Effect.Effect<boolean, CacheError>;
27
+ readonly has: (key: string) => Effect.Effect<boolean, CacheError>;
28
+ readonly clear: () => Effect.Effect<void, CacheError>;
29
+ readonly invalidateTag: (tag: string) => Effect.Effect<number, CacheError>;
30
+ readonly wrap: <A, E, R>(key: string, options: WrapOptions, compute: Effect.Effect<A, E, R>) => Effect.Effect<A, E | CacheError, R>;
31
+ /** A named, key-prefixed partition with its own default ttl/swr/tags.
32
+ * Keys become `<name>:<key>`; per-call options override the defaults;
33
+ * tags stay global (unprefixed) so bus invalidation still reaches
34
+ * partitioned entries. */
35
+ readonly partition: (name: string, defaults?: PartitionDefaults) => CachePartition;
36
+ /** Read the hit/miss counters + derived hit-rate (0–1). Drives the
37
+ * dashboard cache panel. */
38
+ readonly stats: () => Effect.Effect<{
39
+ hits: number;
40
+ misses: number;
41
+ hitRate: number;
42
+ }>;
43
+ }> & {
44
+ readonly make: Effect.Effect<{
15
45
  /** Read a typed value. `None` on miss/expiry. */
16
46
  readonly get: <A = unknown>(key: string) => Effect.Effect<Option.Option<A>, CacheError>;
17
47
  readonly set: <A>(key: string, value: A, options?: CacheSetOptions) => Effect.Effect<void, CacheError>;
@@ -39,22 +69,20 @@ declare const Cache_base: Effect.Service.Class<Cache, "@voltro/Cache", {
39
69
  hitRate: number;
40
70
  }>;
41
71
  }, never, CacheStore>;
42
- }>;
72
+ };
43
73
 
44
74
  export declare class CacheError extends CacheError_base {
45
75
  }
46
76
 
47
- declare const CacheError_base: Schema.TaggedErrorClass<CacheError, "CacheError", {
48
- readonly _tag: Schema.tag<"CacheError">;
49
- } & {
77
+ declare const CacheError_base: Schema.Class<CacheError, Schema.TaggedStruct<"CacheError", {
50
78
  /** Which op failed: 'get' | 'set' | 'setWithTags' | 'remove' | 'has' |
51
79
  * 'clear' | 'invalidateTag' | 'connect' | 'serialize' | 'deserialize'. */
52
- operation: typeof Schema.String;
80
+ readonly operation: Schema.String;
53
81
  /** The cache key (or tag) involved; '' for clear / connect. */
54
- key: typeof Schema.String;
82
+ readonly key: Schema.String;
55
83
  /** `String(originalError)` — round-trip-safe diagnostic form. */
56
- cause: typeof Schema.String;
57
- }>;
84
+ readonly cause: Schema.String;
85
+ }>, YieldableError>;
58
86
 
59
87
  export declare namespace CacheLayer {
60
88
  export {
@@ -103,7 +131,7 @@ export declare interface CacheSetWithTagsOptions extends CacheSetOptions {
103
131
  export declare class CacheStore extends CacheStore_base {
104
132
  }
105
133
 
106
- declare const CacheStore_base: Context.TagClass<CacheStore, "@voltro/CacheStore", CacheStoreShape>;
134
+ declare const CacheStore_base: Context.ServiceClass<CacheStore, "@voltro/CacheStore", CacheStoreShape>;
107
135
 
108
136
  export declare interface CacheStoreShape {
109
137
  /** Read a value. `None` on miss OR expiry (expired entries are lazily
@@ -160,21 +188,27 @@ export declare const cosineSimilarity: (a: ReadonlyArray<number>, b: ReadonlyArr
160
188
  export declare const depsForChange: (c: ChangeSignal) => ReadonlyArray<string>;
161
189
 
162
190
  export declare class InvalidationBus extends InvalidationBus_base {
191
+ /** The bus with its own scope: sinks live as long as the layer. */
192
+ static readonly layer: Layer.Layer<InvalidationBus, never, never>;
163
193
  }
164
194
 
165
- declare const InvalidationBus_base: Effect.Service.Class<InvalidationBus, "@voltro/InvalidationBus", {
166
- readonly scoped: Effect.Effect<{
195
+ declare const InvalidationBus_base: Context.ServiceClass<InvalidationBus, "@voltro/InvalidationBus", {
196
+ readonly publish: (table: string) => Effect.Effect<void>;
197
+ readonly changes: Stream.Stream<string, never, never>;
198
+ readonly addSink: (handle: (table: string) => Effect.Effect<unknown, unknown>) => Effect.Effect<void>;
199
+ }> & {
200
+ readonly make: Effect.Effect<{
167
201
  readonly publish: (table: string) => Effect.Effect<void>;
168
202
  readonly changes: Stream.Stream<string, never, never>;
169
203
  readonly addSink: (handle: (table: string) => Effect.Effect<unknown, unknown>) => Effect.Effect<void>;
170
204
  }, never, Scope.Scope>;
171
- }>;
205
+ };
172
206
 
173
207
  /**
174
208
  * `Layer<Cache>` whose backend is chosen from the environment. Provide
175
209
  * this in the app's layer stack so handlers can `yield* Cache`.
176
210
  */
177
- declare const layer: Layer.Layer<Cache, ConfigError.ConfigError | CacheError>;
211
+ declare const layer: Layer.Layer<Cache, Config.ConfigError | CacheError>;
178
212
 
179
213
  /** `Layer<CacheStore>` backed by an in-process `Ref`. */
180
214
  export declare const layerMemory: (options?: MemoryCacheOptions) => Layer.Layer<CacheStore>;
@@ -231,15 +265,17 @@ export declare const rowDep: (table: string, id: string) => string;
231
265
  * `CacheStore` in context — mirror of how `Cache` is built on `CacheStore`.
232
266
  *
233
267
  * ```ts
234
- * const layer = SemanticCache.Default.pipe(Layer.provide(CacheLayer.layer))
268
+ * const layer = SemanticCache.layer.pipe(Layer.provide(CacheLayer.layer))
235
269
  * ```
236
270
  */
237
271
  export declare class SemanticCache extends SemanticCache_base {
272
+ /** `SemanticCache` over whatever `CacheStore` is provided. */
273
+ static readonly layer: Layer.Layer<SemanticCache, never, CacheStore>;
238
274
  }
239
275
 
240
- declare const SemanticCache_base: Effect.Service.Class<SemanticCache, "@voltro/SemanticCache", {
241
- readonly effect: Effect.Effect<SemanticCacheShape, never, CacheStore>;
242
- }>;
276
+ declare const SemanticCache_base: Context.ServiceClass<SemanticCache, "@voltro/SemanticCache", SemanticCacheShape> & {
277
+ readonly make: Effect.Effect<SemanticCacheShape, never, CacheStore>;
278
+ };
243
279
 
244
280
  export declare interface SemanticCacheOptions {
245
281
  /** Default similarity threshold when a `lookup` omits one. Default 0.95. */
@@ -313,7 +349,7 @@ export declare interface SemanticPutOptions {
313
349
  * `Cache` and a `SemanticCache` end up over the same backend — see
314
350
  * `cli/src/cacheFacade.ts`).
315
351
  */
316
- declare const storeLayer: Layer.Layer<CacheStore, ConfigError.ConfigError | CacheError>;
352
+ declare const storeLayer: Layer.Layer<CacheStore, Config.ConfigError | CacheError>;
317
353
 
318
354
  /** The dependency tag for a whole table. Coarser than {@link rowDep}: it also
319
355
  * catches INSERTs (a new matching row the cached answer never read, so no