@knowsuchagency/fulcrum 2.7.1 → 2.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/bin/fulcrum.js +95 -4
- package/dist/assets/{index-_cFoHsjb.js → index-BfBfuxBH.js} +165 -165
- package/dist/assets/index-TyeuSbkG.css +1 -0
- package/dist/index.html +2 -2
- package/drizzle/0052_agent_memory.sql +27 -0
- package/drizzle/0053_add_memory_source.sql +1 -0
- package/drizzle/meta/_journal.json +14 -0
- package/package.json +1 -1
- package/server/index.js +341 -47
- package/dist/assets/index-Bajq2D5F.css +0 -1
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ Fulcrum doesn't replace your tools—it gives you leverage over them. You config
|
|
|
19
19
|
- **Work From Anywhere** — Run Fulcrum on a remote server. Close your laptop, agents keep working.
|
|
20
20
|
- **Project Management** — Tasks with dependencies, due dates, labels, and attachments. Visual kanban boards.
|
|
21
21
|
- **Production Deployment** — Docker Compose with automatic Traefik routing and Cloudflare DNS/tunnels.
|
|
22
|
+
- **Agent Memory** — Persistent knowledge store with full-text search. Agents remember across sessions.
|
|
22
23
|
- **MCP-First Architecture** — 60+ tools exposed via Model Context Protocol. Agents discover what they need.
|
|
23
24
|
|
|
24
25
|
## MCP-First Architecture
|
|
@@ -183,6 +184,16 @@ Chat with the AI assistant from anywhere via your favorite messaging platform.
|
|
|
183
184
|
|
|
184
185
|
Enable in Settings → Messaging and follow the setup instructions for each platform.
|
|
185
186
|
|
|
187
|
+
### Agent Memory
|
|
188
|
+
|
|
189
|
+
Agents can store and recall knowledge across conversations using a persistent memory system backed by SQLite FTS5 full-text search.
|
|
190
|
+
|
|
191
|
+
- **Persistent** — Memories survive across sessions and agent restarts
|
|
192
|
+
- **Searchable** — Full-text search with boolean operators, phrase matching, and prefix queries
|
|
193
|
+
- **Tagged** — Categorize memories with tags (preferences, decisions, architecture, etc.)
|
|
194
|
+
- **Browsable** — View, search, edit, and delete memories from the Monitoring > Memory tab
|
|
195
|
+
- **MCP tools** — `memory_store` and `memory_search` available to all connected agents
|
|
196
|
+
|
|
186
197
|
### System Monitoring
|
|
187
198
|
|
|
188
199
|
Track CPU, memory, and disk usage while your agents work. The Jobs tab manages systemd (Linux) or launchd (macOS) timers. The Messages tab shows all channel messages (WhatsApp, Discord, Telegram, Slack, Email) with filtering by channel and direction.
|
|
@@ -235,6 +246,7 @@ Both plugins include an MCP server with 60+ tools:
|
|
|
235
246
|
| **Notifications** | Send notifications to enabled channels |
|
|
236
247
|
| **Backup & Restore** | Snapshot database and settings; auto-safety-backup on restore |
|
|
237
248
|
| **Settings** | View and update configuration; manage notification channels |
|
|
249
|
+
| **Memory** | Store and search persistent knowledge with FTS5 full-text search |
|
|
238
250
|
| **Assistant Events** | Track actionable events; query decision history |
|
|
239
251
|
|
|
240
252
|
Use `search_tools` to discover available tools by keyword or category.
|
package/bin/fulcrum.js
CHANGED
|
@@ -1583,6 +1583,34 @@ class FulcrumClient {
|
|
|
1583
1583
|
method: "DELETE"
|
|
1584
1584
|
});
|
|
1585
1585
|
}
|
|
1586
|
+
async storeMemory(input) {
|
|
1587
|
+
return this.fetch("/api/memory", {
|
|
1588
|
+
method: "POST",
|
|
1589
|
+
body: JSON.stringify(input)
|
|
1590
|
+
});
|
|
1591
|
+
}
|
|
1592
|
+
async searchMemories(input) {
|
|
1593
|
+
const params = new URLSearchParams({ q: input.query });
|
|
1594
|
+
if (input.tags?.length)
|
|
1595
|
+
params.set("tags", input.tags.join(","));
|
|
1596
|
+
if (input.limit)
|
|
1597
|
+
params.set("limit", String(input.limit));
|
|
1598
|
+
return this.fetch(`/api/memory/search?${params.toString()}`);
|
|
1599
|
+
}
|
|
1600
|
+
async listMemories(input) {
|
|
1601
|
+
const params = new URLSearchParams;
|
|
1602
|
+
if (input?.tags?.length)
|
|
1603
|
+
params.set("tags", input.tags.join(","));
|
|
1604
|
+
if (input?.limit)
|
|
1605
|
+
params.set("limit", String(input.limit));
|
|
1606
|
+
if (input?.offset)
|
|
1607
|
+
params.set("offset", String(input.offset));
|
|
1608
|
+
const query = params.toString();
|
|
1609
|
+
return this.fetch(`/api/memory${query ? `?${query}` : ""}`);
|
|
1610
|
+
}
|
|
1611
|
+
async deleteMemory(id) {
|
|
1612
|
+
return this.fetch(`/api/memory/${id}`, { method: "DELETE" });
|
|
1613
|
+
}
|
|
1586
1614
|
async getAssistantStats() {
|
|
1587
1615
|
return this.fetch("/api/assistant/stats");
|
|
1588
1616
|
}
|
|
@@ -43421,7 +43449,8 @@ var init_types4 = __esm(() => {
|
|
|
43421
43449
|
"email",
|
|
43422
43450
|
"messaging",
|
|
43423
43451
|
"assistant",
|
|
43424
|
-
"caldav"
|
|
43452
|
+
"caldav",
|
|
43453
|
+
"memory"
|
|
43425
43454
|
]);
|
|
43426
43455
|
AgentTypeSchema = exports_external.enum(["claude", "opencode"]);
|
|
43427
43456
|
});
|
|
@@ -44173,6 +44202,20 @@ var init_registry = __esm(() => {
|
|
|
44173
44202
|
category: "caldav",
|
|
44174
44203
|
keywords: ["calendar", "event", "delete", "remove", "cancel"],
|
|
44175
44204
|
defer_loading: true
|
|
44205
|
+
},
|
|
44206
|
+
{
|
|
44207
|
+
name: "memory_store",
|
|
44208
|
+
description: "Store a piece of knowledge in persistent memory",
|
|
44209
|
+
category: "memory",
|
|
44210
|
+
keywords: ["memory", "store", "save", "remember", "knowledge", "persist", "fact"],
|
|
44211
|
+
defer_loading: false
|
|
44212
|
+
},
|
|
44213
|
+
{
|
|
44214
|
+
name: "memory_search",
|
|
44215
|
+
description: "Search persistent memory using full-text search",
|
|
44216
|
+
category: "memory",
|
|
44217
|
+
keywords: ["memory", "search", "find", "recall", "knowledge", "retrieve", "remember"],
|
|
44218
|
+
defer_loading: false
|
|
44176
44219
|
}
|
|
44177
44220
|
];
|
|
44178
44221
|
});
|
|
@@ -45782,6 +45825,52 @@ var init_caldav = __esm(() => {
|
|
|
45782
45825
|
init_utils();
|
|
45783
45826
|
});
|
|
45784
45827
|
|
|
45828
|
+
// shared/types.ts
|
|
45829
|
+
var MEMORY_SOURCES;
|
|
45830
|
+
var init_types5 = __esm(() => {
|
|
45831
|
+
MEMORY_SOURCES = [
|
|
45832
|
+
"channel:whatsapp",
|
|
45833
|
+
"channel:slack",
|
|
45834
|
+
"channel:discord",
|
|
45835
|
+
"channel:telegram",
|
|
45836
|
+
"channel:email",
|
|
45837
|
+
"conversation:assistant"
|
|
45838
|
+
];
|
|
45839
|
+
});
|
|
45840
|
+
|
|
45841
|
+
// cli/src/mcp/tools/memory.ts
|
|
45842
|
+
var registerMemoryTools = (server, client) => {
|
|
45843
|
+
server.tool("memory_store", "Store a piece of knowledge in persistent memory. Use this to remember facts, preferences, decisions, patterns, or any information that should persist across conversations.", {
|
|
45844
|
+
content: exports_external.string().describe("The memory content to store. Be specific and self-contained."),
|
|
45845
|
+
tags: exports_external.optional(exports_external.array(exports_external.string())).describe('Optional tags for categorization (e.g., ["preference", "architecture", "decision"])'),
|
|
45846
|
+
source: exports_external.optional(exports_external.enum(MEMORY_SOURCES)).describe('Where this memory originated (e.g., "channel:whatsapp", "conversation:assistant")')
|
|
45847
|
+
}, async ({ content, tags, source }) => {
|
|
45848
|
+
try {
|
|
45849
|
+
const result = await client.storeMemory({ content, tags, source });
|
|
45850
|
+
return formatSuccess(result);
|
|
45851
|
+
} catch (err) {
|
|
45852
|
+
return handleToolError(err);
|
|
45853
|
+
}
|
|
45854
|
+
});
|
|
45855
|
+
server.tool("memory_search", 'Search persistent memory using full-text search. Supports boolean operators (AND, OR, NOT), phrase matching ("quoted phrases"), and prefix matching (term*). Try different search terms or synonyms if initial results are insufficient.', {
|
|
45856
|
+
query: exports_external.string().describe('FTS5 search query. Supports: AND, OR, NOT operators, "quoted phrases", prefix* matching. Example: "user preference" OR settings'),
|
|
45857
|
+
tags: exports_external.optional(exports_external.array(exports_external.string())).describe("Optional tag filter - only return memories with at least one of these tags"),
|
|
45858
|
+
limit: exports_external.optional(exports_external.number()).describe("Maximum results to return (default: 20)")
|
|
45859
|
+
}, async ({ query, tags, limit }) => {
|
|
45860
|
+
try {
|
|
45861
|
+
const results = await client.searchMemories({ query, tags, limit });
|
|
45862
|
+
return formatSuccess(results);
|
|
45863
|
+
} catch (err) {
|
|
45864
|
+
return handleToolError(err);
|
|
45865
|
+
}
|
|
45866
|
+
});
|
|
45867
|
+
};
|
|
45868
|
+
var init_memory = __esm(() => {
|
|
45869
|
+
init_zod2();
|
|
45870
|
+
init_utils();
|
|
45871
|
+
init_types5();
|
|
45872
|
+
});
|
|
45873
|
+
|
|
45785
45874
|
// cli/src/mcp/tools/index.ts
|
|
45786
45875
|
function registerTools(server, client) {
|
|
45787
45876
|
registerCoreTools(server, client);
|
|
@@ -45797,6 +45886,7 @@ function registerTools(server, client) {
|
|
|
45797
45886
|
registerEmailTools(server, client);
|
|
45798
45887
|
registerAssistantEventTools(server, client);
|
|
45799
45888
|
registerCaldavTools(server, client);
|
|
45889
|
+
registerMemoryTools(server, client);
|
|
45800
45890
|
}
|
|
45801
45891
|
var init_tools = __esm(() => {
|
|
45802
45892
|
init_core5();
|
|
@@ -45812,6 +45902,7 @@ var init_tools = __esm(() => {
|
|
|
45812
45902
|
init_email();
|
|
45813
45903
|
init_assistant_events();
|
|
45814
45904
|
init_caldav();
|
|
45905
|
+
init_memory();
|
|
45815
45906
|
init_types4();
|
|
45816
45907
|
});
|
|
45817
45908
|
|
|
@@ -45830,7 +45921,7 @@ async function runMcpServer(urlOverride, portOverride) {
|
|
|
45830
45921
|
const client = new FulcrumClient(urlOverride, portOverride);
|
|
45831
45922
|
const server = new McpServer({
|
|
45832
45923
|
name: "fulcrum",
|
|
45833
|
-
version: "2.
|
|
45924
|
+
version: "2.8.2"
|
|
45834
45925
|
});
|
|
45835
45926
|
registerTools(server, client);
|
|
45836
45927
|
const transport = new StdioServerTransport;
|
|
@@ -48179,7 +48270,7 @@ var marketplace_default = `{
|
|
|
48179
48270
|
"name": "fulcrum",
|
|
48180
48271
|
"source": "./",
|
|
48181
48272
|
"description": "Task orchestration for Claude Code",
|
|
48182
|
-
"version": "2.
|
|
48273
|
+
"version": "2.8.2",
|
|
48183
48274
|
"skills": [
|
|
48184
48275
|
"./skills/fulcrum"
|
|
48185
48276
|
],
|
|
@@ -49367,7 +49458,7 @@ function compareVersions(v1, v2) {
|
|
|
49367
49458
|
var package_default = {
|
|
49368
49459
|
name: "@knowsuchagency/fulcrum",
|
|
49369
49460
|
private: true,
|
|
49370
|
-
version: "2.
|
|
49461
|
+
version: "2.8.2",
|
|
49371
49462
|
description: "Harness Attention. Orchestrate Agents. Ship.",
|
|
49372
49463
|
license: "PolyForm-Perimeter-1.0.0",
|
|
49373
49464
|
type: "module",
|