@rudderjs/ai 1.18.2 → 1.18.4

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.
Files changed (38) hide show
  1. package/README.md +16 -11
  2. package/dist/budget-orm/index.d.ts +95 -1
  3. package/dist/budget-orm/index.d.ts.map +1 -1
  4. package/dist/budget-orm/index.js +176 -4
  5. package/dist/budget-orm/index.js.map +1 -1
  6. package/dist/commands/ai-eval.d.ts +97 -1
  7. package/dist/commands/ai-eval.d.ts.map +1 -1
  8. package/dist/commands/ai-eval.js +379 -4
  9. package/dist/commands/ai-eval.js.map +1 -1
  10. package/dist/commands/make-agent.d.ts +2 -1
  11. package/dist/commands/make-agent.d.ts.map +1 -1
  12. package/dist/commands/make-agent.js +22 -4
  13. package/dist/commands/make-agent.js.map +1 -1
  14. package/dist/conversation-orm/index.d.ts +115 -1
  15. package/dist/conversation-orm/index.d.ts.map +1 -1
  16. package/dist/conversation-orm/index.js +214 -4
  17. package/dist/conversation-orm/index.js.map +1 -1
  18. package/dist/doctor.d.ts +1 -1
  19. package/dist/doctor.d.ts.map +1 -1
  20. package/dist/doctor.js +67 -4
  21. package/dist/doctor.js.map +1 -1
  22. package/dist/memory-embedding/index.d.ts +120 -1
  23. package/dist/memory-embedding/index.d.ts.map +1 -1
  24. package/dist/memory-embedding/index.js +228 -4
  25. package/dist/memory-embedding/index.js.map +1 -1
  26. package/dist/memory-orm/index.d.ts +117 -1
  27. package/dist/memory-orm/index.d.ts.map +1 -1
  28. package/dist/memory-orm/index.js +186 -4
  29. package/dist/memory-orm/index.js.map +1 -1
  30. package/dist/server/index.d.ts +1 -1
  31. package/dist/server/index.d.ts.map +1 -1
  32. package/dist/server/index.js +5 -4
  33. package/dist/server/index.js.map +1 -1
  34. package/dist/server/provider.d.ts +22 -0
  35. package/dist/server/provider.d.ts.map +1 -0
  36. package/dist/server/provider.js +179 -0
  37. package/dist/server/provider.js.map +1 -0
  38. package/package.json +12 -6
