@cerefox/memory 1.1.1 → 1.2.0
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/dist/bin/cerefox.js +94 -5
- package/dist/server-assets/_shared/ef-meta/index.ts +2 -2
- package/dist/server-assets/_shared/mcp-tools/audit-log.ts +7 -0
- package/dist/server-assets/_shared/mcp-tools/get-document.ts +7 -0
- package/dist/server-assets/_shared/mcp-tools/get-help.ts +7 -0
- package/dist/server-assets/_shared/mcp-tools/ingest.ts +11 -0
- package/dist/server-assets/_shared/mcp-tools/list-metadata-keys.ts +7 -0
- package/dist/server-assets/_shared/mcp-tools/list-projects.ts +7 -0
- package/dist/server-assets/_shared/mcp-tools/list-versions.ts +7 -0
- package/dist/server-assets/_shared/mcp-tools/metadata-search.ts +7 -0
- package/dist/server-assets/_shared/mcp-tools/relations.ts +30 -0
- package/dist/server-assets/_shared/mcp-tools/search.ts +7 -0
- package/dist/server-assets/_shared/mcp-tools/set-document-projects.ts +9 -0
- package/dist/server-assets/_shared/mcp-tools/types.ts +34 -0
- package/dist/server-assets/db/migrations/0018_ingest_defers_retention_to_config.sql +48 -0
- package/dist/server-assets/db/rpcs.sql +13 -5
- package/dist/server-assets/db/schema.sql +1 -1
- package/dist/server-assets/supabase/functions/cerefox-mcp/index.ts +2 -0
- package/docs/guides/setup-local.md +8 -1
- package/docs/guides/upgrading.md +27 -0
- package/package.json +1 -1
package/dist/bin/cerefox.js
CHANGED
|
@@ -7438,7 +7438,7 @@ var exports_meta = {};
|
|
|
7438
7438
|
__export(exports_meta, {
|
|
7439
7439
|
PKG_VERSION: () => PKG_VERSION
|
|
7440
7440
|
});
|
|
7441
|
-
var PKG_VERSION = "1.
|
|
7441
|
+
var PKG_VERSION = "1.2.0";
|
|
7442
7442
|
var init_meta = () => {};
|
|
7443
7443
|
|
|
7444
7444
|
// ../../_shared/config/paths.ts
|
|
@@ -25858,7 +25858,7 @@ async function checkServerCompatibility(opts) {
|
|
|
25858
25858
|
var COMPATIBILITY;
|
|
25859
25859
|
var init_compatibility = __esm(() => {
|
|
25860
25860
|
COMPATIBILITY = {
|
|
25861
|
-
minSchema: "0.10.
|
|
25861
|
+
minSchema: "0.10.5",
|
|
25862
25862
|
minEdgeFunctions: "0.6.0"
|
|
25863
25863
|
};
|
|
25864
25864
|
});
|
|
@@ -55148,6 +55148,12 @@ var init_audit_log = __esm(() => {
|
|
|
55148
55148
|
auditLogTool = {
|
|
55149
55149
|
name: "cerefox_get_audit_log",
|
|
55150
55150
|
description: "Retrieve audit log entries showing who changed what and when. Supports filtering by document, author, operation type, and time range. Returns entries with document titles, author attribution, size changes, and descriptions.",
|
|
55151
|
+
annotations: {
|
|
55152
|
+
title: "Read audit log",
|
|
55153
|
+
readOnlyHint: true,
|
|
55154
|
+
idempotentHint: true,
|
|
55155
|
+
openWorldHint: false
|
|
55156
|
+
},
|
|
55151
55157
|
inputSchema: {
|
|
55152
55158
|
type: "object",
|
|
55153
55159
|
required: [],
|
|
@@ -55346,6 +55352,13 @@ var init_relations = __esm(() => {
|
|
|
55346
55352
|
setRelationTool = {
|
|
55347
55353
|
name: "cerefox_set_relation",
|
|
55348
55354
|
description: "Link two documents with a typed, directed relation (source → target). " + `Known types with behaviour: ${KNOWN_TYPES}. Symmetric types (related_to, ` + "contradicts, duplicates) write both directions. `supersedes` marks the target " + "superseded; `contradicts` marks both stale. Any other type string is accepted " + "and stored, just without special behaviour. Re-setting the same edge updates it.",
|
|
55355
|
+
annotations: {
|
|
55356
|
+
title: "Link two documents",
|
|
55357
|
+
readOnlyHint: false,
|
|
55358
|
+
destructiveHint: false,
|
|
55359
|
+
idempotentHint: true,
|
|
55360
|
+
openWorldHint: false
|
|
55361
|
+
},
|
|
55349
55362
|
inputSchema: {
|
|
55350
55363
|
type: "object",
|
|
55351
55364
|
required: ["source_id", "target_id", "rel_type"],
|
|
@@ -55369,6 +55382,13 @@ var init_relations = __esm(() => {
|
|
|
55369
55382
|
deleteRelationTool = {
|
|
55370
55383
|
name: "cerefox_delete_relation",
|
|
55371
55384
|
description: "Remove a typed relation between two documents. Symmetric types remove both " + "directions. Lifecycle status set by an earlier relation is NOT reverted.",
|
|
55385
|
+
annotations: {
|
|
55386
|
+
title: "Remove a relation",
|
|
55387
|
+
readOnlyHint: false,
|
|
55388
|
+
destructiveHint: true,
|
|
55389
|
+
idempotentHint: true,
|
|
55390
|
+
openWorldHint: false
|
|
55391
|
+
},
|
|
55372
55392
|
inputSchema: {
|
|
55373
55393
|
type: "object",
|
|
55374
55394
|
required: ["source_id", "target_id", "rel_type"],
|
|
@@ -55385,6 +55405,12 @@ var init_relations = __esm(() => {
|
|
|
55385
55405
|
getRelationsTool = {
|
|
55386
55406
|
name: "cerefox_get_relations",
|
|
55387
55407
|
description: "List every relation touching a document, in both directions (→ outbound, " + "← inbound). Shows each neighbour's title and lifecycle status, so an agent " + "can tell whether retrieved knowledge has been superseded or contradicted.",
|
|
55408
|
+
annotations: {
|
|
55409
|
+
title: "List a document's relations",
|
|
55410
|
+
readOnlyHint: true,
|
|
55411
|
+
idempotentHint: true,
|
|
55412
|
+
openWorldHint: false
|
|
55413
|
+
},
|
|
55388
55414
|
inputSchema: {
|
|
55389
55415
|
type: "object",
|
|
55390
55416
|
required: ["document_id"],
|
|
@@ -55398,6 +55424,12 @@ var init_relations = __esm(() => {
|
|
|
55398
55424
|
getNeighborsTool = {
|
|
55399
55425
|
name: "cerefox_get_neighbors",
|
|
55400
55426
|
description: "Walk the relation graph outward from a document along ONE relation type. " + "Use after cerefox_get_relations shows which types exist. depth > 1 follows " + "chains (useful for follows / reply_to); cycles terminate safely. Optional " + "from_time / to_time filter neighbours by their creation time.",
|
|
55427
|
+
annotations: {
|
|
55428
|
+
title: "Walk the relation graph",
|
|
55429
|
+
readOnlyHint: true,
|
|
55430
|
+
idempotentHint: true,
|
|
55431
|
+
openWorldHint: false
|
|
55432
|
+
},
|
|
55401
55433
|
inputSchema: {
|
|
55402
55434
|
type: "object",
|
|
55403
55435
|
required: ["document_id", "rel_type"],
|
|
@@ -55450,6 +55482,12 @@ var init_get_document = __esm(() => {
|
|
|
55450
55482
|
getDocumentTool = {
|
|
55451
55483
|
name: "cerefox_get_document",
|
|
55452
55484
|
description: "Retrieve the full reconstructed content of a document. Pass version_id to retrieve an archived version; omit it (or pass null) for the current version. Version UUIDs are returned by cerefox_list_versions. The response header includes the document's current content_hash — pass it back as expected_content_hash when updating via cerefox_ingest (optimistic concurrency).",
|
|
55485
|
+
annotations: {
|
|
55486
|
+
title: "Read document",
|
|
55487
|
+
readOnlyHint: true,
|
|
55488
|
+
idempotentHint: true,
|
|
55489
|
+
openWorldHint: false
|
|
55490
|
+
},
|
|
55453
55491
|
inputSchema: {
|
|
55454
55492
|
type: "object",
|
|
55455
55493
|
required: ["document_id"],
|
|
@@ -55535,6 +55573,12 @@ var init_get_help = __esm(() => {
|
|
|
55535
55573
|
getHelpTool = {
|
|
55536
55574
|
name: "cerefox_get_help",
|
|
55537
55575
|
description: "Retrieve Cerefox's own agent-usage guidance (the AGENT_QUICK_REFERENCE.md content). Call with no arguments to get the full reference + a section index. Call with `topic` to get a single section (case-insensitive substring match against H2 headings). Use this whenever you're uncertain about Cerefox conventions — link forms, project-membership semantics, update workflows, etc.",
|
|
55576
|
+
annotations: {
|
|
55577
|
+
title: "Read Cerefox conventions",
|
|
55578
|
+
readOnlyHint: true,
|
|
55579
|
+
idempotentHint: true,
|
|
55580
|
+
openWorldHint: false
|
|
55581
|
+
},
|
|
55538
55582
|
inputSchema: {
|
|
55539
55583
|
type: "object",
|
|
55540
55584
|
properties: {
|
|
@@ -55789,6 +55833,13 @@ var init_ingest = __esm(() => {
|
|
|
55789
55833
|
ingestTool = {
|
|
55790
55834
|
name: "cerefox_ingest",
|
|
55791
55835
|
description: "Save a note or document to the Cerefox knowledge base.",
|
|
55836
|
+
annotations: {
|
|
55837
|
+
title: "Save or update a document",
|
|
55838
|
+
readOnlyHint: false,
|
|
55839
|
+
destructiveHint: true,
|
|
55840
|
+
idempotentHint: false,
|
|
55841
|
+
openWorldHint: false
|
|
55842
|
+
},
|
|
55792
55843
|
inputSchema: {
|
|
55793
55844
|
type: "object",
|
|
55794
55845
|
required: ["title", "content"],
|
|
@@ -55853,6 +55904,12 @@ var init_list_metadata_keys = __esm(() => {
|
|
|
55853
55904
|
listMetadataKeysTool = {
|
|
55854
55905
|
name: "cerefox_list_metadata_keys",
|
|
55855
55906
|
description: "List all metadata keys currently in use across documents in the Cerefox knowledge base. Returns each key with its document count and up to 5 example values.",
|
|
55907
|
+
annotations: {
|
|
55908
|
+
title: "List metadata keys",
|
|
55909
|
+
readOnlyHint: true,
|
|
55910
|
+
idempotentHint: true,
|
|
55911
|
+
openWorldHint: false
|
|
55912
|
+
},
|
|
55856
55913
|
inputSchema: {
|
|
55857
55914
|
type: "object",
|
|
55858
55915
|
properties: {
|
|
@@ -55894,6 +55951,12 @@ var init_list_projects = __esm(() => {
|
|
|
55894
55951
|
listProjectsTool = {
|
|
55895
55952
|
name: "cerefox_list_projects",
|
|
55896
55953
|
description: "List all projects with their names and IDs. Use this to discover available projects before filtering by project_name in other tools.",
|
|
55954
|
+
annotations: {
|
|
55955
|
+
title: "List projects",
|
|
55956
|
+
readOnlyHint: true,
|
|
55957
|
+
idempotentHint: true,
|
|
55958
|
+
openWorldHint: false
|
|
55959
|
+
},
|
|
55897
55960
|
inputSchema: {
|
|
55898
55961
|
type: "object",
|
|
55899
55962
|
properties: {
|
|
@@ -55939,6 +56002,12 @@ var init_list_versions = __esm(() => {
|
|
|
55939
56002
|
listVersionsTool = {
|
|
55940
56003
|
name: "cerefox_list_versions",
|
|
55941
56004
|
description: "List all archived versions of a document, newest first. Returns version_id (use with cerefox_get_document), version_number, source, chunk_count, total_chars, and created_at.",
|
|
56005
|
+
annotations: {
|
|
56006
|
+
title: "List document versions",
|
|
56007
|
+
readOnlyHint: true,
|
|
56008
|
+
idempotentHint: true,
|
|
56009
|
+
openWorldHint: false
|
|
56010
|
+
},
|
|
55942
56011
|
inputSchema: {
|
|
55943
56012
|
type: "object",
|
|
55944
56013
|
required: ["document_id"],
|
|
@@ -56032,6 +56101,12 @@ var init_metadata_search = __esm(() => {
|
|
|
56032
56101
|
metadataSearchTool = {
|
|
56033
56102
|
name: "cerefox_metadata_search",
|
|
56034
56103
|
description: "Find or list documents by metadata key-value criteria without a text search term. Use to discover documents tagged with specific attributes, browse by taxonomy, retrieve messages/tasks by type and status, or list all documents in a project (pass project_name alone). At least one of metadata_filter, project_name, updated_since, or created_since must be supplied; results are ordered newest-updated first.",
|
|
56104
|
+
annotations: {
|
|
56105
|
+
title: "Find documents by metadata",
|
|
56106
|
+
readOnlyHint: true,
|
|
56107
|
+
idempotentHint: true,
|
|
56108
|
+
openWorldHint: false
|
|
56109
|
+
},
|
|
56035
56110
|
inputSchema: {
|
|
56036
56111
|
type: "object",
|
|
56037
56112
|
properties: {
|
|
@@ -56192,6 +56267,12 @@ var init_search = __esm(() => {
|
|
|
56192
56267
|
searchTool = {
|
|
56193
56268
|
name: "cerefox_search",
|
|
56194
56269
|
description: "Search the Cerefox personal knowledge base. Returns complete documents ranked by hybrid (FTS + semantic) relevance.",
|
|
56270
|
+
annotations: {
|
|
56271
|
+
title: "Search knowledge base",
|
|
56272
|
+
readOnlyHint: true,
|
|
56273
|
+
idempotentHint: true,
|
|
56274
|
+
openWorldHint: false
|
|
56275
|
+
},
|
|
56195
56276
|
inputSchema: {
|
|
56196
56277
|
type: "object",
|
|
56197
56278
|
required: ["query"],
|
|
@@ -56277,6 +56358,13 @@ var init_set_document_projects = __esm(() => {
|
|
|
56277
56358
|
setDocumentProjectsTool = {
|
|
56278
56359
|
name: "cerefox_set_document_projects",
|
|
56279
56360
|
description: "Set the document's project memberships to EXACTLY the given list. Destructive replace: any existing memberships not in this list are removed. Pass an empty list to clear all project memberships. Projects are looked up by name (case-insensitive); missing projects are created. Logged as update-metadata in the audit log — content is untouched. Use cerefox_ingest with project_names if you want to set memberships AND update content in one call. Use this tool when you only need to change project membership without re-writing the document body.",
|
|
56361
|
+
annotations: {
|
|
56362
|
+
title: "Replace project memberships",
|
|
56363
|
+
readOnlyHint: false,
|
|
56364
|
+
destructiveHint: true,
|
|
56365
|
+
idempotentHint: true,
|
|
56366
|
+
openWorldHint: false
|
|
56367
|
+
},
|
|
56280
56368
|
inputSchema: {
|
|
56281
56369
|
type: "object",
|
|
56282
56370
|
required: ["document_id", "project_names"],
|
|
@@ -69491,7 +69579,8 @@ function buildServer() {
|
|
|
69491
69579
|
tools: (await listEnabledTools(supabase)).map((t) => ({
|
|
69492
69580
|
name: t.name,
|
|
69493
69581
|
description: t.description,
|
|
69494
|
-
inputSchema: t.inputSchema
|
|
69582
|
+
inputSchema: t.inputSchema,
|
|
69583
|
+
...t.annotations ? { annotations: t.annotations } : {}
|
|
69495
69584
|
}))
|
|
69496
69585
|
}));
|
|
69497
69586
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
@@ -75610,8 +75699,8 @@ import { homedir as homedir6 } from "node:os";
|
|
|
75610
75699
|
import { join as join9 } from "node:path";
|
|
75611
75700
|
|
|
75612
75701
|
// ../../_shared/ef-meta/index.ts
|
|
75613
|
-
var EF_VERSION = "1.
|
|
75614
|
-
var EF_LAST_CHANGED = "1.
|
|
75702
|
+
var EF_VERSION = "1.2.0";
|
|
75703
|
+
var EF_LAST_CHANGED = "1.2.0";
|
|
75615
75704
|
|
|
75616
75705
|
// src/cli/util/checks.ts
|
|
75617
75706
|
init_config();
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* doesn't touch `supabase/functions/` leaves it alone).
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
export const EF_VERSION = "1.
|
|
21
|
+
export const EF_VERSION = "1.2.0";
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* The most recent version whose EF-side SOURCE actually changed (#127).
|
|
@@ -28,7 +28,7 @@ export const EF_VERSION = "1.1.1";
|
|
|
28
28
|
* `cut_release.ts` ONLY when EF source changed since the last tag; doctor
|
|
29
29
|
* uses it to stay silent on label-only drift.
|
|
30
30
|
*/
|
|
31
|
-
export const EF_LAST_CHANGED = "1.
|
|
31
|
+
export const EF_LAST_CHANGED = "1.2.0";
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* The 8 peer EFs the cerefox-mcp aggregator probes (excludes cerefox-mcp
|
|
@@ -65,6 +65,13 @@ export const auditLogTool: ToolDefinition = {
|
|
|
65
65
|
name: "cerefox_get_audit_log",
|
|
66
66
|
description:
|
|
67
67
|
"Retrieve audit log entries showing who changed what and when. Supports filtering by document, author, operation type, and time range. Returns entries with document titles, author attribution, size changes, and descriptions.",
|
|
68
|
+
// Read-only: touches nothing. Safe for a client to run without prompting.
|
|
69
|
+
annotations: {
|
|
70
|
+
title: "Read audit log",
|
|
71
|
+
readOnlyHint: true,
|
|
72
|
+
idempotentHint: true,
|
|
73
|
+
openWorldHint: false,
|
|
74
|
+
},
|
|
68
75
|
inputSchema: {
|
|
69
76
|
type: "object",
|
|
70
77
|
required: [],
|
|
@@ -57,6 +57,13 @@ export const getDocumentTool: ToolDefinition = {
|
|
|
57
57
|
name: "cerefox_get_document",
|
|
58
58
|
description:
|
|
59
59
|
"Retrieve the full reconstructed content of a document. Pass version_id to retrieve an archived version; omit it (or pass null) for the current version. Version UUIDs are returned by cerefox_list_versions. The response header includes the document's current content_hash — pass it back as expected_content_hash when updating via cerefox_ingest (optimistic concurrency).",
|
|
60
|
+
// Read-only: touches nothing. Safe for a client to run without prompting.
|
|
61
|
+
annotations: {
|
|
62
|
+
title: "Read document",
|
|
63
|
+
readOnlyHint: true,
|
|
64
|
+
idempotentHint: true,
|
|
65
|
+
openWorldHint: false,
|
|
66
|
+
},
|
|
60
67
|
inputSchema: {
|
|
61
68
|
type: "object",
|
|
62
69
|
required: ["document_id"],
|
|
@@ -71,6 +71,13 @@ export const getHelpTool: ToolDefinition = {
|
|
|
71
71
|
name: "cerefox_get_help",
|
|
72
72
|
description:
|
|
73
73
|
"Retrieve Cerefox's own agent-usage guidance (the AGENT_QUICK_REFERENCE.md content). Call with no arguments to get the full reference + a section index. Call with `topic` to get a single section (case-insensitive substring match against H2 headings). Use this whenever you're uncertain about Cerefox conventions — link forms, project-membership semantics, update workflows, etc.",
|
|
74
|
+
// Read-only: touches nothing. Safe for a client to run without prompting.
|
|
75
|
+
annotations: {
|
|
76
|
+
title: "Read Cerefox conventions",
|
|
77
|
+
readOnlyHint: true,
|
|
78
|
+
idempotentHint: true,
|
|
79
|
+
openWorldHint: false,
|
|
80
|
+
},
|
|
74
81
|
inputSchema: {
|
|
75
82
|
type: "object",
|
|
76
83
|
properties: {
|
|
@@ -350,6 +350,17 @@ async function handler(
|
|
|
350
350
|
export const ingestTool: ToolDefinition = {
|
|
351
351
|
name: "cerefox_ingest",
|
|
352
352
|
description: "Save a note or document to the Cerefox knowledge base.",
|
|
353
|
+
/** Destructive: `project_names` REPLACES the document's project memberships, and
|
|
354
|
+
* memberships have no version history — a partial list silently drops the rest.
|
|
355
|
+
* Content itself is version-snapshotted and guarded by expected_content_hash, so
|
|
356
|
+
* the destructive part is the membership replace, not the body. */
|
|
357
|
+
annotations: {
|
|
358
|
+
title: "Save or update a document",
|
|
359
|
+
readOnlyHint: false,
|
|
360
|
+
destructiveHint: true,
|
|
361
|
+
idempotentHint: false,
|
|
362
|
+
openWorldHint: false,
|
|
363
|
+
},
|
|
353
364
|
inputSchema: {
|
|
354
365
|
type: "object",
|
|
355
366
|
required: ["title", "content"],
|
|
@@ -41,6 +41,13 @@ export const listMetadataKeysTool: ToolDefinition = {
|
|
|
41
41
|
name: "cerefox_list_metadata_keys",
|
|
42
42
|
description:
|
|
43
43
|
"List all metadata keys currently in use across documents in the Cerefox knowledge base. Returns each key with its document count and up to 5 example values.",
|
|
44
|
+
// Read-only: touches nothing. Safe for a client to run without prompting.
|
|
45
|
+
annotations: {
|
|
46
|
+
title: "List metadata keys",
|
|
47
|
+
readOnlyHint: true,
|
|
48
|
+
idempotentHint: true,
|
|
49
|
+
openWorldHint: false,
|
|
50
|
+
},
|
|
44
51
|
inputSchema: {
|
|
45
52
|
type: "object",
|
|
46
53
|
properties: {
|
|
@@ -45,6 +45,13 @@ export const listProjectsTool: ToolDefinition = {
|
|
|
45
45
|
name: "cerefox_list_projects",
|
|
46
46
|
description:
|
|
47
47
|
"List all projects with their names and IDs. Use this to discover available projects before filtering by project_name in other tools.",
|
|
48
|
+
// Read-only: touches nothing. Safe for a client to run without prompting.
|
|
49
|
+
annotations: {
|
|
50
|
+
title: "List projects",
|
|
51
|
+
readOnlyHint: true,
|
|
52
|
+
idempotentHint: true,
|
|
53
|
+
openWorldHint: false,
|
|
54
|
+
},
|
|
48
55
|
inputSchema: {
|
|
49
56
|
type: "object",
|
|
50
57
|
properties: {
|
|
@@ -53,6 +53,13 @@ export const listVersionsTool: ToolDefinition = {
|
|
|
53
53
|
name: "cerefox_list_versions",
|
|
54
54
|
description:
|
|
55
55
|
"List all archived versions of a document, newest first. Returns version_id (use with cerefox_get_document), version_number, source, chunk_count, total_chars, and created_at.",
|
|
56
|
+
// Read-only: touches nothing. Safe for a client to run without prompting.
|
|
57
|
+
annotations: {
|
|
58
|
+
title: "List document versions",
|
|
59
|
+
readOnlyHint: true,
|
|
60
|
+
idempotentHint: true,
|
|
61
|
+
openWorldHint: false,
|
|
62
|
+
},
|
|
56
63
|
inputSchema: {
|
|
57
64
|
type: "object",
|
|
58
65
|
required: ["document_id"],
|
|
@@ -124,6 +124,13 @@ export const metadataSearchTool: ToolDefinition = {
|
|
|
124
124
|
name: "cerefox_metadata_search",
|
|
125
125
|
description:
|
|
126
126
|
"Find or list documents by metadata key-value criteria without a text search term. Use to discover documents tagged with specific attributes, browse by taxonomy, retrieve messages/tasks by type and status, or list all documents in a project (pass project_name alone). At least one of metadata_filter, project_name, updated_since, or created_since must be supplied; results are ordered newest-updated first.",
|
|
127
|
+
// Read-only: touches nothing. Safe for a client to run without prompting.
|
|
128
|
+
annotations: {
|
|
129
|
+
title: "Find documents by metadata",
|
|
130
|
+
readOnlyHint: true,
|
|
131
|
+
idempotentHint: true,
|
|
132
|
+
openWorldHint: false,
|
|
133
|
+
},
|
|
127
134
|
inputSchema: {
|
|
128
135
|
type: "object",
|
|
129
136
|
properties: {
|
|
@@ -81,6 +81,14 @@ export const setRelationTool: ToolDefinition = {
|
|
|
81
81
|
"contradicts, duplicates) write both directions. `supersedes` marks the target " +
|
|
82
82
|
"superseded; `contradicts` marks both stale. Any other type string is accepted " +
|
|
83
83
|
"and stored, just without special behaviour. Re-setting the same edge updates it.",
|
|
84
|
+
/** Upsert: re-running with the same edge changes nothing. Adds an edge; removes nothing. */
|
|
85
|
+
annotations: {
|
|
86
|
+
title: "Link two documents",
|
|
87
|
+
readOnlyHint: false,
|
|
88
|
+
destructiveHint: false,
|
|
89
|
+
idempotentHint: true,
|
|
90
|
+
openWorldHint: false,
|
|
91
|
+
},
|
|
84
92
|
inputSchema: {
|
|
85
93
|
type: "object",
|
|
86
94
|
required: ["source_id", "target_id", "rel_type"],
|
|
@@ -143,6 +151,14 @@ export const deleteRelationTool: ToolDefinition = {
|
|
|
143
151
|
description:
|
|
144
152
|
"Remove a typed relation between two documents. Symmetric types remove both " +
|
|
145
153
|
"directions. Lifecycle status set by an earlier relation is NOT reverted.",
|
|
154
|
+
/** Removes an edge (and its mirror for symmetric types). Relations are not versioned, so the edge is gone. */
|
|
155
|
+
annotations: {
|
|
156
|
+
title: "Remove a relation",
|
|
157
|
+
readOnlyHint: false,
|
|
158
|
+
destructiveHint: true,
|
|
159
|
+
idempotentHint: true,
|
|
160
|
+
openWorldHint: false,
|
|
161
|
+
},
|
|
146
162
|
inputSchema: {
|
|
147
163
|
type: "object",
|
|
148
164
|
required: ["source_id", "target_id", "rel_type"],
|
|
@@ -203,6 +219,13 @@ export const getRelationsTool: ToolDefinition = {
|
|
|
203
219
|
"List every relation touching a document, in both directions (→ outbound, " +
|
|
204
220
|
"← inbound). Shows each neighbour's title and lifecycle status, so an agent " +
|
|
205
221
|
"can tell whether retrieved knowledge has been superseded or contradicted.",
|
|
222
|
+
// Read-only: traversal only, mutates nothing.
|
|
223
|
+
annotations: {
|
|
224
|
+
title: "List a document's relations",
|
|
225
|
+
readOnlyHint: true,
|
|
226
|
+
idempotentHint: true,
|
|
227
|
+
openWorldHint: false,
|
|
228
|
+
},
|
|
206
229
|
inputSchema: {
|
|
207
230
|
type: "object",
|
|
208
231
|
required: ["document_id"],
|
|
@@ -267,6 +290,13 @@ export const getNeighborsTool: ToolDefinition = {
|
|
|
267
290
|
"Use after cerefox_get_relations shows which types exist. depth > 1 follows " +
|
|
268
291
|
"chains (useful for follows / reply_to); cycles terminate safely. Optional " +
|
|
269
292
|
"from_time / to_time filter neighbours by their creation time.",
|
|
293
|
+
// Read-only: traversal only, mutates nothing.
|
|
294
|
+
annotations: {
|
|
295
|
+
title: "Walk the relation graph",
|
|
296
|
+
readOnlyHint: true,
|
|
297
|
+
idempotentHint: true,
|
|
298
|
+
openWorldHint: false,
|
|
299
|
+
},
|
|
270
300
|
inputSchema: {
|
|
271
301
|
type: "object",
|
|
272
302
|
required: ["document_id", "rel_type"],
|
|
@@ -192,6 +192,13 @@ export const searchTool: ToolDefinition = {
|
|
|
192
192
|
name: "cerefox_search",
|
|
193
193
|
description:
|
|
194
194
|
"Search the Cerefox personal knowledge base. Returns complete documents ranked by hybrid (FTS + semantic) relevance.",
|
|
195
|
+
// Read-only: touches nothing. Safe for a client to run without prompting.
|
|
196
|
+
annotations: {
|
|
197
|
+
title: "Search knowledge base",
|
|
198
|
+
readOnlyHint: true,
|
|
199
|
+
idempotentHint: true,
|
|
200
|
+
openWorldHint: false,
|
|
201
|
+
},
|
|
195
202
|
inputSchema: {
|
|
196
203
|
type: "object",
|
|
197
204
|
required: ["query"],
|
|
@@ -72,6 +72,15 @@ export const setDocumentProjectsTool: ToolDefinition = {
|
|
|
72
72
|
name: "cerefox_set_document_projects",
|
|
73
73
|
description:
|
|
74
74
|
"Set the document's project memberships to EXACTLY the given list. Destructive replace: any existing memberships not in this list are removed. Pass an empty list to clear all project memberships. Projects are looked up by name (case-insensitive); missing projects are created. Logged as update-metadata in the audit log — content is untouched. Use cerefox_ingest with project_names if you want to set memberships AND update content in one call. Use this tool when you only need to change project membership without re-writing the document body.",
|
|
75
|
+
/** Destructive by contract: any membership not in the list is removed, and an
|
|
76
|
+
* empty list clears all of them. No version history for memberships. */
|
|
77
|
+
annotations: {
|
|
78
|
+
title: "Replace project memberships",
|
|
79
|
+
readOnlyHint: false,
|
|
80
|
+
destructiveHint: true,
|
|
81
|
+
idempotentHint: true,
|
|
82
|
+
openWorldHint: false,
|
|
83
|
+
},
|
|
75
84
|
inputSchema: {
|
|
76
85
|
type: "object",
|
|
77
86
|
required: ["document_id", "project_names"],
|
|
@@ -66,10 +66,44 @@ export interface ToolContext {
|
|
|
66
66
|
accessPath: AccessPath;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
/**
|
|
70
|
+
* MCP tool annotations (spec revision 2025-03-26).
|
|
71
|
+
*
|
|
72
|
+
* Hints that let a client reason about a tool BEFORE calling it. Without them a
|
|
73
|
+
* tool inherits the spec defaults `readOnlyHint: false` and
|
|
74
|
+
* `destructiveHint: true` — i.e. "may do something irreversible" — so declaring
|
|
75
|
+
* nothing tells every client that `cerefox_search` is as dangerous as a
|
|
76
|
+
* destructive write. The usual result is that users blanket-approve the server,
|
|
77
|
+
* which drains the meaning from the prompt on the tools that genuinely warrant
|
|
78
|
+
* one.
|
|
79
|
+
*
|
|
80
|
+
* These are hints from a server the client may not trust, so a client must not
|
|
81
|
+
* use them as a security boundary. They exist to inform UX, not to enforce it.
|
|
82
|
+
*/
|
|
83
|
+
export interface ToolAnnotations {
|
|
84
|
+
/** Human-readable label for UIs. */
|
|
85
|
+
title?: string;
|
|
86
|
+
/** The tool does not modify anything. */
|
|
87
|
+
readOnlyHint?: boolean;
|
|
88
|
+
/** The tool may perform IRREVERSIBLE updates. Only meaningful when the tool
|
|
89
|
+
* is not read-only. Static per tool: if any argument shape can destroy, the
|
|
90
|
+
* tool is destructive. */
|
|
91
|
+
destructiveHint?: boolean;
|
|
92
|
+
/** Repeated calls with the same arguments have no additional effect. */
|
|
93
|
+
idempotentHint?: boolean;
|
|
94
|
+
/** The tool reaches external entities (a web search) rather than a closed
|
|
95
|
+
* domain. False throughout Cerefox: every tool talks to the operator's own
|
|
96
|
+
* store. */
|
|
97
|
+
openWorldHint?: boolean;
|
|
98
|
+
}
|
|
99
|
+
|
|
69
100
|
export interface ToolDefinition {
|
|
70
101
|
name: string;
|
|
71
102
|
description: string;
|
|
72
103
|
inputSchema: JsonSchema;
|
|
104
|
+
/** See `ToolAnnotations`. Required in practice: a unit test fails if a tool
|
|
105
|
+
* omits it, so adding a tool forces the read-only/destructive decision. */
|
|
106
|
+
annotations?: ToolAnnotations;
|
|
73
107
|
/** Returns the MCP `TextContent.text` body. Tools that fail throw; the
|
|
74
108
|
* consumer's request wrapper translates thrown errors into JSON-RPC
|
|
75
109
|
* `-32603` (internal error) responses, or `-32602` (invalid params)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
-- 0018_ingest_defers_retention_to_config.sql — make the store's retention policy
|
|
2
|
+
-- actually take effect on the write path (#183, reported by @tdebasis).
|
|
3
|
+
--
|
|
4
|
+
-- v1.1.0 moved version retention into `cerefox_config` and changed
|
|
5
|
+
-- `cerefox_snapshot_version` to default its parameters to NULL so that
|
|
6
|
+
-- COALESCE(param, config, default) could fall through to the store's policy.
|
|
7
|
+
--
|
|
8
|
+
-- That half worked. `cerefox_ingest_document` — snapshot_version's ONLY caller —
|
|
9
|
+
-- kept the pre-1.1.0 concrete defaults:
|
|
10
|
+
--
|
|
11
|
+
-- p_retention_hours INT DEFAULT 48
|
|
12
|
+
-- p_cleanup_enabled BOOLEAN DEFAULT TRUE
|
|
13
|
+
--
|
|
14
|
+
-- and passed them straight through. So snapshot_version never once received NULL
|
|
15
|
+
-- on a real write, and never once consulted `cerefox_config`. The store-level
|
|
16
|
+
-- switch was inert on the only path that matters.
|
|
17
|
+
--
|
|
18
|
+
-- Consequences, all silent:
|
|
19
|
+
--
|
|
20
|
+
-- * `version_cleanup_enabled = false` did nothing. Pruning ran anyway.
|
|
21
|
+
-- * Migration 0016's fail-safe — which seeds `false` on existing stores during
|
|
22
|
+
-- the 1.1.0 upgrade precisely so history could not be quietly discarded —
|
|
23
|
+
-- was defeated by this.
|
|
24
|
+
-- * `version_retention_hours` did nothing. The window stayed at 48 hours, not
|
|
25
|
+
-- the configured value (or the 120h default from migration 0017).
|
|
26
|
+
-- * The v1.1.0 release notes promised "Nothing is deleted." That was false.
|
|
27
|
+
--
|
|
28
|
+
-- The damage is per-document and latent rather than immediate: cleanup only runs
|
|
29
|
+
-- for a document when THAT document is next written. So versions older than the
|
|
30
|
+
-- window survive until their document is edited, then vanish. On the maintainer's
|
|
31
|
+
-- store, 362 of 397 versions were older than 48h and still intact when this was
|
|
32
|
+
-- found — every one of them was one edit away from being pruned.
|
|
33
|
+
--
|
|
34
|
+
-- Fix: `cerefox_ingest_document`'s parameters default to NULL, so the store's
|
|
35
|
+
-- policy resolves. An explicit value still overrides for a single call.
|
|
36
|
+
--
|
|
37
|
+
-- Lives in rpcs.sql, which `cerefox server deploy` re-applies. This migration
|
|
38
|
+
-- exists so the schema version moves and operators are told to redeploy.
|
|
39
|
+
--
|
|
40
|
+
-- Idempotent: safe to re-run.
|
|
41
|
+
|
|
42
|
+
DO $$
|
|
43
|
+
BEGIN
|
|
44
|
+
RAISE NOTICE
|
|
45
|
+
'Migration 0018: cerefox_ingest_document now defers version retention to '
|
|
46
|
+
'cerefox_config. Before this, version_cleanup_enabled and '
|
|
47
|
+
'version_retention_hours were silently ignored on every write (#183).';
|
|
48
|
+
END $$;
|
|
@@ -1268,8 +1268,10 @@ $$;
|
|
|
1268
1268
|
-- content, char_count, embedding (float[]), embedder (text)
|
|
1269
1269
|
-- p_author, p_author_type : for audit entry
|
|
1270
1270
|
-- p_source_label : version source label for snapshot ('file','paste','agent','manual')
|
|
1271
|
-
-- p_retention_hours :
|
|
1272
|
-
--
|
|
1271
|
+
-- p_retention_hours : version-cleanup window. NULL (default) = use the store's
|
|
1272
|
+
-- `version_retention_hours` from cerefox_config.
|
|
1273
|
+
-- p_cleanup_enabled : whether cleanup runs. NULL (default) = use the store's
|
|
1274
|
+
-- `version_cleanup_enabled`.
|
|
1273
1275
|
-- p_expected_content_hash : optimistic-concurrency token (iter-32). On the UPDATE
|
|
1274
1276
|
-- path this must equal the document's current content_hash —
|
|
1275
1277
|
-- the caller proves they based their edit on the live version.
|
|
@@ -1301,8 +1303,14 @@ CREATE FUNCTION cerefox_ingest_document(
|
|
|
1301
1303
|
p_author TEXT DEFAULT 'unknown',
|
|
1302
1304
|
p_author_type TEXT DEFAULT 'user',
|
|
1303
1305
|
p_source_label TEXT DEFAULT 'manual',
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
+
-- NULL, so `cerefox_snapshot_version` falls through to the store's policy in
|
|
1307
|
+
-- cerefox_config. These carried concrete defaults (48 / TRUE) until v1.1.2,
|
|
1308
|
+
-- which silently defeated the whole store-level retention feature: this is
|
|
1309
|
+
-- snapshot_version's ONLY caller, so it never once received NULL and never
|
|
1310
|
+
-- once consulted the config (#183, reported by @tdebasis). A caller may still
|
|
1311
|
+
-- pass explicit values to override the store for one call.
|
|
1312
|
+
p_retention_hours INT DEFAULT NULL,
|
|
1313
|
+
p_cleanup_enabled BOOLEAN DEFAULT NULL,
|
|
1306
1314
|
p_expected_content_hash TEXT DEFAULT NULL,
|
|
1307
1315
|
p_last_write_wins BOOLEAN DEFAULT FALSE,
|
|
1308
1316
|
-- content_format for the chunks being written (iter-28D). 2 = exact-partition
|
|
@@ -2325,7 +2333,7 @@ SET search_path = public, pg_catalog
|
|
|
2325
2333
|
AS $$
|
|
2326
2334
|
-- Keep in lockstep with the `@version:` marker in schema.sql (cut_release.ts
|
|
2327
2335
|
-- enforces it). Bump whenever schema.sql OR rpcs.sql changes.
|
|
2328
|
-
SELECT '0.10.
|
|
2336
|
+
SELECT '0.10.5'::TEXT;
|
|
2329
2337
|
$$;
|
|
2330
2338
|
|
|
2331
2339
|
-- ── 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.10.
|
|
8
|
+
-- @version: 0.10.5
|
|
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 —
|
|
@@ -68,6 +68,8 @@ async function buildToolList(supabase: MCPSupabaseClient) {
|
|
|
68
68
|
name: t.name,
|
|
69
69
|
description: t.description,
|
|
70
70
|
inputSchema: t.inputSchema,
|
|
71
|
+
// MCP 2025-03-26 tool annotations; MCP_VERSION already declares that revision.
|
|
72
|
+
...(t.annotations ? { annotations: t.annotations } : {}),
|
|
71
73
|
}));
|
|
72
74
|
}
|
|
73
75
|
|
|
@@ -145,13 +145,20 @@ cerefox-local start # start a stopped container
|
|
|
145
145
|
cerefox-local stop # stop it (your data persists in the Docker volume)
|
|
146
146
|
cerefox-local restart
|
|
147
147
|
cerefox-local logs -f # follow the logs
|
|
148
|
-
cerefox-local upgrade #
|
|
148
|
+
cerefox-local upgrade # newest stable release + recreate (keeps data + OPENAI key)
|
|
149
149
|
cerefox-local upgrade v1.2.3 # pin an exact version (also how you downgrade)
|
|
150
150
|
cerefox-local upgrade --latest # follow the moving :latest tag from now on
|
|
151
151
|
cerefox-local uninstall # remove the container, KEEP the data volume
|
|
152
152
|
cerefox-local uninstall --purge # remove the container AND delete the data volume
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
+
> **Coming from an image older than v1.1.0?** Run `cerefox-local upgrade v1.1.1`
|
|
156
|
+
> (an explicit tag) once. A bare `upgrade` on those versions re-pulled the pinned
|
|
157
|
+
> tag and reported success without changing anything (#153), and it cannot fix
|
|
158
|
+
> itself: the launcher on your host is refreshed out of the container image, so an
|
|
159
|
+
> old image keeps reinstalling the old launcher. See
|
|
160
|
+
> [`upgrading.md`](upgrading.md).
|
|
161
|
+
|
|
155
162
|
`upgrade` is the single update path: it pulls the newest image, recreates the container,
|
|
156
163
|
and refreshes the `cerefox-local` script itself. Because the CLI, web server, PostgREST,
|
|
157
164
|
and database schema all ship together in one versioned image, they never drift out of
|
package/docs/guides/upgrading.md
CHANGED
|
@@ -18,6 +18,33 @@ to re-run.
|
|
|
18
18
|
> repo `.env` to `~/.cerefox/.env`, deploy the server, and wire up your agent.
|
|
19
19
|
> After that you're on the end-user path below.
|
|
20
20
|
|
|
21
|
+
> ### Cerefox Local on an image older than v1.1.0: upgrade once with an explicit tag
|
|
22
|
+
>
|
|
23
|
+
> If your container is on **v1.0.6 or earlier**, run this once:
|
|
24
|
+
>
|
|
25
|
+
> ```bash
|
|
26
|
+
> cerefox-local upgrade v1.1.1 # or any newer tag
|
|
27
|
+
> ```
|
|
28
|
+
>
|
|
29
|
+
> A bare `cerefox-local upgrade` will **not** get you off an old image, and it
|
|
30
|
+
> fails quietly: it prints "Pulling …", "container (re)started" and "refreshed
|
|
31
|
+
> cerefox-local from the new image", having changed nothing. Before v1.1.0 a bare
|
|
32
|
+
> `upgrade` re-pulled the **pinned** tag rather than resolving the newest release
|
|
33
|
+
> (#153).
|
|
34
|
+
>
|
|
35
|
+
> The reason it cannot fix itself is a bootstrap loop: the `cerefox-local`
|
|
36
|
+
> launcher on your host is refreshed *out of the container image* at the end of
|
|
37
|
+
> every upgrade, so an old image keeps reinstalling the old launcher. Naming a
|
|
38
|
+
> tag explicitly bypasses the pin, pulls the new image, and the new launcher
|
|
39
|
+
> comes with it. `curl … install-local.sh | sh` also works, since the installer
|
|
40
|
+
> writes the launcher directly.
|
|
41
|
+
>
|
|
42
|
+
> **After that, a bare `cerefox-local upgrade` behaves as you would expect**: it
|
|
43
|
+
> resolves the newest *stable* release and pins that exact version. It does not
|
|
44
|
+
> start following the moving `:latest` tag — that is what `upgrade --latest`
|
|
45
|
+
> does, and automatic operations (`init`, `start`, `restart`) never follow a
|
|
46
|
+
> moving tag by design (#100).
|
|
47
|
+
|
|
21
48
|
## End-user upgrade
|
|
22
49
|
|
|
23
50
|
> ### Upgrading to v1.1.0 — `cerefox server deploy` is required
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cerefox/memory",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
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",
|