stitch-forge 0.3.1

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 (145) hide show
  1. package/.claude/skills/forge-build/SKILL.md +79 -0
  2. package/.claude/skills/forge-design/SKILL.md +64 -0
  3. package/.claude/skills/forge-discover/SKILL.md +139 -0
  4. package/.claude/skills/forge-generate/SKILL.md +77 -0
  5. package/.claude/skills/forge-preview/SKILL.md +26 -0
  6. package/.claude/skills/forge-research/SKILL.md +42 -0
  7. package/.claude/skills/forge-sync/SKILL.md +45 -0
  8. package/DESIGN.md +113 -0
  9. package/LICENSE +21 -0
  10. package/README.es.md +242 -0
  11. package/README.md +242 -0
  12. package/dist/adapters/astro.d.ts +8 -0
  13. package/dist/adapters/astro.js +24 -0
  14. package/dist/adapters/astro.js.map +1 -0
  15. package/dist/adapters/index.d.ts +3 -0
  16. package/dist/adapters/index.js +9 -0
  17. package/dist/adapters/index.js.map +1 -0
  18. package/dist/adapters/nextjs.d.ts +7 -0
  19. package/dist/adapters/nextjs.js +136 -0
  20. package/dist/adapters/nextjs.js.map +1 -0
  21. package/dist/adapters/static.d.ts +7 -0
  22. package/dist/adapters/static.js +43 -0
  23. package/dist/adapters/static.js.map +1 -0
  24. package/dist/adapters/types.d.ts +22 -0
  25. package/dist/adapters/types.js +6 -0
  26. package/dist/adapters/types.js.map +1 -0
  27. package/dist/commands/build.d.ts +7 -0
  28. package/dist/commands/build.js +98 -0
  29. package/dist/commands/build.js.map +1 -0
  30. package/dist/commands/design.d.ts +3 -0
  31. package/dist/commands/design.js +39 -0
  32. package/dist/commands/design.js.map +1 -0
  33. package/dist/commands/discover.d.ts +9 -0
  34. package/dist/commands/discover.js +91 -0
  35. package/dist/commands/discover.js.map +1 -0
  36. package/dist/commands/generate.d.ts +7 -0
  37. package/dist/commands/generate.js +105 -0
  38. package/dist/commands/generate.js.map +1 -0
  39. package/dist/commands/init.d.ts +1 -0
  40. package/dist/commands/init.js +99 -0
  41. package/dist/commands/init.js.map +1 -0
  42. package/dist/commands/preview.d.ts +5 -0
  43. package/dist/commands/preview.js +41 -0
  44. package/dist/commands/preview.js.map +1 -0
  45. package/dist/commands/research.d.ts +1 -0
  46. package/dist/commands/research.js +38 -0
  47. package/dist/commands/research.js.map +1 -0
  48. package/dist/commands/sync.d.ts +1 -0
  49. package/dist/commands/sync.js +53 -0
  50. package/dist/commands/sync.js.map +1 -0
  51. package/dist/commands/workflow.d.ts +1 -0
  52. package/dist/commands/workflow.js +38 -0
  53. package/dist/commands/workflow.js.map +1 -0
  54. package/dist/index.d.ts +2 -0
  55. package/dist/index.js +113 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/mcp/auth.d.ts +15 -0
  58. package/dist/mcp/auth.js +56 -0
  59. package/dist/mcp/auth.js.map +1 -0
  60. package/dist/mcp/client.d.ts +65 -0
  61. package/dist/mcp/client.js +302 -0
  62. package/dist/mcp/client.js.map +1 -0
  63. package/dist/mcp/tools.d.ts +26 -0
  64. package/dist/mcp/tools.js +46 -0
  65. package/dist/mcp/tools.js.map +1 -0
  66. package/dist/research/business-researcher.d.ts +41 -0
  67. package/dist/research/business-researcher.js +888 -0
  68. package/dist/research/business-researcher.js.map +1 -0
  69. package/dist/research/crawler.d.ts +11 -0
  70. package/dist/research/crawler.js +56 -0
  71. package/dist/research/crawler.js.map +1 -0
  72. package/dist/research/design-synthesizer.d.ts +46 -0
  73. package/dist/research/design-synthesizer.js +628 -0
  74. package/dist/research/design-synthesizer.js.map +1 -0
  75. package/dist/research/differ.d.ts +19 -0
  76. package/dist/research/differ.js +58 -0
  77. package/dist/research/differ.js.map +1 -0
  78. package/dist/research/known-state.json +68 -0
  79. package/dist/research/research-cache.d.ts +6 -0
  80. package/dist/research/research-cache.js +62 -0
  81. package/dist/research/research-cache.js.map +1 -0
  82. package/dist/research/types.d.ts +98 -0
  83. package/dist/research/types.js +6 -0
  84. package/dist/research/types.js.map +1 -0
  85. package/dist/research/updater.d.ts +5 -0
  86. package/dist/research/updater.js +43 -0
  87. package/dist/research/updater.js.map +1 -0
  88. package/dist/templates/design-md.d.ts +52 -0
  89. package/dist/templates/design-md.js +315 -0
  90. package/dist/templates/design-md.js.map +1 -0
  91. package/dist/templates/prompts.d.ts +31 -0
  92. package/dist/templates/prompts.js +39 -0
  93. package/dist/templates/prompts.js.map +1 -0
  94. package/dist/templates/workflows.d.ts +9 -0
  95. package/dist/templates/workflows.js +21 -0
  96. package/dist/templates/workflows.js.map +1 -0
  97. package/dist/tui/App.d.ts +1 -0
  98. package/dist/tui/App.js +87 -0
  99. package/dist/tui/App.js.map +1 -0
  100. package/dist/tui/Dashboard.d.ts +5 -0
  101. package/dist/tui/Dashboard.js +23 -0
  102. package/dist/tui/Dashboard.js.map +1 -0
  103. package/dist/tui/DesignEditor.d.ts +6 -0
  104. package/dist/tui/DesignEditor.js +76 -0
  105. package/dist/tui/DesignEditor.js.map +1 -0
  106. package/dist/tui/PromptBuilder.d.ts +5 -0
  107. package/dist/tui/PromptBuilder.js +102 -0
  108. package/dist/tui/PromptBuilder.js.map +1 -0
  109. package/dist/tui/components/QuotaMeter.d.ts +8 -0
  110. package/dist/tui/components/QuotaMeter.js +10 -0
  111. package/dist/tui/components/QuotaMeter.js.map +1 -0
  112. package/dist/tui/components/ScreenCard.d.ts +7 -0
  113. package/dist/tui/components/ScreenCard.js +6 -0
  114. package/dist/tui/components/ScreenCard.js.map +1 -0
  115. package/dist/tui/components/Spinner.d.ts +5 -0
  116. package/dist/tui/components/Spinner.js +7 -0
  117. package/dist/tui/components/Spinner.js.map +1 -0
  118. package/dist/tui/components/StatusBar.d.ts +7 -0
  119. package/dist/tui/components/StatusBar.js +6 -0
  120. package/dist/tui/components/StatusBar.js.map +1 -0
  121. package/dist/utils/config.d.ts +26 -0
  122. package/dist/utils/config.js +66 -0
  123. package/dist/utils/config.js.map +1 -0
  124. package/dist/utils/design-validator.d.ts +44 -0
  125. package/dist/utils/design-validator.js +396 -0
  126. package/dist/utils/design-validator.js.map +1 -0
  127. package/dist/utils/logger.d.ts +8 -0
  128. package/dist/utils/logger.js +10 -0
  129. package/dist/utils/logger.js.map +1 -0
  130. package/dist/utils/output-validator.d.ts +18 -0
  131. package/dist/utils/output-validator.js +194 -0
  132. package/dist/utils/output-validator.js.map +1 -0
  133. package/dist/utils/preview.d.ts +4 -0
  134. package/dist/utils/preview.js +49 -0
  135. package/dist/utils/preview.js.map +1 -0
  136. package/dist/utils/prompt-enhancer.d.ts +21 -0
  137. package/dist/utils/prompt-enhancer.js +104 -0
  138. package/dist/utils/prompt-enhancer.js.map +1 -0
  139. package/dist/utils/quota.d.ts +18 -0
  140. package/dist/utils/quota.js +49 -0
  141. package/dist/utils/quota.js.map +1 -0
  142. package/dist/utils/validators.d.ts +125 -0
  143. package/dist/utils/validators.js +110 -0
  144. package/dist/utils/validators.js.map +1 -0
  145. package/package.json +77 -0
