@ponraaj/dimple-sdk 0.0.0-alpha.8 → 0.0.0-alpha.9

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.
@@ -84,8 +84,12 @@ export interface Interface {
84
84
  readonly listIsolatedMemories: (limit: number, modelKey?: string) => Effect.Effect<readonly Record<string, unknown>[], StoreError>;
85
85
  readonly db: DrizzleDB;
86
86
  readonly tables: StoreTables;
87
- readonly ftsSearch: (query: string, namespace: string, limit: number, topicKeys?: ReadonlyArray<string>, modelKey?: string, contentType?: string | ReadonlyArray<string>) => Effect.Effect<readonly Record<string, unknown>[], StoreError>;
88
- readonly vectorSearch: (query: ReadonlyArray<number>, namespace: string, limit: number, model: EmbeddingModelConfig, topicKeys?: ReadonlyArray<string>, contentType?: string | ReadonlyArray<string>) => Effect.Effect<readonly Record<string, unknown>[], StoreError>;
87
+ readonly ftsSearch: (query: string, namespace: string, limit: number, topicKeys?: ReadonlyArray<string>, modelKey?: string, contentType?: string | ReadonlyArray<string>,
88
+ /** Include the 384-float `embedding` blob per row (default false —
89
+ * search results never need vectors; write paths read them via
90
+ * fetchMemoryVectors). */
91
+ includeEmbedding?: boolean) => Effect.Effect<readonly Record<string, unknown>[], StoreError>;
92
+ readonly vectorSearch: (query: ReadonlyArray<number>, namespace: string, limit: number, model: EmbeddingModelConfig, topicKeys?: ReadonlyArray<string>, contentType?: string | ReadonlyArray<string>, includeEmbedding?: boolean) => Effect.Effect<readonly Record<string, unknown>[], StoreError>;
89
93
  readonly sweep: (namespace: string) => Effect.Effect<SweepResult, StoreError>;
90
94
  /** The DB's tables + columns (`dimple db-schema` surface). */
91
95
  readonly listSchema: () => Effect.Effect<ReadonlyArray<{
@@ -109,11 +113,26 @@ export interface Interface {
109
113
  readonly graphNeighbors: (kind: "memory" | "topic" | "concept", id: string, opts?: GraphNeighborsOptions) => Effect.Effect<readonly Record<string, unknown>[], StoreError>;
110
114
  readonly ensureVectorTable: (model: EmbeddingModelConfig) => Effect.Effect<void, StoreError>;
111
115
  readonly insertVector: (memoryId: string, vector: ReadonlyArray<number>, model: EmbeddingModelConfig) => Effect.Effect<void, StoreError>;
116
+ /** Batch variant of `insertVector` — one multi-row statement (bulk
117
+ * ingest: per-memory statements dominate the write path). */
118
+ readonly insertVectors: (entries: ReadonlyArray<{
119
+ readonly memoryId: string;
120
+ readonly vector: ReadonlyArray<number>;
121
+ }>, model: EmbeddingModelConfig) => Effect.Effect<void, StoreError>;
112
122
  readonly deleteVector: (memoryId: string, dimensions: number) => Effect.Effect<void, StoreError>;
113
123
  readonly ensureTopicVectorTable: (model: EmbeddingModelConfig) => Effect.Effect<void, StoreError>;
114
124
  readonly upsertTopicVector: (topicKey: string, sumVector: ReadonlyArray<number>, model: EmbeddingModelConfig) => Effect.Effect<void, StoreError>;
125
+ /** Batch variant of `upsertTopicVector` — one multi-row statement (the
126
+ * bulk-routing path: sequential per-key upserts dominate batch ingest). */
127
+ readonly upsertTopicVectors: (entries: ReadonlyArray<{
128
+ readonly topicKey: string;
129
+ readonly sumVector: ReadonlyArray<number>;
130
+ }>, model: EmbeddingModelConfig) => Effect.Effect<void, StoreError>;
115
131
  readonly deleteTopicVectors: (model: EmbeddingModelConfig) => Effect.Effect<void, StoreError>;
116
132
  readonly fetchTopicVectors: (model: EmbeddingModelConfig) => Effect.Effect<ReadonlyArray<TopicVectorRow>, StoreError>;
133
+ /** Single-row variant — the forget path's per-ancestor maintenance
134
+ * re-read the WHOLE table per level before (O(depth × N) decodes). */
135
+ readonly fetchTopicVector: (topicKey: string, model: EmbeddingModelConfig) => Effect.Effect<TopicVectorRow | undefined, StoreError>;
117
136
  readonly fetchMemoryVectors: (memoryIds: ReadonlyArray<string>, model: EmbeddingModelConfig) => Effect.Effect<ReadonlyArray<MemoryVectorRow>, StoreError>;
118
137
  readonly listMemoryIds: (model: EmbeddingModelConfig) => Effect.Effect<ReadonlyArray<string>, StoreError>;
119
138
  }
@@ -1,5 +1,5 @@
1
1
  import { Context, Effect } from "effect";
2
- import type { MemoryUnit, MemoryEvent, WriteMemoryInput, SweepResult, Concept } from "./models.ts";
2
+ import type { MemoryUnit, MemoryEvent, WriteMemoryInput, SweepResult, Concept, ScoredMemory } from "./models.ts";
3
3
  import type { StoreError, NotFound, DuplicateActiveKey } from "./error.ts";
4
4
  import type { TopicError } from "./topics/errors.ts";
5
5
  import type { MaintenanceOutcome, RebalanceOutcome } from "./topics/maintenance.ts";
@@ -110,6 +110,10 @@ export interface Interface {
110
110
  readonly contentType?: string | ReadonlyArray<string>;
111
111
  /** `false` suppresses the per-leg audit row (fused-row callers). */
112
112
  readonly audit?: boolean;
113
+ /** Include the 384-float embedding on results (default false). */
114
+ readonly includeEmbedding?: boolean;
115
+ /** `false` skips the per-leg graph augmentation (fused-row callers). */
116
+ readonly augment?: boolean;
113
117
  }) => Effect.Effect<ReadonlyArray<AugmentedMemory>, StoreError>;
114
118
  readonly searchVector: (query: ReadonlyArray<number>, namespace: string, limit: number, opts?: {
115
119
  readonly topicKeys?: ReadonlyArray<string>;
@@ -120,7 +124,16 @@ export interface Interface {
120
124
  readonly contentType?: string | ReadonlyArray<string>;
121
125
  /** `false` suppresses the per-leg audit row (fused-row callers). */
122
126
  readonly audit?: boolean;
127
+ /** Include the 384-float embedding on results (default false). */
128
+ readonly includeEmbedding?: boolean;
129
+ /** `false` skips the per-leg graph augmentation (fused-row callers). */
130
+ readonly augment?: boolean;
123
131
  }) => Effect.Effect<ReadonlyArray<AugmentedMemory>, StoreError>;
132
+ /** One-pass graph augmentation over an already-ranked result set (the
133
+ * hybrid path: the per-leg augment passes are skipped and the FUSED set
134
+ * gets one edge fetch + one concept fetch instead of two of each over
135
+ * 2× the rows). */
136
+ readonly augmentSearchResults: (results: ReadonlyArray<ScoredMemory>) => Effect.Effect<ReadonlyArray<AugmentedMemory>, StoreError>;
124
137
  /** The DB's tables + columns (`dimple db-schema` surface). */
125
138
  readonly listSchema: () => Effect.Effect<ReadonlyArray<{
126
139
  readonly table: string;
@@ -147,6 +160,20 @@ export interface Interface {
147
160
  readonly updateEmbedding: (id: string, embedding: ReadonlyArray<number>, model: string, options?: {
148
161
  readonly scanCandidates?: boolean;
149
162
  }) => Effect.Effect<void, NotFound | StoreError>;
163
+ /** Bulk variant of `updateEmbedding` — the writeMany path. One
164
+ * transaction for all memory updates + events, batch vector insert,
165
+ * and `routeInsertMany` (tree read once, all insertions computed in
166
+ * memory, one transaction). For NEW memories: the idempotent re-embed
167
+ * decrement is deliberately NOT part of the batch (use
168
+ * `updateEmbedding` for re-embedding existing routed memories).
169
+ * `scanCandidates` defaults to false-ish via the config: it runs only
170
+ * when explicitly requested AND `graph.enabled` is not false. */
171
+ readonly updateEmbeddingMany: (entries: ReadonlyArray<{
172
+ readonly id: string;
173
+ readonly embedding: ReadonlyArray<number>;
174
+ }>, model: string, options?: {
175
+ readonly scanCandidates?: boolean;
176
+ }) => Effect.Effect<void, StoreError>;
150
177
  readonly findStale: (model: string) => Effect.Effect<readonly string[], StoreError>;
151
178
  readonly createConcept: (name: string, embedding: ReadonlyArray<number>) => Effect.Effect<Concept, StoreError>;
152
179
  readonly getConcept: (id: string) => Effect.Effect<Concept, NotFound | StoreError>;
@@ -88,3 +88,36 @@ export declare const routeInsert: (memoryId: string, vector: ReadonlyArray<numbe
88
88
  topicKey: string;
89
89
  overflow: boolean;
90
90
  }, TopicError | StoreError, DbBackend>;
91
+ /**
92
+ * Batch routing — the bulk-ingest path (`Store.updateEmbeddingMany`).
93
+ *
94
+ * Sequential `routeInsert` re-reads the WHOLE tree (all topics, all
95
+ * relations, all centroid sum-vectors) and commits its own transaction
96
+ * PER UNIT — measured ~42 ms/unit under bulk ingest, dominating the
97
+ * write path. This variant:
98
+ *
99
+ * 1. Reads the tree structure + sum-vectors ONCE.
100
+ * 2. Routes every entry against an IN-MEMORY mirror of the tree state,
101
+ * applying each unit's CF updates locally before the next descent —
102
+ * so the descents are bit-identical to sequential routeInsert calls
103
+ * against the DB (same reads, same writes, same order).
104
+ * 3. Applies ALL membership inserts + topic CF updates in ONE
105
+ * transaction (per-topic deltas accumulated in memory).
106
+ * 4. Writes the derived sum vectors in ONE batched upsert (backend
107
+ * `upsertTopicVectors`), still after commit (backend not
108
+ * transaction-aware — see module docs).
109
+ *
110
+ * Contract differences vs sequential: all-or-nothing (a validation
111
+ * failure or structural corruption rejects the whole batch), and the
112
+ * batch does NOT handle re-embedding (no membership decrement path) —
113
+ * it is for NEW memories; re-embedding existing ones goes through
114
+ * `routeInsert`/`Store.updateEmbedding`.
115
+ */
116
+ export declare const routeInsertMany: (entries: readonly {
117
+ readonly memoryId: string;
118
+ readonly vector: ReadonlyArray<number>;
119
+ }[], model: EmbeddingModelConfig, config: TopicConfig) => Effect.Effect<readonly {
120
+ readonly memoryId: string;
121
+ readonly topicKey: string;
122
+ readonly overflow: boolean;
123
+ }[], TopicError | StoreError, DbBackend>;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * In-process execution-completion signals — the event side of `Runtime.wait`.
3
+ *
4
+ * `wait` used to poll the persisted `${jobId}/result` key every 250ms. The
5
+ * engine knows the exact completion moment, so it now notifies a per-
6
+ * executionId set of Deferreds; `wait` races the signal against its poll
7
+ * interval (the poll stays as the fallback for cross-process waits, where
8
+ * the completing engine lives in another process).
9
+ *
10
+ * Plain module-level Map — no Effect service: the signal is a fire-and-
11
+ * forget wakeup, and the subscribers are runtime-layer Deferreds. Cleanup
12
+ * on unsubscribe keeps the map from leaking job ids.
13
+ */
14
+ import { Deferred } from "effect";
15
+ /** Subscribe to one execution's completion. */
16
+ export declare const onExecutionDone: (executionId: string, deferred: Deferred.Deferred<void>) => void;
17
+ /** Unsubscribe (wait's finally — the poll fallback may still be running). */
18
+ export declare const offExecutionDone: (executionId: string, deferred: Deferred.Deferred<void>) => void;
19
+ /** Fire every subscriber's deferred (the engine's completion tap). */
20
+ export declare const notifyExecutionDone: (executionId: string) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ponraaj/dimple-sdk",
3
- "version": "0.0.0-alpha.8",
3
+ "version": "0.0.0-alpha.9",
4
4
  "private": false,
5
5
  "files": [
6
6
  "dist"