{"owner":"trycompai","repo":"crm","hasSkills":true,"totalSkillsCount":362,"totalTokensCount":361816,"categories":["anthropic-skill","subagent-persona","root-instruction","claude-rule","project-spec","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":[".agents/skills/ai-elements/SKILL.md",".agents/skills/ai-elements/references/agent.md",".agents/skills/ai-elements/references/artifact.md",".agents/skills/ai-elements/references/attachments.md",".agents/skills/ai-elements/references/audio-player.md",".agents/skills/ai-elements/references/canvas.md",".agents/skills/ai-elements/references/chain-of-thought.md",".agents/skills/ai-elements/references/checkpoint.md",".agents/skills/ai-elements/references/code-block.md",".agents/skills/ai-elements/references/commit.md",".agents/skills/ai-elements/references/confirmation.md",".agents/skills/ai-elements/references/connection.md",".agents/skills/ai-elements/references/context.md",".agents/skills/ai-elements/references/controls.md",".agents/skills/ai-elements/references/conversation.md",".agents/skills/ai-elements/references/edge.md",".agents/skills/ai-elements/references/environment-variables.md",".agents/skills/ai-elements/references/file-tree.md",".agents/skills/ai-elements/references/image.md",".agents/skills/ai-elements/references/inline-citation.md",".agents/skills/ai-elements/references/jsx-preview.md",".agents/skills/ai-elements/references/message.md",".agents/skills/ai-elements/references/mic-selector.md",".agents/skills/ai-elements/references/model-selector.md",".agents/skills/ai-elements/references/node.md",".agents/skills/ai-elements/references/open-in-chat.md",".agents/skills/ai-elements/references/package-info.md",".agents/skills/ai-elements/references/panel.md",".agents/skills/ai-elements/references/persona.md",".agents/skills/ai-elements/references/plan.md",".agents/skills/ai-elements/references/prompt-input.md",".agents/skills/ai-elements/references/queue.md",".agents/skills/ai-elements/references/reasoning.md",".agents/skills/ai-elements/references/sandbox.md",".agents/skills/ai-elements/references/schema-display.md",".agents/skills/ai-elements/references/shimmer.md",".agents/skills/ai-elements/references/snippet.md",".agents/skills/ai-elements/references/sources.md",".agents/skills/ai-elements/references/speech-input.md",".agents/skills/ai-elements/references/stack-trace.md",".agents/skills/ai-elements/references/suggestion.md",".agents/skills/ai-elements/references/task.md",".agents/skills/ai-elements/references/terminal.md",".agents/skills/ai-elements/references/test-results.md",".agents/skills/ai-elements/references/tool.md",".agents/skills/ai-elements/references/toolbar.md",".agents/skills/ai-elements/references/transcription.md",".agents/skills/ai-elements/references/voice-selector.md",".agents/skills/ai-elements/references/web-preview.md",".agents/skills/ai-sdk/SKILL.md",".agents/skills/better-accessibility/SKILL.md",".agents/skills/better-accessibility/agents/openai.yaml",".agents/skills/better-accessibility/focus-and-keyboard.md",".agents/skills/better-accessibility/forms.md",".agents/skills/better-accessibility/hit-areas.md",".agents/skills/better-accessibility/motion-and-zoom.md",".agents/skills/better-accessibility/screen-readers.md",".agents/skills/better-accessibility/semantics-and-aria.md",".agents/skills/better-auth-best-practices/SKILL.md",".agents/skills/better-colors/SKILL.md",".agents/skills/better-colors/accessibility-contrast.md",".agents/skills/better-colors/agents/openai.yaml",".agents/skills/better-colors/color-conversion.md",".agents/skills/better-colors/color-usage.md",".agents/skills/better-colors/gamut-and-tailwind.md",".agents/skills/better-colors/palette-generation.md",".agents/skills/better-interface/SKILL.md",".agents/skills/better-interface/agents/openai.yaml",".agents/skills/better-layout/SKILL.md",".agents/skills/better-layout/agents/openai.yaml",".agents/skills/better-layout/grouping-and-alignment.md",".agents/skills/better-layout/spacing-and-adaptivity.md",".agents/skills/better-typography/SKILL.md",".agents/skills/better-typography/agents/openai.yaml",".agents/skills/better-typography/choosing-fonts.md",".agents/skills/better-typography/css-cheat-sheet.md",".agents/skills/better-typography/details-and-accessibility.md",".agents/skills/better-typography/spacing-and-sizing.md",".agents/skills/better-typography/variable-fonts-and-opentype.md",".agents/skills/better-typography/wrapping-and-punctuation.md",".agents/skills/better-ui/SKILL.md",".agents/skills/better-ui/agents/openai.yaml",".agents/skills/better-ui/animations.md",".agents/skills/better-ui/icons.md",".agents/skills/better-ui/performance.md",".agents/skills/better-ui/surfaces.md",".agents/skills/better-writing/SKILL.md",".agents/skills/better-writing/agents/openai.yaml",".agents/skills/code-refactor-review/SKILL.md",".agents/skills/create-draft-pr/SKILL.md",".agents/skills/diffs/SKILL.md",".agents/skills/diffs/references/api-editor.md",".agents/skills/diffs/references/api-react.md",".agents/skills/diffs/references/recipe-code-view.md",".agents/skills/diffs/references/recipe-edit-react.md",".agents/skills/diffs/references/recipe-react.md",".agents/skills/eve/SKILL.md",".agents/skills/ga-pr/SKILL.md",".agents/skills/ga/SKILL.md",".agents/skills/gh-stack/SKILL.md",".agents/skills/gh-stack/references/commands.md",".agents/skills/gh-stack/references/stack-design.md",".agents/skills/gh-stack/references/troubleshooting.md",".agents/skills/install-anti-slop/SKILL.md",".agents/skills/nestjs-best-practices/SKILL.md",".agents/skills/nestjs-best-practices/rules/_sections.md",".agents/skills/nestjs-best-practices/rules/_template.md",".agents/skills/nestjs-best-practices/rules/api-use-dto-serialization.md",".agents/skills/nestjs-best-practices/rules/api-use-interceptors.md",".agents/skills/nestjs-best-practices/rules/api-use-pipes.md",".agents/skills/nestjs-best-practices/rules/api-versioning.md",".agents/skills/nestjs-best-practices/rules/arch-avoid-circular-deps.md",".agents/skills/nestjs-best-practices/rules/arch-feature-modules.md",".agents/skills/nestjs-best-practices/rules/arch-module-sharing.md",".agents/skills/nestjs-best-practices/rules/arch-single-responsibility.md",".agents/skills/nestjs-best-practices/rules/arch-use-events.md",".agents/skills/nestjs-best-practices/rules/arch-use-repository-pattern.md",".agents/skills/nestjs-best-practices/rules/db-avoid-n-plus-one.md",".agents/skills/nestjs-best-practices/rules/db-use-migrations.md",".agents/skills/nestjs-best-practices/rules/db-use-transactions.md",".agents/skills/nestjs-best-practices/rules/devops-graceful-shutdown.md",".agents/skills/nestjs-best-practices/rules/devops-use-config-module.md",".agents/skills/nestjs-best-practices/rules/devops-use-logging.md",".agents/skills/nestjs-best-practices/rules/di-avoid-service-locator.md",".agents/skills/nestjs-best-practices/rules/di-interface-segregation.md",".agents/skills/nestjs-best-practices/rules/di-liskov-substitution.md",".agents/skills/nestjs-best-practices/rules/di-prefer-constructor-injection.md",".agents/skills/nestjs-best-practices/rules/di-scope-awareness.md",".agents/skills/nestjs-best-practices/rules/di-use-interfaces-tokens.md",".agents/skills/nestjs-best-practices/rules/error-handle-async-errors.md",".agents/skills/nestjs-best-practices/rules/error-throw-http-exceptions.md",".agents/skills/nestjs-best-practices/rules/error-use-exception-filters.md",".agents/skills/nestjs-best-practices/rules/micro-use-health-checks.md",".agents/skills/nestjs-best-practices/rules/micro-use-patterns.md",".agents/skills/nestjs-best-practices/rules/micro-use-queues.md",".agents/skills/nestjs-best-practices/rules/perf-async-hooks.md",".agents/skills/nestjs-best-practices/rules/perf-lazy-loading.md",".agents/skills/nestjs-best-practices/rules/perf-optimize-database.md",".agents/skills/nestjs-best-practices/rules/perf-use-caching.md",".agents/skills/nestjs-best-practices/rules/security-auth-jwt.md",".agents/skills/nestjs-best-practices/rules/security-rate-limiting.md",".agents/skills/nestjs-best-practices/rules/security-sanitize-output.md",".agents/skills/nestjs-best-practices/rules/security-use-guards.md",".agents/skills/nestjs-best-practices/rules/security-validate-all-input.md",".agents/skills/nestjs-best-practices/rules/test-e2e-supertest.md",".agents/skills/nestjs-best-practices/rules/test-mock-external-services.md",".agents/skills/nestjs-best-practices/rules/test-use-testing-module.md",".agents/skills/nestjs-trpc/SKILL.md",".agents/skills/nestjs-trpc/references/api-reference.md",".agents/skills/nestjs-trpc/references/codegen-and-client.md",".agents/skills/nestjs-trpc/references/middlewares-and-context.md",".agents/skills/nestjs-trpc/references/module-config.md",".agents/skills/nestjs-trpc/references/routers.md",".agents/skills/no-use-effect/SKILL.md",".agents/skills/nuqs/AGENTS.md",".agents/skills/nuqs/README.md",".agents/skills/nuqs/SKILL.md",".agents/skills/nuqs/assets/templates/_template.md",".agents/skills/nuqs/references/_sections.md",".agents/skills/nuqs/references/advanced-custom-parsers.md",".agents/skills/nuqs/references/advanced-eq-function.md",".agents/skills/nuqs/references/advanced-framework-adapters.md",".agents/skills/nuqs/references/advanced-process-url-search-params.md",".agents/skills/nuqs/references/advanced-url-keys.md",".agents/skills/nuqs/references/debug-enable-logging.md",".agents/skills/nuqs/references/debug-testing.md",".agents/skills/nuqs/references/history-push-navigation.md",".agents/skills/nuqs/references/history-scroll-behavior.md",".agents/skills/nuqs/references/parser-array-format.md",".agents/skills/nuqs/references/parser-date-format.md",".agents/skills/nuqs/references/parser-enum-validation.md",".agents/skills/nuqs/references/parser-index-offset.md",".agents/skills/nuqs/references/parser-json-validation.md",".agents/skills/nuqs/references/parser-use-typed-parsers.md",".agents/skills/nuqs/references/parser-with-default.md",".agents/skills/nuqs/references/perf-avoid-rerender.md",".agents/skills/nuqs/references/perf-clear-on-default.md",".agents/skills/nuqs/references/perf-debounce-search.md",".agents/skills/nuqs/references/perf-key-isolation.md",".agents/skills/nuqs/references/perf-serialize-utility.md",".agents/skills/nuqs/references/perf-throttle-updates.md",".agents/skills/nuqs/references/server-next15-async.md",".agents/skills/nuqs/references/server-parse-before-get.md",".agents/skills/nuqs/references/server-search-params-cache.md",".agents/skills/nuqs/references/server-shallow-false.md",".agents/skills/nuqs/references/server-use-transition.md",".agents/skills/nuqs/references/setup-default-options.md",".agents/skills/nuqs/references/setup-import-server.md",".agents/skills/nuqs/references/setup-nextjs-version.md",".agents/skills/nuqs/references/setup-nuqs-adapter.md",".agents/skills/nuqs/references/setup-shared-parsers.md",".agents/skills/nuqs/references/setup-use-client.md",".agents/skills/nuqs/references/state-avoid-derived.md",".agents/skills/nuqs/references/state-clear-with-null.md",".agents/skills/nuqs/references/state-options-inheritance.md",".agents/skills/nuqs/references/state-setter-return.md",".agents/skills/nuqs/references/state-standard-schema.md",".agents/skills/nuqs/references/state-use-query-states.md",".agents/skills/pit-of-success/SKILL.md",".agents/skills/posthog-instrumentation/SKILL.md",".agents/skills/prepare-branch-context/SKILL.md",".agents/skills/prisma-database-setup/SKILL.md",".agents/skills/prisma-database-setup/references/cockroachdb.md",".agents/skills/prisma-database-setup/references/mongodb.md",".agents/skills/prisma-database-setup/references/mysql.md",".agents/skills/prisma-database-setup/references/postgresql.md",".agents/skills/prisma-database-setup/references/prisma-client-setup.md",".agents/skills/prisma-database-setup/references/prisma-postgres.md",".agents/skills/prisma-database-setup/references/sqlite.md",".agents/skills/prisma-database-setup/references/sqlserver.md",".agents/skills/seo-audit/SKILL.md",".agents/skills/seo-audit/evals/evals.json",".agents/skills/seo-audit/references/ai-writing-detection.md",".agents/skills/seo-audit/references/international-seo.md",".agents/skills/shadcn/SKILL.md",".agents/skills/shadcn/cli.md",".agents/skills/shadcn/customization.md",".agents/skills/shadcn/evals/evals.json",".agents/skills/shadcn/mcp.md",".agents/skills/shadcn/registry.md",".agents/skills/shadcn/rules/base-vs-radix.md",".agents/skills/shadcn/rules/chat.md",".agents/skills/shadcn/rules/composition.md",".agents/skills/shadcn/rules/forms.md",".agents/skills/shadcn/rules/icons.md",".agents/skills/shadcn/rules/styling.md",".agents/skills/skill-creator/SKILL.md",".agents/skills/skill-creator/agents/analyzer.md",".agents/skills/skill-creator/agents/comparator.md",".agents/skills/skill-creator/agents/grader.md",".agents/skills/skill-creator/references/schemas.md",".agents/skills/turborepo/SKILL.md",".agents/skills/turborepo/command/turborepo.md",".agents/skills/turborepo/references/best-practices/RULE.md",".agents/skills/turborepo/references/best-practices/dependencies.md",".agents/skills/turborepo/references/best-practices/packages.md",".agents/skills/turborepo/references/best-practices/structure.md",".agents/skills/turborepo/references/boundaries/RULE.md",".agents/skills/turborepo/references/caching/RULE.md",".agents/skills/turborepo/references/caching/gotchas.md",".agents/skills/turborepo/references/caching/remote-cache.md",".agents/skills/turborepo/references/ci/RULE.md",".agents/skills/turborepo/references/ci/github-actions.md",".agents/skills/turborepo/references/ci/patterns.md",".agents/skills/turborepo/references/ci/vercel.md",".agents/skills/turborepo/references/cli/RULE.md",".agents/skills/turborepo/references/cli/commands.md",".agents/skills/turborepo/references/configuration/RULE.md",".agents/skills/turborepo/references/configuration/global-options.md",".agents/skills/turborepo/references/configuration/gotchas.md",".agents/skills/turborepo/references/configuration/tasks.md",".agents/skills/turborepo/references/environment/RULE.md",".agents/skills/turborepo/references/environment/gotchas.md",".agents/skills/turborepo/references/environment/modes.md",".agents/skills/turborepo/references/filtering/RULE.md",".agents/skills/turborepo/references/filtering/patterns.md",".agents/skills/turborepo/references/watch/RULE.md",".agents/skills/typescript-advanced-types/SKILL.md",".agents/skills/typescript-advanced-types/references/details.md",".agents/skills/ux-flow-plan/SKILL.md",".agents/skills/vercel-composition-patterns/AGENTS.md",".agents/skills/vercel-composition-patterns/README.md",".agents/skills/vercel-composition-patterns/SKILL.md",".agents/skills/vercel-composition-patterns/metadata.json",".agents/skills/vercel-composition-patterns/rules/_sections.md",".agents/skills/vercel-composition-patterns/rules/_template.md",".agents/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md",".agents/skills/vercel-composition-patterns/rules/architecture-compound-components.md",".agents/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md",".agents/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md",".agents/skills/vercel-composition-patterns/rules/react19-no-forwardref.md",".agents/skills/vercel-composition-patterns/rules/state-context-interface.md",".agents/skills/vercel-composition-patterns/rules/state-decouple-implementation.md",".agents/skills/vercel-composition-patterns/rules/state-lift-state.md",".agents/skills/vercel-react-best-practices/AGENTS.md",".agents/skills/vercel-react-best-practices/README.md",".agents/skills/vercel-react-best-practices/SKILL.md",".agents/skills/vercel-react-best-practices/metadata.json",".agents/skills/vercel-react-best-practices/rules/_sections.md",".agents/skills/vercel-react-best-practices/rules/_template.md",".agents/skills/vercel-react-best-practices/rules/advanced-effect-event-deps.md",".agents/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md",".agents/skills/vercel-react-best-practices/rules/advanced-init-once.md",".agents/skills/vercel-react-best-practices/rules/advanced-use-latest.md",".agents/skills/vercel-react-best-practices/rules/async-api-routes.md",".agents/skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md",".agents/skills/vercel-react-best-practices/rules/async-defer-await.md",".agents/skills/vercel-react-best-practices/rules/async-dependencies.md",".agents/skills/vercel-react-best-practices/rules/async-parallel.md",".agents/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md",".agents/skills/vercel-react-best-practices/rules/bundle-analyzable-paths.md",".agents/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md",".agents/skills/vercel-react-best-practices/rules/bundle-conditional.md",".agents/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md",".agents/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md",".agents/skills/vercel-react-best-practices/rules/bundle-preload.md",".agents/skills/vercel-react-best-practices/rules/client-event-listeners.md",".agents/skills/vercel-react-best-practices/rules/client-localstorage-schema.md",".agents/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md",".agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md",".agents/skills/vercel-react-best-practices/rules/js-batch-dom-css.md",".agents/skills/vercel-react-best-practices/rules/js-cache-function-results.md",".agents/skills/vercel-react-best-practices/rules/js-cache-property-access.md",".agents/skills/vercel-react-best-practices/rules/js-cache-storage.md",".agents/skills/vercel-react-best-practices/rules/js-combine-iterations.md",".agents/skills/vercel-react-best-practices/rules/js-early-exit.md",".agents/skills/vercel-react-best-practices/rules/js-flatmap-filter.md",".agents/skills/vercel-react-best-practices/rules/js-hoist-regexp.md",".agents/skills/vercel-react-best-practices/rules/js-index-maps.md",".agents/skills/vercel-react-best-practices/rules/js-length-check-first.md",".agents/skills/vercel-react-best-practices/rules/js-min-max-loop.md",".agents/skills/vercel-react-best-practices/rules/js-request-idle-callback.md",".agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md",".agents/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md",".agents/skills/vercel-react-best-practices/rules/rendering-activity.md",".agents/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md",".agents/skills/vercel-react-best-practices/rules/rendering-conditional-render.md",".agents/skills/vercel-react-best-practices/rules/rendering-content-visibility.md",".agents/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md",".agents/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md",".agents/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md",".agents/skills/vercel-react-best-practices/rules/rendering-resource-hints.md",".agents/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md",".agents/skills/vercel-react-best-practices/rules/rendering-svg-precision.md",".agents/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md",".agents/skills/vercel-react-best-practices/rules/rerender-defer-reads.md",".agents/skills/vercel-react-best-practices/rules/rerender-dependencies.md",".agents/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md",".agents/skills/vercel-react-best-practices/rules/rerender-derived-state.md",".agents/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md",".agents/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md",".agents/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md",".agents/skills/vercel-react-best-practices/rules/rerender-memo.md",".agents/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md",".agents/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md",".agents/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md",".agents/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md",".agents/skills/vercel-react-best-practices/rules/rerender-transitions.md",".agents/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md",".agents/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md",".agents/skills/vercel-react-best-practices/rules/server-after-nonblocking.md",".agents/skills/vercel-react-best-practices/rules/server-auth-actions.md",".agents/skills/vercel-react-best-practices/rules/server-cache-lru.md",".agents/skills/vercel-react-best-practices/rules/server-cache-react.md",".agents/skills/vercel-react-best-practices/rules/server-dedup-props.md",".agents/skills/vercel-react-best-practices/rules/server-hoist-static-io.md",".agents/skills/vercel-react-best-practices/rules/server-no-shared-module-state.md",".agents/skills/vercel-react-best-practices/rules/server-parallel-fetching.md",".agents/skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md",".agents/skills/vercel-react-best-practices/rules/server-serialization.md",".agents/skills/web-design-guidelines/SKILL.md",".agents/skills/zero-tech-debt/SKILL.md","AGENTS.md","CLAUDE.md","apps/agent/agent/skills/data-boundaries.md","apps/agent/agent/skills/evidence.md","apps/agent/agent/skills/identity-matching.md","apps/agent/agent/skills/writing-a-brief.md","docs/api.md","docs/design.md","packages/auth/README.md","packages/db/README.md"],"skills":{".agents/skills/ai-elements/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fai-elements%2FSKILL.md -->",".agents/skills/ai-elements/references/agent.md":"# Agent\n\nA composable component for displaying AI agent configuration with model, instructions, tools, and output schema.\n\nThe `Agent` component displays an interface for showing AI agent configuration details. It's designed to represent a configured agent from the AI SDK, showing the agent's model, system instructions, available tools (with expandable input schemas), and output schema.\n\nSee `scripts/agent.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add agent\n```\n\n## Usage with AI SDK\n\nDisplay an agent's configuration alongside your chat interface. Tools are displayed in an accordion where clicking the description expands to show the input schema.\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport {\n  Agent,\n  AgentContent,\n  AgentHeader,\n  AgentInstructions,\n  AgentOutput,\n  AgentTool,\n  AgentTools,\n} from \"@/components/ai-elements/agent\";\n\nconst webSearch = tool({\n  description: \"Search the web for information\",\n  inputSchema: z.object({\n    query: z.string().describe(\"The search query\"),\n  }),\n});\n\nconst readUrl = tool({\n  description: \"Read and parse content from a URL\",\n  inputSchema: z.object({\n    url: z.string().url().describe(\"The URL to read\"),\n  }),\n});\n\nconst outputSchema = `z.object({\n  sentiment: z.enum(['positive', 'negative', 'neutral']),\n  score: z.number(),\n  summary: z.string(),\n})`;\n\nexport default function Page() {\n  return (\n    <Agent>\n      <AgentHeader\n        name=\"Sentiment Analyzer\"\n        model=\"anthropic/claude-sonnet-4-5\"\n      />\n      <AgentContent>\n        <AgentInstructions>\n          Analyze the sentiment of the provided text and return a structured\n          analysis with sentiment classification, confidence score, and summary.\n        </AgentInstructions>\n        <AgentTools>\n          <AgentTool tool={webSearch} value=\"web_search\" />\n          <AgentTool tool={readUrl} value=\"read_url\" />\n        </AgentTools>\n        <AgentOutput schema={outputSchema} />\n      </AgentContent>\n    </Agent>\n  );\n}\n```\n\n## Features\n\n- Model badge in header\n- Instructions rendered as markdown\n- Tools displayed as accordion items with expandable input schemas\n- Output schema display with syntax highlighting\n- Composable structure for flexible layouts\n- Works with AI SDK `Tool` type\n\n## Props\n\n### `<Agent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any props are spread to the root div. |\n\n### `<AgentHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | The name of the agent. |\n| `model` | `string` | - | The model identifier (e.g.  |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n### `<AgentContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n### `<AgentInstructions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | Required | The instruction text. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n### `<AgentTools />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Accordion>` | - | Any other props are spread to the Accordion component. |\n\n### `<AgentTool />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tool` | `Tool` | Required | The tool object from the AI SDK containing description and inputSchema. |\n| `value` | `string` | Required | Unique identifier for the accordion item. |\n| `...props` | `React.ComponentProps<typeof AccordionItem>` | - | Any other props are spread to the AccordionItem component. |\n\n### `<AgentOutput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `schema` | `string` | Required | The output schema as a string (displayed with syntax highlighting). |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n",".agents/skills/ai-elements/references/artifact.md":"# Artifact\n\nA container component for displaying generated content like code, documents, or other outputs with built-in actions.\n\nThe `Artifact` component provides a structured container for displaying generated content like code, documents, or other outputs with built-in header actions.\n\nSee `scripts/artifact.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add artifact\n```\n\n## Features\n\n- Structured container with header and content areas\n- Built-in header with title and description support\n- Flexible action buttons with tooltips\n- Customizable styling for all subcomponents\n- Support for close buttons and action groups\n- Clean, modern design with border and shadow\n- Responsive layout that adapts to content\n- TypeScript support with proper type definitions\n- Composable architecture for maximum flexibility\n\n## Examples\n\n### With Code Display\n\nSee `scripts/artifact.tsx` for this example.\n\n## Props\n\n### `<Artifact />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n### `<ArtifactHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n### `<ArtifactTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Any other props are spread to the underlying paragraph element. |\n\n### `<ArtifactDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Any other props are spread to the underlying paragraph element. |\n\n### `<ArtifactActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n### `<ArtifactAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string` | - | Tooltip text to display on hover. |\n| `label` | `string` | - | Screen reader label for the action button. |\n| `icon` | `LucideIcon` | - | Lucide icon component to display in the button. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<ArtifactClose />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<ArtifactContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n",".agents/skills/ai-elements/references/attachments.md":"# Attachments\n\nA flexible, composable attachment component for displaying files, images, videos, audio, and source documents.\n\nThe `Attachment` component provides a unified way to display file attachments and source documents with multiple layout variants.\n\nSee `scripts/attachments.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add attachments\n```\n\n## Usage with AI SDK\n\nDisplay user-uploaded files in chat messages or input areas.\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Attachments,\n  Attachment,\n  AttachmentPreview,\n  AttachmentInfo,\n  AttachmentRemove,\n} from \"@/components/ai-elements/attachments\";\nimport type { FileUIPart } from \"ai\";\n\ninterface MessageProps {\n  attachments: (FileUIPart & { id: string })[];\n  onRemove?: (id: string) => void;\n}\n\nconst MessageAttachments = ({ attachments, onRemove }: MessageProps) => (\n  <Attachments variant=\"grid\">\n    {attachments.map((file) => (\n      <Attachment\n        key={file.id}\n        data={file}\n        onRemove={onRemove ? () => onRemove(file.id) : undefined}\n      >\n        <AttachmentPreview />\n        <AttachmentRemove />\n      </Attachment>\n    ))}\n  </Attachments>\n);\n\nexport default MessageAttachments;\n```\n\n## Features\n\n- Three display variants: grid (thumbnails), inline (badges), and list (rows)\n- Supports both FileUIPart and SourceDocumentUIPart from the AI SDK\n- Automatic media type detection (image, video, audio, document, source)\n- Hover card support for inline previews\n- Remove button with customizable callback\n- Composable architecture for maximum flexibility\n- Accessible with proper ARIA labels\n- TypeScript support with exported utility functions\n\n## Examples\n\n### Grid Variant\n\nBest for displaying attachments in messages with visual thumbnails.\n\nSee `scripts/attachments.tsx` for this example.\n\n### Inline Variant\n\nBest for compact badge-style display in input areas with hover previews.\n\nSee `scripts/attachments-inline.tsx` for this example.\n\n### List Variant\n\nBest for file lists with full metadata display.\n\nSee `scripts/attachments-list.tsx` for this example.\n\n## Props\n\n### `<Attachments />`\n\nContainer component that sets the layout variant.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `variant` | `unknown` | - | The display layout variant. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<Attachment />`\n\nIndividual attachment item wrapper.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `data` | `unknown` | - | The attachment data (FileUIPart or SourceDocumentUIPart with id). |\n| `onRemove` | `() => void` | - | Callback fired when the remove button is clicked. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<AttachmentPreview />`\n\nDisplays the media preview (image, video, or icon).\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `fallbackIcon` | `React.ReactNode` | - | Custom icon to display when no preview is available. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<AttachmentInfo />`\n\nDisplays the filename and optional media type.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `showMediaType` | `boolean` | `false` | Whether to show the media type below the filename. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<AttachmentRemove />`\n\nRemove button that appears on hover.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | Screen reader label for the button. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the underlying Button component. |\n\n### `<AttachmentHoverCard />`\n\nWrapper for hover preview functionality.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `openDelay` | `number` | `0` | Delay in ms before opening the hover card. |\n| `closeDelay` | `number` | `0` | Delay in ms before closing the hover card. |\n| `...props` | `React.ComponentProps<typeof HoverCard>` | - | Spread to the underlying HoverCard component. |\n\n### `<AttachmentHoverCardTrigger />`\n\nTrigger element for the hover card.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof HoverCardTrigger>` | - | Spread to the underlying HoverCardTrigger component. |\n\n### `<AttachmentHoverCardContent />`\n\nContent displayed in the hover card.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `align` | `unknown` | - | Alignment of the hover card content. |\n| `...props` | `React.ComponentProps<typeof HoverCardContent>` | - | Spread to the underlying HoverCardContent component. |\n\n### `<AttachmentEmpty />`\n\nEmpty state component when no attachments are present.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n## Utility Functions\n\n### `getMediaCategory(data)`\n\nReturns the media category for an attachment.\n\n```tsx\nimport { getMediaCategory } from \"@/components/ai-elements/attachments\";\n\nconst category = getMediaCategory(attachment);\n// Returns: \"image\" | \"video\" | \"audio\" | \"document\" | \"source\" | \"unknown\"\n```\n\n### `getAttachmentLabel(data)`\n\nReturns the display label for an attachment.\n\n```tsx\nimport { getAttachmentLabel } from \"@/components/ai-elements/attachments\";\n\nconst label = getAttachmentLabel(attachment);\n// Returns filename or fallback like \"Image\" or \"Attachment\"\n```\n",".agents/skills/ai-elements/references/audio-player.md":"# Audio Player\n\nA composable audio player component built on media-chrome, with shadcn styling and flexible controls.\n\nThe `AudioPlayer` component provides a flexible and customizable audio playback interface built on top of media-chrome. It features a composable architecture that allows you to build audio experiences with custom controls, metadata display, and seamless integration with AI-generated audio content.\n\nSee `scripts/audio-player.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add audio-player\n```\n\n## Features\n\n- Built on media-chrome for reliable audio playback\n- Fully composable architecture with granular control components\n- ButtonGroup integration for cohesive control layout\n- Individual control components (play, seek, volume, etc.)\n- Flexible layout with customizable control bars\n- CSS custom properties for deep theming\n- Shadcn/ui Button component styling\n- Responsive design that works across devices\n- Full TypeScript support with proper types for all components\n\n## Variants\n\n### AI SDK Speech Result\n\nThe `AudioPlayer` component can be used to play audio from an AI SDK Speech Result.\n\nSee `scripts/audio-player.tsx` for this example.\n\n### Remote Audio\n\nThe `AudioPlayer` component can be used to play remote audio files.\n\nSee `scripts/audio-player-remote.tsx` for this example.\n\n## Props\n\n### `<AudioPlayer />`\n\nRoot MediaController component. Accepts all MediaController props except `audio` (which is set to `true` by default).\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `style` | `CSSProperties` | - | Custom CSS properties can be passed to override media-chrome theming variables. |\n| `...props` | `Omit<React.ComponentProps<typeof MediaController>, ` | - | Any other props are spread to the MediaController component. |\n\n### `<AudioPlayerElement />`\n\nThe audio element that contains the media source. Accepts either a remote URL or AI SDK Speech Result data.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `src` | `string` | - | The URL of the audio file to play (for remote audio). |\n| `data` | `SpeechResult[` | - | AI SDK Speech Result audio data with base64 encoding (for AI-generated audio). |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the audio element (excluding src when using data). |\n\n### `<AudioPlayerControlBar />`\n\nContainer for control buttons, wraps children in a ButtonGroup.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaControlBar>` | - | Any other props are spread to the MediaControlBar component. |\n\n### `<AudioPlayerPlayButton />`\n\nPlay/pause button wrapped in a shadcn Button component.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaPlayButton>` | - | Any other props are spread to the MediaPlayButton component. |\n\n### `<AudioPlayerSeekBackwardButton />`\n\nSeek backward button wrapped in a shadcn Button component.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `seekOffset` | `number` | `10` | The number of seconds to seek backward. |\n| `...props` | `React.ComponentProps<typeof MediaSeekBackwardButton>` | - | Any other props are spread to the MediaSeekBackwardButton component. |\n\n### `<AudioPlayerSeekForwardButton />`\n\nSeek forward button wrapped in a shadcn Button component.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `seekOffset` | `number` | `10` | The number of seconds to seek forward. |\n| `...props` | `React.ComponentProps<typeof MediaSeekForwardButton>` | - | Any other props are spread to the MediaSeekForwardButton component. |\n\n### `<AudioPlayerTimeDisplay />`\n\nDisplays the current playback time, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaTimeDisplay>` | - | Any other props are spread to the MediaTimeDisplay component. |\n\n### `<AudioPlayerTimeRange />`\n\nSeek slider for controlling playback position, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaTimeRange>` | - | Any other props are spread to the MediaTimeRange component. |\n\n### `<AudioPlayerDurationDisplay />`\n\nDisplays the total duration of the audio, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaDurationDisplay>` | - | Any other props are spread to the MediaDurationDisplay component. |\n\n### `<AudioPlayerMuteButton />`\n\nMute/unmute button, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaMuteButton>` | - | Any other props are spread to the MediaMuteButton component. |\n\n### `<AudioPlayerVolumeRange />`\n\nVolume slider control, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaVolumeRange>` | - | Any other props are spread to the MediaVolumeRange component. |\n",".agents/skills/ai-elements/references/canvas.md":"# Canvas\n\nA React Flow-based canvas component for building interactive node-based interfaces.\n\nThe `Canvas` component provides a React Flow-based canvas for building interactive node-based interfaces. It comes pre-configured with sensible defaults for AI applications, including panning, zooming, and selection behaviors.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add canvas\n```\n\n## Features\n\n- Pre-configured React Flow canvas with AI-optimized defaults\n- Pan on scroll enabled for intuitive navigation\n- Selection on drag for multi-node operations\n- Customizable background color using CSS variables\n- Delete key support (Backspace and Delete keys)\n- Auto-fit view to show all nodes\n- Disabled double-click zoom for better UX\n- Disabled pan on drag to prevent accidental canvas movement\n- Fully compatible with React Flow props and API\n\n## Props\n\n### `<Canvas />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode` | - | Child components like Background, Controls, or MiniMap. |\n| `...props` | `ReactFlowProps` | - | Any other React Flow props like nodes, edges, nodeTypes, edgeTypes, onNodesChange, etc. |\n",".agents/skills/ai-elements/references/chain-of-thought.md":"# Chain of Thought\n\nA collapsible component that visualizes AI reasoning steps with support for search results, images, and step-by-step progress indicators.\n\nThe `ChainOfThought` component provides a visual representation of an AI's reasoning process, showing step-by-step thinking with support for search results, images, and progress indicators. It helps users understand how AI arrives at conclusions.\n\nSee `scripts/chain-of-thought.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add chain-of-thought\n```\n\n## Features\n\n- Collapsible interface with smooth animations powered by Radix UI\n- Step-by-step visualization of AI reasoning process\n- Support for different step statuses (complete, active, pending)\n- Built-in search results display with badge styling\n- Image support with captions for visual content\n- Custom icons for different step types\n- Context-aware components using React Context API\n- Fully typed with TypeScript\n- Accessible with keyboard navigation support\n- Responsive design that adapts to different screen sizes\n- Smooth fade and slide animations for content transitions\n- Composable architecture for flexible customization\n\n## Props\n\n### `<ChainOfThought />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `open` | `boolean` | - | Controlled open state of the collapsible. |\n| `defaultOpen` | `boolean` | `false` | Default open state when uncontrolled. |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback when the open state changes. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div element. |\n\n### `<ChainOfThoughtHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom header text. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<ChainOfThoughtStep />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `icon` | `LucideIcon` | `DotIcon` | Icon to display for the step. |\n| `label` | `string` | - | The main text label for the step. |\n| `description` | `string` | - | Optional description text shown below the label. |\n| `status` | `unknown` | - | Visual status of the step. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div element. |\n\n### `<ChainOfThoughtSearchResults />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any props are spread to the container div element. |\n\n### `<ChainOfThoughtSearchResult />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Badge>` | - | Any props are spread to the Badge component. |\n\n### `<ChainOfThoughtContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any props are spread to the CollapsibleContent component. |\n\n### `<ChainOfThoughtImage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `caption` | `string` | - | Optional caption text displayed below the image. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div element. |\n",".agents/skills/ai-elements/references/checkpoint.md":"# Checkpoint\n\nA simple component for marking conversation history points and restoring the chat to a previous state.\n\nThe `Checkpoint` component provides a way to mark specific points in a conversation history and restore the chat to that state. Inspired by VSCode's Copilot checkpoint feature, it allows users to revert to an earlier conversation state while maintaining a clear visual separation between different conversation segments.\n\nSee `scripts/checkpoint.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add checkpoint\n```\n\n## Features\n\n- Simple flex layout with icon, trigger, and separator\n- Visual separator line for clear conversation breaks\n- Clickable restore button for reverting to checkpoint\n- Customizable icon (defaults to BookmarkIcon)\n- Keyboard accessible with proper ARIA labels\n- Responsive design that adapts to different screen sizes\n- Seamless light/dark theme integration\n\n## Usage with AI SDK\n\nBuild a chat interface with conversation checkpoints that allow users to restore to previous states.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useState, Fragment } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  Checkpoint,\n  CheckpointIcon,\n  CheckpointTrigger,\n} from \"@/components/ai-elements/checkpoint\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport {\n  Conversation,\n  ConversationContent,\n} from \"@/components/ai-elements/conversation\";\n\ntype CheckpointType = {\n  id: string;\n  messageIndex: number;\n  timestamp: Date;\n  messageCount: number;\n};\n\nconst CheckpointDemo = () => {\n  const { messages, setMessages } = useChat();\n  const [checkpoints, setCheckpoints] = useState<CheckpointType[]>([]);\n\n  const createCheckpoint = (messageIndex: number) => {\n    const checkpoint: CheckpointType = {\n      id: nanoid(),\n      messageIndex,\n      timestamp: new Date(),\n      messageCount: messageIndex + 1,\n    };\n    setCheckpoints([...checkpoints, checkpoint]);\n  };\n\n  const restoreToCheckpoint = (messageIndex: number) => {\n    // Restore messages to checkpoint state\n    setMessages(messages.slice(0, messageIndex + 1));\n    // Remove checkpoints after this point\n    setCheckpoints(checkpoints.filter((cp) => cp.messageIndex <= messageIndex));\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <Conversation>\n        <ConversationContent>\n          {messages.map((message, index) => {\n            const checkpoint = checkpoints.find(\n              (cp) => cp.messageIndex === index\n            );\n\n            return (\n              <Fragment key={message.id}>\n                <Message from={message.role}>\n                  <MessageContent>\n                    <MessageResponse>{message.content}</MessageResponse>\n                  </MessageContent>\n                </Message>\n                {checkpoint && (\n                  <Checkpoint>\n                    <CheckpointIcon />\n                    <CheckpointTrigger\n                      onClick={() =>\n                        restoreToCheckpoint(checkpoint.messageIndex)\n                      }\n                    >\n                      Restore checkpoint\n                    </CheckpointTrigger>\n                  </Checkpoint>\n                )}\n              </Fragment>\n            );\n          })}\n        </ConversationContent>\n      </Conversation>\n    </div>\n  );\n};\n\nexport default CheckpointDemo;\n```\n\n## Use Cases\n\n### Manual Checkpoints\n\nAllow users to manually create checkpoints at important conversation points:\n\n```tsx\n<Button onClick={() => createCheckpoint(messages.length - 1)}>\n  Create Checkpoint\n</Button>\n```\n\n### Automatic Checkpoints\n\nCreate checkpoints automatically after significant conversation milestones:\n\n```tsx\nuseEffect(() => {\n  // Create checkpoint every 5 messages\n  if (messages.length > 0 && messages.length % 5 === 0) {\n    createCheckpoint(messages.length - 1);\n  }\n}, [messages.length]);\n```\n\n### Branching Conversations\n\nUse checkpoints to enable conversation branching where users can explore different conversation paths:\n\n```tsx\nconst restoreAndBranch = (messageIndex: number) => {\n  // Save current branch\n  const currentBranch = messages.slice(messageIndex + 1);\n  saveBranch(currentBranch);\n\n  // Restore to checkpoint\n  restoreToCheckpoint(messageIndex);\n};\n```\n\n## Props\n\n### `<Checkpoint />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The checkpoint icon and trigger components. Automatically includes a Separator at the end. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<CheckpointIcon />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom icon content. If not provided, defaults to a BookmarkIcon from lucide-react. |\n| `...props` | `LucideProps` | - | Any other props are spread to the BookmarkIcon component. |\n\n### `<CheckpointTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The text or content to display in the trigger button. |\n| `tooltip` | `string` | - | Optional tooltip text shown on hover. |\n| `variant` | `string` | - | The button variant style. |\n| `size` | `string` | - | The button size. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n",".agents/skills/ai-elements/references/code-block.md":"# Code Block\n\nProvides syntax highlighting, line numbers, and copy to clipboard functionality for code blocks.\n\nThe `CodeBlock` component provides syntax highlighting, line numbers, and copy to clipboard functionality for code blocks. It's fully composable, allowing you to customize the header, actions, and content.\n\nSee `scripts/code-block.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add code-block\n```\n\n## Usage\n\nThe CodeBlock is fully composable. Here's a basic example:\n\n```tsx\nimport {\n  CodeBlock,\n  CodeBlockActions,\n  CodeBlockCopyButton,\n  CodeBlockFilename,\n  CodeBlockHeader,\n  CodeBlockTitle,\n} from \"@/components/ai-elements/code-block\";\nimport { FileIcon } from \"lucide-react\";\n\nexport const Example = () => (\n  <CodeBlock code={code} language=\"typescript\">\n    <CodeBlockHeader>\n      <CodeBlockTitle>\n        <FileIcon size={14} />\n        <CodeBlockFilename>example.ts</CodeBlockFilename>\n      </CodeBlockTitle>\n      <CodeBlockActions>\n        <CodeBlockCopyButton />\n      </CodeBlockActions>\n    </CodeBlockHeader>\n  </CodeBlock>\n);\n```\n\n## Features\n\n- Syntax highlighting with Shiki\n- Line numbers (optional)\n- Copy to clipboard functionality\n- Automatic light/dark theme switching via CSS variables\n- Language selector for multi-language examples\n- Fully composable architecture\n- Accessible design\n\n## Examples\n\n### Dark Mode\n\nTo use the `CodeBlock` component in dark mode, wrap it in a `div` with the `dark` class.\n\nSee `scripts/code-block-dark.tsx` for this example.\n\n### Language Selector\n\nAdd a language selector to switch between different code implementations:\n\nSee `scripts/code-block.tsx` for this example.\n\n## Props\n\n### `<CodeBlock />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `code` | `string` | - | The code content to display. |\n| `language` | `BundledLanguage` | - | The programming language for syntax highlighting. |\n| `showLineNumbers` | `boolean` | `false` | Whether to show line numbers. |\n| `children` | `React.ReactNode` | - | Child elements like CodeBlockHeader. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockHeader />`\n\nContainer for the header row. Uses flexbox with `justify-between`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Header content (CodeBlockTitle, CodeBlockActions, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockTitle />`\n\nLeft-aligned container for icon and filename. Uses flexbox with `gap-2`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Title content (icon, CodeBlockFilename, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockFilename />`\n\nDisplays the filename in monospace font.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The filename to display. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockActions />`\n\nRight-aligned container for action buttons. Uses flexbox with `gap-2`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Action buttons (CodeBlockCopyButton, CodeBlockLanguageSelector, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback fired after a successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback fired if copying fails. |\n| `timeout` | `number` | `2000` | How long to show the copied state (ms). |\n| `children` | `React.ReactNode` | - | Custom content for the button. Defaults to copy/check icons. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockLanguageSelector />`\n\nWrapper for the language selector. Extends shadcn/ui Select.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The currently selected language. |\n| `onValueChange` | `(value: string) => void` | - | Callback when the language changes. |\n| `children` | `React.ReactNode` | - | Selector components (Trigger, Content, Items). |\n\n### `<CodeBlockLanguageSelectorTrigger />`\n\nTrigger button for the language selector dropdown. Pre-styled for code block header.\n\n### `<CodeBlockLanguageSelectorValue />`\n\nDisplays the selected language value.\n\n### `<CodeBlockLanguageSelectorContent />`\n\nDropdown content container. Defaults to `align=\"end\"`.\n\n### `<CodeBlockLanguageSelectorItem />`\n\nIndividual language option in the dropdown.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The language value. |\n| `children` | `React.ReactNode` | - | The display label. |\n\n### `<CodeBlockContainer />`\n\nLow-level container component with performance optimizations (`contentVisibility`). Used internally by CodeBlock.\n\n### `<CodeBlockContent />`\n\nLow-level component that handles syntax highlighting. Used internally by CodeBlock, but can be used directly for custom layouts.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `code` | `string` | - | The code content to display. |\n| `language` | `BundledLanguage` | - | The programming language for syntax highlighting. |\n| `showLineNumbers` | `boolean` | `false` | Whether to show line numbers. |\n",".agents/skills/ai-elements/references/commit.md":"# Commit\n\nDisplay commit information with hash, message, author, and file changes.\n\nThe `Commit` component displays commit details including hash, message, author, timestamp, and changed files.\n\nSee `scripts/commit.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add commit\n```\n\n## Features\n\n- Commit hash display with copy button\n- Author avatar with initials\n- Relative timestamp formatting\n- Collapsible file changes list\n- Color-coded file status (added/modified/deleted/renamed)\n- Line additions/deletions count\n\n## File Status\n\n| Status     | Label | Color  |\n| ---------- | ----- | ------ |\n| `added`    | A     | Green  |\n| `modified` | M     | Yellow |\n| `deleted`  | D     | Red    |\n| `renamed`  | R     | Blue   |\n\n## Props\n\n### `<Commit />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Spread to the Collapsible component. |\n\n### `<CommitHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Spread to the CollapsibleTrigger component. |\n\n### `<CommitAuthor />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitAuthorAvatar />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `initials` | `string` | Required | Author initials to display. |\n| `...props` | `React.ComponentProps<typeof Avatar>` | - | Spread to the Avatar component. |\n\n### `<CommitInfo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitMessage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitMetadata />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitHash />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitSeparator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom separator content. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitTimestamp />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `date` | `Date` | Required | Commit date. |\n| `children` | `React.ReactNode` | - | Custom timestamp content. Defaults to relative time. |\n| `...props` | `React.HTMLAttributes<HTMLTimeElement>` | - | Spread to the time element. |\n\n### `<CommitActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `hash` | `string` | Required | Commit hash to copy. |\n| `onCopy` | `() => void` | - | Callback after successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback if copying fails. |\n| `timeout` | `number` | `2000` | Duration to show copied state (ms). |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the Button component. |\n\n### `<CommitContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Spread to the CollapsibleContent component. |\n\n### `<CommitFiles />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the row div. |\n\n### `<CommitFileInfo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitFileStatus />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `status` | `unknown` | Required | File change status. |\n| `children` | `React.ReactNode` | - | Custom status label. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitFileIcon />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof FileIcon>` | - | Spread to the FileIcon component. |\n\n### `<CommitFilePath />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitFileChanges />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitFileAdditions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `count` | `number` | Required | Number of lines added. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitFileDeletions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `count` | `number` | Required | Number of lines deleted. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n",".agents/skills/ai-elements/references/confirmation.md":"# Confirmation\n\nAn alert-based component for managing tool execution approval workflows with request, accept, and reject states.\n\nThe `Confirmation` component provides a flexible system for displaying tool approval requests and their outcomes. Perfect for showing users when AI tools require approval before execution, and displaying the approval status afterward.\n\nSee `scripts/confirmation.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add confirmation\n```\n\n## Usage with AI SDK\n\nBuild a chat UI with tool approval workflow where dangerous tools require user confirmation before execution.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport { DefaultChatTransport, type ToolUIPart } from \"ai\";\nimport { useState } from \"react\";\nimport { CheckIcon, XIcon } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Confirmation,\n  ConfirmationTitle,\n  ConfirmationRequest,\n  ConfirmationAccepted,\n  ConfirmationRejected,\n  ConfirmationActions,\n  ConfirmationAction,\n} from \"@/components/ai-elements/confirmation\";\nimport { MessageResponse } from \"@/components/ai-elements/message\";\n\ntype DeleteFileInput = {\n  filePath: string;\n  confirm: boolean;\n};\n\ntype DeleteFileToolUIPart = ToolUIPart<{\n  delete_file: {\n    input: DeleteFileInput;\n    output: { success: boolean; message: string };\n  };\n}>;\n\nconst Example = () => {\n  const { messages, sendMessage, status, addToolApprovalResponse } = useChat({\n    transport: new DefaultChatTransport({\n      api: \"/api/chat\",\n    }),\n  });\n\n  const handleDeleteFile = () => {\n    sendMessage({ text: \"Delete the file at /tmp/example.txt\" });\n  };\n\n  const latestMessage = messages[messages.length - 1];\n  const deleteTool = latestMessage?.parts?.find(\n    (part) => part.type === \"tool-delete_file\"\n  ) as DeleteFileToolUIPart | undefined;\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full space-y-4\">\n        <Button onClick={handleDeleteFile} disabled={status !== \"ready\"}>\n          Delete Example File\n        </Button>\n\n        {deleteTool?.approval && (\n          <Confirmation approval={deleteTool.approval} state={deleteTool.state}>\n            <ConfirmationRequest>\n              This tool wants to delete:{\" \"}\n              <code>{deleteTool.input?.filePath}</code>\n              <br />\n              Do you approve this action?\n            </ConfirmationRequest>\n            <ConfirmationAccepted>\n              <CheckIcon className=\"size-4\" />\n              <span>You approved this tool execution</span>\n            </ConfirmationAccepted>\n            <ConfirmationRejected>\n              <XIcon className=\"size-4\" />\n              <span>You rejected this tool execution</span>\n            </ConfirmationRejected>\n            <ConfirmationActions>\n              <ConfirmationAction\n                variant=\"outline\"\n                onClick={() =>\n                  addToolApprovalResponse({\n                    id: deleteTool.approval!.id,\n                    approved: false,\n                  })\n                }\n              >\n                Reject\n              </ConfirmationAction>\n              <ConfirmationAction\n                variant=\"default\"\n                onClick={() =>\n                  addToolApprovalResponse({\n                    id: deleteTool.approval!.id,\n                    approved: true,\n                  })\n                }\n              >\n                Approve\n              </ConfirmationAction>\n            </ConfirmationActions>\n          </Confirmation>\n        )}\n\n        {deleteTool?.output && (\n          <MessageResponse>\n            {deleteTool.output.success\n              ? deleteTool.output.message\n              : `Error: ${deleteTool.output.message}`}\n          </MessageResponse>\n        )}\n      </div>\n    </div>\n  );\n};\n\nexport default Example;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/chat/route.tsx\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\nimport { z } from \"zod\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages: await convertToModelMessages(messages),\n    tools: {\n      delete_file: {\n        description: \"Delete a file from the file system\",\n        parameters: z.object({\n          filePath: z.string().describe(\"The path to the file to delete\"),\n          confirm: z\n            .boolean()\n            .default(false)\n            .describe(\"Confirmation that the user wants to delete the file\"),\n        }),\n        requireApproval: true, // Enable approval workflow\n        execute: async ({ filePath, confirm }) => {\n          if (!confirm) {\n            return {\n              success: false,\n              message: \"Deletion not confirmed\",\n            };\n          }\n\n          // Simulate file deletion\n          await new Promise((resolve) => setTimeout(resolve, 500));\n\n          return {\n            success: true,\n            message: `Successfully deleted ${filePath}`,\n          };\n        },\n      },\n    },\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Context-based state management for approval workflow\n- Conditional rendering based on approval state\n- Support for approval-requested, approval-responded, output-denied, and output-available states\n- Built on shadcn/ui Alert and Button components\n- TypeScript support with comprehensive type definitions\n- Customizable styling with Tailwind CSS\n- Keyboard navigation and accessibility support\n- Theme-aware with automatic dark mode support\n\n## Examples\n\n### Approval Request State\n\nShows the approval request with action buttons when state is `approval-requested`.\n\nSee `scripts/confirmation-request.tsx` for this example.\n\n### Approved State\n\nShows the accepted status when user approves and state is `approval-responded` or `output-available`.\n\nSee `scripts/confirmation-accepted.tsx` for this example.\n\n### Rejected State\n\nShows the rejected status when user rejects and state is `output-denied`.\n\nSee `scripts/confirmation-rejected.tsx` for this example.\n\n## Props\n\n### `<Confirmation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `approval` | `ToolUIPart[` | - | The approval object containing the approval ID and status. If not provided or undefined, the component will not render. |\n| `state` | `ToolUIPart[` | - | The current state of the tool (input-streaming, input-available, approval-requested, approval-responded, output-denied, or output-available). Will not render for input-streaming or input-available states. |\n| `className` | `string` | - | Additional CSS classes to apply to the Alert component. |\n| `...props` | `React.ComponentProps<typeof Alert>` | - | Any other props are spread to the Alert component. |\n\n### `<ConfirmationTitle />`\n\nA styled description element for displaying a title or label within the confirmation alert.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof AlertDescription>` | - | Any other props are spread to the underlying AlertDescription component. |\n\n### `<ConfirmationRequest />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The content to display when approval is requested. Only renders when state is  |\n\n### `<ConfirmationAccepted />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The content to display when approval is accepted. Only renders when approval.approved is true and state is  |\n\n### `<ConfirmationRejected />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The content to display when approval is rejected. Only renders when approval.approved is false and state is  |\n\n### `<ConfirmationActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the actions container. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. Only renders when state is  |\n\n### `<ConfirmationAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component. Styled with h-8 px-3 text-sm classes by default. |\n",".agents/skills/ai-elements/references/connection.md":"# Connection\n\nA custom connection line component for React Flow-based canvases with animated bezier curve styling.\n\nThe `Connection` component provides a styled connection line for React Flow canvases. It renders an animated bezier curve with a circle indicator at the target end, using consistent theming through CSS variables.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add connection\n```\n\n## Features\n\n- Smooth bezier curve animation for connection lines\n- Visual indicator circle at the target position\n- Theme-aware styling using CSS variables\n- Cubic bezier curve calculation for natural flow\n- Lightweight implementation with minimal props\n- Full TypeScript support with React Flow types\n- Compatible with React Flow's connection system\n\n## Props\n\n### `<Connection />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `fromX` | `number` | - | The x-coordinate of the connection start point. |\n| `fromY` | `number` | - | The y-coordinate of the connection start point. |\n| `toX` | `number` | - | The x-coordinate of the connection end point. |\n| `toY` | `number` | - | The y-coordinate of the connection end point. |\n",".agents/skills/ai-elements/references/context.md":"# Context\n\nA compound component system for displaying AI model context window usage, token consumption, and cost estimation.\n\nThe `Context` component provides a comprehensive view of AI model usage through a compound component system. It displays context window utilization, token consumption breakdown (input, output, reasoning, cache), and cost estimation in an interactive hover card interface.\n\nSee `scripts/context.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add context\n```\n\n## Features\n\n- **Compound Component Architecture**: Flexible composition of context display elements\n- **Visual Progress Indicator**: Circular SVG progress ring showing context usage percentage\n- **Token Breakdown**: Detailed view of input, output, reasoning, and cached tokens\n- **Cost Estimation**: Real-time cost calculation using the `tokenlens` library\n- **Intelligent Formatting**: Automatic token count formatting (K, M, B suffixes)\n- **Interactive Hover Card**: Detailed information revealed on hover\n- **Context Provider Pattern**: Clean data flow through React Context API\n- **TypeScript Support**: Full type definitions for all components\n- **Accessible Design**: Proper ARIA labels and semantic HTML\n- **Theme Integration**: Uses currentColor for automatic theme adaptation\n\n## Props\n\n### `<Context />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `maxTokens` | `number` | - | The total context window size in tokens. |\n| `usedTokens` | `number` | - | The number of tokens currently used. |\n| `usage` | `LanguageModelUsage` | - | Detailed token usage breakdown from the AI SDK (input, output, reasoning, cached tokens). |\n| `modelId` | `ModelId` | - | Model identifier for cost calculation (e.g.,  |\n| `...props` | `ComponentProps<HoverCard>` | - | Any other props are spread to the HoverCard component. |\n\n### `<ContextTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom trigger element. If not provided, renders a default button with percentage and icon. |\n| `...props` | `ComponentProps<Button>` | - | Props spread to the default button element. |\n\n### `<ContextContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes for the hover card content. |\n| `...props` | `ComponentProps<HoverCardContent>` | - | Props spread to the HoverCardContent component. |\n\n### `<ContextContentHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom header content. If not provided, renders percentage and token count with progress bar. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the header div element. |\n\n### `<ContextContentBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Body content, typically containing usage breakdown components. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the body div element. |\n\n### `<ContextContentFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom footer content. If not provided, renders total cost when modelId is provided. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the footer div element. |\n\n### Usage Components\n\nAll usage components (`ContextInputUsage`, `ContextOutputUsage`, `ContextReasoningUsage`, `ContextCacheUsage`) share the same props:\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom content. If not provided, renders token count and cost for the respective usage type. |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the div element. |\n\n## Component Architecture\n\nThe Context component uses a compound component pattern with React Context for data sharing:\n\n1. **`<Context>`** - Root provider component that holds all context data\n2. **`<ContextTrigger>`** - Interactive trigger element (default: button with percentage)\n3. **`<ContextContent>`** - Hover card content container\n4. **`<ContextContentHeader>`** - Header section with progress visualization\n5. **`<ContextContentBody>`** - Body section for usage breakdowns\n6. **`<ContextContentFooter>`** - Footer section for total cost\n7. **Usage Components** - Individual token usage displays (Input, Output, Reasoning, Cache)\n\n## Token Formatting\n\nThe component uses `Intl.NumberFormat` with compact notation for automatic formatting:\n\n- Under 1,000: Shows exact count (e.g., \"842\")\n- 1,000+: Shows with K suffix (e.g., \"32K\")\n- 1,000,000+: Shows with M suffix (e.g., \"1.5M\")\n- 1,000,000,000+: Shows with B suffix (e.g., \"2.1B\")\n\n## Cost Calculation\n\nWhen a `modelId` is provided, the component automatically calculates costs using the `tokenlens` library:\n\n- **Input tokens**: Cost based on model's input pricing\n- **Output tokens**: Cost based on model's output pricing\n- **Reasoning tokens**: Special pricing for reasoning-capable models\n- **Cached tokens**: Reduced pricing for cached input tokens\n- **Total cost**: Sum of all token type costs\n\nCosts are formatted using `Intl.NumberFormat` with USD currency.\n\n## Styling\n\nThe component uses Tailwind CSS classes and follows your design system:\n\n- Progress indicator uses `currentColor` for theme adaptation\n- Hover card has customizable width and padding\n- Footer has a secondary background for visual separation\n- All text sizes use the `text-xs` class for consistency\n- Muted foreground colors for secondary information\n",".agents/skills/ai-elements/references/controls.md":"# Controls\n\nA styled controls component for React Flow-based canvases with zoom and fit view functionality.\n\nThe `Controls` component provides interactive zoom and fit view controls for React Flow canvases. It includes a modern, themed design with backdrop blur and card styling.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add controls\n```\n\n## Features\n\n- Zoom in/out controls\n- Fit view button to center and scale content\n- Rounded pill design with backdrop blur\n- Theme-aware card background\n- Subtle drop shadow for depth\n- Full TypeScript support\n- Compatible with all React Flow control features\n\n## Props\n\n### `<Controls />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the controls. |\n| `...props` | `ComponentProps<typeof Controls>` | - | Any other props from @xyflow/react Controls component (showZoom, showFitView, showInteractive, position, etc.). |\n",".agents/skills/ai-elements/references/conversation.md":"# Conversation\n\nWraps messages and automatically scrolls to the bottom. Also includes a scroll button that appears when not at the bottom.\n\nThe `Conversation` component wraps messages and automatically scrolls to the bottom. Also includes a scroll button that appears when not at the bottom.\n\n<Preview path=\"conversation\" className=\"p-0\" />\n\n## Installation\n\n```bash\nnpx ai-elements@latest add conversation\n```\n\n## Usage with AI SDK\n\nBuild a simple conversational UI with `Conversation` and [`PromptInput`](/components/prompt-input):\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationDownload,\n  ConversationEmptyState,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { MessageSquare } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\n\nconst ConversationDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { messages, sendMessage, status } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.length === 0 ? (\n              <ConversationEmptyState\n                icon={<MessageSquare className=\"size-12\" />}\n                title=\"Start a conversation\"\n                description=\"Type a message below to begin chatting\"\n              />\n            ) : (\n              messages.map((message) => (\n                <Message from={message.role} key={message.id}>\n                  <MessageContent>\n                    {message.parts.map((part, i) => {\n                      switch (part.type) {\n                        case \"text\": // we don't use any reasoning or tool calls in this example\n                          return (\n                            <MessageResponse key={`${message.id}-${i}`}>\n                              {part.text}\n                            </MessageResponse>\n                          );\n                        default:\n                          return null;\n                      }\n                    })}\n                  </MessageContent>\n                </Message>\n              ))\n            )}\n          </ConversationContent>\n          <ConversationDownload messages={messages} />\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Say something...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ConversationDemo;\n```\n\nAdd the following route to your backend:\n\n```tsx title=\"api/chat/route.ts\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Automatic scrolling to the bottom when new messages are added\n- Smooth scrolling behavior with configurable animation\n- Scroll button that appears when not at the bottom\n- Download conversation as Markdown\n- Responsive design with customizable padding and spacing\n- Flexible content layout with consistent message spacing\n- Accessible with proper ARIA roles for screen readers\n- Customizable styling through className prop\n- Support for any number of child message components\n\n## Props\n\n### `<Conversation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `contextRef` | `React.Ref<StickToBottomContext>` | - | Optional ref to access the StickToBottom context object. |\n| `instance` | `StickToBottomInstance` | - | Optional instance for controlling the StickToBottom component. |\n| `children` | `((context: StickToBottomContext) => ReactNode) | ReactNode` | - | Render prop or ReactNode for custom rendering with context. |\n| `...props` | `Omit<React.HTMLAttributes<HTMLDivElement>, ` | - | Any other props are spread to the root div. |\n\n### `<ConversationContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `((context: StickToBottomContext) => ReactNode) | ReactNode` | - | Render prop or ReactNode for custom rendering with context. |\n| `...props` | `Omit<React.HTMLAttributes<HTMLDivElement>, ` | - | Any other props are spread to the root div. |\n\n### `<ConversationEmptyState />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | - | The title text to display. |\n| `description` | `string` | - | The description text to display. |\n| `icon` | `React.ReactNode` | - | Optional icon to display above the text. |\n| `children` | `React.ReactNode` | - | Optional additional content to render below the text. |\n| `...props` | `ComponentProps<` | - | Any other props are spread to the root div. |\n\n### `<ConversationScrollButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<ConversationDownload />`\n\nA button that downloads the conversation as a Markdown file.\n\n```tsx\nimport { ConversationDownload } from \"@/components/ai-elements/conversation\";\n\n<Conversation>\n  <ConversationContent>\n    {messages.map(...)}\n  </ConversationContent>\n  <ConversationDownload messages={messages} />\n  <ConversationScrollButton />\n</Conversation>\n```\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `messages` | `UIMessage[]` | Required | Array of messages to include in the download. |\n| `filename` | `string` | - | The filename for the downloaded file. |\n| `formatMessage` | `(message: UIMessage, index: number) => string` | - | Custom function to format each message in the output. |\n| `...props` | `Omit<ComponentProps<typeof Button>, ` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `messagesToMarkdown`\n\nA utility function to convert messages to Markdown format. Useful for custom download implementations.\n\n```tsx\nimport { messagesToMarkdown } from \"@/components/ai-elements/conversation\";\n\nconst markdown = messagesToMarkdown(messages);\n\n// With custom formatter\nconst customMarkdown = messagesToMarkdown(\n  messages,\n  (msg, i) =>\n    `[${msg.role}]: ${msg.parts\n      .filter((p) => p.type === \"text\")\n      .map((p) => p.text)\n      .join(\"\")}`\n);\n```\n",".agents/skills/ai-elements/references/edge.md":"# Edge\n\nCustomizable edge components for React Flow canvases with animated and temporary states.\n\nThe `Edge` component provides two pre-styled edge types for React Flow canvases: `Temporary` for dashed temporary connections and `Animated` for connections with animated indicators.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add edge\n```\n\n## Features\n\n- Two distinct edge types: Temporary and Animated\n- Temporary edges use dashed lines with ring color\n- Animated edges include a moving circle indicator\n- Automatic handle position calculation\n- Smart offset calculation based on handle type and position\n- Uses Bezier curves for smooth, natural-looking connections\n- Fully compatible with React Flow's edge system\n- Type-safe implementation with TypeScript\n\n## Edge Types\n\n### `Edge.Temporary`\n\nA dashed edge style for temporary or preview connections. Uses a simple Bezier path with a dashed stroke pattern.\n\n### `Edge.Animated`\n\nA solid edge with an animated circle that moves along the path. The animation repeats indefinitely with a 2-second duration, providing visual feedback for active connections.\n\n## Props\n\nBoth edge types accept standard React Flow `EdgeProps`:\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `id` | `string` | - | Unique identifier for the edge. |\n| `source` | `string` | - | ID of the source node. |\n| `target` | `string` | - | ID of the target node. |\n| `sourceX` | `number` | - | X coordinate of the source handle (Temporary only). |\n| `sourceY` | `number` | - | Y coordinate of the source handle (Temporary only). |\n| `targetX` | `number` | - | X coordinate of the target handle (Temporary only). |\n| `targetY` | `number` | - | Y coordinate of the target handle (Temporary only). |\n| `sourcePosition` | `Position` | - | Position of the source handle (Left, Right, Top, Bottom). |\n| `targetPosition` | `Position` | - | Position of the target handle (Left, Right, Top, Bottom). |\n| `markerEnd` | `string` | - | SVG marker ID for the edge end (Animated only). |\n| `style` | `React.CSSProperties` | - | Custom styles for the edge (Animated only). |\n",".agents/skills/ai-elements/references/environment-variables.md":"# Environment Variables\n\nDisplay environment variables with masking and copy functionality.\n\nThe `EnvironmentVariables` component displays environment variables with value masking, visibility toggle, and copy functionality.\n\nSee `scripts/environment-variables.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add environment-variables\n```\n\n## Features\n\n- Value masking by default\n- Toggle visibility switch\n- Copy individual values\n- Export format support (`export KEY=\"value\"`)\n- Required badge indicator\n\n## Props\n\n### `<EnvironmentVariables />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `showValues` | `boolean` | - | Controlled visibility state. |\n| `defaultShowValues` | `boolean` | `false` | Default visibility state. |\n| `onShowValuesChange` | `(show: boolean) => void` | - | Callback when visibility changes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<EnvironmentVariablesHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the header div. |\n\n### `<EnvironmentVariablesTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom title text. |\n| `...props` | `React.HTMLAttributes<HTMLHeadingElement>` | - | Spread to the h3 element. |\n\n### `<EnvironmentVariablesToggle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Switch>` | - | Spread to the Switch component. |\n\n### `<EnvironmentVariablesContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the content div. |\n\n### `<EnvironmentVariable />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | Variable name. |\n| `value` | `string` | Required | Variable value. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the row div. |\n\n### `<EnvironmentVariableGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the group div. |\n\n### `<EnvironmentVariableName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom name content. Defaults to the name from context. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<EnvironmentVariableValue />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom value content. Defaults to the masked/unmasked value from context. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<EnvironmentVariableCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `copyFormat` | `unknown` | - | Format to copy. |\n| `onCopy` | `() => void` | - | Callback after successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback if copying fails. |\n| `timeout` | `number` | `2000` | Duration to show copied state (ms). |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the Button component. |\n\n### `<EnvironmentVariableRequired />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom badge text. |\n| `...props` | `React.ComponentProps<typeof Badge>` | - | Spread to the Badge component. |\n",".agents/skills/ai-elements/references/file-tree.md":"# File Tree\n\nDisplay hierarchical file and folder structure with expand/collapse functionality.\n\nThe `FileTree` component displays a hierarchical file system structure with expandable folders and file selection.\n\nSee `scripts/file-tree.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add file-tree\n```\n\n## Features\n\n- Hierarchical folder structure\n- Expand/collapse folders\n- File selection with callback\n- Keyboard accessible\n- Customizable icons\n- Controlled and uncontrolled modes\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/file-tree-basic.tsx` for this example.\n\n### With Selection\n\nSee `scripts/file-tree-selection.tsx` for this example.\n\n### Default Expanded\n\nSee `scripts/file-tree-expanded.tsx` for this example.\n\n## Props\n\n### `<FileTree />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `expanded` | `Set<string>` | - | Controlled expanded paths. |\n| `defaultExpanded` | `Set<string>` | `new Set()` | Default expanded paths. |\n| `selectedPath` | `string` | - | Currently selected file/folder path. |\n| `onSelect` | `(path: string) => void` | - | Callback when a file/folder is selected. |\n| `onExpandedChange` | `(expanded: Set<string>) => void` | - | Callback when expanded paths change. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<FileTreeFolder />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `path` | `string` | - | Unique folder path. |\n| `name` | `string` | - | Display name. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<FileTreeFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `path` | `string` | - | Unique file path. |\n| `name` | `string` | - | Display name. |\n| `icon` | `ReactNode` | - | Custom file icon. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### Subcomponents\n\n- `FileTreeIcon` - Icon wrapper\n- `FileTreeName` - Name text\n- `FileTreeActions` - Action buttons container (stops click propagation)\n",".agents/skills/ai-elements/references/image.md":"# Image\n\nDisplays AI-generated images from the AI SDK.\n\nThe `Image` component displays AI-generated images from the AI SDK. It accepts a [`Experimental_GeneratedImage`](/docs/reference/ai-sdk-core/generate-image) object from the AI SDK's `generateImage` function and automatically renders it as an image.\n\nSee `scripts/image.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add image\n```\n\n## Usage with AI SDK\n\nBuild a simple app allowing a user to generate an image given a prompt.\n\nInstall the `@ai-sdk/openai` package:\n\n```package-install\nnpm i @ai-sdk/openai\n```\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { Image } from \"@/components/ai-elements/image\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { useState } from \"react\";\nimport { Spinner } from \"@/components/ui/spinner\";\n\nconst ImageDemo = () => {\n  const [prompt, setPrompt] = useState(\"A futuristic cityscape at sunset\");\n  const [imageData, setImageData] = useState<any>(null);\n  const [isLoading, setIsLoading] = useState(false);\n\n  const handleSubmit = async (message: PromptInputMessage) => {\n    if (!message.text.trim()) return;\n    setPrompt(\"\");\n\n    setIsLoading(true);\n    try {\n      const response = await fetch(\"/api/image\", {\n        method: \"POST\",\n        body: JSON.stringify({ prompt: message.text.trim() }),\n      });\n\n      const data = await response.json();\n\n      setImageData(data);\n    } catch (error) {\n      console.error(\"Error generating image:\", error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex-1 overflow-y-auto p-4\">\n          {imageData && (\n            <div className=\"flex justify-center\">\n              <Image\n                {...imageData}\n                alt=\"Generated image\"\n                className=\"h-[300px] aspect-square border rounded-lg\"\n              />\n            </div>\n          )}\n          {isLoading && <Spinner />}\n        </div>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={prompt}\n            placeholder=\"Describe the image you want to generate...\"\n            onChange={(e) => setPrompt(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={isLoading ? \"submitted\" : \"ready\"}\n            disabled={!prompt.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ImageDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/image/route.ts\"\nimport { openai } from \"@ai-sdk/openai\";\nimport { experimental_generateImage } from \"ai\";\n\nexport async function POST(req: Request) {\n  const { prompt }: { prompt: string } = await req.json();\n\n  const { image } = await experimental_generateImage({\n    model: openai.image(\"dall-e-3\"),\n    prompt: prompt,\n    size: \"1024x1024\",\n  });\n\n  return Response.json({\n    base64: image.base64,\n    uint8Array: image.uint8Array,\n    mediaType: image.mediaType,\n  });\n}\n```\n\n## Features\n\n- Accepts `Experimental_GeneratedImage` objects directly from the AI SDK\n- Automatically creates proper data URLs from base64-encoded image data\n- Supports all standard HTML image attributes\n- Responsive by default with `max-w-full h-auto` styling\n- Customizable with additional CSS classes\n- Includes proper TypeScript types for AI SDK compatibility\n\n## Props\n\n### `<Image />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `alt` | `string` | - | Alternative text for the image. |\n| `className` | `string` | - | Additional CSS classes to apply to the image. |\n| `...props` | `Experimental_GeneratedImage` | - | The image data to display, as returned by the AI SDK. |\n",".agents/skills/ai-elements/references/inline-citation.md":"# Inline Citation\n\nA hoverable citation component that displays source information and quotes inline with text, perfect for AI-generated content with references.\n\nThe `InlineCitation` component provides a way to display citations inline with text content, similar to academic papers or research documents. It consists of a citation pill that shows detailed source information on hover, making it perfect for AI-generated content that needs to reference sources.\n\nSee `scripts/inline-citation.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add inline-citation\n```\n\n## Usage with AI SDK\n\nBuild citations for AI-generated content using [`experimental_generateObject`](/docs/reference/ai-sdk-ui/use-object).\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { experimental_useObject as useObject } from \"@ai-sdk/react\";\nimport {\n  InlineCitation,\n  InlineCitationText,\n  InlineCitationCard,\n  InlineCitationCardTrigger,\n  InlineCitationCardBody,\n  InlineCitationCarousel,\n  InlineCitationCarouselContent,\n  InlineCitationCarouselItem,\n  InlineCitationCarouselHeader,\n  InlineCitationCarouselIndex,\n  InlineCitationCarouselPrev,\n  InlineCitationCarouselNext,\n  InlineCitationSource,\n  InlineCitationQuote,\n} from \"@/components/ai-elements/inline-citation\";\nimport { Button } from \"@/components/ui/button\";\nimport { citationSchema } from \"@/app/api/citation/route\";\n\nconst CitationDemo = () => {\n  const { object, submit, isLoading } = useObject({\n    api: \"/api/citation\",\n    schema: citationSchema,\n  });\n\n  const handleSubmit = (topic: string) => {\n    submit({ prompt: topic });\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 space-y-6\">\n      <div className=\"flex gap-2 mb-6\">\n        <Button\n          onClick={() => handleSubmit(\"artificial intelligence\")}\n          disabled={isLoading}\n          variant=\"outline\"\n        >\n          Generate AI Content\n        </Button>\n        <Button\n          onClick={() => handleSubmit(\"climate change\")}\n          disabled={isLoading}\n          variant=\"outline\"\n        >\n          Generate Climate Content\n        </Button>\n      </div>\n\n      {isLoading && !object && (\n        <div className=\"text-muted-foreground\">\n          Generating content with citations...\n        </div>\n      )}\n\n      {object?.content && (\n        <div className=\"prose prose-sm max-w-none\">\n          <p className=\"leading-relaxed\">\n            {object.content.split(/(\\[\\d+\\])/).map((part, index) => {\n              const citationMatch = part.match(/\\[(\\d+)\\]/);\n              if (citationMatch) {\n                const citationNumber = citationMatch[1];\n                const citation = object.citations?.find(\n                  (c: any) => c.number === citationNumber\n                );\n\n                if (citation) {\n                  return (\n                    <InlineCitation key={index}>\n                      <InlineCitationCard>\n                        <InlineCitationCardTrigger sources={[citation.url]} />\n                        <InlineCitationCardBody>\n                          <InlineCitationCarousel>\n                            <InlineCitationCarouselHeader>\n                              <InlineCitationCarouselPrev />\n                              <InlineCitationCarouselNext />\n                              <InlineCitationCarouselIndex />\n                            </InlineCitationCarouselHeader>\n                            <InlineCitationCarouselContent>\n                              <InlineCitationCarouselItem>\n                                <InlineCitationSource\n                                  title={citation.title}\n                                  url={citation.url}\n                                  description={citation.description}\n                                />\n                                {citation.quote && (\n                                  <InlineCitationQuote>\n                                    {citation.quote}\n                                  </InlineCitationQuote>\n                                )}\n                              </InlineCitationCarouselItem>\n                            </InlineCitationCarouselContent>\n                          </InlineCitationCarousel>\n                        </InlineCitationCardBody>\n                      </InlineCitationCard>\n                    </InlineCitation>\n                  );\n                }\n              }\n              return part;\n            })}\n          </p>\n        </div>\n      )}\n    </div>\n  );\n};\n\nexport default CitationDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/citation/route.ts\"\nimport { streamObject } from \"ai\";\nimport { z } from \"zod\";\n\nexport const citationSchema = z.object({\n  content: z.string(),\n  citations: z.array(\n    z.object({\n      number: z.string(),\n      title: z.string(),\n      url: z.string(),\n      description: z.string().optional(),\n      quote: z.string().optional(),\n    })\n  ),\n});\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { prompt } = await req.json();\n\n  const result = streamObject({\n    model: \"openai/gpt-4o\",\n    schema: citationSchema,\n    prompt: `Generate a well-researched paragraph about ${prompt} with proper citations. \n    \n    Include:\n    - A comprehensive paragraph with inline citations marked as [1], [2], etc.\n    - 2-3 citations with realistic source information\n    - Each citation should have a title, URL, and optional description/quote\n    - Make the content informative and the sources credible\n    \n    Format citations as numbered references within the text.`,\n  });\n\n  return result.toTextStreamResponse();\n}\n```\n\n## Features\n\n- Hover interaction to reveal detailed citation information\n- **Carousel navigation** for multiple citations with prev/next controls\n- **Live index tracking** showing current slide position (e.g., \"1/5\")\n- Support for source titles, URLs, and descriptions\n- Optional quote blocks for relevant excerpts\n- Composable architecture for flexible citation formats\n- Accessible design with proper keyboard navigation\n- Seamless integration with AI-generated content\n- Clean visual design that doesn't disrupt reading flow\n- Smart badge display showing source hostname and count\n\n## Usage with AI SDK\n\nCurrently, there is no official support for inline citations with Streamdown or the Response component. This is because:\n\n- There isn't any good markdown syntax for inline citations\n- Language models don't naturally respond with inline citation syntax\n- The AI SDK doesn't have built-in support for inline citations\n\n### Potential Approaches\n\nWhile these methods are hypothetical and not officially supported, there are two conceptual ways inline citations could work with Streamdown:\n\n1. **Footnote conversion**: GitHub Flavored Markdown (GFM) handles footnotes using `[^1]` syntax. You could hypothetically remove the default footnote rendering and convert footnotes to inline citations instead.\n\n2. **Custom HTML syntax**: You could add a system prompt instructing the model to use a special HTML syntax like `<citation />` and pass that as a custom component to Streamdown.\n\nThese approaches require custom implementation and are not currently supported out of the box. We will investigate official support for this use case in the future.\n\nFor now, the recommended approach is to use `experimental_useObject` (as shown in the usage example above) to generate structured citation data, then manually parse and render inline citations.\n\n## Props\n\n### `<InlineCitation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root span element. |\n\n### `<InlineCitationText />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying span element. |\n\n### `<InlineCitationCard />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the HoverCard component. |\n\n### `<InlineCitationCardTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `sources` | `string[]` | - | Array of source URLs. The length determines the number displayed in the badge. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying button element. |\n\n### `<InlineCitationCardBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationCarousel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Carousel>` | - | Any other props are spread to the underlying Carousel component. |\n\n### `<InlineCitationCarouselContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying CarouselContent component. |\n\n### `<InlineCitationCarouselItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationCarouselHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationCarouselIndex />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. Children will override the default index display. |\n\n### `<InlineCitationCarouselPrev />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CarouselPrevious>` | - | Any other props are spread to the underlying CarouselPrevious component. |\n\n### `<InlineCitationCarouselNext />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CarouselNext>` | - | Any other props are spread to the underlying CarouselNext component. |\n\n### `<InlineCitationSource />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | - | The title of the source. |\n| `url` | `string` | - | The URL of the source. |\n| `description` | `string` | - | A brief description of the source. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationQuote />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying blockquote element. |\n",".agents/skills/ai-elements/references/jsx-preview.md":"# JSX Preview\n\nA component that dynamically renders JSX strings with streaming support for AI-generated UI.\n\nThe `JSXPreview` component renders JSX strings dynamically, supporting streaming scenarios where JSX may be incomplete. It automatically closes unclosed tags during streaming, making it ideal for displaying AI-generated UI components in real-time.\n\nSee `scripts/jsx-preview.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add jsx-preview\n```\n\n## Features\n\n- Renders JSX strings dynamically using `react-jsx-parser`\n- Streaming support with automatic tag completion\n- Custom component injection for rendering your own components\n- Error handling with customizable error display\n- Context-based architecture for flexible composition\n\n## Usage with AI SDK\n\nThe JSXPreview component integrates with the AI SDK to render generated UI in real-time:\n\n```tsx title=\"components/generated-ui.tsx\"\n\"use client\";\n\nimport {\n  JSXPreview,\n  JSXPreviewContent,\n  JSXPreviewError,\n} from \"@/components/ai-elements/jsx-preview\";\n\ntype GeneratedUIProps = {\n  jsx: string;\n  isStreaming: boolean;\n};\n\nexport const GeneratedUI = ({ jsx, isStreaming }: GeneratedUIProps) => (\n  <JSXPreview\n    jsx={jsx}\n    isStreaming={isStreaming}\n    onError={(error) => console.error(\"JSX Parse Error:\", error)}\n  >\n    <JSXPreviewContent />\n    <JSXPreviewError />\n  </JSXPreview>\n);\n```\n\n### With Custom Components\n\nYou can inject custom components to be used within the rendered JSX:\n\n```tsx title=\"components/generated-ui-with-components.tsx\"\n\"use client\";\n\nimport {\n  JSXPreview,\n  JSXPreviewContent,\n} from \"@/components/ai-elements/jsx-preview\";\nimport { Button } from \"@/components/ui/button\";\nimport { Card } from \"@/components/ui/card\";\n\nconst customComponents = {\n  Button,\n  Card,\n};\n\nexport const GeneratedUIWithComponents = ({ jsx }: { jsx: string }) => (\n  <JSXPreview jsx={jsx} components={customComponents}>\n    <JSXPreviewContent />\n  </JSXPreview>\n);\n```\n\n## Props\n\n### `<JSXPreview />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `jsx` | `string` | Required | The JSX string to render. |\n| `isStreaming` | `boolean` | `false` | When true, automatically completes unclosed tags. |\n| `components` | `Record<string, React.ComponentType>` | - | Custom components available within the rendered JSX. |\n| `bindings` | `Record<string, unknown>` | - | Variables and functions available within the JSX scope. |\n| `onError` | `(error: Error) => void` | - | Callback fired when a parsing or rendering error occurs. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n### `<JSXPreviewContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `renderError` | `JsxParserProps[` | - | Custom error renderer passed to react-jsx-parser. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n### `<JSXPreviewError />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode | ((error: Error) => ReactNode)` | - | Custom error content or render function receiving the error. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n",".agents/skills/ai-elements/references/message.md":"# Message\n\nA comprehensive suite of components for displaying chat messages, including message rendering, branching, actions, and markdown responses.\n\nThe `Message` component suite provides a complete set of tools for building chat interfaces. It includes components for displaying messages from users and AI assistants, managing multiple response branches, adding action buttons, and rendering markdown content.\n\nSee `scripts/message.tsx` for this example.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add message\n```\n\n## Features\n\n- Displays messages from both user and AI assistant with distinct styling and automatic alignment\n- Minimalist flat design with user messages in secondary background and assistant messages full-width\n- **Response branching** with navigation controls to switch between multiple AI response versions\n- **Markdown rendering** with GFM support (tables, task lists, strikethrough), math equations, and smart streaming\n- **Action buttons** for common operations (retry, like, dislike, copy, share) with tooltips and state management\n- **File attachments** display with support for images and generic files with preview and remove functionality\n- Code blocks with syntax highlighting and copy-to-clipboard functionality\n- Keyboard accessible with proper ARIA labels\n- Responsive design that adapts to different screen sizes\n- Seamless light/dark theme integration\n\n\n\n## Usage with AI SDK\n\nBuild a simple chat UI where the user can copy or regenerate the most recent message.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useState } from \"react\";\nimport {\n  MessageActions,\n  MessageAction,\n} from \"@/components/ai-elements/message\";\nimport { Message, MessageContent } from \"@/components/ai-elements/message\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { MessageResponse } from \"@/components/ai-elements/message\";\nimport { RefreshCcwIcon, CopyIcon } from \"lucide-react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport { Fragment } from \"react\";\n\nconst ActionsDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { messages, sendMessage, status, regenerate } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.map((message, messageIndex) => (\n              <Fragment key={message.id}>\n                {message.parts.map((part, i) => {\n                  switch (part.type) {\n                    case \"text\":\n                      const isLastMessage =\n                        messageIndex === messages.length - 1;\n\n                      return (\n                        <Fragment key={`${message.id}-${i}`}>\n                          <Message from={message.role}>\n                            <MessageContent>\n                              <MessageResponse>{part.text}</MessageResponse>\n                            </MessageContent>\n                          </Message>\n                          {message.role === \"assistant\" && isLastMessage && (\n                            <MessageActions>\n                              <MessageAction\n                                onClick={() => regenerate()}\n                                label=\"Retry\"\n                              >\n                                <RefreshCcwIcon className=\"size-3\" />\n                              </MessageAction>\n                              <MessageAction\n                                onClick={() =>\n                                  navigator.clipboard.writeText(part.text)\n                                }\n                                label=\"Copy\"\n                              >\n                                <CopyIcon className=\"size-3\" />\n                              </MessageAction>\n                            </MessageActions>\n                          )}\n                        </Fragment>\n                      );\n                    default:\n                      return null;\n                  }\n                })}\n              </Fragment>\n            ))}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Say something...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ActionsDemo;\n```\n\n## Props\n\n### `<Message />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `from` | `UIMessage[` | - | The role of the message sender ( |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the content div. |\n\n### `<MessageResponse />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The markdown content to render. |\n| `parseIncompleteMarkdown` | `boolean` | `true` | Whether to parse and fix incomplete markdown syntax (e.g., unclosed code blocks or lists). |\n| `className` | `string` | - | CSS class names to apply to the wrapper div element. |\n| `components` | `object` | - | Custom React components to use for rendering markdown elements (e.g., custom heading, paragraph, code block components). |\n| `allowedImagePrefixes` | `string[]` | `[` | Array of allowed URL prefixes for images. Use [ |\n| `allowedLinkPrefixes` | `string[]` | `[` | Array of allowed URL prefixes for links. Use [ |\n| `defaultOrigin` | `string` | - | Default origin to use for relative URLs in links and images. |\n| `rehypePlugins` | `array` | `[rehypeKatex]` | Array of rehype plugins to use for processing HTML. Includes KaTeX for math rendering by default. |\n| `remarkPlugins` | `array` | `[remarkGfm, remarkMath]` | Array of remark plugins to use for processing markdown. Includes GitHub Flavored Markdown and math support by default. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | HTML attributes to spread to the root div. |\n\n### `<MessageAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string` | - | Optional tooltip text shown on hover. |\n| `label` | `string` | - | Accessible label for screen readers. Also used as fallback if tooltip is not provided. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<MessageBranch />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultBranch` | `number` | `0` | The index of the branch to show by default. |\n| `onBranchChange` | `(branchIndex: number) => void` | - | Callback fired when the branch changes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageBranchContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageBranchSelector />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof ButtonGroup>` | - | Any other props are spread to the underlying ButtonGroup component. |\n\n### `<MessageBranchPrevious />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<MessageBranchNext />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<MessageBranchPage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the underlying span element. |\n\n### `<MessageToolbar />`\n\nA container for placing actions and branch selectors below a message. Lays out children in a horizontal row with space-between alignment.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div. |\n```\n",".agents/skills/ai-elements/references/mic-selector.md":"# Mic Selector\n\nA composable dropdown component for selecting audio input devices with permission handling and device change detection.\n\nThe `MicSelector` component provides a flexible and composable interface for selecting microphone input devices. Built on shadcn/ui's Command and Popover components, it features automatic device detection, permission handling, dynamic device list updates, and intelligent device name parsing.\n\nSee `scripts/mic-selector.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add mic-selector\n```\n\n## Features\n\n- Fully composable architecture with granular control components\n- Automatic audio input device enumeration\n- Permission-based device name display\n- Real-time device change detection via devicechange events\n- Intelligent device label parsing with ID extraction\n- Controlled and uncontrolled component patterns\n- Responsive width matching between trigger and content\n- Built on shadcn/ui Command and Popover components\n- Full TypeScript support with proper types for all components\n\n## Props\n\n### `<MicSelector />`\n\nRoot Popover component that provides context for all child components.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultValue` | `string` | - | The default selected device ID (uncontrolled). |\n| `value` | `string` | - | The selected device ID (controlled). |\n| `onValueChange` | `(deviceId: string) => void` | - | Callback fired when the selected device changes. |\n| `defaultOpen` | `boolean` | `false` | The default open state (uncontrolled). |\n| `open` | `boolean` | - | The open state (controlled). |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback fired when the open state changes. Automatically requests microphone permission when opened without permission. |\n| `...props` | `React.ComponentProps<typeof Popover>` | - | Any other props are spread to the Popover component. |\n\n### `<MicSelectorTrigger />`\n\nButton that opens the microphone selector popover. Automatically tracks its width to match the popover content.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component. |\n\n### `<MicSelectorValue />`\n\nDisplays the currently selected microphone name or a placeholder.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<MicSelectorContent />`\n\nContainer for the Command component, rendered inside the popover.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `popoverOptions` | `React.ComponentProps<typeof PopoverContent>` | - | Props to pass to the underlying PopoverContent component. |\n| `...props` | `React.ComponentProps<typeof Command>` | - | Any other props are spread to the Command component. |\n\n### `<MicSelectorInput />`\n\nSearch input for filtering microphones.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the CommandInput component. |\n\n### `<MicSelectorList />`\n\nWrapper for the list of microphone items. Uses render props pattern to provide access to device data.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `(devices: MediaDeviceInfo[]) => ReactNode` | - | Render function that receives the array of available devices. |\n| `...props` | `Omit<React.ComponentProps<typeof CommandList>, ` | - | Any other props are spread to the CommandList component. |\n\n### `<MicSelectorEmpty />`\n\nMessage shown when no microphones match the search.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode` | - | The message to display. |\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the CommandEmpty component. |\n\n### `<MicSelectorItem />`\n\nSelectable item representing a microphone.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The device ID for this item. |\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the CommandItem component. |\n\n### `<MicSelectorLabel />`\n\nDisplays a formatted microphone label with intelligent device ID parsing. Automatically extracts and styles device IDs in the format (XXXX:XXXX).\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `device` | `MediaDeviceInfo` | - | The MediaDeviceInfo object for the device. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n## Hooks\n\n### `useAudioDevices()`\n\nA custom hook for managing audio input devices. This hook is used internally by the `MicSelector` component but can also be used independently.\n\n```tsx\nimport { useAudioDevices } from \"@repo/elements/mic-selector\";\n\nexport default function Example() {\n  const { devices, loading, error, hasPermission, loadDevices } =\n    useAudioDevices();\n\n  return (\n    <div>\n      {loading && <p>Loading devices...</p>}\n      {error && <p>Error: {error}</p>}\n      {devices.map((device) => (\n        <div key={device.deviceId}>{device.label}</div>\n      ))}\n      {!hasPermission && (\n        <button onClick={loadDevices}>Grant Permission</button>\n      )}\n    </div>\n  );\n}\n```\n\n#### Return Value\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `devices` | `MediaDeviceInfo[]` | - | Array of available audio input devices. |\n| `loading` | `boolean` | - | Whether devices are currently being loaded. |\n| `error` | `string | null` | - | Error message if device loading failed. |\n| `hasPermission` | `boolean` | - | Whether microphone permission has been granted. |\n| `loadDevices` | `() => Promise<void>` | - | Function to request microphone permission and load device names. |\n\n## Behavior\n\n### Permission Handling\n\nThe component implements a two-stage permission approach:\n\n1. **Without Permission**: Initially loads devices without requesting permission. Device labels may show as generic names (e.g., \"Microphone 1\").\n2. **With Permission**: When the popover is opened and permission hasn't been granted, automatically requests microphone access and displays actual device names.\n\n### Device Label Parsing\n\nThe `MicSelectorLabel` component intelligently parses device names that include hardware IDs in the format `(XXXX:XXXX)`. It splits the label into the device name and ID, styling the ID with muted text for better readability.\n\nFor example: `\"MacBook Pro Microphone (1a2b:3c4d)\"` becomes:\n\n- Device name: `\"MacBook Pro Microphone\"`\n- Device ID: `\"(1a2b:3c4d)\"` (styled with muted color)\n\n### Width Synchronization\n\nThe `MicSelectorTrigger` uses a ResizeObserver to track its width and automatically synchronizes it with the `MicSelectorContent` popover width for a cohesive appearance.\n\n### Device Change Detection\n\nThe component listens for `devicechange` events (e.g., plugging/unplugging microphones) and automatically updates the device list in real-time.\n\n## Accessibility\n\n- Uses semantic HTML with proper ARIA attributes via shadcn/ui components\n- Full keyboard navigation support through Command component\n- Screen reader friendly with proper labels and roles\n- Searchable device list for quick selection\n\n## Notes\n\n- Requires a secure context (HTTPS or localhost) for microphone access\n- Browser may prompt user for microphone permission on first open\n- Device labels are only fully descriptive after permission is granted\n- Component handles cleanup of temporary media streams during permission requests\n- Uses Radix UI's `useControllableState` for flexible controlled/uncontrolled patterns\n",".agents/skills/ai-elements/references/model-selector.md":"# Model Selector\n\nA searchable command palette for selecting AI models in your chat interface.\n\nThe `ModelSelector` component provides a searchable command palette interface for selecting AI models. It's built on top of the cmdk library and provides a keyboard-navigable interface with search functionality.\n\nSee `scripts/model-selector.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add model-selector\n```\n\n## Features\n\n- Searchable interface with keyboard navigation\n- Fuzzy search filtering across model names\n- Grouped model organization by provider\n- Keyboard shortcuts support\n- Empty state handling\n- Customizable styling with Tailwind CSS\n- Built on cmdk for excellent accessibility\n- TypeScript support with proper type definitions\n\n## Props\n\n### `<ModelSelector />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Dialog>` | - | Any other props are spread to the underlying Dialog component. |\n\n### `<ModelSelectorTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DialogTrigger>` | - | Any other props are spread to the underlying DialogTrigger component. |\n\n### `<ModelSelectorContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `ReactNode` | - | Accessible title for the dialog (rendered in sr-only). |\n| `...props` | `React.ComponentProps<typeof DialogContent>` | - | Any other props are spread to the underlying DialogContent component. |\n\n### `<ModelSelectorDialog />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandDialog>` | - | Any other props are spread to the underlying CommandDialog component. |\n\n### `<ModelSelectorInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the underlying CommandInput component. |\n\n### `<ModelSelectorList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandList>` | - | Any other props are spread to the underlying CommandList component. |\n\n### `<ModelSelectorEmpty />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the underlying CommandEmpty component. |\n\n### `<ModelSelectorGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandGroup>` | - | Any other props are spread to the underlying CommandGroup component. |\n\n### `<ModelSelectorItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the underlying CommandItem component. |\n\n### `<ModelSelectorShortcut />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandShortcut>` | - | Any other props are spread to the underlying CommandShortcut component. |\n\n### `<ModelSelectorSeparator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandSeparator>` | - | Any other props are spread to the underlying CommandSeparator component. |\n\n### `<ModelSelectorLogo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `provider` | `string` | Required | The AI provider name. Supports major providers like  |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the underlying img element (except src and alt which are generated). |\n\n### `<ModelSelectorLogoGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n### `<ModelSelectorName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying span element. |\n",".agents/skills/ai-elements/references/node.md":"# Node\n\nA composable node component for React Flow-based canvases with Card-based styling.\n\nThe `Node` component provides a composable, Card-based node for React Flow canvases. It includes support for connection handles, structured layouts, and consistent styling using shadcn/ui components.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add node\n```\n\n## Features\n\n- Built on shadcn/ui Card components for consistent styling\n- Automatic handle placement (left for target, right for source)\n- Composable sub-components (Header, Title, Description, Action, Content, Footer)\n- Semantic structure for organizing node information\n- Pre-styled sections with borders and backgrounds\n- Responsive sizing with fixed small width\n- Full TypeScript support with proper type definitions\n- Compatible with React Flow's node system\n\n## Props\n\n### `<Node />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `handles` | `unknown` | - | Configuration for connection handles. Target renders on the left, source on the right. |\n| `className` | `string` | - | Additional CSS classes to apply to the node. |\n| `...props` | `ComponentProps<typeof Card>` | - | Any other props are spread to the underlying Card component. |\n\n### `<NodeHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the header. |\n| `...props` | `ComponentProps<typeof CardHeader>` | - | Any other props are spread to the underlying CardHeader component. |\n\n### `<NodeTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof CardTitle>` | - | Any other props are spread to the underlying CardTitle component. |\n\n### `<NodeDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof CardDescription>` | - | Any other props are spread to the underlying CardDescription component. |\n\n### `<NodeAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof CardAction>` | - | Any other props are spread to the underlying CardAction component. |\n\n### `<NodeContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the content. |\n| `...props` | `ComponentProps<typeof CardContent>` | - | Any other props are spread to the underlying CardContent component. |\n\n### `<NodeFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the footer. |\n| `...props` | `ComponentProps<typeof CardFooter>` | - | Any other props are spread to the underlying CardFooter component. |\n",".agents/skills/ai-elements/references/open-in-chat.md":"# Open In Chat\n\nA dropdown menu for opening queries in various AI chat platforms including ChatGPT, Claude, T3, Scira, and v0.\n\nThe `OpenIn` component provides a dropdown menu that allows users to open queries in different AI chat platforms with a single click.\n\nSee `scripts/open-in-chat.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add open-in-chat\n```\n\n## Features\n\n- Pre-configured links to popular AI chat platforms\n- Context-based query passing for cleaner API\n- Customizable dropdown trigger button\n- Automatic URL parameter encoding for queries\n- Support for ChatGPT, Claude, T3 Chat, Scira AI, v0, and Cursor\n- Branded icons for each platform\n- TypeScript support with proper type definitions\n- Accessible dropdown menu with keyboard navigation\n- External link indicators for clarity\n\n## Supported Platforms\n\n- **ChatGPT** - Opens query in OpenAI's ChatGPT with search hints\n- **Claude** - Opens query in Anthropic's Claude AI\n- **T3 Chat** - Opens query in T3 Chat platform\n- **Scira AI** - Opens query in Scira's AI assistant\n- **v0** - Opens query in Vercel's v0 platform\n- **Cursor** - Opens query in Cursor AI editor\n\n## Props\n\n### `<OpenIn />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `query` | `string` | - | The query text to be sent to all AI platforms. |\n| `...props` | `React.ComponentProps<typeof DropdownMenu>` | - | Props to spread to the underlying radix-ui DropdownMenu component. |\n\n### `<OpenInTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom trigger button. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuTrigger>` | - | Props to spread to the underlying DropdownMenuTrigger component. |\n\n### `<OpenInContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the dropdown content. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuContent>` | - | Props to spread to the underlying DropdownMenuContent component. |\n\n### `<OpenInChatGPT />`, `<OpenInClaude />`, `<OpenInT3 />`, `<OpenInScira />`, `<OpenInv0 />`, `<OpenInCursor />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Props to spread to the underlying DropdownMenuItem component. The query is automatically provided via context from the parent OpenIn component. |\n\n### `<OpenInItem />`, `<OpenInLabel />`, `<OpenInSeparator />`\n\nAdditional composable components for custom dropdown menu items, labels, and separators that follow the same props pattern as their underlying radix-ui counterparts.\n",".agents/skills/ai-elements/references/package-info.md":"# Package Info\n\nDisplay dependency information and version changes.\n\nThe `PackageInfo` component displays package dependency information including version changes and change type badges.\n\nSee `scripts/package-info.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add package-info\n```\n\n## Features\n\n- Version change display (current → new)\n- Color-coded change type badges\n- Dependencies list\n- Description support\n\n## Change Types\n\n| Type      | Color  | Use Case           |\n| --------- | ------ | ------------------ |\n| `major`   | Red    | Breaking changes   |\n| `minor`   | Yellow | New features       |\n| `patch`   | Green  | Bug fixes          |\n| `added`   | Blue   | New dependency     |\n| `removed` | Gray   | Removed dependency |\n\n## Props\n\n### `<PackageInfo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | Package name. |\n| `currentVersion` | `string` | - | Current installed version. |\n| `newVersion` | `string` | - | New version being installed. |\n| `changeType` | `unknown` | - | Type of version change. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the header div. |\n\n### `<PackageInfoName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom name content. Defaults to the name from context. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoChangeType />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom change type label. Defaults to the changeType from context. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the Badge component. |\n\n### `<PackageInfoVersion />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom version content. Defaults to version transition display. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Spread to the p element. |\n\n### `<PackageInfoContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoDependencies />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoDependency />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | Dependency name. |\n| `version` | `string` | - | Dependency version. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the row div. |\n",".agents/skills/ai-elements/references/panel.md":"# Panel\n\nA styled panel component for React Flow-based canvases to position custom UI elements.\n\nThe `Panel` component provides a positioned container for custom UI elements on React Flow canvases. It includes modern card styling with backdrop blur and flexible positioning options.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add panel\n```\n\n## Features\n\n- Flexible positioning (top-left, top-right, bottom-left, bottom-right, top-center, bottom-center)\n- Rounded pill design with backdrop blur\n- Theme-aware card background\n- Flexbox layout for easy content alignment\n- Subtle drop shadow for depth\n- Full TypeScript support\n- Compatible with React Flow's panel system\n\n## Props\n\n### `<Panel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `position` | `unknown` | - | Position of the panel on the canvas. |\n| `className` | `string` | - | Additional CSS classes to apply to the panel. |\n| `...props` | `ComponentProps<typeof Panel>` | - | Any other props from @xyflow/react Panel component. |\n",".agents/skills/ai-elements/references/persona.md":"# Persona\n\nAn animated AI visual component powered by Rive that responds to different states like listening, thinking, and speaking.\n\nThe `Persona` component displays an animated AI visual that responds to different conversational states. Built with Rive WebGL2, it provides smooth, high-performance animations for various AI interaction states including idle, listening, thinking, speaking, and asleep. The component supports multiple visual variants to match different design aesthetics.\n\nSee `scripts/persona-obsidian.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add persona\n```\n\n## Features\n\n- Smooth state-based animations powered by Rive\n- Multiple visual variants (obsidian, mana, opal, halo, glint, command)\n- Responsive to five distinct states: idle, listening, thinking, speaking, and asleep\n- WebGL2-accelerated rendering for optimal performance\n- Customizable size and styling\n- Lifecycle callbacks for load, ready, pause, play, and stop events\n- TypeScript support with full type definitions\n\n## Variants\n\nThe Persona component comes with 6 distinct visual variants, each with its own unique aesthetic:\n\n### Obsidian (Default)\n\nSee `scripts/persona-obsidian.tsx` for this example.\n\n### Mana\n\nSee `scripts/persona-mana.tsx` for this example.\n\n### Opal\n\nSee `scripts/persona-opal.tsx` for this example.\n\n### Halo\n\nSee `scripts/persona-halo.tsx` for this example.\n\n### Glint\n\nSee `scripts/persona-glint.tsx` for this example.\n\n### Command\n\nSee `scripts/persona-command.tsx` for this example.\n\n## Props\n\n### `<Persona />`\n\nThe root component that renders the animated AI visual.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `state` | `unknown` | - | The current state of the AI persona. Controls which animation is displayed. |\n| `variant` | `unknown` | - | The visual style variant to display. |\n| `className` | `string` | - | Additional CSS classes to apply to the component. |\n| `onLoad` | `RiveParameters[` | - | Callback fired when the Rive file starts loading. |\n| `onLoadError` | `RiveParameters[` | - | Callback fired if the Rive file fails to load. |\n| `onReady` | `() => void` | - | Callback fired when the Rive animation is ready to play. |\n| `onPause` | `RiveParameters[` | - | Callback fired when the animation is paused. |\n| `onPlay` | `RiveParameters[` | - | Callback fired when the animation starts playing. |\n| `onStop` | `RiveParameters[` | - | Callback fired when the animation is stopped. |\n\n## States\n\nThe Persona component responds to five distinct states, each triggering different animations:\n\n- **idle**: The default resting state when the AI is not active\n- **listening**: Displayed when the AI is actively listening to user input (e.g., during voice recording)\n- **thinking**: Shown when the AI is processing or generating a response\n- **speaking**: Active when the AI is delivering a response (e.g., text-to-speech output)\n- **asleep**: A dormant state for when the AI is inactive or in low-power mode\n\n## React Strict Mode (Vite)\n\nThe Persona component uses WebGL2 for rendering. Browsers limit the number of active WebGL2 contexts (~8–16), and React Strict Mode (enabled by default in Vite dev) double-mounts components, which can exhaust that limit and crash the page.\n\nThe component includes a built-in guard that defers WebGL2 initialization by one frame, preventing context creation during Strict Mode's throw-away mount. This means the component works in Vite dev mode out of the box — no configuration needed.\n\nIf you still experience crashes (for example, when rendering many Persona instances simultaneously), reduce the number of concurrent Persona components on screen.\n\n## Usage Examples\n\n### Basic Usage\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\n\nexport default function App() {\n  return <Persona state=\"listening\" variant=\"opal\" />;\n}\n```\n\n### With State Management\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\nimport { useState } from \"react\";\n\nexport default function App() {\n  const [state, setState] = useState<\n    \"idle\" | \"listening\" | \"thinking\" | \"speaking\" | \"asleep\"\n  >(\"idle\");\n\n  const startListening = () => setState(\"listening\");\n  const startThinking = () => setState(\"thinking\");\n  const startSpeaking = () => setState(\"speaking\");\n  const reset = () => setState(\"idle\");\n\n  return (\n    <div>\n      <Persona state={state} variant=\"opal\" className=\"size-32\" />\n      <div>\n        <button onClick={startListening}>Listen</button>\n        <button onClick={startThinking}>Think</button>\n        <button onClick={startSpeaking}>Speak</button>\n        <button onClick={reset}>Reset</button>\n      </div>\n    </div>\n  );\n}\n```\n\n### With Custom Styling\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\n\nexport default function App() {\n  return (\n    <Persona\n      state=\"thinking\"\n      variant=\"halo\"\n      className=\"size-64 rounded-full border border-border\"\n    />\n  );\n}\n```\n\n### With Lifecycle Callbacks\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\n\nexport default function App() {\n  return (\n    <Persona\n      state=\"listening\"\n      variant=\"glint\"\n      onReady={() => console.log(\"Animation ready\")}\n      onLoad={() => console.log(\"Starting to load\")}\n      onLoadError={(error) => console.error(\"Failed to load:\", error)}\n      onPlay={() => console.log(\"Animation playing\")}\n      onPause={() => console.log(\"Animation paused\")}\n      onStop={() => console.log(\"Animation stopped\")}\n    />\n  );\n}\n```\n",".agents/skills/ai-elements/references/plan.md":"# Plan\n\nA collapsible plan component for displaying AI-generated execution plans with streaming support and shimmer animations.\n\nThe `Plan` component provides a flexible system for displaying AI-generated execution plans with collapsible content. Perfect for showing multi-step workflows, task breakdowns, and implementation strategies with support for streaming content and loading states.\n\nSee `scripts/plan.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add plan\n```\n\n## Features\n\n- Collapsible content with smooth animations\n- Streaming support with shimmer loading states\n- Built on shadcn/ui Card and Collapsible components\n- TypeScript support with comprehensive type definitions\n- Customizable styling with Tailwind CSS\n- Responsive design with mobile-friendly interactions\n- Keyboard navigation and accessibility support\n- Theme-aware with automatic dark mode support\n- Context-based state management for streaming\n\n## Props\n\n### `<Plan />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `isStreaming` | `boolean` | `false` | Whether content is currently streaming. Enables shimmer animations on title and description. |\n| `defaultOpen` | `boolean` | - | Whether the plan is expanded by default. |\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the Collapsible component. |\n\n### `<PlanHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CardHeader>` | - | Any other props are spread to the CardHeader component. |\n\n### `<PlanTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The title text. Displays with shimmer animation when isStreaming is true. |\n| `...props` | `Omit<React.ComponentProps<typeof CardTitle>, ` | - | Any other props (except children) are spread to the CardTitle component. |\n\n### `<PlanDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The description text. Displays with shimmer animation when isStreaming is true. |\n| `...props` | `Omit<React.ComponentProps<typeof CardDescription>, ` | - | Any other props (except children) are spread to the CardDescription component. |\n\n### `<PlanTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. Renders as a Button with chevron icon. |\n\n### `<PlanContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CardContent>` | - | Any other props are spread to the CardContent component. |\n\n### `<PlanFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<PlanAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CardAction>` | - | Any other props are spread to the CardAction component. |\n",".agents/skills/ai-elements/references/prompt-input.md":"# Prompt Input\n\nAllows a user to send a message with file attachments to a large language model. It includes a textarea, file upload capabilities, a submit button, and a dropdown for selecting the model.\n\nThe `PromptInput` component allows a user to send a message with file attachments to a large language model. It includes a textarea, file upload capabilities, a submit button, and a dropdown for selecting the model.\n\nSee `scripts/prompt-input.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add prompt-input\n```\n\n## Usage with AI SDK\n\nBuild a fully functional chat app using `PromptInput`, [`Conversation`](/components/conversation) with a model picker:\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Attachment,\n  AttachmentPreview,\n  AttachmentRemove,\n  Attachments,\n} from \"@/components/ai-elements/attachments\";\nimport {\n  PromptInput,\n  PromptInputActionAddAttachments,\n  PromptInputActionAddScreenshot,\n  PromptInputActionMenu,\n  PromptInputActionMenuContent,\n  PromptInputActionMenuTrigger,\n  PromptInputBody,\n  PromptInputButton,\n  PromptInputHeader,\n  type PromptInputMessage,\n  PromptInputSelect,\n  PromptInputSelectContent,\n  PromptInputSelectItem,\n  PromptInputSelectTrigger,\n  PromptInputSelectValue,\n  PromptInputSubmit,\n  PromptInputTextarea,\n  PromptInputFooter,\n  PromptInputTools,\n  usePromptInputAttachments,\n} from \"@/components/ai-elements/prompt-input\";\nimport { GlobeIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\n\nconst PromptInputAttachmentsDisplay = () => {\n  const attachments = usePromptInputAttachments();\n\n  if (attachments.files.length === 0) {\n    return null;\n  }\n\n  return (\n    <Attachments variant=\"inline\">\n      {attachments.files.map((attachment) => (\n        <Attachment\n          data={attachment}\n          key={attachment.id}\n          onRemove={() => attachments.remove(attachment.id)}\n        >\n          <AttachmentPreview />\n          <AttachmentRemove />\n        </Attachment>\n      ))}\n    </Attachments>\n  );\n};\n\nconst models = [\n  { id: \"gpt-4o\", name: \"GPT-4o\" },\n  { id: \"claude-opus-4-20250514\", name: \"Claude 4 Opus\" },\n];\n\nconst InputDemo = () => {\n  const [text, setText] = useState<string>(\"\");\n  const [model, setModel] = useState<string>(models[0].id);\n  const [useWebSearch, setUseWebSearch] = useState<boolean>(false);\n\n  const { messages, status, sendMessage } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    const hasText = Boolean(message.text);\n    const hasAttachments = Boolean(message.files?.length);\n\n    if (!(hasText || hasAttachments)) {\n      return;\n    }\n\n    sendMessage(\n      {\n        text: message.text || \"Sent with attachments\",\n        files: message.files,\n      },\n      {\n        body: {\n          model: model,\n          webSearch: useWebSearch,\n        },\n      }\n    );\n    setText(\"\");\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.map((message) => (\n              <Message from={message.role} key={message.id}>\n                <MessageContent>\n                  {message.parts.map((part, i) => {\n                    switch (part.type) {\n                      case \"text\":\n                        return (\n                          <MessageResponse key={`${message.id}-${i}`}>\n                            {part.text}\n                          </MessageResponse>\n                        );\n                      default:\n                        return null;\n                    }\n                  })}\n                </MessageContent>\n              </Message>\n            ))}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4\"\n          globalDrop\n          multiple\n        >\n          <PromptInputHeader>\n            <PromptInputAttachmentsDisplay />\n          </PromptInputHeader>\n          <PromptInputBody>\n            <PromptInputTextarea\n              onChange={(e) => setText(e.target.value)}\n              value={text}\n            />\n          </PromptInputBody>\n          <PromptInputFooter>\n            <PromptInputTools>\n              <PromptInputActionMenu>\n                <PromptInputActionMenuTrigger />\n                <PromptInputActionMenuContent>\n                  <PromptInputActionAddAttachments />\n                  <PromptInputActionAddScreenshot />\n                </PromptInputActionMenuContent>\n              </PromptInputActionMenu>\n              <PromptInputButton\n                onClick={() => setUseWebSearch(!useWebSearch)}\n                tooltip={{ content: \"Search the web\", shortcut: \"⌘K\" }}\n                variant={useWebSearch ? \"default\" : \"ghost\"}\n              >\n                <GlobeIcon size={16} />\n                <span>Search</span>\n              </PromptInputButton>\n              <PromptInputSelect\n                onValueChange={(value) => {\n                  setModel(value);\n                }}\n                value={model}\n              >\n                <PromptInputSelectTrigger>\n                  <PromptInputSelectValue />\n                </PromptInputSelectTrigger>\n                <PromptInputSelectContent>\n                  {models.map((model) => (\n                    <PromptInputSelectItem key={model.id} value={model.id}>\n                      {model.name}\n                    </PromptInputSelectItem>\n                  ))}\n                </PromptInputSelectContent>\n              </PromptInputSelect>\n            </PromptInputTools>\n            <PromptInputSubmit disabled={!text && !status} status={status} />\n          </PromptInputFooter>\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default InputDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/chat/route.ts\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const {\n    model,\n    messages,\n    webSearch,\n  }: {\n    messages: UIMessage[];\n    model: string;\n    webSearch?: boolean;\n  } = await req.json();\n\n  const result = streamText({\n    model: webSearch ? \"perplexity/sonar\" : model,\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Auto-resizing textarea that adjusts height based on content\n- File attachment support with drag-and-drop\n- Built-in screenshot capture action\n- Image preview for image attachments\n- Configurable file constraints (max files, max size, accepted types)\n- Automatic submit button icons based on status\n- Support for keyboard shortcuts (Enter to submit, Shift+Enter for new line)\n- Customizable min/max height for the textarea\n- Flexible toolbar with support for custom actions and tools\n- Built-in model selection dropdown\n- Built-in native speech recognition button (Web Speech API)\n- Optional provider for lifted state management\n- Form automatically resets on submit\n- Responsive design with mobile-friendly controls\n- Clean, modern styling with customizable themes\n- Form-based submission handling\n- Hidden file input sync for native form posts\n- Global document drop support (opt-in)\n\n## Examples\n\n### Cursor style\n\nSee `scripts/prompt-input-cursor.tsx` for this example.\n\n### Button tooltips\n\nButtons can display tooltips with optional keyboard shortcut hints. Hover over the buttons below to see the tooltips.\n\nSee `scripts/prompt-input-tooltip.tsx` for this example.\n\n## Props\n\n### `<PromptInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onSubmit` | `(message: PromptInputMessage, event: FormEvent) => void` | - | Handler called when the form is submitted with message text and files. |\n| `accept` | `string` | - | File types to accept (e.g.,  |\n| `multiple` | `boolean` | - | Whether to allow multiple file selection. |\n| `globalDrop` | `boolean` | - | When true, accepts file drops anywhere on the document. |\n| `syncHiddenInput` | `boolean` | - | Render a hidden input with given name for native form posts. |\n| `maxFiles` | `number` | - | Maximum number of files allowed. |\n| `maxFileSize` | `number` | - | Maximum file size in bytes. |\n| `onError` | `(err: { code: ` | - | Handler for file validation errors. |\n| `...props` | `React.HTMLAttributes<HTMLFormElement>` | - | Any other props are spread to the root form element. |\n\n### `<PromptInputTextarea />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Textarea>` | - | Any other props are spread to the underlying Textarea component. |\n\n### `<PromptInputFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the toolbar div. |\n\n### `<PromptInputTools />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the tools div. |\n\n### `<PromptInputButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string | { content: ReactNode; shortcut?: string; side?: ` | - | Optional tooltip to display on hover. Can be a string or an object with content, shortcut, and side properties. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n#### Tooltip Examples\n\n```tsx\n// Simple string tooltip\n<PromptInputButton tooltip=\"Search the web\">\n  <GlobeIcon size={16} />\n</PromptInputButton>\n\n// Tooltip with keyboard shortcut hint\n<PromptInputButton tooltip={{ content: \"Search\", shortcut: \"⌘K\" }}>\n  <GlobeIcon size={16} />\n</PromptInputButton>\n\n// Tooltip with custom position\n<PromptInputButton tooltip={{ content: \"Search\", side: \"bottom\" }}>\n  <GlobeIcon size={16} />\n</PromptInputButton>\n```\n\n### `<PromptInputSubmit />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `status` | `ChatStatus` | - | Current chat status to determine button icon (submitted, streaming, error). |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<PromptInputSelect />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Select>` | - | Any other props are spread to the underlying Select component. |\n\n### `<PromptInputSelectTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof SelectTrigger>` | - | Any other props are spread to the underlying SelectTrigger component. |\n\n### `<PromptInputSelectContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof SelectContent>` | - | Any other props are spread to the underlying SelectContent component. |\n\n### `<PromptInputSelectItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof SelectItem>` | - | Any other props are spread to the underlying SelectItem component. |\n\n### `<PromptInputSelectValue />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof SelectValue>` | - | Any other props are spread to the underlying SelectValue component. |\n\n### `<PromptInputBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the body div. |\n\n### Attachments\n\nAttachment components have been moved to a separate module. See the [Attachment](/components/attachment) component documentation for details on `<Attachments />`, `<Attachment />`, `<AttachmentPreview />`, `<AttachmentInfo />`, and `<AttachmentRemove />`.\n\n### `<PromptInputActionMenu />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenu>` | - | Any other props are spread to the underlying DropdownMenu component. |\n\n### `<PromptInputActionMenuTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying Button component. |\n\n### `<PromptInputActionMenuContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenuContent>` | - | Any other props are spread to the underlying DropdownMenuContent component. |\n\n### `<PromptInputActionMenuItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Any other props are spread to the underlying DropdownMenuItem component. |\n\n### `<PromptInputActionAddAttachments />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | Label for the menu item. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Any other props are spread to the underlying DropdownMenuItem component. |\n\n### `<PromptInputActionAddScreenshot />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | Label for the menu item. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Any other props are spread to the underlying DropdownMenuItem component. |\n\n### `<PromptInputProvider />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `initialInput` | `string` | - | Initial text input value. |\n| `children` | `React.ReactNode` | - | Child components that will have access to the provider context. |\n\nOptional global provider that lifts PromptInput state outside of PromptInput. When used, it allows you to access and control the input state from anywhere within the provider tree. If not used, PromptInput stays fully self-managed.\n\n### `<PromptInputHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `Omit<React.ComponentProps<typeof InputGroupAddon>, ` | - | Any other props (except align) are spread to the InputGroupAddon component. |\n\n### `<PromptInputHoverCard />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `openDelay` | `number` | `0` | Delay in milliseconds before opening. |\n| `closeDelay` | `number` | `0` | Delay in milliseconds before closing. |\n| `...props` | `React.ComponentProps<typeof HoverCard>` | - | Any other props are spread to the HoverCard component. |\n\n### `<PromptInputHoverCardTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof HoverCardTrigger>` | - | Any other props are spread to the HoverCardTrigger component. |\n\n### `<PromptInputHoverCardContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `align` | `unknown` | - | Alignment of the hover card content. |\n| `...props` | `React.ComponentProps<typeof HoverCardContent>` | - | Any other props are spread to the HoverCardContent component. |\n\n### `<PromptInputTabsList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<PromptInputTab />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<PromptInputTabLabel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLHeadingElement>` | - | Any other props are spread to the h3 element. |\n\n### `<PromptInputTabBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<PromptInputTabItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<PromptInputCommand />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Command>` | - | Any other props are spread to the Command component. |\n\n### `<PromptInputCommandInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the CommandInput component. |\n\n### `<PromptInputCommandList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandList>` | - | Any other props are spread to the CommandList component. |\n\n### `<PromptInputCommandEmpty />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the CommandEmpty component. |\n\n### `<PromptInputCommandGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandGroup>` | - | Any other props are spread to the CommandGroup component. |\n\n### `<PromptInputCommandItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the CommandItem component. |\n\n### `<PromptInputCommandSeparator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandSeparator>` | - | Any other props are spread to the CommandSeparator component. |\n\n## Hooks\n\n### `usePromptInputAttachments`\n\nAccess and manage file attachments within a PromptInput context.\n\n```tsx\nconst attachments = usePromptInputAttachments();\n\n// Available methods:\nattachments.files; // Array of current attachments\nattachments.add(files); // Add new files\nattachments.remove(id); // Remove an attachment by ID\nattachments.clear(); // Clear all attachments\nattachments.openFileDialog(); // Open file selection dialog\n```\n\n### `usePromptInputController`\n\nAccess the full PromptInput controller from a PromptInputProvider. Only available when using the provider.\n\n```tsx\nconst controller = usePromptInputController();\n\n// Available methods:\ncontroller.textInput.value; // Current text input value\ncontroller.textInput.setInput(value); // Set text input value\ncontroller.textInput.clear(); // Clear text input\ncontroller.attachments; // Same as usePromptInputAttachments\n```\n\n### `useProviderAttachments`\n\nAccess attachments context from a PromptInputProvider. Only available when using the provider.\n\n```tsx\nconst attachments = useProviderAttachments();\n\n// Same interface as usePromptInputAttachments\n```\n\n### `usePromptInputReferencedSources`\n\nAccess referenced sources context within a PromptInput.\n\n```tsx\nconst sources = usePromptInputReferencedSources();\n\n// Available methods:\nsources.sources; // Array of current referenced sources\nsources.add(sources); // Add new source(s)\nsources.remove(id); // Remove a source by ID\nsources.clear(); // Clear all sources\n```\n",".agents/skills/ai-elements/references/queue.md":"# Queue\n\nA comprehensive queue component system for displaying message lists, todos, and collapsible task sections in AI applications.\n\nThe `Queue` component provides a flexible system for displaying lists of messages, todos, attachments, and collapsible sections. Perfect for showing AI workflow progress, pending tasks, message history, or any structured list of items in your application.\n\nSee `scripts/queue.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add queue\n```\n\n## Features\n\n- Flexible component system with composable parts\n- Collapsible sections with smooth animations\n- Support for completed/pending state indicators\n- Built-in scroll area for long lists\n- Attachment display with images and file indicators\n- Hover-revealed action buttons for queue items\n- TypeScript support with comprehensive type definitions\n- Customizable styling with Tailwind CSS\n- Responsive design with mobile-friendly interactions\n- Keyboard navigation and accessibility support\n- Theme-aware with automatic dark mode support\n\n## Examples\n\n### With PromptInput\n\nSee `scripts/queue-prompt-input.tsx` for this example.\n\n## Props\n\n### `<Queue />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div. |\n\n### `<QueueSection />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultOpen` | `boolean` | `true` | Whether the section is open by default. |\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the Collapsible component. |\n\n### `<QueueSectionTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the button element. |\n\n### `<QueueSectionLabel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | The label text to display. |\n| `count` | `number` | - | The count to display before the label. |\n| `icon` | `React.ReactNode` | - | An optional icon to display before the count. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<QueueSectionContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent component. |\n\n### `<QueueList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof ScrollArea>` | - | Any other props are spread to the ScrollArea component. |\n\n### `<QueueItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the li element. |\n\n### `<QueueItemIndicator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `completed` | `boolean` | `false` | Whether the item is completed. Affects the indicator styling. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<QueueItemContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `completed` | `boolean` | `false` | Whether the item is completed. Affects text styling with strikethrough and opacity. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<QueueItemDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `completed` | `boolean` | `false` | Whether the item is completed. Affects text styling. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<QueueItemActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<QueueItemAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `Omit<React.ComponentProps<typeof Button>, ` | - | Any other props (except variant and size) are spread to the Button component. |\n\n### `<QueueItemAttachment />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<QueueItemImage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the img element. |\n\n### `<QueueItemFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n## Type Exports\n\n### `QueueMessagePart`\n\nInterface for message parts within queue messages.\n\n```tsx\ninterface QueueMessagePart {\n  type: string;\n  text?: string;\n  url?: string;\n  filename?: string;\n  mediaType?: string;\n}\n```\n\n### `QueueMessage`\n\nInterface for queue message items.\n\n```tsx\ninterface QueueMessage {\n  id: string;\n  parts: QueueMessagePart[];\n}\n```\n\n### `QueueTodo`\n\nInterface for todo items in the queue.\n\n```tsx\ninterface QueueTodo {\n  id: string;\n  title: string;\n  description?: string;\n  status?: \"pending\" | \"completed\";\n}\n```\n",".agents/skills/ai-elements/references/reasoning.md":"# Reasoning\n\nA collapsible component that displays AI reasoning content, automatically opening during streaming and closing when finished.\n\nThe `Reasoning` component displays AI reasoning content, automatically opening during streaming and closing when finished.\n\nSee `scripts/reasoning.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add reasoning\n```\n\n## Usage with AI SDK\n\nBuild a chatbot with reasoning using Deepseek R1 or other reasoning models.\n\nSome models (like GPT with high reasoning effort) return multiple reasoning parts instead of a single streaming block. The example below consolidates all reasoning parts into a single component to avoid displaying multiple \"Thinking...\" indicators.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Reasoning,\n  ReasoningContent,\n  ReasoningTrigger,\n} from \"@/components/ai-elements/reasoning\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { Spinner } from \"@/components/ui/spinner\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport type { UIMessage } from \"ai\";\n\nconst MessageParts = ({\n  message,\n  isLastMessage,\n  isStreaming,\n}: {\n  message: UIMessage;\n  isLastMessage: boolean;\n  isStreaming: boolean;\n}) => {\n  // Consolidate all reasoning parts into one block\n  const reasoningParts = message.parts.filter(\n    (part) => part.type === \"reasoning\"\n  );\n  const reasoningText = reasoningParts.map((part) => part.text).join(\"\\n\\n\");\n  const hasReasoning = reasoningParts.length > 0;\n\n  // Check if reasoning is still streaming (last part is reasoning on last message)\n  const lastPart = message.parts.at(-1);\n  const isReasoningStreaming =\n    isLastMessage && isStreaming && lastPart?.type === \"reasoning\";\n\n  return (\n    <>\n      {hasReasoning && (\n        <Reasoning className=\"w-full\" isStreaming={isReasoningStreaming}>\n          <ReasoningTrigger />\n          <ReasoningContent>{reasoningText}</ReasoningContent>\n        </Reasoning>\n      )}\n      {message.parts.map((part, i) => {\n        if (part.type === \"text\") {\n          return (\n            <MessageResponse key={`${message.id}-${i}`}>\n              {part.text}\n            </MessageResponse>\n          );\n        }\n        return null;\n      })}\n    </>\n  );\n};\n\nconst ReasoningDemo = () => {\n  const [input, setInput] = useState(\"\");\n\n  const { messages, sendMessage, status } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    sendMessage({ text: message.text });\n    setInput(\"\");\n  };\n\n  const isStreaming = status === \"streaming\";\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.map((message, index) => (\n              <Message from={message.role} key={message.id}>\n                <MessageContent>\n                  <MessageParts\n                    message={message}\n                    isLastMessage={index === messages.length - 1}\n                    isStreaming={isStreaming}\n                  />\n                </MessageContent>\n              </Message>\n            ))}\n            {status === \"submitted\" && <Spinner />}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Say something...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={isStreaming ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ReasoningDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/chat/route.ts\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { model, messages }: { messages: UIMessage[]; model: string } =\n    await req.json();\n\n  const result = streamText({\n    model: \"deepseek/deepseek-r1\",\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse({\n    sendReasoning: true,\n  });\n}\n```\n\n## Reasoning vs Chain of Thought\n\nUse the `Reasoning` component when your model outputs thinking content as a single block or continuous stream (Deepseek R1, Claude with extended thinking, etc.).\n\nIf your model outputs discrete, labeled steps (search queries, tool calls, distinct thought stages), consider using the [Chain of Thought](/components/chain-of-thought) component instead for a more structured visual representation.\n\n## Features\n\n- Automatically opens when streaming content and closes when finished\n- Manual toggle control for user interaction\n- Smooth animations and transitions powered by Radix UI\n- Visual streaming indicator with pulsing animation\n- Composable architecture with separate trigger and content components\n- Built with accessibility in mind including keyboard navigation\n- Responsive design that works across different screen sizes\n- Seamlessly integrates with both light and dark themes\n- Built on top of shadcn/ui Collapsible primitives\n- TypeScript support with proper type definitions\n\n## Props\n\n### `<Reasoning />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `isStreaming` | `boolean` | `false` | Whether the reasoning is currently streaming (auto-opens and closes the panel). |\n| `open` | `boolean` | - | Controlled open state. |\n| `defaultOpen` | `boolean` | `true` | Default open state when uncontrolled. |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback when open state changes. |\n| `duration` | `number` | - | Duration in seconds to display (can be controlled externally). |\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the underlying Collapsible component. |\n\n### `<ReasoningTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `getThinkingMessage` | `(isStreaming: boolean, duration?: number) => ReactNode` | - | Optional function to customize the thinking message. Receives isStreaming and duration parameters. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the underlying CollapsibleTrigger component. |\n\n### `<ReasoningContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | Required | The reasoning text to display (rendered via Streamdown). |\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the underlying CollapsibleContent component. |\n\n## Hooks\n\n### `useReasoning`\n\nAccess the reasoning context from child components.\n\n```tsx\nconst { isStreaming, isOpen, setIsOpen, duration } = useReasoning();\n```\n\nReturns:\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `isStreaming` | `boolean` | - | Whether reasoning is currently streaming. |\n| `isOpen` | `boolean` | - | Whether the reasoning panel is open. |\n| `setIsOpen` | `(open: boolean) => void` | - | Function to set the open state. |\n| `duration` | `number | undefined` | - | Duration in seconds (undefined while streaming). |\n",".agents/skills/ai-elements/references/sandbox.md":"# Sandbox\n\nA collapsible container for displaying AI-generated code and output in chat interfaces.\n\nThe `Sandbox` component provides a structured way to display AI-generated code alongside its execution output in chat conversations. It features a collapsible container with status indicators and tabbed navigation between code and output views. It's designed to be used with `CodeBlock` for displaying code and `StackTrace` for displaying errors.\n\nSee `scripts/sandbox.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add sandbox\n```\n\n## Features\n\n- Collapsible container with smooth animations\n- Status badges showing execution state (Pending, Running, Completed, Error)\n- Tabs for Code and Output views\n- Syntax-highlighted code display\n- Copy button for easy code sharing\n- Works with AI SDK tool state patterns\n\n## Usage with AI SDK\n\nThe Sandbox component integrates with the AI SDK's tool state to show code generation progress:\n\n```tsx title=\"components/code-sandbox.tsx\"\n\"use client\";\n\nimport type { ToolUIPart } from \"ai\";\nimport {\n  Sandbox,\n  SandboxContent,\n  SandboxHeader,\n  SandboxTabContent,\n  SandboxTabs,\n  SandboxTabsBar,\n  SandboxTabsList,\n  SandboxTabsTrigger,\n} from \"@/components/ai-elements/sandbox\";\nimport { CodeBlock } from \"@/components/ai-elements/code-block\";\n\ntype CodeSandboxProps = {\n  toolPart: ToolUIPart;\n};\n\nexport const CodeSandbox = ({ toolPart }: CodeSandboxProps) => {\n  const code = toolPart.input?.code ?? \"\";\n  const output = toolPart.output?.logs ?? \"\";\n\n  return (\n    <Sandbox>\n      <SandboxHeader\n        state={toolPart.state}\n        title={toolPart.input?.filename ?? \"code.tsx\"}\n      />\n      <SandboxContent>\n        <SandboxTabs defaultValue=\"code\">\n          <SandboxTabsBar>\n            <SandboxTabsList>\n              <SandboxTabsTrigger value=\"code\">Code</SandboxTabsTrigger>\n              <SandboxTabsTrigger value=\"output\">Output</SandboxTabsTrigger>\n            </SandboxTabsList>\n          </SandboxTabsBar>\n          <SandboxTabContent value=\"code\">\n            <CodeBlock code={code} language=\"tsx\" />\n          </SandboxTabContent>\n          <SandboxTabContent value=\"output\">\n            <CodeBlock code={output} language=\"log\" />\n          </SandboxTabContent>\n        </SandboxTabs>\n      </SandboxContent>\n    </Sandbox>\n  );\n};\n```\n\n## Props\n\n### `<Sandbox />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the underlying Collapsible component. |\n\n### `<SandboxHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | `undefined` | The title displayed in the header (e.g., filename). |\n| `state` | `ToolUIPart[` | Required | The current execution state, used to display the appropriate status badge. |\n| `className` | `string` | - | Additional CSS classes for the header. |\n\n### `<SandboxContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent. |\n\n### `<SandboxTabs />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Tabs>` | - | Any other props are spread to the underlying Tabs component. |\n\n### `<SandboxTabsBar />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n\n### `<SandboxTabsList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof TabsList>` | - | Any other props are spread to the underlying TabsList component. |\n\n### `<SandboxTabsTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof TabsTrigger>` | - | Any other props are spread to the underlying TabsTrigger component. |\n\n### `<SandboxTabContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof TabsContent>` | - | Any other props are spread to the underlying TabsContent component. |\n",".agents/skills/ai-elements/references/schema-display.md":"# Schema Display\n\nDisplay REST API endpoint documentation with parameters, request/response bodies.\n\nThe `SchemaDisplay` component visualizes REST API endpoints with HTTP methods, paths, parameters, and request/response schemas.\n\nSee `scripts/schema-display.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add schema-display\n```\n\n## Features\n\n- Color-coded HTTP methods\n- Path parameter highlighting\n- Collapsible parameters section\n- Request/response body schemas\n- Nested object property display\n- Required field indicators\n\n## Method Colors\n\n| Method   | Color  |\n| -------- | ------ |\n| `GET`    | Green  |\n| `POST`   | Blue   |\n| `PUT`    | Orange |\n| `PATCH`  | Yellow |\n| `DELETE` | Red    |\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/schema-display-basic.tsx` for this example.\n\n### With Parameters\n\nSee `scripts/schema-display-params.tsx` for this example.\n\n### With Request/Response Bodies\n\nSee `scripts/schema-display-body.tsx` for this example.\n\n### Nested Properties\n\nSee `scripts/schema-display-nested.tsx` for this example.\n\n## Props\n\n### `<SchemaDisplay />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `method` | `unknown` | - | HTTP method. |\n| `path` | `string` | - | API endpoint path. |\n| `description` | `string` | - | Endpoint description. |\n| `parameters` | `SchemaParameter[]` | - | URL/query parameters. |\n| `requestBody` | `SchemaProperty[]` | - | Request body properties. |\n| `responseBody` | `SchemaProperty[]` | - | Response body properties. |\n\n### `SchemaParameter`\n\n```tsx\ninterface SchemaParameter {\n  name: string;\n  type: string;\n  required?: boolean;\n  description?: string;\n  location?: \"path\" | \"query\" | \"header\";\n}\n```\n\n### `SchemaProperty`\n\n```tsx\ninterface SchemaProperty {\n  name: string;\n  type: string;\n  required?: boolean;\n  description?: string;\n  properties?: SchemaProperty[]; // For objects\n  items?: SchemaProperty; // For arrays\n}\n```\n\n### Subcomponents\n\n- `SchemaDisplayHeader` - Header container\n- `SchemaDisplayMethod` - Color-coded method badge\n- `SchemaDisplayPath` - Path with highlighted parameters\n- `SchemaDisplayDescription` - Description text\n- `SchemaDisplayContent` - Content container\n- `SchemaDisplayParameters` - Collapsible parameters section\n- `SchemaDisplayParameter` - Individual parameter\n- `SchemaDisplayRequest` - Collapsible request body\n- `SchemaDisplayResponse` - Collapsible response body\n- `SchemaDisplayProperty` - Schema property (recursive)\n- `SchemaDisplayExample` - Code example block\n",".agents/skills/ai-elements/references/shimmer.md":"# Shimmer\n\nAn animated text shimmer component for creating eye-catching loading states and progressive reveal effects.\n\nThe `Shimmer` component provides an animated shimmer effect that sweeps across text, perfect for indicating loading states, progressive reveals, or drawing attention to dynamic content in AI applications.\n\nSee `scripts/shimmer.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add shimmer\n```\n\n## Features\n\n- Smooth animated shimmer effect using CSS gradients and Framer Motion\n- Customizable animation duration and spread\n- Polymorphic component - render as any HTML element via the `as` prop\n- Automatic spread calculation based on text length\n- Theme-aware styling using CSS custom properties\n- Infinite looping animation with linear easing\n- TypeScript support with proper type definitions\n- Memoized for optimal performance\n- Responsive and accessible design\n- Uses `text-transparent` with background-clip for crisp text rendering\n\n## Examples\n\n### Different Durations\n\nSee `scripts/shimmer-duration.tsx` for this example.\n\n### Custom Elements\n\nSee `scripts/shimmer-elements.tsx` for this example.\n\n## Props\n\n### `<Shimmer />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The text content to apply the shimmer effect to. |\n| `as` | `ElementType` | - | The HTML element or React component to render. |\n| `className` | `string` | - | Additional CSS classes to apply to the component. |\n| `duration` | `number` | `2` | The duration of the shimmer animation in seconds. |\n| `spread` | `number` | `2` | The spread multiplier for the shimmer gradient, multiplied by text length. |\n",".agents/skills/ai-elements/references/snippet.md":"# Snippet\n\nLightweight inline code display for terminal commands and short code references.\n\nThe `Snippet` component provides a lightweight way to display terminal commands and short code snippets with copy functionality. Built on top of InputGroup, it's designed for brief code references in text.\n\nSee `scripts/snippet.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add snippet\n```\n\n## Features\n\n- Composable architecture with InputGroup\n- Optional prefix text (e.g., `$` for terminal commands)\n- Built-in copy button\n- Compact design for chat/markdown\n\n## Examples\n\n### Without Prefix\n\nSee `scripts/snippet-plain.tsx` for this example.\n\n## Props\n\n### `<Snippet />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `code` | `string` | Required | The code content to display. |\n| `children` | `React.ReactNode` | - | Child elements like SnippetAddon, SnippetInput, etc. |\n| `...props` | `React.ComponentProps<typeof InputGroup>` | - | Spread to the InputGroup component. |\n\n### `<SnippetAddon />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof InputGroupAddon>` | - | Spread to the InputGroupAddon component. |\n\n### `<SnippetText />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof InputGroupText>` | - | Spread to the InputGroupText component. |\n\n### `<SnippetInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `Omit<React.ComponentProps<typeof InputGroupInput>, ` | - | Spread to the InputGroupInput component. Value and readOnly are set automatically. |\n\n### `<SnippetCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback fired after a successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback fired if copying fails. |\n| `timeout` | `number` | `2000` | How long to show the copied state (ms). |\n| `children` | `React.ReactNode` | - | Custom button content. |\n| `...props` | `React.ComponentProps<typeof InputGroupButton>` | - | Spread to the InputGroupButton component. |\n",".agents/skills/ai-elements/references/sources.md":"# Sources\n\nA component that allows a user to view the sources or citations used to generate a response.\n\nThe `Sources` component allows a user to view the sources or citations used to generate a response.\n\nSee `scripts/sources.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add sources\n```\n\n## Usage with AI SDK\n\nBuild a simple web search agent with Perplexity Sonar.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  Source,\n  Sources,\n  SourcesContent,\n  SourcesTrigger,\n} from \"@/components/ai-elements/sources\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport { useState } from \"react\";\nimport { DefaultChatTransport } from \"ai\";\n\nconst SourceDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { messages, sendMessage, status } = useChat({\n    transport: new DefaultChatTransport({\n      api: \"/api/sources\",\n    }),\n  });\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex-1 overflow-auto mb-4\">\n          <Conversation>\n            <ConversationContent>\n              {messages.map((message) => (\n                <div key={message.id}>\n                  {message.role === \"assistant\" && (\n                    <Sources>\n                      <SourcesTrigger\n                        count={\n                          message.parts.filter(\n                            (part) => part.type === \"source-url\"\n                          ).length\n                        }\n                      />\n                      {message.parts.map((part, i) => {\n                        switch (part.type) {\n                          case \"source-url\":\n                            return (\n                              <SourcesContent key={`${message.id}-${i}`}>\n                                <Source\n                                  key={`${message.id}-${i}`}\n                                  href={part.url}\n                                  title={part.url}\n                                />\n                              </SourcesContent>\n                            );\n                        }\n                      })}\n                    </Sources>\n                  )}\n                  <Message from={message.role} key={message.id}>\n                    <MessageContent>\n                      {message.parts.map((part, i) => {\n                        switch (part.type) {\n                          case \"text\":\n                            return (\n                              <MessageResponse key={`${message.id}-${i}`}>\n                                {part.text}\n                              </MessageResponse>\n                            );\n                          default:\n                            return null;\n                        }\n                      })}\n                    </MessageContent>\n                  </Message>\n                </div>\n              ))}\n            </ConversationContent>\n            <ConversationScrollButton />\n          </Conversation>\n        </div>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Ask a question and search the...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default SourceDemo;\n```\n\nAdd the following route to your backend:\n\n```tsx title=\"api/chat/route.ts\"\nimport { convertToModelMessages, streamText, UIMessage } from \"ai\";\nimport { perplexity } from \"@ai-sdk/perplexity\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"perplexity/sonar\",\n    system:\n      \"You are a helpful assistant. Keep your responses short (< 100 words) unless you are asked for more details. ALWAYS USE SEARCH.\",\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse({\n    sendSources: true,\n  });\n}\n```\n\n## Features\n\n- Collapsible component that allows a user to view the sources or citations used to generate a response\n- Customizable trigger and content components\n- Support for custom sources or citations\n- Responsive design with mobile-friendly controls\n- Clean, modern styling with customizable themes\n\n## Examples\n\n### Custom rendering\n\nSee `scripts/sources-custom.tsx` for this example.\n\n## Props\n\n### `<Sources />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<SourcesTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `count` | `number` | Required | The number of sources to display in the trigger. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<SourcesContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the content container. |\n\n### `<Source />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.AnchorHTMLAttributes<HTMLAnchorElement>` | - | Any other props are spread to the anchor element. |\n",".agents/skills/ai-elements/references/speech-input.md":"# Speech Input\n\nA button component that captures voice input and converts it to text, with cross-browser support.\n\nThe `SpeechInput` component provides an easy-to-use interface for capturing voice input in your application. It uses the Web Speech API for real-time transcription in supported browsers (Chrome, Edge), and falls back to MediaRecorder with an external transcription service for browsers that don't support Web Speech API (Firefox, Safari).\n\nSee `scripts/speech-input.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add speech-input\n```\n\n## Features\n\n- Built on Web Speech API (SpeechRecognition) with MediaRecorder fallback\n- Cross-browser support (Chrome, Edge, Firefox, Safari)\n- Continuous speech recognition with interim results\n- Visual feedback with pulse animation when listening\n- Loading state during transcription processing\n- Automatic browser compatibility detection\n- Final transcript extraction and callbacks\n- Error handling and automatic state management\n- Extends shadcn/ui Button component\n- Full TypeScript support\n\n## Props\n\n### `<SpeechInput />`\n\nThe component extends the shadcn/ui Button component, so all Button props are available.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onTranscriptionChange` | `(text: string) => void` | - | Callback fired when final transcription text is available. Only fires for completed phrases, not interim results. |\n| `onAudioRecorded` | `(audioBlob: Blob) => Promise<string>` | - | Callback for MediaRecorder fallback. Required for Firefox/Safari support. Receives recorded audio blob and should return transcribed text from an external service (e.g., OpenAI Whisper). |\n| `lang` | `string` | - | Language for speech recognition. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component, including variant, size, disabled, etc. |\n\n## Behavior\n\n### Speech Recognition Modes\n\nThe component automatically detects browser capabilities and uses the best available method:\n\n| Browser         | Mode           | Behavior                                               |\n| --------------- | -------------- | ------------------------------------------------------ |\n| Chrome, Edge    | Web Speech API | Real-time transcription, no server required            |\n| Firefox, Safari | MediaRecorder  | Records audio, sends to external transcription service |\n| Unsupported     | Disabled       | Button is disabled                                     |\n\n### Web Speech API Mode (Chrome, Edge)\n\nUses the Web Speech API with the following configuration:\n\n- **Continuous**: Set to `true` to keep recognition active until manually stopped\n- **Interim Results**: Set to `true` to receive partial results during speech\n- **Language**: Configurable via `lang` prop, defaults to `\"en-US\"`\n\n### MediaRecorder Mode (Firefox, Safari)\n\nWhen the Web Speech API is unavailable, the component falls back to recording audio:\n\n1. Records audio using `MediaRecorder` API\n2. On stop, creates an audio blob (`audio/webm`)\n3. Calls `onAudioRecorded` with the blob\n4. Waits for transcription result\n5. Passes result to `onTranscriptionChange`\n\n**Note**: The `onAudioRecorded` prop is required for this mode to work. Without it, the button will be disabled in Firefox/Safari.\n\n### Transcription Processing\n\nThe component only calls `onTranscriptionChange` with **final transcripts**. Interim results (Web Speech API) are ignored to prevent incomplete text from being processed.\n\n### Visual States\n\n- **Default State**: Standard button appearance with microphone icon\n- **Listening State**: Pulsing animation with accent colors to indicate active listening\n- **Processing State**: Loading spinner while waiting for transcription (MediaRecorder mode)\n- **Disabled State**: Button is disabled when no API is available or required props are missing\n\n### Lifecycle\n\n1. **Mount**: Detects available APIs and initializes appropriate mode\n2. **Click**: Toggles between listening/recording and stopped states\n3. **Stop (MediaRecorder)**: Processes audio and waits for transcription\n4. **Unmount**: Stops recognition/recording and releases microphone\n\n## Browser Support\n\nThe component provides cross-browser support through a two-tier system:\n\n| Browser | API Used       | Requirements           |\n| ------- | -------------- | ---------------------- |\n| Chrome  | Web Speech API | None                   |\n| Edge    | Web Speech API | None                   |\n| Firefox | MediaRecorder  | `onAudioRecorded` prop |\n| Safari  | MediaRecorder  | `onAudioRecorded` prop |\n\nFor full cross-browser support, provide the `onAudioRecorded` callback that sends audio to a transcription service like OpenAI Whisper, Google Cloud Speech-to-Text, or AssemblyAI.\n\n## Accessibility\n\n- Uses semantic button element via shadcn/ui Button\n- Visual feedback for listening state\n- Keyboard accessible (can be triggered with Space/Enter)\n- Screen reader friendly with proper button semantics\n\n## Usage with MediaRecorder Fallback\n\nTo support Firefox and Safari, provide an `onAudioRecorded` callback that sends audio to a transcription service:\n\n```tsx\nconst handleAudioRecorded = async (audioBlob: Blob): Promise<string> => {\n  const formData = new FormData();\n  formData.append(\"file\", audioBlob, \"audio.webm\");\n  formData.append(\"model\", \"whisper-1\");\n\n  const response = await fetch(\n    \"https://api.openai.com/v1/audio/transcriptions\",\n    {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,\n      },\n      body: formData,\n    }\n  );\n\n  const data = await response.json();\n  return data.text;\n};\n\n<SpeechInput\n  onTranscriptionChange={(text) => console.log(text)}\n  onAudioRecorded={handleAudioRecorded}\n/>;\n```\n\n## Notes\n\n- Requires a secure context (HTTPS or localhost)\n- Browser may prompt user for microphone permission\n- Only final transcripts trigger the `onTranscriptionChange` callback\n- Language is configurable via the `lang` prop\n- Continuous recognition continues until button is clicked again\n- Errors are logged to console and automatically stop recognition/recording\n- MediaRecorder fallback requires the `onAudioRecorded` prop to be provided\n- Audio is recorded in `audio/webm` format for the MediaRecorder fallback\n\n## TypeScript\n\nThe component includes full TypeScript definitions for the Web Speech API:\n\n- `SpeechRecognition`\n- `SpeechRecognitionEvent`\n- `SpeechRecognitionResult`\n- `SpeechRecognitionAlternative`\n- `SpeechRecognitionErrorEvent`\n\nThese types are properly declared for both standard and webkit-prefixed implementations.\n",".agents/skills/ai-elements/references/stack-trace.md":"# Stack Trace\n\nDisplays formatted JavaScript/Node.js error stack traces with syntax highlighting and collapsible frames.\n\nThe `StackTrace` component displays formatted JavaScript/Node.js error stack traces with clickable file paths, internal frame dimming, and collapsible content.\n\nSee `scripts/stack-trace.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add stack-trace\n```\n\n## Usage with AI SDK\n\nBuild an error display tool that shows stack traces from AI-generated code using the [`useChat`](https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-chat) hook.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  StackTrace,\n  StackTraceHeader,\n  StackTraceError,\n  StackTraceErrorType,\n  StackTraceErrorMessage,\n  StackTraceActions,\n  StackTraceCopyButton,\n  StackTraceExpandButton,\n  StackTraceContent,\n  StackTraceFrames,\n} from \"@/components/ai-elements/stack-trace\";\n\nexport default function Page() {\n  const { messages } = useChat({\n    api: \"/api/run-code\",\n  });\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6\">\n      {messages.map((message) => {\n        const toolInvocations = message.parts?.filter(\n          (part) => part.type === \"tool-invocation\"\n        );\n\n        return toolInvocations?.map((tool) => {\n          if (tool.toolName === \"runCode\" && tool.result?.error) {\n            return (\n              <StackTrace\n                key={tool.toolCallId}\n                trace={tool.result.error}\n                defaultOpen\n              >\n                <StackTraceHeader>\n                  <StackTraceError>\n                    <StackTraceErrorType />\n                    <StackTraceErrorMessage />\n                  </StackTraceError>\n                  <StackTraceActions>\n                    <StackTraceCopyButton />\n                    <StackTraceExpandButton />\n                  </StackTraceActions>\n                </StackTraceHeader>\n                <StackTraceContent>\n                  <StackTraceFrames />\n                </StackTraceContent>\n              </StackTrace>\n            );\n          }\n          return null;\n        });\n      })}\n    </div>\n  );\n}\n```\n\nAdd the following route to your backend:\n\n```tsx title=\"api/run-code/route.ts\"\nimport { streamText, tool } from \"ai\";\nimport { z } from \"zod\";\n\nexport async function POST(req: Request) {\n  const { messages } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages,\n    tools: {\n      runCode: tool({\n        description: \"Execute JavaScript code and return any errors\",\n        parameters: z.object({\n          code: z.string(),\n        }),\n        execute: async ({ code }) => {\n          try {\n            // Execute code in sandbox\n            eval(code);\n            return { success: true };\n          } catch (error) {\n            return { error: (error as Error).stack };\n          }\n        },\n      }),\n    },\n  });\n\n  return result.toDataStreamResponse();\n}\n```\n\n## Features\n\n- Parses standard JavaScript/Node.js stack trace format\n- Highlights error type in red\n- Dims internal frames (node_modules, node: paths)\n- Collapsible content with smooth animation\n- Copy full stack trace to clipboard\n- Clickable file paths with line/column numbers\n\n## Examples\n\n### Collapsed by Default\n\nSee `scripts/stack-trace-collapsed.tsx` for this example.\n\n### Hide Internal Frames\n\nSee `scripts/stack-trace-no-internal.tsx` for this example.\n\n## Props\n\n### `<StackTrace />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `trace` | `string` | - | The raw stack trace string to parse and display. |\n| `open` | `boolean` | - | Controlled open state. |\n| `defaultOpen` | `boolean` | `false` | Whether the content is expanded by default. |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback when open state changes. |\n| `onFilePathClick` | `(path: string, line?: number, column?: number) => void` | - | Callback when a file path is clicked. Receives the file path, line number, and column number. |\n| `children` | `React.ReactNode` | - | Child elements (StackTraceHeader, StackTraceContent, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<StackTraceHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Header content (typically StackTraceError and StackTraceActions). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger. |\n\n### `<StackTraceError />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Error content (typically StackTraceErrorType and StackTraceErrorMessage). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n\n### `<StackTraceErrorType />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom content. Defaults to the parsed error type (e.g.,  |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<StackTraceErrorMessage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom content. Defaults to the parsed error message. |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<StackTraceActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Action buttons (typically StackTraceCopyButton and StackTraceExpandButton). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n\n### `<StackTraceCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback fired after a successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback fired if copying fails. |\n| `timeout` | `number` | `2000` | How long to show the copied state (ms). |\n| `children` | `React.ReactNode` | - | Custom content for the button. Defaults to copy/check icons. |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<StackTraceExpandButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n\n### `<StackTraceContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `maxHeight` | `number` | `400` | Maximum height of the content area. Enables scrolling when content exceeds this height. |\n| `children` | `React.ReactNode` | - | Content to display (typically StackTraceFrames). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent. |\n\n### `<StackTraceFrames />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `showInternalFrames` | `boolean` | `true` | Whether to show internal frames (node_modules, node: paths). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n",".agents/skills/ai-elements/references/suggestion.md":"# Suggestion\n\nA suggestion component that displays a horizontal row of clickable suggestions for user interaction.\n\nThe `Suggestion` component displays a horizontal row of clickable suggestions for user interaction.\n\nSee `scripts/suggestion.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add suggestion\n```\n\n## Usage with AI SDK\n\nBuild a simple input with suggestions users can click to send a message to the LLM.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { Suggestion, Suggestions } from \"@/components/ai-elements/suggestion\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\n\nconst suggestions = [\n  \"Can you explain how to play tennis?\",\n  \"What is the weather in Tokyo?\",\n  \"How do I make a really good fish taco?\",\n];\n\nconst SuggestionDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { sendMessage, status } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  const handleSuggestionClick = (suggestion: string) => {\n    sendMessage({ text: suggestion });\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex flex-col gap-4\">\n          <Suggestions>\n            {suggestions.map((suggestion) => (\n              <Suggestion\n                key={suggestion}\n                onClick={handleSuggestionClick}\n                suggestion={suggestion}\n              />\n            ))}\n          </Suggestions>\n          <PromptInput\n            onSubmit={handleSubmit}\n            className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n          >\n            <PromptInputTextarea\n              value={input}\n              placeholder=\"Say something...\"\n              onChange={(e) => setInput(e.currentTarget.value)}\n              className=\"pr-12\"\n            />\n            <PromptInputSubmit\n              status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n              disabled={!input.trim()}\n              className=\"absolute bottom-1 right-1\"\n            />\n          </PromptInput>\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default SuggestionDemo;\n```\n\n## Features\n\n- Horizontal row of clickable suggestion buttons\n- Customizable styling with variant and size options\n- Flexible layout that wraps suggestions on smaller screens\n- onClick callback that emits the selected suggestion string\n- Support for both individual suggestions and suggestion lists\n- Clean, modern styling with hover effects\n- Responsive design with mobile-friendly touch targets\n- TypeScript support with proper type definitions\n\n## Examples\n\n### Usage with AI Input\n\nSee `scripts/suggestion-input.tsx` for this example.\n\n## Props\n\n### `<Suggestions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof ScrollArea>` | - | Any other props are spread to the underlying ScrollArea component. |\n\n### `<Suggestion />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `suggestion` | `string` | Required | The suggestion string to display and emit on click. |\n| `onClick` | `(suggestion: string) => void` | - | Callback fired when the suggestion is clicked. |\n| `...props` | `Omit<React.ComponentProps<typeof Button>, ` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n",".agents/skills/ai-elements/references/task.md":"# Task\n\nA collapsible task list component for displaying AI workflow progress, with status indicators and optional descriptions.\n\nThe `Task` component provides a structured way to display task lists or workflow progress with collapsible details, status indicators, and progress tracking. It consists of a main `Task` container with `TaskTrigger` for the clickable header and `TaskContent` for the collapsible content area.\n\nSee `scripts/task.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add task\n```\n\n## Usage with AI SDK\n\nBuild a mock async programming agent using [`experimental_generateObject`](/docs/reference/ai-sdk-ui/use-object).\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { experimental_useObject as useObject } from \"@ai-sdk/react\";\nimport {\n  Task,\n  TaskItem,\n  TaskItemFile,\n  TaskTrigger,\n  TaskContent,\n} from \"@/components/ai-elements/task\";\nimport { Button } from \"@/components/ui/button\";\nimport { tasksSchema } from \"@/app/api/task/route\";\nimport {\n  SiReact,\n  SiTypescript,\n  SiJavascript,\n  SiCss,\n  SiHtml5,\n  SiJson,\n  SiMarkdown,\n} from \"@icons-pack/react-simple-icons\";\n\nconst iconMap = {\n  react: { component: SiReact, color: \"#149ECA\" },\n  typescript: { component: SiTypescript, color: \"#3178C6\" },\n  javascript: { component: SiJavascript, color: \"#F7DF1E\" },\n  css: { component: SiCss, color: \"#1572B6\" },\n  html: { component: SiHtml5, color: \"#E34F26\" },\n  json: { component: SiJson, color: \"#000000\" },\n  markdown: { component: SiMarkdown, color: \"#000000\" },\n};\n\nconst TaskDemo = () => {\n  const { object, submit, isLoading } = useObject({\n    api: \"/api/agent\",\n    schema: tasksSchema,\n  });\n\n  const handleSubmit = (taskType: string) => {\n    submit({ prompt: taskType });\n  };\n\n  const renderTaskItem = (item: any, index: number) => {\n    if (item?.type === \"file\" && item.file) {\n      const iconInfo = iconMap[item.file.icon as keyof typeof iconMap];\n      if (iconInfo) {\n        const IconComponent = iconInfo.component;\n        return (\n          <span className=\"inline-flex items-center gap-1\" key={index}>\n            {item.text}\n            <TaskItemFile>\n              <IconComponent\n                color={item.file.color || iconInfo.color}\n                className=\"size-4\"\n              />\n              <span>{item.file.name}</span>\n            </TaskItemFile>\n          </span>\n        );\n      }\n    }\n    return item?.text || \"\";\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex gap-2 mb-6 flex-wrap\">\n          <Button\n            onClick={() => handleSubmit(\"React component development\")}\n            disabled={isLoading}\n            variant=\"outline\"\n          >\n            React Development\n          </Button>\n        </div>\n\n        <div className=\"flex-1 overflow-auto space-y-4\">\n          {isLoading && !object && (\n            <div className=\"text-muted-foreground\">Generating tasks...</div>\n          )}\n\n          {object?.tasks?.map((task: any, taskIndex: number) => (\n            <Task key={taskIndex} defaultOpen={taskIndex === 0}>\n              <TaskTrigger title={task.title || \"Loading...\"} />\n              <TaskContent>\n                {task.items?.map((item: any, itemIndex: number) => (\n                  <TaskItem key={itemIndex}>\n                    {renderTaskItem(item, itemIndex)}\n                  </TaskItem>\n                ))}\n              </TaskContent>\n            </Task>\n          ))}\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default TaskDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/agent.ts\"\nimport { streamObject } from \"ai\";\nimport { z } from \"zod\";\n\nexport const taskItemSchema = z.object({\n  type: z.enum([\"text\", \"file\"]),\n  text: z.string(),\n  file: z\n    .object({\n      name: z.string(),\n      icon: z.string(),\n      color: z.string().optional(),\n    })\n    .optional(),\n});\n\nexport const taskSchema = z.object({\n  title: z.string(),\n  items: z.array(taskItemSchema),\n  status: z.enum([\"pending\", \"in_progress\", \"completed\"]),\n});\n\nexport const tasksSchema = z.object({\n  tasks: z.array(taskSchema),\n});\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { prompt } = await req.json();\n\n  const result = streamObject({\n    model: \"openai/gpt-4o\",\n    schema: tasksSchema,\n    prompt: `You are an AI assistant that generates realistic development task workflows. Generate a set of tasks that would occur during ${prompt}.\n\n    Each task should have:\n    - A descriptive title\n    - Multiple task items showing the progression\n    - Some items should be plain text, others should reference files\n    - Use realistic file names and appropriate file types\n    - Status should progress from pending to in_progress to completed\n\n    For file items, use these icon types: 'react', 'typescript', 'javascript', 'css', 'html', 'json', 'markdown'\n\n    Generate 3-4 tasks total, with 4-6 items each.`,\n  });\n\n  return result.toTextStreamResponse();\n}\n```\n\n## Features\n\n- Visual icons for pending, in-progress, completed, and error states\n- Expandable content for task descriptions and additional information\n- Built-in progress counter showing completed vs total tasks\n- Optional progressive reveal of tasks with customizable timing\n- Support for custom content within task items\n- Full type safety with proper TypeScript definitions\n- Keyboard navigation and screen reader support\n\n## Props\n\n### `<Task />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultOpen` | `boolean` | `true` | Whether the task is open by default. |\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the root Collapsible component. |\n\n### `<TaskTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | Required | The title of the task that will be displayed in the trigger. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<TaskContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent component. |\n\n### `<TaskItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<TaskItemFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n",".agents/skills/ai-elements/references/terminal.md":"# Terminal\n\nDisplay streaming console output with full ANSI color support.\n\nThe `Terminal` component displays console output with ANSI color support, streaming indicators, and auto-scroll functionality.\n\nSee `scripts/terminal.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add terminal\n```\n\n## Features\n\n- Full ANSI color support (256 colors, bold, italic, underline)\n- Streaming mode with cursor animation\n- Auto-scroll to latest output\n- Copy output to clipboard\n- Clear button support\n- Dark terminal theme\n\n## ANSI Support\n\nThe Terminal uses `ansi-to-react` to parse ANSI escape codes:\n\n```bash\n\\x1b[32m✓\\x1b[0m Success    # Green checkmark\n\\x1b[31m✗\\x1b[0m Error      # Red X\n\\x1b[33mwarn\\x1b[0m Warning   # Yellow text\n\\x1b[1mBold\\x1b[0m           # Bold text\n```\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/terminal-basic.tsx` for this example.\n\n### Streaming Mode\n\nSee `scripts/terminal-streaming.tsx` for this example.\n\n### With Clear Button\n\nSee `scripts/terminal-clear.tsx` for this example.\n\n## Props\n\n### `<Terminal />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `output` | `string` | - | Terminal output text (supports ANSI codes). |\n| `isStreaming` | `boolean` | `false` | Show streaming indicator. |\n| `autoScroll` | `boolean` | `true` | Auto-scroll to bottom on new output. |\n| `onClear` | `() => void` | - | Callback to clear output (enables clear button). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<TerminalCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback after successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback if copying fails. |\n| `timeout` | `number` | `2000` | Duration to show copied state (ms). |\n\n### `<TerminalHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TerminalTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TerminalStatus />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TerminalActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TerminalClearButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component. |\n\n### `<TerminalContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n",".agents/skills/ai-elements/references/test-results.md":"# Test Results\n\nDisplay test suite results with pass/fail/skip status and error details.\n\nThe `TestResults` component displays test suite results including summary statistics, progress, individual tests, and error details.\n\nSee `scripts/test-results.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add test-results\n```\n\n## Features\n\n- Summary statistics (passed/failed/skipped)\n- Progress bar visualization\n- Collapsible test suites\n- Individual test status and duration\n- Error messages with stack traces\n- Color-coded status indicators\n\n## Status Colors\n\n| Status    | Color           | Use Case         |\n| --------- | --------------- | ---------------- |\n| `passed`  | Green           | Test succeeded   |\n| `failed`  | Red             | Test failed      |\n| `skipped` | Yellow          | Test skipped     |\n| `running` | Blue (animated) | Test in progress |\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/test-results-basic.tsx` for this example.\n\n### With Test Suites\n\nSee `scripts/test-results-suites.tsx` for this example.\n\n### With Error Details\n\nSee `scripts/test-results-errors.tsx` for this example.\n\n## Props\n\n### `<TestResults />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `summary` | `unknown` | - | Test results summary. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<TestSuite />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | - | Suite name. |\n| `status` | `unknown` | - | Overall suite status. |\n| `defaultOpen` | `boolean` | - | Initially expanded. |\n\n### `<Test />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | - | Test name. |\n| `status` | `unknown` | - | Test status. |\n| `duration` | `number` | - | Test duration in ms. |\n\n### `<TestResultsHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestResultsSummary />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestResultsDuration />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<TestResultsProgress />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestResultsContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestSuiteName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<TestSuiteStats />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `passed` | `number` | `0` | Number of passed tests. |\n| `failed` | `number` | `0` | Number of failed tests. |\n| `skipped` | `number` | `0` | Number of skipped tests. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestSuiteContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent component. |\n\n### `<TestStatus />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<TestName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<TestDuration />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<TestError />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestErrorMessage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Any other props are spread to the p element. |\n\n### `<TestErrorStack />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLPreElement>` | - | Any other props are spread to the pre element. |\n",".agents/skills/ai-elements/references/tool.md":"# Tool\n\nA collapsible component for displaying tool invocation details in AI chatbot interfaces.\n\nThe `Tool` component displays a collapsible interface for showing/hiding tool details. It is designed to take the `ToolUIPart` type from the AI SDK and display it in a collapsible interface.\n\nSee `scripts/tool.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add tool\n```\n\n## Usage in AI SDK\n\nBuild a simple stateful weather app that renders the last message in a tool using [`useChat`](/docs/reference/ai-sdk-ui/use-chat).\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport { DefaultChatTransport, type ToolUIPart } from \"ai\";\nimport { Button } from \"@/components/ui/button\";\nimport { MessageResponse } from \"@/components/ai-elements/message\";\nimport {\n  Tool,\n  ToolContent,\n  ToolHeader,\n  ToolInput,\n  ToolOutput,\n} from \"@/components/ai-elements/tool\";\n\ntype WeatherToolInput = {\n  location: string;\n  units: \"celsius\" | \"fahrenheit\";\n};\n\ntype WeatherToolOutput = {\n  location: string;\n  temperature: string;\n  conditions: string;\n  humidity: string;\n  windSpeed: string;\n  lastUpdated: string;\n};\n\ntype WeatherToolUIPart = ToolUIPart<{\n  fetch_weather_data: {\n    input: WeatherToolInput;\n    output: WeatherToolOutput;\n  };\n}>;\n\nconst Example = () => {\n  const { messages, sendMessage, status } = useChat({\n    transport: new DefaultChatTransport({\n      api: \"/api/weather\",\n    }),\n  });\n\n  const handleWeatherClick = () => {\n    sendMessage({ text: \"Get weather data for San Francisco in fahrenheit\" });\n  };\n\n  const latestMessage = messages[messages.length - 1];\n  const weatherTool = latestMessage?.parts?.find(\n    (part) => part.type === \"tool-fetch_weather_data\"\n  ) as WeatherToolUIPart | undefined;\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"space-y-4\">\n          <Button onClick={handleWeatherClick} disabled={status !== \"ready\"}>\n            Get Weather for San Francisco\n          </Button>\n\n          {weatherTool && (\n            <Tool defaultOpen={true}>\n              <ToolHeader\n                type=\"tool-fetch_weather_data\"\n                state={weatherTool.state}\n              />\n              <ToolContent>\n                <ToolInput input={weatherTool.input} />\n                <ToolOutput\n                  output={\n                    <MessageResponse>\n                      {formatWeatherResult(weatherTool.output)}\n                    </MessageResponse>\n                  }\n                  errorText={weatherTool.errorText}\n                />\n              </ToolContent>\n            </Tool>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n};\n\nfunction formatWeatherResult(result: WeatherToolOutput): string {\n  return `**Weather for ${result.location}**\n\n**Temperature:** ${result.temperature}  \n**Conditions:** ${result.conditions}  \n**Humidity:** ${result.humidity}  \n**Wind Speed:** ${result.windSpeed}  \n\n*Last updated: ${result.lastUpdated}*`;\n}\n\nexport default Example;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/weather/route.tsx\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\nimport { z } from \"zod\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages: await convertToModelMessages(messages),\n    tools: {\n      fetch_weather_data: {\n        description: \"Fetch weather information for a specific location\",\n        parameters: z.object({\n          location: z\n            .string()\n            .describe(\"The city or location to get weather for\"),\n          units: z\n            .enum([\"celsius\", \"fahrenheit\"])\n            .default(\"celsius\")\n            .describe(\"Temperature units\"),\n        }),\n        inputSchema: z.object({\n          location: z.string(),\n          units: z.enum([\"celsius\", \"fahrenheit\"]).default(\"celsius\"),\n        }),\n        execute: async ({ location, units }) => {\n          await new Promise((resolve) => setTimeout(resolve, 1500));\n\n          const temp =\n            units === \"celsius\"\n              ? Math.floor(Math.random() * 35) + 5\n              : Math.floor(Math.random() * 63) + 41;\n\n          return {\n            location,\n            temperature: `${temp}°${units === \"celsius\" ? \"C\" : \"F\"}`,\n            conditions: \"Sunny\",\n            humidity: `12%`,\n            windSpeed: `35 ${units === \"celsius\" ? \"km/h\" : \"mph\"}`,\n            lastUpdated: new Date().toLocaleString(),\n          };\n        },\n      },\n    },\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Collapsible interface for showing/hiding tool details\n- Visual status indicators with icons and badges\n- Support for multiple tool execution states (pending, running, completed, error)\n- Formatted parameter display with JSON syntax highlighting\n- Result and error handling with appropriate styling\n- Composable structure for flexible layouts\n- Accessible keyboard navigation and screen reader support\n- Consistent styling that matches your design system\n- Auto-opens completed tools by default for better UX\n\n## Examples\n\n### Input Streaming (Pending)\n\nShows a tool in its initial state while parameters are being processed.\n\nSee `scripts/tool-input-streaming.tsx` for this example.\n\n### Input Available (Running)\n\nShows a tool that's actively executing with its parameters.\n\nSee `scripts/tool-input-available.tsx` for this example.\n\n### Output Available (Completed)\n\nShows a completed tool with successful results. Opens by default to show the results. In this instance, the output is a JSON object, so we can use the `CodeBlock` component to display it.\n\nSee `scripts/tool-output-available.tsx` for this example.\n\n### Output Error\n\nShows a tool that encountered an error during execution. Opens by default to display the error.\n\nSee `scripts/tool-output-error.tsx` for this example.\n\n## Props\n\n### `<Tool />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the root Collapsible component. |\n\n### `<ToolHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | - | Custom title to display instead of the derived tool name. |\n| `type` | `ToolUIPart[` | Required | The type/name of the tool. |\n| `state` | `ToolUIPart[` | Required | The current state of the tool (input-streaming, input-available, output-available, or output-error). |\n| `toolName` | `string` | - | Required when type is  |\n| `className` | `string` | - | Additional CSS classes to apply to the header. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger. |\n\n### `<ToolContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent. |\n\n### `<ToolInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `input` | `ToolUIPart[` | - | The input parameters passed to the tool, displayed as formatted JSON. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<ToolOutput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `output` | `React.ReactNode` | - | The output/result of the tool execution. |\n| `errorText` | `ToolUIPart[` | - | An error message if the tool execution failed. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n## Type Exports\n\n### `ToolPart`\n\nUnion type representing both static and dynamic tool UI parts.\n\n```tsx\ntype ToolPart = ToolUIPart | DynamicToolUIPart;\n```\n\n## Utilities\n\n### `getStatusBadge`\n\nReturns a Badge component with icon and label based on tool state.\n\n```tsx\nimport { getStatusBadge } from \"@/components/ai-elements/tool\";\n\n// Returns a Badge with appropriate icon and label\nconst badge = getStatusBadge(\"output-available\");\n```\n\nSupported states:\n\n- `input-streaming` - \"Pending\"\n- `input-available` - \"Running\"\n- `approval-requested` - \"Awaiting Approval\"\n- `approval-responded` - \"Responded\"\n- `output-available` - \"Completed\"\n- `output-error` - \"Error\"\n- `output-denied` - \"Denied\"\n",".agents/skills/ai-elements/references/toolbar.md":"# Toolbar\n\nA styled toolbar component for React Flow nodes with flexible positioning and custom actions.\n\nThe `Toolbar` component provides a positioned toolbar that attaches to nodes in React Flow canvases. It features modern card styling with backdrop blur and flexbox layout for action buttons and controls.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add toolbar\n```\n\n## Features\n\n- Attaches to any React Flow node\n- Bottom positioning by default\n- Rounded card design with border\n- Theme-aware background styling\n- Flexbox layout with gap spacing\n- Full TypeScript support\n- Compatible with all React Flow NodeToolbar features\n\n## Props\n\n### `<Toolbar />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the toolbar. |\n| `...props` | `ComponentProps<typeof NodeToolbar>` | - | Any other props from @xyflow/react NodeToolbar component (position, offset, isVisible, etc.). |\n",".agents/skills/ai-elements/references/transcription.md":"# Transcription\n\nA composable component for displaying interactive, synchronized transcripts from AI SDK transcribe() results with click-to-seek functionality.\n\nThe `Transcription` component provides a flexible render props interface for displaying audio transcripts with synchronized playback. It automatically highlights the current segment based on playback time and supports click-to-seek functionality for interactive navigation.\n\nSee `scripts/transcription.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add transcription\n```\n\n## Features\n\n- Render props pattern for maximum flexibility\n- Automatic segment highlighting based on current time\n- Click-to-seek functionality for interactive navigation\n- Controlled and uncontrolled component patterns\n- Automatic filtering of empty segments\n- Visual state indicators (active, past, future)\n- Built on Radix UI's `useControllableState` for flexible state management\n- Full TypeScript support with AI SDK transcription types\n\n## Props\n\n### `<Transcription />`\n\nRoot component that provides context and manages transcript state. Uses render props pattern for rendering segments.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `segments` | `TranscriptionSegment[]` | - | Array of transcription segments from AI SDK transcribe() function. |\n| `currentTime` | `number` | `0` | Current playback time in seconds (controlled). |\n| `onSeek` | `(time: number) => void` | - | Callback fired when a segment is clicked or when currentTime changes. |\n| `children` | `(segment: TranscriptionSegment, index: number) => ReactNode` | - | Render function that receives each segment and its index. |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the root div element. |\n\n### `<TranscriptionSegment />`\n\nIndividual segment button with automatic state styling and click-to-seek functionality.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `segment` | `TranscriptionSegment` | - | The transcription segment data. |\n| `index` | `number` | - | The segment index. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the button element. |\n\n## Behavior\n\n### Render Props Pattern\n\nThe component uses a render props pattern where the `children` prop is a function that receives each segment and its index. This provides maximum flexibility for custom rendering while still benefiting from automatic state management and context.\n\n### Segment Highlighting\n\nSegments are automatically styled based on their relationship to the current playback time:\n\n- **Active** (`isActive`): When `currentTime` is within the segment's time range. Styled with primary color.\n- **Past** (`isPast`): When `currentTime` is after the segment's end time. Styled with muted foreground.\n- **Future**: When `currentTime` is before the segment's start time. Styled with dimmed muted foreground.\n\n### Click-to-Seek\n\nWhen `onSeek` is provided, segments become interactive buttons. Clicking a segment calls `onSeek` with the segment's start time, allowing your audio/video player to seek to that position.\n\n### Empty Segment Filtering\n\nThe component automatically filters out segments with empty or whitespace-only text to avoid rendering unnecessary elements.\n\n### State Management\n\nUses Radix UI's `useControllableState` hook to support both controlled and uncontrolled patterns. When `currentTime` is provided, the component operates in controlled mode. Otherwise, it maintains its own internal state.\n\n## Data Format\n\nThe component expects segments from the AI SDK `transcribe()` function:\n\n```ts\ntype TranscriptionSegment = {\n  text: string;\n  startSecond: number;\n  endSecond: number;\n};\n```\n\n## Styling\n\nThe component uses data attributes for custom styling:\n\n- `data-slot=\"transcription\"`: Root container\n- `data-slot=\"transcription-segment\"`: Individual segment button\n- `data-active`: Present on the currently playing segment\n- `data-index`: The segment's index in the array\n\nDefault segment appearance:\n\n- Active segment: `text-primary` (primary brand color)\n- Past segments: `text-muted-foreground`\n- Future segments: `text-muted-foreground/60` (dimmed)\n- Interactive segments: `cursor-pointer hover:text-foreground`\n- Non-interactive segments: `cursor-default`\n\n## Accessibility\n\n- Uses semantic `<button>` elements for interactive segments\n- Full keyboard navigation support\n- Proper button semantics for screen readers\n- `data-active` attribute for assistive technology\n- Hover and focus states for keyboard users\n\n## Notes\n\n- Empty or whitespace-only segments are automatically filtered out\n- The component uses `flex-wrap` for responsive text flow\n- Segments maintain inline layout with `gap-1` spacing\n- `text-sm` and `leading-relaxed` provide comfortable reading\n- Click events on segments still fire the `onClick` handler if provided\n- The `onSeek` callback is called both when segments are clicked and when controlled `currentTime` changes\n",".agents/skills/ai-elements/references/voice-selector.md":"# Voice Selector\n\nA composable dialog component for selecting AI voices with metadata display and search functionality.\n\nThe `VoiceSelector` component provides a flexible and composable interface for selecting AI voices. Built on shadcn/ui's Dialog and Command components, it features a searchable voice list with support for metadata display (gender, accent, age), grouping, and customizable layouts. The component includes a context provider for accessing voice selection state from any nested component.\n\nSee `scripts/voice-selector.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add voice-selector\n```\n\n## Features\n\n- Fully composable architecture with granular control components\n- Built on shadcn/ui Dialog and Command components\n- React Context API for accessing state in nested components\n- Searchable voice list with real-time filtering\n- Support for voice metadata with icons and emojis (gender icons, accent flags, age)\n- Voice preview button with play/pause/loading states\n- Voice grouping with separators and bullet dividers\n- Keyboard navigation support\n- Controlled and uncontrolled component patterns\n- Full TypeScript support with proper types for all components\n\n## Props\n\n### `<VoiceSelector />`\n\nRoot Dialog component that provides context for all child components. Manages both voice selection and dialog open states.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The selected voice ID (controlled). |\n| `defaultValue` | `string` | - | The default selected voice ID (uncontrolled). |\n| `onValueChange` | `(value: string | undefined) => void` | - | Callback fired when the selected voice changes. |\n| `defaultOpen` | `boolean` | `false` | The default open state (uncontrolled). |\n| `open` | `boolean` | - | The open state (controlled). |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback fired when the open state changes. |\n| `modal` | `boolean` | `true` | Whether the dialog is modal (blocks interaction with the rest of the page). |\n| `...props` | `React.ComponentProps<typeof Dialog>` | - | Any other props are spread to the Dialog component. |\n\n### `<VoiceSelectorTrigger />`\n\nButton or element that opens the voice selector dialog.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior. |\n| `...props` | `React.ComponentProps<typeof DialogTrigger>` | - | Any other props are spread to the DialogTrigger component. |\n\n### `<VoiceSelectorContent />`\n\nContainer for the Command component and voice list, rendered inside the dialog.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `ReactNode` | - | The title for screen readers. Hidden visually but accessible to assistive technologies. |\n| `className` | `string` | - | Additional CSS classes to apply to the dialog content. |\n| `...props` | `React.ComponentProps<typeof DialogContent>` | - | Any other props are spread to the DialogContent component. |\n\n### `<VoiceSelectorDialog />`\n\nAlternative dialog implementation using CommandDialog for a full-screen command palette style.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandDialog>` | - | Any other props are spread to the CommandDialog component. |\n\n### `<VoiceSelectorInput />`\n\nSearch input for filtering voices.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `placeholder` | `string` | - | Placeholder text for the search input. |\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the CommandInput component. |\n\n### `<VoiceSelectorList />`\n\nScrollable container for voice items and groups.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandList>` | - | Any other props are spread to the CommandList component. |\n\n### `<VoiceSelectorEmpty />`\n\nMessage shown when no voices match the search query.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode` | - | The message to display. |\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the CommandEmpty component. |\n\n### `<VoiceSelectorGroup />`\n\nGroups related voices together with an optional heading.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `heading` | `string` | - | The heading text for the group. |\n| `...props` | `React.ComponentProps<typeof CommandGroup>` | - | Any other props are spread to the CommandGroup component. |\n\n### `<VoiceSelectorItem />`\n\nSelectable item representing a voice.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The unique identifier for this voice. Used for search filtering. |\n| `onSelect` | `(value: string) => void` | - | Callback fired when the voice is selected. |\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the CommandItem component. |\n\n### `<VoiceSelectorSeparator />`\n\nVisual separator between voice groups.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandSeparator>` | - | Any other props are spread to the CommandSeparator component. |\n\n### `<VoiceSelectorName />`\n\nDisplays the voice name with proper styling.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorGender />`\n\nDisplays the voice gender metadata with icons from Lucide. Supports multiple gender identities with corresponding icons.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `unknown` | - | The gender value that determines which icon to display. Supported values:  |\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `children` | `ReactNode` | - | Override the icon with custom content. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorAccent />`\n\nDisplays the voice accent metadata with emoji flags representing different countries/regions.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `unknown` | - | The accent value that determines which flag emoji to display. Supports 27 different accents including:  |\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `children` | `ReactNode` | - | Override the flag emoji with custom content. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorAge />`\n\nDisplays the voice age metadata with muted styling and tabular numbers for consistent alignment.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorDescription />`\n\nDisplays a description for the voice with muted styling.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorAttributes />`\n\nContainer for grouping voice attributes (gender, accent, age) together. Use with `VoiceSelectorBullet` for separation.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<VoiceSelectorBullet />`\n\nDisplays a bullet separator (•) between voice attributes. Hidden from screen readers via `aria-hidden`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorShortcut />`\n\nDisplays keyboard shortcuts for voice items.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandShortcut>` | - | Any other props are spread to the CommandShortcut component. |\n\n### `<VoiceSelectorPreview />`\n\nA button that allows users to preview/play a voice sample before selecting it. Shows play, pause, or loading icons based on state.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `playing` | `boolean` | - | Whether the voice is currently playing. Shows pause icon when true. |\n| `loading` | `boolean` | - | Whether the voice preview is loading. Shows loading spinner and disables the button. |\n| `onPlay` | `() => void` | - | Callback fired when the preview button is clicked. |\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the button element. |\n\n## Hooks\n\n### `useVoiceSelector()`\n\nA custom hook for accessing the voice selector context. This hook allows you to access and control the voice selection state from any component nested within `VoiceSelector`.\n\n```tsx\nimport { useVoiceSelector } from \"@repo/elements/voice-selector\";\n\nexport default function CustomVoiceDisplay() {\n  const { value, setValue, open, setOpen } = useVoiceSelector();\n\n  return (\n    <div>\n      <p>Selected voice: {value ?? \"None\"}</p>\n      <button onClick={() => setOpen(!open)}>Toggle Dialog</button>\n    </div>\n  );\n}\n```\n\n#### Return Value\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string | undefined` | - | The currently selected voice ID. |\n| `setValue` | `(value: string | undefined) => void` | - | Function to update the selected voice ID. |\n| `open` | `boolean` | - | Whether the dialog is currently open. |\n| `setOpen` | `(open: boolean) => void` | - | Function to control the dialog open state. |\n",".agents/skills/ai-elements/references/web-preview.md":"# Web Preview\n\nA composable component for previewing the result of a generated UI, with support for live examples and code display.\n\nThe `WebPreview` component provides a flexible way to showcase the result of a generated UI component, along with its source code. It is designed for documentation and demo purposes, allowing users to interact with live examples and view the underlying implementation.\n\nSee `scripts/web-preview.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add web-preview\n```\n\n## Usage with AI SDK\n\nBuild a simple v0 clone using the [v0 Platform API](https://v0.dev/docs/api/platform).\n\nInstall the `v0-sdk` package:\n\n```package-install\nnpm i v0-sdk\n```\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  WebPreview,\n  WebPreviewBody,\n  WebPreviewNavigation,\n  WebPreviewUrl,\n} from \"@/components/ai-elements/web-preview\";\nimport { useState } from \"react\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { Spinner } from \"@/components/ui/spinner\";\n\nconst WebPreviewDemo = () => {\n  const [previewUrl, setPreviewUrl] = useState(\"\");\n  const [prompt, setPrompt] = useState(\"\");\n  const [isGenerating, setIsGenerating] = useState(false);\n\n  const handleSubmit = async (message: PromptInputMessage) => {\n    if (!message.text.trim()) return;\n    setPrompt(\"\");\n\n    setIsGenerating(true);\n    try {\n      const response = await fetch(\"/api/v0\", {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\" },\n        body: JSON.stringify({ prompt: message.text }),\n      });\n\n      const data = await response.json();\n      setPreviewUrl(data.demo || \"/\");\n      console.log(\"Generation finished:\", data);\n    } catch (error) {\n      console.error(\"Generation failed:\", error);\n    } finally {\n      setIsGenerating(false);\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex-1 mb-4\">\n          {isGenerating ? (\n            <div className=\"flex flex-col items-center justify-center h-full\">\n              <Spinner />\n              <p className=\"mt-4 text-muted-foreground\">\n                Generating app, this may take a few seconds...\n              </p>\n            </div>\n          ) : previewUrl ? (\n            <WebPreview defaultUrl={previewUrl}>\n              <WebPreviewNavigation>\n                <WebPreviewUrl />\n              </WebPreviewNavigation>\n              <WebPreviewBody src={previewUrl} />\n            </WebPreview>\n          ) : (\n            <div className=\"flex items-center justify-center h-full text-muted-foreground\">\n              Your generated app will appear here\n            </div>\n          )}\n        </div>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={prompt}\n            placeholder=\"Describe the app you want to build...\"\n            onChange={(e) => setPrompt(e.currentTarget.value)}\n            className=\"pr-12 min-h-[60px]\"\n          />\n          <PromptInputSubmit\n            status={isGenerating ? \"streaming\" : \"ready\"}\n            disabled={!prompt.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default WebPreviewDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/v0/route.ts\"\nimport { v0 } from \"v0-sdk\";\n\nexport async function POST(req: Request) {\n  const { prompt }: { prompt: string } = await req.json();\n\n  const result = await v0.chats.create({\n    system: \"You are an expert coder\",\n    message: prompt,\n    modelConfiguration: {\n      modelId: \"v0-1.5-sm\",\n      imageGenerations: false,\n      thinking: false,\n    },\n  });\n\n  return Response.json({\n    demo: result.demo,\n    webUrl: result.webUrl,\n  });\n}\n```\n\n## Features\n\n- Live preview of UI components\n- Composable architecture with dedicated sub-components\n- Responsive design modes (Desktop, Tablet, Mobile)\n- Navigation controls with back/forward functionality\n- URL input and example selector\n- Full screen mode support\n- Console logging with timestamps\n- Context-based state management\n- Consistent styling with the design system\n- Easy integration into documentation pages\n\n## Props\n\n### `<WebPreview />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultUrl` | `string` | - | The initial URL to load in the preview. |\n| `onUrlChange` | `(url: string) => void` | - | Callback fired when the URL changes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<WebPreviewNavigation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the navigation container. |\n\n### `<WebPreviewNavigationButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string` | - | Tooltip text to display on hover. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<WebPreviewUrl />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Input>` | - | Any other props are spread to the underlying shadcn/ui Input component. |\n\n### `<WebPreviewBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `loading` | `React.ReactNode` | - | Optional loading indicator to display over the preview. |\n| `...props` | `React.IframeHTMLAttributes<HTMLIFrameElement>` | - | Any other props are spread to the underlying iframe. |\n\n### `<WebPreviewConsole />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `logs` | `Array<{ level: ` | - | Console log entries to display in the console panel. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n",".agents/skills/ai-sdk/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fai-sdk%2FSKILL.md -->",".agents/skills/better-accessibility/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2FSKILL.md -->",".agents/skills/better-accessibility/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fagents%2Fopenai.yaml -->",".agents/skills/better-accessibility/focus-and-keyboard.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Ffocus-and-keyboard.md -->",".agents/skills/better-accessibility/forms.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fforms.md -->",".agents/skills/better-accessibility/hit-areas.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fhit-areas.md -->",".agents/skills/better-accessibility/motion-and-zoom.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fmotion-and-zoom.md -->",".agents/skills/better-accessibility/screen-readers.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fscreen-readers.md -->",".agents/skills/better-accessibility/semantics-and-aria.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fsemantics-and-aria.md -->",".agents/skills/better-auth-best-practices/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-auth-best-practices%2FSKILL.md -->",".agents/skills/better-colors/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2FSKILL.md -->",".agents/skills/better-colors/accessibility-contrast.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Faccessibility-contrast.md -->",".agents/skills/better-colors/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fagents%2Fopenai.yaml -->",".agents/skills/better-colors/color-conversion.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fcolor-conversion.md -->",".agents/skills/better-colors/color-usage.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fcolor-usage.md -->",".agents/skills/better-colors/gamut-and-tailwind.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fgamut-and-tailwind.md -->",".agents/skills/better-colors/palette-generation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fpalette-generation.md -->",".agents/skills/better-interface/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-interface%2FSKILL.md -->",".agents/skills/better-interface/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-interface%2Fagents%2Fopenai.yaml -->",".agents/skills/better-layout/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-layout%2FSKILL.md -->",".agents/skills/better-layout/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-layout%2Fagents%2Fopenai.yaml -->",".agents/skills/better-layout/grouping-and-alignment.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-layout%2Fgrouping-and-alignment.md -->",".agents/skills/better-layout/spacing-and-adaptivity.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-layout%2Fspacing-and-adaptivity.md -->",".agents/skills/better-typography/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2FSKILL.md -->",".agents/skills/better-typography/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fagents%2Fopenai.yaml -->",".agents/skills/better-typography/choosing-fonts.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fchoosing-fonts.md -->",".agents/skills/better-typography/css-cheat-sheet.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fcss-cheat-sheet.md -->",".agents/skills/better-typography/details-and-accessibility.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fdetails-and-accessibility.md -->",".agents/skills/better-typography/spacing-and-sizing.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fspacing-and-sizing.md -->",".agents/skills/better-typography/variable-fonts-and-opentype.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fvariable-fonts-and-opentype.md -->",".agents/skills/better-typography/wrapping-and-punctuation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fwrapping-and-punctuation.md -->",".agents/skills/better-ui/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2FSKILL.md -->",".agents/skills/better-ui/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Fagents%2Fopenai.yaml -->",".agents/skills/better-ui/animations.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Fanimations.md -->",".agents/skills/better-ui/icons.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Ficons.md -->",".agents/skills/better-ui/performance.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Fperformance.md -->",".agents/skills/better-ui/surfaces.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Fsurfaces.md -->",".agents/skills/better-writing/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-writing%2FSKILL.md -->",".agents/skills/better-writing/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-writing%2Fagents%2Fopenai.yaml -->",".agents/skills/code-refactor-review/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fcode-refactor-review%2FSKILL.md -->",".agents/skills/create-draft-pr/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fcreate-draft-pr%2FSKILL.md -->",".agents/skills/diffs/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2FSKILL.md -->",".agents/skills/diffs/references/api-editor.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Fapi-editor.md -->",".agents/skills/diffs/references/api-react.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Fapi-react.md -->",".agents/skills/diffs/references/recipe-code-view.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Frecipe-code-view.md -->",".agents/skills/diffs/references/recipe-edit-react.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Frecipe-edit-react.md -->",".agents/skills/diffs/references/recipe-react.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Frecipe-react.md -->",".agents/skills/eve/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Feve%2FSKILL.md -->",".agents/skills/ga-pr/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fga-pr%2FSKILL.md -->",".agents/skills/ga/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fga%2FSKILL.md -->",".agents/skills/gh-stack/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fgh-stack%2FSKILL.md -->",".agents/skills/gh-stack/references/commands.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fgh-stack%2Freferences%2Fcommands.md -->",".agents/skills/gh-stack/references/stack-design.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fgh-stack%2Freferences%2Fstack-design.md -->",".agents/skills/gh-stack/references/troubleshooting.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fgh-stack%2Freferences%2Ftroubleshooting.md -->",".agents/skills/install-anti-slop/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Finstall-anti-slop%2FSKILL.md -->",".agents/skills/nestjs-best-practices/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2FSKILL.md -->",".agents/skills/nestjs-best-practices/rules/_sections.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2F_sections.md -->",".agents/skills/nestjs-best-practices/rules/_template.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2F_template.md -->",".agents/skills/nestjs-best-practices/rules/api-use-dto-serialization.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fapi-use-dto-serialization.md -->",".agents/skills/nestjs-best-practices/rules/api-use-interceptors.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fapi-use-interceptors.md -->",".agents/skills/nestjs-best-practices/rules/api-use-pipes.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fapi-use-pipes.md -->",".agents/skills/nestjs-best-practices/rules/api-versioning.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fapi-versioning.md -->",".agents/skills/nestjs-best-practices/rules/arch-avoid-circular-deps.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-avoid-circular-deps.md -->",".agents/skills/nestjs-best-practices/rules/arch-feature-modules.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-feature-modules.md -->",".agents/skills/nestjs-best-practices/rules/arch-module-sharing.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-module-sharing.md -->",".agents/skills/nestjs-best-practices/rules/arch-single-responsibility.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-single-responsibility.md -->",".agents/skills/nestjs-best-practices/rules/arch-use-events.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-use-events.md -->",".agents/skills/nestjs-best-practices/rules/arch-use-repository-pattern.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-use-repository-pattern.md -->",".agents/skills/nestjs-best-practices/rules/db-avoid-n-plus-one.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdb-avoid-n-plus-one.md -->",".agents/skills/nestjs-best-practices/rules/db-use-migrations.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdb-use-migrations.md -->",".agents/skills/nestjs-best-practices/rules/db-use-transactions.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdb-use-transactions.md -->",".agents/skills/nestjs-best-practices/rules/devops-graceful-shutdown.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdevops-graceful-shutdown.md -->",".agents/skills/nestjs-best-practices/rules/devops-use-config-module.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdevops-use-config-module.md -->",".agents/skills/nestjs-best-practices/rules/devops-use-logging.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdevops-use-logging.md -->",".agents/skills/nestjs-best-practices/rules/di-avoid-service-locator.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-avoid-service-locator.md -->",".agents/skills/nestjs-best-practices/rules/di-interface-segregation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-interface-segregation.md -->",".agents/skills/nestjs-best-practices/rules/di-liskov-substitution.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-liskov-substitution.md -->",".agents/skills/nestjs-best-practices/rules/di-prefer-constructor-injection.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-prefer-constructor-injection.md -->",".agents/skills/nestjs-best-practices/rules/di-scope-awareness.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-scope-awareness.md -->",".agents/skills/nestjs-best-practices/rules/di-use-interfaces-tokens.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-use-interfaces-tokens.md -->",".agents/skills/nestjs-best-practices/rules/error-handle-async-errors.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ferror-handle-async-errors.md -->",".agents/skills/nestjs-best-practices/rules/error-throw-http-exceptions.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ferror-throw-http-exceptions.md -->",".agents/skills/nestjs-best-practices/rules/error-use-exception-filters.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ferror-use-exception-filters.md -->",".agents/skills/nestjs-best-practices/rules/micro-use-health-checks.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fmicro-use-health-checks.md -->",".agents/skills/nestjs-best-practices/rules/micro-use-patterns.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fmicro-use-patterns.md -->",".agents/skills/nestjs-best-practices/rules/micro-use-queues.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fmicro-use-queues.md -->",".agents/skills/nestjs-best-practices/rules/perf-async-hooks.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fperf-async-hooks.md -->",".agents/skills/nestjs-best-practices/rules/perf-lazy-loading.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fperf-lazy-loading.md -->",".agents/skills/nestjs-best-practices/rules/perf-optimize-database.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fperf-optimize-database.md -->",".agents/skills/nestjs-best-practices/rules/perf-use-caching.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fperf-use-caching.md -->",".agents/skills/nestjs-best-practices/rules/security-auth-jwt.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-auth-jwt.md -->",".agents/skills/nestjs-best-practices/rules/security-rate-limiting.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-rate-limiting.md -->",".agents/skills/nestjs-best-practices/rules/security-sanitize-output.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-sanitize-output.md -->",".agents/skills/nestjs-best-practices/rules/security-use-guards.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-use-guards.md -->",".agents/skills/nestjs-best-practices/rules/security-validate-all-input.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-validate-all-input.md -->",".agents/skills/nestjs-best-practices/rules/test-e2e-supertest.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ftest-e2e-supertest.md -->",".agents/skills/nestjs-best-practices/rules/test-mock-external-services.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ftest-mock-external-services.md -->",".agents/skills/nestjs-best-practices/rules/test-use-testing-module.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ftest-use-testing-module.md -->",".agents/skills/nestjs-trpc/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2FSKILL.md -->",".agents/skills/nestjs-trpc/references/api-reference.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Fapi-reference.md -->",".agents/skills/nestjs-trpc/references/codegen-and-client.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Fcodegen-and-client.md -->",".agents/skills/nestjs-trpc/references/middlewares-and-context.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Fmiddlewares-and-context.md -->",".agents/skills/nestjs-trpc/references/module-config.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Fmodule-config.md -->",".agents/skills/nestjs-trpc/references/routers.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Frouters.md -->",".agents/skills/no-use-effect/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fno-use-effect%2FSKILL.md -->",".agents/skills/nuqs/AGENTS.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2FAGENTS.md -->",".agents/skills/nuqs/README.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2FREADME.md -->",".agents/skills/nuqs/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2FSKILL.md -->",".agents/skills/nuqs/assets/templates/_template.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Fassets%2Ftemplates%2F_template.md -->",".agents/skills/nuqs/references/_sections.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2F_sections.md -->",".agents/skills/nuqs/references/advanced-custom-parsers.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-custom-parsers.md -->",".agents/skills/nuqs/references/advanced-eq-function.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-eq-function.md -->",".agents/skills/nuqs/references/advanced-framework-adapters.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-framework-adapters.md -->",".agents/skills/nuqs/references/advanced-process-url-search-params.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-process-url-search-params.md -->",".agents/skills/nuqs/references/advanced-url-keys.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-url-keys.md -->",".agents/skills/nuqs/references/debug-enable-logging.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fdebug-enable-logging.md -->",".agents/skills/nuqs/references/debug-testing.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fdebug-testing.md -->",".agents/skills/nuqs/references/history-push-navigation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fhistory-push-navigation.md -->",".agents/skills/nuqs/references/history-scroll-behavior.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fhistory-scroll-behavior.md -->",".agents/skills/nuqs/references/parser-array-format.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-array-format.md -->",".agents/skills/nuqs/references/parser-date-format.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-date-format.md -->",".agents/skills/nuqs/references/parser-enum-validation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-enum-validation.md -->",".agents/skills/nuqs/references/parser-index-offset.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-index-offset.md -->",".agents/skills/nuqs/references/parser-json-validation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-json-validation.md -->",".agents/skills/nuqs/references/parser-use-typed-parsers.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-use-typed-parsers.md -->",".agents/skills/nuqs/references/parser-with-default.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-with-default.md -->",".agents/skills/nuqs/references/perf-avoid-rerender.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-avoid-rerender.md -->",".agents/skills/nuqs/references/perf-clear-on-default.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-clear-on-default.md -->",".agents/skills/nuqs/references/perf-debounce-search.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-debounce-search.md -->",".agents/skills/nuqs/references/perf-key-isolation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-key-isolation.md -->",".agents/skills/nuqs/references/perf-serialize-utility.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-serialize-utility.md -->",".agents/skills/nuqs/references/perf-throttle-updates.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-throttle-updates.md -->",".agents/skills/nuqs/references/server-next15-async.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-next15-async.md -->",".agents/skills/nuqs/references/server-parse-before-get.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-parse-before-get.md -->",".agents/skills/nuqs/references/server-search-params-cache.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-search-params-cache.md -->",".agents/skills/nuqs/references/server-shallow-false.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-shallow-false.md -->",".agents/skills/nuqs/references/server-use-transition.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-use-transition.md -->",".agents/skills/nuqs/references/setup-default-options.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-default-options.md -->",".agents/skills/nuqs/references/setup-import-server.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-import-server.md -->",".agents/skills/nuqs/references/setup-nextjs-version.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-nextjs-version.md -->",".agents/skills/nuqs/references/setup-nuqs-adapter.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-nuqs-adapter.md -->",".agents/skills/nuqs/references/setup-shared-parsers.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-shared-parsers.md -->",".agents/skills/nuqs/references/setup-use-client.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-use-client.md -->",".agents/skills/nuqs/references/state-avoid-derived.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-avoid-derived.md -->",".agents/skills/nuqs/references/state-clear-with-null.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-clear-with-null.md -->",".agents/skills/nuqs/references/state-options-inheritance.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-options-inheritance.md -->",".agents/skills/nuqs/references/state-setter-return.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-setter-return.md -->",".agents/skills/nuqs/references/state-standard-schema.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-standard-schema.md -->",".agents/skills/nuqs/references/state-use-query-states.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-use-query-states.md -->",".agents/skills/pit-of-success/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fpit-of-success%2FSKILL.md -->",".agents/skills/posthog-instrumentation/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fposthog-instrumentation%2FSKILL.md -->",".agents/skills/prepare-branch-context/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprepare-branch-context%2FSKILL.md -->",".agents/skills/prisma-database-setup/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2FSKILL.md -->",".agents/skills/prisma-database-setup/references/cockroachdb.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fcockroachdb.md -->",".agents/skills/prisma-database-setup/references/mongodb.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fmongodb.md -->",".agents/skills/prisma-database-setup/references/mysql.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fmysql.md -->",".agents/skills/prisma-database-setup/references/postgresql.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fpostgresql.md -->",".agents/skills/prisma-database-setup/references/prisma-client-setup.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fprisma-client-setup.md -->",".agents/skills/prisma-database-setup/references/prisma-postgres.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fprisma-postgres.md -->",".agents/skills/prisma-database-setup/references/sqlite.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fsqlite.md -->",".agents/skills/prisma-database-setup/references/sqlserver.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fsqlserver.md -->",".agents/skills/seo-audit/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fseo-audit%2FSKILL.md -->",".agents/skills/seo-audit/evals/evals.json":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fseo-audit%2Fevals%2Fevals.json -->",".agents/skills/seo-audit/references/ai-writing-detection.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fseo-audit%2Freferences%2Fai-writing-detection.md -->",".agents/skills/seo-audit/references/international-seo.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fseo-audit%2Freferences%2Finternational-seo.md -->",".agents/skills/shadcn/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2FSKILL.md -->",".agents/skills/shadcn/cli.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fcli.md -->",".agents/skills/shadcn/customization.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fcustomization.md -->",".agents/skills/shadcn/evals/evals.json":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fevals%2Fevals.json -->",".agents/skills/shadcn/mcp.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fmcp.md -->",".agents/skills/shadcn/registry.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fregistry.md -->",".agents/skills/shadcn/rules/base-vs-radix.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fbase-vs-radix.md -->",".agents/skills/shadcn/rules/chat.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fchat.md -->",".agents/skills/shadcn/rules/composition.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fcomposition.md -->",".agents/skills/shadcn/rules/forms.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fforms.md -->",".agents/skills/shadcn/rules/icons.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Ficons.md -->",".agents/skills/shadcn/rules/styling.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fstyling.md -->",".agents/skills/skill-creator/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2FSKILL.md -->",".agents/skills/skill-creator/agents/analyzer.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2Fagents%2Fanalyzer.md -->",".agents/skills/skill-creator/agents/comparator.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2Fagents%2Fcomparator.md -->",".agents/skills/skill-creator/agents/grader.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2Fagents%2Fgrader.md -->",".agents/skills/skill-creator/references/schemas.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2Freferences%2Fschemas.md -->",".agents/skills/turborepo/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2FSKILL.md -->",".agents/skills/turborepo/command/turborepo.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Fcommand%2Fturborepo.md -->",".agents/skills/turborepo/references/best-practices/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fbest-practices%2FRULE.md -->",".agents/skills/turborepo/references/best-practices/dependencies.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fbest-practices%2Fdependencies.md -->",".agents/skills/turborepo/references/best-practices/packages.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fbest-practices%2Fpackages.md -->",".agents/skills/turborepo/references/best-practices/structure.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fbest-practices%2Fstructure.md -->",".agents/skills/turborepo/references/boundaries/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fboundaries%2FRULE.md -->",".agents/skills/turborepo/references/caching/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcaching%2FRULE.md -->",".agents/skills/turborepo/references/caching/gotchas.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcaching%2Fgotchas.md -->",".agents/skills/turborepo/references/caching/remote-cache.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcaching%2Fremote-cache.md -->",".agents/skills/turborepo/references/ci/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fci%2FRULE.md -->",".agents/skills/turborepo/references/ci/github-actions.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fci%2Fgithub-actions.md -->",".agents/skills/turborepo/references/ci/patterns.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fci%2Fpatterns.md -->",".agents/skills/turborepo/references/ci/vercel.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fci%2Fvercel.md -->",".agents/skills/turborepo/references/cli/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcli%2FRULE.md -->",".agents/skills/turborepo/references/cli/commands.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcli%2Fcommands.md -->",".agents/skills/turborepo/references/configuration/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fconfiguration%2FRULE.md -->",".agents/skills/turborepo/references/configuration/global-options.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fconfiguration%2Fglobal-options.md -->",".agents/skills/turborepo/references/configuration/gotchas.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fconfiguration%2Fgotchas.md -->",".agents/skills/turborepo/references/configuration/tasks.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fconfiguration%2Ftasks.md -->",".agents/skills/turborepo/references/environment/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fenvironment%2FRULE.md -->",".agents/skills/turborepo/references/environment/gotchas.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fenvironment%2Fgotchas.md -->",".agents/skills/turborepo/references/environment/modes.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fenvironment%2Fmodes.md -->",".agents/skills/turborepo/references/filtering/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Ffiltering%2FRULE.md -->",".agents/skills/turborepo/references/filtering/patterns.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Ffiltering%2Fpatterns.md -->",".agents/skills/turborepo/references/watch/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fwatch%2FRULE.md -->",".agents/skills/typescript-advanced-types/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Ftypescript-advanced-types%2FSKILL.md -->",".agents/skills/typescript-advanced-types/references/details.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Ftypescript-advanced-types%2Freferences%2Fdetails.md -->",".agents/skills/ux-flow-plan/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fux-flow-plan%2FSKILL.md -->",".agents/skills/vercel-composition-patterns/AGENTS.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2FAGENTS.md -->",".agents/skills/vercel-composition-patterns/README.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2FREADME.md -->",".agents/skills/vercel-composition-patterns/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2FSKILL.md -->",".agents/skills/vercel-composition-patterns/metadata.json":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Fmetadata.json -->",".agents/skills/vercel-composition-patterns/rules/_sections.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2F_sections.md -->",".agents/skills/vercel-composition-patterns/rules/_template.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2F_template.md -->",".agents/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Farchitecture-avoid-boolean-props.md -->",".agents/skills/vercel-composition-patterns/rules/architecture-compound-components.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Farchitecture-compound-components.md -->",".agents/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fpatterns-children-over-render-props.md -->",".agents/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fpatterns-explicit-variants.md -->",".agents/skills/vercel-composition-patterns/rules/react19-no-forwardref.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Freact19-no-forwardref.md -->",".agents/skills/vercel-composition-patterns/rules/state-context-interface.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fstate-context-interface.md -->",".agents/skills/vercel-composition-patterns/rules/state-decouple-implementation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fstate-decouple-implementation.md -->",".agents/skills/vercel-composition-patterns/rules/state-lift-state.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fstate-lift-state.md -->",".agents/skills/vercel-react-best-practices/AGENTS.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2FAGENTS.md -->",".agents/skills/vercel-react-best-practices/README.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2FREADME.md -->",".agents/skills/vercel-react-best-practices/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2FSKILL.md -->",".agents/skills/vercel-react-best-practices/metadata.json":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Fmetadata.json -->",".agents/skills/vercel-react-best-practices/rules/_sections.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2F_sections.md -->",".agents/skills/vercel-react-best-practices/rules/_template.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2F_template.md -->",".agents/skills/vercel-react-best-practices/rules/advanced-effect-event-deps.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fadvanced-effect-event-deps.md -->",".agents/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fadvanced-event-handler-refs.md -->",".agents/skills/vercel-react-best-practices/rules/advanced-init-once.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fadvanced-init-once.md -->",".agents/skills/vercel-react-best-practices/rules/advanced-use-latest.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fadvanced-use-latest.md -->",".agents/skills/vercel-react-best-practices/rules/async-api-routes.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-api-routes.md -->",".agents/skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-cheap-condition-before-await.md -->",".agents/skills/vercel-react-best-practices/rules/async-defer-await.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-defer-await.md -->",".agents/skills/vercel-react-best-practices/rules/async-dependencies.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-dependencies.md -->",".agents/skills/vercel-react-best-practices/rules/async-parallel.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-parallel.md -->",".agents/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-suspense-boundaries.md -->",".agents/skills/vercel-react-best-practices/rules/bundle-analyzable-paths.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-analyzable-paths.md -->",".agents/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-barrel-imports.md -->",".agents/skills/vercel-react-best-practices/rules/bundle-conditional.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-conditional.md -->",".agents/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-defer-third-party.md -->",".agents/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-dynamic-imports.md -->",".agents/skills/vercel-react-best-practices/rules/bundle-preload.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-preload.md -->",".agents/skills/vercel-react-best-practices/rules/client-event-listeners.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fclient-event-listeners.md -->",".agents/skills/vercel-react-best-practices/rules/client-localstorage-schema.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fclient-localstorage-schema.md -->",".agents/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fclient-passive-event-listeners.md -->",".agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fclient-swr-dedup.md -->",".agents/skills/vercel-react-best-practices/rules/js-batch-dom-css.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-batch-dom-css.md -->",".agents/skills/vercel-react-best-practices/rules/js-cache-function-results.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-cache-function-results.md -->",".agents/skills/vercel-react-best-practices/rules/js-cache-property-access.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-cache-property-access.md -->",".agents/skills/vercel-react-best-practices/rules/js-cache-storage.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-cache-storage.md -->",".agents/skills/vercel-react-best-practices/rules/js-combine-iterations.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-combine-iterations.md -->",".agents/skills/vercel-react-best-practices/rules/js-early-exit.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-early-exit.md -->",".agents/skills/vercel-react-best-practices/rules/js-flatmap-filter.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-flatmap-filter.md -->",".agents/skills/vercel-react-best-practices/rules/js-hoist-regexp.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-hoist-regexp.md -->",".agents/skills/vercel-react-best-practices/rules/js-index-maps.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-index-maps.md -->",".agents/skills/vercel-react-best-practices/rules/js-length-check-first.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-length-check-first.md -->",".agents/skills/vercel-react-best-practices/rules/js-min-max-loop.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-min-max-loop.md -->",".agents/skills/vercel-react-best-practices/rules/js-request-idle-callback.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-request-idle-callback.md -->",".agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-set-map-lookups.md -->",".agents/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-tosorted-immutable.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-activity.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-activity.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-animate-svg-wrapper.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-conditional-render.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-conditional-render.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-content-visibility.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-content-visibility.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-hoist-jsx.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-hydration-no-flicker.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-hydration-suppress-warning.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-resource-hints.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-resource-hints.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-script-defer-async.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-svg-precision.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-svg-precision.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-usetransition-loading.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-defer-reads.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-defer-reads.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-dependencies.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-dependencies.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-derived-state-no-effect.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-derived-state.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-derived-state.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-functional-setstate.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-lazy-state-init.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-memo-with-default-value.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-memo.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-memo.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-move-effect-to-event.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-no-inline-components.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-simple-expression-in-memo.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-split-combined-hooks.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-transitions.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-transitions.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-use-deferred-value.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-use-ref-transient-values.md -->",".agents/skills/vercel-react-best-practices/rules/server-after-nonblocking.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-after-nonblocking.md -->",".agents/skills/vercel-react-best-practices/rules/server-auth-actions.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-auth-actions.md -->",".agents/skills/vercel-react-best-practices/rules/server-cache-lru.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-cache-lru.md -->",".agents/skills/vercel-react-best-practices/rules/server-cache-react.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-cache-react.md -->",".agents/skills/vercel-react-best-practices/rules/server-dedup-props.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-dedup-props.md -->",".agents/skills/vercel-react-best-practices/rules/server-hoist-static-io.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-hoist-static-io.md -->",".agents/skills/vercel-react-best-practices/rules/server-no-shared-module-state.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-no-shared-module-state.md -->",".agents/skills/vercel-react-best-practices/rules/server-parallel-fetching.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-parallel-fetching.md -->",".agents/skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-parallel-nested-fetching.md -->",".agents/skills/vercel-react-best-practices/rules/server-serialization.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-serialization.md -->",".agents/skills/web-design-guidelines/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fweb-design-guidelines%2FSKILL.md -->",".agents/skills/zero-tech-debt/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fzero-tech-debt%2FSKILL.md -->","AGENTS.md":"# Strict rules — review before starting any work\n\n**Read the doc for the area you are touching before you touch it.** The table\nbelow is the whole index. These are plain paths, not imports: they are not in your\ncontext until you read them, and the rules in them are not optional.\n\n| Working on | Read first |\n| --- | --- |\n| Anything in `apps/api` — tRPC, auth, logging, sync, deletes, caching | `docs/api.md` |\n| `apps/agent` — the eve research agent, tools, tasks, dispatch | `docs/agent.md` |\n| `.env`, configuration, which variables exist and why | `docs/environment.md` |\n| UI in `apps/app` or `packages/ui` | `docs/design.md` (below) |\n| Deal amounts, totals, charts, exchange rates | `docs/currency.md` |\n| The record sheet's Agent tab | `docs/agent-panel.md` |\n| `/settings/connections`, integrations, the intake endpoint | `docs/connections.md` |\n| The tracking script, the collector, form submissions | `docs/tracking.md` |\n| Running it locally, Google Cloud, DB commands, secrets | `docs/setup.md` |\n| Anything that sends a telemetry event, or a new property on one | `docs/telemetry.md` |\n| `.github/workflows`, versions, changelog, how a change reaches `release` | `CONTRIBUTING.md` |\n\nAlso check `.agents/skills/` for a relevant skill before starting — better-auth,\nprisma, nestjs-trpc, eve, shadcn, nuqs and others have one. Tell the user which\nrules and skills you read.\n\n## Always true\n\n- **Never add code comments.** Not to new code, not to code you edit.\n- **No coauthoring commits.** No `Co-Authored-By` trailer, ever.\n- **Intelligence lives in `apps/agent`, never in the API.** No vendor client, no\n  enrichment, no scoring, no identity matching in Nest — it writes an `AgentTask`\n  row and lets the agent decide. See `docs/api.md`.\n- **One `.env`, at the repo root.** `.env.example` is its documentation: add every\n  new variable there with a note on what it does, and declare it in\n  `apps/api/src/config/env.validation.ts` if the API reads it. Never add a\n  per-package `.env`.\n- **Anything a self-hoster might not have is optional and must never throw.** A\n  missing key removes a capability. `apps/agent/agent/lib/capabilities.ts` is the\n  pattern.\n- **`/packages/ui` is the single source of truth for UI.** Shared shadcn\n  components only; a new variant is implemented there, not overridden at the call\n  site.\n- **eve's own docs ship in `apps/agent/node_modules/eve/docs`** and match the\n  installed version. Read the relevant guide before writing eve code rather than\n  working from memory — guessing typechecks, builds, and then behaves differently.\n\n## Report every issue. Use ASD-STE100\n\nDo not bury a known problem inside a paragraph. A problem inside prose is a\nproblem nobody reads. Report **every** issue, including ones you caused, in a\nlist at the end of your reply.\n\nWrite every message, every report and every issue in **ASD-STE100**\n(Simplified Technical English):\n\n- One idea per sentence. Maximum 20 words.\n- Active voice. Present tense. No conditionals.\n- One word for one meaning. Do not use synonyms for variety.\n- Say the effect, not only the cause.\n- No hedging: never \"may\", \"might\", \"possibly\", \"somewhat\".\n\nUse exactly this shape:\n\n```\n## Issues\n\n1. BROKEN — Slack is not connected. Agents that post to Slack fail.\n   Fix: connect Slack in Settings → Connections.\n2. RISK — A run longer than 5 minutes is cancelled. Work is lost.\n   Fix: not done. Needs a separate execution lease.\n3. NOT DONE — The manual run button shows on event-only agents.\n```\n\nRules for the list:\n\n- One line for the problem. One line for the fix.\n- Start each with **BROKEN**, **RISK**, **NOT DONE**, or **UNKNOWN**.\n- **BROKEN** is failing now. **RISK** fails later. **NOT DONE** is unbuilt.\n  **UNKNOWN** is not investigated.\n- If you introduced it, write **I caused this** on the fix line.\n- Zero issues? Write `## Issues` then `None.`\n\n**Don't** — bury it in prose:\n\n> The fix works well. One honest limit: abandoning a sweep unblocks the queue but\n> doesn't cancel the underlying hung promise, so it leaks until restart.\n\n**Do** — put it in the list:\n\n> 1. RISK — An abandoned sweep leaks its promise. Memory grows until restart.\n>    Fix: not done. Needs cancellation in `receive()`. I caused this.\n\n## A server page computes. A client component renders.\n\nA client component must never import a server package. `@crm/auth` and `@crm/db`\nare server packages: their barrels reach Prisma, which reaches `pg`, which\nreaches `dns`. The bundler follows that chain into the browser and the build\nfails with `Module not found: Can't resolve 'dns'`.\n\nThe import trace is the whole error. Read it from the bottom: the last line is\nthe page, the line above is the client component that leaked, and the top is the\nNode module that cannot exist in a browser.\n\n**Don't** — a client component reaching for a server package:\n\n```tsx\n\"use client\";\nimport {\n  describeSlackScopes,\n  SLACK_SCOPE_GROUPS,\n} from \"@crm/auth/slack-scopes\";\n\nexport function SlackScopeGroups({ scopes }: { scopes: string[] }) {\n  const groups = SLACK_SCOPE_GROUPS.map(...)\n}\n```\n\n**Do** — the page does the work and hands over plain data:\n\n```tsx\n// page.tsx — server\nimport {\n  describeSlackScopes,\n  SLACK_SCOPE_GROUPS,\n} from \"@crm/auth/slack-scopes\";\n\nconst groups = groupScopes(status.scopes);\nreturn <SlackScopeGroups groups={groups} />;\n```\n\n```tsx\n// slack-scope-groups.tsx — client\n\"use client\";\n\nexport type ScopeGroup = { id: string; label: string; scopes: ScopeLine[] };\n\nexport function SlackScopeGroups({ groups }: { groups: ScopeGroup[] }) { … }\n```\n\nRules that follow:\n\n- The client component owns its own prop types. It does not re-export a server\n  type to get them.\n- Anything interactive — an accordion, a dialog, a search field — is a client\n  component that receives finished data. It never derives it.\n- A `\"use client\"` file may import from `@crm/ui`, the tRPC client, and React.\n  Anything else needs checking.\n- The server page is where `await` and secrets live. The client file has neither.\n\n## Constants belong in one file per area, not beside their first use\n\nA number that someone will want to tune goes in a named config module for its\narea. It does not go at the top of whichever file happened to need it first.\nSomebody changing a timeout must not have to know which file to open.\n\n**Don't** — one constant per file, found only by grep:\n\n```ts\n// dispatch.ts\nconst DRAIN_TIMEOUT_MS = 4 * 60_000;\n// crm.ts\nconst STALE_QUEUE_MS = 5 * 60_000;\n// tasks.ts\nconst LEASE_MS = 10 * 60_000;\n```\n\n**Do** — one object, grouped by concern, imported where used:\n\n```ts\n// dispatch-config.ts\nexport const DISPATCH = {\n  sweep: { timeoutMs: 4 * MINUTE_MS, staleQueueMs: 5 * MINUTE_MS },\n  task: { leaseMs: 10 * MINUTE_MS },\n} as const;\n```\n\n`apps/agent/agent/lib/dispatch-config.ts` is the pattern. Rules:\n\n- Group by concern, not by file that uses it.\n- Derive units from one base (`MINUTE_MS`). Never write `4 * 60_000` twice.\n- `as const`, so the values are literal types.\n- No magic numbers inline. If it is tunable, it belongs in the config.\n- One convention across the codebase. Do not invent a local style for one file.\n\n## Parse at the boundary, never pass `Record<string, unknown>` around\n\nUntyped data — a Prisma `Json` column, a webhook body, an API response — is\nparsed into a **domain type at the moment it enters the process**, with Zod, in a\nmodule that owns that shape. Every consumer downstream receives the parsed type\nand nothing else. `Record<string, unknown>`, `unknown` casts and one-off\n`recordOf()` helpers are how a shape becomes unknowable and a typo becomes a\nruntime bug two files away.\n\n**Don't** — reach into raw JSON, re-deriving the shape at each call site:\n\n```ts\nfunction manifestActions(value: unknown) {\n  const actions = recordOf(value).actions;\n  return Array.isArray(actions) ? actions.map(recordOf) : [];\n}\n\nconst slack = manifestActions(version.manifest).find(\n  (action) => action.type === \"slack.message.post\",\n);\nconst id = (slack?.destination as Record<string, unknown>)?.id;\n```\n\nNothing here is checked. `destination` may be missing, `id` may be a number, and\nthe compiler cannot help. Rename a field and every one of these silently returns\n`undefined`.\n\n**Do** — one schema, parsed once, at the read:\n\n```ts\nexport const agentManifestAction = z.discriminatedUnion(\"type\", [\n  z.object({\n    type: z.literal(AGENT_ACTION_TYPES.SLACK_MESSAGE_POST),\n    provider: z.literal(\"slack\"),\n    summary: z.string(),\n    destination: z.object({\n      kind: z.enum([\"channel\", \"user\"]),\n      resolution: z.literal(\"chosen\"),\n      id: z.string().trim().min(1).max(120),\n      label: z.string().trim().min(1).max(120),\n    }),\n  }),\n]);\n\nexport type AgentManifest = z.infer<typeof agentManifest>;\n\nexport function parseAgentManifest(value: unknown): AgentManifest { … }\n```\n\n```ts\nconst manifest = parseAgentManifest(version.manifest);\nconst slack = manifest.actions.find(\n  (action) => action.type === \"slack.message.post\",\n);\nconst id = slack?.destination.id;\n```\n\n`packages/validation/src/agent-manifest.ts` is the pattern. A shape that crosses\na package boundary — a `Json` column two apps read, a payload one app writes and\nanother consumes — lives in `packages/validation/src`, one module per shape, and\nis imported by subpath (`@crm/validation/agent-manifest`). Rules that follow from\nit:\n\n- The schema describes what is **actually stored**, not the loosest thing that\n  parses. If a test fixture fails the schema, fix the fixture — a fixture that\n  omits required fields is testing data that cannot exist.\n- Parse failure is a real error with a real message. Do not swallow it into an\n  empty array, because \"unreadable manifest\" and \"no actions\" are different\n  problems and only one of them is the user's fault.\n- Derive types with `z.infer`. Never hand-write an interface beside a schema;\n  they drift.\n\n## Design\n\n@docs/design.md\n\n## Commit Messages & Pull Requests\n\n**Branch from `main`, never from `release`.** `release` is the default branch so\nthat a plain clone runs the last tagged release, and the only things that merge\ninto it are release pull requests. A branch cut from `release` carries release\nmerge commits that do not belong in a feature pull request.\n\n**You do not write the pull request title.** `.github/scripts/pr-title.sh` reads\nthe diff and writes one. Retitle it yourself and the automation stops.\n`CONTRIBUTING.md` is the whole account of how a change reaches `release`; read it\nbefore shipping.\n","CLAUDE.md":"@AGENTS.md\n","apps/agent/agent/skills/data-boundaries.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=apps%2Fagent%2Fagent%2Fskills%2Fdata-boundaries.md -->","apps/agent/agent/skills/evidence.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=apps%2Fagent%2Fagent%2Fskills%2Fevidence.md -->","apps/agent/agent/skills/identity-matching.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=apps%2Fagent%2Fagent%2Fskills%2Fidentity-matching.md -->","apps/agent/agent/skills/writing-a-brief.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=apps%2Fagent%2Fagent%2Fskills%2Fwriting-a-brief.md -->","docs/api.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=docs%2Fapi.md -->","docs/design.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=docs%2Fdesign.md -->","packages/auth/README.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=packages%2Fauth%2FREADME.md -->","packages/db/README.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=packages%2Fdb%2FREADME.md -->"},"files":{".agents/skills/ai-elements/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fai-elements%2FSKILL.md -->",".agents/skills/ai-elements/references/agent.md":"# Agent\n\nA composable component for displaying AI agent configuration with model, instructions, tools, and output schema.\n\nThe `Agent` component displays an interface for showing AI agent configuration details. It's designed to represent a configured agent from the AI SDK, showing the agent's model, system instructions, available tools (with expandable input schemas), and output schema.\n\nSee `scripts/agent.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add agent\n```\n\n## Usage with AI SDK\n\nDisplay an agent's configuration alongside your chat interface. Tools are displayed in an accordion where clicking the description expands to show the input schema.\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport {\n  Agent,\n  AgentContent,\n  AgentHeader,\n  AgentInstructions,\n  AgentOutput,\n  AgentTool,\n  AgentTools,\n} from \"@/components/ai-elements/agent\";\n\nconst webSearch = tool({\n  description: \"Search the web for information\",\n  inputSchema: z.object({\n    query: z.string().describe(\"The search query\"),\n  }),\n});\n\nconst readUrl = tool({\n  description: \"Read and parse content from a URL\",\n  inputSchema: z.object({\n    url: z.string().url().describe(\"The URL to read\"),\n  }),\n});\n\nconst outputSchema = `z.object({\n  sentiment: z.enum(['positive', 'negative', 'neutral']),\n  score: z.number(),\n  summary: z.string(),\n})`;\n\nexport default function Page() {\n  return (\n    <Agent>\n      <AgentHeader\n        name=\"Sentiment Analyzer\"\n        model=\"anthropic/claude-sonnet-4-5\"\n      />\n      <AgentContent>\n        <AgentInstructions>\n          Analyze the sentiment of the provided text and return a structured\n          analysis with sentiment classification, confidence score, and summary.\n        </AgentInstructions>\n        <AgentTools>\n          <AgentTool tool={webSearch} value=\"web_search\" />\n          <AgentTool tool={readUrl} value=\"read_url\" />\n        </AgentTools>\n        <AgentOutput schema={outputSchema} />\n      </AgentContent>\n    </Agent>\n  );\n}\n```\n\n## Features\n\n- Model badge in header\n- Instructions rendered as markdown\n- Tools displayed as accordion items with expandable input schemas\n- Output schema display with syntax highlighting\n- Composable structure for flexible layouts\n- Works with AI SDK `Tool` type\n\n## Props\n\n### `<Agent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any props are spread to the root div. |\n\n### `<AgentHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | The name of the agent. |\n| `model` | `string` | - | The model identifier (e.g.  |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n### `<AgentContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n### `<AgentInstructions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | Required | The instruction text. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n### `<AgentTools />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Accordion>` | - | Any other props are spread to the Accordion component. |\n\n### `<AgentTool />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tool` | `Tool` | Required | The tool object from the AI SDK containing description and inputSchema. |\n| `value` | `string` | Required | Unique identifier for the accordion item. |\n| `...props` | `React.ComponentProps<typeof AccordionItem>` | - | Any other props are spread to the AccordionItem component. |\n\n### `<AgentOutput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `schema` | `string` | Required | The output schema as a string (displayed with syntax highlighting). |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n",".agents/skills/ai-elements/references/artifact.md":"# Artifact\n\nA container component for displaying generated content like code, documents, or other outputs with built-in actions.\n\nThe `Artifact` component provides a structured container for displaying generated content like code, documents, or other outputs with built-in header actions.\n\nSee `scripts/artifact.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add artifact\n```\n\n## Features\n\n- Structured container with header and content areas\n- Built-in header with title and description support\n- Flexible action buttons with tooltips\n- Customizable styling for all subcomponents\n- Support for close buttons and action groups\n- Clean, modern design with border and shadow\n- Responsive layout that adapts to content\n- TypeScript support with proper type definitions\n- Composable architecture for maximum flexibility\n\n## Examples\n\n### With Code Display\n\nSee `scripts/artifact.tsx` for this example.\n\n## Props\n\n### `<Artifact />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n### `<ArtifactHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n### `<ArtifactTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Any other props are spread to the underlying paragraph element. |\n\n### `<ArtifactDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Any other props are spread to the underlying paragraph element. |\n\n### `<ArtifactActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n### `<ArtifactAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string` | - | Tooltip text to display on hover. |\n| `label` | `string` | - | Screen reader label for the action button. |\n| `icon` | `LucideIcon` | - | Lucide icon component to display in the button. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<ArtifactClose />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<ArtifactContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n",".agents/skills/ai-elements/references/attachments.md":"# Attachments\n\nA flexible, composable attachment component for displaying files, images, videos, audio, and source documents.\n\nThe `Attachment` component provides a unified way to display file attachments and source documents with multiple layout variants.\n\nSee `scripts/attachments.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add attachments\n```\n\n## Usage with AI SDK\n\nDisplay user-uploaded files in chat messages or input areas.\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Attachments,\n  Attachment,\n  AttachmentPreview,\n  AttachmentInfo,\n  AttachmentRemove,\n} from \"@/components/ai-elements/attachments\";\nimport type { FileUIPart } from \"ai\";\n\ninterface MessageProps {\n  attachments: (FileUIPart & { id: string })[];\n  onRemove?: (id: string) => void;\n}\n\nconst MessageAttachments = ({ attachments, onRemove }: MessageProps) => (\n  <Attachments variant=\"grid\">\n    {attachments.map((file) => (\n      <Attachment\n        key={file.id}\n        data={file}\n        onRemove={onRemove ? () => onRemove(file.id) : undefined}\n      >\n        <AttachmentPreview />\n        <AttachmentRemove />\n      </Attachment>\n    ))}\n  </Attachments>\n);\n\nexport default MessageAttachments;\n```\n\n## Features\n\n- Three display variants: grid (thumbnails), inline (badges), and list (rows)\n- Supports both FileUIPart and SourceDocumentUIPart from the AI SDK\n- Automatic media type detection (image, video, audio, document, source)\n- Hover card support for inline previews\n- Remove button with customizable callback\n- Composable architecture for maximum flexibility\n- Accessible with proper ARIA labels\n- TypeScript support with exported utility functions\n\n## Examples\n\n### Grid Variant\n\nBest for displaying attachments in messages with visual thumbnails.\n\nSee `scripts/attachments.tsx` for this example.\n\n### Inline Variant\n\nBest for compact badge-style display in input areas with hover previews.\n\nSee `scripts/attachments-inline.tsx` for this example.\n\n### List Variant\n\nBest for file lists with full metadata display.\n\nSee `scripts/attachments-list.tsx` for this example.\n\n## Props\n\n### `<Attachments />`\n\nContainer component that sets the layout variant.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `variant` | `unknown` | - | The display layout variant. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<Attachment />`\n\nIndividual attachment item wrapper.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `data` | `unknown` | - | The attachment data (FileUIPart or SourceDocumentUIPart with id). |\n| `onRemove` | `() => void` | - | Callback fired when the remove button is clicked. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<AttachmentPreview />`\n\nDisplays the media preview (image, video, or icon).\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `fallbackIcon` | `React.ReactNode` | - | Custom icon to display when no preview is available. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<AttachmentInfo />`\n\nDisplays the filename and optional media type.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `showMediaType` | `boolean` | `false` | Whether to show the media type below the filename. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<AttachmentRemove />`\n\nRemove button that appears on hover.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | Screen reader label for the button. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the underlying Button component. |\n\n### `<AttachmentHoverCard />`\n\nWrapper for hover preview functionality.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `openDelay` | `number` | `0` | Delay in ms before opening the hover card. |\n| `closeDelay` | `number` | `0` | Delay in ms before closing the hover card. |\n| `...props` | `React.ComponentProps<typeof HoverCard>` | - | Spread to the underlying HoverCard component. |\n\n### `<AttachmentHoverCardTrigger />`\n\nTrigger element for the hover card.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof HoverCardTrigger>` | - | Spread to the underlying HoverCardTrigger component. |\n\n### `<AttachmentHoverCardContent />`\n\nContent displayed in the hover card.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `align` | `unknown` | - | Alignment of the hover card content. |\n| `...props` | `React.ComponentProps<typeof HoverCardContent>` | - | Spread to the underlying HoverCardContent component. |\n\n### `<AttachmentEmpty />`\n\nEmpty state component when no attachments are present.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n## Utility Functions\n\n### `getMediaCategory(data)`\n\nReturns the media category for an attachment.\n\n```tsx\nimport { getMediaCategory } from \"@/components/ai-elements/attachments\";\n\nconst category = getMediaCategory(attachment);\n// Returns: \"image\" | \"video\" | \"audio\" | \"document\" | \"source\" | \"unknown\"\n```\n\n### `getAttachmentLabel(data)`\n\nReturns the display label for an attachment.\n\n```tsx\nimport { getAttachmentLabel } from \"@/components/ai-elements/attachments\";\n\nconst label = getAttachmentLabel(attachment);\n// Returns filename or fallback like \"Image\" or \"Attachment\"\n```\n",".agents/skills/ai-elements/references/audio-player.md":"# Audio Player\n\nA composable audio player component built on media-chrome, with shadcn styling and flexible controls.\n\nThe `AudioPlayer` component provides a flexible and customizable audio playback interface built on top of media-chrome. It features a composable architecture that allows you to build audio experiences with custom controls, metadata display, and seamless integration with AI-generated audio content.\n\nSee `scripts/audio-player.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add audio-player\n```\n\n## Features\n\n- Built on media-chrome for reliable audio playback\n- Fully composable architecture with granular control components\n- ButtonGroup integration for cohesive control layout\n- Individual control components (play, seek, volume, etc.)\n- Flexible layout with customizable control bars\n- CSS custom properties for deep theming\n- Shadcn/ui Button component styling\n- Responsive design that works across devices\n- Full TypeScript support with proper types for all components\n\n## Variants\n\n### AI SDK Speech Result\n\nThe `AudioPlayer` component can be used to play audio from an AI SDK Speech Result.\n\nSee `scripts/audio-player.tsx` for this example.\n\n### Remote Audio\n\nThe `AudioPlayer` component can be used to play remote audio files.\n\nSee `scripts/audio-player-remote.tsx` for this example.\n\n## Props\n\n### `<AudioPlayer />`\n\nRoot MediaController component. Accepts all MediaController props except `audio` (which is set to `true` by default).\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `style` | `CSSProperties` | - | Custom CSS properties can be passed to override media-chrome theming variables. |\n| `...props` | `Omit<React.ComponentProps<typeof MediaController>, ` | - | Any other props are spread to the MediaController component. |\n\n### `<AudioPlayerElement />`\n\nThe audio element that contains the media source. Accepts either a remote URL or AI SDK Speech Result data.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `src` | `string` | - | The URL of the audio file to play (for remote audio). |\n| `data` | `SpeechResult[` | - | AI SDK Speech Result audio data with base64 encoding (for AI-generated audio). |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the audio element (excluding src when using data). |\n\n### `<AudioPlayerControlBar />`\n\nContainer for control buttons, wraps children in a ButtonGroup.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaControlBar>` | - | Any other props are spread to the MediaControlBar component. |\n\n### `<AudioPlayerPlayButton />`\n\nPlay/pause button wrapped in a shadcn Button component.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaPlayButton>` | - | Any other props are spread to the MediaPlayButton component. |\n\n### `<AudioPlayerSeekBackwardButton />`\n\nSeek backward button wrapped in a shadcn Button component.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `seekOffset` | `number` | `10` | The number of seconds to seek backward. |\n| `...props` | `React.ComponentProps<typeof MediaSeekBackwardButton>` | - | Any other props are spread to the MediaSeekBackwardButton component. |\n\n### `<AudioPlayerSeekForwardButton />`\n\nSeek forward button wrapped in a shadcn Button component.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `seekOffset` | `number` | `10` | The number of seconds to seek forward. |\n| `...props` | `React.ComponentProps<typeof MediaSeekForwardButton>` | - | Any other props are spread to the MediaSeekForwardButton component. |\n\n### `<AudioPlayerTimeDisplay />`\n\nDisplays the current playback time, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaTimeDisplay>` | - | Any other props are spread to the MediaTimeDisplay component. |\n\n### `<AudioPlayerTimeRange />`\n\nSeek slider for controlling playback position, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaTimeRange>` | - | Any other props are spread to the MediaTimeRange component. |\n\n### `<AudioPlayerDurationDisplay />`\n\nDisplays the total duration of the audio, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaDurationDisplay>` | - | Any other props are spread to the MediaDurationDisplay component. |\n\n### `<AudioPlayerMuteButton />`\n\nMute/unmute button, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaMuteButton>` | - | Any other props are spread to the MediaMuteButton component. |\n\n### `<AudioPlayerVolumeRange />`\n\nVolume slider control, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaVolumeRange>` | - | Any other props are spread to the MediaVolumeRange component. |\n",".agents/skills/ai-elements/references/canvas.md":"# Canvas\n\nA React Flow-based canvas component for building interactive node-based interfaces.\n\nThe `Canvas` component provides a React Flow-based canvas for building interactive node-based interfaces. It comes pre-configured with sensible defaults for AI applications, including panning, zooming, and selection behaviors.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add canvas\n```\n\n## Features\n\n- Pre-configured React Flow canvas with AI-optimized defaults\n- Pan on scroll enabled for intuitive navigation\n- Selection on drag for multi-node operations\n- Customizable background color using CSS variables\n- Delete key support (Backspace and Delete keys)\n- Auto-fit view to show all nodes\n- Disabled double-click zoom for better UX\n- Disabled pan on drag to prevent accidental canvas movement\n- Fully compatible with React Flow props and API\n\n## Props\n\n### `<Canvas />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode` | - | Child components like Background, Controls, or MiniMap. |\n| `...props` | `ReactFlowProps` | - | Any other React Flow props like nodes, edges, nodeTypes, edgeTypes, onNodesChange, etc. |\n",".agents/skills/ai-elements/references/chain-of-thought.md":"# Chain of Thought\n\nA collapsible component that visualizes AI reasoning steps with support for search results, images, and step-by-step progress indicators.\n\nThe `ChainOfThought` component provides a visual representation of an AI's reasoning process, showing step-by-step thinking with support for search results, images, and progress indicators. It helps users understand how AI arrives at conclusions.\n\nSee `scripts/chain-of-thought.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add chain-of-thought\n```\n\n## Features\n\n- Collapsible interface with smooth animations powered by Radix UI\n- Step-by-step visualization of AI reasoning process\n- Support for different step statuses (complete, active, pending)\n- Built-in search results display with badge styling\n- Image support with captions for visual content\n- Custom icons for different step types\n- Context-aware components using React Context API\n- Fully typed with TypeScript\n- Accessible with keyboard navigation support\n- Responsive design that adapts to different screen sizes\n- Smooth fade and slide animations for content transitions\n- Composable architecture for flexible customization\n\n## Props\n\n### `<ChainOfThought />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `open` | `boolean` | - | Controlled open state of the collapsible. |\n| `defaultOpen` | `boolean` | `false` | Default open state when uncontrolled. |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback when the open state changes. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div element. |\n\n### `<ChainOfThoughtHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom header text. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<ChainOfThoughtStep />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `icon` | `LucideIcon` | `DotIcon` | Icon to display for the step. |\n| `label` | `string` | - | The main text label for the step. |\n| `description` | `string` | - | Optional description text shown below the label. |\n| `status` | `unknown` | - | Visual status of the step. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div element. |\n\n### `<ChainOfThoughtSearchResults />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any props are spread to the container div element. |\n\n### `<ChainOfThoughtSearchResult />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Badge>` | - | Any props are spread to the Badge component. |\n\n### `<ChainOfThoughtContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any props are spread to the CollapsibleContent component. |\n\n### `<ChainOfThoughtImage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `caption` | `string` | - | Optional caption text displayed below the image. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div element. |\n",".agents/skills/ai-elements/references/checkpoint.md":"# Checkpoint\n\nA simple component for marking conversation history points and restoring the chat to a previous state.\n\nThe `Checkpoint` component provides a way to mark specific points in a conversation history and restore the chat to that state. Inspired by VSCode's Copilot checkpoint feature, it allows users to revert to an earlier conversation state while maintaining a clear visual separation between different conversation segments.\n\nSee `scripts/checkpoint.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add checkpoint\n```\n\n## Features\n\n- Simple flex layout with icon, trigger, and separator\n- Visual separator line for clear conversation breaks\n- Clickable restore button for reverting to checkpoint\n- Customizable icon (defaults to BookmarkIcon)\n- Keyboard accessible with proper ARIA labels\n- Responsive design that adapts to different screen sizes\n- Seamless light/dark theme integration\n\n## Usage with AI SDK\n\nBuild a chat interface with conversation checkpoints that allow users to restore to previous states.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useState, Fragment } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  Checkpoint,\n  CheckpointIcon,\n  CheckpointTrigger,\n} from \"@/components/ai-elements/checkpoint\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport {\n  Conversation,\n  ConversationContent,\n} from \"@/components/ai-elements/conversation\";\n\ntype CheckpointType = {\n  id: string;\n  messageIndex: number;\n  timestamp: Date;\n  messageCount: number;\n};\n\nconst CheckpointDemo = () => {\n  const { messages, setMessages } = useChat();\n  const [checkpoints, setCheckpoints] = useState<CheckpointType[]>([]);\n\n  const createCheckpoint = (messageIndex: number) => {\n    const checkpoint: CheckpointType = {\n      id: nanoid(),\n      messageIndex,\n      timestamp: new Date(),\n      messageCount: messageIndex + 1,\n    };\n    setCheckpoints([...checkpoints, checkpoint]);\n  };\n\n  const restoreToCheckpoint = (messageIndex: number) => {\n    // Restore messages to checkpoint state\n    setMessages(messages.slice(0, messageIndex + 1));\n    // Remove checkpoints after this point\n    setCheckpoints(checkpoints.filter((cp) => cp.messageIndex <= messageIndex));\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <Conversation>\n        <ConversationContent>\n          {messages.map((message, index) => {\n            const checkpoint = checkpoints.find(\n              (cp) => cp.messageIndex === index\n            );\n\n            return (\n              <Fragment key={message.id}>\n                <Message from={message.role}>\n                  <MessageContent>\n                    <MessageResponse>{message.content}</MessageResponse>\n                  </MessageContent>\n                </Message>\n                {checkpoint && (\n                  <Checkpoint>\n                    <CheckpointIcon />\n                    <CheckpointTrigger\n                      onClick={() =>\n                        restoreToCheckpoint(checkpoint.messageIndex)\n                      }\n                    >\n                      Restore checkpoint\n                    </CheckpointTrigger>\n                  </Checkpoint>\n                )}\n              </Fragment>\n            );\n          })}\n        </ConversationContent>\n      </Conversation>\n    </div>\n  );\n};\n\nexport default CheckpointDemo;\n```\n\n## Use Cases\n\n### Manual Checkpoints\n\nAllow users to manually create checkpoints at important conversation points:\n\n```tsx\n<Button onClick={() => createCheckpoint(messages.length - 1)}>\n  Create Checkpoint\n</Button>\n```\n\n### Automatic Checkpoints\n\nCreate checkpoints automatically after significant conversation milestones:\n\n```tsx\nuseEffect(() => {\n  // Create checkpoint every 5 messages\n  if (messages.length > 0 && messages.length % 5 === 0) {\n    createCheckpoint(messages.length - 1);\n  }\n}, [messages.length]);\n```\n\n### Branching Conversations\n\nUse checkpoints to enable conversation branching where users can explore different conversation paths:\n\n```tsx\nconst restoreAndBranch = (messageIndex: number) => {\n  // Save current branch\n  const currentBranch = messages.slice(messageIndex + 1);\n  saveBranch(currentBranch);\n\n  // Restore to checkpoint\n  restoreToCheckpoint(messageIndex);\n};\n```\n\n## Props\n\n### `<Checkpoint />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The checkpoint icon and trigger components. Automatically includes a Separator at the end. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<CheckpointIcon />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom icon content. If not provided, defaults to a BookmarkIcon from lucide-react. |\n| `...props` | `LucideProps` | - | Any other props are spread to the BookmarkIcon component. |\n\n### `<CheckpointTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The text or content to display in the trigger button. |\n| `tooltip` | `string` | - | Optional tooltip text shown on hover. |\n| `variant` | `string` | - | The button variant style. |\n| `size` | `string` | - | The button size. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n",".agents/skills/ai-elements/references/code-block.md":"# Code Block\n\nProvides syntax highlighting, line numbers, and copy to clipboard functionality for code blocks.\n\nThe `CodeBlock` component provides syntax highlighting, line numbers, and copy to clipboard functionality for code blocks. It's fully composable, allowing you to customize the header, actions, and content.\n\nSee `scripts/code-block.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add code-block\n```\n\n## Usage\n\nThe CodeBlock is fully composable. Here's a basic example:\n\n```tsx\nimport {\n  CodeBlock,\n  CodeBlockActions,\n  CodeBlockCopyButton,\n  CodeBlockFilename,\n  CodeBlockHeader,\n  CodeBlockTitle,\n} from \"@/components/ai-elements/code-block\";\nimport { FileIcon } from \"lucide-react\";\n\nexport const Example = () => (\n  <CodeBlock code={code} language=\"typescript\">\n    <CodeBlockHeader>\n      <CodeBlockTitle>\n        <FileIcon size={14} />\n        <CodeBlockFilename>example.ts</CodeBlockFilename>\n      </CodeBlockTitle>\n      <CodeBlockActions>\n        <CodeBlockCopyButton />\n      </CodeBlockActions>\n    </CodeBlockHeader>\n  </CodeBlock>\n);\n```\n\n## Features\n\n- Syntax highlighting with Shiki\n- Line numbers (optional)\n- Copy to clipboard functionality\n- Automatic light/dark theme switching via CSS variables\n- Language selector for multi-language examples\n- Fully composable architecture\n- Accessible design\n\n## Examples\n\n### Dark Mode\n\nTo use the `CodeBlock` component in dark mode, wrap it in a `div` with the `dark` class.\n\nSee `scripts/code-block-dark.tsx` for this example.\n\n### Language Selector\n\nAdd a language selector to switch between different code implementations:\n\nSee `scripts/code-block.tsx` for this example.\n\n## Props\n\n### `<CodeBlock />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `code` | `string` | - | The code content to display. |\n| `language` | `BundledLanguage` | - | The programming language for syntax highlighting. |\n| `showLineNumbers` | `boolean` | `false` | Whether to show line numbers. |\n| `children` | `React.ReactNode` | - | Child elements like CodeBlockHeader. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockHeader />`\n\nContainer for the header row. Uses flexbox with `justify-between`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Header content (CodeBlockTitle, CodeBlockActions, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockTitle />`\n\nLeft-aligned container for icon and filename. Uses flexbox with `gap-2`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Title content (icon, CodeBlockFilename, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockFilename />`\n\nDisplays the filename in monospace font.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The filename to display. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockActions />`\n\nRight-aligned container for action buttons. Uses flexbox with `gap-2`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Action buttons (CodeBlockCopyButton, CodeBlockLanguageSelector, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback fired after a successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback fired if copying fails. |\n| `timeout` | `number` | `2000` | How long to show the copied state (ms). |\n| `children` | `React.ReactNode` | - | Custom content for the button. Defaults to copy/check icons. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockLanguageSelector />`\n\nWrapper for the language selector. Extends shadcn/ui Select.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The currently selected language. |\n| `onValueChange` | `(value: string) => void` | - | Callback when the language changes. |\n| `children` | `React.ReactNode` | - | Selector components (Trigger, Content, Items). |\n\n### `<CodeBlockLanguageSelectorTrigger />`\n\nTrigger button for the language selector dropdown. Pre-styled for code block header.\n\n### `<CodeBlockLanguageSelectorValue />`\n\nDisplays the selected language value.\n\n### `<CodeBlockLanguageSelectorContent />`\n\nDropdown content container. Defaults to `align=\"end\"`.\n\n### `<CodeBlockLanguageSelectorItem />`\n\nIndividual language option in the dropdown.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The language value. |\n| `children` | `React.ReactNode` | - | The display label. |\n\n### `<CodeBlockContainer />`\n\nLow-level container component with performance optimizations (`contentVisibility`). Used internally by CodeBlock.\n\n### `<CodeBlockContent />`\n\nLow-level component that handles syntax highlighting. Used internally by CodeBlock, but can be used directly for custom layouts.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `code` | `string` | - | The code content to display. |\n| `language` | `BundledLanguage` | - | The programming language for syntax highlighting. |\n| `showLineNumbers` | `boolean` | `false` | Whether to show line numbers. |\n",".agents/skills/ai-elements/references/commit.md":"# Commit\n\nDisplay commit information with hash, message, author, and file changes.\n\nThe `Commit` component displays commit details including hash, message, author, timestamp, and changed files.\n\nSee `scripts/commit.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add commit\n```\n\n## Features\n\n- Commit hash display with copy button\n- Author avatar with initials\n- Relative timestamp formatting\n- Collapsible file changes list\n- Color-coded file status (added/modified/deleted/renamed)\n- Line additions/deletions count\n\n## File Status\n\n| Status     | Label | Color  |\n| ---------- | ----- | ------ |\n| `added`    | A     | Green  |\n| `modified` | M     | Yellow |\n| `deleted`  | D     | Red    |\n| `renamed`  | R     | Blue   |\n\n## Props\n\n### `<Commit />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Spread to the Collapsible component. |\n\n### `<CommitHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Spread to the CollapsibleTrigger component. |\n\n### `<CommitAuthor />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitAuthorAvatar />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `initials` | `string` | Required | Author initials to display. |\n| `...props` | `React.ComponentProps<typeof Avatar>` | - | Spread to the Avatar component. |\n\n### `<CommitInfo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitMessage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitMetadata />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitHash />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitSeparator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom separator content. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitTimestamp />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `date` | `Date` | Required | Commit date. |\n| `children` | `React.ReactNode` | - | Custom timestamp content. Defaults to relative time. |\n| `...props` | `React.HTMLAttributes<HTMLTimeElement>` | - | Spread to the time element. |\n\n### `<CommitActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `hash` | `string` | Required | Commit hash to copy. |\n| `onCopy` | `() => void` | - | Callback after successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback if copying fails. |\n| `timeout` | `number` | `2000` | Duration to show copied state (ms). |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the Button component. |\n\n### `<CommitContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Spread to the CollapsibleContent component. |\n\n### `<CommitFiles />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the row div. |\n\n### `<CommitFileInfo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitFileStatus />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `status` | `unknown` | Required | File change status. |\n| `children` | `React.ReactNode` | - | Custom status label. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitFileIcon />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof FileIcon>` | - | Spread to the FileIcon component. |\n\n### `<CommitFilePath />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitFileChanges />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitFileAdditions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `count` | `number` | Required | Number of lines added. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitFileDeletions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `count` | `number` | Required | Number of lines deleted. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n",".agents/skills/ai-elements/references/confirmation.md":"# Confirmation\n\nAn alert-based component for managing tool execution approval workflows with request, accept, and reject states.\n\nThe `Confirmation` component provides a flexible system for displaying tool approval requests and their outcomes. Perfect for showing users when AI tools require approval before execution, and displaying the approval status afterward.\n\nSee `scripts/confirmation.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add confirmation\n```\n\n## Usage with AI SDK\n\nBuild a chat UI with tool approval workflow where dangerous tools require user confirmation before execution.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport { DefaultChatTransport, type ToolUIPart } from \"ai\";\nimport { useState } from \"react\";\nimport { CheckIcon, XIcon } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Confirmation,\n  ConfirmationTitle,\n  ConfirmationRequest,\n  ConfirmationAccepted,\n  ConfirmationRejected,\n  ConfirmationActions,\n  ConfirmationAction,\n} from \"@/components/ai-elements/confirmation\";\nimport { MessageResponse } from \"@/components/ai-elements/message\";\n\ntype DeleteFileInput = {\n  filePath: string;\n  confirm: boolean;\n};\n\ntype DeleteFileToolUIPart = ToolUIPart<{\n  delete_file: {\n    input: DeleteFileInput;\n    output: { success: boolean; message: string };\n  };\n}>;\n\nconst Example = () => {\n  const { messages, sendMessage, status, addToolApprovalResponse } = useChat({\n    transport: new DefaultChatTransport({\n      api: \"/api/chat\",\n    }),\n  });\n\n  const handleDeleteFile = () => {\n    sendMessage({ text: \"Delete the file at /tmp/example.txt\" });\n  };\n\n  const latestMessage = messages[messages.length - 1];\n  const deleteTool = latestMessage?.parts?.find(\n    (part) => part.type === \"tool-delete_file\"\n  ) as DeleteFileToolUIPart | undefined;\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full space-y-4\">\n        <Button onClick={handleDeleteFile} disabled={status !== \"ready\"}>\n          Delete Example File\n        </Button>\n\n        {deleteTool?.approval && (\n          <Confirmation approval={deleteTool.approval} state={deleteTool.state}>\n            <ConfirmationRequest>\n              This tool wants to delete:{\" \"}\n              <code>{deleteTool.input?.filePath}</code>\n              <br />\n              Do you approve this action?\n            </ConfirmationRequest>\n            <ConfirmationAccepted>\n              <CheckIcon className=\"size-4\" />\n              <span>You approved this tool execution</span>\n            </ConfirmationAccepted>\n            <ConfirmationRejected>\n              <XIcon className=\"size-4\" />\n              <span>You rejected this tool execution</span>\n            </ConfirmationRejected>\n            <ConfirmationActions>\n              <ConfirmationAction\n                variant=\"outline\"\n                onClick={() =>\n                  addToolApprovalResponse({\n                    id: deleteTool.approval!.id,\n                    approved: false,\n                  })\n                }\n              >\n                Reject\n              </ConfirmationAction>\n              <ConfirmationAction\n                variant=\"default\"\n                onClick={() =>\n                  addToolApprovalResponse({\n                    id: deleteTool.approval!.id,\n                    approved: true,\n                  })\n                }\n              >\n                Approve\n              </ConfirmationAction>\n            </ConfirmationActions>\n          </Confirmation>\n        )}\n\n        {deleteTool?.output && (\n          <MessageResponse>\n            {deleteTool.output.success\n              ? deleteTool.output.message\n              : `Error: ${deleteTool.output.message}`}\n          </MessageResponse>\n        )}\n      </div>\n    </div>\n  );\n};\n\nexport default Example;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/chat/route.tsx\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\nimport { z } from \"zod\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages: await convertToModelMessages(messages),\n    tools: {\n      delete_file: {\n        description: \"Delete a file from the file system\",\n        parameters: z.object({\n          filePath: z.string().describe(\"The path to the file to delete\"),\n          confirm: z\n            .boolean()\n            .default(false)\n            .describe(\"Confirmation that the user wants to delete the file\"),\n        }),\n        requireApproval: true, // Enable approval workflow\n        execute: async ({ filePath, confirm }) => {\n          if (!confirm) {\n            return {\n              success: false,\n              message: \"Deletion not confirmed\",\n            };\n          }\n\n          // Simulate file deletion\n          await new Promise((resolve) => setTimeout(resolve, 500));\n\n          return {\n            success: true,\n            message: `Successfully deleted ${filePath}`,\n          };\n        },\n      },\n    },\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Context-based state management for approval workflow\n- Conditional rendering based on approval state\n- Support for approval-requested, approval-responded, output-denied, and output-available states\n- Built on shadcn/ui Alert and Button components\n- TypeScript support with comprehensive type definitions\n- Customizable styling with Tailwind CSS\n- Keyboard navigation and accessibility support\n- Theme-aware with automatic dark mode support\n\n## Examples\n\n### Approval Request State\n\nShows the approval request with action buttons when state is `approval-requested`.\n\nSee `scripts/confirmation-request.tsx` for this example.\n\n### Approved State\n\nShows the accepted status when user approves and state is `approval-responded` or `output-available`.\n\nSee `scripts/confirmation-accepted.tsx` for this example.\n\n### Rejected State\n\nShows the rejected status when user rejects and state is `output-denied`.\n\nSee `scripts/confirmation-rejected.tsx` for this example.\n\n## Props\n\n### `<Confirmation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `approval` | `ToolUIPart[` | - | The approval object containing the approval ID and status. If not provided or undefined, the component will not render. |\n| `state` | `ToolUIPart[` | - | The current state of the tool (input-streaming, input-available, approval-requested, approval-responded, output-denied, or output-available). Will not render for input-streaming or input-available states. |\n| `className` | `string` | - | Additional CSS classes to apply to the Alert component. |\n| `...props` | `React.ComponentProps<typeof Alert>` | - | Any other props are spread to the Alert component. |\n\n### `<ConfirmationTitle />`\n\nA styled description element for displaying a title or label within the confirmation alert.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof AlertDescription>` | - | Any other props are spread to the underlying AlertDescription component. |\n\n### `<ConfirmationRequest />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The content to display when approval is requested. Only renders when state is  |\n\n### `<ConfirmationAccepted />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The content to display when approval is accepted. Only renders when approval.approved is true and state is  |\n\n### `<ConfirmationRejected />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The content to display when approval is rejected. Only renders when approval.approved is false and state is  |\n\n### `<ConfirmationActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the actions container. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. Only renders when state is  |\n\n### `<ConfirmationAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component. Styled with h-8 px-3 text-sm classes by default. |\n",".agents/skills/ai-elements/references/connection.md":"# Connection\n\nA custom connection line component for React Flow-based canvases with animated bezier curve styling.\n\nThe `Connection` component provides a styled connection line for React Flow canvases. It renders an animated bezier curve with a circle indicator at the target end, using consistent theming through CSS variables.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add connection\n```\n\n## Features\n\n- Smooth bezier curve animation for connection lines\n- Visual indicator circle at the target position\n- Theme-aware styling using CSS variables\n- Cubic bezier curve calculation for natural flow\n- Lightweight implementation with minimal props\n- Full TypeScript support with React Flow types\n- Compatible with React Flow's connection system\n\n## Props\n\n### `<Connection />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `fromX` | `number` | - | The x-coordinate of the connection start point. |\n| `fromY` | `number` | - | The y-coordinate of the connection start point. |\n| `toX` | `number` | - | The x-coordinate of the connection end point. |\n| `toY` | `number` | - | The y-coordinate of the connection end point. |\n",".agents/skills/ai-elements/references/context.md":"# Context\n\nA compound component system for displaying AI model context window usage, token consumption, and cost estimation.\n\nThe `Context` component provides a comprehensive view of AI model usage through a compound component system. It displays context window utilization, token consumption breakdown (input, output, reasoning, cache), and cost estimation in an interactive hover card interface.\n\nSee `scripts/context.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add context\n```\n\n## Features\n\n- **Compound Component Architecture**: Flexible composition of context display elements\n- **Visual Progress Indicator**: Circular SVG progress ring showing context usage percentage\n- **Token Breakdown**: Detailed view of input, output, reasoning, and cached tokens\n- **Cost Estimation**: Real-time cost calculation using the `tokenlens` library\n- **Intelligent Formatting**: Automatic token count formatting (K, M, B suffixes)\n- **Interactive Hover Card**: Detailed information revealed on hover\n- **Context Provider Pattern**: Clean data flow through React Context API\n- **TypeScript Support**: Full type definitions for all components\n- **Accessible Design**: Proper ARIA labels and semantic HTML\n- **Theme Integration**: Uses currentColor for automatic theme adaptation\n\n## Props\n\n### `<Context />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `maxTokens` | `number` | - | The total context window size in tokens. |\n| `usedTokens` | `number` | - | The number of tokens currently used. |\n| `usage` | `LanguageModelUsage` | - | Detailed token usage breakdown from the AI SDK (input, output, reasoning, cached tokens). |\n| `modelId` | `ModelId` | - | Model identifier for cost calculation (e.g.,  |\n| `...props` | `ComponentProps<HoverCard>` | - | Any other props are spread to the HoverCard component. |\n\n### `<ContextTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom trigger element. If not provided, renders a default button with percentage and icon. |\n| `...props` | `ComponentProps<Button>` | - | Props spread to the default button element. |\n\n### `<ContextContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes for the hover card content. |\n| `...props` | `ComponentProps<HoverCardContent>` | - | Props spread to the HoverCardContent component. |\n\n### `<ContextContentHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom header content. If not provided, renders percentage and token count with progress bar. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the header div element. |\n\n### `<ContextContentBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Body content, typically containing usage breakdown components. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the body div element. |\n\n### `<ContextContentFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom footer content. If not provided, renders total cost when modelId is provided. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the footer div element. |\n\n### Usage Components\n\nAll usage components (`ContextInputUsage`, `ContextOutputUsage`, `ContextReasoningUsage`, `ContextCacheUsage`) share the same props:\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom content. If not provided, renders token count and cost for the respective usage type. |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the div element. |\n\n## Component Architecture\n\nThe Context component uses a compound component pattern with React Context for data sharing:\n\n1. **`<Context>`** - Root provider component that holds all context data\n2. **`<ContextTrigger>`** - Interactive trigger element (default: button with percentage)\n3. **`<ContextContent>`** - Hover card content container\n4. **`<ContextContentHeader>`** - Header section with progress visualization\n5. **`<ContextContentBody>`** - Body section for usage breakdowns\n6. **`<ContextContentFooter>`** - Footer section for total cost\n7. **Usage Components** - Individual token usage displays (Input, Output, Reasoning, Cache)\n\n## Token Formatting\n\nThe component uses `Intl.NumberFormat` with compact notation for automatic formatting:\n\n- Under 1,000: Shows exact count (e.g., \"842\")\n- 1,000+: Shows with K suffix (e.g., \"32K\")\n- 1,000,000+: Shows with M suffix (e.g., \"1.5M\")\n- 1,000,000,000+: Shows with B suffix (e.g., \"2.1B\")\n\n## Cost Calculation\n\nWhen a `modelId` is provided, the component automatically calculates costs using the `tokenlens` library:\n\n- **Input tokens**: Cost based on model's input pricing\n- **Output tokens**: Cost based on model's output pricing\n- **Reasoning tokens**: Special pricing for reasoning-capable models\n- **Cached tokens**: Reduced pricing for cached input tokens\n- **Total cost**: Sum of all token type costs\n\nCosts are formatted using `Intl.NumberFormat` with USD currency.\n\n## Styling\n\nThe component uses Tailwind CSS classes and follows your design system:\n\n- Progress indicator uses `currentColor` for theme adaptation\n- Hover card has customizable width and padding\n- Footer has a secondary background for visual separation\n- All text sizes use the `text-xs` class for consistency\n- Muted foreground colors for secondary information\n",".agents/skills/ai-elements/references/controls.md":"# Controls\n\nA styled controls component for React Flow-based canvases with zoom and fit view functionality.\n\nThe `Controls` component provides interactive zoom and fit view controls for React Flow canvases. It includes a modern, themed design with backdrop blur and card styling.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add controls\n```\n\n## Features\n\n- Zoom in/out controls\n- Fit view button to center and scale content\n- Rounded pill design with backdrop blur\n- Theme-aware card background\n- Subtle drop shadow for depth\n- Full TypeScript support\n- Compatible with all React Flow control features\n\n## Props\n\n### `<Controls />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the controls. |\n| `...props` | `ComponentProps<typeof Controls>` | - | Any other props from @xyflow/react Controls component (showZoom, showFitView, showInteractive, position, etc.). |\n",".agents/skills/ai-elements/references/conversation.md":"# Conversation\n\nWraps messages and automatically scrolls to the bottom. Also includes a scroll button that appears when not at the bottom.\n\nThe `Conversation` component wraps messages and automatically scrolls to the bottom. Also includes a scroll button that appears when not at the bottom.\n\n<Preview path=\"conversation\" className=\"p-0\" />\n\n## Installation\n\n```bash\nnpx ai-elements@latest add conversation\n```\n\n## Usage with AI SDK\n\nBuild a simple conversational UI with `Conversation` and [`PromptInput`](/components/prompt-input):\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationDownload,\n  ConversationEmptyState,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { MessageSquare } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\n\nconst ConversationDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { messages, sendMessage, status } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.length === 0 ? (\n              <ConversationEmptyState\n                icon={<MessageSquare className=\"size-12\" />}\n                title=\"Start a conversation\"\n                description=\"Type a message below to begin chatting\"\n              />\n            ) : (\n              messages.map((message) => (\n                <Message from={message.role} key={message.id}>\n                  <MessageContent>\n                    {message.parts.map((part, i) => {\n                      switch (part.type) {\n                        case \"text\": // we don't use any reasoning or tool calls in this example\n                          return (\n                            <MessageResponse key={`${message.id}-${i}`}>\n                              {part.text}\n                            </MessageResponse>\n                          );\n                        default:\n                          return null;\n                      }\n                    })}\n                  </MessageContent>\n                </Message>\n              ))\n            )}\n          </ConversationContent>\n          <ConversationDownload messages={messages} />\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Say something...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ConversationDemo;\n```\n\nAdd the following route to your backend:\n\n```tsx title=\"api/chat/route.ts\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Automatic scrolling to the bottom when new messages are added\n- Smooth scrolling behavior with configurable animation\n- Scroll button that appears when not at the bottom\n- Download conversation as Markdown\n- Responsive design with customizable padding and spacing\n- Flexible content layout with consistent message spacing\n- Accessible with proper ARIA roles for screen readers\n- Customizable styling through className prop\n- Support for any number of child message components\n\n## Props\n\n### `<Conversation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `contextRef` | `React.Ref<StickToBottomContext>` | - | Optional ref to access the StickToBottom context object. |\n| `instance` | `StickToBottomInstance` | - | Optional instance for controlling the StickToBottom component. |\n| `children` | `((context: StickToBottomContext) => ReactNode) | ReactNode` | - | Render prop or ReactNode for custom rendering with context. |\n| `...props` | `Omit<React.HTMLAttributes<HTMLDivElement>, ` | - | Any other props are spread to the root div. |\n\n### `<ConversationContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `((context: StickToBottomContext) => ReactNode) | ReactNode` | - | Render prop or ReactNode for custom rendering with context. |\n| `...props` | `Omit<React.HTMLAttributes<HTMLDivElement>, ` | - | Any other props are spread to the root div. |\n\n### `<ConversationEmptyState />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | - | The title text to display. |\n| `description` | `string` | - | The description text to display. |\n| `icon` | `React.ReactNode` | - | Optional icon to display above the text. |\n| `children` | `React.ReactNode` | - | Optional additional content to render below the text. |\n| `...props` | `ComponentProps<` | - | Any other props are spread to the root div. |\n\n### `<ConversationScrollButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<ConversationDownload />`\n\nA button that downloads the conversation as a Markdown file.\n\n```tsx\nimport { ConversationDownload } from \"@/components/ai-elements/conversation\";\n\n<Conversation>\n  <ConversationContent>\n    {messages.map(...)}\n  </ConversationContent>\n  <ConversationDownload messages={messages} />\n  <ConversationScrollButton />\n</Conversation>\n```\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `messages` | `UIMessage[]` | Required | Array of messages to include in the download. |\n| `filename` | `string` | - | The filename for the downloaded file. |\n| `formatMessage` | `(message: UIMessage, index: number) => string` | - | Custom function to format each message in the output. |\n| `...props` | `Omit<ComponentProps<typeof Button>, ` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `messagesToMarkdown`\n\nA utility function to convert messages to Markdown format. Useful for custom download implementations.\n\n```tsx\nimport { messagesToMarkdown } from \"@/components/ai-elements/conversation\";\n\nconst markdown = messagesToMarkdown(messages);\n\n// With custom formatter\nconst customMarkdown = messagesToMarkdown(\n  messages,\n  (msg, i) =>\n    `[${msg.role}]: ${msg.parts\n      .filter((p) => p.type === \"text\")\n      .map((p) => p.text)\n      .join(\"\")}`\n);\n```\n",".agents/skills/ai-elements/references/edge.md":"# Edge\n\nCustomizable edge components for React Flow canvases with animated and temporary states.\n\nThe `Edge` component provides two pre-styled edge types for React Flow canvases: `Temporary` for dashed temporary connections and `Animated` for connections with animated indicators.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add edge\n```\n\n## Features\n\n- Two distinct edge types: Temporary and Animated\n- Temporary edges use dashed lines with ring color\n- Animated edges include a moving circle indicator\n- Automatic handle position calculation\n- Smart offset calculation based on handle type and position\n- Uses Bezier curves for smooth, natural-looking connections\n- Fully compatible with React Flow's edge system\n- Type-safe implementation with TypeScript\n\n## Edge Types\n\n### `Edge.Temporary`\n\nA dashed edge style for temporary or preview connections. Uses a simple Bezier path with a dashed stroke pattern.\n\n### `Edge.Animated`\n\nA solid edge with an animated circle that moves along the path. The animation repeats indefinitely with a 2-second duration, providing visual feedback for active connections.\n\n## Props\n\nBoth edge types accept standard React Flow `EdgeProps`:\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `id` | `string` | - | Unique identifier for the edge. |\n| `source` | `string` | - | ID of the source node. |\n| `target` | `string` | - | ID of the target node. |\n| `sourceX` | `number` | - | X coordinate of the source handle (Temporary only). |\n| `sourceY` | `number` | - | Y coordinate of the source handle (Temporary only). |\n| `targetX` | `number` | - | X coordinate of the target handle (Temporary only). |\n| `targetY` | `number` | - | Y coordinate of the target handle (Temporary only). |\n| `sourcePosition` | `Position` | - | Position of the source handle (Left, Right, Top, Bottom). |\n| `targetPosition` | `Position` | - | Position of the target handle (Left, Right, Top, Bottom). |\n| `markerEnd` | `string` | - | SVG marker ID for the edge end (Animated only). |\n| `style` | `React.CSSProperties` | - | Custom styles for the edge (Animated only). |\n",".agents/skills/ai-elements/references/environment-variables.md":"# Environment Variables\n\nDisplay environment variables with masking and copy functionality.\n\nThe `EnvironmentVariables` component displays environment variables with value masking, visibility toggle, and copy functionality.\n\nSee `scripts/environment-variables.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add environment-variables\n```\n\n## Features\n\n- Value masking by default\n- Toggle visibility switch\n- Copy individual values\n- Export format support (`export KEY=\"value\"`)\n- Required badge indicator\n\n## Props\n\n### `<EnvironmentVariables />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `showValues` | `boolean` | - | Controlled visibility state. |\n| `defaultShowValues` | `boolean` | `false` | Default visibility state. |\n| `onShowValuesChange` | `(show: boolean) => void` | - | Callback when visibility changes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<EnvironmentVariablesHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the header div. |\n\n### `<EnvironmentVariablesTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom title text. |\n| `...props` | `React.HTMLAttributes<HTMLHeadingElement>` | - | Spread to the h3 element. |\n\n### `<EnvironmentVariablesToggle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Switch>` | - | Spread to the Switch component. |\n\n### `<EnvironmentVariablesContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the content div. |\n\n### `<EnvironmentVariable />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | Variable name. |\n| `value` | `string` | Required | Variable value. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the row div. |\n\n### `<EnvironmentVariableGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the group div. |\n\n### `<EnvironmentVariableName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom name content. Defaults to the name from context. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<EnvironmentVariableValue />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom value content. Defaults to the masked/unmasked value from context. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<EnvironmentVariableCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `copyFormat` | `unknown` | - | Format to copy. |\n| `onCopy` | `() => void` | - | Callback after successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback if copying fails. |\n| `timeout` | `number` | `2000` | Duration to show copied state (ms). |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the Button component. |\n\n### `<EnvironmentVariableRequired />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom badge text. |\n| `...props` | `React.ComponentProps<typeof Badge>` | - | Spread to the Badge component. |\n",".agents/skills/ai-elements/references/file-tree.md":"# File Tree\n\nDisplay hierarchical file and folder structure with expand/collapse functionality.\n\nThe `FileTree` component displays a hierarchical file system structure with expandable folders and file selection.\n\nSee `scripts/file-tree.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add file-tree\n```\n\n## Features\n\n- Hierarchical folder structure\n- Expand/collapse folders\n- File selection with callback\n- Keyboard accessible\n- Customizable icons\n- Controlled and uncontrolled modes\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/file-tree-basic.tsx` for this example.\n\n### With Selection\n\nSee `scripts/file-tree-selection.tsx` for this example.\n\n### Default Expanded\n\nSee `scripts/file-tree-expanded.tsx` for this example.\n\n## Props\n\n### `<FileTree />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `expanded` | `Set<string>` | - | Controlled expanded paths. |\n| `defaultExpanded` | `Set<string>` | `new Set()` | Default expanded paths. |\n| `selectedPath` | `string` | - | Currently selected file/folder path. |\n| `onSelect` | `(path: string) => void` | - | Callback when a file/folder is selected. |\n| `onExpandedChange` | `(expanded: Set<string>) => void` | - | Callback when expanded paths change. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<FileTreeFolder />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `path` | `string` | - | Unique folder path. |\n| `name` | `string` | - | Display name. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<FileTreeFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `path` | `string` | - | Unique file path. |\n| `name` | `string` | - | Display name. |\n| `icon` | `ReactNode` | - | Custom file icon. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### Subcomponents\n\n- `FileTreeIcon` - Icon wrapper\n- `FileTreeName` - Name text\n- `FileTreeActions` - Action buttons container (stops click propagation)\n",".agents/skills/ai-elements/references/image.md":"# Image\n\nDisplays AI-generated images from the AI SDK.\n\nThe `Image` component displays AI-generated images from the AI SDK. It accepts a [`Experimental_GeneratedImage`](/docs/reference/ai-sdk-core/generate-image) object from the AI SDK's `generateImage` function and automatically renders it as an image.\n\nSee `scripts/image.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add image\n```\n\n## Usage with AI SDK\n\nBuild a simple app allowing a user to generate an image given a prompt.\n\nInstall the `@ai-sdk/openai` package:\n\n```package-install\nnpm i @ai-sdk/openai\n```\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { Image } from \"@/components/ai-elements/image\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { useState } from \"react\";\nimport { Spinner } from \"@/components/ui/spinner\";\n\nconst ImageDemo = () => {\n  const [prompt, setPrompt] = useState(\"A futuristic cityscape at sunset\");\n  const [imageData, setImageData] = useState<any>(null);\n  const [isLoading, setIsLoading] = useState(false);\n\n  const handleSubmit = async (message: PromptInputMessage) => {\n    if (!message.text.trim()) return;\n    setPrompt(\"\");\n\n    setIsLoading(true);\n    try {\n      const response = await fetch(\"/api/image\", {\n        method: \"POST\",\n        body: JSON.stringify({ prompt: message.text.trim() }),\n      });\n\n      const data = await response.json();\n\n      setImageData(data);\n    } catch (error) {\n      console.error(\"Error generating image:\", error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex-1 overflow-y-auto p-4\">\n          {imageData && (\n            <div className=\"flex justify-center\">\n              <Image\n                {...imageData}\n                alt=\"Generated image\"\n                className=\"h-[300px] aspect-square border rounded-lg\"\n              />\n            </div>\n          )}\n          {isLoading && <Spinner />}\n        </div>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={prompt}\n            placeholder=\"Describe the image you want to generate...\"\n            onChange={(e) => setPrompt(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={isLoading ? \"submitted\" : \"ready\"}\n            disabled={!prompt.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ImageDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/image/route.ts\"\nimport { openai } from \"@ai-sdk/openai\";\nimport { experimental_generateImage } from \"ai\";\n\nexport async function POST(req: Request) {\n  const { prompt }: { prompt: string } = await req.json();\n\n  const { image } = await experimental_generateImage({\n    model: openai.image(\"dall-e-3\"),\n    prompt: prompt,\n    size: \"1024x1024\",\n  });\n\n  return Response.json({\n    base64: image.base64,\n    uint8Array: image.uint8Array,\n    mediaType: image.mediaType,\n  });\n}\n```\n\n## Features\n\n- Accepts `Experimental_GeneratedImage` objects directly from the AI SDK\n- Automatically creates proper data URLs from base64-encoded image data\n- Supports all standard HTML image attributes\n- Responsive by default with `max-w-full h-auto` styling\n- Customizable with additional CSS classes\n- Includes proper TypeScript types for AI SDK compatibility\n\n## Props\n\n### `<Image />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `alt` | `string` | - | Alternative text for the image. |\n| `className` | `string` | - | Additional CSS classes to apply to the image. |\n| `...props` | `Experimental_GeneratedImage` | - | The image data to display, as returned by the AI SDK. |\n",".agents/skills/ai-elements/references/inline-citation.md":"# Inline Citation\n\nA hoverable citation component that displays source information and quotes inline with text, perfect for AI-generated content with references.\n\nThe `InlineCitation` component provides a way to display citations inline with text content, similar to academic papers or research documents. It consists of a citation pill that shows detailed source information on hover, making it perfect for AI-generated content that needs to reference sources.\n\nSee `scripts/inline-citation.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add inline-citation\n```\n\n## Usage with AI SDK\n\nBuild citations for AI-generated content using [`experimental_generateObject`](/docs/reference/ai-sdk-ui/use-object).\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { experimental_useObject as useObject } from \"@ai-sdk/react\";\nimport {\n  InlineCitation,\n  InlineCitationText,\n  InlineCitationCard,\n  InlineCitationCardTrigger,\n  InlineCitationCardBody,\n  InlineCitationCarousel,\n  InlineCitationCarouselContent,\n  InlineCitationCarouselItem,\n  InlineCitationCarouselHeader,\n  InlineCitationCarouselIndex,\n  InlineCitationCarouselPrev,\n  InlineCitationCarouselNext,\n  InlineCitationSource,\n  InlineCitationQuote,\n} from \"@/components/ai-elements/inline-citation\";\nimport { Button } from \"@/components/ui/button\";\nimport { citationSchema } from \"@/app/api/citation/route\";\n\nconst CitationDemo = () => {\n  const { object, submit, isLoading } = useObject({\n    api: \"/api/citation\",\n    schema: citationSchema,\n  });\n\n  const handleSubmit = (topic: string) => {\n    submit({ prompt: topic });\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 space-y-6\">\n      <div className=\"flex gap-2 mb-6\">\n        <Button\n          onClick={() => handleSubmit(\"artificial intelligence\")}\n          disabled={isLoading}\n          variant=\"outline\"\n        >\n          Generate AI Content\n        </Button>\n        <Button\n          onClick={() => handleSubmit(\"climate change\")}\n          disabled={isLoading}\n          variant=\"outline\"\n        >\n          Generate Climate Content\n        </Button>\n      </div>\n\n      {isLoading && !object && (\n        <div className=\"text-muted-foreground\">\n          Generating content with citations...\n        </div>\n      )}\n\n      {object?.content && (\n        <div className=\"prose prose-sm max-w-none\">\n          <p className=\"leading-relaxed\">\n            {object.content.split(/(\\[\\d+\\])/).map((part, index) => {\n              const citationMatch = part.match(/\\[(\\d+)\\]/);\n              if (citationMatch) {\n                const citationNumber = citationMatch[1];\n                const citation = object.citations?.find(\n                  (c: any) => c.number === citationNumber\n                );\n\n                if (citation) {\n                  return (\n                    <InlineCitation key={index}>\n                      <InlineCitationCard>\n                        <InlineCitationCardTrigger sources={[citation.url]} />\n                        <InlineCitationCardBody>\n                          <InlineCitationCarousel>\n                            <InlineCitationCarouselHeader>\n                              <InlineCitationCarouselPrev />\n                              <InlineCitationCarouselNext />\n                              <InlineCitationCarouselIndex />\n                            </InlineCitationCarouselHeader>\n                            <InlineCitationCarouselContent>\n                              <InlineCitationCarouselItem>\n                                <InlineCitationSource\n                                  title={citation.title}\n                                  url={citation.url}\n                                  description={citation.description}\n                                />\n                                {citation.quote && (\n                                  <InlineCitationQuote>\n                                    {citation.quote}\n                                  </InlineCitationQuote>\n                                )}\n                              </InlineCitationCarouselItem>\n                            </InlineCitationCarouselContent>\n                          </InlineCitationCarousel>\n                        </InlineCitationCardBody>\n                      </InlineCitationCard>\n                    </InlineCitation>\n                  );\n                }\n              }\n              return part;\n            })}\n          </p>\n        </div>\n      )}\n    </div>\n  );\n};\n\nexport default CitationDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/citation/route.ts\"\nimport { streamObject } from \"ai\";\nimport { z } from \"zod\";\n\nexport const citationSchema = z.object({\n  content: z.string(),\n  citations: z.array(\n    z.object({\n      number: z.string(),\n      title: z.string(),\n      url: z.string(),\n      description: z.string().optional(),\n      quote: z.string().optional(),\n    })\n  ),\n});\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { prompt } = await req.json();\n\n  const result = streamObject({\n    model: \"openai/gpt-4o\",\n    schema: citationSchema,\n    prompt: `Generate a well-researched paragraph about ${prompt} with proper citations. \n    \n    Include:\n    - A comprehensive paragraph with inline citations marked as [1], [2], etc.\n    - 2-3 citations with realistic source information\n    - Each citation should have a title, URL, and optional description/quote\n    - Make the content informative and the sources credible\n    \n    Format citations as numbered references within the text.`,\n  });\n\n  return result.toTextStreamResponse();\n}\n```\n\n## Features\n\n- Hover interaction to reveal detailed citation information\n- **Carousel navigation** for multiple citations with prev/next controls\n- **Live index tracking** showing current slide position (e.g., \"1/5\")\n- Support for source titles, URLs, and descriptions\n- Optional quote blocks for relevant excerpts\n- Composable architecture for flexible citation formats\n- Accessible design with proper keyboard navigation\n- Seamless integration with AI-generated content\n- Clean visual design that doesn't disrupt reading flow\n- Smart badge display showing source hostname and count\n\n## Usage with AI SDK\n\nCurrently, there is no official support for inline citations with Streamdown or the Response component. This is because:\n\n- There isn't any good markdown syntax for inline citations\n- Language models don't naturally respond with inline citation syntax\n- The AI SDK doesn't have built-in support for inline citations\n\n### Potential Approaches\n\nWhile these methods are hypothetical and not officially supported, there are two conceptual ways inline citations could work with Streamdown:\n\n1. **Footnote conversion**: GitHub Flavored Markdown (GFM) handles footnotes using `[^1]` syntax. You could hypothetically remove the default footnote rendering and convert footnotes to inline citations instead.\n\n2. **Custom HTML syntax**: You could add a system prompt instructing the model to use a special HTML syntax like `<citation />` and pass that as a custom component to Streamdown.\n\nThese approaches require custom implementation and are not currently supported out of the box. We will investigate official support for this use case in the future.\n\nFor now, the recommended approach is to use `experimental_useObject` (as shown in the usage example above) to generate structured citation data, then manually parse and render inline citations.\n\n## Props\n\n### `<InlineCitation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root span element. |\n\n### `<InlineCitationText />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying span element. |\n\n### `<InlineCitationCard />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the HoverCard component. |\n\n### `<InlineCitationCardTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `sources` | `string[]` | - | Array of source URLs. The length determines the number displayed in the badge. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying button element. |\n\n### `<InlineCitationCardBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationCarousel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Carousel>` | - | Any other props are spread to the underlying Carousel component. |\n\n### `<InlineCitationCarouselContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying CarouselContent component. |\n\n### `<InlineCitationCarouselItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationCarouselHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationCarouselIndex />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. Children will override the default index display. |\n\n### `<InlineCitationCarouselPrev />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CarouselPrevious>` | - | Any other props are spread to the underlying CarouselPrevious component. |\n\n### `<InlineCitationCarouselNext />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CarouselNext>` | - | Any other props are spread to the underlying CarouselNext component. |\n\n### `<InlineCitationSource />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | - | The title of the source. |\n| `url` | `string` | - | The URL of the source. |\n| `description` | `string` | - | A brief description of the source. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationQuote />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying blockquote element. |\n",".agents/skills/ai-elements/references/jsx-preview.md":"# JSX Preview\n\nA component that dynamically renders JSX strings with streaming support for AI-generated UI.\n\nThe `JSXPreview` component renders JSX strings dynamically, supporting streaming scenarios where JSX may be incomplete. It automatically closes unclosed tags during streaming, making it ideal for displaying AI-generated UI components in real-time.\n\nSee `scripts/jsx-preview.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add jsx-preview\n```\n\n## Features\n\n- Renders JSX strings dynamically using `react-jsx-parser`\n- Streaming support with automatic tag completion\n- Custom component injection for rendering your own components\n- Error handling with customizable error display\n- Context-based architecture for flexible composition\n\n## Usage with AI SDK\n\nThe JSXPreview component integrates with the AI SDK to render generated UI in real-time:\n\n```tsx title=\"components/generated-ui.tsx\"\n\"use client\";\n\nimport {\n  JSXPreview,\n  JSXPreviewContent,\n  JSXPreviewError,\n} from \"@/components/ai-elements/jsx-preview\";\n\ntype GeneratedUIProps = {\n  jsx: string;\n  isStreaming: boolean;\n};\n\nexport const GeneratedUI = ({ jsx, isStreaming }: GeneratedUIProps) => (\n  <JSXPreview\n    jsx={jsx}\n    isStreaming={isStreaming}\n    onError={(error) => console.error(\"JSX Parse Error:\", error)}\n  >\n    <JSXPreviewContent />\n    <JSXPreviewError />\n  </JSXPreview>\n);\n```\n\n### With Custom Components\n\nYou can inject custom components to be used within the rendered JSX:\n\n```tsx title=\"components/generated-ui-with-components.tsx\"\n\"use client\";\n\nimport {\n  JSXPreview,\n  JSXPreviewContent,\n} from \"@/components/ai-elements/jsx-preview\";\nimport { Button } from \"@/components/ui/button\";\nimport { Card } from \"@/components/ui/card\";\n\nconst customComponents = {\n  Button,\n  Card,\n};\n\nexport const GeneratedUIWithComponents = ({ jsx }: { jsx: string }) => (\n  <JSXPreview jsx={jsx} components={customComponents}>\n    <JSXPreviewContent />\n  </JSXPreview>\n);\n```\n\n## Props\n\n### `<JSXPreview />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `jsx` | `string` | Required | The JSX string to render. |\n| `isStreaming` | `boolean` | `false` | When true, automatically completes unclosed tags. |\n| `components` | `Record<string, React.ComponentType>` | - | Custom components available within the rendered JSX. |\n| `bindings` | `Record<string, unknown>` | - | Variables and functions available within the JSX scope. |\n| `onError` | `(error: Error) => void` | - | Callback fired when a parsing or rendering error occurs. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n### `<JSXPreviewContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `renderError` | `JsxParserProps[` | - | Custom error renderer passed to react-jsx-parser. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n### `<JSXPreviewError />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode | ((error: Error) => ReactNode)` | - | Custom error content or render function receiving the error. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n",".agents/skills/ai-elements/references/message.md":"# Message\n\nA comprehensive suite of components for displaying chat messages, including message rendering, branching, actions, and markdown responses.\n\nThe `Message` component suite provides a complete set of tools for building chat interfaces. It includes components for displaying messages from users and AI assistants, managing multiple response branches, adding action buttons, and rendering markdown content.\n\nSee `scripts/message.tsx` for this example.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add message\n```\n\n## Features\n\n- Displays messages from both user and AI assistant with distinct styling and automatic alignment\n- Minimalist flat design with user messages in secondary background and assistant messages full-width\n- **Response branching** with navigation controls to switch between multiple AI response versions\n- **Markdown rendering** with GFM support (tables, task lists, strikethrough), math equations, and smart streaming\n- **Action buttons** for common operations (retry, like, dislike, copy, share) with tooltips and state management\n- **File attachments** display with support for images and generic files with preview and remove functionality\n- Code blocks with syntax highlighting and copy-to-clipboard functionality\n- Keyboard accessible with proper ARIA labels\n- Responsive design that adapts to different screen sizes\n- Seamless light/dark theme integration\n\n\n\n## Usage with AI SDK\n\nBuild a simple chat UI where the user can copy or regenerate the most recent message.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useState } from \"react\";\nimport {\n  MessageActions,\n  MessageAction,\n} from \"@/components/ai-elements/message\";\nimport { Message, MessageContent } from \"@/components/ai-elements/message\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { MessageResponse } from \"@/components/ai-elements/message\";\nimport { RefreshCcwIcon, CopyIcon } from \"lucide-react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport { Fragment } from \"react\";\n\nconst ActionsDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { messages, sendMessage, status, regenerate } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.map((message, messageIndex) => (\n              <Fragment key={message.id}>\n                {message.parts.map((part, i) => {\n                  switch (part.type) {\n                    case \"text\":\n                      const isLastMessage =\n                        messageIndex === messages.length - 1;\n\n                      return (\n                        <Fragment key={`${message.id}-${i}`}>\n                          <Message from={message.role}>\n                            <MessageContent>\n                              <MessageResponse>{part.text}</MessageResponse>\n                            </MessageContent>\n                          </Message>\n                          {message.role === \"assistant\" && isLastMessage && (\n                            <MessageActions>\n                              <MessageAction\n                                onClick={() => regenerate()}\n                                label=\"Retry\"\n                              >\n                                <RefreshCcwIcon className=\"size-3\" />\n                              </MessageAction>\n                              <MessageAction\n                                onClick={() =>\n                                  navigator.clipboard.writeText(part.text)\n                                }\n                                label=\"Copy\"\n                              >\n                                <CopyIcon className=\"size-3\" />\n                              </MessageAction>\n                            </MessageActions>\n                          )}\n                        </Fragment>\n                      );\n                    default:\n                      return null;\n                  }\n                })}\n              </Fragment>\n            ))}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Say something...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ActionsDemo;\n```\n\n## Props\n\n### `<Message />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `from` | `UIMessage[` | - | The role of the message sender ( |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the content div. |\n\n### `<MessageResponse />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The markdown content to render. |\n| `parseIncompleteMarkdown` | `boolean` | `true` | Whether to parse and fix incomplete markdown syntax (e.g., unclosed code blocks or lists). |\n| `className` | `string` | - | CSS class names to apply to the wrapper div element. |\n| `components` | `object` | - | Custom React components to use for rendering markdown elements (e.g., custom heading, paragraph, code block components). |\n| `allowedImagePrefixes` | `string[]` | `[` | Array of allowed URL prefixes for images. Use [ |\n| `allowedLinkPrefixes` | `string[]` | `[` | Array of allowed URL prefixes for links. Use [ |\n| `defaultOrigin` | `string` | - | Default origin to use for relative URLs in links and images. |\n| `rehypePlugins` | `array` | `[rehypeKatex]` | Array of rehype plugins to use for processing HTML. Includes KaTeX for math rendering by default. |\n| `remarkPlugins` | `array` | `[remarkGfm, remarkMath]` | Array of remark plugins to use for processing markdown. Includes GitHub Flavored Markdown and math support by default. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | HTML attributes to spread to the root div. |\n\n### `<MessageAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string` | - | Optional tooltip text shown on hover. |\n| `label` | `string` | - | Accessible label for screen readers. Also used as fallback if tooltip is not provided. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<MessageBranch />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultBranch` | `number` | `0` | The index of the branch to show by default. |\n| `onBranchChange` | `(branchIndex: number) => void` | - | Callback fired when the branch changes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageBranchContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageBranchSelector />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof ButtonGroup>` | - | Any other props are spread to the underlying ButtonGroup component. |\n\n### `<MessageBranchPrevious />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<MessageBranchNext />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<MessageBranchPage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the underlying span element. |\n\n### `<MessageToolbar />`\n\nA container for placing actions and branch selectors below a message. Lays out children in a horizontal row with space-between alignment.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div. |\n```\n",".agents/skills/ai-elements/references/mic-selector.md":"# Mic Selector\n\nA composable dropdown component for selecting audio input devices with permission handling and device change detection.\n\nThe `MicSelector` component provides a flexible and composable interface for selecting microphone input devices. Built on shadcn/ui's Command and Popover components, it features automatic device detection, permission handling, dynamic device list updates, and intelligent device name parsing.\n\nSee `scripts/mic-selector.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add mic-selector\n```\n\n## Features\n\n- Fully composable architecture with granular control components\n- Automatic audio input device enumeration\n- Permission-based device name display\n- Real-time device change detection via devicechange events\n- Intelligent device label parsing with ID extraction\n- Controlled and uncontrolled component patterns\n- Responsive width matching between trigger and content\n- Built on shadcn/ui Command and Popover components\n- Full TypeScript support with proper types for all components\n\n## Props\n\n### `<MicSelector />`\n\nRoot Popover component that provides context for all child components.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultValue` | `string` | - | The default selected device ID (uncontrolled). |\n| `value` | `string` | - | The selected device ID (controlled). |\n| `onValueChange` | `(deviceId: string) => void` | - | Callback fired when the selected device changes. |\n| `defaultOpen` | `boolean` | `false` | The default open state (uncontrolled). |\n| `open` | `boolean` | - | The open state (controlled). |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback fired when the open state changes. Automatically requests microphone permission when opened without permission. |\n| `...props` | `React.ComponentProps<typeof Popover>` | - | Any other props are spread to the Popover component. |\n\n### `<MicSelectorTrigger />`\n\nButton that opens the microphone selector popover. Automatically tracks its width to match the popover content.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component. |\n\n### `<MicSelectorValue />`\n\nDisplays the currently selected microphone name or a placeholder.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<MicSelectorContent />`\n\nContainer for the Command component, rendered inside the popover.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `popoverOptions` | `React.ComponentProps<typeof PopoverContent>` | - | Props to pass to the underlying PopoverContent component. |\n| `...props` | `React.ComponentProps<typeof Command>` | - | Any other props are spread to the Command component. |\n\n### `<MicSelectorInput />`\n\nSearch input for filtering microphones.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the CommandInput component. |\n\n### `<MicSelectorList />`\n\nWrapper for the list of microphone items. Uses render props pattern to provide access to device data.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `(devices: MediaDeviceInfo[]) => ReactNode` | - | Render function that receives the array of available devices. |\n| `...props` | `Omit<React.ComponentProps<typeof CommandList>, ` | - | Any other props are spread to the CommandList component. |\n\n### `<MicSelectorEmpty />`\n\nMessage shown when no microphones match the search.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode` | - | The message to display. |\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the CommandEmpty component. |\n\n### `<MicSelectorItem />`\n\nSelectable item representing a microphone.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The device ID for this item. |\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the CommandItem component. |\n\n### `<MicSelectorLabel />`\n\nDisplays a formatted microphone label with intelligent device ID parsing. Automatically extracts and styles device IDs in the format (XXXX:XXXX).\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `device` | `MediaDeviceInfo` | - | The MediaDeviceInfo object for the device. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n## Hooks\n\n### `useAudioDevices()`\n\nA custom hook for managing audio input devices. This hook is used internally by the `MicSelector` component but can also be used independently.\n\n```tsx\nimport { useAudioDevices } from \"@repo/elements/mic-selector\";\n\nexport default function Example() {\n  const { devices, loading, error, hasPermission, loadDevices } =\n    useAudioDevices();\n\n  return (\n    <div>\n      {loading && <p>Loading devices...</p>}\n      {error && <p>Error: {error}</p>}\n      {devices.map((device) => (\n        <div key={device.deviceId}>{device.label}</div>\n      ))}\n      {!hasPermission && (\n        <button onClick={loadDevices}>Grant Permission</button>\n      )}\n    </div>\n  );\n}\n```\n\n#### Return Value\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `devices` | `MediaDeviceInfo[]` | - | Array of available audio input devices. |\n| `loading` | `boolean` | - | Whether devices are currently being loaded. |\n| `error` | `string | null` | - | Error message if device loading failed. |\n| `hasPermission` | `boolean` | - | Whether microphone permission has been granted. |\n| `loadDevices` | `() => Promise<void>` | - | Function to request microphone permission and load device names. |\n\n## Behavior\n\n### Permission Handling\n\nThe component implements a two-stage permission approach:\n\n1. **Without Permission**: Initially loads devices without requesting permission. Device labels may show as generic names (e.g., \"Microphone 1\").\n2. **With Permission**: When the popover is opened and permission hasn't been granted, automatically requests microphone access and displays actual device names.\n\n### Device Label Parsing\n\nThe `MicSelectorLabel` component intelligently parses device names that include hardware IDs in the format `(XXXX:XXXX)`. It splits the label into the device name and ID, styling the ID with muted text for better readability.\n\nFor example: `\"MacBook Pro Microphone (1a2b:3c4d)\"` becomes:\n\n- Device name: `\"MacBook Pro Microphone\"`\n- Device ID: `\"(1a2b:3c4d)\"` (styled with muted color)\n\n### Width Synchronization\n\nThe `MicSelectorTrigger` uses a ResizeObserver to track its width and automatically synchronizes it with the `MicSelectorContent` popover width for a cohesive appearance.\n\n### Device Change Detection\n\nThe component listens for `devicechange` events (e.g., plugging/unplugging microphones) and automatically updates the device list in real-time.\n\n## Accessibility\n\n- Uses semantic HTML with proper ARIA attributes via shadcn/ui components\n- Full keyboard navigation support through Command component\n- Screen reader friendly with proper labels and roles\n- Searchable device list for quick selection\n\n## Notes\n\n- Requires a secure context (HTTPS or localhost) for microphone access\n- Browser may prompt user for microphone permission on first open\n- Device labels are only fully descriptive after permission is granted\n- Component handles cleanup of temporary media streams during permission requests\n- Uses Radix UI's `useControllableState` for flexible controlled/uncontrolled patterns\n",".agents/skills/ai-elements/references/model-selector.md":"# Model Selector\n\nA searchable command palette for selecting AI models in your chat interface.\n\nThe `ModelSelector` component provides a searchable command palette interface for selecting AI models. It's built on top of the cmdk library and provides a keyboard-navigable interface with search functionality.\n\nSee `scripts/model-selector.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add model-selector\n```\n\n## Features\n\n- Searchable interface with keyboard navigation\n- Fuzzy search filtering across model names\n- Grouped model organization by provider\n- Keyboard shortcuts support\n- Empty state handling\n- Customizable styling with Tailwind CSS\n- Built on cmdk for excellent accessibility\n- TypeScript support with proper type definitions\n\n## Props\n\n### `<ModelSelector />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Dialog>` | - | Any other props are spread to the underlying Dialog component. |\n\n### `<ModelSelectorTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DialogTrigger>` | - | Any other props are spread to the underlying DialogTrigger component. |\n\n### `<ModelSelectorContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `ReactNode` | - | Accessible title for the dialog (rendered in sr-only). |\n| `...props` | `React.ComponentProps<typeof DialogContent>` | - | Any other props are spread to the underlying DialogContent component. |\n\n### `<ModelSelectorDialog />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandDialog>` | - | Any other props are spread to the underlying CommandDialog component. |\n\n### `<ModelSelectorInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the underlying CommandInput component. |\n\n### `<ModelSelectorList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandList>` | - | Any other props are spread to the underlying CommandList component. |\n\n### `<ModelSelectorEmpty />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the underlying CommandEmpty component. |\n\n### `<ModelSelectorGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandGroup>` | - | Any other props are spread to the underlying CommandGroup component. |\n\n### `<ModelSelectorItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the underlying CommandItem component. |\n\n### `<ModelSelectorShortcut />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandShortcut>` | - | Any other props are spread to the underlying CommandShortcut component. |\n\n### `<ModelSelectorSeparator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandSeparator>` | - | Any other props are spread to the underlying CommandSeparator component. |\n\n### `<ModelSelectorLogo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `provider` | `string` | Required | The AI provider name. Supports major providers like  |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the underlying img element (except src and alt which are generated). |\n\n### `<ModelSelectorLogoGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n### `<ModelSelectorName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying span element. |\n",".agents/skills/ai-elements/references/node.md":"# Node\n\nA composable node component for React Flow-based canvases with Card-based styling.\n\nThe `Node` component provides a composable, Card-based node for React Flow canvases. It includes support for connection handles, structured layouts, and consistent styling using shadcn/ui components.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add node\n```\n\n## Features\n\n- Built on shadcn/ui Card components for consistent styling\n- Automatic handle placement (left for target, right for source)\n- Composable sub-components (Header, Title, Description, Action, Content, Footer)\n- Semantic structure for organizing node information\n- Pre-styled sections with borders and backgrounds\n- Responsive sizing with fixed small width\n- Full TypeScript support with proper type definitions\n- Compatible with React Flow's node system\n\n## Props\n\n### `<Node />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `handles` | `unknown` | - | Configuration for connection handles. Target renders on the left, source on the right. |\n| `className` | `string` | - | Additional CSS classes to apply to the node. |\n| `...props` | `ComponentProps<typeof Card>` | - | Any other props are spread to the underlying Card component. |\n\n### `<NodeHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the header. |\n| `...props` | `ComponentProps<typeof CardHeader>` | - | Any other props are spread to the underlying CardHeader component. |\n\n### `<NodeTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof CardTitle>` | - | Any other props are spread to the underlying CardTitle component. |\n\n### `<NodeDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof CardDescription>` | - | Any other props are spread to the underlying CardDescription component. |\n\n### `<NodeAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof CardAction>` | - | Any other props are spread to the underlying CardAction component. |\n\n### `<NodeContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the content. |\n| `...props` | `ComponentProps<typeof CardContent>` | - | Any other props are spread to the underlying CardContent component. |\n\n### `<NodeFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the footer. |\n| `...props` | `ComponentProps<typeof CardFooter>` | - | Any other props are spread to the underlying CardFooter component. |\n",".agents/skills/ai-elements/references/open-in-chat.md":"# Open In Chat\n\nA dropdown menu for opening queries in various AI chat platforms including ChatGPT, Claude, T3, Scira, and v0.\n\nThe `OpenIn` component provides a dropdown menu that allows users to open queries in different AI chat platforms with a single click.\n\nSee `scripts/open-in-chat.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add open-in-chat\n```\n\n## Features\n\n- Pre-configured links to popular AI chat platforms\n- Context-based query passing for cleaner API\n- Customizable dropdown trigger button\n- Automatic URL parameter encoding for queries\n- Support for ChatGPT, Claude, T3 Chat, Scira AI, v0, and Cursor\n- Branded icons for each platform\n- TypeScript support with proper type definitions\n- Accessible dropdown menu with keyboard navigation\n- External link indicators for clarity\n\n## Supported Platforms\n\n- **ChatGPT** - Opens query in OpenAI's ChatGPT with search hints\n- **Claude** - Opens query in Anthropic's Claude AI\n- **T3 Chat** - Opens query in T3 Chat platform\n- **Scira AI** - Opens query in Scira's AI assistant\n- **v0** - Opens query in Vercel's v0 platform\n- **Cursor** - Opens query in Cursor AI editor\n\n## Props\n\n### `<OpenIn />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `query` | `string` | - | The query text to be sent to all AI platforms. |\n| `...props` | `React.ComponentProps<typeof DropdownMenu>` | - | Props to spread to the underlying radix-ui DropdownMenu component. |\n\n### `<OpenInTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom trigger button. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuTrigger>` | - | Props to spread to the underlying DropdownMenuTrigger component. |\n\n### `<OpenInContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the dropdown content. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuContent>` | - | Props to spread to the underlying DropdownMenuContent component. |\n\n### `<OpenInChatGPT />`, `<OpenInClaude />`, `<OpenInT3 />`, `<OpenInScira />`, `<OpenInv0 />`, `<OpenInCursor />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Props to spread to the underlying DropdownMenuItem component. The query is automatically provided via context from the parent OpenIn component. |\n\n### `<OpenInItem />`, `<OpenInLabel />`, `<OpenInSeparator />`\n\nAdditional composable components for custom dropdown menu items, labels, and separators that follow the same props pattern as their underlying radix-ui counterparts.\n",".agents/skills/ai-elements/references/package-info.md":"# Package Info\n\nDisplay dependency information and version changes.\n\nThe `PackageInfo` component displays package dependency information including version changes and change type badges.\n\nSee `scripts/package-info.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add package-info\n```\n\n## Features\n\n- Version change display (current → new)\n- Color-coded change type badges\n- Dependencies list\n- Description support\n\n## Change Types\n\n| Type      | Color  | Use Case           |\n| --------- | ------ | ------------------ |\n| `major`   | Red    | Breaking changes   |\n| `minor`   | Yellow | New features       |\n| `patch`   | Green  | Bug fixes          |\n| `added`   | Blue   | New dependency     |\n| `removed` | Gray   | Removed dependency |\n\n## Props\n\n### `<PackageInfo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | Package name. |\n| `currentVersion` | `string` | - | Current installed version. |\n| `newVersion` | `string` | - | New version being installed. |\n| `changeType` | `unknown` | - | Type of version change. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the header div. |\n\n### `<PackageInfoName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom name content. Defaults to the name from context. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoChangeType />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom change type label. Defaults to the changeType from context. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the Badge component. |\n\n### `<PackageInfoVersion />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom version content. Defaults to version transition display. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Spread to the p element. |\n\n### `<PackageInfoContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoDependencies />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoDependency />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | Dependency name. |\n| `version` | `string` | - | Dependency version. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the row div. |\n",".agents/skills/ai-elements/references/panel.md":"# Panel\n\nA styled panel component for React Flow-based canvases to position custom UI elements.\n\nThe `Panel` component provides a positioned container for custom UI elements on React Flow canvases. It includes modern card styling with backdrop blur and flexible positioning options.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add panel\n```\n\n## Features\n\n- Flexible positioning (top-left, top-right, bottom-left, bottom-right, top-center, bottom-center)\n- Rounded pill design with backdrop blur\n- Theme-aware card background\n- Flexbox layout for easy content alignment\n- Subtle drop shadow for depth\n- Full TypeScript support\n- Compatible with React Flow's panel system\n\n## Props\n\n### `<Panel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `position` | `unknown` | - | Position of the panel on the canvas. |\n| `className` | `string` | - | Additional CSS classes to apply to the panel. |\n| `...props` | `ComponentProps<typeof Panel>` | - | Any other props from @xyflow/react Panel component. |\n",".agents/skills/ai-elements/references/persona.md":"# Persona\n\nAn animated AI visual component powered by Rive that responds to different states like listening, thinking, and speaking.\n\nThe `Persona` component displays an animated AI visual that responds to different conversational states. Built with Rive WebGL2, it provides smooth, high-performance animations for various AI interaction states including idle, listening, thinking, speaking, and asleep. The component supports multiple visual variants to match different design aesthetics.\n\nSee `scripts/persona-obsidian.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add persona\n```\n\n## Features\n\n- Smooth state-based animations powered by Rive\n- Multiple visual variants (obsidian, mana, opal, halo, glint, command)\n- Responsive to five distinct states: idle, listening, thinking, speaking, and asleep\n- WebGL2-accelerated rendering for optimal performance\n- Customizable size and styling\n- Lifecycle callbacks for load, ready, pause, play, and stop events\n- TypeScript support with full type definitions\n\n## Variants\n\nThe Persona component comes with 6 distinct visual variants, each with its own unique aesthetic:\n\n### Obsidian (Default)\n\nSee `scripts/persona-obsidian.tsx` for this example.\n\n### Mana\n\nSee `scripts/persona-mana.tsx` for this example.\n\n### Opal\n\nSee `scripts/persona-opal.tsx` for this example.\n\n### Halo\n\nSee `scripts/persona-halo.tsx` for this example.\n\n### Glint\n\nSee `scripts/persona-glint.tsx` for this example.\n\n### Command\n\nSee `scripts/persona-command.tsx` for this example.\n\n## Props\n\n### `<Persona />`\n\nThe root component that renders the animated AI visual.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `state` | `unknown` | - | The current state of the AI persona. Controls which animation is displayed. |\n| `variant` | `unknown` | - | The visual style variant to display. |\n| `className` | `string` | - | Additional CSS classes to apply to the component. |\n| `onLoad` | `RiveParameters[` | - | Callback fired when the Rive file starts loading. |\n| `onLoadError` | `RiveParameters[` | - | Callback fired if the Rive file fails to load. |\n| `onReady` | `() => void` | - | Callback fired when the Rive animation is ready to play. |\n| `onPause` | `RiveParameters[` | - | Callback fired when the animation is paused. |\n| `onPlay` | `RiveParameters[` | - | Callback fired when the animation starts playing. |\n| `onStop` | `RiveParameters[` | - | Callback fired when the animation is stopped. |\n\n## States\n\nThe Persona component responds to five distinct states, each triggering different animations:\n\n- **idle**: The default resting state when the AI is not active\n- **listening**: Displayed when the AI is actively listening to user input (e.g., during voice recording)\n- **thinking**: Shown when the AI is processing or generating a response\n- **speaking**: Active when the AI is delivering a response (e.g., text-to-speech output)\n- **asleep**: A dormant state for when the AI is inactive or in low-power mode\n\n## React Strict Mode (Vite)\n\nThe Persona component uses WebGL2 for rendering. Browsers limit the number of active WebGL2 contexts (~8–16), and React Strict Mode (enabled by default in Vite dev) double-mounts components, which can exhaust that limit and crash the page.\n\nThe component includes a built-in guard that defers WebGL2 initialization by one frame, preventing context creation during Strict Mode's throw-away mount. This means the component works in Vite dev mode out of the box — no configuration needed.\n\nIf you still experience crashes (for example, when rendering many Persona instances simultaneously), reduce the number of concurrent Persona components on screen.\n\n## Usage Examples\n\n### Basic Usage\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\n\nexport default function App() {\n  return <Persona state=\"listening\" variant=\"opal\" />;\n}\n```\n\n### With State Management\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\nimport { useState } from \"react\";\n\nexport default function App() {\n  const [state, setState] = useState<\n    \"idle\" | \"listening\" | \"thinking\" | \"speaking\" | \"asleep\"\n  >(\"idle\");\n\n  const startListening = () => setState(\"listening\");\n  const startThinking = () => setState(\"thinking\");\n  const startSpeaking = () => setState(\"speaking\");\n  const reset = () => setState(\"idle\");\n\n  return (\n    <div>\n      <Persona state={state} variant=\"opal\" className=\"size-32\" />\n      <div>\n        <button onClick={startListening}>Listen</button>\n        <button onClick={startThinking}>Think</button>\n        <button onClick={startSpeaking}>Speak</button>\n        <button onClick={reset}>Reset</button>\n      </div>\n    </div>\n  );\n}\n```\n\n### With Custom Styling\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\n\nexport default function App() {\n  return (\n    <Persona\n      state=\"thinking\"\n      variant=\"halo\"\n      className=\"size-64 rounded-full border border-border\"\n    />\n  );\n}\n```\n\n### With Lifecycle Callbacks\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\n\nexport default function App() {\n  return (\n    <Persona\n      state=\"listening\"\n      variant=\"glint\"\n      onReady={() => console.log(\"Animation ready\")}\n      onLoad={() => console.log(\"Starting to load\")}\n      onLoadError={(error) => console.error(\"Failed to load:\", error)}\n      onPlay={() => console.log(\"Animation playing\")}\n      onPause={() => console.log(\"Animation paused\")}\n      onStop={() => console.log(\"Animation stopped\")}\n    />\n  );\n}\n```\n",".agents/skills/ai-elements/references/plan.md":"# Plan\n\nA collapsible plan component for displaying AI-generated execution plans with streaming support and shimmer animations.\n\nThe `Plan` component provides a flexible system for displaying AI-generated execution plans with collapsible content. Perfect for showing multi-step workflows, task breakdowns, and implementation strategies with support for streaming content and loading states.\n\nSee `scripts/plan.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add plan\n```\n\n## Features\n\n- Collapsible content with smooth animations\n- Streaming support with shimmer loading states\n- Built on shadcn/ui Card and Collapsible components\n- TypeScript support with comprehensive type definitions\n- Customizable styling with Tailwind CSS\n- Responsive design with mobile-friendly interactions\n- Keyboard navigation and accessibility support\n- Theme-aware with automatic dark mode support\n- Context-based state management for streaming\n\n## Props\n\n### `<Plan />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `isStreaming` | `boolean` | `false` | Whether content is currently streaming. Enables shimmer animations on title and description. |\n| `defaultOpen` | `boolean` | - | Whether the plan is expanded by default. |\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the Collapsible component. |\n\n### `<PlanHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CardHeader>` | - | Any other props are spread to the CardHeader component. |\n\n### `<PlanTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The title text. Displays with shimmer animation when isStreaming is true. |\n| `...props` | `Omit<React.ComponentProps<typeof CardTitle>, ` | - | Any other props (except children) are spread to the CardTitle component. |\n\n### `<PlanDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The description text. Displays with shimmer animation when isStreaming is true. |\n| `...props` | `Omit<React.ComponentProps<typeof CardDescription>, ` | - | Any other props (except children) are spread to the CardDescription component. |\n\n### `<PlanTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. Renders as a Button with chevron icon. |\n\n### `<PlanContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CardContent>` | - | Any other props are spread to the CardContent component. |\n\n### `<PlanFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<PlanAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CardAction>` | - | Any other props are spread to the CardAction component. |\n",".agents/skills/ai-elements/references/prompt-input.md":"# Prompt Input\n\nAllows a user to send a message with file attachments to a large language model. It includes a textarea, file upload capabilities, a submit button, and a dropdown for selecting the model.\n\nThe `PromptInput` component allows a user to send a message with file attachments to a large language model. It includes a textarea, file upload capabilities, a submit button, and a dropdown for selecting the model.\n\nSee `scripts/prompt-input.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add prompt-input\n```\n\n## Usage with AI SDK\n\nBuild a fully functional chat app using `PromptInput`, [`Conversation`](/components/conversation) with a model picker:\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Attachment,\n  AttachmentPreview,\n  AttachmentRemove,\n  Attachments,\n} from \"@/components/ai-elements/attachments\";\nimport {\n  PromptInput,\n  PromptInputActionAddAttachments,\n  PromptInputActionAddScreenshot,\n  PromptInputActionMenu,\n  PromptInputActionMenuContent,\n  PromptInputActionMenuTrigger,\n  PromptInputBody,\n  PromptInputButton,\n  PromptInputHeader,\n  type PromptInputMessage,\n  PromptInputSelect,\n  PromptInputSelectContent,\n  PromptInputSelectItem,\n  PromptInputSelectTrigger,\n  PromptInputSelectValue,\n  PromptInputSubmit,\n  PromptInputTextarea,\n  PromptInputFooter,\n  PromptInputTools,\n  usePromptInputAttachments,\n} from \"@/components/ai-elements/prompt-input\";\nimport { GlobeIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\n\nconst PromptInputAttachmentsDisplay = () => {\n  const attachments = usePromptInputAttachments();\n\n  if (attachments.files.length === 0) {\n    return null;\n  }\n\n  return (\n    <Attachments variant=\"inline\">\n      {attachments.files.map((attachment) => (\n        <Attachment\n          data={attachment}\n          key={attachment.id}\n          onRemove={() => attachments.remove(attachment.id)}\n        >\n          <AttachmentPreview />\n          <AttachmentRemove />\n        </Attachment>\n      ))}\n    </Attachments>\n  );\n};\n\nconst models = [\n  { id: \"gpt-4o\", name: \"GPT-4o\" },\n  { id: \"claude-opus-4-20250514\", name: \"Claude 4 Opus\" },\n];\n\nconst InputDemo = () => {\n  const [text, setText] = useState<string>(\"\");\n  const [model, setModel] = useState<string>(models[0].id);\n  const [useWebSearch, setUseWebSearch] = useState<boolean>(false);\n\n  const { messages, status, sendMessage } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    const hasText = Boolean(message.text);\n    const hasAttachments = Boolean(message.files?.length);\n\n    if (!(hasText || hasAttachments)) {\n      return;\n    }\n\n    sendMessage(\n      {\n        text: message.text || \"Sent with attachments\",\n        files: message.files,\n      },\n      {\n        body: {\n          model: model,\n          webSearch: useWebSearch,\n        },\n      }\n    );\n    setText(\"\");\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.map((message) => (\n              <Message from={message.role} key={message.id}>\n                <MessageContent>\n                  {message.parts.map((part, i) => {\n                    switch (part.type) {\n                      case \"text\":\n                        return (\n                          <MessageResponse key={`${message.id}-${i}`}>\n                            {part.text}\n                          </MessageResponse>\n                        );\n                      default:\n                        return null;\n                    }\n                  })}\n                </MessageContent>\n              </Message>\n            ))}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4\"\n          globalDrop\n          multiple\n        >\n          <PromptInputHeader>\n            <PromptInputAttachmentsDisplay />\n          </PromptInputHeader>\n          <PromptInputBody>\n            <PromptInputTextarea\n              onChange={(e) => setText(e.target.value)}\n              value={text}\n            />\n          </PromptInputBody>\n          <PromptInputFooter>\n            <PromptInputTools>\n              <PromptInputActionMenu>\n                <PromptInputActionMenuTrigger />\n                <PromptInputActionMenuContent>\n                  <PromptInputActionAddAttachments />\n                  <PromptInputActionAddScreenshot />\n                </PromptInputActionMenuContent>\n              </PromptInputActionMenu>\n              <PromptInputButton\n                onClick={() => setUseWebSearch(!useWebSearch)}\n                tooltip={{ content: \"Search the web\", shortcut: \"⌘K\" }}\n                variant={useWebSearch ? \"default\" : \"ghost\"}\n              >\n                <GlobeIcon size={16} />\n                <span>Search</span>\n              </PromptInputButton>\n              <PromptInputSelect\n                onValueChange={(value) => {\n                  setModel(value);\n                }}\n                value={model}\n              >\n                <PromptInputSelectTrigger>\n                  <PromptInputSelectValue />\n                </PromptInputSelectTrigger>\n                <PromptInputSelectContent>\n                  {models.map((model) => (\n                    <PromptInputSelectItem key={model.id} value={model.id}>\n                      {model.name}\n                    </PromptInputSelectItem>\n                  ))}\n                </PromptInputSelectContent>\n              </PromptInputSelect>\n            </PromptInputTools>\n            <PromptInputSubmit disabled={!text && !status} status={status} />\n          </PromptInputFooter>\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default InputDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/chat/route.ts\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const {\n    model,\n    messages,\n    webSearch,\n  }: {\n    messages: UIMessage[];\n    model: string;\n    webSearch?: boolean;\n  } = await req.json();\n\n  const result = streamText({\n    model: webSearch ? \"perplexity/sonar\" : model,\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Auto-resizing textarea that adjusts height based on content\n- File attachment support with drag-and-drop\n- Built-in screenshot capture action\n- Image preview for image attachments\n- Configurable file constraints (max files, max size, accepted types)\n- Automatic submit button icons based on status\n- Support for keyboard shortcuts (Enter to submit, Shift+Enter for new line)\n- Customizable min/max height for the textarea\n- Flexible toolbar with support for custom actions and tools\n- Built-in model selection dropdown\n- Built-in native speech recognition button (Web Speech API)\n- Optional provider for lifted state management\n- Form automatically resets on submit\n- Responsive design with mobile-friendly controls\n- Clean, modern styling with customizable themes\n- Form-based submission handling\n- Hidden file input sync for native form posts\n- Global document drop support (opt-in)\n\n## Examples\n\n### Cursor style\n\nSee `scripts/prompt-input-cursor.tsx` for this example.\n\n### Button tooltips\n\nButtons can display tooltips with optional keyboard shortcut hints. Hover over the buttons below to see the tooltips.\n\nSee `scripts/prompt-input-tooltip.tsx` for this example.\n\n## Props\n\n### `<PromptInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onSubmit` | `(message: PromptInputMessage, event: FormEvent) => void` | - | Handler called when the form is submitted with message text and files. |\n| `accept` | `string` | - | File types to accept (e.g.,  |\n| `multiple` | `boolean` | - | Whether to allow multiple file selection. |\n| `globalDrop` | `boolean` | - | When true, accepts file drops anywhere on the document. |\n| `syncHiddenInput` | `boolean` | - | Render a hidden input with given name for native form posts. |\n| `maxFiles` | `number` | - | Maximum number of files allowed. |\n| `maxFileSize` | `number` | - | Maximum file size in bytes. |\n| `onError` | `(err: { code: ` | - | Handler for file validation errors. |\n| `...props` | `React.HTMLAttributes<HTMLFormElement>` | - | Any other props are spread to the root form element. |\n\n### `<PromptInputTextarea />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Textarea>` | - | Any other props are spread to the underlying Textarea component. |\n\n### `<PromptInputFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the toolbar div. |\n\n### `<PromptInputTools />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the tools div. |\n\n### `<PromptInputButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string | { content: ReactNode; shortcut?: string; side?: ` | - | Optional tooltip to display on hover. Can be a string or an object with content, shortcut, and side properties. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n#### Tooltip Examples\n\n```tsx\n// Simple string tooltip\n<PromptInputButton tooltip=\"Search the web\">\n  <GlobeIcon size={16} />\n</PromptInputButton>\n\n// Tooltip with keyboard shortcut hint\n<PromptInputButton tooltip={{ content: \"Search\", shortcut: \"⌘K\" }}>\n  <GlobeIcon size={16} />\n</PromptInputButton>\n\n// Tooltip with custom position\n<PromptInputButton tooltip={{ content: \"Search\", side: \"bottom\" }}>\n  <GlobeIcon size={16} />\n</PromptInputButton>\n```\n\n### `<PromptInputSubmit />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `status` | `ChatStatus` | - | Current chat status to determine button icon (submitted, streaming, error). |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<PromptInputSelect />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Select>` | - | Any other props are spread to the underlying Select component. |\n\n### `<PromptInputSelectTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof SelectTrigger>` | - | Any other props are spread to the underlying SelectTrigger component. |\n\n### `<PromptInputSelectContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof SelectContent>` | - | Any other props are spread to the underlying SelectContent component. |\n\n### `<PromptInputSelectItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof SelectItem>` | - | Any other props are spread to the underlying SelectItem component. |\n\n### `<PromptInputSelectValue />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof SelectValue>` | - | Any other props are spread to the underlying SelectValue component. |\n\n### `<PromptInputBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the body div. |\n\n### Attachments\n\nAttachment components have been moved to a separate module. See the [Attachment](/components/attachment) component documentation for details on `<Attachments />`, `<Attachment />`, `<AttachmentPreview />`, `<AttachmentInfo />`, and `<AttachmentRemove />`.\n\n### `<PromptInputActionMenu />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenu>` | - | Any other props are spread to the underlying DropdownMenu component. |\n\n### `<PromptInputActionMenuTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying Button component. |\n\n### `<PromptInputActionMenuContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenuContent>` | - | Any other props are spread to the underlying DropdownMenuContent component. |\n\n### `<PromptInputActionMenuItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Any other props are spread to the underlying DropdownMenuItem component. |\n\n### `<PromptInputActionAddAttachments />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | Label for the menu item. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Any other props are spread to the underlying DropdownMenuItem component. |\n\n### `<PromptInputActionAddScreenshot />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | Label for the menu item. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Any other props are spread to the underlying DropdownMenuItem component. |\n\n### `<PromptInputProvider />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `initialInput` | `string` | - | Initial text input value. |\n| `children` | `React.ReactNode` | - | Child components that will have access to the provider context. |\n\nOptional global provider that lifts PromptInput state outside of PromptInput. When used, it allows you to access and control the input state from anywhere within the provider tree. If not used, PromptInput stays fully self-managed.\n\n### `<PromptInputHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `Omit<React.ComponentProps<typeof InputGroupAddon>, ` | - | Any other props (except align) are spread to the InputGroupAddon component. |\n\n### `<PromptInputHoverCard />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `openDelay` | `number` | `0` | Delay in milliseconds before opening. |\n| `closeDelay` | `number` | `0` | Delay in milliseconds before closing. |\n| `...props` | `React.ComponentProps<typeof HoverCard>` | - | Any other props are spread to the HoverCard component. |\n\n### `<PromptInputHoverCardTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof HoverCardTrigger>` | - | Any other props are spread to the HoverCardTrigger component. |\n\n### `<PromptInputHoverCardContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `align` | `unknown` | - | Alignment of the hover card content. |\n| `...props` | `React.ComponentProps<typeof HoverCardContent>` | - | Any other props are spread to the HoverCardContent component. |\n\n### `<PromptInputTabsList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<PromptInputTab />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<PromptInputTabLabel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLHeadingElement>` | - | Any other props are spread to the h3 element. |\n\n### `<PromptInputTabBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<PromptInputTabItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<PromptInputCommand />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Command>` | - | Any other props are spread to the Command component. |\n\n### `<PromptInputCommandInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the CommandInput component. |\n\n### `<PromptInputCommandList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandList>` | - | Any other props are spread to the CommandList component. |\n\n### `<PromptInputCommandEmpty />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the CommandEmpty component. |\n\n### `<PromptInputCommandGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandGroup>` | - | Any other props are spread to the CommandGroup component. |\n\n### `<PromptInputCommandItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the CommandItem component. |\n\n### `<PromptInputCommandSeparator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandSeparator>` | - | Any other props are spread to the CommandSeparator component. |\n\n## Hooks\n\n### `usePromptInputAttachments`\n\nAccess and manage file attachments within a PromptInput context.\n\n```tsx\nconst attachments = usePromptInputAttachments();\n\n// Available methods:\nattachments.files; // Array of current attachments\nattachments.add(files); // Add new files\nattachments.remove(id); // Remove an attachment by ID\nattachments.clear(); // Clear all attachments\nattachments.openFileDialog(); // Open file selection dialog\n```\n\n### `usePromptInputController`\n\nAccess the full PromptInput controller from a PromptInputProvider. Only available when using the provider.\n\n```tsx\nconst controller = usePromptInputController();\n\n// Available methods:\ncontroller.textInput.value; // Current text input value\ncontroller.textInput.setInput(value); // Set text input value\ncontroller.textInput.clear(); // Clear text input\ncontroller.attachments; // Same as usePromptInputAttachments\n```\n\n### `useProviderAttachments`\n\nAccess attachments context from a PromptInputProvider. Only available when using the provider.\n\n```tsx\nconst attachments = useProviderAttachments();\n\n// Same interface as usePromptInputAttachments\n```\n\n### `usePromptInputReferencedSources`\n\nAccess referenced sources context within a PromptInput.\n\n```tsx\nconst sources = usePromptInputReferencedSources();\n\n// Available methods:\nsources.sources; // Array of current referenced sources\nsources.add(sources); // Add new source(s)\nsources.remove(id); // Remove a source by ID\nsources.clear(); // Clear all sources\n```\n",".agents/skills/ai-elements/references/queue.md":"# Queue\n\nA comprehensive queue component system for displaying message lists, todos, and collapsible task sections in AI applications.\n\nThe `Queue` component provides a flexible system for displaying lists of messages, todos, attachments, and collapsible sections. Perfect for showing AI workflow progress, pending tasks, message history, or any structured list of items in your application.\n\nSee `scripts/queue.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add queue\n```\n\n## Features\n\n- Flexible component system with composable parts\n- Collapsible sections with smooth animations\n- Support for completed/pending state indicators\n- Built-in scroll area for long lists\n- Attachment display with images and file indicators\n- Hover-revealed action buttons for queue items\n- TypeScript support with comprehensive type definitions\n- Customizable styling with Tailwind CSS\n- Responsive design with mobile-friendly interactions\n- Keyboard navigation and accessibility support\n- Theme-aware with automatic dark mode support\n\n## Examples\n\n### With PromptInput\n\nSee `scripts/queue-prompt-input.tsx` for this example.\n\n## Props\n\n### `<Queue />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div. |\n\n### `<QueueSection />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultOpen` | `boolean` | `true` | Whether the section is open by default. |\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the Collapsible component. |\n\n### `<QueueSectionTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the button element. |\n\n### `<QueueSectionLabel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | The label text to display. |\n| `count` | `number` | - | The count to display before the label. |\n| `icon` | `React.ReactNode` | - | An optional icon to display before the count. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<QueueSectionContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent component. |\n\n### `<QueueList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof ScrollArea>` | - | Any other props are spread to the ScrollArea component. |\n\n### `<QueueItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the li element. |\n\n### `<QueueItemIndicator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `completed` | `boolean` | `false` | Whether the item is completed. Affects the indicator styling. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<QueueItemContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `completed` | `boolean` | `false` | Whether the item is completed. Affects text styling with strikethrough and opacity. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<QueueItemDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `completed` | `boolean` | `false` | Whether the item is completed. Affects text styling. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<QueueItemActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<QueueItemAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `Omit<React.ComponentProps<typeof Button>, ` | - | Any other props (except variant and size) are spread to the Button component. |\n\n### `<QueueItemAttachment />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<QueueItemImage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the img element. |\n\n### `<QueueItemFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n## Type Exports\n\n### `QueueMessagePart`\n\nInterface for message parts within queue messages.\n\n```tsx\ninterface QueueMessagePart {\n  type: string;\n  text?: string;\n  url?: string;\n  filename?: string;\n  mediaType?: string;\n}\n```\n\n### `QueueMessage`\n\nInterface for queue message items.\n\n```tsx\ninterface QueueMessage {\n  id: string;\n  parts: QueueMessagePart[];\n}\n```\n\n### `QueueTodo`\n\nInterface for todo items in the queue.\n\n```tsx\ninterface QueueTodo {\n  id: string;\n  title: string;\n  description?: string;\n  status?: \"pending\" | \"completed\";\n}\n```\n",".agents/skills/ai-elements/references/reasoning.md":"# Reasoning\n\nA collapsible component that displays AI reasoning content, automatically opening during streaming and closing when finished.\n\nThe `Reasoning` component displays AI reasoning content, automatically opening during streaming and closing when finished.\n\nSee `scripts/reasoning.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add reasoning\n```\n\n## Usage with AI SDK\n\nBuild a chatbot with reasoning using Deepseek R1 or other reasoning models.\n\nSome models (like GPT with high reasoning effort) return multiple reasoning parts instead of a single streaming block. The example below consolidates all reasoning parts into a single component to avoid displaying multiple \"Thinking...\" indicators.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Reasoning,\n  ReasoningContent,\n  ReasoningTrigger,\n} from \"@/components/ai-elements/reasoning\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { Spinner } from \"@/components/ui/spinner\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport type { UIMessage } from \"ai\";\n\nconst MessageParts = ({\n  message,\n  isLastMessage,\n  isStreaming,\n}: {\n  message: UIMessage;\n  isLastMessage: boolean;\n  isStreaming: boolean;\n}) => {\n  // Consolidate all reasoning parts into one block\n  const reasoningParts = message.parts.filter(\n    (part) => part.type === \"reasoning\"\n  );\n  const reasoningText = reasoningParts.map((part) => part.text).join(\"\\n\\n\");\n  const hasReasoning = reasoningParts.length > 0;\n\n  // Check if reasoning is still streaming (last part is reasoning on last message)\n  const lastPart = message.parts.at(-1);\n  const isReasoningStreaming =\n    isLastMessage && isStreaming && lastPart?.type === \"reasoning\";\n\n  return (\n    <>\n      {hasReasoning && (\n        <Reasoning className=\"w-full\" isStreaming={isReasoningStreaming}>\n          <ReasoningTrigger />\n          <ReasoningContent>{reasoningText}</ReasoningContent>\n        </Reasoning>\n      )}\n      {message.parts.map((part, i) => {\n        if (part.type === \"text\") {\n          return (\n            <MessageResponse key={`${message.id}-${i}`}>\n              {part.text}\n            </MessageResponse>\n          );\n        }\n        return null;\n      })}\n    </>\n  );\n};\n\nconst ReasoningDemo = () => {\n  const [input, setInput] = useState(\"\");\n\n  const { messages, sendMessage, status } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    sendMessage({ text: message.text });\n    setInput(\"\");\n  };\n\n  const isStreaming = status === \"streaming\";\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.map((message, index) => (\n              <Message from={message.role} key={message.id}>\n                <MessageContent>\n                  <MessageParts\n                    message={message}\n                    isLastMessage={index === messages.length - 1}\n                    isStreaming={isStreaming}\n                  />\n                </MessageContent>\n              </Message>\n            ))}\n            {status === \"submitted\" && <Spinner />}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Say something...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={isStreaming ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ReasoningDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/chat/route.ts\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { model, messages }: { messages: UIMessage[]; model: string } =\n    await req.json();\n\n  const result = streamText({\n    model: \"deepseek/deepseek-r1\",\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse({\n    sendReasoning: true,\n  });\n}\n```\n\n## Reasoning vs Chain of Thought\n\nUse the `Reasoning` component when your model outputs thinking content as a single block or continuous stream (Deepseek R1, Claude with extended thinking, etc.).\n\nIf your model outputs discrete, labeled steps (search queries, tool calls, distinct thought stages), consider using the [Chain of Thought](/components/chain-of-thought) component instead for a more structured visual representation.\n\n## Features\n\n- Automatically opens when streaming content and closes when finished\n- Manual toggle control for user interaction\n- Smooth animations and transitions powered by Radix UI\n- Visual streaming indicator with pulsing animation\n- Composable architecture with separate trigger and content components\n- Built with accessibility in mind including keyboard navigation\n- Responsive design that works across different screen sizes\n- Seamlessly integrates with both light and dark themes\n- Built on top of shadcn/ui Collapsible primitives\n- TypeScript support with proper type definitions\n\n## Props\n\n### `<Reasoning />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `isStreaming` | `boolean` | `false` | Whether the reasoning is currently streaming (auto-opens and closes the panel). |\n| `open` | `boolean` | - | Controlled open state. |\n| `defaultOpen` | `boolean` | `true` | Default open state when uncontrolled. |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback when open state changes. |\n| `duration` | `number` | - | Duration in seconds to display (can be controlled externally). |\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the underlying Collapsible component. |\n\n### `<ReasoningTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `getThinkingMessage` | `(isStreaming: boolean, duration?: number) => ReactNode` | - | Optional function to customize the thinking message. Receives isStreaming and duration parameters. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the underlying CollapsibleTrigger component. |\n\n### `<ReasoningContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | Required | The reasoning text to display (rendered via Streamdown). |\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the underlying CollapsibleContent component. |\n\n## Hooks\n\n### `useReasoning`\n\nAccess the reasoning context from child components.\n\n```tsx\nconst { isStreaming, isOpen, setIsOpen, duration } = useReasoning();\n```\n\nReturns:\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `isStreaming` | `boolean` | - | Whether reasoning is currently streaming. |\n| `isOpen` | `boolean` | - | Whether the reasoning panel is open. |\n| `setIsOpen` | `(open: boolean) => void` | - | Function to set the open state. |\n| `duration` | `number | undefined` | - | Duration in seconds (undefined while streaming). |\n",".agents/skills/ai-elements/references/sandbox.md":"# Sandbox\n\nA collapsible container for displaying AI-generated code and output in chat interfaces.\n\nThe `Sandbox` component provides a structured way to display AI-generated code alongside its execution output in chat conversations. It features a collapsible container with status indicators and tabbed navigation between code and output views. It's designed to be used with `CodeBlock` for displaying code and `StackTrace` for displaying errors.\n\nSee `scripts/sandbox.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add sandbox\n```\n\n## Features\n\n- Collapsible container with smooth animations\n- Status badges showing execution state (Pending, Running, Completed, Error)\n- Tabs for Code and Output views\n- Syntax-highlighted code display\n- Copy button for easy code sharing\n- Works with AI SDK tool state patterns\n\n## Usage with AI SDK\n\nThe Sandbox component integrates with the AI SDK's tool state to show code generation progress:\n\n```tsx title=\"components/code-sandbox.tsx\"\n\"use client\";\n\nimport type { ToolUIPart } from \"ai\";\nimport {\n  Sandbox,\n  SandboxContent,\n  SandboxHeader,\n  SandboxTabContent,\n  SandboxTabs,\n  SandboxTabsBar,\n  SandboxTabsList,\n  SandboxTabsTrigger,\n} from \"@/components/ai-elements/sandbox\";\nimport { CodeBlock } from \"@/components/ai-elements/code-block\";\n\ntype CodeSandboxProps = {\n  toolPart: ToolUIPart;\n};\n\nexport const CodeSandbox = ({ toolPart }: CodeSandboxProps) => {\n  const code = toolPart.input?.code ?? \"\";\n  const output = toolPart.output?.logs ?? \"\";\n\n  return (\n    <Sandbox>\n      <SandboxHeader\n        state={toolPart.state}\n        title={toolPart.input?.filename ?? \"code.tsx\"}\n      />\n      <SandboxContent>\n        <SandboxTabs defaultValue=\"code\">\n          <SandboxTabsBar>\n            <SandboxTabsList>\n              <SandboxTabsTrigger value=\"code\">Code</SandboxTabsTrigger>\n              <SandboxTabsTrigger value=\"output\">Output</SandboxTabsTrigger>\n            </SandboxTabsList>\n          </SandboxTabsBar>\n          <SandboxTabContent value=\"code\">\n            <CodeBlock code={code} language=\"tsx\" />\n          </SandboxTabContent>\n          <SandboxTabContent value=\"output\">\n            <CodeBlock code={output} language=\"log\" />\n          </SandboxTabContent>\n        </SandboxTabs>\n      </SandboxContent>\n    </Sandbox>\n  );\n};\n```\n\n## Props\n\n### `<Sandbox />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the underlying Collapsible component. |\n\n### `<SandboxHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | `undefined` | The title displayed in the header (e.g., filename). |\n| `state` | `ToolUIPart[` | Required | The current execution state, used to display the appropriate status badge. |\n| `className` | `string` | - | Additional CSS classes for the header. |\n\n### `<SandboxContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent. |\n\n### `<SandboxTabs />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Tabs>` | - | Any other props are spread to the underlying Tabs component. |\n\n### `<SandboxTabsBar />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n\n### `<SandboxTabsList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof TabsList>` | - | Any other props are spread to the underlying TabsList component. |\n\n### `<SandboxTabsTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof TabsTrigger>` | - | Any other props are spread to the underlying TabsTrigger component. |\n\n### `<SandboxTabContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof TabsContent>` | - | Any other props are spread to the underlying TabsContent component. |\n",".agents/skills/ai-elements/references/schema-display.md":"# Schema Display\n\nDisplay REST API endpoint documentation with parameters, request/response bodies.\n\nThe `SchemaDisplay` component visualizes REST API endpoints with HTTP methods, paths, parameters, and request/response schemas.\n\nSee `scripts/schema-display.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add schema-display\n```\n\n## Features\n\n- Color-coded HTTP methods\n- Path parameter highlighting\n- Collapsible parameters section\n- Request/response body schemas\n- Nested object property display\n- Required field indicators\n\n## Method Colors\n\n| Method   | Color  |\n| -------- | ------ |\n| `GET`    | Green  |\n| `POST`   | Blue   |\n| `PUT`    | Orange |\n| `PATCH`  | Yellow |\n| `DELETE` | Red    |\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/schema-display-basic.tsx` for this example.\n\n### With Parameters\n\nSee `scripts/schema-display-params.tsx` for this example.\n\n### With Request/Response Bodies\n\nSee `scripts/schema-display-body.tsx` for this example.\n\n### Nested Properties\n\nSee `scripts/schema-display-nested.tsx` for this example.\n\n## Props\n\n### `<SchemaDisplay />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `method` | `unknown` | - | HTTP method. |\n| `path` | `string` | - | API endpoint path. |\n| `description` | `string` | - | Endpoint description. |\n| `parameters` | `SchemaParameter[]` | - | URL/query parameters. |\n| `requestBody` | `SchemaProperty[]` | - | Request body properties. |\n| `responseBody` | `SchemaProperty[]` | - | Response body properties. |\n\n### `SchemaParameter`\n\n```tsx\ninterface SchemaParameter {\n  name: string;\n  type: string;\n  required?: boolean;\n  description?: string;\n  location?: \"path\" | \"query\" | \"header\";\n}\n```\n\n### `SchemaProperty`\n\n```tsx\ninterface SchemaProperty {\n  name: string;\n  type: string;\n  required?: boolean;\n  description?: string;\n  properties?: SchemaProperty[]; // For objects\n  items?: SchemaProperty; // For arrays\n}\n```\n\n### Subcomponents\n\n- `SchemaDisplayHeader` - Header container\n- `SchemaDisplayMethod` - Color-coded method badge\n- `SchemaDisplayPath` - Path with highlighted parameters\n- `SchemaDisplayDescription` - Description text\n- `SchemaDisplayContent` - Content container\n- `SchemaDisplayParameters` - Collapsible parameters section\n- `SchemaDisplayParameter` - Individual parameter\n- `SchemaDisplayRequest` - Collapsible request body\n- `SchemaDisplayResponse` - Collapsible response body\n- `SchemaDisplayProperty` - Schema property (recursive)\n- `SchemaDisplayExample` - Code example block\n",".agents/skills/ai-elements/references/shimmer.md":"# Shimmer\n\nAn animated text shimmer component for creating eye-catching loading states and progressive reveal effects.\n\nThe `Shimmer` component provides an animated shimmer effect that sweeps across text, perfect for indicating loading states, progressive reveals, or drawing attention to dynamic content in AI applications.\n\nSee `scripts/shimmer.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add shimmer\n```\n\n## Features\n\n- Smooth animated shimmer effect using CSS gradients and Framer Motion\n- Customizable animation duration and spread\n- Polymorphic component - render as any HTML element via the `as` prop\n- Automatic spread calculation based on text length\n- Theme-aware styling using CSS custom properties\n- Infinite looping animation with linear easing\n- TypeScript support with proper type definitions\n- Memoized for optimal performance\n- Responsive and accessible design\n- Uses `text-transparent` with background-clip for crisp text rendering\n\n## Examples\n\n### Different Durations\n\nSee `scripts/shimmer-duration.tsx` for this example.\n\n### Custom Elements\n\nSee `scripts/shimmer-elements.tsx` for this example.\n\n## Props\n\n### `<Shimmer />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The text content to apply the shimmer effect to. |\n| `as` | `ElementType` | - | The HTML element or React component to render. |\n| `className` | `string` | - | Additional CSS classes to apply to the component. |\n| `duration` | `number` | `2` | The duration of the shimmer animation in seconds. |\n| `spread` | `number` | `2` | The spread multiplier for the shimmer gradient, multiplied by text length. |\n",".agents/skills/ai-elements/references/snippet.md":"# Snippet\n\nLightweight inline code display for terminal commands and short code references.\n\nThe `Snippet` component provides a lightweight way to display terminal commands and short code snippets with copy functionality. Built on top of InputGroup, it's designed for brief code references in text.\n\nSee `scripts/snippet.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add snippet\n```\n\n## Features\n\n- Composable architecture with InputGroup\n- Optional prefix text (e.g., `$` for terminal commands)\n- Built-in copy button\n- Compact design for chat/markdown\n\n## Examples\n\n### Without Prefix\n\nSee `scripts/snippet-plain.tsx` for this example.\n\n## Props\n\n### `<Snippet />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `code` | `string` | Required | The code content to display. |\n| `children` | `React.ReactNode` | - | Child elements like SnippetAddon, SnippetInput, etc. |\n| `...props` | `React.ComponentProps<typeof InputGroup>` | - | Spread to the InputGroup component. |\n\n### `<SnippetAddon />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof InputGroupAddon>` | - | Spread to the InputGroupAddon component. |\n\n### `<SnippetText />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof InputGroupText>` | - | Spread to the InputGroupText component. |\n\n### `<SnippetInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `Omit<React.ComponentProps<typeof InputGroupInput>, ` | - | Spread to the InputGroupInput component. Value and readOnly are set automatically. |\n\n### `<SnippetCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback fired after a successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback fired if copying fails. |\n| `timeout` | `number` | `2000` | How long to show the copied state (ms). |\n| `children` | `React.ReactNode` | - | Custom button content. |\n| `...props` | `React.ComponentProps<typeof InputGroupButton>` | - | Spread to the InputGroupButton component. |\n",".agents/skills/ai-elements/references/sources.md":"# Sources\n\nA component that allows a user to view the sources or citations used to generate a response.\n\nThe `Sources` component allows a user to view the sources or citations used to generate a response.\n\nSee `scripts/sources.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add sources\n```\n\n## Usage with AI SDK\n\nBuild a simple web search agent with Perplexity Sonar.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  Source,\n  Sources,\n  SourcesContent,\n  SourcesTrigger,\n} from \"@/components/ai-elements/sources\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport { useState } from \"react\";\nimport { DefaultChatTransport } from \"ai\";\n\nconst SourceDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { messages, sendMessage, status } = useChat({\n    transport: new DefaultChatTransport({\n      api: \"/api/sources\",\n    }),\n  });\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex-1 overflow-auto mb-4\">\n          <Conversation>\n            <ConversationContent>\n              {messages.map((message) => (\n                <div key={message.id}>\n                  {message.role === \"assistant\" && (\n                    <Sources>\n                      <SourcesTrigger\n                        count={\n                          message.parts.filter(\n                            (part) => part.type === \"source-url\"\n                          ).length\n                        }\n                      />\n                      {message.parts.map((part, i) => {\n                        switch (part.type) {\n                          case \"source-url\":\n                            return (\n                              <SourcesContent key={`${message.id}-${i}`}>\n                                <Source\n                                  key={`${message.id}-${i}`}\n                                  href={part.url}\n                                  title={part.url}\n                                />\n                              </SourcesContent>\n                            );\n                        }\n                      })}\n                    </Sources>\n                  )}\n                  <Message from={message.role} key={message.id}>\n                    <MessageContent>\n                      {message.parts.map((part, i) => {\n                        switch (part.type) {\n                          case \"text\":\n                            return (\n                              <MessageResponse key={`${message.id}-${i}`}>\n                                {part.text}\n                              </MessageResponse>\n                            );\n                          default:\n                            return null;\n                        }\n                      })}\n                    </MessageContent>\n                  </Message>\n                </div>\n              ))}\n            </ConversationContent>\n            <ConversationScrollButton />\n          </Conversation>\n        </div>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Ask a question and search the...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default SourceDemo;\n```\n\nAdd the following route to your backend:\n\n```tsx title=\"api/chat/route.ts\"\nimport { convertToModelMessages, streamText, UIMessage } from \"ai\";\nimport { perplexity } from \"@ai-sdk/perplexity\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"perplexity/sonar\",\n    system:\n      \"You are a helpful assistant. Keep your responses short (< 100 words) unless you are asked for more details. ALWAYS USE SEARCH.\",\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse({\n    sendSources: true,\n  });\n}\n```\n\n## Features\n\n- Collapsible component that allows a user to view the sources or citations used to generate a response\n- Customizable trigger and content components\n- Support for custom sources or citations\n- Responsive design with mobile-friendly controls\n- Clean, modern styling with customizable themes\n\n## Examples\n\n### Custom rendering\n\nSee `scripts/sources-custom.tsx` for this example.\n\n## Props\n\n### `<Sources />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<SourcesTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `count` | `number` | Required | The number of sources to display in the trigger. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<SourcesContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the content container. |\n\n### `<Source />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.AnchorHTMLAttributes<HTMLAnchorElement>` | - | Any other props are spread to the anchor element. |\n",".agents/skills/ai-elements/references/speech-input.md":"# Speech Input\n\nA button component that captures voice input and converts it to text, with cross-browser support.\n\nThe `SpeechInput` component provides an easy-to-use interface for capturing voice input in your application. It uses the Web Speech API for real-time transcription in supported browsers (Chrome, Edge), and falls back to MediaRecorder with an external transcription service for browsers that don't support Web Speech API (Firefox, Safari).\n\nSee `scripts/speech-input.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add speech-input\n```\n\n## Features\n\n- Built on Web Speech API (SpeechRecognition) with MediaRecorder fallback\n- Cross-browser support (Chrome, Edge, Firefox, Safari)\n- Continuous speech recognition with interim results\n- Visual feedback with pulse animation when listening\n- Loading state during transcription processing\n- Automatic browser compatibility detection\n- Final transcript extraction and callbacks\n- Error handling and automatic state management\n- Extends shadcn/ui Button component\n- Full TypeScript support\n\n## Props\n\n### `<SpeechInput />`\n\nThe component extends the shadcn/ui Button component, so all Button props are available.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onTranscriptionChange` | `(text: string) => void` | - | Callback fired when final transcription text is available. Only fires for completed phrases, not interim results. |\n| `onAudioRecorded` | `(audioBlob: Blob) => Promise<string>` | - | Callback for MediaRecorder fallback. Required for Firefox/Safari support. Receives recorded audio blob and should return transcribed text from an external service (e.g., OpenAI Whisper). |\n| `lang` | `string` | - | Language for speech recognition. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component, including variant, size, disabled, etc. |\n\n## Behavior\n\n### Speech Recognition Modes\n\nThe component automatically detects browser capabilities and uses the best available method:\n\n| Browser         | Mode           | Behavior                                               |\n| --------------- | -------------- | ------------------------------------------------------ |\n| Chrome, Edge    | Web Speech API | Real-time transcription, no server required            |\n| Firefox, Safari | MediaRecorder  | Records audio, sends to external transcription service |\n| Unsupported     | Disabled       | Button is disabled                                     |\n\n### Web Speech API Mode (Chrome, Edge)\n\nUses the Web Speech API with the following configuration:\n\n- **Continuous**: Set to `true` to keep recognition active until manually stopped\n- **Interim Results**: Set to `true` to receive partial results during speech\n- **Language**: Configurable via `lang` prop, defaults to `\"en-US\"`\n\n### MediaRecorder Mode (Firefox, Safari)\n\nWhen the Web Speech API is unavailable, the component falls back to recording audio:\n\n1. Records audio using `MediaRecorder` API\n2. On stop, creates an audio blob (`audio/webm`)\n3. Calls `onAudioRecorded` with the blob\n4. Waits for transcription result\n5. Passes result to `onTranscriptionChange`\n\n**Note**: The `onAudioRecorded` prop is required for this mode to work. Without it, the button will be disabled in Firefox/Safari.\n\n### Transcription Processing\n\nThe component only calls `onTranscriptionChange` with **final transcripts**. Interim results (Web Speech API) are ignored to prevent incomplete text from being processed.\n\n### Visual States\n\n- **Default State**: Standard button appearance with microphone icon\n- **Listening State**: Pulsing animation with accent colors to indicate active listening\n- **Processing State**: Loading spinner while waiting for transcription (MediaRecorder mode)\n- **Disabled State**: Button is disabled when no API is available or required props are missing\n\n### Lifecycle\n\n1. **Mount**: Detects available APIs and initializes appropriate mode\n2. **Click**: Toggles between listening/recording and stopped states\n3. **Stop (MediaRecorder)**: Processes audio and waits for transcription\n4. **Unmount**: Stops recognition/recording and releases microphone\n\n## Browser Support\n\nThe component provides cross-browser support through a two-tier system:\n\n| Browser | API Used       | Requirements           |\n| ------- | -------------- | ---------------------- |\n| Chrome  | Web Speech API | None                   |\n| Edge    | Web Speech API | None                   |\n| Firefox | MediaRecorder  | `onAudioRecorded` prop |\n| Safari  | MediaRecorder  | `onAudioRecorded` prop |\n\nFor full cross-browser support, provide the `onAudioRecorded` callback that sends audio to a transcription service like OpenAI Whisper, Google Cloud Speech-to-Text, or AssemblyAI.\n\n## Accessibility\n\n- Uses semantic button element via shadcn/ui Button\n- Visual feedback for listening state\n- Keyboard accessible (can be triggered with Space/Enter)\n- Screen reader friendly with proper button semantics\n\n## Usage with MediaRecorder Fallback\n\nTo support Firefox and Safari, provide an `onAudioRecorded` callback that sends audio to a transcription service:\n\n```tsx\nconst handleAudioRecorded = async (audioBlob: Blob): Promise<string> => {\n  const formData = new FormData();\n  formData.append(\"file\", audioBlob, \"audio.webm\");\n  formData.append(\"model\", \"whisper-1\");\n\n  const response = await fetch(\n    \"https://api.openai.com/v1/audio/transcriptions\",\n    {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,\n      },\n      body: formData,\n    }\n  );\n\n  const data = await response.json();\n  return data.text;\n};\n\n<SpeechInput\n  onTranscriptionChange={(text) => console.log(text)}\n  onAudioRecorded={handleAudioRecorded}\n/>;\n```\n\n## Notes\n\n- Requires a secure context (HTTPS or localhost)\n- Browser may prompt user for microphone permission\n- Only final transcripts trigger the `onTranscriptionChange` callback\n- Language is configurable via the `lang` prop\n- Continuous recognition continues until button is clicked again\n- Errors are logged to console and automatically stop recognition/recording\n- MediaRecorder fallback requires the `onAudioRecorded` prop to be provided\n- Audio is recorded in `audio/webm` format for the MediaRecorder fallback\n\n## TypeScript\n\nThe component includes full TypeScript definitions for the Web Speech API:\n\n- `SpeechRecognition`\n- `SpeechRecognitionEvent`\n- `SpeechRecognitionResult`\n- `SpeechRecognitionAlternative`\n- `SpeechRecognitionErrorEvent`\n\nThese types are properly declared for both standard and webkit-prefixed implementations.\n",".agents/skills/ai-elements/references/stack-trace.md":"# Stack Trace\n\nDisplays formatted JavaScript/Node.js error stack traces with syntax highlighting and collapsible frames.\n\nThe `StackTrace` component displays formatted JavaScript/Node.js error stack traces with clickable file paths, internal frame dimming, and collapsible content.\n\nSee `scripts/stack-trace.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add stack-trace\n```\n\n## Usage with AI SDK\n\nBuild an error display tool that shows stack traces from AI-generated code using the [`useChat`](https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-chat) hook.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  StackTrace,\n  StackTraceHeader,\n  StackTraceError,\n  StackTraceErrorType,\n  StackTraceErrorMessage,\n  StackTraceActions,\n  StackTraceCopyButton,\n  StackTraceExpandButton,\n  StackTraceContent,\n  StackTraceFrames,\n} from \"@/components/ai-elements/stack-trace\";\n\nexport default function Page() {\n  const { messages } = useChat({\n    api: \"/api/run-code\",\n  });\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6\">\n      {messages.map((message) => {\n        const toolInvocations = message.parts?.filter(\n          (part) => part.type === \"tool-invocation\"\n        );\n\n        return toolInvocations?.map((tool) => {\n          if (tool.toolName === \"runCode\" && tool.result?.error) {\n            return (\n              <StackTrace\n                key={tool.toolCallId}\n                trace={tool.result.error}\n                defaultOpen\n              >\n                <StackTraceHeader>\n                  <StackTraceError>\n                    <StackTraceErrorType />\n                    <StackTraceErrorMessage />\n                  </StackTraceError>\n                  <StackTraceActions>\n                    <StackTraceCopyButton />\n                    <StackTraceExpandButton />\n                  </StackTraceActions>\n                </StackTraceHeader>\n                <StackTraceContent>\n                  <StackTraceFrames />\n                </StackTraceContent>\n              </StackTrace>\n            );\n          }\n          return null;\n        });\n      })}\n    </div>\n  );\n}\n```\n\nAdd the following route to your backend:\n\n```tsx title=\"api/run-code/route.ts\"\nimport { streamText, tool } from \"ai\";\nimport { z } from \"zod\";\n\nexport async function POST(req: Request) {\n  const { messages } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages,\n    tools: {\n      runCode: tool({\n        description: \"Execute JavaScript code and return any errors\",\n        parameters: z.object({\n          code: z.string(),\n        }),\n        execute: async ({ code }) => {\n          try {\n            // Execute code in sandbox\n            eval(code);\n            return { success: true };\n          } catch (error) {\n            return { error: (error as Error).stack };\n          }\n        },\n      }),\n    },\n  });\n\n  return result.toDataStreamResponse();\n}\n```\n\n## Features\n\n- Parses standard JavaScript/Node.js stack trace format\n- Highlights error type in red\n- Dims internal frames (node_modules, node: paths)\n- Collapsible content with smooth animation\n- Copy full stack trace to clipboard\n- Clickable file paths with line/column numbers\n\n## Examples\n\n### Collapsed by Default\n\nSee `scripts/stack-trace-collapsed.tsx` for this example.\n\n### Hide Internal Frames\n\nSee `scripts/stack-trace-no-internal.tsx` for this example.\n\n## Props\n\n### `<StackTrace />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `trace` | `string` | - | The raw stack trace string to parse and display. |\n| `open` | `boolean` | - | Controlled open state. |\n| `defaultOpen` | `boolean` | `false` | Whether the content is expanded by default. |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback when open state changes. |\n| `onFilePathClick` | `(path: string, line?: number, column?: number) => void` | - | Callback when a file path is clicked. Receives the file path, line number, and column number. |\n| `children` | `React.ReactNode` | - | Child elements (StackTraceHeader, StackTraceContent, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<StackTraceHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Header content (typically StackTraceError and StackTraceActions). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger. |\n\n### `<StackTraceError />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Error content (typically StackTraceErrorType and StackTraceErrorMessage). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n\n### `<StackTraceErrorType />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom content. Defaults to the parsed error type (e.g.,  |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<StackTraceErrorMessage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom content. Defaults to the parsed error message. |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<StackTraceActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Action buttons (typically StackTraceCopyButton and StackTraceExpandButton). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n\n### `<StackTraceCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback fired after a successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback fired if copying fails. |\n| `timeout` | `number` | `2000` | How long to show the copied state (ms). |\n| `children` | `React.ReactNode` | - | Custom content for the button. Defaults to copy/check icons. |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<StackTraceExpandButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n\n### `<StackTraceContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `maxHeight` | `number` | `400` | Maximum height of the content area. Enables scrolling when content exceeds this height. |\n| `children` | `React.ReactNode` | - | Content to display (typically StackTraceFrames). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent. |\n\n### `<StackTraceFrames />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `showInternalFrames` | `boolean` | `true` | Whether to show internal frames (node_modules, node: paths). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n",".agents/skills/ai-elements/references/suggestion.md":"# Suggestion\n\nA suggestion component that displays a horizontal row of clickable suggestions for user interaction.\n\nThe `Suggestion` component displays a horizontal row of clickable suggestions for user interaction.\n\nSee `scripts/suggestion.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add suggestion\n```\n\n## Usage with AI SDK\n\nBuild a simple input with suggestions users can click to send a message to the LLM.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { Suggestion, Suggestions } from \"@/components/ai-elements/suggestion\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\n\nconst suggestions = [\n  \"Can you explain how to play tennis?\",\n  \"What is the weather in Tokyo?\",\n  \"How do I make a really good fish taco?\",\n];\n\nconst SuggestionDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { sendMessage, status } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  const handleSuggestionClick = (suggestion: string) => {\n    sendMessage({ text: suggestion });\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex flex-col gap-4\">\n          <Suggestions>\n            {suggestions.map((suggestion) => (\n              <Suggestion\n                key={suggestion}\n                onClick={handleSuggestionClick}\n                suggestion={suggestion}\n              />\n            ))}\n          </Suggestions>\n          <PromptInput\n            onSubmit={handleSubmit}\n            className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n          >\n            <PromptInputTextarea\n              value={input}\n              placeholder=\"Say something...\"\n              onChange={(e) => setInput(e.currentTarget.value)}\n              className=\"pr-12\"\n            />\n            <PromptInputSubmit\n              status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n              disabled={!input.trim()}\n              className=\"absolute bottom-1 right-1\"\n            />\n          </PromptInput>\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default SuggestionDemo;\n```\n\n## Features\n\n- Horizontal row of clickable suggestion buttons\n- Customizable styling with variant and size options\n- Flexible layout that wraps suggestions on smaller screens\n- onClick callback that emits the selected suggestion string\n- Support for both individual suggestions and suggestion lists\n- Clean, modern styling with hover effects\n- Responsive design with mobile-friendly touch targets\n- TypeScript support with proper type definitions\n\n## Examples\n\n### Usage with AI Input\n\nSee `scripts/suggestion-input.tsx` for this example.\n\n## Props\n\n### `<Suggestions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof ScrollArea>` | - | Any other props are spread to the underlying ScrollArea component. |\n\n### `<Suggestion />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `suggestion` | `string` | Required | The suggestion string to display and emit on click. |\n| `onClick` | `(suggestion: string) => void` | - | Callback fired when the suggestion is clicked. |\n| `...props` | `Omit<React.ComponentProps<typeof Button>, ` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n",".agents/skills/ai-elements/references/task.md":"# Task\n\nA collapsible task list component for displaying AI workflow progress, with status indicators and optional descriptions.\n\nThe `Task` component provides a structured way to display task lists or workflow progress with collapsible details, status indicators, and progress tracking. It consists of a main `Task` container with `TaskTrigger` for the clickable header and `TaskContent` for the collapsible content area.\n\nSee `scripts/task.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add task\n```\n\n## Usage with AI SDK\n\nBuild a mock async programming agent using [`experimental_generateObject`](/docs/reference/ai-sdk-ui/use-object).\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { experimental_useObject as useObject } from \"@ai-sdk/react\";\nimport {\n  Task,\n  TaskItem,\n  TaskItemFile,\n  TaskTrigger,\n  TaskContent,\n} from \"@/components/ai-elements/task\";\nimport { Button } from \"@/components/ui/button\";\nimport { tasksSchema } from \"@/app/api/task/route\";\nimport {\n  SiReact,\n  SiTypescript,\n  SiJavascript,\n  SiCss,\n  SiHtml5,\n  SiJson,\n  SiMarkdown,\n} from \"@icons-pack/react-simple-icons\";\n\nconst iconMap = {\n  react: { component: SiReact, color: \"#149ECA\" },\n  typescript: { component: SiTypescript, color: \"#3178C6\" },\n  javascript: { component: SiJavascript, color: \"#F7DF1E\" },\n  css: { component: SiCss, color: \"#1572B6\" },\n  html: { component: SiHtml5, color: \"#E34F26\" },\n  json: { component: SiJson, color: \"#000000\" },\n  markdown: { component: SiMarkdown, color: \"#000000\" },\n};\n\nconst TaskDemo = () => {\n  const { object, submit, isLoading } = useObject({\n    api: \"/api/agent\",\n    schema: tasksSchema,\n  });\n\n  const handleSubmit = (taskType: string) => {\n    submit({ prompt: taskType });\n  };\n\n  const renderTaskItem = (item: any, index: number) => {\n    if (item?.type === \"file\" && item.file) {\n      const iconInfo = iconMap[item.file.icon as keyof typeof iconMap];\n      if (iconInfo) {\n        const IconComponent = iconInfo.component;\n        return (\n          <span className=\"inline-flex items-center gap-1\" key={index}>\n            {item.text}\n            <TaskItemFile>\n              <IconComponent\n                color={item.file.color || iconInfo.color}\n                className=\"size-4\"\n              />\n              <span>{item.file.name}</span>\n            </TaskItemFile>\n          </span>\n        );\n      }\n    }\n    return item?.text || \"\";\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex gap-2 mb-6 flex-wrap\">\n          <Button\n            onClick={() => handleSubmit(\"React component development\")}\n            disabled={isLoading}\n            variant=\"outline\"\n          >\n            React Development\n          </Button>\n        </div>\n\n        <div className=\"flex-1 overflow-auto space-y-4\">\n          {isLoading && !object && (\n            <div className=\"text-muted-foreground\">Generating tasks...</div>\n          )}\n\n          {object?.tasks?.map((task: any, taskIndex: number) => (\n            <Task key={taskIndex} defaultOpen={taskIndex === 0}>\n              <TaskTrigger title={task.title || \"Loading...\"} />\n              <TaskContent>\n                {task.items?.map((item: any, itemIndex: number) => (\n                  <TaskItem key={itemIndex}>\n                    {renderTaskItem(item, itemIndex)}\n                  </TaskItem>\n                ))}\n              </TaskContent>\n            </Task>\n          ))}\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default TaskDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/agent.ts\"\nimport { streamObject } from \"ai\";\nimport { z } from \"zod\";\n\nexport const taskItemSchema = z.object({\n  type: z.enum([\"text\", \"file\"]),\n  text: z.string(),\n  file: z\n    .object({\n      name: z.string(),\n      icon: z.string(),\n      color: z.string().optional(),\n    })\n    .optional(),\n});\n\nexport const taskSchema = z.object({\n  title: z.string(),\n  items: z.array(taskItemSchema),\n  status: z.enum([\"pending\", \"in_progress\", \"completed\"]),\n});\n\nexport const tasksSchema = z.object({\n  tasks: z.array(taskSchema),\n});\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { prompt } = await req.json();\n\n  const result = streamObject({\n    model: \"openai/gpt-4o\",\n    schema: tasksSchema,\n    prompt: `You are an AI assistant that generates realistic development task workflows. Generate a set of tasks that would occur during ${prompt}.\n\n    Each task should have:\n    - A descriptive title\n    - Multiple task items showing the progression\n    - Some items should be plain text, others should reference files\n    - Use realistic file names and appropriate file types\n    - Status should progress from pending to in_progress to completed\n\n    For file items, use these icon types: 'react', 'typescript', 'javascript', 'css', 'html', 'json', 'markdown'\n\n    Generate 3-4 tasks total, with 4-6 items each.`,\n  });\n\n  return result.toTextStreamResponse();\n}\n```\n\n## Features\n\n- Visual icons for pending, in-progress, completed, and error states\n- Expandable content for task descriptions and additional information\n- Built-in progress counter showing completed vs total tasks\n- Optional progressive reveal of tasks with customizable timing\n- Support for custom content within task items\n- Full type safety with proper TypeScript definitions\n- Keyboard navigation and screen reader support\n\n## Props\n\n### `<Task />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultOpen` | `boolean` | `true` | Whether the task is open by default. |\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the root Collapsible component. |\n\n### `<TaskTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | Required | The title of the task that will be displayed in the trigger. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<TaskContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent component. |\n\n### `<TaskItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<TaskItemFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n",".agents/skills/ai-elements/references/terminal.md":"# Terminal\n\nDisplay streaming console output with full ANSI color support.\n\nThe `Terminal` component displays console output with ANSI color support, streaming indicators, and auto-scroll functionality.\n\nSee `scripts/terminal.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add terminal\n```\n\n## Features\n\n- Full ANSI color support (256 colors, bold, italic, underline)\n- Streaming mode with cursor animation\n- Auto-scroll to latest output\n- Copy output to clipboard\n- Clear button support\n- Dark terminal theme\n\n## ANSI Support\n\nThe Terminal uses `ansi-to-react` to parse ANSI escape codes:\n\n```bash\n\\x1b[32m✓\\x1b[0m Success    # Green checkmark\n\\x1b[31m✗\\x1b[0m Error      # Red X\n\\x1b[33mwarn\\x1b[0m Warning   # Yellow text\n\\x1b[1mBold\\x1b[0m           # Bold text\n```\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/terminal-basic.tsx` for this example.\n\n### Streaming Mode\n\nSee `scripts/terminal-streaming.tsx` for this example.\n\n### With Clear Button\n\nSee `scripts/terminal-clear.tsx` for this example.\n\n## Props\n\n### `<Terminal />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `output` | `string` | - | Terminal output text (supports ANSI codes). |\n| `isStreaming` | `boolean` | `false` | Show streaming indicator. |\n| `autoScroll` | `boolean` | `true` | Auto-scroll to bottom on new output. |\n| `onClear` | `() => void` | - | Callback to clear output (enables clear button). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<TerminalCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback after successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback if copying fails. |\n| `timeout` | `number` | `2000` | Duration to show copied state (ms). |\n\n### `<TerminalHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TerminalTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TerminalStatus />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TerminalActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TerminalClearButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component. |\n\n### `<TerminalContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n",".agents/skills/ai-elements/references/test-results.md":"# Test Results\n\nDisplay test suite results with pass/fail/skip status and error details.\n\nThe `TestResults` component displays test suite results including summary statistics, progress, individual tests, and error details.\n\nSee `scripts/test-results.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add test-results\n```\n\n## Features\n\n- Summary statistics (passed/failed/skipped)\n- Progress bar visualization\n- Collapsible test suites\n- Individual test status and duration\n- Error messages with stack traces\n- Color-coded status indicators\n\n## Status Colors\n\n| Status    | Color           | Use Case         |\n| --------- | --------------- | ---------------- |\n| `passed`  | Green           | Test succeeded   |\n| `failed`  | Red             | Test failed      |\n| `skipped` | Yellow          | Test skipped     |\n| `running` | Blue (animated) | Test in progress |\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/test-results-basic.tsx` for this example.\n\n### With Test Suites\n\nSee `scripts/test-results-suites.tsx` for this example.\n\n### With Error Details\n\nSee `scripts/test-results-errors.tsx` for this example.\n\n## Props\n\n### `<TestResults />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `summary` | `unknown` | - | Test results summary. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<TestSuite />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | - | Suite name. |\n| `status` | `unknown` | - | Overall suite status. |\n| `defaultOpen` | `boolean` | - | Initially expanded. |\n\n### `<Test />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | - | Test name. |\n| `status` | `unknown` | - | Test status. |\n| `duration` | `number` | - | Test duration in ms. |\n\n### `<TestResultsHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestResultsSummary />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestResultsDuration />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<TestResultsProgress />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestResultsContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestSuiteName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<TestSuiteStats />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `passed` | `number` | `0` | Number of passed tests. |\n| `failed` | `number` | `0` | Number of failed tests. |\n| `skipped` | `number` | `0` | Number of skipped tests. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestSuiteContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent component. |\n\n### `<TestStatus />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<TestName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<TestDuration />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<TestError />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestErrorMessage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Any other props are spread to the p element. |\n\n### `<TestErrorStack />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLPreElement>` | - | Any other props are spread to the pre element. |\n",".agents/skills/ai-elements/references/tool.md":"# Tool\n\nA collapsible component for displaying tool invocation details in AI chatbot interfaces.\n\nThe `Tool` component displays a collapsible interface for showing/hiding tool details. It is designed to take the `ToolUIPart` type from the AI SDK and display it in a collapsible interface.\n\nSee `scripts/tool.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add tool\n```\n\n## Usage in AI SDK\n\nBuild a simple stateful weather app that renders the last message in a tool using [`useChat`](/docs/reference/ai-sdk-ui/use-chat).\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport { DefaultChatTransport, type ToolUIPart } from \"ai\";\nimport { Button } from \"@/components/ui/button\";\nimport { MessageResponse } from \"@/components/ai-elements/message\";\nimport {\n  Tool,\n  ToolContent,\n  ToolHeader,\n  ToolInput,\n  ToolOutput,\n} from \"@/components/ai-elements/tool\";\n\ntype WeatherToolInput = {\n  location: string;\n  units: \"celsius\" | \"fahrenheit\";\n};\n\ntype WeatherToolOutput = {\n  location: string;\n  temperature: string;\n  conditions: string;\n  humidity: string;\n  windSpeed: string;\n  lastUpdated: string;\n};\n\ntype WeatherToolUIPart = ToolUIPart<{\n  fetch_weather_data: {\n    input: WeatherToolInput;\n    output: WeatherToolOutput;\n  };\n}>;\n\nconst Example = () => {\n  const { messages, sendMessage, status } = useChat({\n    transport: new DefaultChatTransport({\n      api: \"/api/weather\",\n    }),\n  });\n\n  const handleWeatherClick = () => {\n    sendMessage({ text: \"Get weather data for San Francisco in fahrenheit\" });\n  };\n\n  const latestMessage = messages[messages.length - 1];\n  const weatherTool = latestMessage?.parts?.find(\n    (part) => part.type === \"tool-fetch_weather_data\"\n  ) as WeatherToolUIPart | undefined;\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"space-y-4\">\n          <Button onClick={handleWeatherClick} disabled={status !== \"ready\"}>\n            Get Weather for San Francisco\n          </Button>\n\n          {weatherTool && (\n            <Tool defaultOpen={true}>\n              <ToolHeader\n                type=\"tool-fetch_weather_data\"\n                state={weatherTool.state}\n              />\n              <ToolContent>\n                <ToolInput input={weatherTool.input} />\n                <ToolOutput\n                  output={\n                    <MessageResponse>\n                      {formatWeatherResult(weatherTool.output)}\n                    </MessageResponse>\n                  }\n                  errorText={weatherTool.errorText}\n                />\n              </ToolContent>\n            </Tool>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n};\n\nfunction formatWeatherResult(result: WeatherToolOutput): string {\n  return `**Weather for ${result.location}**\n\n**Temperature:** ${result.temperature}  \n**Conditions:** ${result.conditions}  \n**Humidity:** ${result.humidity}  \n**Wind Speed:** ${result.windSpeed}  \n\n*Last updated: ${result.lastUpdated}*`;\n}\n\nexport default Example;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/weather/route.tsx\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\nimport { z } from \"zod\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages: await convertToModelMessages(messages),\n    tools: {\n      fetch_weather_data: {\n        description: \"Fetch weather information for a specific location\",\n        parameters: z.object({\n          location: z\n            .string()\n            .describe(\"The city or location to get weather for\"),\n          units: z\n            .enum([\"celsius\", \"fahrenheit\"])\n            .default(\"celsius\")\n            .describe(\"Temperature units\"),\n        }),\n        inputSchema: z.object({\n          location: z.string(),\n          units: z.enum([\"celsius\", \"fahrenheit\"]).default(\"celsius\"),\n        }),\n        execute: async ({ location, units }) => {\n          await new Promise((resolve) => setTimeout(resolve, 1500));\n\n          const temp =\n            units === \"celsius\"\n              ? Math.floor(Math.random() * 35) + 5\n              : Math.floor(Math.random() * 63) + 41;\n\n          return {\n            location,\n            temperature: `${temp}°${units === \"celsius\" ? \"C\" : \"F\"}`,\n            conditions: \"Sunny\",\n            humidity: `12%`,\n            windSpeed: `35 ${units === \"celsius\" ? \"km/h\" : \"mph\"}`,\n            lastUpdated: new Date().toLocaleString(),\n          };\n        },\n      },\n    },\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Collapsible interface for showing/hiding tool details\n- Visual status indicators with icons and badges\n- Support for multiple tool execution states (pending, running, completed, error)\n- Formatted parameter display with JSON syntax highlighting\n- Result and error handling with appropriate styling\n- Composable structure for flexible layouts\n- Accessible keyboard navigation and screen reader support\n- Consistent styling that matches your design system\n- Auto-opens completed tools by default for better UX\n\n## Examples\n\n### Input Streaming (Pending)\n\nShows a tool in its initial state while parameters are being processed.\n\nSee `scripts/tool-input-streaming.tsx` for this example.\n\n### Input Available (Running)\n\nShows a tool that's actively executing with its parameters.\n\nSee `scripts/tool-input-available.tsx` for this example.\n\n### Output Available (Completed)\n\nShows a completed tool with successful results. Opens by default to show the results. In this instance, the output is a JSON object, so we can use the `CodeBlock` component to display it.\n\nSee `scripts/tool-output-available.tsx` for this example.\n\n### Output Error\n\nShows a tool that encountered an error during execution. Opens by default to display the error.\n\nSee `scripts/tool-output-error.tsx` for this example.\n\n## Props\n\n### `<Tool />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the root Collapsible component. |\n\n### `<ToolHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | - | Custom title to display instead of the derived tool name. |\n| `type` | `ToolUIPart[` | Required | The type/name of the tool. |\n| `state` | `ToolUIPart[` | Required | The current state of the tool (input-streaming, input-available, output-available, or output-error). |\n| `toolName` | `string` | - | Required when type is  |\n| `className` | `string` | - | Additional CSS classes to apply to the header. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger. |\n\n### `<ToolContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent. |\n\n### `<ToolInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `input` | `ToolUIPart[` | - | The input parameters passed to the tool, displayed as formatted JSON. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<ToolOutput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `output` | `React.ReactNode` | - | The output/result of the tool execution. |\n| `errorText` | `ToolUIPart[` | - | An error message if the tool execution failed. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n## Type Exports\n\n### `ToolPart`\n\nUnion type representing both static and dynamic tool UI parts.\n\n```tsx\ntype ToolPart = ToolUIPart | DynamicToolUIPart;\n```\n\n## Utilities\n\n### `getStatusBadge`\n\nReturns a Badge component with icon and label based on tool state.\n\n```tsx\nimport { getStatusBadge } from \"@/components/ai-elements/tool\";\n\n// Returns a Badge with appropriate icon and label\nconst badge = getStatusBadge(\"output-available\");\n```\n\nSupported states:\n\n- `input-streaming` - \"Pending\"\n- `input-available` - \"Running\"\n- `approval-requested` - \"Awaiting Approval\"\n- `approval-responded` - \"Responded\"\n- `output-available` - \"Completed\"\n- `output-error` - \"Error\"\n- `output-denied` - \"Denied\"\n",".agents/skills/ai-elements/references/toolbar.md":"# Toolbar\n\nA styled toolbar component for React Flow nodes with flexible positioning and custom actions.\n\nThe `Toolbar` component provides a positioned toolbar that attaches to nodes in React Flow canvases. It features modern card styling with backdrop blur and flexbox layout for action buttons and controls.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add toolbar\n```\n\n## Features\n\n- Attaches to any React Flow node\n- Bottom positioning by default\n- Rounded card design with border\n- Theme-aware background styling\n- Flexbox layout with gap spacing\n- Full TypeScript support\n- Compatible with all React Flow NodeToolbar features\n\n## Props\n\n### `<Toolbar />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the toolbar. |\n| `...props` | `ComponentProps<typeof NodeToolbar>` | - | Any other props from @xyflow/react NodeToolbar component (position, offset, isVisible, etc.). |\n",".agents/skills/ai-elements/references/transcription.md":"# Transcription\n\nA composable component for displaying interactive, synchronized transcripts from AI SDK transcribe() results with click-to-seek functionality.\n\nThe `Transcription` component provides a flexible render props interface for displaying audio transcripts with synchronized playback. It automatically highlights the current segment based on playback time and supports click-to-seek functionality for interactive navigation.\n\nSee `scripts/transcription.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add transcription\n```\n\n## Features\n\n- Render props pattern for maximum flexibility\n- Automatic segment highlighting based on current time\n- Click-to-seek functionality for interactive navigation\n- Controlled and uncontrolled component patterns\n- Automatic filtering of empty segments\n- Visual state indicators (active, past, future)\n- Built on Radix UI's `useControllableState` for flexible state management\n- Full TypeScript support with AI SDK transcription types\n\n## Props\n\n### `<Transcription />`\n\nRoot component that provides context and manages transcript state. Uses render props pattern for rendering segments.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `segments` | `TranscriptionSegment[]` | - | Array of transcription segments from AI SDK transcribe() function. |\n| `currentTime` | `number` | `0` | Current playback time in seconds (controlled). |\n| `onSeek` | `(time: number) => void` | - | Callback fired when a segment is clicked or when currentTime changes. |\n| `children` | `(segment: TranscriptionSegment, index: number) => ReactNode` | - | Render function that receives each segment and its index. |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the root div element. |\n\n### `<TranscriptionSegment />`\n\nIndividual segment button with automatic state styling and click-to-seek functionality.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `segment` | `TranscriptionSegment` | - | The transcription segment data. |\n| `index` | `number` | - | The segment index. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the button element. |\n\n## Behavior\n\n### Render Props Pattern\n\nThe component uses a render props pattern where the `children` prop is a function that receives each segment and its index. This provides maximum flexibility for custom rendering while still benefiting from automatic state management and context.\n\n### Segment Highlighting\n\nSegments are automatically styled based on their relationship to the current playback time:\n\n- **Active** (`isActive`): When `currentTime` is within the segment's time range. Styled with primary color.\n- **Past** (`isPast`): When `currentTime` is after the segment's end time. Styled with muted foreground.\n- **Future**: When `currentTime` is before the segment's start time. Styled with dimmed muted foreground.\n\n### Click-to-Seek\n\nWhen `onSeek` is provided, segments become interactive buttons. Clicking a segment calls `onSeek` with the segment's start time, allowing your audio/video player to seek to that position.\n\n### Empty Segment Filtering\n\nThe component automatically filters out segments with empty or whitespace-only text to avoid rendering unnecessary elements.\n\n### State Management\n\nUses Radix UI's `useControllableState` hook to support both controlled and uncontrolled patterns. When `currentTime` is provided, the component operates in controlled mode. Otherwise, it maintains its own internal state.\n\n## Data Format\n\nThe component expects segments from the AI SDK `transcribe()` function:\n\n```ts\ntype TranscriptionSegment = {\n  text: string;\n  startSecond: number;\n  endSecond: number;\n};\n```\n\n## Styling\n\nThe component uses data attributes for custom styling:\n\n- `data-slot=\"transcription\"`: Root container\n- `data-slot=\"transcription-segment\"`: Individual segment button\n- `data-active`: Present on the currently playing segment\n- `data-index`: The segment's index in the array\n\nDefault segment appearance:\n\n- Active segment: `text-primary` (primary brand color)\n- Past segments: `text-muted-foreground`\n- Future segments: `text-muted-foreground/60` (dimmed)\n- Interactive segments: `cursor-pointer hover:text-foreground`\n- Non-interactive segments: `cursor-default`\n\n## Accessibility\n\n- Uses semantic `<button>` elements for interactive segments\n- Full keyboard navigation support\n- Proper button semantics for screen readers\n- `data-active` attribute for assistive technology\n- Hover and focus states for keyboard users\n\n## Notes\n\n- Empty or whitespace-only segments are automatically filtered out\n- The component uses `flex-wrap` for responsive text flow\n- Segments maintain inline layout with `gap-1` spacing\n- `text-sm` and `leading-relaxed` provide comfortable reading\n- Click events on segments still fire the `onClick` handler if provided\n- The `onSeek` callback is called both when segments are clicked and when controlled `currentTime` changes\n",".agents/skills/ai-elements/references/voice-selector.md":"# Voice Selector\n\nA composable dialog component for selecting AI voices with metadata display and search functionality.\n\nThe `VoiceSelector` component provides a flexible and composable interface for selecting AI voices. Built on shadcn/ui's Dialog and Command components, it features a searchable voice list with support for metadata display (gender, accent, age), grouping, and customizable layouts. The component includes a context provider for accessing voice selection state from any nested component.\n\nSee `scripts/voice-selector.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add voice-selector\n```\n\n## Features\n\n- Fully composable architecture with granular control components\n- Built on shadcn/ui Dialog and Command components\n- React Context API for accessing state in nested components\n- Searchable voice list with real-time filtering\n- Support for voice metadata with icons and emojis (gender icons, accent flags, age)\n- Voice preview button with play/pause/loading states\n- Voice grouping with separators and bullet dividers\n- Keyboard navigation support\n- Controlled and uncontrolled component patterns\n- Full TypeScript support with proper types for all components\n\n## Props\n\n### `<VoiceSelector />`\n\nRoot Dialog component that provides context for all child components. Manages both voice selection and dialog open states.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The selected voice ID (controlled). |\n| `defaultValue` | `string` | - | The default selected voice ID (uncontrolled). |\n| `onValueChange` | `(value: string | undefined) => void` | - | Callback fired when the selected voice changes. |\n| `defaultOpen` | `boolean` | `false` | The default open state (uncontrolled). |\n| `open` | `boolean` | - | The open state (controlled). |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback fired when the open state changes. |\n| `modal` | `boolean` | `true` | Whether the dialog is modal (blocks interaction with the rest of the page). |\n| `...props` | `React.ComponentProps<typeof Dialog>` | - | Any other props are spread to the Dialog component. |\n\n### `<VoiceSelectorTrigger />`\n\nButton or element that opens the voice selector dialog.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior. |\n| `...props` | `React.ComponentProps<typeof DialogTrigger>` | - | Any other props are spread to the DialogTrigger component. |\n\n### `<VoiceSelectorContent />`\n\nContainer for the Command component and voice list, rendered inside the dialog.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `ReactNode` | - | The title for screen readers. Hidden visually but accessible to assistive technologies. |\n| `className` | `string` | - | Additional CSS classes to apply to the dialog content. |\n| `...props` | `React.ComponentProps<typeof DialogContent>` | - | Any other props are spread to the DialogContent component. |\n\n### `<VoiceSelectorDialog />`\n\nAlternative dialog implementation using CommandDialog for a full-screen command palette style.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandDialog>` | - | Any other props are spread to the CommandDialog component. |\n\n### `<VoiceSelectorInput />`\n\nSearch input for filtering voices.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `placeholder` | `string` | - | Placeholder text for the search input. |\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the CommandInput component. |\n\n### `<VoiceSelectorList />`\n\nScrollable container for voice items and groups.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandList>` | - | Any other props are spread to the CommandList component. |\n\n### `<VoiceSelectorEmpty />`\n\nMessage shown when no voices match the search query.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode` | - | The message to display. |\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the CommandEmpty component. |\n\n### `<VoiceSelectorGroup />`\n\nGroups related voices together with an optional heading.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `heading` | `string` | - | The heading text for the group. |\n| `...props` | `React.ComponentProps<typeof CommandGroup>` | - | Any other props are spread to the CommandGroup component. |\n\n### `<VoiceSelectorItem />`\n\nSelectable item representing a voice.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The unique identifier for this voice. Used for search filtering. |\n| `onSelect` | `(value: string) => void` | - | Callback fired when the voice is selected. |\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the CommandItem component. |\n\n### `<VoiceSelectorSeparator />`\n\nVisual separator between voice groups.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandSeparator>` | - | Any other props are spread to the CommandSeparator component. |\n\n### `<VoiceSelectorName />`\n\nDisplays the voice name with proper styling.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorGender />`\n\nDisplays the voice gender metadata with icons from Lucide. Supports multiple gender identities with corresponding icons.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `unknown` | - | The gender value that determines which icon to display. Supported values:  |\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `children` | `ReactNode` | - | Override the icon with custom content. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorAccent />`\n\nDisplays the voice accent metadata with emoji flags representing different countries/regions.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `unknown` | - | The accent value that determines which flag emoji to display. Supports 27 different accents including:  |\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `children` | `ReactNode` | - | Override the flag emoji with custom content. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorAge />`\n\nDisplays the voice age metadata with muted styling and tabular numbers for consistent alignment.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorDescription />`\n\nDisplays a description for the voice with muted styling.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorAttributes />`\n\nContainer for grouping voice attributes (gender, accent, age) together. Use with `VoiceSelectorBullet` for separation.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<VoiceSelectorBullet />`\n\nDisplays a bullet separator (•) between voice attributes. Hidden from screen readers via `aria-hidden`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorShortcut />`\n\nDisplays keyboard shortcuts for voice items.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandShortcut>` | - | Any other props are spread to the CommandShortcut component. |\n\n### `<VoiceSelectorPreview />`\n\nA button that allows users to preview/play a voice sample before selecting it. Shows play, pause, or loading icons based on state.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `playing` | `boolean` | - | Whether the voice is currently playing. Shows pause icon when true. |\n| `loading` | `boolean` | - | Whether the voice preview is loading. Shows loading spinner and disables the button. |\n| `onPlay` | `() => void` | - | Callback fired when the preview button is clicked. |\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the button element. |\n\n## Hooks\n\n### `useVoiceSelector()`\n\nA custom hook for accessing the voice selector context. This hook allows you to access and control the voice selection state from any component nested within `VoiceSelector`.\n\n```tsx\nimport { useVoiceSelector } from \"@repo/elements/voice-selector\";\n\nexport default function CustomVoiceDisplay() {\n  const { value, setValue, open, setOpen } = useVoiceSelector();\n\n  return (\n    <div>\n      <p>Selected voice: {value ?? \"None\"}</p>\n      <button onClick={() => setOpen(!open)}>Toggle Dialog</button>\n    </div>\n  );\n}\n```\n\n#### Return Value\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string | undefined` | - | The currently selected voice ID. |\n| `setValue` | `(value: string | undefined) => void` | - | Function to update the selected voice ID. |\n| `open` | `boolean` | - | Whether the dialog is currently open. |\n| `setOpen` | `(open: boolean) => void` | - | Function to control the dialog open state. |\n",".agents/skills/ai-elements/references/web-preview.md":"# Web Preview\n\nA composable component for previewing the result of a generated UI, with support for live examples and code display.\n\nThe `WebPreview` component provides a flexible way to showcase the result of a generated UI component, along with its source code. It is designed for documentation and demo purposes, allowing users to interact with live examples and view the underlying implementation.\n\nSee `scripts/web-preview.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add web-preview\n```\n\n## Usage with AI SDK\n\nBuild a simple v0 clone using the [v0 Platform API](https://v0.dev/docs/api/platform).\n\nInstall the `v0-sdk` package:\n\n```package-install\nnpm i v0-sdk\n```\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  WebPreview,\n  WebPreviewBody,\n  WebPreviewNavigation,\n  WebPreviewUrl,\n} from \"@/components/ai-elements/web-preview\";\nimport { useState } from \"react\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { Spinner } from \"@/components/ui/spinner\";\n\nconst WebPreviewDemo = () => {\n  const [previewUrl, setPreviewUrl] = useState(\"\");\n  const [prompt, setPrompt] = useState(\"\");\n  const [isGenerating, setIsGenerating] = useState(false);\n\n  const handleSubmit = async (message: PromptInputMessage) => {\n    if (!message.text.trim()) return;\n    setPrompt(\"\");\n\n    setIsGenerating(true);\n    try {\n      const response = await fetch(\"/api/v0\", {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\" },\n        body: JSON.stringify({ prompt: message.text }),\n      });\n\n      const data = await response.json();\n      setPreviewUrl(data.demo || \"/\");\n      console.log(\"Generation finished:\", data);\n    } catch (error) {\n      console.error(\"Generation failed:\", error);\n    } finally {\n      setIsGenerating(false);\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex-1 mb-4\">\n          {isGenerating ? (\n            <div className=\"flex flex-col items-center justify-center h-full\">\n              <Spinner />\n              <p className=\"mt-4 text-muted-foreground\">\n                Generating app, this may take a few seconds...\n              </p>\n            </div>\n          ) : previewUrl ? (\n            <WebPreview defaultUrl={previewUrl}>\n              <WebPreviewNavigation>\n                <WebPreviewUrl />\n              </WebPreviewNavigation>\n              <WebPreviewBody src={previewUrl} />\n            </WebPreview>\n          ) : (\n            <div className=\"flex items-center justify-center h-full text-muted-foreground\">\n              Your generated app will appear here\n            </div>\n          )}\n        </div>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={prompt}\n            placeholder=\"Describe the app you want to build...\"\n            onChange={(e) => setPrompt(e.currentTarget.value)}\n            className=\"pr-12 min-h-[60px]\"\n          />\n          <PromptInputSubmit\n            status={isGenerating ? \"streaming\" : \"ready\"}\n            disabled={!prompt.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default WebPreviewDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/v0/route.ts\"\nimport { v0 } from \"v0-sdk\";\n\nexport async function POST(req: Request) {\n  const { prompt }: { prompt: string } = await req.json();\n\n  const result = await v0.chats.create({\n    system: \"You are an expert coder\",\n    message: prompt,\n    modelConfiguration: {\n      modelId: \"v0-1.5-sm\",\n      imageGenerations: false,\n      thinking: false,\n    },\n  });\n\n  return Response.json({\n    demo: result.demo,\n    webUrl: result.webUrl,\n  });\n}\n```\n\n## Features\n\n- Live preview of UI components\n- Composable architecture with dedicated sub-components\n- Responsive design modes (Desktop, Tablet, Mobile)\n- Navigation controls with back/forward functionality\n- URL input and example selector\n- Full screen mode support\n- Console logging with timestamps\n- Context-based state management\n- Consistent styling with the design system\n- Easy integration into documentation pages\n\n## Props\n\n### `<WebPreview />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultUrl` | `string` | - | The initial URL to load in the preview. |\n| `onUrlChange` | `(url: string) => void` | - | Callback fired when the URL changes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<WebPreviewNavigation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the navigation container. |\n\n### `<WebPreviewNavigationButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string` | - | Tooltip text to display on hover. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<WebPreviewUrl />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Input>` | - | Any other props are spread to the underlying shadcn/ui Input component. |\n\n### `<WebPreviewBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `loading` | `React.ReactNode` | - | Optional loading indicator to display over the preview. |\n| `...props` | `React.IframeHTMLAttributes<HTMLIFrameElement>` | - | Any other props are spread to the underlying iframe. |\n\n### `<WebPreviewConsole />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `logs` | `Array<{ level: ` | - | Console log entries to display in the console panel. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n",".agents/skills/ai-sdk/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fai-sdk%2FSKILL.md -->",".agents/skills/better-accessibility/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2FSKILL.md -->",".agents/skills/better-accessibility/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fagents%2Fopenai.yaml -->",".agents/skills/better-accessibility/focus-and-keyboard.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Ffocus-and-keyboard.md -->",".agents/skills/better-accessibility/forms.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fforms.md -->",".agents/skills/better-accessibility/hit-areas.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fhit-areas.md -->",".agents/skills/better-accessibility/motion-and-zoom.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fmotion-and-zoom.md -->",".agents/skills/better-accessibility/screen-readers.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fscreen-readers.md -->",".agents/skills/better-accessibility/semantics-and-aria.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fsemantics-and-aria.md -->",".agents/skills/better-auth-best-practices/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-auth-best-practices%2FSKILL.md -->",".agents/skills/better-colors/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2FSKILL.md -->",".agents/skills/better-colors/accessibility-contrast.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Faccessibility-contrast.md -->",".agents/skills/better-colors/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fagents%2Fopenai.yaml -->",".agents/skills/better-colors/color-conversion.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fcolor-conversion.md -->",".agents/skills/better-colors/color-usage.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fcolor-usage.md -->",".agents/skills/better-colors/gamut-and-tailwind.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fgamut-and-tailwind.md -->",".agents/skills/better-colors/palette-generation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fpalette-generation.md -->",".agents/skills/better-interface/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-interface%2FSKILL.md -->",".agents/skills/better-interface/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-interface%2Fagents%2Fopenai.yaml -->",".agents/skills/better-layout/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-layout%2FSKILL.md -->",".agents/skills/better-layout/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-layout%2Fagents%2Fopenai.yaml -->",".agents/skills/better-layout/grouping-and-alignment.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-layout%2Fgrouping-and-alignment.md -->",".agents/skills/better-layout/spacing-and-adaptivity.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-layout%2Fspacing-and-adaptivity.md -->",".agents/skills/better-typography/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2FSKILL.md -->",".agents/skills/better-typography/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fagents%2Fopenai.yaml -->",".agents/skills/better-typography/choosing-fonts.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fchoosing-fonts.md -->",".agents/skills/better-typography/css-cheat-sheet.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fcss-cheat-sheet.md -->",".agents/skills/better-typography/details-and-accessibility.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fdetails-and-accessibility.md -->",".agents/skills/better-typography/spacing-and-sizing.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fspacing-and-sizing.md -->",".agents/skills/better-typography/variable-fonts-and-opentype.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fvariable-fonts-and-opentype.md -->",".agents/skills/better-typography/wrapping-and-punctuation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fwrapping-and-punctuation.md -->",".agents/skills/better-ui/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2FSKILL.md -->",".agents/skills/better-ui/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Fagents%2Fopenai.yaml -->",".agents/skills/better-ui/animations.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Fanimations.md -->",".agents/skills/better-ui/icons.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Ficons.md -->",".agents/skills/better-ui/performance.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Fperformance.md -->",".agents/skills/better-ui/surfaces.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Fsurfaces.md -->",".agents/skills/better-writing/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-writing%2FSKILL.md -->",".agents/skills/better-writing/agents/openai.yaml":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-writing%2Fagents%2Fopenai.yaml -->",".agents/skills/code-refactor-review/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fcode-refactor-review%2FSKILL.md -->",".agents/skills/create-draft-pr/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fcreate-draft-pr%2FSKILL.md -->",".agents/skills/diffs/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2FSKILL.md -->",".agents/skills/diffs/references/api-editor.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Fapi-editor.md -->",".agents/skills/diffs/references/api-react.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Fapi-react.md -->",".agents/skills/diffs/references/recipe-code-view.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Frecipe-code-view.md -->",".agents/skills/diffs/references/recipe-edit-react.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Frecipe-edit-react.md -->",".agents/skills/diffs/references/recipe-react.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Frecipe-react.md -->",".agents/skills/eve/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Feve%2FSKILL.md -->",".agents/skills/ga-pr/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fga-pr%2FSKILL.md -->",".agents/skills/ga/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fga%2FSKILL.md -->",".agents/skills/gh-stack/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fgh-stack%2FSKILL.md -->",".agents/skills/gh-stack/references/commands.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fgh-stack%2Freferences%2Fcommands.md -->",".agents/skills/gh-stack/references/stack-design.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fgh-stack%2Freferences%2Fstack-design.md -->",".agents/skills/gh-stack/references/troubleshooting.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fgh-stack%2Freferences%2Ftroubleshooting.md -->",".agents/skills/install-anti-slop/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Finstall-anti-slop%2FSKILL.md -->",".agents/skills/nestjs-best-practices/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2FSKILL.md -->",".agents/skills/nestjs-best-practices/rules/_sections.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2F_sections.md -->",".agents/skills/nestjs-best-practices/rules/_template.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2F_template.md -->",".agents/skills/nestjs-best-practices/rules/api-use-dto-serialization.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fapi-use-dto-serialization.md -->",".agents/skills/nestjs-best-practices/rules/api-use-interceptors.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fapi-use-interceptors.md -->",".agents/skills/nestjs-best-practices/rules/api-use-pipes.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fapi-use-pipes.md -->",".agents/skills/nestjs-best-practices/rules/api-versioning.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fapi-versioning.md -->",".agents/skills/nestjs-best-practices/rules/arch-avoid-circular-deps.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-avoid-circular-deps.md -->",".agents/skills/nestjs-best-practices/rules/arch-feature-modules.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-feature-modules.md -->",".agents/skills/nestjs-best-practices/rules/arch-module-sharing.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-module-sharing.md -->",".agents/skills/nestjs-best-practices/rules/arch-single-responsibility.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-single-responsibility.md -->",".agents/skills/nestjs-best-practices/rules/arch-use-events.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-use-events.md -->",".agents/skills/nestjs-best-practices/rules/arch-use-repository-pattern.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-use-repository-pattern.md -->",".agents/skills/nestjs-best-practices/rules/db-avoid-n-plus-one.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdb-avoid-n-plus-one.md -->",".agents/skills/nestjs-best-practices/rules/db-use-migrations.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdb-use-migrations.md -->",".agents/skills/nestjs-best-practices/rules/db-use-transactions.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdb-use-transactions.md -->",".agents/skills/nestjs-best-practices/rules/devops-graceful-shutdown.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdevops-graceful-shutdown.md -->",".agents/skills/nestjs-best-practices/rules/devops-use-config-module.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdevops-use-config-module.md -->",".agents/skills/nestjs-best-practices/rules/devops-use-logging.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdevops-use-logging.md -->",".agents/skills/nestjs-best-practices/rules/di-avoid-service-locator.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-avoid-service-locator.md -->",".agents/skills/nestjs-best-practices/rules/di-interface-segregation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-interface-segregation.md -->",".agents/skills/nestjs-best-practices/rules/di-liskov-substitution.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-liskov-substitution.md -->",".agents/skills/nestjs-best-practices/rules/di-prefer-constructor-injection.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-prefer-constructor-injection.md -->",".agents/skills/nestjs-best-practices/rules/di-scope-awareness.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-scope-awareness.md -->",".agents/skills/nestjs-best-practices/rules/di-use-interfaces-tokens.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-use-interfaces-tokens.md -->",".agents/skills/nestjs-best-practices/rules/error-handle-async-errors.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ferror-handle-async-errors.md -->",".agents/skills/nestjs-best-practices/rules/error-throw-http-exceptions.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ferror-throw-http-exceptions.md -->",".agents/skills/nestjs-best-practices/rules/error-use-exception-filters.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ferror-use-exception-filters.md -->",".agents/skills/nestjs-best-practices/rules/micro-use-health-checks.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fmicro-use-health-checks.md -->",".agents/skills/nestjs-best-practices/rules/micro-use-patterns.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fmicro-use-patterns.md -->",".agents/skills/nestjs-best-practices/rules/micro-use-queues.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fmicro-use-queues.md -->",".agents/skills/nestjs-best-practices/rules/perf-async-hooks.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fperf-async-hooks.md -->",".agents/skills/nestjs-best-practices/rules/perf-lazy-loading.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fperf-lazy-loading.md -->",".agents/skills/nestjs-best-practices/rules/perf-optimize-database.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fperf-optimize-database.md -->",".agents/skills/nestjs-best-practices/rules/perf-use-caching.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fperf-use-caching.md -->",".agents/skills/nestjs-best-practices/rules/security-auth-jwt.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-auth-jwt.md -->",".agents/skills/nestjs-best-practices/rules/security-rate-limiting.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-rate-limiting.md -->",".agents/skills/nestjs-best-practices/rules/security-sanitize-output.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-sanitize-output.md -->",".agents/skills/nestjs-best-practices/rules/security-use-guards.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-use-guards.md -->",".agents/skills/nestjs-best-practices/rules/security-validate-all-input.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-validate-all-input.md -->",".agents/skills/nestjs-best-practices/rules/test-e2e-supertest.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ftest-e2e-supertest.md -->",".agents/skills/nestjs-best-practices/rules/test-mock-external-services.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ftest-mock-external-services.md -->",".agents/skills/nestjs-best-practices/rules/test-use-testing-module.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ftest-use-testing-module.md -->",".agents/skills/nestjs-trpc/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2FSKILL.md -->",".agents/skills/nestjs-trpc/references/api-reference.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Fapi-reference.md -->",".agents/skills/nestjs-trpc/references/codegen-and-client.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Fcodegen-and-client.md -->",".agents/skills/nestjs-trpc/references/middlewares-and-context.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Fmiddlewares-and-context.md -->",".agents/skills/nestjs-trpc/references/module-config.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Fmodule-config.md -->",".agents/skills/nestjs-trpc/references/routers.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Frouters.md -->",".agents/skills/no-use-effect/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fno-use-effect%2FSKILL.md -->",".agents/skills/nuqs/AGENTS.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2FAGENTS.md -->",".agents/skills/nuqs/README.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2FREADME.md -->",".agents/skills/nuqs/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2FSKILL.md -->",".agents/skills/nuqs/assets/templates/_template.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Fassets%2Ftemplates%2F_template.md -->",".agents/skills/nuqs/references/_sections.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2F_sections.md -->",".agents/skills/nuqs/references/advanced-custom-parsers.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-custom-parsers.md -->",".agents/skills/nuqs/references/advanced-eq-function.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-eq-function.md -->",".agents/skills/nuqs/references/advanced-framework-adapters.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-framework-adapters.md -->",".agents/skills/nuqs/references/advanced-process-url-search-params.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-process-url-search-params.md -->",".agents/skills/nuqs/references/advanced-url-keys.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-url-keys.md -->",".agents/skills/nuqs/references/debug-enable-logging.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fdebug-enable-logging.md -->",".agents/skills/nuqs/references/debug-testing.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fdebug-testing.md -->",".agents/skills/nuqs/references/history-push-navigation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fhistory-push-navigation.md -->",".agents/skills/nuqs/references/history-scroll-behavior.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fhistory-scroll-behavior.md -->",".agents/skills/nuqs/references/parser-array-format.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-array-format.md -->",".agents/skills/nuqs/references/parser-date-format.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-date-format.md -->",".agents/skills/nuqs/references/parser-enum-validation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-enum-validation.md -->",".agents/skills/nuqs/references/parser-index-offset.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-index-offset.md -->",".agents/skills/nuqs/references/parser-json-validation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-json-validation.md -->",".agents/skills/nuqs/references/parser-use-typed-parsers.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-use-typed-parsers.md -->",".agents/skills/nuqs/references/parser-with-default.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-with-default.md -->",".agents/skills/nuqs/references/perf-avoid-rerender.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-avoid-rerender.md -->",".agents/skills/nuqs/references/perf-clear-on-default.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-clear-on-default.md -->",".agents/skills/nuqs/references/perf-debounce-search.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-debounce-search.md -->",".agents/skills/nuqs/references/perf-key-isolation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-key-isolation.md -->",".agents/skills/nuqs/references/perf-serialize-utility.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-serialize-utility.md -->",".agents/skills/nuqs/references/perf-throttle-updates.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-throttle-updates.md -->",".agents/skills/nuqs/references/server-next15-async.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-next15-async.md -->",".agents/skills/nuqs/references/server-parse-before-get.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-parse-before-get.md -->",".agents/skills/nuqs/references/server-search-params-cache.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-search-params-cache.md -->",".agents/skills/nuqs/references/server-shallow-false.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-shallow-false.md -->",".agents/skills/nuqs/references/server-use-transition.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-use-transition.md -->",".agents/skills/nuqs/references/setup-default-options.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-default-options.md -->",".agents/skills/nuqs/references/setup-import-server.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-import-server.md -->",".agents/skills/nuqs/references/setup-nextjs-version.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-nextjs-version.md -->",".agents/skills/nuqs/references/setup-nuqs-adapter.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-nuqs-adapter.md -->",".agents/skills/nuqs/references/setup-shared-parsers.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-shared-parsers.md -->",".agents/skills/nuqs/references/setup-use-client.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-use-client.md -->",".agents/skills/nuqs/references/state-avoid-derived.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-avoid-derived.md -->",".agents/skills/nuqs/references/state-clear-with-null.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-clear-with-null.md -->",".agents/skills/nuqs/references/state-options-inheritance.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-options-inheritance.md -->",".agents/skills/nuqs/references/state-setter-return.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-setter-return.md -->",".agents/skills/nuqs/references/state-standard-schema.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-standard-schema.md -->",".agents/skills/nuqs/references/state-use-query-states.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-use-query-states.md -->",".agents/skills/pit-of-success/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fpit-of-success%2FSKILL.md -->",".agents/skills/posthog-instrumentation/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fposthog-instrumentation%2FSKILL.md -->",".agents/skills/prepare-branch-context/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprepare-branch-context%2FSKILL.md -->",".agents/skills/prisma-database-setup/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2FSKILL.md -->",".agents/skills/prisma-database-setup/references/cockroachdb.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fcockroachdb.md -->",".agents/skills/prisma-database-setup/references/mongodb.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fmongodb.md -->",".agents/skills/prisma-database-setup/references/mysql.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fmysql.md -->",".agents/skills/prisma-database-setup/references/postgresql.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fpostgresql.md -->",".agents/skills/prisma-database-setup/references/prisma-client-setup.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fprisma-client-setup.md -->",".agents/skills/prisma-database-setup/references/prisma-postgres.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fprisma-postgres.md -->",".agents/skills/prisma-database-setup/references/sqlite.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fsqlite.md -->",".agents/skills/prisma-database-setup/references/sqlserver.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fsqlserver.md -->",".agents/skills/seo-audit/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fseo-audit%2FSKILL.md -->",".agents/skills/seo-audit/evals/evals.json":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fseo-audit%2Fevals%2Fevals.json -->",".agents/skills/seo-audit/references/ai-writing-detection.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fseo-audit%2Freferences%2Fai-writing-detection.md -->",".agents/skills/seo-audit/references/international-seo.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fseo-audit%2Freferences%2Finternational-seo.md -->",".agents/skills/shadcn/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2FSKILL.md -->",".agents/skills/shadcn/cli.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fcli.md -->",".agents/skills/shadcn/customization.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fcustomization.md -->",".agents/skills/shadcn/evals/evals.json":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fevals%2Fevals.json -->",".agents/skills/shadcn/mcp.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fmcp.md -->",".agents/skills/shadcn/registry.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fregistry.md -->",".agents/skills/shadcn/rules/base-vs-radix.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fbase-vs-radix.md -->",".agents/skills/shadcn/rules/chat.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fchat.md -->",".agents/skills/shadcn/rules/composition.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fcomposition.md -->",".agents/skills/shadcn/rules/forms.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fforms.md -->",".agents/skills/shadcn/rules/icons.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Ficons.md -->",".agents/skills/shadcn/rules/styling.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fstyling.md -->",".agents/skills/skill-creator/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2FSKILL.md -->",".agents/skills/skill-creator/agents/analyzer.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2Fagents%2Fanalyzer.md -->",".agents/skills/skill-creator/agents/comparator.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2Fagents%2Fcomparator.md -->",".agents/skills/skill-creator/agents/grader.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2Fagents%2Fgrader.md -->",".agents/skills/skill-creator/references/schemas.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2Freferences%2Fschemas.md -->",".agents/skills/turborepo/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2FSKILL.md -->",".agents/skills/turborepo/command/turborepo.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Fcommand%2Fturborepo.md -->",".agents/skills/turborepo/references/best-practices/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fbest-practices%2FRULE.md -->",".agents/skills/turborepo/references/best-practices/dependencies.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fbest-practices%2Fdependencies.md -->",".agents/skills/turborepo/references/best-practices/packages.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fbest-practices%2Fpackages.md -->",".agents/skills/turborepo/references/best-practices/structure.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fbest-practices%2Fstructure.md -->",".agents/skills/turborepo/references/boundaries/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fboundaries%2FRULE.md -->",".agents/skills/turborepo/references/caching/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcaching%2FRULE.md -->",".agents/skills/turborepo/references/caching/gotchas.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcaching%2Fgotchas.md -->",".agents/skills/turborepo/references/caching/remote-cache.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcaching%2Fremote-cache.md -->",".agents/skills/turborepo/references/ci/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fci%2FRULE.md -->",".agents/skills/turborepo/references/ci/github-actions.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fci%2Fgithub-actions.md -->",".agents/skills/turborepo/references/ci/patterns.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fci%2Fpatterns.md -->",".agents/skills/turborepo/references/ci/vercel.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fci%2Fvercel.md -->",".agents/skills/turborepo/references/cli/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcli%2FRULE.md -->",".agents/skills/turborepo/references/cli/commands.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcli%2Fcommands.md -->",".agents/skills/turborepo/references/configuration/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fconfiguration%2FRULE.md -->",".agents/skills/turborepo/references/configuration/global-options.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fconfiguration%2Fglobal-options.md -->",".agents/skills/turborepo/references/configuration/gotchas.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fconfiguration%2Fgotchas.md -->",".agents/skills/turborepo/references/configuration/tasks.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fconfiguration%2Ftasks.md -->",".agents/skills/turborepo/references/environment/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fenvironment%2FRULE.md -->",".agents/skills/turborepo/references/environment/gotchas.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fenvironment%2Fgotchas.md -->",".agents/skills/turborepo/references/environment/modes.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fenvironment%2Fmodes.md -->",".agents/skills/turborepo/references/filtering/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Ffiltering%2FRULE.md -->",".agents/skills/turborepo/references/filtering/patterns.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Ffiltering%2Fpatterns.md -->",".agents/skills/turborepo/references/watch/RULE.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fwatch%2FRULE.md -->",".agents/skills/typescript-advanced-types/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Ftypescript-advanced-types%2FSKILL.md -->",".agents/skills/typescript-advanced-types/references/details.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Ftypescript-advanced-types%2Freferences%2Fdetails.md -->",".agents/skills/ux-flow-plan/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fux-flow-plan%2FSKILL.md -->",".agents/skills/vercel-composition-patterns/AGENTS.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2FAGENTS.md -->",".agents/skills/vercel-composition-patterns/README.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2FREADME.md -->",".agents/skills/vercel-composition-patterns/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2FSKILL.md -->",".agents/skills/vercel-composition-patterns/metadata.json":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Fmetadata.json -->",".agents/skills/vercel-composition-patterns/rules/_sections.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2F_sections.md -->",".agents/skills/vercel-composition-patterns/rules/_template.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2F_template.md -->",".agents/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Farchitecture-avoid-boolean-props.md -->",".agents/skills/vercel-composition-patterns/rules/architecture-compound-components.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Farchitecture-compound-components.md -->",".agents/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fpatterns-children-over-render-props.md -->",".agents/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fpatterns-explicit-variants.md -->",".agents/skills/vercel-composition-patterns/rules/react19-no-forwardref.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Freact19-no-forwardref.md -->",".agents/skills/vercel-composition-patterns/rules/state-context-interface.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fstate-context-interface.md -->",".agents/skills/vercel-composition-patterns/rules/state-decouple-implementation.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fstate-decouple-implementation.md -->",".agents/skills/vercel-composition-patterns/rules/state-lift-state.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fstate-lift-state.md -->",".agents/skills/vercel-react-best-practices/AGENTS.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2FAGENTS.md -->",".agents/skills/vercel-react-best-practices/README.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2FREADME.md -->",".agents/skills/vercel-react-best-practices/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2FSKILL.md -->",".agents/skills/vercel-react-best-practices/metadata.json":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Fmetadata.json -->",".agents/skills/vercel-react-best-practices/rules/_sections.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2F_sections.md -->",".agents/skills/vercel-react-best-practices/rules/_template.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2F_template.md -->",".agents/skills/vercel-react-best-practices/rules/advanced-effect-event-deps.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fadvanced-effect-event-deps.md -->",".agents/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fadvanced-event-handler-refs.md -->",".agents/skills/vercel-react-best-practices/rules/advanced-init-once.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fadvanced-init-once.md -->",".agents/skills/vercel-react-best-practices/rules/advanced-use-latest.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fadvanced-use-latest.md -->",".agents/skills/vercel-react-best-practices/rules/async-api-routes.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-api-routes.md -->",".agents/skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-cheap-condition-before-await.md -->",".agents/skills/vercel-react-best-practices/rules/async-defer-await.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-defer-await.md -->",".agents/skills/vercel-react-best-practices/rules/async-dependencies.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-dependencies.md -->",".agents/skills/vercel-react-best-practices/rules/async-parallel.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-parallel.md -->",".agents/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-suspense-boundaries.md -->",".agents/skills/vercel-react-best-practices/rules/bundle-analyzable-paths.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-analyzable-paths.md -->",".agents/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-barrel-imports.md -->",".agents/skills/vercel-react-best-practices/rules/bundle-conditional.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-conditional.md -->",".agents/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-defer-third-party.md -->",".agents/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-dynamic-imports.md -->",".agents/skills/vercel-react-best-practices/rules/bundle-preload.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-preload.md -->",".agents/skills/vercel-react-best-practices/rules/client-event-listeners.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fclient-event-listeners.md -->",".agents/skills/vercel-react-best-practices/rules/client-localstorage-schema.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fclient-localstorage-schema.md -->",".agents/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fclient-passive-event-listeners.md -->",".agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fclient-swr-dedup.md -->",".agents/skills/vercel-react-best-practices/rules/js-batch-dom-css.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-batch-dom-css.md -->",".agents/skills/vercel-react-best-practices/rules/js-cache-function-results.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-cache-function-results.md -->",".agents/skills/vercel-react-best-practices/rules/js-cache-property-access.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-cache-property-access.md -->",".agents/skills/vercel-react-best-practices/rules/js-cache-storage.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-cache-storage.md -->",".agents/skills/vercel-react-best-practices/rules/js-combine-iterations.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-combine-iterations.md -->",".agents/skills/vercel-react-best-practices/rules/js-early-exit.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-early-exit.md -->",".agents/skills/vercel-react-best-practices/rules/js-flatmap-filter.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-flatmap-filter.md -->",".agents/skills/vercel-react-best-practices/rules/js-hoist-regexp.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-hoist-regexp.md -->",".agents/skills/vercel-react-best-practices/rules/js-index-maps.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-index-maps.md -->",".agents/skills/vercel-react-best-practices/rules/js-length-check-first.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-length-check-first.md -->",".agents/skills/vercel-react-best-practices/rules/js-min-max-loop.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-min-max-loop.md -->",".agents/skills/vercel-react-best-practices/rules/js-request-idle-callback.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-request-idle-callback.md -->",".agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-set-map-lookups.md -->",".agents/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-tosorted-immutable.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-activity.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-activity.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-animate-svg-wrapper.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-conditional-render.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-conditional-render.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-content-visibility.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-content-visibility.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-hoist-jsx.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-hydration-no-flicker.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-hydration-suppress-warning.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-resource-hints.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-resource-hints.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-script-defer-async.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-svg-precision.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-svg-precision.md -->",".agents/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-usetransition-loading.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-defer-reads.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-defer-reads.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-dependencies.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-dependencies.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-derived-state-no-effect.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-derived-state.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-derived-state.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-functional-setstate.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-lazy-state-init.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-memo-with-default-value.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-memo.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-memo.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-move-effect-to-event.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-no-inline-components.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-simple-expression-in-memo.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-split-combined-hooks.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-transitions.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-transitions.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-use-deferred-value.md -->",".agents/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-use-ref-transient-values.md -->",".agents/skills/vercel-react-best-practices/rules/server-after-nonblocking.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-after-nonblocking.md -->",".agents/skills/vercel-react-best-practices/rules/server-auth-actions.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-auth-actions.md -->",".agents/skills/vercel-react-best-practices/rules/server-cache-lru.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-cache-lru.md -->",".agents/skills/vercel-react-best-practices/rules/server-cache-react.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-cache-react.md -->",".agents/skills/vercel-react-best-practices/rules/server-dedup-props.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-dedup-props.md -->",".agents/skills/vercel-react-best-practices/rules/server-hoist-static-io.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-hoist-static-io.md -->",".agents/skills/vercel-react-best-practices/rules/server-no-shared-module-state.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-no-shared-module-state.md -->",".agents/skills/vercel-react-best-practices/rules/server-parallel-fetching.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-parallel-fetching.md -->",".agents/skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-parallel-nested-fetching.md -->",".agents/skills/vercel-react-best-practices/rules/server-serialization.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-serialization.md -->",".agents/skills/web-design-guidelines/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fweb-design-guidelines%2FSKILL.md -->",".agents/skills/zero-tech-debt/SKILL.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fzero-tech-debt%2FSKILL.md -->","AGENTS.md":"# Strict rules — review before starting any work\n\n**Read the doc for the area you are touching before you touch it.** The table\nbelow is the whole index. These are plain paths, not imports: they are not in your\ncontext until you read them, and the rules in them are not optional.\n\n| Working on | Read first |\n| --- | --- |\n| Anything in `apps/api` — tRPC, auth, logging, sync, deletes, caching | `docs/api.md` |\n| `apps/agent` — the eve research agent, tools, tasks, dispatch | `docs/agent.md` |\n| `.env`, configuration, which variables exist and why | `docs/environment.md` |\n| UI in `apps/app` or `packages/ui` | `docs/design.md` (below) |\n| Deal amounts, totals, charts, exchange rates | `docs/currency.md` |\n| The record sheet's Agent tab | `docs/agent-panel.md` |\n| `/settings/connections`, integrations, the intake endpoint | `docs/connections.md` |\n| The tracking script, the collector, form submissions | `docs/tracking.md` |\n| Running it locally, Google Cloud, DB commands, secrets | `docs/setup.md` |\n| Anything that sends a telemetry event, or a new property on one | `docs/telemetry.md` |\n| `.github/workflows`, versions, changelog, how a change reaches `release` | `CONTRIBUTING.md` |\n\nAlso check `.agents/skills/` for a relevant skill before starting — better-auth,\nprisma, nestjs-trpc, eve, shadcn, nuqs and others have one. Tell the user which\nrules and skills you read.\n\n## Always true\n\n- **Never add code comments.** Not to new code, not to code you edit.\n- **No coauthoring commits.** No `Co-Authored-By` trailer, ever.\n- **Intelligence lives in `apps/agent`, never in the API.** No vendor client, no\n  enrichment, no scoring, no identity matching in Nest — it writes an `AgentTask`\n  row and lets the agent decide. See `docs/api.md`.\n- **One `.env`, at the repo root.** `.env.example` is its documentation: add every\n  new variable there with a note on what it does, and declare it in\n  `apps/api/src/config/env.validation.ts` if the API reads it. Never add a\n  per-package `.env`.\n- **Anything a self-hoster might not have is optional and must never throw.** A\n  missing key removes a capability. `apps/agent/agent/lib/capabilities.ts` is the\n  pattern.\n- **`/packages/ui` is the single source of truth for UI.** Shared shadcn\n  components only; a new variant is implemented there, not overridden at the call\n  site.\n- **eve's own docs ship in `apps/agent/node_modules/eve/docs`** and match the\n  installed version. Read the relevant guide before writing eve code rather than\n  working from memory — guessing typechecks, builds, and then behaves differently.\n\n## Report every issue. Use ASD-STE100\n\nDo not bury a known problem inside a paragraph. A problem inside prose is a\nproblem nobody reads. Report **every** issue, including ones you caused, in a\nlist at the end of your reply.\n\nWrite every message, every report and every issue in **ASD-STE100**\n(Simplified Technical English):\n\n- One idea per sentence. Maximum 20 words.\n- Active voice. Present tense. No conditionals.\n- One word for one meaning. Do not use synonyms for variety.\n- Say the effect, not only the cause.\n- No hedging: never \"may\", \"might\", \"possibly\", \"somewhat\".\n\nUse exactly this shape:\n\n```\n## Issues\n\n1. BROKEN — Slack is not connected. Agents that post to Slack fail.\n   Fix: connect Slack in Settings → Connections.\n2. RISK — A run longer than 5 minutes is cancelled. Work is lost.\n   Fix: not done. Needs a separate execution lease.\n3. NOT DONE — The manual run button shows on event-only agents.\n```\n\nRules for the list:\n\n- One line for the problem. One line for the fix.\n- Start each with **BROKEN**, **RISK**, **NOT DONE**, or **UNKNOWN**.\n- **BROKEN** is failing now. **RISK** fails later. **NOT DONE** is unbuilt.\n  **UNKNOWN** is not investigated.\n- If you introduced it, write **I caused this** on the fix line.\n- Zero issues? Write `## Issues` then `None.`\n\n**Don't** — bury it in prose:\n\n> The fix works well. One honest limit: abandoning a sweep unblocks the queue but\n> doesn't cancel the underlying hung promise, so it leaks until restart.\n\n**Do** — put it in the list:\n\n> 1. RISK — An abandoned sweep leaks its promise. Memory grows until restart.\n>    Fix: not done. Needs cancellation in `receive()`. I caused this.\n\n## A server page computes. A client component renders.\n\nA client component must never import a server package. `@crm/auth` and `@crm/db`\nare server packages: their barrels reach Prisma, which reaches `pg`, which\nreaches `dns`. The bundler follows that chain into the browser and the build\nfails with `Module not found: Can't resolve 'dns'`.\n\nThe import trace is the whole error. Read it from the bottom: the last line is\nthe page, the line above is the client component that leaked, and the top is the\nNode module that cannot exist in a browser.\n\n**Don't** — a client component reaching for a server package:\n\n```tsx\n\"use client\";\nimport {\n  describeSlackScopes,\n  SLACK_SCOPE_GROUPS,\n} from \"@crm/auth/slack-scopes\";\n\nexport function SlackScopeGroups({ scopes }: { scopes: string[] }) {\n  const groups = SLACK_SCOPE_GROUPS.map(...)\n}\n```\n\n**Do** — the page does the work and hands over plain data:\n\n```tsx\n// page.tsx — server\nimport {\n  describeSlackScopes,\n  SLACK_SCOPE_GROUPS,\n} from \"@crm/auth/slack-scopes\";\n\nconst groups = groupScopes(status.scopes);\nreturn <SlackScopeGroups groups={groups} />;\n```\n\n```tsx\n// slack-scope-groups.tsx — client\n\"use client\";\n\nexport type ScopeGroup = { id: string; label: string; scopes: ScopeLine[] };\n\nexport function SlackScopeGroups({ groups }: { groups: ScopeGroup[] }) { … }\n```\n\nRules that follow:\n\n- The client component owns its own prop types. It does not re-export a server\n  type to get them.\n- Anything interactive — an accordion, a dialog, a search field — is a client\n  component that receives finished data. It never derives it.\n- A `\"use client\"` file may import from `@crm/ui`, the tRPC client, and React.\n  Anything else needs checking.\n- The server page is where `await` and secrets live. The client file has neither.\n\n## Constants belong in one file per area, not beside their first use\n\nA number that someone will want to tune goes in a named config module for its\narea. It does not go at the top of whichever file happened to need it first.\nSomebody changing a timeout must not have to know which file to open.\n\n**Don't** — one constant per file, found only by grep:\n\n```ts\n// dispatch.ts\nconst DRAIN_TIMEOUT_MS = 4 * 60_000;\n// crm.ts\nconst STALE_QUEUE_MS = 5 * 60_000;\n// tasks.ts\nconst LEASE_MS = 10 * 60_000;\n```\n\n**Do** — one object, grouped by concern, imported where used:\n\n```ts\n// dispatch-config.ts\nexport const DISPATCH = {\n  sweep: { timeoutMs: 4 * MINUTE_MS, staleQueueMs: 5 * MINUTE_MS },\n  task: { leaseMs: 10 * MINUTE_MS },\n} as const;\n```\n\n`apps/agent/agent/lib/dispatch-config.ts` is the pattern. Rules:\n\n- Group by concern, not by file that uses it.\n- Derive units from one base (`MINUTE_MS`). Never write `4 * 60_000` twice.\n- `as const`, so the values are literal types.\n- No magic numbers inline. If it is tunable, it belongs in the config.\n- One convention across the codebase. Do not invent a local style for one file.\n\n## Parse at the boundary, never pass `Record<string, unknown>` around\n\nUntyped data — a Prisma `Json` column, a webhook body, an API response — is\nparsed into a **domain type at the moment it enters the process**, with Zod, in a\nmodule that owns that shape. Every consumer downstream receives the parsed type\nand nothing else. `Record<string, unknown>`, `unknown` casts and one-off\n`recordOf()` helpers are how a shape becomes unknowable and a typo becomes a\nruntime bug two files away.\n\n**Don't** — reach into raw JSON, re-deriving the shape at each call site:\n\n```ts\nfunction manifestActions(value: unknown) {\n  const actions = recordOf(value).actions;\n  return Array.isArray(actions) ? actions.map(recordOf) : [];\n}\n\nconst slack = manifestActions(version.manifest).find(\n  (action) => action.type === \"slack.message.post\",\n);\nconst id = (slack?.destination as Record<string, unknown>)?.id;\n```\n\nNothing here is checked. `destination` may be missing, `id` may be a number, and\nthe compiler cannot help. Rename a field and every one of these silently returns\n`undefined`.\n\n**Do** — one schema, parsed once, at the read:\n\n```ts\nexport const agentManifestAction = z.discriminatedUnion(\"type\", [\n  z.object({\n    type: z.literal(AGENT_ACTION_TYPES.SLACK_MESSAGE_POST),\n    provider: z.literal(\"slack\"),\n    summary: z.string(),\n    destination: z.object({\n      kind: z.enum([\"channel\", \"user\"]),\n      resolution: z.literal(\"chosen\"),\n      id: z.string().trim().min(1).max(120),\n      label: z.string().trim().min(1).max(120),\n    }),\n  }),\n]);\n\nexport type AgentManifest = z.infer<typeof agentManifest>;\n\nexport function parseAgentManifest(value: unknown): AgentManifest { … }\n```\n\n```ts\nconst manifest = parseAgentManifest(version.manifest);\nconst slack = manifest.actions.find(\n  (action) => action.type === \"slack.message.post\",\n);\nconst id = slack?.destination.id;\n```\n\n`packages/validation/src/agent-manifest.ts` is the pattern. A shape that crosses\na package boundary — a `Json` column two apps read, a payload one app writes and\nanother consumes — lives in `packages/validation/src`, one module per shape, and\nis imported by subpath (`@crm/validation/agent-manifest`). Rules that follow from\nit:\n\n- The schema describes what is **actually stored**, not the loosest thing that\n  parses. If a test fixture fails the schema, fix the fixture — a fixture that\n  omits required fields is testing data that cannot exist.\n- Parse failure is a real error with a real message. Do not swallow it into an\n  empty array, because \"unreadable manifest\" and \"no actions\" are different\n  problems and only one of them is the user's fault.\n- Derive types with `z.infer`. Never hand-write an interface beside a schema;\n  they drift.\n\n## Design\n\n@docs/design.md\n\n## Commit Messages & Pull Requests\n\n**Branch from `main`, never from `release`.** `release` is the default branch so\nthat a plain clone runs the last tagged release, and the only things that merge\ninto it are release pull requests. A branch cut from `release` carries release\nmerge commits that do not belong in a feature pull request.\n\n**You do not write the pull request title.** `.github/scripts/pr-title.sh` reads\nthe diff and writes one. Retitle it yourself and the automation stops.\n`CONTRIBUTING.md` is the whole account of how a change reaches `release`; read it\nbefore shipping.\n","CLAUDE.md":"@AGENTS.md\n","apps/agent/agent/skills/data-boundaries.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=apps%2Fagent%2Fagent%2Fskills%2Fdata-boundaries.md -->","apps/agent/agent/skills/evidence.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=apps%2Fagent%2Fagent%2Fskills%2Fevidence.md -->","apps/agent/agent/skills/identity-matching.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=apps%2Fagent%2Fagent%2Fskills%2Fidentity-matching.md -->","apps/agent/agent/skills/writing-a-brief.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=apps%2Fagent%2Fagent%2Fskills%2Fwriting-a-brief.md -->","docs/api.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=docs%2Fapi.md -->","docs/design.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=docs%2Fdesign.md -->","packages/auth/README.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=packages%2Fauth%2FREADME.md -->","packages/db/README.md":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=packages%2Fdb%2FREADME.md -->"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Strict rules — review before starting any work\n\n**Read the doc for the area you are touching before you touch it.** The table\nbelow is the whole index. These are plain paths, not imports: they are not in your\ncontext until you read them, and the rules in them are not optional.\n\n| Working on | Read first |\n| --- | --- |\n| Anything in `apps/api` — tRPC, auth, logging, sync, deletes, caching | `docs/api.md` |\n| `apps/agent` — the eve research agent, tools, tasks, dispatch | `docs/agent.md` |\n| `.env`, configuration, which variables exist and why | `docs/environment.md` |\n| UI in `apps/app` or `packages/ui` | `docs/design.md` (below) |\n| Deal amounts, totals, charts, exchange rates | `docs/currency.md` |\n| The record sheet's Agent tab | `docs/agent-panel.md` |\n| `/settings/connections`, integrations, the intake endpoint | `docs/connections.md` |\n| The tracking script, the collector, form submissions | `docs/tracking.md` |\n| Running it locally, Google Cloud, DB commands, secrets | `docs/setup.md` |\n| Anything that sends a telemetry event, or a new property on one | `docs/telemetry.md` |\n| `.github/workflows`, versions, changelog, how a change reaches `release` | `CONTRIBUTING.md` |\n\nAlso check `.agents/skills/` for a relevant skill before starting — better-auth,\nprisma, nestjs-trpc, eve, shadcn, nuqs and others have one. Tell the user which\nrules and skills you read.\n\n## Always true\n\n- **Never add code comments.** Not to new code, not to code you edit.\n- **No coauthoring commits.** No `Co-Authored-By` trailer, ever.\n- **Intelligence lives in `apps/agent`, never in the API.** No vendor client, no\n  enrichment, no scoring, no identity matching in Nest — it writes an `AgentTask`\n  row and lets the agent decide. See `docs/api.md`.\n- **One `.env`, at the repo root.** `.env.example` is its documentation: add every\n  new variable there with a note on what it does, and declare it in\n  `apps/api/src/config/env.validation.ts` if the API reads it. Never add a\n  per-package `.env`.\n- **Anything a self-hoster might not have is optional and must never throw.** A\n  missing key removes a capability. `apps/agent/agent/lib/capabilities.ts` is the\n  pattern.\n- **`/packages/ui` is the single source of truth for UI.** Shared shadcn\n  components only; a new variant is implemented there, not overridden at the call\n  site.\n- **eve's own docs ship in `apps/agent/node_modules/eve/docs`** and match the\n  installed version. Read the relevant guide before writing eve code rather than\n  working from memory — guessing typechecks, builds, and then behaves differently.\n\n## Report every issue. Use ASD-STE100\n\nDo not bury a known problem inside a paragraph. A problem inside prose is a\nproblem nobody reads. Report **every** issue, including ones you caused, in a\nlist at the end of your reply.\n\nWrite every message, every report and every issue in **ASD-STE100**\n(Simplified Technical English):\n\n- One idea per sentence. Maximum 20 words.\n- Active voice. Present tense. No conditionals.\n- One word for one meaning. Do not use synonyms for variety.\n- Say the effect, not only the cause.\n- No hedging: never \"may\", \"might\", \"possibly\", \"somewhat\".\n\nUse exactly this shape:\n\n```\n## Issues\n\n1. BROKEN — Slack is not connected. Agents that post to Slack fail.\n   Fix: connect Slack in Settings → Connections.\n2. RISK — A run longer than 5 minutes is cancelled. Work is lost.\n   Fix: not done. Needs a separate execution lease.\n3. NOT DONE — The manual run button shows on event-only agents.\n```\n\nRules for the list:\n\n- One line for the problem. One line for the fix.\n- Start each with **BROKEN**, **RISK**, **NOT DONE**, or **UNKNOWN**.\n- **BROKEN** is failing now. **RISK** fails later. **NOT DONE** is unbuilt.\n  **UNKNOWN** is not investigated.\n- If you introduced it, write **I caused this** on the fix line.\n- Zero issues? Write `## Issues` then `None.`\n\n**Don't** — bury it in prose:\n\n> The fix works well. One honest limit: abandoning a sweep unblocks the queue but\n> doesn't cancel the underlying hung promise, so it leaks until restart.\n\n**Do** — put it in the list:\n\n> 1. RISK — An abandoned sweep leaks its promise. Memory grows until restart.\n>    Fix: not done. Needs cancellation in `receive()`. I caused this.\n\n## A server page computes. A client component renders.\n\nA client component must never import a server package. `@crm/auth` and `@crm/db`\nare server packages: their barrels reach Prisma, which reaches `pg`, which\nreaches `dns`. The bundler follows that chain into the browser and the build\nfails with `Module not found: Can't resolve 'dns'`.\n\nThe import trace is the whole error. Read it from the bottom: the last line is\nthe page, the line above is the client component that leaked, and the top is the\nNode module that cannot exist in a browser.\n\n**Don't** — a client component reaching for a server package:\n\n```tsx\n\"use client\";\nimport {\n  describeSlackScopes,\n  SLACK_SCOPE_GROUPS,\n} from \"@crm/auth/slack-scopes\";\n\nexport function SlackScopeGroups({ scopes }: { scopes: string[] }) {\n  const groups = SLACK_SCOPE_GROUPS.map(...)\n}\n```\n\n**Do** — the page does the work and hands over plain data:\n\n```tsx\n// page.tsx — server\nimport {\n  describeSlackScopes,\n  SLACK_SCOPE_GROUPS,\n} from \"@crm/auth/slack-scopes\";\n\nconst groups = groupScopes(status.scopes);\nreturn <SlackScopeGroups groups={groups} />;\n```\n\n```tsx\n// slack-scope-groups.tsx — client\n\"use client\";\n\nexport type ScopeGroup = { id: string; label: string; scopes: ScopeLine[] };\n\nexport function SlackScopeGroups({ groups }: { groups: ScopeGroup[] }) { … }\n```\n\nRules that follow:\n\n- The client component owns its own prop types. It does not re-export a server\n  type to get them.\n- Anything interactive — an accordion, a dialog, a search field — is a client\n  component that receives finished data. It never derives it.\n- A `\"use client\"` file may import from `@crm/ui`, the tRPC client, and React.\n  Anything else needs checking.\n- The server page is where `await` and secrets live. The client file has neither.\n\n## Constants belong in one file per area, not beside their first use\n\nA number that someone will want to tune goes in a named config module for its\narea. It does not go at the top of whichever file happened to need it first.\nSomebody changing a timeout must not have to know which file to open.\n\n**Don't** — one constant per file, found only by grep:\n\n```ts\n// dispatch.ts\nconst DRAIN_TIMEOUT_MS = 4 * 60_000;\n// crm.ts\nconst STALE_QUEUE_MS = 5 * 60_000;\n// tasks.ts\nconst LEASE_MS = 10 * 60_000;\n```\n\n**Do** — one object, grouped by concern, imported where used:\n\n```ts\n// dispatch-config.ts\nexport const DISPATCH = {\n  sweep: { timeoutMs: 4 * MINUTE_MS, staleQueueMs: 5 * MINUTE_MS },\n  task: { leaseMs: 10 * MINUTE_MS },\n} as const;\n```\n\n`apps/agent/agent/lib/dispatch-config.ts` is the pattern. Rules:\n\n- Group by concern, not by file that uses it.\n- Derive units from one base (`MINUTE_MS`). Never write `4 * 60_000` twice.\n- `as const`, so the values are literal types.\n- No magic numbers inline. If it is tunable, it belongs in the config.\n- One convention across the codebase. Do not invent a local style for one file.\n\n## Parse at the boundary, never pass `Record<string, unknown>` around\n\nUntyped data — a Prisma `Json` column, a webhook body, an API response — is\nparsed into a **domain type at the moment it enters the process**, with Zod, in a\nmodule that owns that shape. Every consumer downstream receives the parsed type\nand nothing else. `Record<string, unknown>`, `unknown` casts and one-off\n`recordOf()` helpers are how a shape becomes unknowable and a typo becomes a\nruntime bug two files away.\n\n**Don't** — reach into raw JSON, re-deriving the shape at each call site:\n\n```ts\nfunction manifestActions(value: unknown) {\n  const actions = recordOf(value).actions;\n  return Array.isArray(actions) ? actions.map(recordOf) : [];\n}\n\nconst slack = manifestActions(version.manifest).find(\n  (action) => action.type === \"slack.message.post\",\n);\nconst id = (slack?.destination as Record<string, unknown>)?.id;\n```\n\nNothing here is checked. `destination` may be missing, `id` may be a number, and\nthe compiler cannot help. Rename a field and every one of these silently returns\n`undefined`.\n\n**Do** — one schema, parsed once, at the read:\n\n```ts\nexport const agentManifestAction = z.discriminatedUnion(\"type\", [\n  z.object({\n    type: z.literal(AGENT_ACTION_TYPES.SLACK_MESSAGE_POST),\n    provider: z.literal(\"slack\"),\n    summary: z.string(),\n    destination: z.object({\n      kind: z.enum([\"channel\", \"user\"]),\n      resolution: z.literal(\"chosen\"),\n      id: z.string().trim().min(1).max(120),\n      label: z.string().trim().min(1).max(120),\n    }),\n  }),\n]);\n\nexport type AgentManifest = z.infer<typeof agentManifest>;\n\nexport function parseAgentManifest(value: unknown): AgentManifest { … }\n```\n\n```ts\nconst manifest = parseAgentManifest(version.manifest);\nconst slack = manifest.actions.find(\n  (action) => action.type === \"slack.message.post\",\n);\nconst id = slack?.destination.id;\n```\n\n`packages/validation/src/agent-manifest.ts` is the pattern. A shape that crosses\na package boundary — a `Json` column two apps read, a payload one app writes and\nanother consumes — lives in `packages/validation/src`, one module per shape, and\nis imported by subpath (`@crm/validation/agent-manifest`). Rules that follow from\nit:\n\n- The schema describes what is **actually stored**, not the loosest thing that\n  parses. If a test fixture fails the schema, fix the fixture — a fixture that\n  omits required fields is testing data that cannot exist.\n- Parse failure is a real error with a real message. Do not swallow it into an\n  empty array, because \"unreadable manifest\" and \"no actions\" are different\n  problems and only one of them is the user's fault.\n- Derive types with `z.infer`. Never hand-write an interface beside a schema;\n  they drift.\n\n## Design\n\n@docs/design.md\n\n## Commit Messages & Pull Requests\n\n**Branch from `main`, never from `release`.** `release` is the default branch so\nthat a plain clone runs the last tagged release, and the only things that merge\ninto it are release pull requests. A branch cut from `release` carries release\nmerge commits that do not belong in a feature pull request.\n\n**You do not write the pull request title.** `.github/scripts/pr-title.sh` reads\nthe diff and writes one. Retitle it yourself and the automation stops.\n`CONTRIBUTING.md` is the whole account of how a change reaches `release`; read it\nbefore shipping.\n","isInternal":false,"tokens":2634,"sizeBytes":10538},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"@AGENTS.md\n","isInternal":false,"tokens":5,"sizeBytes":11},{"name":"agent.md","path":".agents/skills/ai-elements/references/agent.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/agent.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Agent\n\nA composable component for displaying AI agent configuration with model, instructions, tools, and output schema.\n\nThe `Agent` component displays an interface for showing AI agent configuration details. It's designed to represent a configured agent from the AI SDK, showing the agent's model, system instructions, available tools (with expandable input schemas), and output schema.\n\nSee `scripts/agent.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add agent\n```\n\n## Usage with AI SDK\n\nDisplay an agent's configuration alongside your chat interface. Tools are displayed in an accordion where clicking the description expands to show the input schema.\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport {\n  Agent,\n  AgentContent,\n  AgentHeader,\n  AgentInstructions,\n  AgentOutput,\n  AgentTool,\n  AgentTools,\n} from \"@/components/ai-elements/agent\";\n\nconst webSearch = tool({\n  description: \"Search the web for information\",\n  inputSchema: z.object({\n    query: z.string().describe(\"The search query\"),\n  }),\n});\n\nconst readUrl = tool({\n  description: \"Read and parse content from a URL\",\n  inputSchema: z.object({\n    url: z.string().url().describe(\"The URL to read\"),\n  }),\n});\n\nconst outputSchema = `z.object({\n  sentiment: z.enum(['positive', 'negative', 'neutral']),\n  score: z.number(),\n  summary: z.string(),\n})`;\n\nexport default function Page() {\n  return (\n    <Agent>\n      <AgentHeader\n        name=\"Sentiment Analyzer\"\n        model=\"anthropic/claude-sonnet-4-5\"\n      />\n      <AgentContent>\n        <AgentInstructions>\n          Analyze the sentiment of the provided text and return a structured\n          analysis with sentiment classification, confidence score, and summary.\n        </AgentInstructions>\n        <AgentTools>\n          <AgentTool tool={webSearch} value=\"web_search\" />\n          <AgentTool tool={readUrl} value=\"read_url\" />\n        </AgentTools>\n        <AgentOutput schema={outputSchema} />\n      </AgentContent>\n    </Agent>\n  );\n}\n```\n\n## Features\n\n- Model badge in header\n- Instructions rendered as markdown\n- Tools displayed as accordion items with expandable input schemas\n- Output schema display with syntax highlighting\n- Composable structure for flexible layouts\n- Works with AI SDK `Tool` type\n\n## Props\n\n### `<Agent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any props are spread to the root div. |\n\n### `<AgentHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | The name of the agent. |\n| `model` | `string` | - | The model identifier (e.g.  |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n### `<AgentContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n### `<AgentInstructions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | Required | The instruction text. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n### `<AgentTools />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Accordion>` | - | Any other props are spread to the Accordion component. |\n\n### `<AgentTool />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tool` | `Tool` | Required | The tool object from the AI SDK containing description and inputSchema. |\n| `value` | `string` | Required | Unique identifier for the accordion item. |\n| `...props` | `React.ComponentProps<typeof AccordionItem>` | - | Any other props are spread to the AccordionItem component. |\n\n### `<AgentOutput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `schema` | `string` | Required | The output schema as a string (displayed with syntax highlighting). |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n","isInternal":false,"tokens":1003,"sizeBytes":4235},{"name":"artifact.md","path":".agents/skills/ai-elements/references/artifact.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/artifact.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Artifact\n\nA container component for displaying generated content like code, documents, or other outputs with built-in actions.\n\nThe `Artifact` component provides a structured container for displaying generated content like code, documents, or other outputs with built-in header actions.\n\nSee `scripts/artifact.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add artifact\n```\n\n## Features\n\n- Structured container with header and content areas\n- Built-in header with title and description support\n- Flexible action buttons with tooltips\n- Customizable styling for all subcomponents\n- Support for close buttons and action groups\n- Clean, modern design with border and shadow\n- Responsive layout that adapts to content\n- TypeScript support with proper type definitions\n- Composable architecture for maximum flexibility\n\n## Examples\n\n### With Code Display\n\nSee `scripts/artifact.tsx` for this example.\n\n## Props\n\n### `<Artifact />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n### `<ArtifactHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n### `<ArtifactTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Any other props are spread to the underlying paragraph element. |\n\n### `<ArtifactDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Any other props are spread to the underlying paragraph element. |\n\n### `<ArtifactActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n### `<ArtifactAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string` | - | Tooltip text to display on hover. |\n| `label` | `string` | - | Screen reader label for the action button. |\n| `icon` | `LucideIcon` | - | Lucide icon component to display in the button. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<ArtifactClose />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<ArtifactContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n","isInternal":false,"tokens":673,"sizeBytes":3017},{"name":"attachments.md","path":".agents/skills/ai-elements/references/attachments.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/attachments.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Attachments\n\nA flexible, composable attachment component for displaying files, images, videos, audio, and source documents.\n\nThe `Attachment` component provides a unified way to display file attachments and source documents with multiple layout variants.\n\nSee `scripts/attachments.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add attachments\n```\n\n## Usage with AI SDK\n\nDisplay user-uploaded files in chat messages or input areas.\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Attachments,\n  Attachment,\n  AttachmentPreview,\n  AttachmentInfo,\n  AttachmentRemove,\n} from \"@/components/ai-elements/attachments\";\nimport type { FileUIPart } from \"ai\";\n\ninterface MessageProps {\n  attachments: (FileUIPart & { id: string })[];\n  onRemove?: (id: string) => void;\n}\n\nconst MessageAttachments = ({ attachments, onRemove }: MessageProps) => (\n  <Attachments variant=\"grid\">\n    {attachments.map((file) => (\n      <Attachment\n        key={file.id}\n        data={file}\n        onRemove={onRemove ? () => onRemove(file.id) : undefined}\n      >\n        <AttachmentPreview />\n        <AttachmentRemove />\n      </Attachment>\n    ))}\n  </Attachments>\n);\n\nexport default MessageAttachments;\n```\n\n## Features\n\n- Three display variants: grid (thumbnails), inline (badges), and list (rows)\n- Supports both FileUIPart and SourceDocumentUIPart from the AI SDK\n- Automatic media type detection (image, video, audio, document, source)\n- Hover card support for inline previews\n- Remove button with customizable callback\n- Composable architecture for maximum flexibility\n- Accessible with proper ARIA labels\n- TypeScript support with exported utility functions\n\n## Examples\n\n### Grid Variant\n\nBest for displaying attachments in messages with visual thumbnails.\n\nSee `scripts/attachments.tsx` for this example.\n\n### Inline Variant\n\nBest for compact badge-style display in input areas with hover previews.\n\nSee `scripts/attachments-inline.tsx` for this example.\n\n### List Variant\n\nBest for file lists with full metadata display.\n\nSee `scripts/attachments-list.tsx` for this example.\n\n## Props\n\n### `<Attachments />`\n\nContainer component that sets the layout variant.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `variant` | `unknown` | - | The display layout variant. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<Attachment />`\n\nIndividual attachment item wrapper.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `data` | `unknown` | - | The attachment data (FileUIPart or SourceDocumentUIPart with id). |\n| `onRemove` | `() => void` | - | Callback fired when the remove button is clicked. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<AttachmentPreview />`\n\nDisplays the media preview (image, video, or icon).\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `fallbackIcon` | `React.ReactNode` | - | Custom icon to display when no preview is available. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<AttachmentInfo />`\n\nDisplays the filename and optional media type.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `showMediaType` | `boolean` | `false` | Whether to show the media type below the filename. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<AttachmentRemove />`\n\nRemove button that appears on hover.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | Screen reader label for the button. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the underlying Button component. |\n\n### `<AttachmentHoverCard />`\n\nWrapper for hover preview functionality.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `openDelay` | `number` | `0` | Delay in ms before opening the hover card. |\n| `closeDelay` | `number` | `0` | Delay in ms before closing the hover card. |\n| `...props` | `React.ComponentProps<typeof HoverCard>` | - | Spread to the underlying HoverCard component. |\n\n### `<AttachmentHoverCardTrigger />`\n\nTrigger element for the hover card.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof HoverCardTrigger>` | - | Spread to the underlying HoverCardTrigger component. |\n\n### `<AttachmentHoverCardContent />`\n\nContent displayed in the hover card.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `align` | `unknown` | - | Alignment of the hover card content. |\n| `...props` | `React.ComponentProps<typeof HoverCardContent>` | - | Spread to the underlying HoverCardContent component. |\n\n### `<AttachmentEmpty />`\n\nEmpty state component when no attachments are present.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n## Utility Functions\n\n### `getMediaCategory(data)`\n\nReturns the media category for an attachment.\n\n```tsx\nimport { getMediaCategory } from \"@/components/ai-elements/attachments\";\n\nconst category = getMediaCategory(attachment);\n// Returns: \"image\" | \"video\" | \"audio\" | \"document\" | \"source\" | \"unknown\"\n```\n\n### `getAttachmentLabel(data)`\n\nReturns the display label for an attachment.\n\n```tsx\nimport { getAttachmentLabel } from \"@/components/ai-elements/attachments\";\n\nconst label = getAttachmentLabel(attachment);\n// Returns filename or fallback like \"Image\" or \"Attachment\"\n```\n","isInternal":false,"tokens":1300,"sizeBytes":5760},{"name":"audio-player.md","path":".agents/skills/ai-elements/references/audio-player.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/audio-player.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Audio Player\n\nA composable audio player component built on media-chrome, with shadcn styling and flexible controls.\n\nThe `AudioPlayer` component provides a flexible and customizable audio playback interface built on top of media-chrome. It features a composable architecture that allows you to build audio experiences with custom controls, metadata display, and seamless integration with AI-generated audio content.\n\nSee `scripts/audio-player.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add audio-player\n```\n\n## Features\n\n- Built on media-chrome for reliable audio playback\n- Fully composable architecture with granular control components\n- ButtonGroup integration for cohesive control layout\n- Individual control components (play, seek, volume, etc.)\n- Flexible layout with customizable control bars\n- CSS custom properties for deep theming\n- Shadcn/ui Button component styling\n- Responsive design that works across devices\n- Full TypeScript support with proper types for all components\n\n## Variants\n\n### AI SDK Speech Result\n\nThe `AudioPlayer` component can be used to play audio from an AI SDK Speech Result.\n\nSee `scripts/audio-player.tsx` for this example.\n\n### Remote Audio\n\nThe `AudioPlayer` component can be used to play remote audio files.\n\nSee `scripts/audio-player-remote.tsx` for this example.\n\n## Props\n\n### `<AudioPlayer />`\n\nRoot MediaController component. Accepts all MediaController props except `audio` (which is set to `true` by default).\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `style` | `CSSProperties` | - | Custom CSS properties can be passed to override media-chrome theming variables. |\n| `...props` | `Omit<React.ComponentProps<typeof MediaController>, ` | - | Any other props are spread to the MediaController component. |\n\n### `<AudioPlayerElement />`\n\nThe audio element that contains the media source. Accepts either a remote URL or AI SDK Speech Result data.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `src` | `string` | - | The URL of the audio file to play (for remote audio). |\n| `data` | `SpeechResult[` | - | AI SDK Speech Result audio data with base64 encoding (for AI-generated audio). |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the audio element (excluding src when using data). |\n\n### `<AudioPlayerControlBar />`\n\nContainer for control buttons, wraps children in a ButtonGroup.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaControlBar>` | - | Any other props are spread to the MediaControlBar component. |\n\n### `<AudioPlayerPlayButton />`\n\nPlay/pause button wrapped in a shadcn Button component.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaPlayButton>` | - | Any other props are spread to the MediaPlayButton component. |\n\n### `<AudioPlayerSeekBackwardButton />`\n\nSeek backward button wrapped in a shadcn Button component.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `seekOffset` | `number` | `10` | The number of seconds to seek backward. |\n| `...props` | `React.ComponentProps<typeof MediaSeekBackwardButton>` | - | Any other props are spread to the MediaSeekBackwardButton component. |\n\n### `<AudioPlayerSeekForwardButton />`\n\nSeek forward button wrapped in a shadcn Button component.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `seekOffset` | `number` | `10` | The number of seconds to seek forward. |\n| `...props` | `React.ComponentProps<typeof MediaSeekForwardButton>` | - | Any other props are spread to the MediaSeekForwardButton component. |\n\n### `<AudioPlayerTimeDisplay />`\n\nDisplays the current playback time, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaTimeDisplay>` | - | Any other props are spread to the MediaTimeDisplay component. |\n\n### `<AudioPlayerTimeRange />`\n\nSeek slider for controlling playback position, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaTimeRange>` | - | Any other props are spread to the MediaTimeRange component. |\n\n### `<AudioPlayerDurationDisplay />`\n\nDisplays the total duration of the audio, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaDurationDisplay>` | - | Any other props are spread to the MediaDurationDisplay component. |\n\n### `<AudioPlayerMuteButton />`\n\nMute/unmute button, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaMuteButton>` | - | Any other props are spread to the MediaMuteButton component. |\n\n### `<AudioPlayerVolumeRange />`\n\nVolume slider control, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaVolumeRange>` | - | Any other props are spread to the MediaVolumeRange component. |\n","isInternal":false,"tokens":1203,"sizeBytes":5346},{"name":"canvas.md","path":".agents/skills/ai-elements/references/canvas.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/canvas.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Canvas\n\nA React Flow-based canvas component for building interactive node-based interfaces.\n\nThe `Canvas` component provides a React Flow-based canvas for building interactive node-based interfaces. It comes pre-configured with sensible defaults for AI applications, including panning, zooming, and selection behaviors.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add canvas\n```\n\n## Features\n\n- Pre-configured React Flow canvas with AI-optimized defaults\n- Pan on scroll enabled for intuitive navigation\n- Selection on drag for multi-node operations\n- Customizable background color using CSS variables\n- Delete key support (Backspace and Delete keys)\n- Auto-fit view to show all nodes\n- Disabled double-click zoom for better UX\n- Disabled pan on drag to prevent accidental canvas movement\n- Fully compatible with React Flow props and API\n\n## Props\n\n### `<Canvas />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode` | - | Child components like Background, Controls, or MiniMap. |\n| `...props` | `ReactFlowProps` | - | Any other React Flow props like nodes, edges, nodeTypes, edgeTypes, onNodesChange, etc. |\n","isInternal":false,"tokens":254,"sizeBytes":1175},{"name":"chain-of-thought.md","path":".agents/skills/ai-elements/references/chain-of-thought.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/chain-of-thought.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Chain of Thought\n\nA collapsible component that visualizes AI reasoning steps with support for search results, images, and step-by-step progress indicators.\n\nThe `ChainOfThought` component provides a visual representation of an AI's reasoning process, showing step-by-step thinking with support for search results, images, and progress indicators. It helps users understand how AI arrives at conclusions.\n\nSee `scripts/chain-of-thought.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add chain-of-thought\n```\n\n## Features\n\n- Collapsible interface with smooth animations powered by Radix UI\n- Step-by-step visualization of AI reasoning process\n- Support for different step statuses (complete, active, pending)\n- Built-in search results display with badge styling\n- Image support with captions for visual content\n- Custom icons for different step types\n- Context-aware components using React Context API\n- Fully typed with TypeScript\n- Accessible with keyboard navigation support\n- Responsive design that adapts to different screen sizes\n- Smooth fade and slide animations for content transitions\n- Composable architecture for flexible customization\n\n## Props\n\n### `<ChainOfThought />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `open` | `boolean` | - | Controlled open state of the collapsible. |\n| `defaultOpen` | `boolean` | `false` | Default open state when uncontrolled. |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback when the open state changes. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div element. |\n\n### `<ChainOfThoughtHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom header text. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<ChainOfThoughtStep />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `icon` | `LucideIcon` | `DotIcon` | Icon to display for the step. |\n| `label` | `string` | - | The main text label for the step. |\n| `description` | `string` | - | Optional description text shown below the label. |\n| `status` | `unknown` | - | Visual status of the step. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div element. |\n\n### `<ChainOfThoughtSearchResults />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any props are spread to the container div element. |\n\n### `<ChainOfThoughtSearchResult />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Badge>` | - | Any props are spread to the Badge component. |\n\n### `<ChainOfThoughtContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any props are spread to the CollapsibleContent component. |\n\n### `<ChainOfThoughtImage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `caption` | `string` | - | Optional caption text displayed below the image. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div element. |\n","isInternal":false,"tokens":795,"sizeBytes":3410},{"name":"checkpoint.md","path":".agents/skills/ai-elements/references/checkpoint.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/checkpoint.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Checkpoint\n\nA simple component for marking conversation history points and restoring the chat to a previous state.\n\nThe `Checkpoint` component provides a way to mark specific points in a conversation history and restore the chat to that state. Inspired by VSCode's Copilot checkpoint feature, it allows users to revert to an earlier conversation state while maintaining a clear visual separation between different conversation segments.\n\nSee `scripts/checkpoint.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add checkpoint\n```\n\n## Features\n\n- Simple flex layout with icon, trigger, and separator\n- Visual separator line for clear conversation breaks\n- Clickable restore button for reverting to checkpoint\n- Customizable icon (defaults to BookmarkIcon)\n- Keyboard accessible with proper ARIA labels\n- Responsive design that adapts to different screen sizes\n- Seamless light/dark theme integration\n\n## Usage with AI SDK\n\nBuild a chat interface with conversation checkpoints that allow users to restore to previous states.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useState, Fragment } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  Checkpoint,\n  CheckpointIcon,\n  CheckpointTrigger,\n} from \"@/components/ai-elements/checkpoint\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport {\n  Conversation,\n  ConversationContent,\n} from \"@/components/ai-elements/conversation\";\n\ntype CheckpointType = {\n  id: string;\n  messageIndex: number;\n  timestamp: Date;\n  messageCount: number;\n};\n\nconst CheckpointDemo = () => {\n  const { messages, setMessages } = useChat();\n  const [checkpoints, setCheckpoints] = useState<CheckpointType[]>([]);\n\n  const createCheckpoint = (messageIndex: number) => {\n    const checkpoint: CheckpointType = {\n      id: nanoid(),\n      messageIndex,\n      timestamp: new Date(),\n      messageCount: messageIndex + 1,\n    };\n    setCheckpoints([...checkpoints, checkpoint]);\n  };\n\n  const restoreToCheckpoint = (messageIndex: number) => {\n    // Restore messages to checkpoint state\n    setMessages(messages.slice(0, messageIndex + 1));\n    // Remove checkpoints after this point\n    setCheckpoints(checkpoints.filter((cp) => cp.messageIndex <= messageIndex));\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <Conversation>\n        <ConversationContent>\n          {messages.map((message, index) => {\n            const checkpoint = checkpoints.find(\n              (cp) => cp.messageIndex === index\n            );\n\n            return (\n              <Fragment key={message.id}>\n                <Message from={message.role}>\n                  <MessageContent>\n                    <MessageResponse>{message.content}</MessageResponse>\n                  </MessageContent>\n                </Message>\n                {checkpoint && (\n                  <Checkpoint>\n                    <CheckpointIcon />\n                    <CheckpointTrigger\n                      onClick={() =>\n                        restoreToCheckpoint(checkpoint.messageIndex)\n                      }\n                    >\n                      Restore checkpoint\n                    </CheckpointTrigger>\n                  </Checkpoint>\n                )}\n              </Fragment>\n            );\n          })}\n        </ConversationContent>\n      </Conversation>\n    </div>\n  );\n};\n\nexport default CheckpointDemo;\n```\n\n## Use Cases\n\n### Manual Checkpoints\n\nAllow users to manually create checkpoints at important conversation points:\n\n```tsx\n<Button onClick={() => createCheckpoint(messages.length - 1)}>\n  Create Checkpoint\n</Button>\n```\n\n### Automatic Checkpoints\n\nCreate checkpoints automatically after significant conversation milestones:\n\n```tsx\nuseEffect(() => {\n  // Create checkpoint every 5 messages\n  if (messages.length > 0 && messages.length % 5 === 0) {\n    createCheckpoint(messages.length - 1);\n  }\n}, [messages.length]);\n```\n\n### Branching Conversations\n\nUse checkpoints to enable conversation branching where users can explore different conversation paths:\n\n```tsx\nconst restoreAndBranch = (messageIndex: number) => {\n  // Save current branch\n  const currentBranch = messages.slice(messageIndex + 1);\n  saveBranch(currentBranch);\n\n  // Restore to checkpoint\n  restoreToCheckpoint(messageIndex);\n};\n```\n\n## Props\n\n### `<Checkpoint />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The checkpoint icon and trigger components. Automatically includes a Separator at the end. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<CheckpointIcon />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom icon content. If not provided, defaults to a BookmarkIcon from lucide-react. |\n| `...props` | `LucideProps` | - | Any other props are spread to the BookmarkIcon component. |\n\n### `<CheckpointTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The text or content to display in the trigger button. |\n| `tooltip` | `string` | - | Optional tooltip text shown on hover. |\n| `variant` | `string` | - | The button variant style. |\n| `size` | `string` | - | The button size. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n","isInternal":false,"tokens":1181,"sizeBytes":5612},{"name":"code-block.md","path":".agents/skills/ai-elements/references/code-block.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/code-block.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Code Block\n\nProvides syntax highlighting, line numbers, and copy to clipboard functionality for code blocks.\n\nThe `CodeBlock` component provides syntax highlighting, line numbers, and copy to clipboard functionality for code blocks. It's fully composable, allowing you to customize the header, actions, and content.\n\nSee `scripts/code-block.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add code-block\n```\n\n## Usage\n\nThe CodeBlock is fully composable. Here's a basic example:\n\n```tsx\nimport {\n  CodeBlock,\n  CodeBlockActions,\n  CodeBlockCopyButton,\n  CodeBlockFilename,\n  CodeBlockHeader,\n  CodeBlockTitle,\n} from \"@/components/ai-elements/code-block\";\nimport { FileIcon } from \"lucide-react\";\n\nexport const Example = () => (\n  <CodeBlock code={code} language=\"typescript\">\n    <CodeBlockHeader>\n      <CodeBlockTitle>\n        <FileIcon size={14} />\n        <CodeBlockFilename>example.ts</CodeBlockFilename>\n      </CodeBlockTitle>\n      <CodeBlockActions>\n        <CodeBlockCopyButton />\n      </CodeBlockActions>\n    </CodeBlockHeader>\n  </CodeBlock>\n);\n```\n\n## Features\n\n- Syntax highlighting with Shiki\n- Line numbers (optional)\n- Copy to clipboard functionality\n- Automatic light/dark theme switching via CSS variables\n- Language selector for multi-language examples\n- Fully composable architecture\n- Accessible design\n\n## Examples\n\n### Dark Mode\n\nTo use the `CodeBlock` component in dark mode, wrap it in a `div` with the `dark` class.\n\nSee `scripts/code-block-dark.tsx` for this example.\n\n### Language Selector\n\nAdd a language selector to switch between different code implementations:\n\nSee `scripts/code-block.tsx` for this example.\n\n## Props\n\n### `<CodeBlock />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `code` | `string` | - | The code content to display. |\n| `language` | `BundledLanguage` | - | The programming language for syntax highlighting. |\n| `showLineNumbers` | `boolean` | `false` | Whether to show line numbers. |\n| `children` | `React.ReactNode` | - | Child elements like CodeBlockHeader. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockHeader />`\n\nContainer for the header row. Uses flexbox with `justify-between`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Header content (CodeBlockTitle, CodeBlockActions, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockTitle />`\n\nLeft-aligned container for icon and filename. Uses flexbox with `gap-2`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Title content (icon, CodeBlockFilename, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockFilename />`\n\nDisplays the filename in monospace font.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The filename to display. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockActions />`\n\nRight-aligned container for action buttons. Uses flexbox with `gap-2`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Action buttons (CodeBlockCopyButton, CodeBlockLanguageSelector, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback fired after a successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback fired if copying fails. |\n| `timeout` | `number` | `2000` | How long to show the copied state (ms). |\n| `children` | `React.ReactNode` | - | Custom content for the button. Defaults to copy/check icons. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockLanguageSelector />`\n\nWrapper for the language selector. Extends shadcn/ui Select.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The currently selected language. |\n| `onValueChange` | `(value: string) => void` | - | Callback when the language changes. |\n| `children` | `React.ReactNode` | - | Selector components (Trigger, Content, Items). |\n\n### `<CodeBlockLanguageSelectorTrigger />`\n\nTrigger button for the language selector dropdown. Pre-styled for code block header.\n\n### `<CodeBlockLanguageSelectorValue />`\n\nDisplays the selected language value.\n\n### `<CodeBlockLanguageSelectorContent />`\n\nDropdown content container. Defaults to `align=\"end\"`.\n\n### `<CodeBlockLanguageSelectorItem />`\n\nIndividual language option in the dropdown.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The language value. |\n| `children` | `React.ReactNode` | - | The display label. |\n\n### `<CodeBlockContainer />`\n\nLow-level container component with performance optimizations (`contentVisibility`). Used internally by CodeBlock.\n\n### `<CodeBlockContent />`\n\nLow-level component that handles syntax highlighting. Used internally by CodeBlock, but can be used directly for custom layouts.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `code` | `string` | - | The code content to display. |\n| `language` | `BundledLanguage` | - | The programming language for syntax highlighting. |\n| `showLineNumbers` | `boolean` | `false` | Whether to show line numbers. |\n","isInternal":false,"tokens":1325,"sizeBytes":5538},{"name":"commit.md","path":".agents/skills/ai-elements/references/commit.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/commit.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Commit\n\nDisplay commit information with hash, message, author, and file changes.\n\nThe `Commit` component displays commit details including hash, message, author, timestamp, and changed files.\n\nSee `scripts/commit.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add commit\n```\n\n## Features\n\n- Commit hash display with copy button\n- Author avatar with initials\n- Relative timestamp formatting\n- Collapsible file changes list\n- Color-coded file status (added/modified/deleted/renamed)\n- Line additions/deletions count\n\n## File Status\n\n| Status     | Label | Color  |\n| ---------- | ----- | ------ |\n| `added`    | A     | Green  |\n| `modified` | M     | Yellow |\n| `deleted`  | D     | Red    |\n| `renamed`  | R     | Blue   |\n\n## Props\n\n### `<Commit />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Spread to the Collapsible component. |\n\n### `<CommitHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Spread to the CollapsibleTrigger component. |\n\n### `<CommitAuthor />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitAuthorAvatar />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `initials` | `string` | Required | Author initials to display. |\n| `...props` | `React.ComponentProps<typeof Avatar>` | - | Spread to the Avatar component. |\n\n### `<CommitInfo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitMessage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitMetadata />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitHash />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitSeparator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom separator content. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitTimestamp />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `date` | `Date` | Required | Commit date. |\n| `children` | `React.ReactNode` | - | Custom timestamp content. Defaults to relative time. |\n| `...props` | `React.HTMLAttributes<HTMLTimeElement>` | - | Spread to the time element. |\n\n### `<CommitActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `hash` | `string` | Required | Commit hash to copy. |\n| `onCopy` | `() => void` | - | Callback after successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback if copying fails. |\n| `timeout` | `number` | `2000` | Duration to show copied state (ms). |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the Button component. |\n\n### `<CommitContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Spread to the CollapsibleContent component. |\n\n### `<CommitFiles />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the row div. |\n\n### `<CommitFileInfo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitFileStatus />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `status` | `unknown` | Required | File change status. |\n| `children` | `React.ReactNode` | - | Custom status label. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitFileIcon />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof FileIcon>` | - | Spread to the FileIcon component. |\n\n### `<CommitFilePath />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitFileChanges />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitFileAdditions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `count` | `number` | Required | Number of lines added. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitFileDeletions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `count` | `number` | Required | Number of lines deleted. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n","isInternal":false,"tokens":1474,"sizeBytes":5959},{"name":"confirmation.md","path":".agents/skills/ai-elements/references/confirmation.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/confirmation.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Confirmation\n\nAn alert-based component for managing tool execution approval workflows with request, accept, and reject states.\n\nThe `Confirmation` component provides a flexible system for displaying tool approval requests and their outcomes. Perfect for showing users when AI tools require approval before execution, and displaying the approval status afterward.\n\nSee `scripts/confirmation.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add confirmation\n```\n\n## Usage with AI SDK\n\nBuild a chat UI with tool approval workflow where dangerous tools require user confirmation before execution.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport { DefaultChatTransport, type ToolUIPart } from \"ai\";\nimport { useState } from \"react\";\nimport { CheckIcon, XIcon } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Confirmation,\n  ConfirmationTitle,\n  ConfirmationRequest,\n  ConfirmationAccepted,\n  ConfirmationRejected,\n  ConfirmationActions,\n  ConfirmationAction,\n} from \"@/components/ai-elements/confirmation\";\nimport { MessageResponse } from \"@/components/ai-elements/message\";\n\ntype DeleteFileInput = {\n  filePath: string;\n  confirm: boolean;\n};\n\ntype DeleteFileToolUIPart = ToolUIPart<{\n  delete_file: {\n    input: DeleteFileInput;\n    output: { success: boolean; message: string };\n  };\n}>;\n\nconst Example = () => {\n  const { messages, sendMessage, status, addToolApprovalResponse } = useChat({\n    transport: new DefaultChatTransport({\n      api: \"/api/chat\",\n    }),\n  });\n\n  const handleDeleteFile = () => {\n    sendMessage({ text: \"Delete the file at /tmp/example.txt\" });\n  };\n\n  const latestMessage = messages[messages.length - 1];\n  const deleteTool = latestMessage?.parts?.find(\n    (part) => part.type === \"tool-delete_file\"\n  ) as DeleteFileToolUIPart | undefined;\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full space-y-4\">\n        <Button onClick={handleDeleteFile} disabled={status !== \"ready\"}>\n          Delete Example File\n        </Button>\n\n        {deleteTool?.approval && (\n          <Confirmation approval={deleteTool.approval} state={deleteTool.state}>\n            <ConfirmationRequest>\n              This tool wants to delete:{\" \"}\n              <code>{deleteTool.input?.filePath}</code>\n              <br />\n              Do you approve this action?\n            </ConfirmationRequest>\n            <ConfirmationAccepted>\n              <CheckIcon className=\"size-4\" />\n              <span>You approved this tool execution</span>\n            </ConfirmationAccepted>\n            <ConfirmationRejected>\n              <XIcon className=\"size-4\" />\n              <span>You rejected this tool execution</span>\n            </ConfirmationRejected>\n            <ConfirmationActions>\n              <ConfirmationAction\n                variant=\"outline\"\n                onClick={() =>\n                  addToolApprovalResponse({\n                    id: deleteTool.approval!.id,\n                    approved: false,\n                  })\n                }\n              >\n                Reject\n              </ConfirmationAction>\n              <ConfirmationAction\n                variant=\"default\"\n                onClick={() =>\n                  addToolApprovalResponse({\n                    id: deleteTool.approval!.id,\n                    approved: true,\n                  })\n                }\n              >\n                Approve\n              </ConfirmationAction>\n            </ConfirmationActions>\n          </Confirmation>\n        )}\n\n        {deleteTool?.output && (\n          <MessageResponse>\n            {deleteTool.output.success\n              ? deleteTool.output.message\n              : `Error: ${deleteTool.output.message}`}\n          </MessageResponse>\n        )}\n      </div>\n    </div>\n  );\n};\n\nexport default Example;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/chat/route.tsx\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\nimport { z } from \"zod\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages: await convertToModelMessages(messages),\n    tools: {\n      delete_file: {\n        description: \"Delete a file from the file system\",\n        parameters: z.object({\n          filePath: z.string().describe(\"The path to the file to delete\"),\n          confirm: z\n            .boolean()\n            .default(false)\n            .describe(\"Confirmation that the user wants to delete the file\"),\n        }),\n        requireApproval: true, // Enable approval workflow\n        execute: async ({ filePath, confirm }) => {\n          if (!confirm) {\n            return {\n              success: false,\n              message: \"Deletion not confirmed\",\n            };\n          }\n\n          // Simulate file deletion\n          await new Promise((resolve) => setTimeout(resolve, 500));\n\n          return {\n            success: true,\n            message: `Successfully deleted ${filePath}`,\n          };\n        },\n      },\n    },\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Context-based state management for approval workflow\n- Conditional rendering based on approval state\n- Support for approval-requested, approval-responded, output-denied, and output-available states\n- Built on shadcn/ui Alert and Button components\n- TypeScript support with comprehensive type definitions\n- Customizable styling with Tailwind CSS\n- Keyboard navigation and accessibility support\n- Theme-aware with automatic dark mode support\n\n## Examples\n\n### Approval Request State\n\nShows the approval request with action buttons when state is `approval-requested`.\n\nSee `scripts/confirmation-request.tsx` for this example.\n\n### Approved State\n\nShows the accepted status when user approves and state is `approval-responded` or `output-available`.\n\nSee `scripts/confirmation-accepted.tsx` for this example.\n\n### Rejected State\n\nShows the rejected status when user rejects and state is `output-denied`.\n\nSee `scripts/confirmation-rejected.tsx` for this example.\n\n## Props\n\n### `<Confirmation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `approval` | `ToolUIPart[` | - | The approval object containing the approval ID and status. If not provided or undefined, the component will not render. |\n| `state` | `ToolUIPart[` | - | The current state of the tool (input-streaming, input-available, approval-requested, approval-responded, output-denied, or output-available). Will not render for input-streaming or input-available states. |\n| `className` | `string` | - | Additional CSS classes to apply to the Alert component. |\n| `...props` | `React.ComponentProps<typeof Alert>` | - | Any other props are spread to the Alert component. |\n\n### `<ConfirmationTitle />`\n\nA styled description element for displaying a title or label within the confirmation alert.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof AlertDescription>` | - | Any other props are spread to the underlying AlertDescription component. |\n\n### `<ConfirmationRequest />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The content to display when approval is requested. Only renders when state is  |\n\n### `<ConfirmationAccepted />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The content to display when approval is accepted. Only renders when approval.approved is true and state is  |\n\n### `<ConfirmationRejected />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The content to display when approval is rejected. Only renders when approval.approved is false and state is  |\n\n### `<ConfirmationActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the actions container. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. Only renders when state is  |\n\n### `<ConfirmationAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component. Styled with h-8 px-3 text-sm classes by default. |\n","isInternal":false,"tokens":1846,"sizeBytes":8790},{"name":"connection.md","path":".agents/skills/ai-elements/references/connection.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/connection.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Connection\n\nA custom connection line component for React Flow-based canvases with animated bezier curve styling.\n\nThe `Connection` component provides a styled connection line for React Flow canvases. It renders an animated bezier curve with a circle indicator at the target end, using consistent theming through CSS variables.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add connection\n```\n\n## Features\n\n- Smooth bezier curve animation for connection lines\n- Visual indicator circle at the target position\n- Theme-aware styling using CSS variables\n- Cubic bezier curve calculation for natural flow\n- Lightweight implementation with minimal props\n- Full TypeScript support with React Flow types\n- Compatible with React Flow's connection system\n\n## Props\n\n### `<Connection />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `fromX` | `number` | - | The x-coordinate of the connection start point. |\n| `fromY` | `number` | - | The y-coordinate of the connection start point. |\n| `toX` | `number` | - | The x-coordinate of the connection end point. |\n| `toY` | `number` | - | The y-coordinate of the connection end point. |\n","isInternal":false,"tokens":254,"sizeBytes":1165},{"name":"context.md","path":".agents/skills/ai-elements/references/context.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/context.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Context\n\nA compound component system for displaying AI model context window usage, token consumption, and cost estimation.\n\nThe `Context` component provides a comprehensive view of AI model usage through a compound component system. It displays context window utilization, token consumption breakdown (input, output, reasoning, cache), and cost estimation in an interactive hover card interface.\n\nSee `scripts/context.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add context\n```\n\n## Features\n\n- **Compound Component Architecture**: Flexible composition of context display elements\n- **Visual Progress Indicator**: Circular SVG progress ring showing context usage percentage\n- **Token Breakdown**: Detailed view of input, output, reasoning, and cached tokens\n- **Cost Estimation**: Real-time cost calculation using the `tokenlens` library\n- **Intelligent Formatting**: Automatic token count formatting (K, M, B suffixes)\n- **Interactive Hover Card**: Detailed information revealed on hover\n- **Context Provider Pattern**: Clean data flow through React Context API\n- **TypeScript Support**: Full type definitions for all components\n- **Accessible Design**: Proper ARIA labels and semantic HTML\n- **Theme Integration**: Uses currentColor for automatic theme adaptation\n\n## Props\n\n### `<Context />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `maxTokens` | `number` | - | The total context window size in tokens. |\n| `usedTokens` | `number` | - | The number of tokens currently used. |\n| `usage` | `LanguageModelUsage` | - | Detailed token usage breakdown from the AI SDK (input, output, reasoning, cached tokens). |\n| `modelId` | `ModelId` | - | Model identifier for cost calculation (e.g.,  |\n| `...props` | `ComponentProps<HoverCard>` | - | Any other props are spread to the HoverCard component. |\n\n### `<ContextTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom trigger element. If not provided, renders a default button with percentage and icon. |\n| `...props` | `ComponentProps<Button>` | - | Props spread to the default button element. |\n\n### `<ContextContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes for the hover card content. |\n| `...props` | `ComponentProps<HoverCardContent>` | - | Props spread to the HoverCardContent component. |\n\n### `<ContextContentHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom header content. If not provided, renders percentage and token count with progress bar. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the header div element. |\n\n### `<ContextContentBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Body content, typically containing usage breakdown components. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the body div element. |\n\n### `<ContextContentFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom footer content. If not provided, renders total cost when modelId is provided. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the footer div element. |\n\n### Usage Components\n\nAll usage components (`ContextInputUsage`, `ContextOutputUsage`, `ContextReasoningUsage`, `ContextCacheUsage`) share the same props:\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom content. If not provided, renders token count and cost for the respective usage type. |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the div element. |\n\n## Component Architecture\n\nThe Context component uses a compound component pattern with React Context for data sharing:\n\n1. **`<Context>`** - Root provider component that holds all context data\n2. **`<ContextTrigger>`** - Interactive trigger element (default: button with percentage)\n3. **`<ContextContent>`** - Hover card content container\n4. **`<ContextContentHeader>`** - Header section with progress visualization\n5. **`<ContextContentBody>`** - Body section for usage breakdowns\n6. **`<ContextContentFooter>`** - Footer section for total cost\n7. **Usage Components** - Individual token usage displays (Input, Output, Reasoning, Cache)\n\n## Token Formatting\n\nThe component uses `Intl.NumberFormat` with compact notation for automatic formatting:\n\n- Under 1,000: Shows exact count (e.g., \"842\")\n- 1,000+: Shows with K suffix (e.g., \"32K\")\n- 1,000,000+: Shows with M suffix (e.g., \"1.5M\")\n- 1,000,000,000+: Shows with B suffix (e.g., \"2.1B\")\n\n## Cost Calculation\n\nWhen a `modelId` is provided, the component automatically calculates costs using the `tokenlens` library:\n\n- **Input tokens**: Cost based on model's input pricing\n- **Output tokens**: Cost based on model's output pricing\n- **Reasoning tokens**: Special pricing for reasoning-capable models\n- **Cached tokens**: Reduced pricing for cached input tokens\n- **Total cost**: Sum of all token type costs\n\nCosts are formatted using `Intl.NumberFormat` with USD currency.\n\n## Styling\n\nThe component uses Tailwind CSS classes and follows your design system:\n\n- Progress indicator uses `currentColor` for theme adaptation\n- Hover card has customizable width and padding\n- Footer has a secondary background for visual separation\n- All text sizes use the `text-xs` class for consistency\n- Muted foreground colors for secondary information\n","isInternal":false,"tokens":1314,"sizeBytes":5747},{"name":"controls.md","path":".agents/skills/ai-elements/references/controls.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/controls.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Controls\n\nA styled controls component for React Flow-based canvases with zoom and fit view functionality.\n\nThe `Controls` component provides interactive zoom and fit view controls for React Flow canvases. It includes a modern, themed design with backdrop blur and card styling.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add controls\n```\n\n## Features\n\n- Zoom in/out controls\n- Fit view button to center and scale content\n- Rounded pill design with backdrop blur\n- Theme-aware card background\n- Subtle drop shadow for depth\n- Full TypeScript support\n- Compatible with all React Flow control features\n\n## Props\n\n### `<Controls />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the controls. |\n| `...props` | `ComponentProps<typeof Controls>` | - | Any other props from @xyflow/react Controls component (showZoom, showFitView, showInteractive, position, etc.). |\n","isInternal":false,"tokens":212,"sizeBytes":971},{"name":"conversation.md","path":".agents/skills/ai-elements/references/conversation.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/conversation.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Conversation\n\nWraps messages and automatically scrolls to the bottom. Also includes a scroll button that appears when not at the bottom.\n\nThe `Conversation` component wraps messages and automatically scrolls to the bottom. Also includes a scroll button that appears when not at the bottom.\n\n<Preview path=\"conversation\" className=\"p-0\" />\n\n## Installation\n\n```bash\nnpx ai-elements@latest add conversation\n```\n\n## Usage with AI SDK\n\nBuild a simple conversational UI with `Conversation` and [`PromptInput`](/components/prompt-input):\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationDownload,\n  ConversationEmptyState,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { MessageSquare } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\n\nconst ConversationDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { messages, sendMessage, status } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.length === 0 ? (\n              <ConversationEmptyState\n                icon={<MessageSquare className=\"size-12\" />}\n                title=\"Start a conversation\"\n                description=\"Type a message below to begin chatting\"\n              />\n            ) : (\n              messages.map((message) => (\n                <Message from={message.role} key={message.id}>\n                  <MessageContent>\n                    {message.parts.map((part, i) => {\n                      switch (part.type) {\n                        case \"text\": // we don't use any reasoning or tool calls in this example\n                          return (\n                            <MessageResponse key={`${message.id}-${i}`}>\n                              {part.text}\n                            </MessageResponse>\n                          );\n                        default:\n                          return null;\n                      }\n                    })}\n                  </MessageContent>\n                </Message>\n              ))\n            )}\n          </ConversationContent>\n          <ConversationDownload messages={messages} />\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Say something...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ConversationDemo;\n```\n\nAdd the following route to your backend:\n\n```tsx title=\"api/chat/route.ts\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Automatic scrolling to the bottom when new messages are added\n- Smooth scrolling behavior with configurable animation\n- Scroll button that appears when not at the bottom\n- Download conversation as Markdown\n- Responsive design with customizable padding and spacing\n- Flexible content layout with consistent message spacing\n- Accessible with proper ARIA roles for screen readers\n- Customizable styling through className prop\n- Support for any number of child message components\n\n## Props\n\n### `<Conversation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `contextRef` | `React.Ref<StickToBottomContext>` | - | Optional ref to access the StickToBottom context object. |\n| `instance` | `StickToBottomInstance` | - | Optional instance for controlling the StickToBottom component. |\n| `children` | `((context: StickToBottomContext) => ReactNode) | ReactNode` | - | Render prop or ReactNode for custom rendering with context. |\n| `...props` | `Omit<React.HTMLAttributes<HTMLDivElement>, ` | - | Any other props are spread to the root div. |\n\n### `<ConversationContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `((context: StickToBottomContext) => ReactNode) | ReactNode` | - | Render prop or ReactNode for custom rendering with context. |\n| `...props` | `Omit<React.HTMLAttributes<HTMLDivElement>, ` | - | Any other props are spread to the root div. |\n\n### `<ConversationEmptyState />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | - | The title text to display. |\n| `description` | `string` | - | The description text to display. |\n| `icon` | `React.ReactNode` | - | Optional icon to display above the text. |\n| `children` | `React.ReactNode` | - | Optional additional content to render below the text. |\n| `...props` | `ComponentProps<` | - | Any other props are spread to the root div. |\n\n### `<ConversationScrollButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<ConversationDownload />`\n\nA button that downloads the conversation as a Markdown file.\n\n```tsx\nimport { ConversationDownload } from \"@/components/ai-elements/conversation\";\n\n<Conversation>\n  <ConversationContent>\n    {messages.map(...)}\n  </ConversationContent>\n  <ConversationDownload messages={messages} />\n  <ConversationScrollButton />\n</Conversation>\n```\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `messages` | `UIMessage[]` | Required | Array of messages to include in the download. |\n| `filename` | `string` | - | The filename for the downloaded file. |\n| `formatMessage` | `(message: UIMessage, index: number) => string` | - | Custom function to format each message in the output. |\n| `...props` | `Omit<ComponentProps<typeof Button>, ` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `messagesToMarkdown`\n\nA utility function to convert messages to Markdown format. Useful for custom download implementations.\n\n```tsx\nimport { messagesToMarkdown } from \"@/components/ai-elements/conversation\";\n\nconst markdown = messagesToMarkdown(messages);\n\n// With custom formatter\nconst customMarkdown = messagesToMarkdown(\n  messages,\n  (msg, i) =>\n    `[${msg.role}]: ${msg.parts\n      .filter((p) => p.type === \"text\")\n      .map((p) => p.text)\n      .join(\"\")}`\n);\n```\n","isInternal":false,"tokens":1640,"sizeBytes":7555},{"name":"edge.md","path":".agents/skills/ai-elements/references/edge.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/edge.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Edge\n\nCustomizable edge components for React Flow canvases with animated and temporary states.\n\nThe `Edge` component provides two pre-styled edge types for React Flow canvases: `Temporary` for dashed temporary connections and `Animated` for connections with animated indicators.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add edge\n```\n\n## Features\n\n- Two distinct edge types: Temporary and Animated\n- Temporary edges use dashed lines with ring color\n- Animated edges include a moving circle indicator\n- Automatic handle position calculation\n- Smart offset calculation based on handle type and position\n- Uses Bezier curves for smooth, natural-looking connections\n- Fully compatible with React Flow's edge system\n- Type-safe implementation with TypeScript\n\n## Edge Types\n\n### `Edge.Temporary`\n\nA dashed edge style for temporary or preview connections. Uses a simple Bezier path with a dashed stroke pattern.\n\n### `Edge.Animated`\n\nA solid edge with an animated circle that moves along the path. The animation repeats indefinitely with a 2-second duration, providing visual feedback for active connections.\n\n## Props\n\nBoth edge types accept standard React Flow `EdgeProps`:\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `id` | `string` | - | Unique identifier for the edge. |\n| `source` | `string` | - | ID of the source node. |\n| `target` | `string` | - | ID of the target node. |\n| `sourceX` | `number` | - | X coordinate of the source handle (Temporary only). |\n| `sourceY` | `number` | - | Y coordinate of the source handle (Temporary only). |\n| `targetX` | `number` | - | X coordinate of the target handle (Temporary only). |\n| `targetY` | `number` | - | Y coordinate of the target handle (Temporary only). |\n| `sourcePosition` | `Position` | - | Position of the source handle (Left, Right, Top, Bottom). |\n| `targetPosition` | `Position` | - | Position of the target handle (Left, Right, Top, Bottom). |\n| `markerEnd` | `string` | - | SVG marker ID for the edge end (Animated only). |\n| `style` | `React.CSSProperties` | - | Custom styles for the edge (Animated only). |\n","isInternal":false,"tokens":497,"sizeBytes":2121},{"name":"environment-variables.md","path":".agents/skills/ai-elements/references/environment-variables.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/environment-variables.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Environment Variables\n\nDisplay environment variables with masking and copy functionality.\n\nThe `EnvironmentVariables` component displays environment variables with value masking, visibility toggle, and copy functionality.\n\nSee `scripts/environment-variables.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add environment-variables\n```\n\n## Features\n\n- Value masking by default\n- Toggle visibility switch\n- Copy individual values\n- Export format support (`export KEY=\"value\"`)\n- Required badge indicator\n\n## Props\n\n### `<EnvironmentVariables />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `showValues` | `boolean` | - | Controlled visibility state. |\n| `defaultShowValues` | `boolean` | `false` | Default visibility state. |\n| `onShowValuesChange` | `(show: boolean) => void` | - | Callback when visibility changes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<EnvironmentVariablesHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the header div. |\n\n### `<EnvironmentVariablesTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom title text. |\n| `...props` | `React.HTMLAttributes<HTMLHeadingElement>` | - | Spread to the h3 element. |\n\n### `<EnvironmentVariablesToggle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Switch>` | - | Spread to the Switch component. |\n\n### `<EnvironmentVariablesContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the content div. |\n\n### `<EnvironmentVariable />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | Variable name. |\n| `value` | `string` | Required | Variable value. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the row div. |\n\n### `<EnvironmentVariableGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the group div. |\n\n### `<EnvironmentVariableName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom name content. Defaults to the name from context. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<EnvironmentVariableValue />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom value content. Defaults to the masked/unmasked value from context. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<EnvironmentVariableCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `copyFormat` | `unknown` | - | Format to copy. |\n| `onCopy` | `() => void` | - | Callback after successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback if copying fails. |\n| `timeout` | `number` | `2000` | Duration to show copied state (ms). |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the Button component. |\n\n### `<EnvironmentVariableRequired />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom badge text. |\n| `...props` | `React.ComponentProps<typeof Badge>` | - | Spread to the Badge component. |\n","isInternal":false,"tokens":894,"sizeBytes":3751},{"name":"file-tree.md","path":".agents/skills/ai-elements/references/file-tree.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/file-tree.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# File Tree\n\nDisplay hierarchical file and folder structure with expand/collapse functionality.\n\nThe `FileTree` component displays a hierarchical file system structure with expandable folders and file selection.\n\nSee `scripts/file-tree.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add file-tree\n```\n\n## Features\n\n- Hierarchical folder structure\n- Expand/collapse folders\n- File selection with callback\n- Keyboard accessible\n- Customizable icons\n- Controlled and uncontrolled modes\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/file-tree-basic.tsx` for this example.\n\n### With Selection\n\nSee `scripts/file-tree-selection.tsx` for this example.\n\n### Default Expanded\n\nSee `scripts/file-tree-expanded.tsx` for this example.\n\n## Props\n\n### `<FileTree />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `expanded` | `Set<string>` | - | Controlled expanded paths. |\n| `defaultExpanded` | `Set<string>` | `new Set()` | Default expanded paths. |\n| `selectedPath` | `string` | - | Currently selected file/folder path. |\n| `onSelect` | `(path: string) => void` | - | Callback when a file/folder is selected. |\n| `onExpandedChange` | `(expanded: Set<string>) => void` | - | Callback when expanded paths change. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<FileTreeFolder />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `path` | `string` | - | Unique folder path. |\n| `name` | `string` | - | Display name. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<FileTreeFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `path` | `string` | - | Unique file path. |\n| `name` | `string` | - | Display name. |\n| `icon` | `ReactNode` | - | Custom file icon. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### Subcomponents\n\n- `FileTreeIcon` - Icon wrapper\n- `FileTreeName` - Name text\n- `FileTreeActions` - Action buttons container (stops click propagation)\n","isInternal":false,"tokens":511,"sizeBytes":2027},{"name":"image.md","path":".agents/skills/ai-elements/references/image.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/image.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Image\n\nDisplays AI-generated images from the AI SDK.\n\nThe `Image` component displays AI-generated images from the AI SDK. It accepts a [`Experimental_GeneratedImage`](/docs/reference/ai-sdk-core/generate-image) object from the AI SDK's `generateImage` function and automatically renders it as an image.\n\nSee `scripts/image.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add image\n```\n\n## Usage with AI SDK\n\nBuild a simple app allowing a user to generate an image given a prompt.\n\nInstall the `@ai-sdk/openai` package:\n\n```package-install\nnpm i @ai-sdk/openai\n```\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { Image } from \"@/components/ai-elements/image\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { useState } from \"react\";\nimport { Spinner } from \"@/components/ui/spinner\";\n\nconst ImageDemo = () => {\n  const [prompt, setPrompt] = useState(\"A futuristic cityscape at sunset\");\n  const [imageData, setImageData] = useState<any>(null);\n  const [isLoading, setIsLoading] = useState(false);\n\n  const handleSubmit = async (message: PromptInputMessage) => {\n    if (!message.text.trim()) return;\n    setPrompt(\"\");\n\n    setIsLoading(true);\n    try {\n      const response = await fetch(\"/api/image\", {\n        method: \"POST\",\n        body: JSON.stringify({ prompt: message.text.trim() }),\n      });\n\n      const data = await response.json();\n\n      setImageData(data);\n    } catch (error) {\n      console.error(\"Error generating image:\", error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex-1 overflow-y-auto p-4\">\n          {imageData && (\n            <div className=\"flex justify-center\">\n              <Image\n                {...imageData}\n                alt=\"Generated image\"\n                className=\"h-[300px] aspect-square border rounded-lg\"\n              />\n            </div>\n          )}\n          {isLoading && <Spinner />}\n        </div>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={prompt}\n            placeholder=\"Describe the image you want to generate...\"\n            onChange={(e) => setPrompt(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={isLoading ? \"submitted\" : \"ready\"}\n            disabled={!prompt.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ImageDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/image/route.ts\"\nimport { openai } from \"@ai-sdk/openai\";\nimport { experimental_generateImage } from \"ai\";\n\nexport async function POST(req: Request) {\n  const { prompt }: { prompt: string } = await req.json();\n\n  const { image } = await experimental_generateImage({\n    model: openai.image(\"dall-e-3\"),\n    prompt: prompt,\n    size: \"1024x1024\",\n  });\n\n  return Response.json({\n    base64: image.base64,\n    uint8Array: image.uint8Array,\n    mediaType: image.mediaType,\n  });\n}\n```\n\n## Features\n\n- Accepts `Experimental_GeneratedImage` objects directly from the AI SDK\n- Automatically creates proper data URLs from base64-encoded image data\n- Supports all standard HTML image attributes\n- Responsive by default with `max-w-full h-auto` styling\n- Customizable with additional CSS classes\n- Includes proper TypeScript types for AI SDK compatibility\n\n## Props\n\n### `<Image />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `alt` | `string` | - | Alternative text for the image. |\n| `className` | `string` | - | Additional CSS classes to apply to the image. |\n| `...props` | `Experimental_GeneratedImage` | - | The image data to display, as returned by the AI SDK. |\n","isInternal":false,"tokens":944,"sizeBytes":4116},{"name":"inline-citation.md","path":".agents/skills/ai-elements/references/inline-citation.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/inline-citation.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Inline Citation\n\nA hoverable citation component that displays source information and quotes inline with text, perfect for AI-generated content with references.\n\nThe `InlineCitation` component provides a way to display citations inline with text content, similar to academic papers or research documents. It consists of a citation pill that shows detailed source information on hover, making it perfect for AI-generated content that needs to reference sources.\n\nSee `scripts/inline-citation.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add inline-citation\n```\n\n## Usage with AI SDK\n\nBuild citations for AI-generated content using [`experimental_generateObject`](/docs/reference/ai-sdk-ui/use-object).\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { experimental_useObject as useObject } from \"@ai-sdk/react\";\nimport {\n  InlineCitation,\n  InlineCitationText,\n  InlineCitationCard,\n  InlineCitationCardTrigger,\n  InlineCitationCardBody,\n  InlineCitationCarousel,\n  InlineCitationCarouselContent,\n  InlineCitationCarouselItem,\n  InlineCitationCarouselHeader,\n  InlineCitationCarouselIndex,\n  InlineCitationCarouselPrev,\n  InlineCitationCarouselNext,\n  InlineCitationSource,\n  InlineCitationQuote,\n} from \"@/components/ai-elements/inline-citation\";\nimport { Button } from \"@/components/ui/button\";\nimport { citationSchema } from \"@/app/api/citation/route\";\n\nconst CitationDemo = () => {\n  const { object, submit, isLoading } = useObject({\n    api: \"/api/citation\",\n    schema: citationSchema,\n  });\n\n  const handleSubmit = (topic: string) => {\n    submit({ prompt: topic });\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 space-y-6\">\n      <div className=\"flex gap-2 mb-6\">\n        <Button\n          onClick={() => handleSubmit(\"artificial intelligence\")}\n          disabled={isLoading}\n          variant=\"outline\"\n        >\n          Generate AI Content\n        </Button>\n        <Button\n          onClick={() => handleSubmit(\"climate change\")}\n          disabled={isLoading}\n          variant=\"outline\"\n        >\n          Generate Climate Content\n        </Button>\n      </div>\n\n      {isLoading && !object && (\n        <div className=\"text-muted-foreground\">\n          Generating content with citations...\n        </div>\n      )}\n\n      {object?.content && (\n        <div className=\"prose prose-sm max-w-none\">\n          <p className=\"leading-relaxed\">\n            {object.content.split(/(\\[\\d+\\])/).map((part, index) => {\n              const citationMatch = part.match(/\\[(\\d+)\\]/);\n              if (citationMatch) {\n                const citationNumber = citationMatch[1];\n                const citation = object.citations?.find(\n                  (c: any) => c.number === citationNumber\n                );\n\n                if (citation) {\n                  return (\n                    <InlineCitation key={index}>\n                      <InlineCitationCard>\n                        <InlineCitationCardTrigger sources={[citation.url]} />\n                        <InlineCitationCardBody>\n                          <InlineCitationCarousel>\n                            <InlineCitationCarouselHeader>\n                              <InlineCitationCarouselPrev />\n                              <InlineCitationCarouselNext />\n                              <InlineCitationCarouselIndex />\n                            </InlineCitationCarouselHeader>\n                            <InlineCitationCarouselContent>\n                              <InlineCitationCarouselItem>\n                                <InlineCitationSource\n                                  title={citation.title}\n                                  url={citation.url}\n                                  description={citation.description}\n                                />\n                                {citation.quote && (\n                                  <InlineCitationQuote>\n                                    {citation.quote}\n                                  </InlineCitationQuote>\n                                )}\n                              </InlineCitationCarouselItem>\n                            </InlineCitationCarouselContent>\n                          </InlineCitationCarousel>\n                        </InlineCitationCardBody>\n                      </InlineCitationCard>\n                    </InlineCitation>\n                  );\n                }\n              }\n              return part;\n            })}\n          </p>\n        </div>\n      )}\n    </div>\n  );\n};\n\nexport default CitationDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/citation/route.ts\"\nimport { streamObject } from \"ai\";\nimport { z } from \"zod\";\n\nexport const citationSchema = z.object({\n  content: z.string(),\n  citations: z.array(\n    z.object({\n      number: z.string(),\n      title: z.string(),\n      url: z.string(),\n      description: z.string().optional(),\n      quote: z.string().optional(),\n    })\n  ),\n});\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { prompt } = await req.json();\n\n  const result = streamObject({\n    model: \"openai/gpt-4o\",\n    schema: citationSchema,\n    prompt: `Generate a well-researched paragraph about ${prompt} with proper citations. \n    \n    Include:\n    - A comprehensive paragraph with inline citations marked as [1], [2], etc.\n    - 2-3 citations with realistic source information\n    - Each citation should have a title, URL, and optional description/quote\n    - Make the content informative and the sources credible\n    \n    Format citations as numbered references within the text.`,\n  });\n\n  return result.toTextStreamResponse();\n}\n```\n\n## Features\n\n- Hover interaction to reveal detailed citation information\n- **Carousel navigation** for multiple citations with prev/next controls\n- **Live index tracking** showing current slide position (e.g., \"1/5\")\n- Support for source titles, URLs, and descriptions\n- Optional quote blocks for relevant excerpts\n- Composable architecture for flexible citation formats\n- Accessible design with proper keyboard navigation\n- Seamless integration with AI-generated content\n- Clean visual design that doesn't disrupt reading flow\n- Smart badge display showing source hostname and count\n\n## Usage with AI SDK\n\nCurrently, there is no official support for inline citations with Streamdown or the Response component. This is because:\n\n- There isn't any good markdown syntax for inline citations\n- Language models don't naturally respond with inline citation syntax\n- The AI SDK doesn't have built-in support for inline citations\n\n### Potential Approaches\n\nWhile these methods are hypothetical and not officially supported, there are two conceptual ways inline citations could work with Streamdown:\n\n1. **Footnote conversion**: GitHub Flavored Markdown (GFM) handles footnotes using `[^1]` syntax. You could hypothetically remove the default footnote rendering and convert footnotes to inline citations instead.\n\n2. **Custom HTML syntax**: You could add a system prompt instructing the model to use a special HTML syntax like `<citation />` and pass that as a custom component to Streamdown.\n\nThese approaches require custom implementation and are not currently supported out of the box. We will investigate official support for this use case in the future.\n\nFor now, the recommended approach is to use `experimental_useObject` (as shown in the usage example above) to generate structured citation data, then manually parse and render inline citations.\n\n## Props\n\n### `<InlineCitation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root span element. |\n\n### `<InlineCitationText />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying span element. |\n\n### `<InlineCitationCard />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the HoverCard component. |\n\n### `<InlineCitationCardTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `sources` | `string[]` | - | Array of source URLs. The length determines the number displayed in the badge. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying button element. |\n\n### `<InlineCitationCardBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationCarousel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Carousel>` | - | Any other props are spread to the underlying Carousel component. |\n\n### `<InlineCitationCarouselContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying CarouselContent component. |\n\n### `<InlineCitationCarouselItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationCarouselHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationCarouselIndex />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. Children will override the default index display. |\n\n### `<InlineCitationCarouselPrev />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CarouselPrevious>` | - | Any other props are spread to the underlying CarouselPrevious component. |\n\n### `<InlineCitationCarouselNext />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CarouselNext>` | - | Any other props are spread to the underlying CarouselNext component. |\n\n### `<InlineCitationSource />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | - | The title of the source. |\n| `url` | `string` | - | The URL of the source. |\n| `description` | `string` | - | A brief description of the source. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationQuote />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying blockquote element. |\n","isInternal":false,"tokens":2311,"sizeBytes":11089},{"name":"jsx-preview.md","path":".agents/skills/ai-elements/references/jsx-preview.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/jsx-preview.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# JSX Preview\n\nA component that dynamically renders JSX strings with streaming support for AI-generated UI.\n\nThe `JSXPreview` component renders JSX strings dynamically, supporting streaming scenarios where JSX may be incomplete. It automatically closes unclosed tags during streaming, making it ideal for displaying AI-generated UI components in real-time.\n\nSee `scripts/jsx-preview.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add jsx-preview\n```\n\n## Features\n\n- Renders JSX strings dynamically using `react-jsx-parser`\n- Streaming support with automatic tag completion\n- Custom component injection for rendering your own components\n- Error handling with customizable error display\n- Context-based architecture for flexible composition\n\n## Usage with AI SDK\n\nThe JSXPreview component integrates with the AI SDK to render generated UI in real-time:\n\n```tsx title=\"components/generated-ui.tsx\"\n\"use client\";\n\nimport {\n  JSXPreview,\n  JSXPreviewContent,\n  JSXPreviewError,\n} from \"@/components/ai-elements/jsx-preview\";\n\ntype GeneratedUIProps = {\n  jsx: string;\n  isStreaming: boolean;\n};\n\nexport const GeneratedUI = ({ jsx, isStreaming }: GeneratedUIProps) => (\n  <JSXPreview\n    jsx={jsx}\n    isStreaming={isStreaming}\n    onError={(error) => console.error(\"JSX Parse Error:\", error)}\n  >\n    <JSXPreviewContent />\n    <JSXPreviewError />\n  </JSXPreview>\n);\n```\n\n### With Custom Components\n\nYou can inject custom components to be used within the rendered JSX:\n\n```tsx title=\"components/generated-ui-with-components.tsx\"\n\"use client\";\n\nimport {\n  JSXPreview,\n  JSXPreviewContent,\n} from \"@/components/ai-elements/jsx-preview\";\nimport { Button } from \"@/components/ui/button\";\nimport { Card } from \"@/components/ui/card\";\n\nconst customComponents = {\n  Button,\n  Card,\n};\n\nexport const GeneratedUIWithComponents = ({ jsx }: { jsx: string }) => (\n  <JSXPreview jsx={jsx} components={customComponents}>\n    <JSXPreviewContent />\n  </JSXPreview>\n);\n```\n\n## Props\n\n### `<JSXPreview />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `jsx` | `string` | Required | The JSX string to render. |\n| `isStreaming` | `boolean` | `false` | When true, automatically completes unclosed tags. |\n| `components` | `Record<string, React.ComponentType>` | - | Custom components available within the rendered JSX. |\n| `bindings` | `Record<string, unknown>` | - | Variables and functions available within the JSX scope. |\n| `onError` | `(error: Error) => void` | - | Callback fired when a parsing or rendering error occurs. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n### `<JSXPreviewContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `renderError` | `JsxParserProps[` | - | Custom error renderer passed to react-jsx-parser. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n### `<JSXPreviewError />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode | ((error: Error) => ReactNode)` | - | Custom error content or render function receiving the error. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n","isInternal":false,"tokens":771,"sizeBytes":3319},{"name":"message.md","path":".agents/skills/ai-elements/references/message.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/message.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Message\n\nA comprehensive suite of components for displaying chat messages, including message rendering, branching, actions, and markdown responses.\n\nThe `Message` component suite provides a complete set of tools for building chat interfaces. It includes components for displaying messages from users and AI assistants, managing multiple response branches, adding action buttons, and rendering markdown content.\n\nSee `scripts/message.tsx` for this example.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add message\n```\n\n## Features\n\n- Displays messages from both user and AI assistant with distinct styling and automatic alignment\n- Minimalist flat design with user messages in secondary background and assistant messages full-width\n- **Response branching** with navigation controls to switch between multiple AI response versions\n- **Markdown rendering** with GFM support (tables, task lists, strikethrough), math equations, and smart streaming\n- **Action buttons** for common operations (retry, like, dislike, copy, share) with tooltips and state management\n- **File attachments** display with support for images and generic files with preview and remove functionality\n- Code blocks with syntax highlighting and copy-to-clipboard functionality\n- Keyboard accessible with proper ARIA labels\n- Responsive design that adapts to different screen sizes\n- Seamless light/dark theme integration\n\n\n\n## Usage with AI SDK\n\nBuild a simple chat UI where the user can copy or regenerate the most recent message.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useState } from \"react\";\nimport {\n  MessageActions,\n  MessageAction,\n} from \"@/components/ai-elements/message\";\nimport { Message, MessageContent } from \"@/components/ai-elements/message\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { MessageResponse } from \"@/components/ai-elements/message\";\nimport { RefreshCcwIcon, CopyIcon } from \"lucide-react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport { Fragment } from \"react\";\n\nconst ActionsDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { messages, sendMessage, status, regenerate } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.map((message, messageIndex) => (\n              <Fragment key={message.id}>\n                {message.parts.map((part, i) => {\n                  switch (part.type) {\n                    case \"text\":\n                      const isLastMessage =\n                        messageIndex === messages.length - 1;\n\n                      return (\n                        <Fragment key={`${message.id}-${i}`}>\n                          <Message from={message.role}>\n                            <MessageContent>\n                              <MessageResponse>{part.text}</MessageResponse>\n                            </MessageContent>\n                          </Message>\n                          {message.role === \"assistant\" && isLastMessage && (\n                            <MessageActions>\n                              <MessageAction\n                                onClick={() => regenerate()}\n                                label=\"Retry\"\n                              >\n                                <RefreshCcwIcon className=\"size-3\" />\n                              </MessageAction>\n                              <MessageAction\n                                onClick={() =>\n                                  navigator.clipboard.writeText(part.text)\n                                }\n                                label=\"Copy\"\n                              >\n                                <CopyIcon className=\"size-3\" />\n                              </MessageAction>\n                            </MessageActions>\n                          )}\n                        </Fragment>\n                      );\n                    default:\n                      return null;\n                  }\n                })}\n              </Fragment>\n            ))}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Say something...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ActionsDemo;\n```\n\n## Props\n\n### `<Message />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `from` | `UIMessage[` | - | The role of the message sender ( |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the content div. |\n\n### `<MessageResponse />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The markdown content to render. |\n| `parseIncompleteMarkdown` | `boolean` | `true` | Whether to parse and fix incomplete markdown syntax (e.g., unclosed code blocks or lists). |\n| `className` | `string` | - | CSS class names to apply to the wrapper div element. |\n| `components` | `object` | - | Custom React components to use for rendering markdown elements (e.g., custom heading, paragraph, code block components). |\n| `allowedImagePrefixes` | `string[]` | `[` | Array of allowed URL prefixes for images. Use [ |\n| `allowedLinkPrefixes` | `string[]` | `[` | Array of allowed URL prefixes for links. Use [ |\n| `defaultOrigin` | `string` | - | Default origin to use for relative URLs in links and images. |\n| `rehypePlugins` | `array` | `[rehypeKatex]` | Array of rehype plugins to use for processing HTML. Includes KaTeX for math rendering by default. |\n| `remarkPlugins` | `array` | `[remarkGfm, remarkMath]` | Array of remark plugins to use for processing markdown. Includes GitHub Flavored Markdown and math support by default. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | HTML attributes to spread to the root div. |\n\n### `<MessageAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string` | - | Optional tooltip text shown on hover. |\n| `label` | `string` | - | Accessible label for screen readers. Also used as fallback if tooltip is not provided. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<MessageBranch />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultBranch` | `number` | `0` | The index of the branch to show by default. |\n| `onBranchChange` | `(branchIndex: number) => void` | - | Callback fired when the branch changes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageBranchContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageBranchSelector />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof ButtonGroup>` | - | Any other props are spread to the underlying ButtonGroup component. |\n\n### `<MessageBranchPrevious />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<MessageBranchNext />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<MessageBranchPage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the underlying span element. |\n\n### `<MessageToolbar />`\n\nA container for placing actions and branch selectors below a message. Lays out children in a horizontal row with space-between alignment.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div. |\n```\n","isInternal":false,"tokens":2007,"sizeBytes":9595},{"name":"mic-selector.md","path":".agents/skills/ai-elements/references/mic-selector.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/mic-selector.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Mic Selector\n\nA composable dropdown component for selecting audio input devices with permission handling and device change detection.\n\nThe `MicSelector` component provides a flexible and composable interface for selecting microphone input devices. Built on shadcn/ui's Command and Popover components, it features automatic device detection, permission handling, dynamic device list updates, and intelligent device name parsing.\n\nSee `scripts/mic-selector.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add mic-selector\n```\n\n## Features\n\n- Fully composable architecture with granular control components\n- Automatic audio input device enumeration\n- Permission-based device name display\n- Real-time device change detection via devicechange events\n- Intelligent device label parsing with ID extraction\n- Controlled and uncontrolled component patterns\n- Responsive width matching between trigger and content\n- Built on shadcn/ui Command and Popover components\n- Full TypeScript support with proper types for all components\n\n## Props\n\n### `<MicSelector />`\n\nRoot Popover component that provides context for all child components.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultValue` | `string` | - | The default selected device ID (uncontrolled). |\n| `value` | `string` | - | The selected device ID (controlled). |\n| `onValueChange` | `(deviceId: string) => void` | - | Callback fired when the selected device changes. |\n| `defaultOpen` | `boolean` | `false` | The default open state (uncontrolled). |\n| `open` | `boolean` | - | The open state (controlled). |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback fired when the open state changes. Automatically requests microphone permission when opened without permission. |\n| `...props` | `React.ComponentProps<typeof Popover>` | - | Any other props are spread to the Popover component. |\n\n### `<MicSelectorTrigger />`\n\nButton that opens the microphone selector popover. Automatically tracks its width to match the popover content.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component. |\n\n### `<MicSelectorValue />`\n\nDisplays the currently selected microphone name or a placeholder.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<MicSelectorContent />`\n\nContainer for the Command component, rendered inside the popover.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `popoverOptions` | `React.ComponentProps<typeof PopoverContent>` | - | Props to pass to the underlying PopoverContent component. |\n| `...props` | `React.ComponentProps<typeof Command>` | - | Any other props are spread to the Command component. |\n\n### `<MicSelectorInput />`\n\nSearch input for filtering microphones.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the CommandInput component. |\n\n### `<MicSelectorList />`\n\nWrapper for the list of microphone items. Uses render props pattern to provide access to device data.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `(devices: MediaDeviceInfo[]) => ReactNode` | - | Render function that receives the array of available devices. |\n| `...props` | `Omit<React.ComponentProps<typeof CommandList>, ` | - | Any other props are spread to the CommandList component. |\n\n### `<MicSelectorEmpty />`\n\nMessage shown when no microphones match the search.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode` | - | The message to display. |\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the CommandEmpty component. |\n\n### `<MicSelectorItem />`\n\nSelectable item representing a microphone.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The device ID for this item. |\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the CommandItem component. |\n\n### `<MicSelectorLabel />`\n\nDisplays a formatted microphone label with intelligent device ID parsing. Automatically extracts and styles device IDs in the format (XXXX:XXXX).\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `device` | `MediaDeviceInfo` | - | The MediaDeviceInfo object for the device. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n## Hooks\n\n### `useAudioDevices()`\n\nA custom hook for managing audio input devices. This hook is used internally by the `MicSelector` component but can also be used independently.\n\n```tsx\nimport { useAudioDevices } from \"@repo/elements/mic-selector\";\n\nexport default function Example() {\n  const { devices, loading, error, hasPermission, loadDevices } =\n    useAudioDevices();\n\n  return (\n    <div>\n      {loading && <p>Loading devices...</p>}\n      {error && <p>Error: {error}</p>}\n      {devices.map((device) => (\n        <div key={device.deviceId}>{device.label}</div>\n      ))}\n      {!hasPermission && (\n        <button onClick={loadDevices}>Grant Permission</button>\n      )}\n    </div>\n  );\n}\n```\n\n#### Return Value\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `devices` | `MediaDeviceInfo[]` | - | Array of available audio input devices. |\n| `loading` | `boolean` | - | Whether devices are currently being loaded. |\n| `error` | `string | null` | - | Error message if device loading failed. |\n| `hasPermission` | `boolean` | - | Whether microphone permission has been granted. |\n| `loadDevices` | `() => Promise<void>` | - | Function to request microphone permission and load device names. |\n\n## Behavior\n\n### Permission Handling\n\nThe component implements a two-stage permission approach:\n\n1. **Without Permission**: Initially loads devices without requesting permission. Device labels may show as generic names (e.g., \"Microphone 1\").\n2. **With Permission**: When the popover is opened and permission hasn't been granted, automatically requests microphone access and displays actual device names.\n\n### Device Label Parsing\n\nThe `MicSelectorLabel` component intelligently parses device names that include hardware IDs in the format `(XXXX:XXXX)`. It splits the label into the device name and ID, styling the ID with muted text for better readability.\n\nFor example: `\"MacBook Pro Microphone (1a2b:3c4d)\"` becomes:\n\n- Device name: `\"MacBook Pro Microphone\"`\n- Device ID: `\"(1a2b:3c4d)\"` (styled with muted color)\n\n### Width Synchronization\n\nThe `MicSelectorTrigger` uses a ResizeObserver to track its width and automatically synchronizes it with the `MicSelectorContent` popover width for a cohesive appearance.\n\n### Device Change Detection\n\nThe component listens for `devicechange` events (e.g., plugging/unplugging microphones) and automatically updates the device list in real-time.\n\n## Accessibility\n\n- Uses semantic HTML with proper ARIA attributes via shadcn/ui components\n- Full keyboard navigation support through Command component\n- Screen reader friendly with proper labels and roles\n- Searchable device list for quick selection\n\n## Notes\n\n- Requires a secure context (HTTPS or localhost) for microphone access\n- Browser may prompt user for microphone permission on first open\n- Device labels are only fully descriptive after permission is granted\n- Component handles cleanup of temporary media streams during permission requests\n- Uses Radix UI's `useControllableState` for flexible controlled/uncontrolled patterns\n","isInternal":false,"tokens":1728,"sizeBytes":7875},{"name":"model-selector.md","path":".agents/skills/ai-elements/references/model-selector.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/model-selector.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Model Selector\n\nA searchable command palette for selecting AI models in your chat interface.\n\nThe `ModelSelector` component provides a searchable command palette interface for selecting AI models. It's built on top of the cmdk library and provides a keyboard-navigable interface with search functionality.\n\nSee `scripts/model-selector.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add model-selector\n```\n\n## Features\n\n- Searchable interface with keyboard navigation\n- Fuzzy search filtering across model names\n- Grouped model organization by provider\n- Keyboard shortcuts support\n- Empty state handling\n- Customizable styling with Tailwind CSS\n- Built on cmdk for excellent accessibility\n- TypeScript support with proper type definitions\n\n## Props\n\n### `<ModelSelector />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Dialog>` | - | Any other props are spread to the underlying Dialog component. |\n\n### `<ModelSelectorTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DialogTrigger>` | - | Any other props are spread to the underlying DialogTrigger component. |\n\n### `<ModelSelectorContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `ReactNode` | - | Accessible title for the dialog (rendered in sr-only). |\n| `...props` | `React.ComponentProps<typeof DialogContent>` | - | Any other props are spread to the underlying DialogContent component. |\n\n### `<ModelSelectorDialog />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandDialog>` | - | Any other props are spread to the underlying CommandDialog component. |\n\n### `<ModelSelectorInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the underlying CommandInput component. |\n\n### `<ModelSelectorList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandList>` | - | Any other props are spread to the underlying CommandList component. |\n\n### `<ModelSelectorEmpty />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the underlying CommandEmpty component. |\n\n### `<ModelSelectorGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandGroup>` | - | Any other props are spread to the underlying CommandGroup component. |\n\n### `<ModelSelectorItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the underlying CommandItem component. |\n\n### `<ModelSelectorShortcut />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandShortcut>` | - | Any other props are spread to the underlying CommandShortcut component. |\n\n### `<ModelSelectorSeparator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandSeparator>` | - | Any other props are spread to the underlying CommandSeparator component. |\n\n### `<ModelSelectorLogo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `provider` | `string` | Required | The AI provider name. Supports major providers like  |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the underlying img element (except src and alt which are generated). |\n\n### `<ModelSelectorLogoGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n### `<ModelSelectorName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying span element. |\n","isInternal":false,"tokens":971,"sizeBytes":4378},{"name":"node.md","path":".agents/skills/ai-elements/references/node.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/node.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Node\n\nA composable node component for React Flow-based canvases with Card-based styling.\n\nThe `Node` component provides a composable, Card-based node for React Flow canvases. It includes support for connection handles, structured layouts, and consistent styling using shadcn/ui components.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add node\n```\n\n## Features\n\n- Built on shadcn/ui Card components for consistent styling\n- Automatic handle placement (left for target, right for source)\n- Composable sub-components (Header, Title, Description, Action, Content, Footer)\n- Semantic structure for organizing node information\n- Pre-styled sections with borders and backgrounds\n- Responsive sizing with fixed small width\n- Full TypeScript support with proper type definitions\n- Compatible with React Flow's node system\n\n## Props\n\n### `<Node />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `handles` | `unknown` | - | Configuration for connection handles. Target renders on the left, source on the right. |\n| `className` | `string` | - | Additional CSS classes to apply to the node. |\n| `...props` | `ComponentProps<typeof Card>` | - | Any other props are spread to the underlying Card component. |\n\n### `<NodeHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the header. |\n| `...props` | `ComponentProps<typeof CardHeader>` | - | Any other props are spread to the underlying CardHeader component. |\n\n### `<NodeTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof CardTitle>` | - | Any other props are spread to the underlying CardTitle component. |\n\n### `<NodeDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof CardDescription>` | - | Any other props are spread to the underlying CardDescription component. |\n\n### `<NodeAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof CardAction>` | - | Any other props are spread to the underlying CardAction component. |\n\n### `<NodeContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the content. |\n| `...props` | `ComponentProps<typeof CardContent>` | - | Any other props are spread to the underlying CardContent component. |\n\n### `<NodeFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the footer. |\n| `...props` | `ComponentProps<typeof CardFooter>` | - | Any other props are spread to the underlying CardFooter component. |\n","isInternal":false,"tokens":649,"sizeBytes":2870},{"name":"open-in-chat.md","path":".agents/skills/ai-elements/references/open-in-chat.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/open-in-chat.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Open In Chat\n\nA dropdown menu for opening queries in various AI chat platforms including ChatGPT, Claude, T3, Scira, and v0.\n\nThe `OpenIn` component provides a dropdown menu that allows users to open queries in different AI chat platforms with a single click.\n\nSee `scripts/open-in-chat.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add open-in-chat\n```\n\n## Features\n\n- Pre-configured links to popular AI chat platforms\n- Context-based query passing for cleaner API\n- Customizable dropdown trigger button\n- Automatic URL parameter encoding for queries\n- Support for ChatGPT, Claude, T3 Chat, Scira AI, v0, and Cursor\n- Branded icons for each platform\n- TypeScript support with proper type definitions\n- Accessible dropdown menu with keyboard navigation\n- External link indicators for clarity\n\n## Supported Platforms\n\n- **ChatGPT** - Opens query in OpenAI's ChatGPT with search hints\n- **Claude** - Opens query in Anthropic's Claude AI\n- **T3 Chat** - Opens query in T3 Chat platform\n- **Scira AI** - Opens query in Scira's AI assistant\n- **v0** - Opens query in Vercel's v0 platform\n- **Cursor** - Opens query in Cursor AI editor\n\n## Props\n\n### `<OpenIn />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `query` | `string` | - | The query text to be sent to all AI platforms. |\n| `...props` | `React.ComponentProps<typeof DropdownMenu>` | - | Props to spread to the underlying radix-ui DropdownMenu component. |\n\n### `<OpenInTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom trigger button. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuTrigger>` | - | Props to spread to the underlying DropdownMenuTrigger component. |\n\n### `<OpenInContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the dropdown content. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuContent>` | - | Props to spread to the underlying DropdownMenuContent component. |\n\n### `<OpenInChatGPT />`, `<OpenInClaude />`, `<OpenInT3 />`, `<OpenInScira />`, `<OpenInv0 />`, `<OpenInCursor />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Props to spread to the underlying DropdownMenuItem component. The query is automatically provided via context from the parent OpenIn component. |\n\n### `<OpenInItem />`, `<OpenInLabel />`, `<OpenInSeparator />`\n\nAdditional composable components for custom dropdown menu items, labels, and separators that follow the same props pattern as their underlying radix-ui counterparts.\n","isInternal":false,"tokens":660,"sizeBytes":2764},{"name":"package-info.md","path":".agents/skills/ai-elements/references/package-info.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/package-info.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Package Info\n\nDisplay dependency information and version changes.\n\nThe `PackageInfo` component displays package dependency information including version changes and change type badges.\n\nSee `scripts/package-info.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add package-info\n```\n\n## Features\n\n- Version change display (current → new)\n- Color-coded change type badges\n- Dependencies list\n- Description support\n\n## Change Types\n\n| Type      | Color  | Use Case           |\n| --------- | ------ | ------------------ |\n| `major`   | Red    | Breaking changes   |\n| `minor`   | Yellow | New features       |\n| `patch`   | Green  | Bug fixes          |\n| `added`   | Blue   | New dependency     |\n| `removed` | Gray   | Removed dependency |\n\n## Props\n\n### `<PackageInfo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | Package name. |\n| `currentVersion` | `string` | - | Current installed version. |\n| `newVersion` | `string` | - | New version being installed. |\n| `changeType` | `unknown` | - | Type of version change. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the header div. |\n\n### `<PackageInfoName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom name content. Defaults to the name from context. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoChangeType />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom change type label. Defaults to the changeType from context. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the Badge component. |\n\n### `<PackageInfoVersion />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom version content. Defaults to version transition display. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Spread to the p element. |\n\n### `<PackageInfoContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoDependencies />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoDependency />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | Dependency name. |\n| `version` | `string` | - | Dependency version. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the row div. |\n","isInternal":false,"tokens":778,"sizeBytes":3241},{"name":"panel.md","path":".agents/skills/ai-elements/references/panel.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/panel.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Panel\n\nA styled panel component for React Flow-based canvases to position custom UI elements.\n\nThe `Panel` component provides a positioned container for custom UI elements on React Flow canvases. It includes modern card styling with backdrop blur and flexible positioning options.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add panel\n```\n\n## Features\n\n- Flexible positioning (top-left, top-right, bottom-left, bottom-right, top-center, bottom-center)\n- Rounded pill design with backdrop blur\n- Theme-aware card background\n- Flexbox layout for easy content alignment\n- Subtle drop shadow for depth\n- Full TypeScript support\n- Compatible with React Flow's panel system\n\n## Props\n\n### `<Panel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `position` | `unknown` | - | Position of the panel on the canvas. |\n| `className` | `string` | - | Additional CSS classes to apply to the panel. |\n| `...props` | `ComponentProps<typeof Panel>` | - | Any other props from @xyflow/react Panel component. |\n","isInternal":false,"tokens":232,"sizeBytes":1040},{"name":"persona.md","path":".agents/skills/ai-elements/references/persona.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/persona.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Persona\n\nAn animated AI visual component powered by Rive that responds to different states like listening, thinking, and speaking.\n\nThe `Persona` component displays an animated AI visual that responds to different conversational states. Built with Rive WebGL2, it provides smooth, high-performance animations for various AI interaction states including idle, listening, thinking, speaking, and asleep. The component supports multiple visual variants to match different design aesthetics.\n\nSee `scripts/persona-obsidian.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add persona\n```\n\n## Features\n\n- Smooth state-based animations powered by Rive\n- Multiple visual variants (obsidian, mana, opal, halo, glint, command)\n- Responsive to five distinct states: idle, listening, thinking, speaking, and asleep\n- WebGL2-accelerated rendering for optimal performance\n- Customizable size and styling\n- Lifecycle callbacks for load, ready, pause, play, and stop events\n- TypeScript support with full type definitions\n\n## Variants\n\nThe Persona component comes with 6 distinct visual variants, each with its own unique aesthetic:\n\n### Obsidian (Default)\n\nSee `scripts/persona-obsidian.tsx` for this example.\n\n### Mana\n\nSee `scripts/persona-mana.tsx` for this example.\n\n### Opal\n\nSee `scripts/persona-opal.tsx` for this example.\n\n### Halo\n\nSee `scripts/persona-halo.tsx` for this example.\n\n### Glint\n\nSee `scripts/persona-glint.tsx` for this example.\n\n### Command\n\nSee `scripts/persona-command.tsx` for this example.\n\n## Props\n\n### `<Persona />`\n\nThe root component that renders the animated AI visual.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `state` | `unknown` | - | The current state of the AI persona. Controls which animation is displayed. |\n| `variant` | `unknown` | - | The visual style variant to display. |\n| `className` | `string` | - | Additional CSS classes to apply to the component. |\n| `onLoad` | `RiveParameters[` | - | Callback fired when the Rive file starts loading. |\n| `onLoadError` | `RiveParameters[` | - | Callback fired if the Rive file fails to load. |\n| `onReady` | `() => void` | - | Callback fired when the Rive animation is ready to play. |\n| `onPause` | `RiveParameters[` | - | Callback fired when the animation is paused. |\n| `onPlay` | `RiveParameters[` | - | Callback fired when the animation starts playing. |\n| `onStop` | `RiveParameters[` | - | Callback fired when the animation is stopped. |\n\n## States\n\nThe Persona component responds to five distinct states, each triggering different animations:\n\n- **idle**: The default resting state when the AI is not active\n- **listening**: Displayed when the AI is actively listening to user input (e.g., during voice recording)\n- **thinking**: Shown when the AI is processing or generating a response\n- **speaking**: Active when the AI is delivering a response (e.g., text-to-speech output)\n- **asleep**: A dormant state for when the AI is inactive or in low-power mode\n\n## React Strict Mode (Vite)\n\nThe Persona component uses WebGL2 for rendering. Browsers limit the number of active WebGL2 contexts (~8–16), and React Strict Mode (enabled by default in Vite dev) double-mounts components, which can exhaust that limit and crash the page.\n\nThe component includes a built-in guard that defers WebGL2 initialization by one frame, preventing context creation during Strict Mode's throw-away mount. This means the component works in Vite dev mode out of the box — no configuration needed.\n\nIf you still experience crashes (for example, when rendering many Persona instances simultaneously), reduce the number of concurrent Persona components on screen.\n\n## Usage Examples\n\n### Basic Usage\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\n\nexport default function App() {\n  return <Persona state=\"listening\" variant=\"opal\" />;\n}\n```\n\n### With State Management\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\nimport { useState } from \"react\";\n\nexport default function App() {\n  const [state, setState] = useState<\n    \"idle\" | \"listening\" | \"thinking\" | \"speaking\" | \"asleep\"\n  >(\"idle\");\n\n  const startListening = () => setState(\"listening\");\n  const startThinking = () => setState(\"thinking\");\n  const startSpeaking = () => setState(\"speaking\");\n  const reset = () => setState(\"idle\");\n\n  return (\n    <div>\n      <Persona state={state} variant=\"opal\" className=\"size-32\" />\n      <div>\n        <button onClick={startListening}>Listen</button>\n        <button onClick={startThinking}>Think</button>\n        <button onClick={startSpeaking}>Speak</button>\n        <button onClick={reset}>Reset</button>\n      </div>\n    </div>\n  );\n}\n```\n\n### With Custom Styling\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\n\nexport default function App() {\n  return (\n    <Persona\n      state=\"thinking\"\n      variant=\"halo\"\n      className=\"size-64 rounded-full border border-border\"\n    />\n  );\n}\n```\n\n### With Lifecycle Callbacks\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\n\nexport default function App() {\n  return (\n    <Persona\n      state=\"listening\"\n      variant=\"glint\"\n      onReady={() => console.log(\"Animation ready\")}\n      onLoad={() => console.log(\"Starting to load\")}\n      onLoadError={(error) => console.error(\"Failed to load:\", error)}\n      onPlay={() => console.log(\"Animation playing\")}\n      onPause={() => console.log(\"Animation paused\")}\n      onStop={() => console.log(\"Animation stopped\")}\n    />\n  );\n}\n```\n","isInternal":false,"tokens":1272,"sizeBytes":5500},{"name":"plan.md","path":".agents/skills/ai-elements/references/plan.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/plan.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Plan\n\nA collapsible plan component for displaying AI-generated execution plans with streaming support and shimmer animations.\n\nThe `Plan` component provides a flexible system for displaying AI-generated execution plans with collapsible content. Perfect for showing multi-step workflows, task breakdowns, and implementation strategies with support for streaming content and loading states.\n\nSee `scripts/plan.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add plan\n```\n\n## Features\n\n- Collapsible content with smooth animations\n- Streaming support with shimmer loading states\n- Built on shadcn/ui Card and Collapsible components\n- TypeScript support with comprehensive type definitions\n- Customizable styling with Tailwind CSS\n- Responsive design with mobile-friendly interactions\n- Keyboard navigation and accessibility support\n- Theme-aware with automatic dark mode support\n- Context-based state management for streaming\n\n## Props\n\n### `<Plan />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `isStreaming` | `boolean` | `false` | Whether content is currently streaming. Enables shimmer animations on title and description. |\n| `defaultOpen` | `boolean` | - | Whether the plan is expanded by default. |\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the Collapsible component. |\n\n### `<PlanHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CardHeader>` | - | Any other props are spread to the CardHeader component. |\n\n### `<PlanTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The title text. Displays with shimmer animation when isStreaming is true. |\n| `...props` | `Omit<React.ComponentProps<typeof CardTitle>, ` | - | Any other props (except children) are spread to the CardTitle component. |\n\n### `<PlanDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The description text. Displays with shimmer animation when isStreaming is true. |\n| `...props` | `Omit<React.ComponentProps<typeof CardDescription>, ` | - | Any other props (except children) are spread to the CardDescription component. |\n\n### `<PlanTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. Renders as a Button with chevron icon. |\n\n### `<PlanContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CardContent>` | - | Any other props are spread to the CardContent component. |\n\n### `<PlanFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<PlanAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CardAction>` | - | Any other props are spread to the CardAction component. |\n","isInternal":false,"tokens":726,"sizeBytes":3271},{"name":"prompt-input.md","path":".agents/skills/ai-elements/references/prompt-input.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/prompt-input.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Prompt Input\n\nAllows a user to send a message with file attachments to a large language model. It includes a textarea, file upload capabilities, a submit button, and a dropdown for selecting the model.\n\nThe `PromptInput` component allows a user to send a message with file attachments to a large language model. It includes a textarea, file upload capabilities, a submit button, and a dropdown for selecting the model.\n\nSee `scripts/prompt-input.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add prompt-input\n```\n\n## Usage with AI SDK\n\nBuild a fully functional chat app using `PromptInput`, [`Conversation`](/components/conversation) with a model picker:\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Attachment,\n  AttachmentPreview,\n  AttachmentRemove,\n  Attachments,\n} from \"@/components/ai-elements/attachments\";\nimport {\n  PromptInput,\n  PromptInputActionAddAttachments,\n  PromptInputActionAddScreenshot,\n  PromptInputActionMenu,\n  PromptInputActionMenuContent,\n  PromptInputActionMenuTrigger,\n  PromptInputBody,\n  PromptInputButton,\n  PromptInputHeader,\n  type PromptInputMessage,\n  PromptInputSelect,\n  PromptInputSelectContent,\n  PromptInputSelectItem,\n  PromptInputSelectTrigger,\n  PromptInputSelectValue,\n  PromptInputSubmit,\n  PromptInputTextarea,\n  PromptInputFooter,\n  PromptInputTools,\n  usePromptInputAttachments,\n} from \"@/components/ai-elements/prompt-input\";\nimport { GlobeIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\n\nconst PromptInputAttachmentsDisplay = () => {\n  const attachments = usePromptInputAttachments();\n\n  if (attachments.files.length === 0) {\n    return null;\n  }\n\n  return (\n    <Attachments variant=\"inline\">\n      {attachments.files.map((attachment) => (\n        <Attachment\n          data={attachment}\n          key={attachment.id}\n          onRemove={() => attachments.remove(attachment.id)}\n        >\n          <AttachmentPreview />\n          <AttachmentRemove />\n        </Attachment>\n      ))}\n    </Attachments>\n  );\n};\n\nconst models = [\n  { id: \"gpt-4o\", name: \"GPT-4o\" },\n  { id: \"claude-opus-4-20250514\", name: \"Claude 4 Opus\" },\n];\n\nconst InputDemo = () => {\n  const [text, setText] = useState<string>(\"\");\n  const [model, setModel] = useState<string>(models[0].id);\n  const [useWebSearch, setUseWebSearch] = useState<boolean>(false);\n\n  const { messages, status, sendMessage } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    const hasText = Boolean(message.text);\n    const hasAttachments = Boolean(message.files?.length);\n\n    if (!(hasText || hasAttachments)) {\n      return;\n    }\n\n    sendMessage(\n      {\n        text: message.text || \"Sent with attachments\",\n        files: message.files,\n      },\n      {\n        body: {\n          model: model,\n          webSearch: useWebSearch,\n        },\n      }\n    );\n    setText(\"\");\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.map((message) => (\n              <Message from={message.role} key={message.id}>\n                <MessageContent>\n                  {message.parts.map((part, i) => {\n                    switch (part.type) {\n                      case \"text\":\n                        return (\n                          <MessageResponse key={`${message.id}-${i}`}>\n                            {part.text}\n                          </MessageResponse>\n                        );\n                      default:\n                        return null;\n                    }\n                  })}\n                </MessageContent>\n              </Message>\n            ))}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4\"\n          globalDrop\n          multiple\n        >\n          <PromptInputHeader>\n            <PromptInputAttachmentsDisplay />\n          </PromptInputHeader>\n          <PromptInputBody>\n            <PromptInputTextarea\n              onChange={(e) => setText(e.target.value)}\n              value={text}\n            />\n          </PromptInputBody>\n          <PromptInputFooter>\n            <PromptInputTools>\n              <PromptInputActionMenu>\n                <PromptInputActionMenuTrigger />\n                <PromptInputActionMenuContent>\n                  <PromptInputActionAddAttachments />\n                  <PromptInputActionAddScreenshot />\n                </PromptInputActionMenuContent>\n              </PromptInputActionMenu>\n              <PromptInputButton\n                onClick={() => setUseWebSearch(!useWebSearch)}\n                tooltip={{ content: \"Search the web\", shortcut: \"⌘K\" }}\n                variant={useWebSearch ? \"default\" : \"ghost\"}\n              >\n                <GlobeIcon size={16} />\n                <span>Search</span>\n              </PromptInputButton>\n              <PromptInputSelect\n                onValueChange={(value) => {\n                  setModel(value);\n                }}\n                value={model}\n              >\n                <PromptInputSelectTrigger>\n                  <PromptInputSelectValue />\n                </PromptInputSelectTrigger>\n                <PromptInputSelectContent>\n                  {models.map((model) => (\n                    <PromptInputSelectItem key={model.id} value={model.id}>\n                      {model.name}\n                    </PromptInputSelectItem>\n                  ))}\n                </PromptInputSelectContent>\n              </PromptInputSelect>\n            </PromptInputTools>\n            <PromptInputSubmit disabled={!text && !status} status={status} />\n          </PromptInputFooter>\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default InputDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/chat/route.ts\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const {\n    model,\n    messages,\n    webSearch,\n  }: {\n    messages: UIMessage[];\n    model: string;\n    webSearch?: boolean;\n  } = await req.json();\n\n  const result = streamText({\n    model: webSearch ? \"perplexity/sonar\" : model,\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Auto-resizing textarea that adjusts height based on content\n- File attachment support with drag-and-drop\n- Built-in screenshot capture action\n- Image preview for image attachments\n- Configurable file constraints (max files, max size, accepted types)\n- Automatic submit button icons based on status\n- Support for keyboard shortcuts (Enter to submit, Shift+Enter for new line)\n- Customizable min/max height for the textarea\n- Flexible toolbar with support for custom actions and tools\n- Built-in model selection dropdown\n- Built-in native speech recognition button (Web Speech API)\n- Optional provider for lifted state management\n- Form automatically resets on submit\n- Responsive design with mobile-friendly controls\n- Clean, modern styling with customizable themes\n- Form-based submission handling\n- Hidden file input sync for native form posts\n- Global document drop support (opt-in)\n\n## Examples\n\n### Cursor style\n\nSee `scripts/prompt-input-cursor.tsx` for this example.\n\n### Button tooltips\n\nButtons can display tooltips with optional keyboard shortcut hints. Hover over the buttons below to see the tooltips.\n\nSee `scripts/prompt-input-tooltip.tsx` for this example.\n\n## Props\n\n### `<PromptInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onSubmit` | `(message: PromptInputMessage, event: FormEvent) => void` | - | Handler called when the form is submitted with message text and files. |\n| `accept` | `string` | - | File types to accept (e.g.,  |\n| `multiple` | `boolean` | - | Whether to allow multiple file selection. |\n| `globalDrop` | `boolean` | - | When true, accepts file drops anywhere on the document. |\n| `syncHiddenInput` | `boolean` | - | Render a hidden input with given name for native form posts. |\n| `maxFiles` | `number` | - | Maximum number of files allowed. |\n| `maxFileSize` | `number` | - | Maximum file size in bytes. |\n| `onError` | `(err: { code: ` | - | Handler for file validation errors. |\n| `...props` | `React.HTMLAttributes<HTMLFormElement>` | - | Any other props are spread to the root form element. |\n\n### `<PromptInputTextarea />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Textarea>` | - | Any other props are spread to the underlying Textarea component. |\n\n### `<PromptInputFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the toolbar div. |\n\n### `<PromptInputTools />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the tools div. |\n\n### `<PromptInputButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string | { content: ReactNode; shortcut?: string; side?: ` | - | Optional tooltip to display on hover. Can be a string or an object with content, shortcut, and side properties. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n#### Tooltip Examples\n\n```tsx\n// Simple string tooltip\n<PromptInputButton tooltip=\"Search the web\">\n  <GlobeIcon size={16} />\n</PromptInputButton>\n\n// Tooltip with keyboard shortcut hint\n<PromptInputButton tooltip={{ content: \"Search\", shortcut: \"⌘K\" }}>\n  <GlobeIcon size={16} />\n</PromptInputButton>\n\n// Tooltip with custom position\n<PromptInputButton tooltip={{ content: \"Search\", side: \"bottom\" }}>\n  <GlobeIcon size={16} />\n</PromptInputButton>\n```\n\n### `<PromptInputSubmit />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `status` | `ChatStatus` | - | Current chat status to determine button icon (submitted, streaming, error). |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<PromptInputSelect />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Select>` | - | Any other props are spread to the underlying Select component. |\n\n### `<PromptInputSelectTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof SelectTrigger>` | - | Any other props are spread to the underlying SelectTrigger component. |\n\n### `<PromptInputSelectContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof SelectContent>` | - | Any other props are spread to the underlying SelectContent component. |\n\n### `<PromptInputSelectItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof SelectItem>` | - | Any other props are spread to the underlying SelectItem component. |\n\n### `<PromptInputSelectValue />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof SelectValue>` | - | Any other props are spread to the underlying SelectValue component. |\n\n### `<PromptInputBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the body div. |\n\n### Attachments\n\nAttachment components have been moved to a separate module. See the [Attachment](/components/attachment) component documentation for details on `<Attachments />`, `<Attachment />`, `<AttachmentPreview />`, `<AttachmentInfo />`, and `<AttachmentRemove />`.\n\n### `<PromptInputActionMenu />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenu>` | - | Any other props are spread to the underlying DropdownMenu component. |\n\n### `<PromptInputActionMenuTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying Button component. |\n\n### `<PromptInputActionMenuContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenuContent>` | - | Any other props are spread to the underlying DropdownMenuContent component. |\n\n### `<PromptInputActionMenuItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Any other props are spread to the underlying DropdownMenuItem component. |\n\n### `<PromptInputActionAddAttachments />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | Label for the menu item. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Any other props are spread to the underlying DropdownMenuItem component. |\n\n### `<PromptInputActionAddScreenshot />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | Label for the menu item. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Any other props are spread to the underlying DropdownMenuItem component. |\n\n### `<PromptInputProvider />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `initialInput` | `string` | - | Initial text input value. |\n| `children` | `React.ReactNode` | - | Child components that will have access to the provider context. |\n\nOptional global provider that lifts PromptInput state outside of PromptInput. When used, it allows you to access and control the input state from anywhere within the provider tree. If not used, PromptInput stays fully self-managed.\n\n### `<PromptInputHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `Omit<React.ComponentProps<typeof InputGroupAddon>, ` | - | Any other props (except align) are spread to the InputGroupAddon component. |\n\n### `<PromptInputHoverCard />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `openDelay` | `number` | `0` | Delay in milliseconds before opening. |\n| `closeDelay` | `number` | `0` | Delay in milliseconds before closing. |\n| `...props` | `React.ComponentProps<typeof HoverCard>` | - | Any other props are spread to the HoverCard component. |\n\n### `<PromptInputHoverCardTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof HoverCardTrigger>` | - | Any other props are spread to the HoverCardTrigger component. |\n\n### `<PromptInputHoverCardContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `align` | `unknown` | - | Alignment of the hover card content. |\n| `...props` | `React.ComponentProps<typeof HoverCardContent>` | - | Any other props are spread to the HoverCardContent component. |\n\n### `<PromptInputTabsList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<PromptInputTab />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<PromptInputTabLabel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLHeadingElement>` | - | Any other props are spread to the h3 element. |\n\n### `<PromptInputTabBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<PromptInputTabItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<PromptInputCommand />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Command>` | - | Any other props are spread to the Command component. |\n\n### `<PromptInputCommandInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the CommandInput component. |\n\n### `<PromptInputCommandList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandList>` | - | Any other props are spread to the CommandList component. |\n\n### `<PromptInputCommandEmpty />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the CommandEmpty component. |\n\n### `<PromptInputCommandGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandGroup>` | - | Any other props are spread to the CommandGroup component. |\n\n### `<PromptInputCommandItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the CommandItem component. |\n\n### `<PromptInputCommandSeparator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandSeparator>` | - | Any other props are spread to the CommandSeparator component. |\n\n## Hooks\n\n### `usePromptInputAttachments`\n\nAccess and manage file attachments within a PromptInput context.\n\n```tsx\nconst attachments = usePromptInputAttachments();\n\n// Available methods:\nattachments.files; // Array of current attachments\nattachments.add(files); // Add new files\nattachments.remove(id); // Remove an attachment by ID\nattachments.clear(); // Clear all attachments\nattachments.openFileDialog(); // Open file selection dialog\n```\n\n### `usePromptInputController`\n\nAccess the full PromptInput controller from a PromptInputProvider. Only available when using the provider.\n\n```tsx\nconst controller = usePromptInputController();\n\n// Available methods:\ncontroller.textInput.value; // Current text input value\ncontroller.textInput.setInput(value); // Set text input value\ncontroller.textInput.clear(); // Clear text input\ncontroller.attachments; // Same as usePromptInputAttachments\n```\n\n### `useProviderAttachments`\n\nAccess attachments context from a PromptInputProvider. Only available when using the provider.\n\n```tsx\nconst attachments = useProviderAttachments();\n\n// Same interface as usePromptInputAttachments\n```\n\n### `usePromptInputReferencedSources`\n\nAccess referenced sources context within a PromptInput.\n\n```tsx\nconst sources = usePromptInputReferencedSources();\n\n// Available methods:\nsources.sources; // Array of current referenced sources\nsources.add(sources); // Add new source(s)\nsources.remove(id); // Remove a source by ID\nsources.clear(); // Clear all sources\n```\n","isInternal":false,"tokens":4481,"sizeBytes":20226},{"name":"queue.md","path":".agents/skills/ai-elements/references/queue.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/queue.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Queue\n\nA comprehensive queue component system for displaying message lists, todos, and collapsible task sections in AI applications.\n\nThe `Queue` component provides a flexible system for displaying lists of messages, todos, attachments, and collapsible sections. Perfect for showing AI workflow progress, pending tasks, message history, or any structured list of items in your application.\n\nSee `scripts/queue.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add queue\n```\n\n## Features\n\n- Flexible component system with composable parts\n- Collapsible sections with smooth animations\n- Support for completed/pending state indicators\n- Built-in scroll area for long lists\n- Attachment display with images and file indicators\n- Hover-revealed action buttons for queue items\n- TypeScript support with comprehensive type definitions\n- Customizable styling with Tailwind CSS\n- Responsive design with mobile-friendly interactions\n- Keyboard navigation and accessibility support\n- Theme-aware with automatic dark mode support\n\n## Examples\n\n### With PromptInput\n\nSee `scripts/queue-prompt-input.tsx` for this example.\n\n## Props\n\n### `<Queue />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div. |\n\n### `<QueueSection />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultOpen` | `boolean` | `true` | Whether the section is open by default. |\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the Collapsible component. |\n\n### `<QueueSectionTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the button element. |\n\n### `<QueueSectionLabel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | The label text to display. |\n| `count` | `number` | - | The count to display before the label. |\n| `icon` | `React.ReactNode` | - | An optional icon to display before the count. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<QueueSectionContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent component. |\n\n### `<QueueList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof ScrollArea>` | - | Any other props are spread to the ScrollArea component. |\n\n### `<QueueItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the li element. |\n\n### `<QueueItemIndicator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `completed` | `boolean` | `false` | Whether the item is completed. Affects the indicator styling. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<QueueItemContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `completed` | `boolean` | `false` | Whether the item is completed. Affects text styling with strikethrough and opacity. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<QueueItemDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `completed` | `boolean` | `false` | Whether the item is completed. Affects text styling. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<QueueItemActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<QueueItemAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `Omit<React.ComponentProps<typeof Button>, ` | - | Any other props (except variant and size) are spread to the Button component. |\n\n### `<QueueItemAttachment />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<QueueItemImage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the img element. |\n\n### `<QueueItemFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n## Type Exports\n\n### `QueueMessagePart`\n\nInterface for message parts within queue messages.\n\n```tsx\ninterface QueueMessagePart {\n  type: string;\n  text?: string;\n  url?: string;\n  filename?: string;\n  mediaType?: string;\n}\n```\n\n### `QueueMessage`\n\nInterface for queue message items.\n\n```tsx\ninterface QueueMessage {\n  id: string;\n  parts: QueueMessagePart[];\n}\n```\n\n### `QueueTodo`\n\nInterface for todo items in the queue.\n\n```tsx\ninterface QueueTodo {\n  id: string;\n  title: string;\n  description?: string;\n  status?: \"pending\" | \"completed\";\n}\n```\n","isInternal":false,"tokens":1309,"sizeBytes":5481},{"name":"reasoning.md","path":".agents/skills/ai-elements/references/reasoning.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/reasoning.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Reasoning\n\nA collapsible component that displays AI reasoning content, automatically opening during streaming and closing when finished.\n\nThe `Reasoning` component displays AI reasoning content, automatically opening during streaming and closing when finished.\n\nSee `scripts/reasoning.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add reasoning\n```\n\n## Usage with AI SDK\n\nBuild a chatbot with reasoning using Deepseek R1 or other reasoning models.\n\nSome models (like GPT with high reasoning effort) return multiple reasoning parts instead of a single streaming block. The example below consolidates all reasoning parts into a single component to avoid displaying multiple \"Thinking...\" indicators.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Reasoning,\n  ReasoningContent,\n  ReasoningTrigger,\n} from \"@/components/ai-elements/reasoning\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { Spinner } from \"@/components/ui/spinner\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport type { UIMessage } from \"ai\";\n\nconst MessageParts = ({\n  message,\n  isLastMessage,\n  isStreaming,\n}: {\n  message: UIMessage;\n  isLastMessage: boolean;\n  isStreaming: boolean;\n}) => {\n  // Consolidate all reasoning parts into one block\n  const reasoningParts = message.parts.filter(\n    (part) => part.type === \"reasoning\"\n  );\n  const reasoningText = reasoningParts.map((part) => part.text).join(\"\\n\\n\");\n  const hasReasoning = reasoningParts.length > 0;\n\n  // Check if reasoning is still streaming (last part is reasoning on last message)\n  const lastPart = message.parts.at(-1);\n  const isReasoningStreaming =\n    isLastMessage && isStreaming && lastPart?.type === \"reasoning\";\n\n  return (\n    <>\n      {hasReasoning && (\n        <Reasoning className=\"w-full\" isStreaming={isReasoningStreaming}>\n          <ReasoningTrigger />\n          <ReasoningContent>{reasoningText}</ReasoningContent>\n        </Reasoning>\n      )}\n      {message.parts.map((part, i) => {\n        if (part.type === \"text\") {\n          return (\n            <MessageResponse key={`${message.id}-${i}`}>\n              {part.text}\n            </MessageResponse>\n          );\n        }\n        return null;\n      })}\n    </>\n  );\n};\n\nconst ReasoningDemo = () => {\n  const [input, setInput] = useState(\"\");\n\n  const { messages, sendMessage, status } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    sendMessage({ text: message.text });\n    setInput(\"\");\n  };\n\n  const isStreaming = status === \"streaming\";\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.map((message, index) => (\n              <Message from={message.role} key={message.id}>\n                <MessageContent>\n                  <MessageParts\n                    message={message}\n                    isLastMessage={index === messages.length - 1}\n                    isStreaming={isStreaming}\n                  />\n                </MessageContent>\n              </Message>\n            ))}\n            {status === \"submitted\" && <Spinner />}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Say something...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={isStreaming ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ReasoningDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/chat/route.ts\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { model, messages }: { messages: UIMessage[]; model: string } =\n    await req.json();\n\n  const result = streamText({\n    model: \"deepseek/deepseek-r1\",\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse({\n    sendReasoning: true,\n  });\n}\n```\n\n## Reasoning vs Chain of Thought\n\nUse the `Reasoning` component when your model outputs thinking content as a single block or continuous stream (Deepseek R1, Claude with extended thinking, etc.).\n\nIf your model outputs discrete, labeled steps (search queries, tool calls, distinct thought stages), consider using the [Chain of Thought](/components/chain-of-thought) component instead for a more structured visual representation.\n\n## Features\n\n- Automatically opens when streaming content and closes when finished\n- Manual toggle control for user interaction\n- Smooth animations and transitions powered by Radix UI\n- Visual streaming indicator with pulsing animation\n- Composable architecture with separate trigger and content components\n- Built with accessibility in mind including keyboard navigation\n- Responsive design that works across different screen sizes\n- Seamlessly integrates with both light and dark themes\n- Built on top of shadcn/ui Collapsible primitives\n- TypeScript support with proper type definitions\n\n## Props\n\n### `<Reasoning />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `isStreaming` | `boolean` | `false` | Whether the reasoning is currently streaming (auto-opens and closes the panel). |\n| `open` | `boolean` | - | Controlled open state. |\n| `defaultOpen` | `boolean` | `true` | Default open state when uncontrolled. |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback when open state changes. |\n| `duration` | `number` | - | Duration in seconds to display (can be controlled externally). |\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the underlying Collapsible component. |\n\n### `<ReasoningTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `getThinkingMessage` | `(isStreaming: boolean, duration?: number) => ReactNode` | - | Optional function to customize the thinking message. Receives isStreaming and duration parameters. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the underlying CollapsibleTrigger component. |\n\n### `<ReasoningContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | Required | The reasoning text to display (rendered via Streamdown). |\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the underlying CollapsibleContent component. |\n\n## Hooks\n\n### `useReasoning`\n\nAccess the reasoning context from child components.\n\n```tsx\nconst { isStreaming, isOpen, setIsOpen, duration } = useReasoning();\n```\n\nReturns:\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `isStreaming` | `boolean` | - | Whether reasoning is currently streaming. |\n| `isOpen` | `boolean` | - | Whether the reasoning panel is open. |\n| `setIsOpen` | `(open: boolean) => void` | - | Function to set the open state. |\n| `duration` | `number | undefined` | - | Duration in seconds (undefined while streaming). |\n","isInternal":false,"tokens":1757,"sizeBytes":7951},{"name":"sandbox.md","path":".agents/skills/ai-elements/references/sandbox.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/sandbox.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Sandbox\n\nA collapsible container for displaying AI-generated code and output in chat interfaces.\n\nThe `Sandbox` component provides a structured way to display AI-generated code alongside its execution output in chat conversations. It features a collapsible container with status indicators and tabbed navigation between code and output views. It's designed to be used with `CodeBlock` for displaying code and `StackTrace` for displaying errors.\n\nSee `scripts/sandbox.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add sandbox\n```\n\n## Features\n\n- Collapsible container with smooth animations\n- Status badges showing execution state (Pending, Running, Completed, Error)\n- Tabs for Code and Output views\n- Syntax-highlighted code display\n- Copy button for easy code sharing\n- Works with AI SDK tool state patterns\n\n## Usage with AI SDK\n\nThe Sandbox component integrates with the AI SDK's tool state to show code generation progress:\n\n```tsx title=\"components/code-sandbox.tsx\"\n\"use client\";\n\nimport type { ToolUIPart } from \"ai\";\nimport {\n  Sandbox,\n  SandboxContent,\n  SandboxHeader,\n  SandboxTabContent,\n  SandboxTabs,\n  SandboxTabsBar,\n  SandboxTabsList,\n  SandboxTabsTrigger,\n} from \"@/components/ai-elements/sandbox\";\nimport { CodeBlock } from \"@/components/ai-elements/code-block\";\n\ntype CodeSandboxProps = {\n  toolPart: ToolUIPart;\n};\n\nexport const CodeSandbox = ({ toolPart }: CodeSandboxProps) => {\n  const code = toolPart.input?.code ?? \"\";\n  const output = toolPart.output?.logs ?? \"\";\n\n  return (\n    <Sandbox>\n      <SandboxHeader\n        state={toolPart.state}\n        title={toolPart.input?.filename ?? \"code.tsx\"}\n      />\n      <SandboxContent>\n        <SandboxTabs defaultValue=\"code\">\n          <SandboxTabsBar>\n            <SandboxTabsList>\n              <SandboxTabsTrigger value=\"code\">Code</SandboxTabsTrigger>\n              <SandboxTabsTrigger value=\"output\">Output</SandboxTabsTrigger>\n            </SandboxTabsList>\n          </SandboxTabsBar>\n          <SandboxTabContent value=\"code\">\n            <CodeBlock code={code} language=\"tsx\" />\n          </SandboxTabContent>\n          <SandboxTabContent value=\"output\">\n            <CodeBlock code={output} language=\"log\" />\n          </SandboxTabContent>\n        </SandboxTabs>\n      </SandboxContent>\n    </Sandbox>\n  );\n};\n```\n\n## Props\n\n### `<Sandbox />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the underlying Collapsible component. |\n\n### `<SandboxHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | `undefined` | The title displayed in the header (e.g., filename). |\n| `state` | `ToolUIPart[` | Required | The current execution state, used to display the appropriate status badge. |\n| `className` | `string` | - | Additional CSS classes for the header. |\n\n### `<SandboxContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent. |\n\n### `<SandboxTabs />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Tabs>` | - | Any other props are spread to the underlying Tabs component. |\n\n### `<SandboxTabsBar />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n\n### `<SandboxTabsList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof TabsList>` | - | Any other props are spread to the underlying TabsList component. |\n\n### `<SandboxTabsTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof TabsTrigger>` | - | Any other props are spread to the underlying TabsTrigger component. |\n\n### `<SandboxTabContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof TabsContent>` | - | Any other props are spread to the underlying TabsContent component. |\n","isInternal":false,"tokens":1012,"sizeBytes":4356},{"name":"schema-display.md","path":".agents/skills/ai-elements/references/schema-display.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/schema-display.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Schema Display\n\nDisplay REST API endpoint documentation with parameters, request/response bodies.\n\nThe `SchemaDisplay` component visualizes REST API endpoints with HTTP methods, paths, parameters, and request/response schemas.\n\nSee `scripts/schema-display.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add schema-display\n```\n\n## Features\n\n- Color-coded HTTP methods\n- Path parameter highlighting\n- Collapsible parameters section\n- Request/response body schemas\n- Nested object property display\n- Required field indicators\n\n## Method Colors\n\n| Method   | Color  |\n| -------- | ------ |\n| `GET`    | Green  |\n| `POST`   | Blue   |\n| `PUT`    | Orange |\n| `PATCH`  | Yellow |\n| `DELETE` | Red    |\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/schema-display-basic.tsx` for this example.\n\n### With Parameters\n\nSee `scripts/schema-display-params.tsx` for this example.\n\n### With Request/Response Bodies\n\nSee `scripts/schema-display-body.tsx` for this example.\n\n### Nested Properties\n\nSee `scripts/schema-display-nested.tsx` for this example.\n\n## Props\n\n### `<SchemaDisplay />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `method` | `unknown` | - | HTTP method. |\n| `path` | `string` | - | API endpoint path. |\n| `description` | `string` | - | Endpoint description. |\n| `parameters` | `SchemaParameter[]` | - | URL/query parameters. |\n| `requestBody` | `SchemaProperty[]` | - | Request body properties. |\n| `responseBody` | `SchemaProperty[]` | - | Response body properties. |\n\n### `SchemaParameter`\n\n```tsx\ninterface SchemaParameter {\n  name: string;\n  type: string;\n  required?: boolean;\n  description?: string;\n  location?: \"path\" | \"query\" | \"header\";\n}\n```\n\n### `SchemaProperty`\n\n```tsx\ninterface SchemaProperty {\n  name: string;\n  type: string;\n  required?: boolean;\n  description?: string;\n  properties?: SchemaProperty[]; // For objects\n  items?: SchemaProperty; // For arrays\n}\n```\n\n### Subcomponents\n\n- `SchemaDisplayHeader` - Header container\n- `SchemaDisplayMethod` - Color-coded method badge\n- `SchemaDisplayPath` - Path with highlighted parameters\n- `SchemaDisplayDescription` - Description text\n- `SchemaDisplayContent` - Content container\n- `SchemaDisplayParameters` - Collapsible parameters section\n- `SchemaDisplayParameter` - Individual parameter\n- `SchemaDisplayRequest` - Collapsible request body\n- `SchemaDisplayResponse` - Collapsible response body\n- `SchemaDisplayProperty` - Schema property (recursive)\n- `SchemaDisplayExample` - Code example block\n","isInternal":false,"tokens":602,"sizeBytes":2534},{"name":"shimmer.md","path":".agents/skills/ai-elements/references/shimmer.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/shimmer.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Shimmer\n\nAn animated text shimmer component for creating eye-catching loading states and progressive reveal effects.\n\nThe `Shimmer` component provides an animated shimmer effect that sweeps across text, perfect for indicating loading states, progressive reveals, or drawing attention to dynamic content in AI applications.\n\nSee `scripts/shimmer.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add shimmer\n```\n\n## Features\n\n- Smooth animated shimmer effect using CSS gradients and Framer Motion\n- Customizable animation duration and spread\n- Polymorphic component - render as any HTML element via the `as` prop\n- Automatic spread calculation based on text length\n- Theme-aware styling using CSS custom properties\n- Infinite looping animation with linear easing\n- TypeScript support with proper type definitions\n- Memoized for optimal performance\n- Responsive and accessible design\n- Uses `text-transparent` with background-clip for crisp text rendering\n\n## Examples\n\n### Different Durations\n\nSee `scripts/shimmer-duration.tsx` for this example.\n\n### Custom Elements\n\nSee `scripts/shimmer-elements.tsx` for this example.\n\n## Props\n\n### `<Shimmer />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The text content to apply the shimmer effect to. |\n| `as` | `ElementType` | - | The HTML element or React component to render. |\n| `className` | `string` | - | Additional CSS classes to apply to the component. |\n| `duration` | `number` | `2` | The duration of the shimmer animation in seconds. |\n| `spread` | `number` | `2` | The spread multiplier for the shimmer gradient, multiplied by text length. |\n","isInternal":false,"tokens":367,"sizeBytes":1688},{"name":"snippet.md","path":".agents/skills/ai-elements/references/snippet.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/snippet.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Snippet\n\nLightweight inline code display for terminal commands and short code references.\n\nThe `Snippet` component provides a lightweight way to display terminal commands and short code snippets with copy functionality. Built on top of InputGroup, it's designed for brief code references in text.\n\nSee `scripts/snippet.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add snippet\n```\n\n## Features\n\n- Composable architecture with InputGroup\n- Optional prefix text (e.g., `$` for terminal commands)\n- Built-in copy button\n- Compact design for chat/markdown\n\n## Examples\n\n### Without Prefix\n\nSee `scripts/snippet-plain.tsx` for this example.\n\n## Props\n\n### `<Snippet />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `code` | `string` | Required | The code content to display. |\n| `children` | `React.ReactNode` | - | Child elements like SnippetAddon, SnippetInput, etc. |\n| `...props` | `React.ComponentProps<typeof InputGroup>` | - | Spread to the InputGroup component. |\n\n### `<SnippetAddon />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof InputGroupAddon>` | - | Spread to the InputGroupAddon component. |\n\n### `<SnippetText />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof InputGroupText>` | - | Spread to the InputGroupText component. |\n\n### `<SnippetInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `Omit<React.ComponentProps<typeof InputGroupInput>, ` | - | Spread to the InputGroupInput component. Value and readOnly are set automatically. |\n\n### `<SnippetCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback fired after a successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback fired if copying fails. |\n| `timeout` | `number` | `2000` | How long to show the copied state (ms). |\n| `children` | `React.ReactNode` | - | Custom button content. |\n| `...props` | `React.ComponentProps<typeof InputGroupButton>` | - | Spread to the InputGroupButton component. |\n","isInternal":false,"tokens":543,"sizeBytes":2244},{"name":"sources.md","path":".agents/skills/ai-elements/references/sources.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/sources.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Sources\n\nA component that allows a user to view the sources or citations used to generate a response.\n\nThe `Sources` component allows a user to view the sources or citations used to generate a response.\n\nSee `scripts/sources.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add sources\n```\n\n## Usage with AI SDK\n\nBuild a simple web search agent with Perplexity Sonar.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  Source,\n  Sources,\n  SourcesContent,\n  SourcesTrigger,\n} from \"@/components/ai-elements/sources\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport { useState } from \"react\";\nimport { DefaultChatTransport } from \"ai\";\n\nconst SourceDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { messages, sendMessage, status } = useChat({\n    transport: new DefaultChatTransport({\n      api: \"/api/sources\",\n    }),\n  });\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex-1 overflow-auto mb-4\">\n          <Conversation>\n            <ConversationContent>\n              {messages.map((message) => (\n                <div key={message.id}>\n                  {message.role === \"assistant\" && (\n                    <Sources>\n                      <SourcesTrigger\n                        count={\n                          message.parts.filter(\n                            (part) => part.type === \"source-url\"\n                          ).length\n                        }\n                      />\n                      {message.parts.map((part, i) => {\n                        switch (part.type) {\n                          case \"source-url\":\n                            return (\n                              <SourcesContent key={`${message.id}-${i}`}>\n                                <Source\n                                  key={`${message.id}-${i}`}\n                                  href={part.url}\n                                  title={part.url}\n                                />\n                              </SourcesContent>\n                            );\n                        }\n                      })}\n                    </Sources>\n                  )}\n                  <Message from={message.role} key={message.id}>\n                    <MessageContent>\n                      {message.parts.map((part, i) => {\n                        switch (part.type) {\n                          case \"text\":\n                            return (\n                              <MessageResponse key={`${message.id}-${i}`}>\n                                {part.text}\n                              </MessageResponse>\n                            );\n                          default:\n                            return null;\n                        }\n                      })}\n                    </MessageContent>\n                  </Message>\n                </div>\n              ))}\n            </ConversationContent>\n            <ConversationScrollButton />\n          </Conversation>\n        </div>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Ask a question and search the...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default SourceDemo;\n```\n\nAdd the following route to your backend:\n\n```tsx title=\"api/chat/route.ts\"\nimport { convertToModelMessages, streamText, UIMessage } from \"ai\";\nimport { perplexity } from \"@ai-sdk/perplexity\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"perplexity/sonar\",\n    system:\n      \"You are a helpful assistant. Keep your responses short (< 100 words) unless you are asked for more details. ALWAYS USE SEARCH.\",\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse({\n    sendSources: true,\n  });\n}\n```\n\n## Features\n\n- Collapsible component that allows a user to view the sources or citations used to generate a response\n- Customizable trigger and content components\n- Support for custom sources or citations\n- Responsive design with mobile-friendly controls\n- Clean, modern styling with customizable themes\n\n## Examples\n\n### Custom rendering\n\nSee `scripts/sources-custom.tsx` for this example.\n\n## Props\n\n### `<Sources />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<SourcesTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `count` | `number` | Required | The number of sources to display in the trigger. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<SourcesContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the content container. |\n\n### `<Source />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.AnchorHTMLAttributes<HTMLAnchorElement>` | - | Any other props are spread to the anchor element. |\n","isInternal":false,"tokens":1270,"sizeBytes":6394},{"name":"speech-input.md","path":".agents/skills/ai-elements/references/speech-input.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/speech-input.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Speech Input\n\nA button component that captures voice input and converts it to text, with cross-browser support.\n\nThe `SpeechInput` component provides an easy-to-use interface for capturing voice input in your application. It uses the Web Speech API for real-time transcription in supported browsers (Chrome, Edge), and falls back to MediaRecorder with an external transcription service for browsers that don't support Web Speech API (Firefox, Safari).\n\nSee `scripts/speech-input.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add speech-input\n```\n\n## Features\n\n- Built on Web Speech API (SpeechRecognition) with MediaRecorder fallback\n- Cross-browser support (Chrome, Edge, Firefox, Safari)\n- Continuous speech recognition with interim results\n- Visual feedback with pulse animation when listening\n- Loading state during transcription processing\n- Automatic browser compatibility detection\n- Final transcript extraction and callbacks\n- Error handling and automatic state management\n- Extends shadcn/ui Button component\n- Full TypeScript support\n\n## Props\n\n### `<SpeechInput />`\n\nThe component extends the shadcn/ui Button component, so all Button props are available.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onTranscriptionChange` | `(text: string) => void` | - | Callback fired when final transcription text is available. Only fires for completed phrases, not interim results. |\n| `onAudioRecorded` | `(audioBlob: Blob) => Promise<string>` | - | Callback for MediaRecorder fallback. Required for Firefox/Safari support. Receives recorded audio blob and should return transcribed text from an external service (e.g., OpenAI Whisper). |\n| `lang` | `string` | - | Language for speech recognition. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component, including variant, size, disabled, etc. |\n\n## Behavior\n\n### Speech Recognition Modes\n\nThe component automatically detects browser capabilities and uses the best available method:\n\n| Browser         | Mode           | Behavior                                               |\n| --------------- | -------------- | ------------------------------------------------------ |\n| Chrome, Edge    | Web Speech API | Real-time transcription, no server required            |\n| Firefox, Safari | MediaRecorder  | Records audio, sends to external transcription service |\n| Unsupported     | Disabled       | Button is disabled                                     |\n\n### Web Speech API Mode (Chrome, Edge)\n\nUses the Web Speech API with the following configuration:\n\n- **Continuous**: Set to `true` to keep recognition active until manually stopped\n- **Interim Results**: Set to `true` to receive partial results during speech\n- **Language**: Configurable via `lang` prop, defaults to `\"en-US\"`\n\n### MediaRecorder Mode (Firefox, Safari)\n\nWhen the Web Speech API is unavailable, the component falls back to recording audio:\n\n1. Records audio using `MediaRecorder` API\n2. On stop, creates an audio blob (`audio/webm`)\n3. Calls `onAudioRecorded` with the blob\n4. Waits for transcription result\n5. Passes result to `onTranscriptionChange`\n\n**Note**: The `onAudioRecorded` prop is required for this mode to work. Without it, the button will be disabled in Firefox/Safari.\n\n### Transcription Processing\n\nThe component only calls `onTranscriptionChange` with **final transcripts**. Interim results (Web Speech API) are ignored to prevent incomplete text from being processed.\n\n### Visual States\n\n- **Default State**: Standard button appearance with microphone icon\n- **Listening State**: Pulsing animation with accent colors to indicate active listening\n- **Processing State**: Loading spinner while waiting for transcription (MediaRecorder mode)\n- **Disabled State**: Button is disabled when no API is available or required props are missing\n\n### Lifecycle\n\n1. **Mount**: Detects available APIs and initializes appropriate mode\n2. **Click**: Toggles between listening/recording and stopped states\n3. **Stop (MediaRecorder)**: Processes audio and waits for transcription\n4. **Unmount**: Stops recognition/recording and releases microphone\n\n## Browser Support\n\nThe component provides cross-browser support through a two-tier system:\n\n| Browser | API Used       | Requirements           |\n| ------- | -------------- | ---------------------- |\n| Chrome  | Web Speech API | None                   |\n| Edge    | Web Speech API | None                   |\n| Firefox | MediaRecorder  | `onAudioRecorded` prop |\n| Safari  | MediaRecorder  | `onAudioRecorded` prop |\n\nFor full cross-browser support, provide the `onAudioRecorded` callback that sends audio to a transcription service like OpenAI Whisper, Google Cloud Speech-to-Text, or AssemblyAI.\n\n## Accessibility\n\n- Uses semantic button element via shadcn/ui Button\n- Visual feedback for listening state\n- Keyboard accessible (can be triggered with Space/Enter)\n- Screen reader friendly with proper button semantics\n\n## Usage with MediaRecorder Fallback\n\nTo support Firefox and Safari, provide an `onAudioRecorded` callback that sends audio to a transcription service:\n\n```tsx\nconst handleAudioRecorded = async (audioBlob: Blob): Promise<string> => {\n  const formData = new FormData();\n  formData.append(\"file\", audioBlob, \"audio.webm\");\n  formData.append(\"model\", \"whisper-1\");\n\n  const response = await fetch(\n    \"https://api.openai.com/v1/audio/transcriptions\",\n    {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,\n      },\n      body: formData,\n    }\n  );\n\n  const data = await response.json();\n  return data.text;\n};\n\n<SpeechInput\n  onTranscriptionChange={(text) => console.log(text)}\n  onAudioRecorded={handleAudioRecorded}\n/>;\n```\n\n## Notes\n\n- Requires a secure context (HTTPS or localhost)\n- Browser may prompt user for microphone permission\n- Only final transcripts trigger the `onTranscriptionChange` callback\n- Language is configurable via the `lang` prop\n- Continuous recognition continues until button is clicked again\n- Errors are logged to console and automatically stop recognition/recording\n- MediaRecorder fallback requires the `onAudioRecorded` prop to be provided\n- Audio is recorded in `audio/webm` format for the MediaRecorder fallback\n\n## TypeScript\n\nThe component includes full TypeScript definitions for the Web Speech API:\n\n- `SpeechRecognition`\n- `SpeechRecognitionEvent`\n- `SpeechRecognitionResult`\n- `SpeechRecognitionAlternative`\n- `SpeechRecognitionErrorEvent`\n\nThese types are properly declared for both standard and webkit-prefixed implementations.\n","isInternal":false,"tokens":1370,"sizeBytes":6636},{"name":"stack-trace.md","path":".agents/skills/ai-elements/references/stack-trace.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/stack-trace.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Stack Trace\n\nDisplays formatted JavaScript/Node.js error stack traces with syntax highlighting and collapsible frames.\n\nThe `StackTrace` component displays formatted JavaScript/Node.js error stack traces with clickable file paths, internal frame dimming, and collapsible content.\n\nSee `scripts/stack-trace.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add stack-trace\n```\n\n## Usage with AI SDK\n\nBuild an error display tool that shows stack traces from AI-generated code using the [`useChat`](https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-chat) hook.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  StackTrace,\n  StackTraceHeader,\n  StackTraceError,\n  StackTraceErrorType,\n  StackTraceErrorMessage,\n  StackTraceActions,\n  StackTraceCopyButton,\n  StackTraceExpandButton,\n  StackTraceContent,\n  StackTraceFrames,\n} from \"@/components/ai-elements/stack-trace\";\n\nexport default function Page() {\n  const { messages } = useChat({\n    api: \"/api/run-code\",\n  });\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6\">\n      {messages.map((message) => {\n        const toolInvocations = message.parts?.filter(\n          (part) => part.type === \"tool-invocation\"\n        );\n\n        return toolInvocations?.map((tool) => {\n          if (tool.toolName === \"runCode\" && tool.result?.error) {\n            return (\n              <StackTrace\n                key={tool.toolCallId}\n                trace={tool.result.error}\n                defaultOpen\n              >\n                <StackTraceHeader>\n                  <StackTraceError>\n                    <StackTraceErrorType />\n                    <StackTraceErrorMessage />\n                  </StackTraceError>\n                  <StackTraceActions>\n                    <StackTraceCopyButton />\n                    <StackTraceExpandButton />\n                  </StackTraceActions>\n                </StackTraceHeader>\n                <StackTraceContent>\n                  <StackTraceFrames />\n                </StackTraceContent>\n              </StackTrace>\n            );\n          }\n          return null;\n        });\n      })}\n    </div>\n  );\n}\n```\n\nAdd the following route to your backend:\n\n```tsx title=\"api/run-code/route.ts\"\nimport { streamText, tool } from \"ai\";\nimport { z } from \"zod\";\n\nexport async function POST(req: Request) {\n  const { messages } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages,\n    tools: {\n      runCode: tool({\n        description: \"Execute JavaScript code and return any errors\",\n        parameters: z.object({\n          code: z.string(),\n        }),\n        execute: async ({ code }) => {\n          try {\n            // Execute code in sandbox\n            eval(code);\n            return { success: true };\n          } catch (error) {\n            return { error: (error as Error).stack };\n          }\n        },\n      }),\n    },\n  });\n\n  return result.toDataStreamResponse();\n}\n```\n\n## Features\n\n- Parses standard JavaScript/Node.js stack trace format\n- Highlights error type in red\n- Dims internal frames (node_modules, node: paths)\n- Collapsible content with smooth animation\n- Copy full stack trace to clipboard\n- Clickable file paths with line/column numbers\n\n## Examples\n\n### Collapsed by Default\n\nSee `scripts/stack-trace-collapsed.tsx` for this example.\n\n### Hide Internal Frames\n\nSee `scripts/stack-trace-no-internal.tsx` for this example.\n\n## Props\n\n### `<StackTrace />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `trace` | `string` | - | The raw stack trace string to parse and display. |\n| `open` | `boolean` | - | Controlled open state. |\n| `defaultOpen` | `boolean` | `false` | Whether the content is expanded by default. |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback when open state changes. |\n| `onFilePathClick` | `(path: string, line?: number, column?: number) => void` | - | Callback when a file path is clicked. Receives the file path, line number, and column number. |\n| `children` | `React.ReactNode` | - | Child elements (StackTraceHeader, StackTraceContent, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<StackTraceHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Header content (typically StackTraceError and StackTraceActions). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger. |\n\n### `<StackTraceError />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Error content (typically StackTraceErrorType and StackTraceErrorMessage). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n\n### `<StackTraceErrorType />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom content. Defaults to the parsed error type (e.g.,  |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<StackTraceErrorMessage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom content. Defaults to the parsed error message. |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<StackTraceActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Action buttons (typically StackTraceCopyButton and StackTraceExpandButton). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n\n### `<StackTraceCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback fired after a successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback fired if copying fails. |\n| `timeout` | `number` | `2000` | How long to show the copied state (ms). |\n| `children` | `React.ReactNode` | - | Custom content for the button. Defaults to copy/check icons. |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<StackTraceExpandButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n\n### `<StackTraceContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `maxHeight` | `number` | `400` | Maximum height of the content area. Enables scrolling when content exceeds this height. |\n| `children` | `React.ReactNode` | - | Content to display (typically StackTraceFrames). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent. |\n\n### `<StackTraceFrames />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `showInternalFrames` | `boolean` | `true` | Whether to show internal frames (node_modules, node: paths). |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the container div. |\n","isInternal":false,"tokens":1895,"sizeBytes":8108},{"name":"suggestion.md","path":".agents/skills/ai-elements/references/suggestion.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/suggestion.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Suggestion\n\nA suggestion component that displays a horizontal row of clickable suggestions for user interaction.\n\nThe `Suggestion` component displays a horizontal row of clickable suggestions for user interaction.\n\nSee `scripts/suggestion.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add suggestion\n```\n\n## Usage with AI SDK\n\nBuild a simple input with suggestions users can click to send a message to the LLM.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { Suggestion, Suggestions } from \"@/components/ai-elements/suggestion\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\n\nconst suggestions = [\n  \"Can you explain how to play tennis?\",\n  \"What is the weather in Tokyo?\",\n  \"How do I make a really good fish taco?\",\n];\n\nconst SuggestionDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { sendMessage, status } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  const handleSuggestionClick = (suggestion: string) => {\n    sendMessage({ text: suggestion });\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex flex-col gap-4\">\n          <Suggestions>\n            {suggestions.map((suggestion) => (\n              <Suggestion\n                key={suggestion}\n                onClick={handleSuggestionClick}\n                suggestion={suggestion}\n              />\n            ))}\n          </Suggestions>\n          <PromptInput\n            onSubmit={handleSubmit}\n            className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n          >\n            <PromptInputTextarea\n              value={input}\n              placeholder=\"Say something...\"\n              onChange={(e) => setInput(e.currentTarget.value)}\n              className=\"pr-12\"\n            />\n            <PromptInputSubmit\n              status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n              disabled={!input.trim()}\n              className=\"absolute bottom-1 right-1\"\n            />\n          </PromptInput>\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default SuggestionDemo;\n```\n\n## Features\n\n- Horizontal row of clickable suggestion buttons\n- Customizable styling with variant and size options\n- Flexible layout that wraps suggestions on smaller screens\n- onClick callback that emits the selected suggestion string\n- Support for both individual suggestions and suggestion lists\n- Clean, modern styling with hover effects\n- Responsive design with mobile-friendly touch targets\n- TypeScript support with proper type definitions\n\n## Examples\n\n### Usage with AI Input\n\nSee `scripts/suggestion-input.tsx` for this example.\n\n## Props\n\n### `<Suggestions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof ScrollArea>` | - | Any other props are spread to the underlying ScrollArea component. |\n\n### `<Suggestion />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `suggestion` | `string` | Required | The suggestion string to display and emit on click. |\n| `onClick` | `(suggestion: string) => void` | - | Callback fired when the suggestion is clicked. |\n| `...props` | `Omit<React.ComponentProps<typeof Button>, ` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n","isInternal":false,"tokens":804,"sizeBytes":3718},{"name":"task.md","path":".agents/skills/ai-elements/references/task.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/task.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Task\n\nA collapsible task list component for displaying AI workflow progress, with status indicators and optional descriptions.\n\nThe `Task` component provides a structured way to display task lists or workflow progress with collapsible details, status indicators, and progress tracking. It consists of a main `Task` container with `TaskTrigger` for the clickable header and `TaskContent` for the collapsible content area.\n\nSee `scripts/task.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add task\n```\n\n## Usage with AI SDK\n\nBuild a mock async programming agent using [`experimental_generateObject`](/docs/reference/ai-sdk-ui/use-object).\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { experimental_useObject as useObject } from \"@ai-sdk/react\";\nimport {\n  Task,\n  TaskItem,\n  TaskItemFile,\n  TaskTrigger,\n  TaskContent,\n} from \"@/components/ai-elements/task\";\nimport { Button } from \"@/components/ui/button\";\nimport { tasksSchema } from \"@/app/api/task/route\";\nimport {\n  SiReact,\n  SiTypescript,\n  SiJavascript,\n  SiCss,\n  SiHtml5,\n  SiJson,\n  SiMarkdown,\n} from \"@icons-pack/react-simple-icons\";\n\nconst iconMap = {\n  react: { component: SiReact, color: \"#149ECA\" },\n  typescript: { component: SiTypescript, color: \"#3178C6\" },\n  javascript: { component: SiJavascript, color: \"#F7DF1E\" },\n  css: { component: SiCss, color: \"#1572B6\" },\n  html: { component: SiHtml5, color: \"#E34F26\" },\n  json: { component: SiJson, color: \"#000000\" },\n  markdown: { component: SiMarkdown, color: \"#000000\" },\n};\n\nconst TaskDemo = () => {\n  const { object, submit, isLoading } = useObject({\n    api: \"/api/agent\",\n    schema: tasksSchema,\n  });\n\n  const handleSubmit = (taskType: string) => {\n    submit({ prompt: taskType });\n  };\n\n  const renderTaskItem = (item: any, index: number) => {\n    if (item?.type === \"file\" && item.file) {\n      const iconInfo = iconMap[item.file.icon as keyof typeof iconMap];\n      if (iconInfo) {\n        const IconComponent = iconInfo.component;\n        return (\n          <span className=\"inline-flex items-center gap-1\" key={index}>\n            {item.text}\n            <TaskItemFile>\n              <IconComponent\n                color={item.file.color || iconInfo.color}\n                className=\"size-4\"\n              />\n              <span>{item.file.name}</span>\n            </TaskItemFile>\n          </span>\n        );\n      }\n    }\n    return item?.text || \"\";\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex gap-2 mb-6 flex-wrap\">\n          <Button\n            onClick={() => handleSubmit(\"React component development\")}\n            disabled={isLoading}\n            variant=\"outline\"\n          >\n            React Development\n          </Button>\n        </div>\n\n        <div className=\"flex-1 overflow-auto space-y-4\">\n          {isLoading && !object && (\n            <div className=\"text-muted-foreground\">Generating tasks...</div>\n          )}\n\n          {object?.tasks?.map((task: any, taskIndex: number) => (\n            <Task key={taskIndex} defaultOpen={taskIndex === 0}>\n              <TaskTrigger title={task.title || \"Loading...\"} />\n              <TaskContent>\n                {task.items?.map((item: any, itemIndex: number) => (\n                  <TaskItem key={itemIndex}>\n                    {renderTaskItem(item, itemIndex)}\n                  </TaskItem>\n                ))}\n              </TaskContent>\n            </Task>\n          ))}\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default TaskDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/agent.ts\"\nimport { streamObject } from \"ai\";\nimport { z } from \"zod\";\n\nexport const taskItemSchema = z.object({\n  type: z.enum([\"text\", \"file\"]),\n  text: z.string(),\n  file: z\n    .object({\n      name: z.string(),\n      icon: z.string(),\n      color: z.string().optional(),\n    })\n    .optional(),\n});\n\nexport const taskSchema = z.object({\n  title: z.string(),\n  items: z.array(taskItemSchema),\n  status: z.enum([\"pending\", \"in_progress\", \"completed\"]),\n});\n\nexport const tasksSchema = z.object({\n  tasks: z.array(taskSchema),\n});\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { prompt } = await req.json();\n\n  const result = streamObject({\n    model: \"openai/gpt-4o\",\n    schema: tasksSchema,\n    prompt: `You are an AI assistant that generates realistic development task workflows. Generate a set of tasks that would occur during ${prompt}.\n\n    Each task should have:\n    - A descriptive title\n    - Multiple task items showing the progression\n    - Some items should be plain text, others should reference files\n    - Use realistic file names and appropriate file types\n    - Status should progress from pending to in_progress to completed\n\n    For file items, use these icon types: 'react', 'typescript', 'javascript', 'css', 'html', 'json', 'markdown'\n\n    Generate 3-4 tasks total, with 4-6 items each.`,\n  });\n\n  return result.toTextStreamResponse();\n}\n```\n\n## Features\n\n- Visual icons for pending, in-progress, completed, and error states\n- Expandable content for task descriptions and additional information\n- Built-in progress counter showing completed vs total tasks\n- Optional progressive reveal of tasks with customizable timing\n- Support for custom content within task items\n- Full type safety with proper TypeScript definitions\n- Keyboard navigation and screen reader support\n\n## Props\n\n### `<Task />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultOpen` | `boolean` | `true` | Whether the task is open by default. |\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the root Collapsible component. |\n\n### `<TaskTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | Required | The title of the task that will be displayed in the trigger. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<TaskContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent component. |\n\n### `<TaskItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<TaskItemFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n","isInternal":false,"tokens":1632,"sizeBytes":6900},{"name":"terminal.md","path":".agents/skills/ai-elements/references/terminal.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/terminal.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Terminal\n\nDisplay streaming console output with full ANSI color support.\n\nThe `Terminal` component displays console output with ANSI color support, streaming indicators, and auto-scroll functionality.\n\nSee `scripts/terminal.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add terminal\n```\n\n## Features\n\n- Full ANSI color support (256 colors, bold, italic, underline)\n- Streaming mode with cursor animation\n- Auto-scroll to latest output\n- Copy output to clipboard\n- Clear button support\n- Dark terminal theme\n\n## ANSI Support\n\nThe Terminal uses `ansi-to-react` to parse ANSI escape codes:\n\n```bash\n\\x1b[32m✓\\x1b[0m Success    # Green checkmark\n\\x1b[31m✗\\x1b[0m Error      # Red X\n\\x1b[33mwarn\\x1b[0m Warning   # Yellow text\n\\x1b[1mBold\\x1b[0m           # Bold text\n```\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/terminal-basic.tsx` for this example.\n\n### Streaming Mode\n\nSee `scripts/terminal-streaming.tsx` for this example.\n\n### With Clear Button\n\nSee `scripts/terminal-clear.tsx` for this example.\n\n## Props\n\n### `<Terminal />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `output` | `string` | - | Terminal output text (supports ANSI codes). |\n| `isStreaming` | `boolean` | `false` | Show streaming indicator. |\n| `autoScroll` | `boolean` | `true` | Auto-scroll to bottom on new output. |\n| `onClear` | `() => void` | - | Callback to clear output (enables clear button). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<TerminalCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback after successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback if copying fails. |\n| `timeout` | `number` | `2000` | Duration to show copied state (ms). |\n\n### `<TerminalHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TerminalTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TerminalStatus />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TerminalActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TerminalClearButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component. |\n\n### `<TerminalContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n","isInternal":false,"tokens":797,"sizeBytes":3132},{"name":"test-results.md","path":".agents/skills/ai-elements/references/test-results.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/test-results.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Test Results\n\nDisplay test suite results with pass/fail/skip status and error details.\n\nThe `TestResults` component displays test suite results including summary statistics, progress, individual tests, and error details.\n\nSee `scripts/test-results.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add test-results\n```\n\n## Features\n\n- Summary statistics (passed/failed/skipped)\n- Progress bar visualization\n- Collapsible test suites\n- Individual test status and duration\n- Error messages with stack traces\n- Color-coded status indicators\n\n## Status Colors\n\n| Status    | Color           | Use Case         |\n| --------- | --------------- | ---------------- |\n| `passed`  | Green           | Test succeeded   |\n| `failed`  | Red             | Test failed      |\n| `skipped` | Yellow          | Test skipped     |\n| `running` | Blue (animated) | Test in progress |\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/test-results-basic.tsx` for this example.\n\n### With Test Suites\n\nSee `scripts/test-results-suites.tsx` for this example.\n\n### With Error Details\n\nSee `scripts/test-results-errors.tsx` for this example.\n\n## Props\n\n### `<TestResults />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `summary` | `unknown` | - | Test results summary. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<TestSuite />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | - | Suite name. |\n| `status` | `unknown` | - | Overall suite status. |\n| `defaultOpen` | `boolean` | - | Initially expanded. |\n\n### `<Test />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | - | Test name. |\n| `status` | `unknown` | - | Test status. |\n| `duration` | `number` | - | Test duration in ms. |\n\n### `<TestResultsHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestResultsSummary />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestResultsDuration />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<TestResultsProgress />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestResultsContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestSuiteName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<TestSuiteStats />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `passed` | `number` | `0` | Number of passed tests. |\n| `failed` | `number` | `0` | Number of failed tests. |\n| `skipped` | `number` | `0` | Number of skipped tests. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestSuiteContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent component. |\n\n### `<TestStatus />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<TestName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<TestDuration />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the span element. |\n\n### `<TestError />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the div element. |\n\n### `<TestErrorMessage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Any other props are spread to the p element. |\n\n### `<TestErrorStack />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLPreElement>` | - | Any other props are spread to the pre element. |\n","isInternal":false,"tokens":1246,"sizeBytes":5111},{"name":"tool.md","path":".agents/skills/ai-elements/references/tool.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/tool.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Tool\n\nA collapsible component for displaying tool invocation details in AI chatbot interfaces.\n\nThe `Tool` component displays a collapsible interface for showing/hiding tool details. It is designed to take the `ToolUIPart` type from the AI SDK and display it in a collapsible interface.\n\nSee `scripts/tool.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add tool\n```\n\n## Usage in AI SDK\n\nBuild a simple stateful weather app that renders the last message in a tool using [`useChat`](/docs/reference/ai-sdk-ui/use-chat).\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport { DefaultChatTransport, type ToolUIPart } from \"ai\";\nimport { Button } from \"@/components/ui/button\";\nimport { MessageResponse } from \"@/components/ai-elements/message\";\nimport {\n  Tool,\n  ToolContent,\n  ToolHeader,\n  ToolInput,\n  ToolOutput,\n} from \"@/components/ai-elements/tool\";\n\ntype WeatherToolInput = {\n  location: string;\n  units: \"celsius\" | \"fahrenheit\";\n};\n\ntype WeatherToolOutput = {\n  location: string;\n  temperature: string;\n  conditions: string;\n  humidity: string;\n  windSpeed: string;\n  lastUpdated: string;\n};\n\ntype WeatherToolUIPart = ToolUIPart<{\n  fetch_weather_data: {\n    input: WeatherToolInput;\n    output: WeatherToolOutput;\n  };\n}>;\n\nconst Example = () => {\n  const { messages, sendMessage, status } = useChat({\n    transport: new DefaultChatTransport({\n      api: \"/api/weather\",\n    }),\n  });\n\n  const handleWeatherClick = () => {\n    sendMessage({ text: \"Get weather data for San Francisco in fahrenheit\" });\n  };\n\n  const latestMessage = messages[messages.length - 1];\n  const weatherTool = latestMessage?.parts?.find(\n    (part) => part.type === \"tool-fetch_weather_data\"\n  ) as WeatherToolUIPart | undefined;\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"space-y-4\">\n          <Button onClick={handleWeatherClick} disabled={status !== \"ready\"}>\n            Get Weather for San Francisco\n          </Button>\n\n          {weatherTool && (\n            <Tool defaultOpen={true}>\n              <ToolHeader\n                type=\"tool-fetch_weather_data\"\n                state={weatherTool.state}\n              />\n              <ToolContent>\n                <ToolInput input={weatherTool.input} />\n                <ToolOutput\n                  output={\n                    <MessageResponse>\n                      {formatWeatherResult(weatherTool.output)}\n                    </MessageResponse>\n                  }\n                  errorText={weatherTool.errorText}\n                />\n              </ToolContent>\n            </Tool>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n};\n\nfunction formatWeatherResult(result: WeatherToolOutput): string {\n  return `**Weather for ${result.location}**\n\n**Temperature:** ${result.temperature}  \n**Conditions:** ${result.conditions}  \n**Humidity:** ${result.humidity}  \n**Wind Speed:** ${result.windSpeed}  \n\n*Last updated: ${result.lastUpdated}*`;\n}\n\nexport default Example;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/weather/route.tsx\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\nimport { z } from \"zod\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages: await convertToModelMessages(messages),\n    tools: {\n      fetch_weather_data: {\n        description: \"Fetch weather information for a specific location\",\n        parameters: z.object({\n          location: z\n            .string()\n            .describe(\"The city or location to get weather for\"),\n          units: z\n            .enum([\"celsius\", \"fahrenheit\"])\n            .default(\"celsius\")\n            .describe(\"Temperature units\"),\n        }),\n        inputSchema: z.object({\n          location: z.string(),\n          units: z.enum([\"celsius\", \"fahrenheit\"]).default(\"celsius\"),\n        }),\n        execute: async ({ location, units }) => {\n          await new Promise((resolve) => setTimeout(resolve, 1500));\n\n          const temp =\n            units === \"celsius\"\n              ? Math.floor(Math.random() * 35) + 5\n              : Math.floor(Math.random() * 63) + 41;\n\n          return {\n            location,\n            temperature: `${temp}°${units === \"celsius\" ? \"C\" : \"F\"}`,\n            conditions: \"Sunny\",\n            humidity: `12%`,\n            windSpeed: `35 ${units === \"celsius\" ? \"km/h\" : \"mph\"}`,\n            lastUpdated: new Date().toLocaleString(),\n          };\n        },\n      },\n    },\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Collapsible interface for showing/hiding tool details\n- Visual status indicators with icons and badges\n- Support for multiple tool execution states (pending, running, completed, error)\n- Formatted parameter display with JSON syntax highlighting\n- Result and error handling with appropriate styling\n- Composable structure for flexible layouts\n- Accessible keyboard navigation and screen reader support\n- Consistent styling that matches your design system\n- Auto-opens completed tools by default for better UX\n\n## Examples\n\n### Input Streaming (Pending)\n\nShows a tool in its initial state while parameters are being processed.\n\nSee `scripts/tool-input-streaming.tsx` for this example.\n\n### Input Available (Running)\n\nShows a tool that's actively executing with its parameters.\n\nSee `scripts/tool-input-available.tsx` for this example.\n\n### Output Available (Completed)\n\nShows a completed tool with successful results. Opens by default to show the results. In this instance, the output is a JSON object, so we can use the `CodeBlock` component to display it.\n\nSee `scripts/tool-output-available.tsx` for this example.\n\n### Output Error\n\nShows a tool that encountered an error during execution. Opens by default to display the error.\n\nSee `scripts/tool-output-error.tsx` for this example.\n\n## Props\n\n### `<Tool />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Any other props are spread to the root Collapsible component. |\n\n### `<ToolHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | - | Custom title to display instead of the derived tool name. |\n| `type` | `ToolUIPart[` | Required | The type/name of the tool. |\n| `state` | `ToolUIPart[` | Required | The current state of the tool (input-streaming, input-available, output-available, or output-error). |\n| `toolName` | `string` | - | Required when type is  |\n| `className` | `string` | - | Additional CSS classes to apply to the header. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger. |\n\n### `<ToolContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any other props are spread to the CollapsibleContent. |\n\n### `<ToolInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `input` | `ToolUIPart[` | - | The input parameters passed to the tool, displayed as formatted JSON. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<ToolOutput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `output` | `React.ReactNode` | - | The output/result of the tool execution. |\n| `errorText` | `ToolUIPart[` | - | An error message if the tool execution failed. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n## Type Exports\n\n### `ToolPart`\n\nUnion type representing both static and dynamic tool UI parts.\n\n```tsx\ntype ToolPart = ToolUIPart | DynamicToolUIPart;\n```\n\n## Utilities\n\n### `getStatusBadge`\n\nReturns a Badge component with icon and label based on tool state.\n\n```tsx\nimport { getStatusBadge } from \"@/components/ai-elements/tool\";\n\n// Returns a Badge with appropriate icon and label\nconst badge = getStatusBadge(\"output-available\");\n```\n\nSupported states:\n\n- `input-streaming` - \"Pending\"\n- `input-available` - \"Running\"\n- `approval-requested` - \"Awaiting Approval\"\n- `approval-responded` - \"Responded\"\n- `output-available` - \"Completed\"\n- `output-error` - \"Error\"\n- `output-denied` - \"Denied\"\n","isInternal":false,"tokens":1993,"sizeBytes":8669},{"name":"toolbar.md","path":".agents/skills/ai-elements/references/toolbar.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/toolbar.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Toolbar\n\nA styled toolbar component for React Flow nodes with flexible positioning and custom actions.\n\nThe `Toolbar` component provides a positioned toolbar that attaches to nodes in React Flow canvases. It features modern card styling with backdrop blur and flexbox layout for action buttons and controls.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add toolbar\n```\n\n## Features\n\n- Attaches to any React Flow node\n- Bottom positioning by default\n- Rounded card design with border\n- Theme-aware background styling\n- Flexbox layout with gap spacing\n- Full TypeScript support\n- Compatible with all React Flow NodeToolbar features\n\n## Props\n\n### `<Toolbar />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the toolbar. |\n| `...props` | `ComponentProps<typeof NodeToolbar>` | - | Any other props from @xyflow/react NodeToolbar component (position, offset, isVisible, etc.). |\n","isInternal":false,"tokens":210,"sizeBytes":983},{"name":"transcription.md","path":".agents/skills/ai-elements/references/transcription.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/transcription.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Transcription\n\nA composable component for displaying interactive, synchronized transcripts from AI SDK transcribe() results with click-to-seek functionality.\n\nThe `Transcription` component provides a flexible render props interface for displaying audio transcripts with synchronized playback. It automatically highlights the current segment based on playback time and supports click-to-seek functionality for interactive navigation.\n\nSee `scripts/transcription.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add transcription\n```\n\n## Features\n\n- Render props pattern for maximum flexibility\n- Automatic segment highlighting based on current time\n- Click-to-seek functionality for interactive navigation\n- Controlled and uncontrolled component patterns\n- Automatic filtering of empty segments\n- Visual state indicators (active, past, future)\n- Built on Radix UI's `useControllableState` for flexible state management\n- Full TypeScript support with AI SDK transcription types\n\n## Props\n\n### `<Transcription />`\n\nRoot component that provides context and manages transcript state. Uses render props pattern for rendering segments.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `segments` | `TranscriptionSegment[]` | - | Array of transcription segments from AI SDK transcribe() function. |\n| `currentTime` | `number` | `0` | Current playback time in seconds (controlled). |\n| `onSeek` | `(time: number) => void` | - | Callback fired when a segment is clicked or when currentTime changes. |\n| `children` | `(segment: TranscriptionSegment, index: number) => ReactNode` | - | Render function that receives each segment and its index. |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the root div element. |\n\n### `<TranscriptionSegment />`\n\nIndividual segment button with automatic state styling and click-to-seek functionality.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `segment` | `TranscriptionSegment` | - | The transcription segment data. |\n| `index` | `number` | - | The segment index. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the button element. |\n\n## Behavior\n\n### Render Props Pattern\n\nThe component uses a render props pattern where the `children` prop is a function that receives each segment and its index. This provides maximum flexibility for custom rendering while still benefiting from automatic state management and context.\n\n### Segment Highlighting\n\nSegments are automatically styled based on their relationship to the current playback time:\n\n- **Active** (`isActive`): When `currentTime` is within the segment's time range. Styled with primary color.\n- **Past** (`isPast`): When `currentTime` is after the segment's end time. Styled with muted foreground.\n- **Future**: When `currentTime` is before the segment's start time. Styled with dimmed muted foreground.\n\n### Click-to-Seek\n\nWhen `onSeek` is provided, segments become interactive buttons. Clicking a segment calls `onSeek` with the segment's start time, allowing your audio/video player to seek to that position.\n\n### Empty Segment Filtering\n\nThe component automatically filters out segments with empty or whitespace-only text to avoid rendering unnecessary elements.\n\n### State Management\n\nUses Radix UI's `useControllableState` hook to support both controlled and uncontrolled patterns. When `currentTime` is provided, the component operates in controlled mode. Otherwise, it maintains its own internal state.\n\n## Data Format\n\nThe component expects segments from the AI SDK `transcribe()` function:\n\n```ts\ntype TranscriptionSegment = {\n  text: string;\n  startSecond: number;\n  endSecond: number;\n};\n```\n\n## Styling\n\nThe component uses data attributes for custom styling:\n\n- `data-slot=\"transcription\"`: Root container\n- `data-slot=\"transcription-segment\"`: Individual segment button\n- `data-active`: Present on the currently playing segment\n- `data-index`: The segment's index in the array\n\nDefault segment appearance:\n\n- Active segment: `text-primary` (primary brand color)\n- Past segments: `text-muted-foreground`\n- Future segments: `text-muted-foreground/60` (dimmed)\n- Interactive segments: `cursor-pointer hover:text-foreground`\n- Non-interactive segments: `cursor-default`\n\n## Accessibility\n\n- Uses semantic `<button>` elements for interactive segments\n- Full keyboard navigation support\n- Proper button semantics for screen readers\n- `data-active` attribute for assistive technology\n- Hover and focus states for keyboard users\n\n## Notes\n\n- Empty or whitespace-only segments are automatically filtered out\n- The component uses `flex-wrap` for responsive text flow\n- Segments maintain inline layout with `gap-1` spacing\n- `text-sm` and `leading-relaxed` provide comfortable reading\n- Click events on segments still fire the `onClick` handler if provided\n- The `onSeek` callback is called both when segments are clicked and when controlled `currentTime` changes\n","isInternal":false,"tokens":1047,"sizeBytes":5011},{"name":"voice-selector.md","path":".agents/skills/ai-elements/references/voice-selector.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/voice-selector.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Voice Selector\n\nA composable dialog component for selecting AI voices with metadata display and search functionality.\n\nThe `VoiceSelector` component provides a flexible and composable interface for selecting AI voices. Built on shadcn/ui's Dialog and Command components, it features a searchable voice list with support for metadata display (gender, accent, age), grouping, and customizable layouts. The component includes a context provider for accessing voice selection state from any nested component.\n\nSee `scripts/voice-selector.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add voice-selector\n```\n\n## Features\n\n- Fully composable architecture with granular control components\n- Built on shadcn/ui Dialog and Command components\n- React Context API for accessing state in nested components\n- Searchable voice list with real-time filtering\n- Support for voice metadata with icons and emojis (gender icons, accent flags, age)\n- Voice preview button with play/pause/loading states\n- Voice grouping with separators and bullet dividers\n- Keyboard navigation support\n- Controlled and uncontrolled component patterns\n- Full TypeScript support with proper types for all components\n\n## Props\n\n### `<VoiceSelector />`\n\nRoot Dialog component that provides context for all child components. Manages both voice selection and dialog open states.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The selected voice ID (controlled). |\n| `defaultValue` | `string` | - | The default selected voice ID (uncontrolled). |\n| `onValueChange` | `(value: string | undefined) => void` | - | Callback fired when the selected voice changes. |\n| `defaultOpen` | `boolean` | `false` | The default open state (uncontrolled). |\n| `open` | `boolean` | - | The open state (controlled). |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback fired when the open state changes. |\n| `modal` | `boolean` | `true` | Whether the dialog is modal (blocks interaction with the rest of the page). |\n| `...props` | `React.ComponentProps<typeof Dialog>` | - | Any other props are spread to the Dialog component. |\n\n### `<VoiceSelectorTrigger />`\n\nButton or element that opens the voice selector dialog.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior. |\n| `...props` | `React.ComponentProps<typeof DialogTrigger>` | - | Any other props are spread to the DialogTrigger component. |\n\n### `<VoiceSelectorContent />`\n\nContainer for the Command component and voice list, rendered inside the dialog.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `ReactNode` | - | The title for screen readers. Hidden visually but accessible to assistive technologies. |\n| `className` | `string` | - | Additional CSS classes to apply to the dialog content. |\n| `...props` | `React.ComponentProps<typeof DialogContent>` | - | Any other props are spread to the DialogContent component. |\n\n### `<VoiceSelectorDialog />`\n\nAlternative dialog implementation using CommandDialog for a full-screen command palette style.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandDialog>` | - | Any other props are spread to the CommandDialog component. |\n\n### `<VoiceSelectorInput />`\n\nSearch input for filtering voices.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `placeholder` | `string` | - | Placeholder text for the search input. |\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the CommandInput component. |\n\n### `<VoiceSelectorList />`\n\nScrollable container for voice items and groups.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandList>` | - | Any other props are spread to the CommandList component. |\n\n### `<VoiceSelectorEmpty />`\n\nMessage shown when no voices match the search query.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode` | - | The message to display. |\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the CommandEmpty component. |\n\n### `<VoiceSelectorGroup />`\n\nGroups related voices together with an optional heading.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `heading` | `string` | - | The heading text for the group. |\n| `...props` | `React.ComponentProps<typeof CommandGroup>` | - | Any other props are spread to the CommandGroup component. |\n\n### `<VoiceSelectorItem />`\n\nSelectable item representing a voice.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The unique identifier for this voice. Used for search filtering. |\n| `onSelect` | `(value: string) => void` | - | Callback fired when the voice is selected. |\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the CommandItem component. |\n\n### `<VoiceSelectorSeparator />`\n\nVisual separator between voice groups.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandSeparator>` | - | Any other props are spread to the CommandSeparator component. |\n\n### `<VoiceSelectorName />`\n\nDisplays the voice name with proper styling.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorGender />`\n\nDisplays the voice gender metadata with icons from Lucide. Supports multiple gender identities with corresponding icons.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `unknown` | - | The gender value that determines which icon to display. Supported values:  |\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `children` | `ReactNode` | - | Override the icon with custom content. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorAccent />`\n\nDisplays the voice accent metadata with emoji flags representing different countries/regions.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `unknown` | - | The accent value that determines which flag emoji to display. Supports 27 different accents including:  |\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `children` | `ReactNode` | - | Override the flag emoji with custom content. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorAge />`\n\nDisplays the voice age metadata with muted styling and tabular numbers for consistent alignment.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorDescription />`\n\nDisplays a description for the voice with muted styling.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorAttributes />`\n\nContainer for grouping voice attributes (gender, accent, age) together. Use with `VoiceSelectorBullet` for separation.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. |\n\n### `<VoiceSelectorBullet />`\n\nDisplays a bullet separator (•) between voice attributes. Hidden from screen readers via `aria-hidden`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<VoiceSelectorShortcut />`\n\nDisplays keyboard shortcuts for voice items.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandShortcut>` | - | Any other props are spread to the CommandShortcut component. |\n\n### `<VoiceSelectorPreview />`\n\nA button that allows users to preview/play a voice sample before selecting it. Shows play, pause, or loading icons based on state.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `playing` | `boolean` | - | Whether the voice is currently playing. Shows pause icon when true. |\n| `loading` | `boolean` | - | Whether the voice preview is loading. Shows loading spinner and disables the button. |\n| `onPlay` | `() => void` | - | Callback fired when the preview button is clicked. |\n| `className` | `string` | - | Additional CSS classes to apply. |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the button element. |\n\n## Hooks\n\n### `useVoiceSelector()`\n\nA custom hook for accessing the voice selector context. This hook allows you to access and control the voice selection state from any component nested within `VoiceSelector`.\n\n```tsx\nimport { useVoiceSelector } from \"@repo/elements/voice-selector\";\n\nexport default function CustomVoiceDisplay() {\n  const { value, setValue, open, setOpen } = useVoiceSelector();\n\n  return (\n    <div>\n      <p>Selected voice: {value ?? \"None\"}</p>\n      <button onClick={() => setOpen(!open)}>Toggle Dialog</button>\n    </div>\n  );\n}\n```\n\n#### Return Value\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string | undefined` | - | The currently selected voice ID. |\n| `setValue` | `(value: string | undefined) => void` | - | Function to update the selected voice ID. |\n| `open` | `boolean` | - | Whether the dialog is currently open. |\n| `setOpen` | `(open: boolean) => void` | - | Function to control the dialog open state. |\n","isInternal":false,"tokens":2422,"sizeBytes":10565},{"name":"web-preview.md","path":".agents/skills/ai-elements/references/web-preview.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/references/web-preview.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Web Preview\n\nA composable component for previewing the result of a generated UI, with support for live examples and code display.\n\nThe `WebPreview` component provides a flexible way to showcase the result of a generated UI component, along with its source code. It is designed for documentation and demo purposes, allowing users to interact with live examples and view the underlying implementation.\n\nSee `scripts/web-preview.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add web-preview\n```\n\n## Usage with AI SDK\n\nBuild a simple v0 clone using the [v0 Platform API](https://v0.dev/docs/api/platform).\n\nInstall the `v0-sdk` package:\n\n```package-install\nnpm i v0-sdk\n```\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  WebPreview,\n  WebPreviewBody,\n  WebPreviewNavigation,\n  WebPreviewUrl,\n} from \"@/components/ai-elements/web-preview\";\nimport { useState } from \"react\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { Spinner } from \"@/components/ui/spinner\";\n\nconst WebPreviewDemo = () => {\n  const [previewUrl, setPreviewUrl] = useState(\"\");\n  const [prompt, setPrompt] = useState(\"\");\n  const [isGenerating, setIsGenerating] = useState(false);\n\n  const handleSubmit = async (message: PromptInputMessage) => {\n    if (!message.text.trim()) return;\n    setPrompt(\"\");\n\n    setIsGenerating(true);\n    try {\n      const response = await fetch(\"/api/v0\", {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\" },\n        body: JSON.stringify({ prompt: message.text }),\n      });\n\n      const data = await response.json();\n      setPreviewUrl(data.demo || \"/\");\n      console.log(\"Generation finished:\", data);\n    } catch (error) {\n      console.error(\"Generation failed:\", error);\n    } finally {\n      setIsGenerating(false);\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex-1 mb-4\">\n          {isGenerating ? (\n            <div className=\"flex flex-col items-center justify-center h-full\">\n              <Spinner />\n              <p className=\"mt-4 text-muted-foreground\">\n                Generating app, this may take a few seconds...\n              </p>\n            </div>\n          ) : previewUrl ? (\n            <WebPreview defaultUrl={previewUrl}>\n              <WebPreviewNavigation>\n                <WebPreviewUrl />\n              </WebPreviewNavigation>\n              <WebPreviewBody src={previewUrl} />\n            </WebPreview>\n          ) : (\n            <div className=\"flex items-center justify-center h-full text-muted-foreground\">\n              Your generated app will appear here\n            </div>\n          )}\n        </div>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={prompt}\n            placeholder=\"Describe the app you want to build...\"\n            onChange={(e) => setPrompt(e.currentTarget.value)}\n            className=\"pr-12 min-h-[60px]\"\n          />\n          <PromptInputSubmit\n            status={isGenerating ? \"streaming\" : \"ready\"}\n            disabled={!prompt.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default WebPreviewDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/v0/route.ts\"\nimport { v0 } from \"v0-sdk\";\n\nexport async function POST(req: Request) {\n  const { prompt }: { prompt: string } = await req.json();\n\n  const result = await v0.chats.create({\n    system: \"You are an expert coder\",\n    message: prompt,\n    modelConfiguration: {\n      modelId: \"v0-1.5-sm\",\n      imageGenerations: false,\n      thinking: false,\n    },\n  });\n\n  return Response.json({\n    demo: result.demo,\n    webUrl: result.webUrl,\n  });\n}\n```\n\n## Features\n\n- Live preview of UI components\n- Composable architecture with dedicated sub-components\n- Responsive design modes (Desktop, Tablet, Mobile)\n- Navigation controls with back/forward functionality\n- URL input and example selector\n- Full screen mode support\n- Console logging with timestamps\n- Context-based state management\n- Consistent styling with the design system\n- Easy integration into documentation pages\n\n## Props\n\n### `<WebPreview />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultUrl` | `string` | - | The initial URL to load in the preview. |\n| `onUrlChange` | `(url: string) => void` | - | Callback fired when the URL changes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<WebPreviewNavigation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the navigation container. |\n\n### `<WebPreviewNavigationButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string` | - | Tooltip text to display on hover. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<WebPreviewUrl />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Input>` | - | Any other props are spread to the underlying shadcn/ui Input component. |\n\n### `<WebPreviewBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `loading` | `React.ReactNode` | - | Optional loading indicator to display over the preview. |\n| `...props` | `React.IframeHTMLAttributes<HTMLIFrameElement>` | - | Any other props are spread to the underlying iframe. |\n\n### `<WebPreviewConsole />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `logs` | `Array<{ level: ` | - | Console log entries to display in the console panel. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n","isInternal":false,"tokens":1435,"sizeBytes":6278},{"name":"SKILL.md","path":".agents/skills/ai-elements/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-elements/SKILL.md","title":"ai-elements","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fai-elements%2FSKILL.md -->","frontmatter":{"name":"ai-elements","description":"Build AI chat interfaces using ai-elements components — conversations, messages, tool displays, prompt inputs, and more. Use when the user wants to build a chatbot, AI assistant UI, or any AI-powered chat interface."},"isInternal":false,"tokens":1635,"sizeBytes":7246},{"name":"SKILL.md","path":".agents/skills/ai-sdk/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ai-sdk/SKILL.md","title":"ai-sdk","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fai-sdk%2FSKILL.md -->","frontmatter":{"name":"ai-sdk","description":"Answer questions about the AI SDK and help build AI-powered features. Use when developers: (1) Ask about AI SDK functions like generateText, streamText, ToolLoopAgent, embed, or tools, (2) Want to build AI agents, chatbots, RAG systems, or text generation features, (3) Have questions about AI providers (OpenAI, Anthropic, Google, etc.), streaming, tool calling, structured output, or embeddings, (4) Use React hooks like useChat or useCompletion. Triggers on: \"AI SDK\", \"Vercel AI SDK\", \"generateText\", \"streamText\", \"add AI to my app\", \"build an agent\", \"tool calling\", \"structured output\", \"useChat\"."},"isInternal":false,"tokens":1273,"sizeBytes":5547},{"name":"openai.yaml","path":".agents/skills/better-accessibility/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-accessibility/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fagents%2Fopenai.yaml -->","isInternal":false,"tokens":27,"sizeBytes":121},{"name":"focus-and-keyboard.md","path":".agents/skills/better-accessibility/focus-and-keyboard.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-accessibility/focus-and-keyboard.md","title":"Better-accessibility Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Ffocus-and-keyboard.md -->","isInternal":false,"tokens":1513,"sizeBytes":6581},{"name":"forms.md","path":".agents/skills/better-accessibility/forms.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-accessibility/forms.md","title":"Better-accessibility Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fforms.md -->","isInternal":false,"tokens":958,"sizeBytes":3995},{"name":"hit-areas.md","path":".agents/skills/better-accessibility/hit-areas.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-accessibility/hit-areas.md","title":"Better-accessibility Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fhit-areas.md -->","isInternal":false,"tokens":702,"sizeBytes":2903},{"name":"motion-and-zoom.md","path":".agents/skills/better-accessibility/motion-and-zoom.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-accessibility/motion-and-zoom.md","title":"Better-accessibility Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fmotion-and-zoom.md -->","isInternal":false,"tokens":982,"sizeBytes":4078},{"name":"screen-readers.md","path":".agents/skills/better-accessibility/screen-readers.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-accessibility/screen-readers.md","title":"Better-accessibility Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fscreen-readers.md -->","isInternal":false,"tokens":1239,"sizeBytes":5087},{"name":"semantics-and-aria.md","path":".agents/skills/better-accessibility/semantics-and-aria.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-accessibility/semantics-and-aria.md","title":"Better-accessibility Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2Fsemantics-and-aria.md -->","isInternal":false,"tokens":1203,"sizeBytes":5283},{"name":"SKILL.md","path":".agents/skills/better-accessibility/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-accessibility/SKILL.md","title":"better-accessibility","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-accessibility%2FSKILL.md -->","frontmatter":{"name":"better-accessibility","description":"Accessibility engineering for product interfaces, from focus states and keyboard support to ARIA, forms, and screen readers. Use when building or reviewing UI components, modals, menus, forms, custom widgets, or when the user says \"make this accessible\" or reports keyboard or screen-reader issues. Triggers on accessibility, a11y, WCAG, aria, focus ring, focus-visible, focus trap, keyboard navigation, tab order, tabindex, screen reader, sr-only, aria-live, alt text, hit area, touch target, prefers-reduced-motion, autoplay, toast duration, skip link, semantic HTML, aria-label, form errors, disabled buttons, \"not keyboard accessible\"."},"isInternal":false,"tokens":2788,"sizeBytes":12293},{"name":"SKILL.md","path":".agents/skills/better-auth-best-practices/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-auth-best-practices/SKILL.md","title":"better-auth-best-practices","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-auth-best-practices%2FSKILL.md -->","frontmatter":{"name":"better-auth-best-practices","description":"Configure Better Auth server and client, set up database adapters, manage sessions, add plugins, and handle environment variables. Use when users mention Better Auth, betterauth, auth.ts, or need to set up TypeScript authentication with email/password, OAuth, or plugin configuration."},"isInternal":false,"tokens":1904,"sizeBytes":7409},{"name":"accessibility-contrast.md","path":".agents/skills/better-colors/accessibility-contrast.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-colors/accessibility-contrast.md","title":"Better-colors Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Faccessibility-contrast.md -->","isInternal":false,"tokens":1161,"sizeBytes":4327},{"name":"openai.yaml","path":".agents/skills/better-colors/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-colors/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fagents%2Fopenai.yaml -->","isInternal":false,"tokens":26,"sizeBytes":103},{"name":"color-conversion.md","path":".agents/skills/better-colors/color-conversion.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-colors/color-conversion.md","title":"Better-colors Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fcolor-conversion.md -->","isInternal":false,"tokens":553,"sizeBytes":1836},{"name":"color-usage.md","path":".agents/skills/better-colors/color-usage.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-colors/color-usage.md","title":"Better-colors Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fcolor-usage.md -->","isInternal":false,"tokens":1234,"sizeBytes":5002},{"name":"gamut-and-tailwind.md","path":".agents/skills/better-colors/gamut-and-tailwind.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-colors/gamut-and-tailwind.md","title":"Better-colors Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fgamut-and-tailwind.md -->","isInternal":false,"tokens":873,"sizeBytes":2480},{"name":"palette-generation.md","path":".agents/skills/better-colors/palette-generation.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-colors/palette-generation.md","title":"Better-colors Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2Fpalette-generation.md -->","isInternal":false,"tokens":1059,"sizeBytes":3275},{"name":"SKILL.md","path":".agents/skills/better-colors/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-colors/SKILL.md","title":"better-colors","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-colors%2FSKILL.md -->","frontmatter":{"name":"better-colors","description":"OKLCH color space and color usage for web projects. Convert hex/rgb/hsl to oklch, generate palettes, check contrast, handle gamut boundaries, theme with Tailwind v4, and apply color with meaning. Triggers on oklch, color conversion, palette generation, contrast ratio, gamut, display p3, design tokens, semantic color tokens, hue drift, chroma, dark mode colors, accent color, color meaning, light and dark appearance, increased contrast."},"isInternal":false,"tokens":1941,"sizeBytes":7738},{"name":"openai.yaml","path":".agents/skills/better-interface/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-interface/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-interface%2Fagents%2Fopenai.yaml -->","isInternal":false,"tokens":32,"sizeBytes":146},{"name":"SKILL.md","path":".agents/skills/better-interface/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-interface/SKILL.md","title":"better-interface","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-interface%2FSKILL.md -->","frontmatter":{"name":"better-interface","description":"User-invoked, cross-discipline interface review that coordinates better-accessibility, better-layout, better-writing, better-typography, better-colors, and better-ui. Use when explicitly invoked for a holistic review of a screen, flow, feature, or product interface. Supports quick and full review modes. Triggers on better-interface, full interface review, holistic UI audit, cross-discipline design review, review the whole interface."},"isInternal":false,"tokens":1707,"sizeBytes":8114},{"name":"openai.yaml","path":".agents/skills/better-layout/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-layout/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-layout%2Fagents%2Fopenai.yaml -->","isInternal":false,"tokens":24,"sizeBytes":117},{"name":"grouping-and-alignment.md","path":".agents/skills/better-layout/grouping-and-alignment.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-layout/grouping-and-alignment.md","title":"Better-layout Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-layout%2Fgrouping-and-alignment.md -->","isInternal":false,"tokens":1346,"sizeBytes":5701},{"name":"SKILL.md","path":".agents/skills/better-layout/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-layout/SKILL.md","title":"better-layout","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-layout%2FSKILL.md -->","frontmatter":{"name":"better-layout","description":"Layout structure for web interfaces, from grouping and alignment to reading order, progressive disclosure, and adaptive breakpoints. Use when structuring a page or component, spacing or aligning controls, deciding what collapses at small sizes, handling RTL layout direction, or reviewing frontend code for layout. Triggers on layout, spacing, alignment, grouping, negative space, whitespace, visual hierarchy, reading order, progressive disclosure, breakpoints, responsive layout, container queries, safe area, full-bleed, edge-to-edge, layout margins, RTL layout, logical properties."},"isInternal":false,"tokens":1816,"sizeBytes":8486},{"name":"spacing-and-adaptivity.md","path":".agents/skills/better-layout/spacing-and-adaptivity.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-layout/spacing-and-adaptivity.md","title":"Better-layout Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-layout%2Fspacing-and-adaptivity.md -->","isInternal":false,"tokens":1612,"sizeBytes":6771},{"name":"openai.yaml","path":".agents/skills/better-typography/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-typography/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fagents%2Fopenai.yaml -->","isInternal":false,"tokens":24,"sizeBytes":120},{"name":"choosing-fonts.md","path":".agents/skills/better-typography/choosing-fonts.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-typography/choosing-fonts.md","title":"Better-typography Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fchoosing-fonts.md -->","isInternal":false,"tokens":742,"sizeBytes":3258},{"name":"css-cheat-sheet.md","path":".agents/skills/better-typography/css-cheat-sheet.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-typography/css-cheat-sheet.md","title":"Better-typography Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fcss-cheat-sheet.md -->","isInternal":false,"tokens":1095,"sizeBytes":3952},{"name":"details-and-accessibility.md","path":".agents/skills/better-typography/details-and-accessibility.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-typography/details-and-accessibility.md","title":"Better-typography Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fdetails-and-accessibility.md -->","isInternal":false,"tokens":1008,"sizeBytes":4456},{"name":"SKILL.md","path":".agents/skills/better-typography/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-typography/SKILL.md","title":"better-typography","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2FSKILL.md -->","frontmatter":{"name":"better-typography","description":"Web typography from choosing fonts to spacing, wrapping and accessibility. Use when picking or pairing typefaces, configuring variable fonts or OpenType features, setting up a type scale, checking heading hierarchy, styling text in components, truncating text, styling underlines, selection, placeholders or carets, or reviewing frontend code for typography. Triggers on typography, fonts, font formats, woff2, variable fonts, font-weight, opentype, font-feature-settings, letter-spacing, line-height, type scale, heading hierarchy, heading levels, tabular numbers, text-wrap, truncation, line clamp, underlines, text-decoration, text selection, iOS input zoom, font smoothing, text contrast, measure, line length, text-box, smart punctuation, drop cap."},"isInternal":false,"tokens":3491,"sizeBytes":15294},{"name":"spacing-and-sizing.md","path":".agents/skills/better-typography/spacing-and-sizing.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-typography/spacing-and-sizing.md","title":"Better-typography Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fspacing-and-sizing.md -->","isInternal":false,"tokens":1270,"sizeBytes":4889},{"name":"variable-fonts-and-opentype.md","path":".agents/skills/better-typography/variable-fonts-and-opentype.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-typography/variable-fonts-and-opentype.md","title":"Better-typography Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fvariable-fonts-and-opentype.md -->","isInternal":false,"tokens":1038,"sizeBytes":4369},{"name":"wrapping-and-punctuation.md","path":".agents/skills/better-typography/wrapping-and-punctuation.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-typography/wrapping-and-punctuation.md","title":"Better-typography Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-typography%2Fwrapping-and-punctuation.md -->","isInternal":false,"tokens":824,"sizeBytes":3579},{"name":"openai.yaml","path":".agents/skills/better-ui/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-ui/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Fagents%2Fopenai.yaml -->","isInternal":false,"tokens":22,"sizeBytes":113},{"name":"animations.md","path":".agents/skills/better-ui/animations.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-ui/animations.md","title":"Better-ui Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Fanimations.md -->","isInternal":false,"tokens":3296,"sizeBytes":13214},{"name":"icons.md","path":".agents/skills/better-ui/icons.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-ui/icons.md","title":"Better-ui Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Ficons.md -->","isInternal":false,"tokens":1104,"sizeBytes":4422},{"name":"performance.md","path":".agents/skills/better-ui/performance.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-ui/performance.md","title":"Better-ui Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Fperformance.md -->","isInternal":false,"tokens":679,"sizeBytes":3014},{"name":"SKILL.md","path":".agents/skills/better-ui/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-ui/SKILL.md","title":"better-ui","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2FSKILL.md -->","frontmatter":{"name":"better-ui","description":"Design engineering principles for making interfaces feel polished. Use when building UI components, reviewing frontend code, implementing animations, hover states, shadows, borders, micro-interactions, enter/exit animations, choosing or reviewing icons, or any visual detail work. Triggers on UI polish, design details, \"make it feel better\", \"feels off\", stagger animations, border radius, optical alignment, image outlines, box shadows, icons, icon stroke weight, icon states, motion restraint."},"isInternal":false,"tokens":2189,"sizeBytes":9638},{"name":"surfaces.md","path":".agents/skills/better-ui/surfaces.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-ui/surfaces.md","title":"Better-ui Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-ui%2Fsurfaces.md -->","isInternal":false,"tokens":1751,"sizeBytes":6518},{"name":"openai.yaml","path":".agents/skills/better-writing/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-writing/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-writing%2Fagents%2Fopenai.yaml -->","isInternal":false,"tokens":24,"sizeBytes":108},{"name":"SKILL.md","path":".agents/skills/better-writing/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/better-writing/SKILL.md","title":"better-writing","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fbetter-writing%2FSKILL.md -->","frontmatter":{"name":"better-writing","description":"UX writing and interface copy, from voice and button labels to error messages and empty states. Use when writing or reviewing any user-facing text: button and link labels, form errors, placeholders, settings labels, onboarding flows, notifications, or empty states. Triggers on UX writing, microcopy, interface copy, product copy, copywriting, button labels, link text, error messages, empty states, placeholder text, settings labels, capitalization, title case, sentence case, voice and tone."},"isInternal":false,"tokens":2213,"sizeBytes":9961},{"name":"SKILL.md","path":".agents/skills/code-refactor-review/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/code-refactor-review/SKILL.md","title":"code-refactor-review","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fcode-refactor-review%2FSKILL.md -->","frontmatter":{"name":"code-refactor-review","description":"Reviews code changes for reuse, composition, codebase consistency, and slop. Use when asked to review PRs/diffs, check code reuse, composition, cleanliness, or whether code fits the codebase."},"isInternal":false,"tokens":1267,"sizeBytes":6301},{"name":"SKILL.md","path":".agents/skills/create-draft-pr/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/create-draft-pr/SKILL.md","title":"create-draft-pr","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fcreate-draft-pr%2FSKILL.md -->","frontmatter":{"name":"create-draft-pr","description":"Commit, push, and create a draft PR using the pr-description format, with UX flow context when relevant.","user-invocable":true},"isInternal":false,"tokens":558,"sizeBytes":2365},{"name":"api-editor.md","path":".agents/skills/diffs/references/api-editor.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/diffs/references/api-editor.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Fapi-editor.md -->","isInternal":false,"tokens":1342,"sizeBytes":8085},{"name":"api-react.md","path":".agents/skills/diffs/references/api-react.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/diffs/references/api-react.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Fapi-react.md -->","isInternal":false,"tokens":977,"sizeBytes":5474},{"name":"recipe-code-view.md","path":".agents/skills/diffs/references/recipe-code-view.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/diffs/references/recipe-code-view.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Frecipe-code-view.md -->","isInternal":false,"tokens":1461,"sizeBytes":5905},{"name":"recipe-edit-react.md","path":".agents/skills/diffs/references/recipe-edit-react.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/diffs/references/recipe-edit-react.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Frecipe-edit-react.md -->","isInternal":false,"tokens":1062,"sizeBytes":4573},{"name":"recipe-react.md","path":".agents/skills/diffs/references/recipe-react.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/diffs/references/recipe-react.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2Freferences%2Frecipe-react.md -->","isInternal":false,"tokens":308,"sizeBytes":1391},{"name":"SKILL.md","path":".agents/skills/diffs/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/diffs/SKILL.md","title":"diffs","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fdiffs%2FSKILL.md -->","frontmatter":{"name":"diffs","description":"Use when an app uses @pierre/diffs to render or edit code files, diffs, patches, merge conflicts, or CodeView review surfaces, including React, vanilla JavaScript, SSR, workers, annotations, selection, and custom Shiki languages or themes."},"isInternal":false,"tokens":458,"sizeBytes":2105},{"name":"SKILL.md","path":".agents/skills/eve/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/eve/SKILL.md","title":"eve","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Feve%2FSKILL.md -->","frontmatter":{"name":"eve","description":"Build durable backend AI agents with the eve framework. Use when creating, editing, or debugging an eve project — agent instructions, skills, tools, connections, channels, sandboxes, subagents, schedules, or evals."},"isInternal":false,"tokens":230,"sizeBytes":1032},{"name":"SKILL.md","path":".agents/skills/ga-pr/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ga-pr/SKILL.md","title":"ga-pr","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fga-pr%2FSKILL.md -->","frontmatter":{"name":"ga-pr","description":"Kick off follow-up work on an existing PR in a parallel tmux/agent session. Use when the user asks to work on a PR, continue a branch, address PR feedback, or resolve merge conflicts in the background.","user-invocable":true},"isInternal":false,"tokens":437,"sizeBytes":1762},{"name":"SKILL.md","path":".agents/skills/ga/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ga/SKILL.md","title":"ga","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fga%2FSKILL.md -->","frontmatter":{"name":"ga","description":"Kick off a new feature or fix in a parallel clone with Pi working autonomously. Takes a problem description, generates a concise branch name, runs ga to set up the worktree, and sends a crafted prompt to the new Pi session.","user-invocable":true},"isInternal":false,"tokens":764,"sizeBytes":3033},{"name":"commands.md","path":".agents/skills/gh-stack/references/commands.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/gh-stack/references/commands.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fgh-stack%2Freferences%2Fcommands.md -->","isInternal":false,"tokens":2264,"sizeBytes":9268},{"name":"stack-design.md","path":".agents/skills/gh-stack/references/stack-design.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/gh-stack/references/stack-design.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fgh-stack%2Freferences%2Fstack-design.md -->","isInternal":false,"tokens":944,"sizeBytes":4209},{"name":"troubleshooting.md","path":".agents/skills/gh-stack/references/troubleshooting.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/gh-stack/references/troubleshooting.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fgh-stack%2Freferences%2Ftroubleshooting.md -->","isInternal":false,"tokens":1606,"sizeBytes":6712},{"name":"SKILL.md","path":".agents/skills/gh-stack/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/gh-stack/SKILL.md","title":"gh-stack","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fgh-stack%2FSKILL.md -->","frontmatter":{"name":"gh-stack","description":"Manages stacked PRs and splits multi-part work into reviewable branches with gh-stack. Use for stack creation, viewing, edits, push, submit, sync, rebase, merge, or checkout; when asked to split or isolate work for review; whenever a user mentions a stack, branch layers, dependent PRs, or gh stack; or when a stack is checked out.\n","metadata":{"author":"github","version":"0.1.0"}},"isInternal":false,"tokens":2095,"sizeBytes":8323},{"name":"SKILL.md","path":".agents/skills/install-anti-slop/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/install-anti-slop/SKILL.md","title":"install-anti-slop","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Finstall-anti-slop%2FSKILL.md -->","frontmatter":{"name":"install-anti-slop","description":"Install and configure the anti-slop Oxlint plugin in a local TypeScript or JavaScript repository. Use whenever a user asks to add anti-slop lint rules, copy the anti-slop plugin, configure opinionated Oxlint rules, or migrate an existing local anti-slop setup."},"isInternal":false,"tokens":800,"sizeBytes":3594},{"name":"_sections.md","path":".agents/skills/nestjs-best-practices/rules/_sections.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/_sections.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2F_sections.md -->","isInternal":false,"tokens":430,"sizeBytes":2153},{"name":"_template.md","path":".agents/skills/nestjs-best-practices/rules/_template.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/_template.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2F_template.md -->","frontmatter":{"title":"Rule Title Here","impact":"MEDIUM","impactDescription":"Optional description of impact (e.g., \"20-50% improvement\")","tags":"tag1, tag2"},"isInternal":false,"tokens":143,"sizeBytes":631},{"name":"api-use-dto-serialization.md","path":".agents/skills/nestjs-best-practices/rules/api-use-dto-serialization.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/api-use-dto-serialization.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fapi-use-dto-serialization.md -->","frontmatter":{"title":"Use DTOs and Serialization for API Responses","impact":"MEDIUM","impactDescription":"Response DTOs prevent accidental data exposure and ensure consistency","tags":"api, dto, serialization, class-transformer"},"isInternal":false,"tokens":1053,"sizeBytes":4385},{"name":"api-use-interceptors.md","path":".agents/skills/nestjs-best-practices/rules/api-use-interceptors.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/api-use-interceptors.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fapi-use-interceptors.md -->","frontmatter":{"title":"Use Interceptors for Cross-Cutting Concerns","impact":"MEDIUM-HIGH","impactDescription":"Interceptors provide clean separation for cross-cutting logic","tags":"api, interceptors, logging, caching"},"isInternal":false,"tokens":1177,"sizeBytes":5518},{"name":"api-use-pipes.md","path":".agents/skills/nestjs-best-practices/rules/api-use-pipes.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/api-use-pipes.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fapi-use-pipes.md -->","frontmatter":{"title":"Use Pipes for Input Transformation","impact":"MEDIUM","impactDescription":"Pipes ensure clean, validated data reaches your handlers","tags":"api, pipes, validation, transformation"},"isInternal":false,"tokens":1267,"sizeBytes":5386},{"name":"api-versioning.md","path":".agents/skills/nestjs-best-practices/rules/api-versioning.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/api-versioning.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fapi-versioning.md -->","frontmatter":{"title":"Use API Versioning for Breaking Changes","impact":"MEDIUM","impactDescription":"Versioning allows you to evolve APIs without breaking existing clients","tags":"api, versioning, breaking-changes, compatibility"},"isInternal":false,"tokens":1204,"sizeBytes":4986},{"name":"arch-avoid-circular-deps.md","path":".agents/skills/nestjs-best-practices/rules/arch-avoid-circular-deps.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/arch-avoid-circular-deps.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-avoid-circular-deps.md -->","frontmatter":{"title":"Avoid Circular Dependencies","impact":"CRITICAL","impactDescription":"#1 cause of runtime crashes","tags":"architecture, modules, dependencies"},"isInternal":false,"tokens":438,"sizeBytes":2021},{"name":"arch-feature-modules.md","path":".agents/skills/nestjs-best-practices/rules/arch-feature-modules.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/arch-feature-modules.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-feature-modules.md -->","frontmatter":{"title":"Organize by Feature Modules","impact":"CRITICAL","impactDescription":"3-5x faster onboarding and development","tags":"architecture, modules, organization"},"isInternal":false,"tokens":511,"sizeBytes":2316},{"name":"arch-module-sharing.md","path":".agents/skills/nestjs-best-practices/rules/arch-module-sharing.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/arch-module-sharing.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-module-sharing.md -->","frontmatter":{"title":"Use Proper Module Sharing Patterns","impact":"CRITICAL","impactDescription":"Prevents duplicate instances, memory leaks, and state inconsistency","tags":"architecture, modules, sharing, exports"},"isInternal":false,"tokens":825,"sizeBytes":3876},{"name":"arch-single-responsibility.md","path":".agents/skills/nestjs-best-practices/rules/arch-single-responsibility.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/arch-single-responsibility.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-single-responsibility.md -->","frontmatter":{"title":"Single Responsibility for Services","impact":"CRITICAL","impactDescription":"40%+ improvement in testability","tags":"architecture, services, single-responsibility"},"isInternal":false,"tokens":625,"sizeBytes":2922},{"name":"arch-use-events.md","path":".agents/skills/nestjs-best-practices/rules/arch-use-events.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/arch-use-events.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-use-events.md -->","frontmatter":{"title":"Use Event-Driven Architecture for Decoupling","impact":"MEDIUM-HIGH","impactDescription":"Enables async processing and modularity","tags":"architecture, events, decoupling"},"isInternal":false,"tokens":631,"sizeBytes":3051},{"name":"arch-use-repository-pattern.md","path":".agents/skills/nestjs-best-practices/rules/arch-use-repository-pattern.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/arch-use-repository-pattern.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Farch-use-repository-pattern.md -->","frontmatter":{"title":"Use Repository Pattern for Data Access","impact":"HIGH","impactDescription":"Decouples business logic from database","tags":"architecture, repository, data-access"},"isInternal":false,"tokens":626,"sizeBytes":2861},{"name":"db-avoid-n-plus-one.md","path":".agents/skills/nestjs-best-practices/rules/db-avoid-n-plus-one.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/db-avoid-n-plus-one.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdb-avoid-n-plus-one.md -->","frontmatter":{"title":"Avoid N+1 Query Problems","impact":"HIGH","impactDescription":"N+1 queries are one of the most common performance killers","tags":"database, n-plus-one, queries, performance"},"isInternal":false,"tokens":897,"sizeBytes":3888},{"name":"db-use-migrations.md","path":".agents/skills/nestjs-best-practices/rules/db-use-migrations.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/db-use-migrations.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdb-use-migrations.md -->","frontmatter":{"title":"Use Database Migrations","impact":"HIGH","impactDescription":"Enables safe, repeatable database schema changes","tags":"database, migrations, typeorm, schema"},"isInternal":false,"tokens":904,"sizeBytes":3837},{"name":"db-use-transactions.md","path":".agents/skills/nestjs-best-practices/rules/db-use-transactions.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/db-use-transactions.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdb-use-transactions.md -->","frontmatter":{"title":"Use Transactions for Multi-Step Operations","impact":"HIGH","impactDescription":"Ensures data consistency in multi-step operations","tags":"database, transactions, typeorm, consistency"},"isInternal":false,"tokens":811,"sizeBytes":4023},{"name":"devops-graceful-shutdown.md","path":".agents/skills/nestjs-best-practices/rules/devops-graceful-shutdown.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/devops-graceful-shutdown.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdevops-graceful-shutdown.md -->","frontmatter":{"title":"Implement Graceful Shutdown","impact":"MEDIUM-HIGH","impactDescription":"Proper shutdown handling ensures zero-downtime deployments","tags":"devops, graceful-shutdown, lifecycle, kubernetes"},"isInternal":false,"tokens":1273,"sizeBytes":5916},{"name":"devops-use-config-module.md","path":".agents/skills/nestjs-best-practices/rules/devops-use-config-module.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/devops-use-config-module.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdevops-use-config-module.md -->","frontmatter":{"title":"Use ConfigModule for Environment Configuration","impact":"LOW-MEDIUM","impactDescription":"Proper configuration prevents deployment failures","tags":"devops, configuration, environment, validation"},"isInternal":false,"tokens":1001,"sizeBytes":4446},{"name":"devops-use-logging.md","path":".agents/skills/nestjs-best-practices/rules/devops-use-logging.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/devops-use-logging.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdevops-use-logging.md -->","frontmatter":{"title":"Use Structured Logging","impact":"MEDIUM-HIGH","impactDescription":"Structured logging enables effective debugging and monitoring","tags":"devops, logging, structured-logs, pino"},"isInternal":false,"tokens":1267,"sizeBytes":5693},{"name":"di-avoid-service-locator.md","path":".agents/skills/nestjs-best-practices/rules/di-avoid-service-locator.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/di-avoid-service-locator.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-avoid-service-locator.md -->","frontmatter":{"title":"Avoid Service Locator Anti-Pattern","impact":"HIGH","impactDescription":"Hides dependencies and breaks testability","tags":"dependency-injection, anti-patterns, testing"},"isInternal":false,"tokens":614,"sizeBytes":2981},{"name":"di-interface-segregation.md","path":".agents/skills/nestjs-best-practices/rules/di-interface-segregation.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/di-interface-segregation.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-interface-segregation.md -->","frontmatter":{"title":"Apply Interface Segregation Principle","impact":"HIGH","impactDescription":"Reduces coupling and improves testability by 30-50%","tags":"dependency-injection, interfaces, solid, isp"},"isInternal":false,"tokens":1132,"sizeBytes":5224},{"name":"di-liskov-substitution.md","path":".agents/skills/nestjs-best-practices/rules/di-liskov-substitution.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/di-liskov-substitution.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-liskov-substitution.md -->","frontmatter":{"title":"Honor Liskov Substitution Principle","impact":"HIGH","impactDescription":"Ensures implementations are truly interchangeable without breaking callers","tags":"dependency-injection, inheritance, solid, lsp"},"isInternal":false,"tokens":1518,"sizeBytes":7275},{"name":"di-prefer-constructor-injection.md","path":".agents/skills/nestjs-best-practices/rules/di-prefer-constructor-injection.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/di-prefer-constructor-injection.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-prefer-constructor-injection.md -->","frontmatter":{"title":"Prefer Constructor Injection","impact":"CRITICAL","impactDescription":"Required for proper DI and testing","tags":"dependency-injection, constructor, testing"},"isInternal":false,"tokens":486,"sizeBytes":2309},{"name":"di-scope-awareness.md","path":".agents/skills/nestjs-best-practices/rules/di-scope-awareness.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/di-scope-awareness.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-scope-awareness.md -->","frontmatter":{"title":"Understand Provider Scopes","impact":"CRITICAL","impactDescription":"Prevents data leaks and performance issues","tags":"dependency-injection, scopes, request-context"},"isInternal":false,"tokens":564,"sizeBytes":2618},{"name":"di-use-interfaces-tokens.md","path":".agents/skills/nestjs-best-practices/rules/di-use-interfaces-tokens.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/di-use-interfaces-tokens.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fdi-use-interfaces-tokens.md -->","frontmatter":{"title":"Use Injection Tokens for Interfaces","impact":"HIGH","impactDescription":"Enables interface-based DI at runtime","tags":"dependency-injection, tokens, interfaces"},"isInternal":false,"tokens":541,"sizeBytes":2588},{"name":"error-handle-async-errors.md","path":".agents/skills/nestjs-best-practices/rules/error-handle-async-errors.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/error-handle-async-errors.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ferror-handle-async-errors.md -->","frontmatter":{"title":"Handle Async Errors Properly","impact":"HIGH","impactDescription":"Prevents process crashes from unhandled rejections","tags":"error-handling, async, promises"},"isInternal":false,"tokens":777,"sizeBytes":3531},{"name":"error-throw-http-exceptions.md","path":".agents/skills/nestjs-best-practices/rules/error-throw-http-exceptions.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/error-throw-http-exceptions.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ferror-throw-http-exceptions.md -->","frontmatter":{"title":"Throw HTTP Exceptions from Services","impact":"HIGH","impactDescription":"Keeps controllers thin and simplifies error handling","tags":"error-handling, exceptions, services"},"isInternal":false,"tokens":688,"sizeBytes":3181},{"name":"error-use-exception-filters.md","path":".agents/skills/nestjs-best-practices/rules/error-use-exception-filters.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/error-use-exception-filters.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ferror-use-exception-filters.md -->","frontmatter":{"title":"Use Exception Filters for Error Handling","impact":"HIGH","impactDescription":"Consistent, centralized error handling","tags":"error-handling, exception-filters, consistency"},"isInternal":false,"tokens":763,"sizeBytes":3695},{"name":"micro-use-health-checks.md","path":".agents/skills/nestjs-best-practices/rules/micro-use-health-checks.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/micro-use-health-checks.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fmicro-use-health-checks.md -->","frontmatter":{"title":"Implement Health Checks for Microservices","impact":"MEDIUM-HIGH","impactDescription":"Health checks enable orchestrators to manage service lifecycle","tags":"microservices, health-checks, terminus, kubernetes"},"isInternal":false,"tokens":1381,"sizeBytes":5985},{"name":"micro-use-patterns.md","path":".agents/skills/nestjs-best-practices/rules/micro-use-patterns.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/micro-use-patterns.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fmicro-use-patterns.md -->","frontmatter":{"title":"Use Message and Event Patterns Correctly","impact":"MEDIUM","impactDescription":"Proper patterns ensure reliable microservice communication","tags":"microservices, message-pattern, event-pattern, communication"},"isInternal":false,"tokens":1083,"sizeBytes":5102},{"name":"micro-use-queues.md","path":".agents/skills/nestjs-best-practices/rules/micro-use-queues.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/micro-use-queues.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fmicro-use-queues.md -->","frontmatter":{"title":"Use Message Queues for Background Jobs","impact":"MEDIUM-HIGH","impactDescription":"Queues enable reliable background processing","tags":"microservices, queues, bullmq, background-jobs"},"isInternal":false,"tokens":1485,"sizeBytes":6214},{"name":"perf-async-hooks.md","path":".agents/skills/nestjs-best-practices/rules/perf-async-hooks.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/perf-async-hooks.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fperf-async-hooks.md -->","frontmatter":{"title":"Use Async Lifecycle Hooks Correctly","impact":"HIGH","impactDescription":"Improper async handling blocks application startup","tags":"performance, lifecycle, async, hooks"},"isInternal":false,"tokens":612,"sizeBytes":2918},{"name":"perf-lazy-loading.md","path":".agents/skills/nestjs-best-practices/rules/perf-lazy-loading.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/perf-lazy-loading.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fperf-lazy-loading.md -->","frontmatter":{"title":"Use Lazy Loading for Large Modules","impact":"MEDIUM","impactDescription":"Improves startup time for large applications","tags":"performance, lazy-loading, modules, optimization"},"isInternal":false,"tokens":825,"sizeBytes":3822},{"name":"perf-optimize-database.md","path":".agents/skills/nestjs-best-practices/rules/perf-optimize-database.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/perf-optimize-database.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fperf-optimize-database.md -->","frontmatter":{"title":"Optimize Database Queries","impact":"HIGH","impactDescription":"Database queries are typically the largest source of latency","tags":"performance, database, queries, optimization"},"isInternal":false,"tokens":753,"sizeBytes":3276},{"name":"perf-use-caching.md","path":".agents/skills/nestjs-best-practices/rules/perf-use-caching.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/perf-use-caching.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fperf-use-caching.md -->","frontmatter":{"title":"Use Caching Strategically","impact":"HIGH","impactDescription":"Dramatically reduces database load and response times","tags":"performance, caching, redis, optimization"},"isInternal":false,"tokens":821,"sizeBytes":3524},{"name":"security-auth-jwt.md","path":".agents/skills/nestjs-best-practices/rules/security-auth-jwt.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/security-auth-jwt.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-auth-jwt.md -->","frontmatter":{"title":"Implement Secure JWT Authentication","impact":"CRITICAL","impactDescription":"Essential for secure APIs","tags":"security, jwt, authentication, tokens"},"isInternal":false,"tokens":917,"sizeBytes":4083},{"name":"security-rate-limiting.md","path":".agents/skills/nestjs-best-practices/rules/security-rate-limiting.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/security-rate-limiting.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-rate-limiting.md -->","frontmatter":{"title":"Implement Rate Limiting","impact":"HIGH","impactDescription":"Protects against abuse and ensures fair resource usage","tags":"security, rate-limiting, throttler, protection"},"isInternal":false,"tokens":797,"sizeBytes":3324},{"name":"security-sanitize-output.md","path":".agents/skills/nestjs-best-practices/rules/security-sanitize-output.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/security-sanitize-output.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-sanitize-output.md -->","frontmatter":{"title":"Sanitize Output to Prevent XSS","impact":"HIGH","impactDescription":"XSS vulnerabilities can compromise user sessions and data","tags":"security, xss, sanitization, html"},"isInternal":false,"tokens":912,"sizeBytes":3815},{"name":"security-use-guards.md","path":".agents/skills/nestjs-best-practices/rules/security-use-guards.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/security-use-guards.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-use-guards.md -->","frontmatter":{"title":"Use Guards for Authentication and Authorization","impact":"HIGH","impactDescription":"Enforces access control before handlers execute","tags":"security, guards, authentication, authorization"},"isInternal":false,"tokens":795,"sizeBytes":3647},{"name":"security-validate-all-input.md","path":".agents/skills/nestjs-best-practices/rules/security-validate-all-input.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/security-validate-all-input.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Fsecurity-validate-all-input.md -->","frontmatter":{"title":"Validate All Input with DTOs and Pipes","impact":"HIGH","impactDescription":"First line of defense against attacks","tags":"security, validation, dto, pipes"},"isInternal":false,"tokens":858,"sizeBytes":3393},{"name":"test-e2e-supertest.md","path":".agents/skills/nestjs-best-practices/rules/test-e2e-supertest.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/test-e2e-supertest.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ftest-e2e-supertest.md -->","frontmatter":{"title":"Use Supertest for E2E Testing","impact":"HIGH","impactDescription":"Validates the full request/response cycle","tags":"testing, e2e, supertest, integration"},"isInternal":false,"tokens":1116,"sizeBytes":4800},{"name":"test-mock-external-services.md","path":".agents/skills/nestjs-best-practices/rules/test-mock-external-services.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/test-mock-external-services.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ftest-mock-external-services.md -->","frontmatter":{"title":"Mock External Services in Tests","impact":"HIGH","impactDescription":"Ensures fast, reliable, deterministic tests","tags":"testing, mocking, external-services, jest"},"isInternal":false,"tokens":1075,"sizeBytes":4613},{"name":"test-use-testing-module.md","path":".agents/skills/nestjs-best-practices/rules/test-use-testing-module.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/rules/test-use-testing-module.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2Frules%2Ftest-use-testing-module.md -->","frontmatter":{"title":"Use Testing Module for Unit Tests","impact":"HIGH","impactDescription":"Enables proper isolated testing with mocked dependencies","tags":"testing, unit-tests, mocking, jest"},"isInternal":false,"tokens":960,"sizeBytes":4392},{"name":"SKILL.md","path":".agents/skills/nestjs-best-practices/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-best-practices/SKILL.md","title":"nestjs-best-practices","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-best-practices%2FSKILL.md -->","frontmatter":{"name":"nestjs-best-practices","description":"NestJS best practices and architecture patterns for building production-ready applications. This skill should be used when writing, reviewing, or refactoring NestJS code to ensure proper patterns for modules, dependency injection, security, and performance.","license":"MIT","metadata":{"author":"Kadajett","version":"1.2.0"}},"isInternal":false,"tokens":1166,"sizeBytes":4754},{"name":"api-reference.md","path":".agents/skills/nestjs-trpc/references/api-reference.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-trpc/references/api-reference.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Fapi-reference.md -->","isInternal":false,"tokens":2169,"sizeBytes":8625},{"name":"codegen-and-client.md","path":".agents/skills/nestjs-trpc/references/codegen-and-client.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-trpc/references/codegen-and-client.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Fcodegen-and-client.md -->","isInternal":false,"tokens":2654,"sizeBytes":10789},{"name":"middlewares-and-context.md","path":".agents/skills/nestjs-trpc/references/middlewares-and-context.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-trpc/references/middlewares-and-context.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Fmiddlewares-and-context.md -->","isInternal":false,"tokens":2721,"sizeBytes":11792},{"name":"module-config.md","path":".agents/skills/nestjs-trpc/references/module-config.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-trpc/references/module-config.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Fmodule-config.md -->","isInternal":false,"tokens":2391,"sizeBytes":9955},{"name":"routers.md","path":".agents/skills/nestjs-trpc/references/routers.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-trpc/references/routers.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2Freferences%2Frouters.md -->","isInternal":false,"tokens":2497,"sizeBytes":10400},{"name":"SKILL.md","path":".agents/skills/nestjs-trpc/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nestjs-trpc/SKILL.md","title":"nestjs-trpc","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnestjs-trpc%2FSKILL.md -->","frontmatter":{"name":"nestjs-trpc","description":"Build end-to-end type-safe tRPC APIs inside NestJS using the nestjs-trpc adapter — @Router/@Query/@Mutation/@Subscription decorators, TRPCModule.forRoot, injectable middlewares and context, Zod input/output schemas, and the Rust CLI that generates the AppRouter type for clients. Use this skill whenever the user mentions nestjs-trpc, tRPC in a NestJS app, @Router or @Query decorators, TRPCModule, AppRouterHost, \"typed API between my Nest backend and frontend\", generating AppRouter types, or is migrating a NestJS GraphQL/REST API to tRPC — even if they don't name the library explicitly.","license":"MIT","metadata":{"version":"1.0.0","targets":"nestjs-trpc v2.x (verified against 2.13.0)","docs":"https://nestjs-trpc.io/docs"}},"isInternal":false,"tokens":2810,"sizeBytes":11442},{"name":"SKILL.md","path":".agents/skills/no-use-effect/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/no-use-effect/SKILL.md","title":"no-use-effect","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fno-use-effect%2FSKILL.md -->","frontmatter":{"name":"no-use-effect","description":"Enforce the no-useEffect rule when writing or reviewing React code. ACTIVATE when writing React components, refactoring existing useEffect calls, reviewing PRs with useEffect, or when an agent adds useEffect \"just in case.\" Provides the five replacement patterns and the useMountEffect escape hatch."},"isInternal":false,"tokens":1597,"sizeBytes":6734},{"name":"AGENTS.md","path":".agents/skills/nuqs/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/AGENTS.md","title":"Nuqs Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2FAGENTS.md -->","isInternal":false,"tokens":2126,"sizeBytes":8711},{"name":"_template.md","path":".agents/skills/nuqs/assets/templates/_template.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/assets/templates/_template.md","title":"Templates Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Fassets%2Ftemplates%2F_template.md -->","isInternal":false,"tokens":229,"sizeBytes":886},{"name":"README.md","path":".agents/skills/nuqs/README.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/README.md","title":"Nuqs Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2FREADME.md -->","isInternal":false,"tokens":713,"sizeBytes":2826},{"name":"_sections.md","path":".agents/skills/nuqs/references/_sections.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/_sections.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2F_sections.md -->","isInternal":false,"tokens":338,"sizeBytes":1670},{"name":"advanced-custom-parsers.md","path":".agents/skills/nuqs/references/advanced-custom-parsers.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/advanced-custom-parsers.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-custom-parsers.md -->","frontmatter":{"title":"Create Custom Parsers for Complex Types","impact":"LOW","impactDescription":"prevents runtime errors from string coercion","tags":"advanced, createParser, custom, serialize, parse"},"isInternal":false,"tokens":727,"sizeBytes":2739},{"name":"advanced-eq-function.md","path":".agents/skills/nuqs/references/advanced-eq-function.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/advanced-eq-function.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-eq-function.md -->","frontmatter":{"title":"Implement eq Function for Object Parsers","impact":"LOW","impactDescription":"prevents unnecessary URL updates for equivalent objects","tags":"advanced, eq, equality, objects, optimization"},"isInternal":false,"tokens":592,"sizeBytes":2326},{"name":"advanced-framework-adapters.md","path":".agents/skills/nuqs/references/advanced-framework-adapters.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/advanced-framework-adapters.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-framework-adapters.md -->","frontmatter":{"title":"Use Framework-Specific Adapters","impact":"LOW","impactDescription":"prevents URL sync failures in non-Next.js apps","tags":"advanced, adapters, remix, react-router, tanstack-router, frameworks"},"isInternal":false,"tokens":689,"sizeBytes":2629},{"name":"advanced-process-url-search-params.md","path":".agents/skills/nuqs/references/advanced-process-url-search-params.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/advanced-process-url-search-params.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-process-url-search-params.md -->","frontmatter":{"title":"Use processUrlSearchParams for Canonical URL Shape","impact":"LOW-MEDIUM","impactDescription":"enables stable URL ordering for SEO and cache hit-rate","tags":"advanced, processUrlSearchParams, seo, canonical-url, createSerializer"},"isInternal":false,"tokens":687,"sizeBytes":2925},{"name":"advanced-url-keys.md","path":".agents/skills/nuqs/references/advanced-url-keys.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/advanced-url-keys.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fadvanced-url-keys.md -->","frontmatter":{"title":"Use urlKeys for Shorter URLs","impact":"LOW","impactDescription":"keeps shareable links compact by shortening verbose URL keys","tags":"advanced, urlKeys, serializer, url-length, abbreviation"},"isInternal":false,"tokens":416,"sizeBytes":1593},{"name":"debug-enable-logging.md","path":".agents/skills/nuqs/references/debug-enable-logging.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/debug-enable-logging.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fdebug-enable-logging.md -->","frontmatter":{"title":"Enable Debug Logging for Troubleshooting","impact":"LOW-MEDIUM","impactDescription":"surfaces the exact parse/serialize/URL-write step instead of guessing from silent state","tags":"debug, logging, localStorage, troubleshooting, devtools"},"isInternal":false,"tokens":373,"sizeBytes":1554},{"name":"debug-testing.md","path":".agents/skills/nuqs/references/debug-testing.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/debug-testing.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fdebug-testing.md -->","frontmatter":{"title":"Test Components with URL State","impact":"LOW-MEDIUM","impactDescription":"enables reliable CI/CD testing of nuqs components","tags":"debug, testing, jest, vitest, react-testing-library"},"isInternal":false,"tokens":370,"sizeBytes":1552},{"name":"history-push-navigation.md","path":".agents/skills/nuqs/references/history-push-navigation.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/history-push-navigation.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fhistory-push-navigation.md -->","frontmatter":{"title":"Choose the Right history Mode (push vs replace)","impact":"MEDIUM","impactDescription":"back button behaves as users expect for navigation vs ephemeral state","tags":"history, push, replace, navigation, back-button, ux"},"isInternal":false,"tokens":655,"sizeBytes":2623},{"name":"history-scroll-behavior.md","path":".agents/skills/nuqs/references/history-scroll-behavior.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/history-scroll-behavior.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fhistory-scroll-behavior.md -->","frontmatter":{"title":"Control Scroll Behavior on URL Changes","impact":"MEDIUM","impactDescription":"prevents jarring scroll jumps on state changes","tags":"history, scroll, ux, navigation, viewport"},"isInternal":false,"tokens":427,"sizeBytes":1751},{"name":"parser-array-format.md","path":".agents/skills/nuqs/references/parser-array-format.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/parser-array-format.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-array-format.md -->","frontmatter":{"title":"Choose Correct Array Parser Format","impact":"CRITICAL","impactDescription":"prevents API integration failures from wrong URL format","tags":"parser, parseAsArrayOf, parseAsNativeArrayOf, arrays, url-format"},"isInternal":false,"tokens":499,"sizeBytes":1922},{"name":"parser-date-format.md","path":".agents/skills/nuqs/references/parser-date-format.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/parser-date-format.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-date-format.md -->","frontmatter":{"title":"Select Appropriate Date Parser","impact":"CRITICAL","impactDescription":"prevents timezone bugs and parsing failures","tags":"parser, parseAsTimestamp, parseAsIsoDateTime, parseAsIsoDate, dates"},"isInternal":false,"tokens":543,"sizeBytes":2035},{"name":"parser-enum-validation.md","path":".agents/skills/nuqs/references/parser-enum-validation.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/parser-enum-validation.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-enum-validation.md -->","frontmatter":{"title":"Use Enum Parsers for Constrained Values","impact":"CRITICAL","impactDescription":"prevents invalid state from URL manipulation","tags":"parser, parseAsStringEnum, parseAsStringLiteral, validation, security"},"isInternal":false,"tokens":511,"sizeBytes":2040},{"name":"parser-index-offset.md","path":".agents/skills/nuqs/references/parser-index-offset.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/parser-index-offset.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-index-offset.md -->","frontmatter":{"title":"Use parseAsIndex for 1-Based URL Display","impact":"HIGH","impactDescription":"eliminates off-by-one errors between URL and code","tags":"parser, parseAsIndex, pagination, zero-indexed, one-indexed"},"isInternal":false,"tokens":534,"sizeBytes":1821},{"name":"parser-json-validation.md","path":".agents/skills/nuqs/references/parser-json-validation.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/parser-json-validation.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-json-validation.md -->","frontmatter":{"title":"Validate JSON Parser Input","impact":"CRITICAL","impactDescription":"prevents runtime crashes and unsafe casts from URL-supplied JSON","tags":"parser, parseAsJson, validation, standard-schema, zod"},"isInternal":false,"tokens":773,"sizeBytes":3079},{"name":"parser-use-typed-parsers.md","path":".agents/skills/nuqs/references/parser-use-typed-parsers.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/parser-use-typed-parsers.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-use-typed-parsers.md -->","frontmatter":{"title":"Use Typed Parsers for Non-String Values","impact":"CRITICAL","impactDescription":"prevents runtime type errors and hydration mismatches","tags":"parser, type-safety, parseAsInteger, parseAsFloat, parseAsBoolean"},"isInternal":false,"tokens":392,"sizeBytes":1520},{"name":"parser-with-default.md","path":".agents/skills/nuqs/references/parser-with-default.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/parser-with-default.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fparser-with-default.md -->","frontmatter":{"title":"Use withDefault for Non-Nullable State","impact":"CRITICAL","impactDescription":"eliminates null checks throughout component tree","tags":"parser, withDefault, null-safety, type-inference"},"isInternal":false,"tokens":410,"sizeBytes":1619},{"name":"perf-avoid-rerender.md","path":".agents/skills/nuqs/references/perf-avoid-rerender.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/perf-avoid-rerender.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-avoid-rerender.md -->","frontmatter":{"title":"Memoize Components Using URL State","impact":"MEDIUM","impactDescription":"prevents unnecessary re-renders on URL changes (Next.js especially)","tags":"perf, memo, re-renders, key-isolation, react"},"isInternal":false,"tokens":687,"sizeBytes":2808},{"name":"perf-clear-on-default.md","path":".agents/skills/nuqs/references/perf-clear-on-default.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/perf-clear-on-default.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-clear-on-default.md -->","frontmatter":{"title":"Use clearOnDefault for Clean URLs","impact":"MEDIUM","impactDescription":"reduces URL length by 20-50% for default values","tags":"perf, clearOnDefault, url-cleanup, defaults, seo"},"isInternal":false,"tokens":412,"sizeBytes":1617},{"name":"perf-debounce-search.md","path":".agents/skills/nuqs/references/perf-debounce-search.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/perf-debounce-search.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-debounce-search.md -->","frontmatter":{"title":"Debounce Search Input Before URL Update","impact":"HIGH","impactDescription":"reduces server requests during typing from N per keystroke to 1 per pause","tags":"perf, limitUrlUpdates, debounce, search, server-load"},"isInternal":false,"tokens":755,"sizeBytes":3163},{"name":"perf-key-isolation.md","path":".agents/skills/nuqs/references/perf-key-isolation.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/perf-key-isolation.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-key-isolation.md -->","frontmatter":{"title":"Rely on Key Isolation Outside Next.js","impact":"HIGH","impactDescription":"avoids unnecessary memoization on adapters that already scope re-renders per key","tags":"perf, key-isolation, react-router, tanstack-router, remix, re-renders"},"isInternal":false,"tokens":760,"sizeBytes":3024},{"name":"perf-serialize-utility.md","path":".agents/skills/nuqs/references/perf-serialize-utility.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/perf-serialize-utility.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-serialize-utility.md -->","frontmatter":{"title":"Use createSerializer for Link URLs","impact":"MEDIUM","impactDescription":"enables SSR-compatible URL generation without hooks","tags":"perf, createSerializer, links, navigation, ssr"},"isInternal":false,"tokens":511,"sizeBytes":2028},{"name":"perf-throttle-updates.md","path":".agents/skills/nuqs/references/perf-throttle-updates.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/perf-throttle-updates.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fperf-throttle-updates.md -->","frontmatter":{"title":"Throttle Rapid URL Updates","impact":"MEDIUM","impactDescription":"prevents browser history API rate limiting on rapid input","tags":"perf, limitUrlUpdates, throttle, rate-limiting, slider"},"isInternal":false,"tokens":720,"sizeBytes":2966},{"name":"server-next15-async.md","path":".agents/skills/nuqs/references/server-next15-async.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/server-next15-async.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-next15-async.md -->","frontmatter":{"title":"Handle Async searchParams in Next.js 15+","impact":"HIGH","impactDescription":"prevents build errors in Next.js 15 with async props","tags":"server, nextjs15, async, searchParams, promise"},"isInternal":false,"tokens":520,"sizeBytes":2088},{"name":"server-parse-before-get.md","path":".agents/skills/nuqs/references/server-parse-before-get.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/server-parse-before-get.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-parse-before-get.md -->","frontmatter":{"title":"Call parse() Before get() in Server Components","impact":"HIGH","impactDescription":"prevents undefined values and runtime errors","tags":"server, parse, get, searchParamsCache, initialization"},"isInternal":false,"tokens":509,"sizeBytes":2163},{"name":"server-search-params-cache.md","path":".agents/skills/nuqs/references/server-search-params-cache.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/server-search-params-cache.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-search-params-cache.md -->","frontmatter":{"title":"Use createSearchParamsCache for Server Components","impact":"HIGH","impactDescription":"eliminates prop drilling across N component levels","tags":"server, createSearchParamsCache, server-components, type-safety"},"isInternal":false,"tokens":733,"sizeBytes":3151},{"name":"server-shallow-false.md","path":".agents/skills/nuqs/references/server-shallow-false.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/server-shallow-false.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-shallow-false.md -->","frontmatter":{"title":"Use shallow:false to Trigger Server Re-renders","impact":"HIGH","impactDescription":"enables server-side data refetching on URL change","tags":"server, shallow, server-components, data-fetching, rsc"},"isInternal":false,"tokens":526,"sizeBytes":2165},{"name":"server-use-transition.md","path":".agents/skills/nuqs/references/server-use-transition.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/server-use-transition.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fserver-use-transition.md -->","frontmatter":{"title":"Integrate useTransition for Loading States","impact":"HIGH","impactDescription":"exposes pending state for non-shallow server fetches so the UI can show loading","tags":"server, useTransition, loading, suspense, streaming"},"isInternal":false,"tokens":568,"sizeBytes":2425},{"name":"setup-default-options.md","path":".agents/skills/nuqs/references/setup-default-options.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/setup-default-options.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-default-options.md -->","frontmatter":{"title":"Configure App-Wide Defaults on NuqsAdapter","impact":"MEDIUM","impactDescription":"avoids repeating .withOptions on every parser; enforces consistent behaviour","tags":"setup, NuqsAdapter, defaultOptions, configuration, consistency"},"isInternal":false,"tokens":735,"sizeBytes":2980},{"name":"setup-import-server.md","path":".agents/skills/nuqs/references/setup-import-server.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/setup-import-server.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-import-server.md -->","frontmatter":{"title":"Import Server Utilities from nuqs/server","impact":"CRITICAL","impactDescription":"prevents RSC-to-client boundary contamination errors","tags":"setup, nuqs/server, imports, createSearchParamsCache, server-components"},"isInternal":false,"tokens":480,"sizeBytes":1954},{"name":"setup-nextjs-version.md","path":".agents/skills/nuqs/references/setup-nextjs-version.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/setup-nextjs-version.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-nextjs-version.md -->","frontmatter":{"title":"Ensure Compatible Next.js Version","impact":"CRITICAL","impactDescription":"prevents cryptic runtime errors from version mismatch","tags":"setup, nextjs, version, compatibility, app-router"},"isInternal":false,"tokens":572,"sizeBytes":1979},{"name":"setup-nuqs-adapter.md","path":".agents/skills/nuqs/references/setup-nuqs-adapter.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/setup-nuqs-adapter.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-nuqs-adapter.md -->","frontmatter":{"title":"Wrap App with NuqsAdapter","impact":"CRITICAL","impactDescription":"prevents 100% of hook failures from missing provider","tags":"setup, NuqsAdapter, provider, app-router, pages-router"},"isInternal":false,"tokens":619,"sizeBytes":2203},{"name":"setup-shared-parsers.md","path":".agents/skills/nuqs/references/setup-shared-parsers.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/setup-shared-parsers.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-shared-parsers.md -->","frontmatter":{"title":"Define Shared Parsers in Dedicated File","impact":"HIGH","impactDescription":"prevents parser mismatch bugs between components","tags":"setup, parsers, organization, reusability, consistency"},"isInternal":false,"tokens":673,"sizeBytes":2848},{"name":"setup-use-client.md","path":".agents/skills/nuqs/references/setup-use-client.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/setup-use-client.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fsetup-use-client.md -->","frontmatter":{"title":"Add 'use client' Directive for Hooks","impact":"CRITICAL","impactDescription":"prevents build-breaking hook errors in RSC","tags":"setup, use-client, server-components, client-components"},"isInternal":false,"tokens":426,"sizeBytes":1730},{"name":"state-avoid-derived.md","path":".agents/skills/nuqs/references/state-avoid-derived.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/state-avoid-derived.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-avoid-derived.md -->","frontmatter":{"title":"Avoid Derived State from URL Parameters","impact":"HIGH","impactDescription":"prevents sync bugs and unnecessary re-renders","tags":"state, derived-state, anti-pattern, single-source-of-truth"},"isInternal":false,"tokens":570,"sizeBytes":2209},{"name":"state-clear-with-null.md","path":".agents/skills/nuqs/references/state-clear-with-null.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/state-clear-with-null.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-clear-with-null.md -->","frontmatter":{"title":"Clear URL Parameters with null","impact":"HIGH","impactDescription":"reduces URL clutter by removing unnecessary parameters","tags":"state, null, clear, url-cleanup, reset"},"isInternal":false,"tokens":487,"sizeBytes":1863},{"name":"state-options-inheritance.md","path":".agents/skills/nuqs/references/state-options-inheritance.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/state-options-inheritance.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-options-inheritance.md -->","frontmatter":{"title":"Use withOptions for Parser-Level Configuration","impact":"MEDIUM","impactDescription":"reduces boilerplate and ensures consistent behavior","tags":"state, withOptions, configuration, parsers, reusability"},"isInternal":false,"tokens":528,"sizeBytes":2210},{"name":"state-setter-return.md","path":".agents/skills/nuqs/references/state-setter-return.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/state-setter-return.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-setter-return.md -->","frontmatter":{"title":"Use Setter Return Value for URL Access","impact":"MEDIUM","impactDescription":"enables accurate URL tracking for analytics/sharing without re-deriving the URL","tags":"state, setter, return-value, URLSearchParams, analytics"},"isInternal":false,"tokens":670,"sizeBytes":2757},{"name":"state-standard-schema.md","path":".agents/skills/nuqs/references/state-standard-schema.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/state-standard-schema.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-standard-schema.md -->","frontmatter":{"title":"Use Standard Schema for Cross-Library Validation","impact":"MEDIUM","impactDescription":"one parser map validates nuqs, tRPC, route validators, and forms — no duplicated schema","tags":"state, standard-schema, zod, valibot, trpc, validation"},"isInternal":false,"tokens":877,"sizeBytes":3477},{"name":"state-use-query-states.md","path":".agents/skills/nuqs/references/state-use-query-states.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/references/state-use-query-states.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2Freferences%2Fstate-use-query-states.md -->","frontmatter":{"title":"Use useQueryStates for Related Parameters","impact":"HIGH","impactDescription":"gives a single typed object and one combined URLSearchParams flush","tags":"state, useQueryStates, batching, atomic, related-params"},"isInternal":false,"tokens":735,"sizeBytes":2901},{"name":"SKILL.md","path":".agents/skills/nuqs/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/nuqs/SKILL.md","title":"nuqs","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fnuqs%2FSKILL.md -->","frontmatter":{"name":"nuqs","description":"nuqs (type-safe URL query state) best practices for Next.js and other React frameworks. This skill should be used when writing, reviewing, or refactoring code that uses nuqs for URL state management. Triggers on tasks involving useQueryState, useQueryStates, search params, URL state, query parameters, nuqs parsers, limitUrlUpdates, Standard Schema, NuqsAdapter, or Next.js routing with state."},"isInternal":false,"tokens":1569,"sizeBytes":6963},{"name":"SKILL.md","path":".agents/skills/pit-of-success/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/pit-of-success/SKILL.md","title":"pit-of-success","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fpit-of-success%2FSKILL.md -->","frontmatter":{"name":"pit-of-success","description":"Review or refactor code so the correct behavior is the default path; use when APIs, setters, hooks, helpers, or component props have footguns where a natural call bypasses required semantics.","user-invocable":true},"isInternal":false,"tokens":424,"sizeBytes":2009},{"name":"SKILL.md","path":".agents/skills/posthog-instrumentation/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/posthog-instrumentation/SKILL.md","title":"posthog-instrumentation","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fposthog-instrumentation%2FSKILL.md -->","frontmatter":{"name":"posthog-instrumentation","description":"Automatically add PostHog analytics instrumentation to code. Triggers when user asks to add tracking, instrument events, add analytics, or implement feature flags in their codebase."},"isInternal":false,"tokens":395,"sizeBytes":1680},{"name":"SKILL.md","path":".agents/skills/prepare-branch-context/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/prepare-branch-context/SKILL.md","title":"prepare-branch-context","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprepare-branch-context%2FSKILL.md -->","frontmatter":{"name":"prepare-branch-context","description":"Analyze the current branch's diff from main and related PR to build context for followup requests. Triggers on \"prepare context\", \"branch context\", \"catch me up\", \"what's on this branch\".","user-invocable":true},"isInternal":false,"tokens":509,"sizeBytes":2207},{"name":"cockroachdb.md","path":".agents/skills/prisma-database-setup/references/cockroachdb.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/prisma-database-setup/references/cockroachdb.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fcockroachdb.md -->","isInternal":false,"tokens":470,"sizeBytes":1837},{"name":"mongodb.md","path":".agents/skills/prisma-database-setup/references/mongodb.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/prisma-database-setup/references/mongodb.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fmongodb.md -->","isInternal":false,"tokens":682,"sizeBytes":2722},{"name":"mysql.md","path":".agents/skills/prisma-database-setup/references/mysql.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/prisma-database-setup/references/mysql.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fmysql.md -->","isInternal":false,"tokens":671,"sizeBytes":2669},{"name":"postgresql.md","path":".agents/skills/prisma-database-setup/references/postgresql.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/prisma-database-setup/references/postgresql.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fpostgresql.md -->","isInternal":false,"tokens":464,"sizeBytes":1840},{"name":"prisma-client-setup.md","path":".agents/skills/prisma-database-setup/references/prisma-client-setup.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/prisma-database-setup/references/prisma-client-setup.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fprisma-client-setup.md -->","isInternal":false,"tokens":313,"sizeBytes":1325},{"name":"prisma-postgres.md","path":".agents/skills/prisma-database-setup/references/prisma-postgres.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/prisma-database-setup/references/prisma-postgres.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fprisma-postgres.md -->","isInternal":false,"tokens":774,"sizeBytes":3201},{"name":"sqlite.md","path":".agents/skills/prisma-database-setup/references/sqlite.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/prisma-database-setup/references/sqlite.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fsqlite.md -->","isInternal":false,"tokens":573,"sizeBytes":2210},{"name":"sqlserver.md","path":".agents/skills/prisma-database-setup/references/sqlserver.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/prisma-database-setup/references/sqlserver.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2Freferences%2Fsqlserver.md -->","isInternal":false,"tokens":524,"sizeBytes":2114},{"name":"SKILL.md","path":".agents/skills/prisma-database-setup/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/prisma-database-setup/SKILL.md","title":"prisma-database-setup","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fprisma-database-setup%2FSKILL.md -->","frontmatter":{"name":"prisma-database-setup","description":"Guides for configuring Prisma with different database providers (PostgreSQL, MySQL, SQLite, MongoDB, etc.). Use when setting up a new project, changing databases, or troubleshooting connection issues. Triggers on \"configure postgres\", \"connect to mysql\", \"setup mongodb\", \"sqlite setup\".","license":"MIT","metadata":{"author":"prisma","version":"7.6.0"}},"isInternal":false,"tokens":1468,"sizeBytes":5834},{"name":"evals.json","path":".agents/skills/seo-audit/evals/evals.json","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/seo-audit/evals/evals.json","title":"Evals Skill","category":"anthropic-skill","format":"json","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fseo-audit%2Fevals%2Fevals.json -->","frontmatter":{"skill_name":"seo-audit","evals":[{"id":1,"prompt":"Can you do an SEO audit of our SaaS website? We're getting about 2,000 organic visits/month but feel like we should be getting more. URL: https://example.com","expected_output":"Should check for product-marketing.md first. Should ask clarifying questions about priority keywords, Search Console access, recent changes, and competitors. Should follow the audit framework priority order: Crawlability & Indexation, Technical Foundations, On-Page Optimization, Content Quality, Authority & Links. Should check robots.txt, XML sitemap, site architecture. Should evaluate title tags, meta descriptions, heading structure, and content optimization. Should NOT report on schema markup based solely on web_fetch (must note the detection limitation). Output should follow the Audit Report Structure: Executive Summary, Technical SEO Findings, On-Page SEO Findings, Content Findings, and Prioritized Action Plan.","assertions":["Checks for product-marketing.md","Asks clarifying questions about keywords, Search Console, recent changes","Follows audit priority order: crawlability first, then technical, on-page, content, authority","Checks robots.txt and XML sitemap","Evaluates title tags, meta descriptions, heading structure","Does NOT claim 'no schema found' based on web_fetch alone","Notes schema markup detection limitation","Output has Executive Summary","Output has Prioritized Action Plan","Each finding has Issue, Impact, Evidence, Fix, and Priority"],"files":[]},{"id":2,"prompt":"Why am I not ranking for 'project management software'? We have a page targeting that keyword but it's stuck on page 3.","expected_output":"Should trigger on the casual 'why am I not ranking' phrasing. Should investigate both on-page and off-page factors. On-page: check title tag, H1, URL alignment with keyword; evaluate content depth vs competitors; check for keyword cannibalization. Technical: check indexation status, canonical tags, crawlability. Content quality: assess E-E-A-T signals, content depth, user engagement. Should provide specific, actionable fixes organized by priority. Should mention competitive analysis against current top-ranking pages.","assertions":["Triggers on casual 'why am I not ranking' phrasing","Checks title tag, H1, URL alignment with target keyword","Evaluates content depth vs competitors","Checks for keyword cannibalization","Checks indexation status and canonical tags","Assesses E-E-A-T signals","Mentions competitive analysis against top-ranking pages","Provides actionable fixes organized by priority"],"files":[]},{"id":3,"prompt":"We just migrated from WordPress to Next.js and our organic traffic dropped 40% in the last month. Help!","expected_output":"Should treat this as an urgent migration diagnostic. Should immediately check: redirect mapping (301s from old URLs to new), canonical tags on new pages, robots.txt not blocking crawlers, XML sitemap submitted and updated, meta tags preserved. Should check for common migration issues: redirect chains/loops, soft 404s, lost internal links, changed URL structures without redirects. Should reference Search Console coverage report for indexation issues. Should provide a prioritized recovery plan with critical fixes first. Should mention monitoring timeline expectations (recovery can take weeks).","assertions":["Treats as urgent migration diagnostic","Checks redirect mapping (301s)","Checks canonical tags on new pages","Checks robots.txt not blocking crawlers","Checks XML sitemap updated and submitted","Checks for redirect chains or loops","Checks for soft 404s","References Search Console coverage report","Provides prioritized recovery plan","Mentions recovery timeline expectations"],"files":[]},{"id":4,"prompt":"Review the technical SEO of our e-commerce site. We have about 50,000 products and use faceted navigation.","expected_output":"Should focus on e-commerce-specific technical issues: faceted navigation creating duplicate content, crawl budget management for large product catalog, parameterized URLs, product schema markup (with the caveat about detection limitations). Should check for thin category pages, duplicate product descriptions, out-of-stock page handling. Should address crawl budget issues: pagination, infinite scroll handling, session IDs in URLs. Should provide structured findings with Impact ratings and specific fixes.","assertions":["Addresses faceted navigation duplicate content","Addresses crawl budget for large catalog","Checks for parameterized URL issues","Mentions product schema with detection limitation caveat","Checks for thin category pages","Checks for duplicate product descriptions","Addresses out-of-stock page handling","Addresses pagination and infinite scroll","Findings include Impact ratings and specific fixes"],"files":[]},{"id":5,"prompt":"Can you check our blog posts for on-page SEO issues? We publish 4 posts per week but traffic has been flat for 6 months.","expected_output":"Should apply the Content/Blog Sites framework: check for outdated content not refreshed, keyword cannibalization, missing topical clustering, poor internal linking, missing author pages. Should audit on-page elements: title tags, meta descriptions, heading structure, keyword targeting per post. Should assess E-E-A-T signals for blog content. Should check for content depth issues and whether posts answer search intent. Should recommend a content audit process and provide a prioritized action plan for the existing content library.","assertions":["Applies Content/Blog Sites framework","Checks for outdated content","Checks for keyword cannibalization","Checks for topical clustering","Checks for internal linking quality","Checks for author pages and E-E-A-T signals","Audits title tags, meta descriptions, heading structure","Assesses whether content answers search intent","Recommends content audit process","Provides prioritized action plan"],"files":[]},{"id":6,"prompt":"I run a local plumbing business with 3 locations. My website barely shows up when people search for 'plumber near me' in our areas. What's wrong?","expected_output":"Should apply the Local Business site-type framework. Should check for: inconsistent NAP (Name, Address, Phone) across the site, missing local schema markup (with detection limitation caveat), Google Business Profile optimization, missing individual location pages for each of the 3 locations, and missing local content. Should also check standard technical and on-page factors. Should recommend local-specific fixes: location-specific pages with unique content, local schema on each, GBP optimization, citation consistency.","assertions":["Applies Local Business framework","Checks NAP consistency","Checks for local schema markup with detection caveat","Addresses Google Business Profile optimization","Recommends individual location pages for each location","Recommends local content strategy","Checks standard technical SEO factors too","Provides prioritized local SEO action plan"],"files":[]},{"id":7,"prompt":"Our site loads really slowly, especially on mobile. Pages take 5-6 seconds to load. Is this hurting our SEO?","expected_output":"Should focus on Site Speed and Core Web Vitals. Should explain CWV thresholds: LCP < 2.5s, INP < 200ms, CLS < 0.1, and that 5-6s load time is well above acceptable. Should investigate speed factors: server response time (TTFB), image optimization, JavaScript execution, CSS delivery, caching headers, CDN usage, font loading. Should recommend specific tools: PageSpeed Insights, WebPageTest, Chrome DevTools, Search Console CWV report. Should explain that yes, page speed is a ranking factor and directly impacts SEO. Should provide prioritized fixes.","assertions":["Focuses on Core Web Vitals","Explains CWV thresholds (LCP, INP, CLS)","Identifies 5-6s as well above acceptable","Investigates specific speed factors","Recommends specific diagnostic tools","Confirms page speed impacts SEO rankings","Provides prioritized speed fixes","Addresses mobile-specific performance"],"files":[]},{"id":8,"prompt":"I want to add FAQ schema to my product pages. Can you help me set that up?","expected_output":"Should recognize this is a schema markup implementation task, not an SEO audit. Should defer to or cross-reference the schema skill, which specifically handles structured data implementation including FAQ schema. May briefly mention that FAQ schema can enable rich results, but should make clear that schema is the right skill for implementation.","assertions":["Recognizes this as schema markup implementation","References or defers to schema skill","Does not attempt a full SEO audit","May briefly mention FAQ schema benefits"],"files":[]}]},"isInternal":false,"tokens":2013,"sizeBytes":9796},{"name":"ai-writing-detection.md","path":".agents/skills/seo-audit/references/ai-writing-detection.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/seo-audit/references/ai-writing-detection.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fseo-audit%2Freferences%2Fai-writing-detection.md -->","isInternal":false,"tokens":1533,"sizeBytes":6528},{"name":"international-seo.md","path":".agents/skills/seo-audit/references/international-seo.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/seo-audit/references/international-seo.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fseo-audit%2Freferences%2Finternational-seo.md -->","isInternal":false,"tokens":3268,"sizeBytes":14258},{"name":"SKILL.md","path":".agents/skills/seo-audit/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/seo-audit/SKILL.md","title":"seo-audit","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fseo-audit%2FSKILL.md -->","frontmatter":{"name":"seo-audit","description":"When the user wants to audit, review, or diagnose SEO issues on their site. Also use when the user mentions \"SEO audit,\" \"technical SEO,\" \"why am I not ranking,\" \"SEO issues,\" \"on-page SEO,\" \"meta tags review,\" \"SEO health check,\" \"my traffic dropped,\" \"lost rankings,\" \"not showing up in Google,\" \"site isn't ranking,\" \"Google update hit me,\" \"page speed,\" \"core web vitals,\" \"crawl errors,\" or \"indexing issues.\" Use this even if the user just says something vague like \"my SEO is bad\" or \"help with SEO\" — start with an audit. For building pages at scale to target keywords, see programmatic-seo. For adding structured data, see schema. For AI search optimization, see ai-seo.","metadata":{"version":"2.0.0"}},"isInternal":false,"tokens":3768,"sizeBytes":16450},{"name":"cli.md","path":".agents/skills/shadcn/cli.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/shadcn/cli.md","title":"Shadcn Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fcli.md -->","isInternal":false,"tokens":3862,"sizeBytes":17304},{"name":"customization.md","path":".agents/skills/shadcn/customization.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/shadcn/customization.md","title":"Shadcn Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fcustomization.md -->","isInternal":false,"tokens":1487,"sizeBytes":6074},{"name":"evals.json","path":".agents/skills/shadcn/evals/evals.json","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/shadcn/evals/evals.json","title":"Evals Skill","category":"anthropic-skill","format":"json","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fevals%2Fevals.json -->","frontmatter":{"skill_name":"shadcn","evals":[{"id":1,"prompt":"I'm building a Next.js app with shadcn/ui (base-nova preset, lucide icons). Create a settings form component with fields for: full name, email address, and notification preferences (email, SMS, push notifications as toggle options). Add validation states for required fields.","expected_output":"A React component using FieldGroup, Field, ToggleGroup, data-invalid/aria-invalid validation, gap-* spacing, and semantic colors.","files":[],"expectations":["Uses FieldGroup and Field components for form layout instead of raw div with space-y","Uses Switch for independent on/off notification toggles (not looping Button with manual active state)","Uses data-invalid on Field and aria-invalid on the input control for validation states","Uses gap-* (e.g. gap-4, gap-6) instead of space-y-* or space-x-* for spacing","Uses semantic color tokens (e.g. bg-background, text-muted-foreground, text-destructive) instead of raw colors like bg-red-500","No manual dark: color overrides"]},{"id":2,"prompt":"Create a dialog component for editing a user profile. It should have the user's avatar at the top, input fields for name and bio, and Save/Cancel buttons with appropriate icons. Using shadcn/ui with radix-nova preset and tabler icons.","expected_output":"A React component with DialogTitle, Avatar+AvatarFallback, data-icon on icon buttons, no icon sizing classes, tabler icon imports.","files":[],"expectations":["Includes DialogTitle for accessibility (visible or with sr-only class)","Avatar component includes AvatarFallback","Icons on buttons use the data-icon attribute (data-icon=\"inline-start\" or data-icon=\"inline-end\")","No sizing classes on icons inside components (no size-4, w-4, h-4, etc.)","Uses tabler icons (@tabler/icons-react) instead of lucide-react","Uses asChild for custom triggers (radix preset)"]},{"id":3,"prompt":"Create a dashboard component that shows 4 stat cards in a grid. Each card has a title, large number, percentage change badge, and a loading skeleton state. Using shadcn/ui with base-nova preset and lucide icons.","expected_output":"A React component with full Card composition, Skeleton for loading, Badge for changes, semantic colors, gap-* spacing.","files":[],"expectations":["Uses full Card composition with CardHeader, CardTitle, CardContent (not dumping everything into CardContent)","Uses Skeleton component for loading placeholders instead of custom animate-pulse divs","Uses Badge component for percentage change instead of custom styled spans","Uses semantic color tokens instead of raw color values like bg-green-500 or text-red-600","Uses gap-* instead of space-y-* or space-x-* for spacing","Uses size-* when width and height are equal instead of separate w-* h-*"]},{"id":4,"prompt":"I'm building a Next.js app with shadcn/ui (base-nova preset, lucide icons). Build a chat conversation view: a scrollable thread of messages from two different people, each with an avatar, sender name, timestamp, and message bubble. A couple of messages include an image attachment and a PDF file attachment, and there's a 'Today' divider separating the days.","expected_output":"A React component composing MessageScroller, Message, Bubble, Attachment, and Marker from the registry instead of hand-rolled bubble/divider/attachment markup.","files":[],"expectations":["Uses MessageScroller (MessageScrollerProvider, MessageScrollerViewport, MessageScrollerContent, MessageScrollerItem) for the scrollable thread instead of a raw overflow-y-auto div or ScrollArea","Wraps each row in MessageScrollerItem inside MessageScrollerContent","Uses Message with MessageAvatar/MessageContent/MessageHeader for row layout instead of custom flex divs","Uses Bubble + BubbleContent for the message surface instead of a styled div with bg-muted/bg-primary","Uses Attachment (AttachmentMedia, AttachmentContent, AttachmentTitle, AttachmentDescription) for the file and image attachments instead of Item or a custom card","Uses Marker (variant=\"separator\") for the 'Today' divider instead of Separator plus a centered label","Uses semantic color tokens and gap-* spacing; no raw colors like bg-emerald-500 and no space-y-*","Includes \"use client\" when the component uses state or event handlers (isRSC)"]},{"id":5,"prompt":"Using shadcn/ui (base-nova preset, lucide icons), build a streaming AI chat UI. The assistant's reply streams in while it generates, the view auto-scrolls to follow the latest content but stops following if the user scrolls up to read earlier messages, a 'jump to latest' button appears when the user has scrolled away from the bottom, and a subtle 'thinking…' shimmer shows while the model is generating.","expected_output":"A React component that delegates scroll/anchor behavior to MessageScroller and uses MessageScrollerButton for jump-to-latest and the shimmer utility for the thinking indicator — no hand-rolled scroll logic or custom shimmer keyframes.","files":[],"expectations":["Uses MessageScroller with MessageScrollerProvider (autoScroll) and scrollAnchor on message items for the stick-to-bottom/follow behavior instead of a custom useStickToBottom hook or ResizeObserver/scrollTop wiring","Uses MessageScrollerButton for the jump-to-latest control instead of a hand-built conditional button driven by manual scroll-position state","Uses the shimmer utility class for the 'thinking…' indicator instead of a custom @keyframes or bg-clip-text gradient animation","Wraps each message row in MessageScrollerItem inside MessageScrollerContent","Uses Message + Bubble + BubbleContent for the conversation rows instead of hand-rolled bubble divs","Uses semantic color tokens and gap-* spacing; includes \"use client\" (isRSC)"]}]},"isInternal":false,"tokens":1452,"sizeBytes":6089},{"name":"mcp.md","path":".agents/skills/shadcn/mcp.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/shadcn/mcp.md","title":"Shadcn Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fmcp.md -->","isInternal":false,"tokens":886,"sizeBytes":3510},{"name":"registry.md","path":".agents/skills/shadcn/registry.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/shadcn/registry.md","title":"Shadcn Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Fregistry.md -->","isInternal":false,"tokens":2134,"sizeBytes":8817},{"name":"base-vs-radix.md","path":".agents/skills/shadcn/rules/base-vs-radix.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/shadcn/rules/base-vs-radix.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fbase-vs-radix.md -->","isInternal":false,"tokens":1824,"sizeBytes":6954},{"name":"chat.md","path":".agents/skills/shadcn/rules/chat.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/shadcn/rules/chat.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fchat.md -->","isInternal":false,"tokens":1723,"sizeBytes":6948},{"name":"composition.md","path":".agents/skills/shadcn/rules/composition.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/shadcn/rules/composition.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fcomposition.md -->","isInternal":false,"tokens":1213,"sizeBytes":4892},{"name":"forms.md","path":".agents/skills/shadcn/rules/forms.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/shadcn/rules/forms.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fforms.md -->","isInternal":false,"tokens":1203,"sizeBytes":4857},{"name":"icons.md","path":".agents/skills/shadcn/rules/icons.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/shadcn/rules/icons.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Ficons.md -->","isInternal":false,"tokens":522,"sizeBytes":1958},{"name":"styling.md","path":".agents/skills/shadcn/rules/styling.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/shadcn/rules/styling.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2Frules%2Fstyling.md -->","isInternal":false,"tokens":1188,"sizeBytes":4684},{"name":"SKILL.md","path":".agents/skills/shadcn/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/shadcn/SKILL.md","title":"shadcn","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fshadcn%2FSKILL.md -->","frontmatter":{"name":"shadcn","description":"Manages shadcn components and projects — adding, searching, fixing, debugging, styling, and composing UI, including chat interfaces. Provides project context, component docs, and usage examples. Applies when working with shadcn/ui, component registries, presets, --preset codes, or any project with a components.json file. Also triggers for \"shadcn init\", \"create an app with --preset\", or \"switch to --preset\".","user-invocable":false,"allowed-tools":"Bash(npx shadcn@latest *), Bash(pnpm dlx shadcn@latest *), Bash(bunx --bun shadcn@latest *)","allowedTools":["Bash(npx","shadcn@latest","*),","Bash(pnpm","dlx","shadcn@latest","*),","Bash(bunx","--bun","shadcn@latest","*)"]},"allowedTools":["Bash(npx","shadcn@latest","*),","Bash(pnpm","dlx","shadcn@latest","*),","Bash(bunx","--bun","shadcn@latest","*)"],"isInternal":false,"tokens":4867,"sizeBytes":19527},{"name":"schemas.md","path":".agents/skills/skill-creator/references/schemas.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/skill-creator/references/schemas.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2Freferences%2Fschemas.md -->","isInternal":false,"tokens":3373,"sizeBytes":12061},{"name":"SKILL.md","path":".agents/skills/skill-creator/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/skill-creator/SKILL.md","title":"skill-creator","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2FSKILL.md -->","frontmatter":{"name":"skill-creator","description":"Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, edit, or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy."},"isInternal":false,"tokens":7322,"sizeBytes":33168},{"name":"turborepo.md","path":".agents/skills/turborepo/command/turborepo.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/command/turborepo.md","title":"Command Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Fcommand%2Fturborepo.md -->","frontmatter":{"description":"Load Turborepo skill for creating workflows, tasks, and pipelines in monorepos. Use when users ask to \"create a workflow\", \"make a task\", \"generate a pipeline\", or set up build orchestration."},"isInternal":false,"tokens":658,"sizeBytes":2785},{"name":"dependencies.md","path":".agents/skills/turborepo/references/best-practices/dependencies.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/best-practices/dependencies.md","title":"Best-practices Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fbest-practices%2Fdependencies.md -->","isInternal":false,"tokens":1186,"sizeBytes":4255},{"name":"packages.md","path":".agents/skills/turborepo/references/best-practices/packages.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/best-practices/packages.md","title":"Best-practices Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fbest-practices%2Fpackages.md -->","isInternal":false,"tokens":1662,"sizeBytes":6289},{"name":"RULE.md","path":".agents/skills/turborepo/references/best-practices/RULE.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/best-practices/RULE.md","title":"Best-practices Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fbest-practices%2FRULE.md -->","isInternal":false,"tokens":1268,"sizeBytes":4907},{"name":"structure.md","path":".agents/skills/turborepo/references/best-practices/structure.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/best-practices/structure.md","title":"Best-practices Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fbest-practices%2Fstructure.md -->","isInternal":false,"tokens":1534,"sizeBytes":5547},{"name":"RULE.md","path":".agents/skills/turborepo/references/boundaries/RULE.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/boundaries/RULE.md","title":"Boundaries Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fboundaries%2FRULE.md -->","isInternal":false,"tokens":494,"sizeBytes":1948},{"name":"gotchas.md","path":".agents/skills/turborepo/references/caching/gotchas.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/caching/gotchas.md","title":"Caching Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcaching%2Fgotchas.md -->","isInternal":false,"tokens":988,"sizeBytes":3935},{"name":"remote-cache.md","path":".agents/skills/turborepo/references/caching/remote-cache.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/caching/remote-cache.md","title":"Caching Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcaching%2Fremote-cache.md -->","isInternal":false,"tokens":635,"sizeBytes":2538},{"name":"RULE.md","path":".agents/skills/turborepo/references/caching/RULE.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/caching/RULE.md","title":"Caching Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcaching%2FRULE.md -->","isInternal":false,"tokens":1055,"sizeBytes":4199},{"name":"github-actions.md","path":".agents/skills/turborepo/references/ci/github-actions.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/ci/github-actions.md","title":"Ci Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fci%2Fgithub-actions.md -->","isInternal":false,"tokens":800,"sizeBytes":2813},{"name":"patterns.md","path":".agents/skills/turborepo/references/ci/patterns.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/ci/patterns.md","title":"Ci Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fci%2Fpatterns.md -->","isInternal":false,"tokens":700,"sizeBytes":2583},{"name":"RULE.md","path":".agents/skills/turborepo/references/ci/RULE.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/ci/RULE.md","title":"Ci Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fci%2FRULE.md -->","isInternal":false,"tokens":532,"sizeBytes":2189},{"name":"vercel.md","path":".agents/skills/turborepo/references/ci/vercel.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/ci/vercel.md","title":"Ci Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fci%2Fvercel.md -->","isInternal":false,"tokens":528,"sizeBytes":2143},{"name":"commands.md","path":".agents/skills/turborepo/references/cli/commands.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/cli/commands.md","title":"Cli Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcli%2Fcommands.md -->","isInternal":false,"tokens":1431,"sizeBytes":5568},{"name":"RULE.md","path":".agents/skills/turborepo/references/cli/RULE.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/cli/RULE.md","title":"Cli Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fcli%2FRULE.md -->","isInternal":false,"tokens":554,"sizeBytes":2113},{"name":"global-options.md","path":".agents/skills/turborepo/references/configuration/global-options.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/configuration/global-options.md","title":"Configuration Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fconfiguration%2Fglobal-options.md -->","isInternal":false,"tokens":1570,"sizeBytes":7158},{"name":"gotchas.md","path":".agents/skills/turborepo/references/configuration/gotchas.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/configuration/gotchas.md","title":"Configuration Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fconfiguration%2Fgotchas.md -->","isInternal":false,"tokens":2460,"sizeBytes":9318},{"name":"RULE.md","path":".agents/skills/turborepo/references/configuration/RULE.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/configuration/RULE.md","title":"Configuration Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fconfiguration%2FRULE.md -->","isInternal":false,"tokens":1409,"sizeBytes":5176},{"name":"tasks.md","path":".agents/skills/turborepo/references/configuration/tasks.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/configuration/tasks.md","title":"Configuration Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fconfiguration%2Ftasks.md -->","isInternal":false,"tokens":1714,"sizeBytes":6945},{"name":"gotchas.md","path":".agents/skills/turborepo/references/environment/gotchas.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/environment/gotchas.md","title":"Environment Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fenvironment%2Fgotchas.md -->","isInternal":false,"tokens":1090,"sizeBytes":4153},{"name":"modes.md","path":".agents/skills/turborepo/references/environment/modes.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/environment/modes.md","title":"Environment Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fenvironment%2Fmodes.md -->","isInternal":false,"tokens":582,"sizeBytes":2419},{"name":"RULE.md","path":".agents/skills/turborepo/references/environment/RULE.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/environment/RULE.md","title":"Environment Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fenvironment%2FRULE.md -->","isInternal":false,"tokens":685,"sizeBytes":2593},{"name":"patterns.md","path":".agents/skills/turborepo/references/filtering/patterns.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/filtering/patterns.md","title":"Filtering Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Ffiltering%2Fpatterns.md -->","isInternal":false,"tokens":622,"sizeBytes":2412},{"name":"RULE.md","path":".agents/skills/turborepo/references/filtering/RULE.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/filtering/RULE.md","title":"Filtering Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Ffiltering%2FRULE.md -->","isInternal":false,"tokens":962,"sizeBytes":4160},{"name":"RULE.md","path":".agents/skills/turborepo/references/watch/RULE.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/references/watch/RULE.md","title":"Watch Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2Freferences%2Fwatch%2FRULE.md -->","isInternal":false,"tokens":479,"sizeBytes":1989},{"name":"SKILL.md","path":".agents/skills/turborepo/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/turborepo/SKILL.md","title":"turborepo","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fturborepo%2FSKILL.md -->","frontmatter":{"name":"turborepo","description":"Turborepo monorepo build system guidance. Triggers on: turbo.json, task pipelines,\ndependsOn, caching, remote cache, the \"turbo\" CLI, --filter, --affected, CI optimization, environment\nvariables, internal packages, monorepo structure/best practices, and boundaries.\n\nUse when user: configures tasks/workflows/pipelines, creates packages, sets up\nmonorepo, shares code between apps, runs changed/affected packages, debugs cache,\nor has apps/packages directories.\n","metadata":{"version":"2.10.8-canary.4"}},"isInternal":false,"tokens":6843,"sizeBytes":28471},{"name":"details.md","path":".agents/skills/typescript-advanced-types/references/details.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/typescript-advanced-types/references/details.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Ftypescript-advanced-types%2Freferences%2Fdetails.md -->","isInternal":false,"tokens":2428,"sizeBytes":9027},{"name":"SKILL.md","path":".agents/skills/typescript-advanced-types/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/typescript-advanced-types/SKILL.md","title":"typescript-advanced-types","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Ftypescript-advanced-types%2FSKILL.md -->","frontmatter":{"name":"typescript-advanced-types","description":"Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript projects."},"isInternal":false,"tokens":2022,"sizeBytes":8035},{"name":"SKILL.md","path":".agents/skills/ux-flow-plan/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/ux-flow-plan/SKILL.md","title":"ux-flow-plan","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fux-flow-plan%2FSKILL.md -->","frontmatter":{"name":"ux-flow-plan","description":"Create UX-first plans as flow trees, then attach concrete function names, files, and implementation anchors after the high-level flow is clear.","user-invocable":true},"isInternal":false,"tokens":404,"sizeBytes":1896},{"name":"AGENTS.md","path":".agents/skills/vercel-composition-patterns/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/AGENTS.md","title":"Vercel-composition-patterns Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2FAGENTS.md -->","isInternal":false,"tokens":5063,"sizeBytes":22627},{"name":"metadata.json","path":".agents/skills/vercel-composition-patterns/metadata.json","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/metadata.json","title":"Vercel-composition-patterns Skill","category":"anthropic-skill","format":"json","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Fmetadata.json -->","frontmatter":{"version":"1.0.0","organization":"Engineering","date":"January 2026","abstract":"Composition patterns for building flexible, maintainable React components. Avoid boolean prop proliferation by using compound components, lifting state, and composing internals. These patterns make codebases easier for both humans and AI agents to work with as they scale.","references":["https://react.dev","https://react.dev/learn/passing-data-deeply-with-context","https://react.dev/reference/react/use"]},"isInternal":false,"tokens":122,"sizeBytes":518},{"name":"README.md","path":".agents/skills/vercel-composition-patterns/README.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/README.md","title":"Vercel-composition-patterns Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2FREADME.md -->","isInternal":false,"tokens":476,"sizeBytes":2140},{"name":"_sections.md","path":".agents/skills/vercel-composition-patterns/rules/_sections.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/rules/_sections.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2F_sections.md -->","isInternal":false,"tokens":176,"sizeBytes":829},{"name":"_template.md","path":".agents/skills/vercel-composition-patterns/rules/_template.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/rules/_template.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2F_template.md -->","frontmatter":{"title":"Rule Title Here","impact":"MEDIUM","impactDescription":"brief description of impact","tags":"composition, components"},"isInternal":false,"tokens":80,"sizeBytes":329},{"name":"architecture-avoid-boolean-props.md","path":".agents/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Farchitecture-avoid-boolean-props.md -->","frontmatter":{"title":"Avoid Boolean Prop Proliferation","impact":"CRITICAL","impactDescription":"prevents unmaintainable component variants","tags":"composition, props, architecture"},"isInternal":false,"tokens":513,"sizeBytes":2267},{"name":"architecture-compound-components.md","path":".agents/skills/vercel-composition-patterns/rules/architecture-compound-components.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/rules/architecture-compound-components.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Farchitecture-compound-components.md -->","frontmatter":{"title":"Use Compound Components","impact":"HIGH","impactDescription":"enables flexible composition without prop drilling","tags":"composition, compound-components, architecture"},"isInternal":false,"tokens":578,"sizeBytes":2600},{"name":"patterns-children-over-render-props.md","path":".agents/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fpatterns-children-over-render-props.md -->","frontmatter":{"title":"Prefer Composing Children Over Render Props","impact":"MEDIUM","impactDescription":"cleaner composition, better readability","tags":"composition, children, render-props"},"isInternal":false,"tokens":428,"sizeBytes":1886},{"name":"patterns-explicit-variants.md","path":".agents/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fpatterns-explicit-variants.md -->","frontmatter":{"title":"Create Explicit Component Variants","impact":"MEDIUM","impactDescription":"self-documenting code, no hidden conditionals","tags":"composition, variants, architecture"},"isInternal":false,"tokens":503,"sizeBytes":2395},{"name":"react19-no-forwardref.md","path":".agents/skills/vercel-composition-patterns/rules/react19-no-forwardref.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/rules/react19-no-forwardref.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Freact19-no-forwardref.md -->","frontmatter":{"title":"React 19 API Changes","impact":"MEDIUM","impactDescription":"cleaner component definitions and context usage","tags":"react19, refs, context, hooks"},"isInternal":false,"tokens":255,"sizeBytes":953},{"name":"state-context-interface.md","path":".agents/skills/vercel-composition-patterns/rules/state-context-interface.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/rules/state-context-interface.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fstate-context-interface.md -->","frontmatter":{"title":"Define Generic Context Interfaces for Dependency Injection","impact":"HIGH","impactDescription":"enables dependency-injectable state across use-cases","tags":"composition, context, state, typescript, dependency-injection"},"isInternal":false,"tokens":1076,"sizeBytes":4974},{"name":"state-decouple-implementation.md","path":".agents/skills/vercel-composition-patterns/rules/state-decouple-implementation.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/rules/state-decouple-implementation.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fstate-decouple-implementation.md -->","frontmatter":{"title":"Decouple State Management from UI","impact":"MEDIUM","impactDescription":"enables swapping state implementations without changing UI","tags":"composition, state, architecture"},"isInternal":false,"tokens":579,"sizeBytes":2699},{"name":"state-lift-state.md","path":".agents/skills/vercel-composition-patterns/rules/state-lift-state.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/rules/state-lift-state.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2Frules%2Fstate-lift-state.md -->","frontmatter":{"title":"Lift State into Provider Components","impact":"HIGH","impactDescription":"enables state sharing outside component boundaries","tags":"composition, state, context, providers"},"isInternal":false,"tokens":686,"sizeBytes":3224},{"name":"SKILL.md","path":".agents/skills/vercel-composition-patterns/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-composition-patterns/SKILL.md","title":"vercel-composition-patterns","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-composition-patterns%2FSKILL.md -->","frontmatter":{"name":"vercel-composition-patterns","description":"React composition patterns that scale. Use when refactoring components with boolean prop proliferation, building flexible component libraries, or designing reusable APIs. Triggers on tasks involving compound components, render props, context providers, or component architecture. Includes React 19 API changes.","license":"MIT","metadata":{"author":"vercel","version":"1.0.0"}},"isInternal":false,"tokens":630,"sizeBytes":2886},{"name":"AGENTS.md","path":".agents/skills/vercel-react-best-practices/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/AGENTS.md","title":"Vercel-react-best-practices Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2FAGENTS.md -->","isInternal":false,"tokens":12013,"sizeBytes":50062},{"name":"metadata.json","path":".agents/skills/vercel-react-best-practices/metadata.json","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/metadata.json","title":"Vercel-react-best-practices Skill","category":"anthropic-skill","format":"json","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Fmetadata.json -->","frontmatter":{"version":"1.0.0","organization":"Vercel Engineering","date":"January 2026","abstract":"Comprehensive performance optimization guide for React and Next.js applications, designed for AI agents and LLMs. Contains 40+ rules across 8 categories, prioritized by impact from critical (eliminating waterfalls, reducing bundle size) to incremental (advanced patterns). Each rule includes detailed explanations, real-world examples comparing incorrect vs. correct implementations, and specific impact metrics to guide automated refactoring and code generation.","references":["https://react.dev","https://nextjs.org","https://swr.vercel.app","https://github.com/shuding/better-all","https://github.com/isaacs/node-lru-cache","https://vercel.com/blog/how-we-optimized-package-imports-in-next-js","https://vercel.com/blog/how-we-made-the-vercel-dashboard-twice-as-fast"]},"isInternal":false,"tokens":217,"sizeBytes":901},{"name":"README.md","path":".agents/skills/vercel-react-best-practices/README.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/README.md","title":"Vercel-react-best-practices Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2FREADME.md -->","isInternal":false,"tokens":848,"sizeBytes":3360},{"name":"_sections.md","path":".agents/skills/vercel-react-best-practices/rules/_sections.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/_sections.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2F_sections.md -->","isInternal":false,"tokens":318,"sizeBytes":1554},{"name":"_template.md","path":".agents/skills/vercel-react-best-practices/rules/_template.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/_template.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2F_template.md -->","frontmatter":{"title":"Rule Title Here","impact":"MEDIUM","impactDescription":"Optional description of impact (e.g., \"20-50% improvement\")","tags":"tag1, tag2"},"isInternal":false,"tokens":143,"sizeBytes":631},{"name":"advanced-effect-event-deps.md","path":".agents/skills/vercel-react-best-practices/rules/advanced-effect-event-deps.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/advanced-effect-event-deps.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fadvanced-effect-event-deps.md -->","frontmatter":{"title":"Do Not Put Effect Events in Dependency Arrays","impact":"LOW","impactDescription":"avoids unnecessary effect re-runs and lint errors","tags":"advanced, hooks, useEffectEvent, dependencies, effects"},"isInternal":false,"tokens":375,"sizeBytes":1802},{"name":"advanced-event-handler-refs.md","path":".agents/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fadvanced-event-handler-refs.md -->","frontmatter":{"title":"Store Event Handlers in Refs","impact":"LOW","impactDescription":"stable subscriptions","tags":"advanced, hooks, refs, event-handlers, optimization"},"isInternal":false,"tokens":337,"sizeBytes":1483},{"name":"advanced-init-once.md","path":".agents/skills/vercel-react-best-practices/rules/advanced-init-once.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/advanced-init-once.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fadvanced-init-once.md -->","frontmatter":{"title":"Initialize App Once, Not Per Mount","impact":"LOW-MEDIUM","impactDescription":"avoids duplicate init in development","tags":"initialization, useEffect, app-startup, side-effects"},"isInternal":false,"tokens":230,"sizeBytes":958},{"name":"advanced-use-latest.md","path":".agents/skills/vercel-react-best-practices/rules/advanced-use-latest.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/advanced-use-latest.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fadvanced-use-latest.md -->","frontmatter":{"title":"useEffectEvent for Stable Callback Refs","impact":"LOW","impactDescription":"prevents effect re-runs","tags":"advanced, hooks, useEffectEvent, refs, optimization"},"isInternal":false,"tokens":254,"sizeBytes":1072},{"name":"async-api-routes.md","path":".agents/skills/vercel-react-best-practices/rules/async-api-routes.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/async-api-routes.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-api-routes.md -->","frontmatter":{"title":"Prevent Waterfall Chains in API Routes","impact":"CRITICAL","impactDescription":"2-10× improvement","tags":"api-routes, server-actions, waterfalls, parallelization"},"isInternal":false,"tokens":241,"sizeBytes":1125},{"name":"async-cheap-condition-before-await.md","path":".agents/skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-cheap-condition-before-await.md -->","frontmatter":{"title":"Check Cheap Conditions Before Async Flags","impact":"HIGH","impactDescription":"avoids unnecessary async work when a synchronous guard already fails","tags":"async, await, feature-flags, short-circuit, conditional"},"isInternal":false,"tokens":277,"sizeBytes":1220},{"name":"async-defer-await.md","path":".agents/skills/vercel-react-best-practices/rules/async-defer-await.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/async-defer-await.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-defer-await.md -->","frontmatter":{"title":"Defer Await Until Needed","impact":"HIGH","impactDescription":"avoids blocking unused code paths","tags":"async, await, conditional, optimization"},"isInternal":false,"tokens":474,"sizeBytes":2208},{"name":"async-dependencies.md","path":".agents/skills/vercel-react-best-practices/rules/async-dependencies.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/async-dependencies.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-dependencies.md -->","frontmatter":{"title":"Dependency-Based Parallelization","impact":"CRITICAL","impactDescription":"2-10× improvement","tags":"async, parallelization, dependencies, better-all"},"isInternal":false,"tokens":291,"sizeBytes":1293},{"name":"async-parallel.md","path":".agents/skills/vercel-react-best-practices/rules/async-parallel.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/async-parallel.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-parallel.md -->","frontmatter":{"title":"Promise.all() for Independent Operations","impact":"CRITICAL","impactDescription":"2-10× improvement","tags":"async, parallelization, promises, waterfalls"},"isInternal":false,"tokens":144,"sizeBytes":654},{"name":"async-suspense-boundaries.md","path":".agents/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fasync-suspense-boundaries.md -->","frontmatter":{"title":"Strategic Suspense Boundaries","impact":"HIGH","impactDescription":"faster initial paint","tags":"async, suspense, streaming, layout-shift"},"isInternal":false,"tokens":591,"sizeBytes":2510},{"name":"bundle-analyzable-paths.md","path":".agents/skills/vercel-react-best-practices/rules/bundle-analyzable-paths.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/bundle-analyzable-paths.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-analyzable-paths.md -->","frontmatter":{"title":"Prefer Statically Analyzable Paths","impact":"HIGH","impactDescription":"avoids accidental broad bundles and file traces","tags":"bundle, nextjs, vite, webpack, rollup, esbuild, path"},"isInternal":false,"tokens":557,"sizeBytes":2382},{"name":"bundle-barrel-imports.md","path":".agents/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-barrel-imports.md -->","frontmatter":{"title":"Avoid Barrel File Imports","impact":"CRITICAL","impactDescription":"200-800ms import cost, slow builds","tags":"bundle, imports, tree-shaking, barrel-files, performance"},"isInternal":false,"tokens":672,"sizeBytes":2795},{"name":"bundle-conditional.md","path":".agents/skills/vercel-react-best-practices/rules/bundle-conditional.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/bundle-conditional.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-conditional.md -->","frontmatter":{"title":"Conditional Module Loading","impact":"HIGH","impactDescription":"loads large data only when needed","tags":"bundle, conditional-loading, lazy-loading"},"isInternal":false,"tokens":213,"sizeBytes":949},{"name":"bundle-defer-third-party.md","path":".agents/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-defer-third-party.md -->","frontmatter":{"title":"Defer Non-Critical Third-Party Libraries","impact":"MEDIUM","impactDescription":"loads after hydration","tags":"bundle, third-party, analytics, defer"},"isInternal":false,"tokens":221,"sizeBytes":920},{"name":"bundle-dynamic-imports.md","path":".agents/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-dynamic-imports.md -->","frontmatter":{"title":"Dynamic Imports for Heavy Components","impact":"CRITICAL","impactDescription":"directly affects TTI and LCP","tags":"bundle, dynamic-import, code-splitting, next-dynamic"},"isInternal":false,"tokens":197,"sizeBytes":791},{"name":"bundle-preload.md","path":".agents/skills/vercel-react-best-practices/rules/bundle-preload.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/bundle-preload.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fbundle-preload.md -->","frontmatter":{"title":"Preload Based on User Intent","impact":"MEDIUM","impactDescription":"reduces perceived latency","tags":"bundle, preload, user-intent, hover"},"isInternal":false,"tokens":267,"sizeBytes":1149},{"name":"client-event-listeners.md","path":".agents/skills/vercel-react-best-practices/rules/client-event-listeners.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/client-event-listeners.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fclient-event-listeners.md -->","frontmatter":{"title":"Deduplicate Global Event Listeners","impact":"LOW","impactDescription":"single listener for N components","tags":"client, swr, event-listeners, subscription"},"isInternal":false,"tokens":466,"sizeBytes":1969},{"name":"client-localstorage-schema.md","path":".agents/skills/vercel-react-best-practices/rules/client-localstorage-schema.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/client-localstorage-schema.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fclient-localstorage-schema.md -->","frontmatter":{"title":"Version and Minimize localStorage Data","impact":"MEDIUM","impactDescription":"prevents schema conflicts, reduces storage size","tags":"client, localStorage, storage, versioning, data-minimization"},"isInternal":false,"tokens":437,"sizeBytes":1950},{"name":"client-passive-event-listeners.md","path":".agents/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fclient-passive-event-listeners.md -->","frontmatter":{"title":"Use Passive Event Listeners for Scrolling Performance","impact":"MEDIUM","impactDescription":"eliminates scroll delay caused by event listeners","tags":"client, event-listeners, scrolling, performance, touch, wheel"},"isInternal":false,"tokens":361,"sizeBytes":1644},{"name":"client-swr-dedup.md","path":".agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fclient-swr-dedup.md -->","frontmatter":{"title":"Use SWR for Automatic Deduplication","impact":"MEDIUM-HIGH","impactDescription":"automatic deduplication","tags":"client, swr, deduplication, data-fetching"},"isInternal":false,"tokens":308,"sizeBytes":1159},{"name":"js-batch-dom-css.md","path":".agents/skills/vercel-react-best-practices/rules/js-batch-dom-css.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-batch-dom-css.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-batch-dom-css.md -->","frontmatter":{"title":"Avoid Layout Thrashing","impact":"MEDIUM","impactDescription":"prevents forced synchronous layouts and reduces performance bottlenecks","tags":"javascript, dom, css, performance, reflow, layout-thrashing"},"isInternal":false,"tokens":757,"sizeBytes":3266},{"name":"js-cache-function-results.md","path":".agents/skills/vercel-react-best-practices/rules/js-cache-function-results.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-cache-function-results.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-cache-function-results.md -->","frontmatter":{"title":"Cache Repeated Function Calls","impact":"MEDIUM","impactDescription":"avoid redundant computation","tags":"javascript, cache, memoization, performance"},"isInternal":false,"tokens":448,"sizeBytes":1949},{"name":"js-cache-property-access.md","path":".agents/skills/vercel-react-best-practices/rules/js-cache-property-access.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-cache-property-access.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-cache-property-access.md -->","frontmatter":{"title":"Cache Property Access in Loops","impact":"LOW-MEDIUM","impactDescription":"reduces lookups","tags":"javascript, loops, optimization, caching"},"isInternal":false,"tokens":138,"sizeBytes":532},{"name":"js-cache-storage.md","path":".agents/skills/vercel-react-best-practices/rules/js-cache-storage.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-cache-storage.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-cache-storage.md -->","frontmatter":{"title":"Cache Storage API Calls","impact":"LOW-MEDIUM","impactDescription":"reduces expensive I/O","tags":"javascript, localStorage, storage, caching, performance"},"isInternal":false,"tokens":377,"sizeBytes":1651},{"name":"js-combine-iterations.md","path":".agents/skills/vercel-react-best-practices/rules/js-combine-iterations.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-combine-iterations.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-combine-iterations.md -->","frontmatter":{"title":"Combine Multiple Array Iterations","impact":"LOW-MEDIUM","impactDescription":"reduces iterations","tags":"javascript, arrays, loops, performance"},"isInternal":false,"tokens":176,"sizeBytes":753},{"name":"js-early-exit.md","path":".agents/skills/vercel-react-best-practices/rules/js-early-exit.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-early-exit.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-early-exit.md -->","frontmatter":{"title":"Early Return from Functions","impact":"LOW-MEDIUM","impactDescription":"avoids unnecessary computation","tags":"javascript, functions, optimization, early-return"},"isInternal":false,"tokens":266,"sizeBytes":1133},{"name":"js-flatmap-filter.md","path":".agents/skills/vercel-react-best-practices/rules/js-flatmap-filter.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-flatmap-filter.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-flatmap-filter.md -->","frontmatter":{"title":"Use flatMap to Map and Filter in One Pass","impact":"LOW-MEDIUM","impactDescription":"eliminates intermediate array","tags":"javascript, arrays, flatMap, filter, performance"},"isInternal":false,"tokens":342,"sizeBytes":1411},{"name":"js-hoist-regexp.md","path":".agents/skills/vercel-react-best-practices/rules/js-hoist-regexp.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-hoist-regexp.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-hoist-regexp.md -->","frontmatter":{"title":"Hoist RegExp Creation","impact":"LOW-MEDIUM","impactDescription":"avoids recreation","tags":"javascript, regexp, optimization, memoization"},"isInternal":false,"tokens":283,"sizeBytes":1028},{"name":"js-index-maps.md","path":".agents/skills/vercel-react-best-practices/rules/js-index-maps.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-index-maps.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-index-maps.md -->","frontmatter":{"title":"Build Index Maps for Repeated Lookups","impact":"LOW-MEDIUM","impactDescription":"1M ops to 2K ops","tags":"javascript, map, indexing, optimization, performance"},"isInternal":false,"tokens":229,"sizeBytes":837},{"name":"js-length-check-first.md","path":".agents/skills/vercel-react-best-practices/rules/js-length-check-first.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-length-check-first.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-length-check-first.md -->","frontmatter":{"title":"Early Length Check for Array Comparisons","impact":"MEDIUM-HIGH","impactDescription":"avoids expensive operations when lengths differ","tags":"javascript, arrays, performance, optimization, comparison"},"isInternal":false,"tokens":373,"sizeBytes":1747},{"name":"js-min-max-loop.md","path":".agents/skills/vercel-react-best-practices/rules/js-min-max-loop.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-min-max-loop.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-min-max-loop.md -->","frontmatter":{"title":"Use Loop for Min/Max Instead of Sort","impact":"LOW","impactDescription":"O(n) instead of O(n log n)","tags":"javascript, arrays, performance, sorting, algorithms"},"isInternal":false,"tokens":602,"sizeBytes":2290},{"name":"js-request-idle-callback.md","path":".agents/skills/vercel-react-best-practices/rules/js-request-idle-callback.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-request-idle-callback.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-request-idle-callback.md -->","frontmatter":{"title":"Defer Non-Critical Work with requestIdleCallback","impact":"MEDIUM","impactDescription":"keeps UI responsive during background tasks","tags":"javascript, performance, idle, scheduling, analytics"},"isInternal":false,"tokens":597,"sizeBytes":2647},{"name":"js-set-map-lookups.md","path":".agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-set-map-lookups.md -->","frontmatter":{"title":"Use Set/Map for O(1) Lookups","impact":"LOW-MEDIUM","impactDescription":"O(n) to O(1)","tags":"javascript, set, map, data-structures, performance"},"isInternal":false,"tokens":154,"sizeBytes":532},{"name":"js-tosorted-immutable.md","path":".agents/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fjs-tosorted-immutable.md -->","frontmatter":{"title":"Use toSorted() Instead of sort() for Immutability","impact":"MEDIUM-HIGH","impactDescription":"prevents mutation bugs in React state","tags":"javascript, arrays, immutability, react, state, mutation"},"isInternal":false,"tokens":436,"sizeBytes":1782},{"name":"rendering-activity.md","path":".agents/skills/vercel-react-best-practices/rules/rendering-activity.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rendering-activity.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-activity.md -->","frontmatter":{"title":"Use Activity Component for Show/Hide","impact":"MEDIUM","impactDescription":"preserves state/DOM","tags":"rendering, activity, visibility, state-preservation"},"isInternal":false,"tokens":131,"sizeBytes":564},{"name":"rendering-animate-svg-wrapper.md","path":".agents/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-animate-svg-wrapper.md -->","frontmatter":{"title":"Animate SVG Wrapper Instead of SVG Element","impact":"LOW","impactDescription":"enables hardware acceleration","tags":"rendering, svg, css, animation, performance"},"isInternal":false,"tokens":291,"sizeBytes":1185},{"name":"rendering-conditional-render.md","path":".agents/skills/vercel-react-best-practices/rules/rendering-conditional-render.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rendering-conditional-render.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-conditional-render.md -->","frontmatter":{"title":"Use Explicit Conditional Rendering","impact":"LOW","impactDescription":"prevents rendering 0 or NaN","tags":"rendering, conditional, jsx, falsy-values"},"isInternal":false,"tokens":273,"sizeBytes":980},{"name":"rendering-content-visibility.md","path":".agents/skills/vercel-react-best-practices/rules/rendering-content-visibility.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rendering-content-visibility.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-content-visibility.md -->","frontmatter":{"title":"CSS content-visibility for Long Lists","impact":"HIGH","impactDescription":"faster initial render","tags":"rendering, css, content-visibility, long-lists"},"isInternal":false,"tokens":203,"sizeBytes":815},{"name":"rendering-hoist-jsx.md","path":".agents/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-hoist-jsx.md -->","frontmatter":{"title":"Hoist Static JSX Elements","impact":"LOW","impactDescription":"avoids re-creation","tags":"rendering, jsx, static, optimization"},"isInternal":false,"tokens":244,"sizeBytes":1039},{"name":"rendering-hydration-no-flicker.md","path":".agents/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-hydration-no-flicker.md -->","frontmatter":{"title":"Prevent Hydration Mismatch Without Flickering","impact":"MEDIUM","impactDescription":"avoids visual flicker and hydration errors","tags":"rendering, ssr, hydration, localStorage, flicker"},"isInternal":false,"tokens":490,"sizeBytes":2308},{"name":"rendering-hydration-suppress-warning.md","path":".agents/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-hydration-suppress-warning.md -->","frontmatter":{"title":"Suppress Expected Hydration Mismatches","impact":"LOW-MEDIUM","impactDescription":"avoids noisy hydration warnings for known differences","tags":"rendering, hydration, ssr, nextjs"},"isInternal":false,"tokens":197,"sizeBytes":872},{"name":"rendering-resource-hints.md","path":".agents/skills/vercel-react-best-practices/rules/rendering-resource-hints.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rendering-resource-hints.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-resource-hints.md -->","frontmatter":{"title":"Use React DOM Resource Hints","impact":"HIGH","impactDescription":"reduces load time for critical resources","tags":"rendering, preload, preconnect, prefetch, resource-hints"},"isInternal":false,"tokens":621,"sizeBytes":2549},{"name":"rendering-script-defer-async.md","path":".agents/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-script-defer-async.md -->","frontmatter":{"title":"Use defer or async on Script Tags","impact":"HIGH","impactDescription":"eliminates render-blocking","tags":"rendering, script, defer, async, performance"},"isInternal":false,"tokens":430,"sizeBytes":1868},{"name":"rendering-svg-precision.md","path":".agents/skills/vercel-react-best-practices/rules/rendering-svg-precision.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rendering-svg-precision.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-svg-precision.md -->","frontmatter":{"title":"Optimize SVG Precision","impact":"LOW","impactDescription":"reduces file size","tags":"rendering, svg, optimization, svgo"},"isInternal":false,"tokens":167,"sizeBytes":588},{"name":"rendering-usetransition-loading.md","path":".agents/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frendering-usetransition-loading.md -->","frontmatter":{"title":"Use useTransition Over Manual Loading States","impact":"LOW","impactDescription":"reduces re-renders and improves code clarity","tags":"rendering, transitions, useTransition, loading, state"},"isInternal":false,"tokens":457,"sizeBytes":2074},{"name":"rerender-defer-reads.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-defer-reads.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-defer-reads.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-defer-reads.md -->","frontmatter":{"title":"Defer State Reads to Usage Point","impact":"MEDIUM","impactDescription":"avoids unnecessary subscriptions","tags":"rerender, searchParams, localStorage, optimization"},"isInternal":false,"tokens":231,"sizeBytes":973},{"name":"rerender-dependencies.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-dependencies.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-dependencies.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-dependencies.md -->","frontmatter":{"title":"Narrow Effect Dependencies","impact":"LOW","impactDescription":"minimizes effect re-runs","tags":"rerender, useEffect, dependencies, optimization"},"isInternal":false,"tokens":214,"sizeBytes":824},{"name":"rerender-derived-state-no-effect.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-derived-state-no-effect.md -->","frontmatter":{"title":"Calculate Derived State During Rendering","impact":"MEDIUM","impactDescription":"avoids redundant renders and state drift","tags":"rerender, derived-state, useEffect, state"},"isInternal":false,"tokens":283,"sizeBytes":1201},{"name":"rerender-derived-state.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-derived-state.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-derived-state.md -->","frontmatter":{"title":"Subscribe to Derived State","impact":"MEDIUM","impactDescription":"reduces re-render frequency","tags":"rerender, derived-state, media-query, optimization"},"isInternal":false,"tokens":175,"sizeBytes":728},{"name":"rerender-functional-setstate.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-functional-setstate.md -->","frontmatter":{"title":"Use Functional setState Updates","impact":"MEDIUM","impactDescription":"prevents stale closures and unnecessary callback recreations","tags":"react, hooks, useState, useCallback, callbacks, closures"},"isInternal":false,"tokens":654,"sizeBytes":2968},{"name":"rerender-lazy-state-init.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-lazy-state-init.md -->","frontmatter":{"title":"Use Lazy State Initialization","impact":"MEDIUM","impactDescription":"wasted computation on every render","tags":"react, hooks, useState, performance, initialization"},"isInternal":false,"tokens":438,"sizeBytes":2016},{"name":"rerender-memo-with-default-value.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-memo-with-default-value.md -->","frontmatter":{"title":"Extract Default Non-primitive Parameter Value from Memoized Component to Constant","impact":"MEDIUM","impactDescription":"restores memoization by using a constant for default value","tags":"rerender, memo, optimization"},"isInternal":false,"tokens":248,"sizeBytes":1173},{"name":"rerender-memo.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-memo.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-memo.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-memo.md -->","frontmatter":{"title":"Extract to Memoized Components","impact":"MEDIUM","impactDescription":"enables early returns","tags":"rerender, memo, useMemo, optimization"},"isInternal":false,"tokens":278,"sizeBytes":1148},{"name":"rerender-move-effect-to-event.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-move-effect-to-event.md -->","frontmatter":{"title":"Put Interaction Logic in Event Handlers","impact":"MEDIUM","impactDescription":"avoids effect re-runs and duplicate side effects","tags":"rerender, useEffect, events, side-effects, dependencies"},"isInternal":false,"tokens":285,"sizeBytes":1268},{"name":"rerender-no-inline-components.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-no-inline-components.md -->","frontmatter":{"title":"Don't Define Components Inside Components","impact":"HIGH","impactDescription":"prevents remount on every render","tags":"rerender, components, remount, performance"},"isInternal":false,"tokens":523,"sizeBytes":2135},{"name":"rerender-simple-expression-in-memo.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-simple-expression-in-memo.md -->","frontmatter":{"title":"Do not wrap a simple expression with a primitive result type in useMemo","impact":"LOW-MEDIUM","impactDescription":"wasted computation on every render","tags":"rerender, useMemo, optimization"},"isInternal":false,"tokens":217,"sizeBytes":1018},{"name":"rerender-split-combined-hooks.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-split-combined-hooks.md -->","frontmatter":{"title":"Split Combined Hook Computations","impact":"MEDIUM","impactDescription":"avoids recomputing independent steps","tags":"rerender, useMemo, useEffect, dependencies, optimization"},"isInternal":false,"tokens":421,"sizeBytes":1844},{"name":"rerender-transitions.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-transitions.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-transitions.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-transitions.md -->","frontmatter":{"title":"Use Transitions for Non-Urgent Updates","impact":"MEDIUM","impactDescription":"maintains UI responsiveness","tags":"rerender, transitions, startTransition, performance"},"isInternal":false,"tokens":241,"sizeBytes":1055},{"name":"rerender-use-deferred-value.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-use-deferred-value.md -->","frontmatter":{"title":"Use useDeferredValue for Expensive Derived Renders","impact":"MEDIUM","impactDescription":"keeps input responsive during heavy computation","tags":"rerender, useDeferredValue, optimization, concurrent"},"isInternal":false,"tokens":421,"sizeBytes":1846},{"name":"rerender-use-ref-transient-values.md","path":".agents/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Frerender-use-ref-transient-values.md -->","frontmatter":{"title":"Use useRef for Transient Values","impact":"MEDIUM","impactDescription":"avoids unnecessary re-renders on frequent updates","tags":"rerender, useref, state, performance"},"isInternal":false,"tokens":436,"sizeBytes":1742},{"name":"server-after-nonblocking.md","path":".agents/skills/vercel-react-best-practices/rules/server-after-nonblocking.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/server-after-nonblocking.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-after-nonblocking.md -->","frontmatter":{"title":"Use after() for Non-Blocking Operations","impact":"MEDIUM","impactDescription":"faster response times","tags":"server, async, logging, analytics, side-effects"},"isInternal":false,"tokens":458,"sizeBytes":2012},{"name":"server-auth-actions.md","path":".agents/skills/vercel-react-best-practices/rules/server-auth-actions.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/server-auth-actions.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-auth-actions.md -->","frontmatter":{"title":"Authenticate Server Actions Like API Routes","impact":"CRITICAL","impactDescription":"prevents unauthorized access to server mutations","tags":"server, server-actions, authentication, security, authorization"},"isInternal":false,"tokens":585,"sizeBytes":2649},{"name":"server-cache-lru.md","path":".agents/skills/vercel-react-best-practices/rules/server-cache-lru.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/server-cache-lru.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-cache-lru.md -->","frontmatter":{"title":"Cross-Request LRU Caching","impact":"HIGH","impactDescription":"caches across requests","tags":"server, cache, lru, cross-request"},"isInternal":false,"tokens":326,"sizeBytes":1353},{"name":"server-cache-react.md","path":".agents/skills/vercel-react-best-practices/rules/server-cache-react.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/server-cache-react.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-cache-react.md -->","frontmatter":{"title":"Per-Request Deduplication with React.cache()","impact":"MEDIUM","impactDescription":"deduplicates within request","tags":"server, cache, react-cache, deduplication"},"isInternal":false,"tokens":513,"sizeBytes":2228},{"name":"server-dedup-props.md","path":".agents/skills/vercel-react-best-practices/rules/server-dedup-props.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/server-dedup-props.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-dedup-props.md -->","frontmatter":{"title":"Avoid Duplicate Serialization in RSC Props","impact":"LOW","impactDescription":"reduces network payload by avoiding duplicate serialization","tags":"server, rsc, serialization, props, client-components"},"isInternal":false,"tokens":499,"sizeBytes":2060},{"name":"server-hoist-static-io.md","path":".agents/skills/vercel-react-best-practices/rules/server-hoist-static-io.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/server-hoist-static-io.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-hoist-static-io.md -->","frontmatter":{"title":"Hoist Static I/O to Module Level","impact":"HIGH","impactDescription":"avoids repeated file/network I/O per request","tags":"server, io, performance, next.js, route-handlers, og-image"},"isInternal":false,"tokens":1048,"sizeBytes":4423},{"name":"server-no-shared-module-state.md","path":".agents/skills/vercel-react-best-practices/rules/server-no-shared-module-state.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/server-no-shared-module-state.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-no-shared-module-state.md -->","frontmatter":{"title":"Avoid Shared Module State for Request Data","impact":"HIGH","impactDescription":"prevents concurrency bugs and request data leaks","tags":"server, rsc, ssr, concurrency, security, state"},"isInternal":false,"tokens":368,"sizeBytes":1766},{"name":"server-parallel-fetching.md","path":".agents/skills/vercel-react-best-practices/rules/server-parallel-fetching.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/server-parallel-fetching.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-parallel-fetching.md -->","frontmatter":{"title":"Parallel Data Fetching with Component Composition","impact":"CRITICAL","impactDescription":"eliminates server-side waterfalls","tags":"server, rsc, parallel-fetching, composition"},"isInternal":false,"tokens":365,"sizeBytes":1554},{"name":"server-parallel-nested-fetching.md","path":".agents/skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-parallel-nested-fetching.md -->","frontmatter":{"title":"Parallel Nested Data Fetching","impact":"CRITICAL","impactDescription":"eliminates server-side waterfalls","tags":"server, rsc, parallel-fetching, promise-chaining"},"isInternal":false,"tokens":230,"sizeBytes":992},{"name":"server-serialization.md","path":".agents/skills/vercel-react-best-practices/rules/server-serialization.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/rules/server-serialization.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2Frules%2Fserver-serialization.md -->","frontmatter":{"title":"Minimize Serialization at RSC Boundaries","impact":"HIGH","impactDescription":"reduces data transfer size","tags":"server, rsc, serialization, props"},"isInternal":false,"tokens":242,"sizeBytes":996},{"name":"SKILL.md","path":".agents/skills/vercel-react-best-practices/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/vercel-react-best-practices/SKILL.md","title":"vercel-react-best-practices","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fvercel-react-best-practices%2FSKILL.md -->","frontmatter":{"name":"vercel-react-best-practices","description":"React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.","license":"MIT","metadata":{"author":"vercel","version":"1.0.0"}},"isInternal":false,"tokens":1756,"sizeBytes":7251},{"name":"SKILL.md","path":".agents/skills/web-design-guidelines/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/web-design-guidelines/SKILL.md","title":"web-design-guidelines","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fweb-design-guidelines%2FSKILL.md -->","frontmatter":{"name":"web-design-guidelines","description":"Review UI code for Web Interface Guidelines compliance. Use when asked to \"review my UI\", \"check accessibility\", \"audit design\", \"review UX\", or \"check my site against best practices\".","metadata":{"author":"vercel","version":"1.0.0","argument-hint":"<file-or-pattern>"}},"isInternal":false,"tokens":268,"sizeBytes":1231},{"name":"SKILL.md","path":".agents/skills/zero-tech-debt/SKILL.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/zero-tech-debt/SKILL.md","title":"zero-tech-debt","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fzero-tech-debt%2FSKILL.md -->","frontmatter":{"name":"zero-tech-debt","description":"Rework a change as if the intended UX and architecture existed from day one, deleting compatibility cruft and accidental complexity.","user-invocable":true},"isInternal":false,"tokens":287,"sizeBytes":1415},{"name":"data-boundaries.md","path":"apps/agent/agent/skills/data-boundaries.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/apps/agent/agent/skills/data-boundaries.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=apps%2Fagent%2Fagent%2Fskills%2Fdata-boundaries.md -->","frontmatter":{"description":"Use before reading CRM history or sending anything to a third party — what this agent may read (all of it) and what may leave."},"isInternal":false,"tokens":470,"sizeBytes":2088},{"name":"evidence.md","path":"apps/agent/agent/skills/evidence.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/apps/agent/agent/skills/evidence.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=apps%2Fagent%2Fagent%2Fskills%2Fevidence.md -->","frontmatter":{"description":"Use when recording a fact — picking the right evidence kind for what you actually saw, and understanding why a claim was written, offered or held."},"isInternal":false,"tokens":748,"sizeBytes":3132},{"name":"identity-matching.md","path":"apps/agent/agent/skills/identity-matching.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/apps/agent/agent/skills/identity-matching.md","title":"identity-matching","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=apps%2Fagent%2Fagent%2Fskills%2Fidentity-matching.md -->","frontmatter":{"name":"identity-matching","description":"How to decide that a LinkedIn profile is the person behind a CRM email address, and when to refuse."},"isInternal":false,"tokens":1325,"sizeBytes":5551},{"name":"writing-a-brief.md","path":"apps/agent/agent/skills/writing-a-brief.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/apps/agent/agent/skills/writing-a-brief.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=apps%2Fagent%2Fagent%2Fskills%2Fwriting-a-brief.md -->","frontmatter":{"description":"Use when writing the Background panel on a contact — the shape, the tone, and when to write nothing at all."},"isInternal":false,"tokens":498,"sizeBytes":2063},{"name":"analyzer.md","path":".agents/skills/skill-creator/agents/analyzer.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/skill-creator/agents/analyzer.md","title":"Subagent: analyzer","category":"subagent-persona","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2Fagents%2Fanalyzer.md -->","isInternal":false,"tokens":2258,"sizeBytes":10376},{"name":"comparator.md","path":".agents/skills/skill-creator/agents/comparator.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/skill-creator/agents/comparator.md","title":"Subagent: comparator","category":"subagent-persona","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2Fagents%2Fcomparator.md -->","isInternal":false,"tokens":1743,"sizeBytes":7287},{"name":"grader.md","path":".agents/skills/skill-creator/agents/grader.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/.agents/skills/skill-creator/agents/grader.md","title":"Subagent: grader","category":"subagent-persona","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=.agents%2Fskills%2Fskill-creator%2Fagents%2Fgrader.md -->","isInternal":false,"tokens":2036,"sizeBytes":9049},{"name":"api.md","path":"docs/api.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/docs/api.md","title":"docs - API Interface Contract & Specifications","category":"project-spec","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=docs%2Fapi.md -->","isInternal":false,"tokens":4667,"sizeBytes":18521},{"name":"design.md","path":"docs/design.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/docs/design.md","title":"docs - UI Design System & Style Tokens","category":"project-spec","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=docs%2Fdesign.md -->","isInternal":false,"tokens":442,"sizeBytes":1781},{"name":"README.md","path":"packages/auth/README.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/packages/auth/README.md","title":"auth Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=packages%2Fauth%2FREADME.md -->","isInternal":false,"tokens":945,"sizeBytes":3875},{"name":"README.md","path":"packages/db/README.md","rawUrl":"https://raw.githubusercontent.com/trycompai/crm/HEAD/packages/db/README.md","title":"db Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/trycompai/crm?path=packages%2Fdb%2FREADME.md -->","isInternal":false,"tokens":761,"sizeBytes":3166}],"systemPromptSnippet":"<yakaai_skills repo=\"trycompai/crm\">\n<!-- File: AGENTS.md (Tokens: ~2634 | Category: root-instruction) -->\n# Strict rules — review before starting any work\n\n**Read the doc for the area you are touching before you touch it.** The table\nbelow is the whole index. These are plain paths, not imports: they are not in your\ncontext until you read them, and the rules in them are not optional.\n\n| Working on | Read first |\n| --- | --- |\n| Anything in `apps/api` — tRPC, auth, logging, sync, deletes, caching | `docs/api.md` |\n| `apps/agent` — the eve research agent, tools, tasks, dispatch | `docs/agent.md` |\n| `.env`, configuration, which variables exist and why | `docs/environment.md` |\n| UI in `apps/app` or `packages/ui` | `docs/design.md` (below) |\n| Deal amounts, totals, charts, exchange rates | `docs/currency.md` |\n| The record sheet's Agent tab | `docs/agent-panel.md` |\n| `/settings/connections`, integrations, the intake endpoint | `docs/connections.md` |\n| The tracking script, the collector, form submissions | `docs/tracking.md` |\n| Running it locally, Google Cloud, DB commands, secrets | `docs/setup.md` |\n| Anything that sends a telemetry event, or a new property on one | `docs/telemetry.md` |\n| `.github/workflows`, versions, changelog, how a change reaches `release` | `CONTRIBUTING.md` |\n\nAlso check `.agents/skills/` for a relevant skill before starting — better-auth,\nprisma, nestjs-trpc, eve, shadcn, nuqs and others have one. Tell the user which\nrules and skills you read.\n\n## Always true\n\n- **Never add code comments.** Not to new code, not to code you edit.\n- **No coauthoring commits.** No `Co-Authored-By` trailer, ever.\n- **Intelligence lives in `apps/agent`, never in the API.** No vendor client, no\n  enrichment, no scoring, no identity matching in Nest — it writes an `AgentTask`\n  row and lets the agent decide. See `docs/api.md`.\n- **One `.env`, at the repo root.** `.env.example` is its documentation: add every\n  new variable there with a note on what it does, and declare it in\n  `apps/api/src/config/env.validation.ts` if the API reads it. Never add a\n  per-package `.env`.\n- **Anything a self-hoster might not have is optional and must never throw.** A\n  missing key removes a capability. `apps/agent/agent/lib/capabilities.ts` is the\n  pattern.\n- **`/packages/ui` is the single source of truth for UI.** Shared shadcn\n  components only; a new variant is implemented there, not overridden at the call\n  site.\n- **eve's own docs ship in `apps/agent/node_modules/eve/docs`** and match the\n  installed version. Read the relevant guide before writing eve code rather than\n  working from memory — guessing typechecks, builds, and then behaves differently.\n\n## Report every issue. Use ASD-STE100\n\nDo not bury a known problem inside a paragraph. A problem inside prose is a\nproblem nobody reads. Report **every** issue, including ones you caused, in a\nlist at the end of your reply.\n\nWrite every message, every report and every issue in **ASD-STE100**\n(Simplified Technical English):\n\n- One idea per sentence. Maximum 20 words.\n- Active voice. Present tense. No conditionals.\n- One word for one meaning. Do not use synonyms for variety.\n- Say the effect, not only the cause.\n- No hedging: never \"may\", \"might\", \"possibly\", \"somewhat\".\n\nUse exactly this shape:\n\n```\n## Issues\n\n1. BROKEN — Slack is not connected. Agents that post to Slack fail.\n   Fix: connect Slack in Settings → Connections.\n2. RISK — A run longer than 5 minutes is cancelled. Work is lost.\n   Fix: not done. Needs a separate execution lease.\n3. NOT DONE — The manual run button shows on event-only agents.\n```\n\nRules for the list:\n\n- One line for the problem. One line for the fix.\n- Start each with **BROKEN**, **RISK**, **NOT DONE**, or **UNKNOWN**.\n- **BROKEN** is failing now. **RISK** fails later. **NOT DONE** is unbuilt.\n  **UNKNOWN** is not investigated.\n- If you introduced it, write **I caused this** on the fix line.\n- Zero issues? Write `## Issues` then `None.`\n\n**Don't** — bury it in prose:\n\n> The fix works well. One honest limit: abandoning a sweep unblocks the queue but\n> doesn't cancel the underlying hung promise, so it leaks until restart.\n\n**Do** — put it in the list:\n\n> 1. RISK — An abandoned sweep leaks its promise. Memory grows until restart.\n>    Fix: not done. Needs cancellation in `receive()`. I caused this.\n\n## A server page computes. A client component renders.\n\nA client component must never import a server package. `@crm/auth` and `@crm/db`\nare server packages: their barrels reach Prisma, which reaches `pg`, which\nreaches `dns`. The bundler follows that chain into the browser and the build\nfails with `Module not found: Can't resolve 'dns'`.\n\nThe import trace is the whole error. Read it from the bottom: the last line is\nthe page, the line above is the client component that leaked, and the top is the\nNode module that cannot exist in a browser.\n\n**Don't** — a client component reaching for a server package:\n\n```tsx\n\"use client\";\nimport {\n  describeSlackScopes,\n  SLACK_SCOPE_GROUPS,\n} from \"@crm/auth/slack-scopes\";\n\nexport function SlackScopeGroups({ scopes }: { scopes: string[] }) {\n  const groups = SLACK_SCOPE_GROUPS.map(...)\n}\n```\n\n**Do** — the page does the work and hands over plain data:\n\n```tsx\n// page.tsx — server\nimport {\n  describeSlackScopes,\n  SLACK_SCOPE_GROUPS,\n} from \"@crm/auth/slack-scopes\";\n\nconst groups = groupScopes(status.scopes);\nreturn <SlackScopeGroups groups={groups} />;\n```\n\n```tsx\n// slack-scope-groups.tsx — client\n\"use client\";\n\nexport type ScopeGroup = { id: string; label: string; scopes: ScopeLine[] };\n\nexport function SlackScopeGroups({ groups }: { groups: ScopeGroup[] }) { … }\n```\n\nRules that follow:\n\n- The client component owns its own prop types. It does not re-export a server\n  type to get them.\n- Anything interactive — an accordion, a dialog, a search field — is a client\n  component that receives finished data. It never derives it.\n- A `\"use client\"` file may import from `@crm/ui`, the tRPC client, and React.\n  Anything else needs checking.\n- The server page is where `await` and secrets live. The client file has neither.\n\n## Constants belong in one file per area, not beside their first use\n\nA number that someone will want to tune goes in a named config module for its\narea. It does not go at the top of whichever file happened to need it first.\nSomebody changing a timeout must not have to know which file to open.\n\n**Don't** — one constant per file, found only by grep:\n\n```ts\n// dispatch.ts\nconst DRAIN_TIMEOUT_MS = 4 * 60_000;\n// crm.ts\nconst STALE_QUEUE_MS = 5 * 60_000;\n// tasks.ts\nconst LEASE_MS = 10 * 60_000;\n```\n\n**Do** — one object, grouped by concern, imported where used:\n\n```ts\n// dispatch-config.ts\nexport const DISPATCH = {\n  sweep: { timeoutMs: 4 * MINUTE_MS, staleQueueMs: 5 * MINUTE_MS },\n  task: { leaseMs: 10 * MINUTE_MS },\n} as const;\n```\n\n`apps/agent/agent/lib/dispatch-config.ts` is the pattern. Rules:\n\n- Group by concern, not by file that uses it.\n- Derive units from one base (`MINUTE_MS`). Never write `4 * 60_000` twice.\n- `as const`, so the values are literal types.\n- No magic numbers inline. If it is tunable, it belongs in the config.\n- One convention across the codebase. Do not invent a local style for one file.\n\n## Parse at the boundary, never pass `Record<string, unknown>` around\n\nUntyped data — a Prisma `Json` column, a webhook body, an API response — is\nparsed into a **domain type at the moment it enters the process**, with Zod, in a\nmodule that owns that shape. Every consumer downstream receives the parsed type\nand nothing else. `Record<string, unknown>`, `unknown` casts and one-off\n`recordOf()` helpers are how a shape becomes unknowable and a typo becomes a\nruntime bug two files away.\n\n**Don't** — reach into raw JSON, re-deriving the shape at each call site:\n\n```ts\nfunction manifestActions(value: unknown) {\n  const actions = recordOf(value).actions;\n  return Array.isArray(actions) ? actions.map(recordOf) : [];\n}\n\nconst slack = manifestActions(version.manifest).find(\n  (action) => action.type === \"slack.message.post\",\n);\nconst id = (slack?.destination as Record<string, unknown>)?.id;\n```\n\nNothing here is checked. `destination` may be missing, `id` may be a number, and\nthe compiler cannot help. Rename a field and every one of these silently returns\n`undefined`.\n\n**Do** — one schema, parsed once, at the read:\n\n```ts\nexport const agentManifestAction = z.discriminatedUnion(\"type\", [\n  z.object({\n    type: z.literal(AGENT_ACTION_TYPES.SLACK_MESSAGE_POST),\n    provider: z.literal(\"slack\"),\n    summary: z.string(),\n    destination: z.object({\n      kind: z.enum([\"channel\", \"user\"]),\n      resolution: z.literal(\"chosen\"),\n      id: z.string().trim().min(1).max(120),\n      label: z.string().trim().min(1).max(120),\n    }),\n  }),\n]);\n\nexport type AgentManifest = z.infer<typeof agentManifest>;\n\nexport function parseAgentManifest(value: unknown): AgentManifest { … }\n```\n\n```ts\nconst manifest = parseAgentManifest(version.manifest);\nconst slack = manifest.actions.find(\n  (action) => action.type === \"slack.message.post\",\n);\nconst id = slack?.destination.id;\n```\n\n`packages/validation/src/agent-manifest.ts` is the pattern. A shape that crosses\na package boundary — a `Json` column two apps read, a payload one app writes and\nanother consumes — lives in `packages/validation/src`, one module per shape, and\nis imported by subpath (`@crm/validation/agent-manifest`). Rules that follow from\nit:\n\n- The schema describes what is **actually stored**, not the loosest thing that\n  parses. If a test fixture fails the schema, fix the fixture — a fixture that\n  omits required fields is testing data that cannot exist.\n- Parse failure is a real error with a real message. Do not swallow it into an\n  empty array, because \"unreadable manifest\" and \"no actions\" are different\n  problems and only one of them is the user's fault.\n- Derive types with `z.infer`. Never hand-write an interface beside a schema;\n  they drift.\n\n## Design\n\n@docs/design.md\n\n## Commit Messages & Pull Requests\n\n**Branch from `main`, never from `release`.** `release` is the default branch so\nthat a plain clone runs the last tagged release, and the only things that merge\ninto it are release pull requests. A branch cut from `release` carries release\nmerge commits that do not belong in a feature pull request.\n\n**You do not write the pull request title.** `.github/scripts/pr-title.sh` reads\nthe diff and writes one. Retitle it yourself and the automation stops.\n`CONTRIBUTING.md` is the whole account of how a change reaches `release`; read it\nbefore shipping.\n\n<!-- File: CLAUDE.md (Tokens: ~5 | Category: claude-rule) -->\n@AGENTS.md\n\n<!-- File: .agents/skills/ai-elements/references/agent.md (Tokens: ~1003 | Category: anthropic-skill) -->\n# Agent\n\nA composable component for displaying AI agent configuration with model, instructions, tools, and output schema.\n\nThe `Agent` component displays an interface for showing AI agent configuration details. It's designed to represent a configured agent from the AI SDK, showing the agent's model, system instructions, available tools (with expandable input schemas), and output schema.\n\nSee `scripts/agent.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add agent\n```\n\n## Usage with AI SDK\n\nDisplay an agent's configuration alongside your chat interface. Tools are displayed in an accordion where clicking the description expands to show the input schema.\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport {\n  Agent,\n  AgentContent,\n  AgentHeader,\n  AgentInstructions,\n  AgentOutput,\n  AgentTool,\n  AgentTools,\n} from \"@/components/ai-elements/agent\";\n\nconst webSearch = tool({\n  description: \"Search the web for information\",\n  inputSchema: z.object({\n    query: z.string().describe(\"The search query\"),\n  }),\n});\n\nconst readUrl = tool({\n  description: \"Read and parse content from a URL\",\n  inputSchema: z.object({\n    url: z.string().url().describe(\"The URL to read\"),\n  }),\n});\n\nconst outputSchema = `z.object({\n  sentiment: z.enum(['positive', 'negative', 'neutral']),\n  score: z.number(),\n  summary: z.string(),\n})`;\n\nexport default function Page() {\n  return (\n    <Agent>\n      <AgentHeader\n        name=\"Sentiment Analyzer\"\n        model=\"anthropic/claude-sonnet-4-5\"\n      />\n      <AgentContent>\n        <AgentInstructions>\n          Analyze the sentiment of the provided text and return a structured\n          analysis with sentiment classification, confidence score, and summary.\n        </AgentInstructions>\n        <AgentTools>\n          <AgentTool tool={webSearch} value=\"web_search\" />\n          <AgentTool tool={readUrl} value=\"read_url\" />\n        </AgentTools>\n        <AgentOutput schema={outputSchema} />\n      </AgentContent>\n    </Agent>\n  );\n}\n```\n\n## Features\n\n- Model badge in header\n- Instructions rendered as markdown\n- Tools displayed as accordion items with expandable input schemas\n- Output schema display with syntax highlighting\n- Composable structure for flexible layouts\n- Works with AI SDK `Tool` type\n\n## Props\n\n### `<Agent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any props are spread to the root div. |\n\n### `<AgentHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | The name of the agent. |\n| `model` | `string` | - | The model identifier (e.g.  |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n### `<AgentContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n### `<AgentInstructions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | Required | The instruction text. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n### `<AgentTools />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Accordion>` | - | Any other props are spread to the Accordion component. |\n\n### `<AgentTool />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tool` | `Tool` | Required | The tool object from the AI SDK containing description and inputSchema. |\n| `value` | `string` | Required | Unique identifier for the accordion item. |\n| `...props` | `React.ComponentProps<typeof AccordionItem>` | - | Any other props are spread to the AccordionItem component. |\n\n### `<AgentOutput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `schema` | `string` | Required | The output schema as a string (displayed with syntax highlighting). |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |\n\n<!-- File: .agents/skills/ai-elements/references/artifact.md (Tokens: ~673 | Category: anthropic-skill) -->\n# Artifact\n\nA container component for displaying generated content like code, documents, or other outputs with built-in actions.\n\nThe `Artifact` component provides a structured container for displaying generated content like code, documents, or other outputs with built-in header actions.\n\nSee `scripts/artifact.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add artifact\n```\n\n## Features\n\n- Structured container with header and content areas\n- Built-in header with title and description support\n- Flexible action buttons with tooltips\n- Customizable styling for all subcomponents\n- Support for close buttons and action groups\n- Clean, modern design with border and shadow\n- Responsive layout that adapts to content\n- TypeScript support with proper type definitions\n- Composable architecture for maximum flexibility\n\n## Examples\n\n### With Code Display\n\nSee `scripts/artifact.tsx` for this example.\n\n## Props\n\n### `<Artifact />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n### `<ArtifactHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n### `<ArtifactTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Any other props are spread to the underlying paragraph element. |\n\n### `<ArtifactDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Any other props are spread to the underlying paragraph element. |\n\n### `<ArtifactActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n### `<ArtifactAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string` | - | Tooltip text to display on hover. |\n| `label` | `string` | - | Screen reader label for the action button. |\n| `icon` | `LucideIcon` | - | Lucide icon component to display in the button. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<ArtifactClose />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<ArtifactContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the underlying div element. |\n\n<!-- File: .agents/skills/ai-elements/references/attachments.md (Tokens: ~1300 | Category: anthropic-skill) -->\n# Attachments\n\nA flexible, composable attachment component for displaying files, images, videos, audio, and source documents.\n\nThe `Attachment` component provides a unified way to display file attachments and source documents with multiple layout variants.\n\nSee `scripts/attachments.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add attachments\n```\n\n## Usage with AI SDK\n\nDisplay user-uploaded files in chat messages or input areas.\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Attachments,\n  Attachment,\n  AttachmentPreview,\n  AttachmentInfo,\n  AttachmentRemove,\n} from \"@/components/ai-elements/attachments\";\nimport type { FileUIPart } from \"ai\";\n\ninterface MessageProps {\n  attachments: (FileUIPart & { id: string })[];\n  onRemove?: (id: string) => void;\n}\n\nconst MessageAttachments = ({ attachments, onRemove }: MessageProps) => (\n  <Attachments variant=\"grid\">\n    {attachments.map((file) => (\n      <Attachment\n        key={file.id}\n        data={file}\n        onRemove={onRemove ? () => onRemove(file.id) : undefined}\n      >\n        <AttachmentPreview />\n        <AttachmentRemove />\n      </Attachment>\n    ))}\n  </Attachments>\n);\n\nexport default MessageAttachments;\n```\n\n## Features\n\n- Three display variants: grid (thumbnails), inline (badges), and list (rows)\n- Supports both FileUIPart and SourceDocumentUIPart from the AI SDK\n- Automatic media type detection (image, video, audio, document, source)\n- Hover card support for inline previews\n- Remove button with customizable callback\n- Composable architecture for maximum flexibility\n- Accessible with proper ARIA labels\n- TypeScript support with exported utility functions\n\n## Examples\n\n### Grid Variant\n\nBest for displaying attachments in messages with visual thumbnails.\n\nSee `scripts/attachments.tsx` for this example.\n\n### Inline Variant\n\nBest for compact badge-style display in input areas with hover previews.\n\nSee `scripts/attachments-inline.tsx` for this example.\n\n### List Variant\n\nBest for file lists with full metadata display.\n\nSee `scripts/attachments-list.tsx` for this example.\n\n## Props\n\n### `<Attachments />`\n\nContainer component that sets the layout variant.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `variant` | `unknown` | - | The display layout variant. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<Attachment />`\n\nIndividual attachment item wrapper.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `data` | `unknown` | - | The attachment data (FileUIPart or SourceDocumentUIPart with id). |\n| `onRemove` | `() => void` | - | Callback fired when the remove button is clicked. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<AttachmentPreview />`\n\nDisplays the media preview (image, video, or icon).\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `fallbackIcon` | `React.ReactNode` | - | Custom icon to display when no preview is available. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<AttachmentInfo />`\n\nDisplays the filename and optional media type.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `showMediaType` | `boolean` | `false` | Whether to show the media type below the filename. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n### `<AttachmentRemove />`\n\nRemove button that appears on hover.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `label` | `string` | - | Screen reader label for the button. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the underlying Button component. |\n\n### `<AttachmentHoverCard />`\n\nWrapper for hover preview functionality.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `openDelay` | `number` | `0` | Delay in ms before opening the hover card. |\n| `closeDelay` | `number` | `0` | Delay in ms before closing the hover card. |\n| `...props` | `React.ComponentProps<typeof HoverCard>` | - | Spread to the underlying HoverCard component. |\n\n### `<AttachmentHoverCardTrigger />`\n\nTrigger element for the hover card.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof HoverCardTrigger>` | - | Spread to the underlying HoverCardTrigger component. |\n\n### `<AttachmentHoverCardContent />`\n\nContent displayed in the hover card.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `align` | `unknown` | - | Alignment of the hover card content. |\n| `...props` | `React.ComponentProps<typeof HoverCardContent>` | - | Spread to the underlying HoverCardContent component. |\n\n### `<AttachmentEmpty />`\n\nEmpty state component when no attachments are present.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |\n\n## Utility Functions\n\n### `getMediaCategory(data)`\n\nReturns the media category for an attachment.\n\n```tsx\nimport { getMediaCategory } from \"@/components/ai-elements/attachments\";\n\nconst category = getMediaCategory(attachment);\n// Returns: \"image\" | \"video\" | \"audio\" | \"document\" | \"source\" | \"unknown\"\n```\n\n### `getAttachmentLabel(data)`\n\nReturns the display label for an attachment.\n\n```tsx\nimport { getAttachmentLabel } from \"@/components/ai-elements/attachments\";\n\nconst label = getAttachmentLabel(attachment);\n// Returns filename or fallback like \"Image\" or \"Attachment\"\n```\n\n<!-- File: .agents/skills/ai-elements/references/audio-player.md (Tokens: ~1203 | Category: anthropic-skill) -->\n# Audio Player\n\nA composable audio player component built on media-chrome, with shadcn styling and flexible controls.\n\nThe `AudioPlayer` component provides a flexible and customizable audio playback interface built on top of media-chrome. It features a composable architecture that allows you to build audio experiences with custom controls, metadata display, and seamless integration with AI-generated audio content.\n\nSee `scripts/audio-player.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add audio-player\n```\n\n## Features\n\n- Built on media-chrome for reliable audio playback\n- Fully composable architecture with granular control components\n- ButtonGroup integration for cohesive control layout\n- Individual control components (play, seek, volume, etc.)\n- Flexible layout with customizable control bars\n- CSS custom properties for deep theming\n- Shadcn/ui Button component styling\n- Responsive design that works across devices\n- Full TypeScript support with proper types for all components\n\n## Variants\n\n### AI SDK Speech Result\n\nThe `AudioPlayer` component can be used to play audio from an AI SDK Speech Result.\n\nSee `scripts/audio-player.tsx` for this example.\n\n### Remote Audio\n\nThe `AudioPlayer` component can be used to play remote audio files.\n\nSee `scripts/audio-player-remote.tsx` for this example.\n\n## Props\n\n### `<AudioPlayer />`\n\nRoot MediaController component. Accepts all MediaController props except `audio` (which is set to `true` by default).\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `style` | `CSSProperties` | - | Custom CSS properties can be passed to override media-chrome theming variables. |\n| `...props` | `Omit<React.ComponentProps<typeof MediaController>, ` | - | Any other props are spread to the MediaController component. |\n\n### `<AudioPlayerElement />`\n\nThe audio element that contains the media source. Accepts either a remote URL or AI SDK Speech Result data.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `src` | `string` | - | The URL of the audio file to play (for remote audio). |\n| `data` | `SpeechResult[` | - | AI SDK Speech Result audio data with base64 encoding (for AI-generated audio). |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the audio element (excluding src when using data). |\n\n### `<AudioPlayerControlBar />`\n\nContainer for control buttons, wraps children in a ButtonGroup.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaControlBar>` | - | Any other props are spread to the MediaControlBar component. |\n\n### `<AudioPlayerPlayButton />`\n\nPlay/pause button wrapped in a shadcn Button component.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaPlayButton>` | - | Any other props are spread to the MediaPlayButton component. |\n\n### `<AudioPlayerSeekBackwardButton />`\n\nSeek backward button wrapped in a shadcn Button component.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `seekOffset` | `number` | `10` | The number of seconds to seek backward. |\n| `...props` | `React.ComponentProps<typeof MediaSeekBackwardButton>` | - | Any other props are spread to the MediaSeekBackwardButton component. |\n\n### `<AudioPlayerSeekForwardButton />`\n\nSeek forward button wrapped in a shadcn Button component.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `seekOffset` | `number` | `10` | The number of seconds to seek forward. |\n| `...props` | `React.ComponentProps<typeof MediaSeekForwardButton>` | - | Any other props are spread to the MediaSeekForwardButton component. |\n\n### `<AudioPlayerTimeDisplay />`\n\nDisplays the current playback time, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaTimeDisplay>` | - | Any other props are spread to the MediaTimeDisplay component. |\n\n### `<AudioPlayerTimeRange />`\n\nSeek slider for controlling playback position, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaTimeRange>` | - | Any other props are spread to the MediaTimeRange component. |\n\n### `<AudioPlayerDurationDisplay />`\n\nDisplays the total duration of the audio, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaDurationDisplay>` | - | Any other props are spread to the MediaDurationDisplay component. |\n\n### `<AudioPlayerMuteButton />`\n\nMute/unmute button, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaMuteButton>` | - | Any other props are spread to the MediaMuteButton component. |\n\n### `<AudioPlayerVolumeRange />`\n\nVolume slider control, wrapped in ButtonGroupText.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof MediaVolumeRange>` | - | Any other props are spread to the MediaVolumeRange component. |\n\n<!-- File: .agents/skills/ai-elements/references/canvas.md (Tokens: ~254 | Category: anthropic-skill) -->\n# Canvas\n\nA React Flow-based canvas component for building interactive node-based interfaces.\n\nThe `Canvas` component provides a React Flow-based canvas for building interactive node-based interfaces. It comes pre-configured with sensible defaults for AI applications, including panning, zooming, and selection behaviors.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add canvas\n```\n\n## Features\n\n- Pre-configured React Flow canvas with AI-optimized defaults\n- Pan on scroll enabled for intuitive navigation\n- Selection on drag for multi-node operations\n- Customizable background color using CSS variables\n- Delete key support (Backspace and Delete keys)\n- Auto-fit view to show all nodes\n- Disabled double-click zoom for better UX\n- Disabled pan on drag to prevent accidental canvas movement\n- Fully compatible with React Flow props and API\n\n## Props\n\n### `<Canvas />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode` | - | Child components like Background, Controls, or MiniMap. |\n| `...props` | `ReactFlowProps` | - | Any other React Flow props like nodes, edges, nodeTypes, edgeTypes, onNodesChange, etc. |\n\n<!-- File: .agents/skills/ai-elements/references/chain-of-thought.md (Tokens: ~795 | Category: anthropic-skill) -->\n# Chain of Thought\n\nA collapsible component that visualizes AI reasoning steps with support for search results, images, and step-by-step progress indicators.\n\nThe `ChainOfThought` component provides a visual representation of an AI's reasoning process, showing step-by-step thinking with support for search results, images, and progress indicators. It helps users understand how AI arrives at conclusions.\n\nSee `scripts/chain-of-thought.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add chain-of-thought\n```\n\n## Features\n\n- Collapsible interface with smooth animations powered by Radix UI\n- Step-by-step visualization of AI reasoning process\n- Support for different step statuses (complete, active, pending)\n- Built-in search results display with badge styling\n- Image support with captions for visual content\n- Custom icons for different step types\n- Context-aware components using React Context API\n- Fully typed with TypeScript\n- Accessible with keyboard navigation support\n- Responsive design that adapts to different screen sizes\n- Smooth fade and slide animations for content transitions\n- Composable architecture for flexible customization\n\n## Props\n\n### `<ChainOfThought />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `open` | `boolean` | - | Controlled open state of the collapsible. |\n| `defaultOpen` | `boolean` | `false` | Default open state when uncontrolled. |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback when the open state changes. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div element. |\n\n### `<ChainOfThoughtHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom header text. |\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Any other props are spread to the CollapsibleTrigger component. |\n\n### `<ChainOfThoughtStep />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `icon` | `LucideIcon` | `DotIcon` | Icon to display for the step. |\n| `label` | `string` | - | The main text label for the step. |\n| `description` | `string` | - | Optional description text shown below the label. |\n| `status` | `unknown` | - | Visual status of the step. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div element. |\n\n### `<ChainOfThoughtSearchResults />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any props are spread to the container div element. |\n\n### `<ChainOfThoughtSearchResult />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Badge>` | - | Any props are spread to the Badge component. |\n\n### `<ChainOfThoughtContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Any props are spread to the CollapsibleContent component. |\n\n### `<ChainOfThoughtImage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `caption` | `string` | - | Optional caption text displayed below the image. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div element. |\n\n<!-- File: .agents/skills/ai-elements/references/checkpoint.md (Tokens: ~1181 | Category: anthropic-skill) -->\n# Checkpoint\n\nA simple component for marking conversation history points and restoring the chat to a previous state.\n\nThe `Checkpoint` component provides a way to mark specific points in a conversation history and restore the chat to that state. Inspired by VSCode's Copilot checkpoint feature, it allows users to revert to an earlier conversation state while maintaining a clear visual separation between different conversation segments.\n\nSee `scripts/checkpoint.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add checkpoint\n```\n\n## Features\n\n- Simple flex layout with icon, trigger, and separator\n- Visual separator line for clear conversation breaks\n- Clickable restore button for reverting to checkpoint\n- Customizable icon (defaults to BookmarkIcon)\n- Keyboard accessible with proper ARIA labels\n- Responsive design that adapts to different screen sizes\n- Seamless light/dark theme integration\n\n## Usage with AI SDK\n\nBuild a chat interface with conversation checkpoints that allow users to restore to previous states.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useState, Fragment } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n  Checkpoint,\n  CheckpointIcon,\n  CheckpointTrigger,\n} from \"@/components/ai-elements/checkpoint\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport {\n  Conversation,\n  ConversationContent,\n} from \"@/components/ai-elements/conversation\";\n\ntype CheckpointType = {\n  id: string;\n  messageIndex: number;\n  timestamp: Date;\n  messageCount: number;\n};\n\nconst CheckpointDemo = () => {\n  const { messages, setMessages } = useChat();\n  const [checkpoints, setCheckpoints] = useState<CheckpointType[]>([]);\n\n  const createCheckpoint = (messageIndex: number) => {\n    const checkpoint: CheckpointType = {\n      id: nanoid(),\n      messageIndex,\n      timestamp: new Date(),\n      messageCount: messageIndex + 1,\n    };\n    setCheckpoints([...checkpoints, checkpoint]);\n  };\n\n  const restoreToCheckpoint = (messageIndex: number) => {\n    // Restore messages to checkpoint state\n    setMessages(messages.slice(0, messageIndex + 1));\n    // Remove checkpoints after this point\n    setCheckpoints(checkpoints.filter((cp) => cp.messageIndex <= messageIndex));\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <Conversation>\n        <ConversationContent>\n          {messages.map((message, index) => {\n            const checkpoint = checkpoints.find(\n              (cp) => cp.messageIndex === index\n            );\n\n            return (\n              <Fragment key={message.id}>\n                <Message from={message.role}>\n                  <MessageContent>\n                    <MessageResponse>{message.content}</MessageResponse>\n                  </MessageContent>\n                </Message>\n                {checkpoint && (\n                  <Checkpoint>\n                    <CheckpointIcon />\n                    <CheckpointTrigger\n                      onClick={() =>\n                        restoreToCheckpoint(checkpoint.messageIndex)\n                      }\n                    >\n                      Restore checkpoint\n                    </CheckpointTrigger>\n                  </Checkpoint>\n                )}\n              </Fragment>\n            );\n          })}\n        </ConversationContent>\n      </Conversation>\n    </div>\n  );\n};\n\nexport default CheckpointDemo;\n```\n\n## Use Cases\n\n### Manual Checkpoints\n\nAllow users to manually create checkpoints at important conversation points:\n\n```tsx\n<Button onClick={() => createCheckpoint(messages.length - 1)}>\n  Create Checkpoint\n</Button>\n```\n\n### Automatic Checkpoints\n\nCreate checkpoints automatically after significant conversation milestones:\n\n```tsx\nuseEffect(() => {\n  // Create checkpoint every 5 messages\n  if (messages.length > 0 && messages.length % 5 === 0) {\n    createCheckpoint(messages.length - 1);\n  }\n}, [messages.length]);\n```\n\n### Branching Conversations\n\nUse checkpoints to enable conversation branching where users can explore different conversation paths:\n\n```tsx\nconst restoreAndBranch = (messageIndex: number) => {\n  // Save current branch\n  const currentBranch = messages.slice(messageIndex + 1);\n  saveBranch(currentBranch);\n\n  // Restore to checkpoint\n  restoreToCheckpoint(messageIndex);\n};\n```\n\n## Props\n\n### `<Checkpoint />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The checkpoint icon and trigger components. Automatically includes a Separator at the end. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<CheckpointIcon />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom icon content. If not provided, defaults to a BookmarkIcon from lucide-react. |\n| `...props` | `LucideProps` | - | Any other props are spread to the BookmarkIcon component. |\n\n### `<CheckpointTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The text or content to display in the trigger button. |\n| `tooltip` | `string` | - | Optional tooltip text shown on hover. |\n| `variant` | `string` | - | The button variant style. |\n| `size` | `string` | - | The button size. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n<!-- File: .agents/skills/ai-elements/references/code-block.md (Tokens: ~1325 | Category: anthropic-skill) -->\n# Code Block\n\nProvides syntax highlighting, line numbers, and copy to clipboard functionality for code blocks.\n\nThe `CodeBlock` component provides syntax highlighting, line numbers, and copy to clipboard functionality for code blocks. It's fully composable, allowing you to customize the header, actions, and content.\n\nSee `scripts/code-block.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add code-block\n```\n\n## Usage\n\nThe CodeBlock is fully composable. Here's a basic example:\n\n```tsx\nimport {\n  CodeBlock,\n  CodeBlockActions,\n  CodeBlockCopyButton,\n  CodeBlockFilename,\n  CodeBlockHeader,\n  CodeBlockTitle,\n} from \"@/components/ai-elements/code-block\";\nimport { FileIcon } from \"lucide-react\";\n\nexport const Example = () => (\n  <CodeBlock code={code} language=\"typescript\">\n    <CodeBlockHeader>\n      <CodeBlockTitle>\n        <FileIcon size={14} />\n        <CodeBlockFilename>example.ts</CodeBlockFilename>\n      </CodeBlockTitle>\n      <CodeBlockActions>\n        <CodeBlockCopyButton />\n      </CodeBlockActions>\n    </CodeBlockHeader>\n  </CodeBlock>\n);\n```\n\n## Features\n\n- Syntax highlighting with Shiki\n- Line numbers (optional)\n- Copy to clipboard functionality\n- Automatic light/dark theme switching via CSS variables\n- Language selector for multi-language examples\n- Fully composable architecture\n- Accessible design\n\n## Examples\n\n### Dark Mode\n\nTo use the `CodeBlock` component in dark mode, wrap it in a `div` with the `dark` class.\n\nSee `scripts/code-block-dark.tsx` for this example.\n\n### Language Selector\n\nAdd a language selector to switch between different code implementations:\n\nSee `scripts/code-block.tsx` for this example.\n\n## Props\n\n### `<CodeBlock />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `code` | `string` | - | The code content to display. |\n| `language` | `BundledLanguage` | - | The programming language for syntax highlighting. |\n| `showLineNumbers` | `boolean` | `false` | Whether to show line numbers. |\n| `children` | `React.ReactNode` | - | Child elements like CodeBlockHeader. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockHeader />`\n\nContainer for the header row. Uses flexbox with `justify-between`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Header content (CodeBlockTitle, CodeBlockActions, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockTitle />`\n\nLeft-aligned container for icon and filename. Uses flexbox with `gap-2`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Title content (icon, CodeBlockFilename, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockFilename />`\n\nDisplays the filename in monospace font.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The filename to display. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockActions />`\n\nRight-aligned container for action buttons. Uses flexbox with `gap-2`.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Action buttons (CodeBlockCopyButton, CodeBlockLanguageSelector, etc.). |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onCopy` | `() => void` | - | Callback fired after a successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback fired if copying fails. |\n| `timeout` | `number` | `2000` | How long to show the copied state (ms). |\n| `children` | `React.ReactNode` | - | Custom content for the button. Defaults to copy/check icons. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<CodeBlockLanguageSelector />`\n\nWrapper for the language selector. Extends shadcn/ui Select.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The currently selected language. |\n| `onValueChange` | `(value: string) => void` | - | Callback when the language changes. |\n| `children` | `React.ReactNode` | - | Selector components (Trigger, Content, Items). |\n\n### `<CodeBlockLanguageSelectorTrigger />`\n\nTrigger button for the language selector dropdown. Pre-styled for code block header.\n\n### `<CodeBlockLanguageSelectorValue />`\n\nDisplays the selected language value.\n\n### `<CodeBlockLanguageSelectorContent />`\n\nDropdown content container. Defaults to `align=\"end\"`.\n\n### `<CodeBlockLanguageSelectorItem />`\n\nIndividual language option in the dropdown.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The language value. |\n| `children` | `React.ReactNode` | - | The display label. |\n\n### `<CodeBlockContainer />`\n\nLow-level container component with performance optimizations (`contentVisibility`). Used internally by CodeBlock.\n\n### `<CodeBlockContent />`\n\nLow-level component that handles syntax highlighting. Used internally by CodeBlock, but can be used directly for custom layouts.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `code` | `string` | - | The code content to display. |\n| `language` | `BundledLanguage` | - | The programming language for syntax highlighting. |\n| `showLineNumbers` | `boolean` | `false` | Whether to show line numbers. |\n\n<!-- File: .agents/skills/ai-elements/references/commit.md (Tokens: ~1474 | Category: anthropic-skill) -->\n# Commit\n\nDisplay commit information with hash, message, author, and file changes.\n\nThe `Commit` component displays commit details including hash, message, author, timestamp, and changed files.\n\nSee `scripts/commit.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add commit\n```\n\n## Features\n\n- Commit hash display with copy button\n- Author avatar with initials\n- Relative timestamp formatting\n- Collapsible file changes list\n- Color-coded file status (added/modified/deleted/renamed)\n- Line additions/deletions count\n\n## File Status\n\n| Status     | Label | Color  |\n| ---------- | ----- | ------ |\n| `added`    | A     | Green  |\n| `modified` | M     | Yellow |\n| `deleted`  | D     | Red    |\n| `renamed`  | R     | Blue   |\n\n## Props\n\n### `<Commit />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Collapsible>` | - | Spread to the Collapsible component. |\n\n### `<CommitHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleTrigger>` | - | Spread to the CollapsibleTrigger component. |\n\n### `<CommitAuthor />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitAuthorAvatar />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `initials` | `string` | Required | Author initials to display. |\n| `...props` | `React.ComponentProps<typeof Avatar>` | - | Spread to the Avatar component. |\n\n### `<CommitInfo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitMessage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitMetadata />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitHash />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitSeparator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom separator content. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitTimestamp />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `date` | `Date` | Required | Commit date. |\n| `children` | `React.ReactNode` | - | Custom timestamp content. Defaults to relative time. |\n| `...props` | `React.HTMLAttributes<HTMLTimeElement>` | - | Spread to the time element. |\n\n### `<CommitActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `hash` | `string` | Required | Commit hash to copy. |\n| `onCopy` | `() => void` | - | Callback after successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback if copying fails. |\n| `timeout` | `number` | `2000` | Duration to show copied state (ms). |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the Button component. |\n\n### `<CommitContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CollapsibleContent>` | - | Spread to the CollapsibleContent component. |\n\n### `<CommitFiles />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the row div. |\n\n### `<CommitFileInfo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitFileStatus />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `status` | `unknown` | Required | File change status. |\n| `children` | `React.ReactNode` | - | Custom status label. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitFileIcon />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof FileIcon>` | - | Spread to the FileIcon component. |\n\n### `<CommitFilePath />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitFileChanges />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<CommitFileAdditions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `count` | `number` | Required | Number of lines added. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<CommitFileDeletions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `count` | `number` | Required | Number of lines deleted. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n<!-- File: .agents/skills/ai-elements/references/confirmation.md (Tokens: ~1846 | Category: anthropic-skill) -->\n# Confirmation\n\nAn alert-based component for managing tool execution approval workflows with request, accept, and reject states.\n\nThe `Confirmation` component provides a flexible system for displaying tool approval requests and their outcomes. Perfect for showing users when AI tools require approval before execution, and displaying the approval status afterward.\n\nSee `scripts/confirmation.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add confirmation\n```\n\n## Usage with AI SDK\n\nBuild a chat UI with tool approval workflow where dangerous tools require user confirmation before execution.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport { DefaultChatTransport, type ToolUIPart } from \"ai\";\nimport { useState } from \"react\";\nimport { CheckIcon, XIcon } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Confirmation,\n  ConfirmationTitle,\n  ConfirmationRequest,\n  ConfirmationAccepted,\n  ConfirmationRejected,\n  ConfirmationActions,\n  ConfirmationAction,\n} from \"@/components/ai-elements/confirmation\";\nimport { MessageResponse } from \"@/components/ai-elements/message\";\n\ntype DeleteFileInput = {\n  filePath: string;\n  confirm: boolean;\n};\n\ntype DeleteFileToolUIPart = ToolUIPart<{\n  delete_file: {\n    input: DeleteFileInput;\n    output: { success: boolean; message: string };\n  };\n}>;\n\nconst Example = () => {\n  const { messages, sendMessage, status, addToolApprovalResponse } = useChat({\n    transport: new DefaultChatTransport({\n      api: \"/api/chat\",\n    }),\n  });\n\n  const handleDeleteFile = () => {\n    sendMessage({ text: \"Delete the file at /tmp/example.txt\" });\n  };\n\n  const latestMessage = messages[messages.length - 1];\n  const deleteTool = latestMessage?.parts?.find(\n    (part) => part.type === \"tool-delete_file\"\n  ) as DeleteFileToolUIPart | undefined;\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full space-y-4\">\n        <Button onClick={handleDeleteFile} disabled={status !== \"ready\"}>\n          Delete Example File\n        </Button>\n\n        {deleteTool?.approval && (\n          <Confirmation approval={deleteTool.approval} state={deleteTool.state}>\n            <ConfirmationRequest>\n              This tool wants to delete:{\" \"}\n              <code>{deleteTool.input?.filePath}</code>\n              <br />\n              Do you approve this action?\n            </ConfirmationRequest>\n            <ConfirmationAccepted>\n              <CheckIcon className=\"size-4\" />\n              <span>You approved this tool execution</span>\n            </ConfirmationAccepted>\n            <ConfirmationRejected>\n              <XIcon className=\"size-4\" />\n              <span>You rejected this tool execution</span>\n            </ConfirmationRejected>\n            <ConfirmationActions>\n              <ConfirmationAction\n                variant=\"outline\"\n                onClick={() =>\n                  addToolApprovalResponse({\n                    id: deleteTool.approval!.id,\n                    approved: false,\n                  })\n                }\n              >\n                Reject\n              </ConfirmationAction>\n              <ConfirmationAction\n                variant=\"default\"\n                onClick={() =>\n                  addToolApprovalResponse({\n                    id: deleteTool.approval!.id,\n                    approved: true,\n                  })\n                }\n              >\n                Approve\n              </ConfirmationAction>\n            </ConfirmationActions>\n          </Confirmation>\n        )}\n\n        {deleteTool?.output && (\n          <MessageResponse>\n            {deleteTool.output.success\n              ? deleteTool.output.message\n              : `Error: ${deleteTool.output.message}`}\n          </MessageResponse>\n        )}\n      </div>\n    </div>\n  );\n};\n\nexport default Example;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/chat/route.tsx\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\nimport { z } from \"zod\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages: await convertToModelMessages(messages),\n    tools: {\n      delete_file: {\n        description: \"Delete a file from the file system\",\n        parameters: z.object({\n          filePath: z.string().describe(\"The path to the file to delete\"),\n          confirm: z\n            .boolean()\n            .default(false)\n            .describe(\"Confirmation that the user wants to delete the file\"),\n        }),\n        requireApproval: true, // Enable approval workflow\n        execute: async ({ filePath, confirm }) => {\n          if (!confirm) {\n            return {\n              success: false,\n              message: \"Deletion not confirmed\",\n            };\n          }\n\n          // Simulate file deletion\n          await new Promise((resolve) => setTimeout(resolve, 500));\n\n          return {\n            success: true,\n            message: `Successfully deleted ${filePath}`,\n          };\n        },\n      },\n    },\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Context-based state management for approval workflow\n- Conditional rendering based on approval state\n- Support for approval-requested, approval-responded, output-denied, and output-available states\n- Built on shadcn/ui Alert and Button components\n- TypeScript support with comprehensive type definitions\n- Customizable styling with Tailwind CSS\n- Keyboard navigation and accessibility support\n- Theme-aware with automatic dark mode support\n\n## Examples\n\n### Approval Request State\n\nShows the approval request with action buttons when state is `approval-requested`.\n\nSee `scripts/confirmation-request.tsx` for this example.\n\n### Approved State\n\nShows the accepted status when user approves and state is `approval-responded` or `output-available`.\n\nSee `scripts/confirmation-accepted.tsx` for this example.\n\n### Rejected State\n\nShows the rejected status when user rejects and state is `output-denied`.\n\nSee `scripts/confirmation-rejected.tsx` for this example.\n\n## Props\n\n### `<Confirmation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `approval` | `ToolUIPart[` | - | The approval object containing the approval ID and status. If not provided or undefined, the component will not render. |\n| `state` | `ToolUIPart[` | - | The current state of the tool (input-streaming, input-available, approval-requested, approval-responded, output-denied, or output-available). Will not render for input-streaming or input-available states. |\n| `className` | `string` | - | Additional CSS classes to apply to the Alert component. |\n| `...props` | `React.ComponentProps<typeof Alert>` | - | Any other props are spread to the Alert component. |\n\n### `<ConfirmationTitle />`\n\nA styled description element for displaying a title or label within the confirmation alert.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof AlertDescription>` | - | Any other props are spread to the underlying AlertDescription component. |\n\n### `<ConfirmationRequest />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The content to display when approval is requested. Only renders when state is  |\n\n### `<ConfirmationAccepted />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The content to display when approval is accepted. Only renders when approval.approved is true and state is  |\n\n### `<ConfirmationRejected />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | The content to display when approval is rejected. Only renders when approval.approved is false and state is  |\n\n### `<ConfirmationActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the actions container. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. Only renders when state is  |\n\n### `<ConfirmationAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component. Styled with h-8 px-3 text-sm classes by default. |\n\n<!-- File: .agents/skills/ai-elements/references/connection.md (Tokens: ~254 | Category: anthropic-skill) -->\n# Connection\n\nA custom connection line component for React Flow-based canvases with animated bezier curve styling.\n\nThe `Connection` component provides a styled connection line for React Flow canvases. It renders an animated bezier curve with a circle indicator at the target end, using consistent theming through CSS variables.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add connection\n```\n\n## Features\n\n- Smooth bezier curve animation for connection lines\n- Visual indicator circle at the target position\n- Theme-aware styling using CSS variables\n- Cubic bezier curve calculation for natural flow\n- Lightweight implementation with minimal props\n- Full TypeScript support with React Flow types\n- Compatible with React Flow's connection system\n\n## Props\n\n### `<Connection />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `fromX` | `number` | - | The x-coordinate of the connection start point. |\n| `fromY` | `number` | - | The y-coordinate of the connection start point. |\n| `toX` | `number` | - | The x-coordinate of the connection end point. |\n| `toY` | `number` | - | The y-coordinate of the connection end point. |\n\n<!-- File: .agents/skills/ai-elements/references/context.md (Tokens: ~1314 | Category: anthropic-skill) -->\n# Context\n\nA compound component system for displaying AI model context window usage, token consumption, and cost estimation.\n\nThe `Context` component provides a comprehensive view of AI model usage through a compound component system. It displays context window utilization, token consumption breakdown (input, output, reasoning, cache), and cost estimation in an interactive hover card interface.\n\nSee `scripts/context.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add context\n```\n\n## Features\n\n- **Compound Component Architecture**: Flexible composition of context display elements\n- **Visual Progress Indicator**: Circular SVG progress ring showing context usage percentage\n- **Token Breakdown**: Detailed view of input, output, reasoning, and cached tokens\n- **Cost Estimation**: Real-time cost calculation using the `tokenlens` library\n- **Intelligent Formatting**: Automatic token count formatting (K, M, B suffixes)\n- **Interactive Hover Card**: Detailed information revealed on hover\n- **Context Provider Pattern**: Clean data flow through React Context API\n- **TypeScript Support**: Full type definitions for all components\n- **Accessible Design**: Proper ARIA labels and semantic HTML\n- **Theme Integration**: Uses currentColor for automatic theme adaptation\n\n## Props\n\n### `<Context />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `maxTokens` | `number` | - | The total context window size in tokens. |\n| `usedTokens` | `number` | - | The number of tokens currently used. |\n| `usage` | `LanguageModelUsage` | - | Detailed token usage breakdown from the AI SDK (input, output, reasoning, cached tokens). |\n| `modelId` | `ModelId` | - | Model identifier for cost calculation (e.g.,  |\n| `...props` | `ComponentProps<HoverCard>` | - | Any other props are spread to the HoverCard component. |\n\n### `<ContextTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom trigger element. If not provided, renders a default button with percentage and icon. |\n| `...props` | `ComponentProps<Button>` | - | Props spread to the default button element. |\n\n### `<ContextContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes for the hover card content. |\n| `...props` | `ComponentProps<HoverCardContent>` | - | Props spread to the HoverCardContent component. |\n\n### `<ContextContentHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom header content. If not provided, renders percentage and token count with progress bar. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the header div element. |\n\n### `<ContextContentBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Body content, typically containing usage breakdown components. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the body div element. |\n\n### `<ContextContentFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom footer content. If not provided, renders total cost when modelId is provided. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the footer div element. |\n\n### Usage Components\n\nAll usage components (`ContextInputUsage`, `ContextOutputUsage`, `ContextReasoningUsage`, `ContextCacheUsage`) share the same props:\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom content. If not provided, renders token count and cost for the respective usage type. |\n| `className` | `string` | - | Additional CSS classes. |\n| `...props` | `ComponentProps<div>` | - | Props spread to the div element. |\n\n## Component Architecture\n\nThe Context component uses a compound component pattern with React Context for data sharing:\n\n1. **`<Context>`** - Root provider component that holds all context data\n2. **`<ContextTrigger>`** - Interactive trigger element (default: button with percentage)\n3. **`<ContextContent>`** - Hover card content container\n4. **`<ContextContentHeader>`** - Header section with progress visualization\n5. **`<ContextContentBody>`** - Body section for usage breakdowns\n6. **`<ContextContentFooter>`** - Footer section for total cost\n7. **Usage Components** - Individual token usage displays (Input, Output, Reasoning, Cache)\n\n## Token Formatting\n\nThe component uses `Intl.NumberFormat` with compact notation for automatic formatting:\n\n- Under 1,000: Shows exact count (e.g., \"842\")\n- 1,000+: Shows with K suffix (e.g., \"32K\")\n- 1,000,000+: Shows with M suffix (e.g., \"1.5M\")\n- 1,000,000,000+: Shows with B suffix (e.g., \"2.1B\")\n\n## Cost Calculation\n\nWhen a `modelId` is provided, the component automatically calculates costs using the `tokenlens` library:\n\n- **Input tokens**: Cost based on model's input pricing\n- **Output tokens**: Cost based on model's output pricing\n- **Reasoning tokens**: Special pricing for reasoning-capable models\n- **Cached tokens**: Reduced pricing for cached input tokens\n- **Total cost**: Sum of all token type costs\n\nCosts are formatted using `Intl.NumberFormat` with USD currency.\n\n## Styling\n\nThe component uses Tailwind CSS classes and follows your design system:\n\n- Progress indicator uses `currentColor` for theme adaptation\n- Hover card has customizable width and padding\n- Footer has a secondary background for visual separation\n- All text sizes use the `text-xs` class for consistency\n- Muted foreground colors for secondary information\n\n<!-- File: .agents/skills/ai-elements/references/controls.md (Tokens: ~212 | Category: anthropic-skill) -->\n# Controls\n\nA styled controls component for React Flow-based canvases with zoom and fit view functionality.\n\nThe `Controls` component provides interactive zoom and fit view controls for React Flow canvases. It includes a modern, themed design with backdrop blur and card styling.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add controls\n```\n\n## Features\n\n- Zoom in/out controls\n- Fit view button to center and scale content\n- Rounded pill design with backdrop blur\n- Theme-aware card background\n- Subtle drop shadow for depth\n- Full TypeScript support\n- Compatible with all React Flow control features\n\n## Props\n\n### `<Controls />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the controls. |\n| `...props` | `ComponentProps<typeof Controls>` | - | Any other props from @xyflow/react Controls component (showZoom, showFitView, showInteractive, position, etc.). |\n\n<!-- File: .agents/skills/ai-elements/references/conversation.md (Tokens: ~1640 | Category: anthropic-skill) -->\n# Conversation\n\nWraps messages and automatically scrolls to the bottom. Also includes a scroll button that appears when not at the bottom.\n\nThe `Conversation` component wraps messages and automatically scrolls to the bottom. Also includes a scroll button that appears when not at the bottom.\n\n<Preview path=\"conversation\" className=\"p-0\" />\n\n## Installation\n\n```bash\nnpx ai-elements@latest add conversation\n```\n\n## Usage with AI SDK\n\nBuild a simple conversational UI with `Conversation` and [`PromptInput`](/components/prompt-input):\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationDownload,\n  ConversationEmptyState,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from \"@/components/ai-elements/message\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { MessageSquare } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useChat } from \"@ai-sdk/react\";\n\nconst ConversationDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { messages, sendMessage, status } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.length === 0 ? (\n              <ConversationEmptyState\n                icon={<MessageSquare className=\"size-12\" />}\n                title=\"Start a conversation\"\n                description=\"Type a message below to begin chatting\"\n              />\n            ) : (\n              messages.map((message) => (\n                <Message from={message.role} key={message.id}>\n                  <MessageContent>\n                    {message.parts.map((part, i) => {\n                      switch (part.type) {\n                        case \"text\": // we don't use any reasoning or tool calls in this example\n                          return (\n                            <MessageResponse key={`${message.id}-${i}`}>\n                              {part.text}\n                            </MessageResponse>\n                          );\n                        default:\n                          return null;\n                      }\n                    })}\n                  </MessageContent>\n                </Message>\n              ))\n            )}\n          </ConversationContent>\n          <ConversationDownload messages={messages} />\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Say something...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ConversationDemo;\n```\n\nAdd the following route to your backend:\n\n```tsx title=\"api/chat/route.ts\"\nimport { streamText, UIMessage, convertToModelMessages } from \"ai\";\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { messages }: { messages: UIMessage[] } = await req.json();\n\n  const result = streamText({\n    model: \"openai/gpt-4o\",\n    messages: await convertToModelMessages(messages),\n  });\n\n  return result.toUIMessageStreamResponse();\n}\n```\n\n## Features\n\n- Automatic scrolling to the bottom when new messages are added\n- Smooth scrolling behavior with configurable animation\n- Scroll button that appears when not at the bottom\n- Download conversation as Markdown\n- Responsive design with customizable padding and spacing\n- Flexible content layout with consistent message spacing\n- Accessible with proper ARIA roles for screen readers\n- Customizable styling through className prop\n- Support for any number of child message components\n\n## Props\n\n### `<Conversation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `contextRef` | `React.Ref<StickToBottomContext>` | - | Optional ref to access the StickToBottom context object. |\n| `instance` | `StickToBottomInstance` | - | Optional instance for controlling the StickToBottom component. |\n| `children` | `((context: StickToBottomContext) => ReactNode) | ReactNode` | - | Render prop or ReactNode for custom rendering with context. |\n| `...props` | `Omit<React.HTMLAttributes<HTMLDivElement>, ` | - | Any other props are spread to the root div. |\n\n### `<ConversationContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `((context: StickToBottomContext) => ReactNode) | ReactNode` | - | Render prop or ReactNode for custom rendering with context. |\n| `...props` | `Omit<React.HTMLAttributes<HTMLDivElement>, ` | - | Any other props are spread to the root div. |\n\n### `<ConversationEmptyState />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | - | The title text to display. |\n| `description` | `string` | - | The description text to display. |\n| `icon` | `React.ReactNode` | - | Optional icon to display above the text. |\n| `children` | `React.ReactNode` | - | Optional additional content to render below the text. |\n| `...props` | `ComponentProps<` | - | Any other props are spread to the root div. |\n\n### `<ConversationScrollButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<ConversationDownload />`\n\nA button that downloads the conversation as a Markdown file.\n\n```tsx\nimport { ConversationDownload } from \"@/components/ai-elements/conversation\";\n\n<Conversation>\n  <ConversationContent>\n    {messages.map(...)}\n  </ConversationContent>\n  <ConversationDownload messages={messages} />\n  <ConversationScrollButton />\n</Conversation>\n```\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `messages` | `UIMessage[]` | Required | Array of messages to include in the download. |\n| `filename` | `string` | - | The filename for the downloaded file. |\n| `formatMessage` | `(message: UIMessage, index: number) => string` | - | Custom function to format each message in the output. |\n| `...props` | `Omit<ComponentProps<typeof Button>, ` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `messagesToMarkdown`\n\nA utility function to convert messages to Markdown format. Useful for custom download implementations.\n\n```tsx\nimport { messagesToMarkdown } from \"@/components/ai-elements/conversation\";\n\nconst markdown = messagesToMarkdown(messages);\n\n// With custom formatter\nconst customMarkdown = messagesToMarkdown(\n  messages,\n  (msg, i) =>\n    `[${msg.role}]: ${msg.parts\n      .filter((p) => p.type === \"text\")\n      .map((p) => p.text)\n      .join(\"\")}`\n);\n```\n\n<!-- File: .agents/skills/ai-elements/references/edge.md (Tokens: ~497 | Category: anthropic-skill) -->\n# Edge\n\nCustomizable edge components for React Flow canvases with animated and temporary states.\n\nThe `Edge` component provides two pre-styled edge types for React Flow canvases: `Temporary` for dashed temporary connections and `Animated` for connections with animated indicators.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add edge\n```\n\n## Features\n\n- Two distinct edge types: Temporary and Animated\n- Temporary edges use dashed lines with ring color\n- Animated edges include a moving circle indicator\n- Automatic handle position calculation\n- Smart offset calculation based on handle type and position\n- Uses Bezier curves for smooth, natural-looking connections\n- Fully compatible with React Flow's edge system\n- Type-safe implementation with TypeScript\n\n## Edge Types\n\n### `Edge.Temporary`\n\nA dashed edge style for temporary or preview connections. Uses a simple Bezier path with a dashed stroke pattern.\n\n### `Edge.Animated`\n\nA solid edge with an animated circle that moves along the path. The animation repeats indefinitely with a 2-second duration, providing visual feedback for active connections.\n\n## Props\n\nBoth edge types accept standard React Flow `EdgeProps`:\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `id` | `string` | - | Unique identifier for the edge. |\n| `source` | `string` | - | ID of the source node. |\n| `target` | `string` | - | ID of the target node. |\n| `sourceX` | `number` | - | X coordinate of the source handle (Temporary only). |\n| `sourceY` | `number` | - | Y coordinate of the source handle (Temporary only). |\n| `targetX` | `number` | - | X coordinate of the target handle (Temporary only). |\n| `targetY` | `number` | - | Y coordinate of the target handle (Temporary only). |\n| `sourcePosition` | `Position` | - | Position of the source handle (Left, Right, Top, Bottom). |\n| `targetPosition` | `Position` | - | Position of the target handle (Left, Right, Top, Bottom). |\n| `markerEnd` | `string` | - | SVG marker ID for the edge end (Animated only). |\n| `style` | `React.CSSProperties` | - | Custom styles for the edge (Animated only). |\n\n<!-- File: .agents/skills/ai-elements/references/environment-variables.md (Tokens: ~894 | Category: anthropic-skill) -->\n# Environment Variables\n\nDisplay environment variables with masking and copy functionality.\n\nThe `EnvironmentVariables` component displays environment variables with value masking, visibility toggle, and copy functionality.\n\nSee `scripts/environment-variables.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add environment-variables\n```\n\n## Features\n\n- Value masking by default\n- Toggle visibility switch\n- Copy individual values\n- Export format support (`export KEY=\"value\"`)\n- Required badge indicator\n\n## Props\n\n### `<EnvironmentVariables />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `showValues` | `boolean` | - | Controlled visibility state. |\n| `defaultShowValues` | `boolean` | `false` | Default visibility state. |\n| `onShowValuesChange` | `(show: boolean) => void` | - | Callback when visibility changes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<EnvironmentVariablesHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the header div. |\n\n### `<EnvironmentVariablesTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom title text. |\n| `...props` | `React.HTMLAttributes<HTMLHeadingElement>` | - | Spread to the h3 element. |\n\n### `<EnvironmentVariablesToggle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Switch>` | - | Spread to the Switch component. |\n\n### `<EnvironmentVariablesContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the content div. |\n\n### `<EnvironmentVariable />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | Variable name. |\n| `value` | `string` | Required | Variable value. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the row div. |\n\n### `<EnvironmentVariableGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the group div. |\n\n### `<EnvironmentVariableName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom name content. Defaults to the name from context. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<EnvironmentVariableValue />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom value content. Defaults to the masked/unmasked value from context. |\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Spread to the span element. |\n\n### `<EnvironmentVariableCopyButton />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `copyFormat` | `unknown` | - | Format to copy. |\n| `onCopy` | `() => void` | - | Callback after successful copy. |\n| `onError` | `(error: Error) => void` | - | Callback if copying fails. |\n| `timeout` | `number` | `2000` | Duration to show copied state (ms). |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the Button component. |\n\n### `<EnvironmentVariableRequired />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom badge text. |\n| `...props` | `React.ComponentProps<typeof Badge>` | - | Spread to the Badge component. |\n\n<!-- File: .agents/skills/ai-elements/references/file-tree.md (Tokens: ~511 | Category: anthropic-skill) -->\n# File Tree\n\nDisplay hierarchical file and folder structure with expand/collapse functionality.\n\nThe `FileTree` component displays a hierarchical file system structure with expandable folders and file selection.\n\nSee `scripts/file-tree.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add file-tree\n```\n\n## Features\n\n- Hierarchical folder structure\n- Expand/collapse folders\n- File selection with callback\n- Keyboard accessible\n- Customizable icons\n- Controlled and uncontrolled modes\n\n## Examples\n\n### Basic Usage\n\nSee `scripts/file-tree-basic.tsx` for this example.\n\n### With Selection\n\nSee `scripts/file-tree-selection.tsx` for this example.\n\n### Default Expanded\n\nSee `scripts/file-tree-expanded.tsx` for this example.\n\n## Props\n\n### `<FileTree />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `expanded` | `Set<string>` | - | Controlled expanded paths. |\n| `defaultExpanded` | `Set<string>` | `new Set()` | Default expanded paths. |\n| `selectedPath` | `string` | - | Currently selected file/folder path. |\n| `onSelect` | `(path: string) => void` | - | Callback when a file/folder is selected. |\n| `onExpandedChange` | `(expanded: Set<string>) => void` | - | Callback when expanded paths change. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<FileTreeFolder />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `path` | `string` | - | Unique folder path. |\n| `name` | `string` | - | Display name. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### `<FileTreeFile />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `path` | `string` | - | Unique file path. |\n| `name` | `string` | - | Display name. |\n| `icon` | `ReactNode` | - | Custom file icon. |\n| `className` | `string` | - | Additional CSS classes. |\n\n### Subcomponents\n\n- `FileTreeIcon` - Icon wrapper\n- `FileTreeName` - Name text\n- `FileTreeActions` - Action buttons container (stops click propagation)\n\n<!-- File: .agents/skills/ai-elements/references/image.md (Tokens: ~944 | Category: anthropic-skill) -->\n# Image\n\nDisplays AI-generated images from the AI SDK.\n\nThe `Image` component displays AI-generated images from the AI SDK. It accepts a [`Experimental_GeneratedImage`](/docs/reference/ai-sdk-core/generate-image) object from the AI SDK's `generateImage` function and automatically renders it as an image.\n\nSee `scripts/image.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add image\n```\n\n## Usage with AI SDK\n\nBuild a simple app allowing a user to generate an image given a prompt.\n\nInstall the `@ai-sdk/openai` package:\n\n```package-install\nnpm i @ai-sdk/openai\n```\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { Image } from \"@/components/ai-elements/image\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { useState } from \"react\";\nimport { Spinner } from \"@/components/ui/spinner\";\n\nconst ImageDemo = () => {\n  const [prompt, setPrompt] = useState(\"A futuristic cityscape at sunset\");\n  const [imageData, setImageData] = useState<any>(null);\n  const [isLoading, setIsLoading] = useState(false);\n\n  const handleSubmit = async (message: PromptInputMessage) => {\n    if (!message.text.trim()) return;\n    setPrompt(\"\");\n\n    setIsLoading(true);\n    try {\n      const response = await fetch(\"/api/image\", {\n        method: \"POST\",\n        body: JSON.stringify({ prompt: message.text.trim() }),\n      });\n\n      const data = await response.json();\n\n      setImageData(data);\n    } catch (error) {\n      console.error(\"Error generating image:\", error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <div className=\"flex-1 overflow-y-auto p-4\">\n          {imageData && (\n            <div className=\"flex justify-center\">\n              <Image\n                {...imageData}\n                alt=\"Generated image\"\n                className=\"h-[300px] aspect-square border rounded-lg\"\n              />\n            </div>\n          )}\n          {isLoading && <Spinner />}\n        </div>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={prompt}\n            placeholder=\"Describe the image you want to generate...\"\n            onChange={(e) => setPrompt(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={isLoading ? \"submitted\" : \"ready\"}\n            disabled={!prompt.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ImageDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/image/route.ts\"\nimport { openai } from \"@ai-sdk/openai\";\nimport { experimental_generateImage } from \"ai\";\n\nexport async function POST(req: Request) {\n  const { prompt }: { prompt: string } = await req.json();\n\n  const { image } = await experimental_generateImage({\n    model: openai.image(\"dall-e-3\"),\n    prompt: prompt,\n    size: \"1024x1024\",\n  });\n\n  return Response.json({\n    base64: image.base64,\n    uint8Array: image.uint8Array,\n    mediaType: image.mediaType,\n  });\n}\n```\n\n## Features\n\n- Accepts `Experimental_GeneratedImage` objects directly from the AI SDK\n- Automatically creates proper data URLs from base64-encoded image data\n- Supports all standard HTML image attributes\n- Responsive by default with `max-w-full h-auto` styling\n- Customizable with additional CSS classes\n- Includes proper TypeScript types for AI SDK compatibility\n\n## Props\n\n### `<Image />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `alt` | `string` | - | Alternative text for the image. |\n| `className` | `string` | - | Additional CSS classes to apply to the image. |\n| `...props` | `Experimental_GeneratedImage` | - | The image data to display, as returned by the AI SDK. |\n\n<!-- File: .agents/skills/ai-elements/references/inline-citation.md (Tokens: ~2311 | Category: anthropic-skill) -->\n# Inline Citation\n\nA hoverable citation component that displays source information and quotes inline with text, perfect for AI-generated content with references.\n\nThe `InlineCitation` component provides a way to display citations inline with text content, similar to academic papers or research documents. It consists of a citation pill that shows detailed source information on hover, making it perfect for AI-generated content that needs to reference sources.\n\nSee `scripts/inline-citation.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add inline-citation\n```\n\n## Usage with AI SDK\n\nBuild citations for AI-generated content using [`experimental_generateObject`](/docs/reference/ai-sdk-ui/use-object).\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { experimental_useObject as useObject } from \"@ai-sdk/react\";\nimport {\n  InlineCitation,\n  InlineCitationText,\n  InlineCitationCard,\n  InlineCitationCardTrigger,\n  InlineCitationCardBody,\n  InlineCitationCarousel,\n  InlineCitationCarouselContent,\n  InlineCitationCarouselItem,\n  InlineCitationCarouselHeader,\n  InlineCitationCarouselIndex,\n  InlineCitationCarouselPrev,\n  InlineCitationCarouselNext,\n  InlineCitationSource,\n  InlineCitationQuote,\n} from \"@/components/ai-elements/inline-citation\";\nimport { Button } from \"@/components/ui/button\";\nimport { citationSchema } from \"@/app/api/citation/route\";\n\nconst CitationDemo = () => {\n  const { object, submit, isLoading } = useObject({\n    api: \"/api/citation\",\n    schema: citationSchema,\n  });\n\n  const handleSubmit = (topic: string) => {\n    submit({ prompt: topic });\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 space-y-6\">\n      <div className=\"flex gap-2 mb-6\">\n        <Button\n          onClick={() => handleSubmit(\"artificial intelligence\")}\n          disabled={isLoading}\n          variant=\"outline\"\n        >\n          Generate AI Content\n        </Button>\n        <Button\n          onClick={() => handleSubmit(\"climate change\")}\n          disabled={isLoading}\n          variant=\"outline\"\n        >\n          Generate Climate Content\n        </Button>\n      </div>\n\n      {isLoading && !object && (\n        <div className=\"text-muted-foreground\">\n          Generating content with citations...\n        </div>\n      )}\n\n      {object?.content && (\n        <div className=\"prose prose-sm max-w-none\">\n          <p className=\"leading-relaxed\">\n            {object.content.split(/(\\[\\d+\\])/).map((part, index) => {\n              const citationMatch = part.match(/\\[(\\d+)\\]/);\n              if (citationMatch) {\n                const citationNumber = citationMatch[1];\n                const citation = object.citations?.find(\n                  (c: any) => c.number === citationNumber\n                );\n\n                if (citation) {\n                  return (\n                    <InlineCitation key={index}>\n                      <InlineCitationCard>\n                        <InlineCitationCardTrigger sources={[citation.url]} />\n                        <InlineCitationCardBody>\n                          <InlineCitationCarousel>\n                            <InlineCitationCarouselHeader>\n                              <InlineCitationCarouselPrev />\n                              <InlineCitationCarouselNext />\n                              <InlineCitationCarouselIndex />\n                            </InlineCitationCarouselHeader>\n                            <InlineCitationCarouselContent>\n                              <InlineCitationCarouselItem>\n                                <InlineCitationSource\n                                  title={citation.title}\n                                  url={citation.url}\n                                  description={citation.description}\n                                />\n                                {citation.quote && (\n                                  <InlineCitationQuote>\n                                    {citation.quote}\n                                  </InlineCitationQuote>\n                                )}\n                              </InlineCitationCarouselItem>\n                            </InlineCitationCarouselContent>\n                          </InlineCitationCarousel>\n                        </InlineCitationCardBody>\n                      </InlineCitationCard>\n                    </InlineCitation>\n                  );\n                }\n              }\n              return part;\n            })}\n          </p>\n        </div>\n      )}\n    </div>\n  );\n};\n\nexport default CitationDemo;\n```\n\nAdd the following route to your backend:\n\n```ts title=\"app/api/citation/route.ts\"\nimport { streamObject } from \"ai\";\nimport { z } from \"zod\";\n\nexport const citationSchema = z.object({\n  content: z.string(),\n  citations: z.array(\n    z.object({\n      number: z.string(),\n      title: z.string(),\n      url: z.string(),\n      description: z.string().optional(),\n      quote: z.string().optional(),\n    })\n  ),\n});\n\n// Allow streaming responses up to 30 seconds\nexport const maxDuration = 30;\n\nexport async function POST(req: Request) {\n  const { prompt } = await req.json();\n\n  const result = streamObject({\n    model: \"openai/gpt-4o\",\n    schema: citationSchema,\n    prompt: `Generate a well-researched paragraph about ${prompt} with proper citations. \n    \n    Include:\n    - A comprehensive paragraph with inline citations marked as [1], [2], etc.\n    - 2-3 citations with realistic source information\n    - Each citation should have a title, URL, and optional description/quote\n    - Make the content informative and the sources credible\n    \n    Format citations as numbered references within the text.`,\n  });\n\n  return result.toTextStreamResponse();\n}\n```\n\n## Features\n\n- Hover interaction to reveal detailed citation information\n- **Carousel navigation** for multiple citations with prev/next controls\n- **Live index tracking** showing current slide position (e.g., \"1/5\")\n- Support for source titles, URLs, and descriptions\n- Optional quote blocks for relevant excerpts\n- Composable architecture for flexible citation formats\n- Accessible design with proper keyboard navigation\n- Seamless integration with AI-generated content\n- Clean visual design that doesn't disrupt reading flow\n- Smart badge display showing source hostname and count\n\n## Usage with AI SDK\n\nCurrently, there is no official support for inline citations with Streamdown or the Response component. This is because:\n\n- There isn't any good markdown syntax for inline citations\n- Language models don't naturally respond with inline citation syntax\n- The AI SDK doesn't have built-in support for inline citations\n\n### Potential Approaches\n\nWhile these methods are hypothetical and not officially supported, there are two conceptual ways inline citations could work with Streamdown:\n\n1. **Footnote conversion**: GitHub Flavored Markdown (GFM) handles footnotes using `[^1]` syntax. You could hypothetically remove the default footnote rendering and convert footnotes to inline citations instead.\n\n2. **Custom HTML syntax**: You could add a system prompt instructing the model to use a special HTML syntax like `<citation />` and pass that as a custom component to Streamdown.\n\nThese approaches require custom implementation and are not currently supported out of the box. We will investigate official support for this use case in the future.\n\nFor now, the recommended approach is to use `experimental_useObject` (as shown in the usage example above) to generate structured citation data, then manually parse and render inline citations.\n\n## Props\n\n### `<InlineCitation />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root span element. |\n\n### `<InlineCitationText />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying span element. |\n\n### `<InlineCitationCard />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the HoverCard component. |\n\n### `<InlineCitationCardTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `sources` | `string[]` | - | Array of source URLs. The length determines the number displayed in the badge. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying button element. |\n\n### `<InlineCitationCardBody />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationCarousel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Carousel>` | - | Any other props are spread to the underlying Carousel component. |\n\n### `<InlineCitationCarouselContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying CarouselContent component. |\n\n### `<InlineCitationCarouselItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationCarouselHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationCarouselIndex />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. Children will override the default index display. |\n\n### `<InlineCitationCarouselPrev />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CarouselPrevious>` | - | Any other props are spread to the underlying CarouselPrevious component. |\n\n### `<InlineCitationCarouselNext />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CarouselNext>` | - | Any other props are spread to the underlying CarouselNext component. |\n\n### `<InlineCitationSource />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `string` | - | The title of the source. |\n| `url` | `string` | - | The URL of the source. |\n| `description` | `string` | - | A brief description of the source. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |\n\n### `<InlineCitationQuote />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying blockquote element. |\n\n<!-- File: .agents/skills/ai-elements/references/jsx-preview.md (Tokens: ~771 | Category: anthropic-skill) -->\n# JSX Preview\n\nA component that dynamically renders JSX strings with streaming support for AI-generated UI.\n\nThe `JSXPreview` component renders JSX strings dynamically, supporting streaming scenarios where JSX may be incomplete. It automatically closes unclosed tags during streaming, making it ideal for displaying AI-generated UI components in real-time.\n\nSee `scripts/jsx-preview.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add jsx-preview\n```\n\n## Features\n\n- Renders JSX strings dynamically using `react-jsx-parser`\n- Streaming support with automatic tag completion\n- Custom component injection for rendering your own components\n- Error handling with customizable error display\n- Context-based architecture for flexible composition\n\n## Usage with AI SDK\n\nThe JSXPreview component integrates with the AI SDK to render generated UI in real-time:\n\n```tsx title=\"components/generated-ui.tsx\"\n\"use client\";\n\nimport {\n  JSXPreview,\n  JSXPreviewContent,\n  JSXPreviewError,\n} from \"@/components/ai-elements/jsx-preview\";\n\ntype GeneratedUIProps = {\n  jsx: string;\n  isStreaming: boolean;\n};\n\nexport const GeneratedUI = ({ jsx, isStreaming }: GeneratedUIProps) => (\n  <JSXPreview\n    jsx={jsx}\n    isStreaming={isStreaming}\n    onError={(error) => console.error(\"JSX Parse Error:\", error)}\n  >\n    <JSXPreviewContent />\n    <JSXPreviewError />\n  </JSXPreview>\n);\n```\n\n### With Custom Components\n\nYou can inject custom components to be used within the rendered JSX:\n\n```tsx title=\"components/generated-ui-with-components.tsx\"\n\"use client\";\n\nimport {\n  JSXPreview,\n  JSXPreviewContent,\n} from \"@/components/ai-elements/jsx-preview\";\nimport { Button } from \"@/components/ui/button\";\nimport { Card } from \"@/components/ui/card\";\n\nconst customComponents = {\n  Button,\n  Card,\n};\n\nexport const GeneratedUIWithComponents = ({ jsx }: { jsx: string }) => (\n  <JSXPreview jsx={jsx} components={customComponents}>\n    <JSXPreviewContent />\n  </JSXPreview>\n);\n```\n\n## Props\n\n### `<JSXPreview />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `jsx` | `string` | Required | The JSX string to render. |\n| `isStreaming` | `boolean` | `false` | When true, automatically completes unclosed tags. |\n| `components` | `Record<string, React.ComponentType>` | - | Custom components available within the rendered JSX. |\n| `bindings` | `Record<string, unknown>` | - | Variables and functions available within the JSX scope. |\n| `onError` | `(error: Error) => void` | - | Callback fired when a parsing or rendering error occurs. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n### `<JSXPreviewContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `renderError` | `JsxParserProps[` | - | Custom error renderer passed to react-jsx-parser. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n### `<JSXPreviewError />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode | ((error: Error) => ReactNode)` | - | Custom error content or render function receiving the error. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n<!-- File: .agents/skills/ai-elements/references/message.md (Tokens: ~2007 | Category: anthropic-skill) -->\n# Message\n\nA comprehensive suite of components for displaying chat messages, including message rendering, branching, actions, and markdown responses.\n\nThe `Message` component suite provides a complete set of tools for building chat interfaces. It includes components for displaying messages from users and AI assistants, managing multiple response branches, adding action buttons, and rendering markdown content.\n\nSee `scripts/message.tsx` for this example.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add message\n```\n\n## Features\n\n- Displays messages from both user and AI assistant with distinct styling and automatic alignment\n- Minimalist flat design with user messages in secondary background and assistant messages full-width\n- **Response branching** with navigation controls to switch between multiple AI response versions\n- **Markdown rendering** with GFM support (tables, task lists, strikethrough), math equations, and smart streaming\n- **Action buttons** for common operations (retry, like, dislike, copy, share) with tooltips and state management\n- **File attachments** display with support for images and generic files with preview and remove functionality\n- Code blocks with syntax highlighting and copy-to-clipboard functionality\n- Keyboard accessible with proper ARIA labels\n- Responsive design that adapts to different screen sizes\n- Seamless light/dark theme integration\n\n\n\n## Usage with AI SDK\n\nBuild a simple chat UI where the user can copy or regenerate the most recent message.\n\nAdd the following component to your frontend:\n\n```tsx title=\"app/page.tsx\"\n\"use client\";\n\nimport { useState } from \"react\";\nimport {\n  MessageActions,\n  MessageAction,\n} from \"@/components/ai-elements/message\";\nimport { Message, MessageContent } from \"@/components/ai-elements/message\";\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from \"@/components/ai-elements/conversation\";\nimport {\n  PromptInput,\n  type PromptInputMessage,\n  PromptInputTextarea,\n  PromptInputSubmit,\n} from \"@/components/ai-elements/prompt-input\";\nimport { MessageResponse } from \"@/components/ai-elements/message\";\nimport { RefreshCcwIcon, CopyIcon } from \"lucide-react\";\nimport { useChat } from \"@ai-sdk/react\";\nimport { Fragment } from \"react\";\n\nconst ActionsDemo = () => {\n  const [input, setInput] = useState(\"\");\n  const { messages, sendMessage, status, regenerate } = useChat();\n\n  const handleSubmit = (message: PromptInputMessage) => {\n    if (message.text.trim()) {\n      sendMessage({ text: message.text });\n      setInput(\"\");\n    }\n  };\n\n  return (\n    <div className=\"max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]\">\n      <div className=\"flex flex-col h-full\">\n        <Conversation>\n          <ConversationContent>\n            {messages.map((message, messageIndex) => (\n              <Fragment key={message.id}>\n                {message.parts.map((part, i) => {\n                  switch (part.type) {\n                    case \"text\":\n                      const isLastMessage =\n                        messageIndex === messages.length - 1;\n\n                      return (\n                        <Fragment key={`${message.id}-${i}`}>\n                          <Message from={message.role}>\n                            <MessageContent>\n                              <MessageResponse>{part.text}</MessageResponse>\n                            </MessageContent>\n                          </Message>\n                          {message.role === \"assistant\" && isLastMessage && (\n                            <MessageActions>\n                              <MessageAction\n                                onClick={() => regenerate()}\n                                label=\"Retry\"\n                              >\n                                <RefreshCcwIcon className=\"size-3\" />\n                              </MessageAction>\n                              <MessageAction\n                                onClick={() =>\n                                  navigator.clipboard.writeText(part.text)\n                                }\n                                label=\"Copy\"\n                              >\n                                <CopyIcon className=\"size-3\" />\n                              </MessageAction>\n                            </MessageActions>\n                          )}\n                        </Fragment>\n                      );\n                    default:\n                      return null;\n                  }\n                })}\n              </Fragment>\n            ))}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n\n        <PromptInput\n          onSubmit={handleSubmit}\n          className=\"mt-4 w-full max-w-2xl mx-auto relative\"\n        >\n          <PromptInputTextarea\n            value={input}\n            placeholder=\"Say something...\"\n            onChange={(e) => setInput(e.currentTarget.value)}\n            className=\"pr-12\"\n          />\n          <PromptInputSubmit\n            status={status === \"streaming\" ? \"streaming\" : \"ready\"}\n            disabled={!input.trim()}\n            className=\"absolute bottom-1 right-1\"\n          />\n        </PromptInput>\n      </div>\n    </div>\n  );\n};\n\nexport default ActionsDemo;\n```\n\n## Props\n\n### `<Message />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `from` | `UIMessage[` | - | The role of the message sender ( |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the content div. |\n\n### `<MessageResponse />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `string` | - | The markdown content to render. |\n| `parseIncompleteMarkdown` | `boolean` | `true` | Whether to parse and fix incomplete markdown syntax (e.g., unclosed code blocks or lists). |\n| `className` | `string` | - | CSS class names to apply to the wrapper div element. |\n| `components` | `object` | - | Custom React components to use for rendering markdown elements (e.g., custom heading, paragraph, code block components). |\n| `allowedImagePrefixes` | `string[]` | `[` | Array of allowed URL prefixes for images. Use [ |\n| `allowedLinkPrefixes` | `string[]` | `[` | Array of allowed URL prefixes for links. Use [ |\n| `defaultOrigin` | `string` | - | Default origin to use for relative URLs in links and images. |\n| `rehypePlugins` | `array` | `[rehypeKatex]` | Array of rehype plugins to use for processing HTML. Includes KaTeX for math rendering by default. |\n| `remarkPlugins` | `array` | `[remarkGfm, remarkMath]` | Array of remark plugins to use for processing markdown. Includes GitHub Flavored Markdown and math support by default. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageActions />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | HTML attributes to spread to the root div. |\n\n### `<MessageAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `tooltip` | `string` | - | Optional tooltip text shown on hover. |\n| `label` | `string` | - | Accessible label for screen readers. Also used as fallback if tooltip is not provided. |\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<MessageBranch />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultBranch` | `number` | `0` | The index of the branch to show by default. |\n| `onBranchChange` | `(branchIndex: number) => void` | - | Callback fired when the branch changes. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageBranchContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |\n\n### `<MessageBranchSelector />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof ButtonGroup>` | - | Any other props are spread to the underlying ButtonGroup component. |\n\n### `<MessageBranchPrevious />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<MessageBranchNext />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |\n\n### `<MessageBranchPage />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the underlying span element. |\n\n### `<MessageToolbar />`\n\nA container for placing actions and branch selectors below a message. Lays out children in a horizontal row with space-between alignment.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root div. |\n```\n\n<!-- File: .agents/skills/ai-elements/references/mic-selector.md (Tokens: ~1728 | Category: anthropic-skill) -->\n# Mic Selector\n\nA composable dropdown component for selecting audio input devices with permission handling and device change detection.\n\nThe `MicSelector` component provides a flexible and composable interface for selecting microphone input devices. Built on shadcn/ui's Command and Popover components, it features automatic device detection, permission handling, dynamic device list updates, and intelligent device name parsing.\n\nSee `scripts/mic-selector.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add mic-selector\n```\n\n## Features\n\n- Fully composable architecture with granular control components\n- Automatic audio input device enumeration\n- Permission-based device name display\n- Real-time device change detection via devicechange events\n- Intelligent device label parsing with ID extraction\n- Controlled and uncontrolled component patterns\n- Responsive width matching between trigger and content\n- Built on shadcn/ui Command and Popover components\n- Full TypeScript support with proper types for all components\n\n## Props\n\n### `<MicSelector />`\n\nRoot Popover component that provides context for all child components.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultValue` | `string` | - | The default selected device ID (uncontrolled). |\n| `value` | `string` | - | The selected device ID (controlled). |\n| `onValueChange` | `(deviceId: string) => void` | - | Callback fired when the selected device changes. |\n| `defaultOpen` | `boolean` | `false` | The default open state (uncontrolled). |\n| `open` | `boolean` | - | The open state (controlled). |\n| `onOpenChange` | `(open: boolean) => void` | - | Callback fired when the open state changes. Automatically requests microphone permission when opened without permission. |\n| `...props` | `React.ComponentProps<typeof Popover>` | - | Any other props are spread to the Popover component. |\n\n### `<MicSelectorTrigger />`\n\nButton that opens the microphone selector popover. Automatically tracks its width to match the popover content.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component. |\n\n### `<MicSelectorValue />`\n\nDisplays the currently selected microphone name or a placeholder.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n### `<MicSelectorContent />`\n\nContainer for the Command component, rendered inside the popover.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `popoverOptions` | `React.ComponentProps<typeof PopoverContent>` | - | Props to pass to the underlying PopoverContent component. |\n| `...props` | `React.ComponentProps<typeof Command>` | - | Any other props are spread to the Command component. |\n\n### `<MicSelectorInput />`\n\nSearch input for filtering microphones.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the CommandInput component. |\n\n### `<MicSelectorList />`\n\nWrapper for the list of microphone items. Uses render props pattern to provide access to device data.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `(devices: MediaDeviceInfo[]) => ReactNode` | - | Render function that receives the array of available devices. |\n| `...props` | `Omit<React.ComponentProps<typeof CommandList>, ` | - | Any other props are spread to the CommandList component. |\n\n### `<MicSelectorEmpty />`\n\nMessage shown when no microphones match the search.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode` | - | The message to display. |\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the CommandEmpty component. |\n\n### `<MicSelectorItem />`\n\nSelectable item representing a microphone.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `value` | `string` | - | The device ID for this item. |\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the CommandItem component. |\n\n### `<MicSelectorLabel />`\n\nDisplays a formatted microphone label with intelligent device ID parsing. Automatically extracts and styles device IDs in the format (XXXX:XXXX).\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `device` | `MediaDeviceInfo` | - | The MediaDeviceInfo object for the device. |\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the span element. |\n\n## Hooks\n\n### `useAudioDevices()`\n\nA custom hook for managing audio input devices. This hook is used internally by the `MicSelector` component but can also be used independently.\n\n```tsx\nimport { useAudioDevices } from \"@repo/elements/mic-selector\";\n\nexport default function Example() {\n  const { devices, loading, error, hasPermission, loadDevices } =\n    useAudioDevices();\n\n  return (\n    <div>\n      {loading && <p>Loading devices...</p>}\n      {error && <p>Error: {error}</p>}\n      {devices.map((device) => (\n        <div key={device.deviceId}>{device.label}</div>\n      ))}\n      {!hasPermission && (\n        <button onClick={loadDevices}>Grant Permission</button>\n      )}\n    </div>\n  );\n}\n```\n\n#### Return Value\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `devices` | `MediaDeviceInfo[]` | - | Array of available audio input devices. |\n| `loading` | `boolean` | - | Whether devices are currently being loaded. |\n| `error` | `string | null` | - | Error message if device loading failed. |\n| `hasPermission` | `boolean` | - | Whether microphone permission has been granted. |\n| `loadDevices` | `() => Promise<void>` | - | Function to request microphone permission and load device names. |\n\n## Behavior\n\n### Permission Handling\n\nThe component implements a two-stage permission approach:\n\n1. **Without Permission**: Initially loads devices without requesting permission. Device labels may show as generic names (e.g., \"Microphone 1\").\n2. **With Permission**: When the popover is opened and permission hasn't been granted, automatically requests microphone access and displays actual device names.\n\n### Device Label Parsing\n\nThe `MicSelectorLabel` component intelligently parses device names that include hardware IDs in the format `(XXXX:XXXX)`. It splits the label into the device name and ID, styling the ID with muted text for better readability.\n\nFor example: `\"MacBook Pro Microphone (1a2b:3c4d)\"` becomes:\n\n- Device name: `\"MacBook Pro Microphone\"`\n- Device ID: `\"(1a2b:3c4d)\"` (styled with muted color)\n\n### Width Synchronization\n\nThe `MicSelectorTrigger` uses a ResizeObserver to track its width and automatically synchronizes it with the `MicSelectorContent` popover width for a cohesive appearance.\n\n### Device Change Detection\n\nThe component listens for `devicechange` events (e.g., plugging/unplugging microphones) and automatically updates the device list in real-time.\n\n## Accessibility\n\n- Uses semantic HTML with proper ARIA attributes via shadcn/ui components\n- Full keyboard navigation support through Command component\n- Screen reader friendly with proper labels and roles\n- Searchable device list for quick selection\n\n## Notes\n\n- Requires a secure context (HTTPS or localhost) for microphone access\n- Browser may prompt user for microphone permission on first open\n- Device labels are only fully descriptive after permission is granted\n- Component handles cleanup of temporary media streams during permission requests\n- Uses Radix UI's `useControllableState` for flexible controlled/uncontrolled patterns\n\n<!-- File: .agents/skills/ai-elements/references/model-selector.md (Tokens: ~971 | Category: anthropic-skill) -->\n# Model Selector\n\nA searchable command palette for selecting AI models in your chat interface.\n\nThe `ModelSelector` component provides a searchable command palette interface for selecting AI models. It's built on top of the cmdk library and provides a keyboard-navigable interface with search functionality.\n\nSee `scripts/model-selector.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add model-selector\n```\n\n## Features\n\n- Searchable interface with keyboard navigation\n- Fuzzy search filtering across model names\n- Grouped model organization by provider\n- Keyboard shortcuts support\n- Empty state handling\n- Customizable styling with Tailwind CSS\n- Built on cmdk for excellent accessibility\n- TypeScript support with proper type definitions\n\n## Props\n\n### `<ModelSelector />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof Dialog>` | - | Any other props are spread to the underlying Dialog component. |\n\n### `<ModelSelectorTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DialogTrigger>` | - | Any other props are spread to the underlying DialogTrigger component. |\n\n### `<ModelSelectorContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `title` | `ReactNode` | - | Accessible title for the dialog (rendered in sr-only). |\n| `...props` | `React.ComponentProps<typeof DialogContent>` | - | Any other props are spread to the underlying DialogContent component. |\n\n### `<ModelSelectorDialog />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandDialog>` | - | Any other props are spread to the underlying CommandDialog component. |\n\n### `<ModelSelectorInput />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandInput>` | - | Any other props are spread to the underlying CommandInput component. |\n\n### `<ModelSelectorList />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandList>` | - | Any other props are spread to the underlying CommandList component. |\n\n### `<ModelSelectorEmpty />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandEmpty>` | - | Any other props are spread to the underlying CommandEmpty component. |\n\n### `<ModelSelectorGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandGroup>` | - | Any other props are spread to the underlying CommandGroup component. |\n\n### `<ModelSelectorItem />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandItem>` | - | Any other props are spread to the underlying CommandItem component. |\n\n### `<ModelSelectorShortcut />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandShortcut>` | - | Any other props are spread to the underlying CommandShortcut component. |\n\n### `<ModelSelectorSeparator />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof CommandSeparator>` | - | Any other props are spread to the underlying CommandSeparator component. |\n\n### `<ModelSelectorLogo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `provider` | `string` | Required | The AI provider name. Supports major providers like  |\n| `...props` | `Omit<React.ComponentProps<` | - | Any other props are spread to the underlying img element (except src and alt which are generated). |\n\n### `<ModelSelectorLogoGroup />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |\n\n### `<ModelSelectorName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying span element. |\n\n<!-- File: .agents/skills/ai-elements/references/node.md (Tokens: ~649 | Category: anthropic-skill) -->\n# Node\n\nA composable node component for React Flow-based canvases with Card-based styling.\n\nThe `Node` component provides a composable, Card-based node for React Flow canvases. It includes support for connection handles, structured layouts, and consistent styling using shadcn/ui components.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add node\n```\n\n## Features\n\n- Built on shadcn/ui Card components for consistent styling\n- Automatic handle placement (left for target, right for source)\n- Composable sub-components (Header, Title, Description, Action, Content, Footer)\n- Semantic structure for organizing node information\n- Pre-styled sections with borders and backgrounds\n- Responsive sizing with fixed small width\n- Full TypeScript support with proper type definitions\n- Compatible with React Flow's node system\n\n## Props\n\n### `<Node />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `handles` | `unknown` | - | Configuration for connection handles. Target renders on the left, source on the right. |\n| `className` | `string` | - | Additional CSS classes to apply to the node. |\n| `...props` | `ComponentProps<typeof Card>` | - | Any other props are spread to the underlying Card component. |\n\n### `<NodeHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the header. |\n| `...props` | `ComponentProps<typeof CardHeader>` | - | Any other props are spread to the underlying CardHeader component. |\n\n### `<NodeTitle />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof CardTitle>` | - | Any other props are spread to the underlying CardTitle component. |\n\n### `<NodeDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof CardDescription>` | - | Any other props are spread to the underlying CardDescription component. |\n\n### `<NodeAction />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `ComponentProps<typeof CardAction>` | - | Any other props are spread to the underlying CardAction component. |\n\n### `<NodeContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the content. |\n| `...props` | `ComponentProps<typeof CardContent>` | - | Any other props are spread to the underlying CardContent component. |\n\n### `<NodeFooter />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the footer. |\n| `...props` | `ComponentProps<typeof CardFooter>` | - | Any other props are spread to the underlying CardFooter component. |\n\n<!-- File: .agents/skills/ai-elements/references/open-in-chat.md (Tokens: ~660 | Category: anthropic-skill) -->\n# Open In Chat\n\nA dropdown menu for opening queries in various AI chat platforms including ChatGPT, Claude, T3, Scira, and v0.\n\nThe `OpenIn` component provides a dropdown menu that allows users to open queries in different AI chat platforms with a single click.\n\nSee `scripts/open-in-chat.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add open-in-chat\n```\n\n## Features\n\n- Pre-configured links to popular AI chat platforms\n- Context-based query passing for cleaner API\n- Customizable dropdown trigger button\n- Automatic URL parameter encoding for queries\n- Support for ChatGPT, Claude, T3 Chat, Scira AI, v0, and Cursor\n- Branded icons for each platform\n- TypeScript support with proper type definitions\n- Accessible dropdown menu with keyboard navigation\n- External link indicators for clarity\n\n## Supported Platforms\n\n- **ChatGPT** - Opens query in OpenAI's ChatGPT with search hints\n- **Claude** - Opens query in Anthropic's Claude AI\n- **T3 Chat** - Opens query in T3 Chat platform\n- **Scira AI** - Opens query in Scira's AI assistant\n- **v0** - Opens query in Vercel's v0 platform\n- **Cursor** - Opens query in Cursor AI editor\n\n## Props\n\n### `<OpenIn />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `query` | `string` | - | The query text to be sent to all AI platforms. |\n| `...props` | `React.ComponentProps<typeof DropdownMenu>` | - | Props to spread to the underlying radix-ui DropdownMenu component. |\n\n### `<OpenInTrigger />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom trigger button. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuTrigger>` | - | Props to spread to the underlying DropdownMenuTrigger component. |\n\n### `<OpenInContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `className` | `string` | - | Additional CSS classes to apply to the dropdown content. |\n| `...props` | `React.ComponentProps<typeof DropdownMenuContent>` | - | Props to spread to the underlying DropdownMenuContent component. |\n\n### `<OpenInChatGPT />`, `<OpenInClaude />`, `<OpenInT3 />`, `<OpenInScira />`, `<OpenInv0 />`, `<OpenInCursor />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.ComponentProps<typeof DropdownMenuItem>` | - | Props to spread to the underlying DropdownMenuItem component. The query is automatically provided via context from the parent OpenIn component. |\n\n### `<OpenInItem />`, `<OpenInLabel />`, `<OpenInSeparator />`\n\nAdditional composable components for custom dropdown menu items, labels, and separators that follow the same props pattern as their underlying radix-ui counterparts.\n\n<!-- File: .agents/skills/ai-elements/references/package-info.md (Tokens: ~778 | Category: anthropic-skill) -->\n# Package Info\n\nDisplay dependency information and version changes.\n\nThe `PackageInfo` component displays package dependency information including version changes and change type badges.\n\nSee `scripts/package-info.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add package-info\n```\n\n## Features\n\n- Version change display (current → new)\n- Color-coded change type badges\n- Dependencies list\n- Description support\n\n## Change Types\n\n| Type      | Color  | Use Case           |\n| --------- | ------ | ------------------ |\n| `major`   | Red    | Breaking changes   |\n| `minor`   | Yellow | New features       |\n| `patch`   | Green  | Bug fixes          |\n| `added`   | Blue   | New dependency     |\n| `removed` | Gray   | Removed dependency |\n\n## Props\n\n### `<PackageInfo />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | Package name. |\n| `currentVersion` | `string` | - | Current installed version. |\n| `newVersion` | `string` | - | New version being installed. |\n| `changeType` | `unknown` | - | Type of version change. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoHeader />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the header div. |\n\n### `<PackageInfoName />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom name content. Defaults to the name from context. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoChangeType />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom change type label. Defaults to the changeType from context. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the Badge component. |\n\n### `<PackageInfoVersion />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `React.ReactNode` | - | Custom version content. Defaults to version transition display. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoDescription />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLParagraphElement>` | - | Spread to the p element. |\n\n### `<PackageInfoContent />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoDependencies />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the container div. |\n\n### `<PackageInfoDependency />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | Required | Dependency name. |\n| `version` | `string` | - | Dependency version. |\n| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the row div. |\n\n<!-- File: .agents/skills/ai-elements/references/panel.md (Tokens: ~232 | Category: anthropic-skill) -->\n# Panel\n\nA styled panel component for React Flow-based canvases to position custom UI elements.\n\nThe `Panel` component provides a positioned container for custom UI elements on React Flow canvases. It includes modern card styling with backdrop blur and flexible positioning options.\n\n\n\n## Installation\n\n```bash\nnpx ai-elements@latest add panel\n```\n\n## Features\n\n- Flexible positioning (top-left, top-right, bottom-left, bottom-right, top-center, bottom-center)\n- Rounded pill design with backdrop blur\n- Theme-aware card background\n- Flexbox layout for easy content alignment\n- Subtle drop shadow for depth\n- Full TypeScript support\n- Compatible with React Flow's panel system\n\n## Props\n\n### `<Panel />`\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `position` | `unknown` | - | Position of the panel on the canvas. |\n| `className` | `string` | - | Additional CSS classes to apply to the panel. |\n| `...props` | `ComponentProps<typeof Panel>` | - | Any other props from @xyflow/react Panel component. |\n\n<!-- File: .agents/skills/ai-elements/references/persona.md (Tokens: ~1272 | Category: anthropic-skill) -->\n# Persona\n\nAn animated AI visual component powered by Rive that responds to different states like listening, thinking, and speaking.\n\nThe `Persona` component displays an animated AI visual that responds to different conversational states. Built with Rive WebGL2, it provides smooth, high-performance animations for various AI interaction states including idle, listening, thinking, speaking, and asleep. The component supports multiple visual variants to match different design aesthetics.\n\nSee `scripts/persona-obsidian.tsx` for this example.\n\n## Installation\n\n```bash\nnpx ai-elements@latest add persona\n```\n\n## Features\n\n- Smooth state-based animations powered by Rive\n- Multiple visual variants (obsidian, mana, opal, halo, glint, command)\n- Responsive to five distinct states: idle, listening, thinking, speaking, and asleep\n- WebGL2-accelerated rendering for optimal performance\n- Customizable size and styling\n- Lifecycle callbacks for load, ready, pause, play, and stop events\n- TypeScript support with full type definitions\n\n## Variants\n\nThe Persona component comes with 6 distinct visual variants, each with its own unique aesthetic:\n\n### Obsidian (Default)\n\nSee `scripts/persona-obsidian.tsx` for this example.\n\n### Mana\n\nSee `scripts/persona-mana.tsx` for this example.\n\n### Opal\n\nSee `scripts/persona-opal.tsx` for this example.\n\n### Halo\n\nSee `scripts/persona-halo.tsx` for this example.\n\n### Glint\n\nSee `scripts/persona-glint.tsx` for this example.\n\n### Command\n\nSee `scripts/persona-command.tsx` for this example.\n\n## Props\n\n### `<Persona />`\n\nThe root component that renders the animated AI visual.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `state` | `unknown` | - | The current state of the AI persona. Controls which animation is displayed. |\n| `variant` | `unknown` | - | The visual style variant to display. |\n| `className` | `string` | - | Additional CSS classes to apply to the component. |\n| `onLoad` | `RiveParameters[` | - | Callback fired when the Rive file starts loading. |\n| `onLoadError` | `RiveParameters[` | - | Callback fired if the Rive file fails to load. |\n| `onReady` | `() => void` | - | Callback fired when the Rive animation is ready to play. |\n| `onPause` | `RiveParameters[` | - | Callback fired when the animation is paused. |\n| `onPlay` | `RiveParameters[` | - | Callback fired when the animation starts playing. |\n| `onStop` | `RiveParameters[` | - | Callback fired when the animation is stopped. |\n\n## States\n\nThe Persona component responds to five distinct states, each triggering different animations:\n\n- **idle**: The default resting state when the AI is not active\n- **listening**: Displayed when the AI is actively listening to user input (e.g., during voice recording)\n- **thinking**: Shown when the AI is processing or generating a response\n- **speaking**: Active when the AI is delivering a response (e.g., text-to-speech output)\n- **asleep**: A dormant state for when the AI is inactive or in low-power mode\n\n## React Strict Mode (Vite)\n\nThe Persona component uses WebGL2 for rendering. Browsers limit the number of active WebGL2 contexts (~8–16), and React Strict Mode (enabled by default in Vite dev) double-mounts components, which can exhaust that limit and crash the page.\n\nThe component includes a built-in guard that defers WebGL2 initialization by one frame, preventing context creation during Strict Mode's throw-away mount. This means the component works in Vite dev mode out of the box — no configuration needed.\n\nIf you still experience crashes (for example, when rendering many Persona instances simultaneously), reduce the number of concurrent Persona components on screen.\n\n## Usage Examples\n\n### Basic Usage\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\n\nexport default function App() {\n  return <Persona state=\"listening\" variant=\"opal\" />;\n}\n```\n\n### With State Management\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\nimport { useState } from \"react\";\n\nexport default function App() {\n  const [state, setState] = useState<\n    \"idle\" | \"listening\" | \"thinking\" | \"speaking\" | \"asleep\"\n  >(\"idle\");\n\n  const startListening = () => setState(\"listening\");\n  const startThinking = () => setState(\"thinking\");\n  const startSpeaking = () => setState(\"speaking\");\n  const reset = () => setState(\"idle\");\n\n  return (\n    <div>\n      <Persona state={state} variant=\"opal\" className=\"size-32\" />\n      <div>\n        <button onClick={startListening}>Listen</button>\n        <button onClick={startThinking}>Think</button>\n        <button onClick={startSpeaking}>Speak</button>\n        <button onClick={reset}>Reset</button>\n      </div>\n    </div>\n  );\n}\n```\n\n### With Custom Styling\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\n\nexport default function App() {\n  return (\n    <Persona\n      state=\"thinking\"\n      variant=\"halo\"\n      className=\"size-64 rounded-full border border-border\"\n    />\n  );\n}\n```\n\n### With Lifecycle Callbacks\n\n```tsx\nimport { Persona } from \"@repo/elements/persona\";\n\nexport default function App() {\n  return (\n    <Persona\n      state=\"listening\"\n      variant=\"glint\"\n      onReady={() => console.log(\"Animation ready\")}\n      onLoad={() => console.log(\"Starting to load\")}\n      onLoadError={(error) => console.error(\"Failed to load:\", error)}\n      onPlay={() => console.log(\"Animation playing\")}\n      onPause={() => console.log(\"Animation paused\")}\n      onStop={() => console.log(\"Animation stopped\")}\n    />\n  );\n}\n```\n\n<!-- ... +332 more modular skills available via /api/skills/trycompai/crm?path={path} -->\n</yakaai_skills>"}