@sentry/junior-memory 0.89.0 → 0.90.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/tools.d.ts CHANGED
@@ -15,96 +15,147 @@ export interface MemoryToolContext {
15
15
  export interface MemoryCreateToolContext extends MemoryToolContext {
16
16
  supersessionDecider?: MemorySupersessionDecider;
17
17
  }
18
- type MemoryWriteToolInput = {
19
- content: string;
20
- expires_at?: string;
21
- };
22
18
  /** Create a tool that submits an explicit memory candidate for storage. */
23
- export declare function createMemoryCreateTool(context: MemoryCreateToolContext): {
24
- description: string;
25
- executionMode: string;
26
- inputSchema: import("@sinclair/typebox").TObject<{
27
- content: import("@sinclair/typebox").TString;
28
- expires_at: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
29
- }>;
30
- execute: (input: MemoryWriteToolInput, options: import("@sentry/junior-plugin-api").PluginToolExecuteOptions) => Promise<{
31
- ok: boolean;
19
+ export declare function createMemoryCreateTool(context: MemoryCreateToolContext): import("@sentry/junior-plugin-api").PluginToolDefinition<{
20
+ content: string;
21
+ expires_at?: string | undefined;
22
+ }, {
23
+ [x: string]: unknown;
24
+ ok: true;
25
+ status: "success";
26
+ target: string;
27
+ data: {
32
28
  created: boolean;
33
29
  memory: {
34
- expiresAtMs?: number | undefined;
35
30
  id: string;
36
31
  content: string;
37
- observedAtMs: number;
38
32
  createdAtMs: number;
33
+ observedAtMs: number;
34
+ expiresAtMs?: number | undefined;
39
35
  };
40
- }>;
41
- };
42
- /** Create a tool that archives a visible memory in the active context. */
43
- export declare function createMemoryRemoveTool(context: MemoryToolContext): {
44
- description: string;
45
- executionMode: string;
46
- inputSchema: import("@sinclair/typebox").TObject<{
47
- id: import("@sinclair/typebox").TString;
48
- }>;
49
- execute: (input: {
36
+ };
37
+ created: boolean;
38
+ memory: {
50
39
  id: string;
51
- }) => Promise<{
52
- ok: boolean;
40
+ content: string;
41
+ createdAtMs: number;
42
+ observedAtMs: number;
43
+ expiresAtMs?: number | undefined;
44
+ };
45
+ truncated?: boolean | undefined;
46
+ continuation?: {
47
+ arguments: Record<string, unknown>;
48
+ reason?: string | undefined;
49
+ } | undefined;
50
+ error?: string | {
51
+ kind: string;
52
+ message: string;
53
+ retryable?: boolean | undefined;
54
+ } | undefined;
55
+ }>;
56
+ /** Create a tool that archives a visible memory in the active context. */
57
+ export declare function createMemoryRemoveTool(context: MemoryToolContext): import("@sentry/junior-plugin-api").PluginToolDefinition<{
58
+ id: string;
59
+ }, {
60
+ [x: string]: unknown;
61
+ ok: true;
62
+ status: "success";
63
+ target: string;
64
+ data: {
53
65
  memory: {
54
- expiresAtMs?: number | undefined;
55
66
  id: string;
56
67
  content: string;
57
- observedAtMs: number;
58
68
  createdAtMs: number;
69
+ observedAtMs: number;
70
+ expiresAtMs?: number | undefined;
59
71
  };
60
- }>;
61
- };
62
- /** Create a tool that lists visible active memories in the active context. */
63
- export declare function createMemoryListTool(context: MemoryToolContext): {
64
- description: string;
65
- annotations: {
66
- readOnlyHint: boolean;
67
- destructiveHint: boolean;
68
72
  };
69
- inputSchema: import("@sinclair/typebox").TObject<{
70
- limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
71
- }>;
72
- execute: (input: {
73
- limit?: number;
74
- }) => Promise<{
75
- ok: boolean;
73
+ memory: {
74
+ id: string;
75
+ content: string;
76
+ createdAtMs: number;
77
+ observedAtMs: number;
78
+ expiresAtMs?: number | undefined;
79
+ };
80
+ truncated?: boolean | undefined;
81
+ continuation?: {
82
+ arguments: Record<string, unknown>;
83
+ reason?: string | undefined;
84
+ } | undefined;
85
+ error?: string | {
86
+ kind: string;
87
+ message: string;
88
+ retryable?: boolean | undefined;
89
+ } | undefined;
90
+ }>;
91
+ /** Create a tool that lists visible active memories in the active context. */
92
+ export declare function createMemoryListTool(context: MemoryToolContext): import("@sentry/junior-plugin-api").PluginToolDefinition<{
93
+ limit?: number | undefined;
94
+ }, {
95
+ [x: string]: unknown;
96
+ ok: true;
97
+ status: "success";
98
+ target: string;
99
+ data: {
76
100
  memories: {
77
- expiresAtMs?: number | undefined;
78
101
  id: string;
79
102
  content: string;
80
- observedAtMs: number;
81
103
  createdAtMs: number;
104
+ observedAtMs: number;
105
+ expiresAtMs?: number | undefined;
82
106
  }[];
83
- }>;
84
- };
85
- /** Create a tool that searches visible active memories in the active context. */
86
- export declare function createMemorySearchTool(context: MemoryToolContext): {
87
- description: string;
88
- annotations: {
89
- readOnlyHint: boolean;
90
- destructiveHint: boolean;
91
107
  };
92
- inputSchema: import("@sinclair/typebox").TObject<{
93
- query: import("@sinclair/typebox").TString;
94
- limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
95
- }>;
96
- execute: (input: {
97
- limit?: number;
98
- query: string;
99
- }) => Promise<{
100
- ok: boolean;
108
+ memories: {
109
+ id: string;
110
+ content: string;
111
+ createdAtMs: number;
112
+ observedAtMs: number;
113
+ expiresAtMs?: number | undefined;
114
+ }[];
115
+ truncated?: boolean | undefined;
116
+ continuation?: {
117
+ arguments: Record<string, unknown>;
118
+ reason?: string | undefined;
119
+ } | undefined;
120
+ error?: string | {
121
+ kind: string;
122
+ message: string;
123
+ retryable?: boolean | undefined;
124
+ } | undefined;
125
+ }>;
126
+ /** Create a tool that searches visible active memories in the active context. */
127
+ export declare function createMemorySearchTool(context: MemoryToolContext): import("@sentry/junior-plugin-api").PluginToolDefinition<{
128
+ query: string;
129
+ limit?: number | undefined;
130
+ }, {
131
+ [x: string]: unknown;
132
+ ok: true;
133
+ status: "success";
134
+ target: string;
135
+ data: {
101
136
  memories: {
102
- expiresAtMs?: number | undefined;
103
137
  id: string;
104
138
  content: string;
105
- observedAtMs: number;
106
139
  createdAtMs: number;
140
+ observedAtMs: number;
141
+ expiresAtMs?: number | undefined;
107
142
  }[];
108
- }>;
109
- };
110
- export {};
143
+ };
144
+ memories: {
145
+ id: string;
146
+ content: string;
147
+ createdAtMs: number;
148
+ observedAtMs: number;
149
+ expiresAtMs?: number | undefined;
150
+ }[];
151
+ truncated?: boolean | undefined;
152
+ continuation?: {
153
+ arguments: Record<string, unknown>;
154
+ reason?: string | undefined;
155
+ } | undefined;
156
+ error?: string | {
157
+ kind: string;
158
+ message: string;
159
+ retryable?: boolean | undefined;
160
+ } | undefined;
161
+ }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior-memory",
3
- "version": "0.89.0",
3
+ "version": "0.90.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.89.0"
30
+ "@sentry/junior-plugin-api": "0.90.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^25.9.1",
package/src/tools.ts CHANGED
@@ -1,12 +1,15 @@
1
- import { Type, type Static, type TSchema } from "@sinclair/typebox";
1
+ import { Type, type Static } from "@sinclair/typebox";
2
2
  import { Value } from "@sinclair/typebox/value";
3
3
  import {
4
+ definePluginTool,
4
5
  getSourceKey,
5
6
  PluginToolInputError,
6
- type PluginToolDefinition,
7
+ type PluginToolResult,
7
8
  type Source,
8
9
  type Requester,
10
+ pluginToolResultSchema,
9
11
  } from "@sentry/junior-plugin-api";
12
+ import { z } from "zod";
10
13
  import {
11
14
  createMemoryStore,
12
15
  type CreateMemoryInput,
@@ -227,69 +230,59 @@ function requireMemoryContent(value: string): string {
227
230
  return value;
228
231
  }
229
232
 
230
- type MemoryWriteToolInput = {
231
- content: string;
232
- expires_at?: string;
233
- };
234
-
235
- const createMemoryInputSchema = Type.Object(
236
- {
237
- content: Type.String({
238
- minLength: 1,
239
- maxLength: MAX_TOOL_CONTENT_CHARS,
240
- description:
233
+ const createMemoryInputSchema = z
234
+ .object({
235
+ content: z
236
+ .string()
237
+ .min(1)
238
+ .max(MAX_TOOL_CONTENT_CHARS)
239
+ .describe(
241
240
  "Self-contained public/shareable memory candidate. Include the subject in natural language when it matters; do not rely on surrounding chat context.",
242
- }),
243
- expires_at: Type.Optional(
244
- Type.String({
245
- minLength: 1,
246
- description:
247
- 'Expiration selector. Omit or use "never" when the memory should not expire, or use an exact ISO timestamp such as "2027-06-21T00:00:00Z".',
248
- }),
249
- ),
250
- },
251
- { additionalProperties: false },
252
- );
253
-
254
- const removeMemoryInputSchema = Type.Object(
255
- {
256
- id: Type.String({
257
- minLength: 1,
258
- description: "Memory id or unambiguous short id prefix to remove.",
259
- }),
260
- },
261
- { additionalProperties: false },
262
- );
263
-
264
- const listMemoriesInputSchema = Type.Object(
265
- {
266
- limit: Type.Optional(
267
- Type.Number({
268
- minimum: 1,
269
- maximum: 50,
270
- description: "Maximum number of visible memories to return.",
271
- }),
272
- ),
273
- },
274
- { additionalProperties: false },
275
- );
276
-
277
- const searchMemoriesInputSchema = Type.Object(
278
- {
279
- query: Type.String({
280
- minLength: 1,
281
- description: "Search query for visible memory content.",
282
- }),
283
- limit: Type.Optional(
284
- Type.Number({
285
- minimum: 1,
286
- maximum: 50,
287
- description: "Maximum number of matching memories to return.",
288
- }),
289
- ),
290
- },
291
- { additionalProperties: false },
292
- );
241
+ ),
242
+ expires_at: z
243
+ .string()
244
+ .min(1)
245
+ .describe(
246
+ 'Expiration selector. Omit or use "never" when the memory should not expire, or use an exact ISO timestamp such as "2027-06-21T00:00:00Z".',
247
+ )
248
+ .optional(),
249
+ })
250
+ .strict();
251
+
252
+ const removeMemoryInputSchema = z
253
+ .object({
254
+ id: z
255
+ .string()
256
+ .min(1)
257
+ .describe("Memory id or unambiguous short id prefix to remove."),
258
+ })
259
+ .strict();
260
+
261
+ const listMemoriesInputSchema = z
262
+ .object({
263
+ limit: z
264
+ .number()
265
+ .min(1)
266
+ .max(50)
267
+ .describe("Maximum number of visible memories to return.")
268
+ .optional(),
269
+ })
270
+ .strict();
271
+
272
+ const searchMemoriesInputSchema = z
273
+ .object({
274
+ query: z
275
+ .string()
276
+ .min(1)
277
+ .describe("Search query for visible memory content."),
278
+ limit: z
279
+ .number()
280
+ .min(1)
281
+ .max(50)
282
+ .describe("Maximum number of matching memories to return.")
283
+ .optional(),
284
+ })
285
+ .strict();
293
286
 
294
287
  const memoryToolProjectionSchema = Type.Object(
295
288
  {
@@ -303,17 +296,69 @@ const memoryToolProjectionSchema = Type.Object(
303
296
  );
304
297
  type MemoryToolProjection = Static<typeof memoryToolProjectionSchema>;
305
298
 
306
- function parseToolInput<T>(schema: TSchema, input: unknown): T {
307
- try {
308
- if (!Value.Check(schema, input)) {
309
- throw new Error("Input does not match memory tool schema.");
310
- }
311
- return Value.Parse(schema, input) as T;
312
- } catch (error) {
299
+ type MemoryStructuredToolResult<TData extends Record<string, unknown>> =
300
+ PluginToolResult &
301
+ TData & {
302
+ ok: true;
303
+ status: "success";
304
+ target: string;
305
+ data: TData;
306
+ };
307
+
308
+ const memoryProjectionOutputSchema = z.object({
309
+ id: z.string(),
310
+ content: z.string(),
311
+ createdAtMs: z.number(),
312
+ observedAtMs: z.number(),
313
+ expiresAtMs: z.number().optional(),
314
+ });
315
+
316
+ const memoryCreateDataOutputSchema = z.object({
317
+ created: z.boolean(),
318
+ memory: memoryProjectionOutputSchema,
319
+ });
320
+
321
+ const memorySingleDataOutputSchema = z.object({
322
+ memory: memoryProjectionOutputSchema,
323
+ });
324
+
325
+ const memoryManyDataOutputSchema = z.object({
326
+ memories: z.array(memoryProjectionOutputSchema),
327
+ });
328
+
329
+ const memoryCreateOutputSchema = pluginToolResultSchema.extend({
330
+ ok: z.literal(true),
331
+ status: z.literal("success"),
332
+ target: z.string(),
333
+ data: memoryCreateDataOutputSchema,
334
+ created: z.boolean(),
335
+ memory: memoryProjectionOutputSchema,
336
+ });
337
+
338
+ const memorySingleOutputSchema = pluginToolResultSchema.extend({
339
+ ok: z.literal(true),
340
+ status: z.literal("success"),
341
+ target: z.string(),
342
+ data: memorySingleDataOutputSchema,
343
+ memory: memoryProjectionOutputSchema,
344
+ });
345
+
346
+ const memoryManyOutputSchema = pluginToolResultSchema.extend({
347
+ ok: z.literal(true),
348
+ status: z.literal("success"),
349
+ target: z.string(),
350
+ data: memoryManyDataOutputSchema,
351
+ memories: z.array(memoryProjectionOutputSchema),
352
+ });
353
+
354
+ function parseMemoryToolInput<T>(schema: z.ZodType<T>, input: unknown): T {
355
+ const result = schema.safeParse(input);
356
+ if (!result.success) {
313
357
  throw new PluginToolInputError("Invalid memory tool input.", {
314
- cause: error,
358
+ cause: result.error,
315
359
  });
316
360
  }
361
+ return result.data;
317
362
  }
318
363
 
319
364
  function sourceIdempotencyKey(context: MemoryToolContext): string {
@@ -359,18 +404,29 @@ function compactMemory(memory: MemoryRecord): MemoryToolProjection {
359
404
  });
360
405
  }
361
406
 
407
+ function memoryToolResult<TData extends Record<string, unknown>>(
408
+ target: string,
409
+ data: TData,
410
+ ): MemoryStructuredToolResult<TData> {
411
+ return {
412
+ ok: true,
413
+ status: "success",
414
+ target,
415
+ data,
416
+ ...data,
417
+ };
418
+ }
419
+
362
420
  /** Create a tool that submits an explicit memory candidate for storage. */
363
421
  export function createMemoryCreateTool(context: MemoryCreateToolContext) {
364
- return {
422
+ return definePluginTool({
365
423
  description:
366
424
  "Explicit memory-write tool. Use only when the latest user message directly asks Junior to remember, store, save, or forget-and-replace a public/shareable fact. Do not use for ordinary statements like 'I prefer X', 'I use Y', or 'X goes before Y' unless the user also asks you to remember/store/save it; passive memory learning handles those after the visible reply. Pass one self-contained natural-language candidate preserving the user's explicit memory intent. Do not ask the user to rephrase ordinary first-person facts, and do not rewrite them into display-name or third-person wording. Do not include secrets, private personal details, medical/legal/financial/sensitive facts, or another person's personal preference, opinion, habit, identity, relationship, workflow, or private life. Runtime context derives actor, scope, source, and subject ids; the memory agent decides canonical stored content and memory kind, then the plugin derives storage target from kind.",
367
425
  executionMode: "sequential",
368
426
  inputSchema: createMemoryInputSchema,
427
+ outputSchema: memoryCreateOutputSchema,
369
428
  execute: async (input, options) => {
370
- const parsedInput = parseToolInput<MemoryWriteToolInput>(
371
- createMemoryInputSchema,
372
- input,
373
- );
429
+ const parsedInput = parseMemoryToolInput(createMemoryInputSchema, input);
374
430
  const toolCallId = requireToolCallId(options.toolCallId);
375
431
  const requestedExpiresAtMs = parseExpiresAt(parsedInput.expires_at);
376
432
  const runtimeContext = memoryRuntimeContext(context);
@@ -439,27 +495,24 @@ export function createMemoryCreateTool(context: MemoryCreateToolContext) {
439
495
  asToolInputError(error);
440
496
  }
441
497
  })();
442
- return {
443
- ok: true,
498
+ return memoryToolResult("createMemory", {
444
499
  created: result.created,
445
500
  memory: compactMemory(result.memory),
446
- };
501
+ });
447
502
  },
448
- } satisfies PluginToolDefinition<MemoryWriteToolInput>;
503
+ });
449
504
  }
450
505
 
451
506
  /** Create a tool that archives a visible memory in the active context. */
452
507
  export function createMemoryRemoveTool(context: MemoryToolContext) {
453
- return {
508
+ return definePluginTool({
454
509
  description:
455
510
  "Forget one memory visible in the active context. Use only ids or short id prefixes returned by listMemories or searchMemories. Never remove memories by hidden actor, Slack, scope, or subject identifiers.",
456
511
  executionMode: "sequential",
457
512
  inputSchema: removeMemoryInputSchema,
513
+ outputSchema: memorySingleOutputSchema,
458
514
  execute: async (input) => {
459
- const parsedInput = parseToolInput<{ id: string }>(
460
- removeMemoryInputSchema,
461
- input,
462
- );
515
+ const parsedInput = parseMemoryToolInput(removeMemoryInputSchema, input);
463
516
  const memory = await (async () => {
464
517
  try {
465
518
  return await memoryStore(context).archiveMemory({
@@ -470,46 +523,43 @@ export function createMemoryRemoveTool(context: MemoryToolContext) {
470
523
  asToolInputError(error);
471
524
  }
472
525
  })();
473
- return {
474
- ok: true,
526
+ return memoryToolResult("removeMemory", {
475
527
  memory: compactMemory(memory),
476
- };
528
+ });
477
529
  },
478
- } satisfies PluginToolDefinition<{ id: string }>;
530
+ });
479
531
  }
480
532
 
481
533
  /** Create a tool that lists visible active memories in the active context. */
482
534
  export function createMemoryListTool(context: MemoryToolContext) {
483
- return {
535
+ return definePluginTool({
484
536
  description:
485
537
  "List active memories visible in the current context. Use when the user asks what Junior remembers or when memory ids are needed before removing a memory.",
486
538
  annotations: { readOnlyHint: true, destructiveHint: false },
487
539
  inputSchema: listMemoriesInputSchema,
540
+ outputSchema: memoryManyOutputSchema,
488
541
  execute: async (input) => {
489
- const parsedInput = parseToolInput<{ limit?: number }>(
490
- listMemoriesInputSchema,
491
- input,
492
- );
542
+ const parsedInput = parseMemoryToolInput(listMemoriesInputSchema, input);
493
543
  const memories = await memoryStore(context).listMemories({
494
544
  limit: boundedLimit(parsedInput.limit, DEFAULT_RESULT_LIMIT),
495
545
  });
496
- return {
497
- ok: true,
546
+ return memoryToolResult("listMemories", {
498
547
  memories: memories.map(compactMemory),
499
- };
548
+ });
500
549
  },
501
- } satisfies PluginToolDefinition<{ limit?: number }>;
550
+ });
502
551
  }
503
552
 
504
553
  /** Create a tool that searches visible active memories in the active context. */
505
554
  export function createMemorySearchTool(context: MemoryToolContext) {
506
- return {
555
+ return definePluginTool({
507
556
  description:
508
557
  "Search active memories visible in the current context. Use when the model needs targeted memory recall. The tool searches only the current requester and active conversation scopes.",
509
558
  annotations: { readOnlyHint: true, destructiveHint: false },
510
559
  inputSchema: searchMemoriesInputSchema,
560
+ outputSchema: memoryManyOutputSchema,
511
561
  execute: async (input) => {
512
- const parsedInput = parseToolInput<{ limit?: number; query: string }>(
562
+ const parsedInput = parseMemoryToolInput(
513
563
  searchMemoriesInputSchema,
514
564
  input,
515
565
  );
@@ -517,10 +567,9 @@ export function createMemorySearchTool(context: MemoryToolContext) {
517
567
  query: parsedInput.query,
518
568
  limit: boundedLimit(parsedInput.limit, DEFAULT_SEARCH_LIMIT),
519
569
  });
520
- return {
521
- ok: true,
570
+ return memoryToolResult("searchMemories", {
522
571
  memories: memories.map(compactMemory),
523
- };
572
+ });
524
573
  },
525
- } satisfies PluginToolDefinition<{ limit?: number; query: string }>;
574
+ });
526
575
  }