@mise-en-scene/taste-memory 0.1.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 +145 -0
- package/dist/db.d.ts +5 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +63 -0
- package/dist/db.js.map +1 -0
- package/dist/embeddings.d.ts +3 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +21 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +112 -0
- package/dist/index.js.map +1 -0
- package/dist/profile.d.ts +6 -0
- package/dist/profile.d.ts.map +1 -0
- package/dist/profile.js +38 -0
- package/dist/profile.js.map +1 -0
- package/dist/search.d.ts +16 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +53 -0
- package/dist/search.js.map +1 -0
- package/dist/server.d.ts +43 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +63 -0
- package/dist/server.js.map +1 -0
- package/dist/store.d.ts +20 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +66 -0
- package/dist/store.js.map +1 -0
- package/dist/types.d.ts +95 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# @mise-en-scene/taste-memory
|
|
2
|
+
|
|
3
|
+
Aesthetic intelligence MCP server. Stores taste observations, design decisions, anti-patterns, and reference analyses in SQLite. Builds taste profiles that persist across sessions — the agent develops real preferences over time.
|
|
4
|
+
|
|
5
|
+
## MCP Tools
|
|
6
|
+
|
|
7
|
+
| Tool | Input | Description |
|
|
8
|
+
|------|-------|-------------|
|
|
9
|
+
| `taste_remember` | `type`, `scope`, `data`, `reasoning?`, `project?` | Store a taste observation |
|
|
10
|
+
| `taste_recall` | `query`, `type?`, `scope?`, `project?`, `limit?` | Search taste memory by text |
|
|
11
|
+
| `taste_profile` | `scope` (`user` / `project` / `merged`), `project?` | Get aggregated taste profile |
|
|
12
|
+
| `taste_decide` | `chosen`, `rejected`, `reason`, `project?` | Record a design decision |
|
|
13
|
+
| `taste_reference` | `project`, `analysis`, `image_path?` | Store a reference analysis |
|
|
14
|
+
| `taste_system` | `project`, `tokens?` | Get or set design system tokens |
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
### As an MCP Server
|
|
19
|
+
|
|
20
|
+
The package runs as a stdio MCP server. Configure it in your `.mcp.json`:
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"mcpServers": {
|
|
25
|
+
"mise-en-scene-taste-memory": {
|
|
26
|
+
"command": "npx",
|
|
27
|
+
"args": ["@mise-en-scene/taste-memory"]
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or run directly:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx mise-en-scene-taste-memory
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Environment Variables
|
|
40
|
+
|
|
41
|
+
| Variable | Default | Description |
|
|
42
|
+
|----------|---------|-------------|
|
|
43
|
+
| `MISE_TASTE_DB` | `~/.mise-en-scene/taste.db` | SQLite database path |
|
|
44
|
+
|
|
45
|
+
### Programmatic Usage
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { createDatabase, closeDatabase } from '@mise-en-scene/taste-memory/db';
|
|
49
|
+
import { TasteStore } from '@mise-en-scene/taste-memory/store';
|
|
50
|
+
import { TasteSearch } from '@mise-en-scene/taste-memory/search';
|
|
51
|
+
import { buildProfile } from '@mise-en-scene/taste-memory/profile';
|
|
52
|
+
|
|
53
|
+
// Initialize
|
|
54
|
+
const db = createDatabase('/path/to/taste.db');
|
|
55
|
+
const store = new TasteStore(db);
|
|
56
|
+
const search = new TasteSearch(db);
|
|
57
|
+
|
|
58
|
+
// Store observations
|
|
59
|
+
store.remember('palette', 'user', {
|
|
60
|
+
dominant: '#1a1a2e',
|
|
61
|
+
accent: '#e94560',
|
|
62
|
+
}, { reasoning: 'Dark moody palette with warm accent' });
|
|
63
|
+
|
|
64
|
+
store.remember('anti-pattern', 'user', {
|
|
65
|
+
rejected: 'Roboto',
|
|
66
|
+
context: 'too generic',
|
|
67
|
+
}, { reasoning: 'AI default font' });
|
|
68
|
+
|
|
69
|
+
// Record decisions
|
|
70
|
+
store.decide(
|
|
71
|
+
{ layout: 'asymmetric' },
|
|
72
|
+
{ layout: 'centered' },
|
|
73
|
+
'Asymmetric creates visual tension',
|
|
74
|
+
'wine-label'
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Store reference analysis
|
|
78
|
+
store.storeReference('wine-label', {
|
|
79
|
+
colors: ['#f5f0e8', '#c9a96e'],
|
|
80
|
+
typography: 'transitional serif + humanist sans',
|
|
81
|
+
mood: ['luxury', 'warm'],
|
|
82
|
+
cultural_context: 'French wine label tradition',
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Search
|
|
86
|
+
const results = search.textSearch('editorial dark premium');
|
|
87
|
+
const decisions = search.searchDecisions('layout', 'wine-label');
|
|
88
|
+
|
|
89
|
+
// Build profile
|
|
90
|
+
const profile = buildProfile(store, 'merged', 'wine-label');
|
|
91
|
+
|
|
92
|
+
// Cleanup
|
|
93
|
+
closeDatabase();
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Data Model
|
|
97
|
+
|
|
98
|
+
### Taste Types
|
|
99
|
+
|
|
100
|
+
| Type | What It Captures |
|
|
101
|
+
|------|-----------------|
|
|
102
|
+
| `palette` | Color choices — dominant, secondary, accent |
|
|
103
|
+
| `typography` | Font preferences, pairings, classifications |
|
|
104
|
+
| `layout` | Composition patterns, grid preferences |
|
|
105
|
+
| `texture` | Surface treatments — grain, gradients, shadows |
|
|
106
|
+
| `mood` | Emotional descriptors — "editorial", "warm", "refined" |
|
|
107
|
+
| `anti-pattern` | Things to avoid — "generic gradients", "Roboto" |
|
|
108
|
+
|
|
109
|
+
### Scopes
|
|
110
|
+
|
|
111
|
+
| Scope | Persists Across |
|
|
112
|
+
|-------|----------------|
|
|
113
|
+
| `user` | All projects — your personal aesthetic |
|
|
114
|
+
| `project` | Single project — project-specific choices |
|
|
115
|
+
| `merged` | Both combined, project overrides user |
|
|
116
|
+
|
|
117
|
+
### Database Schema
|
|
118
|
+
|
|
119
|
+
Four tables in SQLite with WAL mode:
|
|
120
|
+
|
|
121
|
+
- **`taste_entries`** — Observations with type, scope, JSON data, reasoning, timestamps
|
|
122
|
+
- **`taste_decisions`** — Chosen vs rejected options with reasoning
|
|
123
|
+
- **`taste_references`** — Reference image analyses with structured extraction
|
|
124
|
+
- **`design_systems`** — Design tokens per project (upsert on conflict)
|
|
125
|
+
|
|
126
|
+
## Search
|
|
127
|
+
|
|
128
|
+
Text search uses token-based similarity scoring (Jaccard-style overlap). Queries are tokenized, matched against stored entry data and reasoning fields, and ranked by relevance.
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// Search with filters
|
|
132
|
+
const results = search.textSearch('warm editorial', {
|
|
133
|
+
type: 'palette',
|
|
134
|
+
scope: 'user',
|
|
135
|
+
limit: 10,
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Development
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
npm test # Run tests (24 unit + 2 integration)
|
|
143
|
+
npm run build # Compile TypeScript
|
|
144
|
+
npm run test:watch # Watch mode
|
|
145
|
+
```
|
package/dist/db.d.ts
ADDED
package/dist/db.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAItC,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAkDhE;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAAC,QAAQ,CAG/C;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC"}
|
package/dist/db.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
let db = null;
|
|
3
|
+
export function createDatabase(dbPath) {
|
|
4
|
+
db = new Database(dbPath);
|
|
5
|
+
db.pragma('journal_mode = WAL');
|
|
6
|
+
db.pragma('foreign_keys = ON');
|
|
7
|
+
db.exec(`
|
|
8
|
+
CREATE TABLE IF NOT EXISTS taste_entries (
|
|
9
|
+
id TEXT PRIMARY KEY,
|
|
10
|
+
type TEXT NOT NULL CHECK(type IN ('palette','typography','layout','texture','mood','anti-pattern')),
|
|
11
|
+
scope TEXT NOT NULL CHECK(scope IN ('user','project')),
|
|
12
|
+
project TEXT,
|
|
13
|
+
data TEXT NOT NULL,
|
|
14
|
+
reasoning TEXT,
|
|
15
|
+
embedding BLOB,
|
|
16
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
17
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
CREATE TABLE IF NOT EXISTS taste_decisions (
|
|
21
|
+
id TEXT PRIMARY KEY,
|
|
22
|
+
project TEXT,
|
|
23
|
+
chosen TEXT NOT NULL,
|
|
24
|
+
rejected TEXT NOT NULL,
|
|
25
|
+
reason TEXT NOT NULL,
|
|
26
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE TABLE IF NOT EXISTS taste_references (
|
|
30
|
+
id TEXT PRIMARY KEY,
|
|
31
|
+
project TEXT NOT NULL,
|
|
32
|
+
image_path TEXT,
|
|
33
|
+
analysis TEXT NOT NULL,
|
|
34
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
CREATE TABLE IF NOT EXISTS design_systems (
|
|
38
|
+
project TEXT PRIMARY KEY,
|
|
39
|
+
tokens TEXT NOT NULL,
|
|
40
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
41
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
CREATE INDEX IF NOT EXISTS idx_entries_type ON taste_entries(type);
|
|
45
|
+
CREATE INDEX IF NOT EXISTS idx_entries_scope ON taste_entries(scope);
|
|
46
|
+
CREATE INDEX IF NOT EXISTS idx_entries_project ON taste_entries(project);
|
|
47
|
+
CREATE INDEX IF NOT EXISTS idx_decisions_project ON taste_decisions(project);
|
|
48
|
+
CREATE INDEX IF NOT EXISTS idx_references_project ON taste_references(project);
|
|
49
|
+
`);
|
|
50
|
+
return db;
|
|
51
|
+
}
|
|
52
|
+
export function getDatabase() {
|
|
53
|
+
if (!db)
|
|
54
|
+
throw new Error('Database not initialized. Call createDatabase() first.');
|
|
55
|
+
return db;
|
|
56
|
+
}
|
|
57
|
+
export function closeDatabase() {
|
|
58
|
+
if (db) {
|
|
59
|
+
db.close();
|
|
60
|
+
db = null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=db.js.map
|
package/dist/db.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,IAAI,EAAE,GAA6B,IAAI,CAAC;AAExC,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1B,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAE/B,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CP,CAAC,CAAC;IAEH,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IACnF,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,IAAI,EAAE,EAAE,CAAC;QACP,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,EAAE,GAAG,IAAI,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../src/embeddings.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAM/C;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWtE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function tokenize(text) {
|
|
2
|
+
return text
|
|
3
|
+
.toLowerCase()
|
|
4
|
+
.replace(/[^a-z0-9\s#]/g, ' ')
|
|
5
|
+
.split(/\s+/)
|
|
6
|
+
.filter((t) => t.length > 1);
|
|
7
|
+
}
|
|
8
|
+
export function textSimilarity(query, document) {
|
|
9
|
+
const queryTokens = new Set(tokenize(query));
|
|
10
|
+
const docTokens = tokenize(document);
|
|
11
|
+
if (queryTokens.size === 0 || docTokens.length === 0)
|
|
12
|
+
return 0;
|
|
13
|
+
const docTokenSet = new Set(docTokens);
|
|
14
|
+
let matches = 0;
|
|
15
|
+
for (const token of queryTokens) {
|
|
16
|
+
if (docTokenSet.has(token))
|
|
17
|
+
matches++;
|
|
18
|
+
}
|
|
19
|
+
return matches / queryTokens.size;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=embeddings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../src/embeddings.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,IAAI;SACR,WAAW,EAAE;SACb,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC;SAC7B,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,QAAgB;IAC5D,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAE/D,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IACvC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,IAAI,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC;AACpC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { createToolHandlers } from './server.js';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import os from 'os';
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
const DB_PATH = process.env.MISE_TASTE_DB
|
|
10
|
+
?? path.join(os.homedir(), '.mise-en-scene', 'taste-memory.db');
|
|
11
|
+
fs.mkdirSync(path.dirname(DB_PATH), { recursive: true });
|
|
12
|
+
const handlers = createToolHandlers(DB_PATH);
|
|
13
|
+
const server = new Server({ name: 'mise-en-scene-taste-memory', version: '0.1.0' }, { capabilities: { tools: {} } });
|
|
14
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
15
|
+
tools: [
|
|
16
|
+
{
|
|
17
|
+
name: 'taste_remember',
|
|
18
|
+
description: 'Store a taste observation (palette, typography, layout, texture, mood, or anti-pattern)',
|
|
19
|
+
inputSchema: {
|
|
20
|
+
type: 'object',
|
|
21
|
+
properties: {
|
|
22
|
+
type: { type: 'string', enum: ['palette', 'typography', 'layout', 'texture', 'mood', 'anti-pattern'] },
|
|
23
|
+
scope: { type: 'string', enum: ['user', 'project'], default: 'user' },
|
|
24
|
+
data: { type: 'object', description: 'The taste data to store' },
|
|
25
|
+
reasoning: { type: 'string', description: 'Why this taste observation matters' },
|
|
26
|
+
project: { type: 'string', description: 'Project name (required if scope is project)' },
|
|
27
|
+
},
|
|
28
|
+
required: ['type', 'data'],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'taste_recall',
|
|
33
|
+
description: 'Semantic search across taste memory',
|
|
34
|
+
inputSchema: {
|
|
35
|
+
type: 'object',
|
|
36
|
+
properties: {
|
|
37
|
+
query: { type: 'string', description: 'Search query' },
|
|
38
|
+
type: { type: 'string', enum: ['palette', 'typography', 'layout', 'texture', 'mood', 'anti-pattern'] },
|
|
39
|
+
scope: { type: 'string', enum: ['user', 'project'] },
|
|
40
|
+
project: { type: 'string' },
|
|
41
|
+
limit: { type: 'number', default: 10 },
|
|
42
|
+
},
|
|
43
|
+
required: ['query'],
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'taste_profile',
|
|
48
|
+
description: 'Get the full taste profile (user-level, project-level, or merged)',
|
|
49
|
+
inputSchema: {
|
|
50
|
+
type: 'object',
|
|
51
|
+
properties: {
|
|
52
|
+
scope: { type: 'string', enum: ['user', 'project', 'merged'] },
|
|
53
|
+
project: { type: 'string', description: 'Project name (required for project/merged scope)' },
|
|
54
|
+
},
|
|
55
|
+
required: ['scope'],
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'taste_decide',
|
|
60
|
+
description: 'Record a design decision with reasoning (what was chosen, what was rejected, and why)',
|
|
61
|
+
inputSchema: {
|
|
62
|
+
type: 'object',
|
|
63
|
+
properties: {
|
|
64
|
+
chosen: { type: 'object', description: 'The chosen option' },
|
|
65
|
+
rejected: { type: 'object', description: 'The rejected option' },
|
|
66
|
+
reason: { type: 'string', description: 'Why this choice was made' },
|
|
67
|
+
project: { type: 'string' },
|
|
68
|
+
},
|
|
69
|
+
required: ['chosen', 'rejected', 'reason'],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'taste_reference',
|
|
74
|
+
description: 'Store analyzed reference image data',
|
|
75
|
+
inputSchema: {
|
|
76
|
+
type: 'object',
|
|
77
|
+
properties: {
|
|
78
|
+
project: { type: 'string' },
|
|
79
|
+
analysis: { type: 'object', description: 'Structured analysis of the reference image' },
|
|
80
|
+
image_path: { type: 'string' },
|
|
81
|
+
},
|
|
82
|
+
required: ['project', 'analysis'],
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'taste_system',
|
|
87
|
+
description: 'Store or retrieve project design system tokens. Pass tokens to store, omit to retrieve.',
|
|
88
|
+
inputSchema: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {
|
|
91
|
+
project: { type: 'string' },
|
|
92
|
+
tokens: { type: 'object', description: 'Design system tokens to store. Omit to retrieve existing.' },
|
|
93
|
+
},
|
|
94
|
+
required: ['project'],
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
}));
|
|
99
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
100
|
+
const { name, arguments: args } = request.params;
|
|
101
|
+
const handler = handlers[name];
|
|
102
|
+
if (!handler) {
|
|
103
|
+
return { content: [{ type: 'text', text: `Unknown tool: ${name}` }] };
|
|
104
|
+
}
|
|
105
|
+
return handler(args);
|
|
106
|
+
});
|
|
107
|
+
async function main() {
|
|
108
|
+
const transport = new StdioServerTransport();
|
|
109
|
+
await server.connect(transport);
|
|
110
|
+
}
|
|
111
|
+
main().catch(console.error);
|
|
112
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { TasteStore } from './store.js';
|
|
2
|
+
import type { TasteProfile } from './types.js';
|
|
3
|
+
type ProfileScope = 'user' | 'project' | 'merged';
|
|
4
|
+
export declare function buildProfile(store: TasteStore, scope: ProfileScope, project?: string): TasteProfile;
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,KAAK,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAElD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,YAAY,EACnB,OAAO,CAAC,EAAE,MAAM,GACf,YAAY,CAwCd"}
|
package/dist/profile.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export function buildProfile(store, scope, project) {
|
|
2
|
+
const profile = {
|
|
3
|
+
palettes: [],
|
|
4
|
+
typography: [],
|
|
5
|
+
layouts: [],
|
|
6
|
+
textures: [],
|
|
7
|
+
moods: [],
|
|
8
|
+
anti_patterns: [],
|
|
9
|
+
decisions: [],
|
|
10
|
+
references: [],
|
|
11
|
+
};
|
|
12
|
+
if (scope === 'user' || scope === 'merged') {
|
|
13
|
+
profile.palettes.push(...store.getEntriesByType('palette', 'user'));
|
|
14
|
+
profile.typography.push(...store.getEntriesByType('typography', 'user'));
|
|
15
|
+
profile.layouts.push(...store.getEntriesByType('layout', 'user'));
|
|
16
|
+
profile.textures.push(...store.getEntriesByType('texture', 'user'));
|
|
17
|
+
profile.moods.push(...store.getEntriesByType('mood', 'user'));
|
|
18
|
+
profile.anti_patterns.push(...store.getEntriesByType('anti-pattern', 'user'));
|
|
19
|
+
}
|
|
20
|
+
if ((scope === 'project' || scope === 'merged') && project) {
|
|
21
|
+
profile.palettes.push(...store.getEntriesByType('palette', 'project', project));
|
|
22
|
+
profile.typography.push(...store.getEntriesByType('typography', 'project', project));
|
|
23
|
+
profile.layouts.push(...store.getEntriesByType('layout', 'project', project));
|
|
24
|
+
profile.textures.push(...store.getEntriesByType('texture', 'project', project));
|
|
25
|
+
profile.moods.push(...store.getEntriesByType('mood', 'project', project));
|
|
26
|
+
profile.anti_patterns.push(...store.getEntriesByType('anti-pattern', 'project', project));
|
|
27
|
+
// Decisions and references are always project-scoped
|
|
28
|
+
const db = store.db;
|
|
29
|
+
profile.decisions = db
|
|
30
|
+
.prepare('SELECT * FROM taste_decisions WHERE project = ? ORDER BY created_at DESC')
|
|
31
|
+
.all(project);
|
|
32
|
+
profile.references = db
|
|
33
|
+
.prepare('SELECT * FROM taste_references WHERE project = ? ORDER BY created_at DESC')
|
|
34
|
+
.all(project);
|
|
35
|
+
}
|
|
36
|
+
return profile;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,YAAY,CAC1B,KAAiB,EACjB,KAAmB,EACnB,OAAgB;IAEhB,MAAM,OAAO,GAAiB;QAC5B,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,EAAE;QACd,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,EAAE;QACZ,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,EAAE;QACjB,SAAS,EAAE,EAAE;QACb,UAAU,EAAE,EAAE;KACf,CAAC;IAEF,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAU,CAAC,CAAC;QAC7E,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,YAAY,EAAE,MAAM,CAAU,CAAC,CAAC;QAClF,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAU,CAAC,CAAC;QAC3E,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAU,CAAC,CAAC;QAC7E,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAU,CAAC,CAAC;QACvE,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,cAAc,EAAE,MAAM,CAAU,CAAC,CAAC;IACzF,CAAC;IAED,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,QAAQ,CAAC,IAAI,OAAO,EAAE,CAAC;QAC3D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAU,CAAC,CAAC;QACzF,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,YAAY,EAAE,SAAS,EAAE,OAAO,CAAU,CAAC,CAAC;QAC9F,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAU,CAAC,CAAC;QACvF,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAU,CAAC,CAAC;QACzF,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAU,CAAC,CAAC;QACnF,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,cAAc,EAAE,SAAS,EAAE,OAAO,CAAU,CAAC,CAAC;QAEnG,qDAAqD;QACrD,MAAM,EAAE,GAAI,KAAa,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,SAAS,GAAG,EAAE;aACnB,OAAO,CAAC,0EAA0E,CAAC;aACnF,GAAG,CAAC,OAAO,CAAC,CAAC;QAChB,OAAO,CAAC,UAAU,GAAG,EAAE;aACpB,OAAO,CAAC,2EAA2E,CAAC;aACpF,GAAG,CAAC,OAAO,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/search.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { TasteType } from './types.js';
|
|
3
|
+
interface SearchOptions {
|
|
4
|
+
type?: TasteType;
|
|
5
|
+
scope?: 'user' | 'project';
|
|
6
|
+
project?: string;
|
|
7
|
+
limit?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare class TasteSearch {
|
|
10
|
+
private db;
|
|
11
|
+
constructor(db: Database.Database);
|
|
12
|
+
textSearch(query: string, opts?: SearchOptions): any[];
|
|
13
|
+
searchDecisions(query: string, project?: string, limit?: number): any[];
|
|
14
|
+
}
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,WAAW;IACV,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAEzC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,GAAG,EAAE;IA+BtD,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,GAAG,EAAE;CAqBpE"}
|
package/dist/search.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { textSimilarity } from './embeddings.js';
|
|
2
|
+
export class TasteSearch {
|
|
3
|
+
db;
|
|
4
|
+
constructor(db) {
|
|
5
|
+
this.db = db;
|
|
6
|
+
}
|
|
7
|
+
textSearch(query, opts) {
|
|
8
|
+
const limit = opts?.limit ?? 10;
|
|
9
|
+
let sql = 'SELECT * FROM taste_entries WHERE 1=1';
|
|
10
|
+
const params = [];
|
|
11
|
+
if (opts?.type) {
|
|
12
|
+
sql += ' AND type = ?';
|
|
13
|
+
params.push(opts.type);
|
|
14
|
+
}
|
|
15
|
+
if (opts?.scope) {
|
|
16
|
+
sql += ' AND scope = ?';
|
|
17
|
+
params.push(opts.scope);
|
|
18
|
+
}
|
|
19
|
+
if (opts?.project) {
|
|
20
|
+
sql += ' AND project = ?';
|
|
21
|
+
params.push(opts.project);
|
|
22
|
+
}
|
|
23
|
+
const rows = this.db.prepare(sql).all(...params);
|
|
24
|
+
return rows
|
|
25
|
+
.map((row) => {
|
|
26
|
+
const searchable = [row.data, row.reasoning ?? ''].join(' ');
|
|
27
|
+
const score = textSimilarity(query, searchable);
|
|
28
|
+
return { ...row, _score: score };
|
|
29
|
+
})
|
|
30
|
+
.filter((r) => r._score > 0)
|
|
31
|
+
.sort((a, b) => b._score - a._score)
|
|
32
|
+
.slice(0, limit);
|
|
33
|
+
}
|
|
34
|
+
searchDecisions(query, project, limit = 10) {
|
|
35
|
+
let sql = 'SELECT * FROM taste_decisions WHERE 1=1';
|
|
36
|
+
const params = [];
|
|
37
|
+
if (project) {
|
|
38
|
+
sql += ' AND project = ?';
|
|
39
|
+
params.push(project);
|
|
40
|
+
}
|
|
41
|
+
const rows = this.db.prepare(sql).all(...params);
|
|
42
|
+
return rows
|
|
43
|
+
.map((row) => {
|
|
44
|
+
const searchable = [row.chosen, row.rejected, row.reason].join(' ');
|
|
45
|
+
const score = textSimilarity(query, searchable);
|
|
46
|
+
return { ...row, _score: score };
|
|
47
|
+
})
|
|
48
|
+
.filter((r) => r._score > 0)
|
|
49
|
+
.sort((a, b) => b._score - a._score)
|
|
50
|
+
.slice(0, limit);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
interface ToolResult {
|
|
2
|
+
content: Array<{
|
|
3
|
+
type: 'text';
|
|
4
|
+
text: string;
|
|
5
|
+
}>;
|
|
6
|
+
}
|
|
7
|
+
export declare function createToolHandlers(dbPath: string): {
|
|
8
|
+
taste_remember(args: {
|
|
9
|
+
type: string;
|
|
10
|
+
scope?: string;
|
|
11
|
+
data: Record<string, unknown>;
|
|
12
|
+
reasoning?: string;
|
|
13
|
+
project?: string;
|
|
14
|
+
}): Promise<ToolResult>;
|
|
15
|
+
taste_recall(args: {
|
|
16
|
+
query: string;
|
|
17
|
+
type?: string;
|
|
18
|
+
scope?: string;
|
|
19
|
+
project?: string;
|
|
20
|
+
limit?: number;
|
|
21
|
+
}): Promise<ToolResult>;
|
|
22
|
+
taste_profile(args: {
|
|
23
|
+
scope: string;
|
|
24
|
+
project?: string;
|
|
25
|
+
}): Promise<ToolResult>;
|
|
26
|
+
taste_decide(args: {
|
|
27
|
+
chosen: Record<string, unknown>;
|
|
28
|
+
rejected: Record<string, unknown>;
|
|
29
|
+
reason: string;
|
|
30
|
+
project?: string;
|
|
31
|
+
}): Promise<ToolResult>;
|
|
32
|
+
taste_reference(args: {
|
|
33
|
+
project: string;
|
|
34
|
+
analysis: Record<string, unknown>;
|
|
35
|
+
image_path?: string;
|
|
36
|
+
}): Promise<ToolResult>;
|
|
37
|
+
taste_system(args: {
|
|
38
|
+
project: string;
|
|
39
|
+
tokens?: Record<string, unknown>;
|
|
40
|
+
}): Promise<ToolResult>;
|
|
41
|
+
};
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAKA,UAAU,UAAU;IAClB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAMD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM;yBAMlB;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,UAAU,CAAC;uBAUE;QACvB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,UAAU,CAAC;wBAyBG;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,UAAU,CAAC;uBAKE;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,UAAU,CAAC;0BAKK;QAC1B,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,UAAU,CAAC;uBAKE;QACvB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,GAAG,OAAO,CAAC,UAAU,CAAC;EAY1B"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createDatabase } from './db.js';
|
|
2
|
+
import { TasteStore } from './store.js';
|
|
3
|
+
import { TasteSearch } from './search.js';
|
|
4
|
+
import { buildProfile } from './profile.js';
|
|
5
|
+
function text(msg) {
|
|
6
|
+
return { content: [{ type: 'text', text: msg }] };
|
|
7
|
+
}
|
|
8
|
+
export function createToolHandlers(dbPath) {
|
|
9
|
+
const db = createDatabase(dbPath);
|
|
10
|
+
const store = new TasteStore(db);
|
|
11
|
+
const search = new TasteSearch(db);
|
|
12
|
+
return {
|
|
13
|
+
async taste_remember(args) {
|
|
14
|
+
const id = store.remember(args.type, (args.scope ?? 'user'), args.data, { project: args.project, reasoning: args.reasoning });
|
|
15
|
+
return text(`Stored ${args.type} entry (id: ${id})`);
|
|
16
|
+
},
|
|
17
|
+
async taste_recall(args) {
|
|
18
|
+
const results = search.textSearch(args.query, {
|
|
19
|
+
type: args.type,
|
|
20
|
+
scope: args.scope,
|
|
21
|
+
project: args.project,
|
|
22
|
+
limit: args.limit,
|
|
23
|
+
});
|
|
24
|
+
if (results.length === 0) {
|
|
25
|
+
return text('No matching taste entries found.');
|
|
26
|
+
}
|
|
27
|
+
const formatted = results.map((r) => ({
|
|
28
|
+
id: r.id,
|
|
29
|
+
type: r.type,
|
|
30
|
+
scope: r.scope,
|
|
31
|
+
project: r.project,
|
|
32
|
+
data: JSON.parse(r.data),
|
|
33
|
+
reasoning: r.reasoning,
|
|
34
|
+
score: r._score,
|
|
35
|
+
}));
|
|
36
|
+
return text(JSON.stringify(formatted, null, 2));
|
|
37
|
+
},
|
|
38
|
+
async taste_profile(args) {
|
|
39
|
+
const profile = buildProfile(store, args.scope, args.project);
|
|
40
|
+
return text(JSON.stringify(profile, null, 2));
|
|
41
|
+
},
|
|
42
|
+
async taste_decide(args) {
|
|
43
|
+
const id = store.decide(args.chosen, args.rejected, args.reason, args.project);
|
|
44
|
+
return text(`Recorded design decision (id: ${id})`);
|
|
45
|
+
},
|
|
46
|
+
async taste_reference(args) {
|
|
47
|
+
const id = store.storeReference(args.project, args.analysis, args.image_path);
|
|
48
|
+
return text(`Stored reference analysis for project "${args.project}" (id: ${id})`);
|
|
49
|
+
},
|
|
50
|
+
async taste_system(args) {
|
|
51
|
+
if (args.tokens) {
|
|
52
|
+
store.storeDesignSystem(args.project, args.tokens);
|
|
53
|
+
return text(`Stored design system tokens for project "${args.project}"`);
|
|
54
|
+
}
|
|
55
|
+
const system = store.getDesignSystem(args.project);
|
|
56
|
+
if (!system) {
|
|
57
|
+
return text(`No design system found for project "${args.project}"`);
|
|
58
|
+
}
|
|
59
|
+
return text(JSON.stringify(JSON.parse(system.tokens), null, 2));
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { TasteType, TasteScope } from './types.js';
|
|
3
|
+
export declare class TasteStore {
|
|
4
|
+
private db;
|
|
5
|
+
constructor(db: Database.Database);
|
|
6
|
+
remember(type: TasteType, scope: TasteScope, data: Record<string, unknown>, opts?: {
|
|
7
|
+
project?: string;
|
|
8
|
+
reasoning?: string;
|
|
9
|
+
}): string;
|
|
10
|
+
getById(id: string): any | undefined;
|
|
11
|
+
getEntriesByType(type: TasteType, scope: TasteScope, project?: string): unknown[];
|
|
12
|
+
decide(chosen: Record<string, unknown>, rejected: Record<string, unknown>, reason: string, project?: string): string;
|
|
13
|
+
getDecision(id: string): any | undefined;
|
|
14
|
+
storeReference(project: string, analysis: Record<string, unknown>, imagePath?: string): string;
|
|
15
|
+
getReference(id: string): any | undefined;
|
|
16
|
+
getReferencesByProject(project: string): unknown[];
|
|
17
|
+
storeDesignSystem(project: string, tokens: Record<string, unknown>): void;
|
|
18
|
+
getDesignSystem(project: string): any | undefined;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExD,qBAAa,UAAU;IACT,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAEzC,QAAQ,CACN,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9C,MAAM;IAWT,OAAO,CAAC,EAAE,EAAE,MAAM,GAC8D,GAAG,GAAG,SAAS;IAG/F,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,MAAM;IAWrE,MAAM,CACJ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,GACf,MAAM;IAWT,WAAW,CAAC,EAAE,EAAE,MAAM,GAC4D,GAAG,GAAG,SAAS;IAGjG,cAAc,CACZ,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM;IAWT,YAAY,CAAC,EAAE,EAAE,MAAM,GAC4D,GAAG,GAAG,SAAS;IAGlG,sBAAsB,CAAC,OAAO,EAAE,MAAM;IAMtC,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAUzE,eAAe,CAAC,OAAO,EAAE,MAAM,GAC4D,GAAG,GAAG,SAAS;CAE3G"}
|
package/dist/store.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
export class TasteStore {
|
|
3
|
+
db;
|
|
4
|
+
constructor(db) {
|
|
5
|
+
this.db = db;
|
|
6
|
+
}
|
|
7
|
+
remember(type, scope, data, opts) {
|
|
8
|
+
const id = randomUUID();
|
|
9
|
+
this.db
|
|
10
|
+
.prepare(`INSERT INTO taste_entries (id, type, scope, project, data, reasoning)
|
|
11
|
+
VALUES (?, ?, ?, ?, ?, ?)`)
|
|
12
|
+
.run(id, type, scope, opts?.project ?? null, JSON.stringify(data), opts?.reasoning ?? null);
|
|
13
|
+
return id;
|
|
14
|
+
}
|
|
15
|
+
getById(id) {
|
|
16
|
+
return this.db.prepare('SELECT * FROM taste_entries WHERE id = ?').get(id);
|
|
17
|
+
}
|
|
18
|
+
getEntriesByType(type, scope, project) {
|
|
19
|
+
if (scope === 'project' && project) {
|
|
20
|
+
return this.db
|
|
21
|
+
.prepare('SELECT * FROM taste_entries WHERE type = ? AND scope = ? AND project = ?')
|
|
22
|
+
.all(type, scope, project);
|
|
23
|
+
}
|
|
24
|
+
return this.db
|
|
25
|
+
.prepare('SELECT * FROM taste_entries WHERE type = ? AND scope = ?')
|
|
26
|
+
.all(type, scope);
|
|
27
|
+
}
|
|
28
|
+
decide(chosen, rejected, reason, project) {
|
|
29
|
+
const id = randomUUID();
|
|
30
|
+
this.db
|
|
31
|
+
.prepare(`INSERT INTO taste_decisions (id, project, chosen, rejected, reason)
|
|
32
|
+
VALUES (?, ?, ?, ?, ?)`)
|
|
33
|
+
.run(id, project ?? null, JSON.stringify(chosen), JSON.stringify(rejected), reason);
|
|
34
|
+
return id;
|
|
35
|
+
}
|
|
36
|
+
getDecision(id) {
|
|
37
|
+
return this.db.prepare('SELECT * FROM taste_decisions WHERE id = ?').get(id);
|
|
38
|
+
}
|
|
39
|
+
storeReference(project, analysis, imagePath) {
|
|
40
|
+
const id = randomUUID();
|
|
41
|
+
this.db
|
|
42
|
+
.prepare(`INSERT INTO taste_references (id, project, image_path, analysis)
|
|
43
|
+
VALUES (?, ?, ?, ?)`)
|
|
44
|
+
.run(id, project, imagePath ?? null, JSON.stringify(analysis));
|
|
45
|
+
return id;
|
|
46
|
+
}
|
|
47
|
+
getReference(id) {
|
|
48
|
+
return this.db.prepare('SELECT * FROM taste_references WHERE id = ?').get(id);
|
|
49
|
+
}
|
|
50
|
+
getReferencesByProject(project) {
|
|
51
|
+
return this.db
|
|
52
|
+
.prepare('SELECT * FROM taste_references WHERE project = ?')
|
|
53
|
+
.all(project);
|
|
54
|
+
}
|
|
55
|
+
storeDesignSystem(project, tokens) {
|
|
56
|
+
this.db
|
|
57
|
+
.prepare(`INSERT INTO design_systems (project, tokens)
|
|
58
|
+
VALUES (?, ?)
|
|
59
|
+
ON CONFLICT(project) DO UPDATE SET tokens = ?, updated_at = datetime('now')`)
|
|
60
|
+
.run(project, JSON.stringify(tokens), JSON.stringify(tokens));
|
|
61
|
+
}
|
|
62
|
+
getDesignSystem(project) {
|
|
63
|
+
return this.db.prepare('SELECT * FROM design_systems WHERE project = ?').get(project);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export type TasteType = 'palette' | 'typography' | 'layout' | 'texture' | 'mood' | 'anti-pattern';
|
|
2
|
+
export type TasteScope = 'user' | 'project';
|
|
3
|
+
export interface TasteEntry {
|
|
4
|
+
id: string;
|
|
5
|
+
type: TasteType;
|
|
6
|
+
scope: TasteScope;
|
|
7
|
+
project?: string;
|
|
8
|
+
data: Record<string, unknown>;
|
|
9
|
+
reasoning?: string;
|
|
10
|
+
created_at: string;
|
|
11
|
+
updated_at: string;
|
|
12
|
+
}
|
|
13
|
+
export interface TasteDecision {
|
|
14
|
+
id: string;
|
|
15
|
+
project?: string;
|
|
16
|
+
chosen: Record<string, unknown>;
|
|
17
|
+
rejected: Record<string, unknown>;
|
|
18
|
+
reason: string;
|
|
19
|
+
created_at: string;
|
|
20
|
+
}
|
|
21
|
+
export interface TasteReference {
|
|
22
|
+
id: string;
|
|
23
|
+
project: string;
|
|
24
|
+
image_path?: string;
|
|
25
|
+
analysis: ReferenceAnalysis;
|
|
26
|
+
created_at: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ReferenceAnalysis {
|
|
29
|
+
colors: {
|
|
30
|
+
dominant: string[];
|
|
31
|
+
secondary: string[];
|
|
32
|
+
accent: string[];
|
|
33
|
+
};
|
|
34
|
+
typography: {
|
|
35
|
+
classification: string;
|
|
36
|
+
subtype?: string;
|
|
37
|
+
weight?: string;
|
|
38
|
+
scale?: string;
|
|
39
|
+
};
|
|
40
|
+
layout: {
|
|
41
|
+
type: string;
|
|
42
|
+
density?: string;
|
|
43
|
+
whitespace_ratio?: string;
|
|
44
|
+
focal_points?: string[];
|
|
45
|
+
};
|
|
46
|
+
texture: {
|
|
47
|
+
effects: string[];
|
|
48
|
+
description?: string;
|
|
49
|
+
};
|
|
50
|
+
mood: string[];
|
|
51
|
+
cultural_context?: {
|
|
52
|
+
movement?: string;
|
|
53
|
+
region?: string;
|
|
54
|
+
era?: string;
|
|
55
|
+
symbols?: string[];
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export interface TasteProfile {
|
|
59
|
+
palettes: TasteEntry[];
|
|
60
|
+
typography: TasteEntry[];
|
|
61
|
+
layouts: TasteEntry[];
|
|
62
|
+
textures: TasteEntry[];
|
|
63
|
+
moods: TasteEntry[];
|
|
64
|
+
anti_patterns: TasteEntry[];
|
|
65
|
+
decisions: TasteDecision[];
|
|
66
|
+
references: TasteReference[];
|
|
67
|
+
}
|
|
68
|
+
export interface DesignSystem {
|
|
69
|
+
project: string;
|
|
70
|
+
colors: Record<string, string>;
|
|
71
|
+
typography: {
|
|
72
|
+
display: {
|
|
73
|
+
family: string;
|
|
74
|
+
weights: number[];
|
|
75
|
+
fallback: string;
|
|
76
|
+
};
|
|
77
|
+
body: {
|
|
78
|
+
family: string;
|
|
79
|
+
weights: number[];
|
|
80
|
+
fallback: string;
|
|
81
|
+
};
|
|
82
|
+
mono?: {
|
|
83
|
+
family: string;
|
|
84
|
+
weights: number[];
|
|
85
|
+
fallback: string;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
scale: {
|
|
89
|
+
ratio: number;
|
|
90
|
+
base: number;
|
|
91
|
+
steps: Record<string, string>;
|
|
92
|
+
};
|
|
93
|
+
spacing: Record<string, string>;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mise-en-scene/taste-memory",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Aesthetic intelligence MCP server — taste memory for AI design agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"mise-en-scene-taste-memory": "dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/daviesayo/mise-en-scene.git",
|
|
18
|
+
"directory": "packages/taste-memory"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/daviesayo/mise-en-scene#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/daviesayo/mise-en-scene/issues"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"keywords": [
|
|
26
|
+
"mise-en-scene",
|
|
27
|
+
"design",
|
|
28
|
+
"mcp",
|
|
29
|
+
"ai",
|
|
30
|
+
"taste",
|
|
31
|
+
"aesthetic-memory"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc",
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"test:watch": "vitest"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
40
|
+
"better-sqlite3": "^11.0.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/better-sqlite3": "^7.6.0",
|
|
44
|
+
"vitest": "^3.0.0"
|
|
45
|
+
}
|
|
46
|
+
}
|