design-brain-memory 0.2.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.
Files changed (47) hide show
  1. package/README.md +167 -0
  2. package/dist/agentBrowser.d.ts +9 -0
  3. package/dist/agentBrowser.js +96 -0
  4. package/dist/agentBrowser.js.map +1 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +212 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands.d.ts +27 -0
  9. package/dist/commands.js +178 -0
  10. package/dist/commands.js.map +1 -0
  11. package/dist/extractFromImage.d.ts +7 -0
  12. package/dist/extractFromImage.js +72 -0
  13. package/dist/extractFromImage.js.map +1 -0
  14. package/dist/extractFromUrl.d.ts +13 -0
  15. package/dist/extractFromUrl.js +605 -0
  16. package/dist/extractFromUrl.js.map +1 -0
  17. package/dist/index.d.ts +3 -0
  18. package/dist/index.js +3 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/interactive.d.ts +3 -0
  21. package/dist/interactive.js +42 -0
  22. package/dist/interactive.js.map +1 -0
  23. package/dist/llm.d.ts +33 -0
  24. package/dist/llm.js +250 -0
  25. package/dist/llm.js.map +1 -0
  26. package/dist/query.d.ts +25 -0
  27. package/dist/query.js +150 -0
  28. package/dist/query.js.map +1 -0
  29. package/dist/render.d.ts +2 -0
  30. package/dist/render.js +365 -0
  31. package/dist/render.js.map +1 -0
  32. package/dist/skillPrompt.d.ts +3 -0
  33. package/dist/skillPrompt.js +66 -0
  34. package/dist/skillPrompt.js.map +1 -0
  35. package/dist/store.d.ts +14 -0
  36. package/dist/store.js +69 -0
  37. package/dist/store.js.map +1 -0
  38. package/dist/svg.d.ts +5 -0
  39. package/dist/svg.js +162 -0
  40. package/dist/svg.js.map +1 -0
  41. package/dist/types.d.ts +175 -0
  42. package/dist/types.js +2 -0
  43. package/dist/types.js.map +1 -0
  44. package/dist/util.d.ts +9 -0
  45. package/dist/util.js +51 -0
  46. package/dist/util.js.map +1 -0
  47. package/package.json +53 -0
