@promptbook/cli 0.104.0-1 → 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 (199) 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/page.tsx +10 -3
  48. package/apps/agents-server/src/app/agents/[agentName]/links/page.tsx +11 -4
  49. package/apps/agents-server/src/app/agents/[agentName]/opengraph-image.tsx +11 -2
  50. package/apps/agents-server/src/app/agents/[agentName]/page.tsx +18 -10
  51. package/apps/agents-server/src/app/agents/[agentName]/system-message/page.tsx +100 -0
  52. package/apps/agents-server/src/app/api/admin-email/route.ts +12 -0
  53. package/apps/agents-server/src/app/api/agents/[agentName]/clone/route.ts +13 -14
  54. package/apps/agents-server/src/app/api/agents/[agentName]/restore/route.ts +20 -0
  55. package/apps/agents-server/src/app/api/agents/[agentName]/route.ts +43 -1
  56. package/apps/agents-server/src/app/api/agents/route.ts +28 -3
  57. package/apps/agents-server/src/app/api/api-tokens/route.ts +6 -7
  58. package/apps/agents-server/src/app/api/browser-test/act/route.ts +141 -0
  59. package/apps/agents-server/src/app/api/browser-test/screenshot/route.ts +30 -0
  60. package/apps/agents-server/src/app/api/browser-test/scroll-facebook/route.ts +62 -0
  61. package/apps/agents-server/src/app/api/docs/book.md/route.ts +61 -0
  62. package/apps/agents-server/src/app/api/emails/incoming/sendgrid/route.ts +48 -0
  63. package/apps/agents-server/src/app/api/federated-agents/route.ts +12 -0
  64. package/apps/agents-server/src/app/api/images/[filename]/route.ts +107 -0
  65. package/apps/agents-server/src/app/api/messages/route.ts +102 -0
  66. package/apps/agents-server/src/app/api/metadata/route.ts +5 -6
  67. package/apps/agents-server/src/app/api/upload/route.ts +128 -45
  68. package/apps/agents-server/src/app/docs/[docId]/page.tsx +2 -3
  69. package/apps/agents-server/src/app/docs/page.tsx +12 -12
  70. package/apps/agents-server/src/app/globals.css +140 -33
  71. package/apps/agents-server/src/app/humans.txt/route.ts +1 -1
  72. package/apps/agents-server/src/app/layout.tsx +27 -22
  73. package/apps/agents-server/src/app/page.tsx +54 -6
  74. package/apps/agents-server/src/app/recycle-bin/actions.ts +20 -14
  75. package/apps/agents-server/src/app/recycle-bin/page.tsx +27 -41
  76. package/apps/agents-server/src/app/robots.txt/route.ts +1 -1
  77. package/apps/agents-server/src/app/security.txt/route.ts +1 -1
  78. package/apps/agents-server/src/app/sitemap.xml/route.ts +9 -7
  79. package/apps/agents-server/src/app/swagger/page.tsx +14 -0
  80. package/apps/agents-server/src/components/AgentProfile/AgentProfile.tsx +41 -116
  81. package/apps/agents-server/src/components/AgentProfile/AgentProfileImage.tsx +92 -0
  82. package/apps/agents-server/src/components/AgentProfile/QrCodeModal.tsx +0 -1
  83. package/apps/agents-server/src/components/AgentProfile/useAgentBackground.ts +97 -0
  84. package/apps/agents-server/src/components/Auth/AuthControls.tsx +5 -4
  85. package/apps/agents-server/src/components/DeletedAgentBanner.tsx +26 -0
  86. package/apps/agents-server/src/components/DocsToolbar/DocsToolbar.tsx +38 -0
  87. package/apps/agents-server/src/components/DocumentationContent/DocumentationContent.tsx +11 -9
  88. package/apps/agents-server/src/components/Footer/Footer.tsx +5 -5
  89. package/apps/agents-server/src/components/ForgottenPasswordDialog/ForgottenPasswordDialog.tsx +61 -0
  90. package/apps/agents-server/src/components/Header/Header.tsx +114 -40
  91. package/apps/agents-server/src/components/Homepage/AgentCard.tsx +145 -23
  92. package/apps/agents-server/src/components/Homepage/AgentsList.tsx +93 -15
  93. package/apps/agents-server/src/components/Homepage/DeletedAgentsList.tsx +66 -0
  94. package/apps/agents-server/src/components/Homepage/ExternalAgentsSection.tsx +12 -3
  95. package/apps/agents-server/src/components/Homepage/ExternalAgentsSectionClient.tsx +19 -10
  96. package/apps/agents-server/src/components/LayoutWrapper/LayoutWrapper.tsx +3 -2
  97. package/apps/agents-server/src/components/LoginForm/LoginForm.tsx +50 -1
  98. package/apps/agents-server/src/components/NewAgentDialog/NewAgentDialog.tsx +88 -0
  99. package/apps/agents-server/src/components/NotFoundPage/NotFoundPage.tsx +7 -2
  100. package/apps/agents-server/src/components/OpenMojiIcon/OpenMojiIcon.tsx +16 -7
  101. package/apps/agents-server/src/components/PrintHeader/PrintHeader.tsx +4 -4
  102. package/apps/agents-server/src/components/RegisterUserDialog/RegisterUserDialog.tsx +61 -0
  103. package/apps/agents-server/src/components/VercelDeploymentCard/VercelDeploymentCard.tsx +2 -0
  104. package/apps/agents-server/src/components/_utils/generateMetaTxt.ts +12 -10
  105. package/apps/agents-server/src/components/_utils/headlessParam.tsx +7 -3
  106. package/apps/agents-server/src/database/$provideSupabaseForBrowser.ts +3 -3
  107. package/apps/agents-server/src/database/$provideSupabaseForServer.ts +1 -1
  108. package/apps/agents-server/src/database/$provideSupabaseForWorker.ts +3 -3
  109. package/apps/agents-server/src/database/metadataDefaults.ts +19 -1
  110. package/apps/agents-server/src/database/migrate.ts +34 -1
  111. package/apps/agents-server/src/database/migrations/2025-11-0001-initial-schema.sql +1 -3
  112. package/apps/agents-server/src/database/migrations/2025-11-0002-metadata-table.sql +1 -3
  113. package/apps/agents-server/src/database/migrations/2025-12-0240-agent-public-id.sql +3 -0
  114. package/apps/agents-server/src/database/migrations/2025-12-0360-agent-deleted-at.sql +1 -0
  115. package/apps/agents-server/src/database/migrations/2025-12-0370-image-table.sql +19 -0
  116. package/apps/agents-server/src/database/migrations/2025-12-0380-agent-visibility.sql +1 -0
  117. package/apps/agents-server/src/database/migrations/2025-12-0390-upload-tracking.sql +20 -0
  118. package/apps/agents-server/src/database/migrations/2025-12-0401-file-upload-status.sql +13 -0
  119. package/apps/agents-server/src/database/migrations/2025-12-0402-message-table.sql +42 -0
  120. package/apps/agents-server/src/database/migrations/2025-12-0403-generation-lock-table.sql +15 -0
  121. package/apps/agents-server/src/database/migrations/2025-12-0640-openai-assistant-cache.sql +12 -0
  122. package/apps/agents-server/src/database/migrations/2025-12-0820-agent-history-permanent-id.sql +29 -0
  123. package/apps/agents-server/src/database/schema.ts +231 -4
  124. package/apps/agents-server/src/generated/reservedPaths.ts +32 -0
  125. package/apps/agents-server/src/message-providers/email/_common/Email.ts +73 -0
  126. package/apps/agents-server/src/message-providers/email/_common/utils/TODO.txt +1 -0
  127. package/apps/agents-server/src/message-providers/email/_common/utils/parseEmailAddress.test.ts.todo +108 -0
  128. package/apps/agents-server/src/message-providers/email/_common/utils/parseEmailAddress.ts +62 -0
  129. package/apps/agents-server/src/message-providers/email/_common/utils/parseEmailAddresses.test.ts.todo +117 -0
  130. package/apps/agents-server/src/message-providers/email/_common/utils/parseEmailAddresses.ts +19 -0
  131. package/apps/agents-server/src/message-providers/email/_common/utils/stringifyEmailAddress.test.ts.todo +119 -0
  132. package/apps/agents-server/src/message-providers/email/_common/utils/stringifyEmailAddress.ts +19 -0
  133. package/apps/agents-server/src/message-providers/email/_common/utils/stringifyEmailAddresses.test.ts.todo +74 -0
  134. package/apps/agents-server/src/message-providers/email/_common/utils/stringifyEmailAddresses.ts +14 -0
  135. package/apps/agents-server/src/message-providers/email/sendgrid/SendgridMessageProvider.ts +44 -0
  136. package/apps/agents-server/src/message-providers/email/sendgrid/parseInboundSendgridEmail.ts +49 -0
  137. package/apps/agents-server/src/message-providers/email/zeptomail/ZeptomailMessageProvider.ts +51 -0
  138. package/apps/agents-server/src/message-providers/index.ts +13 -0
  139. package/apps/agents-server/src/message-providers/interfaces/MessageProvider.ts +11 -0
  140. package/apps/agents-server/src/middleware.ts +19 -23
  141. package/apps/agents-server/src/tools/$provideBrowserForServer.ts +32 -0
  142. package/apps/agents-server/src/tools/$provideCdnForServer.ts +7 -2
  143. package/apps/agents-server/src/utils/auth.ts +117 -17
  144. package/apps/agents-server/src/utils/cdn/classes/TrackedFilesStorage.ts +57 -0
  145. package/apps/agents-server/src/utils/cdn/classes/VercelBlobStorage.ts +4 -0
  146. package/apps/agents-server/src/utils/cdn/interfaces/IFilesStorage.ts +18 -0
  147. package/apps/agents-server/src/utils/content/extractBodyContentFromHtml.ts +19 -0
  148. package/apps/agents-server/src/utils/getUserIdFromRequest.ts +35 -0
  149. package/apps/agents-server/src/utils/handleChatCompletion.ts +65 -5
  150. package/apps/agents-server/src/utils/messages/sendMessage.ts +91 -0
  151. package/apps/agents-server/src/utils/messagesAdmin.ts +72 -0
  152. package/apps/agents-server/src/utils/normalization/filenameToPrompt.test.ts +36 -0
  153. package/apps/agents-server/src/utils/normalization/filenameToPrompt.ts +25 -0
  154. package/apps/agents-server/src/utils/validateApiKey.ts +7 -11
  155. package/esm/index.es.js +2890 -2737
  156. package/esm/index.es.js.map +1 -1
  157. package/esm/typings/servers.d.ts +8 -0
  158. package/esm/typings/src/_packages/core.index.d.ts +2 -0
  159. package/esm/typings/src/_packages/types.index.d.ts +10 -2
  160. package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +6 -1
  161. package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirements.d.ts +6 -6
  162. package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.closed.test.d.ts +1 -0
  163. package/esm/typings/src/book-2.0/utils/generatePlaceholderAgentProfileImageUrl.d.ts +3 -3
  164. package/esm/typings/src/book-components/Chat/Chat/ChatMessageItem.d.ts +5 -1
  165. package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +5 -0
  166. package/esm/typings/src/book-components/Chat/CodeBlock/CodeBlock.d.ts +13 -0
  167. package/esm/typings/src/book-components/Chat/MarkdownContent/MarkdownContent.d.ts +1 -0
  168. package/esm/typings/src/book-components/Chat/types/ChatMessage.d.ts +7 -11
  169. package/esm/typings/src/book-components/_common/Dropdown/Dropdown.d.ts +2 -2
  170. package/esm/typings/src/book-components/_common/MenuHoisting/MenuHoistingContext.d.ts +56 -0
  171. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +21 -11
  172. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentsDatabaseSchema.d.ts +80 -14
  173. package/esm/typings/src/commitments/DICTIONARY/DICTIONARY.d.ts +46 -0
  174. package/esm/typings/src/commitments/index.d.ts +2 -1
  175. package/esm/typings/src/llm-providers/_multiple/MultipleLlmExecutionTools.d.ts +6 -2
  176. package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +1 -1
  177. package/esm/typings/src/llm-providers/ollama/OllamaExecutionTools.d.ts +1 -1
  178. package/esm/typings/src/llm-providers/openai/createOpenAiCompatibleExecutionTools.d.ts +1 -1
  179. package/esm/typings/src/llm-providers/remote/RemoteLlmExecutionTools.d.ts +1 -0
  180. package/esm/typings/src/types/Message.d.ts +49 -0
  181. package/esm/typings/src/types/ModelRequirements.d.ts +38 -14
  182. package/esm/typings/src/types/typeAliases.d.ts +23 -1
  183. package/esm/typings/src/utils/color/utils/colorToDataUrl.d.ts +2 -1
  184. package/esm/typings/src/utils/environment/$detectRuntimeEnvironment.d.ts +4 -4
  185. package/esm/typings/src/utils/environment/$isRunningInBrowser.d.ts +1 -1
  186. package/esm/typings/src/utils/environment/$isRunningInJest.d.ts +1 -1
  187. package/esm/typings/src/utils/environment/$isRunningInNode.d.ts +1 -1
  188. package/esm/typings/src/utils/environment/$isRunningInWebWorker.d.ts +1 -1
  189. package/esm/typings/src/utils/markdown/extractAllBlocksFromMarkdown.d.ts +2 -2
  190. package/esm/typings/src/utils/markdown/extractOneBlockFromMarkdown.d.ts +2 -2
  191. package/esm/typings/src/utils/random/$randomBase58.d.ts +12 -0
  192. package/esm/typings/src/version.d.ts +1 -1
  193. package/package.json +1 -1
  194. package/umd/index.umd.js +4018 -3865
  195. package/umd/index.umd.js.map +1 -1
  196. package/apps/agents-server/package-lock.json +0 -27
  197. package/apps/agents-server/public/fonts/download-font.js +0 -22
  198. package/apps/agents-server/src/components/PrintButton/PrintButton.tsx +0 -18
  199. package/esm/typings/src/book-2.0/utils/generateGravatarUrl.d.ts +0 -10
