@design-ai/cli 4.55.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/.claude-plugin/plugin.json +164 -0
- package/AGENTS.ko.md +126 -0
- package/AGENTS.md +182 -0
- package/CHANGELOG.md +6883 -0
- package/CLAUDE.md +39 -0
- package/LICENSE +21 -0
- package/README.ko.md +245 -0
- package/README.md +277 -0
- package/agents/README.md +14 -0
- package/agents/a11y-reviewer.md +121 -0
- package/agents/component-architect.md +57 -0
- package/agents/design-critic.md +46 -0
- package/agents/token-extractor.md +63 -0
- package/cli/bin/design-ai-mcp.mjs +6 -0
- package/cli/bin/design-ai.mjs +40 -0
- package/cli/commands/audit.mjs +111 -0
- package/cli/commands/check.mjs +226 -0
- package/cli/commands/doctor.mjs +141 -0
- package/cli/commands/examples.mjs +58 -0
- package/cli/commands/help.mjs +271 -0
- package/cli/commands/install.mjs +161 -0
- package/cli/commands/learn.mjs +1871 -0
- package/cli/commands/list.mjs +143 -0
- package/cli/commands/mcp.mjs +27 -0
- package/cli/commands/pack.mjs +211 -0
- package/cli/commands/prompt.mjs +199 -0
- package/cli/commands/route.mjs +247 -0
- package/cli/commands/search.mjs +60 -0
- package/cli/commands/show.mjs +52 -0
- package/cli/commands/site.mjs +558 -0
- package/cli/commands/status.mjs +161 -0
- package/cli/commands/uninstall.mjs +119 -0
- package/cli/commands/update.mjs +184 -0
- package/cli/commands/version.mjs +94 -0
- package/cli/commands/workspace.mjs +176 -0
- package/cli/lib/brief.mjs +52 -0
- package/cli/lib/check.mjs +642 -0
- package/cli/lib/dispatch.mjs +109 -0
- package/cli/lib/doctor.mjs +505 -0
- package/cli/lib/examples.mjs +258 -0
- package/cli/lib/exec.mjs +63 -0
- package/cli/lib/help-flags.mjs +5 -0
- package/cli/lib/learn.mjs +3694 -0
- package/cli/lib/log.mjs +47 -0
- package/cli/lib/mcp-server.mjs +426 -0
- package/cli/lib/output.mjs +101 -0
- package/cli/lib/pack.mjs +599 -0
- package/cli/lib/paths.mjs +63 -0
- package/cli/lib/prompt.mjs +603 -0
- package/cli/lib/route.mjs +740 -0
- package/cli/lib/search.mjs +158 -0
- package/cli/lib/show.mjs +161 -0
- package/cli/lib/signals.mjs +2337 -0
- package/cli/lib/site.mjs +6617 -0
- package/cli/lib/skill-proposals.mjs +2046 -0
- package/cli/lib/suggest.mjs +66 -0
- package/cli/lib/workspace.mjs +1056 -0
- package/commands/README.md +25 -0
- package/commands/component-spec.md +34 -0
- package/commands/conversational.md +44 -0
- package/commands/design-from-brief.md +141 -0
- package/commands/design-review.md +62 -0
- package/commands/document-from-brief.md +47 -0
- package/commands/extract-tokens.md +38 -0
- package/commands/game-ui.md +40 -0
- package/commands/illustration.md +37 -0
- package/commands/iterate.md +167 -0
- package/commands/motion-design.md +54 -0
- package/commands/palette-from-brand.md +50 -0
- package/commands/print.md +49 -0
- package/commands/slide-deck.md +46 -0
- package/commands/spatial.md +47 -0
- package/commands/stability-review.md +74 -0
- package/commands/video.md +42 -0
- package/commands/website-improvement.md +77 -0
- package/docs/AGENT-DEVELOPMENT.md +658 -0
- package/docs/AI-LEARNING.md +429 -0
- package/docs/AIDER-INTEGRATION.md +224 -0
- package/docs/ARCHITECTURE.ko.md +183 -0
- package/docs/ARCHITECTURE.md +105 -0
- package/docs/CODEX-INTEGRATION.md +311 -0
- package/docs/COMPANY-WEBSITE-DOGFOOD.ko.md +144 -0
- package/docs/COMPANY-WEBSITE-DOGFOOD.md +150 -0
- package/docs/COMPANY-WEBSITE-INTAKE-TEMPLATE.ko.md +153 -0
- package/docs/COMPANY-WEBSITE-INTAKE-TEMPLATE.md +154 -0
- package/docs/CONTRIBUTING.ko.md +203 -0
- package/docs/CONTRIBUTING.md +242 -0
- package/docs/CURSOR-INTEGRATION.md +220 -0
- package/docs/DISTRIBUTION.ko.md +248 -0
- package/docs/DISTRIBUTION.md +253 -0
- package/docs/DOGFOOD-FINDINGS.md +180 -0
- package/docs/DOGFOOD-V4-FINDINGS.md +139 -0
- package/docs/DOGFOOD-V4-MKDOCS-FINDINGS.md +233 -0
- package/docs/DOGFOOD-V4-NPM-FINDINGS.md +157 -0
- package/docs/DOGFOOD-V4-VSCODE-FINDINGS.md +135 -0
- package/docs/FIGMA-INTEGRATION.md +222 -0
- package/docs/MCP-INTEGRATION.md +243 -0
- package/docs/MIGRATION-v4.md +121 -0
- package/docs/PLUGIN-PACKAGING.md +240 -0
- package/docs/PRODUCT-READINESS.md +66 -0
- package/docs/QUICKSTART.ko.md +178 -0
- package/docs/QUICKSTART.md +179 -0
- package/docs/RELEASE-CHECKLIST.md +292 -0
- package/docs/ROADMAP.md +19495 -0
- package/docs/SESSION-LOG.md +940 -0
- package/docs/TOKEN-SYNC.md +237 -0
- package/docs/USING.ko.md +206 -0
- package/docs/USING.md +218 -0
- package/docs/WEBSITE-IMPROVEMENT.ko.md +75 -0
- package/docs/WEBSITE-IMPROVEMENT.md +89 -0
- package/docs/announcements/README.md +56 -0
- package/docs/announcements/dev-to-korea.md +206 -0
- package/docs/announcements/hashnode-post.ko.md +232 -0
- package/docs/announcements/okky-post.ko.md +158 -0
- package/docs/announcements/press-kit.md +101 -0
- package/docs/announcements/reddit-r-korea.md +196 -0
- package/docs/announcements/show-hn.md +114 -0
- package/docs/announcements/twitter-thread.md +255 -0
- package/docs/external-status.md +34 -0
- package/docs/integrations/aider-walkthrough.ko.md +275 -0
- package/docs/integrations/aider-walkthrough.md +274 -0
- package/docs/integrations/codex-walkthrough.ko.md +297 -0
- package/docs/integrations/codex-walkthrough.md +297 -0
- package/docs/integrations/cursor-walkthrough.ko.md +281 -0
- package/docs/integrations/cursor-walkthrough.md +284 -0
- package/docs/integrations/design-ai-mcp-server.md +169 -0
- package/docs/integrations/figma-mcp.md +149 -0
- package/docs/integrations/github-mcp.md +178 -0
- package/docs/integrations/linear-mcp.md +215 -0
- package/docs/integrations/notion-mcp.md +174 -0
- package/docs/integrations/sdk-walkthrough.ko.md +375 -0
- package/docs/integrations/sdk-walkthrough.md +375 -0
- package/docs/integrations/slack-mcp.md +208 -0
- package/docs/integrations/vscode-walkthrough.ko.md +202 -0
- package/docs/integrations/vscode-walkthrough.md +205 -0
- package/docs/requirements.txt +16 -0
- package/docs/site-overrides/extra.css +83 -0
- package/docs/site-overrides/favicon.svg +4 -0
- package/docs/site-overrides/logo.svg +10 -0
- package/docs/site-overrides/main.html +18 -0
- package/docs/website-console/app.js +2540 -0
- package/docs/website-console/index.html +24 -0
- package/docs/website-console/styles.css +975 -0
- package/examples/README.md +252 -0
- package/examples/cases/dogfood-v4-korean-hr-onboarding.md +356 -0
- package/examples/component-accordion-actions.md +153 -0
- package/examples/component-accordion-details.md +147 -0
- package/examples/component-accordion-summary.md +180 -0
- package/examples/component-accordion.md +229 -0
- package/examples/component-account-card.md +284 -0
- package/examples/component-address-input.md +260 -0
- package/examples/component-affix.md +190 -0
- package/examples/component-alert-dialog.md +210 -0
- package/examples/component-alert-title.md +77 -0
- package/examples/component-alert.md +192 -0
- package/examples/component-amount-input.md +278 -0
- package/examples/component-anchor.md +198 -0
- package/examples/component-app-bar.md +249 -0
- package/examples/component-aspect-ratio.md +156 -0
- package/examples/component-auto-complete.md +199 -0
- package/examples/component-avatar-group.md +170 -0
- package/examples/component-avatar.md +191 -0
- package/examples/component-back-top.md +123 -0
- package/examples/component-backdrop.md +148 -0
- package/examples/component-badge.md +181 -0
- package/examples/component-banner.md +237 -0
- package/examples/component-biometric-gate.md +281 -0
- package/examples/component-blockquote.md +153 -0
- package/examples/component-border-beam.md +207 -0
- package/examples/component-bottom-navigation.md +226 -0
- package/examples/component-box.md +112 -0
- package/examples/component-breadcrumb.md +222 -0
- package/examples/component-button-base.md +190 -0
- package/examples/component-button-group.md +117 -0
- package/examples/component-button.md +213 -0
- package/examples/component-calendar.md +280 -0
- package/examples/component-callout.md +131 -0
- package/examples/component-card-actions.md +101 -0
- package/examples/component-card-content.md +90 -0
- package/examples/component-card-header.md +122 -0
- package/examples/component-card-media.md +79 -0
- package/examples/component-card.md +233 -0
- package/examples/component-carousel.md +266 -0
- package/examples/component-cascader.md +135 -0
- package/examples/component-category-picker.md +271 -0
- package/examples/component-chart.md +237 -0
- package/examples/component-chat-interface.md +399 -0
- package/examples/component-checkbox.md +149 -0
- package/examples/component-click-away-listener.md +87 -0
- package/examples/component-code.md +213 -0
- package/examples/component-collapsible.md +219 -0
- package/examples/component-color-picker.md +110 -0
- package/examples/component-combobox.md +267 -0
- package/examples/component-command.md +299 -0
- package/examples/component-config-provider.md +190 -0
- package/examples/component-context-menu.md +179 -0
- package/examples/component-css-baseline.md +148 -0
- package/examples/component-date-picker.md +249 -0
- package/examples/component-descriptions.md +242 -0
- package/examples/component-dialog-actions.md +111 -0
- package/examples/component-dialog-content-text.md +76 -0
- package/examples/component-dialog-content.md +105 -0
- package/examples/component-dialog-title.md +104 -0
- package/examples/component-dialog.md +176 -0
- package/examples/component-divider.md +182 -0
- package/examples/component-doc-page.md +217 -0
- package/examples/component-drawer.md +257 -0
- package/examples/component-dropdown.md +220 -0
- package/examples/component-email-layout.md +253 -0
- package/examples/component-empty-state.md +269 -0
- package/examples/component-empty.md +172 -0
- package/examples/component-fade.md +87 -0
- package/examples/component-feature-grid.md +201 -0
- package/examples/component-field.md +266 -0
- package/examples/component-filled-input.md +114 -0
- package/examples/component-flex.md +117 -0
- package/examples/component-float-button.md +214 -0
- package/examples/component-form-control-label.md +134 -0
- package/examples/component-form-control.md +113 -0
- package/examples/component-form-controls.md +251 -0
- package/examples/component-form-group.md +86 -0
- package/examples/component-form-helper-text.md +95 -0
- package/examples/component-form-label.md +98 -0
- package/examples/component-form.md +291 -0
- package/examples/component-game-hud.md +362 -0
- package/examples/component-game-menu.md +327 -0
- package/examples/component-grid.md +140 -0
- package/examples/component-grow.md +79 -0
- package/examples/component-hero-block.md +252 -0
- package/examples/component-hover-card.md +211 -0
- package/examples/component-icon-button.md +142 -0
- package/examples/component-icon.md +102 -0
- package/examples/component-illustration.md +280 -0
- package/examples/component-image-list.md +107 -0
- package/examples/component-image.md +282 -0
- package/examples/component-input-adornment.md +101 -0
- package/examples/component-input-base.md +134 -0
- package/examples/component-input-number.md +141 -0
- package/examples/component-input-otp.md +271 -0
- package/examples/component-input.md +213 -0
- package/examples/component-item.md +243 -0
- package/examples/component-kbd.md +197 -0
- package/examples/component-krw-amount.md +219 -0
- package/examples/component-label.md +118 -0
- package/examples/component-layout.md +217 -0
- package/examples/component-link.md +223 -0
- package/examples/component-list-item-avatar.md +72 -0
- package/examples/component-list-item-button.md +139 -0
- package/examples/component-list-item-icon.md +82 -0
- package/examples/component-list-item-text.md +98 -0
- package/examples/component-list-item.md +116 -0
- package/examples/component-list-subheader.md +70 -0
- package/examples/component-list.md +198 -0
- package/examples/component-loading-button.md +125 -0
- package/examples/component-loading-sequence.md +254 -0
- package/examples/component-lottie-player.md +279 -0
- package/examples/component-masonry.md +191 -0
- package/examples/component-mentions.md +189 -0
- package/examples/component-menu-item.md +102 -0
- package/examples/component-menu-list.md +98 -0
- package/examples/component-menu.md +139 -0
- package/examples/component-menubar.md +259 -0
- package/examples/component-message.md +162 -0
- package/examples/component-mobile-stepper.md +155 -0
- package/examples/component-modal.md +220 -0
- package/examples/component-navigation-menu.md +295 -0
- package/examples/component-notification.md +166 -0
- package/examples/component-otp-countdown.md +245 -0
- package/examples/component-outlined-input.md +145 -0
- package/examples/component-page-transition.md +281 -0
- package/examples/component-pagination.md +226 -0
- package/examples/component-paper.md +199 -0
- package/examples/component-pass-auth.md +265 -0
- package/examples/component-payment-brand-button.md +253 -0
- package/examples/component-payment-method-selector.md +272 -0
- package/examples/component-payment-receipt.md +277 -0
- package/examples/component-popconfirm.md +144 -0
- package/examples/component-popover.md +239 -0
- package/examples/component-popper.md +129 -0
- package/examples/component-pricing-cards.md +247 -0
- package/examples/component-progress.md +195 -0
- package/examples/component-qr-code.md +201 -0
- package/examples/component-radio.md +167 -0
- package/examples/component-rate.md +202 -0
- package/examples/component-resizable.md +163 -0
- package/examples/component-result.md +270 -0
- package/examples/component-scroll-area.md +199 -0
- package/examples/component-scroll-reveal.md +320 -0
- package/examples/component-segmented.md +178 -0
- package/examples/component-select.md +258 -0
- package/examples/component-separator.md +177 -0
- package/examples/component-sheet.md +277 -0
- package/examples/component-sidebar.md +257 -0
- package/examples/component-skeleton.md +178 -0
- package/examples/component-slide.md +89 -0
- package/examples/component-slider.md +208 -0
- package/examples/component-snackbar-content.md +92 -0
- package/examples/component-snackbar.md +121 -0
- package/examples/component-sonner.md +165 -0
- package/examples/component-space.md +125 -0
- package/examples/component-spatial-locomotion.md +373 -0
- package/examples/component-spatial-panel.md +330 -0
- package/examples/component-speed-dial-action.md +78 -0
- package/examples/component-speed-dial.md +177 -0
- package/examples/component-spin.md +173 -0
- package/examples/component-spinner.md +204 -0
- package/examples/component-splitter.md +210 -0
- package/examples/component-stack.md +130 -0
- package/examples/component-statistic.md +282 -0
- package/examples/component-step-button.md +157 -0
- package/examples/component-step-connector.md +157 -0
- package/examples/component-step-content.md +121 -0
- package/examples/component-step-icon.md +115 -0
- package/examples/component-step-label.md +101 -0
- package/examples/component-step.md +84 -0
- package/examples/component-steps.md +264 -0
- package/examples/component-stock-chart.md +251 -0
- package/examples/component-swipeable-drawer.md +149 -0
- package/examples/component-switch.md +99 -0
- package/examples/component-tab-scroll-button.md +180 -0
- package/examples/component-tab.md +120 -0
- package/examples/component-table-body.md +82 -0
- package/examples/component-table-cell.md +118 -0
- package/examples/component-table-container.md +75 -0
- package/examples/component-table-footer.md +72 -0
- package/examples/component-table-head.md +78 -0
- package/examples/component-table-pagination.md +137 -0
- package/examples/component-table-row.md +113 -0
- package/examples/component-table-sort-label.md +109 -0
- package/examples/component-table.md +202 -0
- package/examples/component-tabs.md +184 -0
- package/examples/component-tag-badge.md +309 -0
- package/examples/component-tag.md +102 -0
- package/examples/component-testimonial-carousel.md +218 -0
- package/examples/component-textarea-autosize.md +114 -0
- package/examples/component-textarea.md +173 -0
- package/examples/component-time-picker.md +205 -0
- package/examples/component-timeline.md +170 -0
- package/examples/component-toast.md +224 -0
- package/examples/component-toggle-button.md +129 -0
- package/examples/component-toggle.md +220 -0
- package/examples/component-toolbar.md +104 -0
- package/examples/component-tooltip.md +178 -0
- package/examples/component-tour.md +176 -0
- package/examples/component-transaction-list-item.md +243 -0
- package/examples/component-transfer.md +156 -0
- package/examples/component-tree-select.md +202 -0
- package/examples/component-tree.md +297 -0
- package/examples/component-typography.md +215 -0
- package/examples/component-upload.md +295 -0
- package/examples/component-video-hero.md +409 -0
- package/examples/component-video-player.md +340 -0
- package/examples/component-voice-input.md +408 -0
- package/examples/component-watermark.md +217 -0
- package/examples/component-zoom.md +92 -0
- package/examples/doc-explanation-example.md +196 -0
- package/examples/doc-how-to-example.md +205 -0
- package/examples/doc-tutorial-example.md +162 -0
- package/examples/dogfood-korean-fintech-system.md +433 -0
- package/examples/email-transactional-example.md +259 -0
- package/examples/palette-saas-violet.md +235 -0
- package/examples/print-business-card-spec.md +205 -0
- package/examples/print-packaging-spec.md +285 -0
- package/examples/report-example.md +228 -0
- package/examples/slide-deck-example.md +237 -0
- package/examples/website-improvement-report.md +128 -0
- package/examples/website-improvement-workspace.json +126 -0
- package/install.sh +189 -0
- package/knowledge/COVERAGE.md +740 -0
- package/knowledge/PRINCIPLES.md +108 -0
- package/knowledge/a11y/contrast.md +70 -0
- package/knowledge/a11y/keyboard-and-focus.md +108 -0
- package/knowledge/colors/color-theory.md +90 -0
- package/knowledge/colors/mui-palette-structure.md +105 -0
- package/knowledge/colors/palettes-by-product-type.md +876 -0
- package/knowledge/components/INDEX.md +231 -0
- package/knowledge/components/index.json +1470 -0
- package/knowledge/components/shadcn-registry.md +159 -0
- package/knowledge/conversational/ai-chat-interfaces.md +323 -0
- package/knowledge/conversational/chatbot-design.md +312 -0
- package/knowledge/conversational/conversational-ui-fundamentals.md +299 -0
- package/knowledge/conversational/korean-voice-conventions.md +281 -0
- package/knowledge/conversational/voice-ui-patterns.md +297 -0
- package/knowledge/design-tokens/ant-design.md +124 -0
- package/knowledge/design-tokens/material-3.md +235 -0
- package/knowledge/design-tokens/polaris-and-carbon.md +231 -0
- package/knowledge/design-tokens/tailwind-v4.md +284 -0
- package/knowledge/game-ui/game-accessibility.md +317 -0
- package/knowledge/game-ui/game-ui-fundamentals.md +281 -0
- package/knowledge/game-ui/hud-design.md +324 -0
- package/knowledge/game-ui/korean-gaming-conventions.md +312 -0
- package/knowledge/game-ui/menu-systems.md +388 -0
- package/knowledge/i18n/korean-app-store-visual.md +223 -0
- package/knowledge/i18n/korean-document-style.md +301 -0
- package/knowledge/i18n/korean-payments.md +211 -0
- package/knowledge/i18n/korean-product-conventions.md +96 -0
- package/knowledge/i18n/korean-publishing.md +139 -0
- package/knowledge/i18n/korean-typography.md +123 -0
- package/knowledge/icons/curated-sets.md +225 -0
- package/knowledge/illustration/hero-illustrations.md +234 -0
- package/knowledge/illustration/illustration-systems.md +221 -0
- package/knowledge/illustration/mascot-design.md +208 -0
- package/knowledge/illustration/spot-illustrations.md +246 -0
- package/knowledge/illustration/svg-optimization.md +308 -0
- package/knowledge/layout/spacing-and-grid.md +119 -0
- package/knowledge/motion/app-loading-sequences.md +277 -0
- package/knowledge/motion/choreography-depth.md +297 -0
- package/knowledge/motion/marketing-motion.md +223 -0
- package/knowledge/motion/micro-interactions.md +266 -0
- package/knowledge/motion/motion-tools.md +281 -0
- package/knowledge/motion/principles.md +126 -0
- package/knowledge/patterns/auth-flow-design.md +316 -0
- package/knowledge/patterns/b2b-onboarding-flows.md +182 -0
- package/knowledge/patterns/brand-identity.md +238 -0
- package/knowledge/patterns/brand-references.md +97 -0
- package/knowledge/patterns/chart-color-encoding.md +269 -0
- package/knowledge/patterns/chart-types.md +344 -0
- package/knowledge/patterns/dashboard-composition.md +299 -0
- package/knowledge/patterns/design-system-qa.md +356 -0
- package/knowledge/patterns/document-typography.md +248 -0
- package/knowledge/patterns/email-design.md +338 -0
- package/knowledge/patterns/empty-states.md +263 -0
- package/knowledge/patterns/error-states.md +318 -0
- package/knowledge/patterns/form-design.md +237 -0
- package/knowledge/patterns/information-architecture.md +341 -0
- package/knowledge/patterns/landing-hero-design.md +283 -0
- package/knowledge/patterns/landing-page-patterns.md +681 -0
- package/knowledge/patterns/list-and-feed.md +371 -0
- package/knowledge/patterns/mobile-navigation.md +278 -0
- package/knowledge/patterns/money-and-amount.md +301 -0
- package/knowledge/patterns/onboarding.md +300 -0
- package/knowledge/patterns/pricing-page-design.md +261 -0
- package/knowledge/patterns/realtime-data.md +280 -0
- package/knowledge/patterns/report-design.md +330 -0
- package/knowledge/patterns/search-ux.md +373 -0
- package/knowledge/patterns/settings-page.md +325 -0
- package/knowledge/patterns/slide-deck-design.md +316 -0
- package/knowledge/patterns/styles-catalog.md +2599 -0
- package/knowledge/patterns/technical-writing.md +306 -0
- package/knowledge/patterns/ui-reasoning.md +1853 -0
- package/knowledge/patterns/ux-guidelines.md +1454 -0
- package/knowledge/platforms/react-native.md +395 -0
- package/knowledge/print/brochures-and-flyers.md +276 -0
- package/knowledge/print/korean-print-conventions.md +284 -0
- package/knowledge/print/packaging.md +321 -0
- package/knowledge/print/print-fundamentals.md +238 -0
- package/knowledge/print/signage-and-posters.md +235 -0
- package/knowledge/print/stationery.md +262 -0
- package/knowledge/spatial/ar-patterns.md +253 -0
- package/knowledge/spatial/comfort-and-accessibility.md +245 -0
- package/knowledge/spatial/spatial-design-fundamentals.md +346 -0
- package/knowledge/spatial/spatial-ui-elements.md +343 -0
- package/knowledge/spatial/vr-patterns.md +302 -0
- package/knowledge/typography/font-pairings.md +332 -0
- package/knowledge/typography/mui-type-scale.md +57 -0
- package/knowledge/typography/type-scale-fundamentals.md +105 -0
- package/knowledge/video/in-product-video.md +277 -0
- package/knowledge/video/korean-video-conventions.md +247 -0
- package/knowledge/video/marketing-video.md +258 -0
- package/knowledge/video/social-and-short-form.md +257 -0
- package/knowledge/video/video-fundamentals.md +296 -0
- package/package.json +106 -0
- package/skills/README.md +39 -0
- package/skills/color-palette/PLAYBOOK.md +175 -0
- package/skills/color-palette/SKILL.md +6 -0
- package/skills/color-palette/TEMPLATE.md +103 -0
- package/skills/component-spec-writer/PLAYBOOK.md +169 -0
- package/skills/component-spec-writer/SKILL.md +6 -0
- package/skills/component-spec-writer/TEMPLATE.md +115 -0
- package/skills/conversational-ui-designer/PLAYBOOK.md +231 -0
- package/skills/conversational-ui-designer/SKILL.md +6 -0
- package/skills/design-broadcast/PLAYBOOK.md +146 -0
- package/skills/design-broadcast/SKILL.md +6 -0
- package/skills/design-critique/PLAYBOOK.md +137 -0
- package/skills/design-critique/SKILL.md +6 -0
- package/skills/design-pr-review/PLAYBOOK.md +171 -0
- package/skills/design-pr-review/SKILL.md +6 -0
- package/skills/design-system-builder/PLAYBOOK.md +218 -0
- package/skills/design-system-builder/SKILL.md +6 -0
- package/skills/design-system-qa/PLAYBOOK.md +163 -0
- package/skills/design-system-qa/SKILL.md +6 -0
- package/skills/document-author/PLAYBOOK.md +167 -0
- package/skills/document-author/SKILL.md +6 -0
- package/skills/figma-token-sync/PLAYBOOK.md +149 -0
- package/skills/figma-token-sync/SKILL.md +6 -0
- package/skills/game-ui-designer/PLAYBOOK.md +209 -0
- package/skills/game-ui-designer/SKILL.md +6 -0
- package/skills/handoff-spec/PLAYBOOK.md +170 -0
- package/skills/handoff-spec/SKILL.md +6 -0
- package/skills/illustration-designer/PLAYBOOK.md +166 -0
- package/skills/illustration-designer/SKILL.md +6 -0
- package/skills/motion-designer/PLAYBOOK.md +223 -0
- package/skills/motion-designer/SKILL.md +6 -0
- package/skills/print-designer/PLAYBOOK.md +209 -0
- package/skills/print-designer/SKILL.md +6 -0
- package/skills/slide-deck-author/PLAYBOOK.md +198 -0
- package/skills/slide-deck-author/SKILL.md +6 -0
- package/skills/spatial-designer/PLAYBOOK.md +238 -0
- package/skills/spatial-designer/SKILL.md +6 -0
- package/skills/ux-audit/PLAYBOOK.md +142 -0
- package/skills/ux-audit/SKILL.md +6 -0
- package/skills/video-designer/PLAYBOOK.md +240 -0
- package/skills/video-designer/SKILL.md +6 -0
- package/skills/website-improvement/PLAYBOOK.md +118 -0
- package/skills/website-improvement/SKILL.md +6 -0
- package/skills/website-improvement/TEMPLATE.md +103 -0
- package/tools/audit/changelog-generate.py +176 -0
- package/tools/audit/check-coverage.py +483 -0
- package/tools/audit/doctor_assertions.py +256 -0
- package/tools/audit/example-qa.py +108 -0
- package/tools/audit/frontmatter-check.py +199 -0
- package/tools/audit/integration-check.py +95 -0
- package/tools/audit/korean-copy-check.py +161 -0
- package/tools/audit/link-check.py +146 -0
- package/tools/audit/local-ci.py +558 -0
- package/tools/audit/package-contents.py +723 -0
- package/tools/audit/package-smoke.py +22443 -0
- package/tools/audit/raw-hex-check.py +252 -0
- package/tools/audit/registry-smoke.py +8188 -0
- package/tools/audit/release-metadata.py +9832 -0
- package/tools/audit/run-all.py +351 -0
- package/tools/audit/smoke_assertions.py +12742 -0
- package/tools/audit/stability-review.py +332 -0
- package/tools/audit/stale-check.py +156 -0
- package/tools/migrations/add-version-frontmatter.py +132 -0
- package/tools/migrations/bump-last-updated.py +131 -0
- package/tools/migrations/promote-stability.py +172 -0
- package/tools/preview/README.md +58 -0
- package/tools/preview/render-tokens.py +454 -0
package/cli/lib/log.mjs
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Terminal output helpers.
|
|
2
|
+
|
|
3
|
+
const isTTY = process.stdout.isTTY;
|
|
4
|
+
const noColor = process.env.NO_COLOR || !isTTY;
|
|
5
|
+
|
|
6
|
+
const codes = {
|
|
7
|
+
reset: "\x1b[0m",
|
|
8
|
+
bold: "\x1b[1m",
|
|
9
|
+
dim: "\x1b[2m",
|
|
10
|
+
red: "\x1b[31m",
|
|
11
|
+
green: "\x1b[32m",
|
|
12
|
+
yellow: "\x1b[33m",
|
|
13
|
+
blue: "\x1b[34m",
|
|
14
|
+
cyan: "\x1b[36m",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const c = (color) => (s) => noColor ? s : `${codes[color]}${s}${codes.reset}`;
|
|
18
|
+
|
|
19
|
+
export const bold = c("bold");
|
|
20
|
+
export const dim = c("dim");
|
|
21
|
+
export const red = c("red");
|
|
22
|
+
export const green = c("green");
|
|
23
|
+
export const yellow = c("yellow");
|
|
24
|
+
export const blue = c("blue");
|
|
25
|
+
export const cyan = c("cyan");
|
|
26
|
+
|
|
27
|
+
export const info = (msg) => console.log(`${blue("ℹ")} ${msg}`);
|
|
28
|
+
export const success = (msg) => console.log(`${green("✓")} ${msg}`);
|
|
29
|
+
export const warn = (msg) => console.log(`${yellow("⚠")} ${msg}`);
|
|
30
|
+
export const error = (msg) => console.error(`${red("✗")} ${msg}`);
|
|
31
|
+
|
|
32
|
+
export function header(title, subtitle) {
|
|
33
|
+
if (noColor) {
|
|
34
|
+
console.log(`\n ${title}`);
|
|
35
|
+
if (subtitle) console.log(` ${subtitle}`);
|
|
36
|
+
console.log();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const w = 64;
|
|
40
|
+
const top = `${codes.blue}╔${"═".repeat(w - 2)}╗${codes.reset}`;
|
|
41
|
+
const bot = `${codes.blue}╚${"═".repeat(w - 2)}╝${codes.reset}`;
|
|
42
|
+
const pad = (s) => `${codes.blue}║${codes.reset} ${s.padEnd(w - 5)}${codes.blue}║${codes.reset}`;
|
|
43
|
+
console.log(`\n${top}`);
|
|
44
|
+
console.log(pad(bold(title)));
|
|
45
|
+
if (subtitle) console.log(pad(dim(subtitle)));
|
|
46
|
+
console.log(`${bot}\n`);
|
|
47
|
+
}
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
// Minimal stdio MCP server for exposing design-ai CLI workflows to Claude/Codex.
|
|
2
|
+
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { createInterface } from "node:readline";
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
|
|
8
|
+
import { DESIGN_AI_HOME, PACKAGE_ROOT } from "./paths.mjs";
|
|
9
|
+
|
|
10
|
+
const PROTOCOL_VERSION = "2025-11-25";
|
|
11
|
+
const MAX_TOOL_OUTPUT_BYTES = 220_000;
|
|
12
|
+
const DESIGN_AI_BIN = path.join(PACKAGE_ROOT, "cli", "bin", "design-ai.mjs");
|
|
13
|
+
|
|
14
|
+
function optionalString(description = "") {
|
|
15
|
+
return { type: "string", description };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function optionalBoolean(description = "") {
|
|
19
|
+
return { type: "boolean", description };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function optionalInteger({ description = "", minimum = 1, maximum = 100 } = {}) {
|
|
23
|
+
return { type: "integer", minimum, maximum, description };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const MCP_TOOLS = [
|
|
27
|
+
{
|
|
28
|
+
name: "design_ai_route",
|
|
29
|
+
title: "Route a design task",
|
|
30
|
+
description: "Recommend the best design-ai route, command, skills, and knowledge files for a task brief. Read-only.",
|
|
31
|
+
inputSchema: {
|
|
32
|
+
type: "object",
|
|
33
|
+
properties: {
|
|
34
|
+
brief: { type: "string", minLength: 1, description: "Task brief to route." },
|
|
35
|
+
limit: optionalInteger({ description: "Maximum route recommendations, 1-10.", minimum: 1, maximum: 10 }),
|
|
36
|
+
explain: optionalBoolean("Include route scoring and reference coverage details."),
|
|
37
|
+
},
|
|
38
|
+
required: ["brief"],
|
|
39
|
+
additionalProperties: false,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "design_ai_prompt",
|
|
44
|
+
title: "Generate an agent prompt",
|
|
45
|
+
description: "Generate a ready-to-use design-ai agent prompt from a brief. Read-only unless withLearning is true, which records local usage metadata.",
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
brief: { type: "string", minLength: 1, description: "Task brief." },
|
|
50
|
+
routeId: optionalString("Optional forced route id, such as component-spec or website-improvement."),
|
|
51
|
+
withLearning: optionalBoolean("Include local learning preferences and record local usage metadata."),
|
|
52
|
+
learningCategory: optionalString("Optional learning category when withLearning is true."),
|
|
53
|
+
learningLimit: optionalInteger({ description: "Maximum learning entries, 1-100.", minimum: 1, maximum: 100 }),
|
|
54
|
+
json: optionalBoolean("Return machine-readable prompt plan JSON instead of Markdown."),
|
|
55
|
+
},
|
|
56
|
+
required: ["brief"],
|
|
57
|
+
additionalProperties: false,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "design_ai_pack",
|
|
62
|
+
title: "Generate prompt plus bounded context",
|
|
63
|
+
description: "Generate a prompt pack with relevant design-ai context files. Read-only unless withLearning is true, which records local usage metadata.",
|
|
64
|
+
inputSchema: {
|
|
65
|
+
type: "object",
|
|
66
|
+
properties: {
|
|
67
|
+
brief: { type: "string", minLength: 1, description: "Task brief." },
|
|
68
|
+
routeId: optionalString("Optional forced route id."),
|
|
69
|
+
maxBytes: optionalInteger({ description: "Maximum context bytes to include.", minimum: 1000, maximum: 1_000_000 }),
|
|
70
|
+
withLearning: optionalBoolean("Include local learning preferences and record local usage metadata."),
|
|
71
|
+
learningCategory: optionalString("Optional learning category when withLearning is true."),
|
|
72
|
+
learningLimit: optionalInteger({ description: "Maximum learning entries, 1-100.", minimum: 1, maximum: 100 }),
|
|
73
|
+
json: optionalBoolean("Return machine-readable pack JSON instead of Markdown."),
|
|
74
|
+
},
|
|
75
|
+
required: ["brief"],
|
|
76
|
+
additionalProperties: false,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: "design_ai_search",
|
|
81
|
+
title: "Search design-ai corpus",
|
|
82
|
+
description: "Search knowledge, examples, skills, docs, agents, or commands. Read-only.",
|
|
83
|
+
inputSchema: {
|
|
84
|
+
type: "object",
|
|
85
|
+
properties: {
|
|
86
|
+
query: { type: "string", minLength: 2, description: "Search query." },
|
|
87
|
+
dir: optionalString("Optional corpus directory: knowledge, examples, skills, docs, agents, commands."),
|
|
88
|
+
limit: optionalInteger({ description: "Maximum hits, 1-500.", minimum: 1, maximum: 500 }),
|
|
89
|
+
},
|
|
90
|
+
required: ["query"],
|
|
91
|
+
additionalProperties: false,
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "design_ai_show",
|
|
96
|
+
title: "Show corpus file",
|
|
97
|
+
description: "Read a design-ai corpus file or line range. Read-only.",
|
|
98
|
+
inputSchema: {
|
|
99
|
+
type: "object",
|
|
100
|
+
properties: {
|
|
101
|
+
target: { type: "string", minLength: 1, description: "Path or path:line target, such as knowledge/PRINCIPLES.md:1." },
|
|
102
|
+
lines: optionalString("Optional line range N:M."),
|
|
103
|
+
context: optionalInteger({ description: "Context lines around target.", minimum: 0, maximum: 100 }),
|
|
104
|
+
},
|
|
105
|
+
required: ["target"],
|
|
106
|
+
additionalProperties: false,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: "design_ai_examples",
|
|
111
|
+
title: "Find worked examples",
|
|
112
|
+
description: "Find worked design-ai examples by query or route id. Read-only.",
|
|
113
|
+
inputSchema: {
|
|
114
|
+
type: "object",
|
|
115
|
+
properties: {
|
|
116
|
+
query: optionalString("Optional example search query."),
|
|
117
|
+
routeId: optionalString("Optional route id, such as component-spec."),
|
|
118
|
+
limit: optionalInteger({ description: "Maximum examples.", minimum: 1, maximum: 50 }),
|
|
119
|
+
},
|
|
120
|
+
additionalProperties: false,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: "design_ai_check",
|
|
125
|
+
title: "Check Markdown artifact quality",
|
|
126
|
+
description: "Check generated Markdown for grounding, accessibility, responsive notes, unresolved markers, and route-specific requirements. Read-only.",
|
|
127
|
+
inputSchema: {
|
|
128
|
+
type: "object",
|
|
129
|
+
properties: {
|
|
130
|
+
artifact: { type: "string", minLength: 1, description: "Markdown artifact content to check." },
|
|
131
|
+
routeId: optionalString("Optional route-specific checks."),
|
|
132
|
+
strict: optionalBoolean("Treat warnings as failures."),
|
|
133
|
+
issuesOnly: optionalBoolean("Show only warnings/failures in human output."),
|
|
134
|
+
json: optionalBoolean("Return machine-readable JSON. Defaults to true."),
|
|
135
|
+
},
|
|
136
|
+
required: ["artifact"],
|
|
137
|
+
additionalProperties: false,
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: "design_ai_site_mcp_check",
|
|
142
|
+
title: "Check Website Improvement MCP readiness",
|
|
143
|
+
description: "Validate Website Improvement workspace MCP readiness without external MCP calls or target-repo mutation.",
|
|
144
|
+
inputSchema: {
|
|
145
|
+
type: "object",
|
|
146
|
+
properties: {
|
|
147
|
+
workspaceJson: { type: "string", minLength: 2, description: "Website Improvement workspace JSON." },
|
|
148
|
+
probes: optionalBoolean("Include read-only local probes."),
|
|
149
|
+
strict: optionalBoolean("Exit non-zero on warning/failure readiness."),
|
|
150
|
+
json: optionalBoolean("Return machine-readable JSON. Defaults to true."),
|
|
151
|
+
},
|
|
152
|
+
required: ["workspaceJson"],
|
|
153
|
+
additionalProperties: false,
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "design_ai_site_mcp_plan",
|
|
158
|
+
title: "Generate Website Improvement MCP action plan",
|
|
159
|
+
description: "Generate a Website Improvement MCP action plan without external MCP calls or target-repo mutation.",
|
|
160
|
+
inputSchema: {
|
|
161
|
+
type: "object",
|
|
162
|
+
properties: {
|
|
163
|
+
workspaceJson: { type: "string", minLength: 2, description: "Website Improvement workspace JSON." },
|
|
164
|
+
probes: optionalBoolean("Include read-only local probes."),
|
|
165
|
+
strict: optionalBoolean("Exit non-zero on warning/failure readiness."),
|
|
166
|
+
json: optionalBoolean("Return machine-readable JSON instead of Markdown."),
|
|
167
|
+
},
|
|
168
|
+
required: ["workspaceJson"],
|
|
169
|
+
additionalProperties: false,
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: "design_ai_version",
|
|
174
|
+
title: "Show design-ai version",
|
|
175
|
+
description: "Return design-ai CLI and corpus version metadata. Read-only.",
|
|
176
|
+
inputSchema: {
|
|
177
|
+
type: "object",
|
|
178
|
+
properties: {},
|
|
179
|
+
additionalProperties: false,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
];
|
|
183
|
+
|
|
184
|
+
function readPackageVersion() {
|
|
185
|
+
try {
|
|
186
|
+
return JSON.parse(readFileSync(path.join(PACKAGE_ROOT, "package.json"), "utf8")).version || "unknown";
|
|
187
|
+
} catch {
|
|
188
|
+
return "unknown";
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function assertString(value, name) {
|
|
193
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
194
|
+
throw new Error(`${name} must be a non-empty string`);
|
|
195
|
+
}
|
|
196
|
+
return value;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function maybePush(args, flag, value) {
|
|
200
|
+
if (value !== undefined && value !== null && value !== "") args.push(flag, String(value));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function maybeBool(args, flag, value) {
|
|
204
|
+
if (value === true) args.push(flag);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function truncateText(text) {
|
|
208
|
+
const bytes = Buffer.byteLength(text, "utf8");
|
|
209
|
+
if (bytes <= MAX_TOOL_OUTPUT_BYTES) return text;
|
|
210
|
+
const truncated = Buffer.from(text, "utf8").subarray(0, MAX_TOOL_OUTPUT_BYTES).toString("utf8");
|
|
211
|
+
return `${truncated}\n\n[design-ai MCP output truncated at ${MAX_TOOL_OUTPUT_BYTES} bytes from ${bytes} bytes]`;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function buildCliInvocation(toolName, input = {}) {
|
|
215
|
+
const args = [];
|
|
216
|
+
let stdin = "";
|
|
217
|
+
|
|
218
|
+
if (toolName === "design_ai_route") {
|
|
219
|
+
args.push("route", assertString(input.brief, "brief"), "--json");
|
|
220
|
+
maybePush(args, "--limit", input.limit);
|
|
221
|
+
maybeBool(args, "--explain", input.explain);
|
|
222
|
+
return { args, stdin };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (toolName === "design_ai_prompt") {
|
|
226
|
+
args.push("prompt", assertString(input.brief, "brief"));
|
|
227
|
+
maybePush(args, "--route", input.routeId);
|
|
228
|
+
maybeBool(args, "--with-learning", input.withLearning);
|
|
229
|
+
maybePush(args, "--learning-category", input.learningCategory);
|
|
230
|
+
maybePush(args, "--learning-limit", input.learningLimit);
|
|
231
|
+
maybeBool(args, "--json", input.json);
|
|
232
|
+
return { args, stdin };
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (toolName === "design_ai_pack") {
|
|
236
|
+
args.push("pack", assertString(input.brief, "brief"));
|
|
237
|
+
maybePush(args, "--route", input.routeId);
|
|
238
|
+
maybePush(args, "--max-bytes", input.maxBytes);
|
|
239
|
+
maybeBool(args, "--with-learning", input.withLearning);
|
|
240
|
+
maybePush(args, "--learning-category", input.learningCategory);
|
|
241
|
+
maybePush(args, "--learning-limit", input.learningLimit);
|
|
242
|
+
maybeBool(args, "--json", input.json);
|
|
243
|
+
return { args, stdin };
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (toolName === "design_ai_search") {
|
|
247
|
+
args.push("search", assertString(input.query, "query"), "--json");
|
|
248
|
+
maybePush(args, "--dir", input.dir);
|
|
249
|
+
maybePush(args, "--limit", input.limit);
|
|
250
|
+
return { args, stdin };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (toolName === "design_ai_show") {
|
|
254
|
+
args.push("show", assertString(input.target, "target"), "--json");
|
|
255
|
+
maybePush(args, "--lines", input.lines);
|
|
256
|
+
maybePush(args, "--context", input.context);
|
|
257
|
+
return { args, stdin };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (toolName === "design_ai_examples") {
|
|
261
|
+
args.push("examples", "--json");
|
|
262
|
+
if (input.query) args.splice(1, 0, String(input.query));
|
|
263
|
+
maybePush(args, "--route", input.routeId);
|
|
264
|
+
maybePush(args, "--limit", input.limit);
|
|
265
|
+
return { args, stdin };
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (toolName === "design_ai_check") {
|
|
269
|
+
args.push("check", "--stdin");
|
|
270
|
+
stdin = assertString(input.artifact, "artifact");
|
|
271
|
+
maybePush(args, "--route", input.routeId);
|
|
272
|
+
maybeBool(args, "--strict", input.strict);
|
|
273
|
+
maybeBool(args, "--issues-only", input.issuesOnly);
|
|
274
|
+
if (input.json !== false) args.push("--json");
|
|
275
|
+
return { args, stdin };
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (toolName === "design_ai_site_mcp_check") {
|
|
279
|
+
args.push("site", "--stdin", "--mcp-check");
|
|
280
|
+
stdin = assertString(input.workspaceJson, "workspaceJson");
|
|
281
|
+
maybeBool(args, "--probes", input.probes);
|
|
282
|
+
maybeBool(args, "--strict", input.strict);
|
|
283
|
+
if (input.json !== false) args.push("--json");
|
|
284
|
+
return { args, stdin };
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (toolName === "design_ai_site_mcp_plan") {
|
|
288
|
+
args.push("site", "--stdin", "--mcp-plan");
|
|
289
|
+
stdin = assertString(input.workspaceJson, "workspaceJson");
|
|
290
|
+
maybeBool(args, "--probes", input.probes);
|
|
291
|
+
maybeBool(args, "--strict", input.strict);
|
|
292
|
+
maybeBool(args, "--json", input.json);
|
|
293
|
+
return { args, stdin };
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (toolName === "design_ai_version") {
|
|
297
|
+
args.push("version", "--json");
|
|
298
|
+
return { args, stdin };
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
throw new Error(`Unknown MCP tool: ${toolName}`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export function runDesignAiCli(args, { stdin = "" } = {}) {
|
|
305
|
+
return new Promise((resolve) => {
|
|
306
|
+
const child = spawn(process.execPath, [DESIGN_AI_BIN, ...args], {
|
|
307
|
+
cwd: DESIGN_AI_HOME,
|
|
308
|
+
env: process.env,
|
|
309
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
let stdout = "";
|
|
313
|
+
let stderr = "";
|
|
314
|
+
child.stdout.on("data", (chunk) => {
|
|
315
|
+
stdout += chunk;
|
|
316
|
+
});
|
|
317
|
+
child.stderr.on("data", (chunk) => {
|
|
318
|
+
stderr += chunk;
|
|
319
|
+
});
|
|
320
|
+
child.on("error", (error) => {
|
|
321
|
+
resolve({ code: 1, stdout, stderr: `${stderr}${error.message}` });
|
|
322
|
+
});
|
|
323
|
+
child.on("close", (code) => {
|
|
324
|
+
resolve({ code: code ?? 1, stdout, stderr });
|
|
325
|
+
});
|
|
326
|
+
child.stdin.end(stdin);
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export async function callMcpTool(name, input = {}, runCli = runDesignAiCli) {
|
|
331
|
+
const invocation = buildCliInvocation(name, input || {});
|
|
332
|
+
const result = await runCli(invocation.args, { stdin: invocation.stdin });
|
|
333
|
+
const text = [
|
|
334
|
+
result.stdout.trimEnd(),
|
|
335
|
+
result.stderr.trim() ? `\n[stderr]\n${result.stderr.trimEnd()}` : "",
|
|
336
|
+
].filter(Boolean).join("\n");
|
|
337
|
+
|
|
338
|
+
return {
|
|
339
|
+
content: [{ type: "text", text: truncateText(text || "(no output)") }],
|
|
340
|
+
isError: result.code !== 0,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function successResponse(id, result) {
|
|
345
|
+
return { jsonrpc: "2.0", id, result };
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function errorResponse(id, code, message) {
|
|
349
|
+
return { jsonrpc: "2.0", id: id ?? null, error: { code, message } };
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export async function handleMcpRequest(message, { runCli = runDesignAiCli } = {}) {
|
|
353
|
+
const { id, method, params = {} } = message || {};
|
|
354
|
+
|
|
355
|
+
if (!method) return errorResponse(id, -32600, "Invalid MCP request: missing method");
|
|
356
|
+
|
|
357
|
+
if (method === "initialize") {
|
|
358
|
+
return successResponse(id, {
|
|
359
|
+
protocolVersion: params.protocolVersion || PROTOCOL_VERSION,
|
|
360
|
+
capabilities: {
|
|
361
|
+
tools: { listChanged: false },
|
|
362
|
+
},
|
|
363
|
+
serverInfo: {
|
|
364
|
+
name: "design-ai",
|
|
365
|
+
version: readPackageVersion(),
|
|
366
|
+
},
|
|
367
|
+
instructions: "Use design-ai MCP tools for local, deterministic design expertise: route briefs, generate prompts/packs, search/show the design corpus, check Markdown artifacts, and validate Website Improvement MCP readiness. Prefer read-only tools unless the user explicitly asks to record local learning usage.",
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (method === "notifications/initialized") return null;
|
|
372
|
+
if (method === "ping") return successResponse(id, {});
|
|
373
|
+
|
|
374
|
+
if (method === "tools/list") {
|
|
375
|
+
return successResponse(id, { tools: MCP_TOOLS });
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (method === "tools/call") {
|
|
379
|
+
const name = params.name;
|
|
380
|
+
const tool = MCP_TOOLS.find((item) => item.name === name);
|
|
381
|
+
if (!tool) return errorResponse(id, -32602, `Unknown tool: ${name}`);
|
|
382
|
+
try {
|
|
383
|
+
const result = await callMcpTool(name, params.arguments || {}, runCli);
|
|
384
|
+
return successResponse(id, result);
|
|
385
|
+
} catch (error) {
|
|
386
|
+
return successResponse(id, {
|
|
387
|
+
content: [{ type: "text", text: error.message || String(error) }],
|
|
388
|
+
isError: true,
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (method === "resources/list") return successResponse(id, { resources: [] });
|
|
394
|
+
if (method === "prompts/list") return successResponse(id, { prompts: [] });
|
|
395
|
+
|
|
396
|
+
return errorResponse(id, -32601, `Method not found: ${method}`);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
export function startMcpStdioServer({ input = process.stdin, output = process.stdout, error = process.stderr } = {}) {
|
|
400
|
+
const rl = createInterface({ input, crlfDelay: Infinity });
|
|
401
|
+
|
|
402
|
+
rl.on("line", async (line) => {
|
|
403
|
+
if (!line.trim()) return;
|
|
404
|
+
let message;
|
|
405
|
+
try {
|
|
406
|
+
message = JSON.parse(line);
|
|
407
|
+
} catch (parseError) {
|
|
408
|
+
output.write(`${JSON.stringify(errorResponse(null, -32700, `Parse error: ${parseError.message}`))}\n`);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
try {
|
|
413
|
+
const response = await handleMcpRequest(message);
|
|
414
|
+
if (response && message.id !== undefined) {
|
|
415
|
+
output.write(`${JSON.stringify(response)}\n`);
|
|
416
|
+
}
|
|
417
|
+
} catch (requestError) {
|
|
418
|
+
const id = message && message.id !== undefined ? message.id : null;
|
|
419
|
+
output.write(`${JSON.stringify(errorResponse(id, -32603, requestError.message || String(requestError)))}\n`);
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
rl.on("error", (streamError) => {
|
|
424
|
+
error.write(`design-ai MCP stdin error: ${streamError.message}\n`);
|
|
425
|
+
});
|
|
426
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Output file helpers for CLI commands that can write artifacts.
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
existsSync,
|
|
5
|
+
mkdirSync,
|
|
6
|
+
statSync,
|
|
7
|
+
writeFileSync,
|
|
8
|
+
} from "node:fs";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
|
|
11
|
+
function exists(p) {
|
|
12
|
+
try {
|
|
13
|
+
return existsSync(p);
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function parseOutputFlags(args, out) {
|
|
20
|
+
const arg = args[out.index];
|
|
21
|
+
if (arg === "--out" || arg === "--output") {
|
|
22
|
+
const next = args[out.index + 1];
|
|
23
|
+
if (!next || next.startsWith("--")) throw new Error(`${arg} expects a file path`);
|
|
24
|
+
out.outPath = next;
|
|
25
|
+
out.index += 1;
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
if (arg === "--force") {
|
|
29
|
+
out.force = true;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function writeOutputFile({ outPath, content, force = false, cwd = process.cwd() }) {
|
|
36
|
+
if (!outPath) throw new Error("Missing output path");
|
|
37
|
+
|
|
38
|
+
const absolute = path.resolve(cwd, outPath);
|
|
39
|
+
if (exists(absolute)) {
|
|
40
|
+
if (statSync(absolute).isDirectory()) {
|
|
41
|
+
throw new Error(`Output path is a directory: ${absolute}`);
|
|
42
|
+
}
|
|
43
|
+
if (!force) {
|
|
44
|
+
throw new Error(`Output file already exists: ${absolute}. Use --force to overwrite.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
mkdirSync(path.dirname(absolute), { recursive: true });
|
|
49
|
+
writeFileSync(absolute, content, "utf8");
|
|
50
|
+
return absolute;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function assertSafeRelativePath(relPath) {
|
|
54
|
+
const normalized = path.normalize(String(relPath || ""));
|
|
55
|
+
if (!normalized || normalized === ".") {
|
|
56
|
+
throw new Error("Output bundle file path is empty");
|
|
57
|
+
}
|
|
58
|
+
if (path.isAbsolute(normalized) || normalized.startsWith("..") || normalized.includes(`${path.sep}..${path.sep}`)) {
|
|
59
|
+
throw new Error(`Output bundle file path must stay inside the output directory: ${relPath}`);
|
|
60
|
+
}
|
|
61
|
+
return normalized;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function writeOutputFiles({ outPath, files, force = false, cwd = process.cwd() }) {
|
|
65
|
+
if (!outPath) throw new Error("Missing output directory");
|
|
66
|
+
if (!Array.isArray(files) || files.length === 0) throw new Error("No output files provided");
|
|
67
|
+
|
|
68
|
+
const absolute = path.resolve(cwd, outPath);
|
|
69
|
+
if (exists(absolute) && !statSync(absolute).isDirectory()) {
|
|
70
|
+
throw new Error(`Output path is not a directory: ${absolute}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const planned = files.map((file) => {
|
|
74
|
+
const relativePath = assertSafeRelativePath(file.path);
|
|
75
|
+
const target = path.join(absolute, relativePath);
|
|
76
|
+
if (exists(target)) {
|
|
77
|
+
if (statSync(target).isDirectory()) {
|
|
78
|
+
throw new Error(`Output bundle file path is a directory: ${target}`);
|
|
79
|
+
}
|
|
80
|
+
if (!force) {
|
|
81
|
+
throw new Error(`Output bundle file already exists: ${target}. Use --force to overwrite.`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
relativePath,
|
|
86
|
+
target,
|
|
87
|
+
content: String(file.content ?? ""),
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
mkdirSync(absolute, { recursive: true });
|
|
92
|
+
for (const file of planned) {
|
|
93
|
+
mkdirSync(path.dirname(file.target), { recursive: true });
|
|
94
|
+
writeFileSync(file.target, file.content, "utf8");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
directory: absolute,
|
|
99
|
+
files: planned.map((file) => file.target),
|
|
100
|
+
};
|
|
101
|
+
}
|