update_faction
Modify an existing faction's details in the MemoryMesh knowledge graph, including its name, type, description, goals, leader, or metadata, to reflect updated information accurately.
Instructions
Update an existing faction in the knowledge graph
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| update_faction | Yes |
Implementation Reference
- Main handler function for all dynamic 'update_<schema>' tools including 'update_faction'. Performs transaction-based update of node metadata and edges.export async function handleSchemaUpdate( updates: NodeData, schema: SchemaConfig, nodeType: string, applicationManager: ApplicationManager ): Promise<ToolResponse> { try { // Start a transaction to ensure atomic updates await applicationManager.beginTransaction(); // Get the complete current state const fullGraph = await applicationManager.readGraph(); const node = fullGraph.nodes.find((n: Node) => n.nodeType === nodeType && n.name === updates.name); if (!node) { await applicationManager.rollback(); return formatToolError({ operation: 'updateSchema', error: `${nodeType} "${updates.name}" not found`, context: {updates, nodeType}, suggestions: ["Verify the node exists", "Check node type matches"] }); } try { // Process updates const {metadata, edgeChanges} = await updateSchemaNode( updates, node, schema, fullGraph ); // Update the node first const updatedNode: Node = { ...node, metadata }; await applicationManager.updateNodes([updatedNode]); // Then handle edges if there are any changes if (edgeChanges.remove.length > 0) { await applicationManager.deleteEdges(edgeChanges.remove); } if (edgeChanges.add.length > 0) { await applicationManager.addEdges(edgeChanges.add); } // If everything succeeded, commit the transaction await applicationManager.commit(); return formatToolResponse({ data: { updatedNode, edgeChanges }, actionTaken: `Updated ${nodeType}: ${updatedNode.name}` }); } catch (error) { // If anything fails, rollback all changes await applicationManager.rollback(); throw error; } } catch (error) { if (applicationManager.isInTransaction()) { await applicationManager.rollback(); } return formatToolError({ operation: 'updateSchema', error: error instanceof Error ? error.message : 'Unknown error occurred', context: {updates, schema, nodeType}, suggestions: [ "Check all required fields are provided", "Verify relationship targets exist" ], recoverySteps: [ "Review schema requirements", "Ensure node exists before updating" ] }); } }
- Helper function that processes update data for a schema node, computing new metadata array and edge add/remove changes.export async function updateSchemaNode( updates: NodeData, currentNode: Node, schema: SchemaConfig, currentGraph: Graph ): Promise<SchemaUpdateResult> { const {metadataConfig, relationships} = schema; const metadata = new Map<string, string>(); const edgeChanges = { remove: [] as Edge[], add: [] as Edge[] }; // Create a set of all schema-defined fields const schemaFields = new Set<string>([ ...metadataConfig.requiredFields, ...metadataConfig.optionalFields, ...(metadataConfig.excludeFields || []), 'name', 'metadata' ]); // Add relationship fields to schema fields if (relationships) { Object.keys(relationships).forEach(field => schemaFields.add(field)); } // Process existing metadata into the Map currentNode.metadata.forEach(meta => { const colonIndex = meta.indexOf(':'); if (colonIndex !== -1) { const key = meta.substring(0, colonIndex).trim().toLowerCase(); const value = meta.substring(colonIndex + 1).trim(); metadata.set(key, value); } }); const updateMetadataEntry = (key: string, value: unknown) => { const formattedValue = Array.isArray(value) ? value.join(', ') : String(value); metadata.set(key.toLowerCase(), formattedValue); }; // Process standard metadata fields const allSchemaFields = [...metadataConfig.requiredFields, ...metadataConfig.optionalFields]; for (const field of allSchemaFields) { if (updates[field] !== undefined && (!relationships || !relationships[field])) { updateMetadataEntry(field, updates[field]); } } // Process relationships if they exist in the schema if (relationships) { for (const [field, config] of Object.entries(relationships)) { // Only process relationship if it's being updated if (updates[field] !== undefined) { // Get all existing edges for this relationship type from this node const existingEdges = currentGraph.edges.filter(edge => edge.from === currentNode.name && edge.edgeType === config.edgeType ); // Only mark edges for removal if they're part of this relationship type edgeChanges.remove.push(...existingEdges); // Add new edges const value = updates[field]; if (Array.isArray(value)) { value.forEach((target: string) => { edgeChanges.add.push({ type: 'edge', from: currentNode.name, to: target, edgeType: config.edgeType }); }); } else if (value) { edgeChanges.add.push({ type: 'edge', from: currentNode.name, to: value as string, edgeType: config.edgeType }); } updateMetadataEntry(field, value); } } } // Process additional fields not defined in schema for (const [key, value] of Object.entries(updates)) { if (!schemaFields.has(key) && value !== undefined) { updateMetadataEntry(key, value); } } const updatedMetadata = Array.from(metadata).map(([key, value]) => { const capitalizedKey = key.charAt(0).toUpperCase() + key.slice(1); return `${capitalizedKey}: ${value}`; }); return { metadata: updatedMetadata, edgeChanges }; }
- Generates the input schema definition and Tool object structure for 'update_<entity>' tools like update_faction.createUpdateSchema(excludeFields: Set<string> = new Set()): SchemaConfig { const schemaName = this.schema.name!.replace('add_', 'update_'); const updateSchemaBuilder = new SchemaBuilder( schemaName, `Update an existing ${schemaName.replace('update_', '')} in the knowledge graph` ); const baseProperties = this.schema.inputSchema!.properties[this.schema.name!.replace('add_', '')].properties; // Copy properties except excluded ones Object.entries(baseProperties).forEach(([propName, propValue]) => { if (!excludeFields.has(propName)) { if (propValue.type === 'array') { updateSchemaBuilder.addArrayProperty( propName, propValue.description, false, propValue.items?.enum ); } else { updateSchemaBuilder.addStringProperty( propName, propValue.description, false, propValue.enum ); } } }); // Copy relationships this.relationships.forEach((config, propName) => { if (!excludeFields.has(propName)) { updateSchemaBuilder.addRelationship( propName, config.edgeType, config.description || 'Relationship property', config.nodeType || null ); } }); // Add metadata array updateSchemaBuilder.addArrayProperty( 'metadata', 'An array of metadata contents to replace the existing metadata' ); return updateSchemaBuilder.build(); }
- src/integration/tools/DynamicSchemaToolRegistry.ts:89-131 (registration)Registers the dynamic 'update_<schemaName>' tool (e.g. update_faction) by generating its Tool definition from schema and adding to cache.private async generateToolsForSchema(schemaName: string, schema: SchemaBuilder): Promise<Tool[]> { const tools: Tool[] = []; const baseSchema = schema.build(); // Add tool tools.push(baseSchema as unknown as Tool); // Update tool const updateSchema = schema.createUpdateSchema(); tools.push(updateSchema as unknown as Tool); // Delete tool const deleteSchema: Tool = { name: `delete_${schemaName}`, description: `Delete an existing ${schemaName} from the knowledge graph`, inputSchema: { type: "object", properties: { [`delete_${schemaName}`]: { type: "object", description: `Delete parameters for ${schemaName}`, properties: { name: { type: "string", description: `The name of the ${schemaName} to delete` } }, required: ["name"] } }, required: [`delete_${schemaName}`] } }; tools.push(deleteSchema); return tools; }
- Dynamic tool dispatcher that parses toolName 'update_faction' to schemaName='faction' and invokes the update handler.case 'update': { return handleSchemaUpdate( args[`update_${schemaName}`], schema, schemaName, knowledgeGraphManager ); }