amalfa 1.0.0 → 1.0.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 +226 -247
- package/amalfa.config.example.ts +8 -6
- package/docs/AGENT-METADATA-PATTERNS.md +1021 -0
- package/docs/CONFIG_E2E_VALIDATION.md +147 -0
- package/docs/CONFIG_UNIFICATION.md +187 -0
- package/docs/CONFIG_VALIDATION.md +103 -0
- package/docs/LEGACY_DEPRECATION.md +174 -0
- package/docs/MCP_SETUP.md +317 -0
- package/docs/QUICK_START_MCP.md +168 -0
- package/docs/SESSION-2026-01-06-METADATA-PATTERNS.md +346 -0
- package/docs/SETUP.md +464 -0
- package/docs/SETUP_COMPLETE.md +464 -0
- package/docs/VISION-AGENT-LEARNING.md +1242 -0
- package/docs/_current-config-status.md +93 -0
- package/package.json +6 -3
- package/polyvis.settings.json.bak +38 -0
- package/src/cli.ts +159 -31
- package/src/config/defaults.ts +73 -15
- package/src/core/VectorEngine.ts +18 -9
- package/src/daemon/index.ts +12 -8
- package/src/mcp/index.ts +62 -7
- package/src/pipeline/AmalfaIngestor.ts +22 -12
- package/src/pipeline/PreFlightAnalyzer.ts +434 -0
- package/src/resonance/DatabaseFactory.ts +3 -4
- package/src/resonance/db.ts +8 -6
- package/src/resonance/schema.ts +19 -1
- package/src/resonance/services/vector-daemon.ts +151 -0
- package/src/utils/DaemonManager.ts +147 -0
- package/src/utils/ZombieDefense.ts +5 -1
- package/:memory: +0 -0
- package/:memory:-shm +0 -0
- package/:memory:-wal +0 -0
- package/README.old.md +0 -112
- package/agents.config.json +0 -11
- package/drizzle/0000_minor_iron_fist.sql +0 -19
- package/drizzle/meta/0000_snapshot.json +0 -139
- package/drizzle/meta/_journal.json +0 -13
- package/example_usage.ts +0 -39
- package/experiment.sh +0 -35
- package/hello +0 -2
- package/index.html +0 -52
- package/knowledge/excalibur.md +0 -12
- package/plans/experience-graph-integration.md +0 -60
- package/prompts/gemini-king-mode-prompt.md +0 -46
- package/public/docs/MCP_TOOLS.md +0 -372
- package/schemas/README.md +0 -20
- package/schemas/cda.schema.json +0 -84
- package/schemas/conceptual-lexicon.schema.json +0 -75
- package/scratchpads/dummy-debrief-boxed.md +0 -39
- package/scratchpads/dummy-debrief.md +0 -27
- package/scratchpads/scratchpad-design.md +0 -50
- package/scratchpads/scratchpad-scrolling.md +0 -20
- package/scratchpads/scratchpad-toc-disappearance.md +0 -23
- package/scratchpads/scratchpad-toc.md +0 -28
- package/scratchpads/test_gardener.md +0 -7
- package/src/core/LLMClient.ts +0 -93
- package/src/core/TagEngine.ts +0 -56
- package/src/db/schema.ts +0 -46
- package/src/gardeners/AutoTagger.ts +0 -116
- package/src/pipeline/HarvesterPipeline.ts +0 -101
- package/src/pipeline/Ingestor.ts +0 -555
- package/src/resonance/cli/ingest.ts +0 -41
- package/src/resonance/cli/migrate.ts +0 -54
- package/src/resonance/config.ts +0 -40
- package/src/resonance/daemon.ts +0 -236
- package/src/resonance/pipeline/extract.ts +0 -89
- package/src/resonance/pipeline/transform_docs.ts +0 -60
- package/src/resonance/services/tokenizer.ts +0 -159
- package/src/resonance/transform/cda.ts +0 -393
- package/src/utils/EnvironmentVerifier.ts +0 -67
- package/substack/substack-playbook-1.md +0 -95
- package/substack/substack-playbook-2.md +0 -78
- package/tasks/ui-investigation.md +0 -26
- package/test-db +0 -0
- package/test-db-shm +0 -0
- package/test-db-wal +0 -0
- package/tests/canary/verify_pinch_check.ts +0 -44
- package/tests/fixtures/ingest_test.md +0 -12
- package/tests/fixtures/ingest_test_boxed.md +0 -13
- package/tests/fixtures/safety_test.md +0 -45
- package/tests/fixtures/safety_test_boxed.md +0 -49
- package/tests/fixtures/tagged_output.md +0 -49
- package/tests/fixtures/tagged_test.md +0 -49
- package/tests/mcp-server-settings.json +0 -8
- package/verify-embedder.ts +0 -54
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Current Configuration Status
|
|
2
|
+
|
|
3
|
+
**Last Updated:** 2026-01-06
|
|
4
|
+
|
|
5
|
+
## Configuration Files (Single Source of Truth)
|
|
6
|
+
|
|
7
|
+
### 1. AMALFA Core Configuration
|
|
8
|
+
**File:** `amalfa.config.json` (root)
|
|
9
|
+
**Purpose:** Main AMALFA system settings
|
|
10
|
+
**Loaded by:** `src/config/defaults.ts`
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"sources": ["../polyvis/docs", "../polyvis/playbooks"],
|
|
15
|
+
"database": ".amalfa/multi-source-test.db",
|
|
16
|
+
"embeddings": {
|
|
17
|
+
"model": "BAAI/bge-small-en-v1.5",
|
|
18
|
+
"dimensions": 384
|
|
19
|
+
},
|
|
20
|
+
"watch": {
|
|
21
|
+
"enabled": true,
|
|
22
|
+
"debounce": 1000
|
|
23
|
+
},
|
|
24
|
+
"excludePatterns": ["node_modules", ".git", ".amalfa"]
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Status:** ✅ Active, primary config for AMALFA operations
|
|
29
|
+
|
|
30
|
+
### 2. Resonance Configuration (Legacy)
|
|
31
|
+
**File:** `polyvis.settings.json` (root)
|
|
32
|
+
**Purpose:** Resonance database and pipeline settings
|
|
33
|
+
**Loaded by:** `src/resonance/config.ts`
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"paths": {
|
|
38
|
+
"database": { "resonance": "public/resonance.db" },
|
|
39
|
+
"docs": { ... },
|
|
40
|
+
"sources": {
|
|
41
|
+
"experience": [...],
|
|
42
|
+
"persona": { ... }
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"graph": { "tuning": { ... } },
|
|
46
|
+
"schema": { "version": "1.0.0" }
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Status:** 🔄 Legacy, used by resonance pipeline only
|
|
51
|
+
|
|
52
|
+
### 3. Beads Issue Tracking
|
|
53
|
+
**File:** `.beads/config.yaml`
|
|
54
|
+
**Purpose:** Beads issue tracking system configuration
|
|
55
|
+
**Loaded by:** Beads CLI (`bd` commands)
|
|
56
|
+
|
|
57
|
+
**Status:** ✅ Active, separate system
|
|
58
|
+
|
|
59
|
+
## Configuration Strategy
|
|
60
|
+
|
|
61
|
+
### Current Approach (2026-01-06)
|
|
62
|
+
- **AMALFA** and **Resonance** have separate configs
|
|
63
|
+
- This is **intentional** - they serve different purposes:
|
|
64
|
+
- AMALFA: User-facing MCP server and CLI
|
|
65
|
+
- Resonance: Internal database/pipeline layer
|
|
66
|
+
|
|
67
|
+
### Future Unification (v1.0+)
|
|
68
|
+
- Consider consolidating if Resonance becomes AMALFA-exclusive
|
|
69
|
+
- Keep separate if Resonance remains standalone library
|
|
70
|
+
|
|
71
|
+
## Configuration Hierarchy
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
Project Root
|
|
75
|
+
├── amalfa.config.json ← AMALFA core (MCP, CLI, daemon)
|
|
76
|
+
├── polyvis.settings.json ← Resonance (database, pipeline)
|
|
77
|
+
└── .beads/
|
|
78
|
+
└── config.yaml ← Beads (issue tracking)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Action Items
|
|
82
|
+
|
|
83
|
+
- [x] Decide: Keep separate, deprecate polyvis.settings.json gradually (See CONFIG_UNIFICATION.md)
|
|
84
|
+
- [x] Document: Which config controls what (See CONFIG_UNIFICATION.md)
|
|
85
|
+
- [ ] Add deprecation warning when polyvis.settings.json is loaded
|
|
86
|
+
- [ ] Migrate graph tuning to amalfa.config.json (optional)
|
|
87
|
+
- [ ] Remove polyvis.settings.json in v2.0
|
|
88
|
+
|
|
89
|
+
## Notes
|
|
90
|
+
|
|
91
|
+
- No `_current-*` files existed prior to 2026-01-06
|
|
92
|
+
- Configuration is stable but not unified
|
|
93
|
+
- Each system has clear ownership of its config file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amalfa",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Local-first knowledge graph engine for AI agents. Transforms markdown into searchable memory with MCP protocol.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/pjsvis/amalfa#readme",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"author": "Peter John Smith <729613+pjsvis@users.noreply.github.com>",
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
13
|
-
"url": "https://github.com/pjsvis/amalfa"
|
|
13
|
+
"url": "git+https://github.com/pjsvis/amalfa.git"
|
|
14
14
|
},
|
|
15
15
|
"keywords": [
|
|
16
16
|
"mcp",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"pkm"
|
|
30
30
|
],
|
|
31
31
|
"bin": {
|
|
32
|
-
"amalfa": "
|
|
32
|
+
"amalfa": "src/cli.ts"
|
|
33
33
|
},
|
|
34
34
|
"engines": {
|
|
35
35
|
"bun": "1.3.x",
|
|
@@ -48,6 +48,9 @@
|
|
|
48
48
|
"start": "bun run src/mcp/index.ts start",
|
|
49
49
|
"stop": "bun run src/mcp/index.ts stop",
|
|
50
50
|
"status": "bun run src/mcp/index.ts status",
|
|
51
|
+
"servers": "bun run scripts/cli/servers.ts",
|
|
52
|
+
"validate-config": "bun run scripts/validate-config.ts",
|
|
53
|
+
"release": "bun run scripts/release.ts",
|
|
51
54
|
"check": "biome check .",
|
|
52
55
|
"format": "biome format --write ."
|
|
53
56
|
},
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "⚠️ DEPRECATED: This file will be removed in v2.0. Use amalfa.config.json for user-facing settings. See docs/CONFIG_UNIFICATION.md",
|
|
3
|
+
"paths": {
|
|
4
|
+
"database": {
|
|
5
|
+
"resonance": "public/resonance.db"
|
|
6
|
+
},
|
|
7
|
+
"docs": {
|
|
8
|
+
"root": "docs",
|
|
9
|
+
"webdocs": "docs/webdocs",
|
|
10
|
+
"architecture": "docs/architecture",
|
|
11
|
+
"public": "public/docs"
|
|
12
|
+
},
|
|
13
|
+
"sources": {
|
|
14
|
+
"experience": [
|
|
15
|
+
{ "path": "debriefs", "name": "Debrief" },
|
|
16
|
+
{ "path": "playbooks", "name": "Playbook" },
|
|
17
|
+
{ "path": "briefs", "name": "Brief" },
|
|
18
|
+
{ "path": "docs", "name": "Docs" }
|
|
19
|
+
],
|
|
20
|
+
"persona": {
|
|
21
|
+
"lexicon": "scripts/fixtures/conceptual-lexicon-ref-v1.79.json",
|
|
22
|
+
"cda": "scripts/fixtures/cda-ref-v63.json"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"graph": {
|
|
27
|
+
"tuning": {
|
|
28
|
+
"louvain": {
|
|
29
|
+
"persona": 0.3,
|
|
30
|
+
"experience": 0.25
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
"schema": {
|
|
36
|
+
"version": "1.0.0"
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -3,8 +3,10 @@ import { existsSync, statSync } from "node:fs";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
5
|
|
|
6
|
-
const VERSION = "1.0.
|
|
7
|
-
|
|
6
|
+
const VERSION = "1.0.2";
|
|
7
|
+
|
|
8
|
+
// Database path loaded from config (lazy loaded per command)
|
|
9
|
+
let DB_PATH: string | null = null;
|
|
8
10
|
|
|
9
11
|
// Parse command line arguments
|
|
10
12
|
const args = process.argv.slice(2);
|
|
@@ -18,14 +20,21 @@ Usage:
|
|
|
18
20
|
amalfa <command> [options]
|
|
19
21
|
|
|
20
22
|
Commands:
|
|
21
|
-
init
|
|
23
|
+
init [--force] Initialize database from markdown files
|
|
22
24
|
serve Start MCP server (stdio transport)
|
|
23
25
|
stats Show database statistics
|
|
24
26
|
doctor Check installation and configuration
|
|
27
|
+
setup-mcp Generate MCP configuration JSON
|
|
25
28
|
daemon <action> Manage file watcher (start|stop|status|restart)
|
|
26
29
|
|
|
30
|
+
Options:
|
|
31
|
+
--force Override pre-flight warnings (errors still block)
|
|
32
|
+
--version, -v Show version number
|
|
33
|
+
--help, -h Show this help message
|
|
34
|
+
|
|
27
35
|
Examples:
|
|
28
|
-
amalfa init # Initialize
|
|
36
|
+
amalfa init # Initialize with pre-flight validation
|
|
37
|
+
amalfa init --force # Override warnings (use with caution)
|
|
29
38
|
amalfa serve # Start MCP server for Claude Desktop
|
|
30
39
|
amalfa stats # Show knowledge graph statistics
|
|
31
40
|
amalfa doctor # Verify installation
|
|
@@ -38,10 +47,21 @@ function showVersion() {
|
|
|
38
47
|
console.log(`amalfa v${VERSION}`);
|
|
39
48
|
}
|
|
40
49
|
|
|
50
|
+
async function getDbPath(): Promise<string> {
|
|
51
|
+
if (DB_PATH) return DB_PATH;
|
|
52
|
+
|
|
53
|
+
// Load from config
|
|
54
|
+
const { loadConfig } = await import("./config/defaults");
|
|
55
|
+
const config = await loadConfig();
|
|
56
|
+
DB_PATH = join(process.cwd(), config.database);
|
|
57
|
+
return DB_PATH;
|
|
58
|
+
}
|
|
59
|
+
|
|
41
60
|
async function checkDatabase(): Promise<boolean> {
|
|
42
|
-
|
|
61
|
+
const dbPath = await getDbPath();
|
|
62
|
+
if (!existsSync(dbPath)) {
|
|
43
63
|
console.error(`
|
|
44
|
-
❌ Database not found at: ${
|
|
64
|
+
❌ Database not found at: ${dbPath}
|
|
45
65
|
|
|
46
66
|
To initialize AMALFA:
|
|
47
67
|
1. Create markdown files in ./docs/ (or your preferred location)
|
|
@@ -60,8 +80,9 @@ async function cmdServe() {
|
|
|
60
80
|
process.exit(1);
|
|
61
81
|
}
|
|
62
82
|
|
|
83
|
+
const dbPath = await getDbPath();
|
|
63
84
|
console.error("🚀 Starting AMALFA MCP Server...");
|
|
64
|
-
console.error(`📊 Database: ${
|
|
85
|
+
console.error(`📊 Database: ${dbPath}`);
|
|
65
86
|
console.error("");
|
|
66
87
|
|
|
67
88
|
// Run MCP server (it handles stdio transport)
|
|
@@ -83,18 +104,19 @@ async function cmdStats() {
|
|
|
83
104
|
}
|
|
84
105
|
|
|
85
106
|
// Import database wrapper
|
|
107
|
+
const dbPath = await getDbPath();
|
|
86
108
|
const { ResonanceDB } = await import("./resonance/db");
|
|
87
|
-
const db = new ResonanceDB(
|
|
109
|
+
const db = new ResonanceDB(dbPath);
|
|
88
110
|
|
|
89
111
|
try {
|
|
90
112
|
const stats = db.getStats();
|
|
91
|
-
const fileSize = statSync(
|
|
113
|
+
const fileSize = statSync(dbPath).size;
|
|
92
114
|
const fileSizeMB = (fileSize / 1024 / 1024).toFixed(2);
|
|
93
115
|
|
|
94
|
-
|
|
116
|
+
console.log(`
|
|
95
117
|
📊 AMALFA Database Statistics
|
|
96
118
|
|
|
97
|
-
Database: ${
|
|
119
|
+
Database: ${dbPath}
|
|
98
120
|
Size: ${fileSizeMB} MB
|
|
99
121
|
|
|
100
122
|
Nodes: ${stats.nodes.toLocaleString()}
|
|
@@ -102,7 +124,7 @@ Edges: ${stats.edges.toLocaleString()}
|
|
|
102
124
|
Embeddings: ${stats.vectors.toLocaleString()} (384-dim)
|
|
103
125
|
|
|
104
126
|
Source: ./docs (markdown files)
|
|
105
|
-
Last modified: ${new Date(statSync(
|
|
127
|
+
Last modified: ${new Date(statSync(dbPath).mtime).toISOString()}
|
|
106
128
|
|
|
107
129
|
🔍 To search: Use with Claude Desktop or other MCP client
|
|
108
130
|
📝 To update: Run 'amalfa daemon start' (coming soon)
|
|
@@ -118,24 +140,64 @@ Last modified: ${new Date(statSync(DB_PATH).mtime).toISOString()}
|
|
|
118
140
|
async function cmdInit() {
|
|
119
141
|
console.log("🚀 AMALFA Initialization\n");
|
|
120
142
|
|
|
143
|
+
// Check for --force flag
|
|
144
|
+
const forceMode = args.includes("--force");
|
|
145
|
+
|
|
121
146
|
// Load configuration
|
|
122
147
|
const { loadConfig } = await import("./config/defaults");
|
|
123
148
|
const config = await loadConfig();
|
|
124
149
|
|
|
125
|
-
|
|
150
|
+
const sources = config.sources || ["./docs"];
|
|
151
|
+
console.log(`📁 Sources: ${sources.join(", ")}`);
|
|
126
152
|
console.log(`💾 Database: ${config.database}`);
|
|
127
153
|
console.log(`🧠 Model: ${config.embeddings.model}\n`);
|
|
128
154
|
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
155
|
+
// Run pre-flight analysis
|
|
156
|
+
console.log("🔍 Running pre-flight analysis...\n");
|
|
157
|
+
const { PreFlightAnalyzer } = await import("./pipeline/PreFlightAnalyzer");
|
|
158
|
+
const analyzer = new PreFlightAnalyzer(config);
|
|
159
|
+
const report = await analyzer.analyze();
|
|
160
|
+
|
|
161
|
+
// Display summary
|
|
162
|
+
console.log("📊 Pre-Flight Summary:");
|
|
163
|
+
console.log(` Total files: ${report.totalFiles}`);
|
|
164
|
+
console.log(` Valid files: ${report.validFiles}`);
|
|
165
|
+
console.log(` Skipped files: ${report.skippedFiles}`);
|
|
166
|
+
console.log(` Total size: ${(report.totalSizeBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
167
|
+
console.log(` Estimated nodes: ${report.estimatedNodes}\n`);
|
|
168
|
+
|
|
169
|
+
if (report.hasErrors) {
|
|
170
|
+
console.error("❌ Pre-flight check failed with errors\n");
|
|
171
|
+
console.error("Errors detected:");
|
|
172
|
+
for (const issue of report.issues.filter((i) => i.severity === "error")) {
|
|
173
|
+
console.error(` - ${issue.path}: ${issue.details}`);
|
|
174
|
+
}
|
|
175
|
+
console.error("\nSee .amalfa-pre-flight.log for details and recommendations");
|
|
176
|
+
console.error("\nFix these issues and try again.");
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (report.hasWarnings && !forceMode) {
|
|
181
|
+
console.warn("⚠️ Pre-flight check completed with warnings\n");
|
|
182
|
+
console.warn("Warnings detected:");
|
|
183
|
+
for (const issue of report.issues.filter((i) => i.severity === "warning")) {
|
|
184
|
+
console.warn(` - ${issue.path}: ${issue.details}`);
|
|
185
|
+
}
|
|
186
|
+
console.warn("\nSee .amalfa-pre-flight.log for recommendations");
|
|
187
|
+
console.warn("\nTo proceed anyway, use: amalfa init --force");
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (report.validFiles === 0) {
|
|
192
|
+
console.error("\n❌ No valid markdown files found");
|
|
193
|
+
console.error("See .amalfa-pre-flight.log for details");
|
|
136
194
|
process.exit(1);
|
|
137
195
|
}
|
|
138
196
|
|
|
197
|
+
if (forceMode && report.hasWarnings) {
|
|
198
|
+
console.warn("⚠️ Proceeding with --force despite warnings\n");
|
|
199
|
+
}
|
|
200
|
+
|
|
139
201
|
// Create .amalfa directory
|
|
140
202
|
const amalfaDir = join(process.cwd(), ".amalfa");
|
|
141
203
|
if (!existsSync(amalfaDir)) {
|
|
@@ -204,6 +266,55 @@ async function cmdDaemon() {
|
|
|
204
266
|
});
|
|
205
267
|
}
|
|
206
268
|
|
|
269
|
+
async function cmdSetupMcp() {
|
|
270
|
+
const { resolve } = await import("node:path");
|
|
271
|
+
|
|
272
|
+
const cwd = resolve(process.cwd());
|
|
273
|
+
const mcpScript = resolve(cwd, "src/mcp/index.ts");
|
|
274
|
+
|
|
275
|
+
// Minimal PATH for MCP - only include essential directories
|
|
276
|
+
const bunPath = process.execPath.replace(/\/bun$/, ''); // Directory containing bun
|
|
277
|
+
const minimalPath = [
|
|
278
|
+
bunPath,
|
|
279
|
+
'/usr/local/bin',
|
|
280
|
+
'/usr/bin',
|
|
281
|
+
'/bin',
|
|
282
|
+
'/usr/sbin',
|
|
283
|
+
'/sbin',
|
|
284
|
+
'/opt/homebrew/bin', // Apple Silicon Homebrew
|
|
285
|
+
].join(':');
|
|
286
|
+
|
|
287
|
+
const config = {
|
|
288
|
+
mcpServers: {
|
|
289
|
+
amalfa: {
|
|
290
|
+
command: "bun",
|
|
291
|
+
args: ["run", mcpScript],
|
|
292
|
+
env: {
|
|
293
|
+
PATH: minimalPath,
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
console.log("\n✅ AMALFA MCP Configuration");
|
|
300
|
+
console.log("=".repeat(60));
|
|
301
|
+
console.log(`📂 Installation: ${cwd}`);
|
|
302
|
+
console.log("=".repeat(60));
|
|
303
|
+
console.log("\n📋 Copy this JSON to your MCP client config:");
|
|
304
|
+
console.log(" Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json");
|
|
305
|
+
console.log(" Warp Preview: MCP settings\n");
|
|
306
|
+
console.log("=".repeat(60));
|
|
307
|
+
console.log();
|
|
308
|
+
|
|
309
|
+
console.log(JSON.stringify(config, null, 2));
|
|
310
|
+
|
|
311
|
+
console.log();
|
|
312
|
+
console.log("=".repeat(60));
|
|
313
|
+
console.log("💡 Tip: If you move this folder, run 'amalfa setup-mcp' again");
|
|
314
|
+
console.log("=".repeat(60));
|
|
315
|
+
console.log();
|
|
316
|
+
}
|
|
317
|
+
|
|
207
318
|
async function cmdDoctor() {
|
|
208
319
|
console.log("🩺 AMALFA Health Check\n");
|
|
209
320
|
|
|
@@ -212,12 +323,14 @@ async function cmdDoctor() {
|
|
|
212
323
|
// Check Bun runtime
|
|
213
324
|
console.log("✓ Bun runtime: OK");
|
|
214
325
|
|
|
215
|
-
// Check database
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
326
|
+
// Check config and database
|
|
327
|
+
const dbPath = await getDbPath();
|
|
328
|
+
if (existsSync(dbPath)) {
|
|
329
|
+
const fileSizeMB = (statSync(dbPath).size / 1024 / 1024).toFixed(2);
|
|
330
|
+
console.log(`✓ Database found: ${dbPath} (${fileSizeMB} MB)`);
|
|
219
331
|
} else {
|
|
220
|
-
console.log(`✗ Database not found: ${
|
|
332
|
+
console.log(`✗ Database not found: ${dbPath}`);
|
|
333
|
+
console.log(` Run: amalfa init`);
|
|
221
334
|
issues++;
|
|
222
335
|
}
|
|
223
336
|
|
|
@@ -230,12 +343,23 @@ async function cmdDoctor() {
|
|
|
230
343
|
issues++;
|
|
231
344
|
}
|
|
232
345
|
|
|
233
|
-
// Check source directories
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
346
|
+
// Check source directories from config
|
|
347
|
+
const { loadConfig } = await import("./config/defaults");
|
|
348
|
+
const config = await loadConfig();
|
|
349
|
+
const sources = config.sources || ["./docs"];
|
|
350
|
+
let sourcesFound = 0;
|
|
351
|
+
for (const source of sources) {
|
|
352
|
+
const sourcePath = join(process.cwd(), source);
|
|
353
|
+
if (existsSync(sourcePath)) {
|
|
354
|
+
console.log(`✓ Source directory: ${sourcePath}`);
|
|
355
|
+
sourcesFound++;
|
|
356
|
+
} else {
|
|
357
|
+
console.log(`✗ Source directory not found: ${sourcePath}`);
|
|
358
|
+
issues++;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
if (sourcesFound === 0) {
|
|
362
|
+
console.log(` Configure sources in amalfa.config.json`);
|
|
239
363
|
}
|
|
240
364
|
|
|
241
365
|
// Check dependencies (FastEmbed)
|
|
@@ -292,6 +416,10 @@ async function main() {
|
|
|
292
416
|
await cmdDaemon();
|
|
293
417
|
break;
|
|
294
418
|
|
|
419
|
+
case "setup-mcp":
|
|
420
|
+
await cmdSetupMcp();
|
|
421
|
+
break;
|
|
422
|
+
|
|
295
423
|
case "version":
|
|
296
424
|
case "--version":
|
|
297
425
|
case "-v":
|
package/src/config/defaults.ts
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export interface AmalfaConfig {
|
|
7
|
-
|
|
7
|
+
/** @deprecated Use sources array instead */
|
|
8
|
+
source?: string;
|
|
9
|
+
sources?: string[];
|
|
8
10
|
database: string;
|
|
9
11
|
embeddings: {
|
|
10
12
|
model: string;
|
|
@@ -15,10 +17,24 @@ export interface AmalfaConfig {
|
|
|
15
17
|
debounce: number;
|
|
16
18
|
};
|
|
17
19
|
excludePatterns: string[];
|
|
20
|
+
/** Graph analysis tuning parameters (optional) */
|
|
21
|
+
graph?: {
|
|
22
|
+
tuning?: {
|
|
23
|
+
louvain?: {
|
|
24
|
+
persona?: number;
|
|
25
|
+
experience?: number;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
/** Persona fixture paths (optional, for legacy Resonance features) */
|
|
30
|
+
fixtures?: {
|
|
31
|
+
lexicon?: string;
|
|
32
|
+
cda?: string;
|
|
33
|
+
};
|
|
18
34
|
}
|
|
19
35
|
|
|
20
36
|
export const DEFAULT_CONFIG: AmalfaConfig = {
|
|
21
|
-
|
|
37
|
+
sources: ["./docs"],
|
|
22
38
|
database: ".amalfa/resonance.db",
|
|
23
39
|
embeddings: {
|
|
24
40
|
model: "BAAI/bge-small-en-v1.5",
|
|
@@ -29,6 +45,20 @@ export const DEFAULT_CONFIG: AmalfaConfig = {
|
|
|
29
45
|
debounce: 1000,
|
|
30
46
|
},
|
|
31
47
|
excludePatterns: ["node_modules", ".git", ".amalfa"],
|
|
48
|
+
// Optional graph tuning (for advanced use)
|
|
49
|
+
graph: {
|
|
50
|
+
tuning: {
|
|
51
|
+
louvain: {
|
|
52
|
+
persona: 0.3,
|
|
53
|
+
experience: 0.25,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
// Optional fixtures (for legacy Resonance features)
|
|
58
|
+
fixtures: {
|
|
59
|
+
lexicon: "scripts/fixtures/conceptual-lexicon-ref-v1.79.json",
|
|
60
|
+
cda: "scripts/fixtures/cda-ref-v63.json",
|
|
61
|
+
},
|
|
32
62
|
};
|
|
33
63
|
|
|
34
64
|
/**
|
|
@@ -56,19 +86,42 @@ export async function loadConfig(): Promise<AmalfaConfig> {
|
|
|
56
86
|
userConfig = imported.default || imported;
|
|
57
87
|
}
|
|
58
88
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
89
|
+
// Merge with defaults
|
|
90
|
+
const merged = {
|
|
91
|
+
...DEFAULT_CONFIG,
|
|
92
|
+
...userConfig,
|
|
93
|
+
embeddings: {
|
|
94
|
+
...DEFAULT_CONFIG.embeddings,
|
|
95
|
+
...(userConfig.embeddings || {}),
|
|
96
|
+
},
|
|
97
|
+
watch: {
|
|
98
|
+
...DEFAULT_CONFIG.watch,
|
|
99
|
+
...(userConfig.watch || {}),
|
|
100
|
+
},
|
|
101
|
+
graph: {
|
|
102
|
+
...DEFAULT_CONFIG.graph,
|
|
103
|
+
...(userConfig.graph || {}),
|
|
104
|
+
tuning: {
|
|
105
|
+
...(DEFAULT_CONFIG.graph?.tuning || {}),
|
|
106
|
+
...(userConfig.graph?.tuning || {}),
|
|
70
107
|
},
|
|
71
|
-
}
|
|
108
|
+
},
|
|
109
|
+
fixtures: {
|
|
110
|
+
...DEFAULT_CONFIG.fixtures,
|
|
111
|
+
...(userConfig.fixtures || {}),
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// Normalize: Convert legacy 'source' to 'sources' array
|
|
116
|
+
if (merged.source && !merged.sources) {
|
|
117
|
+
merged.sources = [merged.source];
|
|
118
|
+
}
|
|
119
|
+
if (!merged.sources || merged.sources.length === 0) {
|
|
120
|
+
merged.sources = ["./docs"];
|
|
121
|
+
}
|
|
122
|
+
delete merged.source; // Clean up legacy field
|
|
123
|
+
|
|
124
|
+
return merged;
|
|
72
125
|
}
|
|
73
126
|
} catch (e) {
|
|
74
127
|
// Silently continue to next config file
|
|
@@ -77,5 +130,10 @@ export async function loadConfig(): Promise<AmalfaConfig> {
|
|
|
77
130
|
}
|
|
78
131
|
|
|
79
132
|
// Return defaults if no config found
|
|
80
|
-
|
|
133
|
+
const defaultCopy = { ...DEFAULT_CONFIG };
|
|
134
|
+
// Ensure sources is always an array
|
|
135
|
+
if (!defaultCopy.sources || defaultCopy.sources.length === 0) {
|
|
136
|
+
defaultCopy.sources = ["./docs"];
|
|
137
|
+
}
|
|
138
|
+
return defaultCopy;
|
|
81
139
|
}
|
package/src/core/VectorEngine.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { Database } from "bun:sqlite";
|
|
2
|
-
import { join } from "node:path";
|
|
3
2
|
import { EmbeddingModel, FlagEmbedding } from "fastembed";
|
|
4
|
-
import settings from "@/polyvis.settings.json";
|
|
5
3
|
|
|
6
4
|
// Types
|
|
7
5
|
export interface SearchResult {
|
|
@@ -89,9 +87,7 @@ export class VectorEngine {
|
|
|
89
87
|
console.warn(
|
|
90
88
|
"⚠️ DEPRECATED: VectorEngine string path constructor bypasses DatabaseFactory. Pass Database object instead. Will be removed in v2.0.",
|
|
91
89
|
);
|
|
92
|
-
|
|
93
|
-
dbOrPath || join(process.cwd(), settings.paths.database.resonance);
|
|
94
|
-
this.db = new Database(path);
|
|
90
|
+
this.db = new Database(dbOrPath);
|
|
95
91
|
|
|
96
92
|
// Apply Safeguards if we created it
|
|
97
93
|
this.db.run("PRAGMA journal_mode = WAL;");
|
|
@@ -192,22 +188,35 @@ export class VectorEngine {
|
|
|
192
188
|
const topK = scored.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
193
189
|
|
|
194
190
|
// 5. Hydrate Content (for top K only)
|
|
191
|
+
// Note: Hollow Nodes have content=NULL, use meta.source to read from filesystem if needed
|
|
195
192
|
const results: SearchResult[] = [];
|
|
196
193
|
const contentStmt = this.db.prepare(
|
|
197
|
-
"SELECT title, content FROM nodes WHERE id = ?",
|
|
194
|
+
"SELECT title, content, meta FROM nodes WHERE id = ?",
|
|
198
195
|
);
|
|
199
196
|
|
|
200
197
|
for (const item of topK) {
|
|
201
198
|
const row = contentStmt.get(item.id) as {
|
|
202
199
|
title: string;
|
|
203
|
-
content: string;
|
|
200
|
+
content: string | null;
|
|
201
|
+
meta: string | null;
|
|
204
202
|
};
|
|
205
203
|
if (row) {
|
|
204
|
+
// For hollow nodes, extract a preview from title or meta
|
|
205
|
+
let content = row.content || "";
|
|
206
|
+
if (!content && row.meta) {
|
|
207
|
+
try {
|
|
208
|
+
const meta = JSON.parse(row.meta);
|
|
209
|
+
// Provide source path as content placeholder for hollow nodes
|
|
210
|
+
content = `[Hollow Node: ${meta.source || "no source"}]`;
|
|
211
|
+
} catch {
|
|
212
|
+
content = "[Hollow Node: parse error]";
|
|
213
|
+
}
|
|
214
|
+
}
|
|
206
215
|
results.push({
|
|
207
216
|
id: item.id,
|
|
208
217
|
score: item.score,
|
|
209
|
-
title: row.title,
|
|
210
|
-
content:
|
|
218
|
+
title: row.title,
|
|
219
|
+
content: content,
|
|
211
220
|
});
|
|
212
221
|
}
|
|
213
222
|
}
|
package/src/daemon/index.ts
CHANGED
|
@@ -45,21 +45,25 @@ async function main() {
|
|
|
45
45
|
const config = await loadConfig();
|
|
46
46
|
const DEBOUNCE_MS = config.watch.debounce;
|
|
47
47
|
|
|
48
|
+
const sources = config.sources || ["./docs"];
|
|
48
49
|
log.info({
|
|
49
|
-
|
|
50
|
+
sources,
|
|
50
51
|
database: config.database,
|
|
51
52
|
debounce: DEBOUNCE_MS,
|
|
52
53
|
}, "🚀 AMALFA Daemon starting...");
|
|
53
54
|
|
|
54
|
-
// Verify source
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
// Verify source directories exist
|
|
56
|
+
for (const source of sources) {
|
|
57
|
+
const sourcePath = join(process.cwd(), source);
|
|
58
|
+
if (!existsSync(sourcePath)) {
|
|
59
|
+
log.warn({ path: sourcePath }, "⚠️ Source directory not found, skipping");
|
|
60
|
+
}
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
// Start file
|
|
62
|
-
|
|
63
|
+
// Start file watchers for all sources
|
|
64
|
+
for (const source of sources) {
|
|
65
|
+
startWatcher(source, DEBOUNCE_MS);
|
|
66
|
+
}
|
|
63
67
|
|
|
64
68
|
log.info("✅ Daemon ready. Watching for changes...");
|
|
65
69
|
|