prism-mcp-server 4.2.0 β 4.3.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/README.md +46 -3
- package/dist/server.js +9 -0
- package/dist/storage/sqlite.js +31 -0
- package/dist/storage/supabase.js +25 -0
- package/dist/tools/index.js +2 -2
- package/dist/tools/sessionMemoryDefinitions.js +40 -0
- package/dist/tools/sessionMemoryHandlers.js +131 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,7 +42,13 @@
|
|
|
42
42
|
|
|
43
43
|
---
|
|
44
44
|
|
|
45
|
-
## What's New in v4.
|
|
45
|
+
## What's New in v4.3.0 β The Bridge π
|
|
46
|
+
|
|
47
|
+
> **π§ Active Behavioral Memory & IDE Sync**
|
|
48
|
+
> Prism doesn't just log what happenedβit learns. When an agent is corrected, the memory gains "Importance". Once an insight graduates (Importance >= 7), Prism can automatically sync it directly to your `.cursorrules` or `.clauderules` file, turning dynamic behavioral learnings into permanent, zero-token IDE enforcement.
|
|
49
|
+
|
|
50
|
+
<details>
|
|
51
|
+
<summary><strong>What's in v4.2.0 β Project Repo Registry ποΈ</strong></summary>
|
|
46
52
|
|
|
47
53
|
| Feature | Description |
|
|
48
54
|
|---|---|
|
|
@@ -50,6 +56,8 @@
|
|
|
50
56
|
| π **Universal Auto-Load** | Auto-load projects via dynamic tool descriptions β works across all MCP clients (Claude, Cursor, Gemini, Antigravity) without lifecycle hooks. Dashboard is the sole source of truth. |
|
|
51
57
|
| π **Dashboard-First Config** | Removed `PRISM_AUTOLOAD_PROJECTS` env var override. The Mind Palace dashboard is now the single source of truth for auto-load project configuration. |
|
|
52
58
|
|
|
59
|
+
</details>
|
|
60
|
+
|
|
53
61
|
<details>
|
|
54
62
|
<summary><strong>What's in v4.1.0 β Auto-Migration & Multi-Instance π</strong></summary>
|
|
55
63
|
|
|
@@ -690,6 +698,41 @@ The tool and dashboard button both call the same repair logic β the dashboard
|
|
|
690
698
|
4. On `session_load_context`, high-importance corrections auto-surface as `[β οΈ BEHAVIORAL WARNINGS]`
|
|
691
699
|
5. Agent sees warnings and avoids repeating past mistakes
|
|
692
700
|
|
|
701
|
+
### v4.2 Knowledge Sync Rules β "The Bridge"
|
|
702
|
+
|
|
703
|
+
Bridges **v4.0 Behavioral Memory** (graduated insights) with **v4.2 Project Registry** (repo paths) to physically write agent learnings into your project's IDE rules file.
|
|
704
|
+
|
|
705
|
+
| Feature | Without Sync Rules | With `knowledge_sync_rules` |
|
|
706
|
+
|---------|-------------------|----------------------------|
|
|
707
|
+
| **Insight Visibility** | Only in Prism context injection | Persisted as static IDE context (`.cursorrules` / `.clauderules`) |
|
|
708
|
+
| **Cross-Session** | Loaded per-session via tool call | Always-on β IDE reads rules file on every prompt |
|
|
709
|
+
| **Agent Learning Loop** | Behavioral warnings during context load | Rules enforced even without Prism connected |
|
|
710
|
+
| **Idempotency** | N/A | Sentinel markers ensure safe re-runs |
|
|
711
|
+
| **User Control** | View in dashboard | User-maintained rules preserved; only sentinel block updated |
|
|
712
|
+
|
|
713
|
+
**Syncing graduated insights:**
|
|
714
|
+
|
|
715
|
+
```json
|
|
716
|
+
{ "name": "knowledge_sync_rules", "arguments": {
|
|
717
|
+
"project": "my-app",
|
|
718
|
+
"target_file": ".cursorrules",
|
|
719
|
+
"dry_run": true
|
|
720
|
+
}}
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
**How it works:**
|
|
724
|
+
1. Fetches graduated insights (`importance >= 7`) from the ledger
|
|
725
|
+
2. Formats them as markdown rules inside `<!-- PRISM:AUTO-RULES:START/END -->` sentinel markers
|
|
726
|
+
3. Idempotently writes them into the target file at the project's configured `repo_path`
|
|
727
|
+
|
|
728
|
+
| Tool | Purpose | Key Args |
|
|
729
|
+
|------|---------|----------|
|
|
730
|
+
| `knowledge_sync_rules` | Sync graduated insights to IDE rules file | `project`, `target_file`, `dry_run` |
|
|
731
|
+
| `knowledge_upvote` | Increase entry importance (+1) | `id` |
|
|
732
|
+
| `knowledge_downvote` | Decrease entry importance (-1) | `id` |
|
|
733
|
+
|
|
734
|
+
> π‘ **Prerequisite:** Set a `repo_path` for your project in the Mind Palace dashboard (βοΈ Settings β Project Repo Paths) before syncing.
|
|
735
|
+
|
|
693
736
|
### Code Mode Templates (v2.1)
|
|
694
737
|
|
|
695
738
|
Instead of writing custom JavaScript, pass a `template` name for instant extraction:
|
|
@@ -1348,13 +1391,14 @@ See [`vertex-ai/`](vertex-ai/) for setup and benchmarks.
|
|
|
1348
1391
|
|
|
1349
1392
|
> **[View the full project board β](https://github.com/users/dcostenco/projects/1/views/1)**
|
|
1350
1393
|
|
|
1351
|
-
### β
v4.2 β Project Repo Registry (Shipped!)
|
|
1394
|
+
### β
v4.2 β Project Repo Registry + Knowledge Sync Rules (Shipped!)
|
|
1352
1395
|
|
|
1353
1396
|
| Feature | Description |
|
|
1354
1397
|
|---|---|
|
|
1355
1398
|
| ποΈ **Project Repo Paths** | Dashboard UI to map projects to repo directories + `session_save_ledger` path validation. |
|
|
1356
1399
|
| π **Universal Auto-Load** | Dynamic tool descriptions replace env var β dashboard is sole source of truth. |
|
|
1357
1400
|
| π **Dashboard-First Config** | Removed `PRISM_AUTOLOAD_PROJECTS` env var override. |
|
|
1401
|
+
| π **Knowledge Sync Rules** | `knowledge_sync_rules` β auto-sync graduated insights to `.cursorrules` / `.clauderules` with idempotent sentinel markers. |
|
|
1358
1402
|
|
|
1359
1403
|
### β
v4.1 β Auto-Migration & Multi-Instance (Shipped!)
|
|
1360
1404
|
|
|
@@ -1376,7 +1420,6 @@ See [What's in v3.0.0](#whats-in-v300--agent-hivemind-) above.
|
|
|
1376
1420
|
|
|
1377
1421
|
| Feature | Issue | Description |
|
|
1378
1422
|
|---------|-------|-------------|
|
|
1379
|
-
| Insight Graduation | β | `knowledge_upvote` / `knowledge_downvote` β importance β₯ 7 promotes to rule |
|
|
1380
1423
|
| OpenTelemetry | [#6](https://github.com/dcostenco/prism-mcp/issues/6) | W3C tracing with Jaeger/Zipkin export |
|
|
1381
1424
|
| GDPR Portability | [#7](https://github.com/dcostenco/prism-mcp/issues/7) | `session_export_memory` for Art. 20 |
|
|
1382
1425
|
| CRDT Conflict Resolution | [#9](https://github.com/dcostenco/prism-mcp/issues/9) | Conflict-free types for concurrent edits |
|
package/dist/server.js
CHANGED
|
@@ -102,6 +102,8 @@ sessionForgetMemoryHandler,
|
|
|
102
102
|
knowledgeSetRetentionHandler,
|
|
103
103
|
// v4.0: Active Behavioral Memory handlers
|
|
104
104
|
sessionSaveExperienceHandler, knowledgeUpvoteHandler, knowledgeDownvoteHandler,
|
|
105
|
+
// v4.2: Knowledge Sync Rules
|
|
106
|
+
KNOWLEDGE_SYNC_RULES_TOOL, knowledgeSyncRulesHandler,
|
|
105
107
|
// βββ v3.0: Agent Hivemind tools βββ
|
|
106
108
|
AGENT_REGISTRY_TOOLS, agentRegisterHandler, agentHeartbeatHandler, agentListTeamHandler, } from "./tools/index.js";
|
|
107
109
|
// βββ Dynamic Tool Registration βββββββββββββββββββββββββββββββββββ
|
|
@@ -159,6 +161,8 @@ function buildSessionMemoryTools(autoloadList) {
|
|
|
159
161
|
SESSION_SAVE_EXPERIENCE_TOOL, // session_save_experience β record typed experience events
|
|
160
162
|
KNOWLEDGE_UPVOTE_TOOL, // knowledge_upvote β increase entry importance
|
|
161
163
|
KNOWLEDGE_DOWNVOTE_TOOL, // knowledge_downvote β decrease entry importance
|
|
164
|
+
// βββ v4.2: Knowledge Sync Rules tool βββ
|
|
165
|
+
KNOWLEDGE_SYNC_RULES_TOOL, // knowledge_sync_rules β sync graduated insights to IDE rules files
|
|
162
166
|
];
|
|
163
167
|
}
|
|
164
168
|
// βββ v0.4.0: Resource Subscription Tracking ββββββββββββββββββββββ
|
|
@@ -638,6 +642,11 @@ export function createServer() {
|
|
|
638
642
|
if (!SESSION_MEMORY_ENABLED)
|
|
639
643
|
throw new Error("Session memory not configured. Set SUPABASE_URL and SUPABASE_KEY.");
|
|
640
644
|
return await knowledgeDownvoteHandler(args);
|
|
645
|
+
// βββ v4.2: Knowledge Sync Rules Tool βββ
|
|
646
|
+
case "knowledge_sync_rules":
|
|
647
|
+
if (!SESSION_MEMORY_ENABLED)
|
|
648
|
+
throw new Error("Session memory not configured. Set SUPABASE_URL and SUPABASE_KEY.");
|
|
649
|
+
return await knowledgeSyncRulesHandler(args);
|
|
641
650
|
// βββ v3.0: Agent Hivemind Tools βββ
|
|
642
651
|
case "agent_register":
|
|
643
652
|
if (!SESSION_MEMORY_ENABLED)
|
package/dist/storage/sqlite.js
CHANGED
|
@@ -1391,4 +1391,35 @@ export class SqliteStorage {
|
|
|
1391
1391
|
});
|
|
1392
1392
|
debugLog(`[SqliteStorage] Adjusted importance for ${id} by ${delta > 0 ? "+" : ""}${delta}`);
|
|
1393
1393
|
}
|
|
1394
|
+
// βββ v4.2: Graduated Insights Query ββββββββββββββββββββββββββ
|
|
1395
|
+
//
|
|
1396
|
+
// Returns ledger entries that have "graduated" β i.e., their
|
|
1397
|
+
// importance score has reached the threshold (default 7).
|
|
1398
|
+
// Used by knowledge_sync_rules to physically write insights
|
|
1399
|
+
// into .cursorrules / .clauderules files at the project repo path.
|
|
1400
|
+
async getGraduatedInsights(project, userId, minImportance = 7) {
|
|
1401
|
+
const result = await this.db.execute({
|
|
1402
|
+
sql: `SELECT id, project, user_id, role, summary, importance,
|
|
1403
|
+
event_type, decisions, created_at
|
|
1404
|
+
FROM session_ledger
|
|
1405
|
+
WHERE project = ? AND user_id = ?
|
|
1406
|
+
AND importance >= ?
|
|
1407
|
+
AND deleted_at IS NULL
|
|
1408
|
+
AND archived_at IS NULL
|
|
1409
|
+
ORDER BY importance DESC, created_at DESC`,
|
|
1410
|
+
args: [project, userId, minImportance],
|
|
1411
|
+
});
|
|
1412
|
+
return result.rows.map(row => ({
|
|
1413
|
+
id: row.id,
|
|
1414
|
+
project: row.project,
|
|
1415
|
+
user_id: row.user_id,
|
|
1416
|
+
role: row.role || "global",
|
|
1417
|
+
summary: row.summary,
|
|
1418
|
+
importance: Number(row.importance),
|
|
1419
|
+
event_type: row.event_type || "session",
|
|
1420
|
+
decisions: this.parseJsonColumn(row.decisions),
|
|
1421
|
+
created_at: row.created_at,
|
|
1422
|
+
conversation_id: "",
|
|
1423
|
+
}));
|
|
1424
|
+
}
|
|
1394
1425
|
}
|
package/dist/storage/supabase.js
CHANGED
|
@@ -383,4 +383,29 @@ export class SupabaseStorage {
|
|
|
383
383
|
debugLog("[SupabaseStorage] adjustImportance failed: " + (e instanceof Error ? e.message : String(e)));
|
|
384
384
|
}
|
|
385
385
|
}
|
|
386
|
+
// βββ v4.2: Graduated Insights Query ββββββββββββββββββββββββββ
|
|
387
|
+
async getGraduatedInsights(project, userId, minImportance = 7) {
|
|
388
|
+
const data = await supabaseGet("session_ledger", {
|
|
389
|
+
project: `eq.${project}`,
|
|
390
|
+
user_id: `eq.${userId}`,
|
|
391
|
+
importance: `gte.${minImportance}`,
|
|
392
|
+
deleted_at: "is.null",
|
|
393
|
+
archived_at: "is.null",
|
|
394
|
+
select: "id,project,user_id,role,summary,importance,event_type,decisions,created_at",
|
|
395
|
+
order: "importance.desc,created_at.desc",
|
|
396
|
+
});
|
|
397
|
+
const rows = Array.isArray(data) ? data : [];
|
|
398
|
+
return rows.map((r) => ({
|
|
399
|
+
id: r.id,
|
|
400
|
+
project: r.project,
|
|
401
|
+
user_id: r.user_id,
|
|
402
|
+
role: r.role || "global",
|
|
403
|
+
summary: r.summary,
|
|
404
|
+
importance: r.importance || 0,
|
|
405
|
+
event_type: r.event_type || "session",
|
|
406
|
+
decisions: Array.isArray(r.decisions) ? r.decisions : [],
|
|
407
|
+
created_at: r.created_at,
|
|
408
|
+
conversation_id: "",
|
|
409
|
+
}));
|
|
410
|
+
}
|
|
386
411
|
}
|
package/dist/tools/index.js
CHANGED
|
@@ -26,8 +26,8 @@ export { webSearchHandler, braveWebSearchCodeModeHandler, localSearchHandler, br
|
|
|
26
26
|
// This file always exports them β server.ts decides whether to include them in the tool list.
|
|
27
27
|
//
|
|
28
28
|
// v0.4.0: Added SESSION_COMPACT_LEDGER_TOOL and SESSION_SEARCH_MEMORY_TOOL
|
|
29
|
-
export { SESSION_SAVE_LEDGER_TOOL, SESSION_SAVE_HANDOFF_TOOL, SESSION_LOAD_CONTEXT_TOOL, KNOWLEDGE_SEARCH_TOOL, KNOWLEDGE_FORGET_TOOL, SESSION_COMPACT_LEDGER_TOOL, SESSION_SEARCH_MEMORY_TOOL, MEMORY_HISTORY_TOOL, MEMORY_CHECKOUT_TOOL, SESSION_SAVE_IMAGE_TOOL, SESSION_VIEW_IMAGE_TOOL, SESSION_HEALTH_CHECK_TOOL, SESSION_FORGET_MEMORY_TOOL, KNOWLEDGE_SET_RETENTION_TOOL, SESSION_SAVE_EXPERIENCE_TOOL, KNOWLEDGE_UPVOTE_TOOL, KNOWLEDGE_DOWNVOTE_TOOL } from "./sessionMemoryDefinitions.js";
|
|
30
|
-
export { sessionSaveLedgerHandler, sessionSaveHandoffHandler, sessionLoadContextHandler, knowledgeSearchHandler, knowledgeForgetHandler, sessionSearchMemoryHandler, backfillEmbeddingsHandler, memoryHistoryHandler, memoryCheckoutHandler, sessionSaveImageHandler, sessionViewImageHandler, sessionHealthCheckHandler, sessionForgetMemoryHandler, knowledgeSetRetentionHandler, sessionSaveExperienceHandler, knowledgeUpvoteHandler, knowledgeDownvoteHandler } from "./sessionMemoryHandlers.js";
|
|
29
|
+
export { SESSION_SAVE_LEDGER_TOOL, SESSION_SAVE_HANDOFF_TOOL, SESSION_LOAD_CONTEXT_TOOL, KNOWLEDGE_SEARCH_TOOL, KNOWLEDGE_FORGET_TOOL, SESSION_COMPACT_LEDGER_TOOL, SESSION_SEARCH_MEMORY_TOOL, MEMORY_HISTORY_TOOL, MEMORY_CHECKOUT_TOOL, SESSION_SAVE_IMAGE_TOOL, SESSION_VIEW_IMAGE_TOOL, SESSION_HEALTH_CHECK_TOOL, SESSION_FORGET_MEMORY_TOOL, KNOWLEDGE_SET_RETENTION_TOOL, SESSION_SAVE_EXPERIENCE_TOOL, KNOWLEDGE_UPVOTE_TOOL, KNOWLEDGE_DOWNVOTE_TOOL, KNOWLEDGE_SYNC_RULES_TOOL } from "./sessionMemoryDefinitions.js";
|
|
30
|
+
export { sessionSaveLedgerHandler, sessionSaveHandoffHandler, sessionLoadContextHandler, knowledgeSearchHandler, knowledgeForgetHandler, sessionSearchMemoryHandler, backfillEmbeddingsHandler, memoryHistoryHandler, memoryCheckoutHandler, sessionSaveImageHandler, sessionViewImageHandler, sessionHealthCheckHandler, sessionForgetMemoryHandler, knowledgeSetRetentionHandler, sessionSaveExperienceHandler, knowledgeUpvoteHandler, knowledgeDownvoteHandler, knowledgeSyncRulesHandler } from "./sessionMemoryHandlers.js";
|
|
31
31
|
// ββ Compaction Handler (v0.4.0 β Enhancement #2) ββ
|
|
32
32
|
// The compaction handler is in a separate file because it's significantly
|
|
33
33
|
// more complex than the other session memory handlers (chunked Gemini
|
|
@@ -743,3 +743,43 @@ export function isKnowledgeVoteArgs(args) {
|
|
|
743
743
|
"id" in args &&
|
|
744
744
|
typeof args.id === "string");
|
|
745
745
|
}
|
|
746
|
+
// βββ v4.2: Knowledge Sync Rules Tool βββββββββββββββββββββββββ
|
|
747
|
+
export const KNOWLEDGE_SYNC_RULES_TOOL = {
|
|
748
|
+
name: "knowledge_sync_rules",
|
|
749
|
+
description: "Auto-sync graduated insights (importance >= 7) into your project's IDE rules file " +
|
|
750
|
+
"(.cursorrules or .clauderules). This bridges behavioral memory with static IDE context β " +
|
|
751
|
+
"turning dynamic agent learnings into always-on rules.\n\n" +
|
|
752
|
+
"**How it works:**\n" +
|
|
753
|
+
"1. Fetches graduated insights from the ledger\n" +
|
|
754
|
+
"2. Formats them as markdown rules inside sentinel markers\n" +
|
|
755
|
+
"3. Idempotently writes them into the target file at the project's configured repo_path\n\n" +
|
|
756
|
+
"**Requirements:** The project must have a repo_path configured in the dashboard.\n\n" +
|
|
757
|
+
"**Idempotency:** Uses `<!-- PRISM:AUTO-RULES:START -->` / `<!-- PRISM:AUTO-RULES:END -->` " +
|
|
758
|
+
"sentinel markers. Running this tool multiple times produces the same file. " +
|
|
759
|
+
"User-maintained content outside the sentinels is never touched.",
|
|
760
|
+
inputSchema: {
|
|
761
|
+
type: "object",
|
|
762
|
+
properties: {
|
|
763
|
+
project: {
|
|
764
|
+
type: "string",
|
|
765
|
+
description: "Project identifier. Must have a repo_path configured in the dashboard.",
|
|
766
|
+
},
|
|
767
|
+
target_file: {
|
|
768
|
+
type: "string",
|
|
769
|
+
description: "Target rules filename (default: '.cursorrules'). " +
|
|
770
|
+
"Common values: '.cursorrules', '.clauderules'.",
|
|
771
|
+
},
|
|
772
|
+
dry_run: {
|
|
773
|
+
type: "boolean",
|
|
774
|
+
description: "If true, returns a preview of the rules block without writing to disk. Default: false.",
|
|
775
|
+
},
|
|
776
|
+
},
|
|
777
|
+
required: ["project"],
|
|
778
|
+
},
|
|
779
|
+
};
|
|
780
|
+
export function isKnowledgeSyncRulesArgs(args) {
|
|
781
|
+
return (typeof args === "object" &&
|
|
782
|
+
args !== null &&
|
|
783
|
+
"project" in args &&
|
|
784
|
+
typeof args.project === "string");
|
|
785
|
+
}
|
|
@@ -34,7 +34,13 @@ import { isSessionSaveLedgerArgs, isSessionSaveHandoffArgs, isSessionLoadContext
|
|
|
34
34
|
isSessionForgetMemoryArgs, // Phase 2: GDPR-compliant memory deletion type guard
|
|
35
35
|
isKnowledgeSetRetentionArgs, // v3.1: TTL retention policy type guard
|
|
36
36
|
// v4.0: Active Behavioral Memory type guards
|
|
37
|
-
isSessionSaveExperienceArgs, isKnowledgeVoteArgs,
|
|
37
|
+
isSessionSaveExperienceArgs, isKnowledgeVoteArgs,
|
|
38
|
+
// v4.2: Sync Rules type guard
|
|
39
|
+
isKnowledgeSyncRulesArgs, } from "./sessionMemoryDefinitions.js";
|
|
40
|
+
// v4.2: File system access for knowledge_sync_rules
|
|
41
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
42
|
+
import { existsSync } from "node:fs";
|
|
43
|
+
import { join, dirname } from "node:path";
|
|
38
44
|
// v3.1: In-memory debounce lock for auto-compaction.
|
|
39
45
|
// Prevents multiple concurrent Gemini compaction tasks for the same project
|
|
40
46
|
// when many agents call session_save_ledger at the same time.
|
|
@@ -1703,3 +1709,127 @@ export async function knowledgeDownvoteHandler(args) {
|
|
|
1703
1709
|
isError: false,
|
|
1704
1710
|
};
|
|
1705
1711
|
}
|
|
1712
|
+
// βββ v4.2: Knowledge Sync Rules Handler βββββββββββββββββββββ
|
|
1713
|
+
//
|
|
1714
|
+
// "The Bridge" β bridges v4.0 Behavioral Memory with v4.2 Repo
|
|
1715
|
+
// Registry. Extracts graduated insights (importance >= 7) from
|
|
1716
|
+
// the ledger and idempotently syncs them into the project's
|
|
1717
|
+
// .cursorrules or .clauderules file, turning dynamic learnings
|
|
1718
|
+
// into static, always-on IDE context.
|
|
1719
|
+
//
|
|
1720
|
+
// Sentinel markers ensure the auto-generated block is isolated
|
|
1721
|
+
// from user-maintained rules. Re-running always produces the
|
|
1722
|
+
// same output, preventing drift.
|
|
1723
|
+
const SENTINEL_START = "<!-- PRISM:AUTO-RULES:START -->";
|
|
1724
|
+
const SENTINEL_END = "<!-- PRISM:AUTO-RULES:END -->";
|
|
1725
|
+
/**
|
|
1726
|
+
* Formats graduated insights into a markdown rules block.
|
|
1727
|
+
* Each insight is rendered as a bullet with its importance score,
|
|
1728
|
+
* event type, and the summary/correction text.
|
|
1729
|
+
*/
|
|
1730
|
+
function formatRulesBlock(insights, project) {
|
|
1731
|
+
const header = `## Prism Graduated Insights (auto-synced)\n\n` +
|
|
1732
|
+
`> These rules were automatically generated by [Prism MCP](https://github.com/fdarcy/prism) ` +
|
|
1733
|
+
`from behavioral memory for project \"${project}\".\n` +
|
|
1734
|
+
`> Last synced: ${new Date().toISOString().split("T")[0]}\n\n`;
|
|
1735
|
+
const rules = insights.map(i => {
|
|
1736
|
+
const tag = i.event_type && i.event_type !== "session" ? ` (${i.event_type})` : "";
|
|
1737
|
+
return `- **[importance: ${i.importance}]**${tag} ${i.summary}`;
|
|
1738
|
+
}).join("\n");
|
|
1739
|
+
return `${SENTINEL_START}\n${header}${rules}\n${SENTINEL_END}`;
|
|
1740
|
+
}
|
|
1741
|
+
/**
|
|
1742
|
+
* Idempotently replaces or appends the sentinel block in a rules file.
|
|
1743
|
+
* Content outside the sentinels is never modified.
|
|
1744
|
+
*/
|
|
1745
|
+
function applySentinelBlock(existingContent, rulesBlock) {
|
|
1746
|
+
const startIdx = existingContent.indexOf(SENTINEL_START);
|
|
1747
|
+
const endIdx = existingContent.indexOf(SENTINEL_END);
|
|
1748
|
+
if (startIdx !== -1 && endIdx !== -1) {
|
|
1749
|
+
// Replace existing block
|
|
1750
|
+
const before = existingContent.substring(0, startIdx);
|
|
1751
|
+
const after = existingContent.substring(endIdx + SENTINEL_END.length);
|
|
1752
|
+
return `${before}${rulesBlock}${after}`;
|
|
1753
|
+
}
|
|
1754
|
+
// Append with separator
|
|
1755
|
+
const separator = existingContent.length > 0 && !existingContent.endsWith("\n\n")
|
|
1756
|
+
? (existingContent.endsWith("\n") ? "\n" : "\n\n")
|
|
1757
|
+
: "";
|
|
1758
|
+
return `${existingContent}${separator}${rulesBlock}\n`;
|
|
1759
|
+
}
|
|
1760
|
+
export async function knowledgeSyncRulesHandler(args) {
|
|
1761
|
+
if (!isKnowledgeSyncRulesArgs(args)) {
|
|
1762
|
+
throw new Error("Invalid arguments for knowledge_sync_rules");
|
|
1763
|
+
}
|
|
1764
|
+
const { project, target_file = ".cursorrules", dry_run = false } = args;
|
|
1765
|
+
const storage = await getStorage();
|
|
1766
|
+
// 1. Resolve repo path
|
|
1767
|
+
const repoPath = await getSetting(`repo_path:${project}`, "");
|
|
1768
|
+
if (!repoPath || !repoPath.trim()) {
|
|
1769
|
+
return {
|
|
1770
|
+
content: [{
|
|
1771
|
+
type: "text",
|
|
1772
|
+
text: `β No repo_path configured for project "${project}".\n` +
|
|
1773
|
+
`Set it in the Mind Palace dashboard (Settings β Project Repo Paths) before syncing rules.`,
|
|
1774
|
+
}],
|
|
1775
|
+
isError: true,
|
|
1776
|
+
};
|
|
1777
|
+
}
|
|
1778
|
+
const normalizedRepoPath = repoPath.trim().replace(/\/+$/, "");
|
|
1779
|
+
// 2. Fetch graduated insights
|
|
1780
|
+
const insights = await storage.getGraduatedInsights(project, PRISM_USER_ID, 7);
|
|
1781
|
+
if (insights.length === 0) {
|
|
1782
|
+
return {
|
|
1783
|
+
content: [{
|
|
1784
|
+
type: "text",
|
|
1785
|
+
text: `βΉοΈ No graduated insights found for project "${project}".\n` +
|
|
1786
|
+
`Insights graduate when their importance score reaches 7 or higher.\n` +
|
|
1787
|
+
`Use \`knowledge_upvote\` to increase importance of valuable entries.`,
|
|
1788
|
+
}],
|
|
1789
|
+
isError: false,
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
// 3. Format rules block
|
|
1793
|
+
const rulesBlock = formatRulesBlock(insights.map(i => ({ ...i, importance: i.importance ?? 0 })), project);
|
|
1794
|
+
// 4. Dry-run: return preview without writing
|
|
1795
|
+
if (dry_run) {
|
|
1796
|
+
return {
|
|
1797
|
+
content: [{
|
|
1798
|
+
type: "text",
|
|
1799
|
+
text: `π **Dry Run Preview** β ${insights.length} graduated insight(s) for "${project}":\n\n` +
|
|
1800
|
+
`Target: ${normalizedRepoPath}/${target_file}\n\n` +
|
|
1801
|
+
`\`\`\`markdown\n${rulesBlock}\n\`\`\`\n\n` +
|
|
1802
|
+
`Run again without \`dry_run\` to write this to disk.`,
|
|
1803
|
+
}],
|
|
1804
|
+
isError: false,
|
|
1805
|
+
};
|
|
1806
|
+
}
|
|
1807
|
+
// 5. Idempotent file write
|
|
1808
|
+
const targetPath = join(normalizedRepoPath, target_file);
|
|
1809
|
+
// Ensure directory exists (handles nested target_file like ".config/rules.md")
|
|
1810
|
+
const targetDir = dirname(targetPath);
|
|
1811
|
+
if (!existsSync(targetDir)) {
|
|
1812
|
+
await mkdir(targetDir, { recursive: true });
|
|
1813
|
+
}
|
|
1814
|
+
let existingContent = "";
|
|
1815
|
+
try {
|
|
1816
|
+
existingContent = await readFile(targetPath, "utf-8");
|
|
1817
|
+
}
|
|
1818
|
+
catch {
|
|
1819
|
+
// File doesn't exist yet β will be created
|
|
1820
|
+
debugLog(`[knowledge_sync_rules] File ${targetPath} doesn't exist, creating new`);
|
|
1821
|
+
}
|
|
1822
|
+
const newContent = applySentinelBlock(existingContent, rulesBlock);
|
|
1823
|
+
await writeFile(targetPath, newContent, "utf-8");
|
|
1824
|
+
debugLog(`[knowledge_sync_rules] Synced ${insights.length} insights to ${targetPath}`);
|
|
1825
|
+
return {
|
|
1826
|
+
content: [{
|
|
1827
|
+
type: "text",
|
|
1828
|
+
text: `β
Synced ${insights.length} graduated insight(s) to \`${targetPath}\`\n\n` +
|
|
1829
|
+
`Top insights synced:\n` +
|
|
1830
|
+
insights.slice(0, 5).map(i => ` β’ [${i.importance}] ${i.summary.substring(0, 80)}${i.summary.length > 80 ? "..." : ""}`).join("\n") +
|
|
1831
|
+
(insights.length > 5 ? `\n ... and ${insights.length - 5} more` : ""),
|
|
1832
|
+
}],
|
|
1833
|
+
isError: false,
|
|
1834
|
+
};
|
|
1835
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prism-mcp-server",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"mcpName": "io.github.dcostenco/prism-mcp",
|
|
5
5
|
"description": "The Mind Palace for AI Agents β local-first MCP server with persistent memory (SQLite/Supabase), visual dashboard, time travel, multi-agent sync, Morning Briefings, reality drift detection, code mode templates, semantic vector search, and Brave Search + Gemini analysis. Zero-config local mode.",
|
|
6
6
|
"module": "index.ts",
|