@@ -1,5 +1,229 @@
1
- // @rudderjs/ai is deprecated. The AI engine now lives in @gemstack/ai-sdk.
2
- // This module re-exports it for backwards compatibility; import from
3
- // '@gemstack/ai-sdk/memory-embedding' directly in new code.
4
- export * from '@gemstack/ai-sdk/memory-embedding';
1
+ /**
2
+ * `@rudderjs/ai/memory-embedding` embedding-backed {@link UserMemory}
3
+ * for #A4 Phase 5.
4
+ *
5
+ * Composes Phase 4's {@link OrmUserMemory} with the embedding
6
+ * provider registered on {@link AiRegistry}: `remember()` embeds the
7
+ * fact and writes the Float32-packed vector into the row's
8
+ * `embedding` column; `recall()` embeds the query and ranks by
9
+ * cosine similarity. `forget()` / `forgetAll()` delegate to the
10
+ * inner store — the embedding lives in the same row, so deleting
11
+ * the row deletes the vector. GDPR right-to-be-forgotten cascades
12
+ * automatically.
13
+ *
14
+ * v1 is **pure-JS cosine over the user's full set** — fine up to
15
+ * a few thousand facts per user. For larger workloads, B7 lands a
16
+ * pgvector-backed `EmbeddingUserMemory` that pushes the dot-product
17
+ * into the database.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { OrmUserMemory } from '@rudderjs/ai/memory-orm'
22
+ * import { EmbeddingUserMemory } from '@rudderjs/ai/memory-embedding'
23
+ *
24
+ * const memory = new EmbeddingUserMemory({
25
+ * inner: new OrmUserMemory(),
26
+ * model: 'openai/text-embedding-3-small',
27
+ * threshold: 0.5, // cosine floor; matches below are dropped
28
+ * })
29
+ * ```
30
+ *
31
+ * **Pre-Phase-5 facts** (rows with `embedding === null`) fall back to
32
+ * token-overlap matching against the `fact` column — same shape as
33
+ * `MemoryUserMemory.recall()`. So upgrading from `OrmUserMemory` to
34
+ * `EmbeddingUserMemory` doesn't lose recall on existing rows; new
35
+ * `remember()` calls populate the embedding column going forward.
36
+ */
37
+ import { AI } from '@gemstack/ai-sdk';
38
+ import { UserMemoryRecord } from '../memory-orm/index.js';
39
+ export class EmbeddingUserMemory {
40
+ inner;
41
+ model;
42
+ threshold;
43
+ fallback;
44
+ constructor(opts) {
45
+ this.inner = opts.inner;
46
+ if (opts.model !== undefined)
47
+ this.model = opts.model;
48
+ this.threshold = opts.threshold ?? 0;
49
+ this.fallback = opts.nullEmbeddingFallback ?? 'token-overlap';
50
+ }
51
+ async remember(userId, fact, opts) {
52
+ const entry = await this.inner.remember(userId, fact, opts);
53
+ // Best-effort embed + persist. Failures are logged via the inner
54
+ // store still having the entry; we don't break the caller.
55
+ try {
56
+ const vector = await this.embed(fact);
57
+ await UserMemoryRecord.update(entry.id, {
58
+ embedding: serializeVector(vector),
59
+ });
60
+ }
61
+ catch {
62
+ // Embedding failed (network, missing peer SDK). The row is
63
+ // already in the store; recall will fall back to
64
+ // token-overlap if the column stays null. No-op.
65
+ }
66
+ return entry;
67
+ }
68
+ async recall(userId, query, opts) {
69
+ let queryVector = null;
70
+ try {
71
+ queryVector = await this.embed(query);
72
+ }
73
+ catch {
74
+ // Embed failed — fall through to token-overlap on every row.
75
+ }
76
+ const rows = await UserMemoryRecord.where('userId', userId).get();
77
+ const wanted = opts?.tags;
78
+ const queryTokens = tokenize(query);
79
+ const scored = [];
80
+ for (const row of rows) {
81
+ const entry = rowToEntry(row);
82
+ if (!matchesTags(entry, wanted))
83
+ continue;
84
+ let score;
85
+ if (queryVector !== null && row.embedding !== null && row.embedding !== undefined) {
86
+ const factVector = deserializeVector(row.embedding);
87
+ score = cosineSimilarity(queryVector, factVector);
88
+ }
89
+ else if (this.fallback === 'skip') {
90
+ continue;
91
+ }
92
+ else {
93
+ // token-overlap fallback — score 0 (mid-range) if any
94
+ // token matches, otherwise drop.
95
+ if (factHasAnyToken(entry.fact, queryTokens)) {
96
+ score = 0;
97
+ }
98
+ else {
99
+ continue;
100
+ }
101
+ }
102
+ if (score >= this.threshold) {
103
+ scored.push({ entry, score });
104
+ }
105
+ }
106
+ scored.sort((a, b) => b.score - a.score);
107
+ const capped = capLimit(scored, opts?.limit);
108
+ return capped.map(s => ({ ...s.entry, score: s.score }));
109
+ }
110
+ async forget(userId, factId) {
111
+ // The embedding lives in the same row — deleting via the inner
112
+ // store deletes the vector too. GDPR cascade is automatic.
113
+ return this.inner.forget(userId, factId);
114
+ }
115
+ async list(userId, opts) {
116
+ return this.inner.list(userId, opts);
117
+ }
118
+ async forgetAll(userId) {
119
+ if (!this.inner.forgetAll)
120
+ return;
121
+ return this.inner.forgetAll(userId);
122
+ }
123
+ /**
124
+ * Single-string embedding via the {@link AI} facade. Returns the
125
+ * first (and only) embedding vector. Throws on provider/network
126
+ * failure; callers route through try/catch and degrade.
127
+ */
128
+ async embed(text) {
129
+ const result = await AI.embed(text, this.model ? { model: this.model } : undefined);
130
+ const vec = result.embeddings[0];
131
+ if (!vec)
132
+ throw new Error('[ai-sdk] embed() returned no vectors');
133
+ return vec;
134
+ }
135
+ }
136
+ // ─── Vector + similarity helpers (exported for tests + B7) ─────
137
+ /**
138
+ * Pack a `number[]` into a Float32 byte buffer. 4 bytes per dim;
139
+ * a 1536-dim OpenAI embedding compresses to 6144 bytes.
140
+ *
141
+ * Uses `ArrayBuffer` + `Float32Array` so the output is a portable
142
+ * `Uint8Array` (works in Node, browser, RN). Prisma's `Bytes`
143
+ * column accepts both `Uint8Array` and `Buffer`.
144
+ */
145
+ export function serializeVector(v) {
146
+ const buf = new ArrayBuffer(v.length * 4);
147
+ const view = new Float32Array(buf);
148
+ for (let i = 0; i < v.length; i++)
149
+ view[i] = v[i];
150
+ return new Uint8Array(buf);
151
+ }
152
+ /**
153
+ * Reverse of {@link serializeVector}. Reads the underlying byte
154
+ * buffer as Float32 and returns a fresh `number[]` so callers can
155
+ * mutate without affecting the source row.
156
+ */
157
+ export function deserializeVector(bytes) {
158
+ // The `bytes.buffer` may be a slice; honor byteOffset + byteLength
159
+ // so we don't read into adjacent memory.
160
+ const view = new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 4);
161
+ return Array.from(view);
162
+ }
163
+ /**
164
+ * Cosine similarity in `[-1, 1]`. Returns `0` when either vector
165
+ * has zero magnitude, or when lengths don't match (defensive — should
166
+ * never happen if remember/recall use the same embedding model).
167
+ */
168
+ export function cosineSimilarity(a, b) {
169
+ if (a.length !== b.length)
170
+ return 0;
171
+ let dot = 0;
172
+ let magA = 0;
173
+ let magB = 0;
174
+ for (let i = 0; i < a.length; i++) {
175
+ const ai = a[i];
176
+ const bi = b[i];
177
+ dot += ai * bi;
178
+ magA += ai * ai;
179
+ magB += bi * bi;
180
+ }
181
+ if (magA === 0 || magB === 0)
182
+ return 0;
183
+ return dot / (Math.sqrt(magA) * Math.sqrt(magB));
184
+ }
185
+ // ─── Internal helpers ─────────────────────────────────────
186
+ function rowToEntry(row) {
187
+ const tags = row.getTags();
188
+ const out = {
189
+ id: row.id,
190
+ userId: row.userId,
191
+ fact: row.fact,
192
+ createdAt: row.createdAt,
193
+ };
194
+ if (tags.length > 0)
195
+ out.tags = tags;
196
+ if (row.score != null)
197
+ out.score = row.score;
198
+ if (row.updatedAt != null)
199
+ out.updatedAt = row.updatedAt;
200
+ return out;
201
+ }
202
+ function tokenize(s) {
203
+ const out = new Set();
204
+ for (const tok of s.toLowerCase().split(/[^a-z0-9]+/)) {
205
+ if (tok.length >= 3)
206
+ out.add(tok);
207
+ }
208
+ return out;
209
+ }
210
+ function factHasAnyToken(fact, queryTokens) {
211
+ if (queryTokens.size === 0)
212
+ return true;
213
+ const factTokens = tokenize(fact);
214
+ for (const t of factTokens)
215
+ if (queryTokens.has(t))
216
+ return true;
217
+ return false;
218
+ }
219
+ function matchesTags(entry, wanted) {
220
+ if (!wanted || wanted.length === 0)
221
+ return true;
222
+ if (!entry.tags || entry.tags.length === 0)
223
+ return false;
224
+ return wanted.every(t => entry.tags.includes(t));
225
+ }
226
+ function capLimit(items, limit) {
227
+ return limit !== undefined && limit > 0 ? items.slice(0, limit) : items;
228
+ }
5
229
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory-embedding/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,qEAAqE;AACrE,4DAA4D;AAC5D,cAAc,mCAAmC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory-embedding/index.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,118 @@
1
- export * from '@gemstack/ai-sdk/memory-orm';
1
+ /**
2
+ * `@rudderjs/ai/memory-orm` — ORM-backed {@link UserMemory} for #A4 Phase 4.
3
+ *
4
+ * Stores per-user facts in a `UserMemory` table via the registered
5
+ * `@rudderjs/orm` adapter (Prisma today; Drizzle as well once the user's
6
+ * tables are wired). Drop-in alongside Phase 1's in-process
7
+ * `MemoryUserMemory`.
8
+ *
9
+ * Wire it from your AI config:
10
+ *
11
+ * ```ts
12
+ * // config/ai.ts
13
+ * import type { AiConfig } from '@gemstack/ai-sdk'
14
+ * import { OrmUserMemory } from '@rudderjs/ai/memory-orm'
15
+ *
16
+ * export default {
17
+ * default: 'anthropic/claude-sonnet-4-5',
18
+ * providers: { ... },
19
+ * memory: new OrmUserMemory(),
20
+ * } satisfies AiConfig
21
+ * ```
22
+ *
23
+ * The schema lives at `@rudderjs/ai/memory-orm`'s {@link userMemoryPrismaSchema}
24
+ * — copy it into your Prisma schema. The optional `embedding Bytes?`
25
+ * column is shipped here in Phase 4 (intentionally nullable) so Phase 5's
26
+ * `EmbeddingUserMemory` can populate it without forcing an additive
27
+ * migration.
28
+ */
29
+ import { Model } from '@rudderjs/orm';
30
+ import type { MemoryEntry, UserMemory } from '@gemstack/ai-sdk';
31
+ /**
32
+ * The Model row backing {@link OrmUserMemory}. Exposed so apps that
33
+ * want their own queries (admin views, audit dumps) can use the
34
+ * familiar `UserMemoryRecord.where(...).get()` instead of routing
35
+ * everything through the {@link UserMemory} interface.
36
+ *
37
+ * Tags persist as a JSON-encoded string in the `tags` column — both
38
+ * Prisma's portable `String?` and Drizzle's `text` work without
39
+ * needing native array columns. The {@link UserMemory.recall} path
40
+ * filters tags in JavaScript for the same reason.
41
+ *
42
+ * The `embedding Bytes?` column is in the schema as of Phase 4
43
+ * (nullable) so `@rudderjs/ai/memory-embedding`'s `EmbeddingUserMemory`
44
+ * (Phase 5) writes the Float32-packed vector here on `remember()` and
45
+ * reads it for cosine recall. `OrmUserMemory` ignores it — the
46
+ * column stays `null` for any row stored without the embedding
47
+ * composer.
48
+ */
49
+ export declare class UserMemoryRecord extends Model {
50
+ static table: string;
51
+ static fillable: string[];
52
+ id: string;
53
+ userId: string;
54
+ fact: string;
55
+ /** JSON-encoded `string[]` or null. Use `getTags()` for the parsed shape. */
56
+ tags: string | null;
57
+ score: number | null;
58
+ /**
59
+ * Float32-packed vector serialized via
60
+ * `@rudderjs/ai/memory-embedding`'s `serializeVector` /
61
+ * `deserializeVector`. `null` when the row was stored without the
62
+ * embedding composer (Phase 4-only setups).
63
+ */
64
+ embedding: Uint8Array | null;
65
+ createdAt: Date;
66
+ updatedAt: Date | null;
67
+ /** Parsed tags array; empty when nothing was stored. */
68
+ getTags(): string[];
69
+ }
70
+ /**
71
+ * `UserMemory` implementation that persists rows to the registered
72
+ * ORM adapter. Designed for production use — the in-process
73
+ * `MemoryUserMemory` is for tests and dev.
74
+ *
75
+ * Adapter coverage:
76
+ * - Prisma — works out of the box; copy {@link userMemoryPrismaSchema}
77
+ * into your schema.
78
+ * - Drizzle — works once you define a table matching the schema's
79
+ * columns and register it via `tables: { userMemory: <table> }` on
80
+ * the `drizzle()` config.
81
+ *
82
+ * Recall semantics: case-insensitive **token-OR-LIKE** matching against
83
+ * the `fact` column. The query is tokenized on non-alphanumeric
84
+ * boundaries (≥3-char tokens) and any row whose `fact` matches at
85
+ * least one token via `LIKE %tok%` is returned. Mirrors Phase 1's
86
+ * `MemoryUserMemory.recall()` behavior so the two backends are
87
+ * swap-compatible. Tag scope is applied JS-side after fetch — pushing
88
+ * tag-array filtering into the WHERE is adapter-specific and lands in a
89
+ * follow-up.
90
+ */
91
+ export declare class OrmUserMemory implements UserMemory {
92
+ remember(userId: string, fact: string, opts?: {
93
+ tags?: string[];
94
+ score?: number;
95
+ }): Promise<MemoryEntry>;
96
+ recall(userId: string, query: string, opts?: {
97
+ limit?: number;
98
+ tags?: string[];
99
+ }): Promise<MemoryEntry[]>;
100
+ forget(userId: string, factId: string): Promise<void>;
101
+ list(userId: string, opts?: {
102
+ tags?: string[];
103
+ limit?: number;
104
+ }): Promise<MemoryEntry[]>;
105
+ forgetAll(userId: string): Promise<void>;
106
+ }
107
+ /**
108
+ * Reference Prisma schema for `OrmUserMemory`. Copy into your
109
+ * `prisma/schema/<file>.prisma` (or paste alongside an existing
110
+ * model). The `embedding Bytes?` column is intentionally nullable so
111
+ * Phase 5's `EmbeddingUserMemory` becomes additive — no schema
112
+ * migration when you upgrade.
113
+ *
114
+ * SQLite stores `Bytes` as `BLOB`; Postgres stores it as `bytea`.
115
+ * Both work for the dot-product implementation Phase 5 will use.
116
+ */
117
+ export declare const userMemoryPrismaSchema = "model UserMemory {\n id String @id @default(cuid())\n userId String\n fact String\n /// JSON-encoded `string[]` of tags, or null\n tags String?\n /// Confidence score in [0, 1] \u2014 extract sets this from the model's self-rating\n score Float?\n /// Phase 5 \u2014 vector embedding for cosine recall (nullable so Phase 4 ignores it)\n embedding Bytes?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n}\n";
2
118
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory-orm/index.ts"],"names":[],"mappings":"AAGA,cAAc,6BAA6B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory-orm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACrC,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACX,MAAM,kBAAkB,CAAA;AAIzB;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,OAAgB,KAAK,SAAe;IAEpC,OAAgB,QAAQ,WAAmD;IAEnE,EAAE,EAAS,MAAM,CAAA;IACjB,MAAM,EAAK,MAAM,CAAA;IACjB,IAAI,EAAO,MAAM,CAAA;IACzB,6EAA6E;IACrE,IAAI,EAAO,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,EAAM,MAAM,GAAG,IAAI,CAAA;IAChC;;;;;OAKG;IACK,SAAS,EAAE,UAAU,GAAG,IAAI,CAAA;IAC5B,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,EAAE,IAAI,GAAG,IAAI,CAAA;IAE9B,wDAAwD;IACxD,OAAO,IAAI,MAAM,EAAE;CASpB;AAID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,aAAc,YAAW,UAAU;IACxC,QAAQ,CACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAI,MAAM,EACd,IAAI,CAAC,EAAG;QAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1C,OAAO,CAAC,WAAW,CAAC;IASjB,MAAM,CACV,MAAM,EAAE,MAAM,EACd,KAAK,EAAG,MAAM,EACd,IAAI,CAAC,EAAG;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAC1C,OAAO,CAAC,WAAW,EAAE,CAAC;IAgBnB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrD,IAAI,CACR,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAG;QAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1C,OAAO,CAAC,WAAW,EAAE,CAAC;IAMnB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG/C;AAID;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,4eAelC,CAAA"}
@@ -1,5 +1,187 @@
1
- // @rudderjs/ai is deprecated. The AI engine now lives in @gemstack/ai-sdk.
2
- // This module re-exports it for backwards compatibility; import from
3
- // '@gemstack/ai-sdk/memory-orm' directly in new code.
4
- export * from '@gemstack/ai-sdk/memory-orm';
1
+ /**
2
+ * `@rudderjs/ai/memory-orm` — ORM-backed {@link UserMemory} for #A4 Phase 4.
3
+ *
4
+ * Stores per-user facts in a `UserMemory` table via the registered
5
+ * `@rudderjs/orm` adapter (Prisma today; Drizzle as well once the user's
6
+ * tables are wired). Drop-in alongside Phase 1's in-process
7
+ * `MemoryUserMemory`.
8
+ *
9
+ * Wire it from your AI config:
10
+ *
11
+ * ```ts
12
+ * // config/ai.ts
13
+ * import type { AiConfig } from '@gemstack/ai-sdk'
14
+ * import { OrmUserMemory } from '@rudderjs/ai/memory-orm'
15
+ *
16
+ * export default {
17
+ * default: 'anthropic/claude-sonnet-4-5',
18
+ * providers: { ... },
19
+ * memory: new OrmUserMemory(),
20
+ * } satisfies AiConfig
21
+ * ```
22
+ *
23
+ * The schema lives at `@rudderjs/ai/memory-orm`'s {@link userMemoryPrismaSchema}
24
+ * — copy it into your Prisma schema. The optional `embedding Bytes?`
25
+ * column is shipped here in Phase 4 (intentionally nullable) so Phase 5's
26
+ * `EmbeddingUserMemory` can populate it without forcing an additive
27
+ * migration.
28
+ */
29
+ import { Model } from '@rudderjs/orm';
30
+ // ─── ORM Model ────────────────────────────────────────────
31
+ /**
32
+ * The Model row backing {@link OrmUserMemory}. Exposed so apps that
33
+ * want their own queries (admin views, audit dumps) can use the
34
+ * familiar `UserMemoryRecord.where(...).get()` instead of routing
35
+ * everything through the {@link UserMemory} interface.
36
+ *
37
+ * Tags persist as a JSON-encoded string in the `tags` column — both
38
+ * Prisma's portable `String?` and Drizzle's `text` work without
39
+ * needing native array columns. The {@link UserMemory.recall} path
40
+ * filters tags in JavaScript for the same reason.
41
+ *
42
+ * The `embedding Bytes?` column is in the schema as of Phase 4
43
+ * (nullable) so `@rudderjs/ai/memory-embedding`'s `EmbeddingUserMemory`
44
+ * (Phase 5) writes the Float32-packed vector here on `remember()` and
45
+ * reads it for cosine recall. `OrmUserMemory` ignores it — the
46
+ * column stays `null` for any row stored without the embedding
47
+ * composer.
48
+ */
49
+ export class UserMemoryRecord extends Model {
50
+ static table = 'userMemory';
51
+ static fillable = ['userId', 'fact', 'tags', 'score', 'embedding'];
52
+ /** Parsed tags array; empty when nothing was stored. */
53
+ getTags() {
54
+ if (this.tags == null || this.tags === '')
55
+ return [];
56
+ try {
57
+ const parsed = JSON.parse(this.tags);
58
+ return Array.isArray(parsed) ? parsed.filter(t => typeof t === 'string') : [];
59
+ }
60
+ catch {
61
+ return [];
62
+ }
63
+ }
64
+ }
65
+ // ─── UserMemory adapter ───────────────────────────────────
66
+ /**
67
+ * `UserMemory` implementation that persists rows to the registered
68
+ * ORM adapter. Designed for production use — the in-process
69
+ * `MemoryUserMemory` is for tests and dev.
70
+ *
71
+ * Adapter coverage:
72
+ * - Prisma — works out of the box; copy {@link userMemoryPrismaSchema}
73
+ * into your schema.
74
+ * - Drizzle — works once you define a table matching the schema's
75
+ * columns and register it via `tables: { userMemory: <table> }` on
76
+ * the `drizzle()` config.
77
+ *
78
+ * Recall semantics: case-insensitive **token-OR-LIKE** matching against
79
+ * the `fact` column. The query is tokenized on non-alphanumeric
80
+ * boundaries (≥3-char tokens) and any row whose `fact` matches at
81
+ * least one token via `LIKE %tok%` is returned. Mirrors Phase 1's
82
+ * `MemoryUserMemory.recall()` behavior so the two backends are
83
+ * swap-compatible. Tag scope is applied JS-side after fetch — pushing
84
+ * tag-array filtering into the WHERE is adapter-specific and lands in a
85
+ * follow-up.
86
+ */
87
+ export class OrmUserMemory {
88
+ async remember(userId, fact, opts) {
89
+ const data = { userId, fact };
90
+ if (opts?.tags !== undefined)
91
+ data['tags'] = JSON.stringify(opts.tags);
92
+ if (opts?.score !== undefined)
93
+ data['score'] = opts.score;
94
+ const created = await UserMemoryRecord.create(data);
95
+ return rowToEntry(created);
96
+ }
97
+ async recall(userId, query, opts) {
98
+ const tokens = tokenize(query);
99
+ let q = UserMemoryRecord.where('userId', userId);
100
+ if (tokens.size > 0) {
101
+ const tokenList = [...tokens];
102
+ q = q.whereGroup(g => {
103
+ for (const tok of tokenList)
104
+ g.orWhere('fact', 'LIKE', `%${tok}%`);
105
+ });
106
+ }
107
+ const rows = await q.orderBy('createdAt', 'ASC').get();
108
+ const entries = rows.map(rowToEntry).filter(e => matchesTags(e, opts?.tags));
109
+ return capLimit(entries, opts?.limit);
110
+ }
111
+ async forget(userId, factId) {
112
+ const row = await UserMemoryRecord.where('id', factId).where('userId', userId).first();
113
+ if (row)
114
+ await row.delete();
115
+ }
116
+ async list(userId, opts) {
117
+ const rows = await UserMemoryRecord.where('userId', userId).orderBy('createdAt', 'ASC').get();
118
+ const entries = rows.map(rowToEntry).filter(e => matchesTags(e, opts?.tags));
119
+ return capLimit(entries, opts?.limit);
120
+ }
121
+ async forgetAll(userId) {
122
+ await UserMemoryRecord.where('userId', userId).deleteAll();
123
+ }
124
+ }
125
+ // ─── Schema reference ─────────────────────────────────────
126
+ /**
127
+ * Reference Prisma schema for `OrmUserMemory`. Copy into your
128
+ * `prisma/schema/<file>.prisma` (or paste alongside an existing
129
+ * model). The `embedding Bytes?` column is intentionally nullable so
130
+ * Phase 5's `EmbeddingUserMemory` becomes additive — no schema
131
+ * migration when you upgrade.
132
+ *
133
+ * SQLite stores `Bytes` as `BLOB`; Postgres stores it as `bytea`.
134
+ * Both work for the dot-product implementation Phase 5 will use.
135
+ */
136
+ export const userMemoryPrismaSchema = `model UserMemory {
137
+ id String @id @default(cuid())
138
+ userId String
139
+ fact String
140
+ /// JSON-encoded \`string[]\` of tags, or null
141
+ tags String?
142
+ /// Confidence score in [0, 1] — extract sets this from the model's self-rating
143
+ score Float?
144
+ /// Phase 5 — vector embedding for cosine recall (nullable so Phase 4 ignores it)
145
+ embedding Bytes?
146
+ createdAt DateTime @default(now())
147
+ updatedAt DateTime @updatedAt
148
+
149
+ @@index([userId])
150
+ }
151
+ `;
152
+ // ─── Helpers ──────────────────────────────────────────────
153
+ function rowToEntry(row) {
154
+ const tags = row.getTags();
155
+ const out = {
156
+ id: row.id,
157
+ userId: row.userId,
158
+ fact: row.fact,
159
+ createdAt: row.createdAt,
160
+ };
161
+ if (tags.length > 0)
162
+ out.tags = tags;
163
+ if (row.score != null)
164
+ out.score = row.score;
165
+ if (row.updatedAt != null)
166
+ out.updatedAt = row.updatedAt;
167
+ return out;
168
+ }
169
+ function tokenize(s) {
170
+ const out = new Set();
171
+ for (const tok of s.toLowerCase().split(/[^a-z0-9]+/)) {
172
+ if (tok.length >= 3)
173
+ out.add(tok);
174
+ }
175
+ return out;
176
+ }
177
+ function matchesTags(entry, wanted) {
178
+ if (!wanted || wanted.length === 0)
179
+ return true;
180
+ if (!entry.tags || entry.tags.length === 0)
181
+ return false;
182
+ return wanted.every(t => entry.tags.includes(t));
183
+ }
184
+ function capLimit(items, limit) {
185
+ return limit !== undefined && limit > 0 ? items.slice(0, limit) : items;
186
+ }
5
187
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory-orm/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,qEAAqE;AACrE,sDAAsD;AACtD,cAAc,6BAA6B,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory-orm/index.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export * from '@gemstack/ai-sdk/server';
1
+ export { AiProvider } from './provider.js';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAGA,cAAc,yBAAyB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA"}
@@ -1,5 +1,6 @@
1
- // @rudderjs/ai is deprecated. The AI engine now lives in @gemstack/ai-sdk.
2
- // This module re-exports it for backwards compatibility; import from
3
- // '@gemstack/ai-sdk/server' directly in new code.
4
- export * from '@gemstack/ai-sdk/server';
1
+ // `@rudderjs/ai/server` the Rudder `ServiceProvider` binding for the AI
2
+ // engine. The engine itself lives in `@gemstack/ai-sdk`; this provider reads
3
+ // `config('ai')` and wires the engine into the Rudder container, so it lives
4
+ // on the Rudder side rather than in the framework-agnostic engine.
5
+ export { AiProvider } from './provider.js';
5
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,qEAAqE;AACrE,kDAAkD;AAClD,cAAc,yBAAyB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,6EAA6E;AAC7E,6EAA6E;AAC7E,mEAAmE;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,22 @@
1
+ import { ServiceProvider } from '@rudderjs/core';
2
+ /**
3
+ * AI ServiceProvider — reads config from `config('ai')`.
4
+ *
5
+ * @example
6
+ * // bootstrap/providers.ts
7
+ * import { AiProvider } from '@rudderjs/ai/server'
8
+ * export default [AiProvider, ...]
9
+ */
10
+ export declare class AiProvider extends ServiceProvider {
11
+ register(): void;
12
+ boot(): Promise<void>;
13
+ /**
14
+ * Build a `GoogleCacheRegistry` for Gemini's `cachedContent` resources.
15
+ * When `@rudderjs/cache` is installed and booted, the registered cache
16
+ * adapter is plumbed in for cross-process / cross-restart persistence.
17
+ * Otherwise the registry uses an in-process `Map` and warns once on
18
+ * first use.
19
+ */
20
+ private buildGoogleCacheRegistry;
21
+ }
22
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/server/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,MAAM,gBAAgB,CAAA;AAyHpE;;;;;;;GAOG;AACH,qBAAa,UAAW,SAAQ,eAAe;IAC7C,QAAQ,IAAI,IAAI;IAEV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA4C3B;;;;;;OAMG;IACH,OAAO,CAAC,wBAAwB;CAOjC"}