@sentry/junior-memory 0.117.0 → 0.118.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/store.d.ts CHANGED
@@ -166,6 +166,8 @@ export interface MemoryStore {
166
166
  createConversationMemory(input: CreateMemoryInput): Promise<CreateMemoryResult>;
167
167
  /** List active memories visible in the current runtime context. */
168
168
  listMemories(input: ListMemoriesInput): Promise<MemoryRecord[]>;
169
+ /** List active personal memories owned by the current actor. */
170
+ listPersonalMemories(input: ListMemoriesInput): Promise<MemoryRecord[]>;
169
171
  /** Search active memories visible in the current runtime context. */
170
172
  searchMemories(input: SearchMemoriesInput): Promise<MemoryRecord[]>;
171
173
  }
@@ -0,0 +1,4 @@
1
+ /** Project actor-owned memories into Junior's core-rendered user page. */
2
+ import type { PluginUserPageDefinition } from "@sentry/junior-plugin-api";
3
+ /** Create the read-only personal Memories dashboard page. */
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.117.0",
3
+ "version": "0.118.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.117.0"
30
+ "@sentry/junior-plugin-api": "0.118.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^25.9.1",
package/src/plugin.ts CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  import { processMemorySession } from "./process-session";
14
14
  import { createMemoryPromptContributions } from "./recall";
15
15
  import type { MemoryDb } from "./store";
16
+ import { createMemoryUserPage } from "./user-pages";
16
17
 
17
18
  const MEMORY_MODEL_ENV = "AI_MEMORY_MODEL";
18
19
  const MEMORY_RECALL_MAX_VECTOR_DISTANCE_ENV =
@@ -107,6 +108,7 @@ export function createMemoryPlugin(options: MemoryPluginOptions = {}) {
107
108
  },
108
109
  },
109
110
  },
111
+ userPages: [createMemoryUserPage()],
110
112
  hooks: {
111
113
  tools(ctx) {
112
114
  const agent = createMemoryAgent(ctx.model);
package/src/store.ts CHANGED
@@ -324,6 +324,8 @@ export interface MemoryStore {
324
324
  ): Promise<CreateMemoryResult>;
325
325
  /** List active memories visible in the current runtime context. */
326
326
  listMemories(input: ListMemoriesInput): Promise<MemoryRecord[]>;
327
+ /** List active personal memories owned by the current actor. */
328
+ listPersonalMemories(input: ListMemoriesInput): Promise<MemoryRecord[]>;
327
329
  /** Search active memories visible in the current runtime context. */
328
330
  searchMemories(input: SearchMemoriesInput): Promise<MemoryRecord[]>;
329
331
  }
@@ -1468,6 +1470,23 @@ export function createMemoryStore(
1468
1470
  });
1469
1471
  },
1470
1472
 
1473
+ async listPersonalMemories(input) {
1474
+ input = listMemoriesInputSchema.parse(input);
1475
+ const nowMs = getNowMs();
1476
+ const scopes = [deriveMemoryScope(runtimeContext, "personal")];
1477
+ await archiveExpiredMemoryBatch({
1478
+ db,
1479
+ nowMs,
1480
+ scopes,
1481
+ });
1482
+ return await listVisibleMemories({
1483
+ db,
1484
+ limit: input.limit,
1485
+ nowMs,
1486
+ scopes,
1487
+ });
1488
+ },
1489
+
1471
1490
  async searchMemories(input) {
1472
1491
  input = searchMemoriesInputSchema.parse(input);
1473
1492
  const nowMs = getNowMs();
@@ -0,0 +1,94 @@
1
+ /** Project actor-owned memories into Junior's core-rendered user page. */
2
+ import type {
3
+ PluginUserPageActor,
4
+ PluginUserPageDefinition,
5
+ } from "@sentry/junior-plugin-api";
6
+ import { createMemoryStore, type MemoryDb, type MemoryRecord } from "./store";
7
+ import type { MemoryRuntimeContext } from "./types";
8
+
9
+ const MEMORY_PAGE_LIMIT = 100;
10
+
11
+ function runtimeContext(
12
+ actor: PluginUserPageActor,
13
+ ): MemoryRuntimeContext | undefined {
14
+ if (actor.platform === "slack") {
15
+ return {
16
+ actor,
17
+ source: {
18
+ platform: "slack",
19
+ type: "priv",
20
+ teamId: actor.teamId,
21
+ channelId: "DDASHBOARD",
22
+ },
23
+ };
24
+ }
25
+ return {
26
+ actor,
27
+ source: {
28
+ platform: "local",
29
+ type: "priv",
30
+ conversationId: "local:dashboard:memories",
31
+ },
32
+ };
33
+ }
34
+
35
+ function memoryKindLabel(kind: MemoryRecord["kind"]): string {
36
+ return kind.charAt(0).toUpperCase() + kind.slice(1);
37
+ }
38
+
39
+ function rememberedDate(createdAtMs: number): string {
40
+ return new Intl.DateTimeFormat("en-US", {
41
+ dateStyle: "medium",
42
+ timeZone: "UTC",
43
+ }).format(new Date(createdAtMs));
44
+ }
45
+
46
+ async function readPersonalMemories(
47
+ db: MemoryDb,
48
+ actors: PluginUserPageActor[],
49
+ ): Promise<MemoryRecord[]> {
50
+ const memories = await Promise.all(
51
+ actors.flatMap((actor) => {
52
+ const context = runtimeContext(actor);
53
+ return context
54
+ ? [
55
+ createMemoryStore(db, context).listPersonalMemories({
56
+ limit: MEMORY_PAGE_LIMIT,
57
+ }),
58
+ ]
59
+ : [];
60
+ }),
61
+ );
62
+ return [
63
+ ...new Map(memories.flat().map((memory) => [memory.id, memory])).values(),
64
+ ]
65
+ .sort((left, right) => right.createdAtMs - left.createdAtMs)
66
+ .slice(0, MEMORY_PAGE_LIMIT);
67
+ }
68
+
69
+ /** Create the read-only personal Memories dashboard page. */
70
+ export function createMemoryUserPage(): PluginUserPageDefinition {
71
+ return {
72
+ id: "memories",
73
+ label: "Memories",
74
+ description: "Personal facts and preferences Junior remembers about you.",
75
+ async read(ctx) {
76
+ const memories = await readPersonalMemories(
77
+ ctx.db as MemoryDb,
78
+ ctx.viewer.actors,
79
+ );
80
+ return {
81
+ type: "list",
82
+ emptyText: "No personal memories yet.",
83
+ records: memories.map((memory) => ({
84
+ id: memory.id,
85
+ title: memory.content,
86
+ metadata: [
87
+ { label: "Type", value: memoryKindLabel(memory.kind) },
88
+ { label: "Remembered", value: rememberedDate(memory.createdAtMs) },
89
+ ],
90
+ })),
91
+ };
92
+ },
93
+ };
94
+ }