@promptbook/cli 0.104.0-0 → 0.104.0-10

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 (204) hide show
  1. package/apps/agents-server/config.ts +1 -3
  2. package/apps/agents-server/next.config.ts +2 -2
  3. package/apps/agents-server/package.json +7 -3
  4. package/apps/agents-server/public/fonts/OpenMoji-color-cbdt.woff2 +0 -0
  5. package/apps/agents-server/public/swagger.json +115 -0
  6. package/apps/agents-server/scripts/generate-reserved-paths/generate-reserved-paths.ts +54 -0
  7. package/apps/agents-server/scripts/generate-reserved-paths/tsconfig.json +19 -0
  8. package/apps/agents-server/src/app/AddAgentButton.tsx +47 -21
  9. package/apps/agents-server/src/app/actions.ts +22 -5
  10. package/apps/agents-server/src/app/admin/browser-test/BrowserTestClient.tsx +211 -0
  11. package/apps/agents-server/src/app/admin/browser-test/page.tsx +13 -0
  12. package/apps/agents-server/src/app/admin/chat-feedback/ChatFeedbackClient.tsx +221 -274
  13. package/apps/agents-server/src/app/admin/chat-history/ChatHistoryClient.tsx +94 -137
  14. package/apps/agents-server/src/app/admin/messages/MessagesClient.tsx +294 -0
  15. package/apps/agents-server/src/app/admin/messages/page.tsx +13 -0
  16. package/apps/agents-server/src/app/admin/messages/send-email/SendEmailClient.tsx +104 -0
  17. package/apps/agents-server/src/app/admin/messages/send-email/actions.ts +35 -0
  18. package/apps/agents-server/src/app/admin/messages/send-email/page.tsx +13 -0
  19. package/apps/agents-server/src/app/admin/metadata/MetadataClient.tsx +23 -19
  20. package/apps/agents-server/src/app/agents/[agentName]/AgentChatWrapper.tsx +15 -1
  21. package/apps/agents-server/src/app/agents/[agentName]/AgentOptionsMenu.tsx +51 -9
  22. package/apps/agents-server/src/app/agents/[agentName]/AgentProfileChat.tsx +47 -4
  23. package/apps/agents-server/src/app/agents/[agentName]/AgentProfileWrapper.tsx +53 -11
  24. package/apps/agents-server/src/app/agents/[agentName]/_utils.ts +23 -3
  25. package/apps/agents-server/src/app/agents/[agentName]/agentLinks.tsx +8 -8
  26. package/apps/agents-server/src/app/agents/[agentName]/api/agents/route.ts +17 -26
  27. package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +4 -2
  28. package/apps/agents-server/src/app/agents/[agentName]/api/chat/route.ts +20 -0
  29. package/apps/agents-server/src/app/agents/[agentName]/api/mcp/route.ts +6 -11
  30. package/apps/agents-server/src/app/agents/[agentName]/api/profile/route.ts +5 -1
  31. package/apps/agents-server/src/app/agents/[agentName]/api/voice/route.ts +5 -2
  32. package/apps/agents-server/src/app/agents/[agentName]/book/BookEditorWrapper.tsx +20 -16
  33. package/apps/agents-server/src/app/agents/[agentName]/book/page.tsx +15 -2
  34. package/apps/agents-server/src/app/agents/[agentName]/book+chat/page.tsx +15 -2
  35. package/apps/agents-server/src/app/agents/[agentName]/chat/page.tsx +12 -0
  36. package/apps/agents-server/src/app/agents/[agentName]/code/api/route.ts +68 -0
  37. package/apps/agents-server/src/app/agents/[agentName]/code/page.tsx +223 -0
  38. package/apps/agents-server/src/app/agents/[agentName]/generateAgentMetadata.ts +5 -0
  39. package/apps/agents-server/src/app/agents/[agentName]/history/actions.ts +2 -2
  40. package/apps/agents-server/src/app/agents/[agentName]/history/page.tsx +10 -3
  41. package/apps/agents-server/src/app/agents/[agentName]/images/default-avatar.png/getAgentDefaultAvatarPrompt.ts +31 -0
  42. package/apps/agents-server/src/app/agents/[agentName]/images/default-avatar.png/route.ts +194 -0
  43. package/apps/agents-server/src/app/agents/[agentName]/images/icon-256.png/route.tsx +14 -2
  44. package/apps/agents-server/src/app/agents/[agentName]/images/page.tsx +200 -0
  45. package/apps/agents-server/src/app/agents/[agentName]/images/screenshot-fullhd.png/route.tsx +4 -3
  46. package/apps/agents-server/src/app/agents/[agentName]/images/screenshot-phone.png/route.tsx +4 -3
  47. package/apps/agents-server/src/app/agents/[agentName]/integration/WebsiteIntegrationTabs.tsx +26 -0
  48. package/apps/agents-server/src/app/agents/[agentName]/integration/page.tsx +32 -8
  49. package/apps/agents-server/src/app/agents/[agentName]/links/page.tsx +11 -4
  50. package/apps/agents-server/src/app/agents/[agentName]/opengraph-image.tsx +11 -2
  51. package/apps/agents-server/src/app/agents/[agentName]/page.tsx +18 -10
  52. package/apps/agents-server/src/app/agents/[agentName]/system-message/page.tsx +100 -0
  53. package/apps/agents-server/src/app/agents/[agentName]/website-integration/page.tsx +35 -18
  54. package/apps/agents-server/src/app/api/admin-email/route.ts +12 -0
  55. package/apps/agents-server/src/app/api/agents/[agentName]/clone/route.ts +13 -14
  56. package/apps/agents-server/src/app/api/agents/[agentName]/restore/route.ts +20 -0
  57. package/apps/agents-server/src/app/api/agents/[agentName]/route.ts +43 -1
  58. package/apps/agents-server/src/app/api/agents/route.ts +28 -3
  59. package/apps/agents-server/src/app/api/api-tokens/route.ts +6 -7
  60. package/apps/agents-server/src/app/api/browser-test/act/route.ts +141 -0
  61. package/apps/agents-server/src/app/api/browser-test/screenshot/route.ts +30 -0
  62. package/apps/agents-server/src/app/api/browser-test/scroll-facebook/route.ts +62 -0
  63. package/apps/agents-server/src/app/api/docs/book.md/route.ts +61 -0
  64. package/apps/agents-server/src/app/api/emails/incoming/sendgrid/route.ts +48 -0
  65. package/apps/agents-server/src/app/api/embed.js/route.ts +87 -67
  66. package/apps/agents-server/src/app/api/federated-agents/route.ts +12 -0
  67. package/apps/agents-server/src/app/api/images/[filename]/route.ts +107 -0
  68. package/apps/agents-server/src/app/api/messages/route.ts +102 -0
  69. package/apps/agents-server/src/app/api/metadata/route.ts +5 -6
  70. package/apps/agents-server/src/app/api/upload/route.ts +128 -45
  71. package/apps/agents-server/src/app/docs/[docId]/page.tsx +2 -3
  72. package/apps/agents-server/src/app/docs/page.tsx +12 -12
  73. package/apps/agents-server/src/app/embed/layout.tsx +31 -0
  74. package/apps/agents-server/src/app/embed/page.tsx +22 -9
  75. package/apps/agents-server/src/app/globals.css +140 -33
  76. package/apps/agents-server/src/app/humans.txt/route.ts +1 -1
  77. package/apps/agents-server/src/app/layout.tsx +27 -22
  78. package/apps/agents-server/src/app/page.tsx +54 -6
  79. package/apps/agents-server/src/app/recycle-bin/actions.ts +20 -14
  80. package/apps/agents-server/src/app/recycle-bin/page.tsx +27 -41
  81. package/apps/agents-server/src/app/robots.txt/route.ts +1 -1
  82. package/apps/agents-server/src/app/security.txt/route.ts +1 -1
  83. package/apps/agents-server/src/app/sitemap.xml/route.ts +9 -7
  84. package/apps/agents-server/src/app/swagger/page.tsx +14 -0
  85. package/apps/agents-server/src/components/AgentProfile/AgentProfile.tsx +41 -116
  86. package/apps/agents-server/src/components/AgentProfile/AgentProfileImage.tsx +92 -0
  87. package/apps/agents-server/src/components/AgentProfile/QrCodeModal.tsx +0 -1
  88. package/apps/agents-server/src/components/AgentProfile/useAgentBackground.ts +97 -0
  89. package/apps/agents-server/src/components/Auth/AuthControls.tsx +5 -4
  90. package/apps/agents-server/src/components/DeletedAgentBanner.tsx +26 -0
  91. package/apps/agents-server/src/components/DocsToolbar/DocsToolbar.tsx +38 -0
  92. package/apps/agents-server/src/components/DocumentationContent/DocumentationContent.tsx +11 -9
  93. package/apps/agents-server/src/components/Footer/Footer.tsx +5 -5
  94. package/apps/agents-server/src/components/ForgottenPasswordDialog/ForgottenPasswordDialog.tsx +61 -0
  95. package/apps/agents-server/src/components/Header/Header.tsx +114 -40
  96. package/apps/agents-server/src/components/Homepage/AgentCard.tsx +145 -23
  97. package/apps/agents-server/src/components/Homepage/AgentsList.tsx +93 -15
  98. package/apps/agents-server/src/components/Homepage/DeletedAgentsList.tsx +66 -0
  99. package/apps/agents-server/src/components/Homepage/ExternalAgentsSection.tsx +12 -3
  100. package/apps/agents-server/src/components/Homepage/ExternalAgentsSectionClient.tsx +19 -10
  101. package/apps/agents-server/src/components/LayoutWrapper/LayoutWrapper.tsx +3 -2
  102. package/apps/agents-server/src/components/LoginForm/LoginForm.tsx +50 -1
  103. package/apps/agents-server/src/components/NewAgentDialog/NewAgentDialog.tsx +88 -0
  104. package/apps/agents-server/src/components/NotFoundPage/NotFoundPage.tsx +7 -2
  105. package/apps/agents-server/src/components/OpenMojiIcon/OpenMojiIcon.tsx +16 -7
  106. package/apps/agents-server/src/components/PrintHeader/PrintHeader.tsx +4 -4
  107. package/apps/agents-server/src/components/RegisterUserDialog/RegisterUserDialog.tsx +61 -0
  108. package/apps/agents-server/src/components/VercelDeploymentCard/VercelDeploymentCard.tsx +2 -0
  109. package/apps/agents-server/src/components/_utils/generateMetaTxt.ts +12 -10
  110. package/apps/agents-server/src/components/_utils/headlessParam.tsx +7 -3
  111. package/apps/agents-server/src/database/$provideSupabaseForBrowser.ts +3 -3
  112. package/apps/agents-server/src/database/$provideSupabaseForServer.ts +1 -1
  113. package/apps/agents-server/src/database/$provideSupabaseForWorker.ts +3 -3
  114. package/apps/agents-server/src/database/metadataDefaults.ts +19 -1
  115. package/apps/agents-server/src/database/migrate.ts +34 -1
  116. package/apps/agents-server/src/database/migrations/2025-11-0001-initial-schema.sql +1 -3
  117. package/apps/agents-server/src/database/migrations/2025-11-0002-metadata-table.sql +1 -3
  118. package/apps/agents-server/src/database/migrations/2025-12-0240-agent-public-id.sql +3 -0
  119. package/apps/agents-server/src/database/migrations/2025-12-0360-agent-deleted-at.sql +1 -0
  120. package/apps/agents-server/src/database/migrations/2025-12-0370-image-table.sql +19 -0
  121. package/apps/agents-server/src/database/migrations/2025-12-0380-agent-visibility.sql +1 -0
  122. package/apps/agents-server/src/database/migrations/2025-12-0390-upload-tracking.sql +20 -0
  123. package/apps/agents-server/src/database/migrations/2025-12-0401-file-upload-status.sql +13 -0
  124. package/apps/agents-server/src/database/migrations/2025-12-0402-message-table.sql +42 -0
  125. package/apps/agents-server/src/database/migrations/2025-12-0403-generation-lock-table.sql +15 -0
  126. package/apps/agents-server/src/database/migrations/2025-12-0640-openai-assistant-cache.sql +12 -0
  127. package/apps/agents-server/src/database/migrations/2025-12-0820-agent-history-permanent-id.sql +29 -0
  128. package/apps/agents-server/src/database/schema.ts +231 -4
  129. package/apps/agents-server/src/generated/reservedPaths.ts +32 -0
  130. package/apps/agents-server/src/message-providers/email/_common/Email.ts +73 -0
  131. package/apps/agents-server/src/message-providers/email/_common/utils/TODO.txt +1 -0
  132. package/apps/agents-server/src/message-providers/email/_common/utils/parseEmailAddress.test.ts.todo +108 -0
  133. package/apps/agents-server/src/message-providers/email/_common/utils/parseEmailAddress.ts +62 -0
  134. package/apps/agents-server/src/message-providers/email/_common/utils/parseEmailAddresses.test.ts.todo +117 -0
  135. package/apps/agents-server/src/message-providers/email/_common/utils/parseEmailAddresses.ts +19 -0
  136. package/apps/agents-server/src/message-providers/email/_common/utils/stringifyEmailAddress.test.ts.todo +119 -0
  137. package/apps/agents-server/src/message-providers/email/_common/utils/stringifyEmailAddress.ts +19 -0
  138. package/apps/agents-server/src/message-providers/email/_common/utils/stringifyEmailAddresses.test.ts.todo +74 -0
  139. package/apps/agents-server/src/message-providers/email/_common/utils/stringifyEmailAddresses.ts +14 -0
  140. package/apps/agents-server/src/message-providers/email/sendgrid/SendgridMessageProvider.ts +44 -0
  141. package/apps/agents-server/src/message-providers/email/sendgrid/parseInboundSendgridEmail.ts +49 -0
  142. package/apps/agents-server/src/message-providers/email/zeptomail/ZeptomailMessageProvider.ts +51 -0
  143. package/apps/agents-server/src/message-providers/index.ts +13 -0
  144. package/apps/agents-server/src/message-providers/interfaces/MessageProvider.ts +11 -0
  145. package/apps/agents-server/src/middleware.ts +19 -23
  146. package/apps/agents-server/src/tools/$provideBrowserForServer.ts +32 -0
  147. package/apps/agents-server/src/tools/$provideCdnForServer.ts +7 -2
  148. package/apps/agents-server/src/utils/auth.ts +117 -17
  149. package/apps/agents-server/src/utils/cdn/classes/TrackedFilesStorage.ts +57 -0
  150. package/apps/agents-server/src/utils/cdn/classes/VercelBlobStorage.ts +4 -0
  151. package/apps/agents-server/src/utils/cdn/interfaces/IFilesStorage.ts +18 -0
  152. package/apps/agents-server/src/utils/content/extractBodyContentFromHtml.ts +19 -0
  153. package/apps/agents-server/src/utils/getUserIdFromRequest.ts +35 -0
  154. package/apps/agents-server/src/utils/handleChatCompletion.ts +65 -5
  155. package/apps/agents-server/src/utils/messages/sendMessage.ts +91 -0
  156. package/apps/agents-server/src/utils/messagesAdmin.ts +72 -0
  157. package/apps/agents-server/src/utils/normalization/filenameToPrompt.test.ts +36 -0
  158. package/apps/agents-server/src/utils/normalization/filenameToPrompt.ts +25 -0
  159. package/apps/agents-server/src/utils/validateApiKey.ts +7 -11
  160. package/esm/index.es.js +2890 -2737
  161. package/esm/index.es.js.map +1 -1
  162. package/esm/typings/servers.d.ts +8 -0
  163. package/esm/typings/src/_packages/core.index.d.ts +2 -0
  164. package/esm/typings/src/_packages/types.index.d.ts +10 -2
  165. package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +6 -1
  166. package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirements.d.ts +6 -6
  167. package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.closed.test.d.ts +1 -0
  168. package/esm/typings/src/book-2.0/utils/generatePlaceholderAgentProfileImageUrl.d.ts +3 -3
  169. package/esm/typings/src/book-components/Chat/Chat/ChatMessageItem.d.ts +5 -1
  170. package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +5 -0
  171. package/esm/typings/src/book-components/Chat/CodeBlock/CodeBlock.d.ts +13 -0
  172. package/esm/typings/src/book-components/Chat/MarkdownContent/MarkdownContent.d.ts +1 -0
  173. package/esm/typings/src/book-components/Chat/types/ChatMessage.d.ts +7 -11
  174. package/esm/typings/src/book-components/_common/Dropdown/Dropdown.d.ts +2 -2
  175. package/esm/typings/src/book-components/_common/MenuHoisting/MenuHoistingContext.d.ts +56 -0
  176. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +21 -11
  177. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentsDatabaseSchema.d.ts +80 -14
  178. package/esm/typings/src/commitments/DICTIONARY/DICTIONARY.d.ts +46 -0
  179. package/esm/typings/src/commitments/index.d.ts +2 -1
  180. package/esm/typings/src/llm-providers/_multiple/MultipleLlmExecutionTools.d.ts +6 -2
  181. package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +1 -1
  182. package/esm/typings/src/llm-providers/ollama/OllamaExecutionTools.d.ts +1 -1
  183. package/esm/typings/src/llm-providers/openai/createOpenAiCompatibleExecutionTools.d.ts +1 -1
  184. package/esm/typings/src/llm-providers/remote/RemoteLlmExecutionTools.d.ts +1 -0
  185. package/esm/typings/src/types/Message.d.ts +49 -0
  186. package/esm/typings/src/types/ModelRequirements.d.ts +38 -14
  187. package/esm/typings/src/types/typeAliases.d.ts +23 -1
  188. package/esm/typings/src/utils/color/utils/colorToDataUrl.d.ts +2 -1
  189. package/esm/typings/src/utils/environment/$detectRuntimeEnvironment.d.ts +4 -4
  190. package/esm/typings/src/utils/environment/$isRunningInBrowser.d.ts +1 -1
  191. package/esm/typings/src/utils/environment/$isRunningInJest.d.ts +1 -1
  192. package/esm/typings/src/utils/environment/$isRunningInNode.d.ts +1 -1
  193. package/esm/typings/src/utils/environment/$isRunningInWebWorker.d.ts +1 -1
  194. package/esm/typings/src/utils/markdown/extractAllBlocksFromMarkdown.d.ts +2 -2
  195. package/esm/typings/src/utils/markdown/extractOneBlockFromMarkdown.d.ts +2 -2
  196. package/esm/typings/src/utils/random/$randomBase58.d.ts +12 -0
  197. package/esm/typings/src/version.d.ts +1 -1
  198. package/package.json +1 -1
  199. package/umd/index.umd.js +4018 -3865
  200. package/umd/index.umd.js.map +1 -1
  201. package/apps/agents-server/package-lock.json +0 -27
  202. package/apps/agents-server/public/fonts/download-font.js +0 -22
  203. package/apps/agents-server/src/components/PrintButton/PrintButton.tsx +0 -18
  204. package/esm/typings/src/book-2.0/utils/generateGravatarUrl.d.ts +0 -10
