@props-labs/mesh-os 0.1.7 → 0.1.9

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
@@ -143,15 +143,8 @@ flowchart LR
143
143
 
144
144
  ## Getting Started
145
145
 
146
- ### Install & Create a New Instance
147
- ```bash
148
- # Install the CLI tool
149
- npm install -g @props-labs/mesh-os
146
+ > **Important Note**: The JavaScript client can only connect to an existing MeshOS instance. To launch a new MeshOS system, please use the [Python version](https://github.com/Props-Labs/mesh-os) which includes deployment capabilities.
150
147
 
151
- # Create and start a new project
152
- mesh-os init my-project && cd my-project
153
- mesh-os up
154
- ```
155
148
 
156
149
  ## Usage
157
150
  ```typescript
@@ -161,7 +154,7 @@ import dotenv from 'dotenv';
161
154
  // Load environment variables
162
155
  dotenv.config();
163
156
 
164
- // Initialize MeshOS
157
+ // Connect To MeshOS
165
158
  const client = new MeshOS({
166
159
  url: process.env.HASURA_URL || 'http://localhost:8080',
167
160
  apiKey: process.env.HASURA_ADMIN_SECRET || 'meshos',
@@ -1,4 +1,4 @@
1
- import { EdgeType, type EdgeMetadata, type MemoryMetadata } from './taxonomy';
1
+ import { EdgeType, type AgentStatus, type EdgeMetadata, type MemoryMetadata } from './taxonomy';
2
2
  /**
3
3
  * An agent in the system.
4
4
  */
@@ -7,7 +7,7 @@ export interface Agent {
7
7
  name: string;
8
8
  description: string;
9
9
  metadata: Record<string, unknown>;
10
- status: string;
10
+ status: AgentStatus;
11
11
  slug?: string;
12
12
  }
13
13
  /**
@@ -91,7 +91,7 @@ export declare class MeshOS {
91
91
  /**
92
92
  * Store a new memory.
93
93
  */
94
- remember(content: string, agentId: string, metadata?: Partial<MemoryMetadata>): Promise<Memory>;
94
+ remember(content: string, agentId: string, metadata?: Partial<MemoryMetadata>): Promise<Memory | Memory[]>;
95
95
  /**
96
96
  * Delete a specific memory.
97
97
  */
@@ -107,7 +107,7 @@ export declare class MeshOS {
107
107
  /**
108
108
  * Update a memory and optionally create a version edge to the previous version.
109
109
  */
110
- updateMemory(memoryId: string, content: string, metadata?: Partial<MemoryMetadata>, createVersionEdge?: boolean): Promise<Memory>;
110
+ updateMemory(memoryId: string, content: string, metadata?: Partial<MemoryMetadata>, createVersionEdge?: boolean): Promise<Memory | Memory[]>;
111
111
  /**
112
112
  * Get memories connected to the given memory.
113
113
  */
@@ -139,4 +139,8 @@ export declare class MeshOS {
139
139
  * Internal method to perform recall with a specific threshold.
140
140
  */
141
141
  private recallWithThreshold;
142
+ /**
143
+ * Update an agent's status.
144
+ */
145
+ updateAgentStatus(agentId: string, status: AgentStatus): Promise<Agent>;
142
146
  }
@@ -12,7 +12,6 @@ const chalk_1 = __importDefault(require("chalk"));
12
12
  const boxen_1 = __importDefault(require("boxen"));
13
13
  const taxonomy_1 = require("./taxonomy");
14
14
  // Constants
15
- const MIN_THRESHOLD = 0.3;
16
15
  const SLUG_PATTERN = /^[a-z][a-z0-9_-]*[a-z0-9]$/;
17
16
  /**
18
17
  * GraphQL error class.
@@ -117,7 +116,7 @@ class MeshOS {
117
116
  name: $name,
118
117
  description: $description,
119
118
  metadata: $metadata,
120
- status: "active",
119
+ status: "${taxonomy_1.CoreAgentStatus.IDLE}",
121
120
  slug: $slug
122
121
  }) {
123
122
  id
@@ -211,41 +210,120 @@ class MeshOS {
211
210
  additional: {},
212
211
  ...metadata
213
212
  });
214
- // Create embedding
215
- const embedding = await this.createEmbedding(content);
216
- const embeddingStr = `[${embedding.join(',')}]`;
217
- const query = `
218
- mutation Remember($content: String!, $agentId: uuid!, $metadata: jsonb!, $embedding: vector!) {
219
- insert_memories_one(object: {
220
- content: $content,
221
- agent_id: $agentId,
222
- metadata: $metadata,
223
- embedding: $embedding
224
- }) {
225
- id
226
- agent_id
227
- content
228
- metadata
229
- embedding
230
- created_at
231
- updated_at
213
+ // Check if content needs chunking (8192 tokens is approximately 32K characters)
214
+ const CHUNK_SIZE = 32000;
215
+ if (content.length <= CHUNK_SIZE) {
216
+ // Create embedding for single chunk
217
+ const embedding = await this.createEmbedding(content);
218
+ const embeddingStr = `[${embedding.join(',')}]`;
219
+ const query = `
220
+ mutation Remember($content: String!, $agentId: uuid!, $metadata: jsonb!, $embedding: vector!) {
221
+ insert_memories_one(object: {
222
+ content: $content,
223
+ agent_id: $agentId,
224
+ metadata: $metadata,
225
+ embedding: $embedding
226
+ }) {
227
+ id
228
+ agent_id
229
+ content
230
+ metadata
231
+ embedding
232
+ created_at
233
+ updated_at
234
+ }
232
235
  }
233
- }
234
- `;
235
- const result = await this.executeQuery(query, {
236
- content,
237
- agentId,
238
- metadata: fullMetadata,
239
- embedding: embeddingStr
240
- });
241
- // Convert snake_case to camelCase
242
- const { agent_id, created_at, updated_at, ...rest } = result.insert_memories_one;
243
- return {
244
- ...rest,
245
- agentId: agent_id,
246
- createdAt: created_at,
247
- updatedAt: updated_at,
248
- };
236
+ `;
237
+ const result = await this.executeQuery(query, {
238
+ content,
239
+ agentId,
240
+ metadata: fullMetadata,
241
+ embedding: embeddingStr
242
+ });
243
+ // Convert snake_case to camelCase
244
+ const { agent_id, created_at, updated_at, ...rest } = result.insert_memories_one;
245
+ return {
246
+ ...rest,
247
+ agentId: agent_id,
248
+ createdAt: created_at,
249
+ updatedAt: updated_at,
250
+ };
251
+ }
252
+ // Split content into chunks
253
+ const chunks = [];
254
+ for (let i = 0; i < content.length; i += CHUNK_SIZE) {
255
+ chunks.push(content.slice(i, i + CHUNK_SIZE));
256
+ }
257
+ // Store each chunk and create links
258
+ const memories = [];
259
+ let previousChunkId = null;
260
+ for (let i = 0; i < chunks.length; i++) {
261
+ const chunkMetadata = {
262
+ ...fullMetadata,
263
+ additional: {
264
+ ...fullMetadata.additional,
265
+ chunk_info: {
266
+ chunk_index: i,
267
+ total_chunks: chunks.length,
268
+ is_chunk: true
269
+ }
270
+ }
271
+ };
272
+ // Create embedding for chunk
273
+ const embedding = await this.createEmbedding(chunks[i]);
274
+ const embeddingStr = `[${embedding.join(',')}]`;
275
+ const query = `
276
+ mutation Remember($content: String!, $agentId: uuid!, $metadata: jsonb!, $embedding: vector!) {
277
+ insert_memories_one(object: {
278
+ content: $content,
279
+ agent_id: $agentId,
280
+ metadata: $metadata,
281
+ embedding: $embedding
282
+ }) {
283
+ id
284
+ agent_id
285
+ content
286
+ metadata
287
+ embedding
288
+ created_at
289
+ updated_at
290
+ }
291
+ }
292
+ `;
293
+ const result = await this.executeQuery(query, {
294
+ content: chunks[i],
295
+ agentId,
296
+ metadata: chunkMetadata,
297
+ embedding: embeddingStr
298
+ });
299
+ // Convert snake_case to camelCase
300
+ const { agent_id, created_at, updated_at, ...rest } = result.insert_memories_one;
301
+ const memory = {
302
+ ...rest,
303
+ agentId: agent_id,
304
+ createdAt: created_at,
305
+ updatedAt: updated_at,
306
+ };
307
+ memories.push(memory);
308
+ // Link chunks sequentially
309
+ if (previousChunkId) {
310
+ await this.linkMemories(previousChunkId, memory.id, taxonomy_1.EdgeType.FOLLOWS_UP, 1.0, {
311
+ relationship: taxonomy_1.EdgeType.FOLLOWS_UP,
312
+ weight: 1.0,
313
+ bidirectional: false,
314
+ additional: { is_chunk_link: true }
315
+ });
316
+ // Also add PART_OF relationship to show these are parts of the same content
317
+ await this.linkMemories(memory.id, previousChunkId, taxonomy_1.EdgeType.PART_OF, 1.0, {
318
+ relationship: taxonomy_1.EdgeType.PART_OF,
319
+ weight: 1.0,
320
+ bidirectional: true,
321
+ additional: { is_chunk_link: true }
322
+ });
323
+ }
324
+ previousChunkId = memory.id;
325
+ }
326
+ return memories;
249
327
  }
250
328
  /**
251
329
  * Delete a specific memory.
@@ -364,7 +442,7 @@ class MeshOS {
364
442
  throw new Error(`Memory ${memoryId} not found`);
365
443
  }
366
444
  // Create new memory with updated content and metadata
367
- const newMemory = await this.remember(content, oldMemory.agent_id, {
445
+ const newMemories = await this.remember(content, oldMemory.agent_id, {
368
446
  ...oldMemory.metadata,
369
447
  version: oldMemory.metadata.version + 1,
370
448
  previousVersion: oldMemory.id,
@@ -372,14 +450,16 @@ class MeshOS {
372
450
  });
373
451
  // Create version edge if requested
374
452
  if (createVersionEdge) {
375
- await this.linkMemories(oldMemory.id, newMemory.id, taxonomy_1.EdgeType.VERSION_OF, 1.0, {
453
+ // If we got multiple memories (chunks), link the first one
454
+ const firstNewMemory = Array.isArray(newMemories) ? newMemories[0] : newMemories;
455
+ await this.linkMemories(oldMemory.id, firstNewMemory.id, taxonomy_1.EdgeType.VERSION_OF, 1.0, {
376
456
  relationship: taxonomy_1.EdgeType.VERSION_OF,
377
457
  weight: 1.0,
378
458
  bidirectional: false,
379
459
  additional: { version_increment: 1 }
380
460
  });
381
461
  }
382
- return newMemory;
462
+ return newMemories;
383
463
  }
384
464
  /**
385
465
  * Get memories connected to the given memory.
@@ -457,10 +537,11 @@ class MeshOS {
457
537
  if (results.length >= minResults) {
458
538
  return results.slice(0, limit);
459
539
  }
460
- // Second try: Adaptive threshold
540
+ // Second try: If adaptive threshold is enabled, try lowering the threshold
461
541
  if (adaptiveThreshold) {
462
542
  let currentThreshold = threshold - 0.05;
463
- while (currentThreshold >= MIN_THRESHOLD && results.length < minResults) {
543
+ const minThreshold = 0.3; // Don't go below this to avoid irrelevant matches
544
+ while (currentThreshold >= minThreshold && results.length < minResults) {
464
545
  const newResults = await this.recallWithThreshold({
465
546
  query,
466
547
  threshold: currentThreshold,
@@ -468,23 +549,25 @@ class MeshOS {
468
549
  limit,
469
550
  filters
470
551
  });
471
- // Add new unique results
552
+ // Add new results that aren't already in the list
472
553
  for (const result of newResults) {
473
554
  if (!results.some(r => r.id === result.id)) {
474
555
  results.push(result);
475
556
  }
476
557
  }
477
- if (results.length >= minResults)
558
+ if (results.length >= minResults) {
478
559
  break;
560
+ }
479
561
  currentThreshold -= 0.05;
480
562
  }
481
563
  }
482
- // Third try: Semantic expansion
564
+ // Third try: If we still don't have ANY results and semantic expansion is enabled
483
565
  if (results.length === 0 && useSemanticExpansion) {
484
566
  const variations = await this.expandQuery(query);
485
567
  const seenIds = new Map();
486
- // Try each variation with original threshold
487
- for (const variation of variations.slice(1)) {
568
+ const minThreshold = 0.3; // Don't go below this to avoid irrelevant matches
569
+ // Try each variation with the original threshold first
570
+ for (const variation of variations.slice(1)) { // Skip original query as we already tried it
488
571
  const variationResults = await this.recallWithThreshold({
489
572
  query: variation,
490
573
  threshold,
@@ -492,19 +575,21 @@ class MeshOS {
492
575
  limit,
493
576
  filters
494
577
  });
578
+ // Add new results or update if better similarity
495
579
  for (const memory of variationResults) {
496
580
  const existingMemory = seenIds.get(memory.id);
497
581
  if (!existingMemory || (memory.similarity || 0) > (existingMemory.similarity || 0)) {
498
582
  seenIds.set(memory.id, memory);
499
583
  }
500
584
  }
501
- if (seenIds.size >= minResults)
585
+ if (seenIds.size >= minResults) {
502
586
  break;
587
+ }
503
588
  }
504
589
  // If still no results, try variations with adaptive threshold
505
590
  if (seenIds.size === 0 && adaptiveThreshold) {
506
591
  let currentThreshold = threshold - 0.05;
507
- while (currentThreshold >= MIN_THRESHOLD && seenIds.size === 0) {
592
+ while (currentThreshold >= minThreshold && seenIds.size === 0) {
508
593
  for (const variation of variations.slice(1)) {
509
594
  const variationResults = await this.recallWithThreshold({
510
595
  query: variation,
@@ -519,19 +604,22 @@ class MeshOS {
519
604
  seenIds.set(memory.id, memory);
520
605
  }
521
606
  }
522
- if (seenIds.size > 0)
607
+ if (seenIds.size > 0) {
523
608
  break;
609
+ }
524
610
  }
525
- if (seenIds.size > 0)
611
+ if (seenIds.size > 0) {
526
612
  break;
613
+ }
527
614
  currentThreshold -= 0.05;
528
615
  }
529
616
  }
617
+ // Update results with any found memories
530
618
  if (seenIds.size > 0) {
531
619
  results = Array.from(seenIds.values());
532
620
  }
533
621
  }
534
- // Sort by similarity and return
622
+ // Sort by similarity and return top results
535
623
  results.sort((a, b) => (b.similarity || 0) - (a.similarity || 0));
536
624
  return results.slice(0, limit);
537
625
  }
@@ -557,13 +645,39 @@ class MeshOS {
557
645
  }
558
646
  }
559
647
  `;
648
+ // Process metadata filters
649
+ let metadataFilter;
650
+ if (filters) {
651
+ // Extract metadata filters
652
+ const { type, subtype, tags, relevance, version, _contains, ...additionalFilters } = filters;
653
+ metadataFilter = {};
654
+ // Add basic metadata filters
655
+ if (type)
656
+ metadataFilter.type = type;
657
+ if (subtype)
658
+ metadataFilter.subtype = subtype;
659
+ if (tags)
660
+ metadataFilter.tags = tags;
661
+ if (relevance)
662
+ metadataFilter.relevance = relevance;
663
+ if (version)
664
+ metadataFilter.version = version;
665
+ // Add array containment operations
666
+ if (_contains) {
667
+ metadataFilter._contains = _contains;
668
+ }
669
+ // Add any additional filters to the metadata.additional object
670
+ if (Object.keys(additionalFilters).length > 0) {
671
+ metadataFilter.additional = additionalFilters;
672
+ }
673
+ }
560
674
  const result = await this.executeQuery(gqlQuery, {
561
675
  args: {
562
676
  query_embedding: embeddingStr,
563
677
  match_threshold: threshold,
564
678
  match_count: limit,
565
679
  filter_agent_id: agentId,
566
- ...filters
680
+ metadata_filter: metadataFilter
567
681
  }
568
682
  });
569
683
  return result.search_memories.map(memory => ({
@@ -577,5 +691,33 @@ class MeshOS {
577
691
  updatedAt: memory.updated_at
578
692
  }));
579
693
  }
694
+ /**
695
+ * Update an agent's status.
696
+ */
697
+ async updateAgentStatus(agentId, status) {
698
+ const query = `
699
+ mutation UpdateAgentStatus($id: uuid!, $status: String!) {
700
+ update_agents_by_pk(
701
+ pk_columns: { id: $id },
702
+ _set: { status: $status }
703
+ ) {
704
+ id
705
+ name
706
+ description
707
+ metadata
708
+ status
709
+ slug
710
+ }
711
+ }
712
+ `;
713
+ const result = await this.executeQuery(query, {
714
+ id: agentId,
715
+ status
716
+ });
717
+ if (!result.update_agents_by_pk) {
718
+ throw new Error(`Agent with ID ${agentId} not found`);
719
+ }
720
+ return result.update_agents_by_pk;
721
+ }
580
722
  }
581
723
  exports.MeshOS = MeshOS;
@@ -63,7 +63,8 @@ export declare enum EdgeType {
63
63
  CONTRADICTS = "contradicts",// Conflicting information
64
64
  DEPENDS_ON = "depends_on",// Prerequisite relationship
65
65
  SUMMARIZES = "summarizes",// Condensed version
66
- INFLUENCES = "influences"
66
+ INFLUENCES = "influences",// Impact relationship
67
+ PART_OF = "part_of"
67
68
  }
68
69
  /**
69
70
  * Relevance classification tags.
@@ -75,6 +76,17 @@ export declare enum RelevanceTag {
75
76
  VOLATILE = "volatile",
76
77
  EXPERIMENTAL = "experimental"
77
78
  }
79
+ /**
80
+ * Core agent status types.
81
+ * The type allows for both predefined and custom status strings.
82
+ */
83
+ export declare const CoreAgentStatus: {
84
+ readonly IDLE: "idle";
85
+ readonly RUNNING: "running";
86
+ readonly ERROR: "error";
87
+ readonly PAUSED: "paused";
88
+ };
89
+ export type AgentStatus = typeof CoreAgentStatus[keyof typeof CoreAgentStatus] | string;
78
90
  /**
79
91
  * Version history entry.
80
92
  */
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.edgeMetadataSchema = exports.memoryMetadataSchema = exports.RelevanceTag = exports.EdgeType = exports.MediaSubtype = exports.DecisionSubtype = exports.KnowledgeSubtype = exports.ActivitySubtype = exports.DataType = void 0;
3
+ exports.edgeMetadataSchema = exports.memoryMetadataSchema = exports.CoreAgentStatus = exports.RelevanceTag = exports.EdgeType = exports.MediaSubtype = exports.DecisionSubtype = exports.KnowledgeSubtype = exports.ActivitySubtype = exports.DataType = void 0;
4
4
  /**
5
5
  * Taxonomy and classification models for MeshOS.
6
6
  */
@@ -73,6 +73,7 @@ var EdgeType;
73
73
  EdgeType["DEPENDS_ON"] = "depends_on";
74
74
  EdgeType["SUMMARIZES"] = "summarizes";
75
75
  EdgeType["INFLUENCES"] = "influences";
76
+ EdgeType["PART_OF"] = "part_of";
76
77
  })(EdgeType || (exports.EdgeType = EdgeType = {}));
