monomind 1.18.8 → 1.18.10
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/package.json +1 -1
- package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.d.ts +1 -0
- package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.js +17 -1
- package/packages/@monomind/cli/dist/src/commands/doctor.js +15 -1
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.d.ts +1 -2
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.js +1 -2
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.d.ts +1 -2
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.js +2 -117
- package/packages/@monomind/cli/dist/src/commands/hooks.js +1 -2
- package/packages/@monomind/cli/dist/src/commands/index.d.ts +0 -4
- package/packages/@monomind/cli/dist/src/commands/index.js +0 -22
- package/packages/@monomind/cli/dist/src/init/executor.d.ts +3 -0
- package/packages/@monomind/cli/dist/src/init/executor.js +20 -111
- package/packages/@monomind/cli/dist/src/mcp-client.js +0 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/index.d.ts +0 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/index.js +0 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/coverage-analysis/track-trends.d.ts +4 -4
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/test-generation/suggest-tests.d.ts +4 -4
- package/packages/@monomind/cli/package.json +1 -1
- package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.d.ts +0 -134
- package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.js +0 -340
- package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.d.ts +0 -36
- package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.js +0 -125
- package/packages/@monomind/cli/dist/src/commands/benchmark.d.ts +0 -10
- package/packages/@monomind/cli/dist/src/commands/benchmark.js +0 -586
- package/packages/@monomind/cli/dist/src/commands/migrate.d.ts +0 -8
- package/packages/@monomind/cli/dist/src/commands/migrate.js +0 -789
- package/packages/@monomind/cli/dist/src/commands/monovector/backup.d.ts +0 -11
- package/packages/@monomind/cli/dist/src/commands/monovector/backup.js +0 -752
- package/packages/@monomind/cli/dist/src/commands/monovector/benchmark.d.ts +0 -11
- package/packages/@monomind/cli/dist/src/commands/monovector/benchmark.js +0 -502
- package/packages/@monomind/cli/dist/src/commands/monovector/import.d.ts +0 -18
- package/packages/@monomind/cli/dist/src/commands/monovector/import.js +0 -374
- package/packages/@monomind/cli/dist/src/commands/monovector/index.d.ts +0 -29
- package/packages/@monomind/cli/dist/src/commands/monovector/index.js +0 -129
- package/packages/@monomind/cli/dist/src/commands/monovector/init.d.ts +0 -11
- package/packages/@monomind/cli/dist/src/commands/monovector/init.js +0 -481
- package/packages/@monomind/cli/dist/src/commands/monovector/migrate.d.ts +0 -11
- package/packages/@monomind/cli/dist/src/commands/monovector/migrate.js +0 -500
- package/packages/@monomind/cli/dist/src/commands/monovector/optimize.d.ts +0 -11
- package/packages/@monomind/cli/dist/src/commands/monovector/optimize.js +0 -515
- package/packages/@monomind/cli/dist/src/commands/monovector/setup.d.ts +0 -18
- package/packages/@monomind/cli/dist/src/commands/monovector/setup.js +0 -775
- package/packages/@monomind/cli/dist/src/commands/monovector/status.d.ts +0 -11
- package/packages/@monomind/cli/dist/src/commands/monovector/status.js +0 -491
- package/packages/@monomind/cli/dist/src/commands/progress.d.ts +0 -11
- package/packages/@monomind/cli/dist/src/commands/progress.js +0 -261
- package/packages/@monomind/cli/dist/src/mcp-tools/progress-tools.d.ts +0 -14
- package/packages/@monomind/cli/dist/src/mcp-tools/progress-tools.js +0 -353
|
@@ -1,775 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI MonoVector Setup Command
|
|
3
|
-
* Outputs Docker files and SQL for easy MonoVector PostgreSQL setup
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* npx monomind monovector setup # Output to ./monovector-postgres/
|
|
7
|
-
* npx monomind monovector setup --output /path/to/dir
|
|
8
|
-
* npx monomind monovector setup --print # Print to stdout only
|
|
9
|
-
*
|
|
10
|
-
* https://github.com/monoes/monomind
|
|
11
|
-
*/
|
|
12
|
-
import { output } from '../../output.js';
|
|
13
|
-
import * as fs from 'fs';
|
|
14
|
-
import * as path from 'path';
|
|
15
|
-
/**
|
|
16
|
-
* Docker Compose template for MonoVector PostgreSQL
|
|
17
|
-
*/
|
|
18
|
-
const DOCKER_COMPOSE_TEMPLATE = `# MonoVector PostgreSQL Testing Environment
|
|
19
|
-
# Official MonoVector extension from nokhodian/monovector-postgres
|
|
20
|
-
#
|
|
21
|
-
# Features:
|
|
22
|
-
# - 77+ SQL functions for vector operations
|
|
23
|
-
# - HNSW/IVFFlat indexing with SIMD acceleration
|
|
24
|
-
# - Hyperbolic embeddings (Poincaré ball)
|
|
25
|
-
# - Graph operations and GNN support
|
|
26
|
-
# - Agent routing and learning
|
|
27
|
-
#
|
|
28
|
-
# Performance: ~61µs latency, 16,400 QPS with HNSW
|
|
29
|
-
|
|
30
|
-
services:
|
|
31
|
-
postgres:
|
|
32
|
-
image: nokhodian/monovector-postgres:latest
|
|
33
|
-
container_name: monovector-postgres
|
|
34
|
-
environment:
|
|
35
|
-
POSTGRES_USER: claude
|
|
36
|
-
POSTGRES_PASSWORD: monomind-test
|
|
37
|
-
POSTGRES_DB: monomind
|
|
38
|
-
ports:
|
|
39
|
-
- "5432:5432"
|
|
40
|
-
volumes:
|
|
41
|
-
- postgres_data:/var/lib/postgresql/data
|
|
42
|
-
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/01-init.sql
|
|
43
|
-
healthcheck:
|
|
44
|
-
test: ["CMD-SHELL", "pg_isready -U claude -d monomind"]
|
|
45
|
-
interval: 5s
|
|
46
|
-
timeout: 5s
|
|
47
|
-
retries: 10
|
|
48
|
-
command: >
|
|
49
|
-
postgres
|
|
50
|
-
-c work_mem=256MB
|
|
51
|
-
-c maintenance_work_mem=512MB
|
|
52
|
-
|
|
53
|
-
# Optional: pgAdmin for visual database management
|
|
54
|
-
pgadmin:
|
|
55
|
-
image: dpage/pgadmin4:latest
|
|
56
|
-
container_name: monovector-pgadmin
|
|
57
|
-
environment:
|
|
58
|
-
PGADMIN_DEFAULT_EMAIL: admin@monomind.local
|
|
59
|
-
PGADMIN_DEFAULT_PASSWORD: admin
|
|
60
|
-
PGADMIN_CONFIG_SERVER_MODE: 'False'
|
|
61
|
-
ports:
|
|
62
|
-
- "5050:80"
|
|
63
|
-
depends_on:
|
|
64
|
-
postgres:
|
|
65
|
-
condition: service_healthy
|
|
66
|
-
profiles:
|
|
67
|
-
- gui
|
|
68
|
-
|
|
69
|
-
volumes:
|
|
70
|
-
postgres_data:
|
|
71
|
-
`;
|
|
72
|
-
/**
|
|
73
|
-
* Init SQL template for MonoVector PostgreSQL
|
|
74
|
-
*/
|
|
75
|
-
const INIT_SQL_TEMPLATE = `-- ============================================
|
|
76
|
-
-- MONOVECTOR POSTGRESQL INITIALIZATION SCRIPT
|
|
77
|
-
-- ============================================
|
|
78
|
-
--
|
|
79
|
-
-- This script initializes MonoVector PostgreSQL extension
|
|
80
|
-
-- from nokhodian/monovector-postgres with Monomind integration.
|
|
81
|
-
--
|
|
82
|
-
-- MonoVector provides 77+ SQL functions including:
|
|
83
|
-
-- - Vector similarity search (HNSW with SIMD)
|
|
84
|
-
-- - Hyperbolic embeddings (Poincaré/Lorentz)
|
|
85
|
-
-- - Graph operations (Cypher queries)
|
|
86
|
-
-- - Agent routing and learning
|
|
87
|
-
--
|
|
88
|
-
-- Performance: ~61µs latency, 16,400 QPS
|
|
89
|
-
|
|
90
|
-
-- ============================================
|
|
91
|
-
-- PART 1: EXTENSION AND SCHEMA SETUP
|
|
92
|
-
-- ============================================
|
|
93
|
-
|
|
94
|
-
-- IMPORTANT: MonoVector requires explicit VERSION
|
|
95
|
-
-- The control file says 2.0.0 but only 0.1.0 SQL exists
|
|
96
|
-
CREATE EXTENSION IF NOT EXISTS monovector VERSION '0.1.0';
|
|
97
|
-
|
|
98
|
-
-- Enable additional required extensions
|
|
99
|
-
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
100
|
-
|
|
101
|
-
-- Create the monomind schema
|
|
102
|
-
CREATE SCHEMA IF NOT EXISTS monomind;
|
|
103
|
-
|
|
104
|
-
-- Grant permissions
|
|
105
|
-
GRANT ALL ON SCHEMA monomind TO claude;
|
|
106
|
-
|
|
107
|
-
-- Set search path
|
|
108
|
-
SET search_path TO monomind, public;
|
|
109
|
-
|
|
110
|
-
-- ============================================
|
|
111
|
-
-- PART 2: CORE TABLES
|
|
112
|
-
-- ============================================
|
|
113
|
-
|
|
114
|
-
-- Embeddings table with MonoVector vector type (384-dim for all-MiniLM-L6-v2)
|
|
115
|
-
CREATE TABLE IF NOT EXISTS monomind.embeddings (
|
|
116
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
117
|
-
content TEXT NOT NULL,
|
|
118
|
-
embedding monovector(384),
|
|
119
|
-
metadata JSONB DEFAULT '{}',
|
|
120
|
-
namespace VARCHAR(100) DEFAULT 'default',
|
|
121
|
-
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
122
|
-
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
-- Patterns table for learned patterns (ReasoningBank)
|
|
126
|
-
CREATE TABLE IF NOT EXISTS monomind.patterns (
|
|
127
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
128
|
-
name VARCHAR(255) NOT NULL,
|
|
129
|
-
description TEXT,
|
|
130
|
-
embedding monovector(384),
|
|
131
|
-
pattern_type VARCHAR(50),
|
|
132
|
-
confidence FLOAT DEFAULT 0.5,
|
|
133
|
-
success_count INT DEFAULT 0,
|
|
134
|
-
failure_count INT DEFAULT 0,
|
|
135
|
-
ewc_importance FLOAT DEFAULT 1.0,
|
|
136
|
-
metadata JSONB DEFAULT '{}',
|
|
137
|
-
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
-- Agents table for multi-agent memory coordination
|
|
141
|
-
CREATE TABLE IF NOT EXISTS monomind.agents (
|
|
142
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
143
|
-
agent_id VARCHAR(255) NOT NULL UNIQUE,
|
|
144
|
-
agent_type VARCHAR(50),
|
|
145
|
-
state JSONB DEFAULT '{}',
|
|
146
|
-
memory_embedding monovector(384),
|
|
147
|
-
last_active TIMESTAMPTZ DEFAULT NOW(),
|
|
148
|
-
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
-- Trajectories table for SONA reinforcement learning
|
|
152
|
-
CREATE TABLE IF NOT EXISTS monomind.trajectories (
|
|
153
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
154
|
-
trajectory_id VARCHAR(255) NOT NULL UNIQUE,
|
|
155
|
-
agent_type VARCHAR(50),
|
|
156
|
-
task_description TEXT,
|
|
157
|
-
status VARCHAR(20) DEFAULT 'in_progress',
|
|
158
|
-
steps JSONB DEFAULT '[]',
|
|
159
|
-
outcome VARCHAR(20),
|
|
160
|
-
quality_score FLOAT,
|
|
161
|
-
started_at TIMESTAMPTZ DEFAULT NOW(),
|
|
162
|
-
ended_at TIMESTAMPTZ
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
-- Memory entries table (main storage for Monomind memory)
|
|
166
|
-
CREATE TABLE IF NOT EXISTS monomind.memory_entries (
|
|
167
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
168
|
-
key VARCHAR(255) NOT NULL,
|
|
169
|
-
value TEXT NOT NULL,
|
|
170
|
-
embedding monovector(384),
|
|
171
|
-
namespace VARCHAR(100) DEFAULT 'default',
|
|
172
|
-
metadata JSONB DEFAULT '{}',
|
|
173
|
-
ttl TIMESTAMPTZ,
|
|
174
|
-
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
175
|
-
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
176
|
-
UNIQUE(key, namespace)
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
-- Hyperbolic embeddings for hierarchical data
|
|
180
|
-
CREATE TABLE IF NOT EXISTS monomind.hyperbolic_embeddings (
|
|
181
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
182
|
-
content TEXT NOT NULL,
|
|
183
|
-
euclidean_embedding monovector(384),
|
|
184
|
-
poincare_embedding real[], -- Array for hyperbolic operations
|
|
185
|
-
curvature FLOAT DEFAULT -1.0,
|
|
186
|
-
hierarchy_level INT DEFAULT 0,
|
|
187
|
-
parent_id UUID REFERENCES monomind.hyperbolic_embeddings(id),
|
|
188
|
-
metadata JSONB DEFAULT '{}',
|
|
189
|
-
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
-- Graph nodes for GNN operations
|
|
193
|
-
CREATE TABLE IF NOT EXISTS monomind.graph_nodes (
|
|
194
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
195
|
-
node_id VARCHAR(255) NOT NULL UNIQUE,
|
|
196
|
-
node_type VARCHAR(50),
|
|
197
|
-
embedding monovector(384),
|
|
198
|
-
features JSONB DEFAULT '{}',
|
|
199
|
-
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
200
|
-
);
|
|
201
|
-
|
|
202
|
-
-- Graph edges for message passing
|
|
203
|
-
CREATE TABLE IF NOT EXISTS monomind.graph_edges (
|
|
204
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
205
|
-
source_id UUID REFERENCES monomind.graph_nodes(id),
|
|
206
|
-
target_id UUID REFERENCES monomind.graph_nodes(id),
|
|
207
|
-
edge_type VARCHAR(50),
|
|
208
|
-
weight FLOAT DEFAULT 1.0,
|
|
209
|
-
metadata JSONB DEFAULT '{}',
|
|
210
|
-
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
-- ============================================
|
|
214
|
-
-- PART 3: HNSW INDICES (150x-12,500x faster)
|
|
215
|
-
-- ============================================
|
|
216
|
-
|
|
217
|
-
-- HNSW index for embeddings (cosine distance)
|
|
218
|
-
CREATE INDEX IF NOT EXISTS idx_embeddings_hnsw
|
|
219
|
-
ON monomind.embeddings
|
|
220
|
-
USING hnsw (embedding monovector_cosine_ops)
|
|
221
|
-
WITH (m = 16, ef_construction = 100);
|
|
222
|
-
|
|
223
|
-
-- HNSW index for patterns
|
|
224
|
-
CREATE INDEX IF NOT EXISTS idx_patterns_hnsw
|
|
225
|
-
ON monomind.patterns
|
|
226
|
-
USING hnsw (embedding monovector_cosine_ops)
|
|
227
|
-
WITH (m = 16, ef_construction = 100);
|
|
228
|
-
|
|
229
|
-
-- HNSW index for agent memory
|
|
230
|
-
CREATE INDEX IF NOT EXISTS idx_agents_hnsw
|
|
231
|
-
ON monomind.agents
|
|
232
|
-
USING hnsw (memory_embedding monovector_cosine_ops)
|
|
233
|
-
WITH (m = 16, ef_construction = 64);
|
|
234
|
-
|
|
235
|
-
-- HNSW index for memory entries
|
|
236
|
-
CREATE INDEX IF NOT EXISTS idx_memory_entries_hnsw
|
|
237
|
-
ON monomind.memory_entries
|
|
238
|
-
USING hnsw (embedding monovector_cosine_ops)
|
|
239
|
-
WITH (m = 16, ef_construction = 100);
|
|
240
|
-
|
|
241
|
-
-- HNSW index for hyperbolic embeddings
|
|
242
|
-
CREATE INDEX IF NOT EXISTS idx_hyperbolic_hnsw
|
|
243
|
-
ON monomind.hyperbolic_embeddings
|
|
244
|
-
USING hnsw (euclidean_embedding monovector_cosine_ops)
|
|
245
|
-
WITH (m = 16, ef_construction = 100);
|
|
246
|
-
|
|
247
|
-
-- HNSW index for graph nodes
|
|
248
|
-
CREATE INDEX IF NOT EXISTS idx_graph_nodes_hnsw
|
|
249
|
-
ON monomind.graph_nodes
|
|
250
|
-
USING hnsw (embedding monovector_cosine_ops)
|
|
251
|
-
WITH (m = 16, ef_construction = 64);
|
|
252
|
-
|
|
253
|
-
-- Additional indices for common queries
|
|
254
|
-
CREATE INDEX IF NOT EXISTS idx_embeddings_namespace ON monomind.embeddings(namespace);
|
|
255
|
-
CREATE INDEX IF NOT EXISTS idx_memory_entries_namespace ON monomind.memory_entries(namespace);
|
|
256
|
-
CREATE INDEX IF NOT EXISTS idx_memory_entries_key ON monomind.memory_entries(key);
|
|
257
|
-
|
|
258
|
-
-- ============================================
|
|
259
|
-
-- PART 4: CORE SEARCH FUNCTIONS
|
|
260
|
-
-- ============================================
|
|
261
|
-
|
|
262
|
-
-- Semantic similarity search using MonoVector HNSW
|
|
263
|
-
CREATE OR REPLACE FUNCTION monomind.search_similar(
|
|
264
|
-
query_embedding monovector(384),
|
|
265
|
-
limit_count INT DEFAULT 10,
|
|
266
|
-
min_similarity FLOAT DEFAULT 0.5
|
|
267
|
-
)
|
|
268
|
-
RETURNS TABLE (
|
|
269
|
-
id UUID,
|
|
270
|
-
content TEXT,
|
|
271
|
-
similarity FLOAT,
|
|
272
|
-
metadata JSONB
|
|
273
|
-
) AS $$
|
|
274
|
-
BEGIN
|
|
275
|
-
RETURN QUERY
|
|
276
|
-
SELECT
|
|
277
|
-
e.id,
|
|
278
|
-
e.content,
|
|
279
|
-
(1 - (e.embedding <=> query_embedding))::FLOAT AS similarity,
|
|
280
|
-
e.metadata
|
|
281
|
-
FROM monomind.embeddings e
|
|
282
|
-
WHERE e.embedding IS NOT NULL
|
|
283
|
-
AND (1 - (e.embedding <=> query_embedding)) >= min_similarity
|
|
284
|
-
ORDER BY e.embedding <=> query_embedding
|
|
285
|
-
LIMIT limit_count;
|
|
286
|
-
END;
|
|
287
|
-
$$ LANGUAGE plpgsql STABLE;
|
|
288
|
-
|
|
289
|
-
-- Memory search with namespace filtering
|
|
290
|
-
CREATE OR REPLACE FUNCTION monomind.search_memory(
|
|
291
|
-
query_embedding monovector(384),
|
|
292
|
-
namespace_filter VARCHAR(100) DEFAULT NULL,
|
|
293
|
-
limit_count INT DEFAULT 10,
|
|
294
|
-
min_similarity FLOAT DEFAULT 0.5
|
|
295
|
-
)
|
|
296
|
-
RETURNS TABLE (
|
|
297
|
-
id UUID,
|
|
298
|
-
key VARCHAR(255),
|
|
299
|
-
value TEXT,
|
|
300
|
-
namespace VARCHAR(100),
|
|
301
|
-
similarity FLOAT,
|
|
302
|
-
metadata JSONB
|
|
303
|
-
) AS $$
|
|
304
|
-
BEGIN
|
|
305
|
-
RETURN QUERY
|
|
306
|
-
SELECT
|
|
307
|
-
m.id,
|
|
308
|
-
m.key,
|
|
309
|
-
m.value,
|
|
310
|
-
m.namespace,
|
|
311
|
-
(1 - (m.embedding <=> query_embedding))::FLOAT AS similarity,
|
|
312
|
-
m.metadata
|
|
313
|
-
FROM monomind.memory_entries m
|
|
314
|
-
WHERE m.embedding IS NOT NULL
|
|
315
|
-
AND (1 - (m.embedding <=> query_embedding)) >= min_similarity
|
|
316
|
-
AND (namespace_filter IS NULL OR m.namespace = namespace_filter)
|
|
317
|
-
AND (m.ttl IS NULL OR m.ttl > NOW())
|
|
318
|
-
ORDER BY m.embedding <=> query_embedding
|
|
319
|
-
LIMIT limit_count;
|
|
320
|
-
END;
|
|
321
|
-
$$ LANGUAGE plpgsql STABLE;
|
|
322
|
-
|
|
323
|
-
-- Pattern search with type filtering
|
|
324
|
-
CREATE OR REPLACE FUNCTION monomind.search_patterns(
|
|
325
|
-
query_embedding monovector(384),
|
|
326
|
-
pattern_type_filter VARCHAR(50) DEFAULT NULL,
|
|
327
|
-
limit_count INT DEFAULT 10,
|
|
328
|
-
min_confidence FLOAT DEFAULT 0.5
|
|
329
|
-
)
|
|
330
|
-
RETURNS TABLE (
|
|
331
|
-
id UUID,
|
|
332
|
-
name VARCHAR(255),
|
|
333
|
-
description TEXT,
|
|
334
|
-
similarity FLOAT,
|
|
335
|
-
confidence FLOAT,
|
|
336
|
-
metadata JSONB
|
|
337
|
-
) AS $$
|
|
338
|
-
BEGIN
|
|
339
|
-
RETURN QUERY
|
|
340
|
-
SELECT
|
|
341
|
-
p.id,
|
|
342
|
-
p.name,
|
|
343
|
-
p.description,
|
|
344
|
-
(1 - (p.embedding <=> query_embedding))::FLOAT AS similarity,
|
|
345
|
-
p.confidence,
|
|
346
|
-
p.metadata
|
|
347
|
-
FROM monomind.patterns p
|
|
348
|
-
WHERE p.embedding IS NOT NULL
|
|
349
|
-
AND p.confidence >= min_confidence
|
|
350
|
-
AND (pattern_type_filter IS NULL OR p.pattern_type = pattern_type_filter)
|
|
351
|
-
ORDER BY p.embedding <=> query_embedding
|
|
352
|
-
LIMIT limit_count;
|
|
353
|
-
END;
|
|
354
|
-
$$ LANGUAGE plpgsql STABLE;
|
|
355
|
-
|
|
356
|
-
-- Agent routing by expertise similarity
|
|
357
|
-
CREATE OR REPLACE FUNCTION monomind.find_agents(
|
|
358
|
-
query_embedding monovector(384),
|
|
359
|
-
agent_type_filter VARCHAR(50) DEFAULT NULL,
|
|
360
|
-
limit_count INT DEFAULT 5
|
|
361
|
-
)
|
|
362
|
-
RETURNS TABLE (
|
|
363
|
-
agent_id VARCHAR(255),
|
|
364
|
-
agent_type VARCHAR(50),
|
|
365
|
-
similarity FLOAT,
|
|
366
|
-
state JSONB
|
|
367
|
-
) AS $$
|
|
368
|
-
BEGIN
|
|
369
|
-
RETURN QUERY
|
|
370
|
-
SELECT
|
|
371
|
-
a.agent_id,
|
|
372
|
-
a.agent_type,
|
|
373
|
-
(1 - (a.memory_embedding <=> query_embedding))::FLOAT AS similarity,
|
|
374
|
-
a.state
|
|
375
|
-
FROM monomind.agents a
|
|
376
|
-
WHERE a.memory_embedding IS NOT NULL
|
|
377
|
-
AND (agent_type_filter IS NULL OR a.agent_type = agent_type_filter)
|
|
378
|
-
ORDER BY a.memory_embedding <=> query_embedding
|
|
379
|
-
LIMIT limit_count;
|
|
380
|
-
END;
|
|
381
|
-
$$ LANGUAGE plpgsql STABLE;
|
|
382
|
-
|
|
383
|
-
-- ============================================
|
|
384
|
-
-- PART 5: HYPERBOLIC OPERATIONS
|
|
385
|
-
-- ============================================
|
|
386
|
-
|
|
387
|
-
-- Convert Euclidean to Poincaré embedding
|
|
388
|
-
CREATE OR REPLACE FUNCTION monomind.to_poincare(
|
|
389
|
-
euclidean real[],
|
|
390
|
-
curvature FLOAT DEFAULT -1.0
|
|
391
|
-
)
|
|
392
|
-
RETURNS real[] AS $$
|
|
393
|
-
BEGIN
|
|
394
|
-
RETURN monovector_exp_map(ARRAY_FILL(0.0::real, ARRAY[array_length(euclidean, 1)]), euclidean, curvature);
|
|
395
|
-
END;
|
|
396
|
-
$$ LANGUAGE plpgsql IMMUTABLE;
|
|
397
|
-
|
|
398
|
-
-- Poincaré distance (geodesic)
|
|
399
|
-
CREATE OR REPLACE FUNCTION monomind.poincare_distance(
|
|
400
|
-
x real[],
|
|
401
|
-
y real[],
|
|
402
|
-
curvature FLOAT DEFAULT -1.0
|
|
403
|
-
)
|
|
404
|
-
RETURNS FLOAT AS $$
|
|
405
|
-
BEGIN
|
|
406
|
-
RETURN monovector_poincare_distance(x, y, curvature);
|
|
407
|
-
END;
|
|
408
|
-
$$ LANGUAGE plpgsql IMMUTABLE;
|
|
409
|
-
|
|
410
|
-
-- Hyperbolic search in Poincaré ball
|
|
411
|
-
CREATE OR REPLACE FUNCTION monomind.hyperbolic_search(
|
|
412
|
-
query monovector(384),
|
|
413
|
-
limit_count INT DEFAULT 10,
|
|
414
|
-
curvature FLOAT DEFAULT -1.0
|
|
415
|
-
)
|
|
416
|
-
RETURNS TABLE (
|
|
417
|
-
id UUID,
|
|
418
|
-
content TEXT,
|
|
419
|
-
euclidean_dist FLOAT,
|
|
420
|
-
hyperbolic_dist FLOAT,
|
|
421
|
-
hierarchy_level INT,
|
|
422
|
-
metadata JSONB
|
|
423
|
-
) AS $$
|
|
424
|
-
DECLARE
|
|
425
|
-
query_arr real[];
|
|
426
|
-
query_poincare real[];
|
|
427
|
-
BEGIN
|
|
428
|
-
-- Convert query to array and then to Poincaré
|
|
429
|
-
SELECT array_agg(x::real ORDER BY ordinality) INTO query_arr
|
|
430
|
-
FROM unnest(string_to_array(trim(both '[]' from query::text), ',')) WITH ORDINALITY AS t(x, ordinality);
|
|
431
|
-
|
|
432
|
-
query_poincare := monomind.to_poincare(query_arr, curvature);
|
|
433
|
-
|
|
434
|
-
RETURN QUERY
|
|
435
|
-
SELECT
|
|
436
|
-
he.id,
|
|
437
|
-
he.content,
|
|
438
|
-
(he.euclidean_embedding <-> query)::FLOAT AS euc_dist,
|
|
439
|
-
COALESCE(monovector_poincare_distance(he.poincare_embedding, query_poincare, curvature), 999.0)::FLOAT AS hyp_dist,
|
|
440
|
-
he.hierarchy_level,
|
|
441
|
-
he.metadata
|
|
442
|
-
FROM monomind.hyperbolic_embeddings he
|
|
443
|
-
WHERE he.euclidean_embedding IS NOT NULL
|
|
444
|
-
ORDER BY he.euclidean_embedding <-> query
|
|
445
|
-
LIMIT limit_count;
|
|
446
|
-
END;
|
|
447
|
-
$$ LANGUAGE plpgsql STABLE;
|
|
448
|
-
|
|
449
|
-
-- ============================================
|
|
450
|
-
-- PART 6: UTILITY FUNCTIONS
|
|
451
|
-
-- ============================================
|
|
452
|
-
|
|
453
|
-
-- Get MonoVector version info
|
|
454
|
-
CREATE OR REPLACE FUNCTION monomind.monovector_info()
|
|
455
|
-
RETURNS TABLE (
|
|
456
|
-
version TEXT,
|
|
457
|
-
simd_info TEXT
|
|
458
|
-
) AS $$
|
|
459
|
-
BEGIN
|
|
460
|
-
RETURN QUERY
|
|
461
|
-
SELECT monovector_version(), monovector_simd_info();
|
|
462
|
-
END;
|
|
463
|
-
$$ LANGUAGE plpgsql STABLE;
|
|
464
|
-
|
|
465
|
-
-- Cosine similarity helper (converts cosine distance to similarity)
|
|
466
|
-
CREATE OR REPLACE FUNCTION monomind.cosine_similarity(
|
|
467
|
-
a monovector,
|
|
468
|
-
b monovector
|
|
469
|
-
)
|
|
470
|
-
RETURNS FLOAT AS $$
|
|
471
|
-
BEGIN
|
|
472
|
-
RETURN (1 - (a <=> b))::FLOAT;
|
|
473
|
-
END;
|
|
474
|
-
$$ LANGUAGE plpgsql IMMUTABLE;
|
|
475
|
-
|
|
476
|
-
-- L2 distance helper
|
|
477
|
-
CREATE OR REPLACE FUNCTION monomind.l2_distance(
|
|
478
|
-
a monovector,
|
|
479
|
-
b monovector
|
|
480
|
-
)
|
|
481
|
-
RETURNS FLOAT AS $$
|
|
482
|
-
BEGIN
|
|
483
|
-
RETURN (a <-> b)::FLOAT;
|
|
484
|
-
END;
|
|
485
|
-
$$ LANGUAGE plpgsql IMMUTABLE;
|
|
486
|
-
|
|
487
|
-
-- Upsert memory entry
|
|
488
|
-
CREATE OR REPLACE FUNCTION monomind.upsert_memory(
|
|
489
|
-
p_key VARCHAR(255),
|
|
490
|
-
p_value TEXT,
|
|
491
|
-
p_embedding monovector(384) DEFAULT NULL,
|
|
492
|
-
p_namespace VARCHAR(100) DEFAULT 'default',
|
|
493
|
-
p_metadata JSONB DEFAULT '{}',
|
|
494
|
-
p_ttl TIMESTAMPTZ DEFAULT NULL
|
|
495
|
-
)
|
|
496
|
-
RETURNS UUID AS $$
|
|
497
|
-
DECLARE
|
|
498
|
-
v_id UUID;
|
|
499
|
-
BEGIN
|
|
500
|
-
INSERT INTO monomind.memory_entries (key, value, embedding, namespace, metadata, ttl, updated_at)
|
|
501
|
-
VALUES (p_key, p_value, p_embedding, p_namespace, p_metadata, p_ttl, NOW())
|
|
502
|
-
ON CONFLICT (key, namespace) DO UPDATE SET
|
|
503
|
-
value = EXCLUDED.value,
|
|
504
|
-
embedding = COALESCE(EXCLUDED.embedding, monomind.memory_entries.embedding),
|
|
505
|
-
metadata = EXCLUDED.metadata,
|
|
506
|
-
ttl = EXCLUDED.ttl,
|
|
507
|
-
updated_at = NOW()
|
|
508
|
-
RETURNING id INTO v_id;
|
|
509
|
-
|
|
510
|
-
RETURN v_id;
|
|
511
|
-
END;
|
|
512
|
-
$$ LANGUAGE plpgsql;
|
|
513
|
-
|
|
514
|
-
-- ============================================
|
|
515
|
-
-- COMPLETION
|
|
516
|
-
-- ============================================
|
|
517
|
-
|
|
518
|
-
DO $$
|
|
519
|
-
DECLARE
|
|
520
|
-
v_version TEXT;
|
|
521
|
-
v_simd TEXT;
|
|
522
|
-
BEGIN
|
|
523
|
-
SELECT monovector_version() INTO v_version;
|
|
524
|
-
SELECT monovector_simd_info() INTO v_simd;
|
|
525
|
-
|
|
526
|
-
RAISE NOTICE '';
|
|
527
|
-
RAISE NOTICE '============================================';
|
|
528
|
-
RAISE NOTICE 'MonoVector PostgreSQL Initialization Complete!';
|
|
529
|
-
RAISE NOTICE '============================================';
|
|
530
|
-
RAISE NOTICE '';
|
|
531
|
-
RAISE NOTICE 'MonoVector Version: %', v_version;
|
|
532
|
-
RAISE NOTICE 'SIMD: %', v_simd;
|
|
533
|
-
RAISE NOTICE '';
|
|
534
|
-
RAISE NOTICE 'Schema: monomind';
|
|
535
|
-
RAISE NOTICE 'Tables: embeddings, patterns, agents, trajectories,';
|
|
536
|
-
RAISE NOTICE ' memory_entries, hyperbolic_embeddings,';
|
|
537
|
-
RAISE NOTICE ' graph_nodes, graph_edges';
|
|
538
|
-
RAISE NOTICE 'Indices: 6 HNSW indices + 3 B-tree indices';
|
|
539
|
-
RAISE NOTICE '';
|
|
540
|
-
RAISE NOTICE 'Key Functions:';
|
|
541
|
-
RAISE NOTICE ' - monomind.search_similar(embedding, limit, min_sim)';
|
|
542
|
-
RAISE NOTICE ' - monomind.search_memory(embedding, namespace, limit)';
|
|
543
|
-
RAISE NOTICE ' - monomind.search_patterns(embedding, type, limit)';
|
|
544
|
-
RAISE NOTICE ' - monomind.find_agents(embedding, type, limit)';
|
|
545
|
-
RAISE NOTICE ' - monomind.hyperbolic_search(embedding, limit, curvature)';
|
|
546
|
-
RAISE NOTICE ' - monomind.upsert_memory(key, value, embedding, namespace)';
|
|
547
|
-
RAISE NOTICE '';
|
|
548
|
-
RAISE NOTICE 'Operators: <=> (cosine), <-> (L2), <#> (neg inner product)';
|
|
549
|
-
RAISE NOTICE '';
|
|
550
|
-
END $$;
|
|
551
|
-
`;
|
|
552
|
-
/**
|
|
553
|
-
* README template
|
|
554
|
-
*/
|
|
555
|
-
const README_TEMPLATE = `# MonoVector PostgreSQL Setup
|
|
556
|
-
|
|
557
|
-
This directory contains the Docker configuration for MonoVector PostgreSQL with Monomind.
|
|
558
|
-
|
|
559
|
-
## Quick Start
|
|
560
|
-
|
|
561
|
-
\`\`\`bash
|
|
562
|
-
# Start the container
|
|
563
|
-
docker-compose up -d
|
|
564
|
-
|
|
565
|
-
# Verify it's running
|
|
566
|
-
docker-compose ps
|
|
567
|
-
|
|
568
|
-
# Check MonoVector version
|
|
569
|
-
docker exec monovector-postgres psql -U claude -d monomind -c "SELECT monovector_version();"
|
|
570
|
-
\`\`\`
|
|
571
|
-
|
|
572
|
-
## Connection Details
|
|
573
|
-
|
|
574
|
-
| Setting | Value |
|
|
575
|
-
|---------|-------|
|
|
576
|
-
| Host | localhost |
|
|
577
|
-
| Port | 5432 |
|
|
578
|
-
| Database | monomind |
|
|
579
|
-
| Username | claude |
|
|
580
|
-
| Password | monomind-test |
|
|
581
|
-
| Schema | monomind |
|
|
582
|
-
|
|
583
|
-
## MonoVector Syntax
|
|
584
|
-
|
|
585
|
-
### Extension Installation
|
|
586
|
-
\`\`\`sql
|
|
587
|
-
-- IMPORTANT: Requires explicit version
|
|
588
|
-
CREATE EXTENSION IF NOT EXISTS monovector VERSION '0.1.0';
|
|
589
|
-
\`\`\`
|
|
590
|
-
|
|
591
|
-
### Vector Type
|
|
592
|
-
\`\`\`sql
|
|
593
|
-
-- Use monovector(384), NOT vector(384)
|
|
594
|
-
CREATE TABLE embeddings (
|
|
595
|
-
id UUID PRIMARY KEY,
|
|
596
|
-
embedding monovector(384)
|
|
597
|
-
);
|
|
598
|
-
\`\`\`
|
|
599
|
-
|
|
600
|
-
### Distance Operators
|
|
601
|
-
| Operator | Description |
|
|
602
|
-
|----------|-------------|
|
|
603
|
-
| \`<=>\` | Cosine distance |
|
|
604
|
-
| \`<->\` | L2 (Euclidean) distance |
|
|
605
|
-
| \`<#>\` | Negative inner product |
|
|
606
|
-
|
|
607
|
-
### HNSW Index
|
|
608
|
-
\`\`\`sql
|
|
609
|
-
CREATE INDEX idx_embeddings_hnsw
|
|
610
|
-
ON embeddings
|
|
611
|
-
USING hnsw (embedding monovector_cosine_ops)
|
|
612
|
-
WITH (m = 16, ef_construction = 100);
|
|
613
|
-
\`\`\`
|
|
614
|
-
|
|
615
|
-
## Import from sql.js/JSON
|
|
616
|
-
|
|
617
|
-
\`\`\`bash
|
|
618
|
-
# Export current Monomind memory
|
|
619
|
-
npx monomind memory list --format json > memory-export.json
|
|
620
|
-
|
|
621
|
-
# Import to MonoVector PostgreSQL
|
|
622
|
-
npx monomind monovector import --input memory-export.json
|
|
623
|
-
\`\`\`
|
|
624
|
-
|
|
625
|
-
## pgAdmin (Optional)
|
|
626
|
-
|
|
627
|
-
\`\`\`bash
|
|
628
|
-
docker-compose --profile gui up -d
|
|
629
|
-
\`\`\`
|
|
630
|
-
|
|
631
|
-
Access at: http://localhost:5050
|
|
632
|
-
- Email: admin@monomind.local
|
|
633
|
-
- Password: admin
|
|
634
|
-
|
|
635
|
-
## Troubleshooting
|
|
636
|
-
|
|
637
|
-
### Extension creation fails
|
|
638
|
-
Use explicit version: \`CREATE EXTENSION monovector VERSION '0.1.0';\`
|
|
639
|
-
|
|
640
|
-
### Container won't start
|
|
641
|
-
\`\`\`bash
|
|
642
|
-
docker-compose logs postgres
|
|
643
|
-
docker-compose down -v
|
|
644
|
-
docker-compose up -d
|
|
645
|
-
\`\`\`
|
|
646
|
-
|
|
647
|
-
## Learn More
|
|
648
|
-
- [MonoVector Docker Hub](https://hub.docker.com/r/nokhodian/monovector-postgres)
|
|
649
|
-
- [Monomind Documentation](https://github.com/monoes/monomind)
|
|
650
|
-
`;
|
|
651
|
-
/**
|
|
652
|
-
* MonoVector Setup command - outputs Docker files and SQL
|
|
653
|
-
*/
|
|
654
|
-
export const setupCommand = {
|
|
655
|
-
name: 'setup',
|
|
656
|
-
description: 'Output Docker files and SQL for MonoVector PostgreSQL setup',
|
|
657
|
-
aliases: ['scaffold', 'docker'],
|
|
658
|
-
options: [
|
|
659
|
-
{
|
|
660
|
-
name: 'output',
|
|
661
|
-
short: 'o',
|
|
662
|
-
description: 'Output directory (default: ./monovector-postgres)',
|
|
663
|
-
type: 'string',
|
|
664
|
-
default: './monovector-postgres',
|
|
665
|
-
},
|
|
666
|
-
{
|
|
667
|
-
name: 'print',
|
|
668
|
-
short: 'p',
|
|
669
|
-
description: 'Print to stdout instead of writing files',
|
|
670
|
-
type: 'boolean',
|
|
671
|
-
default: false,
|
|
672
|
-
},
|
|
673
|
-
{
|
|
674
|
-
name: 'force',
|
|
675
|
-
short: 'f',
|
|
676
|
-
description: 'Overwrite existing files',
|
|
677
|
-
type: 'boolean',
|
|
678
|
-
default: false,
|
|
679
|
-
},
|
|
680
|
-
],
|
|
681
|
-
examples: [
|
|
682
|
-
{ command: 'monomind monovector setup', description: 'Output files to ./monovector-postgres/' },
|
|
683
|
-
{ command: 'monomind monovector setup --output /path/to/dir', description: 'Output to custom directory' },
|
|
684
|
-
{ command: 'monomind monovector setup --print', description: 'Print files to stdout' },
|
|
685
|
-
{ command: 'monomind monovector setup --force', description: 'Overwrite existing files' },
|
|
686
|
-
],
|
|
687
|
-
action: async (ctx) => {
|
|
688
|
-
const rawOutputDir = ctx.flags.output || './monovector-postgres';
|
|
689
|
-
const printOnly = ctx.flags.print;
|
|
690
|
-
const force = ctx.flags.force;
|
|
691
|
-
output.writeln();
|
|
692
|
-
output.writeln(output.bold('MonoVector PostgreSQL Setup'));
|
|
693
|
-
output.writeln(output.dim('='.repeat(50)));
|
|
694
|
-
output.writeln();
|
|
695
|
-
// Guard against path traversal: resolve to absolute and ensure it stays within
|
|
696
|
-
// the current working directory or the user's home directory.
|
|
697
|
-
const resolvedOutput = path.resolve(rawOutputDir);
|
|
698
|
-
const safeBases = [process.cwd(), process.env.HOME || process.env.USERPROFILE || ''].filter(Boolean);
|
|
699
|
-
const withinSafeBase = safeBases.some(base => resolvedOutput.startsWith(base + path.sep) || resolvedOutput === base);
|
|
700
|
-
if (!withinSafeBase) {
|
|
701
|
-
output.printError(`Output path must be within the current directory or home directory: ${resolvedOutput}`);
|
|
702
|
-
return { success: false, exitCode: 1 };
|
|
703
|
-
}
|
|
704
|
-
const outputDir = resolvedOutput;
|
|
705
|
-
if (printOnly) {
|
|
706
|
-
// Print to stdout
|
|
707
|
-
output.writeln(output.bold('=== docker-compose.yml ==='));
|
|
708
|
-
output.writeln();
|
|
709
|
-
output.writeln(DOCKER_COMPOSE_TEMPLATE);
|
|
710
|
-
output.writeln();
|
|
711
|
-
output.writeln(output.bold('=== scripts/init-db.sql ==='));
|
|
712
|
-
output.writeln();
|
|
713
|
-
output.writeln(INIT_SQL_TEMPLATE);
|
|
714
|
-
output.writeln();
|
|
715
|
-
output.writeln(output.bold('=== README.md ==='));
|
|
716
|
-
output.writeln();
|
|
717
|
-
output.writeln(README_TEMPLATE);
|
|
718
|
-
return { success: true };
|
|
719
|
-
}
|
|
720
|
-
// Create directory structure
|
|
721
|
-
const scriptsDir = path.join(outputDir, 'scripts');
|
|
722
|
-
try {
|
|
723
|
-
// Check if directory exists
|
|
724
|
-
if (fs.existsSync(outputDir) && !force) {
|
|
725
|
-
const files = fs.readdirSync(outputDir);
|
|
726
|
-
if (files.length > 0) {
|
|
727
|
-
output.printWarning(`Directory ${outputDir} already exists and is not empty.`);
|
|
728
|
-
output.printInfo('Use --force to overwrite existing files.');
|
|
729
|
-
return { success: false, message: 'Directory not empty' };
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
// Create directories
|
|
733
|
-
output.printInfo(`Creating directory: ${outputDir}`);
|
|
734
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
735
|
-
fs.mkdirSync(scriptsDir, { recursive: true });
|
|
736
|
-
// Write files
|
|
737
|
-
const dockerComposePath = path.join(outputDir, 'docker-compose.yml');
|
|
738
|
-
const initSqlPath = path.join(scriptsDir, 'init-db.sql');
|
|
739
|
-
const readmePath = path.join(outputDir, 'README.md');
|
|
740
|
-
output.printInfo(`Writing: ${dockerComposePath}`);
|
|
741
|
-
fs.writeFileSync(dockerComposePath, DOCKER_COMPOSE_TEMPLATE);
|
|
742
|
-
output.printInfo(`Writing: ${initSqlPath}`);
|
|
743
|
-
fs.writeFileSync(initSqlPath, INIT_SQL_TEMPLATE);
|
|
744
|
-
output.printInfo(`Writing: ${readmePath}`);
|
|
745
|
-
fs.writeFileSync(readmePath, README_TEMPLATE);
|
|
746
|
-
output.writeln();
|
|
747
|
-
output.printSuccess('MonoVector PostgreSQL setup files created!');
|
|
748
|
-
output.writeln();
|
|
749
|
-
output.printBox([
|
|
750
|
-
'Files created:',
|
|
751
|
-
'',
|
|
752
|
-
` ${outputDir}/`,
|
|
753
|
-
' ├── docker-compose.yml',
|
|
754
|
-
' ├── README.md',
|
|
755
|
-
' └── scripts/',
|
|
756
|
-
' └── init-db.sql',
|
|
757
|
-
'',
|
|
758
|
-
'Next steps:',
|
|
759
|
-
'',
|
|
760
|
-
` cd ${outputDir}`,
|
|
761
|
-
' docker-compose up -d',
|
|
762
|
-
' docker exec monovector-postgres psql -U claude -d monomind -c "SELECT monovector_version();"',
|
|
763
|
-
].join('\n'), 'Setup Complete');
|
|
764
|
-
output.writeln();
|
|
765
|
-
return { success: true };
|
|
766
|
-
}
|
|
767
|
-
catch (error) {
|
|
768
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
769
|
-
output.printError(`Failed to create setup files: ${errorMessage}`);
|
|
770
|
-
return { success: false, message: errorMessage };
|
|
771
|
-
}
|
|
772
|
-
},
|
|
773
|
-
};
|
|
774
|
-
export default setupCommand;
|
|
775
|
-
//# sourceMappingURL=setup.js.map
|