@sentry/junior-memory 0.133.0 → 0.135.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.
package/dist/plugin.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  export interface MemoryPluginOptions {
2
+ /** Disable automatic prompt recall while keeping explicit memory tools available. */
3
+ disableRecall?: boolean;
4
+ /** Disable passive memory extraction from completed sessions. */
5
+ disableExtraction?: boolean;
2
6
  modelId?: string;
3
- /** Maximum cosine distance for vector recall candidates. Defaults to MEMORY_RECALL_MAX_VECTOR_DISTANCE env or 0.45. */
4
- recallMaxVectorDistance?: number;
5
7
  }
6
8
  /** Register Junior's long-term memory plugin. */
7
9
  export declare function memoryPlugin(options?: MemoryPluginOptions): import("@sentry/junior-plugin-api").PluginRegistration;
package/dist/ranking.d.ts CHANGED
@@ -12,5 +12,9 @@ export interface MemoryMatch {
12
12
  /** Fuse lexical and vector ranks without comparing provider raw scores. */
13
13
  export declare function rankMemoryMatches(matches: MemoryMatch[], options: {
14
14
  channelPrefix?: string;
15
+ /** Optional RRF weight for the lexical leg. Defaults to 1. */
16
+ lexicalWeight?: number;
15
17
  nowMs: number;
18
+ /** Optional RRF weight for the vector leg. Defaults to 1. */
19
+ vectorWeight?: number;
16
20
  }): MemoryMatch[];
package/dist/recall.d.ts CHANGED
@@ -9,8 +9,6 @@ export interface MemoryRecallContext {
9
9
  embedder?: MemoryEmbeddingProvider;
10
10
  events?: PluginConversationEvents;
11
11
  log: PluginLogger;
12
- /** Maximum cosine distance for vector recall. Passed through to the memory store. */
13
- maxVectorDistance?: number;
14
12
  actor?: Actor;
15
13
  source: Source;
16
14
  text: string;
package/dist/store.d.ts CHANGED
@@ -156,8 +156,6 @@ export interface MemorySupersessionDecider {
156
156
  }
157
157
  export interface MemoryStoreOptions {
158
158
  embedder?: MemoryEmbeddingProvider;
159
- /** Maximum cosine distance for vector recall candidates. Model-dependent; tune when changing AI_EMBEDDING_MODEL. */
160
- maxVectorDistance?: number;
161
159
  now?: () => number;
162
160
  supersessionDecider?: MemorySupersessionDecider;
163
161
  }
@@ -0,0 +1 @@
1
+ CREATE INDEX "junior_memory_embeddings_embedding_hnsw_idx" ON "junior_memory_embeddings" USING hnsw ("embedding" vector_cosine_ops) WITH (m=16,ef_construction=64);
@@ -0,0 +1,409 @@
1
+ {
2
+ "id": "eeef198b-34d7-4ab8-9e1e-1a238ce8bdd5",
3
+ "prevId": "f18fa309-6485-40f3-921a-5d65552fbdf6",
4
+ "version": "7",
5
+ "dialect": "postgresql",
6
+ "tables": {
7
+ "public.junior_memory_embeddings": {
8
+ "name": "junior_memory_embeddings",
9
+ "schema": "",
10
+ "columns": {
11
+ "memory_id": {
12
+ "name": "memory_id",
13
+ "type": "text",
14
+ "primaryKey": true,
15
+ "notNull": true
16
+ },
17
+ "provider": {
18
+ "name": "provider",
19
+ "type": "text",
20
+ "primaryKey": false,
21
+ "notNull": true
22
+ },
23
+ "model": {
24
+ "name": "model",
25
+ "type": "text",
26
+ "primaryKey": false,
27
+ "notNull": true
28
+ },
29
+ "dimensions": {
30
+ "name": "dimensions",
31
+ "type": "integer",
32
+ "primaryKey": false,
33
+ "notNull": true
34
+ },
35
+ "metric": {
36
+ "name": "metric",
37
+ "type": "text",
38
+ "primaryKey": false,
39
+ "notNull": true
40
+ },
41
+ "content_hash": {
42
+ "name": "content_hash",
43
+ "type": "text",
44
+ "primaryKey": false,
45
+ "notNull": true
46
+ },
47
+ "embedding": {
48
+ "name": "embedding",
49
+ "type": "vector(1536)",
50
+ "primaryKey": false,
51
+ "notNull": true
52
+ },
53
+ "created_at_ms": {
54
+ "name": "created_at_ms",
55
+ "type": "bigint",
56
+ "primaryKey": false,
57
+ "notNull": true
58
+ }
59
+ },
60
+ "indexes": {
61
+ "junior_memory_embeddings_model_idx": {
62
+ "name": "junior_memory_embeddings_model_idx",
63
+ "columns": [
64
+ {
65
+ "expression": "provider",
66
+ "isExpression": false,
67
+ "asc": true,
68
+ "nulls": "last"
69
+ },
70
+ {
71
+ "expression": "model",
72
+ "isExpression": false,
73
+ "asc": true,
74
+ "nulls": "last"
75
+ },
76
+ {
77
+ "expression": "dimensions",
78
+ "isExpression": false,
79
+ "asc": true,
80
+ "nulls": "last"
81
+ },
82
+ {
83
+ "expression": "metric",
84
+ "isExpression": false,
85
+ "asc": true,
86
+ "nulls": "last"
87
+ }
88
+ ],
89
+ "isUnique": false,
90
+ "concurrently": false,
91
+ "method": "btree",
92
+ "with": {}
93
+ },
94
+ "junior_memory_embeddings_embedding_hnsw_idx": {
95
+ "name": "junior_memory_embeddings_embedding_hnsw_idx",
96
+ "columns": [
97
+ {
98
+ "expression": "embedding",
99
+ "isExpression": false,
100
+ "asc": true,
101
+ "nulls": "last",
102
+ "opclass": "vector_cosine_ops"
103
+ }
104
+ ],
105
+ "isUnique": false,
106
+ "concurrently": false,
107
+ "method": "hnsw",
108
+ "with": {
109
+ "m": 16,
110
+ "ef_construction": 64
111
+ }
112
+ }
113
+ },
114
+ "foreignKeys": {
115
+ "junior_memory_embeddings_memory_id_junior_memory_memories_id_fk": {
116
+ "name": "junior_memory_embeddings_memory_id_junior_memory_memories_id_fk",
117
+ "tableFrom": "junior_memory_embeddings",
118
+ "tableTo": "junior_memory_memories",
119
+ "columnsFrom": [
120
+ "memory_id"
121
+ ],
122
+ "columnsTo": [
123
+ "id"
124
+ ],
125
+ "onDelete": "cascade",
126
+ "onUpdate": "no action"
127
+ }
128
+ },
129
+ "compositePrimaryKeys": {},
130
+ "uniqueConstraints": {},
131
+ "policies": {},
132
+ "checkConstraints": {
133
+ "junior_memory_embeddings_metric_check": {
134
+ "name": "junior_memory_embeddings_metric_check",
135
+ "value": "\"junior_memory_embeddings\".\"metric\" IN ('cosine')"
136
+ },
137
+ "junior_memory_embeddings_dimensions_check": {
138
+ "name": "junior_memory_embeddings_dimensions_check",
139
+ "value": "\"junior_memory_embeddings\".\"dimensions\" = 1536"
140
+ }
141
+ },
142
+ "isRLSEnabled": false
143
+ },
144
+ "public.junior_memory_memories": {
145
+ "name": "junior_memory_memories",
146
+ "schema": "",
147
+ "columns": {
148
+ "id": {
149
+ "name": "id",
150
+ "type": "text",
151
+ "primaryKey": true,
152
+ "notNull": true
153
+ },
154
+ "scope": {
155
+ "name": "scope",
156
+ "type": "text",
157
+ "primaryKey": false,
158
+ "notNull": true
159
+ },
160
+ "scope_key": {
161
+ "name": "scope_key",
162
+ "type": "text",
163
+ "primaryKey": false,
164
+ "notNull": true
165
+ },
166
+ "type": {
167
+ "name": "type",
168
+ "type": "text",
169
+ "primaryKey": false,
170
+ "notNull": true
171
+ },
172
+ "subject_type": {
173
+ "name": "subject_type",
174
+ "type": "text",
175
+ "primaryKey": false,
176
+ "notNull": true
177
+ },
178
+ "subject_key": {
179
+ "name": "subject_key",
180
+ "type": "text",
181
+ "primaryKey": false,
182
+ "notNull": false
183
+ },
184
+ "content": {
185
+ "name": "content",
186
+ "type": "text",
187
+ "primaryKey": false,
188
+ "notNull": true
189
+ },
190
+ "search_vector": {
191
+ "name": "search_vector",
192
+ "type": "tsvector",
193
+ "primaryKey": false,
194
+ "notNull": false,
195
+ "generated": {
196
+ "as": "to_tsvector('english', \"content\")",
197
+ "type": "stored"
198
+ }
199
+ },
200
+ "source_platform": {
201
+ "name": "source_platform",
202
+ "type": "text",
203
+ "primaryKey": false,
204
+ "notNull": true
205
+ },
206
+ "source_key": {
207
+ "name": "source_key",
208
+ "type": "text",
209
+ "primaryKey": false,
210
+ "notNull": true
211
+ },
212
+ "idempotency_key": {
213
+ "name": "idempotency_key",
214
+ "type": "text",
215
+ "primaryKey": false,
216
+ "notNull": false
217
+ },
218
+ "observed_at_ms": {
219
+ "name": "observed_at_ms",
220
+ "type": "bigint",
221
+ "primaryKey": false,
222
+ "notNull": true
223
+ },
224
+ "created_at_ms": {
225
+ "name": "created_at_ms",
226
+ "type": "bigint",
227
+ "primaryKey": false,
228
+ "notNull": true
229
+ },
230
+ "expires_at_ms": {
231
+ "name": "expires_at_ms",
232
+ "type": "bigint",
233
+ "primaryKey": false,
234
+ "notNull": false
235
+ },
236
+ "superseded_at_ms": {
237
+ "name": "superseded_at_ms",
238
+ "type": "bigint",
239
+ "primaryKey": false,
240
+ "notNull": false
241
+ },
242
+ "superseded_by_id": {
243
+ "name": "superseded_by_id",
244
+ "type": "text",
245
+ "primaryKey": false,
246
+ "notNull": false
247
+ },
248
+ "archived_at_ms": {
249
+ "name": "archived_at_ms",
250
+ "type": "bigint",
251
+ "primaryKey": false,
252
+ "notNull": false
253
+ },
254
+ "archive_reason": {
255
+ "name": "archive_reason",
256
+ "type": "text",
257
+ "primaryKey": false,
258
+ "notNull": false
259
+ }
260
+ },
261
+ "indexes": {
262
+ "junior_memory_memories_visible_idx": {
263
+ "name": "junior_memory_memories_visible_idx",
264
+ "columns": [
265
+ {
266
+ "expression": "scope",
267
+ "isExpression": false,
268
+ "asc": true,
269
+ "nulls": "last"
270
+ },
271
+ {
272
+ "expression": "scope_key",
273
+ "isExpression": false,
274
+ "asc": true,
275
+ "nulls": "last"
276
+ },
277
+ {
278
+ "expression": "created_at_ms",
279
+ "isExpression": false,
280
+ "asc": false,
281
+ "nulls": "last"
282
+ },
283
+ {
284
+ "expression": "id",
285
+ "isExpression": false,
286
+ "asc": true,
287
+ "nulls": "last"
288
+ }
289
+ ],
290
+ "isUnique": false,
291
+ "where": "\"junior_memory_memories\".\"archived_at_ms\" IS NULL AND \"junior_memory_memories\".\"superseded_at_ms\" IS NULL AND \"junior_memory_memories\".\"superseded_by_id\" IS NULL",
292
+ "concurrently": false,
293
+ "method": "btree",
294
+ "with": {}
295
+ },
296
+ "junior_memory_memories_expiration_idx": {
297
+ "name": "junior_memory_memories_expiration_idx",
298
+ "columns": [
299
+ {
300
+ "expression": "expires_at_ms",
301
+ "isExpression": false,
302
+ "asc": true,
303
+ "nulls": "last"
304
+ }
305
+ ],
306
+ "isUnique": false,
307
+ "where": "\"junior_memory_memories\".\"archived_at_ms\" IS NULL AND \"junior_memory_memories\".\"expires_at_ms\" IS NOT NULL",
308
+ "concurrently": false,
309
+ "method": "btree",
310
+ "with": {}
311
+ },
312
+ "junior_memory_memories_search_idx": {
313
+ "name": "junior_memory_memories_search_idx",
314
+ "columns": [
315
+ {
316
+ "expression": "scope",
317
+ "isExpression": false,
318
+ "asc": true,
319
+ "nulls": "last"
320
+ },
321
+ {
322
+ "expression": "scope_key",
323
+ "isExpression": false,
324
+ "asc": true,
325
+ "nulls": "last"
326
+ },
327
+ {
328
+ "expression": "search_vector",
329
+ "isExpression": false,
330
+ "asc": true,
331
+ "nulls": "last"
332
+ }
333
+ ],
334
+ "isUnique": false,
335
+ "where": "\"junior_memory_memories\".\"archived_at_ms\" IS NULL AND \"junior_memory_memories\".\"superseded_at_ms\" IS NULL AND \"junior_memory_memories\".\"superseded_by_id\" IS NULL",
336
+ "concurrently": false,
337
+ "method": "gin",
338
+ "with": {}
339
+ },
340
+ "junior_memory_memories_idempotency_idx": {
341
+ "name": "junior_memory_memories_idempotency_idx",
342
+ "columns": [
343
+ {
344
+ "expression": "scope",
345
+ "isExpression": false,
346
+ "asc": true,
347
+ "nulls": "last"
348
+ },
349
+ {
350
+ "expression": "scope_key",
351
+ "isExpression": false,
352
+ "asc": true,
353
+ "nulls": "last"
354
+ },
355
+ {
356
+ "expression": "idempotency_key",
357
+ "isExpression": false,
358
+ "asc": true,
359
+ "nulls": "last"
360
+ }
361
+ ],
362
+ "isUnique": true,
363
+ "where": "\"junior_memory_memories\".\"idempotency_key\" IS NOT NULL AND \"junior_memory_memories\".\"archived_at_ms\" IS NULL AND \"junior_memory_memories\".\"superseded_at_ms\" IS NULL AND \"junior_memory_memories\".\"superseded_by_id\" IS NULL",
364
+ "concurrently": false,
365
+ "method": "btree",
366
+ "with": {}
367
+ }
368
+ },
369
+ "foreignKeys": {},
370
+ "compositePrimaryKeys": {},
371
+ "uniqueConstraints": {},
372
+ "policies": {},
373
+ "checkConstraints": {
374
+ "junior_memory_memories_scope_check": {
375
+ "name": "junior_memory_memories_scope_check",
376
+ "value": "\"junior_memory_memories\".\"scope\" IN ('personal', 'conversation')"
377
+ },
378
+ "junior_memory_memories_kind_check": {
379
+ "name": "junior_memory_memories_kind_check",
380
+ "value": "\"junior_memory_memories\".\"type\" IN (\n 'preference',\n 'procedure',\n 'knowledge'\n )"
381
+ },
382
+ "junior_memory_memories_subject_type_check": {
383
+ "name": "junior_memory_memories_subject_type_check",
384
+ "value": "\"junior_memory_memories\".\"subject_type\" IN ('user', 'conversation', 'general')"
385
+ },
386
+ "junior_memory_memories_subject_key_check": {
387
+ "name": "junior_memory_memories_subject_key_check",
388
+ "value": "(\"junior_memory_memories\".\"subject_type\" = 'general' AND \"junior_memory_memories\".\"subject_key\" IS NULL) OR (\"junior_memory_memories\".\"subject_type\" IN ('user', 'conversation') AND \"junior_memory_memories\".\"subject_key\" IS NOT NULL AND length(\"junior_memory_memories\".\"subject_key\") > 0)"
389
+ },
390
+ "junior_memory_memories_source_platform_check": {
391
+ "name": "junior_memory_memories_source_platform_check",
392
+ "value": "\"junior_memory_memories\".\"source_platform\" IN ('slack', 'local')"
393
+ }
394
+ },
395
+ "isRLSEnabled": false
396
+ }
397
+ },
398
+ "enums": {},
399
+ "schemas": {},
400
+ "sequences": {},
401
+ "roles": {},
402
+ "policies": {},
403
+ "views": {},
404
+ "_meta": {
405
+ "columns": {},
406
+ "schemas": {},
407
+ "tables": {}
408
+ }
409
+ }
@@ -50,6 +50,13 @@
50
50
  "when": 1785878952301,
51
51
  "tag": "0006_friendly_hydra",
52
52
  "breakpoints": true
53
+ },
54
+ {
55
+ "idx": 7,
56
+ "version": "7",
57
+ "when": 1785910292191,
58
+ "tag": "0007_military_tyger_tiger",
59
+ "breakpoints": true
53
60
  }
54
61
  ]
