@sentry/junior-memory 0.147.0 → 0.149.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/agent.d.ts CHANGED
@@ -26,6 +26,12 @@ declare const createMemoryRequestSchema: z.ZodObject<{
26
26
  fullName: z.ZodOptional<z.ZodString>;
27
27
  userId: z.ZodString;
28
28
  userName: z.ZodOptional<z.ZodString>;
29
+ }, z.core.$strict>, z.ZodObject<{
30
+ platform: z.ZodLiteral<"web">;
31
+ email: z.ZodOptional<z.ZodString>;
32
+ fullName: z.ZodOptional<z.ZodString>;
33
+ userId: z.ZodString;
34
+ userName: z.ZodOptional<z.ZodString>;
29
35
  }, z.core.$strict>, z.ZodObject<{
30
36
  platform: z.ZodLiteral<"system">;
31
37
  name: z.ZodString;
@@ -44,6 +50,13 @@ declare const createMemoryRequestSchema: z.ZodObject<{
44
50
  platform: z.ZodLiteral<"local">;
45
51
  visibility: z.ZodLiteral<"private">;
46
52
  conversationId: z.ZodString;
53
+ }, z.core.$strict>, z.ZodObject<{
54
+ platform: z.ZodLiteral<"web">;
55
+ visibility: z.ZodEnum<{
56
+ public: "public";
57
+ private: "private";
58
+ }>;
59
+ conversationId: z.ZodString;
47
60
  }, z.core.$strict>], "platform">;
48
61
  }, z.core.$strict>;