@@ -1,58 +1,44 @@
1
1
  import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
2
+ import { $provideServer } from '@/src/tools/$provideServer';
2
3
  import { TrashIcon } from 'lucide-react';
3
4
  import Link from 'next/link';
4
- import { RestoreAgentButton } from './RestoreAgentButton';
5
+ import { DeletedAgentsList } from '../../components/Homepage/DeletedAgentsList';
6
+ import { isUserAdmin } from '../../utils/isUserAdmin';
5
7
 
6
8
  export const metadata = {
7
9
  title: 'Recycle Bin',
8
10
  };
9
11
 
10
12
  export default async function RecycleBinPage() {
13
+ const { publicUrl } = await $provideServer();
11
14
  const collection = await $provideAgentCollectionForServer();
12
15
  const deletedAgents = await collection.listDeletedAgents();
16
+ const isAdmin = await isUserAdmin();
13
17
 
14
18
  return (
15
- <div className="container mx-auto p-6 max-w-4xl">
16
- <header className="flex items-center gap-4 mb-8">
17
- <div className="bg-red-100 p-3 rounded-full">
18
- <TrashIcon className="w-8 h-8 text-red-600" />
19
- </div>
20
- <div>
21
- <h1 className="text-3xl font-bold text-gray-900">Recycle Bin</h1>
22
- <p className="text-gray-600">Restore deleted agents from here.</p>
23
- </div>
24
- </header>
19
+ <div className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-purple-50">
20
+ <div className="container mx-auto px-4 py-16">
21
+ <header className="flex items-center gap-4 mb-8">
22
+ <div className="bg-red-100 p-3 rounded-full">
23
+ <TrashIcon className="w-8 h-8 text-red-600" />
24
+ </div>
25
+ <div>
26
+ <h1 className="text-3xl font-bold text-gray-900">Recycle Bin</h1>
27
+ <p className="text-gray-600">Restore deleted agents from here.</p>
28
+ </div>
29
+ </header>
25
30
 
26
- {deletedAgents.length === 0 ? (
27
- <div className="text-center py-12 bg-gray-50 rounded-lg border border-dashed border-gray-300">
28
- <p className="text-gray-500 text-lg">Recycle bin is empty</p>
29
- <Link href="/" className="text-blue-600 hover:underline mt-2 inline-block">
30
- Go back to agents
31
- </Link>
32
- </div>
33
- ) : (
34
- <div className="grid gap-4">
35
- {deletedAgents.map((agentName) => (
36
- <div
37
- key={agentName}
38
- className="bg-white p-4 rounded-lg shadow-sm border border-gray-200 flex items-center justify-between hover:shadow-md transition-shadow"
39
- >
40
- <div className="flex items-center gap-3">
41
- <div className="w-10 h-10 bg-gray-100 rounded-full flex items-center justify-center text-gray-500 font-bold text-lg">
42
- {agentName.charAt(0).toUpperCase()}
43
- </div>
44
- <div>
45
- <h3 className="font-semibold text-lg text-gray-900">{agentName}</h3>
46
- <p className="text-sm text-gray-500">Deleted agent</p>
47
- </div>
48
- </div>
49
- <div className="flex gap-2">
50
- <RestoreAgentButton agentName={agentName} />
51
- </div>
52
- </div>
53
- ))}
54
- </div>
55
- )}
31
+ {deletedAgents.length === 0 ? (
32
+ <div className="text-center py-12 bg-gray-50 rounded-lg border border-dashed border-gray-300">
33
+ <p className="text-gray-500 text-lg">Recycle bin is empty</p>
34
+ <Link href="/" className="text-blue-600 hover:underline mt-2 inline-block">
35
+ Go back to agents
36
+ </Link>
37
+ </div>
38
+ ) : (
39
+ <DeletedAgentsList agents={deletedAgents} isAdmin={isAdmin} publicUrl={publicUrl} />
40
+ )}
41
+ </div>
56
42
  </div>
57
43
  );
58
44
  }
