@polpo-ai/dashboard 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +44 -0
  3. package/app/(dashboard)/error.tsx +47 -0
  4. package/app/(dashboard)/layout.tsx +41 -0
  5. package/app/(dashboard)/loading.tsx +30 -0
  6. package/app/(dashboard)/projects/[id]/agents/[name]/memory/view.tsx +36 -0
  7. package/app/(dashboard)/projects/[id]/agents/[name]/models-view.tsx +30 -0
  8. package/app/(dashboard)/projects/[id]/agents/[name]/page.tsx +51 -0
  9. package/app/(dashboard)/projects/[id]/agents/[name]/prompt/view.tsx +211 -0
  10. package/app/(dashboard)/projects/[id]/agents/[name]/skills/view.tsx +84 -0
  11. package/app/(dashboard)/projects/[id]/agents/[name]/tools/view.tsx +525 -0
  12. package/app/(dashboard)/projects/[id]/agents/[name]/vault/view.tsx +61 -0
  13. package/app/(dashboard)/projects/[id]/agents/page.tsx +39 -0
  14. package/app/(dashboard)/projects/[id]/agents/view.tsx +283 -0
  15. package/app/(dashboard)/projects/[id]/layout.tsx +11 -0
  16. package/app/(dashboard)/projects/[id]/logs/page.tsx +27 -0
  17. package/app/(dashboard)/projects/[id]/logs/view.tsx +184 -0
  18. package/app/(dashboard)/projects/[id]/memory/page.tsx +40 -0
  19. package/app/(dashboard)/projects/[id]/memory/view.tsx +17 -0
  20. package/app/(dashboard)/projects/[id]/missions/[missionId]/page.tsx +88 -0
  21. package/app/(dashboard)/projects/[id]/missions/[missionId]/view.tsx +569 -0
  22. package/app/(dashboard)/projects/[id]/missions/page.tsx +32 -0
  23. package/app/(dashboard)/projects/[id]/missions/view.tsx +282 -0
  24. package/app/(dashboard)/projects/[id]/onboarding-checklist.tsx +359 -0
  25. package/app/(dashboard)/projects/[id]/page.tsx +68 -0
  26. package/app/(dashboard)/projects/[id]/playbooks/[name]/page.tsx +5 -0
  27. package/app/(dashboard)/projects/[id]/playbooks/[name]/view.tsx +433 -0
  28. package/app/(dashboard)/projects/[id]/playbooks/page.tsx +5 -0
  29. package/app/(dashboard)/projects/[id]/playbooks/view.tsx +222 -0
  30. package/app/(dashboard)/projects/[id]/schedules/page.tsx +44 -0
  31. package/app/(dashboard)/projects/[id]/schedules/view.tsx +385 -0
  32. package/app/(dashboard)/projects/[id]/sessions/[sessionId]/page.tsx +55 -0
  33. package/app/(dashboard)/projects/[id]/sessions/[sessionId]/raw-view.tsx +373 -0
  34. package/app/(dashboard)/projects/[id]/sessions/[sessionId]/view.tsx +124 -0
  35. package/app/(dashboard)/projects/[id]/sessions/page.tsx +31 -0
  36. package/app/(dashboard)/projects/[id]/sessions/view.tsx +242 -0
  37. package/app/(dashboard)/projects/[id]/settings/page.tsx +52 -0
  38. package/app/(dashboard)/projects/[id]/skills/[name]/page.tsx +65 -0
  39. package/app/(dashboard)/projects/[id]/skills/[name]/view.tsx +227 -0
  40. package/app/(dashboard)/projects/[id]/skills/page.tsx +31 -0
  41. package/app/(dashboard)/projects/[id]/skills/view.tsx +243 -0
  42. package/app/(dashboard)/projects/[id]/storage/page.tsx +5 -0
  43. package/app/(dashboard)/projects/[id]/storage/view.tsx +385 -0
  44. package/app/(dashboard)/projects/[id]/tasks/[taskId]/activity/view.tsx +336 -0
  45. package/app/(dashboard)/projects/[id]/tasks/[taskId]/assessment/view.tsx +113 -0
  46. package/app/(dashboard)/projects/[id]/tasks/[taskId]/blueprint.ts +72 -0
  47. package/app/(dashboard)/projects/[id]/tasks/[taskId]/output/view.tsx +90 -0
  48. package/app/(dashboard)/projects/[id]/tasks/[taskId]/page.tsx +63 -0
  49. package/app/(dashboard)/projects/[id]/tasks/[taskId]/view.tsx +137 -0
  50. package/app/(dashboard)/projects/[id]/tasks/page.tsx +40 -0
  51. package/app/(dashboard)/projects/[id]/tasks/view.tsx +421 -0
  52. package/app/(dashboard)/projects/[id]/view.tsx +421 -0
  53. package/app/(dashboard)/projects/[id]/welcome-banner.tsx +156 -0
  54. package/app/(dashboard)/projects/projects-list.tsx +126 -0
  55. package/app/(playground)/error.tsx +42 -0
  56. package/app/(playground)/layout.tsx +27 -0
  57. package/app/(playground)/projects/[id]/playground/page.tsx +57 -0
  58. package/app/(playground)/projects/[id]/playground/view.tsx +167 -0
  59. package/app/(playground)/projects/[id]/playground-legacy/page.tsx +47 -0
  60. package/app/(playground)/projects/[id]/playground-legacy/skeleton.tsx +63 -0
  61. package/app/(playground)/projects/[id]/playground-legacy/view.tsx +237 -0
  62. package/app/favicon.ico +0 -0
  63. package/app/globals.css +385 -0
  64. package/app/icon.svg +6 -0
  65. package/app/layout.tsx +39 -0
  66. package/app/page.tsx +11 -0
  67. package/components/ai-elements/code-block.tsx +562 -0
  68. package/components/dashboard/agent-capabilities.tsx +326 -0
  69. package/components/dashboard/agent-identity-header.tsx +50 -0
  70. package/components/dashboard/agent-model-picker.tsx +195 -0
  71. package/components/dashboard/agent-model-selector.tsx +121 -0
  72. package/components/dashboard/agent-picker-card.tsx +46 -0
  73. package/components/dashboard/agent-studio.tsx +242 -0
  74. package/components/dashboard/agents-table.tsx +48 -0
  75. package/components/dashboard/breadcrumb.tsx +70 -0
  76. package/components/dashboard/builder-chat.tsx +418 -0
  77. package/components/dashboard/chat-shell.tsx +40 -0
  78. package/components/dashboard/client-picker.tsx +63 -0
  79. package/components/dashboard/command-snippet.tsx +77 -0
  80. package/components/dashboard/connect-dialog.tsx +680 -0
  81. package/components/dashboard/copy-button.tsx +45 -0
  82. package/components/dashboard/copy-card.tsx +48 -0
  83. package/components/dashboard/file-browser.tsx +161 -0
  84. package/components/dashboard/hint.tsx +22 -0
  85. package/components/dashboard/inference-mode.tsx +15 -0
  86. package/components/dashboard/manual-refresh-button.tsx +52 -0
  87. package/components/dashboard/markdown.tsx +31 -0
  88. package/components/dashboard/mcp-install-panel.tsx +196 -0
  89. package/components/dashboard/mission-graph.tsx +262 -0
  90. package/components/dashboard/nav-tabs.tsx +86 -0
  91. package/components/dashboard/polpo-chat.tsx +468 -0
  92. package/components/dashboard/project-copilot.tsx +253 -0
  93. package/components/dashboard/sdk-snippet-panel.tsx +194 -0
  94. package/components/dashboard/section-header.tsx +37 -0
  95. package/components/dashboard/settings-form.tsx +2477 -0
  96. package/components/dashboard/sidebar.tsx +385 -0
  97. package/components/dashboard/skeletons.tsx +1054 -0
  98. package/components/dashboard/skills-install-wizard.tsx +273 -0
  99. package/components/dashboard/swarm-runs.tsx +316 -0
  100. package/components/dashboard/tab-toggle.tsx +35 -0
  101. package/components/dashboard/task-studio.tsx +224 -0
  102. package/components/dashboard/top-header.tsx +203 -0
  103. package/components/dashboard/webhook-deliveries.tsx +234 -0
  104. package/components/icons/coding-agents.tsx +151 -0
  105. package/components/json-ld.tsx +8 -0
  106. package/components/providers.tsx +25 -0
  107. package/components/ui/badge.tsx +52 -0
  108. package/components/ui/button.tsx +60 -0
  109. package/components/ui/card.tsx +103 -0
  110. package/components/ui/chart.tsx +356 -0
  111. package/components/ui/command.tsx +196 -0
  112. package/components/ui/dialog.tsx +157 -0
  113. package/components/ui/input-group.tsx +158 -0
  114. package/components/ui/input.tsx +20 -0
  115. package/components/ui/multi-select.tsx +161 -0
  116. package/components/ui/popover.tsx +90 -0
  117. package/components/ui/select.tsx +201 -0
  118. package/components/ui/separator.tsx +25 -0
  119. package/components/ui/sheet.tsx +135 -0
  120. package/components/ui/skeleton.tsx +13 -0
  121. package/components/ui/tabs.tsx +56 -0
  122. package/components/ui/textarea.tsx +18 -0
  123. package/components/ui/tooltip.tsx +66 -0
  124. package/hooks/use-desktop-sidebar.tsx +50 -0
  125. package/hooks/use-mobile-sidebar.tsx +37 -0
  126. package/index.ts +14 -0
  127. package/lib/api.ts +194 -0
  128. package/lib/builder-context.ts +60 -0
  129. package/lib/data-client.ts +68 -0
  130. package/lib/get-query-client.ts +25 -0
  131. package/lib/polpo-client.tsx +49 -0
  132. package/lib/tool-catalog.ts +234 -0
  133. package/lib/use-event-catalog.ts +28 -0
  134. package/lib/utils.ts +6 -0
  135. package/package.json +99 -0
