@sentry/junior-memory 0.118.0 → 0.120.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/README.md +23 -7
- package/dist/agent.d.ts +11 -1
- package/dist/api.d.ts +45 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +634 -272
- package/dist/index.js.map +1 -1
- package/dist/personal-store.d.ts +39 -0
- package/dist/personal.d.ts +21 -0
- package/dist/plugin.d.ts +2 -3
- package/dist/ranking.d.ts +20 -0
- package/dist/recall.d.ts +4 -1
- package/dist/store.d.ts +25 -0
- package/dist/user-pages.d.ts +2 -2
- package/migrations/0005_short_jamie_braddock.sql +1 -0
- package/migrations/meta/0005_snapshot.json +364 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +2 -2
- package/src/agent.ts +65 -1
- package/src/api.ts +168 -0
- package/src/db/schema.ts +5 -0
- package/src/index.ts +7 -1
- package/src/personal-store.ts +195 -0
- package/src/personal.ts +120 -0
- package/src/plugin.ts +11 -4
- package/src/ranking.ts +98 -0
- package/src/recall.ts +31 -4
- package/src/store.ts +151 -236
- package/src/user-pages.ts +27 -62
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type MemoryDb, type MemoryRecord } from "./store";
|
|
3
|
+
import type { MemoryRuntimeContext } from "./types";
|
|
4
|
+
declare const personalMemoryCursorSchema: z.ZodObject<{
|
|
5
|
+
createdAtMs: z.ZodNumber;
|
|
6
|
+
id: z.ZodString;
|
|
7
|
+
}, z.core.$strict>;
|
|
8
|
+
declare const personalMemoryPageInputSchema: z.ZodObject<{
|
|
9
|
+
cursor: z.ZodOptional<z.ZodObject<{
|
|
10
|
+
createdAtMs: z.ZodNumber;
|
|
11
|
+
id: z.ZodString;
|
|
12
|
+
}, z.core.$strict>>;
|
|
13
|
+
limit: z.ZodNumber;
|
|
14
|
+
query: z.ZodOptional<z.ZodString>;
|
|
15
|
+
}, z.core.$strict>;
|
|
16
|
+
export type PersonalMemoryCursor = z.output<typeof personalMemoryCursorSchema>;
|
|
17
|
+
export type PersonalMemoryPageInput = z.output<typeof personalMemoryPageInputSchema>;
|
|
18
|
+
export interface PersonalMemoryPage {
|
|
19
|
+
memories: MemoryRecord[];
|
|
20
|
+
nextCursor?: PersonalMemoryCursor;
|
|
21
|
+
}
|
|
22
|
+
/** Expected failure when a viewer does not own the requested memory. */
|
|
23
|
+
export declare class PersonalMemoryNotFoundError extends Error {
|
|
24
|
+
constructor();
|
|
25
|
+
}
|
|
26
|
+
/** Viewer-scoped personal memory operations shared by dashboard and REST. */
|
|
27
|
+
export interface PersonalMemoryCollection {
|
|
28
|
+
/** Archive one exact personal memory owned by a linked actor. */
|
|
29
|
+
archive(id: string): Promise<MemoryRecord>;
|
|
30
|
+
/** Read one exact personal memory owned by a linked actor. */
|
|
31
|
+
get(id: string): Promise<MemoryRecord>;
|
|
32
|
+
/** List one stable page across every linked personal scope. */
|
|
33
|
+
list(input: PersonalMemoryPageInput): Promise<PersonalMemoryPage>;
|
|
34
|
+
}
|
|
35
|
+
/** Build storage operations for every personal scope linked to one viewer. */
|
|
36
|
+
export declare function createPersonalMemoryCollection(db: MemoryDb, runtimeContexts: MemoryRuntimeContext[], options?: {
|
|
37
|
+
now?: () => number;
|
|
38
|
+
}): PersonalMemoryCollection;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PluginUserPageActor } from "@sentry/junior-plugin-api";
|
|
2
|
+
import type { MemoryDb, MemoryRecord } from "./store";
|
|
3
|
+
export interface ViewerMemoryPage {
|
|
4
|
+
memories: MemoryRecord[];
|
|
5
|
+
nextCursor?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ViewerMemoryPageInput {
|
|
8
|
+
cursor?: string;
|
|
9
|
+
limit: number;
|
|
10
|
+
query?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class InvalidMemoryCursorError extends Error {
|
|
13
|
+
constructor();
|
|
14
|
+
}
|
|
15
|
+
export { PersonalMemoryNotFoundError } from "./personal-store";
|
|
16
|
+
/** Build personal-memory operations authorized by a viewer's linked actors. */
|
|
17
|
+
export declare function createViewerMemories(db: MemoryDb, actors: PluginUserPageActor[]): {
|
|
18
|
+
archive(id: string): Promise<MemoryRecord>;
|
|
19
|
+
get(id: string): Promise<MemoryRecord>;
|
|
20
|
+
list(input: ViewerMemoryPageInput): Promise<ViewerMemoryPage>;
|
|
21
|
+
};
|
package/dist/plugin.d.ts
CHANGED
|
@@ -3,6 +3,5 @@ export interface MemoryPluginOptions {
|
|
|
3
3
|
/** Maximum cosine distance for vector recall candidates. Defaults to MEMORY_RECALL_MAX_VECTOR_DISTANCE env or 0.45. */
|
|
4
4
|
recallMaxVectorDistance?: number;
|
|
5
5
|
}
|
|
6
|
-
/**
|
|
7
|
-
export declare function
|
|
8
|
-
export declare const memoryPlugin: import("@sentry/junior-plugin-api").PluginRegistration;
|
|
6
|
+
/** Register Junior's long-term memory plugin. */
|
|
7
|
+
export declare function memoryPlugin(options?: MemoryPluginOptions): import("@sentry/junior-plugin-api").PluginRegistration;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MemoryRecord } from "./store";
|
|
2
|
+
export interface MemoryMatch {
|
|
3
|
+
exactIdentifier: boolean;
|
|
4
|
+
lexical?: {
|
|
5
|
+
rank: number;
|
|
6
|
+
};
|
|
7
|
+
memory: MemoryRecord;
|
|
8
|
+
sourceKey: string;
|
|
9
|
+
vector?: {
|
|
10
|
+
rank: number;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Keep exact structured-identifier matches in the strongest relevance tier,
|
|
15
|
+
* then fuse lexical and vector ranks without comparing provider raw scores.
|
|
16
|
+
*/
|
|
17
|
+
export declare function rankMemoryMatches(matches: MemoryMatch[], options: {
|
|
18
|
+
channelPrefix?: string;
|
|
19
|
+
nowMs: number;
|
|
20
|
+
}): MemoryMatch[];
|
package/dist/recall.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { type UserPromptContribution, type Actor, type Source } from "@sentry/junior-plugin-api";
|
|
1
|
+
import { type UserPromptContribution, type Actor, type PluginLogger, type Source } from "@sentry/junior-plugin-api";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import type { MemoryAgent } from "./agent";
|
|
3
4
|
import { type MemoryDb, type MemoryEmbeddingProvider } from "./store";
|
|
4
5
|
export interface MemoryRecallContext {
|
|
6
|
+
agent: Pick<MemoryAgent, "selectRelevantMemories">;
|
|
5
7
|
conversationId?: string;
|
|
6
8
|
db: MemoryDb;
|
|
7
9
|
embedder?: MemoryEmbeddingProvider;
|
|
10
|
+
log: PluginLogger;
|
|
8
11
|
/** Maximum cosine distance for vector recall. Passed through to the memory store. */
|
|
9
12
|
maxVectorDistance?: number;
|
|
10
13
|
actor?: Actor;
|
package/dist/store.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { type SQL } from "drizzle-orm";
|
|
1
2
|
import type { PgDatabase } from "drizzle-orm/pg-core";
|
|
2
3
|
import type { PgQueryResultHKT } from "drizzle-orm/pg-core/session";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
import * as memorySqlSchema from "./db/schema";
|
|
5
6
|
import { type MemoryRuntimeContext } from "./types";
|
|
7
|
+
import { type ResolvedMemoryScope } from "./scope";
|
|
6
8
|
export type MemoryDb = PgDatabase<PgQueryResultHKT, typeof memorySqlSchema>;
|
|
7
9
|
declare const createMemoryInputSchema: z.ZodObject<{
|
|
8
10
|
content: z.ZodString;
|
|
@@ -168,9 +170,32 @@ export interface MemoryStore {
|
|
|
168
170
|
listMemories(input: ListMemoriesInput): Promise<MemoryRecord[]>;
|
|
169
171
|
/** List active personal memories owned by the current actor. */
|
|
170
172
|
listPersonalMemories(input: ListMemoriesInput): Promise<MemoryRecord[]>;
|
|
173
|
+
/**
|
|
174
|
+
* Retrieve a broad relevance-ranked candidate window for automatic recall.
|
|
175
|
+
* Prompt admission remains owned by the recall boundary.
|
|
176
|
+
*/
|
|
177
|
+
recallMemories(input: SearchMemoriesInput): Promise<MemoryRecord[]>;
|
|
171
178
|
/** Search active memories visible in the current runtime context. */
|
|
172
179
|
searchMemories(input: SearchMemoriesInput): Promise<MemoryRecord[]>;
|
|
173
180
|
}
|
|
181
|
+
/** Parse one SQL row into the public memory record projection. */
|
|
182
|
+
/** Parse one SQL row into the public memory projection. */
|
|
183
|
+
export declare function parseMemoryRow(row: unknown): MemoryRecord;
|
|
184
|
+
/** Build the active-row predicate for already-authorized memory scopes. */
|
|
185
|
+
export declare function activeVisiblePredicate(args: {
|
|
186
|
+
nowMs: number;
|
|
187
|
+
scopes: ResolvedMemoryScope[];
|
|
188
|
+
}): SQL | undefined;
|
|
189
|
+
/**
|
|
190
|
+
* Archive a bounded batch of expired active rows and remove their derived vectors.
|
|
191
|
+
*/
|
|
192
|
+
export declare function archiveExpiredMemoryBatch(args: {
|
|
193
|
+
db: MemoryDb;
|
|
194
|
+
idempotencyKey?: string;
|
|
195
|
+
limit?: number;
|
|
196
|
+
nowMs: number;
|
|
197
|
+
scopes: ResolvedMemoryScope[];
|
|
198
|
+
}): Promise<ArchiveExpiredMemoriesResult>;
|
|
174
199
|
/** Create a context-bound SQL-backed store for explicit memory operations. */
|
|
175
200
|
export declare function createMemoryStore(db: MemoryDb, context: MemoryRuntimeContext, options?: MemoryStoreOptions): MemoryStore;
|
|
176
201
|
export {};
|
package/dist/user-pages.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Project
|
|
1
|
+
/** Project viewer-owned memories into Junior's core-rendered user page. */
|
|
2
2
|
import type { PluginUserPageDefinition } from "@sentry/junior-plugin-api";
|
|
3
|
-
/** Create the
|
|
3
|
+
/** Create the interactive personal Memories dashboard page. */
|
|
4
4
|
export declare function createMemoryUserPage(): PluginUserPageDefinition;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CREATE INDEX "junior_memory_memories_search_idx" ON "junior_memory_memories" USING gin (to_tsvector('english', "content")) 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;
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "6948ea3f-2e44-49ce-aa94-8a993ce61cec",
|
|
3
|
+
"prevId": "e915b537-996a-488c-a828-7cf4da06be44",
|
|
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
|
+
},
|
|
95
|
+
"foreignKeys": {
|
|
96
|
+
"junior_memory_embeddings_memory_id_junior_memory_memories_id_fk": {
|
|
97
|
+
"name": "junior_memory_embeddings_memory_id_junior_memory_memories_id_fk",
|
|
98
|
+
"tableFrom": "junior_memory_embeddings",
|
|
99
|
+
"tableTo": "junior_memory_memories",
|
|
100
|
+
"columnsFrom": ["memory_id"],
|
|
101
|
+
"columnsTo": ["id"],
|
|
102
|
+
"onDelete": "cascade",
|
|
103
|
+
"onUpdate": "no action"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"compositePrimaryKeys": {},
|
|
107
|
+
"uniqueConstraints": {},
|
|
108
|
+
"policies": {},
|
|
109
|
+
"checkConstraints": {
|
|
110
|
+
"junior_memory_embeddings_metric_check": {
|
|
111
|
+
"name": "junior_memory_embeddings_metric_check",
|
|
112
|
+
"value": "\"junior_memory_embeddings\".\"metric\" IN ('cosine')"
|
|
113
|
+
},
|
|
114
|
+
"junior_memory_embeddings_dimensions_check": {
|
|
115
|
+
"name": "junior_memory_embeddings_dimensions_check",
|
|
116
|
+
"value": "\"junior_memory_embeddings\".\"dimensions\" = 1536"
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"isRLSEnabled": false
|
|
120
|
+
},
|
|
121
|
+
"public.junior_memory_memories": {
|
|
122
|
+
"name": "junior_memory_memories",
|
|
123
|
+
"schema": "",
|
|
124
|
+
"columns": {
|
|
125
|
+
"id": {
|
|
126
|
+
"name": "id",
|
|
127
|
+
"type": "text",
|
|
128
|
+
"primaryKey": true,
|
|
129
|
+
"notNull": true
|
|
130
|
+
},
|
|
131
|
+
"scope": {
|
|
132
|
+
"name": "scope",
|
|
133
|
+
"type": "text",
|
|
134
|
+
"primaryKey": false,
|
|
135
|
+
"notNull": true
|
|
136
|
+
},
|
|
137
|
+
"scope_key": {
|
|
138
|
+
"name": "scope_key",
|
|
139
|
+
"type": "text",
|
|
140
|
+
"primaryKey": false,
|
|
141
|
+
"notNull": true
|
|
142
|
+
},
|
|
143
|
+
"type": {
|
|
144
|
+
"name": "type",
|
|
145
|
+
"type": "text",
|
|
146
|
+
"primaryKey": false,
|
|
147
|
+
"notNull": true
|
|
148
|
+
},
|
|
149
|
+
"subject_type": {
|
|
150
|
+
"name": "subject_type",
|
|
151
|
+
"type": "text",
|
|
152
|
+
"primaryKey": false,
|
|
153
|
+
"notNull": true
|
|
154
|
+
},
|
|
155
|
+
"subject_key": {
|
|
156
|
+
"name": "subject_key",
|
|
157
|
+
"type": "text",
|
|
158
|
+
"primaryKey": false,
|
|
159
|
+
"notNull": false
|
|
160
|
+
},
|
|
161
|
+
"content": {
|
|
162
|
+
"name": "content",
|
|
163
|
+
"type": "text",
|
|
164
|
+
"primaryKey": false,
|
|
165
|
+
"notNull": true
|
|
166
|
+
},
|
|
167
|
+
"source_platform": {
|
|
168
|
+
"name": "source_platform",
|
|
169
|
+
"type": "text",
|
|
170
|
+
"primaryKey": false,
|
|
171
|
+
"notNull": true
|
|
172
|
+
},
|
|
173
|
+
"source_key": {
|
|
174
|
+
"name": "source_key",
|
|
175
|
+
"type": "text",
|
|
176
|
+
"primaryKey": false,
|
|
177
|
+
"notNull": true
|
|
178
|
+
},
|
|
179
|
+
"idempotency_key": {
|
|
180
|
+
"name": "idempotency_key",
|
|
181
|
+
"type": "text",
|
|
182
|
+
"primaryKey": false,
|
|
183
|
+
"notNull": false
|
|
184
|
+
},
|
|
185
|
+
"observed_at_ms": {
|
|
186
|
+
"name": "observed_at_ms",
|
|
187
|
+
"type": "bigint",
|
|
188
|
+
"primaryKey": false,
|
|
189
|
+
"notNull": true
|
|
190
|
+
},
|
|
191
|
+
"created_at_ms": {
|
|
192
|
+
"name": "created_at_ms",
|
|
193
|
+
"type": "bigint",
|
|
194
|
+
"primaryKey": false,
|
|
195
|
+
"notNull": true
|
|
196
|
+
},
|
|
197
|
+
"expires_at_ms": {
|
|
198
|
+
"name": "expires_at_ms",
|
|
199
|
+
"type": "bigint",
|
|
200
|
+
"primaryKey": false,
|
|
201
|
+
"notNull": false
|
|
202
|
+
},
|
|
203
|
+
"superseded_at_ms": {
|
|
204
|
+
"name": "superseded_at_ms",
|
|
205
|
+
"type": "bigint",
|
|
206
|
+
"primaryKey": false,
|
|
207
|
+
"notNull": false
|
|
208
|
+
},
|
|
209
|
+
"superseded_by_id": {
|
|
210
|
+
"name": "superseded_by_id",
|
|
211
|
+
"type": "text",
|
|
212
|
+
"primaryKey": false,
|
|
213
|
+
"notNull": false
|
|
214
|
+
},
|
|
215
|
+
"archived_at_ms": {
|
|
216
|
+
"name": "archived_at_ms",
|
|
217
|
+
"type": "bigint",
|
|
218
|
+
"primaryKey": false,
|
|
219
|
+
"notNull": false
|
|
220
|
+
},
|
|
221
|
+
"archive_reason": {
|
|
222
|
+
"name": "archive_reason",
|
|
223
|
+
"type": "text",
|
|
224
|
+
"primaryKey": false,
|
|
225
|
+
"notNull": false
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
"indexes": {
|
|
229
|
+
"junior_memory_memories_visible_idx": {
|
|
230
|
+
"name": "junior_memory_memories_visible_idx",
|
|
231
|
+
"columns": [
|
|
232
|
+
{
|
|
233
|
+
"expression": "scope",
|
|
234
|
+
"isExpression": false,
|
|
235
|
+
"asc": true,
|
|
236
|
+
"nulls": "last"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"expression": "scope_key",
|
|
240
|
+
"isExpression": false,
|
|
241
|
+
"asc": true,
|
|
242
|
+
"nulls": "last"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"expression": "created_at_ms",
|
|
246
|
+
"isExpression": false,
|
|
247
|
+
"asc": false,
|
|
248
|
+
"nulls": "last"
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"expression": "id",
|
|
252
|
+
"isExpression": false,
|
|
253
|
+
"asc": true,
|
|
254
|
+
"nulls": "last"
|
|
255
|
+
}
|
|
256
|
+
],
|
|
257
|
+
"isUnique": false,
|
|
258
|
+
"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",
|
|
259
|
+
"concurrently": false,
|
|
260
|
+
"method": "btree",
|
|
261
|
+
"with": {}
|
|
262
|
+
},
|
|
263
|
+
"junior_memory_memories_expiration_idx": {
|
|
264
|
+
"name": "junior_memory_memories_expiration_idx",
|
|
265
|
+
"columns": [
|
|
266
|
+
{
|
|
267
|
+
"expression": "expires_at_ms",
|
|
268
|
+
"isExpression": false,
|
|
269
|
+
"asc": true,
|
|
270
|
+
"nulls": "last"
|
|
271
|
+
}
|
|
272
|
+
],
|
|
273
|
+
"isUnique": false,
|
|
274
|
+
"where": "\"junior_memory_memories\".\"archived_at_ms\" IS NULL AND \"junior_memory_memories\".\"expires_at_ms\" IS NOT NULL",
|
|
275
|
+
"concurrently": false,
|
|
276
|
+
"method": "btree",
|
|
277
|
+
"with": {}
|
|
278
|
+
},
|
|
279
|
+
"junior_memory_memories_search_idx": {
|
|
280
|
+
"name": "junior_memory_memories_search_idx",
|
|
281
|
+
"columns": [
|
|
282
|
+
{
|
|
283
|
+
"expression": "to_tsvector('english', \"content\")",
|
|
284
|
+
"asc": true,
|
|
285
|
+
"isExpression": true,
|
|
286
|
+
"nulls": "last"
|
|
287
|
+
}
|
|
288
|
+
],
|
|
289
|
+
"isUnique": false,
|
|
290
|
+
"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",
|
|
291
|
+
"concurrently": false,
|
|
292
|
+
"method": "gin",
|
|
293
|
+
"with": {}
|
|
294
|
+
},
|
|
295
|
+
"junior_memory_memories_idempotency_idx": {
|
|
296
|
+
"name": "junior_memory_memories_idempotency_idx",
|
|
297
|
+
"columns": [
|
|
298
|
+
{
|
|
299
|
+
"expression": "scope",
|
|
300
|
+
"isExpression": false,
|
|
301
|
+
"asc": true,
|
|
302
|
+
"nulls": "last"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"expression": "scope_key",
|
|
306
|
+
"isExpression": false,
|
|
307
|
+
"asc": true,
|
|
308
|
+
"nulls": "last"
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"expression": "idempotency_key",
|
|
312
|
+
"isExpression": false,
|
|
313
|
+
"asc": true,
|
|
314
|
+
"nulls": "last"
|
|
315
|
+
}
|
|
316
|
+
],
|
|
317
|
+
"isUnique": true,
|
|
318
|
+
"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",
|
|
319
|
+
"concurrently": false,
|
|
320
|
+
"method": "btree",
|
|
321
|
+
"with": {}
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
"foreignKeys": {},
|
|
325
|
+
"compositePrimaryKeys": {},
|
|
326
|
+
"uniqueConstraints": {},
|
|
327
|
+
"policies": {},
|
|
328
|
+
"checkConstraints": {
|
|
329
|
+
"junior_memory_memories_scope_check": {
|
|
330
|
+
"name": "junior_memory_memories_scope_check",
|
|
331
|
+
"value": "\"junior_memory_memories\".\"scope\" IN ('personal', 'conversation')"
|
|
332
|
+
},
|
|
333
|
+
"junior_memory_memories_kind_check": {
|
|
334
|
+
"name": "junior_memory_memories_kind_check",
|
|
335
|
+
"value": "\"junior_memory_memories\".\"type\" IN (\n 'preference',\n 'procedure',\n 'knowledge'\n )"
|
|
336
|
+
},
|
|
337
|
+
"junior_memory_memories_subject_type_check": {
|
|
338
|
+
"name": "junior_memory_memories_subject_type_check",
|
|
339
|
+
"value": "\"junior_memory_memories\".\"subject_type\" IN ('user', 'conversation', 'general')"
|
|
340
|
+
},
|
|
341
|
+
"junior_memory_memories_subject_key_check": {
|
|
342
|
+
"name": "junior_memory_memories_subject_key_check",
|
|
343
|
+
"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)"
|
|
344
|
+
},
|
|
345
|
+
"junior_memory_memories_source_platform_check": {
|
|
346
|
+
"name": "junior_memory_memories_source_platform_check",
|
|
347
|
+
"value": "\"junior_memory_memories\".\"source_platform\" IN ('slack', 'local')"
|
|
348
|
+
}
|
|
349
|
+
},
|
|
350
|
+
"isRLSEnabled": false
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
"enums": {},
|
|
354
|
+
"schemas": {},
|
|
355
|
+
"sequences": {},
|
|
356
|
+
"roles": {},
|
|
357
|
+
"policies": {},
|
|
358
|
+
"views": {},
|
|
359
|
+
"_meta": {
|
|
360
|
+
"columns": {},
|
|
361
|
+
"schemas": {},
|
|
362
|
+
"tables": {}
|
|
363
|
+
}
|
|
364
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/junior-memory",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.120.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.
|
|
30
|
+
"@sentry/junior-plugin-api": "0.120.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^25.9.1",
|
package/src/agent.ts
CHANGED
|
@@ -23,6 +23,28 @@ const memoryRejectReasonSchema = z.enum([
|
|
|
23
23
|
"assistant_or_system_detail",
|
|
24
24
|
"unsupported_scope",
|
|
25
25
|
]);
|
|
26
|
+
const memoryRecallCandidateSchema = z
|
|
27
|
+
.object({
|
|
28
|
+
content: z.string().min(1),
|
|
29
|
+
id: z.string().min(1),
|
|
30
|
+
})
|
|
31
|
+
.strict();
|
|
32
|
+
const memoryRecallInputSchema = z
|
|
33
|
+
.object({
|
|
34
|
+
candidates: z.array(memoryRecallCandidateSchema).min(1).max(20),
|
|
35
|
+
userRequest: z.string().min(1),
|
|
36
|
+
})
|
|
37
|
+
.strict();
|
|
38
|
+
const memoryRecallDecisionSchema = z
|
|
39
|
+
.object({
|
|
40
|
+
relevantIds: z
|
|
41
|
+
.array(z.string().min(1))
|
|
42
|
+
.max(20)
|
|
43
|
+
.describe(
|
|
44
|
+
"Candidate ids whose memories directly help with the current request, ordered by relevance.",
|
|
45
|
+
),
|
|
46
|
+
})
|
|
47
|
+
.strict();
|
|
26
48
|
const createMemoryRequestSchema = z
|
|
27
49
|
.object({
|
|
28
50
|
content: z.string().min(1),
|
|
@@ -169,6 +191,7 @@ type MemoryReviewResponse = z.output<typeof memoryReviewResponseSchema>;
|
|
|
169
191
|
type ExtractMemoriesResponse = z.output<typeof extractMemoriesResponseSchema>;
|
|
170
192
|
|
|
171
193
|
export type MemoryReview = z.output<typeof memoryReviewDecisionSchema>;
|
|
194
|
+
export type MemoryRecallInput = z.output<typeof memoryRecallInputSchema>;
|
|
172
195
|
|
|
173
196
|
export type CreateMemoryRequest = z.output<typeof createMemoryRequestSchema>;
|
|
174
197
|
export type ExtractSessionRequest = z.output<
|
|
@@ -177,6 +200,10 @@ export type ExtractSessionRequest = z.output<
|
|
|
177
200
|
export type ExtractedMemory = z.output<typeof extractedMemoryResultSchema>;
|
|
178
201
|
|
|
179
202
|
export interface MemoryAgent {
|
|
203
|
+
/** Select candidate memories that directly help with the current request. */
|
|
204
|
+
selectRelevantMemories(
|
|
205
|
+
request: MemoryRecallInput,
|
|
206
|
+
): Promise<string[]> | string[];
|
|
180
207
|
/** Classify a new preference against related active preferences. */
|
|
181
208
|
adjudicateSupersession(
|
|
182
209
|
request: MemorySupersessionInput,
|
|
@@ -203,6 +230,13 @@ const MEMORY_EXTRACTION_SYSTEM = [
|
|
|
203
230
|
"Reject secrets, credentials, private or sensitive personal details, gossip, speculative claims about other people, assistant/system implementation details, vague references, and low-durability chatter.",
|
|
204
231
|
"If no public, durable, self-contained memory remains after rewriting, return an empty memories array.",
|
|
205
232
|
].join("\n");
|
|
233
|
+
const MEMORY_RECALL_SYSTEM = [
|
|
234
|
+
"You are Junior's memory recall relevance agent.",
|
|
235
|
+
"Select only memories that would directly help answer the user's current request.",
|
|
236
|
+
"Reject memories that merely share a company, product family, repository vocabulary, programming language, or general engineering context.",
|
|
237
|
+
"Prefer specific matches on the exact repository, workflow, command, test, CI setup, project, or user preference being asked about.",
|
|
238
|
+
"An empty relevantIds array is correct when no candidate is directly helpful.",
|
|
239
|
+
].join("\n");
|
|
206
240
|
const MEMORY_PREFERENCE_ADJUDICATION_SYSTEM = [
|
|
207
241
|
"You are Junior's memory preference adjudication agent.",
|
|
208
242
|
"Classify how one new actor preference relates to existing active actor preferences.",
|
|
@@ -444,6 +478,22 @@ function sessionExtractionPrompt(request: ExtractSessionRequest): string {
|
|
|
444
478
|
].join("\n");
|
|
445
479
|
}
|
|
446
480
|
|
|
481
|
+
function recallRelevancePrompt(request: MemoryRecallInput): string {
|
|
482
|
+
return [
|
|
483
|
+
"<memory-recall-input>",
|
|
484
|
+
"<user-request>",
|
|
485
|
+
escapeXml(request.userRequest),
|
|
486
|
+
"</user-request>",
|
|
487
|
+
"",
|
|
488
|
+
"<candidate-memories>",
|
|
489
|
+
escapeXml(JSON.stringify(request.candidates)),
|
|
490
|
+
"</candidate-memories>",
|
|
491
|
+
"",
|
|
492
|
+
"Return only ids from candidate-memories. Preserve the most relevant candidates first.",
|
|
493
|
+
"</memory-recall-input>",
|
|
494
|
+
].join("\n");
|
|
495
|
+
}
|
|
496
|
+
|
|
447
497
|
function preferenceAdjudicationPrompt(
|
|
448
498
|
request: MemorySupersessionInput,
|
|
449
499
|
): string {
|
|
@@ -477,9 +527,23 @@ function preferenceAdjudicationPrompt(
|
|
|
477
527
|
].join("\n");
|
|
478
528
|
}
|
|
479
529
|
|
|
480
|
-
/** Create the memory-owned agent that reviews and
|
|
530
|
+
/** Create the memory-owned agent that reviews, extracts, and recalls memories. */
|
|
481
531
|
export function createMemoryAgent(model: PluginModel): MemoryAgent {
|
|
482
532
|
return {
|
|
533
|
+
async selectRelevantMemories(rawRequest) {
|
|
534
|
+
const request = memoryRecallInputSchema.parse(rawRequest);
|
|
535
|
+
const result = await model.completeObject({
|
|
536
|
+
schema: memoryRecallDecisionSchema,
|
|
537
|
+
system: MEMORY_RECALL_SYSTEM,
|
|
538
|
+
prompt: recallRelevancePrompt(request),
|
|
539
|
+
maxTokens: 400,
|
|
540
|
+
});
|
|
541
|
+
const decision = memoryRecallDecisionSchema.parse(result.object);
|
|
542
|
+
const candidateIds = new Set(request.candidates.map(({ id }) => id));
|
|
543
|
+
return [...new Set(decision.relevantIds)].filter((id) =>
|
|
544
|
+
candidateIds.has(id),
|
|
545
|
+
);
|
|
546
|
+
},
|
|
483
547
|
async adjudicateSupersession(rawRequest) {
|
|
484
548
|
const request = memorySupersessionInputSchema.parse(rawRequest);
|
|
485
549
|
const result = await model.completeObject({
|