UNPKG

@jeelidev/personal-neo4j-memory-server

Version:

Personal MCP Memory Server with Neo4j backend - Enhanced Cloudflare Access support with robust tunnel management and remove functionality

78 lines (77 loc) 25.4 kB
import{a as u,b,e as L,f as C,g as y}from"./chunk-R5RY4KXE.mjs";import{a as s,b as E,c as l,d as g,e as x,g as f,h as O}from"./chunk-ULWSXDW6.mjs";var v=class{resolveMemoryRequest(e,t){return{resolved:e.map(a=>({...a,from:this.resolveId(a.from,t),to:this.resolveId(a.to,t)})),mapping:t}}buildMapping(e){let t=new Map;for(let r of e)r.localId&&t.set(r.localId,r.id);return t}validateLocalIds(e){let t=new Set;for(let r of e)if(r.localId){if(t.has(r.localId))throw new Error(`Duplicate localId "${r.localId}" in request. LocalIds must be unique within a single operation.`);if(this.looksLikeRealId(r.localId))throw new Error(`Local ID cannot look like real memory ID: ${r.localId}`);t.add(r.localId)}}resolveId(e,t){if(!e)throw new Error("ID cannot be undefined in relation");let r=t.get(e);if(r)return r;if(!this.looksLikeRealId(e)){let a=Array.from(t.keys()).join(", ");throw new Error(`LocalId "${e}" not found. LocalIds only work within the same operation. Available localIds in this operation: [${a}]. For cross-operation references, use real memory IDs from previous responses.`)}return e}looksLikeRealId(e){return e.length!==18?!1:/^[0-9A-Za-z!#$%&()*+,\-./:;=?@_{}~`]+$/.test(e)}mappingToResponse(e){let t={};for(let[r,a]of e.entries())t[r]=a;return t}};var R=class{applyContextLevel(e,t="full"){switch(t){case"minimal":return this.applyMinimalContext(e);case"relations-only":return this.applyRelationsOnlyContext(e);case"full":default:return e}}applyMinimalContext(e){return e.map(t=>({id:t.id,name:t.name,memoryType:t.memoryType,...t.score!==void 0&&{score:t.score}}))}applyRelationsOnlyContext(e){return e.map(t=>({id:t.id,name:t.name,memoryType:t.memoryType,...t.score!==void 0&&{score:t.score},...t.related&&{related:t.related}}))}validateContextLevel(e){let t=["minimal","full","relations-only"];if(!t.includes(e))throw new Error(`Invalid context level: ${e}. Valid options: ${t.join(", ")}`);return e}getContextLevelDescription(e){switch(e){case"minimal":return"Only id, name, memoryType, score (for lists and quick references)";case"full":return"Complete memory data with observations and graph context (default)";case"relations-only":return"Only id, name, memoryType, and related context (graph analysis)"}}};var I=class{processDateFilters(e){let t=[],r={};if(e.createdAfter){let a=this.parseDate(e.createdAfter);t.push("m.createdAt >= $createdAfter"),r.createdAfter=a}if(e.createdBefore){let a=this.parseDate(e.createdBefore);t.push("m.createdAt <= $createdBefore"),r.createdBefore=a}if(e.modifiedSince){let a=this.parseDate(e.modifiedSince);t.push("m.modifiedAt >= $modifiedSince"),r.modifiedSince=a}if(e.accessedSince){let a=this.parseDate(e.accessedSince);t.push("m.lastAccessed >= $accessedSince"),r.accessedSince=a}return{cypher:t.length>0?t.join(" AND "):"",params:r}}parseDate(e){let t=e.match(/^(\d+)([hmdyHMDY])$/);if(t)return this.parseRelativeDate(parseInt(t[1]),t[2].toLowerCase());try{let r=new Date(e);if(isNaN(r.getTime()))throw new Error(`Invalid date format: ${e}`);return r.toISOString()}catch{throw new Error(`Invalid date format: ${e}. Use ISO format (2025-01-01) or relative format (1h, 24h, 7d, 30d, 3m, 1y)`)}}parseRelativeDate(e,t){let r=new Date;switch(t){case"h":r.setHours(r.getHours()-e);break;case"d":r.setDate(r.getDate()-e);break;case"m":r.setMonth(r.getMonth()-e);break;case"y":r.setFullYear(r.getFullYear()-e);break;default:throw new Error(`Invalid relative date unit: ${t}. Use 'h' (hours), 'd' (days), 'm' (months), or 'y' (years)`)}return r.toISOString()}validateDateFilters(e){if(e.createdAfter&&e.createdBefore){let t=new Date(this.parseDate(e.createdAfter)),r=new Date(this.parseDate(e.createdBefore));if(t>=r)throw new Error("createdAfter must be earlier than createdBefore")}Object.entries(e).forEach(([t,r])=>{if(r)try{this.parseDate(r)}catch(a){throw new Error(`Invalid ${t}: ${a instanceof Error?a.message:String(a)}`)}})}getSupportedFormats(){return['ISO dates: "2025-01-01", "2025-01-01T10:00:00Z"','Relative: "1h" (1 hour ago), "24h" (24 hours ago)','Relative: "7d" (7 days ago), "30d" (30 days ago)','Relative: "3m" (3 months ago), "1y" (1 year ago)']}};var M=class{processTraversal(e){this.validateTraversalOptions(e);let t=u(),r=Math.min(e.maxDepth||2,t.maxTraversalDepth),a=e.traverseDirection||"both",i=e.traverseRelations,o,n={startId:e.traverseFrom,maxDepth:r};switch(i&&i.length>0&&(n.relationTypes=i),a){case"outbound":o=this.buildOutboundTraversal(r,i);break;case"inbound":o=this.buildInboundTraversal(r,i);break;case"both":default:o=this.buildBidirectionalTraversal(r,i);break}return{cypher:o,params:n}}buildOutboundTraversal(e,t){return` MATCH (start:Memory {id: $startId}) MATCH path = (start)-[r:RELATES_TO*1..${e}]->(end:Memory) WHERE ${t?"ALL(rel IN relationships(path) WHERE rel.relationType IN $relationTypes) AND":""} end <> start AND end.id IS NOT NULL WITH end, length(path) as distance, relationships(path)[0] as firstRel RETURN DISTINCT end.id as id, end.name as name, end.memoryType as type, distance, firstRel.relationType as relation, firstRel.strength as strength, firstRel.source as source, firstRel.createdAt as createdAt ORDER BY distance ASC, end.name ASC LIMIT 50 `}buildInboundTraversal(e,t){return` MATCH (target:Memory {id: $startId}) MATCH path = (start:Memory)-[r:RELATES_TO*1..${e}]->(target) WHERE ${t?"ALL(rel IN relationships(path) WHERE rel.relationType IN $relationTypes) AND":""} start <> target AND start.id IS NOT NULL WITH start, length(path) as distance, relationships(path)[-1] as lastRel RETURN DISTINCT start.id as id, start.name as name, start.memoryType as type, distance, lastRel.relationType as relation, lastRel.strength as strength, lastRel.source as source, lastRel.createdAt as createdAt ORDER BY distance ASC, start.name ASC LIMIT 50 `}buildBidirectionalTraversal(e,t){return` MATCH (center:Memory {id: $startId}) MATCH path = (center)-[r:RELATES_TO*1..${e}]-(connected:Memory) WHERE ${t?"ALL(rel IN relationships(path) WHERE rel.relationType IN $relationTypes) AND":""} connected <> center AND connected.id IS NOT NULL WITH connected, length(path) as distance, CASE WHEN startNode(relationships(path)[0]) = center THEN relationships(path)[0] ELSE relationships(path)[-1] END as relevantRel RETURN DISTINCT connected.id as id, connected.name as name, connected.memoryType as type, distance, relevantRel.relationType as relation, relevantRel.strength as strength, relevantRel.source as source, relevantRel.createdAt as createdAt ORDER BY distance ASC, connected.name ASC LIMIT 50 `}validateTraversalOptions(e){if(!e.traverseFrom)throw new Error("traverseFrom memory ID is required for graph traversal");let t=u();if(e.maxDepth!==void 0&&(e.maxDepth<1||e.maxDepth>t.maxTraversalDepth))throw new Error(`maxDepth must be between 1 and ${t.maxTraversalDepth}`);let r=["outbound","inbound","both"];if(e.traverseDirection&&!r.includes(e.traverseDirection))throw new Error(`Invalid traversal direction: ${e.traverseDirection}. Valid options: ${r.join(", ")}`);if(e.traverseRelations&&e.traverseRelations.length===0)throw new Error("traverseRelations array cannot be empty if provided")}processTraversalResults(e){return e.map(t=>({id:t.id,name:t.name,type:t.type,distance:this.convertNeo4jInteger(t.distance),relation:t.relation,strength:t.strength,source:t.source,createdAt:t.createdAt}))}convertNeo4jInteger(e){return typeof e=="number"?e:e&&typeof e.toNumber=="function"?e.toNumber():0}getSupportedDirections(){return["outbound: What this memory influences","inbound: What influences this memory","both: All connected memories (default)"]}};var A=class{constructor(e,t){this.memoryHandler=e,this.relationHandler=t,this.localIdResolver=new v}async handleMemoryStore(e){let t=this.applyDefaultOptions(e.options);return t.transactional?this.handleTransactionalStore(e,t):this.handleNonTransactionalStore(e,t)}async handleTransactionalStore(e,t){let i=y.getInstance().getSessionFactory().createSession(),o=i.beginTransaction();try{this.validateStoreRequest(e,t);let n=await this.createMemoriesInTransaction(o,e.memories),c=this.localIdResolver.buildMapping(e.memories.map((m,D)=>({localId:m.localId,id:n[D]}))),d=await this.createRelationsInTransaction(o,e.relations||[],c);return await o.commit(),this.buildSuccessResponse(n,d,c,t)}catch(n){await o.rollback();let c=O(n);return c?this.buildErrorResponse(c,t):this.buildErrorResponse(n,t)}finally{await i.close()}}async createMemoriesInTransaction(e,t){let r=[];for(let a of t){let i=b(),o=` CREATE (m:Memory { id: $id, name: $name, memoryType: $memoryType, metadata: $metadata, createdAt: $createdAt, modifiedAt: $modifiedAt, lastAccessed: $lastAccessed }) RETURN m.id as id `,n=new Date().toISOString();await e.run(o,{id:i,name:a.name,memoryType:a.memoryType,metadata:JSON.stringify(a.metadata||{}),createdAt:n,modifiedAt:n,lastAccessed:n});for(let c of a.observations){let d=b();await e.run(` MATCH (m:Memory {id: $memoryId}) CREATE (o:Observation { id: $obsId, content: $content, createdAt: $timestamp }) CREATE (m)-[:HAS_OBSERVATION]->(o) `,{memoryId:i,obsId:d,content:c,timestamp:new Date().toISOString()})}r.push(i)}return r}async createRelationsInTransaction(e,t,r){let a=[];for(let i of t){let o=this.resolveId(i.from,r),n=this.resolveId(i.to,r);if((await e.run(` MATCH (from:Memory {id: $fromId}), (to:Memory {id: $toId}) CREATE (from)-[:RELATES_TO { relationType: $relationType, strength: $strength, source: $source, createdAt: $createdAt }]->(to) RETURN from.id as fromId, to.id as toId `,{fromId:o,toId:n,relationType:i.type,strength:i.strength||.5,source:i.source||"agent",createdAt:new Date().toISOString()})).records.length===0)throw new g(`Failed to create relation: ${o} \u2192 ${n} (${i.type}). One or both memories do not exist.`,s.MEMORY_NOT_FOUND,{fromId:o,toId:n,relationType:i.type});a.push({from:o,to:n,type:i.type,strength:i.strength||.5,source:i.source||"agent"})}return a}async handleNonTransactionalStore(e,t){try{this.validateStoreRequest(e,t);let r=await this.createMemories(e.memories),a=this.localIdResolver.buildMapping(e.memories.map((o,n)=>({localId:o.localId,id:r[n]}))),i=await this.createRelations(e.relations||[],a);return this.buildSuccessResponse(r,i,a,t)}catch(r){return this.buildErrorResponse(r,t)}}async createMemories(e){let t=e.map(a=>({name:a.name,memoryType:a.memoryType,metadata:a.metadata||{},observations:a.observations||[]})),r=await this.memoryHandler.handleMemoryManage({operation:"create",memories:t});if(!r.success)throw new f(`Memory creation failed: ${r.results.map(a=>a.error).filter(Boolean).join("; ")}`,s.DATABASE_OPERATION_FAILED,{errors:r.results.filter(a=>a.error)});return r.results.filter(a=>a.status==="created").map(a=>a.id)}async createRelations(e,t){if(e.length===0)return[];let r;try{r=e.map(o=>({fromId:this.resolveId(o.from,t),toId:this.resolveId(o.to,t),relationType:o.type,strength:o.strength||.5,source:o.source||"agent"}))}catch(o){throw new l(`Local ID resolution failed: ${o instanceof Error?o.message:String(o)}`,s.INVALID_LOCAL_ID,{originalError:o instanceof Error?o.message:String(o)})}let a=await this.relationHandler.handleRelationManage({operation:"create",relations:r}),i=a.results.filter(o=>o.status==="failed");if(i.length>0){let o=i.map(n=>`${n.fromId} \u2192 ${n.toId} (${n.relationType}): ${n.error||"Unknown error"}`);throw new f(`Relation creation failed: ${o.join("; ")}`,s.DATABASE_OPERATION_FAILED,{failedRelations:i})}return a.results.filter(o=>o.status==="created").map(o=>({from:o.fromId,to:o.toId,type:o.relationType,strength:r.find(n=>n.fromId===o.fromId&&n.toId===o.toId&&n.relationType===o.relationType)?.strength||.5,source:r.find(n=>n.fromId===o.fromId&&n.toId===o.toId&&n.relationType===o.relationType)?.source||"agent"}))}resolveId(e,t){return t.get(e)||e}validateStoreRequest(e,t){if(e.memories.length===0)throw new l("memories array cannot be empty",s.EMPTY_ARRAY);if(e.memories.length>t.maxMemories)throw new l(`Too many memories: ${e.memories.length} > ${t.maxMemories}`,s.INVALID_MEMORY_COUNT,{requested:e.memories.length,limit:t.maxMemories});if(e.relations&&e.relations.length>t.maxRelations)throw new l(`Too many relations: ${e.relations.length} > ${t.maxRelations}`,s.INVALID_RELATION_COUNT,{requested:e.relations.length,limit:t.maxRelations});this.localIdResolver.validateLocalIds(e.memories);for(let r of e.memories){if(!r.name?.trim())throw new l("Memory name cannot be empty",s.INVALID_NAME);if(!r.memoryType?.trim())throw new l("Memory type cannot be empty",s.INVALID_TYPE);if(!r.observations||r.observations.length===0)throw new l(`Memory "${r.name}" must have at least one observation`,s.EMPTY_ARRAY,{memoryName:r.name})}if(e.relations)for(let r of e.relations){if(!r.from?.trim()||!r.to?.trim())throw new l("Relation from/to IDs cannot be empty",s.VALIDATION_FAILED,{from:r.from,to:r.to});if(!r.type?.trim())throw new l("Relation type cannot be empty",s.INVALID_TYPE);if(r.strength!==void 0&&(r.strength<0||r.strength>1))throw new l(`Relation strength must be between 0.0 and 1.0, got: ${r.strength}`,s.INVALID_STRENGTH,{providedStrength:r.strength})}}applyDefaultOptions(e){let t=u();return{validateReferences:e?.validateReferences??!0,allowDuplicateRelations:e?.allowDuplicateRelations??!1,transactional:e?.transactional??!0,maxMemories:e?.maxMemories??t.maxMemoriesPerOperation,maxRelations:e?.maxRelations??t.maxRelationsPerOperation}}buildSuccessResponse(e,t,r,a){let i=y.getInstance().getCurrentDatabase();return{success:!0,created:e,connected:t,localIdMap:this.localIdResolver.mappingToResponse(r),limits:{memoriesLimit:a.maxMemories,relationsLimit:a.maxRelations},_meta:{database:i.database,operation:"store",timestamp:new Date().toISOString()}}}buildErrorResponse(e,t){let r=e instanceof Error?e.message:String(e),a=y.getInstance().getCurrentDatabase();return{success:!1,created:[],connected:[],errors:[r],limits:{memoriesLimit:t.maxMemories,relationsLimit:t.maxRelations},_meta:{database:a.database,operation:"store",timestamp:new Date().toISOString()}}}};var T=class{constructor(e){this.memoryHandler=e,this.contextProcessor=new R,this.dateProcessor=new I,this.graphProcessor=new M}async handleMemoryFind(e){let t=Date.now();try{this.validateFindRequest(e);let r=e.includeContext||"full",a;e.traverseFrom?a=await this.handleGraphTraversal(e):Array.isArray(e.query)||this.isStringifiedArray(e.query)?a=await this.handleDirectRetrieval(e):a=await this.handleSearch(e);let i=this.contextProcessor.applyContextLevel(a.memories||[],r),o=y.getInstance().getCurrentDatabase();return{memories:i,_meta:{database:o.database,total:i.length,query:e.query,queryTime:Date.now()-t,contextLevel:r}}}catch(r){throw r instanceof Error&&r.message.includes("Invalid context level")?new l(r.message,s.INVALID_CONTEXT_LEVEL):new x(`Memory find failed: ${r instanceof Error?r.message:String(r)}`,s.SERVICE_UNAVAILABLE,{originalError:r instanceof Error?r.message:String(r)})}}async handleGraphTraversal(e){if(!e.traverseFrom)throw new l("traverseFrom is required for graph traversal",s.VALIDATION_FAILED);let t={traverseFrom:e.traverseFrom,traverseRelations:e.traverseRelations,maxDepth:e.maxDepth,traverseDirection:e.traverseDirection},r=this.graphProcessor.processTraversal(t),o=y.getInstance().getSessionFactory().createSession();try{let n=await o.run(r.cypher,r.params),c=this.graphProcessor.processTraversalResults(n.records.map(p=>({id:p.get("id"),name:p.get("name"),type:p.get("type"),distance:p.get("distance"),relation:p.get("relation"),strength:p.get("strength"),source:p.get("source"),createdAt:p.get("createdAt")}))),d=c.map(p=>p.id);return d.length===0?{memories:[]}:{memories:(await this.memoryHandler.handleMemoryRetrieve(d)).memories.map(p=>{let S=c.find(F=>F.id===p.id);if(!S)return p;let N=this.buildTraversalRelationshipContext(e.traverseFrom,e.traverseDirection||"both",S);return{...p,related:N}})}}finally{await o.close()}}buildTraversalRelationshipContext(e,t,r){let a={id:e,name:e,type:"starting_point",relation:r.relation,distance:r.distance,strength:r.strength,source:r.source,createdAt:r.createdAt};switch(t){case"outbound":return{ancestors:[a]};case"inbound":return{descendants:[a]};case"both":default:return{related:[a]}}}async handleDirectRetrieval(e){let t=this.parseQueryArray(e.query);e.memoryTypes&&e.memoryTypes.length>0;let r=await this.memoryHandler.handleMemoryRetrieve(t);return e.memoryTypes&&e.memoryTypes.length>0&&(r.memories=r.memories.filter(a=>e.memoryTypes.includes(a.memoryType))),r}async handleSearch(e){if(typeof e.query!="string")throw new l("Query must be string for search operation",s.INVALID_QUERY,{queryType:typeof e.query});let t=this.extractDateFilters(e),r={cypher:"",params:{}};return Object.keys(t).length>0&&(this.dateProcessor.validateDateFilters(t),r=this.dateProcessor.processDateFilters(t)),e.query==="*"?await this.executeWildcardSearchWithDateFilters(e.limit||10,e.includeContext!=="minimal",e.memoryTypes,r):await this.memoryHandler.handleMemorySearch(e.query,e.limit||10,e.includeContext!=="minimal",e.memoryTypes,e.threshold||.1)}extractDateFilters(e){return{createdAfter:e.createdAfter,createdBefore:e.createdBefore,modifiedSince:e.modifiedSince,accessedSince:e.accessedSince}}async executeWildcardSearchWithDateFilters(e,t,r,a){let i=this.memoryHandler.container;await i.initializeDatabase();let n=i.getSessionFactory().createSession();try{let d=await new C(n).search(e,t,r,a?.cypher,a?.params);return{memories:d.map(m=>({id:m.id,name:m.name,memoryType:m.type,observations:m.observations,metadata:m.metadata,createdAt:m.createdAt,modifiedAt:m.modifiedAt,lastAccessed:m.lastAccessed,score:m.score,related:m.related})),_meta:{database:i.getCurrentDatabase(),total:d.length,query:"*",queryTime:0,contextLevel:t?"full":"minimal"}}}finally{await n.close()}}isStringifiedArray(e){if(typeof e!="string"||!e.startsWith("[")||!e.endsWith("]"))return!1;try{let t=JSON.parse(e);return Array.isArray(t)&&t.every(r=>typeof r=="string")}catch{return!1}}parseQueryArray(e){if(Array.isArray(e))return e;if(typeof e=="string"&&this.isStringifiedArray(e))try{return JSON.parse(e)}catch{return[e]}return[e]}validateFindRequest(e){if(!e.query)throw new l("query parameter is required",s.VALIDATION_FAILED);if(e.limit!==void 0&&e.limit<=0)throw new l("limit must be positive",s.INVALID_PARAMS,{limit:e.limit});if(e.threshold!==void 0&&(e.threshold<0||e.threshold>1))throw new l("threshold must be between 0.0 and 1.0",s.VALIDATION_FAILED,{threshold:e.threshold});e.includeContext&&this.contextProcessor.validateContextLevel(e.includeContext);let t=["relevance","created","modified","accessed"];if(e.orderBy&&!t.includes(e.orderBy))throw new l(`Invalid orderBy: ${e.orderBy}. Valid options: ${t.join(", ")}`,s.VALIDATION_FAILED,{providedOrderBy:e.orderBy,validOptions:t});if((e.traverseFrom||e.traverseRelations||e.maxDepth||e.traverseDirection)&&!e.traverseFrom)throw new l("traverseFrom is required when using graph traversal parameters",s.INVALID_TRAVERSAL_OPTIONS)}};var w=class{constructor(e,t,r){this.memoryHandler=e,this.observationHandler=t,this.relationHandler=r}async handleMemoryModify(e){try{this.validateModifyRequest(e);let t;switch(e.operation){case"update":t=await this.handleUpdate(e);break;case"delete":t=await this.handleDelete(e);break;case"batch-delete":t=await this.handleBatchDelete(e);break;case"add-observations":t=await this.handleAddObservations(e);break;case"delete-observations":t=await this.handleDeleteObservations(e);break;case"create-relations":t=await this.handleCreateRelations(e);break;case"update-relations":t=await this.handleUpdateRelations(e);break;case"delete-relations":t=await this.handleDeleteRelations(e);break;default:throw new l(`Unknown operation: ${e.operation}`,s.VALIDATION_FAILED,{operation:e.operation})}return this.formatResponse(t,e.operation)}catch(t){if(t instanceof l||t instanceof g||t instanceof f)throw t;return this.buildErrorResponse(t,e.operation)}}async handleUpdate(e){if(!e.target||!e.changes)throw new l("target and changes are required for update operation",s.VALIDATION_FAILED,{hasTarget:!!e.target,hasChanges:!!e.changes});return await this.memoryHandler.handleMemoryManage({operation:"update",updates:[{id:e.target,...e.changes}]})}async handleDelete(e){if(!e.target)throw new l("target is required for delete operation",s.INVALID_REQUEST_PARAMS);return await this.memoryHandler.handleMemoryManage({operation:"delete",identifiers:[e.target]})}async handleBatchDelete(e){if(!e.targets||e.targets.length===0)throw new l("targets array is required for batch-delete operation",s.INVALID_REQUEST_PARAMS);return await this.memoryHandler.handleMemoryManage({operation:"delete",identifiers:e.targets})}async handleAddObservations(e){if(!e.observations||e.observations.length===0)throw new l("observations array is required for add-observations operation",s.INVALID_REQUEST_PARAMS);return await this.observationHandler.handleObservationManage({operation:"add",observations:e.observations})}async handleDeleteObservations(e){if(!e.observations||e.observations.length===0)throw new l("observations array is required for delete-observations operation",s.INVALID_REQUEST_PARAMS);return await this.observationHandler.handleObservationManage({operation:"delete",observations:e.observations})}async handleCreateRelations(e){if(!e.relations||e.relations.length===0)throw new l("relations array is required for create-relations operation",s.INVALID_REQUEST_PARAMS);return await this.relationHandler.handleRelationManage({operation:"create",relations:e.relations.map(t=>({fromId:t.from,toId:t.to,relationType:t.type,strength:t.strength,source:t.source}))})}async handleUpdateRelations(e){if(!e.relations||e.relations.length===0)throw new l("relations array is required for update-relations operation",s.INVALID_REQUEST_PARAMS);let r=y.getInstance().getSessionFactory(),a=new L,i=[];for(let n of e.relations){let c=r.createSession();try{let d={fromId:n.from,toId:n.to,relationType:n.type,strength:n.strength||.5,source:n.source||"agent",createdAt:new Date().toISOString()};if(!await a.updateEnhancedRelation(c,d))throw new f(`Relation not found: ${n.from} \u2192 ${n.to} (${n.type})`,s.RESOURCE_NOT_FOUND);i.push({fromId:n.from,toId:n.to,relationType:n.type,status:"updated"})}catch(d){throw d instanceof E?d:new g(`Failed to update relation: ${d instanceof Error?d.message:String(d)}`,s.DATABASE_OPERATION_FAILED)}finally{await c.close()}}let o=y.getInstance().getCurrentDatabase();return{success:!0,results:i,summary:{requested:e.relations.length,succeeded:i.filter(n=>n.status==="updated").length,failed:i.filter(n=>n.status==="failed").length,not_found:i.filter(n=>n.status==="not_found").length},_meta:{database:o.database,operation:"update-relations",timestamp:new Date().toISOString()}}}async handleDeleteRelations(e){if(!e.relations||e.relations.length===0)throw new l("relations array is required for delete-relations operation",s.INVALID_REQUEST_PARAMS);return await this.relationHandler.handleRelationManage({operation:"delete",relations:e.relations.map(t=>({fromId:t.from,toId:t.to,relationType:t.type}))})}formatResponse(e,t){let r=y.getInstance().getCurrentDatabase();return{success:e.success||!0,results:e.results||[],summary:e.summary||{requested:1,succeeded:e.success?1:0,failed:e.success?0:1},_meta:{database:r.database,operation:t,timestamp:new Date().toISOString()}}}buildErrorResponse(e,t){let r=e instanceof Error?e.message:String(e),a=y.getInstance().getCurrentDatabase();return{success:!1,results:[{id:"error",status:"failed",error:r}],summary:{requested:1,succeeded:0,failed:1},_meta:{database:a.database,operation:t,timestamp:new Date().toISOString()}}}validateModifyRequest(e){if(!e.operation)throw new l("operation is required",s.INVALID_REQUEST_PARAMS);let t=["update","delete"],r=["batch-delete"],a=["add-observations","delete-observations"],i=["create-relations","update-relations","delete-relations"];if(t.includes(e.operation)&&!e.target)throw new l(`${e.operation} operation requires target parameter`,s.INVALID_REQUEST_PARAMS);if(r.includes(e.operation)&&(!e.targets||e.targets.length===0))throw new l(`${e.operation} operation requires targets array`,s.INVALID_REQUEST_PARAMS);if(a.includes(e.operation)&&(!e.observations||e.observations.length===0))throw new l(`${e.operation} operation requires observations array`,s.INVALID_REQUEST_PARAMS);if(i.includes(e.operation)&&(!e.relations||e.relations.length===0))throw new l(`${e.operation} operation requires relations array`,s.INVALID_REQUEST_PARAMS)}};export{v as a,R as b,I as c,M as d,A as e,T as f,w as g};