@@ -0,0 +1,151 @@
1
+ import type { SVGProps } from "react";
2
+
3
+ /**
4
+ * Brand glyphs for the coding agents the `skills` CLI can target.
5
+ * Paths are taken from each agent's public brand material. Icons either
6
+ * use their brand fill (Cursor/Claude/Trae/Qoder) or `currentColor` so
7
+ * they inherit from the parent (the ones without a strict brand color).
8
+ *
9
+ * The gradient IDs in CursorIcon are suffixed `-polpo` to reduce the
10
+ * chance of collision with other SVGs on the same page.
11
+ */
12
+
13
+ export function CursorIcon(props: SVGProps<SVGSVGElement>) {
14
+ return (
15
+ <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
16
+ <path d="M12.692 1.273L20.5205 6.1985C20.819 6.386 21 6.714 21 7.0665V16.444C21 16.79 20.8225 17.1115 20.5295 17.2955L12.686 22.225C12.4175 22.394 12.077 22.398 11.8045 22.236L3.49 17.2915C3.299 17.178 3.1545 17.006 3.0735 16.8065C3.0255 16.6885 3 16.561 3 16.43V7.06851C3 6.716 3.1855 6.3895 3.489 6.209L11.8105 1.2615C12.083 1.0995 12.4235 1.104 12.692 1.273Z" fill="url(#cursor-a-polpo)" />
17
+ <path d="M12.5 11.4995L20.8975 16.8745C20.814 17.0375 20.6915 17.178 20.5295 17.2955L12.712 22.2095C12.409 22.3905 12.0985 22.41 11.779 22.2225L3.49 17.2915C3.2985 17.176 3.1575 17.0165 3.0735 16.8065L12.5 11.4995Z" fill="url(#cursor-b-polpo)" />
18
+ <path d="M12.248 1.146V11.589L3.0735 16.8065C3.0235 16.6805 2.9995 16.555 3 16.43V7.0685C3.021 6.7405 3.1185 6.435 3.489 6.209L11.8545 1.2385C11.993 1.1745 12.125 1.14 12.248 1.146Z" fill="url(#cursor-c-polpo)" />
19
+ <path d="M4.264 7.9994L11.74 11.8359C11.904 11.9324 12.005 12.1084 12.005 12.299L11.9995 20.476C11.9995 21.0285 12.733 21.221 13.004 20.7395L20.001 7.7839C20.2025 7.4259 19.9435 6.9839 19.533 6.9839L4.5355 6.9999C3.9885 6.9999 3.7925 7.7224 4.264 7.9994Z" fill="#E0E0E0" />
20
+ <defs>
21
+ <linearGradient id="cursor-a-polpo" x1="15.451" y1="17.86" x2="8.257" y2="5.112" gradientUnits="userSpaceOnUse">
22
+ <stop stopColor="#636363" />
23
+ <stop offset="1" stopColor="#444" />
24
+ </linearGradient>
25
+ <linearGradient id="cursor-b-polpo" x1="13.56" y1="20.903" x2="10.544" y2="13.121" gradientUnits="userSpaceOnUse">
26
+ <stop stopColor="#A1AAB3" />
27
+ <stop offset="1" stopColor="#8F979E" />
28
+ </linearGradient>
29
+ <linearGradient id="cursor-c-polpo" x1="9.31" y1="11.899" x2="4.424" y2="3.242" gradientUnits="userSpaceOnUse">
30
+ <stop stopColor="#636363" />
31
+ <stop offset="0.997" stopColor="#90989F" />
32
+ </linearGradient>
33
+ </defs>
34
+ </svg>
35
+ );
36
+ }
37
+
38
+ export function ClaudeCodeIcon(props: SVGProps<SVGSVGElement>) {
39
+ return (
40
+ <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
41
+ <path
42
+ d="M5.924 15.296l3.934-2.206.067-.192-.067-.107h-.192l-.658-.04-2.248-.06-1.95-.08-1.888-.103-.476-.1-.446-.587.046-.293.4-.268.572.05 1.267.086 1.898.132 1.377.08 2.041.214h.324l.046-.131-.112-.082-.086-.079-1.965-1.33-2.126-1.407-1.114-.81-.603-.41-.303-.385-.131-.84.546-.602.735.05.187.05.744.572L7.332 7.647 9.407 9.174l.304.253.12-.086.016-.06-.136-.228-1.13-2.04-1.205-2.075L6.84 4.08l-.141-.516c-.054-.198-.083-.403-.087-.608l.623-.844.345-.112.83.112.35.304.517 1.178.835 1.858 1.296 2.525.38.748.203.694.076.213h.131v-.122l.107-1.421.197-1.746.192-2.245.067-.634.313-.758.622-.41.487.234.4.57-.056.37-.239 1.544-.466 2.42-.303 1.618h.176l.203-.202.82-1.089 1.376-1.72.608-.682.709-.754.456-.358h.861l.634.941-.284.972-.886 1.122-.734.952-1.053 1.417-.659 1.133.061.092.157-.017 2.38-.505 1.285-.233 1.535-.263.694.324.075.33-.273.673-1.64.405-1.925.385-2.866.677-.035.025.04.05 1.291.123.552.03h1.351l2.517.186.658.435.394.533-.065.404-1.013.517-1.366-.325-3.19-.758-1.094-.274h-.15v.092l.91.89 1.672 1.508 2.09 1.942.107.482-.268.379-.284-.041-1.837-1.38-.71-.623-1.605-1.35h-.106v.142l.37.54 1.954 2.935.102.9-.143.294-.506.177-.557-.102-1.144-1.604-1.18-1.806-.952-1.619-.116.067-.561 6.045-.264.308-.607.233-.506-.384-.269-.622.268-1.23.324-1.603.263-1.275.238-1.584.142-.527-.01-.035-.117.015-1.194 1.64-1.817 2.454-1.438 1.538-.345.136-.598-.308.056-.552.334-.49 1.99-2.53 1.2-1.57.775-.906-.005-.131h-.045l-5.287 3.43-.941.12-.406-.379.051-.622.192-.202 1.59-1.094-.005.005z"
43
+ fill="#D97757"
44
+ />
45
+ </svg>
46
+ );
47
+ }
48
+
49
+ export function TraeIcon(props: SVGProps<SVGSVGElement>) {
50
+ return (
51
+ <svg viewBox="0 0 28 21" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
52
+ <path
53
+ d="M28 20.9645H3.99933V16.9675H0V0.966675H28V20.9645ZM3.99933 16.9675H24.0007V4.96484H3.99933V16.9675ZM14.0012 10.9055L11.172 13.7335L8.344 10.9055L11.172 8.07751L14.0012 10.9055ZM22.001 10.9043L19.173 13.7312L16.3438 10.9043L19.173 8.07517L22.001 10.9043Z"
54
+ fill="#32F08C"
55
+ />
56
+ </svg>
57
+ );
58
+ }
59
+
60
+ export function ClineIcon(props: SVGProps<SVGSVGElement>) {
61
+ return (
62
+ <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
63
+ <path
64
+ fillRule="evenodd"
65
+ clipRule="evenodd"
66
+ d="M15.776 5.993c2.063 0 3.735 1.68 3.735 3.753v1.25l1.088 2.172a.998.998 0 0 1-.001.778l-1.086 2.148v1.251c0 2.07-1.672 3.752-3.735 3.752H8.305c-2.063 0-3.735-1.682-3.735-3.752v-1.251l-1.11-2.141a.997.997 0 0 1-.007-.7L4.57 10.996V9.745c0-2.072 1.672-3.752 3.735-3.752h7.471zM9.199 10.2a2.45 2.45 0 0 0-2.45 2.45v3.032a2.45 2.45 0 0 0 4.9 0v-3.032a2.45 2.45 0 0 0-2.45-2.45zm5.494 0a2.45 2.45 0 0 0-2.45 2.45v3.032a2.45 2.45 0 1 0 4.9 0v-3.032a2.45 2.45 0 0 0-2.45-2.45z"
67
+ fill="currentColor"
68
+ />
69
+ <path
70
+ fillRule="evenodd"
71
+ clipRule="evenodd"
72
+ d="M12.04 7.168a2.084 2.084 0 1 0 0-4.168 2.084 2.084 0 0 0 0 4.168z"
73
+ fill="currentColor"
74
+ />
75
+ </svg>
76
+ );
77
+ }
78
+
79
+ export function WindsurfIcon(props: SVGProps<SVGSVGElement>) {
80
+ return (
81
+ <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
82
+ <path
83
+ fillRule="evenodd"
84
+ clipRule="evenodd"
85
+ d="M20.835 6.753h-.171a2.401 2.401 0 0 0-2.4 2.4v3.53a1.37 1.37 0 0 1-1.32 1.332 1.34 1.34 0 0 1-1.104-.58l-3.729-5.373a1.619 1.619 0 0 0-1.358-.662c-.85 0-1.615.729-1.615 1.63v3.705a1.331 1.331 0 0 1-1.32 1.332 1.34 1.34 0 0 1-1.104-.58L3.306 6.823c-.094-.135-.306-.068-.306.098v3.213c0 .162.05.32.141.453l4.106 5.917c.243.35.6.609 1.014.703 1.032.237 1.984-.565 1.984-1.588v-3.701c0-.735.59-1.332 1.32-1.332h.002c.44 0 .851.216 1.104.58l3.729 5.372a1.64 1.64 0 0 0 1.358.662c.868 0 1.614-.73 1.614-1.63v-3.704c0-.735.59-1.331 1.32-1.331h.145a.165.165 0 0 0 .165-.166V6.919a.165.165 0 0 0-.165-.165v-.001z"
86
+ fill="currentColor"
87
+ />
88
+ </svg>
89
+ );
90
+ }
91
+
92
+ export function RooIcon(props: SVGProps<SVGSVGElement>) {
93
+ return (
94
+ <svg viewBox="40 110 300 200" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
95
+ <path
96
+ fill="currentColor"
97
+ d="M278.25 193.336c-12.22 6.163-24.098 12.177-35.998 18.146-2.744 1.376-4.872 3.179-6.473 5.943-3.755 6.479-7.714 12.854-11.891 19.069-1.994 2.967-2.196 5.257-.412 8.545 9.288 17.12 18.265 34.408 27.353 51.635 3.33 6.312 2.42 7.041-4.707 7.87-8.285.962-12.844-2.433-17.25-9.161-11.489-17.546-23.78-34.569-35.887-51.705-2.136-3.024-3.153-6.047-2.97-9.74.344-6.981.342-13.98.592-20.967.098-2.725-.714-4.704-3.056-6.34-8.872-6.197-17.675-12.495-26.406-18.887-3.06-2.24-5.555-.953-8.284.512-12.173 6.53-24.384 12.99-36.572 19.492-1.478.789-2.923 1.583-4.674 1.553-19.133-.331-38.266-.61-57.372-1.819-2.48-.156-4.258-.73-4.289-3.616-.029-2.817 1.92-3.744 4.164-4.1 14.92-2.363 29.838-4.747 44.79-6.888 2.931-.42 5.343-1.258 7.65-3.116 26.979-21.727 54.044-43.347 80.981-65.125 2.77-2.239 5.09-2.756 8.554-1.699 26.884 8.208 53.848 16.156 80.757 24.283 3.093.934 4.673.22 5.45-2.935 1.072-4.358 2.36-8.663 3.596-12.979.493-1.717.588-3.857 2.809-4.32 2.338-.486 3.109 1.614 4.07 3.064 11.774 17.767 23.5 35.565 35.238 53.355a198.5 198.5 0 0 1 4.625 7.115c1.604 2.95.778 4.677-2.859 4.879-8.778.486-17.271.33-24.17-6.445-4.986-4.9-10.4-5.558-16.426-1.343-3.242 2.268-7.046 3.733-10.93 5.724z"
98
+ />
99
+ </svg>
100
+ );
101
+ }
102
+
103
+ export function QoderIcon(props: SVGProps<SVGSVGElement>) {
104
+ return (
105
+ <svg viewBox="0 0 360 360" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
106
+ <path
107
+ fill="#FEFEFE"
108
+ d="M206.873 51.045c8.46 4.648 17.035 9.057 25.626 13.455 10.315 5.281 20.574 10.63 30.713 16.245 4.593 2.537 9.211 5 13.89 7.376 1.026.524 2.053 1.047 3.11 1.587a93.4 93.4 0 0 1 5.853 2.973c15.257 7.76 27.992 20.035 33.934 36.358 3.245 11.228 4.588 21.721 4.518 33.398.005 1.556.013 3.112.021 4.668.018 4.167.012 8.334-.001 12.5-.01 4.386 0 8.772.006 13.158.007 7.35-.002 14.7-.021 22.05-.022 8.482-.015 16.963.007 25.445.018 7.314.021 14.628.01 21.942-.006 4.355-.007 8.71.006 13.065.012 4.087.003 8.174-.02 12.26a112.23 112.23 0 0 0 .005 4.495c.047 8.878.016 16.259-6.46 23.05-6.18 4.293-11.352 6.835-19.07 5.977-5.879-1.83-11.496-4.252-17.036-6.925-.67-.323-1.341-.646-2.032-.978a173 173 0 0 1-6.008-3.187c-3.346-1.668-3.346-1.668-7.002-2.079-3.168 1.456-6.252 3.057-9.336 4.68-21.147 10.827-44.935 16.47-68.375 10.575-14.403-4.748-27.962-13.067-41.185-20.369-8.46-4.648-17.036-9.058-25.628-13.455-10.361-5.306-20.67-10.677-30.854-16.318-4.387-2.425-8.792-4.785-13.267-7.046-18.433-9.321-33.036-19.831-40.378-40.137-3.534-11.38-4.613-21.82-4.566-33.668-.005-1.654-.012-3.307-.019-4.96-.01-3.442-.006-6.883.008-10.325a185 185 0 0 0-.02-10.445c-.2-25.234.891-47.703 12.594-70.603a92 92 0 0 1 .92-1.804c13.697-26.604 37.341-49.42 66.051-58.873 36.456-11.42 59.416-3.204 91.916 14.76z"
109
+ />
110
+ <path
111
+ fill="#2ADB5C"
112
+ d="M301.695 102.855c13.583 12.64 21.36 28.625 22.678 47.212.14 4.115.17 8.214.145 12.331.006 1.556.013 3.112.022 4.668.018 4.168.011 8.335-.002 12.502-.01 4.385 0 8.77.006 13.156.008 7.35-.002 14.7-.021 22.05-.022 8.482-.015 16.964.007 25.446.018 7.314.021 14.628.01 21.942-.006 4.355-.007 8.71.006 13.065.012 4.087.003 8.174-.02 12.26.003 1.495-.001 2.99-.016 4.484.048 8.879.017 16.26-6.46 23.05-6.178 4.294-11.35 6.836-19.07 5.978-5.878-1.83-11.495-4.252-17.035-6.925-.671-.323-1.342-.646-2.033-.978a170 170 0 0 1-6.007-3.188c-3.346-1.667-3.346-1.667-7.002-2.078-3.168 1.455-6.252 3.056-9.336 4.679-21.01 10.752-45.564 16.99-68.804.363a21 21 0 0 1-2.61-1.086 61 61 0 0 1-2.329-1.091c-4.453-2.048-7.387-4.367-10.723-8.027a80 80 0 0 1-2.025-1.829c-12.744-11.742-18.56-27.311-20.976-44.17-.202-1.277-.403-2.555-.61-3.871-.337-3.735-.411-6.515.61-10.13a63 63 0 0 1 11.976-7.997c25.523-18.013 42.983-46.076 48.98-76.622 2.073-12.123 1.601-24.621 1.708-36.88.03-2.673.067-5.347.102-8.02.084-6.493.153-12.986.21-19.48 7.94-4.155 15.643-7.947 24.31-10.375.816-.247 1.63-.493 2.47-.746 21.549-6.275 47.484-4.03 64.917 10.97z"
113
+ />
114
+ </svg>
115
+ );
116
+ }
117
+
118
+ export function CopilotIcon(props: SVGProps<SVGSVGElement>) {
119
+ return (
120
+ <svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
121
+ <path
122
+ fillRule="evenodd"
123
+ clipRule="evenodd"
124
+ d="M16.038 4.47c1.101 1.133 1.564 2.68 1.758 4.848.518 0 1 .112 1.326.545l.608.803a1.6 1.6 0 0 1 .27.796v2.183c0 .283-.144.558-.378.724-2.756 1.967-6.158 3.548-9.622 3.548-3.834 0-7.671-2.152-9.623-3.548A.73.73 0 0 1 0 13.645v-2.183c0-.288.094-.566.268-.797l.608-.803c.327-.43.812-.545 1.328-.545l.024-.247c.208-2.039.675-3.51 1.735-4.6 2.05-2.117 4.758-2.376 5.955-2.387h.165c1.197.011 3.904.27 5.955 2.387zM10 8.077c-.236 0-.51.013-.801.041-.103.373-.254.709-.475.924-.875.852-1.93.983-2.495.983-.532 0-1.089-.108-1.543-.386-.43.137-.843.335-.87.829-.034.8-.052 1.602-.052 2.403v.4c-.002.469-.004.938-.01 1.408.001.272.169.525.424.637 2.068.919 4.025 1.381 5.825 1.381s3.757-.462 5.824-1.38a.73.73 0 0 0 .425-.638c.025-1.402.005-2.81-.063-4.211-.026-.497-.44-.692-.871-.83-.455.278-1.01.386-1.542.386-.564 0-1.618-.131-2.494-.983-.222-.215-.373-.551-.475-.924a10.9 10.9 0 0 0-.807-.04zm-2.103 3.344c.45 0 .813.355.813.791v1.46c0 .438-.364.792-.813.792a.83.83 0 0 1-.814-.791v-1.46c0-.438.364-.792.814-.792zm4.167 0c.449 0 .813.355.813.791v1.46c0 .438-.364.792-.813.792a.83.83 0 0 1-.814-.791v-1.46c0-.438.364-.792.814-.792zM6.362 4.239c-.875.085-1.613.365-1.988.755-.812.864-.637 3.056-.175 3.52.338.328.975.547 1.663.547h.075c.54-.011 1.487-.147 2.275-.925.362-.342.587-1.194.562-2.058-.025-.695-.225-1.267-.525-1.51-.325-.28-1.063-.402-1.888-.329zm5.388.328c-.3.244-.5.817-.525 1.51-.025.865.2 1.718.562 2.06.807.798 1.78.92 2.314.925h.037c.687 0 1.325-.22 1.662-.547.463-.463.638-2.655-.175-3.52-.375-.389-1.113-.67-1.988-.754-.825-.074-1.562.047-1.887.327zM10 6.346c-.2 0-.438.013-.7.037.025.133.037.28.05.438l-.001.133c0 .07-.004.14-.01.209.187-.018.354-.022.51-.023h.303c.156 0 .322.005.51.023-.013-.122-.013-.23-.013-.34.012-.159.025-.305.05-.44C10.467 6.36 10.234 6.348 10 6.346z"
125
+ fill="currentColor"
126
+ />
127
+ </svg>
128
+ );
129
+ }
130
+
131
+ export function CodexIcon(props: SVGProps<SVGSVGElement>) {
132
+ return (
133
+ <svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
134
+ <path
135
+ fillRule="evenodd"
136
+ clipRule="evenodd"
137
+ d="M17.958 8.337a5.2 5.2 0 0 0 .212-1.919 5.2 5.2 0 0 0-.61-1.831 5.02 5.02 0 0 0-5.04-2.218 4.9 4.9 0 0 0-1.582-1.136A4.9 4.9 0 0 0 9.026.834a5.01 5.01 0 0 0-4.465 3.2 4.9 4.9 0 0 0-1.786.765 4.9 4.9 0 0 0-1.311 1.44A4.96 4.96 0 0 0 .86 9.052c.103.975.518 1.89 1.183 2.612A4.95 4.95 0 0 0 1.83 13.58a4.98 4.98 0 0 0 .61 1.836 5.01 5.01 0 0 0 5.04 2.217 5.01 5.01 0 0 0 3.494 1.535 5.01 5.01 0 0 0 4.466-3.2 4.96 4.96 0 0 0 1.787-.765c.534-.382.98-.874 1.31-1.442a4.94 4.94 0 0 0 .605-2.803 4.94 4.94 0 0 0-1.183-2.622zM10.974 17.97a3.73 3.73 0 0 1-2.229-.795c.028-.015.077-.042.11-.062l3.7-2.108c.092-.052.17-.127.223-.218.053-.092.081-.196.08-.302V9.338l1.565.89c.016.01.027.025.03.043v4.262c-.003 1.895-1.558 3.432-3.479 3.436m-7.48-3.15a3.7 3.7 0 0 1-.416-2.305c.027.016.075.046.11.065l3.7 2.109c.187.108.42.108.608 0l4.517-2.574v1.782c0 .009-.003.018-.007.026-.004.009-.01.016-.017.022l-3.74 2.13c-1.666.947-3.793.383-4.756-1.258zm-.975-7.97a3.7 3.7 0 0 1 1.812-1.504v4.217c-.001.106.027.21.08.3.054.092.13.168.223.22l4.516 2.572-1.563.892a.03.03 0 0 1-.03 0l-3.74-2.132c-1.663-.95-2.233-3.048-1.275-4.691zm12.847 2.95-4.516-2.573 1.563-.89a.03.03 0 0 1 .03.005l3.74 2.13c1.666.95 2.237 3.052 1.275 4.694a3.77 3.77 0 0 1-1.811 1.506v-4.343a.7.7 0 0 0-.08-.301.7.7 0 0 0-.222-.219v.001zm1.556-2.31a4 4 0 0 0-.11-.065l-3.7-2.108a.61.61 0 0 0-.608 0L7.988 7.887V6.105a.05.05 0 0 1 .023-.047l3.74-2.13c1.666-.947 3.795-.383 4.755 1.261.406.694.554 1.508.416 2.298zM7.138 10.662l-1.564-.89a.03.03 0 0 1-.017-.041V5.467a3.5 3.5 0 0 1 4.96-3.196 3.7 3.7 0 0 1 .71.595l-.11.06-3.7 2.109a.65.65 0 0 0-.222.219.62.62 0 0 0-.08.301zm.85-1.807 2.012-1.146 2.012 1.146v2.292L10 12.292l-2.012-1.146V8.855z"
138
+ fill="currentColor"
139
+ />
140
+ </svg>
141
+ );
142
+ }
143
+
144
+ export function OpenCodeIcon(props: SVGProps<SVGSVGElement>) {
145
+ return (
146
+ <svg viewBox="0 0 240 300" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
147
+ <path d="M180 240H60V120h120v120z" fill="#7C7C7C" />
148
+ <path d="M180 60H60v180h120V60zM240 300H0V0h240v300z" fill="currentColor" />
149
+ </svg>
150
+ );
151
+ }
@@ -0,0 +1,8 @@
1
+ export function JsonLd({ data }: { data: Record<string, unknown> }) {
2
+ return (
3
+ <script
4
+ type="application/ld+json"
5
+ dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
6
+ />
7
+ );
8
+ }
@@ -0,0 +1,25 @@
1
+ "use client";
2
+
3
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
+ import { useState } from "react";
5
+ import { TooltipProvider } from "#/components/ui/tooltip";
6
+
7
+ export function Providers({ children }: { children: React.ReactNode }) {
8
+ const [queryClient] = useState(() => new QueryClient({
9
+ defaultOptions: {
10
+ queries: {
11
+ staleTime: 5 * 60_000,
12
+ refetchOnWindowFocus: false,
13
+ retry: 1,
14
+ },
15
+ },
16
+ }));
17
+
18
+ return (
19
+ <QueryClientProvider client={queryClient}>
20
+ <TooltipProvider delay={150}>
21
+ {children}
22
+ </TooltipProvider>
23
+ </QueryClientProvider>
24
+ );
25
+ }
@@ -0,0 +1,52 @@
1
+ import { mergeProps } from "@base-ui/react/merge-props"
2
+ import { useRender } from "@base-ui/react/use-render"
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+
5
+ import { cn } from "#/lib/utils"
6
+
7
+ const badgeVariants = cva(
8
+ "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
13
+ secondary:
14
+ "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
15
+ destructive:
16
+ "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
17
+ outline:
18
+ "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
19
+ ghost:
20
+ "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
21
+ link: "text-primary underline-offset-4 hover:underline",
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ variant: "default",
26
+ },
27
+ }
28
+ )
29
+
30
+ function Badge({
31
+ className,
32
+ variant = "default",
33
+ render,
34
+ ...props
35
+ }: useRender.ComponentProps<"span"> & VariantProps<typeof badgeVariants>) {
36
+ return useRender({
37
+ defaultTagName: "span",
38
+ props: mergeProps<"span">(
39
+ {
40
+ className: cn(badgeVariants({ variant }), className),
41
+ },
42
+ props
43
+ ),
44
+ render,
45
+ state: {
46
+ slot: "badge",
47
+ variant,
48
+ },
49
+ })
50
+ }
51
+
52
+ export { Badge, badgeVariants }
@@ -0,0 +1,60 @@
1
+ "use client"
2
+
3
+ import { Button as ButtonPrimitive } from "@base-ui/react/button"
4
+ import { cva, type VariantProps } from "class-variance-authority"
5
+
6
+ import { cn } from "#/lib/utils"
7
+
8
+ const buttonVariants = cva(
9
+ "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
10
+ {
11
+ variants: {
12
+ variant: {
13
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
14
+ outline:
15
+ "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
16
+ secondary:
17
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
18
+ ghost:
19
+ "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
20
+ destructive:
21
+ "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
22
+ link: "text-primary underline-offset-4 hover:underline",
23
+ },
24
+ size: {
25
+ default:
26
+ "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
27
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
28
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
29
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
30
+ icon: "size-8",
31
+ "icon-xs":
32
+ "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
33
+ "icon-sm":
34
+ "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
35
+ "icon-lg": "size-9",
36
+ },
37
+ },
38
+ defaultVariants: {
39
+ variant: "default",
40
+ size: "default",
41
+ },
42
+ }
43
+ )
44
+
45
+ function Button({
46
+ className,
47
+ variant = "default",
48
+ size = "default",
49
+ ...props
50
+ }: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {
51
+ return (
52
+ <ButtonPrimitive
53
+ data-slot="button"
54
+ className={cn(buttonVariants({ variant, size, className }))}
55
+ {...props}
56
+ />
57
+ )
58
+ }
59
+
60
+ export { Button, buttonVariants }
@@ -0,0 +1,103 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "#/lib/utils"
4
+
5
+ function Card({
6
+ className,
7
+ size = "default",
8
+ ...props
9
+ }: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
10
+ return (
11
+ <div
12
+ data-slot="card"
13
+ data-size={size}
14
+ className={cn(
15
+ "group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
16
+ className
17
+ )}
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
24
+ return (
25
+ <div
26
+ data-slot="card-header"
27
+ className={cn(
28
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3",
29
+ className
30
+ )}
31
+ {...props}
32
+ />
33
+ )
34
+ }
35
+
36
+ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
37
+ return (
38
+ <div
39
+ data-slot="card-title"
40
+ className={cn(
41
+ "text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
42
+ className
43
+ )}
44
+ {...props}
45
+ />
46
+ )
47
+ }
48
+
49
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
50
+ return (
51
+ <div
52
+ data-slot="card-description"
53
+ className={cn("text-sm text-muted-foreground", className)}
54
+ {...props}
55
+ />
56
+ )
57
+ }
58
+
59
+ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
60
+ return (
61
+ <div
62
+ data-slot="card-action"
63
+ className={cn(
64
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
65
+ className
66
+ )}
67
+ {...props}
68
+ />
69
+ )
70
+ }
71
+
72
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
73
+ return (
74
+ <div
75
+ data-slot="card-content"
76
+ className={cn("px-4 group-data-[size=sm]/card:px-3", className)}
77
+ {...props}
78
+ />
79
+ )
80
+ }
81
+
82
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
83
+ return (
84
+ <div
85
+ data-slot="card-footer"
86
+ className={cn(
87
+ "flex items-center rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/card:p-3",
88
+ className
89
+ )}
90
+ {...props}
91
+ />
92
+ )
93
+ }
94
+
95
+ export {
96
+ Card,
97
+ CardHeader,
98
+ CardFooter,
99
+ CardTitle,
100
+ CardAction,
101
+ CardDescription,
102
+ CardContent,
103
+ }