@ponraaj/dimple-sdk 0.0.0-alpha.1
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/config.d.ts +13 -0
- package/dist/dimple.d.ts +101 -0
- package/dist/errors.d.ts +63 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +8430 -0
- package/dist/indexer.d.ts +43 -0
- package/dist/internal/config/index.d.ts +4 -0
- package/dist/internal/config/loader.d.ts +9 -0
- package/dist/internal/config/schema.d.ts +176 -0
- package/dist/internal/config/service.d.ts +10 -0
- package/dist/internal/core/core.d.ts +95 -0
- package/dist/internal/core/index.d.ts +3 -0
- package/dist/internal/core/layer.d.ts +21 -0
- package/dist/internal/embedder/index.d.ts +4 -0
- package/dist/internal/embedder/openai.d.ts +8 -0
- package/dist/internal/embedder/provider.d.ts +29 -0
- package/dist/internal/embedder/registry.d.ts +10 -0
- package/dist/internal/embedder/transformers.d.ts +18 -0
- package/dist/internal/extractor/code-extractor.d.ts +15 -0
- package/dist/internal/extractor/content-handler.d.ts +17 -0
- package/dist/internal/extractor/index.d.ts +4 -0
- package/dist/internal/extractor/languages/index.d.ts +24 -0
- package/dist/internal/extractor/languages/javascript.d.ts +22 -0
- package/dist/internal/extractor/languages/typescript.d.ts +20 -0
- package/dist/internal/extractor/models/extraction.d.ts +53 -0
- package/dist/internal/llm/dream-classifier.d.ts +14 -0
- package/dist/internal/llm/index.d.ts +4 -0
- package/dist/internal/llm/llm.d.ts +54 -0
- package/dist/internal/llm/provider.d.ts +14 -0
- package/dist/internal/llm/service.d.ts +29 -0
- package/dist/internal/logger/format.d.ts +6 -0
- package/dist/internal/logger/index.d.ts +4 -0
- package/dist/internal/logger/ring.d.ts +33 -0
- package/dist/internal/logger/service.d.ts +50 -0
- package/dist/internal/logger/types.d.ts +39 -0
- package/dist/internal/parser/code-parser.d.ts +12 -0
- package/dist/internal/parser/index.d.ts +7 -0
- package/dist/internal/parser/language-store.d.ts +12 -0
- package/dist/internal/parser/models/parseRequest.d.ts +17 -0
- package/dist/internal/parser/models/treeHandle.d.ts +23 -0
- package/dist/internal/parser/tree-sitter-engine.d.ts +15 -0
- package/dist/internal/retriever/hybrid.d.ts +48 -0
- package/dist/internal/retriever/index.d.ts +3 -0
- package/dist/internal/retriever/rrf.d.ts +11 -0
- package/dist/internal/shared/errors/index.d.ts +2 -0
- package/dist/internal/shared/errors/parser.d.ts +21 -0
- package/dist/internal/shared/errors/wasm.d.ts +28 -0
- package/dist/internal/shared/types/index.d.ts +1 -0
- package/dist/internal/shared/types/language.d.ts +3 -0
- package/dist/internal/store/audit.d.ts +21 -0
- package/dist/internal/store/db-backend.d.ts +111 -0
- package/dist/internal/store/drizzle-schema.d.ts +1 -0
- package/dist/internal/store/error.d.ts +19 -0
- package/dist/internal/store/fnv1a32.d.ts +14 -0
- package/dist/internal/store/generated-migrations.d.ts +15 -0
- package/dist/internal/store/graph/candidates.d.ts +93 -0
- package/dist/internal/store/graph/concepts.d.ts +169 -0
- package/dist/internal/store/graph/dream.d.ts +171 -0
- package/dist/internal/store/graph/errors.d.ts +25 -0
- package/dist/internal/store/graph/index.d.ts +15 -0
- package/dist/internal/store/graph/observability.d.ts +37 -0
- package/dist/internal/store/graph/repair.d.ts +85 -0
- package/dist/internal/store/graph/retrieval-post-pass.d.ts +58 -0
- package/dist/internal/store/graph/traversal.d.ts +39 -0
- package/dist/internal/store/index.d.ts +38 -0
- package/dist/internal/store/libsql-backend.d.ts +18 -0
- package/dist/internal/store/models.d.ts +122 -0
- package/dist/internal/store/schema/graph.d.ts +970 -0
- package/dist/internal/store/schema/index.d.ts +7 -0
- package/dist/internal/store/schema/libsql.d.ts +2356 -0
- package/dist/internal/store/schema/metadata.d.ts +51 -0
- package/dist/internal/store/schema/topics.d.ts +1966 -0
- package/dist/internal/store/service.d.ts +162 -0
- package/dist/internal/store/store.d.ts +70 -0
- package/dist/internal/store/topics/errors.d.ts +39 -0
- package/dist/internal/store/topics/index.d.ts +24 -0
- package/dist/internal/store/topics/jobs.d.ts +149 -0
- package/dist/internal/store/topics/lifecycle.d.ts +126 -0
- package/dist/internal/store/topics/maintenance.d.ts +110 -0
- package/dist/internal/store/topics/observability.d.ts +102 -0
- package/dist/internal/store/topics/query.d.ts +43 -0
- package/dist/internal/store/topics/routing.d.ts +90 -0
- package/dist/internal/store/topics/topic-vectors.d.ts +24 -0
- package/dist/internal/store/topics/tree.d.ts +181 -0
- package/dist/internal/wasm/grammar-store.d.ts +14 -0
- package/dist/internal/wasm/index.d.ts +5 -0
- package/dist/internal/wasm/wasm-cache.d.ts +17 -0
- package/dist/internal/wasm/wasm-downloader.d.ts +10 -0
- package/dist/internal/wasm/wasm-registry.d.ts +16 -0
- package/dist/internal/workflow/config.d.ts +39 -0
- package/dist/internal/workflow/engine.d.ts +54 -0
- package/dist/internal/workflow/errors.d.ts +77 -0
- package/dist/internal/workflow/executor.d.ts +53 -0
- package/dist/internal/workflow/index.d.ts +13 -0
- package/dist/internal/workflow/persistence.d.ts +122 -0
- package/dist/internal/workflow/queue-store.d.ts +5 -0
- package/dist/internal/workflow/queue.d.ts +298 -0
- package/dist/internal/workflow/registry.d.ts +57 -0
- package/dist/internal/workflow/runtime.d.ts +161 -0
- package/dist/make.d.ts +27 -0
- package/package.json +45 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { Context, Effect } from "effect";
|
|
2
|
+
import type { MemoryUnit, MemoryEvent, WriteMemoryInput, SweepResult, Concept } from "./models.ts";
|
|
3
|
+
import type { StoreError, NotFound, DuplicateActiveKey } from "./error.ts";
|
|
4
|
+
import type { TopicError } from "./topics/errors.ts";
|
|
5
|
+
import type { MaintenanceOutcome, RebalanceOutcome } from "./topics/maintenance.ts";
|
|
6
|
+
import type { EmbeddingModelConfig } from "./internal/config/index.js";
|
|
7
|
+
import type { Topic, TopicChangeLog } from "./schema/topics.ts";
|
|
8
|
+
import type { ArtifactEdge, EdgeKind, EdgeSource } from "./schema/graph.ts";
|
|
9
|
+
import type { AugmentedMemory } from "./graph/retrieval-post-pass.ts";
|
|
10
|
+
import type { TopicMetrics, TopicChangeLogOptions, TopicHealth } from "./topics/observability.ts";
|
|
11
|
+
import type { SetActiveModelResult } from "./topics/lifecycle.ts";
|
|
12
|
+
import type { GraphNeighborsOptions } from "./db-backend.ts";
|
|
13
|
+
import type { EdgeNotFound, EdgeExists } from "./graph/errors.ts";
|
|
14
|
+
import type { MemoryMetadata } from "./schema/metadata.ts";
|
|
15
|
+
import type { GraphCandidatesOptions, GraphCandidatesResult } from "./graph/candidates.ts";
|
|
16
|
+
import type { GraphCoverage } from "./graph/observability.ts";
|
|
17
|
+
/** Shape of one topic-membership reference (topicMembers). */
|
|
18
|
+
export interface TopicMemberRef {
|
|
19
|
+
readonly memoryId: string;
|
|
20
|
+
}
|
|
21
|
+
/** Aggregate tree shape (topicStats). */
|
|
22
|
+
export interface TopicStats {
|
|
23
|
+
readonly depth: number;
|
|
24
|
+
readonly leafCount: number;
|
|
25
|
+
readonly internalCount: number;
|
|
26
|
+
readonly totalTopics: number;
|
|
27
|
+
}
|
|
28
|
+
/** Input for `Store.addEdge` — one memory↔memory edge (the only kinds
|
|
29
|
+
* the lean `artifact_edges` table holds). */
|
|
30
|
+
export interface AddEdgeInput {
|
|
31
|
+
readonly fromMemoryId: string;
|
|
32
|
+
readonly toMemoryId: string;
|
|
33
|
+
readonly edgeKind: EdgeKind;
|
|
34
|
+
readonly source: EdgeSource;
|
|
35
|
+
readonly confidence?: number;
|
|
36
|
+
readonly weight?: number;
|
|
37
|
+
/** Bypass pending — for the identity rule (same logicalKey) and confirmed API writes. */
|
|
38
|
+
readonly confirmed?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** Options for `Store.listEdges`. Expired edges are excluded by default
|
|
41
|
+
* (soft-delete — history stays queryable via `includeExpired`). */
|
|
42
|
+
export interface ListEdgesOptions {
|
|
43
|
+
/** Restrict to edges touching this memory (either endpoint). */
|
|
44
|
+
readonly memoryId?: string;
|
|
45
|
+
readonly edgeKind?: EdgeKind;
|
|
46
|
+
readonly status?: ArtifactEdge["status"];
|
|
47
|
+
readonly includeExpired?: boolean;
|
|
48
|
+
}
|
|
49
|
+
/** One reached node of an `explain` traversal (the other endpoint of a
|
|
50
|
+
* neighbor edge, deduplicated — first reach wins, so the shallowest depth). */
|
|
51
|
+
export interface ExplainNode {
|
|
52
|
+
readonly id: string;
|
|
53
|
+
readonly kind: string;
|
|
54
|
+
readonly edgeKind: string;
|
|
55
|
+
readonly depth: number;
|
|
56
|
+
}
|
|
57
|
+
export interface ExplainResult {
|
|
58
|
+
readonly seed: {
|
|
59
|
+
readonly kind: string;
|
|
60
|
+
readonly id: string;
|
|
61
|
+
};
|
|
62
|
+
readonly nodes: readonly ExplainNode[];
|
|
63
|
+
/** Pending conflicts surfaced even though they are not confirmed. */
|
|
64
|
+
readonly pendingConflicts: readonly string[];
|
|
65
|
+
}
|
|
66
|
+
export interface Interface {
|
|
67
|
+
readonly write: (input: WriteMemoryInput) => Effect.Effect<MemoryUnit, StoreError | DuplicateActiveKey>;
|
|
68
|
+
readonly get: (id: string) => Effect.Effect<MemoryUnit, NotFound | StoreError>;
|
|
69
|
+
readonly getByKey: (key: string, namespace: string) => Effect.Effect<MemoryUnit, NotFound | StoreError>;
|
|
70
|
+
readonly recency: (namespace: string, limit: number) => Effect.Effect<ReadonlyArray<AugmentedMemory>, StoreError>;
|
|
71
|
+
readonly searchFts5: (query: string, namespace: string, limit: number, opts?: {
|
|
72
|
+
readonly topicKeys?: ReadonlyArray<string>;
|
|
73
|
+
/** `false` suppresses the per-leg audit row (fused-row callers). */
|
|
74
|
+
readonly audit?: boolean;
|
|
75
|
+
}) => Effect.Effect<ReadonlyArray<AugmentedMemory>, StoreError>;
|
|
76
|
+
readonly searchVector: (query: ReadonlyArray<number>, namespace: string, limit: number, opts?: {
|
|
77
|
+
readonly topicKeys?: ReadonlyArray<string>;
|
|
78
|
+
/** Restrict to memories annotated with ANY of these concept ids. */
|
|
79
|
+
readonly conceptIds?: ReadonlyArray<string>;
|
|
80
|
+
/** `false` suppresses the per-leg audit row (fused-row callers). */
|
|
81
|
+
readonly audit?: boolean;
|
|
82
|
+
}) => Effect.Effect<ReadonlyArray<AugmentedMemory>, StoreError>;
|
|
83
|
+
/** One fused retrieval-audit row (the hybrid path's audit contract). */
|
|
84
|
+
readonly logAudit: (input: {
|
|
85
|
+
readonly query: string;
|
|
86
|
+
readonly namespace: string;
|
|
87
|
+
readonly mode: string;
|
|
88
|
+
readonly resultCount: number;
|
|
89
|
+
readonly startTime: number;
|
|
90
|
+
readonly queryProfile?: string | null;
|
|
91
|
+
readonly sources?: string | null;
|
|
92
|
+
readonly hashSeed?: string;
|
|
93
|
+
}) => Effect.Effect<void, StoreError>;
|
|
94
|
+
readonly supersede: (key: string, namespace: string) => Effect.Effect<void, NotFound | StoreError>;
|
|
95
|
+
readonly forget: (id: string) => Effect.Effect<void, NotFound | StoreError>;
|
|
96
|
+
readonly sweep: (namespace: string) => Effect.Effect<SweepResult, StoreError>;
|
|
97
|
+
readonly events: (memoryId: string) => Effect.Effect<readonly MemoryEvent[], StoreError>;
|
|
98
|
+
readonly updateEmbedding: (id: string, embedding: ReadonlyArray<number>, model: string) => Effect.Effect<void, NotFound | StoreError>;
|
|
99
|
+
readonly findStale: (model: string) => Effect.Effect<readonly string[], StoreError>;
|
|
100
|
+
readonly createConcept: (name: string, embedding: ReadonlyArray<number>) => Effect.Effect<Concept, StoreError>;
|
|
101
|
+
readonly getConcept: (id: string) => Effect.Effect<Concept, NotFound | StoreError>;
|
|
102
|
+
readonly listConcepts: () => Effect.Effect<readonly Concept[], StoreError>;
|
|
103
|
+
readonly annotateMemory: (memoryId: string, conceptId: string, confidence?: number) => Effect.Effect<void, NotFound | StoreError>;
|
|
104
|
+
readonly getMemoryAnnotations: (memoryId: string) => Effect.Effect<readonly string[], StoreError>;
|
|
105
|
+
readonly queryByMetadata: (filter: Record<string, unknown>) => Effect.Effect<readonly MemoryUnit[], StoreError>;
|
|
106
|
+
readonly getMemoryMetadata: (id: string) => Effect.Effect<MemoryMetadata | undefined, NotFound | StoreError>;
|
|
107
|
+
readonly setMemoryMetadata: (id: string, metadata: MemoryMetadata) => Effect.Effect<void, NotFound | StoreError>;
|
|
108
|
+
readonly ensureTopicTree: (modelKey: string) => Effect.Effect<{
|
|
109
|
+
rootKey: string;
|
|
110
|
+
unassignedKey: string;
|
|
111
|
+
}, TopicError | StoreError>;
|
|
112
|
+
readonly resolveTopics: (queryVector: ReadonlyArray<number>, opts?: {
|
|
113
|
+
readonly beamWidth?: number;
|
|
114
|
+
}) => Effect.Effect<readonly string[], TopicError | StoreError>;
|
|
115
|
+
readonly topicMembers: (topicKey: string) => Effect.Effect<readonly TopicMemberRef[], StoreError>;
|
|
116
|
+
readonly listTopics: (modelKey: string) => Effect.Effect<readonly Topic[], StoreError>;
|
|
117
|
+
readonly topicStats: (modelKey: string) => Effect.Effect<TopicStats, StoreError>;
|
|
118
|
+
readonly deleteTree: (modelKey: string) => Effect.Effect<void, TopicError | StoreError>;
|
|
119
|
+
readonly processSplits: (modelKey: string) => Effect.Effect<number, TopicError | StoreError>;
|
|
120
|
+
readonly mergeOrBorrow: (modelKey: string, topicKey: string) => Effect.Effect<MaintenanceOutcome, TopicError | StoreError>;
|
|
121
|
+
readonly rebalanceSiblings: (modelKey: string, topicKey: string) => Effect.Effect<RebalanceOutcome, TopicError | StoreError>;
|
|
122
|
+
readonly setActiveModel: (model: EmbeddingModelConfig) => Effect.Effect<SetActiveModelResult, TopicError | StoreError>;
|
|
123
|
+
readonly isActive: (modelKey: string) => Effect.Effect<boolean, TopicError | StoreError>;
|
|
124
|
+
readonly topicMetrics: (modelKey: string) => Effect.Effect<TopicMetrics, TopicError | StoreError>;
|
|
125
|
+
readonly topicChangeLog: (modelKey: string, opts?: TopicChangeLogOptions) => Effect.Effect<ReadonlyArray<TopicChangeLog>, TopicError | StoreError>;
|
|
126
|
+
readonly topicHealth: (modelKey: string) => Effect.Effect<TopicHealth, TopicError | StoreError>;
|
|
127
|
+
/** Insert one memory↔memory edge. A `(from, to, kind)` duplicate fails
|
|
128
|
+
* with `EdgeExists` (the composite PK). `confirmed` bypasses pending —
|
|
129
|
+
* the identity rule and explicit API writes. */
|
|
130
|
+
readonly addEdge: (input: AddEdgeInput) => Effect.Effect<ArtifactEdge, EdgeExists | StoreError | NotFound>;
|
|
131
|
+
/** Soft-delete (never a hard delete of history): sets `expired_at=now`.
|
|
132
|
+
* Expired edges are excluded from `listEdges` and traversal by default. */
|
|
133
|
+
readonly expireEdge: (id: string) => Effect.Effect<void, EdgeNotFound | StoreError>;
|
|
134
|
+
/** Promote a pending edge to confirmed. For `memory_supersedes` the OLD
|
|
135
|
+
* memory (the `from` endpoint) flips `active → superseded` in the SAME
|
|
136
|
+
* transaction (pending candidates never mutate state). */
|
|
137
|
+
readonly confirmEdge: (id: string) => Effect.Effect<void, EdgeNotFound | StoreError>;
|
|
138
|
+
readonly rejectEdge: (id: string) => Effect.Effect<void, EdgeNotFound | StoreError>;
|
|
139
|
+
readonly listEdges: (opts?: ListEdgesOptions) => Effect.Effect<readonly ArtifactEdge[], StoreError>;
|
|
140
|
+
/** The "what is near this exact artifact" API — per-hop traversal over the
|
|
141
|
+
* `graph_edges` view with caps + deterministic order, plus the seed's
|
|
142
|
+
* pending conflicts surfaced. */
|
|
143
|
+
readonly explain: (node: {
|
|
144
|
+
readonly kind: "memory" | "topic" | "concept";
|
|
145
|
+
readonly id: string;
|
|
146
|
+
}, opts?: GraphNeighborsOptions) => Effect.Effect<ExplainResult, StoreError>;
|
|
147
|
+
/** Read-only review surface for the write-path candidate rules: the
|
|
148
|
+
* newest pending `artifact_edges` rows (created_at desc, bounded —
|
|
149
|
+
* default 50) plus the isolated-memory survey (count + oldest examples:
|
|
150
|
+
* memories with no live incident edge on either endpoint). */
|
|
151
|
+
readonly graphCandidates: (opts?: GraphCandidatesOptions) => Effect.Effect<GraphCandidatesResult, StoreError>;
|
|
152
|
+
/** The artifact graph's reach over one model's memories: total active
|
|
153
|
+
* memories embedded by the model, how many have at least one live
|
|
154
|
+
* incident edge (confirmed or pending, not expired), the coverage
|
|
155
|
+
* percentage, the pending candidate backlog, concept + annotated-memory
|
|
156
|
+
* counts, and the isolated-memory count. */
|
|
157
|
+
readonly graphCoverage: (modelKey: string) => Effect.Effect<GraphCoverage, StoreError>;
|
|
158
|
+
}
|
|
159
|
+
declare const Service_base: Context.ServiceClass<Service, "@dimple/store/Store", Interface>;
|
|
160
|
+
export declare class Service extends Service_base {
|
|
161
|
+
}
|
|
162
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Config, Effect, Layer } from "effect";
|
|
2
|
+
import type { Scope } from "effect/Scope";
|
|
3
|
+
import type { RetrievalAuditRow } from "./models.ts";
|
|
4
|
+
import { Service as DbBackend } from "./db-backend.ts";
|
|
5
|
+
import { Service } from "./service.ts";
|
|
6
|
+
import { StoreError } from "./error.ts";
|
|
7
|
+
import { Service as ConfigService } from "./internal/config/index.js";
|
|
8
|
+
import { type LogConfig, type Logging } from "./internal/logger/index.js";
|
|
9
|
+
import type { EmbeddingModelConfig } from "./internal/config/index.js";
|
|
10
|
+
import type { TopicConfig as TopicConfigType } from "./schema/topics.ts";
|
|
11
|
+
import { GraphConfig } from "./schema/graph.ts";
|
|
12
|
+
/**
|
|
13
|
+
* Topic-tree layer options. `enabled` gates the write hook only — the
|
|
14
|
+
* read-side methods (resolveTopics/topicMembers/listTopics/topicStats) are
|
|
15
|
+
* always available; the write hook routes every embedded memory into the tree
|
|
16
|
+
* and enqueues splits on overflow.
|
|
17
|
+
*
|
|
18
|
+
* `enqueueSplit` is the production-path injection seam:
|
|
19
|
+
* when set, the write hook delegates overflow to it instead of running splits
|
|
20
|
+
* inline. It receives the overflowed leaf key and the layer's model key; the
|
|
21
|
+
* app root wires it to `JobRuntime.enqueue(TopicSplit, ...)` — `@dimple/store`
|
|
22
|
+
* never imports `@dimple/workflow` (the seam is a plain effect callback). The
|
|
23
|
+
* hook may fail with any error; the store surfaces it as `StoreError`
|
|
24
|
+
* (post-commit reporting — the memory write + topic routing already
|
|
25
|
+
* committed by the time overflow fires). When unset, overflow keeps the
|
|
26
|
+
* inline `processSplits` fallback (sync convenience; production
|
|
27
|
+
* wiring always provides the seam).
|
|
28
|
+
*/
|
|
29
|
+
export interface StoreTopicsOptions {
|
|
30
|
+
readonly enabled?: boolean;
|
|
31
|
+
readonly config?: TopicConfigType;
|
|
32
|
+
readonly enqueueSplit?: (topicKey: string, modelKey: string) => Effect.Effect<void, unknown>;
|
|
33
|
+
/** Production-path seam for underflow maintenance (mirrors `enqueueSplit`):
|
|
34
|
+
* fires with the underfilled leaf key after a forget drops it below
|
|
35
|
+
* `minLeafItems`. The app root wires it to
|
|
36
|
+
* `JobRuntime.enqueue(TopicMerge, ...)`. When unset, the forget path runs
|
|
37
|
+
* the inline drain instead. */
|
|
38
|
+
readonly enqueueMerge?: (topicKey: string, modelKey: string) => Effect.Effect<void, unknown>;
|
|
39
|
+
}
|
|
40
|
+
export declare const layer: (url: string, options?: {
|
|
41
|
+
migrationFolder?: string;
|
|
42
|
+
/** Close the underlying client when the layer's scope closes (the
|
|
43
|
+
* app-root/SDK path — dispose releases the fd). Bare-store
|
|
44
|
+
* compositions leave it open (services may outlive the scope). */
|
|
45
|
+
releaseClient?: boolean;
|
|
46
|
+
embeddingModelConfig?: EmbeddingModelConfig;
|
|
47
|
+
topics?: StoreTopicsOptions;
|
|
48
|
+
graphConfig?: GraphConfig;
|
|
49
|
+
/** Retrieval-audit seam: when present, `retrieval_log` rows are
|
|
50
|
+
* enqueued as `audit.write` jobs instead of fire-and-forget inserts
|
|
51
|
+
* (the `@dimple/core` default; the query path never blocks). */
|
|
52
|
+
enqueueAudit?: (row: RetrievalAuditRow) => Effect.Effect<void, unknown>;
|
|
53
|
+
/** Structured-logging config; when present the Logging service is
|
|
54
|
+
* installed and Effect's default logger is replaced (all `Effect.log*`
|
|
55
|
+
* output flows through `@dimple/logger` per this config). */
|
|
56
|
+
logging?: LogConfig;
|
|
57
|
+
/** Default TTL for writes that omit `ttlSecs` (the config's
|
|
58
|
+
* `defaultTtlSecs`; default 604800). */
|
|
59
|
+
defaultTtlSecs?: number;
|
|
60
|
+
}) => Layer.Layer<Logging | DbBackend | Service, StoreError, Scope>;
|
|
61
|
+
export declare const layerConfig: (config: Config.Wrap<{
|
|
62
|
+
url: string;
|
|
63
|
+
}>, options?: {
|
|
64
|
+
migrationFolder?: string;
|
|
65
|
+
embeddingModelConfig?: EmbeddingModelConfig;
|
|
66
|
+
}) => Layer.Layer<Logging | DbBackend | Service, Config.ConfigError | StoreError, Scope>;
|
|
67
|
+
export declare const layerFromConfig: (options?: {
|
|
68
|
+
migrationFolder?: string;
|
|
69
|
+
}) => Layer.Layer<Service | DbBackend | Logging, StoreError, ConfigService | Scope>;
|
|
70
|
+
export declare const loggingFromConfig: Layer.Layer<Logging, never, ConfigService | Scope>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
declare const TopicNotFound_base: Schema.Class<TopicNotFound, Schema.TaggedStruct<"topics.TopicNotFound", {
|
|
3
|
+
readonly topicKey: Schema.String;
|
|
4
|
+
}>, import("effect/Cause").YieldableError>;
|
|
5
|
+
/**
|
|
6
|
+
* Topic-tree error types. Each distinct failure mode gets its
|
|
7
|
+
* own `Schema.TaggedErrorClass` so callers can `catchTag` precisely.
|
|
8
|
+
* `TopicError` is the tagged union; individual classes are exported for
|
|
9
|
+
* pattern matching.
|
|
10
|
+
*/
|
|
11
|
+
/** A topic that routing/structural operations needed does not exist. */
|
|
12
|
+
export declare class TopicNotFound extends TopicNotFound_base {
|
|
13
|
+
}
|
|
14
|
+
declare const InvariantViolation_base: Schema.Class<InvariantViolation, Schema.TaggedStruct<"topics.InvariantViolation", {
|
|
15
|
+
readonly topicKey: Schema.String;
|
|
16
|
+
readonly violations: Schema.$Array<Schema.String>;
|
|
17
|
+
}>, import("effect/Cause").YieldableError>;
|
|
18
|
+
/** A `TopicConfig` violates the structural invariants (`validateConfig`). */
|
|
19
|
+
export declare class InvariantViolation extends InvariantViolation_base {
|
|
20
|
+
}
|
|
21
|
+
declare const ModelMismatch_base: Schema.Class<ModelMismatch, Schema.TaggedStruct<"topics.ModelMismatch", {
|
|
22
|
+
readonly expected: Schema.String;
|
|
23
|
+
readonly actual: Schema.String;
|
|
24
|
+
}>, import("effect/Cause").YieldableError>;
|
|
25
|
+
/** Two embeddings/models that must agree do not (dimension or model mismatch). */
|
|
26
|
+
export declare class ModelMismatch extends ModelMismatch_base {
|
|
27
|
+
}
|
|
28
|
+
declare const RoutingFailure_base: Schema.Class<RoutingFailure, Schema.TaggedStruct<"topics.RoutingFailure", {
|
|
29
|
+
readonly cause: Schema.optional<Schema.Unknown>;
|
|
30
|
+
}>, import("effect/Cause").YieldableError>;
|
|
31
|
+
/**
|
|
32
|
+
* Unexpected failure inside routing/seed — wraps the underlying cause
|
|
33
|
+
* (backend `StoreError`, driver exception, ...).
|
|
34
|
+
*/
|
|
35
|
+
export declare class RoutingFailure extends RoutingFailure_base {
|
|
36
|
+
}
|
|
37
|
+
/** Tagged union of all topic-tree errors. */
|
|
38
|
+
export type TopicError = TopicNotFound | InvariantViolation | ModelMismatch | RoutingFailure;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Topic-tree barrel. Re-exports the pure algorithms, seeding/routing, the
|
|
3
|
+
* split job, query routing, maintenance (merge/rebalance), the multi-model
|
|
4
|
+
* lifecycle + `memory.embed` backfill handler, observability, canonical
|
|
5
|
+
* error types, and the `topics` schema tables + `TopicConfig`.
|
|
6
|
+
*
|
|
7
|
+
* The canonical error classes live in `topics/errors.ts`; the job handlers
|
|
8
|
+
* (`topicSplitHandler` / `topicMergeHandler` / `topicRebalanceHandler` /
|
|
9
|
+
* `memoryEmbedHandler`) take app-root-injected deps (see their module docs).
|
|
10
|
+
*/
|
|
11
|
+
export * from "./tree.ts";
|
|
12
|
+
export * from "./routing.ts";
|
|
13
|
+
export * from "./query.ts";
|
|
14
|
+
export * from "./lifecycle.ts";
|
|
15
|
+
export { memoryEmbedHandler } from "./lifecycle.ts";
|
|
16
|
+
export type { MemoryEmbedHandler, MemoryEmbedHandlerDeps } from "./lifecycle.ts";
|
|
17
|
+
export * from "./errors.ts";
|
|
18
|
+
export { splitTopic, topicSplitHandler, shouldSplit } from "./jobs.ts";
|
|
19
|
+
export type { SplitOutcome, TopicSplitHandler, TopicSplitHandlerDeps } from "./jobs.ts";
|
|
20
|
+
export { mergeOrBorrow, rebalanceSiblings, topicMergeHandler, topicRebalanceHandler, } from "./maintenance.ts";
|
|
21
|
+
export type { MaintenanceOutcome, RebalanceOutcome, TopicMaintenanceHandler, TopicMaintenanceHandlerDeps, } from "./maintenance.ts";
|
|
22
|
+
export { topicMetrics, topicChangeLog, topicHealth } from "./observability.ts";
|
|
23
|
+
export type { TopicMetrics, TopicChangeLogOptions, TopicHealth } from "./observability.ts";
|
|
24
|
+
export * from "../schema/topics.ts";
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Topic-tree split job — the leaf-split store operation and its
|
|
3
|
+
* `@dimple/workflow` handler.
|
|
4
|
+
*
|
|
5
|
+
* `splitTopic` is the pure store operation: load a leaf's members + vectors,
|
|
6
|
+
* run the deterministic split plan (`tree.ts`), and materialize an accepted
|
|
7
|
+
* split in ONE transaction (child topics, per-model topic vectors, membership
|
|
8
|
+
* re-parenting, relations, growth state, change log). A rejected plan defers
|
|
9
|
+
* the split (`split_deferred` + `splitRejectedCount`); the hard-limit backstop force-
|
|
10
|
+
* splits a leaf once it exceeds `splitDeferredHardLimit`.
|
|
11
|
+
*
|
|
12
|
+
* `topicSplitHandler` wraps the operation for the frozen `topic.split` job
|
|
13
|
+
* definition (`packages/workflow/src/queue.ts`): payload `{ topicId, modelKey }`,
|
|
14
|
+
* success `Schema.Void`, error `Schema.String` (the executor maps
|
|
15
|
+
* `JobFailure.message` into the queue error channel — never wrap in
|
|
16
|
+
* `JobFailed` here).
|
|
17
|
+
*
|
|
18
|
+
* ## Errors (canonical union, topics/errors.ts)
|
|
19
|
+
*
|
|
20
|
+
* - `TopicNotFound` — the topic is missing, not a leaf, or retired (inactive).
|
|
21
|
+
* - `ModelMismatch` — the topic belongs to another model's tree.
|
|
22
|
+
* - `InvariantViolation` — the plan produced an invalid child shape; the
|
|
23
|
+
* transaction rolls back (nothing commits).
|
|
24
|
+
* - `StoreError` — backend/persistence failures.
|
|
25
|
+
*
|
|
26
|
+
* A rejected split is a **logged outcome, not an error**: `splitTopic` returns
|
|
27
|
+
* `{ accepted: false, reason }` and the handler completes successfully.
|
|
28
|
+
*
|
|
29
|
+
* ## Determinism
|
|
30
|
+
*
|
|
31
|
+
* Child keys are content-addressable: FNV-1a 32-bit hex over `{ parent,
|
|
32
|
+
* members }` where `members` is the child's vector fingerprint in
|
|
33
|
+
* content-canonical order (`childBaseKey` below) — vectors, never memory
|
|
34
|
+
* ids, so identical embeddings yield identical keys across runs and DBs
|
|
35
|
+
* (the `-2` suffix disambiguates collisions). No randomness; ties follow
|
|
36
|
+
* `tree.ts` (smaller index). Audit timestamps come from the injectable
|
|
37
|
+
* Effect Clock (captured once per transaction, outside the closure) —
|
|
38
|
+
* observability data only, they never influence the split decision.
|
|
39
|
+
*
|
|
40
|
+
* ## Backend dependency note
|
|
41
|
+
*
|
|
42
|
+
* The split transaction writes topic-vector rows through the Drizzle `tx`
|
|
43
|
+
* handle (the backend's `upsertTopicVector` uses the standalone client and
|
|
44
|
+
* cannot join the transaction), so the per-model topic-vector table name and
|
|
45
|
+
* the `vector32`-family convert map are mirrored here from `libsql-backend.ts`
|
|
46
|
+
* (the canonical source — keep both in sync).
|
|
47
|
+
*/
|
|
48
|
+
import { Effect } from "effect";
|
|
49
|
+
import { JobFailure, type Handler, type JobContext } from "./internal/workflow/index.js";
|
|
50
|
+
import type { EmbeddingModelConfig } from "./internal/config/index.js";
|
|
51
|
+
import { Service as DbBackend } from "../db-backend.ts";
|
|
52
|
+
import type { Interface as DbBackendInterface } from "../db-backend.ts";
|
|
53
|
+
import { StoreError } from "../error.ts";
|
|
54
|
+
import type { TopicConfig } from "../schema/topics.ts";
|
|
55
|
+
import type { TopicError } from "./errors.ts";
|
|
56
|
+
/**
|
|
57
|
+
* Overflow predicate for the insert path (used by routing): a leaf needs a
|
|
58
|
+
* split job once its member count exceeds `maxLeafItems`.
|
|
59
|
+
*/
|
|
60
|
+
export declare const shouldSplit: (leafMemberCount: number, config: TopicConfig) => boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Result of {@link splitTopic}: an accepted split returns the two child keys
|
|
63
|
+
* and their member counts (the counts let callers detect an uneven split —
|
|
64
|
+
* e.g. the `onUnevenSplit` seam in {@link topicSplitHandler}).
|
|
65
|
+
*/
|
|
66
|
+
export type SplitOutcome = {
|
|
67
|
+
readonly accepted: true;
|
|
68
|
+
readonly children: readonly [string, string];
|
|
69
|
+
readonly childCounts: readonly [number, number];
|
|
70
|
+
} | {
|
|
71
|
+
readonly accepted: false;
|
|
72
|
+
readonly reason: "unbalanced" | "no-improvement";
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Deterministic 2-way split of a leaf topic.
|
|
76
|
+
*
|
|
77
|
+
* Loads the leaf + its members (sorted by `memory_id`) and their vectors,
|
|
78
|
+
* runs {@link splitPlan}, and materializes the split in one transaction:
|
|
79
|
+
* children + topic vectors + membership re-parenting + relations + growth
|
|
80
|
+
* state + change log. Rejections defer (status `split_deferred`,
|
|
81
|
+
* `splitRejectedCount` bumped, one change-log row on the 0→1 flip); the
|
|
82
|
+
* backstop force-splits past `splitDeferredHardLimit` (logged `split_forced`).
|
|
83
|
+
*
|
|
84
|
+
* Idempotency: a leaf at or below `maxLeafItems` with no pending deferral
|
|
85
|
+
* returns `{ accepted: false, reason: "no-improvement" }` without writing
|
|
86
|
+
* anything (the early no-op that keeps concurrent overflow checks harmless);
|
|
87
|
+
* an already-split parent is `TopicNotFound` (the workflow handler converts
|
|
88
|
+
* that into a stale-job success).
|
|
89
|
+
*/
|
|
90
|
+
export declare const splitTopic: (topicKey: string, model: EmbeddingModelConfig, config: TopicConfig) => Effect.Effect<SplitOutcome, TopicError | StoreError, DbBackend>;
|
|
91
|
+
/** Dependencies for {@link topicSplitHandler}. */
|
|
92
|
+
export interface TopicSplitHandlerDeps {
|
|
93
|
+
/** Resolves a model key to its config (the model registry). */
|
|
94
|
+
readonly getModelConfig: (modelKey: string) => EmbeddingModelConfig | undefined;
|
|
95
|
+
/** Tree-shape config for the split decision. */
|
|
96
|
+
readonly config: TopicConfig;
|
|
97
|
+
/**
|
|
98
|
+
* Production-path seam for sibling rebalance (mirrors `enqueueSplit`):
|
|
99
|
+
* fired after an ACCEPTED split whose two children are uneven
|
|
100
|
+
* (`max(counts) > 2 × min(counts)` — the rebalanceSiblings criterion). The
|
|
101
|
+
* app root wires this to `JobRuntime.enqueue(TopicRebalance, …)`; the
|
|
102
|
+
* rebalance job resolves the parent internally, so the child key is the
|
|
103
|
+
* right trigger. The store cannot fire this itself: the split runs
|
|
104
|
+
* asynchronously in the worker, so the post-split imbalance is only
|
|
105
|
+
* observable here.
|
|
106
|
+
*/
|
|
107
|
+
readonly onUnevenSplit?: (childKey: string, modelKey: string) => Effect.Effect<void, unknown>;
|
|
108
|
+
/**
|
|
109
|
+
* Self-healing seam: fired for every child of an ACCEPTED split that is
|
|
110
|
+
* STILL over `maxLeafItems`. The app root wires this to another
|
|
111
|
+
* `topic.split` job, so a worker that lagged behind a write burst splits
|
|
112
|
+
* the overgrown leaf AND keeps re-enqueuing its over-budget children —
|
|
113
|
+
* the maintenance chain converges every leaf to the page budget (the
|
|
114
|
+
* "keep compacting on current state" rule — the write path only enqueues
|
|
115
|
+
* splits for leaves that CURRENT writes overflow, so children left over
|
|
116
|
+
* budget by a lagged split would otherwise stall forever).
|
|
117
|
+
*/
|
|
118
|
+
readonly onChildOverflow?: (childKey: string, modelKey: string) => Effect.Effect<void, unknown>;
|
|
119
|
+
/**
|
|
120
|
+
* Store backend captured at registration time. Required for the standard
|
|
121
|
+
* workflow worker path: worker fibers only see services declared in the
|
|
122
|
+
* worker layer's requirements, and the JobRegistry handler type erases
|
|
123
|
+
* requirements — so the backend must be captured in the closure (the
|
|
124
|
+
* registration site is a `Layer.effect` where `yield* DbBackend` works).
|
|
125
|
+
* When omitted, the handler effect requires `DbBackend` from its own
|
|
126
|
+
* environment (direct/in-process use).
|
|
127
|
+
*/
|
|
128
|
+
readonly backend?: DbBackendInterface;
|
|
129
|
+
}
|
|
130
|
+
/** The `topic.split` handler shape — `unknown` success like `JobRegistry.Handler`. */
|
|
131
|
+
export type TopicSplitHandler = (payload: unknown, ctx: JobContext) => Effect.Effect<unknown, JobFailure, DbBackend>;
|
|
132
|
+
/**
|
|
133
|
+
* Factory for the `topic.split` job handler.
|
|
134
|
+
*
|
|
135
|
+
* Resolves the model via `deps.getModelConfig` (missing model → `JobFailure`,
|
|
136
|
+
* which the executor maps to the queue's `Schema.String` error channel),
|
|
137
|
+
* runs {@link splitTopic}, and returns `undefined` — the definition's success
|
|
138
|
+
* schema is `Schema.Void` (the outcome lives in the DB: topics/memberships/
|
|
139
|
+
* change log, not the job result). A rejected split is a success (the deferral
|
|
140
|
+
* is the recorded outcome,).
|
|
141
|
+
*
|
|
142
|
+
* Pass `deps.backend` (captured at registration) to get a plain
|
|
143
|
+
* `JobRegistry.Handler` runnable inside the standard worker; without it the
|
|
144
|
+
* handler requires `DbBackend` from its own environment.
|
|
145
|
+
*/
|
|
146
|
+
export declare function topicSplitHandler(deps: TopicSplitHandlerDeps & {
|
|
147
|
+
readonly backend: DbBackendInterface;
|
|
148
|
+
}): Handler;
|
|
149
|
+
export declare function topicSplitHandler(deps: TopicSplitHandlerDeps): TopicSplitHandler;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-model lifecycle: `setActiveModel` + `isActive`, and the
|
|
3
|
+
* `memory.embed` backfill job handler (`memoryEmbedHandler`) that re-embeds
|
|
4
|
+
* one memory with a target model — the per-memory production path for the
|
|
5
|
+
* switch (see the switch description below).
|
|
6
|
+
*
|
|
7
|
+
* ## The invariant
|
|
8
|
+
*
|
|
9
|
+
* Routing NEVER mixes models: `routeInsert` / `resolveTopics` take an
|
|
10
|
+
* explicit model and read only that model's topic rows (`model_key` scoped)
|
|
11
|
+
* and that model's per-model vector tables (`vec_<dims>_<model>` /
|
|
12
|
+
* `topic_vec_<dims>_<model>`). Since the topic tables carry a
|
|
13
|
+
* `(topic_key, model_key)` composite PK — every model's tree has its own
|
|
14
|
+
* reserved rows, so ACTIVE and RETIRED trees coexist. "The active tree" is
|
|
15
|
+
* simply the tree whose `topics.status = 'active'` rows belong to the
|
|
16
|
+
* current model; `setActiveModel` flips statuses, nothing else.
|
|
17
|
+
*
|
|
18
|
+
* ## The switch
|
|
19
|
+
*
|
|
20
|
+
* 1. `ensureTopicTree(model, config)` — seed the new tree if absent
|
|
21
|
+
* (idempotent, model-scoped).
|
|
22
|
+
* 2. `listMemoryIds(model)` — every memory with a vector for the NEW model,
|
|
23
|
+
* sorted by `memory_id` (deterministic order — the task's "never iterate
|
|
24
|
+
* unordered sets").
|
|
25
|
+
* 3. For each memory (sorted): already a member of the new model's tree →
|
|
26
|
+
* `alreadyInTree`; otherwise fetch its vector and `routeInsert` →
|
|
27
|
+
* `routed`. Each `routeInsert` commits in its own transaction: the batch
|
|
28
|
+
* is per-memory-committed by design. The durable production path is the
|
|
29
|
+
* `memory.embed` job (this module's `memoryEmbedHandler`) — the app root
|
|
30
|
+
* enqueues one job per stale memory (via `findStale`) and the worker
|
|
31
|
+
* re-embeds + routes each. A future batch re-route JOB with resume could
|
|
32
|
+
* amortize the per-memory commits; the per-memory job is correct and
|
|
33
|
+
* resumable today.
|
|
34
|
+
* 4. Deactivate every OTHER model's trees: `status = 'inactive'` where
|
|
35
|
+
* `model_key != model.id` and not already inactive. The distinct affected
|
|
36
|
+
* model keys are returned as `deactivated`. Growth state is NOT touched:
|
|
37
|
+
* it is per-topic audit data (`lastSplitAt`, rejection counters, …) and
|
|
38
|
+
* remains valid if the model is ever re-activated.
|
|
39
|
+
* 5. One change-log entry on the new tree's root (`__root__`),
|
|
40
|
+
* operation `"activate"`, reason `{ model, deactivated }`. The entry is
|
|
41
|
+
* written only when the activation
|
|
42
|
+
* changed observable state (deactivated other trees or routed memories) —
|
|
43
|
+
* a pure re-activation of the already-active model writes nothing
|
|
44
|
+
* (idempotent, deterministic). Note: `topic_change_log` has no
|
|
45
|
+
* `model_key` column, and the reserved root key is the same string in
|
|
46
|
+
* every model's tree — the entry is unambiguous in practice because it is
|
|
47
|
+
* the ONLY `activate` row for the root written by this switch, but
|
|
48
|
+
* key-based log queries (topicChangeLog) can surface it for other models.
|
|
49
|
+
* Documented ambiguity.
|
|
50
|
+
*
|
|
51
|
+
* ## Determinism
|
|
52
|
+
*
|
|
53
|
+
* All iteration derives from persisted state: `listMemoryIds` is ordered by
|
|
54
|
+
* `memory_id`, topic rows by `topic_key`, and the deactivation query filters
|
|
55
|
+
* on status. The audit timestamp comes from the injectable Effect Clock
|
|
56
|
+
* (observability only — never read by routing).
|
|
57
|
+
*/
|
|
58
|
+
import { Effect } from "effect";
|
|
59
|
+
import type { EmbeddingModelConfig } from "./internal/config/index.js";
|
|
60
|
+
import { Service as DbBackend } from "../db-backend.ts";
|
|
61
|
+
import type { TopicConfig } from "../schema/topics.ts";
|
|
62
|
+
import type { TopicError } from "./errors.ts";
|
|
63
|
+
import { NotFound, StoreError } from "../error.ts";
|
|
64
|
+
import { JobFailure, type Handler, type JobContext } from "./internal/workflow/index.js";
|
|
65
|
+
import type { Interface as DbBackendInterface } from "../db-backend.ts";
|
|
66
|
+
/** Result of {@link setActiveModel}. */
|
|
67
|
+
export interface SetActiveModelResult {
|
|
68
|
+
/** Memories routed into the new model's tree by this call. */
|
|
69
|
+
readonly routed: number;
|
|
70
|
+
/** Memories already members of the new model's tree (idempotent no-ops). */
|
|
71
|
+
readonly alreadyInTree: number;
|
|
72
|
+
/** Distinct model keys whose trees this call flipped to `inactive`. */
|
|
73
|
+
readonly deactivated: readonly string[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* True when the model's tree has at least one active topic row — i.e. the
|
|
77
|
+
* model is the current default for routing. A model whose tree was never
|
|
78
|
+
* seeded, or whose every row was deactivated, is not active.
|
|
79
|
+
*/
|
|
80
|
+
export declare const isActive: (modelKey: string) => Effect.Effect<boolean, TopicError | StoreError, DbBackend>;
|
|
81
|
+
/**
|
|
82
|
+
* Switch the ACTIVE tree to `model`: seed the new
|
|
83
|
+
* tree, re-route every memory that has a vector for the new model, retire
|
|
84
|
+
* every other model's trees, and record the activation in the change log.
|
|
85
|
+
*
|
|
86
|
+
* Deterministic order everywhere: `listMemoryIds` returns ids sorted by
|
|
87
|
+
* `memory_id`; the already-in-tree check is per memory, in that order;
|
|
88
|
+
* deactivation is a single status flip filtered on persisted state.
|
|
89
|
+
*
|
|
90
|
+
* Idempotent: re-activating the already-active model routes nothing
|
|
91
|
+
* (memberships exist → `alreadyInTree`), flips nothing (`deactivated` is
|
|
92
|
+
* empty), and writes no log entry.
|
|
93
|
+
*/
|
|
94
|
+
export declare const setActiveModel: (model: EmbeddingModelConfig, config: TopicConfig) => Effect.Effect<SetActiveModelResult, TopicError | StoreError, DbBackend>;
|
|
95
|
+
/**
|
|
96
|
+
* Dependencies for {@link memoryEmbedHandler}: the app root composes the
|
|
97
|
+
* embedder registry and the store backend (the store package does not
|
|
98
|
+
* depend on `@dimple/embedder` — the handler is the wiring seam).
|
|
99
|
+
*/
|
|
100
|
+
export interface MemoryEmbedHandlerDeps {
|
|
101
|
+
/** Resolves a model key to its config (the model registry). */
|
|
102
|
+
readonly getModelConfig: (modelKey: string) => EmbeddingModelConfig | undefined;
|
|
103
|
+
/** Embeds one text with the TARGET model (the app root's embedder). */
|
|
104
|
+
readonly embedOne: (text: string, model: EmbeddingModelConfig) => Effect.Effect<Float32Array, unknown>;
|
|
105
|
+
/** Loads one memory's content by id (the store backend's read path).
|
|
106
|
+
* `undefined` = stale re-offer (memory gone) — the handler treats it as a
|
|
107
|
+
* success no-op. The error channel mirrors `Store.get` (`NotFound |
|
|
108
|
+
* StoreError`) so the handler can `catchTag("Store.NotFound")` cleanly. */
|
|
109
|
+
readonly getMemoryContent: (memoryId: string) => Effect.Effect<string | undefined, NotFound | StoreError>;
|
|
110
|
+
/** Tree-shape config for the routing decision. */
|
|
111
|
+
readonly config: TopicConfig;
|
|
112
|
+
/** Backend captured at registration (see {@link topicSplitHandler}). */
|
|
113
|
+
readonly backend?: DbBackendInterface;
|
|
114
|
+
}
|
|
115
|
+
/** The `memory.embed` handler shape (see jobs.ts). */
|
|
116
|
+
export type MemoryEmbedHandler = (payload: unknown, ctx: JobContext) => Effect.Effect<unknown, JobFailure, DbBackend>;
|
|
117
|
+
/**
|
|
118
|
+
* Factory for the `memory.embed` job handler: re-embeds one memory with the
|
|
119
|
+
* target model and routes it into that model's tree. The success schema is
|
|
120
|
+
* `Schema.Void` — the outcome lives in the DB (vector row + membership).
|
|
121
|
+
* A memory with no content is a stale re-offer → success no-op.
|
|
122
|
+
*/
|
|
123
|
+
export declare function memoryEmbedHandler(deps: MemoryEmbedHandlerDeps & {
|
|
124
|
+
readonly backend: DbBackendInterface;
|
|
125
|
+
}): Handler;
|
|
126
|
+
export declare function memoryEmbedHandler(deps: MemoryEmbedHandlerDeps): MemoryEmbedHandler;
|