@sentry/junior-memory 0.124.1 → 0.125.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 +11 -1
- package/dist/agent.d.ts +12 -2
- package/dist/api.d.ts +23 -7
- package/dist/events.d.ts +17 -1
- package/dist/index.js +282 -106
- package/dist/index.js.map +1 -1
- package/dist/operational-report.d.ts +2 -1
- package/dist/personal-store.d.ts +22 -11
- package/dist/personal.d.ts +5 -3
- package/dist/recall.d.ts +2 -1
- package/dist/store.d.ts +1 -0
- package/dist/user-pages.d.ts +2 -2
- package/package.json +2 -2
- package/src/agent.ts +26 -8
- package/src/api.ts +32 -9
- package/src/events.ts +53 -16
- package/src/operational-report.ts +37 -1
- package/src/personal-store.ts +108 -46
- package/src/personal.ts +14 -6
- package/src/plugin.ts +17 -2
- package/src/process-session.ts +39 -28
- package/src/recall.ts +52 -5
- package/src/store.ts +2 -0
- package/src/tools.ts +1 -0
- package/src/user-pages.ts +34 -23
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { PluginOperationalReportContent } from "@sentry/junior-plugin-api";
|
|
1
|
+
import type { PluginConversationEventCostDay, PluginOperationalReportContent } from "@sentry/junior-plugin-api";
|
|
2
2
|
import type { MemoryDb } from "./store";
|
|
3
3
|
/** Build aggregate memory storage and indexing diagnostics for the System page. */
|
|
4
4
|
export declare function buildMemoryOperationalReport(args: {
|
|
5
5
|
db: MemoryDb;
|
|
6
|
+
extractionDays: PluginConversationEventCostDay[];
|
|
6
7
|
nowMs: number;
|
|
7
8
|
}): Promise<PluginOperationalReportContent>;
|
package/dist/personal-store.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { type MemoryDb, type MemoryRecord } from "./store";
|
|
3
3
|
import { type MemoryRuntimeContext } from "./types";
|
|
4
|
+
declare const memoryVisibilitySchema: z.ZodEnum<{
|
|
5
|
+
public: "public";
|
|
6
|
+
private: "private";
|
|
7
|
+
}>;
|
|
4
8
|
declare const personalMemoryCursorSchema: z.ZodObject<{
|
|
5
9
|
createdAtMs: z.ZodNumber;
|
|
6
10
|
id: z.ZodString;
|
|
@@ -21,17 +25,23 @@ declare const personalMemoryPageInputSchema: z.ZodObject<{
|
|
|
21
25
|
explicit: "explicit";
|
|
22
26
|
}>>;
|
|
23
27
|
query: z.ZodOptional<z.ZodString>;
|
|
28
|
+
visibility: z.ZodOptional<z.ZodEnum<{
|
|
29
|
+
public: "public";
|
|
30
|
+
private: "private";
|
|
31
|
+
}>>;
|
|
24
32
|
}, z.core.$strict>;
|
|
25
33
|
export type PersonalMemoryCursor = z.output<typeof personalMemoryCursorSchema>;
|
|
26
34
|
export type PersonalMemoryPageInput = z.output<typeof personalMemoryPageInputSchema>;
|
|
35
|
+
export type MemoryVisibility = z.output<typeof memoryVisibilitySchema>;
|
|
27
36
|
export interface PersonalMemoryPage {
|
|
28
37
|
memories: PersonalMemoryRecord[];
|
|
29
38
|
nextCursor?: PersonalMemoryCursor;
|
|
30
39
|
}
|
|
31
|
-
/** Safe provenance attached to one viewer-
|
|
40
|
+
/** Safe provenance attached to one viewer-visible memory. */
|
|
32
41
|
export type PersonalMemoryRecord = MemoryRecord & {
|
|
33
42
|
origin: "automatic" | "explicit" | "other";
|
|
34
43
|
sourcePlatform: "local" | "slack";
|
|
44
|
+
visibility: MemoryVisibility;
|
|
35
45
|
};
|
|
36
46
|
/** Viewer-scoped active memory totals used by the dashboard. */
|
|
37
47
|
export interface PersonalMemoryStats {
|
|
@@ -41,36 +51,37 @@ export interface PersonalMemoryStats {
|
|
|
41
51
|
embedded: number;
|
|
42
52
|
explicit: number;
|
|
43
53
|
knowledge: number;
|
|
54
|
+
personal: number;
|
|
44
55
|
preference: number;
|
|
45
56
|
procedure: number;
|
|
57
|
+
public: number;
|
|
46
58
|
}
|
|
47
59
|
/** Viewer-scoped memory creation totals for one UTC calendar day. */
|
|
48
60
|
export interface PersonalMemoryDay {
|
|
49
61
|
date: string;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
procedure: number;
|
|
62
|
+
personal: number;
|
|
63
|
+
public: number;
|
|
53
64
|
}
|
|
54
65
|
/** Expected failure when a viewer does not own the requested memory. */
|
|
55
66
|
export declare class PersonalMemoryNotFoundError extends Error {
|
|
56
67
|
constructor();
|
|
57
68
|
}
|
|
58
|
-
/** Viewer-scoped
|
|
69
|
+
/** Viewer-scoped memory operations shared by dashboard and REST. */
|
|
59
70
|
export interface PersonalMemoryCollection {
|
|
60
71
|
/** Archive one exact personal memory owned by a linked actor. */
|
|
61
72
|
archive(id: string): Promise<MemoryRecord>;
|
|
62
|
-
/** Read one exact
|
|
63
|
-
get(id: string): Promise<
|
|
64
|
-
/** List one stable page across every
|
|
73
|
+
/** Read one exact memory visible to a linked actor. */
|
|
74
|
+
get(id: string): Promise<PersonalMemoryRecord>;
|
|
75
|
+
/** List one stable page across every authorized viewer scope. */
|
|
65
76
|
list(input: PersonalMemoryPageInput): Promise<PersonalMemoryPage>;
|
|
66
|
-
/** Summarize active memories across every
|
|
77
|
+
/** Summarize active memories across every authorized viewer scope. */
|
|
67
78
|
stats(): Promise<PersonalMemoryStats>;
|
|
68
|
-
/** Read memory creation history across every
|
|
79
|
+
/** Read memory creation history across every authorized viewer scope. */
|
|
69
80
|
timeline(input: {
|
|
70
81
|
days: number;
|
|
71
82
|
}): Promise<PersonalMemoryDay[]>;
|
|
72
83
|
}
|
|
73
|
-
/** Build storage operations for every
|
|
84
|
+
/** Build storage operations for every memory scope linked to one viewer. */
|
|
74
85
|
export declare function createPersonalMemoryCollection(db: MemoryDb, runtimeContexts: MemoryRuntimeContext[], options?: {
|
|
75
86
|
now?: () => number;
|
|
76
87
|
}): PersonalMemoryCollection;
|
package/dist/personal.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PluginUserPageActor } from "@sentry/junior-plugin-api";
|
|
2
|
-
import { type PersonalMemoryRecord } from "./personal-store";
|
|
2
|
+
import { type MemoryVisibility, type PersonalMemoryRecord } from "./personal-store";
|
|
3
3
|
import type { MemoryDb, MemoryRecord } from "./store";
|
|
4
4
|
import type { MemoryKind } from "./types";
|
|
5
5
|
export interface ViewerMemoryPage {
|
|
@@ -12,15 +12,17 @@ export interface ViewerMemoryPageInput {
|
|
|
12
12
|
limit: number;
|
|
13
13
|
origin?: "automatic" | "explicit";
|
|
14
14
|
query?: string;
|
|
15
|
+
visibility?: MemoryVisibility;
|
|
15
16
|
}
|
|
16
17
|
export declare class InvalidMemoryCursorError extends Error {
|
|
17
18
|
constructor();
|
|
18
19
|
}
|
|
19
20
|
export { PersonalMemoryNotFoundError } from "./personal-store";
|
|
20
|
-
|
|
21
|
+
export type { MemoryVisibility, PersonalMemoryRecord } from "./personal-store";
|
|
22
|
+
/** Build viewer memory operations authorized by a viewer's linked actors. */
|
|
21
23
|
export declare function createViewerMemories(db: MemoryDb, actors: PluginUserPageActor[]): {
|
|
22
24
|
archive(id: string): Promise<MemoryRecord>;
|
|
23
|
-
get(id: string): Promise<
|
|
25
|
+
get(id: string): Promise<PersonalMemoryRecord>;
|
|
24
26
|
list(input: ViewerMemoryPageInput): Promise<ViewerMemoryPage>;
|
|
25
27
|
stats(): Promise<import("./personal-store").PersonalMemoryStats>;
|
|
26
28
|
timeline(input: {
|
package/dist/recall.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type UserPromptContribution, type Actor, type PluginLogger, type Source } from "@sentry/junior-plugin-api";
|
|
1
|
+
import { type UserPromptContribution, type Actor, type PluginConversationEvents, type PluginLogger, type Source } from "@sentry/junior-plugin-api";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import type { MemoryAgent } from "./agent";
|
|
4
4
|
import { type MemoryDb, type MemoryEmbeddingProvider } from "./store";
|
|
@@ -7,6 +7,7 @@ export interface MemoryRecallContext {
|
|
|
7
7
|
conversationId?: string;
|
|
8
8
|
db: MemoryDb;
|
|
9
9
|
embedder?: MemoryEmbeddingProvider;
|
|
10
|
+
events?: PluginConversationEvents;
|
|
10
11
|
log: PluginLogger;
|
|
11
12
|
/** Maximum cosine distance for vector recall. Passed through to the memory store. */
|
|
12
13
|
maxVectorDistance?: number;
|
package/dist/store.d.ts
CHANGED
package/dist/user-pages.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Project viewer-
|
|
1
|
+
/** Project viewer-visible memories into Junior's core-rendered user page. */
|
|
2
2
|
import type { PluginUserPageDefinition } from "@sentry/junior-plugin-api";
|
|
3
|
-
/** Create the interactive
|
|
3
|
+
/** Create the interactive Memories dashboard page. */
|
|
4
4
|
export declare function createMemoryUserPage(): PluginUserPageDefinition;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/junior-memory",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.125.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.125.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^25.9.1",
|
package/src/agent.ts
CHANGED
|
@@ -199,18 +199,30 @@ export type ExtractSessionRequest = z.output<
|
|
|
199
199
|
>;
|
|
200
200
|
export type ExtractedMemory = z.output<typeof extractedMemoryResultSchema>;
|
|
201
201
|
|
|
202
|
+
/** Memories proposed by passive extraction and the model cost of that pass. */
|
|
203
|
+
export type MemoryExtractionResult = {
|
|
204
|
+
costUsd?: number;
|
|
205
|
+
memories: ExtractedMemory[];
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/** Memories admitted by automatic recall and the model cost of that decision. */
|
|
209
|
+
export type MemoryRecallResult = {
|
|
210
|
+
costUsd?: number;
|
|
211
|
+
relevantIds: string[];
|
|
212
|
+
};
|
|
213
|
+
|
|
202
214
|
export interface MemoryAgent {
|
|
203
215
|
/** Select candidate memories that directly help with the current request. */
|
|
204
216
|
selectRelevantMemories(
|
|
205
217
|
request: MemoryRecallInput,
|
|
206
|
-
): Promise<
|
|
218
|
+
): Promise<MemoryRecallResult> | MemoryRecallResult;
|
|
207
219
|
/** Classify a new preference against related active preferences. */
|
|
208
220
|
adjudicateSupersession(
|
|
209
221
|
request: MemorySupersessionInput,
|
|
210
222
|
): Promise<MemorySupersessionDecision> | MemorySupersessionDecision;
|
|
211
223
|
extractSessionMemories(
|
|
212
224
|
request: ExtractSessionRequest,
|
|
213
|
-
): Promise<
|
|
225
|
+
): Promise<MemoryExtractionResult> | MemoryExtractionResult;
|
|
214
226
|
reviewCreateRequest(
|
|
215
227
|
request: CreateMemoryRequest,
|
|
216
228
|
): Promise<MemoryReview> | MemoryReview;
|
|
@@ -540,9 +552,12 @@ export function createMemoryAgent(model: PluginModel): MemoryAgent {
|
|
|
540
552
|
});
|
|
541
553
|
const decision = memoryRecallDecisionSchema.parse(result.object);
|
|
542
554
|
const candidateIds = new Set(request.candidates.map(({ id }) => id));
|
|
543
|
-
return
|
|
544
|
-
|
|
545
|
-
|
|
555
|
+
return {
|
|
556
|
+
relevantIds: [...new Set(decision.relevantIds)].filter((id) =>
|
|
557
|
+
candidateIds.has(id),
|
|
558
|
+
),
|
|
559
|
+
...(result.costUsd !== undefined ? { costUsd: result.costUsd } : {}),
|
|
560
|
+
};
|
|
546
561
|
},
|
|
547
562
|
async adjudicateSupersession(rawRequest) {
|
|
548
563
|
const request = memorySupersessionInputSchema.parse(rawRequest);
|
|
@@ -562,9 +577,12 @@ export function createMemoryAgent(model: PluginModel): MemoryAgent {
|
|
|
562
577
|
prompt: sessionExtractionPrompt(request),
|
|
563
578
|
maxTokens: 1_000,
|
|
564
579
|
});
|
|
565
|
-
return
|
|
566
|
-
|
|
567
|
-
|
|
580
|
+
return {
|
|
581
|
+
memories: extractedMemoriesFromResponse(
|
|
582
|
+
extractMemoriesResponseSchema.parse(result.object),
|
|
583
|
+
),
|
|
584
|
+
...(result.costUsd !== undefined ? { costUsd: result.costUsd } : {}),
|
|
585
|
+
};
|
|
568
586
|
},
|
|
569
587
|
async reviewCreateRequest(rawRequest) {
|
|
570
588
|
const request = parseCreateMemoryRequest(rawRequest);
|
package/src/api.ts
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Authenticated REST resources for
|
|
2
|
+
* Authenticated REST resources for viewer-visible memories.
|
|
3
3
|
*
|
|
4
4
|
* HTTP identity is one verified viewer. Linked platform actors are resolved
|
|
5
|
-
* behind the route boundary and used only to authorize personal
|
|
5
|
+
* behind the route boundary and used only to authorize personal and public
|
|
6
|
+
* workspace scopes.
|
|
6
7
|
*/
|
|
7
8
|
import { z } from "zod";
|
|
8
9
|
import {
|
|
9
10
|
pluginApiRouteRequestContextSchema,
|
|
11
|
+
type PluginConversationEventStats,
|
|
10
12
|
type PluginApiRouteRequestContext,
|
|
11
13
|
type PluginRouteApp,
|
|
12
14
|
type PluginUserPageActor,
|
|
13
15
|
} from "@sentry/junior-plugin-api";
|
|
14
|
-
import type { MemoryDb
|
|
16
|
+
import type { MemoryDb } from "./store";
|
|
15
17
|
import {
|
|
16
18
|
createViewerMemories,
|
|
17
19
|
InvalidMemoryCursorError,
|
|
18
20
|
PersonalMemoryNotFoundError,
|
|
21
|
+
type PersonalMemoryRecord,
|
|
19
22
|
} from "./personal";
|
|
20
23
|
|
|
21
24
|
export const memoryApiSchema = z
|
|
@@ -26,6 +29,7 @@ export const memoryApiSchema = z
|
|
|
26
29
|
id: z.string().min(1),
|
|
27
30
|
kind: z.enum(["preference", "procedure", "knowledge"]),
|
|
28
31
|
observedAt: z.iso.datetime(),
|
|
32
|
+
visibility: z.enum(["private", "public"]),
|
|
29
33
|
})
|
|
30
34
|
.strict();
|
|
31
35
|
|
|
@@ -39,15 +43,23 @@ export const memoryListResponseSchema = z
|
|
|
39
43
|
const memoryDashboardDaySchema = z
|
|
40
44
|
.object({
|
|
41
45
|
date: z.iso.date(),
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
personal: z.number().int().min(0),
|
|
47
|
+
public: z.number().int().min(0),
|
|
48
|
+
})
|
|
49
|
+
.strict();
|
|
50
|
+
|
|
51
|
+
const memoryExtractionDaySchema = z
|
|
52
|
+
.object({
|
|
53
|
+
costUsd: z.number().finite().nonnegative(),
|
|
54
|
+
date: z.iso.date(),
|
|
55
|
+
events: z.number().int().min(0),
|
|
45
56
|
})
|
|
46
57
|
.strict();
|
|
47
58
|
|
|
48
59
|
export const memoryDashboardResponseSchema = z
|
|
49
60
|
.object({
|
|
50
61
|
days: z.array(memoryDashboardDaySchema).length(90),
|
|
62
|
+
extractionDays: z.array(memoryExtractionDaySchema).length(90),
|
|
51
63
|
generatedAt: z.iso.datetime(),
|
|
52
64
|
stats: z
|
|
53
65
|
.object({
|
|
@@ -57,8 +69,10 @@ export const memoryDashboardResponseSchema = z
|
|
|
57
69
|
embedded: z.number().int().min(0),
|
|
58
70
|
explicit: z.number().int().min(0),
|
|
59
71
|
knowledge: z.number().int().min(0),
|
|
72
|
+
personal: z.number().int().min(0),
|
|
60
73
|
preference: z.number().int().min(0),
|
|
61
74
|
procedure: z.number().int().min(0),
|
|
75
|
+
public: z.number().int().min(0),
|
|
62
76
|
})
|
|
63
77
|
.strict(),
|
|
64
78
|
})
|
|
@@ -81,6 +95,7 @@ const memoryListQuerySchema = z
|
|
|
81
95
|
interface MemoryApiOptions {
|
|
82
96
|
actors(email: string): Promise<PluginUserPageActor[]>;
|
|
83
97
|
db: MemoryDb;
|
|
98
|
+
eventStats: PluginConversationEventStats;
|
|
84
99
|
}
|
|
85
100
|
|
|
86
101
|
function json(body: unknown, status = 200): Response {
|
|
@@ -90,7 +105,9 @@ function json(body: unknown, status = 200): Response {
|
|
|
90
105
|
});
|
|
91
106
|
}
|
|
92
107
|
|
|
93
|
-
function apiMemory(
|
|
108
|
+
function apiMemory(
|
|
109
|
+
memory: PersonalMemoryRecord,
|
|
110
|
+
): z.output<typeof memoryApiSchema> {
|
|
94
111
|
return {
|
|
95
112
|
content: memory.content,
|
|
96
113
|
createdAt: new Date(memory.createdAtMs).toISOString(),
|
|
@@ -100,6 +117,7 @@ function apiMemory(memory: MemoryRecord): z.output<typeof memoryApiSchema> {
|
|
|
100
117
|
id: memory.id,
|
|
101
118
|
kind: memory.kind,
|
|
102
119
|
observedAt: new Date(memory.observedAtMs).toISOString(),
|
|
120
|
+
visibility: memory.visibility,
|
|
103
121
|
};
|
|
104
122
|
}
|
|
105
123
|
|
|
@@ -113,7 +131,7 @@ function viewerEmail(
|
|
|
113
131
|
return parsed.data.auth.user.email?.trim().toLowerCase() || undefined;
|
|
114
132
|
}
|
|
115
133
|
|
|
116
|
-
/** Create the authenticated
|
|
134
|
+
/** Create the authenticated viewer-memory REST app. */
|
|
117
135
|
export function createMemoryApi(options: MemoryApiOptions): PluginRouteApp {
|
|
118
136
|
return {
|
|
119
137
|
async fetch(request, context) {
|
|
@@ -137,12 +155,17 @@ export function createMemoryApi(options: MemoryApiOptions): PluginRouteApp {
|
|
|
137
155
|
isDashboard &&
|
|
138
156
|
(request.method === "GET" || request.method === "HEAD")
|
|
139
157
|
) {
|
|
140
|
-
const [stats, days] = await Promise.all([
|
|
158
|
+
const [stats, days, extractionDays] = await Promise.all([
|
|
141
159
|
memories.stats(),
|
|
142
160
|
memories.timeline({ days: 90 }),
|
|
161
|
+
options.eventStats.costsByDay({
|
|
162
|
+
days: 90,
|
|
163
|
+
eventName: "memories_captured",
|
|
164
|
+
}),
|
|
143
165
|
]);
|
|
144
166
|
const body = memoryDashboardResponseSchema.parse({
|
|
145
167
|
days,
|
|
168
|
+
extractionDays,
|
|
146
169
|
generatedAt: new Date().toISOString(),
|
|
147
170
|
stats,
|
|
148
171
|
});
|
package/src/events.ts
CHANGED
|
@@ -21,8 +21,41 @@ function eventPreview(content: string): string {
|
|
|
21
21
|
return `${trimmed.slice(0, MAX_EVENT_PREVIEW_CHARS - 3).trimEnd()}...`;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
const capturedMemoriesSchema = z
|
|
25
|
+
.object({
|
|
26
|
+
memories: z.array(capturedMemorySchema).max(100),
|
|
27
|
+
costUsd: z.number().finite().nonnegative().optional(),
|
|
28
|
+
})
|
|
29
|
+
.strict();
|
|
30
|
+
|
|
31
|
+
const recalledMemoriesSchema = z
|
|
32
|
+
.object({
|
|
33
|
+
memories: z.array(z.string().min(1)).max(5),
|
|
34
|
+
costUsd: z.number().finite().nonnegative().optional(),
|
|
35
|
+
})
|
|
36
|
+
.strict();
|
|
37
|
+
|
|
38
|
+
function renderCapturedMemories(
|
|
39
|
+
event: z.output<typeof capturedMemoriesSchema>,
|
|
40
|
+
) {
|
|
41
|
+
const count = event.memories.length;
|
|
42
|
+
if (count === 0) return undefined;
|
|
43
|
+
return {
|
|
44
|
+
icon: "brain" as const,
|
|
45
|
+
title: count === 1 ? "Memory captured" : "Memories captured",
|
|
46
|
+
preview:
|
|
47
|
+
count === 1
|
|
48
|
+
? eventPreview(event.memories[0]!.content)
|
|
49
|
+
: `${count} memories`,
|
|
50
|
+
details: event.memories.map((memory) => ({
|
|
51
|
+
title: memory.content,
|
|
52
|
+
metadata: [memory.kind, memory.scope],
|
|
53
|
+
})),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Previous stored memory-capture event shape retained for transcript rendering. */
|
|
58
|
+
export const memoriesCapturedEventV1 = defineConversationEvent({
|
|
26
59
|
name: "memories_captured",
|
|
27
60
|
version: 1,
|
|
28
61
|
schema: z
|
|
@@ -30,20 +63,24 @@ export const memoriesCapturedEvent = defineConversationEvent({
|
|
|
30
63
|
memories: z.array(capturedMemorySchema).min(1).max(100),
|
|
31
64
|
})
|
|
32
65
|
.strict(),
|
|
33
|
-
renderEvent
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
66
|
+
renderEvent: renderCapturedMemories,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
/** Durable outcome emitted after every completed passive memory extraction. */
|
|
70
|
+
export const memoriesCapturedEvent = defineConversationEvent({
|
|
71
|
+
name: "memories_captured",
|
|
72
|
+
version: 2,
|
|
73
|
+
schema: capturedMemoriesSchema,
|
|
74
|
+
renderEvent: renderCapturedMemories,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
/** Durable outcome emitted after one completed automatic recall attempt. */
|
|
78
|
+
export const memoriesRecalledEvent = defineConversationEvent({
|
|
79
|
+
name: "memories_recalled",
|
|
80
|
+
version: 1,
|
|
81
|
+
schema: recalledMemoriesSchema,
|
|
82
|
+
renderEvent() {
|
|
83
|
+
return undefined;
|
|
47
84
|
},
|
|
48
85
|
});
|
|
49
86
|
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
PluginConversationEventCostDay,
|
|
3
|
+
PluginOperationalReportContent,
|
|
4
|
+
} from "@sentry/junior-plugin-api";
|
|
2
5
|
import { and, eq, gt, isNull, or, sql } from "drizzle-orm";
|
|
3
6
|
import { z } from "zod";
|
|
4
7
|
import { juniorMemoryEmbeddings, juniorMemoryMemories } from "./db/schema";
|
|
@@ -87,9 +90,20 @@ function formatPercent(value: number): string {
|
|
|
87
90
|
}).format(value);
|
|
88
91
|
}
|
|
89
92
|
|
|
93
|
+
function formatUsd(value: number): string {
|
|
94
|
+
const maximumFractionDigits = value > 0 && value < 0.01 ? 4 : 2;
|
|
95
|
+
return new Intl.NumberFormat("en-US", {
|
|
96
|
+
currency: "USD",
|
|
97
|
+
maximumFractionDigits,
|
|
98
|
+
minimumFractionDigits: 2,
|
|
99
|
+
style: "currency",
|
|
100
|
+
}).format(value);
|
|
101
|
+
}
|
|
102
|
+
|
|
90
103
|
/** Build aggregate memory storage and indexing diagnostics for the System page. */
|
|
91
104
|
export async function buildMemoryOperationalReport(args: {
|
|
92
105
|
db: MemoryDb;
|
|
106
|
+
extractionDays: PluginConversationEventCostDay[];
|
|
93
107
|
nowMs: number;
|
|
94
108
|
}): Promise<PluginOperationalReportContent> {
|
|
95
109
|
const active = and(
|
|
@@ -133,6 +147,11 @@ export async function buildMemoryOperationalReport(args: {
|
|
|
133
147
|
const activeCount = counts?.active ?? 0;
|
|
134
148
|
const embeddedCount = counts?.embedded ?? 0;
|
|
135
149
|
const embeddingCoverage = activeCount === 0 ? 0 : embeddedCount / activeCount;
|
|
150
|
+
const extractionThirtyDays = args.extractionDays.slice(-30);
|
|
151
|
+
const extractionCostThirtyDays = extractionThirtyDays.reduce(
|
|
152
|
+
(total, day) => total + day.costUsd,
|
|
153
|
+
0,
|
|
154
|
+
);
|
|
136
155
|
|
|
137
156
|
return {
|
|
138
157
|
generatedAt: new Date(args.nowMs).toISOString(),
|
|
@@ -143,6 +162,10 @@ export async function buildMemoryOperationalReport(args: {
|
|
|
143
162
|
tone: activeCount > 0 ? "good" : "neutral",
|
|
144
163
|
value: formatCount(activeCount),
|
|
145
164
|
},
|
|
165
|
+
{
|
|
166
|
+
label: "extraction cost · 30d",
|
|
167
|
+
value: formatUsd(extractionCostThirtyDays),
|
|
168
|
+
},
|
|
146
169
|
{
|
|
147
170
|
label: "created · 30d",
|
|
148
171
|
value: formatCount(counts?.createdThirtyDays ?? 0),
|
|
@@ -167,6 +190,19 @@ export async function buildMemoryOperationalReport(args: {
|
|
|
167
190
|
},
|
|
168
191
|
],
|
|
169
192
|
widgets: [
|
|
193
|
+
{
|
|
194
|
+
categories: args.extractionDays.map((day) => ({
|
|
195
|
+
id: day.date,
|
|
196
|
+
label: day.date,
|
|
197
|
+
values: { costUsd: day.costUsd },
|
|
198
|
+
})),
|
|
199
|
+
description: "Estimated model cost of passive memory extraction",
|
|
200
|
+
id: "extraction-cost",
|
|
201
|
+
series: [{ format: "usd", key: "costUsd", label: "Cost" }],
|
|
202
|
+
timeRangeDays: [...WINDOWS],
|
|
203
|
+
title: "Extraction cost",
|
|
204
|
+
type: "bar_chart",
|
|
205
|
+
},
|
|
170
206
|
{
|
|
171
207
|
categories: memoryDays.map((day) => ({
|
|
172
208
|
id: day.date,
|