@cerefox/memory 1.0.5 → 1.1.0-beta.1
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/AGENT_QUICK_REFERENCE.md +11 -2
- package/dist/bin/cerefox.js +836 -198
- package/dist/frontend/assets/index-BMFGsK0D.js +121 -0
- package/dist/frontend/assets/index-BMFGsK0D.js.map +1 -0
- package/dist/frontend/assets/index-C1JXZA9m.css +1 -0
- package/dist/frontend/index.html +2 -2
- package/dist/server-assets/_shared/ef-meta/index.ts +2 -2
- package/dist/server-assets/_shared/mcp-tools/_utils.ts +74 -12
- package/dist/server-assets/_shared/mcp-tools/get-help-content.ts +4 -4
- package/dist/server-assets/_shared/mcp-tools/index.ts +11 -0
- package/dist/server-assets/_shared/mcp-tools/relations.ts +284 -0
- package/dist/server-assets/_shared/mcp-tools/search.ts +14 -8
- package/dist/server-assets/db/migrations/0014_document_relations.sql +59 -0
- package/dist/server-assets/db/rpcs.sql +311 -17
- package/dist/server-assets/db/schema.sql +35 -2
- package/docs/guides/configuration.md +23 -5
- package/docs/guides/setup-local.md +3 -1
- package/docs/guides/upgrading.md +1 -1
- package/package.json +3 -3
- package/dist/frontend/assets/index-Asx5wD7g.css +0 -1
- package/dist/frontend/assets/index-Csj-6UHY.js +0 -125
- package/dist/frontend/assets/index-Csj-6UHY.js.map +0 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
-- 0014_document_relations.sql — typed edges between documents (iteration 29).
|
|
2
|
+
--
|
|
3
|
+
-- Adds the relation graph on top of the existing document model:
|
|
4
|
+
-- * cerefox_document_relations — typed, directed edges (source → target)
|
|
5
|
+
-- * cerefox_documents.lifecycle_status — 'active' | 'superseded' | 'stale' | 'archived'
|
|
6
|
+
--
|
|
7
|
+
-- Design: docs/research/document-relations-and-semantic-graph.md §2.2, §3.
|
|
8
|
+
-- Idempotent: safe to re-run.
|
|
9
|
+
|
|
10
|
+
CREATE TABLE IF NOT EXISTS cerefox_document_relations (
|
|
11
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
12
|
+
source_id UUID NOT NULL REFERENCES cerefox_documents(id) ON DELETE CASCADE,
|
|
13
|
+
target_id UUID NOT NULL REFERENCES cerefox_documents(id) ON DELETE CASCADE,
|
|
14
|
+
-- Free-text by design: agents define new types without a migration. The
|
|
15
|
+
-- type dictionary (in the RPCs) gives known types behaviour; unknown types
|
|
16
|
+
-- are stored and returned, just without special handling.
|
|
17
|
+
rel_type TEXT NOT NULL,
|
|
18
|
+
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
19
|
+
author TEXT NOT NULL DEFAULT 'unknown',
|
|
20
|
+
author_type TEXT NOT NULL DEFAULT 'agent',
|
|
21
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
22
|
+
-- One edge of a given type per ordered pair; different types may coexist.
|
|
23
|
+
UNIQUE (source_id, target_id, rel_type),
|
|
24
|
+
-- A document relating to itself is always a mistake, and self-edges would
|
|
25
|
+
-- make traversal loop.
|
|
26
|
+
CONSTRAINT cerefox_relations_no_self_edge CHECK (source_id <> target_id)
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE INDEX IF NOT EXISTS idx_cerefox_relations_source ON cerefox_document_relations(source_id);
|
|
30
|
+
CREATE INDEX IF NOT EXISTS idx_cerefox_relations_target ON cerefox_document_relations(target_id);
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_cerefox_relations_type ON cerefox_document_relations(rel_type);
|
|
32
|
+
|
|
33
|
+
-- Lifecycle status: how a document stands relative to the rest of the graph.
|
|
34
|
+
-- Distinct from review_status (editorial state) and deleted_at (existence).
|
|
35
|
+
ALTER TABLE cerefox_documents
|
|
36
|
+
ADD COLUMN IF NOT EXISTS lifecycle_status TEXT NOT NULL DEFAULT 'active';
|
|
37
|
+
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_cerefox_docs_lifecycle
|
|
39
|
+
ON cerefox_documents(lifecycle_status)
|
|
40
|
+
WHERE lifecycle_status <> 'active';
|
|
41
|
+
|
|
42
|
+
-- Data-API grants for the new table (migration 0013 / #26: privileges are
|
|
43
|
+
-- explicit now, and a new table gets none by default).
|
|
44
|
+
DO $$
|
|
45
|
+
BEGIN
|
|
46
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'service_role') THEN
|
|
47
|
+
GRANT SELECT, INSERT, UPDATE, DELETE
|
|
48
|
+
ON TABLE public.cerefox_document_relations TO service_role;
|
|
49
|
+
END IF;
|
|
50
|
+
END
|
|
51
|
+
$$;
|
|
52
|
+
|
|
53
|
+
-- Relation writes are auditable operations; widen the audit-log constraint.
|
|
54
|
+
ALTER TABLE cerefox_audit_log DROP CONSTRAINT IF EXISTS cerefox_audit_log_operation_check;
|
|
55
|
+
ALTER TABLE cerefox_audit_log ADD CONSTRAINT cerefox_audit_log_operation_check CHECK (
|
|
56
|
+
operation IN ('create', 'update-content', 'update-metadata', 'delete',
|
|
57
|
+
'status-change', 'archive', 'unarchive', 'restore',
|
|
58
|
+
'relation-set', 'relation-delete')
|
|
59
|
+
);
|
|
@@ -99,10 +99,13 @@ CREATE OR REPLACE FUNCTION cerefox_hybrid_search(
|
|
|
99
99
|
p_query_text TEXT,
|
|
100
100
|
p_query_embedding VECTOR(768),
|
|
101
101
|
p_match_count INT DEFAULT 10,
|
|
102
|
-
p_alpha FLOAT DEFAULT
|
|
102
|
+
p_alpha FLOAT DEFAULT NULL,
|
|
103
103
|
p_use_upgrade BOOLEAN DEFAULT FALSE,
|
|
104
104
|
p_project_id UUID DEFAULT NULL,
|
|
105
|
-
|
|
105
|
+
-- NULL means "not specified by the caller" (#133): resolve from
|
|
106
|
+
-- cerefox_config, else the built-in default. Callers that pass a value
|
|
107
|
+
-- still win — the chain is per-call > client .env > DB config > default.
|
|
108
|
+
p_min_score FLOAT DEFAULT NULL,
|
|
106
109
|
p_metadata_filter JSONB DEFAULT NULL,
|
|
107
110
|
-- 28I follow-up (v1.0.4): in OR-fallback mode, the unconditional FTS pass
|
|
108
111
|
-- requires at least this fraction of the query's meaningful (non-stopword,
|
|
@@ -110,7 +113,7 @@ CREATE OR REPLACE FUNCTION cerefox_hybrid_search(
|
|
|
110
113
|
-- meant 100% of terms — the pass this gate generalizes. Chunks below the
|
|
111
114
|
-- bar can still pass via the vector threshold, else they are
|
|
112
115
|
-- below-confidence material. 0 restores the pre-gate OR behavior.
|
|
113
|
-
p_min_term_coverage FLOAT DEFAULT
|
|
116
|
+
p_min_term_coverage FLOAT DEFAULT NULL
|
|
114
117
|
)
|
|
115
118
|
RETURNS TABLE (
|
|
116
119
|
chunk_id UUID,
|
|
@@ -164,6 +167,13 @@ DECLARE
|
|
|
164
167
|
seen_tokens TEXT[] := '{}';
|
|
165
168
|
total_tokens INT;
|
|
166
169
|
candidate_count INT := p_match_count * 5;
|
|
170
|
+
-- #133 resolution: caller value, else deployment config, else built-in.
|
|
171
|
+
v_min_score FLOAT := COALESCE(p_min_score,
|
|
172
|
+
cerefox_config_float('min_search_score', 0.5));
|
|
173
|
+
v_alpha FLOAT := COALESCE(p_alpha,
|
|
174
|
+
cerefox_config_float('search_alpha', 0.7));
|
|
175
|
+
v_min_coverage FLOAT := COALESCE(p_min_term_coverage,
|
|
176
|
+
cerefox_config_float('min_term_coverage', 0.5));
|
|
167
177
|
BEGIN
|
|
168
178
|
-- Build the OR-composed query: plainto each whitespace token (so tokens get
|
|
169
179
|
-- the same normalization/stemming as the AND path), skip stopword-only
|
|
@@ -217,7 +227,7 @@ BEGIN
|
|
|
217
227
|
WHEN and_matches OR total_tokens = 0 THEN TRUE
|
|
218
228
|
ELSE (SELECT COUNT(*) FROM unnest(tok_queries) tq
|
|
219
229
|
WHERE c.fts @@ tq)::FLOAT
|
|
220
|
-
>=
|
|
230
|
+
>= v_min_coverage * total_tokens
|
|
221
231
|
END AS coverage_ok
|
|
222
232
|
FROM cerefox_chunks c
|
|
223
233
|
JOIN cerefox_documents d ON c.document_id = d.id
|
|
@@ -261,8 +271,8 @@ BEGIN
|
|
|
261
271
|
combined AS (
|
|
262
272
|
SELECT
|
|
263
273
|
COALESCE(f.id, v.id) AS id,
|
|
264
|
-
(
|
|
265
|
-
(1.0 -
|
|
274
|
+
( v_alpha * COALESCE(v.vec_score, 0.0) +
|
|
275
|
+
(1.0 - v_alpha) * COALESCE(f.fts_score, 0.0)
|
|
266
276
|
) AS score,
|
|
267
277
|
COALESCE(v.vec_score, 0.0) AS vec_score,
|
|
268
278
|
-- TRUE when the chunk matched the @@ FTS operator WITH enough
|
|
@@ -282,10 +292,24 @@ BEGIN
|
|
|
282
292
|
-- results (no FTS match) are filtered by the cosine threshold.
|
|
283
293
|
flagged AS (
|
|
284
294
|
SELECT *,
|
|
285
|
-
(combined.has_fts_match OR combined.vec_score >=
|
|
295
|
+
(combined.has_fts_match OR combined.vec_score >= v_min_score) AS passes
|
|
286
296
|
FROM combined
|
|
287
297
|
),
|
|
288
|
-
any_pass AS (SELECT bool_or(fl.passes) AS ok FROM flagged fl)
|
|
298
|
+
any_pass AS (SELECT bool_or(fl.passes) AS ok FROM flagged fl),
|
|
299
|
+
-- v1.0.6: in the below-confidence fallback, rank each candidate WITHIN
|
|
300
|
+
-- its parent document so we can return one chunk per document. The cap
|
|
301
|
+
-- used to apply to chunks, so when a document owned several of the top
|
|
302
|
+
-- chunks the caller saw fewer than 3 results after document-level
|
|
303
|
+
-- de-duplication (cerefox_search_docs, CLI and web) — the count varied
|
|
304
|
+
-- with corpus shape rather than with the cap.
|
|
305
|
+
ranked AS (
|
|
306
|
+
SELECT fl.*,
|
|
307
|
+
ROW_NUMBER() OVER (
|
|
308
|
+
PARTITION BY ch.document_id ORDER BY fl.score DESC
|
|
309
|
+
) AS rank_in_doc
|
|
310
|
+
FROM flagged fl
|
|
311
|
+
JOIN cerefox_chunks ch ON ch.id = fl.id
|
|
312
|
+
)
|
|
289
313
|
SELECT
|
|
290
314
|
c.id AS chunk_id,
|
|
291
315
|
c.document_id,
|
|
@@ -311,11 +335,13 @@ BEGIN
|
|
|
311
335
|
-- memory layer can produce. "Truly nothing" (no candidates at all)
|
|
312
336
|
-- still returns zero rows.
|
|
313
337
|
NOT ap.ok AS below_confidence
|
|
314
|
-
FROM
|
|
338
|
+
FROM ranked cm
|
|
315
339
|
CROSS JOIN any_pass ap
|
|
316
340
|
JOIN cerefox_chunks c ON c.id = cm.id
|
|
317
341
|
JOIN cerefox_documents d ON c.document_id = d.id
|
|
318
|
-
|
|
342
|
+
-- Normal results are unchanged; fallback rows are restricted to each
|
|
343
|
+
-- document's best chunk so the cap below counts documents, not chunks.
|
|
344
|
+
WHERE cm.passes OR (NOT ap.ok AND cm.rank_in_doc = 1)
|
|
319
345
|
ORDER BY cm.score DESC
|
|
320
346
|
LIMIT (SELECT CASE WHEN ap2.ok THEN p_match_count
|
|
321
347
|
ELSE LEAST(p_match_count, 3) END
|
|
@@ -333,7 +359,7 @@ CREATE OR REPLACE FUNCTION cerefox_fts_search(
|
|
|
333
359
|
p_metadata_filter JSONB DEFAULT NULL,
|
|
334
360
|
-- v1.0.4: see cerefox_hybrid_search. In OR-fallback mode results must
|
|
335
361
|
-- match at least this fraction of the query's meaningful terms.
|
|
336
|
-
p_min_term_coverage FLOAT DEFAULT
|
|
362
|
+
p_min_term_coverage FLOAT DEFAULT NULL
|
|
337
363
|
)
|
|
338
364
|
RETURNS TABLE (
|
|
339
365
|
chunk_id UUID,
|
|
@@ -367,6 +393,8 @@ DECLARE
|
|
|
367
393
|
tok_queries tsquery[] := '{}';
|
|
368
394
|
seen_tokens TEXT[] := '{}';
|
|
369
395
|
total_tokens INT;
|
|
396
|
+
v_min_coverage FLOAT := COALESCE(p_min_term_coverage,
|
|
397
|
+
cerefox_config_float('min_term_coverage', 0.5));
|
|
370
398
|
BEGIN
|
|
371
399
|
FOR tok IN SELECT unnest(regexp_split_to_array(trim(p_query_text), '\s+')) LOOP
|
|
372
400
|
tok_q := plainto_tsquery('english', tok);
|
|
@@ -427,7 +455,7 @@ BEGIN
|
|
|
427
455
|
-- returns only chunks matching enough of the query's terms.
|
|
428
456
|
AND (and_matches OR total_tokens = 0
|
|
429
457
|
OR (SELECT COUNT(*) FROM unnest(tok_queries) tq
|
|
430
|
-
WHERE c.fts @@ tq)::FLOAT >=
|
|
458
|
+
WHERE c.fts @@ tq)::FLOAT >= v_min_coverage * total_tokens)
|
|
431
459
|
AND (p_project_id IS NULL OR EXISTS (
|
|
432
460
|
SELECT 1 FROM cerefox_document_projects dp
|
|
433
461
|
WHERE dp.document_id = d.id AND dp.project_id = p_project_id
|
|
@@ -733,13 +761,15 @@ CREATE OR REPLACE FUNCTION cerefox_search_docs(
|
|
|
733
761
|
p_query_text TEXT,
|
|
734
762
|
p_query_embedding VECTOR(768),
|
|
735
763
|
p_match_count INT DEFAULT 5,
|
|
736
|
-
p_alpha FLOAT DEFAULT
|
|
764
|
+
p_alpha FLOAT DEFAULT NULL,
|
|
737
765
|
p_project_id UUID DEFAULT NULL,
|
|
738
|
-
p_min_score FLOAT DEFAULT
|
|
766
|
+
p_min_score FLOAT DEFAULT NULL,
|
|
739
767
|
p_small_to_big_threshold INT DEFAULT 20000,
|
|
740
768
|
p_context_window INT DEFAULT 1,
|
|
741
769
|
p_metadata_filter JSONB DEFAULT NULL,
|
|
742
|
-
|
|
770
|
+
-- NULL flows through to cerefox_hybrid_search, which resolves the
|
|
771
|
+
-- caller > cerefox_config > built-in chain in one place (#133).
|
|
772
|
+
p_min_term_coverage FLOAT DEFAULT NULL
|
|
743
773
|
)
|
|
744
774
|
RETURNS TABLE (
|
|
745
775
|
document_id UUID,
|
|
@@ -1724,6 +1754,239 @@ BEGIN
|
|
|
1724
1754
|
END;
|
|
1725
1755
|
$$;
|
|
1726
1756
|
|
|
1757
|
+
-- ══ Document relations (iteration 29) ═════════════════════════════════════════
|
|
1758
|
+
-- Typed edges between documents. Design:
|
|
1759
|
+
-- docs/research/document-relations-and-semantic-graph.md
|
|
1760
|
+
--
|
|
1761
|
+
-- Type dictionary: rel_type is free text (any string is accepted and returned),
|
|
1762
|
+
-- but a few KNOWN types carry behaviour. Keeping the dictionary in one place
|
|
1763
|
+
-- here — rather than scattered CASE expressions — is what lets the set/delete
|
|
1764
|
+
-- RPCs stay symmetric with each other.
|
|
1765
|
+
-- symmetric both directions are written/removed together
|
|
1766
|
+
-- supersedes target becomes 'superseded'
|
|
1767
|
+
-- contradicts both documents become 'stale'
|
|
1768
|
+
CREATE OR REPLACE FUNCTION cerefox_relation_is_symmetric(p_rel_type TEXT)
|
|
1769
|
+
RETURNS BOOLEAN
|
|
1770
|
+
LANGUAGE sql
|
|
1771
|
+
IMMUTABLE
|
|
1772
|
+
SET search_path = public, pg_catalog
|
|
1773
|
+
AS $$
|
|
1774
|
+
SELECT p_rel_type IN ('related_to', 'contradicts', 'duplicates');
|
|
1775
|
+
$$;
|
|
1776
|
+
|
|
1777
|
+
-- Create (or update) a relation. Symmetric types write both directions in one
|
|
1778
|
+
-- transaction, so a half-written pair is impossible.
|
|
1779
|
+
CREATE OR REPLACE FUNCTION cerefox_set_relation(
|
|
1780
|
+
p_source_id UUID,
|
|
1781
|
+
p_target_id UUID,
|
|
1782
|
+
p_rel_type TEXT,
|
|
1783
|
+
p_author TEXT DEFAULT 'unknown',
|
|
1784
|
+
p_author_type TEXT DEFAULT 'agent',
|
|
1785
|
+
p_metadata JSONB DEFAULT '{}'::jsonb
|
|
1786
|
+
)
|
|
1787
|
+
RETURNS TABLE (
|
|
1788
|
+
relation_id UUID,
|
|
1789
|
+
source_id UUID,
|
|
1790
|
+
target_id UUID,
|
|
1791
|
+
rel_type TEXT,
|
|
1792
|
+
is_symmetric BOOLEAN
|
|
1793
|
+
)
|
|
1794
|
+
LANGUAGE plpgsql
|
|
1795
|
+
SECURITY DEFINER
|
|
1796
|
+
SET search_path = public, pg_catalog
|
|
1797
|
+
AS $$
|
|
1798
|
+
-- The OUT columns (source_id, target_id, rel_type) share names with the
|
|
1799
|
+
-- table's columns; inside the INSERT/ON CONFLICT below the COLUMN is meant.
|
|
1800
|
+
#variable_conflict use_column
|
|
1801
|
+
DECLARE
|
|
1802
|
+
v_symmetric BOOLEAN := cerefox_relation_is_symmetric(p_rel_type);
|
|
1803
|
+
v_id UUID;
|
|
1804
|
+
BEGIN
|
|
1805
|
+
IF p_source_id = p_target_id THEN
|
|
1806
|
+
RAISE EXCEPTION 'A document cannot relate to itself (%).', p_source_id
|
|
1807
|
+
USING ERRCODE = '22023';
|
|
1808
|
+
END IF;
|
|
1809
|
+
IF p_rel_type IS NULL OR btrim(p_rel_type) = '' THEN
|
|
1810
|
+
RAISE EXCEPTION 'rel_type is required.' USING ERRCODE = '22023';
|
|
1811
|
+
END IF;
|
|
1812
|
+
-- Explicit existence checks give a clear error instead of an FK violation.
|
|
1813
|
+
IF NOT EXISTS (SELECT 1 FROM cerefox_documents d
|
|
1814
|
+
WHERE d.id = p_source_id AND d.deleted_at IS NULL) THEN
|
|
1815
|
+
RAISE EXCEPTION 'Source document % not found (or deleted).', p_source_id
|
|
1816
|
+
USING ERRCODE = '22023';
|
|
1817
|
+
END IF;
|
|
1818
|
+
IF NOT EXISTS (SELECT 1 FROM cerefox_documents d
|
|
1819
|
+
WHERE d.id = p_target_id AND d.deleted_at IS NULL) THEN
|
|
1820
|
+
RAISE EXCEPTION 'Target document % not found (or deleted).', p_target_id
|
|
1821
|
+
USING ERRCODE = '22023';
|
|
1822
|
+
END IF;
|
|
1823
|
+
|
|
1824
|
+
INSERT INTO cerefox_document_relations AS r
|
|
1825
|
+
(source_id, target_id, rel_type, metadata, author, author_type)
|
|
1826
|
+
VALUES (p_source_id, p_target_id, btrim(p_rel_type), COALESCE(p_metadata, '{}'::jsonb),
|
|
1827
|
+
p_author, p_author_type)
|
|
1828
|
+
ON CONFLICT (source_id, target_id, rel_type) DO UPDATE
|
|
1829
|
+
SET metadata = EXCLUDED.metadata,
|
|
1830
|
+
author = EXCLUDED.author,
|
|
1831
|
+
author_type = EXCLUDED.author_type
|
|
1832
|
+
RETURNING r.id INTO v_id;
|
|
1833
|
+
|
|
1834
|
+
IF v_symmetric THEN
|
|
1835
|
+
INSERT INTO cerefox_document_relations
|
|
1836
|
+
(source_id, target_id, rel_type, metadata, author, author_type)
|
|
1837
|
+
VALUES (p_target_id, p_source_id, btrim(p_rel_type),
|
|
1838
|
+
COALESCE(p_metadata, '{}'::jsonb), p_author, p_author_type)
|
|
1839
|
+
ON CONFLICT (source_id, target_id, rel_type) DO UPDATE
|
|
1840
|
+
SET metadata = EXCLUDED.metadata,
|
|
1841
|
+
author = EXCLUDED.author,
|
|
1842
|
+
author_type = EXCLUDED.author_type;
|
|
1843
|
+
END IF;
|
|
1844
|
+
|
|
1845
|
+
-- Lifecycle side effects (type dictionary).
|
|
1846
|
+
IF btrim(p_rel_type) = 'supersedes' THEN
|
|
1847
|
+
UPDATE cerefox_documents SET lifecycle_status = 'superseded'
|
|
1848
|
+
WHERE id = p_target_id;
|
|
1849
|
+
ELSIF btrim(p_rel_type) = 'contradicts' THEN
|
|
1850
|
+
UPDATE cerefox_documents SET lifecycle_status = 'stale'
|
|
1851
|
+
WHERE id IN (p_source_id, p_target_id);
|
|
1852
|
+
END IF;
|
|
1853
|
+
|
|
1854
|
+
INSERT INTO cerefox_audit_log (document_id, operation, author, author_type, description)
|
|
1855
|
+
VALUES (p_source_id, 'relation-set', p_author, p_author_type,
|
|
1856
|
+
format('%s → %s (%s)', p_source_id, p_target_id, btrim(p_rel_type)));
|
|
1857
|
+
|
|
1858
|
+
RETURN QUERY SELECT v_id, p_source_id, p_target_id, btrim(p_rel_type), v_symmetric;
|
|
1859
|
+
END;
|
|
1860
|
+
$$;
|
|
1861
|
+
|
|
1862
|
+
-- Remove a relation. Symmetric types remove both directions. Lifecycle side
|
|
1863
|
+
-- effects are NOT auto-reverted: a document marked superseded may have been
|
|
1864
|
+
-- superseded by something else too, and guessing wrong is worse than leaving
|
|
1865
|
+
-- the operator to set it explicitly.
|
|
1866
|
+
CREATE OR REPLACE FUNCTION cerefox_delete_relation(
|
|
1867
|
+
p_source_id UUID,
|
|
1868
|
+
p_target_id UUID,
|
|
1869
|
+
p_rel_type TEXT,
|
|
1870
|
+
p_author TEXT DEFAULT 'unknown',
|
|
1871
|
+
p_author_type TEXT DEFAULT 'agent'
|
|
1872
|
+
)
|
|
1873
|
+
RETURNS INT
|
|
1874
|
+
LANGUAGE plpgsql
|
|
1875
|
+
SECURITY DEFINER
|
|
1876
|
+
SET search_path = public, pg_catalog
|
|
1877
|
+
AS $$
|
|
1878
|
+
DECLARE
|
|
1879
|
+
v_deleted INT := 0;
|
|
1880
|
+
v_n INT;
|
|
1881
|
+
BEGIN
|
|
1882
|
+
DELETE FROM cerefox_document_relations
|
|
1883
|
+
WHERE source_id = p_source_id AND target_id = p_target_id
|
|
1884
|
+
AND rel_type = btrim(p_rel_type);
|
|
1885
|
+
GET DIAGNOSTICS v_n = ROW_COUNT; v_deleted := v_deleted + v_n;
|
|
1886
|
+
|
|
1887
|
+
IF cerefox_relation_is_symmetric(p_rel_type) THEN
|
|
1888
|
+
DELETE FROM cerefox_document_relations
|
|
1889
|
+
WHERE source_id = p_target_id AND target_id = p_source_id
|
|
1890
|
+
AND rel_type = btrim(p_rel_type);
|
|
1891
|
+
GET DIAGNOSTICS v_n = ROW_COUNT; v_deleted := v_deleted + v_n;
|
|
1892
|
+
END IF;
|
|
1893
|
+
|
|
1894
|
+
IF v_deleted > 0 THEN
|
|
1895
|
+
INSERT INTO cerefox_audit_log (document_id, operation, author, author_type, description)
|
|
1896
|
+
VALUES (p_source_id, 'relation-delete', p_author, p_author_type,
|
|
1897
|
+
format('%s → %s (%s)', p_source_id, p_target_id, btrim(p_rel_type)));
|
|
1898
|
+
END IF;
|
|
1899
|
+
RETURN v_deleted;
|
|
1900
|
+
END;
|
|
1901
|
+
$$;
|
|
1902
|
+
|
|
1903
|
+
-- All edges touching a document, in both directions. `direction` tells the
|
|
1904
|
+
-- caller which way each edge points relative to the document asked about.
|
|
1905
|
+
CREATE OR REPLACE FUNCTION cerefox_get_relations(p_document_id UUID)
|
|
1906
|
+
RETURNS TABLE (
|
|
1907
|
+
relation_id UUID,
|
|
1908
|
+
direction TEXT,
|
|
1909
|
+
rel_type TEXT,
|
|
1910
|
+
other_id UUID,
|
|
1911
|
+
other_title TEXT,
|
|
1912
|
+
other_lifecycle TEXT,
|
|
1913
|
+
metadata JSONB,
|
|
1914
|
+
author TEXT,
|
|
1915
|
+
created_at TIMESTAMPTZ
|
|
1916
|
+
)
|
|
1917
|
+
LANGUAGE sql
|
|
1918
|
+
SECURITY DEFINER
|
|
1919
|
+
STABLE
|
|
1920
|
+
SET search_path = public, pg_catalog
|
|
1921
|
+
AS $$
|
|
1922
|
+
SELECT r.id, 'outbound'::TEXT, r.rel_type, r.target_id, d.title,
|
|
1923
|
+
d.lifecycle_status, r.metadata, r.author, r.created_at
|
|
1924
|
+
FROM cerefox_document_relations r
|
|
1925
|
+
JOIN cerefox_documents d ON d.id = r.target_id
|
|
1926
|
+
WHERE r.source_id = p_document_id AND d.deleted_at IS NULL
|
|
1927
|
+
UNION ALL
|
|
1928
|
+
SELECT r.id, 'inbound'::TEXT, r.rel_type, r.source_id, d.title,
|
|
1929
|
+
d.lifecycle_status, r.metadata, r.author, r.created_at
|
|
1930
|
+
FROM cerefox_document_relations r
|
|
1931
|
+
JOIN cerefox_documents d ON d.id = r.source_id
|
|
1932
|
+
WHERE r.target_id = p_document_id AND d.deleted_at IS NULL
|
|
1933
|
+
ORDER BY 3, 9 DESC;
|
|
1934
|
+
$$;
|
|
1935
|
+
|
|
1936
|
+
-- Walk the graph from a document along ONE relation type. Depth > 1 follows
|
|
1937
|
+
-- chains (meaningful for e.g. `follows` / `reply_to`); a visited-set stops
|
|
1938
|
+
-- cycles, which free-text types make possible.
|
|
1939
|
+
CREATE OR REPLACE FUNCTION cerefox_get_neighbors(
|
|
1940
|
+
p_document_id UUID,
|
|
1941
|
+
p_rel_type TEXT,
|
|
1942
|
+
p_depth INT DEFAULT 1,
|
|
1943
|
+
p_from_time TIMESTAMPTZ DEFAULT NULL,
|
|
1944
|
+
p_to_time TIMESTAMPTZ DEFAULT NULL,
|
|
1945
|
+
p_limit INT DEFAULT 50
|
|
1946
|
+
)
|
|
1947
|
+
RETURNS TABLE (
|
|
1948
|
+
document_id UUID,
|
|
1949
|
+
title TEXT,
|
|
1950
|
+
lifecycle_status TEXT,
|
|
1951
|
+
depth INT,
|
|
1952
|
+
direction TEXT,
|
|
1953
|
+
doc_created_at TIMESTAMPTZ
|
|
1954
|
+
)
|
|
1955
|
+
LANGUAGE sql
|
|
1956
|
+
SECURITY DEFINER
|
|
1957
|
+
STABLE
|
|
1958
|
+
SET search_path = public, pg_catalog
|
|
1959
|
+
AS $$
|
|
1960
|
+
WITH RECURSIVE walk AS (
|
|
1961
|
+
SELECT p_document_id AS id, 0 AS depth, 'self'::TEXT AS direction,
|
|
1962
|
+
ARRAY[p_document_id] AS seen
|
|
1963
|
+
UNION ALL
|
|
1964
|
+
SELECT nxt.id, w.depth + 1, nxt.direction, w.seen || nxt.id
|
|
1965
|
+
FROM walk w
|
|
1966
|
+
CROSS JOIN LATERAL (
|
|
1967
|
+
SELECT r.target_id AS id, 'outbound'::TEXT AS direction
|
|
1968
|
+
FROM cerefox_document_relations r
|
|
1969
|
+
WHERE r.source_id = w.id AND r.rel_type = btrim(p_rel_type)
|
|
1970
|
+
UNION ALL
|
|
1971
|
+
SELECT r.source_id, 'inbound'::TEXT
|
|
1972
|
+
FROM cerefox_document_relations r
|
|
1973
|
+
WHERE r.target_id = w.id AND r.rel_type = btrim(p_rel_type)
|
|
1974
|
+
) nxt
|
|
1975
|
+
WHERE w.depth < GREATEST(p_depth, 1)
|
|
1976
|
+
AND NOT (nxt.id = ANY(w.seen)) -- cycle guard
|
|
1977
|
+
)
|
|
1978
|
+
SELECT DISTINCT ON (w.id)
|
|
1979
|
+
w.id, d.title, d.lifecycle_status, w.depth, w.direction, d.created_at
|
|
1980
|
+
FROM walk w
|
|
1981
|
+
JOIN cerefox_documents d ON d.id = w.id
|
|
1982
|
+
WHERE w.depth > 0
|
|
1983
|
+
AND d.deleted_at IS NULL
|
|
1984
|
+
AND (p_from_time IS NULL OR d.created_at >= p_from_time)
|
|
1985
|
+
AND (p_to_time IS NULL OR d.created_at <= p_to_time)
|
|
1986
|
+
ORDER BY w.id, w.depth
|
|
1987
|
+
LIMIT GREATEST(p_limit, 1);
|
|
1988
|
+
$$;
|
|
1989
|
+
|
|
1727
1990
|
-- ── cerefox_get_config / cerefox_set_config ──────────────────────────────────
|
|
1728
1991
|
-- Read/write key-value config from cerefox_config table.
|
|
1729
1992
|
|
|
@@ -1737,6 +2000,31 @@ AS $$
|
|
|
1737
2000
|
SELECT value FROM cerefox_config WHERE key = p_key;
|
|
1738
2001
|
$$;
|
|
1739
2002
|
|
|
2003
|
+
-- Numeric config reader with a fallback (v1.1.0, #133). Returns p_fallback
|
|
2004
|
+
-- when the key is unset or unparseable, so a malformed row can never break
|
|
2005
|
+
-- search — it just reverts to the built-in default.
|
|
2006
|
+
CREATE OR REPLACE FUNCTION cerefox_config_float(p_key TEXT, p_fallback FLOAT)
|
|
2007
|
+
RETURNS FLOAT
|
|
2008
|
+
LANGUAGE plpgsql
|
|
2009
|
+
SECURITY DEFINER
|
|
2010
|
+
STABLE
|
|
2011
|
+
SET search_path = public, pg_catalog
|
|
2012
|
+
AS $$
|
|
2013
|
+
DECLARE
|
|
2014
|
+
v_raw TEXT;
|
|
2015
|
+
v_num FLOAT;
|
|
2016
|
+
BEGIN
|
|
2017
|
+
SELECT value INTO v_raw FROM cerefox_config WHERE key = p_key;
|
|
2018
|
+
IF v_raw IS NULL OR v_raw = '' THEN RETURN p_fallback; END IF;
|
|
2019
|
+
BEGIN
|
|
2020
|
+
v_num := v_raw::FLOAT;
|
|
2021
|
+
EXCEPTION WHEN others THEN
|
|
2022
|
+
RETURN p_fallback;
|
|
2023
|
+
END;
|
|
2024
|
+
RETURN v_num;
|
|
2025
|
+
END;
|
|
2026
|
+
$$;
|
|
2027
|
+
|
|
1740
2028
|
CREATE OR REPLACE FUNCTION cerefox_set_config(p_key TEXT, p_value TEXT)
|
|
1741
2029
|
RETURNS VOID
|
|
1742
2030
|
LANGUAGE plpgsql
|
|
@@ -1744,7 +2032,13 @@ SECURITY DEFINER
|
|
|
1744
2032
|
SET search_path = public, pg_catalog
|
|
1745
2033
|
AS $$
|
|
1746
2034
|
DECLARE
|
|
1747
|
-
|
|
2035
|
+
-- Retrieval tunables (#133) join the governance keys: setting one here
|
|
2036
|
+
-- governs EVERY access path (CLI, local + remote MCP, Edge Functions, web),
|
|
2037
|
+
-- because they all resolve through these RPCs.
|
|
2038
|
+
v_allowed TEXT[] := ARRAY[
|
|
2039
|
+
'usage_tracking_enabled', 'require_requestor_identity', 'requestor_identity_format',
|
|
2040
|
+
'min_search_score', 'min_term_coverage', 'search_alpha'
|
|
2041
|
+
];
|
|
1748
2042
|
BEGIN
|
|
1749
2043
|
IF NOT (p_key = ANY(v_allowed)) THEN
|
|
1750
2044
|
RAISE EXCEPTION 'Unknown config key: %. Allowed keys: %', p_key, v_allowed;
|
|
@@ -1938,7 +2232,7 @@ SET search_path = public, pg_catalog
|
|
|
1938
2232
|
AS $$
|
|
1939
2233
|
-- Keep in lockstep with the `@version:` marker in schema.sql (cut_release.ts
|
|
1940
2234
|
-- enforces it). Bump whenever schema.sql OR rpcs.sql changes.
|
|
1941
|
-
SELECT '0.
|
|
2235
|
+
SELECT '0.10.0'::TEXT;
|
|
1942
2236
|
$$;
|
|
1943
2237
|
|
|
1944
2238
|
-- ── cerefox_content_format_stats ─────────────────────────────────────────────
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
-- Requires extensions: vector (pgvector), uuid-ossp
|
|
6
6
|
-- These are enabled at the top of db_deploy.py before this file is applied.
|
|
7
7
|
--
|
|
8
|
-
-- @version: 0.
|
|
8
|
+
-- @version: 0.10.0
|
|
9
9
|
-- The `@version` marker above is read by the schema-version-mismatch banner
|
|
10
10
|
-- (see /api/v1/schema-version). Bump it whenever schema.sql OR rpcs.sql
|
|
11
11
|
-- changes in a way that requires `cerefox server deploy` to be re-run —
|
|
@@ -49,6 +49,11 @@ CREATE TABLE IF NOT EXISTS cerefox_documents (
|
|
|
49
49
|
-- 'pending_review' = modified by agent, not yet reviewed.
|
|
50
50
|
-- Content is searchable in both states.
|
|
51
51
|
review_status TEXT NOT NULL DEFAULT 'approved',
|
|
52
|
+
-- lifecycle_status: where this document stands relative to the graph —
|
|
53
|
+
-- 'active' | 'superseded' | 'stale' | 'archived'. Distinct from
|
|
54
|
+
-- review_status (editorial state) and deleted_at (existence). Maintained by
|
|
55
|
+
-- the relation RPCs (e.g. `supersedes` marks its target superseded).
|
|
56
|
+
lifecycle_status TEXT NOT NULL DEFAULT 'active',
|
|
52
57
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
53
58
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
54
59
|
-- Soft delete: NULL = active, timestamp = deleted (recoverable).
|
|
@@ -118,7 +123,9 @@ CREATE TABLE IF NOT EXISTS cerefox_audit_log (
|
|
|
118
123
|
|
|
119
124
|
CONSTRAINT cerefox_audit_log_operation_check CHECK (
|
|
120
125
|
operation IN ('create', 'update-content', 'update-metadata', 'delete',
|
|
121
|
-
'status-change', 'archive', 'unarchive', 'restore'
|
|
126
|
+
'status-change', 'archive', 'unarchive', 'restore',
|
|
127
|
+
-- iteration 29: graph edges are auditable writes too
|
|
128
|
+
'relation-set', 'relation-delete')
|
|
122
129
|
),
|
|
123
130
|
CONSTRAINT cerefox_audit_log_author_type_check CHECK (author_type IN ('user', 'agent'))
|
|
124
131
|
);
|
|
@@ -132,6 +139,32 @@ CREATE TABLE IF NOT EXISTS cerefox_document_projects (
|
|
|
132
139
|
PRIMARY KEY (document_id, project_id)
|
|
133
140
|
);
|
|
134
141
|
|
|
142
|
+
-- ── Document relations (iteration 29) ─────────────────────────────────────────
|
|
143
|
+
-- Typed, directed edges between documents. rel_type is free text by design so
|
|
144
|
+
-- agents can define new types without a migration; the type dictionary lives in
|
|
145
|
+
-- the RPCs and gives KNOWN types behaviour (symmetry, lifecycle side effects).
|
|
146
|
+
-- Design: docs/research/document-relations-and-semantic-graph.md §2.2.
|
|
147
|
+
|
|
148
|
+
CREATE TABLE IF NOT EXISTS cerefox_document_relations (
|
|
149
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
150
|
+
source_id UUID NOT NULL REFERENCES cerefox_documents(id) ON DELETE CASCADE,
|
|
151
|
+
target_id UUID NOT NULL REFERENCES cerefox_documents(id) ON DELETE CASCADE,
|
|
152
|
+
rel_type TEXT NOT NULL,
|
|
153
|
+
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
154
|
+
author TEXT NOT NULL DEFAULT 'unknown',
|
|
155
|
+
author_type TEXT NOT NULL DEFAULT 'agent',
|
|
156
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
157
|
+
UNIQUE (source_id, target_id, rel_type),
|
|
158
|
+
CONSTRAINT cerefox_relations_no_self_edge CHECK (source_id <> target_id)
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
CREATE INDEX IF NOT EXISTS idx_cerefox_relations_source ON cerefox_document_relations(source_id);
|
|
162
|
+
CREATE INDEX IF NOT EXISTS idx_cerefox_relations_target ON cerefox_document_relations(target_id);
|
|
163
|
+
CREATE INDEX IF NOT EXISTS idx_cerefox_relations_type ON cerefox_document_relations(rel_type);
|
|
164
|
+
CREATE INDEX IF NOT EXISTS idx_cerefox_docs_lifecycle
|
|
165
|
+
ON cerefox_documents(lifecycle_status)
|
|
166
|
+
WHERE lifecycle_status <> 'active';
|
|
167
|
+
|
|
135
168
|
-- ── Chunks ────────────────────────────────────────────────────────────────────
|
|
136
169
|
-- One row per chunk of a document. Embeddings and FTS live here.
|
|
137
170
|
--
|
|
@@ -117,18 +117,36 @@ This handles intermittent OpenAI API errors (500s) that would otherwise cause se
|
|
|
117
117
|
|
|
118
118
|
## Retrieval
|
|
119
119
|
|
|
120
|
+
> **Deployment-wide defaults (v1.1.0+).** `min_search_score`,
|
|
121
|
+
> `min_term_coverage`, and `search_alpha` can also be set **once, in the
|
|
122
|
+
> database**, and every access path obeys — CLI, local and remote MCP, Edge
|
|
123
|
+
> Functions, web — because they all resolve through the same search RPCs:
|
|
124
|
+
>
|
|
125
|
+
> ```bash
|
|
126
|
+
> cerefox config set min_search_score 0.6
|
|
127
|
+
> cerefox config list # shows every settable key
|
|
128
|
+
> ```
|
|
129
|
+
>
|
|
130
|
+
> Resolution order, highest first: **per-call argument** (`--min-score`, the
|
|
131
|
+
> `min_score` MCP parameter) → **client env var** below → **`cerefox_config`**
|
|
132
|
+
> → built-in default. A malformed stored value is ignored in favour of the
|
|
133
|
+
> built-in, so a bad setting can never break search.
|
|
134
|
+
|
|
120
135
|
> **Which paths read these?** Client-side tunables in this section are read
|
|
121
136
|
> from *your* `.env` by the **CLI**, the **local MCP server**, and `cerefox
|
|
122
|
-
> web`.
|
|
123
|
-
>
|
|
124
|
-
>
|
|
125
|
-
> `
|
|
126
|
-
>
|
|
137
|
+
> web`. Since **v1.0.6** the same values are also honored on the **remote MCP /
|
|
138
|
+
> Edge Function path** when set as Supabase **Function secrets**
|
|
139
|
+
> (`supabase secrets set CEREFOX_MIN_SEARCH_SCORE=0.55 --project-ref <ref>`) —
|
|
140
|
+
> the shared helpers read `Deno.env` as well as `process.env`. Per-call
|
|
141
|
+
> parameters (`min_score`, `min_term_coverage`, `alpha` on `cerefox_search`)
|
|
142
|
+
> override both. A single setting that governs every path without secrets is
|
|
143
|
+
> tracked as issue #133 (DB-backed config).
|
|
127
144
|
|
|
128
145
|
| Variable | Default | Description |
|
|
129
146
|
|----------|---------|-------------|
|
|
130
147
|
| `CEREFOX_MAX_RESPONSE_BYTES` | `200000` | Maximum bytes in a single search response (local MCP path). See explanation below. |
|
|
131
148
|
| `CEREFOX_MIN_SEARCH_SCORE` | `0.50` (`0.60` with the local embedder) | Minimum cosine similarity for hybrid and semantic search results (0.0–1.0). The default is embedder-aware: nomic scores unrelated text higher than OpenAI, so `CEREFOX_EMBEDDER=local` raises the floor to 0.60. In **hybrid search**, chunks that matched the FTS keyword operator (`@@`) always pass through regardless of their vector score — the threshold only filters vector-only results. In **semantic search**, all results are filtered. The pure **FTS search** mode is unaffected. Increase for stricter precision; decrease for wider recall. |
|
|
149
|
+
| `CEREFOX_SEARCH_ALPHA` | `0.7` | Hybrid fusion weight (0.0–1.0): `1.0` = pure semantic, `0.0` = pure keyword. Applies to hybrid and document-mode search. Per-call override: `cerefox search --alpha`, or the `alpha` parameter on the `cerefox_search` MCP tool. |
|
|
132
150
|
| `CEREFOX_MIN_TERM_COVERAGE` | *(unset — server default `0.5`)* | Confidence bar for the keyword OR-fallback (v1.0.4, schema ≥ 0.9.1): when a strict all-terms match fails and search relaxes to any-term matching, a result counts as a confident hit only if it matches at least this fraction of the query's meaningful terms; weaker matches surface as below-confidence candidates. `0` restores pre-gate behavior (any matching term passes); `1` requires every term. Per-call override: `cerefox search --min-term-coverage`. Leave unset against pre-0.9.1 servers. |
|
|
133
151
|
| `CEREFOX_EMBED_MAX_INPUT_CHARS` | `20000` | Safety cap on the characters sent to the embedding model per input. The full chunk content is always stored and reconstructed untouched; only the embedding uses the (rare) truncated prefix, so an oversized chunk can never fail an ingest. |
|
|
134
152
|
| `CEREFOX_MODELS_DIR` | `~/.cerefox/models` (in-container: inside the data volume) | Where the local embedder caches downloaded model weights (Cerefox Local; `CEREFOX_EMBEDDER=local`). |
|
|
@@ -143,7 +143,9 @@ cerefox-local start # start a stopped container
|
|
|
143
143
|
cerefox-local stop # stop it (your data persists in the Docker volume)
|
|
144
144
|
cerefox-local restart
|
|
145
145
|
cerefox-local logs -f # follow the logs
|
|
146
|
-
cerefox-local upgrade #
|
|
146
|
+
cerefox-local upgrade # upgrade to the newest release + recreate (keeps data + OPENAI key)
|
|
147
|
+
cerefox-local upgrade v1.2.3 # pin an exact version (also how you downgrade)
|
|
148
|
+
cerefox-local upgrade --latest # follow the moving :latest tag from now on
|
|
147
149
|
cerefox-local uninstall # remove the container, KEEP the data volume
|
|
148
150
|
cerefox-local uninstall --purge # remove the container AND delete the data volume
|
|
149
151
|
```
|
package/docs/guides/upgrading.md
CHANGED
|
@@ -10,7 +10,7 @@ to re-run.
|
|
|
10
10
|
|---|---|
|
|
11
11
|
| **Installer / npm** (end user, no repo clone) | `cerefox self-update` (or re-run the [installer](quickstart.md#1-install), or `bun/npm update -g @cerefox/memory`). Then `cerefox server deploy` **if the release notes flag a server-side change**. `cerefox doctor` verifies. |
|
|
12
12
|
| **Source checkout** (`git clone`, contributor) | `git pull`, then `cerefox server deploy` (or the lower-level `bun scripts/db_*.ts` + `npx supabase functions deploy`). Rebuild the SPA if you run `cerefox web` from source. |
|
|
13
|
-
| **Local / self-hosted (Docker, World B)** | `cerefox-local upgrade` —
|
|
13
|
+
| **Local / self-hosted (Docker, World B)** | `cerefox-local upgrade` — resolves the newest release, pulls it, and recreates the container (`upgrade <tag>` pins an exact version; `upgrade --latest` follows the moving tag). Data persists in the volume; OpenAI key + tuning overrides preserved. **No separate `server deploy`/`reindex`**: the CLI, web, PostgREST, and schema all ship together in one versioned image, so they can't drift. See [`setup-local.md`](setup-local.md). |
|
|
14
14
|
|
|
15
15
|
> **On an old pre-installer clone (0.1.x)?** The cleanest upgrade is to stop
|
|
16
16
|
> running from the repo and install the package: follow the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cerefox/memory",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.1.0-beta.1",
|
|
4
4
|
"description": "Cerefox — user-owned shared memory for AI agents. CLI + stdio MCP server + web UI + ingestion for a knowledge base on your own Supabase project (or fully self-hosted with Cerefox Local).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/fstamatelopoulos/cerefox",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
44
44
|
"@supabase/supabase-js": "^2.45.0",
|
|
45
45
|
"cli-progress": "^3.12.0",
|
|
46
|
-
"commander": "^
|
|
46
|
+
"commander": "^14.0.3",
|
|
47
47
|
"hono": "^4.12.34",
|
|
48
48
|
"mammoth": "^1.9.0",
|
|
49
49
|
"ora": "^9.4.0",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"zod": "^3.23.0"
|
|
55
55
|
},
|
|
56
56
|
"optionalDependencies": {
|
|
57
|
-
"@huggingface/transformers": "^
|
|
57
|
+
"@huggingface/transformers": "^4.2.0",
|
|
58
58
|
"onnxruntime-node": "^1.21.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|