77
78
  /**
78
79
  * Relevance classification tags.
@@ -85,6 +86,16 @@ var RelevanceTag;
85
86
  RelevanceTag["VOLATILE"] = "volatile";
86
87
  RelevanceTag["EXPERIMENTAL"] = "experimental";
87
88
  })(RelevanceTag || (exports.RelevanceTag = RelevanceTag = {}));
89
+ /**
90
+ * Core agent status types.
91
+ * The type allows for both predefined and custom status strings.
92
+ */
93
+ exports.CoreAgentStatus = {
94
+ IDLE: 'idle',
95
+ RUNNING: 'running',
96
+ ERROR: 'error',
97
+ PAUSED: 'paused'
98
+ };
88
99
  /**
89
100
  * Standardized metadata structure for memories.
90
101
  */
package/dist/index.d.ts CHANGED
@@ -2,5 +2,5 @@
2
2
  * MeshOS - A lightweight multi-agent memory system with semantic search.
3
3
  */
4
4
  export { Agent, Memory, MemoryEdge, MeshOS, GraphQLError, InvalidSlugError, type MeshOSConfig } from './core/client';
5
- export { DataType, ActivitySubtype, KnowledgeSubtype, DecisionSubtype, MediaSubtype, EdgeType, RelevanceTag, type VersionInfo, type MemoryMetadata, type EdgeMetadata, } from './core/taxonomy';
6
- export declare const VERSION = "0.1.6";
5
+ export { DataType, ActivitySubtype, KnowledgeSubtype, DecisionSubtype, MediaSubtype, EdgeType, RelevanceTag, CoreAgentStatus, type AgentStatus, type VersionInfo, type MemoryMetadata, type EdgeMetadata, } from './core/taxonomy';
6
+ export declare const VERSION = "0.1.9";
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * MeshOS - A lightweight multi-agent memory system with semantic search.
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.VERSION = exports.RelevanceTag = exports.EdgeType = exports.MediaSubtype = exports.DecisionSubtype = exports.KnowledgeSubtype = exports.ActivitySubtype = exports.DataType = exports.InvalidSlugError = exports.GraphQLError = exports.MeshOS = void 0;
6
+ exports.VERSION = exports.CoreAgentStatus = exports.RelevanceTag = exports.EdgeType = exports.MediaSubtype = exports.DecisionSubtype = exports.KnowledgeSubtype = exports.ActivitySubtype = exports.DataType = exports.InvalidSlugError = exports.GraphQLError = exports.MeshOS = void 0;
7
7
  var client_1 = require("./core/client");
