@frontmcp/plugin-remember 1.11.2 → 1.12.0-rc.1

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 CHANGED
@@ -153,6 +153,9 @@ With `tools.enabled: true`, the plugin registers four tools, named with `tools.p
153
153
  | `forget` | `key`, `scope?` |
154
154
  | `list_memories` | `scope?`, `pattern?`, `limit?` (default 50, at most 100) |
155
155
 
156
+ Their `scope` is `session` (the default), `user` or `global`. They don't offer `tool` scope: it belongs to the tool
157
+ that runs the call, so `recall` would never find what `remember_this` stored there. Up to 1.11.2 they accepted it.
158
+
156
159
  The package also exports their classes, `RememberThisTool`, `RecallTool`, `ForgetTool` and `ListMemoriesTool`, to list
157
160
  in an app's `tools` yourself. Use one way or the other, not both.
158
161
 
package/esm/index.mjs CHANGED
@@ -5,4 +5,4 @@ var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDe
5
5
  if redis.call('EXISTS', KEYS[1], KEYS[2]) > 0 then return 0 end
6
6
  if ARGV[2] ~= '' then redis.call('SET', KEYS[1], ARGV[1], 'EX', ARGV[2]) else redis.call('SET', KEYS[1], ARGV[1]) end
7
7
  return 1
8
- `;function createRedisClient(options){const ioredis=__require("ioredis");const Redis=ioredis.default??ioredis;return new Redis(options)}var RememberRedisProvider=class{client;keyPrefix;defaultTTL;ownsClient;constructor(options){this.keyPrefix=options.keyPrefix??"";this.defaultTTL=options.defaultTTL;if(options.type==="redis-client"){this.client=options.client;this.ownsClient=false;return}this.ownsClient=true;this.client=createRedisClient({lazyConnect:false,maxRetriesPerRequest:3,...options.config});this.client.on("connect",()=>{if(process.env["DEBUG"]==="true"){console.log("[RememberPlugin:Redis] Connected")}});this.client.on("error",err=>{console.error("[RememberPlugin:Redis] Error:",err.message)})}async setValue(key,value,ttlSeconds){if(value===void 0){throw new Error("Cannot store undefined value. Use null or delete the key instead.")}if(ttlSeconds!==void 0){if(typeof ttlSeconds!=="number"||!Number.isFinite(ttlSeconds)){throw new Error(`Invalid TTL: expected a number, got ${typeof ttlSeconds}`)}if(ttlSeconds<=0){throw new Error(`Invalid TTL: must be positive, got ${ttlSeconds}`)}if(!Number.isInteger(ttlSeconds)){throw new Error(`Invalid TTL: must be an integer, got ${ttlSeconds}`)}}const fullKey=prefixedStoreKey(this.keyPrefix,key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;if(ttl!==void 0&&ttl>0){await this.client.set(fullKey,strValue,"EX",ttl)}else{await this.client.set(fullKey,strValue)}await this.deleteDoubledPrefixKey(key)}async setIfAbsent(key,value,ttlSeconds){const fullKey=prefixedStoreKey(this.keyPrefix,key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;const hasTtl=ttl!==void 0&&ttl>0;const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(doubledKey){const ttlArgument=hasTtl?String(ttl):"";const created=await this.client.eval(SET_IF_NEITHER_KEY_EXISTS_SCRIPT,2,fullKey,doubledKey,strValue,ttlArgument);return created===1}const result=hasTtl?await this.client.set(fullKey,strValue,"EX",ttl,"NX"):await this.client.set(fullKey,strValue,"NX");return result==="OK"}async getValue(key,defaultValue){const raw=await this.client.get(prefixedStoreKey(this.keyPrefix,key))??await this.readDoubledPrefixValue(key);if(raw===null)return defaultValue;try{return JSON.parse(raw)}catch{return defaultValue}}async delete(key){await this.client.del(prefixedStoreKey(this.keyPrefix,key));await this.deleteDoubledPrefixKey(key)}async exists(key){if(await this.client.exists(prefixedStoreKey(this.keyPrefix,key))===1)return true;const doubledKey=doubledPrefixKey(this.keyPrefix,key);return doubledKey!==void 0&&await this.client.exists(doubledKey)===1}async keys(pattern="*"){const result=new Set;for(const key of await this.scan(prefixedStoreKey(this.keyPrefix,pattern))){result.add(callerKeyOf(this.keyPrefix,pattern,key))}const doubledPattern=doubledPrefixKey(this.keyPrefix,pattern);if(doubledPattern){for(const key of await this.scan(doubledPattern))result.add(key.slice(this.keyPrefix.length))}return[...result]}async scan(match){const found=[];let cursor="0";do{const[nextCursor,keys]=await this.client.scan(cursor,"MATCH",match,"COUNT",100);cursor=nextCursor;found.push(...keys)}while(cursor!=="0");return found}async readDoubledPrefixValue(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);return doubledKey?this.client.get(doubledKey):null}async deleteDoubledPrefixKey(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(doubledKey)await this.client.del(doubledKey)}async close(){if(this.ownsClient){await this.client.quit()}}};RememberRedisProvider=__decorateClass([Provider3({name:"provider:remember:redis",description:"Redis-based storage provider for RememberPlugin",scope:ProviderScope3.GLOBAL})],RememberRedisProvider);import{Provider as Provider4,ProviderScope as ProviderScope4}from"@frontmcp/sdk";import{createVercelKvClient}from"@frontmcp/utils";var RememberVercelKvProvider=class{connection;client;keyPrefix;defaultTTL;constructor(options={}){const hasUrl=options.url!==void 0;const hasToken=options.token!==void 0;if(hasUrl!==hasToken){throw new Error(`RememberVercelKvProvider: Both 'url' and 'token' must be provided together, or neither. Received: url=${hasUrl?"provided":"missing"}, token=${hasToken?"provided":"missing"}`)}this.connection={url:options.url,token:options.token};this.keyPrefix=options.keyPrefix??"remember:";this.defaultTTL=options.defaultTTL}kv(){this.client??=createVercelKvClient(this.connection).catch(error=>{this.client=void 0;throw error});return this.client}prefixKey(key){return prefixedStoreKey(this.keyPrefix,key)}async setValue(key,value,ttlSeconds){const fullKey=this.prefixKey(key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;const kv=await this.kv();if(ttl&&ttl>0){await kv.set(fullKey,strValue,{ex:ttl})}else{await kv.set(fullKey,strValue)}await this.deleteDoubledPrefixKey(key)}async setIfAbsent(key,value,ttlSeconds){const fullKey=this.prefixKey(key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;const doubledKey=doubledPrefixKey(this.keyPrefix,key);const kv=await this.kv();if(doubledKey){const ttlArgument=ttl&&ttl>0?String(ttl):"";const created=await kv.eval(SET_IF_NEITHER_KEY_EXISTS_SCRIPT,[fullKey,doubledKey],[strValue,ttlArgument]);return Number(created)===1}const result=ttl&&ttl>0?await kv.set(fullKey,strValue,{nx:true,ex:ttl}):await kv.set(fullKey,strValue,{nx:true});return result==="OK"}async getValue(key,defaultValue){const kv=await this.kv();const raw=await kv.get(this.prefixKey(key))??await this.readDoubledPrefixValue(key);if(raw===null)return defaultValue;try{return JSON.parse(raw)}catch{return raw}}async delete(key){const kv=await this.kv();await kv.del(this.prefixKey(key));await this.deleteDoubledPrefixKey(key)}async exists(key){const kv=await this.kv();if(await kv.exists(this.prefixKey(key))===1)return true;const doubledKey=doubledPrefixKey(this.keyPrefix,key);return doubledKey!==void 0&&await kv.exists(doubledKey)===1}async keys(pattern="*"){const result=new Set;for(const key of await this.scan(this.prefixKey(pattern))){result.add(callerKeyOf(this.keyPrefix,pattern,key))}const doubledPattern=doubledPrefixKey(this.keyPrefix,pattern);if(doubledPattern){for(const key of await this.scan(doubledPattern))result.add(key.slice(this.keyPrefix.length))}return[...result]}async scan(match){const found=[];const kv=await this.kv();try{let cursor=0;do{const[nextCursor,keys]=await kv.scan(cursor,{match,count:100});cursor=nextCursor;found.push(...keys)}while(String(cursor)!=="0")}catch{try{found.push(...await kv.keys(match))}catch{console.warn("[RememberPlugin:VercelKV] keys() operation not supported")}}return found}async readDoubledPrefixValue(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(!doubledKey)return null;const kv=await this.kv();return kv.get(doubledKey)}async deleteDoubledPrefixKey(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(!doubledKey)return;const kv=await this.kv();await kv.del(doubledKey)}async close(){}};RememberVercelKvProvider=__decorateClass([Provider4({name:"provider:remember:vercel-kv",description:"Vercel KV-based storage provider for RememberPlugin",scope:ProviderScope4.GLOBAL})],RememberVercelKvProvider);var RememberStoreToken=Symbol("plugin:remember:store");var RememberConfigToken=Symbol("plugin:remember:config");var RememberAccessorToken=Symbol("plugin:remember:accessor");import{Tool as Tool5}from"@frontmcp/sdk";import{z as z2}from"@frontmcp/lazy-zod";import{Tool,ToolContext}from"@frontmcp/sdk";var REMEMBER_SCOPE_DESCRIPTION="Whose memory to use (default: session). session: this session; without one (stateless HTTP, MCP 2026-07-28), the signed-in caller across its requests. user: the signed-in caller, across all of its sessions. tool: the tool running the call, for the same caller as session; each memory tool has its own, so the other memory tools do not see what one of them stores in tool scope. global: shared by every caller. An anonymous caller cannot use user scope, nor session or tool scope without a session.";function rememberToolNames(prefix=""){return{rememberThis:`${prefix}remember_this`,recall:`${prefix}recall`,forget:`${prefix}forget`,listMemories:`${prefix}list_memories`}}var forgetInputSchema={key:z2.string().min(1).describe("What memory to forget"),scope:z2.enum(["session","user","tool","global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION)};var forgetOutputSchema=z2.object({success:z2.boolean(),key:z2.string(),scope:z2.string(),existed:z2.boolean()});function forgetDescription(){return"Forget a previously remembered value. Use this when the user wants to delete stored preferences or information."}function forgetToolMetadata(names=rememberToolNames()){return{name:names.forget,description:forgetDescription(),inputSchema:forgetInputSchema,outputSchema:forgetOutputSchema,annotations:{readOnlyHint:false}}}var ForgetTool=class extends ToolContext{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=config.tools?.allowedScopes??["session","user","tool","global"];if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const existed=await remember.knows(input.key,{scope});await remember.forget(input.key,{scope});return{success:true,key:input.key,scope,existed}}};ForgetTool=__decorateClass([Tool(forgetToolMetadata())],ForgetTool);import{z as z3}from"@frontmcp/lazy-zod";import{Tool as Tool2,ToolContext as ToolContext2}from"@frontmcp/sdk";var listMemoriesInputSchema={scope:z3.enum(["session","user","tool","global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION),pattern:z3.string().optional().describe('Pattern to filter keys (e.g., "user_*")'),limit:z3.number().positive().max(100).optional().describe("Maximum number of keys to return (default: 50)")};var listMemoriesOutputSchema=z3.object({keys:z3.array(z3.string()),scope:z3.string(),count:z3.number(),truncated:z3.boolean()});function listMemoriesDescription(names=rememberToolNames()){return`List the remembered keys in one scope (default: session). Use this to see what memories are stored before you ${names.recall} or ${names.forget} one.`}function listMemoriesToolMetadata(names=rememberToolNames()){return{name:names.listMemories,description:listMemoriesDescription(names),inputSchema:listMemoriesInputSchema,outputSchema:listMemoriesOutputSchema,annotations:{readOnlyHint:true}}}var ListMemoriesTool=class extends ToolContext2{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=config.tools?.allowedScopes??["session","user","tool","global"];if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const limit=input.limit??50;let keys=await remember.list({scope,pattern:input.pattern});const truncated=keys.length>limit;if(truncated){keys=keys.slice(0,limit)}return{keys,scope,count:keys.length,truncated}}};ListMemoriesTool=__decorateClass([Tool2(listMemoriesToolMetadata())],ListMemoriesTool);import{z as z4}from"@frontmcp/lazy-zod";import{Tool as Tool3,ToolContext as ToolContext3}from"@frontmcp/sdk";var recallInputSchema={key:z4.string().min(1).describe("What memory to recall"),scope:z4.enum(["session","user","tool","global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION)};var recallOutputSchema=z4.object({found:z4.boolean(),key:z4.string(),value:z4.unknown().optional(),scope:z4.string(),createdAt:z4.number().optional(),expiresAt:z4.number().optional()});function recallDescription(names=rememberToolNames()){return`Recall something that was previously remembered. Use this to retrieve stored preferences, settings, or any information that was saved with ${names.rememberThis}.`}function recallToolMetadata(names=rememberToolNames()){return{name:names.recall,description:recallDescription(names),inputSchema:recallInputSchema,outputSchema:recallOutputSchema,annotations:{readOnlyHint:true}}}var RecallTool=class extends ToolContext3{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=config.tools?.allowedScopes??["session","user","tool","global"];if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const entry=await remember.getEntry(input.key,{scope});if(!entry){return{found:false,key:input.key,scope}}return{found:true,key:input.key,value:entry.value,scope,createdAt:entry.createdAt,expiresAt:entry.expiresAt}}};RecallTool=__decorateClass([Tool3(recallToolMetadata())],RecallTool);import{z as z5}from"@frontmcp/lazy-zod";import{Tool as Tool4,ToolContext as ToolContext4}from"@frontmcp/sdk";var rememberThisInputSchema={key:z5.string().min(1).describe('What to call this memory (e.g., "user_preference", "last_action")'),value:z5.unknown().describe("The value to remember (any JSON-serializable data)"),scope:z5.enum(["session","user","tool","global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION),ttl:z5.number().int().positive().optional().describe("Forget after this many whole seconds"),brand:z5.enum(["preference","cache","state","conversation","custom"]).optional().describe("Type hint for the stored value")};var rememberThisOutputSchema=z5.object({success:z5.boolean(),key:z5.string(),scope:z5.string(),expiresAt:z5.number().optional()});function rememberThisDescription(names=rememberToolNames()){return`Remember something for later: store a value under a key that ${names.recall} can read back, in the scope you choose (this session by default; user scope for the signed-in user across sessions). It lasts until it is forgotten or its ttl runs out. Use this when the user asks you to remember preferences, settings, or any information they want to persist.`}function rememberThisToolMetadata(names=rememberToolNames()){return{name:names.rememberThis,description:rememberThisDescription(names),inputSchema:rememberThisInputSchema,outputSchema:rememberThisOutputSchema,annotations:{readOnlyHint:false}}}var RememberThisTool=class extends ToolContext4{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=config.tools?.allowedScopes??["session","user","tool","global"];if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const entry=await remember.set(input.key,input.value,{scope,ttl:input.ttl,brand:input.brand});return{success:true,key:input.key,scope,expiresAt:entry.expiresAt}}};RememberThisTool=__decorateClass([Tool4(rememberThisToolMetadata())],RememberThisTool);function createRememberTools(prefix=""){if(!prefix)return[RememberThisTool,RecallTool,ForgetTool,ListMemoriesTool];const names=rememberToolNames(prefix);let PrefixedRememberThisTool=class extends RememberThisTool{};PrefixedRememberThisTool=__decorateClass([Tool5(rememberThisToolMetadata(names))],PrefixedRememberThisTool);let PrefixedRecallTool=class extends RecallTool{};PrefixedRecallTool=__decorateClass([Tool5(recallToolMetadata(names))],PrefixedRecallTool);let PrefixedForgetTool=class extends ForgetTool{};PrefixedForgetTool=__decorateClass([Tool5(forgetToolMetadata(names))],PrefixedForgetTool);let PrefixedListMemoriesTool=class extends ListMemoriesTool{};PrefixedListMemoriesTool=__decorateClass([Tool5(listMemoriesToolMetadata(names))],PrefixedListMemoriesTool);return[PrefixedRememberThisTool,PrefixedRecallTool,PrefixedForgetTool,PrefixedListMemoriesTool]}function withCheckedOptions(options){const customKey=options.encryption?.customKey;if(customKey!==void 0&&customKey.trim()===""){throw new RememberConfigurationError("RememberPlugin encryption.customKey must not be empty; omit it to derive keys from the server secret")}const{defaultTTL}=options;if(defaultTTL===void 0)return options;if(defaultTTL===0)return{...options,defaultTTL:void 0};if(!Number.isInteger(defaultTTL)||defaultTTL<0){throw new RememberConfigurationError(`RememberPlugin defaultTTL must be a whole number of seconds (0 for no default expiry), got ${defaultTTL}`)}return options}var RememberPlugin=class extends DynamicPlugin{options;constructor(options={}){super();this.options={...RememberPlugin.defaultOptions,...withCheckedOptions(options)}}};__publicField(RememberPlugin,"defaultOptions",{type:"memory",keyPrefix:"remember:",encryption:{enabled:true}});__publicField(RememberPlugin,"dynamicTools",options=>options.tools?.enabled?createRememberTools(options.tools.prefix):[]);__publicField(RememberPlugin,"browserStores",(options,server)=>{const type=options.type??RememberPlugin.defaultOptions.type;const onRedis=type==="redis"||type==="redis-client"||type==="global-store"&&server.redis!==void 0&&!isVercelKvProvider(server.redis);return[{plugin:"RememberPlugin",option:onRedis?`type: '${type}'`:void 0,memory:"type: 'memory'"}]});__publicField(RememberPlugin,"dynamicProviders",options=>{const providers=[];const config={...RememberPlugin.defaultOptions,...withCheckedOptions(options)};switch(config.type){case"global-store":providers.push(storeProvider({name:"remember:store:global",provide:RememberStoreToken,inject:()=>[FrontMcpConfig],useFactory:frontmcpConfig=>{const storeConfig=getGlobalStoreConfig("RememberPlugin",frontmcpConfig);if(isVercelKvProvider(storeConfig)){return new RememberVercelKvProvider({url:storeConfig.url,token:storeConfig.token,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})}return new RememberRedisProvider({type:"redis",config:{host:storeConfig.host??"localhost",port:storeConfig.port??6379,password:storeConfig.password,db:storeConfig.db},keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})}}));break;case"redis":if("config"in config&&config.config){const redisConfig=config.config;let store;providers.push(storeProvider({name:"remember:store:redis",provide:RememberStoreToken,inject:()=>[],useFactory:()=>store??=new RememberRedisProvider({type:"redis",config:redisConfig,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})}))}break;case"redis-client":if("client"in config&&config.client){providers.push({name:"remember:store:redis-client",provide:RememberStoreToken,useValue:new RememberRedisProvider({type:"redis-client",client:config.client,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})})}break;case"vercel-kv":providers.push({name:"remember:store:vercel-kv",provide:RememberStoreToken,useValue:new RememberVercelKvProvider({url:"url"in config?config.url:void 0,token:"token"in config?config.token:void 0,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})});break;case"memory":default:providers.push({name:"remember:store:memory",provide:RememberStoreToken,inject:()=>[],useFactory:()=>new RememberMemoryProvider(void 0,config.defaultTTL)});break}providers.push({name:"remember:config",provide:RememberConfigToken,useValue:config});providers.push({name:"remember:accessor",provide:RememberAccessorToken,scope:ProviderScope5.CONTEXT,inject:()=>[RememberStoreToken,FRONTMCP_CONTEXT,RememberConfigToken,FrontMcpLogger],useFactory:(store,ctx,cfg,logger)=>createRememberAccessor(store,ctx,cfg,logger)});return providers});RememberPlugin=__decorateClass([Plugin({name:"remember",description:"Help your LLM remember things across sessions",providers:[{name:"remember:store:memory",provide:RememberStoreToken,inject:()=>[],useFactory:()=>new RememberMemoryProvider}],contextExtensions:[{property:"remember",token:RememberAccessorToken,errorMessage:"RememberPlugin is not installed. Add RememberPlugin.init() to your plugins array."}]})],RememberPlugin);import{z as z6}from"@frontmcp/lazy-zod";var rememberScopeSchema=z6.enum(["session","user","tool","global"]);function brand(data,_brand){return data}var rememberEntrySchema=z6.object({value:z6.unknown(),brand:z6.enum(["approval","preference","cache","state","conversation","custom"]).optional(),createdAt:z6.number(),updatedAt:z6.number(),expiresAt:z6.number().optional(),metadata:z6.record(z6.string(),z6.unknown()).optional()});function getRemember(ctx){return ctx.get(RememberAccessorToken)}function tryGetRemember(ctx){if(typeof ctx.tryGet==="function"){return ctx.tryGet(RememberAccessorToken)}return void 0}export{ForgetTool,ListMemoriesTool,RecallTool,RememberAccessor,RememberAccessorToken,RememberConfigToken,RememberConfigurationError,RememberIdentityError,RememberMemoryProvider,RememberPlugin,RememberRedisProvider,RememberScopeNotAllowedError,RememberStoreToken,RememberThisTool,RememberVercelKvProvider,brand,RememberPlugin as default,getRemember,tryGetRemember};
8
+ `;function createRedisClient(options){const ioredis=__require("ioredis");const Redis=ioredis.default??ioredis;return new Redis(options)}var RememberRedisProvider=class{client;keyPrefix;defaultTTL;ownsClient;constructor(options){this.keyPrefix=options.keyPrefix??"";this.defaultTTL=options.defaultTTL;if(options.type==="redis-client"){this.client=options.client;this.ownsClient=false;return}this.ownsClient=true;this.client=createRedisClient({lazyConnect:false,maxRetriesPerRequest:3,...options.config});this.client.on("connect",()=>{if(process.env["DEBUG"]==="true"){console.log("[RememberPlugin:Redis] Connected")}});this.client.on("error",err=>{console.error("[RememberPlugin:Redis] Error:",err.message)})}async setValue(key,value,ttlSeconds){if(value===void 0){throw new Error("Cannot store undefined value. Use null or delete the key instead.")}if(ttlSeconds!==void 0){if(typeof ttlSeconds!=="number"||!Number.isFinite(ttlSeconds)){throw new Error(`Invalid TTL: expected a number, got ${typeof ttlSeconds}`)}if(ttlSeconds<=0){throw new Error(`Invalid TTL: must be positive, got ${ttlSeconds}`)}if(!Number.isInteger(ttlSeconds)){throw new Error(`Invalid TTL: must be an integer, got ${ttlSeconds}`)}}const fullKey=prefixedStoreKey(this.keyPrefix,key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;if(ttl!==void 0&&ttl>0){await this.client.set(fullKey,strValue,"EX",ttl)}else{await this.client.set(fullKey,strValue)}await this.deleteDoubledPrefixKey(key)}async setIfAbsent(key,value,ttlSeconds){const fullKey=prefixedStoreKey(this.keyPrefix,key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;const hasTtl=ttl!==void 0&&ttl>0;const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(doubledKey){const ttlArgument=hasTtl?String(ttl):"";const created=await this.client.eval(SET_IF_NEITHER_KEY_EXISTS_SCRIPT,2,fullKey,doubledKey,strValue,ttlArgument);return created===1}const result=hasTtl?await this.client.set(fullKey,strValue,"EX",ttl,"NX"):await this.client.set(fullKey,strValue,"NX");return result==="OK"}async getValue(key,defaultValue){const raw=await this.client.get(prefixedStoreKey(this.keyPrefix,key))??await this.readDoubledPrefixValue(key);if(raw===null)return defaultValue;try{return JSON.parse(raw)}catch{return defaultValue}}async delete(key){await this.client.del(prefixedStoreKey(this.keyPrefix,key));await this.deleteDoubledPrefixKey(key)}async exists(key){if(await this.client.exists(prefixedStoreKey(this.keyPrefix,key))===1)return true;const doubledKey=doubledPrefixKey(this.keyPrefix,key);return doubledKey!==void 0&&await this.client.exists(doubledKey)===1}async keys(pattern="*"){const result=new Set;for(const key of await this.scan(prefixedStoreKey(this.keyPrefix,pattern))){result.add(callerKeyOf(this.keyPrefix,pattern,key))}const doubledPattern=doubledPrefixKey(this.keyPrefix,pattern);if(doubledPattern){for(const key of await this.scan(doubledPattern))result.add(key.slice(this.keyPrefix.length))}return[...result]}async scan(match){const found=[];let cursor="0";do{const[nextCursor,keys]=await this.client.scan(cursor,"MATCH",match,"COUNT",100);cursor=nextCursor;found.push(...keys)}while(cursor!=="0");return found}async readDoubledPrefixValue(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);return doubledKey?this.client.get(doubledKey):null}async deleteDoubledPrefixKey(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(doubledKey)await this.client.del(doubledKey)}async close(){if(this.ownsClient){await this.client.quit()}}};RememberRedisProvider=__decorateClass([Provider3({name:"provider:remember:redis",description:"Redis-based storage provider for RememberPlugin",scope:ProviderScope3.GLOBAL})],RememberRedisProvider);import{Provider as Provider4,ProviderScope as ProviderScope4}from"@frontmcp/sdk";import{createVercelKvClient}from"@frontmcp/utils";var RememberVercelKvProvider=class{connection;client;keyPrefix;defaultTTL;constructor(options={}){const hasUrl=options.url!==void 0;const hasToken=options.token!==void 0;if(hasUrl!==hasToken){throw new Error(`RememberVercelKvProvider: Both 'url' and 'token' must be provided together, or neither. Received: url=${hasUrl?"provided":"missing"}, token=${hasToken?"provided":"missing"}`)}this.connection={url:options.url,token:options.token};this.keyPrefix=options.keyPrefix??"remember:";this.defaultTTL=options.defaultTTL}kv(){this.client??=createVercelKvClient(this.connection).catch(error=>{this.client=void 0;throw error});return this.client}prefixKey(key){return prefixedStoreKey(this.keyPrefix,key)}async setValue(key,value,ttlSeconds){const fullKey=this.prefixKey(key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;const kv=await this.kv();if(ttl&&ttl>0){await kv.set(fullKey,strValue,{ex:ttl})}else{await kv.set(fullKey,strValue)}await this.deleteDoubledPrefixKey(key)}async setIfAbsent(key,value,ttlSeconds){const fullKey=this.prefixKey(key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;const doubledKey=doubledPrefixKey(this.keyPrefix,key);const kv=await this.kv();if(doubledKey){const ttlArgument=ttl&&ttl>0?String(ttl):"";const created=await kv.eval(SET_IF_NEITHER_KEY_EXISTS_SCRIPT,[fullKey,doubledKey],[strValue,ttlArgument]);return Number(created)===1}const result=ttl&&ttl>0?await kv.set(fullKey,strValue,{nx:true,ex:ttl}):await kv.set(fullKey,strValue,{nx:true});return result==="OK"}async getValue(key,defaultValue){const kv=await this.kv();const raw=await kv.get(this.prefixKey(key))??await this.readDoubledPrefixValue(key);if(raw===null)return defaultValue;try{return JSON.parse(raw)}catch{return raw}}async delete(key){const kv=await this.kv();await kv.del(this.prefixKey(key));await this.deleteDoubledPrefixKey(key)}async exists(key){const kv=await this.kv();if(await kv.exists(this.prefixKey(key))===1)return true;const doubledKey=doubledPrefixKey(this.keyPrefix,key);return doubledKey!==void 0&&await kv.exists(doubledKey)===1}async keys(pattern="*"){const result=new Set;for(const key of await this.scan(this.prefixKey(pattern))){result.add(callerKeyOf(this.keyPrefix,pattern,key))}const doubledPattern=doubledPrefixKey(this.keyPrefix,pattern);if(doubledPattern){for(const key of await this.scan(doubledPattern))result.add(key.slice(this.keyPrefix.length))}return[...result]}async scan(match){const found=[];const kv=await this.kv();try{let cursor=0;do{const[nextCursor,keys]=await kv.scan(cursor,{match,count:100});cursor=nextCursor;found.push(...keys)}while(String(cursor)!=="0")}catch{try{found.push(...await kv.keys(match))}catch{console.warn("[RememberPlugin:VercelKV] keys() operation not supported")}}return found}async readDoubledPrefixValue(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(!doubledKey)return null;const kv=await this.kv();return kv.get(doubledKey)}async deleteDoubledPrefixKey(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(!doubledKey)return;const kv=await this.kv();await kv.del(doubledKey)}async close(){}};RememberVercelKvProvider=__decorateClass([Provider4({name:"provider:remember:vercel-kv",description:"Vercel KV-based storage provider for RememberPlugin",scope:ProviderScope4.GLOBAL})],RememberVercelKvProvider);var RememberStoreToken=Symbol("plugin:remember:store");var RememberConfigToken=Symbol("plugin:remember:config");var RememberAccessorToken=Symbol("plugin:remember:accessor");import{Tool as Tool5}from"@frontmcp/sdk";import{z as z2}from"@frontmcp/lazy-zod";import{Tool,ToolContext}from"@frontmcp/sdk";var MEMORY_TOOL_SCOPES=["session","user","global"];function allowedMemoryToolScopes(allowedScopes){return(allowedScopes??MEMORY_TOOL_SCOPES).filter(scope=>scope!=="tool")}var REMEMBER_SCOPE_DESCRIPTION="Whose memory to use (default: session). session: this session; without one (stateless HTTP, MCP 2026-07-28), the signed-in caller across its requests. user: the signed-in caller, across all of its sessions. global: shared by every caller. An anonymous caller cannot use user scope, nor session scope without a session.";function rememberToolNames(prefix=""){return{rememberThis:`${prefix}remember_this`,recall:`${prefix}recall`,forget:`${prefix}forget`,listMemories:`${prefix}list_memories`}}var forgetInputSchema={key:z2.string().min(1).describe("What memory to forget"),scope:z2.enum(MEMORY_TOOL_SCOPES).optional().describe(REMEMBER_SCOPE_DESCRIPTION)};var forgetOutputSchema=z2.object({success:z2.boolean(),key:z2.string(),scope:z2.string(),existed:z2.boolean()});function forgetDescription(){return"Forget a previously remembered value. Use this when the user wants to delete stored preferences or information."}function forgetToolMetadata(names=rememberToolNames()){return{name:names.forget,description:forgetDescription(),inputSchema:forgetInputSchema,outputSchema:forgetOutputSchema,annotations:{readOnlyHint:false}}}var ForgetTool=class extends ToolContext{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=allowedMemoryToolScopes(config.tools?.allowedScopes);if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const existed=await remember.knows(input.key,{scope});await remember.forget(input.key,{scope});return{success:true,key:input.key,scope,existed}}};ForgetTool=__decorateClass([Tool(forgetToolMetadata())],ForgetTool);import{z as z3}from"@frontmcp/lazy-zod";import{Tool as Tool2,ToolContext as ToolContext2}from"@frontmcp/sdk";var listMemoriesInputSchema={scope:z3.enum(MEMORY_TOOL_SCOPES).optional().describe(REMEMBER_SCOPE_DESCRIPTION),pattern:z3.string().optional().describe('Pattern to filter keys (e.g., "user_*")'),limit:z3.number().positive().max(100).optional().describe("Maximum number of keys to return (default: 50)")};var listMemoriesOutputSchema=z3.object({keys:z3.array(z3.string()),scope:z3.string(),count:z3.number(),truncated:z3.boolean()});function listMemoriesDescription(names=rememberToolNames()){return`List the remembered keys in one scope (default: session). Use this to see what memories are stored before you ${names.recall} or ${names.forget} one.`}function listMemoriesToolMetadata(names=rememberToolNames()){return{name:names.listMemories,description:listMemoriesDescription(names),inputSchema:listMemoriesInputSchema,outputSchema:listMemoriesOutputSchema,annotations:{readOnlyHint:true}}}var ListMemoriesTool=class extends ToolContext2{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=allowedMemoryToolScopes(config.tools?.allowedScopes);if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const limit=input.limit??50;let keys=await remember.list({scope,pattern:input.pattern});const truncated=keys.length>limit;if(truncated){keys=keys.slice(0,limit)}return{keys,scope,count:keys.length,truncated}}};ListMemoriesTool=__decorateClass([Tool2(listMemoriesToolMetadata())],ListMemoriesTool);import{z as z4}from"@frontmcp/lazy-zod";import{Tool as Tool3,ToolContext as ToolContext3}from"@frontmcp/sdk";var recallInputSchema={key:z4.string().min(1).describe("What memory to recall"),scope:z4.enum(MEMORY_TOOL_SCOPES).optional().describe(REMEMBER_SCOPE_DESCRIPTION)};var recallOutputSchema=z4.object({found:z4.boolean(),key:z4.string(),value:z4.unknown().optional(),scope:z4.string(),createdAt:z4.number().optional(),expiresAt:z4.number().optional()});function recallDescription(names=rememberToolNames()){return`Recall something that was previously remembered. Use this to retrieve stored preferences, settings, or any information that was saved with ${names.rememberThis}.`}function recallToolMetadata(names=rememberToolNames()){return{name:names.recall,description:recallDescription(names),inputSchema:recallInputSchema,outputSchema:recallOutputSchema,annotations:{readOnlyHint:true}}}var RecallTool=class extends ToolContext3{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=allowedMemoryToolScopes(config.tools?.allowedScopes);if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const entry=await remember.getEntry(input.key,{scope});if(!entry){return{found:false,key:input.key,scope}}return{found:true,key:input.key,value:entry.value,scope,createdAt:entry.createdAt,expiresAt:entry.expiresAt}}};RecallTool=__decorateClass([Tool3(recallToolMetadata())],RecallTool);import{z as z5}from"@frontmcp/lazy-zod";import{Tool as Tool4,ToolContext as ToolContext4}from"@frontmcp/sdk";var rememberThisInputSchema={key:z5.string().min(1).describe('What to call this memory (e.g., "user_preference", "last_action")'),value:z5.unknown().describe("The value to remember (any JSON-serializable data)"),scope:z5.enum(MEMORY_TOOL_SCOPES).optional().describe(REMEMBER_SCOPE_DESCRIPTION),ttl:z5.number().int().positive().optional().describe("Forget after this many whole seconds"),brand:z5.enum(["preference","cache","state","conversation","custom"]).optional().describe("Type hint for the stored value")};var rememberThisOutputSchema=z5.object({success:z5.boolean(),key:z5.string(),scope:z5.string(),expiresAt:z5.number().optional()});function rememberThisDescription(names=rememberToolNames()){return`Remember something for later: store a value under a key that ${names.recall} can read back, in the scope you choose (this session by default; user scope for the signed-in user across sessions). It lasts until it is forgotten or its ttl runs out. Use this when the user asks you to remember preferences, settings, or any information they want to persist.`}function rememberThisToolMetadata(names=rememberToolNames()){return{name:names.rememberThis,description:rememberThisDescription(names),inputSchema:rememberThisInputSchema,outputSchema:rememberThisOutputSchema,annotations:{readOnlyHint:false}}}var RememberThisTool=class extends ToolContext4{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=allowedMemoryToolScopes(config.tools?.allowedScopes);if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const entry=await remember.set(input.key,input.value,{scope,ttl:input.ttl,brand:input.brand});return{success:true,key:input.key,scope,expiresAt:entry.expiresAt}}};RememberThisTool=__decorateClass([Tool4(rememberThisToolMetadata())],RememberThisTool);function createRememberTools(prefix=""){if(!prefix)return[RememberThisTool,RecallTool,ForgetTool,ListMemoriesTool];const names=rememberToolNames(prefix);let PrefixedRememberThisTool=class extends RememberThisTool{};PrefixedRememberThisTool=__decorateClass([Tool5(rememberThisToolMetadata(names))],PrefixedRememberThisTool);let PrefixedRecallTool=class extends RecallTool{};PrefixedRecallTool=__decorateClass([Tool5(recallToolMetadata(names))],PrefixedRecallTool);let PrefixedForgetTool=class extends ForgetTool{};PrefixedForgetTool=__decorateClass([Tool5(forgetToolMetadata(names))],PrefixedForgetTool);let PrefixedListMemoriesTool=class extends ListMemoriesTool{};PrefixedListMemoriesTool=__decorateClass([Tool5(listMemoriesToolMetadata(names))],PrefixedListMemoriesTool);return[PrefixedRememberThisTool,PrefixedRecallTool,PrefixedForgetTool,PrefixedListMemoriesTool]}function withCheckedOptions(options){const customKey=options.encryption?.customKey;if(customKey!==void 0&&customKey.trim()===""){throw new RememberConfigurationError("RememberPlugin encryption.customKey must not be empty; omit it to derive keys from the server secret")}const{defaultTTL}=options;if(defaultTTL===void 0)return options;if(defaultTTL===0)return{...options,defaultTTL:void 0};if(!Number.isInteger(defaultTTL)||defaultTTL<0){throw new RememberConfigurationError(`RememberPlugin defaultTTL must be a whole number of seconds (0 for no default expiry), got ${defaultTTL}`)}return options}var RememberPlugin=class extends DynamicPlugin{options;constructor(options={}){super();this.options={...RememberPlugin.defaultOptions,...withCheckedOptions(options)}}};__publicField(RememberPlugin,"defaultOptions",{type:"memory",keyPrefix:"remember:",encryption:{enabled:true}});__publicField(RememberPlugin,"dynamicTools",options=>options.tools?.enabled?createRememberTools(options.tools.prefix):[]);__publicField(RememberPlugin,"browserStores",(options,server)=>{const type=options.type??RememberPlugin.defaultOptions.type;const onRedis=type==="redis"||type==="redis-client"||type==="global-store"&&server.redis!==void 0&&!isVercelKvProvider(server.redis);return[{plugin:"RememberPlugin",option:onRedis?`type: '${type}'`:void 0,memory:"type: 'memory'"}]});__publicField(RememberPlugin,"dynamicProviders",options=>{const providers=[];const config={...RememberPlugin.defaultOptions,...withCheckedOptions(options)};switch(config.type){case"global-store":providers.push(storeProvider({name:"remember:store:global",provide:RememberStoreToken,inject:()=>[FrontMcpConfig],useFactory:frontmcpConfig=>{const storeConfig=getGlobalStoreConfig("RememberPlugin",frontmcpConfig);if(isVercelKvProvider(storeConfig)){return new RememberVercelKvProvider({url:storeConfig.url,token:storeConfig.token,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})}return new RememberRedisProvider({type:"redis",config:{host:storeConfig.host??"localhost",port:storeConfig.port??6379,password:storeConfig.password,db:storeConfig.db},keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})}}));break;case"redis":if("config"in config&&config.config){const redisConfig=config.config;let store;providers.push(storeProvider({name:"remember:store:redis",provide:RememberStoreToken,inject:()=>[],useFactory:()=>store??=new RememberRedisProvider({type:"redis",config:redisConfig,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})}))}break;case"redis-client":if("client"in config&&config.client){providers.push({name:"remember:store:redis-client",provide:RememberStoreToken,useValue:new RememberRedisProvider({type:"redis-client",client:config.client,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})})}break;case"vercel-kv":providers.push({name:"remember:store:vercel-kv",provide:RememberStoreToken,useValue:new RememberVercelKvProvider({url:"url"in config?config.url:void 0,token:"token"in config?config.token:void 0,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})});break;case"memory":default:providers.push({name:"remember:store:memory",provide:RememberStoreToken,inject:()=>[],useFactory:()=>new RememberMemoryProvider(void 0,config.defaultTTL)});break}providers.push({name:"remember:config",provide:RememberConfigToken,useValue:config});providers.push({name:"remember:accessor",provide:RememberAccessorToken,scope:ProviderScope5.CONTEXT,inject:()=>[RememberStoreToken,FRONTMCP_CONTEXT,RememberConfigToken,FrontMcpLogger],useFactory:(store,ctx,cfg,logger)=>createRememberAccessor(store,ctx,cfg,logger)});return providers});RememberPlugin=__decorateClass([Plugin({name:"remember",description:"Help your LLM remember things across sessions",providers:[{name:"remember:store:memory",provide:RememberStoreToken,inject:()=>[],useFactory:()=>new RememberMemoryProvider}],contextExtensions:[{property:"remember",token:RememberAccessorToken,errorMessage:"RememberPlugin is not installed. Add RememberPlugin.init() to your plugins array."}]})],RememberPlugin);import{z as z6}from"@frontmcp/lazy-zod";var rememberScopeSchema=z6.enum(["session","user","tool","global"]);function brand(data,_brand){return data}var rememberEntrySchema=z6.object({value:z6.unknown(),brand:z6.enum(["approval","preference","cache","state","conversation","custom"]).optional(),createdAt:z6.number(),updatedAt:z6.number(),expiresAt:z6.number().optional(),metadata:z6.record(z6.string(),z6.unknown()).optional()});function getRemember(ctx){return ctx.get(RememberAccessorToken)}function tryGetRemember(ctx){if(typeof ctx.tryGet==="function"){return ctx.tryGet(RememberAccessorToken)}return void 0}export{ForgetTool,ListMemoriesTool,RecallTool,RememberAccessor,RememberAccessorToken,RememberConfigToken,RememberConfigurationError,RememberIdentityError,RememberMemoryProvider,RememberPlugin,RememberRedisProvider,RememberScopeNotAllowedError,RememberStoreToken,RememberThisTool,RememberVercelKvProvider,brand,RememberPlugin as default,getRemember,tryGetRemember};
package/esm/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/plugin-remember",
3
- "version": "1.11.2",
3
+ "version": "1.12.0-rc.1",
4
4
  "description": "Remember plugin for FrontMCP: encrypted key-value memory for tools (this.remember) in session, user, tool and global scopes, stored in memory, Redis or Vercel KV",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "license": "Apache-2.0",
@@ -52,12 +52,12 @@
52
52
  }
53
53
  },
54
54
  "dependencies": {
55
- "@frontmcp/utils": "1.11.2",
55
+ "@frontmcp/utils": "1.12.0-rc.1",
56
56
  "ioredis": "^5.8.0"
57
57
  },
58
58
  "peerDependencies": {
59
- "@frontmcp/lazy-zod": "1.11.2",
60
- "@frontmcp/sdk": "1.11.2",
59
+ "@frontmcp/lazy-zod": "1.12.0-rc.1",
60
+ "@frontmcp/sdk": "1.12.0-rc.1",
61
61
  "@vercel/kv": "^2.0.0 || ^3.0.0"
62
62
  },
63
63
  "peerDependenciesMeta": {
@@ -66,7 +66,7 @@
66
66
  }
67
67
  },
68
68
  "devDependencies": {
69
- "@frontmcp/sdk": "1.11.2",
69
+ "@frontmcp/sdk": "1.12.0-rc.1",
70
70
  "reflect-metadata": "^0.2.2"
71
71
  }
72
72
  }
package/index.js CHANGED
@@ -2,4 +2,4 @@
2
2
  if redis.call('EXISTS', KEYS[1], KEYS[2]) > 0 then return 0 end
3
3
  if ARGV[2] ~= '' then redis.call('SET', KEYS[1], ARGV[1], 'EX', ARGV[2]) else redis.call('SET', KEYS[1], ARGV[1]) end
4
4
  return 1
5
- `;function createRedisClient(options){const ioredis=require("ioredis");const Redis=ioredis.default??ioredis;return new Redis(options)}var RememberRedisProvider=class{client;keyPrefix;defaultTTL;ownsClient;constructor(options){this.keyPrefix=options.keyPrefix??"";this.defaultTTL=options.defaultTTL;if(options.type==="redis-client"){this.client=options.client;this.ownsClient=false;return}this.ownsClient=true;this.client=createRedisClient({lazyConnect:false,maxRetriesPerRequest:3,...options.config});this.client.on("connect",()=>{if(process.env["DEBUG"]==="true"){console.log("[RememberPlugin:Redis] Connected")}});this.client.on("error",err=>{console.error("[RememberPlugin:Redis] Error:",err.message)})}async setValue(key,value,ttlSeconds){if(value===void 0){throw new Error("Cannot store undefined value. Use null or delete the key instead.")}if(ttlSeconds!==void 0){if(typeof ttlSeconds!=="number"||!Number.isFinite(ttlSeconds)){throw new Error(`Invalid TTL: expected a number, got ${typeof ttlSeconds}`)}if(ttlSeconds<=0){throw new Error(`Invalid TTL: must be positive, got ${ttlSeconds}`)}if(!Number.isInteger(ttlSeconds)){throw new Error(`Invalid TTL: must be an integer, got ${ttlSeconds}`)}}const fullKey=prefixedStoreKey(this.keyPrefix,key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;if(ttl!==void 0&&ttl>0){await this.client.set(fullKey,strValue,"EX",ttl)}else{await this.client.set(fullKey,strValue)}await this.deleteDoubledPrefixKey(key)}async setIfAbsent(key,value,ttlSeconds){const fullKey=prefixedStoreKey(this.keyPrefix,key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;const hasTtl=ttl!==void 0&&ttl>0;const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(doubledKey){const ttlArgument=hasTtl?String(ttl):"";const created=await this.client.eval(SET_IF_NEITHER_KEY_EXISTS_SCRIPT,2,fullKey,doubledKey,strValue,ttlArgument);return created===1}const result=hasTtl?await this.client.set(fullKey,strValue,"EX",ttl,"NX"):await this.client.set(fullKey,strValue,"NX");return result==="OK"}async getValue(key,defaultValue){const raw=await this.client.get(prefixedStoreKey(this.keyPrefix,key))??await this.readDoubledPrefixValue(key);if(raw===null)return defaultValue;try{return JSON.parse(raw)}catch{return defaultValue}}async delete(key){await this.client.del(prefixedStoreKey(this.keyPrefix,key));await this.deleteDoubledPrefixKey(key)}async exists(key){if(await this.client.exists(prefixedStoreKey(this.keyPrefix,key))===1)return true;const doubledKey=doubledPrefixKey(this.keyPrefix,key);return doubledKey!==void 0&&await this.client.exists(doubledKey)===1}async keys(pattern="*"){const result=new Set;for(const key of await this.scan(prefixedStoreKey(this.keyPrefix,pattern))){result.add(callerKeyOf(this.keyPrefix,pattern,key))}const doubledPattern=doubledPrefixKey(this.keyPrefix,pattern);if(doubledPattern){for(const key of await this.scan(doubledPattern))result.add(key.slice(this.keyPrefix.length))}return[...result]}async scan(match){const found=[];let cursor="0";do{const[nextCursor,keys]=await this.client.scan(cursor,"MATCH",match,"COUNT",100);cursor=nextCursor;found.push(...keys)}while(cursor!=="0");return found}async readDoubledPrefixValue(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);return doubledKey?this.client.get(doubledKey):null}async deleteDoubledPrefixKey(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(doubledKey)await this.client.del(doubledKey)}async close(){if(this.ownsClient){await this.client.quit()}}};RememberRedisProvider=__decorateClass([(0,import_sdk4.Provider)({name:"provider:remember:redis",description:"Redis-based storage provider for RememberPlugin",scope:import_sdk4.ProviderScope.GLOBAL})],RememberRedisProvider);var import_sdk5=require("@frontmcp/sdk");var import_utils3=require("@frontmcp/utils");var RememberVercelKvProvider=class{connection;client;keyPrefix;defaultTTL;constructor(options={}){const hasUrl=options.url!==void 0;const hasToken=options.token!==void 0;if(hasUrl!==hasToken){throw new Error(`RememberVercelKvProvider: Both 'url' and 'token' must be provided together, or neither. Received: url=${hasUrl?"provided":"missing"}, token=${hasToken?"provided":"missing"}`)}this.connection={url:options.url,token:options.token};this.keyPrefix=options.keyPrefix??"remember:";this.defaultTTL=options.defaultTTL}kv(){this.client??=(0,import_utils3.createVercelKvClient)(this.connection).catch(error=>{this.client=void 0;throw error});return this.client}prefixKey(key){return prefixedStoreKey(this.keyPrefix,key)}async setValue(key,value,ttlSeconds){const fullKey=this.prefixKey(key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;const kv=await this.kv();if(ttl&&ttl>0){await kv.set(fullKey,strValue,{ex:ttl})}else{await kv.set(fullKey,strValue)}await this.deleteDoubledPrefixKey(key)}async setIfAbsent(key,value,ttlSeconds){const fullKey=this.prefixKey(key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;const doubledKey=doubledPrefixKey(this.keyPrefix,key);const kv=await this.kv();if(doubledKey){const ttlArgument=ttl&&ttl>0?String(ttl):"";const created=await kv.eval(SET_IF_NEITHER_KEY_EXISTS_SCRIPT,[fullKey,doubledKey],[strValue,ttlArgument]);return Number(created)===1}const result=ttl&&ttl>0?await kv.set(fullKey,strValue,{nx:true,ex:ttl}):await kv.set(fullKey,strValue,{nx:true});return result==="OK"}async getValue(key,defaultValue){const kv=await this.kv();const raw=await kv.get(this.prefixKey(key))??await this.readDoubledPrefixValue(key);if(raw===null)return defaultValue;try{return JSON.parse(raw)}catch{return raw}}async delete(key){const kv=await this.kv();await kv.del(this.prefixKey(key));await this.deleteDoubledPrefixKey(key)}async exists(key){const kv=await this.kv();if(await kv.exists(this.prefixKey(key))===1)return true;const doubledKey=doubledPrefixKey(this.keyPrefix,key);return doubledKey!==void 0&&await kv.exists(doubledKey)===1}async keys(pattern="*"){const result=new Set;for(const key of await this.scan(this.prefixKey(pattern))){result.add(callerKeyOf(this.keyPrefix,pattern,key))}const doubledPattern=doubledPrefixKey(this.keyPrefix,pattern);if(doubledPattern){for(const key of await this.scan(doubledPattern))result.add(key.slice(this.keyPrefix.length))}return[...result]}async scan(match){const found=[];const kv=await this.kv();try{let cursor=0;do{const[nextCursor,keys]=await kv.scan(cursor,{match,count:100});cursor=nextCursor;found.push(...keys)}while(String(cursor)!=="0")}catch{try{found.push(...await kv.keys(match))}catch{console.warn("[RememberPlugin:VercelKV] keys() operation not supported")}}return found}async readDoubledPrefixValue(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(!doubledKey)return null;const kv=await this.kv();return kv.get(doubledKey)}async deleteDoubledPrefixKey(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(!doubledKey)return;const kv=await this.kv();await kv.del(doubledKey)}async close(){}};RememberVercelKvProvider=__decorateClass([(0,import_sdk5.Provider)({name:"provider:remember:vercel-kv",description:"Vercel KV-based storage provider for RememberPlugin",scope:import_sdk5.ProviderScope.GLOBAL})],RememberVercelKvProvider);var RememberStoreToken=Symbol("plugin:remember:store");var RememberConfigToken=Symbol("plugin:remember:config");var RememberAccessorToken=Symbol("plugin:remember:accessor");var import_sdk10=require("@frontmcp/sdk");var import_lazy_zod2=require("@frontmcp/lazy-zod");var import_sdk6=require("@frontmcp/sdk");var REMEMBER_SCOPE_DESCRIPTION="Whose memory to use (default: session). session: this session; without one (stateless HTTP, MCP 2026-07-28), the signed-in caller across its requests. user: the signed-in caller, across all of its sessions. tool: the tool running the call, for the same caller as session; each memory tool has its own, so the other memory tools do not see what one of them stores in tool scope. global: shared by every caller. An anonymous caller cannot use user scope, nor session or tool scope without a session.";function rememberToolNames(prefix=""){return{rememberThis:`${prefix}remember_this`,recall:`${prefix}recall`,forget:`${prefix}forget`,listMemories:`${prefix}list_memories`}}var forgetInputSchema={key:import_lazy_zod2.z.string().min(1).describe("What memory to forget"),scope:import_lazy_zod2.z.enum(["session","user","tool","global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION)};var forgetOutputSchema=import_lazy_zod2.z.object({success:import_lazy_zod2.z.boolean(),key:import_lazy_zod2.z.string(),scope:import_lazy_zod2.z.string(),existed:import_lazy_zod2.z.boolean()});function forgetDescription(){return"Forget a previously remembered value. Use this when the user wants to delete stored preferences or information."}function forgetToolMetadata(names=rememberToolNames()){return{name:names.forget,description:forgetDescription(),inputSchema:forgetInputSchema,outputSchema:forgetOutputSchema,annotations:{readOnlyHint:false}}}var ForgetTool=class extends import_sdk6.ToolContext{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=config.tools?.allowedScopes??["session","user","tool","global"];if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const existed=await remember.knows(input.key,{scope});await remember.forget(input.key,{scope});return{success:true,key:input.key,scope,existed}}};ForgetTool=__decorateClass([(0,import_sdk6.Tool)(forgetToolMetadata())],ForgetTool);var import_lazy_zod3=require("@frontmcp/lazy-zod");var import_sdk7=require("@frontmcp/sdk");var listMemoriesInputSchema={scope:import_lazy_zod3.z.enum(["session","user","tool","global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION),pattern:import_lazy_zod3.z.string().optional().describe('Pattern to filter keys (e.g., "user_*")'),limit:import_lazy_zod3.z.number().positive().max(100).optional().describe("Maximum number of keys to return (default: 50)")};var listMemoriesOutputSchema=import_lazy_zod3.z.object({keys:import_lazy_zod3.z.array(import_lazy_zod3.z.string()),scope:import_lazy_zod3.z.string(),count:import_lazy_zod3.z.number(),truncated:import_lazy_zod3.z.boolean()});function listMemoriesDescription(names=rememberToolNames()){return`List the remembered keys in one scope (default: session). Use this to see what memories are stored before you ${names.recall} or ${names.forget} one.`}function listMemoriesToolMetadata(names=rememberToolNames()){return{name:names.listMemories,description:listMemoriesDescription(names),inputSchema:listMemoriesInputSchema,outputSchema:listMemoriesOutputSchema,annotations:{readOnlyHint:true}}}var ListMemoriesTool=class extends import_sdk7.ToolContext{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=config.tools?.allowedScopes??["session","user","tool","global"];if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const limit=input.limit??50;let keys=await remember.list({scope,pattern:input.pattern});const truncated=keys.length>limit;if(truncated){keys=keys.slice(0,limit)}return{keys,scope,count:keys.length,truncated}}};ListMemoriesTool=__decorateClass([(0,import_sdk7.Tool)(listMemoriesToolMetadata())],ListMemoriesTool);var import_lazy_zod4=require("@frontmcp/lazy-zod");var import_sdk8=require("@frontmcp/sdk");var recallInputSchema={key:import_lazy_zod4.z.string().min(1).describe("What memory to recall"),scope:import_lazy_zod4.z.enum(["session","user","tool","global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION)};var recallOutputSchema=import_lazy_zod4.z.object({found:import_lazy_zod4.z.boolean(),key:import_lazy_zod4.z.string(),value:import_lazy_zod4.z.unknown().optional(),scope:import_lazy_zod4.z.string(),createdAt:import_lazy_zod4.z.number().optional(),expiresAt:import_lazy_zod4.z.number().optional()});function recallDescription(names=rememberToolNames()){return`Recall something that was previously remembered. Use this to retrieve stored preferences, settings, or any information that was saved with ${names.rememberThis}.`}function recallToolMetadata(names=rememberToolNames()){return{name:names.recall,description:recallDescription(names),inputSchema:recallInputSchema,outputSchema:recallOutputSchema,annotations:{readOnlyHint:true}}}var RecallTool=class extends import_sdk8.ToolContext{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=config.tools?.allowedScopes??["session","user","tool","global"];if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const entry=await remember.getEntry(input.key,{scope});if(!entry){return{found:false,key:input.key,scope}}return{found:true,key:input.key,value:entry.value,scope,createdAt:entry.createdAt,expiresAt:entry.expiresAt}}};RecallTool=__decorateClass([(0,import_sdk8.Tool)(recallToolMetadata())],RecallTool);var import_lazy_zod5=require("@frontmcp/lazy-zod");var import_sdk9=require("@frontmcp/sdk");var rememberThisInputSchema={key:import_lazy_zod5.z.string().min(1).describe('What to call this memory (e.g., "user_preference", "last_action")'),value:import_lazy_zod5.z.unknown().describe("The value to remember (any JSON-serializable data)"),scope:import_lazy_zod5.z.enum(["session","user","tool","global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION),ttl:import_lazy_zod5.z.number().int().positive().optional().describe("Forget after this many whole seconds"),brand:import_lazy_zod5.z.enum(["preference","cache","state","conversation","custom"]).optional().describe("Type hint for the stored value")};var rememberThisOutputSchema=import_lazy_zod5.z.object({success:import_lazy_zod5.z.boolean(),key:import_lazy_zod5.z.string(),scope:import_lazy_zod5.z.string(),expiresAt:import_lazy_zod5.z.number().optional()});function rememberThisDescription(names=rememberToolNames()){return`Remember something for later: store a value under a key that ${names.recall} can read back, in the scope you choose (this session by default; user scope for the signed-in user across sessions). It lasts until it is forgotten or its ttl runs out. Use this when the user asks you to remember preferences, settings, or any information they want to persist.`}function rememberThisToolMetadata(names=rememberToolNames()){return{name:names.rememberThis,description:rememberThisDescription(names),inputSchema:rememberThisInputSchema,outputSchema:rememberThisOutputSchema,annotations:{readOnlyHint:false}}}var RememberThisTool=class extends import_sdk9.ToolContext{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=config.tools?.allowedScopes??["session","user","tool","global"];if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const entry=await remember.set(input.key,input.value,{scope,ttl:input.ttl,brand:input.brand});return{success:true,key:input.key,scope,expiresAt:entry.expiresAt}}};RememberThisTool=__decorateClass([(0,import_sdk9.Tool)(rememberThisToolMetadata())],RememberThisTool);function createRememberTools(prefix=""){if(!prefix)return[RememberThisTool,RecallTool,ForgetTool,ListMemoriesTool];const names=rememberToolNames(prefix);let PrefixedRememberThisTool=class extends RememberThisTool{};PrefixedRememberThisTool=__decorateClass([(0,import_sdk10.Tool)(rememberThisToolMetadata(names))],PrefixedRememberThisTool);let PrefixedRecallTool=class extends RecallTool{};PrefixedRecallTool=__decorateClass([(0,import_sdk10.Tool)(recallToolMetadata(names))],PrefixedRecallTool);let PrefixedForgetTool=class extends ForgetTool{};PrefixedForgetTool=__decorateClass([(0,import_sdk10.Tool)(forgetToolMetadata(names))],PrefixedForgetTool);let PrefixedListMemoriesTool=class extends ListMemoriesTool{};PrefixedListMemoriesTool=__decorateClass([(0,import_sdk10.Tool)(listMemoriesToolMetadata(names))],PrefixedListMemoriesTool);return[PrefixedRememberThisTool,PrefixedRecallTool,PrefixedForgetTool,PrefixedListMemoriesTool]}function withCheckedOptions(options){const customKey=options.encryption?.customKey;if(customKey!==void 0&&customKey.trim()===""){throw new RememberConfigurationError("RememberPlugin encryption.customKey must not be empty; omit it to derive keys from the server secret")}const{defaultTTL}=options;if(defaultTTL===void 0)return options;if(defaultTTL===0)return{...options,defaultTTL:void 0};if(!Number.isInteger(defaultTTL)||defaultTTL<0){throw new RememberConfigurationError(`RememberPlugin defaultTTL must be a whole number of seconds (0 for no default expiry), got ${defaultTTL}`)}return options}var RememberPlugin=class extends import_sdk11.DynamicPlugin{options;constructor(options={}){super();this.options={...RememberPlugin.defaultOptions,...withCheckedOptions(options)}}};__publicField(RememberPlugin,"defaultOptions",{type:"memory",keyPrefix:"remember:",encryption:{enabled:true}});__publicField(RememberPlugin,"dynamicTools",options=>options.tools?.enabled?createRememberTools(options.tools.prefix):[]);__publicField(RememberPlugin,"browserStores",(options,server)=>{const type=options.type??RememberPlugin.defaultOptions.type;const onRedis=type==="redis"||type==="redis-client"||type==="global-store"&&server.redis!==void 0&&!(0,import_sdk11.isVercelKvProvider)(server.redis);return[{plugin:"RememberPlugin",option:onRedis?`type: '${type}'`:void 0,memory:"type: 'memory'"}]});__publicField(RememberPlugin,"dynamicProviders",options=>{const providers=[];const config={...RememberPlugin.defaultOptions,...withCheckedOptions(options)};switch(config.type){case"global-store":providers.push((0,import_sdk11.storeProvider)({name:"remember:store:global",provide:RememberStoreToken,inject:()=>[import_sdk11.FrontMcpConfig],useFactory:frontmcpConfig=>{const storeConfig=(0,import_sdk11.getGlobalStoreConfig)("RememberPlugin",frontmcpConfig);if((0,import_sdk11.isVercelKvProvider)(storeConfig)){return new RememberVercelKvProvider({url:storeConfig.url,token:storeConfig.token,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})}return new RememberRedisProvider({type:"redis",config:{host:storeConfig.host??"localhost",port:storeConfig.port??6379,password:storeConfig.password,db:storeConfig.db},keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})}}));break;case"redis":if("config"in config&&config.config){const redisConfig=config.config;let store;providers.push((0,import_sdk11.storeProvider)({name:"remember:store:redis",provide:RememberStoreToken,inject:()=>[],useFactory:()=>store??=new RememberRedisProvider({type:"redis",config:redisConfig,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})}))}break;case"redis-client":if("client"in config&&config.client){providers.push({name:"remember:store:redis-client",provide:RememberStoreToken,useValue:new RememberRedisProvider({type:"redis-client",client:config.client,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})})}break;case"vercel-kv":providers.push({name:"remember:store:vercel-kv",provide:RememberStoreToken,useValue:new RememberVercelKvProvider({url:"url"in config?config.url:void 0,token:"token"in config?config.token:void 0,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})});break;case"memory":default:providers.push({name:"remember:store:memory",provide:RememberStoreToken,inject:()=>[],useFactory:()=>new RememberMemoryProvider(void 0,config.defaultTTL)});break}providers.push({name:"remember:config",provide:RememberConfigToken,useValue:config});providers.push({name:"remember:accessor",provide:RememberAccessorToken,scope:import_sdk11.ProviderScope.CONTEXT,inject:()=>[RememberStoreToken,import_sdk11.FRONTMCP_CONTEXT,RememberConfigToken,import_sdk11.FrontMcpLogger],useFactory:(store,ctx,cfg,logger)=>createRememberAccessor(store,ctx,cfg,logger)});return providers});RememberPlugin=__decorateClass([(0,import_sdk11.Plugin)({name:"remember",description:"Help your LLM remember things across sessions",providers:[{name:"remember:store:memory",provide:RememberStoreToken,inject:()=>[],useFactory:()=>new RememberMemoryProvider}],contextExtensions:[{property:"remember",token:RememberAccessorToken,errorMessage:"RememberPlugin is not installed. Add RememberPlugin.init() to your plugins array."}]})],RememberPlugin);var import_lazy_zod6=require("@frontmcp/lazy-zod");var rememberScopeSchema=import_lazy_zod6.z.enum(["session","user","tool","global"]);function brand(data,_brand){return data}var rememberEntrySchema=import_lazy_zod6.z.object({value:import_lazy_zod6.z.unknown(),brand:import_lazy_zod6.z.enum(["approval","preference","cache","state","conversation","custom"]).optional(),createdAt:import_lazy_zod6.z.number(),updatedAt:import_lazy_zod6.z.number(),expiresAt:import_lazy_zod6.z.number().optional(),metadata:import_lazy_zod6.z.record(import_lazy_zod6.z.string(),import_lazy_zod6.z.unknown()).optional()});function getRemember(ctx){return ctx.get(RememberAccessorToken)}function tryGetRemember(ctx){if(typeof ctx.tryGet==="function"){return ctx.tryGet(RememberAccessorToken)}return void 0}0&&(module.exports={ForgetTool,ListMemoriesTool,RecallTool,RememberAccessor,RememberAccessorToken,RememberConfigToken,RememberConfigurationError,RememberIdentityError,RememberMemoryProvider,RememberPlugin,RememberRedisProvider,RememberScopeNotAllowedError,RememberStoreToken,RememberThisTool,RememberVercelKvProvider,brand,getRemember,tryGetRemember});
5
+ `;function createRedisClient(options){const ioredis=require("ioredis");const Redis=ioredis.default??ioredis;return new Redis(options)}var RememberRedisProvider=class{client;keyPrefix;defaultTTL;ownsClient;constructor(options){this.keyPrefix=options.keyPrefix??"";this.defaultTTL=options.defaultTTL;if(options.type==="redis-client"){this.client=options.client;this.ownsClient=false;return}this.ownsClient=true;this.client=createRedisClient({lazyConnect:false,maxRetriesPerRequest:3,...options.config});this.client.on("connect",()=>{if(process.env["DEBUG"]==="true"){console.log("[RememberPlugin:Redis] Connected")}});this.client.on("error",err=>{console.error("[RememberPlugin:Redis] Error:",err.message)})}async setValue(key,value,ttlSeconds){if(value===void 0){throw new Error("Cannot store undefined value. Use null or delete the key instead.")}if(ttlSeconds!==void 0){if(typeof ttlSeconds!=="number"||!Number.isFinite(ttlSeconds)){throw new Error(`Invalid TTL: expected a number, got ${typeof ttlSeconds}`)}if(ttlSeconds<=0){throw new Error(`Invalid TTL: must be positive, got ${ttlSeconds}`)}if(!Number.isInteger(ttlSeconds)){throw new Error(`Invalid TTL: must be an integer, got ${ttlSeconds}`)}}const fullKey=prefixedStoreKey(this.keyPrefix,key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;if(ttl!==void 0&&ttl>0){await this.client.set(fullKey,strValue,"EX",ttl)}else{await this.client.set(fullKey,strValue)}await this.deleteDoubledPrefixKey(key)}async setIfAbsent(key,value,ttlSeconds){const fullKey=prefixedStoreKey(this.keyPrefix,key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;const hasTtl=ttl!==void 0&&ttl>0;const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(doubledKey){const ttlArgument=hasTtl?String(ttl):"";const created=await this.client.eval(SET_IF_NEITHER_KEY_EXISTS_SCRIPT,2,fullKey,doubledKey,strValue,ttlArgument);return created===1}const result=hasTtl?await this.client.set(fullKey,strValue,"EX",ttl,"NX"):await this.client.set(fullKey,strValue,"NX");return result==="OK"}async getValue(key,defaultValue){const raw=await this.client.get(prefixedStoreKey(this.keyPrefix,key))??await this.readDoubledPrefixValue(key);if(raw===null)return defaultValue;try{return JSON.parse(raw)}catch{return defaultValue}}async delete(key){await this.client.del(prefixedStoreKey(this.keyPrefix,key));await this.deleteDoubledPrefixKey(key)}async exists(key){if(await this.client.exists(prefixedStoreKey(this.keyPrefix,key))===1)return true;const doubledKey=doubledPrefixKey(this.keyPrefix,key);return doubledKey!==void 0&&await this.client.exists(doubledKey)===1}async keys(pattern="*"){const result=new Set;for(const key of await this.scan(prefixedStoreKey(this.keyPrefix,pattern))){result.add(callerKeyOf(this.keyPrefix,pattern,key))}const doubledPattern=doubledPrefixKey(this.keyPrefix,pattern);if(doubledPattern){for(const key of await this.scan(doubledPattern))result.add(key.slice(this.keyPrefix.length))}return[...result]}async scan(match){const found=[];let cursor="0";do{const[nextCursor,keys]=await this.client.scan(cursor,"MATCH",match,"COUNT",100);cursor=nextCursor;found.push(...keys)}while(cursor!=="0");return found}async readDoubledPrefixValue(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);return doubledKey?this.client.get(doubledKey):null}async deleteDoubledPrefixKey(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(doubledKey)await this.client.del(doubledKey)}async close(){if(this.ownsClient){await this.client.quit()}}};RememberRedisProvider=__decorateClass([(0,import_sdk4.Provider)({name:"provider:remember:redis",description:"Redis-based storage provider for RememberPlugin",scope:import_sdk4.ProviderScope.GLOBAL})],RememberRedisProvider);var import_sdk5=require("@frontmcp/sdk");var import_utils3=require("@frontmcp/utils");var RememberVercelKvProvider=class{connection;client;keyPrefix;defaultTTL;constructor(options={}){const hasUrl=options.url!==void 0;const hasToken=options.token!==void 0;if(hasUrl!==hasToken){throw new Error(`RememberVercelKvProvider: Both 'url' and 'token' must be provided together, or neither. Received: url=${hasUrl?"provided":"missing"}, token=${hasToken?"provided":"missing"}`)}this.connection={url:options.url,token:options.token};this.keyPrefix=options.keyPrefix??"remember:";this.defaultTTL=options.defaultTTL}kv(){this.client??=(0,import_utils3.createVercelKvClient)(this.connection).catch(error=>{this.client=void 0;throw error});return this.client}prefixKey(key){return prefixedStoreKey(this.keyPrefix,key)}async setValue(key,value,ttlSeconds){const fullKey=this.prefixKey(key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;const kv=await this.kv();if(ttl&&ttl>0){await kv.set(fullKey,strValue,{ex:ttl})}else{await kv.set(fullKey,strValue)}await this.deleteDoubledPrefixKey(key)}async setIfAbsent(key,value,ttlSeconds){const fullKey=this.prefixKey(key);const strValue=JSON.stringify(value);const ttl=ttlSeconds??this.defaultTTL;const doubledKey=doubledPrefixKey(this.keyPrefix,key);const kv=await this.kv();if(doubledKey){const ttlArgument=ttl&&ttl>0?String(ttl):"";const created=await kv.eval(SET_IF_NEITHER_KEY_EXISTS_SCRIPT,[fullKey,doubledKey],[strValue,ttlArgument]);return Number(created)===1}const result=ttl&&ttl>0?await kv.set(fullKey,strValue,{nx:true,ex:ttl}):await kv.set(fullKey,strValue,{nx:true});return result==="OK"}async getValue(key,defaultValue){const kv=await this.kv();const raw=await kv.get(this.prefixKey(key))??await this.readDoubledPrefixValue(key);if(raw===null)return defaultValue;try{return JSON.parse(raw)}catch{return raw}}async delete(key){const kv=await this.kv();await kv.del(this.prefixKey(key));await this.deleteDoubledPrefixKey(key)}async exists(key){const kv=await this.kv();if(await kv.exists(this.prefixKey(key))===1)return true;const doubledKey=doubledPrefixKey(this.keyPrefix,key);return doubledKey!==void 0&&await kv.exists(doubledKey)===1}async keys(pattern="*"){const result=new Set;for(const key of await this.scan(this.prefixKey(pattern))){result.add(callerKeyOf(this.keyPrefix,pattern,key))}const doubledPattern=doubledPrefixKey(this.keyPrefix,pattern);if(doubledPattern){for(const key of await this.scan(doubledPattern))result.add(key.slice(this.keyPrefix.length))}return[...result]}async scan(match){const found=[];const kv=await this.kv();try{let cursor=0;do{const[nextCursor,keys]=await kv.scan(cursor,{match,count:100});cursor=nextCursor;found.push(...keys)}while(String(cursor)!=="0")}catch{try{found.push(...await kv.keys(match))}catch{console.warn("[RememberPlugin:VercelKV] keys() operation not supported")}}return found}async readDoubledPrefixValue(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(!doubledKey)return null;const kv=await this.kv();return kv.get(doubledKey)}async deleteDoubledPrefixKey(key){const doubledKey=doubledPrefixKey(this.keyPrefix,key);if(!doubledKey)return;const kv=await this.kv();await kv.del(doubledKey)}async close(){}};RememberVercelKvProvider=__decorateClass([(0,import_sdk5.Provider)({name:"provider:remember:vercel-kv",description:"Vercel KV-based storage provider for RememberPlugin",scope:import_sdk5.ProviderScope.GLOBAL})],RememberVercelKvProvider);var RememberStoreToken=Symbol("plugin:remember:store");var RememberConfigToken=Symbol("plugin:remember:config");var RememberAccessorToken=Symbol("plugin:remember:accessor");var import_sdk10=require("@frontmcp/sdk");var import_lazy_zod2=require("@frontmcp/lazy-zod");var import_sdk6=require("@frontmcp/sdk");var MEMORY_TOOL_SCOPES=["session","user","global"];function allowedMemoryToolScopes(allowedScopes){return(allowedScopes??MEMORY_TOOL_SCOPES).filter(scope=>scope!=="tool")}var REMEMBER_SCOPE_DESCRIPTION="Whose memory to use (default: session). session: this session; without one (stateless HTTP, MCP 2026-07-28), the signed-in caller across its requests. user: the signed-in caller, across all of its sessions. global: shared by every caller. An anonymous caller cannot use user scope, nor session scope without a session.";function rememberToolNames(prefix=""){return{rememberThis:`${prefix}remember_this`,recall:`${prefix}recall`,forget:`${prefix}forget`,listMemories:`${prefix}list_memories`}}var forgetInputSchema={key:import_lazy_zod2.z.string().min(1).describe("What memory to forget"),scope:import_lazy_zod2.z.enum(MEMORY_TOOL_SCOPES).optional().describe(REMEMBER_SCOPE_DESCRIPTION)};var forgetOutputSchema=import_lazy_zod2.z.object({success:import_lazy_zod2.z.boolean(),key:import_lazy_zod2.z.string(),scope:import_lazy_zod2.z.string(),existed:import_lazy_zod2.z.boolean()});function forgetDescription(){return"Forget a previously remembered value. Use this when the user wants to delete stored preferences or information."}function forgetToolMetadata(names=rememberToolNames()){return{name:names.forget,description:forgetDescription(),inputSchema:forgetInputSchema,outputSchema:forgetOutputSchema,annotations:{readOnlyHint:false}}}var ForgetTool=class extends import_sdk6.ToolContext{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=allowedMemoryToolScopes(config.tools?.allowedScopes);if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const existed=await remember.knows(input.key,{scope});await remember.forget(input.key,{scope});return{success:true,key:input.key,scope,existed}}};ForgetTool=__decorateClass([(0,import_sdk6.Tool)(forgetToolMetadata())],ForgetTool);var import_lazy_zod3=require("@frontmcp/lazy-zod");var import_sdk7=require("@frontmcp/sdk");var listMemoriesInputSchema={scope:import_lazy_zod3.z.enum(MEMORY_TOOL_SCOPES).optional().describe(REMEMBER_SCOPE_DESCRIPTION),pattern:import_lazy_zod3.z.string().optional().describe('Pattern to filter keys (e.g., "user_*")'),limit:import_lazy_zod3.z.number().positive().max(100).optional().describe("Maximum number of keys to return (default: 50)")};var listMemoriesOutputSchema=import_lazy_zod3.z.object({keys:import_lazy_zod3.z.array(import_lazy_zod3.z.string()),scope:import_lazy_zod3.z.string(),count:import_lazy_zod3.z.number(),truncated:import_lazy_zod3.z.boolean()});function listMemoriesDescription(names=rememberToolNames()){return`List the remembered keys in one scope (default: session). Use this to see what memories are stored before you ${names.recall} or ${names.forget} one.`}function listMemoriesToolMetadata(names=rememberToolNames()){return{name:names.listMemories,description:listMemoriesDescription(names),inputSchema:listMemoriesInputSchema,outputSchema:listMemoriesOutputSchema,annotations:{readOnlyHint:true}}}var ListMemoriesTool=class extends import_sdk7.ToolContext{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=allowedMemoryToolScopes(config.tools?.allowedScopes);if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const limit=input.limit??50;let keys=await remember.list({scope,pattern:input.pattern});const truncated=keys.length>limit;if(truncated){keys=keys.slice(0,limit)}return{keys,scope,count:keys.length,truncated}}};ListMemoriesTool=__decorateClass([(0,import_sdk7.Tool)(listMemoriesToolMetadata())],ListMemoriesTool);var import_lazy_zod4=require("@frontmcp/lazy-zod");var import_sdk8=require("@frontmcp/sdk");var recallInputSchema={key:import_lazy_zod4.z.string().min(1).describe("What memory to recall"),scope:import_lazy_zod4.z.enum(MEMORY_TOOL_SCOPES).optional().describe(REMEMBER_SCOPE_DESCRIPTION)};var recallOutputSchema=import_lazy_zod4.z.object({found:import_lazy_zod4.z.boolean(),key:import_lazy_zod4.z.string(),value:import_lazy_zod4.z.unknown().optional(),scope:import_lazy_zod4.z.string(),createdAt:import_lazy_zod4.z.number().optional(),expiresAt:import_lazy_zod4.z.number().optional()});function recallDescription(names=rememberToolNames()){return`Recall something that was previously remembered. Use this to retrieve stored preferences, settings, or any information that was saved with ${names.rememberThis}.`}function recallToolMetadata(names=rememberToolNames()){return{name:names.recall,description:recallDescription(names),inputSchema:recallInputSchema,outputSchema:recallOutputSchema,annotations:{readOnlyHint:true}}}var RecallTool=class extends import_sdk8.ToolContext{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=allowedMemoryToolScopes(config.tools?.allowedScopes);if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const entry=await remember.getEntry(input.key,{scope});if(!entry){return{found:false,key:input.key,scope}}return{found:true,key:input.key,value:entry.value,scope,createdAt:entry.createdAt,expiresAt:entry.expiresAt}}};RecallTool=__decorateClass([(0,import_sdk8.Tool)(recallToolMetadata())],RecallTool);var import_lazy_zod5=require("@frontmcp/lazy-zod");var import_sdk9=require("@frontmcp/sdk");var rememberThisInputSchema={key:import_lazy_zod5.z.string().min(1).describe('What to call this memory (e.g., "user_preference", "last_action")'),value:import_lazy_zod5.z.unknown().describe("The value to remember (any JSON-serializable data)"),scope:import_lazy_zod5.z.enum(MEMORY_TOOL_SCOPES).optional().describe(REMEMBER_SCOPE_DESCRIPTION),ttl:import_lazy_zod5.z.number().int().positive().optional().describe("Forget after this many whole seconds"),brand:import_lazy_zod5.z.enum(["preference","cache","state","conversation","custom"]).optional().describe("Type hint for the stored value")};var rememberThisOutputSchema=import_lazy_zod5.z.object({success:import_lazy_zod5.z.boolean(),key:import_lazy_zod5.z.string(),scope:import_lazy_zod5.z.string(),expiresAt:import_lazy_zod5.z.number().optional()});function rememberThisDescription(names=rememberToolNames()){return`Remember something for later: store a value under a key that ${names.recall} can read back, in the scope you choose (this session by default; user scope for the signed-in user across sessions). It lasts until it is forgotten or its ttl runs out. Use this when the user asks you to remember preferences, settings, or any information they want to persist.`}function rememberThisToolMetadata(names=rememberToolNames()){return{name:names.rememberThis,description:rememberThisDescription(names),inputSchema:rememberThisInputSchema,outputSchema:rememberThisOutputSchema,annotations:{readOnlyHint:false}}}var RememberThisTool=class extends import_sdk9.ToolContext{async execute(input){const remember=this.get(RememberAccessorToken);const config=this.get(RememberConfigToken);const scope=input.scope??"session";const allowedScopes=allowedMemoryToolScopes(config.tools?.allowedScopes);if(!allowedScopes.includes(scope)){throw this.fail(new RememberScopeNotAllowedError(scope,allowedScopes))}const entry=await remember.set(input.key,input.value,{scope,ttl:input.ttl,brand:input.brand});return{success:true,key:input.key,scope,expiresAt:entry.expiresAt}}};RememberThisTool=__decorateClass([(0,import_sdk9.Tool)(rememberThisToolMetadata())],RememberThisTool);function createRememberTools(prefix=""){if(!prefix)return[RememberThisTool,RecallTool,ForgetTool,ListMemoriesTool];const names=rememberToolNames(prefix);let PrefixedRememberThisTool=class extends RememberThisTool{};PrefixedRememberThisTool=__decorateClass([(0,import_sdk10.Tool)(rememberThisToolMetadata(names))],PrefixedRememberThisTool);let PrefixedRecallTool=class extends RecallTool{};PrefixedRecallTool=__decorateClass([(0,import_sdk10.Tool)(recallToolMetadata(names))],PrefixedRecallTool);let PrefixedForgetTool=class extends ForgetTool{};PrefixedForgetTool=__decorateClass([(0,import_sdk10.Tool)(forgetToolMetadata(names))],PrefixedForgetTool);let PrefixedListMemoriesTool=class extends ListMemoriesTool{};PrefixedListMemoriesTool=__decorateClass([(0,import_sdk10.Tool)(listMemoriesToolMetadata(names))],PrefixedListMemoriesTool);return[PrefixedRememberThisTool,PrefixedRecallTool,PrefixedForgetTool,PrefixedListMemoriesTool]}function withCheckedOptions(options){const customKey=options.encryption?.customKey;if(customKey!==void 0&&customKey.trim()===""){throw new RememberConfigurationError("RememberPlugin encryption.customKey must not be empty; omit it to derive keys from the server secret")}const{defaultTTL}=options;if(defaultTTL===void 0)return options;if(defaultTTL===0)return{...options,defaultTTL:void 0};if(!Number.isInteger(defaultTTL)||defaultTTL<0){throw new RememberConfigurationError(`RememberPlugin defaultTTL must be a whole number of seconds (0 for no default expiry), got ${defaultTTL}`)}return options}var RememberPlugin=class extends import_sdk11.DynamicPlugin{options;constructor(options={}){super();this.options={...RememberPlugin.defaultOptions,...withCheckedOptions(options)}}};__publicField(RememberPlugin,"defaultOptions",{type:"memory",keyPrefix:"remember:",encryption:{enabled:true}});__publicField(RememberPlugin,"dynamicTools",options=>options.tools?.enabled?createRememberTools(options.tools.prefix):[]);__publicField(RememberPlugin,"browserStores",(options,server)=>{const type=options.type??RememberPlugin.defaultOptions.type;const onRedis=type==="redis"||type==="redis-client"||type==="global-store"&&server.redis!==void 0&&!(0,import_sdk11.isVercelKvProvider)(server.redis);return[{plugin:"RememberPlugin",option:onRedis?`type: '${type}'`:void 0,memory:"type: 'memory'"}]});__publicField(RememberPlugin,"dynamicProviders",options=>{const providers=[];const config={...RememberPlugin.defaultOptions,...withCheckedOptions(options)};switch(config.type){case"global-store":providers.push((0,import_sdk11.storeProvider)({name:"remember:store:global",provide:RememberStoreToken,inject:()=>[import_sdk11.FrontMcpConfig],useFactory:frontmcpConfig=>{const storeConfig=(0,import_sdk11.getGlobalStoreConfig)("RememberPlugin",frontmcpConfig);if((0,import_sdk11.isVercelKvProvider)(storeConfig)){return new RememberVercelKvProvider({url:storeConfig.url,token:storeConfig.token,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})}return new RememberRedisProvider({type:"redis",config:{host:storeConfig.host??"localhost",port:storeConfig.port??6379,password:storeConfig.password,db:storeConfig.db},keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})}}));break;case"redis":if("config"in config&&config.config){const redisConfig=config.config;let store;providers.push((0,import_sdk11.storeProvider)({name:"remember:store:redis",provide:RememberStoreToken,inject:()=>[],useFactory:()=>store??=new RememberRedisProvider({type:"redis",config:redisConfig,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})}))}break;case"redis-client":if("client"in config&&config.client){providers.push({name:"remember:store:redis-client",provide:RememberStoreToken,useValue:new RememberRedisProvider({type:"redis-client",client:config.client,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})})}break;case"vercel-kv":providers.push({name:"remember:store:vercel-kv",provide:RememberStoreToken,useValue:new RememberVercelKvProvider({url:"url"in config?config.url:void 0,token:"token"in config?config.token:void 0,keyPrefix:config.keyPrefix,defaultTTL:config.defaultTTL})});break;case"memory":default:providers.push({name:"remember:store:memory",provide:RememberStoreToken,inject:()=>[],useFactory:()=>new RememberMemoryProvider(void 0,config.defaultTTL)});break}providers.push({name:"remember:config",provide:RememberConfigToken,useValue:config});providers.push({name:"remember:accessor",provide:RememberAccessorToken,scope:import_sdk11.ProviderScope.CONTEXT,inject:()=>[RememberStoreToken,import_sdk11.FRONTMCP_CONTEXT,RememberConfigToken,import_sdk11.FrontMcpLogger],useFactory:(store,ctx,cfg,logger)=>createRememberAccessor(store,ctx,cfg,logger)});return providers});RememberPlugin=__decorateClass([(0,import_sdk11.Plugin)({name:"remember",description:"Help your LLM remember things across sessions",providers:[{name:"remember:store:memory",provide:RememberStoreToken,inject:()=>[],useFactory:()=>new RememberMemoryProvider}],contextExtensions:[{property:"remember",token:RememberAccessorToken,errorMessage:"RememberPlugin is not installed. Add RememberPlugin.init() to your plugins array."}]})],RememberPlugin);var import_lazy_zod6=require("@frontmcp/lazy-zod");var rememberScopeSchema=import_lazy_zod6.z.enum(["session","user","tool","global"]);function brand(data,_brand){return data}var rememberEntrySchema=import_lazy_zod6.z.object({value:import_lazy_zod6.z.unknown(),brand:import_lazy_zod6.z.enum(["approval","preference","cache","state","conversation","custom"]).optional(),createdAt:import_lazy_zod6.z.number(),updatedAt:import_lazy_zod6.z.number(),expiresAt:import_lazy_zod6.z.number().optional(),metadata:import_lazy_zod6.z.record(import_lazy_zod6.z.string(),import_lazy_zod6.z.unknown()).optional()});function getRemember(ctx){return ctx.get(RememberAccessorToken)}function tryGetRemember(ctx){if(typeof ctx.tryGet==="function"){return ctx.tryGet(RememberAccessorToken)}return void 0}0&&(module.exports={ForgetTool,ListMemoriesTool,RecallTool,RememberAccessor,RememberAccessorToken,RememberConfigToken,RememberConfigurationError,RememberIdentityError,RememberMemoryProvider,RememberPlugin,RememberRedisProvider,RememberScopeNotAllowedError,RememberStoreToken,RememberThisTool,RememberVercelKvProvider,brand,getRemember,tryGetRemember});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/plugin-remember",
3
- "version": "1.11.2",
3
+ "version": "1.12.0-rc.1",
4
4
  "description": "Remember plugin for FrontMCP: encrypted key-value memory for tools (this.remember) in session, user, tool and global scopes, stored in memory, Redis or Vercel KV",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "license": "Apache-2.0",
@@ -52,12 +52,12 @@
52
52
  }
53
53
  },
54
54
  "dependencies": {
55
- "@frontmcp/utils": "1.11.2",
55
+ "@frontmcp/utils": "1.12.0-rc.1",
56
56
  "ioredis": "^5.8.0"
57
57
  },
58
58
  "peerDependencies": {
59
- "@frontmcp/lazy-zod": "1.11.2",
60
- "@frontmcp/sdk": "1.11.2",
59
+ "@frontmcp/lazy-zod": "1.12.0-rc.1",
60
+ "@frontmcp/sdk": "1.12.0-rc.1",
61
61
  "@vercel/kv": "^2.0.0 || ^3.0.0"
62
62
  },
63
63
  "peerDependenciesMeta": {
@@ -66,7 +66,7 @@
66
66
  }
67
67
  },
68
68
  "devDependencies": {
69
- "@frontmcp/sdk": "1.11.2",
69
+ "@frontmcp/sdk": "1.12.0-rc.1",
70
70
  "reflect-metadata": "^0.2.2"
71
71
  }
72
72
  }
@@ -1,6 +1,6 @@
1
1
  import { Reference } from '@frontmcp/sdk';
2
- import type { RememberStoreInterface } from './providers/remember-store.interface';
3
2
  import type { RememberAccessor } from './providers/remember-accessor.provider';
3
+ import type { RememberStoreInterface } from './providers/remember-store.interface';
4
4
  import type { RememberPluginOptions } from './remember.types';
5
5
  /**
6
6
  * DI token for the underlying storage provider.
@@ -1 +1 @@
1
- {"version":3,"file":"remember.symbols.d.ts","sourceRoot":"","sources":["../src/remember.symbols.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE9D;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,CAAC,sBAAsB,CAE3B,CAAC;AAEvC;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,qBAAqB,CAE5B,CAAC;AAEtC;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,CAAC,gBAAgB,CAE9B,CAAC"}
1
+ {"version":3,"file":"remember.symbols.d.ts","sourceRoot":"","sources":["../src/remember.symbols.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE9D;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,CAAC,sBAAsB,CAE3B,CAAC;AAEvC;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,qBAAqB,CAE5B,CAAC;AAEtC;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,CAAC,gBAAgB,CAE9B,CAAC"}
@@ -126,7 +126,7 @@ export interface BaseRememberPluginOptions {
126
126
  tools?: {
127
127
  /** Whether to expose tools to LLM (default: false) */
128
128
  enabled?: boolean;
129
- /** Restrict which scopes tools can access */
129
+ /** Restrict which scopes tools can access. The tools never offer `tool` scope, which is per tool. */
130
130
  allowedScopes?: RememberScope[];
131
131
  /** Tool name prefix (default: none) */
132
132
  prefix?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"remember.types.d.ts","sourceRoot":"","sources":["../src/remember.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"remember.types.d.ts","sourceRoot":"","sources":["../src/remember.types.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,6 @@ export declare const forgetInputSchema: {
9
9
  scope: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodEnum<{
10
10
  session: "session";
11
11
  user: "user";
12
- tool: "tool";
13
12
  global: "global";
14
13
  }>>;
15
14
  };
@@ -33,7 +32,6 @@ export declare function forgetToolMetadata(names?: RememberToolNames): {
33
32
  scope: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodEnum<{
34
33
  session: "session";
35
34
  user: "user";
36
- tool: "tool";
37
35
  global: "global";
38
36
  }>>;
39
37
  };
@@ -1 +1 @@
1
- {"version":3,"file":"forget.tool.d.ts","sourceRoot":"","sources":["../../src/tools/forget.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AACvC,OAAO,EAAQ,WAAW,EAAE,MAAM,eAAe,CAAC;AAKlD,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAElF;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;CAG7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;gCAK7B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC;AAEzE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,wBAAgB,iBAAiB,IAAI,MAAM,CAK1C;AAED,wBAAgB,kBAAkB,CAAC,KAAK,GAAE,iBAAuC;;;;;;;;;;;;;;;;;;;;;EAQhF;AAED;;GAEG;AAEH,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,WAAW;IAC3C,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAyBzD"}
1
+ {"version":3,"file":"forget.tool.d.ts","sourceRoot":"","sources":["../../src/tools/forget.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AACvC,OAAO,EAAQ,WAAW,EAAE,MAAM,eAAe,CAAC;AAKlD,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAElF;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;CAG7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;gCAK7B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC;AAEzE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,wBAAgB,iBAAiB,IAAI,MAAM,CAK1C;AAED,wBAAgB,kBAAkB,CAAC,KAAK,GAAE,iBAAuC;;;;;;;;;;;;;;;;;;;;EAQhF;AAED;;GAEG;AAEH,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,WAAW;IAC3C,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAyBzD"}
@@ -8,7 +8,6 @@ export declare const listMemoriesInputSchema: {
8
8
  scope: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodEnum<{
9
9
  session: "session";
10
10
  user: "user";
11
- tool: "tool";
12
11
  global: "global";
13
12
  }>>;
14
13
  pattern: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
@@ -33,7 +32,6 @@ export declare function listMemoriesToolMetadata(names?: RememberToolNames): {
33
32
  scope: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodEnum<{
34
33
  session: "session";
35
34
  user: "user";
36
- tool: "tool";
37
35
  global: "global";
38
36
  }>>;
39
37
  pattern: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
@@ -1 +1 @@
1
- {"version":3,"file":"list-memories.tool.d.ts","sourceRoot":"","sources":["../../src/tools/list-memories.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AACvC,OAAO,EAAQ,WAAW,EAAE,MAAM,eAAe,CAAC;AAKlD,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAElF;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;CAInC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;gCAKnC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,uBAAuB,CAAC,CAAC,CAAC;AAErF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,wBAAgB,uBAAuB,CAAC,KAAK,GAAE,iBAAuC,GAAG,MAAM,CAK9F;AAED,wBAAgB,wBAAwB,CAAC,KAAK,GAAE,iBAAuC;;;;;;;;;;;;;;;;;;;;;;EAQtF;AAED;;GAEG;AAEH,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,WAAW;IACjD,OAAO,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CA8BrE"}
1
+ {"version":3,"file":"list-memories.tool.d.ts","sourceRoot":"","sources":["../../src/tools/list-memories.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AACvC,OAAO,EAAQ,WAAW,EAAE,MAAM,eAAe,CAAC;AAKlD,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAElF;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;CAInC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;gCAKnC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,uBAAuB,CAAC,CAAC,CAAC;AAErF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,wBAAgB,uBAAuB,CAAC,KAAK,GAAE,iBAAuC,GAAG,MAAM,CAK9F;AAED,wBAAgB,wBAAwB,CAAC,KAAK,GAAE,iBAAuC;;;;;;;;;;;;;;;;;;;;;EAQtF;AAED;;GAEG;AAEH,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,WAAW;IACjD,OAAO,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CA8BrE"}
@@ -1,6 +1,5 @@
1
1
  import { z } from '@frontmcp/lazy-zod';
2
2
  import { ToolContext } from '@frontmcp/sdk';
3
- import type { RememberScope } from '../remember.types';
4
3
  import { type RememberToolNames } from './remember-tool-names';
5
4
  /**
6
5
  * Input schema for the recall tool.
@@ -10,7 +9,6 @@ export declare const recallInputSchema: {
10
9
  scope: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodEnum<{
11
10
  session: "session";
12
11
  user: "user";
13
- tool: "tool";
14
12
  global: "global";
15
13
  }>>;
16
14
  };
@@ -25,10 +23,7 @@ export declare const recallOutputSchema: import("@frontmcp/lazy-zod").ZodObject<
25
23
  createdAt: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodNumber>;
26
24
  expiresAt: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodNumber>;
27
25
  }, import("zod/v4/core").$strip>;
28
- export type RecallInput = {
29
- key: string;
30
- scope?: RememberScope;
31
- };
26
+ export type RecallInput = z.infer<z.ZodObject<typeof recallInputSchema>>;
32
27
  export type RecallOutput = z.infer<typeof recallOutputSchema>;
33
28
  export declare function recallDescription(names?: RememberToolNames): string;
34
29
  export declare function recallToolMetadata(names?: RememberToolNames): {
@@ -39,7 +34,6 @@ export declare function recallToolMetadata(names?: RememberToolNames): {
39
34
  scope: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodEnum<{
40
35
  session: "session";
41
36
  user: "user";
42
- tool: "tool";
43
37
  global: "global";
44
38
  }>>;
45
39
  };
@@ -1 +1 @@
1
- {"version":3,"file":"recall.tool.d.ts","sourceRoot":"","sources":["../../src/tools/recall.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AACvC,OAAO,EAAQ,WAAW,EAAE,MAAM,eAAe,CAAC;AAIlD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAElF;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;CAG7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;;;gCAO7B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,wBAAgB,iBAAiB,CAAC,KAAK,GAAE,iBAAuC,GAAG,MAAM,CAKxF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,GAAE,iBAAuC;;;;;;;;;;;;;;;;;;;;;;;EAQhF;AAED;;GAEG;AAEH,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,WAAW;IAC3C,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAgCzD"}
1
+ {"version":3,"file":"recall.tool.d.ts","sourceRoot":"","sources":["../../src/tools/recall.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AACvC,OAAO,EAAQ,WAAW,EAAE,MAAM,eAAe,CAAC;AAKlD,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAElF;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;CAG7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;;;gCAO7B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC;AAEzE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,wBAAgB,iBAAiB,CAAC,KAAK,GAAE,iBAAuC,GAAG,MAAM,CAKxF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,GAAE,iBAAuC;;;;;;;;;;;;;;;;;;;;;;EAQhF;AAED;;GAEG;AAEH,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,WAAW;IAC3C,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAgCzD"}
@@ -1,10 +1,17 @@
1
+ import type { RememberScope } from '../remember.types';
2
+ /**
3
+ * The scopes the memory tools offer. `tool` scope is the memory of the tool that runs the call, so what
4
+ * `remember_this` stored there `recall` never found: the tools leave it out.
5
+ */
6
+ export declare const MEMORY_TOOL_SCOPES: readonly ["session", "user", "global"];
7
+ /** The scopes a memory tool accepts: `tools.allowedScopes` without `tool`, else every scope the tools offer. */
8
+ export declare function allowedMemoryToolScopes(allowedScopes: readonly RememberScope[] | undefined): RememberScope[];
1
9
  /**
2
10
  * What each memory scope means, for the `scope` argument of all four Remember tools.
3
11
  *
4
12
  * One text, so the tools never disagree, and one that holds on every transport: under MCP
5
- * 2026-07-28 and on the stateless HTTP transport there is no session, and `session` and `tool`
6
- * memory then belong to the signed-in caller (`RememberAccessor.resolveSessionIdentity`). The
7
- * `tool` scope is the memory of the tool that runs the call, so each of these tools has its own.
13
+ * 2026-07-28 and on the stateless HTTP transport there is no session, and `session` memory then
14
+ * belongs to the signed-in caller (`RememberAccessor.resolveSessionIdentity`).
8
15
  */
9
16
  export declare const REMEMBER_SCOPE_DESCRIPTION: string;
10
17
  //# sourceMappingURL=remember-scope.description.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"remember-scope.description.d.ts","sourceRoot":"","sources":["../../src/tools/remember-scope.description.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,QAOoD,CAAC"}
1
+ {"version":3,"file":"remember-scope.description.d.ts","sourceRoot":"","sources":["../../src/tools/remember-scope.description.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,wCAAyC,CAAC;AAEzE,gHAAgH;AAChH,wBAAgB,uBAAuB,CAAC,aAAa,EAAE,SAAS,aAAa,EAAE,GAAG,SAAS,GAAG,aAAa,EAAE,CAE5G;AAED;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,QAK4C,CAAC"}
@@ -10,7 +10,6 @@ export declare const rememberThisInputSchema: {
10
10
  scope: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodEnum<{
11
11
  session: "session";
12
12
  user: "user";
13
- tool: "tool";
14
13
  global: "global";
15
14
  }>>;
16
15
  ttl: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodNumber>;
@@ -43,7 +42,6 @@ export declare function rememberThisToolMetadata(names?: RememberToolNames): {
43
42
  scope: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodEnum<{
44
43
  session: "session";
45
44
  user: "user";
46
- tool: "tool";
47
45
  global: "global";
48
46
  }>>;
49
47
  ttl: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodNumber>;
@@ -1 +1 @@
1
- {"version":3,"file":"remember-this.tool.d.ts","sourceRoot":"","sources":["../../src/tools/remember-this.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AACvC,OAAO,EAAQ,WAAW,EAAE,MAAM,eAAe,CAAC;AAKlD,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAElF;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;CASnC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;gCAKnC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,uBAAuB,CAAC,CAAC,CAAC;AAErF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,wBAAgB,uBAAuB,CAAC,KAAK,GAAE,iBAAuC,GAAG,MAAM,CAO9F;AAED,wBAAgB,wBAAwB,CAAC,KAAK,GAAE,iBAAuC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQtF;AAED;;;GAGG;AAEH,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,WAAW;IACjD,OAAO,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAyBrE"}
1
+ {"version":3,"file":"remember-this.tool.d.ts","sourceRoot":"","sources":["../../src/tools/remember-this.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AACvC,OAAO,EAAQ,WAAW,EAAE,MAAM,eAAe,CAAC;AAKlD,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAElF;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;CASnC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;gCAKnC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,uBAAuB,CAAC,CAAC,CAAC;AAErF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,wBAAgB,uBAAuB,CAAC,KAAK,GAAE,iBAAuC,GAAG,MAAM,CAO9F;AAED,wBAAgB,wBAAwB,CAAC,KAAK,GAAE,iBAAuC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQtF;AAED;;;GAGG;AAEH,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,WAAW;IACjD,OAAO,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAyBrE"}