49
62
  sourceContext: z.ZodOptional<z.ZodObject<{
@@ -67,6 +80,12 @@ declare const extractSessionRequestSchema: z.ZodObject<{
67
80
  fullName: z.ZodOptional<z.ZodString>;
68
81
  userId: z.ZodString;
69
82
  userName: z.ZodOptional<z.ZodString>;
83
+ }, z.core.$strict>, z.ZodObject<{
84
+ platform: z.ZodLiteral<"web">;
85
+ email: z.ZodOptional<z.ZodString>;
86
+ fullName: z.ZodOptional<z.ZodString>;
87
+ userId: z.ZodString;
88
+ userName: z.ZodOptional<z.ZodString>;
70
89
  }, z.core.$strict>, z.ZodObject<{
71
90
  platform: z.ZodLiteral<"system">;
72
91
  name: z.ZodString;
@@ -86,6 +105,12 @@ declare const extractSessionRequestSchema: z.ZodObject<{
86
105
  fullName: z.ZodOptional<z.ZodString>;
87
106
  userId: z.ZodString;
88
107
  userName: z.ZodOptional<z.ZodString>;
108
+ }, z.core.$strict>, z.ZodObject<{
109
+ platform: z.ZodLiteral<"web">;
110
+ email: z.ZodOptional<z.ZodString>;
111
+ fullName: z.ZodOptional<z.ZodString>;
112
+ userId: z.ZodString;
113
+ userName: z.ZodOptional<z.ZodString>;
89
114
  }, z.core.$strict>, z.ZodObject<{
90
115
  platform: z.ZodLiteral<"system">;
91
116
  name: z.ZodString;
@@ -104,6 +129,13 @@ declare const extractSessionRequestSchema: z.ZodObject<{
104
129
  platform: z.ZodLiteral<"local">;
105
130
  visibility: z.ZodLiteral<"private">;
106
131
  conversationId: z.ZodString;
132
+ }, z.core.$strict>, z.ZodObject<{
133
+ platform: z.ZodLiteral<"web">;
134
+ visibility: z.ZodEnum<{
135
+ public: "public";
136
+ private: "private";
137
+ }>;
138
+ conversationId: z.ZodString;
107
139
  }, z.core.$strict>], "platform">;
108
140
  }, z.core.$strict>;
109
141
  transcript: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -131,6 +163,12 @@ declare const extractSessionRequestSchema: z.ZodObject<{
131
163
  fullName: z.ZodOptional<z.ZodString>;
132
164
  userId: z.ZodString;
133
165
  userName: z.ZodOptional<z.ZodString>;
166
+ }, z.core.$strict>, z.ZodObject<{
167
+ platform: z.ZodLiteral<"web">;
168
+ email: z.ZodOptional<z.ZodString>;
169
+ fullName: z.ZodOptional<z.ZodString>;
170
+ userId: z.ZodString;
171
+ userName: z.ZodOptional<z.ZodString>;
134
172
  }, z.core.$strict>, z.ZodObject<{
135
173
  platform: z.ZodLiteral<"system">;
136
174
  name: z.ZodString;
package/dist/api.d.ts CHANGED
@@ -26,6 +26,7 @@ export declare const memoryApiSchema: z.ZodObject<{
26
26
  sourcePlatform: z.ZodEnum<{
27
27
  slack: "slack";
28
28
  local: "local";
29
+ web: "web";
29
30
  }>;
30
31
  visibility: z.ZodEnum<{
31
32
  public: "public";
@@ -52,6 +53,7 @@ export declare const memoryListResponseSchema: z.ZodObject<{
52
53
  sourcePlatform: z.ZodEnum<{
53
54
  slack: "slack";
54
55
  local: "local";
56
+ web: "web";
55
57
  }>;
56
58
  visibility: z.ZodEnum<{
57
59
  public: "public";
@@ -147,14 +147,14 @@ export declare const juniorMemoryMemories: import("drizzle-orm/pg-core").PgTable
147
147
  tableName: "junior_memory_memories";
148
148
  dataType: "string";
149
149
  columnType: "PgText";
150
- data: "slack" | "local";
150
+ data: "slack" | "local" | "web";
151
151
  driverParam: string;
152
152
  notNull: true;
153
153
  hasDefault: false;
154
154
  isPrimaryKey: false;
155
155
  isAutoincrement: false;
156
156
  hasRuntimeDefault: false;
157
- enumValues: ["slack", "local"];
157
+ enumValues: ["slack", "local", "web"];
158
158
  baseColumn: never;
159
159
  identity: undefined;
160
160
  generated: undefined;
package/dist/index.js CHANGED
@@ -2,7 +2,9 @@
2
2
  import { defineJuniorPlugin } from "@sentry/junior-plugin-api";
3
3
 
4
4
  // src/agent.ts
5
- import { actorSchema as actorSchema2 } from "@sentry/junior-plugin-api";
5
+ import {
6
+ actorSchema as actorSchema2
7
+ } from "@sentry/junior-plugin-api";
6
8
  import { z as z3 } from "zod";
7
9
 
8
10
  // src/store.ts
@@ -39,10 +41,7 @@ import {
39
41
  } from "drizzle-orm/pg-core";
40
42
 
41
43
  // src/types.ts
42
- import {
43
- actorSchema,
44
- sourceSchema
45
- } from "@sentry/junior-plugin-api";
44
+ import { actorSchema, sourceSchema } from "@sentry/junior-plugin-api";
46
45
  import { z } from "zod";
47
46
  var MEMORY_KINDS = ["preference", "procedure", "knowledge"];
48
47
  var MEMORY_SCOPES = ["personal", "conversation"];
@@ -51,10 +50,7 @@ var MEMORY_SUBJECT_TYPES = [
51
50
  "conversation",
52
51
  "general"
53
52
  ];
54
- var MEMORY_SOURCE_PLATFORMS = [
55
- "slack",
56
- "local"
57
- ];
53
+ var MEMORY_SOURCE_PLATFORMS = ["slack", "local", "web"];
58
54
  var MEMORY_EMBEDDING_METRICS = ["cosine"];
59
55
  var MEMORY_EMBEDDING_DIMENSIONS = 1536;
60
56
  var nonEmptyStringSchema = z.string().min(1);
@@ -131,7 +127,7 @@ var juniorMemoryMemories = pgTable(
131
127
  ),
132
128
  check(
133
129
  "junior_memory_memories_source_platform_check",
134
- sql`${table.sourcePlatform} IN ('slack', 'local')`
130
+ sql`${table.sourcePlatform} IN ('slack', 'local', 'web')`
135
131
  )
136
132
  ]
137
133
  );
@@ -235,7 +231,6 @@ function rankMemoryMatches(matches, options) {
235
231
  }
236
232
 
237
233
  // src/scope.ts
238
- import { isPrivateSource } from "@sentry/junior-plugin-api";
239
234
  function uniqueScopes(scopes) {
240
235
  return [
241
236
  ...new Map(
@@ -243,25 +238,31 @@ function uniqueScopes(scopes) {
243
238
  ).values()
244
239
  ];
245
240
  }
241
+ function personalScopeFromIdentity(identity) {
242
+ if (identity.provider === "local") {
243
+ return {
244
+ scope: "personal",
245
+ scopeKey: `local:${identity.providerSubjectId}`
246
+ };
247
+ }
248
+ if (identity.provider === "junior") {
249
+ return {
250
+ scope: "personal",
251
+ scopeKey: `junior:${identity.providerSubjectId}`
252
+ };
253
+ }
254
+ if (identity.provider === "slack" && identity.providerTenantId) {
255
+ return {
256
+ scope: "personal",
257
+ scopeKey: `slack:${identity.providerTenantId}:${identity.providerSubjectId}`
258
+ };
259
+ }
260
+ return void 0;
261
+ }
246
262
  function deriveViewerMemoryScopes(identities) {
247
263
  const privateScopes = identities.flatMap((identity) => {
248
- if (identity.provider === "local") {
249
- return [
250
- {
251
- scope: "personal",
252
- scopeKey: `local:${identity.providerSubjectId}`
253
- }
254
- ];
255
- }
256
- if (identity.provider === "slack" && identity.providerTenantId) {
257
- return [
258
- {
259
- scope: "personal",
260
- scopeKey: `slack:${identity.providerTenantId}:${identity.providerSubjectId}`
261
- }
262
- ];
263
- }
264
- return [];
264
+ const scope = personalScopeFromIdentity(identity);
265
+ return scope ? [scope] : [];
265
266
  });
266
267
  const publicScopes = identities.flatMap(
267
268
  (identity) => identity.provider === "slack" && identity.providerTenantId ? [
@@ -276,38 +277,49 @@ function deriveViewerMemoryScopes(identities) {
276
277
  publicScopes: uniqueScopes(publicScopes)
277
278
  };
278
279
  }
279
- function sourceConversationKey(ctx) {
280
- if (ctx.source.platform === "local") {
281
- return ctx.source.conversationId;
282
- }
283
- if (!isPrivateSource(ctx.source)) {
284
- return `slack:${ctx.source.teamId}`;
285
- }
286
- const threadKey = ctx.source.threadTs ?? ctx.source.messageTs;
287
- if (!threadKey) {
288
- return void 0;
280
+ function sourceConversationKey(source) {
281
+ switch (source.platform) {
282
+ case "web":
283
+ case "local":
284
+ return source.conversationId;
285
+ case "slack": {
286
+ if (source.visibility === "public") {
287
+ return `slack:${source.teamId}`;
288
+ }
289
+ const threadKey = source.threadTs ?? source.messageTs;
290
+ if (!threadKey) {
291
+ return void 0;
292
+ }
293
+ return `slack:${source.teamId}:${source.channelId}:${threadKey}`;
294
+ }
289
295
  }
290
- return `slack:${ctx.source.teamId}:${ctx.source.channelId}:${threadKey}`;
291
296
  }
292
- function actorScopeKey(ctx) {
293
- const actor = ctx.actor;
294
- if (!actor || actor.platform === "system") {
297
+ function actorScopeKey(actor) {
298
+ if (!actor) {
295
299
  return void 0;
296
300
  }
297
- if (actor.platform === "slack") {
298
- return `slack:${actor.teamId}:${actor.userId}`;
301
+ switch (actor.platform) {
302
+ case "system":
303
+ return void 0;
304
+ case "slack":
305
+ return `slack:${actor.teamId}:${actor.userId}`;
306
+ case "local":
307
+ return `local:${actor.userId}`;
308
+ case "web": {
309
+ const email = actor.email?.trim().toLowerCase();
310
+ return email ? `junior:${email}` : void 0;
311
+ }
299
312
  }
300
- return `local:${actor.userId}`;
301
313
  }
302
314
  function deriveMemoryScope(ctx, scope) {
303
315
  if (scope === "personal") {
304
- const scopeKey2 = actorScopeKey(ctx);
316
+ const scopeKey2 = actorScopeKey(ctx.actor);
305
317
  if (!scopeKey2) {
306
318
  throw new Error("Personal memory requires actor context.");
307
319
  }
308
320
  return { scope, scopeKey: scopeKey2 };
309
321
  }
310
- const scopeKey = sourceConversationKey(ctx);
322
+ const scopeKey = sourceConversationKey(ctx.source);
311
323
  if (!scopeKey) {
312
324
  throw new Error("Conversation memory requires conversation context.");
313
325
  }
@@ -315,13 +327,13 @@ function deriveMemoryScope(ctx, scope) {
315
327
  }
316
328
  function deriveMemorySubject(ctx, scope) {
317
329
  if (scope.scope === "personal") {
318
- const subjectKey2 = actorScopeKey(ctx);
330
+ const subjectKey2 = actorScopeKey(ctx.actor);
319
331
  if (!subjectKey2) {
320
332
  throw new Error("User-subject memory requires actor context.");
321
333
  }
322
334
  return { subjectType: "user", subjectKey: subjectKey2 };
323
335
  }
324
- const subjectKey = sourceConversationKey(ctx);
336
+ const subjectKey = sourceConversationKey(ctx.source);
325
337
  if (!subjectKey) {
326
338
  throw new Error(
327
339
  "Conversation-subject memory requires conversation context."
@@ -503,23 +515,40 @@ function boundedLimit(value, fallback) {
503
515
  }
504
516
  return Math.min(200, Math.max(1, Math.floor(value)));
505
517
  }
506
- function sourceKey(ctx) {
507
- if (ctx.source.platform === "local") {
508
- return ctx.source.conversationId;
518
+ function memorySourcePlatform(source) {
519
+ switch (source.platform) {
520
+ case "slack":
521
+ return "slack";
522
+ case "local":
523
+ return "local";
524
+ case "web":
525
+ return "web";
509
526
  }
510
- const threadKey = ctx.source.threadTs ?? ctx.source.messageTs;
511
- if (!threadKey) {
512
- throw new Error(
513
- "Memory source requires a Slack message or thread timestamp."
514
- );
527
+ }
528
+ function sourceKey(ctx) {
529
+ switch (ctx.source.platform) {
530
+ case "web":
531
+ case "local":
532
+ return ctx.source.conversationId;
533
+ case "slack": {
534
+ const threadKey = ctx.source.threadTs ?? ctx.source.messageTs;
535
+ if (!threadKey) {
536
+ throw new Error(
537
+ "Memory source requires a Slack message or thread timestamp."
538
+ );
539
+ }
540
+ return `slack:${ctx.source.teamId}:${ctx.source.channelId}:${threadKey}`;
541
+ }
515
542
  }
516
- return `slack:${ctx.source.teamId}:${ctx.source.channelId}:${threadKey}`;
517
543
  }
518
544
  function sourceChannelPrefix(ctx) {
519
- if (ctx.source.platform !== "slack") {
520
- return void 0;
545
+ switch (ctx.source.platform) {
546
+ case "slack":
547
+ return `slack:${ctx.source.teamId}:${ctx.source.channelId}:`;
548
+ case "web":
549
+ case "local":
550
+ return void 0;
521
551
  }
522
- return `slack:${ctx.source.teamId}:${ctx.source.channelId}:`;
523
552
  }
524
553
  function parseMemoryRow(row) {
525
554
  const parsed = memoryRowSchema.parse(row);
@@ -784,7 +813,7 @@ async function rememberDuplicateIdempotency(args) {
784
813
  scope: args.scope.scope,
785
814
  scopeKey: args.scope.scopeKey,
786
815
  sourceKey: sourceKey(args.runtimeContext),
787
- sourcePlatform: args.runtimeContext.source.platform,
816
+ sourcePlatform: memorySourcePlatform(args.runtimeContext.source),
788
817
  subjectKey: args.subject.subjectKey,
789
818
  subjectType: args.subject.subjectType,
790
819
  supersededAtMs: args.nowMs,
@@ -1158,7 +1187,7 @@ function createMemoryStore(db, context, options = {}) {
1158
1187
  scope: scope.scope,
1159
1188
  scopeKey: scope.scopeKey,
1160
1189
  sourceKey: sourceKey(runtimeContext),
1161
- sourcePlatform: runtimeContext.source.platform,
1190
+ sourcePlatform: memorySourcePlatform(runtimeContext.source),
1162
1191
  subjectKey: subject.subjectKey,
1163
1192
  subjectType: subject.subjectType,
1164
1193
  kind: input.kind
@@ -1531,13 +1560,35 @@ var CANONICAL_CONTENT_RULES = [
1531
1560
  function escapeXml(value) {
1532
1561
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
1533
1562
  }
1563
+ function actorLabel(actor) {
1564
+ if (!actor) {
1565
+ return "none";
1566
+ }
1567
+ switch (actor.platform) {
1568
+ case "system":
1569
+ return `system:${actor.name}`;
1570
+ case "slack":
1571
+ return `slack:${actor.teamId}:${actor.userId}`;
1572
+ case "local":
1573
+ return `local:${actor.userId}`;
1574
+ case "web":
1575
+ return `web:${actor.userId}`;
1576
+ }
1577
+ }
1578
+ function sourceLabel(source) {
1579
+ switch (source.platform) {
1580
+ case "slack":
1581
+ return `slack:${source.teamId}:${source.channelId}`;
1582
+ case "web":
1583
+ case "local":
1584
+ return `${source.platform}:${source.conversationId}`;
1585
+ }
1586
+ }
1534
1587
  function runtimeDescription(request) {
1535
1588
  const runtime = request.runtimeContext;
1536
- const actor = runtime.actor?.platform === "slack" ? `slack:${runtime.actor.teamId}:${runtime.actor.userId}` : runtime.actor?.platform === "local" ? `local:${runtime.actor.userId}` : "none";
1537
- const source = runtime.source.platform === "slack" ? `slack:${runtime.source.teamId}:${runtime.source.channelId}` : `local:${runtime.source.conversationId}`;
1538
1589
  const lines = [
1539
- `- actor: ${escapeXml(actor)}`,
1540
- `- source: ${escapeXml(source)}`,
1590
+ `- actor: ${escapeXml(actorLabel(runtime.actor))}`,
1591
+ `- source: ${escapeXml(sourceLabel(runtime.source))}`,
1541
1592
  `- has_conversation: ${runtime.conversationId ? "true" : "false"}`,
1542
1593
  `- expires_at: ${request.expiresAtMs === void 0 ? "never" : escapeXml(new Date(request.expiresAtMs).toISOString())}`
1543
1594
  ];
@@ -1621,15 +1672,6 @@ function reviewPrompt(request) {
1621
1672
  ].filter((section) => section !== void 0);
1622
1673
  return sections.join("\n");
1623
1674
  }
1624
- function transcriptActorLabel(actor) {
1625
- if (!actor) {
1626
- return "none";
1627
- }
1628
- if (actor.platform === "system") {
1629
- return `system:${actor.name}`;
1630
- }
1631
- return actor.platform === "slack" ? `slack:${actor.teamId}:${actor.userId}` : `local:${actor.userId}`;
1632
- }
1633
1675
  function runTranscriptContext(request) {
1634
1676
  return [
1635
1677
  "<run-transcript>",
@@ -1643,7 +1685,7 @@ function runTranscriptContext(request) {
1643
1685
  }
1644
1686
  const authority = entry.provenance?.authority ?? "context";
1645
1687
  const isRunActor = entry.isRunActor === true;
1646
- const actor = transcriptActorLabel(entry.provenance?.actor);
1688
+ const actor = actorLabel(entry.provenance?.actor);
1647
1689
  return [
1648
1690
  `<message index="${index2}" role="${entry.role}" authority="${authority}" is_run_actor="${isRunActor ? "true" : "false"}" actor="${escapeXml(actor)}">`,
1649
1691
  escapeXml(entry.text),
@@ -2203,7 +2245,7 @@ var memoryApiSchema = z6.object({
2203
2245
  kind: z6.enum(["preference", "procedure", "knowledge"]),
2204
2246
  observedAt: z6.iso.datetime(),
2205
2247
  origin: z6.enum(["automatic", "explicit", "other"]),
2206
- sourcePlatform: z6.enum(["local", "slack"]),
2248
+ sourcePlatform: z6.enum(MEMORY_SOURCE_PLATFORMS),
2207
2249
  visibility: z6.enum(["private", "public"])
2208
2250
  }).strict();
2209
2251
  var memoryListResponseSchema = z6.object({
@@ -2885,8 +2927,7 @@ function createMemorySearchTool(context) {
2885
2927
  // src/process-session.ts
2886
2928
  import { createHash as createHash2 } from "crypto";
2887
2929
  import {
2888
- getSourceKey as getSourceKey2,
2889
- isPrivateSource as isPrivateSource2
2930
+ getSourceKey as getSourceKey2
2890
2931
  } from "@sentry/junior-plugin-api";
2891
2932
  import { z as z9 } from "zod";
2892
2933
 
@@ -2973,6 +3014,15 @@ var extractedMemoryCacheSchema = z9.union([
2973
3014
  }).strict(),
2974
3015
  z9.array(extractedMemorySchema2).max(5).transform((memories) => ({ memories }))
2975
3016
  ]);
3017
+ function allowsPassiveMemoryExtraction(source) {
3018
+ switch (source.platform) {
3019
+ case "local":
3020
+ return true;
3021
+ case "web":
3022
+ case "slack":
3023
+ return source.visibility === "public";
3024
+ }
3025
+ }
2976
3026
  function recordCapturedMemory(captured, result) {
2977
3027
  const supersededIds = new Set(result.supersededIds ?? []);
2978
3028
  for (let index2 = captured.length - 1; index2 >= 0; index2 -= 1) {
@@ -3060,7 +3110,7 @@ async function processMemorySession(context) {
3060
3110
  )) {
3061
3111
  return;
3062
3112
  }
3063
- if (run.source.platform !== "local" && isPrivateSource2(run.source)) {
3113
+ if (!allowsPassiveMemoryExtraction(run.source)) {
3064
3114
  return;
3065
3115
  }
3066
3116
  const sourceKey2 = getSourceKey2(run.source);