@@ -29,9 +29,7 @@ const config = ConfigChecker.from({
29
29
  *
30
30
  * Note: When `SERVERS` are used, this URL will be overridden by the server URL.
31
31
  */
32
- export const NEXT_PUBLIC_SITE_URL = config
33
- .get('NEXT_PUBLIC_SITE_URL')
34
- .url()./* <- TODO: !!!! Is it ok not to be required().*/ value;
32
+ export const NEXT_PUBLIC_SITE_URL = config.get('NEXT_PUBLIC_SITE_URL').url().value;
35
33
 
36
34
  /**
37
35
  * [♐️] Vercel environment: "development" | "preview" | "production"
@@ -2,8 +2,8 @@ import type { NextConfig } from 'next';
2
2
  import path from 'path';
3
3
 
4
4
  const nextConfig: NextConfig = {
5
- output: 'standalone',
6
- // <- TODO: [🐱‍🚀][🧠] How to propperly build Next.js app
5
+ // output: 'standalone',
6
+ // <- TODO: [🐱‍🚀][🧠] How to propperly build Next.js app, for both Vercel and Doceker?
7
7
 
8
8
  experimental: {
9
9
  externalDir: true,
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "promptbook-agents-server",
3
3
  "scripts": {
4
- "migrate-database": "npx tsx src/database/migrate.ts",
4
+ "migrate-database": "npx tsx ./src/database/migrate.ts",
5
+ "generate-reserved-paths": "ts-node ./scripts/generate-reserved-paths/generate-reserved-paths.ts",
6
+ "prebuild": "npm run generate-reserved-paths",
7
+ "predev": "npm run generate-reserved-paths",
5
8
  "dev": "(npx kill-port 4440 || true) && next dev -p 4440",
6
- "test-build": "npm run build",
9
+ "test": "npm run lint && npm run test-build",
10
+ "test-build": "(npx kill-port 4440 || true) && next build",
7
11
  "build": "(npx kill-port 4440 || true) && next build",
8
12
  "start": "next start -p 4440",
9
- "lint": "next lint",
13
+ "lint": "next lint --max-warnings=0",
10
14
  "postinstall": "cd ../../ && npm ci"
11
15
  }
12
16
  }
@@ -0,0 +1,115 @@
1
+ {
2
+ "openapi": "3.0.0",
3
+ "info": {
4
+ "title": "Agents Server API",
5
+ "version": "1.0.0",
6
+ "description": "API documentation for the Agents Server"
7
+ },
8
+ "servers": [
9
+ {
10
+ "url": "/",
11
+ "description": "Current Server"
12
+ }
13
+ ],
14
+ "paths": {
15
+ "/api/agents": {
16
+ "get": {
17
+ "summary": "List all agents",
18
+ "tags": ["Agents"],
19
+ "responses": {
20
+ "200": {
21
+ "description": "A list of agents",
22
+ "content": {
23
+ "application/json": {
24
+ "schema": {
25
+ "type": "array",
26
+ "items": {
27
+ "type": "object",
28
+ "properties": {
29
+ "name": { "type": "string" },
30
+ "title": { "type": "string" },
31
+ "description": { "type": "string" }
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
40
+ },
41
+ "/api/chat": {
42
+ "post": {
43
+ "summary": "Chat with an agent",
44
+ "tags": ["Chat"],
45
+ "requestBody": {
46
+ "required": true,
47
+ "content": {
48
+ "application/json": {
49
+ "schema": {
50
+ "type": "object",
51
+ "properties": {
52
+ "agentName": { "type": "string" },
53
+ "message": { "type": "string" }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ },
59
+ "responses": {
60
+ "200": {
61
+ "description": "Chat response"
62
+ }
63
+ }
64
+ }
65
+ },
66
+ "/api/agents/{agentName}": {
67
+ "get": {
68
+ "summary": "Get agent details",
69
+ "tags": ["Agents"],
70
+ "parameters": [
71
+ {
72
+ "name": "agentName",
73
+ "in": "path",
74
+ "required": true,
75
+ "schema": {
76
+ "type": "string"
77
+ }
78
+ }
79
+ ],
80
+ "responses": {
81
+ "200": {
82
+ "description": "Agent details"
83
+ }
84
+ }
85
+ }
86
+ },
87
+ "/api/upload": {
88
+ "post": {
89
+ "summary": "Upload a file",
90
+ "tags": ["Upload"],
91
+ "requestBody": {
92
+ "content": {
93
+ "multipart/form-data": {
94
+ "schema": {
95
+ "type": "object",
96
+ "properties": {
97
+ "file": {
98
+ "type": "string",
99
+ "format": "binary"
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ },
106
+ "responses": {
107
+ "200": {
108
+ "description": "File uploaded"
109
+ }
110
+ }
111
+ }
112
+ }
113
+ },
114
+ "--0": "<- TODO: !!!! Generate this file dynamically from the codebase of the Agents server app"
115
+ }
@@ -0,0 +1,54 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { GENERATOR_WARNING } from '../../../../src/config';
4
+
5
+ const appDir = path.join(__dirname, '..', '..', 'src', 'app');
6
+ const publicDir = path.join(__dirname, '..', '..', 'public');
7
+ const outputFile = path.join(__dirname, '..', '..', 'src', 'generated', 'reservedPaths.ts');
8
+
9
+ // Read the app directory
10
+ const appEntries = fs.readdirSync(appDir, { withFileTypes: true });
11
+
12
+ // Filter to get only directories (excluding dynamic routes like [agentName])
13
+ const reservedPaths = appEntries
14
+ .filter((entry) => entry.isDirectory())
15
+ .map((entry) => entry.name)
16
+ .filter((name) => !name.startsWith('[') && !name.endsWith(']'));
17
+
18
+ // Read the public directory (files and folders)
19
+ const publicEntries = fs.readdirSync(publicDir, { withFileTypes: true });
20
+ const publicPaths = publicEntries.map((entry) => entry.name).filter((name) => !name.startsWith('.'));
21
+
22
+ // Add additional paths that are not in app or public but should be reserved
23
+ const additionalPaths = [
24
+ '_next', // Next.js internal paths
25
+ 'manifest.webmanifest', // PWA manifest
26
+ ];
27
+
28
+ const allReservedPaths = [...new Set([...reservedPaths, ...publicPaths, ...additionalPaths])].sort();
29
+
30
+ // Generate the TypeScript file
31
+ const content = `/**
32
+ * Reserved paths that should not be treated as agent names.
33
+ * This file is auto-generated by scripts/generate-reserved-paths.js
34
+ *
35
+ * ${GENERATOR_WARNING}
36
+ *
37
+ * @see /apps/agents-server/src/app - source directory for routes
38
+ * @see /apps/agents-server/public - source directory for static files
39
+ * @see /apps/agents-server/src/middleware.ts - where this is used
40
+ */
41
+ export const RESERVED_PATHS: readonly string[] = ${JSON.stringify(allReservedPaths, null, 4)} as const;
42
+ `;
43
+
44
+ // Ensure the generated directory exists
45
+ const generatedDir = path.dirname(outputFile);
46
+ if (!fs.existsSync(generatedDir)) {
47
+ fs.mkdirSync(generatedDir, { recursive: true });
48
+ }
49
+
50
+ // Write the file
51
+ fs.writeFileSync(outputFile, content, 'utf-8');
52
+
53
+ console.log(`Generated ${outputFile} with ${allReservedPaths.length} reserved paths:`);
54
+ console.log(allReservedPaths.join(', '));
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "commonjs",
5
+ "downlevelIteration": true,
6
+ "allowJs": true,
7
+ "moduleResolution": "node",
8
+ "forceConsistentCasingInFileNames": true,
9
+ "noImplicitReturns": true,
10
+ "noImplicitThis": true,
11
+ "noImplicitAny": true,
12
+ "strictNullChecks": true,
13
+ "experimentalDecorators": true,
14
+ "noUnusedLocals": false,
15
+ "resolveJsonModule": true,
16
+ "esModuleInterop": true
17
+ },
18
+ "exclude": ["node_modules"]
19
+ }
@@ -1,41 +1,67 @@
1
1
  'use client';
2
2
 
3
+ import { string_book } from '@promptbook-local/types';
3
4
  import { useRouter } from 'next/navigation';
4
5
  import { useState } from 'react';
5
6
  import { Card } from '../components/Homepage/Card';
6
- import { $createAgentAction } from './actions';
7
+ import { NewAgentDialog } from '../components/NewAgentDialog/NewAgentDialog';
8
+ import { $createAgentFromBookAction, $generateAgentBoilerplateAction } from './actions';
7
9
 
8
10
  export function AddAgentButton() {
9
11
  const router = useRouter();
10
12
  const [isLoading, setIsLoading] = useState(false);
13
+ const [isDialogOpen, setIsDialogOpen] = useState(false);
14
+ const [agentSource, setAgentSource] = useState<string_book>('' as string_book);
11
15
 
12
16
  const handleAddAgent = async () => {
13
17
  setIsLoading(true);
14
- const agentName = await $createAgentAction();
15
- // TODO: Add proper error handling and UI feedback
16
- if (agentName) {
17
- router.push(`/agents/${agentName}`);
18
+ try {
19
+ const boilerplate = await $generateAgentBoilerplateAction();
20
+ setAgentSource(boilerplate);
21
+ setIsDialogOpen(true);
22
+ } catch (error) {
23
+ console.error('Failed to generate agent boilerplate', error);
24
+ // TODO: Add proper error handling and UI feedback
25
+ } finally {
26
+ setIsLoading(false);
27
+ }
28
+ };
29
+
30
+ const handleCreate = async (source: string_book) => {
31
+ // Note: [🧠] Logic for creation is now handled inside the dialog (waiting for promise), here we just handle navigation
32
+ const { permanentId } = await $createAgentFromBookAction(source);
33
+
34
+ if (permanentId) {
35
+ router.push(`/agents/${permanentId}`);
18
36
  } else {
19
37
  router.refresh();
20
- setIsLoading(false);
21
38
  }
22
39
  };
23
40
 
24
41
  return (
25
- <div
26
- onClick={isLoading ? undefined : handleAddAgent}
27
- className={`cursor-pointer h-full group ${isLoading ? 'pointer-events-none' : ''}`}
28
- >
29
- <Card className="flex items-center justify-center text-lg font-medium text-gray-500 group-hover:text-blue-500 group-hover:border-blue-400 border-dashed border-2">
30
- {isLoading ? (
31
- <>
32
- <span className="mr-2 inline-block h-4 w-4 animate-spin rounded-full border-2 border-blue-500 border-t-transparent" />
33
- Creating agent...
34
- </>
35
- ) : (
36
- '+ Add New Agent'
37
- )}
38
- </Card>
39
- </div>
42
+ <>
43
+ <div
44
+ onClick={isLoading ? undefined : handleAddAgent}
45
+ className={`cursor-pointer h-full group ${isLoading ? 'pointer-events-none' : ''}`}
46
+ >
47
+ <Card className="flex items-center justify-center text-lg font-medium text-gray-500 group-hover:text-blue-500 group-hover:border-blue-400 border-dashed border-2">
48
+ {isLoading ? (
49
+ <>
50
+ <span className="mr-2 inline-block h-4 w-4 animate-spin rounded-full border-2 border-blue-500 border-t-transparent" />
51
+ Preparing...
52
+ </>
53
+ ) : (
54
+ '+ Add New Agent'
55
+ )}
56
+ </Card>
57
+ </div>
58
+
59
+ <NewAgentDialog
60
+ isOpen={isDialogOpen}
61
+ onClose={() => setIsDialogOpen(false)}
62
+ initialAgentSource={agentSource}
63
+ onCreate={handleCreate}
64
+ />
65
+ </>
40
66
  );
41
67
  }
@@ -1,16 +1,16 @@
1
1
  'use server';
2
2
 
3
3
  import { $generateBookBoilerplate } from '@promptbook-local/core';
4
- import { string_agent_name } from '@promptbook-local/types';
4
+ import { string_agent_name, string_book } from '@promptbook-local/types';
5
5
  import { revalidatePath } from 'next/cache';
6
- import { cookies } from 'next/headers';
6
+ import { string_agent_permanent_id } from '../../../../src/types/typeAliases';
7
7
  import { getMetadata } from '../database/getMetadata';
8
8
  import { $provideAgentCollectionForServer } from '../tools/$provideAgentCollectionForServer';
9
9
  import { authenticateUser } from '../utils/authenticateUser';
10
10
  import { isUserAdmin } from '../utils/isUserAdmin';
11
11
  import { clearSession, setSession } from '../utils/session';
12
12
 
13
- export async function $createAgentAction(): Promise<string_agent_name> {
13
+ export async function $createAgentAction(): Promise<{ agentName: string_agent_name; permanentId: string_agent_permanent_id }> {
14
14
  // TODO: [👹] Check permissions here
15
15
  if (!(await isUserAdmin())) {
16
16
  throw new Error('You are not authorized to create agents');
@@ -20,9 +20,26 @@ export async function $createAgentAction(): Promise<string_agent_name> {
20
20
  const namePool = (await getMetadata('NAME_POOL')) || 'ENGLISH';
21
21
  const agentSource = $generateBookBoilerplate({ namePool });
22
22
 
23
- const { agentName } = await collection.createAgent(agentSource);
23
+ const { agentName, permanentId } = await collection.createAgent(agentSource);
24
24
 
25
- return agentName;
25
+ return { agentName, permanentId };
26
+ }
27
+
28
+ export async function $generateAgentBoilerplateAction(): Promise<string_book> {
29
+ const namePool = (await getMetadata('NAME_POOL')) || 'ENGLISH';
30
+ return $generateBookBoilerplate({ namePool });
31
+ }
32
+
33
+ export async function $createAgentFromBookAction(bookContent: string_book): Promise<{ agentName: string_agent_name; permanentId: string_agent_permanent_id }> {
34
+ // TODO: [👹] Check permissions here
35
+ if (!(await isUserAdmin())) {
36
+ throw new Error('You are not authorized to create agents');
37
+ }
38
+
39
+ const collection = await $provideAgentCollectionForServer();
40
+ const { agentName, permanentId } = await collection.createAgent(bookContent);
41
+
42
+ return { agentName, permanentId };
26
43
  }
27
44
 
28
45
  export async function loginAction(formData: FormData) {
@@ -0,0 +1,211 @@
1
+ 'use client';
2
+
3
+ import { useState, useEffect } from 'react';
4
+ import { Card } from '../../../components/Homepage/Card';
5
+
6
+ export function BrowserTestClient() {
7
+ const [imageUrl, setImageUrl] = useState<string | null>(null);
8
+ const [facebookStreamUrl, setFacebookStreamUrl] = useState<string | null>(null);
9
+ const [goal, setGoal] = useState<string>('');
10
+ const [plan, setPlan] = useState<string | null>(null);
11
+ const [isConfirming, setIsConfirming] = useState<boolean>(false);
12
+
13
+ useEffect(() => {
14
+ return () => {
15
+ if (imageUrl) {
16
+ URL.revokeObjectURL(imageUrl);
17
+ }
18
+ };
19
+ }, [imageUrl]);
20
+ const [isLoading, setIsLoading] = useState(false);
21
+ const [error, setError] = useState<string | null>(null);
22
+
23
+ const handleTakeScreenshot = async () => {
24
+ setFacebookStreamUrl(null);
25
+ setIsLoading(true);
26
+ setError(null);
27
+ try {
28
+ const response = await fetch('/api/browser-test/screenshot');
29
+ if (!response.ok) {
30
+ const text = await response.text();
31
+ let errorMessage;
32
+ try {
33
+ const json = JSON.parse(text);
34
+ errorMessage = json.error || response.statusText;
35
+ } catch {
36
+ errorMessage = text || response.statusText;
37
+ }
38
+ throw new Error(`Error: ${response.status} ${errorMessage}`);
39
+ }
40
+ const blob = await response.blob();
41
+ const url = URL.createObjectURL(blob);
42
+ setImageUrl(url);
43
+ } catch (err) {
44
+ setError(String(err));
45
+ } finally {
46
+ setIsLoading(false);
47
+ }
48
+ };
49
+
50
+ const handleScrollFacebook = () => {
51
+ setImageUrl(null);
52
+ setError(null);
53
+ setFacebookStreamUrl(`/api/browser-test/scroll-facebook?t=${Date.now()}`);
54
+ };
55
+
56
+ const handleActOnFacebook = async () => {
57
+ setError(null);
58
+ setIsLoading(true);
59
+ // Start streaming view if not already started
60
+ if (!facebookStreamUrl) {
61
+ setFacebookStreamUrl(`/api/browser-test/scroll-facebook?t=${Date.now()}`);
62
+ }
63
+
64
+ try {
65
+ const response = await fetch('/api/browser-test/act', {
66
+ method: 'POST',
67
+ headers: { 'Content-Type': 'application/json' },
68
+ body: JSON.stringify({ goal, action: 'plan' }),
69
+ });
70
+
71
+ if (!response.ok) {
72
+ const text = await response.text();
73
+ throw new Error(`Error: ${response.status} ${text}`);
74
+ }
75
+
76
+ const data = await response.json();
77
+ setPlan(data.plan);
78
+ setIsConfirming(true);
79
+ } catch (err) {
80
+ setError(String(err));
81
+ } finally {
82
+ setIsLoading(false);
83
+ }
84
+ };
85
+
86
+ const handleConfirmAction = async () => {
87
+ setError(null);
88
+ setIsLoading(true);
89
+ setIsConfirming(false);
90
+ setPlan(null);
91
+
92
+ try {
93
+ const response = await fetch('/api/browser-test/act', {
94
+ method: 'POST',
95
+ headers: { 'Content-Type': 'application/json' },
96
+ body: JSON.stringify({ goal, action: 'execute', plan }),
97
+ });
98
+
99
+ if (!response.ok) {
100
+ const text = await response.text();
101
+ throw new Error(`Error: ${response.status} ${text}`);
102
+ }
103
+
104
+ const data = await response.json();
105
+ // Optionally show success message
106
+ console.log('Action executed:', data);
107
+ } catch (err) {
108
+ setError(String(err));
109
+ } finally {
110
+ setIsLoading(false);
111
+ }
112
+ };
113
+
114
+ return (
115
+ <div className="container mx-auto px-4 py-8 space-y-6">
116
+ <div className="mt-20 mb-4 flex flex-col gap-2 md:flex-row md:items-end md:justify-between">
117
+ <div>
118
+ <h1 className="text-3xl text-gray-900 font-light">Browser Test</h1>
119
+ <p className="mt-1 text-sm text-gray-500">
120
+ Launch a browser instance and take a screenshot to verify functionality.
121
+ </p>
122
+ </div>
123
+ </div>
124
+
125
+ <Card>
126
+ <div className="mb-4">
127
+ <p className="mb-2">Click the button below to launch a browser instance (if not running), navigate to ptbk.io, and take a screenshot.</p>
128
+ <button
129
+ onClick={handleTakeScreenshot}
130
+ disabled={isLoading}
131
+ className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded disabled:opacity-50"
132
+ >
133
+ {isLoading ? 'Taking Screenshot...' : 'Take Screenshot'}
134
+ </button>
135
+ <button
136
+ onClick={handleScrollFacebook}
137
+ disabled={isLoading}
138
+ className="ml-2 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded disabled:opacity-50"
139
+ >
140
+ View Facebook Stream
141
+ </button>
142
+ </div>
143
+
144
+ <div className="mb-4 space-y-2">
145
+ <label className="block text-sm font-medium text-gray-700">Goal for Agent</label>
146
+ <div className="flex gap-2">
147
+ <input
148
+ type="text"
149
+ value={goal}
150
+ onChange={(e) => setGoal(e.target.value)}
151
+ placeholder="e.g., Like 5 posts about AI"
152
+ className="flex-1 p-2 border border-gray-300 rounded"
153
+ disabled={isLoading}
154
+ />
155
+ <button
156
+ onClick={handleActOnFacebook}
157
+ disabled={isLoading || !goal}
158
+ className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded disabled:opacity-50"
159
+ >
160
+ {isLoading ? 'Processing...' : 'Act on Facebook'}
161
+ </button>
162
+ </div>
163
+ </div>
164
+
165
+ {isConfirming && plan && (
166
+ <div className="bg-yellow-50 border border-yellow-200 p-4 rounded mb-4">
167
+ <h3 className="font-bold text-lg mb-2">Confirm Plan</h3>
168
+ <pre className="whitespace-pre-wrap bg-white p-3 border rounded mb-3 text-sm">{plan}</pre>
169
+ <div className="flex gap-2">
170
+ <button
171
+ onClick={handleConfirmAction}
172
+ className="bg-green-600 hover:bg-green-800 text-white font-bold py-2 px-4 rounded"
173
+ >
174
+ Confirm & Execute
175
+ </button>
176
+ <button
177
+ onClick={() => setIsConfirming(false)}
178
+ className="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded"
179
+ >
180
+ Cancel
181
+ </button>
182
+ </div>
183
+ </div>
184
+ )}
185
+
186
+ {error && (
187
+ <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4" role="alert">
188
+ <strong className="font-bold">Error: </strong>
189
+ <span className="block sm:inline">{error}</span>
190
+ </div>
191
+ )}
192
+
193
+ {imageUrl && (
194
+ <div className="border rounded shadow-lg overflow-hidden">
195
+ <h2 className="text-xl font-semibold p-2 bg-gray-100">Screenshot</h2>
196
+ {/* eslint-disable-next-line @next/next/no-img-element */}
197
+ <img src={imageUrl} alt="Screenshot of ptbk.io" className="w-full h-auto" />
198
+ </div>
199
+ )}
200
+
201
+ {facebookStreamUrl && (
202
+ <div className="border rounded shadow-lg overflow-hidden">
203
+ <h2 className="text-xl font-semibold p-2 bg-gray-100">Facebook Scroll Stream</h2>
204
+ {/* eslint-disable-next-line @next/next/no-img-element */}
205
+ <img src={facebookStreamUrl} alt="Live stream of Facebook scrolling" className="w-full h-auto" />
206
+ </div>
207
+ )}
208
+ </Card>
209
+ </div>
210
+ );
211
+ }
@@ -0,0 +1,13 @@
1
+ import { ForbiddenPage } from '../../../components/ForbiddenPage/ForbiddenPage';
2
+ import { isUserAdmin } from '../../../utils/isUserAdmin';
3
+ import { BrowserTestClient } from './BrowserTestClient';
4
+
5
+ export default async function BrowserTestPage() {
6
+ const isAdmin = await isUserAdmin();
7
+
8
+ if (!isAdmin) {
9
+ return <ForbiddenPage />;
10
+ }
11
+
12
+ return <BrowserTestClient />;
13
+ }