@props-labs/mesh-os 0.1.9 → 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
package/dist/core/client.d.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { EdgeType, type AgentStatus, type EdgeMetadata, type MemoryMetadata } from './taxonomy';
|
1
|
+
import { EdgeType, type AgentStatus, type EdgeMetadata, type MemoryMetadata, type TimestampFilter } from './taxonomy';
|
2
2
|
/**
|
3
3
|
* An agent in the system.
|
4
4
|
*/
|
@@ -21,6 +21,7 @@ export interface Memory {
|
|
21
21
|
embedding: number[];
|
22
22
|
createdAt: string;
|
23
23
|
updatedAt: string;
|
24
|
+
expiresAt?: string;
|
24
25
|
similarity?: number;
|
25
26
|
}
|
26
27
|
/**
|
@@ -91,7 +92,7 @@ export declare class MeshOS {
|
|
91
92
|
/**
|
92
93
|
* Store a new memory.
|
93
94
|
*/
|
94
|
-
remember(content: string, agentId: string, metadata?: Partial<MemoryMetadata
|
95
|
+
remember(content: string, agentId: string, metadata?: Partial<MemoryMetadata>, expiresAt?: string): Promise<Memory | Memory[]>;
|
95
96
|
/**
|
96
97
|
* Delete a specific memory.
|
97
98
|
*/
|
@@ -134,6 +135,8 @@ export declare class MeshOS {
|
|
134
135
|
adaptiveThreshold?: boolean;
|
135
136
|
useSemanticExpansion?: boolean;
|
136
137
|
filters?: Record<string, unknown>;
|
138
|
+
createdAtFilter?: TimestampFilter;
|
139
|
+
expiresAtFilter?: TimestampFilter;
|
137
140
|
}): Promise<Memory[]>;
|
138
141
|
/**
|
139
142
|
* Internal method to perform recall with a specific threshold.
|
package/dist/core/client.js
CHANGED
@@ -199,7 +199,7 @@ class MeshOS {
|
|
199
199
|
/**
|
200
200
|
* Store a new memory.
|
201
201
|
*/
|
202
|
-
async remember(content, agentId, metadata) {
|
202
|
+
async remember(content, agentId, metadata, expiresAt) {
|
203
203
|
// Create default metadata if none provided
|
204
204
|
const fullMetadata = taxonomy_1.memoryMetadataSchema.parse({
|
205
205
|
type: taxonomy_1.DataType.KNOWLEDGE,
|
@@ -217,12 +217,13 @@ class MeshOS {
|
|
217
217
|
const embedding = await this.createEmbedding(content);
|
218
218
|
const embeddingStr = `[${embedding.join(',')}]`;
|
219
219
|
const query = `
|
220
|
-
mutation Remember($content: String!, $agentId: uuid!, $metadata: jsonb!, $embedding: vector
|
220
|
+
mutation Remember($content: String!, $agentId: uuid!, $metadata: jsonb!, $embedding: vector!, $expiresAt: timestamptz) {
|
221
221
|
insert_memories_one(object: {
|
222
222
|
content: $content,
|
223
223
|
agent_id: $agentId,
|
224
224
|
metadata: $metadata,
|
225
|
-
embedding: $embedding
|
225
|
+
embedding: $embedding,
|
226
|
+
expires_at: $expiresAt
|
226
227
|
}) {
|
227
228
|
id
|
228
229
|
agent_id
|
@@ -231,6 +232,7 @@ class MeshOS {
|
|
231
232
|
embedding
|
232
233
|
created_at
|
233
234
|
updated_at
|
235
|
+
expires_at
|
234
236
|
}
|
235
237
|
}
|
236
238
|
`;
|
@@ -238,15 +240,17 @@ class MeshOS {
|
|
238
240
|
content,
|
239
241
|
agentId,
|
240
242
|
metadata: fullMetadata,
|
241
|
-
embedding: embeddingStr
|
243
|
+
embedding: embeddingStr,
|
244
|
+
expiresAt
|
242
245
|
});
|
243
246
|
// Convert snake_case to camelCase
|
244
|
-
const { agent_id, created_at, updated_at, ...rest } = result.insert_memories_one;
|
247
|
+
const { agent_id, created_at, updated_at, expires_at, ...rest } = result.insert_memories_one;
|
245
248
|
return {
|
246
249
|
...rest,
|
247
250
|
agentId: agent_id,
|
248
251
|
createdAt: created_at,
|
249
252
|
updatedAt: updated_at,
|
253
|
+
expiresAt: expires_at,
|
250
254
|
};
|
251
255
|
}
|
252
256
|
// Split content into chunks
|
@@ -273,12 +277,13 @@ class MeshOS {
|
|
273
277
|
const embedding = await this.createEmbedding(chunks[i]);
|
274
278
|
const embeddingStr = `[${embedding.join(',')}]`;
|
275
279
|
const query = `
|
276
|
-
mutation Remember($content: String!, $agentId: uuid!, $metadata: jsonb!, $embedding: vector
|
280
|
+
mutation Remember($content: String!, $agentId: uuid!, $metadata: jsonb!, $embedding: vector!, $expiresAt: timestamptz) {
|
277
281
|
insert_memories_one(object: {
|
278
282
|
content: $content,
|
279
283
|
agent_id: $agentId,
|
280
284
|
metadata: $metadata,
|
281
|
-
embedding: $embedding
|
285
|
+
embedding: $embedding,
|
286
|
+
expires_at: $expiresAt
|
282
287
|
}) {
|
283
288
|
id
|
284
289
|
agent_id
|
@@ -287,6 +292,7 @@ class MeshOS {
|
|
287
292
|
embedding
|
288
293
|
created_at
|
289
294
|
updated_at
|
295
|
+
expires_at
|
290
296
|
}
|
291
297
|
}
|
292
298
|
`;
|
@@ -294,15 +300,17 @@ class MeshOS {
|
|
294
300
|
content: chunks[i],
|
295
301
|
agentId,
|
296
302
|
metadata: chunkMetadata,
|
297
|
-
embedding: embeddingStr
|
303
|
+
embedding: embeddingStr,
|
304
|
+
expiresAt
|
298
305
|
});
|
299
306
|
// Convert snake_case to camelCase
|
300
|
-
const { agent_id, created_at, updated_at, ...rest } = result.insert_memories_one;
|
307
|
+
const { agent_id, created_at, updated_at, expires_at, ...rest } = result.insert_memories_one;
|
301
308
|
const memory = {
|
302
309
|
...rest,
|
303
310
|
agentId: agent_id,
|
304
311
|
createdAt: created_at,
|
305
312
|
updatedAt: updated_at,
|
313
|
+
expiresAt: expires_at,
|
306
314
|
};
|
307
315
|
memories.push(memory);
|
308
316
|
// Link chunks sequentially
|
@@ -525,14 +533,16 @@ class MeshOS {
|
|
525
533
|
* Search memories by semantic similarity.
|
526
534
|
*/
|
527
535
|
async recall(options) {
|
528
|
-
const { query, agentId, limit = 5, threshold = 0.7, minResults = 1, adaptiveThreshold = true, useSemanticExpansion = true, filters } = options;
|
536
|
+
const { query, agentId, limit = 5, threshold = 0.7, minResults = 1, adaptiveThreshold = true, useSemanticExpansion = true, filters, createdAtFilter, expiresAtFilter } = options;
|
529
537
|
// First try: Direct search with initial threshold
|
530
538
|
let results = await this.recallWithThreshold({
|
531
539
|
query,
|
532
540
|
threshold,
|
533
541
|
agentId,
|
534
542
|
limit,
|
535
|
-
filters
|
543
|
+
filters,
|
544
|
+
createdAtFilter,
|
545
|
+
expiresAtFilter
|
536
546
|
});
|
537
547
|
if (results.length >= minResults) {
|
538
548
|
return results.slice(0, limit);
|
@@ -547,7 +557,9 @@ class MeshOS {
|
|
547
557
|
threshold: currentThreshold,
|
548
558
|
agentId,
|
549
559
|
limit,
|
550
|
-
filters
|
560
|
+
filters,
|
561
|
+
createdAtFilter,
|
562
|
+
expiresAtFilter
|
551
563
|
});
|
552
564
|
// Add new results that aren't already in the list
|
553
565
|
for (const result of newResults) {
|
@@ -573,7 +585,9 @@ class MeshOS {
|
|
573
585
|
threshold,
|
574
586
|
agentId,
|
575
587
|
limit,
|
576
|
-
filters
|
588
|
+
filters,
|
589
|
+
createdAtFilter,
|
590
|
+
expiresAtFilter
|
577
591
|
});
|
578
592
|
// Add new results or update if better similarity
|
579
593
|
for (const memory of variationResults) {
|
@@ -596,7 +610,9 @@ class MeshOS {
|
|
596
610
|
threshold: currentThreshold,
|
597
611
|
agentId,
|
598
612
|
limit,
|
599
|
-
filters
|
613
|
+
filters,
|
614
|
+
createdAtFilter,
|
615
|
+
expiresAtFilter
|
600
616
|
});
|
601
617
|
for (const memory of variationResults) {
|
602
618
|
const existingMemory = seenIds.get(memory.id);
|
@@ -627,7 +643,7 @@ class MeshOS {
|
|
627
643
|
* Internal method to perform recall with a specific threshold.
|
628
644
|
*/
|
629
645
|
async recallWithThreshold(options) {
|
630
|
-
const { query, threshold, agentId, limit = 10, filters } = options;
|
646
|
+
const { query, threshold, agentId, limit = 10, filters, createdAtFilter, expiresAtFilter } = options;
|
631
647
|
// Create embedding for the query
|
632
648
|
const embedding = await this.createEmbedding(query);
|
633
649
|
const embeddingStr = `[${embedding.join(',')}]`;
|
@@ -638,10 +654,10 @@ class MeshOS {
|
|
638
654
|
agent_id
|
639
655
|
content
|
640
656
|
metadata
|
641
|
-
embedding
|
642
657
|
similarity
|
643
658
|
created_at
|
644
659
|
updated_at
|
660
|
+
expires_at
|
645
661
|
}
|
646
662
|
}
|
647
663
|
`;
|
@@ -677,7 +693,9 @@ class MeshOS {
|
|
677
693
|
match_threshold: threshold,
|
678
694
|
match_count: limit,
|
679
695
|
filter_agent_id: agentId,
|
680
|
-
metadata_filter: metadataFilter
|
696
|
+
metadata_filter: metadataFilter,
|
697
|
+
created_at_filter: createdAtFilter,
|
698
|
+
expires_at_filter: expiresAtFilter
|
681
699
|
}
|
682
700
|
});
|
683
701
|
return result.search_memories.map(memory => ({
|
@@ -688,7 +706,8 @@ class MeshOS {
|
|
688
706
|
embedding: memory.embedding,
|
689
707
|
similarity: memory.similarity,
|
690
708
|
createdAt: memory.created_at,
|
691
|
-
updatedAt: memory.updated_at
|
709
|
+
updatedAt: memory.updated_at,
|
710
|
+
expiresAt: memory.expires_at
|
692
711
|
}));
|
693
712
|
}
|
694
713
|
/**
|
package/dist/core/taxonomy.d.ts
CHANGED
@@ -229,3 +229,13 @@ export declare const edgeMetadataSchema: z.ZodObject<{
|
|
229
229
|
bidirectional?: boolean | undefined;
|
230
230
|
}>;
|
231
231
|
export type EdgeMetadata = z.infer<typeof edgeMetadataSchema>;
|
232
|
+
/**
|
233
|
+
* Timestamp filter operators
|
234
|
+
*/
|
235
|
+
export interface TimestampFilter {
|
236
|
+
_gt?: string;
|
237
|
+
_gte?: string;
|
238
|
+
_lt?: string;
|
239
|
+
_lte?: string;
|
240
|
+
_eq?: string;
|
241
|
+
}
|
package/package.json
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
-- Drop the updated search_memories function
|
2
|
+
DROP FUNCTION IF EXISTS public.search_memories(vector(1536), float8, integer, uuid, jsonb, jsonb, jsonb);
|
3
|
+
|
4
|
+
-- Remove expires_at column
|
5
|
+
ALTER TABLE public.memories DROP COLUMN expires_at;
|
6
|
+
|
7
|
+
-- Drop and recreate the view without expires_at
|
8
|
+
DROP VIEW IF EXISTS public.memories_with_similarity;
|
9
|
+
CREATE OR REPLACE VIEW public.memories_with_similarity AS
|
10
|
+
SELECT
|
11
|
+
m.*,
|
12
|
+
0::float8 as similarity
|
13
|
+
FROM memories m;
|
14
|
+
|
15
|
+
-- Restore the previous version of search_memories from 2_metadata_filtering
|
16
|
+
CREATE OR REPLACE FUNCTION public.search_memories(
|
17
|
+
query_embedding vector(1536),
|
18
|
+
match_threshold float8,
|
19
|
+
match_count integer,
|
20
|
+
filter_agent_id uuid DEFAULT NULL,
|
21
|
+
metadata_filter jsonb DEFAULT NULL
|
22
|
+
)
|
23
|
+
RETURNS SETOF public.memories_with_similarity
|
24
|
+
LANGUAGE sql
|
25
|
+
STABLE
|
26
|
+
AS $$
|
27
|
+
WITH normalized_query AS (
|
28
|
+
SELECT l2_normalize(query_embedding) AS normalized_vector
|
29
|
+
)
|
30
|
+
SELECT
|
31
|
+
m.id,
|
32
|
+
m.agent_id,
|
33
|
+
m.content,
|
34
|
+
m.metadata,
|
35
|
+
m.embedding,
|
36
|
+
m.created_at,
|
37
|
+
m.updated_at,
|
38
|
+
-(m.embedding <#> (SELECT normalized_vector FROM normalized_query)) as similarity
|
39
|
+
FROM memories m
|
40
|
+
WHERE
|
41
|
+
CASE
|
42
|
+
WHEN filter_agent_id IS NOT NULL THEN m.agent_id = filter_agent_id
|
43
|
+
ELSE TRUE
|
44
|
+
END
|
45
|
+
AND CASE
|
46
|
+
WHEN metadata_filter IS NOT NULL THEN m.metadata @> metadata_filter
|
47
|
+
ELSE TRUE
|
48
|
+
END
|
49
|
+
AND -(m.embedding <#> (SELECT normalized_vector FROM normalized_query)) >= match_threshold
|
50
|
+
ORDER BY -(m.embedding <#> (SELECT normalized_vector FROM normalized_query)) DESC
|
51
|
+
LIMIT match_count;
|
52
|
+
$$;
|
53
|
+
|
54
|
+
-- Track the function in Hasura
|
55
|
+
COMMENT ON FUNCTION public.search_memories IS E'@graphql({"type": "Query"})';
|
@@ -0,0 +1,108 @@
|
|
1
|
+
-- Add expires_at column to memories table
|
2
|
+
ALTER TABLE public.memories ADD COLUMN expires_at TIMESTAMPTZ;
|
3
|
+
|
4
|
+
-- Create a view for memories with similarity that includes all fields
|
5
|
+
DROP VIEW IF EXISTS public.memories_with_similarity;
|
6
|
+
CREATE OR REPLACE VIEW public.memories_with_similarity AS
|
7
|
+
SELECT
|
8
|
+
m.*,
|
9
|
+
0::float8 as similarity -- Default similarity, will be replaced in search
|
10
|
+
FROM memories m;
|
11
|
+
|
12
|
+
-- Drop the existing search_memories function
|
13
|
+
DROP FUNCTION IF EXISTS public.search_memories;
|
14
|
+
|
15
|
+
-- Create the updated search_memories function with standard Hasura filtering
|
16
|
+
CREATE OR REPLACE FUNCTION public.search_memories(
|
17
|
+
query_embedding vector(1536),
|
18
|
+
match_threshold float8,
|
19
|
+
match_count integer,
|
20
|
+
filter_agent_id uuid DEFAULT NULL,
|
21
|
+
metadata_filter jsonb DEFAULT NULL,
|
22
|
+
created_at_filter jsonb DEFAULT NULL,
|
23
|
+
expires_at_filter jsonb DEFAULT NULL
|
24
|
+
)
|
25
|
+
RETURNS SETOF public.memories_with_similarity
|
26
|
+
LANGUAGE sql
|
27
|
+
STABLE
|
28
|
+
AS $$
|
29
|
+
WITH normalized_query AS (
|
30
|
+
SELECT l2_normalize(query_embedding) AS normalized_vector
|
31
|
+
)
|
32
|
+
SELECT
|
33
|
+
m.id,
|
34
|
+
m.agent_id,
|
35
|
+
m.content,
|
36
|
+
m.metadata,
|
37
|
+
m.embedding,
|
38
|
+
m.created_at,
|
39
|
+
m.updated_at,
|
40
|
+
m.expires_at,
|
41
|
+
-(m.embedding <#> (SELECT normalized_vector FROM normalized_query)) as similarity
|
42
|
+
FROM memories m
|
43
|
+
WHERE
|
44
|
+
CASE
|
45
|
+
WHEN filter_agent_id IS NOT NULL THEN m.agent_id = filter_agent_id
|
46
|
+
ELSE TRUE
|
47
|
+
END
|
48
|
+
AND CASE
|
49
|
+
WHEN metadata_filter IS NOT NULL THEN m.metadata @> metadata_filter
|
50
|
+
ELSE TRUE
|
51
|
+
END
|
52
|
+
AND CASE
|
53
|
+
WHEN created_at_filter IS NOT NULL THEN (
|
54
|
+
CASE
|
55
|
+
WHEN created_at_filter ? '_gt' THEN m.created_at > (created_at_filter->>'_gt')::timestamptz
|
56
|
+
ELSE TRUE
|
57
|
+
END
|
58
|
+
AND CASE
|
59
|
+
WHEN created_at_filter ? '_gte' THEN m.created_at >= (created_at_filter->>'_gte')::timestamptz
|
60
|
+
ELSE TRUE
|
61
|
+
END
|
62
|
+
AND CASE
|
63
|
+
WHEN created_at_filter ? '_lt' THEN m.created_at < (created_at_filter->>'_lt')::timestamptz
|
64
|
+
ELSE TRUE
|
65
|
+
END
|
66
|
+
AND CASE
|
67
|
+
WHEN created_at_filter ? '_lte' THEN m.created_at <= (created_at_filter->>'_lte')::timestamptz
|
68
|
+
ELSE TRUE
|
69
|
+
END
|
70
|
+
AND CASE
|
71
|
+
WHEN created_at_filter ? '_eq' THEN m.created_at = (created_at_filter->>'_eq')::timestamptz
|
72
|
+
ELSE TRUE
|
73
|
+
END
|
74
|
+
)
|
75
|
+
ELSE TRUE
|
76
|
+
END
|
77
|
+
AND CASE
|
78
|
+
WHEN expires_at_filter IS NOT NULL THEN (
|
79
|
+
CASE
|
80
|
+
WHEN expires_at_filter ? '_gt' THEN m.expires_at > (expires_at_filter->>'_gt')::timestamptz
|
81
|
+
ELSE TRUE
|
82
|
+
END
|
83
|
+
AND CASE
|
84
|
+
WHEN expires_at_filter ? '_gte' THEN m.expires_at >= (expires_at_filter->>'_gte')::timestamptz
|
85
|
+
ELSE TRUE
|
86
|
+
END
|
87
|
+
AND CASE
|
88
|
+
WHEN expires_at_filter ? '_lt' THEN m.expires_at < (expires_at_filter->>'_lt')::timestamptz
|
89
|
+
ELSE TRUE
|
90
|
+
END
|
91
|
+
AND CASE
|
92
|
+
WHEN expires_at_filter ? '_lte' THEN m.expires_at <= (expires_at_filter->>'_lte')::timestamptz
|
93
|
+
ELSE TRUE
|
94
|
+
END
|
95
|
+
AND CASE
|
96
|
+
WHEN expires_at_filter ? '_eq' THEN m.expires_at = (expires_at_filter->>'_eq')::timestamptz
|
97
|
+
ELSE TRUE
|
98
|
+
END
|
99
|
+
)
|
100
|
+
ELSE TRUE
|
101
|
+
END
|
102
|
+
AND -(m.embedding <#> (SELECT normalized_vector FROM normalized_query)) >= match_threshold
|
103
|
+
ORDER BY -(m.embedding <#> (SELECT normalized_vector FROM normalized_query)) DESC
|
104
|
+
LIMIT match_count;
|
105
|
+
$$;
|
106
|
+
|
107
|
+
-- Track the function in Hasura
|
108
|
+
COMMENT ON FUNCTION public.search_memories IS E'@graphql({"type": "Query"})';
|