remdb 0.3.181__py3-none-any.whl → 0.3.223__py3-none-any.whl
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.
Potentially problematic release.
This version of remdb might be problematic. Click here for more details.
- rem/agentic/README.md +262 -2
- rem/agentic/context.py +173 -0
- rem/agentic/context_builder.py +12 -2
- rem/agentic/mcp/tool_wrapper.py +2 -2
- rem/agentic/providers/pydantic_ai.py +1 -1
- rem/agentic/schema.py +2 -2
- rem/api/main.py +1 -1
- rem/api/mcp_router/server.py +4 -0
- rem/api/mcp_router/tools.py +542 -170
- rem/api/routers/admin.py +30 -4
- rem/api/routers/auth.py +106 -10
- rem/api/routers/chat/completions.py +66 -18
- rem/api/routers/chat/sse_events.py +7 -3
- rem/api/routers/chat/streaming.py +254 -22
- rem/api/routers/common.py +18 -0
- rem/api/routers/dev.py +7 -1
- rem/api/routers/feedback.py +9 -1
- rem/api/routers/messages.py +176 -38
- rem/api/routers/models.py +9 -1
- rem/api/routers/query.py +12 -1
- rem/api/routers/shared_sessions.py +16 -0
- rem/auth/jwt.py +19 -4
- rem/auth/middleware.py +42 -28
- rem/cli/README.md +62 -0
- rem/cli/commands/db.py +33 -19
- rem/cli/commands/process.py +171 -43
- rem/models/entities/ontology.py +18 -20
- rem/schemas/agents/rem.yaml +1 -1
- rem/services/content/service.py +18 -5
- rem/services/postgres/__init__.py +28 -3
- rem/services/postgres/diff_service.py +57 -5
- rem/services/postgres/programmable_diff_service.py +635 -0
- rem/services/postgres/pydantic_to_sqlalchemy.py +2 -2
- rem/services/postgres/register_type.py +11 -10
- rem/services/postgres/repository.py +14 -4
- rem/services/session/__init__.py +8 -1
- rem/services/session/compression.py +40 -2
- rem/services/session/pydantic_messages.py +276 -0
- rem/settings.py +28 -0
- rem/sql/migrations/001_install.sql +125 -7
- rem/sql/migrations/002_install_models.sql +136 -126
- rem/sql/migrations/004_cache_system.sql +7 -275
- rem/sql/migrations/migrate_session_id_to_uuid.sql +45 -0
- rem/utils/schema_loader.py +6 -6
- {remdb-0.3.181.dist-info → remdb-0.3.223.dist-info}/METADATA +1 -1
- {remdb-0.3.181.dist-info → remdb-0.3.223.dist-info}/RECORD +48 -44
- {remdb-0.3.181.dist-info → remdb-0.3.223.dist-info}/WHEEL +0 -0
- {remdb-0.3.181.dist-info → remdb-0.3.223.dist-info}/entry_points.txt +0 -0
|
@@ -121,18 +121,18 @@ CREATE UNLOGGED TABLE IF NOT EXISTS kv_store (
|
|
|
121
121
|
entity_key VARCHAR(255) NOT NULL,
|
|
122
122
|
entity_type VARCHAR(100) NOT NULL,
|
|
123
123
|
entity_id UUID NOT NULL,
|
|
124
|
-
tenant_id VARCHAR(100)
|
|
124
|
+
tenant_id VARCHAR(100), -- NULL = public/shared data
|
|
125
125
|
user_id VARCHAR(100),
|
|
126
126
|
content_summary TEXT,
|
|
127
127
|
metadata JSONB DEFAULT '{}',
|
|
128
128
|
graph_edges JSONB DEFAULT '[]'::jsonb, -- Cached edges for fast graph traversal
|
|
129
129
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
130
|
-
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
131
|
-
|
|
132
|
-
-- Composite primary key: entity_key unique per tenant
|
|
133
|
-
PRIMARY KEY (tenant_id, entity_key)
|
|
130
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
134
131
|
);
|
|
135
132
|
|
|
133
|
+
-- Unique constraint on (tenant_id, entity_key) using COALESCE to handle NULL tenant_id
|
|
134
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_kv_store_tenant_key ON kv_store (COALESCE(tenant_id, ''), entity_key);
|
|
135
|
+
|
|
136
136
|
-- Index for user-scoped lookups (when user_id IS NOT NULL)
|
|
137
137
|
CREATE INDEX IF NOT EXISTS idx_kv_store_user ON kv_store (tenant_id, user_id)
|
|
138
138
|
WHERE user_id IS NOT NULL;
|
|
@@ -173,7 +173,7 @@ COMMENT ON COLUMN kv_store.entity_id IS
|
|
|
173
173
|
'UUID from primary table for reverse lookup';
|
|
174
174
|
|
|
175
175
|
COMMENT ON COLUMN kv_store.tenant_id IS
|
|
176
|
-
'Tenant identifier for multi-tenancy isolation';
|
|
176
|
+
'Tenant identifier for multi-tenancy isolation. NULL = public/shared data visible to all.';
|
|
177
177
|
|
|
178
178
|
COMMENT ON COLUMN kv_store.user_id IS
|
|
179
179
|
'Optional user scoping. NULL = system-level entity, visible to all users in tenant';
|
|
@@ -271,8 +271,12 @@ BEGIN
|
|
|
271
271
|
AND kv.entity_key = normalize_key(p_entity_key)
|
|
272
272
|
LIMIT 1;
|
|
273
273
|
|
|
274
|
-
-- If not found,
|
|
274
|
+
-- If not found, check if cache is empty and maybe trigger rebuild
|
|
275
275
|
IF entity_table IS NULL THEN
|
|
276
|
+
-- SELF-HEALING: Check if this is because cache is empty
|
|
277
|
+
IF rem_kv_store_empty(effective_user_id) THEN
|
|
278
|
+
PERFORM maybe_trigger_kv_rebuild(effective_user_id, 'rem_lookup');
|
|
279
|
+
END IF;
|
|
276
280
|
RETURN;
|
|
277
281
|
END IF;
|
|
278
282
|
|
|
@@ -357,6 +361,7 @@ DECLARE
|
|
|
357
361
|
entities_by_table JSONB := '{}'::jsonb;
|
|
358
362
|
table_keys JSONB;
|
|
359
363
|
effective_user_id VARCHAR(100);
|
|
364
|
+
v_found_any BOOLEAN := FALSE;
|
|
360
365
|
BEGIN
|
|
361
366
|
effective_user_id := COALESCE(p_user_id, p_tenant_id);
|
|
362
367
|
|
|
@@ -373,6 +378,7 @@ BEGIN
|
|
|
373
378
|
ORDER BY sim_score DESC
|
|
374
379
|
LIMIT p_limit
|
|
375
380
|
LOOP
|
|
381
|
+
v_found_any := TRUE;
|
|
376
382
|
-- Build JSONB mapping {table: [keys]}
|
|
377
383
|
IF entities_by_table ? kv_matches.entity_type THEN
|
|
378
384
|
table_keys := entities_by_table->kv_matches.entity_type;
|
|
@@ -390,6 +396,11 @@ BEGIN
|
|
|
390
396
|
END IF;
|
|
391
397
|
END LOOP;
|
|
392
398
|
|
|
399
|
+
-- SELF-HEALING: If no matches and cache is empty, trigger rebuild
|
|
400
|
+
IF NOT v_found_any AND rem_kv_store_empty(effective_user_id) THEN
|
|
401
|
+
PERFORM maybe_trigger_kv_rebuild(effective_user_id, 'rem_fuzzy');
|
|
402
|
+
END IF;
|
|
403
|
+
|
|
393
404
|
-- Fetch full records using rem_fetch (which now supports NULL user_id)
|
|
394
405
|
RETURN QUERY
|
|
395
406
|
SELECT
|
|
@@ -436,9 +447,25 @@ DECLARE
|
|
|
436
447
|
entities_by_table JSONB := '{}'::jsonb;
|
|
437
448
|
table_keys JSONB;
|
|
438
449
|
effective_user_id VARCHAR(100);
|
|
450
|
+
v_found_start BOOLEAN := FALSE;
|
|
439
451
|
BEGIN
|
|
440
452
|
effective_user_id := COALESCE(p_user_id, p_tenant_id);
|
|
441
453
|
|
|
454
|
+
-- Check if start entity exists in kv_store
|
|
455
|
+
SELECT TRUE INTO v_found_start
|
|
456
|
+
FROM kv_store kv
|
|
457
|
+
WHERE (kv.user_id = effective_user_id OR kv.user_id IS NULL)
|
|
458
|
+
AND kv.entity_key = normalize_key(p_entity_key)
|
|
459
|
+
LIMIT 1;
|
|
460
|
+
|
|
461
|
+
-- SELF-HEALING: If start not found and cache is empty, trigger rebuild
|
|
462
|
+
IF NOT COALESCE(v_found_start, FALSE) THEN
|
|
463
|
+
IF rem_kv_store_empty(effective_user_id) THEN
|
|
464
|
+
PERFORM maybe_trigger_kv_rebuild(effective_user_id, 'rem_traverse');
|
|
465
|
+
END IF;
|
|
466
|
+
RETURN;
|
|
467
|
+
END IF;
|
|
468
|
+
|
|
442
469
|
FOR graph_keys IN
|
|
443
470
|
WITH RECURSIVE graph_traversal AS (
|
|
444
471
|
-- Base case: Find starting entity (user-owned OR public)
|
|
@@ -789,6 +816,97 @@ $$ LANGUAGE plpgsql STABLE;
|
|
|
789
816
|
COMMENT ON FUNCTION fn_get_shared_messages IS
|
|
790
817
|
'Get messages from sessions shared by a specific user with the recipient.';
|
|
791
818
|
|
|
819
|
+
-- ============================================================================
|
|
820
|
+
-- SESSIONS WITH USER INFO
|
|
821
|
+
-- ============================================================================
|
|
822
|
+
-- Function to list sessions with user details (name, email) for admin views
|
|
823
|
+
|
|
824
|
+
-- List sessions with user info, CTE pagination
|
|
825
|
+
-- Note: messages.session_id stores the session UUID (sessions.id)
|
|
826
|
+
CREATE OR REPLACE FUNCTION fn_list_sessions_with_user(
|
|
827
|
+
p_user_id VARCHAR(256) DEFAULT NULL, -- Filter by user_id (NULL = all users, admin only)
|
|
828
|
+
p_user_name VARCHAR(256) DEFAULT NULL, -- Filter by user name (partial match, admin only)
|
|
829
|
+
p_user_email VARCHAR(256) DEFAULT NULL, -- Filter by user email (partial match, admin only)
|
|
830
|
+
p_mode VARCHAR(50) DEFAULT NULL, -- Filter by session mode
|
|
831
|
+
p_page INTEGER DEFAULT 1,
|
|
832
|
+
p_page_size INTEGER DEFAULT 50
|
|
833
|
+
)
|
|
834
|
+
RETURNS TABLE(
|
|
835
|
+
id UUID,
|
|
836
|
+
name VARCHAR(256),
|
|
837
|
+
mode TEXT,
|
|
838
|
+
description TEXT,
|
|
839
|
+
user_id VARCHAR(256),
|
|
840
|
+
user_name VARCHAR(256),
|
|
841
|
+
user_email VARCHAR(256),
|
|
842
|
+
message_count INTEGER,
|
|
843
|
+
total_tokens INTEGER,
|
|
844
|
+
created_at TIMESTAMP,
|
|
845
|
+
updated_at TIMESTAMP,
|
|
846
|
+
metadata JSONB,
|
|
847
|
+
total_count BIGINT
|
|
848
|
+
) AS $$
|
|
849
|
+
BEGIN
|
|
850
|
+
RETURN QUERY
|
|
851
|
+
WITH session_msg_counts AS (
|
|
852
|
+
-- Count messages per session (joining on session UUID)
|
|
853
|
+
SELECT
|
|
854
|
+
m.session_id,
|
|
855
|
+
COUNT(*)::INTEGER as actual_message_count
|
|
856
|
+
FROM messages m
|
|
857
|
+
GROUP BY m.session_id
|
|
858
|
+
),
|
|
859
|
+
filtered_sessions AS (
|
|
860
|
+
SELECT
|
|
861
|
+
s.id,
|
|
862
|
+
s.name,
|
|
863
|
+
s.mode,
|
|
864
|
+
s.description,
|
|
865
|
+
s.user_id,
|
|
866
|
+
COALESCE(u.name, s.user_id)::VARCHAR(256) AS user_name,
|
|
867
|
+
u.email::VARCHAR(256) AS user_email,
|
|
868
|
+
COALESCE(mc.actual_message_count, 0) AS message_count,
|
|
869
|
+
s.total_tokens,
|
|
870
|
+
s.created_at,
|
|
871
|
+
s.updated_at,
|
|
872
|
+
s.metadata
|
|
873
|
+
FROM sessions s
|
|
874
|
+
LEFT JOIN users u ON u.id::text = s.user_id
|
|
875
|
+
LEFT JOIN session_msg_counts mc ON mc.session_id = s.id::text
|
|
876
|
+
WHERE s.deleted_at IS NULL
|
|
877
|
+
AND (p_user_id IS NULL OR s.user_id = p_user_id)
|
|
878
|
+
AND (p_user_name IS NULL OR u.name ILIKE '%' || p_user_name || '%')
|
|
879
|
+
AND (p_user_email IS NULL OR u.email ILIKE '%' || p_user_email || '%')
|
|
880
|
+
AND (p_mode IS NULL OR s.mode = p_mode)
|
|
881
|
+
),
|
|
882
|
+
counted AS (
|
|
883
|
+
SELECT *, COUNT(*) OVER () AS total_count
|
|
884
|
+
FROM filtered_sessions
|
|
885
|
+
)
|
|
886
|
+
SELECT
|
|
887
|
+
c.id,
|
|
888
|
+
c.name,
|
|
889
|
+
c.mode,
|
|
890
|
+
c.description,
|
|
891
|
+
c.user_id,
|
|
892
|
+
c.user_name,
|
|
893
|
+
c.user_email,
|
|
894
|
+
c.message_count,
|
|
895
|
+
c.total_tokens,
|
|
896
|
+
c.created_at,
|
|
897
|
+
c.updated_at,
|
|
898
|
+
c.metadata,
|
|
899
|
+
c.total_count
|
|
900
|
+
FROM counted c
|
|
901
|
+
ORDER BY c.created_at DESC
|
|
902
|
+
LIMIT p_page_size
|
|
903
|
+
OFFSET (p_page - 1) * p_page_size;
|
|
904
|
+
END;
|
|
905
|
+
$$ LANGUAGE plpgsql STABLE;
|
|
906
|
+
|
|
907
|
+
COMMENT ON FUNCTION fn_list_sessions_with_user IS
|
|
908
|
+
'List sessions with user details and computed message counts. Joins messages on session name.';
|
|
909
|
+
|
|
792
910
|
-- ============================================================================
|
|
793
911
|
-- RECORD INSTALLATION
|
|
794
912
|
-- ============================================================================
|