@@ -0,0 +1,178 @@
1
+ import path from 'node:path';
2
+ import fs from 'fs-extra';
3
+ import { captureDesignFromImage } from './extractFromImage.js';
4
+ import { captureDesignFromUrl } from './extractFromUrl.js';
5
+ import { enrichWithLlm } from './llm.js';
6
+ import { askDesignBrain, searchDesignBrain } from './query.js';
7
+ import { renderAll } from './render.js';
8
+ import { ensureBrainExists, ensureProject, loadDatabase, projectAssetDir, saveDatabase, } from './store.js';
9
+ import { makeId, normalizeUrl, nowIso, slugify, stableHash, unique } from './util.js';
10
+ function computeFingerprint(input) {
11
+ const basis = {
12
+ url: input.url ? normalizeUrl(input.url) : null,
13
+ topColors: input.analysis.colors.slice(0, 20).map((color) => color.hex.toUpperCase()),
14
+ componentKinds: input.analysis.components.slice(0, 40).map((component) => component.kind),
15
+ layout: input.analysis.layout.slice(0, 20).map((layout) => `${layout.tag}:${layout.role}`),
16
+ motion: input.analysis.motion.slice(0, 20).map((motion) => `${motion.transition}|${motion.animation}`),
17
+ };
18
+ return stableHash(JSON.stringify(basis));
19
+ }
20
+ function buildDiff(previous, next) {
21
+ const previousColors = new Set(previous.analysis.colors.map((color) => color.hex.toUpperCase()));
22
+ const nextColors = new Set(next.colors.map((color) => color.hex.toUpperCase()));
23
+ const addedColors = [...nextColors].filter((color) => !previousColors.has(color)).slice(0, 30);
24
+ const removedColors = [...previousColors].filter((color) => !nextColors.has(color)).slice(0, 30);
25
+ return {
26
+ previousId: previous.id,
27
+ addedColors,
28
+ removedColors,
29
+ componentCountDelta: next.components.length - previous.analysis.components.length,
30
+ motionCountDelta: next.motion.length - previous.analysis.motion.length,
31
+ };
32
+ }
33
+ function resolvePreviousVersion(projectInspirations, fingerprint) {
34
+ const versions = projectInspirations
35
+ .filter((entry) => entry.fingerprint === fingerprint)
36
+ .sort((a, b) => a.capturedAt.localeCompare(b.capturedAt));
37
+ return versions.at(-1);
38
+ }
39
+ function mergeTags(...lists) {
40
+ return unique(lists
41
+ .flat()
42
+ .map((tag) => slugify(tag))
43
+ .filter((tag) => tag.length > 0));
44
+ }
45
+ export async function initBrain(rootDir) {
46
+ await ensureBrainExists(rootDir);
47
+ const db = await loadDatabase(rootDir);
48
+ await renderAll(rootDir, db);
49
+ }
50
+ export async function ingestInspiration(options) {
51
+ if (!options.url && !options.screenshot) {
52
+ throw new Error('Provide either --url or --screenshot');
53
+ }
54
+ if (options.url && options.screenshot) {
55
+ throw new Error('Use either --url or --screenshot, not both');
56
+ }
57
+ await ensureBrainExists(options.rootDir);
58
+ const db = await loadDatabase(options.rootDir);
59
+ const project = ensureProject(db, {
60
+ projectId: options.project,
61
+ projectName: options.projectName,
62
+ description: options.projectDescription,
63
+ });
64
+ const inspirationName = options.name?.trim() || options.url || options.screenshot || 'inspiration';
65
+ const inspirationId = makeId('inspo', inspirationName);
66
+ const assetDir = projectAssetDir(options.rootDir, project.id);
67
+ await fs.ensureDir(assetDir);
68
+ let screenshotPath;
69
+ let analysis;
70
+ if (options.url) {
71
+ screenshotPath = path.join(assetDir, `${inspirationId}.png`);
72
+ const sessionName = `designbrain-${project.id}-${Date.now().toString(36)}`;
73
+ analysis = await captureDesignFromUrl({
74
+ url: options.url,
75
+ sessionName,
76
+ screenshotPath,
77
+ workingDir: options.rootDir,
78
+ journeySteps: options.journeySteps,
79
+ responsiveViewports: options.responsiveViewports,
80
+ });
81
+ }
82
+ else {
83
+ const source = path.resolve(options.rootDir, options.screenshot);
84
+ const ext = path.extname(source) || '.png';
85
+ screenshotPath = path.join(assetDir, `${inspirationId}${ext}`);
86
+ await fs.copy(source, screenshotPath);
87
+ analysis = await captureDesignFromImage({
88
+ imagePath: screenshotPath,
89
+ sourceName: inspirationName,
90
+ notes: options.notes,
91
+ llm: options.llm,
92
+ });
93
+ }
94
+ let llmEnrichment;
95
+ if (options.llm) {
96
+ llmEnrichment = await enrichWithLlm({
97
+ llm: options.llm,
98
+ sourceName: inspirationName,
99
+ sourceUrl: options.url,
100
+ notes: options.notes,
101
+ fallbackSummary: options.inspirationSummary,
102
+ analysis,
103
+ });
104
+ }
105
+ const fingerprint = computeFingerprint({
106
+ url: options.url,
107
+ analysis,
108
+ });
109
+ const previousVersion = resolvePreviousVersion(project.inspirations, fingerprint);
110
+ const version = previousVersion ? previousVersion.version + 1 : 1;
111
+ const mergedTags = mergeTags(options.tags, llmEnrichment?.suggestedTags ?? []);
112
+ const inspirationSummary = options.inspirationSummary
113
+ || llmEnrichment?.summary
114
+ || undefined;
115
+ const record = {
116
+ id: inspirationId,
117
+ name: inspirationName,
118
+ sourceType: options.url ? 'url' : 'screenshot',
119
+ url: options.url,
120
+ originalImagePath: options.screenshot ? path.resolve(options.rootDir, options.screenshot) : undefined,
121
+ screenshotPath,
122
+ capturedAt: nowIso(),
123
+ tags: mergedTags,
124
+ notes: options.notes,
125
+ inspirationSummary,
126
+ llmEnrichment,
127
+ fingerprint,
128
+ version,
129
+ supersedes: previousVersion?.id,
130
+ diffFromPrevious: previousVersion ? buildDiff(previousVersion, analysis) : undefined,
131
+ analysis,
132
+ };
133
+ project.inspirations.push(record);
134
+ project.updatedAt = nowIso();
135
+ await saveDatabase(options.rootDir, db);
136
+ await renderAll(options.rootDir, db, options.skipVisuals);
137
+ return { projectId: project.id, inspirationId };
138
+ }
139
+ export async function recordOutcome(options) {
140
+ if (!options.title.trim()) {
141
+ throw new Error('--title is required');
142
+ }
143
+ if (!options.description.trim()) {
144
+ throw new Error('--description is required');
145
+ }
146
+ await ensureBrainExists(options.rootDir);
147
+ const db = await loadDatabase(options.rootDir);
148
+ const project = ensureProject(db, {
149
+ projectId: options.project,
150
+ });
151
+ const outcomeId = makeId('outcome', options.title);
152
+ const knownInspirationIds = new Set(project.inspirations.map((entry) => entry.id));
153
+ const inspiredBy = options.inspiredBy.filter((id) => knownInspirationIds.has(id));
154
+ project.outcomes.push({
155
+ id: outcomeId,
156
+ title: options.title,
157
+ description: options.description,
158
+ inspiredBy,
159
+ artifactUrl: options.artifactUrl,
160
+ createdAt: nowIso(),
161
+ tags: unique(options.tags.map((tag) => slugify(tag)).filter(Boolean)),
162
+ });
163
+ project.updatedAt = nowIso();
164
+ await saveDatabase(options.rootDir, db);
165
+ await renderAll(options.rootDir, db);
166
+ return { projectId: project.id, outcomeId };
167
+ }
168
+ export async function reindexBrain(rootDir, skipVisuals = false) {
169
+ const db = await loadDatabase(rootDir);
170
+ await renderAll(rootDir, db, skipVisuals);
171
+ }
172
+ export async function searchBrain(params) {
173
+ return searchDesignBrain(params);
174
+ }
175
+ export async function askBrain(params) {
176
+ return askDesignBrain(params);
177
+ }
178
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { DesignAnalysis, LlmConfig } from './types.js';
2
+ export declare function captureDesignFromImage(params: {
3
+ imagePath: string;
4
+ sourceName: string;
5
+ notes?: string;
6
+ llm?: LlmConfig;
7
+ }): Promise<DesignAnalysis>;
@@ -0,0 +1,72 @@
1
+ import fs from 'fs-extra';
2
+ import sharp from 'sharp';
3
+ import { enrichImageWithLlmVision } from './llm.js';
4
+ function channelBucket(value) {
5
+ return Math.max(0, Math.min(255, Math.round(value / 16) * 16));
6
+ }
7
+ function toHex(value) {
8
+ return Math.max(0, Math.min(255, value)).toString(16).padStart(2, '0');
9
+ }
10
+ function collectTopColors(raw, channels) {
11
+ const frequency = new Map();
12
+ for (let i = 0; i < raw.length; i += channels * 4) {
13
+ const r = channelBucket(raw[i] ?? 0);
14
+ const g = channelBucket(raw[i + 1] ?? 0);
15
+ const b = channelBucket(raw[i + 2] ?? 0);
16
+ const hex = `#${toHex(r)}${toHex(g)}${toHex(b)}`;
17
+ const entry = frequency.get(hex) ?? { hex, count: 0, samples: [] };
18
+ entry.count += 1;
19
+ frequency.set(hex, entry);
20
+ }
21
+ return [...frequency.values()]
22
+ .sort((a, b) => b.count - a.count)
23
+ .slice(0, 30)
24
+ .map((token) => ({
25
+ hex: token.hex,
26
+ count: token.count,
27
+ samples: ['image-palette'],
28
+ }));
29
+ }
30
+ export async function captureDesignFromImage(params) {
31
+ await fs.access(params.imagePath);
32
+ const image = sharp(params.imagePath);
33
+ const metadata = await image.metadata();
34
+ const resized = await image
35
+ .resize({ width: 280, height: 280, fit: 'inside', withoutEnlargement: true })
36
+ .removeAlpha()
37
+ .raw()
38
+ .toBuffer({ resolveWithObject: true });
39
+ const colors = collectTopColors(resized.data, resized.info.channels);
40
+ const base = {
41
+ pageTitle: metadata.format ? `Image source (${metadata.format})` : 'Image source',
42
+ pageUrl: undefined,
43
+ viewport: {
44
+ width: metadata.width ?? 0,
45
+ height: metadata.height ?? 0,
46
+ },
47
+ colors,
48
+ typography: [],
49
+ components: [],
50
+ motion: [],
51
+ layout: [],
52
+ cssVariables: {},
53
+ accessibilitySnapshot: undefined,
54
+ };
55
+ if (!params.llm) {
56
+ return base;
57
+ }
58
+ const vision = await enrichImageWithLlmVision({
59
+ llm: params.llm,
60
+ imagePath: params.imagePath,
61
+ sourceName: params.sourceName,
62
+ notes: params.notes,
63
+ });
64
+ return {
65
+ ...base,
66
+ components: vision.components,
67
+ typography: vision.typography,
68
+ motion: vision.motion,
69
+ layout: vision.layout,
70
+ };
71
+ }
72
+ //# sourceMappingURL=extractFromImage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractFromImage.js","sourceRoot":"","sources":["../src/extractFromImage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { DesignAnalysis } from './types.js';
2
+ export declare function captureDesignFromUrl(params: {
3
+ url: string;
4
+ sessionName: string;
5
+ screenshotPath: string;
6
+ workingDir: string;
7
+ journeySteps?: number;
8
+ responsiveViewports?: Array<{
9
+ label: string;
10
+ width: number;
11
+ height: number;
12
+ }>;
13
+ }): Promise<DesignAnalysis>;