@@ -0,0 +1,19 @@
1
+ import type { CrawlResult } from './crawler.js';
2
+ export interface DiffResult {
3
+ hasChanges: boolean;
4
+ changes: Change[];
5
+ }
6
+ export interface Change {
7
+ category: 'models' | 'tools' | 'exports' | 'features' | 'limits' | 'other';
8
+ description: string;
9
+ severity: 'info' | 'warning' | 'breaking';
10
+ source: string;
11
+ }
12
+ /**
13
+ * Compare crawled content against known state to detect changes.
14
+ * Uses keyword matching — not perfect, but catches major changes.
15
+ *
16
+ * For Claude Code usage, the /research slash command uses web search
17
+ * instead of crawling, which is more reliable.
18
+ */
19
+ export declare function diffAgainstKnownState(crawlResults: CrawlResult[], knownState: Record<string, unknown>): DiffResult;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Compare crawled content against known state to detect changes.
3
+ * Uses keyword matching — not perfect, but catches major changes.
4
+ *
5
+ * For Claude Code usage, the /research slash command uses web search
6
+ * instead of crawling, which is more reliable.
7
+ */
8
+ export function diffAgainstKnownState(crawlResults, knownState) {
9
+ const changes = [];
10
+ const allContent = crawlResults.map(r => r.content).join(' ').toLowerCase();
11
+ // Check for new model mentions
12
+ const modelPatterns = [
13
+ { pattern: /gemini\s*4/i, desc: 'New Gemini 4 model detected' },
14
+ { pattern: /gemini\s*3\.5/i, desc: 'New Gemini 3.5 model detected' },
15
+ ];
16
+ for (const { pattern, desc } of modelPatterns) {
17
+ if (pattern.test(allContent)) {
18
+ changes.push({ category: 'models', description: desc, severity: 'warning', source: 'docs' });
19
+ }
20
+ }
21
+ // Check for new export options
22
+ const exportPatterns = [
23
+ { pattern: /export.*figma/i, exists: true },
24
+ { pattern: /export.*react/i, desc: 'React export option detected' },
25
+ { pattern: /export.*flutter/i, desc: 'Flutter export option detected' },
26
+ ];
27
+ for (const { pattern, desc } of exportPatterns) {
28
+ if (desc && pattern.test(allContent)) {
29
+ changes.push({ category: 'exports', description: desc, severity: 'info', source: 'docs' });
30
+ }
31
+ }
32
+ // Check for quota changes
33
+ if (/quota|limit|generation/i.test(allContent)) {
34
+ const quotaMatch = allContent.match(/(\d+)\s*generation/i);
35
+ if (quotaMatch) {
36
+ const mentioned = parseInt(quotaMatch[1]);
37
+ if (mentioned !== 350 && mentioned !== 50) {
38
+ changes.push({
39
+ category: 'limits',
40
+ description: `Possible quota change detected: ${mentioned} generations mentioned`,
41
+ severity: 'warning',
42
+ source: 'docs',
43
+ });
44
+ }
45
+ }
46
+ }
47
+ // Check for deprecated features
48
+ if (/deprecat|removed|no longer/i.test(allContent)) {
49
+ changes.push({
50
+ category: 'features',
51
+ description: 'Possible deprecation notice detected — review manually',
52
+ severity: 'breaking',
53
+ source: 'docs',
54
+ });
55
+ }
56
+ return { hasChanges: changes.length > 0, changes };
57
+ }
58
+ //# sourceMappingURL=differ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"differ.js","sourceRoot":"","sources":["../../src/research/differ.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,YAA2B,EAC3B,UAAmC;IAEnC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAE5E,+BAA+B;IAC/B,MAAM,aAAa,GAAG;QACpB,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,6BAA6B,EAAE;QAC/D,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,+BAA+B,EAAE;KACrE,CAAC;IACF,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,aAAa,EAAE,CAAC;QAC9C,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IAED,+BAA+B;IAC/B,MAAM,cAAc,GAAG;QACrB,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,EAAE;QAC3C,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,8BAA8B,EAAE;QACnE,EAAE,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,gCAAgC,EAAE;KACxE,CAAC;IACF,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,cAAc,EAAE,CAAC;QAC/C,IAAI,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,IAAI,yBAAyB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/C,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAC3D,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,SAAS,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,EAAE,EAAE,CAAC;gBAC1C,OAAO,CAAC,IAAI,CAAC;oBACX,QAAQ,EAAE,QAAQ;oBAClB,WAAW,EAAE,mCAAmC,SAAS,wBAAwB;oBACjF,QAAQ,EAAE,SAAS;oBACnB,MAAM,EAAE,MAAM;iBACf,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,IAAI,6BAA6B,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC;YACX,QAAQ,EAAE,UAAU;YACpB,WAAW,EAAE,wDAAwD;YACrE,QAAQ,EAAE,UAAU;YACpB,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC"}
@@ -0,0 +1,68 @@
1
+ {
2
+ "lastUpdated": "2026-04-11T00:00:00Z",
3
+ "models": [
4
+ { "id": "GEMINI_3_PRO", "quotaMonthly": 200, "notes": "Highest quality, complex screens, image input" },
5
+ { "id": "GEMINI_2_5_FLASH", "quotaMonthly": 350, "notes": "Fast iteration" }
6
+ ],
7
+ "exportOptions": ["figma", "html_css_tailwind", "ai_studio", "antigravity"],
8
+ "mcpEndpoint": "https://stitch.googleapis.com/mcp",
9
+ "mcpTools": [
10
+ "list_projects",
11
+ "get_project",
12
+ "generate_screen_from_text",
13
+ "list_screens",
14
+ "get_screen",
15
+ "create_project",
16
+ "list_design_systems",
17
+ "create_design_system",
18
+ "update_design_system",
19
+ "apply_design_system",
20
+ "edit_screens",
21
+ "generate_variants"
22
+ ],
23
+ "proxyTools": [
24
+ "get_screen_code",
25
+ "get_screen_image",
26
+ "build_site"
27
+ ],
28
+ "authMethods": ["api_key", "gcloud_oauth", "system_gcloud"],
29
+ "designMdSections": 8,
30
+ "promptMaxChars": 5000,
31
+ "features": {
32
+ "infiniteCanvas": true,
33
+ "voiceCanvas": true,
34
+ "vibeDesign": true,
35
+ "fiveScreenCanvas": true,
36
+ "directEdits": true,
37
+ "interactivePrototypes": true,
38
+ "designDnaExtraction": true,
39
+ "urlDesignExtraction": true,
40
+ "screenStitching": true,
41
+ "designAgent": true,
42
+ "designMdImportExport": true
43
+ },
44
+ "knownLimitations": [
45
+ "No JS-heavy interactive pages — static UI only",
46
+ "Login-walled URLs fail design extraction",
47
+ "Long prompts (>5000 chars) cause component omissions",
48
+ "Multiple changes in one prompt causes full redesign instead of edit",
49
+ "No production code output — starting point only",
50
+ "Precision control limited — positional instructions interpreted variably",
51
+ "Repetitive layouts — defaults to limited set of layout structures",
52
+ "WCAG accessibility — frequently fails compliance",
53
+ "Not responsive by default — manual adaptation for breakpoints needed",
54
+ "Figma export unavailable in Pro/Experimental mode"
55
+ ],
56
+ "officialSdk": {
57
+ "package": "@google/stitch-sdk",
58
+ "repo": "github.com/google-labs-code/stitch-sdk"
59
+ },
60
+ "officialSkills": {
61
+ "repo": "github.com/google-labs-code/stitch-skills",
62
+ "skills": ["stitch-design", "stitch-loop", "design-md", "enhance-prompt", "react-components", "remotion", "shadcn-ui"]
63
+ },
64
+ "thirdPartyMcpServers": [
65
+ { "package": "@_davideast/stitch-mcp", "source": "npm", "type": "cli+proxy" },
66
+ { "package": "stitch-mcp", "author": "kargatharaakash", "source": "npm", "type": "oauth" }
67
+ ]
68
+ }
@@ -0,0 +1,6 @@
1
+ import type { BusinessResearchResult, SiteAnalysis } from './types.js';
2
+ export declare function isCacheValid(cachedAt: string, ttlDays?: number): boolean;
3
+ export declare function cacheResearch(companyName: string, result: BusinessResearchResult): void;
4
+ export declare function getCachedResearch(companyName: string): BusinessResearchResult | null;
5
+ export declare function cacheSiteAnalysis(url: string, analysis: SiteAnalysis): void;
6
+ export declare function getCachedSiteAnalysis(url: string): SiteAnalysis | null;
@@ -0,0 +1,62 @@
1
+ import { mkdirSync, writeFileSync, readFileSync, existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { createHash } from 'node:crypto';
4
+ const CACHE_DIR = '.forge-research';
5
+ const CACHE_TTL_DAYS = 7;
6
+ function ensureCacheDir() {
7
+ const dir = join(process.cwd(), CACHE_DIR);
8
+ if (!existsSync(dir))
9
+ mkdirSync(dir, { recursive: true });
10
+ return dir;
11
+ }
12
+ function hashKey(key) {
13
+ return createHash('md5').update(key).digest('hex').slice(0, 12);
14
+ }
15
+ export function isCacheValid(cachedAt, ttlDays = CACHE_TTL_DAYS) {
16
+ const cached = new Date(cachedAt).getTime();
17
+ const now = Date.now();
18
+ return (now - cached) < ttlDays * 24 * 60 * 60 * 1000;
19
+ }
20
+ export function cacheResearch(companyName, result) {
21
+ const dir = ensureCacheDir();
22
+ writeFileSync(join(dir, 'latest.json'), JSON.stringify(result, null, 2) + '\n');
23
+ writeFileSync(join(dir, `${hashKey(companyName)}.json`), JSON.stringify(result, null, 2) + '\n');
24
+ }
25
+ export function getCachedResearch(companyName) {
26
+ const dir = join(process.cwd(), CACHE_DIR);
27
+ const file = join(dir, `${hashKey(companyName)}.json`);
28
+ if (!existsSync(file))
29
+ return null;
30
+ try {
31
+ const data = JSON.parse(readFileSync(file, 'utf-8'));
32
+ if (isCacheValid(data.researchedAt))
33
+ return data;
34
+ return null;
35
+ }
36
+ catch {
37
+ return null;
38
+ }
39
+ }
40
+ export function cacheSiteAnalysis(url, analysis) {
41
+ const dir = ensureCacheDir();
42
+ const sitesDir = join(dir, 'sites');
43
+ if (!existsSync(sitesDir))
44
+ mkdirSync(sitesDir, { recursive: true });
45
+ writeFileSync(join(sitesDir, `${hashKey(url)}.json`), JSON.stringify(analysis, null, 2) + '\n');
46
+ }
47
+ export function getCachedSiteAnalysis(url) {
48
+ const dir = join(process.cwd(), CACHE_DIR, 'sites');
49
+ const file = join(dir, `${hashKey(url)}.json`);
50
+ if (!existsSync(file))
51
+ return null;
52
+ try {
53
+ const data = JSON.parse(readFileSync(file, 'utf-8'));
54
+ if (isCacheValid(data.fetchedAt))
55
+ return data;
56
+ return null;
57
+ }
58
+ catch {
59
+ return null;
60
+ }
61
+ }
62
+ //# sourceMappingURL=research-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"research-cache.js","sourceRoot":"","sources":["../../src/research/research-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Shared types for the Design Intelligence Agent pipeline.
3
+ * Used by: business-researcher, design-synthesizer, design-validator, discover command.
4
+ */
5
+ export interface BusinessBrief {
6
+ companyName: string;
7
+ industry: string;
8
+ targetAudience: string;
9
+ aesthetic: string;
10
+ websiteUrl?: string;
11
+ competitorUrls?: string[];
12
+ locale?: string;
13
+ }
14
+ export interface ExtractedColor {
15
+ hex: string;
16
+ frequency: number;
17
+ context: 'background' | 'text' | 'accent' | 'border' | 'unknown';
18
+ }
19
+ export interface ExtractedPalette {
20
+ colors: ExtractedColor[];
21
+ dominantHex: string;
22
+ accentHex?: string;
23
+ }
24
+ export interface ExtractedTypography {
25
+ fonts: string[];
26
+ headingFont?: string;
27
+ bodyFont?: string;
28
+ }
29
+ export interface SiteAnalysis {
30
+ url: string;
31
+ palette: ExtractedPalette;
32
+ typography: ExtractedTypography;
33
+ layoutPatterns: string[];
34
+ contentTone: 'formal' | 'casual' | 'technical' | 'warm' | 'neutral';
35
+ navItems: string[];
36
+ ctaTexts: string[];
37
+ fetchedAt: string;
38
+ }
39
+ export interface CompetitorAnalysis {
40
+ url: string;
41
+ name: string;
42
+ palette: ExtractedPalette;
43
+ typography: ExtractedTypography;
44
+ strengths: string[];
45
+ commonPatterns: string[];
46
+ fetchedAt: string;
47
+ }
48
+ export interface AudienceInsight {
49
+ trustSignals: string[];
50
+ accessibilityNeeds: string[];
51
+ culturalConsiderations: string[];
52
+ expectations: string[];
53
+ }
54
+ export interface MarketPosition {
55
+ pricePoint: 'budget' | 'mid-range' | 'premium' | 'luxury';
56
+ reach: 'local' | 'regional' | 'national' | 'global';
57
+ personality: 'traditional' | 'modern' | 'innovative' | 'disruptive';
58
+ }
59
+ export interface BusinessModelContext {
60
+ type: 'physical-retail' | 'e-commerce' | 'saas' | 'marketplace' | 'service' | 'media' | 'nonprofit' | 'other';
61
+ primaryRevenue: string;
62
+ websitePurpose: string;
63
+ primaryUserGoals: string[];
64
+ keyFeatures: string[];
65
+ notFeatures: string[];
66
+ differentiators: string[];
67
+ confidence: number;
68
+ }
69
+ export interface BusinessResearchResult {
70
+ brief: BusinessBrief;
71
+ businessModel: BusinessModelContext;
72
+ currentSite?: SiteAnalysis;
73
+ competitors: CompetitorAnalysis[];
74
+ audienceInsights: AudienceInsight;
75
+ marketPosition: MarketPosition;
76
+ researchedAt: string;
77
+ confidence: number;
78
+ fallbacksUsed: string[];
79
+ }
80
+ export interface DesignQualityIssue {
81
+ section: string;
82
+ severity: 'error' | 'warning' | 'info';
83
+ message: string;
84
+ }
85
+ export interface DesignQualityScore {
86
+ specificity: number;
87
+ differentiation: number;
88
+ completeness: number;
89
+ actionability: number;
90
+ total: number;
91
+ issues: DesignQualityIssue[];
92
+ }
93
+ export interface SynthesizedDesign {
94
+ markdown: string;
95
+ tokenEstimate: number;
96
+ qualityScore: DesignQualityScore;
97
+ sources: string[];
98
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Shared types for the Design Intelligence Agent pipeline.
3
+ * Used by: business-researcher, design-synthesizer, design-validator, discover command.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/research/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,5 @@
1
+ import type { Change } from './differ.js';
2
+ export declare function getKnownState(): Record<string, unknown>;
3
+ export declare function updateKnownState(changes: Change[]): void;
4
+ export declare function getLastUpdated(): Date;
5
+ export declare function isStale(thresholdDays?: number): boolean;
@@ -0,0 +1,43 @@
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ import { join, dirname } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ const __dirname = dirname(fileURLToPath(import.meta.url));
5
+ const KNOWN_STATE_PATH = join(__dirname, 'known-state.json');
6
+ export function getKnownState() {
7
+ const raw = readFileSync(KNOWN_STATE_PATH, 'utf-8');
8
+ return JSON.parse(raw);
9
+ }
10
+ export function updateKnownState(changes) {
11
+ const state = getKnownState();
12
+ state.lastUpdated = new Date().toISOString();
13
+ if (!Array.isArray(state.detectedChanges)) {
14
+ state.detectedChanges = [];
15
+ }
16
+ const existing = state.detectedChanges;
17
+ for (const change of changes) {
18
+ const isDuplicate = existing.some(e => e.category === change.category && e.description === change.description);
19
+ if (!isDuplicate) {
20
+ existing.push({
21
+ date: new Date().toISOString(),
22
+ ...change,
23
+ });
24
+ }
25
+ }
26
+ // Keep only the last 50 changes
27
+ if (existing.length > 50) {
28
+ state.detectedChanges = existing.slice(-50);
29
+ }
30
+ writeFileSync(KNOWN_STATE_PATH, JSON.stringify(state, null, 2) + '\n');
31
+ }
32
+ export function getLastUpdated() {
33
+ const state = getKnownState();
34
+ return new Date(state.lastUpdated);
35
+ }
36
+ export function isStale(thresholdDays = 30) {
37
+ const lastUpdated = getLastUpdated();
38
+ const now = new Date();
39
+ const diffMs = now.getTime() - lastUpdated.getTime();
40
+ const diffDays = diffMs / (1000 * 60 * 60 * 24);
41
+ return diffDays > thresholdDays;
42
+ }
43
+ //# sourceMappingURL=updater.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updater.js","sourceRoot":"","sources":["../../src/research/updater.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAE7D,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IACpD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAiB;IAChD,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,KAAK,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE7C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC;QAC1C,KAAK,CAAC,eAAe,GAAG,EAAE,CAAC;IAC7B,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,eAA+F,CAAC;IAEvH,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAC/B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,WAAW,KAAK,MAAM,CAAC,WAAW,CAC5E,CAAC;QACF,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC9B,GAAG,MAAM;aACV,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,IAAI,QAAQ,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACzB,KAAK,CAAC,eAAe,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,WAAqB,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,aAAa,GAAG,EAAE;IACxC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC;IACrD,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAChD,OAAO,QAAQ,GAAG,aAAa,CAAC;AAClC,CAAC"}
@@ -0,0 +1,52 @@
1
+ export interface DesignBrief {
2
+ companyName: string;
3
+ industry: string;
4
+ targetAudience: string;
5
+ aesthetic: string;
6
+ primaryColor?: string;
7
+ secondaryColor?: string;
8
+ }
9
+ export interface IndustryPalette {
10
+ primary: {
11
+ name: string;
12
+ hex: string;
13
+ };
14
+ secondary: {
15
+ name: string;
16
+ hex: string;
17
+ };
18
+ accent?: {
19
+ name: string;
20
+ hex: string;
21
+ };
22
+ }
23
+ export declare const INDUSTRY_PALETTES: Record<string, IndustryPalette>;
24
+ export declare function matchIndustry(industry: string): IndustryPalette;
25
+ export interface AestheticModifier {
26
+ surface: {
27
+ name: string;
28
+ hex: string;
29
+ };
30
+ onSurface: {
31
+ name: string;
32
+ hex: string;
33
+ };
34
+ muted: {
35
+ name: string;
36
+ hex: string;
37
+ };
38
+ headingFont: string;
39
+ bodyFont: string;
40
+ monoFont: string;
41
+ iconStyle: string;
42
+ borderRadius: string;
43
+ shadowStyle: string;
44
+ }
45
+ export declare const AESTHETIC_MODIFIERS: Record<string, AestheticModifier>;
46
+ export declare function matchAesthetic(aesthetic: string): AestheticModifier;
47
+ export declare function generateImageryGuidelines(industry: string, audience: string): string;
48
+ export declare function generateDosAndDonts(industry: string, audience: string): {
49
+ dos: string[];
50
+ donts: string[];
51
+ };
52
+ export declare function generateDesignMdTemplate(brief: DesignBrief): string;