55
- }
62
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior-memory",
3
- "version": "0.133.0",
3
+ "version": "0.135.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -27,7 +27,7 @@
27
27
  "commander": "^14.0.3",
28
28
  "drizzle-orm": "^0.45.2",
29
29
  "zod": "^4.4.3",
30
- "@sentry/junior-plugin-api": "0.133.0"
30
+ "@sentry/junior-plugin-api": "0.135.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^25.9.1",
package/src/db/schema.ts CHANGED
@@ -128,6 +128,11 @@ export const juniorMemoryEmbeddings = pgTable(
128
128
  table.dimensions,
129
129
  table.metric,
130
130
  ),
131
+ // Cosine ANN for vector recall/search. Ops must match cosineDistance (<=>).
132
+ // Keep this unfiltered so planners can use HNSW before scope/status joins.
133
+ index("junior_memory_embeddings_embedding_hnsw_idx")
134
+ .using("hnsw", table.embedding.op("vector_cosine_ops"))
135
+ .with({ m: 16, ef_construction: 64 }),
131
136
  check(
132
137
  "junior_memory_embeddings_metric_check",
133
138
  sql`${table.metric} IN ('cosine')`,
package/src/plugin.ts CHANGED
@@ -23,14 +23,13 @@ import type { MemoryDb } from "./store";
23
23
  import { createMemoryUserPage } from "./user-pages";
24
24
 
25
25
  const MEMORY_MODEL_ENV = "AI_MEMORY_MODEL";
26
- const MEMORY_RECALL_MAX_VECTOR_DISTANCE_ENV =
27
- "MEMORY_RECALL_MAX_VECTOR_DISTANCE";
28
- const DEFAULT_RECALL_MAX_VECTOR_DISTANCE = 0.45;
29
26
 
30
27
  export interface MemoryPluginOptions {
28
+ /** Disable automatic prompt recall while keeping explicit memory tools available. */
29
+ disableRecall?: boolean;
30
+ /** Disable passive memory extraction from completed sessions. */
31
+ disableExtraction?: boolean;
31
32
  modelId?: string;
32
- /** Maximum cosine distance for vector recall candidates. Defaults to MEMORY_RECALL_MAX_VECTOR_DISTANCE env or 0.45. */
33
- recallMaxVectorDistance?: number;
34
33
  }
35
34
 
36
35
  function memoryModelId(options: MemoryPluginOptions): string | undefined {
@@ -42,20 +41,6 @@ function memoryModelId(options: MemoryPluginOptions): string | undefined {
42
41
  return envModelId || undefined;
43
42
  }
44
43
 
45
- function recallMaxVectorDistance(options: MemoryPluginOptions): number {
46
- if (options.recallMaxVectorDistance !== undefined) {
47
- return options.recallMaxVectorDistance;
48
- }
49
- const raw = process.env[MEMORY_RECALL_MAX_VECTOR_DISTANCE_ENV]?.trim();
50
- if (raw) {
51
- const parsed = Number(raw);
52
- if (Number.isFinite(parsed) && parsed > 0) {
53
- return Math.min(parsed, 1);
54
- }
55
- }
56
- return DEFAULT_RECALL_MAX_VECTOR_DISTANCE;
57
- }
58
-
59
44
  function memoryToolContext(ctx: {
60
45
  agent: MemoryReviewer;
61
46
  conversationId?: string;
@@ -113,13 +98,15 @@ export function memoryPlugin(options: MemoryPluginOptions = {}) {
113
98
  cli: {
114
99
  commands: [createMemoryCliCommand()],
115
100
  },
116
- tasks: {
117
- processSession: {
118
- async run(ctx) {
119
- await processMemorySession(ctx);
101
+ tasks: options.disableExtraction
102
+ ? {}
103
+ : {
104
+ processSession: {
105
+ async run(ctx) {
106
+ await processMemorySession(ctx);
107
+ },
108
+ },
120
109
  },
121
- },
122
- },
123
110
  userPages: [createMemoryUserPage()],
124
111
  hooks: {
125
112
  async operationalReport(ctx) {
@@ -163,20 +150,25 @@ export function memoryPlugin(options: MemoryPluginOptions = {}) {
163
150
  searchMemories: createMemorySearchTool(context),
164
151
  };
165
152
  },
166
- async userPrompt(ctx) {
167
- return await createMemoryPromptContributions({
168
- agent: createMemoryAgent(ctx.model),
169
- ...(ctx.conversationId ? { conversationId: ctx.conversationId } : {}),
170
- ...(ctx.actor ? { actor: ctx.actor } : {}),
171
- db: ctx.db as MemoryDb,
172
- embedder: ctx.embedder,
173
- events: ctx.events,
174
- log: ctx.log,
175
- maxVectorDistance: recallMaxVectorDistance(options),
176
- source: ctx.source,
177
- text: ctx.text,
178
- });
179
- },
153
+ ...(!options.disableRecall
154
+ ? {
155
+ async userPrompt(ctx) {
156
+ return await createMemoryPromptContributions({
157
+ agent: createMemoryAgent(ctx.model),
158
+ ...(ctx.conversationId
159
+ ? { conversationId: ctx.conversationId }
160
+ : {}),
161
+ ...(ctx.actor ? { actor: ctx.actor } : {}),
162
+ db: ctx.db as MemoryDb,
163
+ embedder: ctx.embedder,
164
+ events: ctx.events,
165
+ log: ctx.log,
166
+ source: ctx.source,
167
+ text: ctx.text,
168
+ });
169
+ },
170
+ }
171
+ : {}),
180
172
  },
181
173
  });
182
174
  }