@@ -6,7 +6,7 @@ import { NextResponse } from 'next/server';
6
6
  export const dynamic = 'force-dynamic';
7
7
 
8
8
  export async function GET() {
9
- const txt = generateRobotsTxt();
9
+ const txt = await generateRobotsTxt();
10
10
  return new NextResponse(txt, {
11
11
  headers: {
12
12
  'Content-Type': 'text/plain',
@@ -6,7 +6,7 @@ import { NextResponse } from 'next/server';
6
6
  export const dynamic = 'force-dynamic';
7
7
 
8
8
  export async function GET() {
9
- const txt = generateSecurityTxt();
9
+ const txt = await generateSecurityTxt();
10
10
  return new NextResponse(txt, {
11
11
  headers: {
12
12
  'Content-Type': 'text/plain',
@@ -1,23 +1,25 @@
1
1
  // Dynamic sitemap.xml for Agents Server
2
2
 
3
- import { NEXT_PUBLIC_SITE_URL } from '@/config';
4
3
  import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
4
+ import { $provideServer } from '@/src/tools/$provideServer';
5
5
  import { spaceTrim } from '@promptbook-local/utils';
6
6
  import { NextResponse } from 'next/server';
7
7
 
8
8
  export const dynamic = 'force-dynamic';
9
9
 
10
10
  export async function GET() {
11
+ const { publicUrl } = await $provideServer();
12
+
11
13
  const collection = await $provideAgentCollectionForServer();
12
14
 
13
15
  // Assume collection.listAgents() returns an array of agent names
14
- const agentNames = await collection.listAgents();
15
-
16
- // Get base URL from environment or config
17
- const baseUrl = NEXT_PUBLIC_SITE_URL?.href || process.env.PUBLIC_URL || 'https://ptbk.io';
16
+ const agents = await collection.listAgents();
18
17
 
19
- const urls = agentNames
20
- .map(({ agentName }) => `<url><loc>${baseUrl}agents/${encodeURIComponent(agentName)}</loc></url>`)
18
+ const urls = agents
19
+ .map(
20
+ ({ permanentId, agentName }) =>
21
+ `<url><loc>${publicUrl.href}agents/${encodeURIComponent(permanentId || agentName)}</loc></url>`,
22
+ )
21
23
  .join('\n');
22
24
 
23
25
  const xml = spaceTrim(
@@ -0,0 +1,14 @@
1
+ 'use client';
2
+
3
+ import dynamic from 'next/dynamic';
4
+ import 'swagger-ui-react/swagger-ui.css';
5
+
6
+ const SwaggerUI = dynamic(() => import('swagger-ui-react'), { ssr: false });
7
+
8
+ export default function SwaggerPage() {
9
+ return (
10
+ <div className="swagger-container bg-white min-h-screen">
11
+ <SwaggerUI url="/swagger.json" />
12
+ </div>
13
+ );
14
+ }
@@ -1,14 +1,14 @@
1
1
  'use client';
2
2
 
3
- import { AgentBasicInformation } from '@promptbook-local/types';
3
+ import { colorToDataUrl } from '@promptbook-local/color';
4
+ import { generatePlaceholderAgentProfileImageUrl } from '@promptbook-local/core';
5
+ import { AgentBasicInformation, string_agent_permanent_id } from '@promptbook-local/types';
4
6
  import { RepeatIcon } from 'lucide-react';
5
- import { useMemo, useState } from 'react';
6
- import spaceTrim from 'spacetrim';
7
- import { Color } from '../../../../../src/utils/color/Color';
8
- import { darken } from '../../../../../src/utils/color/operators/darken';
9
- import { lighten } from '../../../../../src/utils/color/operators/lighten';
7
+ import { useState } from 'react';
8
+ import { AgentProfileImage } from './AgentProfileImage';
10
9
  import { AgentQrCode } from './AgentQrCode';
11
10
  import { QrCodeModal } from './QrCodeModal';
11
+ import { useAgentBackground } from './useAgentBackground';
12
12
 
13
13
  type AgentProfileProps = {
14
14
  /**
@@ -16,6 +16,11 @@ type AgentProfileProps = {
16
16
  */
17
17
  readonly agent: AgentBasicInformation;
18
18
 
19
+ /**
20
+ * The permanent ID of the agent
21
+ */
22
+ readonly permanentId: string_agent_permanent_id;
23
+
19
24
  /**
20
25
  * URL of the agent page
21
26
  *
@@ -23,6 +28,11 @@ type AgentProfileProps = {
23
28
  */
24
29
  readonly agentUrl?: string;
25
30
 
31
+ /**
32
+ * Base URL of the agents server
33
+ */
34
+ readonly publicUrl: URL;
35
+
26
36
  /**
27
37
  * Email of the agent
28
38
  */
@@ -61,16 +71,19 @@ export function AgentProfile(props: AgentProfileProps) {
61
71
  agent,
62
72
  agentUrl = '',
63
73
  agentEmail = '',
74
+ publicUrl,
75
+ permanentId,
64
76
  renderMenu,
65
77
  children,
66
78
  actions,
67
79
  isHeadless = false,
68
80
  className,
69
81
  } = props;
82
+
70
83
  const { meta, agentName } = agent;
71
84
  const fullname = (meta.fullname as string) || agentName || 'Agent';
72
85
  const personaDescription = agent.personaDescription || '';
73
- const imageUrl = (meta.image as string) || null;
86
+ const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(permanentId, publicUrl);
74
87
 
75
88
  const [isQrModalOpen, setIsQrModalOpen] = useState(false);
76
89
  const [isFlipped, setIsFlipped] = useState(false);
@@ -81,102 +94,14 @@ export function AgentProfile(props: AgentProfileProps) {
81
94
 
82
95
  if (fontString) {
83
96
  // [🧠] TODO: Properly parse font string to get family name
84
- const primaryFont = fontString.split(',')[0].trim().replace(/['"]/g, '');
97
+ // const primaryFont = fontString.split(',')[0].trim().replace(/['"]/g, '');
85
98
  fontStyle = {
86
99
  fontFamily: fontString,
87
100
  };
88
101
  }
89
102
 
90
103
  // Compute Colors and Background
91
- const { brandColorHex, brandColorLightHex, brandColorDarkHex, backgroundImage } = useMemo(() => {
92
- // [🧠] Default color should be imported constant, but for now hardcoded fallback
93
- const PROMPTBOOK_COLOR_HEX = '#f15b24'; // TODO: Import PROMPTBOOK_COLOR
94
- const brandColorString = meta.color || PROMPTBOOK_COLOR_HEX;
95
-
96
- let brandColor;
97
- try {
98
- brandColor = Color.fromSafe(brandColorString.split(',')[0].trim());
99
- } catch {
100
- brandColor = Color.fromHex(PROMPTBOOK_COLOR_HEX);
101
- }
102
-
103
- const brandColorHex = brandColor.toHex();
104
- const brandColorLightHex = brandColor.then(lighten(0.2)).toHex();
105
- const brandColorDarkHex = brandColor.then(darken(0.15)).toHex();
106
-
107
- // Generate Noisy SVG Background
108
- const color1 = brandColor;
109
- // const color2 = brandColors[1] || brandColors[0]!; // Use secondary color if available?
110
- // For simplicity using primary color for now or derive second one
111
- const color2 = brandColor;
112
-
113
- // [🧠] Make colors much lighter for the background
114
- const color1Light = color1.then(lighten(0.3)).toHex();
115
- const color1Main = color1.toHex();
116
- const color1Dark = color1.then(darken(0.3)).toHex();
117
-
118
- const color2Light = color2.then(lighten(0.3)).toHex();
119
- const color2Main = color2.toHex();
120
- const color2Dark = color2.then(darken(0.3)).toHex();
121
-
122
- const svgContent = spaceTrim(`
123
- <svg xmlns="http://www.w3.org/2000/svg"
124
- viewBox="0 0 1920 1080"
125
- width="1920" height="1080"
126
- preserveAspectRatio="xMidYMid slice">
127
- <defs>
128
- <!-- Bottom-left -->
129
- <radialGradient id="grad1" cx="0%" cy="100%" r="90%">
130
- <stop offset="0%" stop-color="${color1Light}" />
131
- <stop offset="50%" stop-color="${color1Main}" />
132
- <stop offset="100%" stop-color="${color1Dark}" />
133
- </radialGradient>
134
-
135
- <!-- Bottom-right -->
136
- <radialGradient id="grad2" cx="100%" cy="100%" r="90%">
137
- <stop offset="0%" stop-color="${color2Light}" />
138
- <stop offset="50%" stop-color="${color2Main}" />
139
- <stop offset="100%" stop-color="${color2Dark}" />
140
- </radialGradient>
141
-
142
- <!-- White top fade -->
143
- <linearGradient id="whiteTopGrad" x1="0%" y1="0%" x2="0%" y2="100%">
144
- <stop offset="0%" stop-color="#ffffff" stop-opacity="1" />
145
- <stop offset="100%" stop-color="#ffffff" stop-opacity="0.3" />
146
- </linearGradient>
147
-
148
- <!-- Strong grain -->
149
- <filter id="grain" x="-10%" y="-10%" width="120%" height="120%">
150
- <feTurbulence type="fractalNoise" baseFrequency="3.5" numOctaves="3" seed="8" result="noise" />
151
- <feComponentTransfer>
152
- <feFuncR type="linear" slope="3.5" intercept="-1.2" />
153
- <feFuncG type="linear" slope="3.5" intercept="-1.2" />
154
- <feFuncB type="linear" slope="3.5" intercept="-1.2" />
155
- <feFuncA type="table" tableValues="0 0.8" />
156
- </feComponentTransfer>
157
- </filter>
158
- </defs>
159
-
160
- <!-- White base -->
161
- <rect width="100%" height="100%" fill="#ffffff" />
162
-
163
- <!-- Gradients -->
164
- <rect width="100%" height="100%" fill="url(#grad1)" />
165
- <rect width="100%" height="100%" fill="url(#grad2)" style="mix-blend-mode:screen; opacity:0.85" />
166
-
167
- <!-- White fade on top -->
168
- <rect width="100%" height="100%" fill="url(#whiteTopGrad)" />
169
-
170
- <!-- Strong visible noise -->
171
- <rect width="100%" height="100%" filter="url(#grain)"
172
- style="mix-blend-mode:soft-light; opacity:1.2" />
173
- </svg>
174
- `);
175
-
176
- const backgroundImage = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgContent)}`;
177
-
178
- return { brandColorHex, brandColorLightHex, brandColorDarkHex, backgroundImage };
179
- }, [meta.color]);
104
+ const { brandColorHex, brandColorLightHex, brandColorDarkHex, backgroundImage } = useAgentBackground(meta.color);
180
105
 
181
106
  return (
182
107
  <>
@@ -208,14 +133,14 @@ export function AgentProfile(props: AgentProfileProps) {
208
133
  )}
209
134
 
210
135
  {/* Main profile content */}
211
- <div className="relative z-10 grid grid-cols-[auto_1fr] gap-x-6 gap-y-4 md:gap-12 max-w-5xl w-full items-start">
136
+ <div className="relative z-10 flex flex-col md:grid md:grid-cols-[auto_1fr] gap-y-6 md:gap-y-4 md:gap-x-12 max-w-5xl w-full items-center md:items-start">
212
137
  {/* Agent image card (Flippable) */}
213
138
  <div
214
- className="flex-shrink-0 perspective-1000 group row-start-1 col-start-1 md:row-span-3"
139
+ className="flex-shrink-0 perspective-1000 group w-full md:w-auto md:row-start-1 md:col-start-1 md:row-span-3"
215
140
  style={{ perspective: '1000px' }}
216
141
  >
217
142
  <div
218
- className="relative w-24 md:w-80 transition-all duration-700 transform-style-3d cursor-pointer"
143
+ className="relative w-full md:w-80 transition-all duration-700 transform-style-3d cursor-pointer max-w-sm mx-auto md:max-w-none md:mx-0"
219
144
  style={{
220
145
  aspectRatio: '1 / 1.618', // Golden Ratio
221
146
  transformStyle: 'preserve-3d',
@@ -230,19 +155,21 @@ export function AgentProfile(props: AgentProfileProps) {
230
155
  backfaceVisibility: 'hidden',
231
156
  backgroundColor: brandColorDarkHex,
232
157
  boxShadow: `0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 0 0 1px ${brandColorLightHex}40`,
158
+
159
+ // Note: Make it squircle
160
+ // borderRadius: '50%',
161
+ // ['cornerShape' as really_any /* <- Note: `cornerShape` is non standard CSS property */]: 'squircle ',
233
162
  }}
234
163
  >
235
- {imageUrl ? (
236
- // eslint-disable-next-line @next/next/no-img-element
237
- <img src={imageUrl} alt={fullname} className="w-full h-full object-cover" />
238
- ) : (
239
- <div
240
- className="w-full h-full flex items-center justify-center text-3xl md:text-8xl font-bold text-white/80"
241
- style={{ backgroundColor: brandColorDarkHex }}
242
- >
243
- {fullname.charAt(0).toUpperCase()}
244
- </div>
245
- )}
164
+ <AgentProfileImage
165
+ src={imageUrl}
166
+ alt={fullname}
167
+ className="w-full h-full object-cover"
168
+ style={{
169
+ objectFit: 'cover',
170
+ backgroundImage: `url(${colorToDataUrl(brandColorLightHex)})`,
171
+ }}
172
+ />
246
173
 
247
174
  {/* Flip hint icon */}
248
175
  <div className="absolute bottom-2 md:bottom-4 right-2 md:right-4 bg-black/30 p-1 md:p-2 rounded-full text-white/80 backdrop-blur-md opacity-0 group-hover:opacity-100 transition-opacity">
@@ -280,7 +207,7 @@ export function AgentProfile(props: AgentProfileProps) {
280
207
  </div>
281
208
 
282
209
  {/* Agent info - Header Area */}
283
- <div className="row-start-1 col-start-2 flex flex-col justify-center md:justify-start h-full md:h-auto gap-1 md:gap-6">
210
+ <div className="w-full md:w-auto md:row-start-1 md:col-start-2 flex flex-col justify-center md:justify-start items-center md:items-start h-auto gap-4 md:gap-6 text-center md:text-left">
284
211
  {/* Agent name with custom font */}
285
212
  <h1
286
213
  className="text-2xl md:text-5xl lg:text-6xl font-bold text-gray-900 tracking-tight leading-tight"
@@ -298,13 +225,11 @@ export function AgentProfile(props: AgentProfileProps) {
298
225
  </div>
299
226
 
300
227
  {/* Chat Area */}
301
- <div className="col-span-2 md:col-span-1 md:col-start-2 w-full mt-2 md:mt-0">
302
- {children}
303
- </div>
228
+ <div className="w-full md:col-span-1 md:col-start-2 mt-4 md:mt-0">{children}</div>
304
229
 
305
230
  {/* Secondary Actions */}
306
231
  {!isHeadless && (
307
- <div className="col-span-2 md:col-span-1 md:col-start-2 flex flex-wrap justify-center md:justify-start items-center gap-4 md:gap-6 mt-2">
232
+ <div className="w-full md:col-span-1 md:col-start-2 flex flex-wrap justify-center md:justify-start items-center gap-4 md:gap-6 mt-4 md:mt-2">
308
233
  {actions}
309
234
  </div>
310
235
  )}
@@ -0,0 +1,92 @@
1
+ import { Loader2 } from 'lucide-react';
2
+ import { useEffect, useState } from 'react';
3
+
4
+ type AgentProfileImageProps = {
5
+ readonly src: string;
6
+ readonly alt: string;
7
+ readonly className?: string;
8
+ readonly style?: React.CSSProperties;
9
+ };
10
+
11
+ export function AgentProfileImage({ src, alt, className, style }: AgentProfileImageProps) {
12
+ const [imageSrc, setImageSrc] = useState<string | null>(null);
13
+ const [isLoading, setIsLoading] = useState(true);
14
+
15
+ useEffect(() => {
16
+ let isMounted = true;
17
+ let timeoutId: NodeJS.Timeout;
18
+ let objectUrl: string | null = null;
19
+
20
+ const fetchImage = async () => {
21
+ try {
22
+ const response = await fetch(src);
23
+ if (response.ok) {
24
+ const blob = await response.blob();
25
+ if (!isMounted) {
26
+ return;
27
+ }
28
+
29
+ objectUrl = URL.createObjectURL(blob);
30
+ setImageSrc(objectUrl);
31
+ setIsLoading(false);
32
+ } else {
33
+ // Retry on non-200
34
+ if (isMounted) {
35
+ timeoutId = setTimeout(fetchImage, 2000);
36
+ }
37
+ }
38
+ } catch (error) {
39
+ console.warn('Failed to fetch image, retrying...', error);
40
+ if (isMounted) {
41
+ timeoutId = setTimeout(fetchImage, 2000);
42
+ }
43
+ }
44
+ };
45
+
46
+ const isExternal = (() => {
47
+ try {
48
+ return new URL(src, window.location.href).origin !== window.location.origin;
49
+ } catch {
50
+ return false;
51
+ }
52
+ })();
53
+
54
+ if (isExternal) {
55
+ setImageSrc(src);
56
+ setIsLoading(false);
57
+ } else {
58
+ setIsLoading(true);
59
+ fetchImage();
60
+ }
61
+
62
+ return () => {
63
+ isMounted = false;
64
+ clearTimeout(timeoutId);
65
+ if (objectUrl) {
66
+ URL.revokeObjectURL(objectUrl);
67
+ }
68
+ };
69
+ }, [src]);
70
+
71
+ return (
72
+ <div className={`relative ${className}`} style={style}>
73
+ {/* Note: We apply style to the container, so backgroundImage works here */}
74
+
75
+ {isLoading && (
76
+ <div className="absolute inset-0 flex items-center justify-center">
77
+ <Loader2 className="w-8 h-8 animate-spin text-white/50" />
78
+ </div>
79
+ )}
80
+
81
+ {imageSrc && (
82
+ // eslint-disable-next-line @next/next/no-img-element
83
+ <img
84
+ src={imageSrc}
85
+ alt={alt}
86
+ className="w-full h-full object-cover"
87
+ // We don't pass style here because it is applied to container
88
+ />
89
+ )}
90
+ </div>
91
+ );
92
+ }
@@ -24,7 +24,6 @@ export function QrCodeModal({
24
24
  personaDescription,
25
25
  agentUrl,
26
26
  agentEmail,
27
- brandColorHex,
28
27
  }: QrCodeModalProps) {
29
28
  useEffect(() => {
30
29
  if (isOpen) {
@@ -0,0 +1,97 @@
1
+ import { Color } from '../../../../../src/utils/color/Color';
2
+ import { darken } from '../../../../../src/utils/color/operators/darken';
3
+ import { lighten } from '../../../../../src/utils/color/operators/lighten';
4
+ import { useMemo } from 'react';
5
+ import spaceTrim from 'spacetrim';
6
+
7
+ export function useAgentBackground(colorString: string | undefined) {
8
+ return useMemo(() => {
9
+ // [🧠] Default color should be imported constant, but for now hardcoded fallback
10
+ const PROMPTBOOK_COLOR_HEX = '#f15b24'; // TODO: Import PROMPTBOOK_COLOR
11
+ const brandColorString = colorString || PROMPTBOOK_COLOR_HEX;
12
+
13
+ let brandColor;
14
+ try {
15
+ brandColor = Color.fromSafe(brandColorString.split(',')[0].trim());
16
+ } catch {
17
+ brandColor = Color.fromHex(PROMPTBOOK_COLOR_HEX);
18
+ }
19
+
20
+ const brandColorHex = brandColor.toHex();
21
+ const brandColorLightHex = brandColor.then(lighten(0.2)).toHex();
22
+ const brandColorDarkHex = brandColor.then(darken(0.15)).toHex();
23
+
24
+ // Generate Noisy SVG Background
25
+ const color1 = brandColor;
26
+ // const color2 = brandColors[1] || brandColors[0]!; // Use secondary color if available?
27
+ // For simplicity using primary color for now or derive second one
28
+ const color2 = brandColor;
29
+
30
+ // [🧠] Make colors much lighter for the background
31
+ const color1Light = color1.then(lighten(0.3)).toHex();
32
+ const color1Main = color1.toHex();
33
+ const color1Dark = color1.then(darken(0.3)).toHex();
34
+
35
+ const color2Light = color2.then(lighten(0.3)).toHex();
36
+ const color2Main = color2.toHex();
37
+ const color2Dark = color2.then(darken(0.3)).toHex();
38
+
39
+ const svgContent = spaceTrim(`
40
+ <svg xmlns="http://www.w3.org/2000/svg"
41
+ viewBox="0 0 1920 1080"
42
+ width="1920" height="1080"
43
+ preserveAspectRatio="xMidYMid slice">
44
+ <defs>
45
+ <!-- Bottom-left -->
46
+ <radialGradient id="grad1" cx="0%" cy="100%" r="90%">
47
+ <stop offset="0%" stop-color="${color1Light}" />
48
+ <stop offset="50%" stop-color="${color1Main}" />
49
+ <stop offset="100%" stop-color="${color1Dark}" />
50
+ </radialGradient>
51
+
52
+ <!-- Bottom-right -->
53
+ <radialGradient id="grad2" cx="100%" cy="100%" r="90%">
54
+ <stop offset="0%" stop-color="${color2Light}" />
55
+ <stop offset="50%" stop-color="${color2Main}" />
56
+ <stop offset="100%" stop-color="${color2Dark}" />
57
+ </radialGradient>
58
+
59
+ <!-- White top fade -->
60
+ <linearGradient id="whiteTopGrad" x1="0%" y1="0%" x2="0%" y2="100%">
61
+ <stop offset="0%" stop-color="#ffffff" stop-opacity="1" />
62
+ <stop offset="100%" stop-color="#ffffff" stop-opacity="0.3" />
63
+ </linearGradient>
64
+
65
+ <!-- Strong grain -->
66
+ <filter id="grain" x="-10%" y="-10%" width="120%" height="120%">
67
+ <feTurbulence type="fractalNoise" baseFrequency="3.5" numOctaves="3" seed="8" result="noise" />
68
+ <feComponentTransfer>
69
+ <feFuncR type="linear" slope="3.5" intercept="-1.2" />
70
+ <feFuncG type="linear" slope="3.5" intercept="-1.2" />
71
+ <feFuncB type="linear" slope="3.5" intercept="-1.2" />
72
+ <feFuncA type="table" tableValues="0 0.8" />
73
+ </feComponentTransfer>
74
+ </filter>
75
+ </defs>
76
+
77
+ <!-- White base -->
78
+ <rect width="100%" height="100%" fill="#ffffff" />
79
+
80
+ <!-- Gradients -->
81
+ <rect width="100%" height="100%" fill="url(#grad1)" />
82
+ <rect width="100%" height="100%" fill="url(#grad2)" style="mix-blend-mode:screen; opacity:0.85" />
83
+
84
+ <!-- White fade on top -->
85
+ <rect width="100%" height="100%" fill="url(#whiteTopGrad)" />
86
+
87
+ <!-- Strong visible noise -->
88
+ <rect width="100%" height="100%" filter="url(#grain)"
89
+ style="mix-blend-mode:soft-light; opacity:1.2" />
90
+ </svg>
91
+ `);
92
+
93
+ const backgroundImage = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgContent)}`;
94
+
95
+ return { brandColorHex, brandColorLightHex, brandColorDarkHex, backgroundImage };
96
+ }, [colorString]);
97
+ }
@@ -1,15 +1,14 @@
1
1
  'use client';
2
2
 
3
3
  import { useState } from 'react';
4
- import { useRouter } from 'next/navigation';
5
4
 
6
5
  type AuthControlsProps = {
7
6
  initialUser: { username: string; isAdmin: boolean } | null;
8
7
  };
9
8
 
10
9
  export function AuthControls({ initialUser }: AuthControlsProps) {
11
- const router = useRouter();
12
- const [user, setUser] = useState(initialUser);
10
+ // const router = useRouter();
11
+ const [user] = useState(initialUser);
13
12
  const [isLoginOpen, setIsLoginOpen] = useState(false);
14
13
  const [username, setUsername] = useState('');
15
14
  const [password, setPassword] = useState('');
@@ -52,7 +51,9 @@ export function AuthControls({ initialUser }: AuthControlsProps) {
52
51
  <div className="flex items-center space-x-4">
53
52
  <span className="text-gray-600">
54
53
  Logged in as <strong>{user.username}</strong>
55
- {user.isAdmin && <span className="ml-2 bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded">Admin</span>}
54
+ {user.isAdmin && (
55
+ <span className="ml-2 bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded">Admin</span>
56
+ )}
56
57
  </span>
57
58
  <button
58
59
  onClick={handleLogout}
@@ -0,0 +1,26 @@
1
+ 'use client';
2
+
3
+ type DeletedAgentBannerProps = {
4
+ message?: string;
5
+ };
6
+
7
+ export function DeletedAgentBanner({
8
+ message = "This agent has been deleted. You can restore it from the Recycle Bin."
9
+ }: DeletedAgentBannerProps) {
10
+ return (
11
+ <div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4 mb-6">
12
+ <div className="flex">
13
+ <div className="flex-shrink-0">
14
+ <svg className="h-5 w-5 text-yellow-400" viewBox="0 0 20 20" fill="currentColor">
15
+ <path fillRule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clipRule="evenodd" />
16
+ </svg>
17
+ </div>
18
+ <div className="ml-3">
19
+ <p className="text-sm text-yellow-700">
20
+ {message}
21
+ </p>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ );
26
+ }