8
8
  Object.defineProperty(exports, "MeshOS", { enumerable: true, get: function () { return client_1.MeshOS; } });
9
9
  Object.defineProperty(exports, "GraphQLError", { enumerable: true, get: function () { return client_1.GraphQLError; } });
@@ -17,4 +17,6 @@ Object.defineProperty(exports, "DecisionSubtype", { enumerable: true, get: funct
17
17
  Object.defineProperty(exports, "MediaSubtype", { enumerable: true, get: function () { return taxonomy_1.MediaSubtype; } });
18
18
  Object.defineProperty(exports, "EdgeType", { enumerable: true, get: function () { return taxonomy_1.EdgeType; } });
19
19
  Object.defineProperty(exports, "RelevanceTag", { enumerable: true, get: function () { return taxonomy_1.RelevanceTag; } });
20
- exports.VERSION = '0.1.6';
20
+ // Agent status types
21
+ Object.defineProperty(exports, "CoreAgentStatus", { enumerable: true, get: function () { return taxonomy_1.CoreAgentStatus; } });
22
+ exports.VERSION = '0.1.9';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@props-labs/mesh-os",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "MeshOS - A memory system for AI agents",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -14,4 +14,10 @@ computed_fields:
14
14
  function:
15
15
  name: search_memories
16
16
  schema: public
17
+ arguments:
18
+ query_embedding: $query_embedding
19
+ match_threshold: $match_threshold
20
+ match_count: $match_count
21
+ filter_agent_id: $filter_agent_id
22
+ metadata_filter: $metadata_filter
17
23
  comment: Computes similarity score for vector search
@@ -1,13 +1,26 @@
1
- -- Drop functions
2
- DROP FUNCTION IF EXISTS search_memories;
1
+ -- Drop all versions of search_memories function
2
+ DROP FUNCTION IF EXISTS public.search_memories(vector(1536), float8, integer, uuid, jsonb);
3
+ DROP FUNCTION IF EXISTS public.search_memories(vector(1536), float8, integer, uuid);
4
+ DROP FUNCTION IF EXISTS public.search_memories;
5
+
6
+ -- Drop other functions
3
7
  DROP FUNCTION IF EXISTS get_connected_memories;
8
+
9
+ -- Drop triggers first
10
+ DROP TRIGGER IF EXISTS update_agents_updated_at ON public.agents;
11
+ DROP TRIGGER IF EXISTS update_memories_updated_at ON public.memories;
12
+
13
+ -- Now we can safely drop the trigger function
4
14
  DROP FUNCTION IF EXISTS update_updated_at_column;
5
15
 
16
+ -- Drop views first
17
+ DROP VIEW IF EXISTS public.memories_with_similarity;
18
+
6
19
  -- Drop tables
7
20
  DROP TABLE IF EXISTS public.memory_edges;
8
21
  DROP TABLE IF EXISTS public.memories;
9
22
  DROP TABLE IF EXISTS public.agents;
10
23
 
11
- -- Drop extensions
12
- DROP EXTENSION IF EXISTS vector;
24
+ -- Drop extensions (with CASCADE for vector since it has dependent objects)
25
+ DROP EXTENSION IF EXISTS vector CASCADE;
13
26
  DROP EXTENSION IF EXISTS "uuid-ossp";
@@ -0,0 +1,4 @@
1
+ -- Drop the updated search_memories function with metadata filtering
2
+ DROP FUNCTION public.search_memories(vector(1536), float8, integer, uuid, jsonb);
3
+
4
+ -- Note: The original search_memories function from 1_init will be restored when that migration is reapplied
@@ -0,0 +1,44 @@
1
+ -- Drop the existing search_memories function
2
+ DROP FUNCTION IF EXISTS public.search_memories;
3
+
4
+ -- Create the updated search_memories function with metadata filtering
5
+ CREATE OR REPLACE FUNCTION public.search_memories(
6
+ query_embedding vector(1536),
7
+ match_threshold float8,
8
+ match_count integer,
9
+ filter_agent_id uuid DEFAULT NULL,
10
+ metadata_filter jsonb DEFAULT NULL
11
+ )
12
+ RETURNS SETOF public.memories_with_similarity
13
+ LANGUAGE sql
14
+ STABLE
15
+ AS $$
16
+ WITH normalized_query AS (
17
+ SELECT l2_normalize(query_embedding) AS normalized_vector
18
+ )
19
+ SELECT
20
+ m.id,
21
+ m.agent_id,
22
+ m.content,
23
+ m.metadata,
24
+ m.embedding,
25
+ m.created_at,
26
+ m.updated_at,
27
+ -(m.embedding <#> (SELECT normalized_vector FROM normalized_query)) as similarity
28
+ FROM memories m
29
+ WHERE
30
+ CASE
31
+ WHEN filter_agent_id IS NOT NULL THEN m.agent_id = filter_agent_id
32
+ ELSE TRUE
33
+ END
34
+ AND CASE
35
+ WHEN metadata_filter IS NOT NULL THEN m.metadata @> metadata_filter
36
+ ELSE TRUE
37
+ END
38
+ AND -(m.embedding <#> (SELECT normalized_vector FROM normalized_query)) >= match_threshold
39
+ ORDER BY -(m.embedding <#> (SELECT normalized_vector FROM normalized_query)) DESC
40
+ LIMIT match_count;
41
+ $$;
42
+
43
+ -- Track the function in Hasura
44
+ COMMENT ON FUNCTION public.search_memories IS E'@graphql({"type": "Query"})';