@nextsparkjs/theme-default 0.1.0-beta.1

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 (333) hide show
  1. package/about/business.md +49 -0
  2. package/about/features.json +302 -0
  3. package/about/team.md +79 -0
  4. package/api/ai/chat/stream/route.ts +212 -0
  5. package/api/ai/orchestrator/route.ts +226 -0
  6. package/api/ai/single-agent/route.ts +291 -0
  7. package/api/ai/usage/route.ts +122 -0
  8. package/blocks/benefits/component.tsx +100 -0
  9. package/blocks/benefits/config.ts +11 -0
  10. package/blocks/benefits/examples.ts +85 -0
  11. package/blocks/benefits/fields.ts +156 -0
  12. package/blocks/benefits/schema.ts +33 -0
  13. package/blocks/cta-section/component.tsx +100 -0
  14. package/blocks/cta-section/config.ts +11 -0
  15. package/blocks/cta-section/examples.ts +41 -0
  16. package/blocks/cta-section/fields.ts +89 -0
  17. package/blocks/cta-section/index.ts +6 -0
  18. package/blocks/cta-section/schema.ts +32 -0
  19. package/blocks/cta-section/thumbnail.png +1 -0
  20. package/blocks/faq-accordion/component.tsx +156 -0
  21. package/blocks/faq-accordion/config.ts +11 -0
  22. package/blocks/faq-accordion/examples.ts +77 -0
  23. package/blocks/faq-accordion/fields.ts +119 -0
  24. package/blocks/faq-accordion/index.ts +6 -0
  25. package/blocks/faq-accordion/schema.ts +45 -0
  26. package/blocks/features-grid/component.tsx +112 -0
  27. package/blocks/features-grid/config.ts +11 -0
  28. package/blocks/features-grid/examples.ts +63 -0
  29. package/blocks/features-grid/fields.ts +97 -0
  30. package/blocks/features-grid/index.ts +6 -0
  31. package/blocks/features-grid/schema.ts +40 -0
  32. package/blocks/features-grid/thumbnail.png +1 -0
  33. package/blocks/hero/component.tsx +100 -0
  34. package/blocks/hero/config.ts +11 -0
  35. package/blocks/hero/examples.ts +35 -0
  36. package/blocks/hero/fields.ts +60 -0
  37. package/blocks/hero/index.ts +6 -0
  38. package/blocks/hero/schema.ts +32 -0
  39. package/blocks/hero/thumbnail.png +1 -0
  40. package/blocks/hero/thumbnail.png.txt +6 -0
  41. package/blocks/hero-with-form/component.tsx +232 -0
  42. package/blocks/hero-with-form/config.ts +11 -0
  43. package/blocks/hero-with-form/examples.ts +16 -0
  44. package/blocks/hero-with-form/fields.ts +207 -0
  45. package/blocks/hero-with-form/index.ts +6 -0
  46. package/blocks/hero-with-form/schema.ts +54 -0
  47. package/blocks/jumbotron/component.tsx +136 -0
  48. package/blocks/jumbotron/config.ts +11 -0
  49. package/blocks/jumbotron/examples.ts +36 -0
  50. package/blocks/jumbotron/fields.ts +202 -0
  51. package/blocks/jumbotron/index.ts +6 -0
  52. package/blocks/jumbotron/schema.ts +55 -0
  53. package/blocks/logo-cloud/component.tsx +154 -0
  54. package/blocks/logo-cloud/config.ts +11 -0
  55. package/blocks/logo-cloud/examples.ts +34 -0
  56. package/blocks/logo-cloud/fields.ts +133 -0
  57. package/blocks/logo-cloud/index.ts +6 -0
  58. package/blocks/logo-cloud/schema.ts +46 -0
  59. package/blocks/post-content/component.tsx +197 -0
  60. package/blocks/post-content/config.ts +11 -0
  61. package/blocks/post-content/examples.ts +33 -0
  62. package/blocks/post-content/fields.ts +165 -0
  63. package/blocks/post-content/index.ts +4 -0
  64. package/blocks/post-content/schema.ts +46 -0
  65. package/blocks/pricing-table/component.tsx +154 -0
  66. package/blocks/pricing-table/config.ts +11 -0
  67. package/blocks/pricing-table/examples.ts +96 -0
  68. package/blocks/pricing-table/fields.ts +161 -0
  69. package/blocks/pricing-table/index.ts +4 -0
  70. package/blocks/pricing-table/schema.ts +50 -0
  71. package/blocks/split-content/component.tsx +135 -0
  72. package/blocks/split-content/config.ts +11 -0
  73. package/blocks/split-content/examples.ts +38 -0
  74. package/blocks/split-content/fields.ts +198 -0
  75. package/blocks/split-content/index.ts +6 -0
  76. package/blocks/split-content/schema.ts +67 -0
  77. package/blocks/stats-counter/component.tsx +124 -0
  78. package/blocks/stats-counter/config.ts +11 -0
  79. package/blocks/stats-counter/examples.ts +61 -0
  80. package/blocks/stats-counter/fields.ts +134 -0
  81. package/blocks/stats-counter/index.ts +6 -0
  82. package/blocks/stats-counter/schema.ts +47 -0
  83. package/blocks/testimonials/component.tsx +114 -0
  84. package/blocks/testimonials/config.ts +11 -0
  85. package/blocks/testimonials/examples.ts +65 -0
  86. package/blocks/testimonials/fields.ts +105 -0
  87. package/blocks/testimonials/index.ts +6 -0
  88. package/blocks/testimonials/schema.ts +41 -0
  89. package/blocks/testimonials/thumbnail.png +1 -0
  90. package/blocks/text-content/component.tsx +97 -0
  91. package/blocks/text-content/config.ts +11 -0
  92. package/blocks/text-content/examples.ts +30 -0
  93. package/blocks/text-content/fields.ts +88 -0
  94. package/blocks/text-content/index.ts +6 -0
  95. package/blocks/text-content/schema.ts +30 -0
  96. package/blocks/text-content/thumbnail.png +1 -0
  97. package/blocks/timeline/component.tsx +267 -0
  98. package/blocks/timeline/config.ts +11 -0
  99. package/blocks/timeline/examples.ts +68 -0
  100. package/blocks/timeline/fields.ts +147 -0
  101. package/blocks/timeline/index.ts +6 -0
  102. package/blocks/timeline/schema.ts +49 -0
  103. package/blocks/video-hero/component.tsx +270 -0
  104. package/blocks/video-hero/config.ts +11 -0
  105. package/blocks/video-hero/examples.ts +24 -0
  106. package/blocks/video-hero/fields.ts +98 -0
  107. package/blocks/video-hero/index.ts +6 -0
  108. package/blocks/video-hero/schema.ts +39 -0
  109. package/components/ai-chat/ChatPanel.tsx +575 -0
  110. package/components/ai-chat/ConversationItem.tsx +266 -0
  111. package/components/ai-chat/ConversationSidebar.tsx +99 -0
  112. package/components/ai-chat/MarkdownRenderer.tsx +15 -0
  113. package/components/ai-chat/Message.tsx +42 -0
  114. package/components/ai-chat/MessageInput.tsx +49 -0
  115. package/components/ai-chat/MessageList.tsx +46 -0
  116. package/components/ai-chat/TypingIndicator.tsx +11 -0
  117. package/config/app.config.ts +367 -0
  118. package/config/billing.config.ts +349 -0
  119. package/config/dashboard.config.ts +506 -0
  120. package/config/dev.config.ts +104 -0
  121. package/config/features.config.ts +203 -0
  122. package/config/flows.config.ts +129 -0
  123. package/config/permissions.config.ts +245 -0
  124. package/config/theme.config.ts +74 -0
  125. package/docs/01-overview/01-introduction.md +335 -0
  126. package/docs/01-overview/02-customization.md +671 -0
  127. package/docs/02-features/01-components.md +155 -0
  128. package/docs/02-features/02-styling.md +139 -0
  129. package/docs/02-features/03-tasks-entity.md +407 -0
  130. package/docs/03-ai/01-overview.md +211 -0
  131. package/docs/03-ai/02-customization.md +436 -0
  132. package/entities/customers/customers.config.ts +75 -0
  133. package/entities/customers/customers.fields.ts +165 -0
  134. package/entities/customers/customers.service.ts +516 -0
  135. package/entities/customers/customers.types.ts +83 -0
  136. package/entities/customers/messages/en.json +66 -0
  137. package/entities/customers/messages/es.json +66 -0
  138. package/entities/customers/migrations/001_customers_table.sql +102 -0
  139. package/entities/customers/migrations/002_customers_metas.sql +92 -0
  140. package/entities/pages/messages/en.json +41 -0
  141. package/entities/pages/messages/es.json +41 -0
  142. package/entities/pages/migrations/001_pages_table.sql +112 -0
  143. package/entities/pages/migrations/002_pages_metas.sql +56 -0
  144. package/entities/pages/migrations/003_add_status.sql +50 -0
  145. package/entities/pages/pages-management.service.ts +610 -0
  146. package/entities/pages/pages.config.ts +94 -0
  147. package/entities/pages/pages.fields.ts +101 -0
  148. package/entities/pages/pages.service.ts +290 -0
  149. package/entities/pages/pages.types.ts +124 -0
  150. package/entities/posts/components/post-header.tsx +97 -0
  151. package/entities/posts/messages/en.json +55 -0
  152. package/entities/posts/messages/es.json +55 -0
  153. package/entities/posts/migrations/001_posts_table.sql +115 -0
  154. package/entities/posts/migrations/003_add_status.sql +44 -0
  155. package/entities/posts/migrations/004_entity_taxonomy_relations.sql +129 -0
  156. package/entities/posts/migrations/006_posts_metas.sql +56 -0
  157. package/entities/posts/posts.config.ts +101 -0
  158. package/entities/posts/posts.fields.ts +116 -0
  159. package/entities/posts/posts.service.ts +376 -0
  160. package/entities/posts/posts.types.ts +74 -0
  161. package/entities/tasks/messages/en.json +204 -0
  162. package/entities/tasks/messages/es.json +204 -0
  163. package/entities/tasks/migrations/001_tasks_table.sql +105 -0
  164. package/entities/tasks/migrations/002_task_metas.sql +85 -0
  165. package/entities/tasks/migrations/sample_data.json +77 -0
  166. package/entities/tasks/tasks.config.ts +79 -0
  167. package/entities/tasks/tasks.fields.ts +196 -0
  168. package/entities/tasks/tasks.service.ts +541 -0
  169. package/entities/tasks/tasks.types.ts +56 -0
  170. package/lib/hooks/useAiChat.ts +114 -0
  171. package/lib/hooks/useConversations.ts +376 -0
  172. package/lib/hooks/useOrchestratorChat.ts +122 -0
  173. package/lib/hooks/usePersistentChat.ts +315 -0
  174. package/lib/hooks/useStreamingChat.ts +127 -0
  175. package/lib/hooks/useTokenUsage.ts +63 -0
  176. package/lib/langchain/agents/customer-assistant.md +69 -0
  177. package/lib/langchain/agents/index.ts +61 -0
  178. package/lib/langchain/agents/orchestrator.md +59 -0
  179. package/lib/langchain/agents/page-assistant.md +85 -0
  180. package/lib/langchain/agents/single-agent.md +46 -0
  181. package/lib/langchain/agents/task-assistant.md +55 -0
  182. package/lib/langchain/config.ts +45 -0
  183. package/lib/langchain/handlers/customer-handler.ts +338 -0
  184. package/lib/langchain/handlers/page-handler.ts +232 -0
  185. package/lib/langchain/handlers/task-handler.ts +323 -0
  186. package/lib/langchain/langchain.config.ts +223 -0
  187. package/lib/langchain/observability.config.ts +30 -0
  188. package/lib/langchain/orchestrator.ts +562 -0
  189. package/lib/langchain/tools/customers.ts +176 -0
  190. package/lib/langchain/tools/index.ts +10 -0
  191. package/lib/langchain/tools/orchestrator.ts +92 -0
  192. package/lib/langchain/tools/pages.ts +289 -0
  193. package/lib/langchain/tools/tasks.ts +167 -0
  194. package/lib/scheduled-actions/billing.ts +149 -0
  195. package/lib/scheduled-actions/index.ts +170 -0
  196. package/lib/scheduled-actions/webhook.ts +231 -0
  197. package/lib/selectors.ts +197 -0
  198. package/messages/de/admin.json +219 -0
  199. package/messages/de/aiUsage.json +36 -0
  200. package/messages/de/buttons.json +19 -0
  201. package/messages/de/categories.json +35 -0
  202. package/messages/de/common.json +16 -0
  203. package/messages/de/dev.json +101 -0
  204. package/messages/de/docs.json +27 -0
  205. package/messages/de/entities.json +7 -0
  206. package/messages/de/features.json +119 -0
  207. package/messages/de/footer.json +22 -0
  208. package/messages/de/home.json +57 -0
  209. package/messages/de/index.ts +39 -0
  210. package/messages/de/mobileNav.json +13 -0
  211. package/messages/de/navigation.json +8 -0
  212. package/messages/de/observability.json +74 -0
  213. package/messages/de/posts.json +54 -0
  214. package/messages/de/pricing.json +102 -0
  215. package/messages/de/support.json +9 -0
  216. package/messages/de/teams.json +8 -0
  217. package/messages/en/admin.json +219 -0
  218. package/messages/en/aiUsage.json +36 -0
  219. package/messages/en/buttons.json +19 -0
  220. package/messages/en/categories.json +35 -0
  221. package/messages/en/common.json +16 -0
  222. package/messages/en/dev.json +106 -0
  223. package/messages/en/docs.json +27 -0
  224. package/messages/en/entities.json +7 -0
  225. package/messages/en/features.json +119 -0
  226. package/messages/en/footer.json +22 -0
  227. package/messages/en/home.json +57 -0
  228. package/messages/en/index.ts +39 -0
  229. package/messages/en/mobileNav.json +13 -0
  230. package/messages/en/navigation.json +8 -0
  231. package/messages/en/observability.json +74 -0
  232. package/messages/en/posts.json +54 -0
  233. package/messages/en/pricing.json +102 -0
  234. package/messages/en/support.json +9 -0
  235. package/messages/en/teams.json +8 -0
  236. package/messages/es/admin.json +219 -0
  237. package/messages/es/aiUsage.json +36 -0
  238. package/messages/es/buttons.json +19 -0
  239. package/messages/es/categories.json +35 -0
  240. package/messages/es/common.json +16 -0
  241. package/messages/es/dev.json +101 -0
  242. package/messages/es/docs.json +27 -0
  243. package/messages/es/entities.json +7 -0
  244. package/messages/es/features.json +119 -0
  245. package/messages/es/footer.json +22 -0
  246. package/messages/es/home.json +57 -0
  247. package/messages/es/index.ts +39 -0
  248. package/messages/es/mobileNav.json +13 -0
  249. package/messages/es/navigation.json +8 -0
  250. package/messages/es/observability.json +74 -0
  251. package/messages/es/posts.json +54 -0
  252. package/messages/es/pricing.json +102 -0
  253. package/messages/es/support.json +9 -0
  254. package/messages/es/teams.json +8 -0
  255. package/messages/fr/admin.json +219 -0
  256. package/messages/fr/aiUsage.json +36 -0
  257. package/messages/fr/buttons.json +19 -0
  258. package/messages/fr/categories.json +35 -0
  259. package/messages/fr/common.json +16 -0
  260. package/messages/fr/dev.json +101 -0
  261. package/messages/fr/docs.json +27 -0
  262. package/messages/fr/entities.json +7 -0
  263. package/messages/fr/features.json +119 -0
  264. package/messages/fr/footer.json +22 -0
  265. package/messages/fr/home.json +57 -0
  266. package/messages/fr/index.ts +39 -0
  267. package/messages/fr/mobileNav.json +13 -0
  268. package/messages/fr/navigation.json +8 -0
  269. package/messages/fr/observability.json +74 -0
  270. package/messages/fr/posts.json +54 -0
  271. package/messages/fr/pricing.json +102 -0
  272. package/messages/fr/support.json +9 -0
  273. package/messages/fr/teams.json +8 -0
  274. package/messages/it/admin.json +219 -0
  275. package/messages/it/aiUsage.json +36 -0
  276. package/messages/it/buttons.json +19 -0
  277. package/messages/it/categories.json +35 -0
  278. package/messages/it/common.json +16 -0
  279. package/messages/it/dev.json +101 -0
  280. package/messages/it/docs.json +27 -0
  281. package/messages/it/entities.json +7 -0
  282. package/messages/it/features.json +119 -0
  283. package/messages/it/footer.json +22 -0
  284. package/messages/it/home.json +57 -0
  285. package/messages/it/index.ts +39 -0
  286. package/messages/it/mobileNav.json +13 -0
  287. package/messages/it/navigation.json +8 -0
  288. package/messages/it/observability.json +74 -0
  289. package/messages/it/posts.json +54 -0
  290. package/messages/it/pricing.json +102 -0
  291. package/messages/it/support.json +9 -0
  292. package/messages/it/teams.json +8 -0
  293. package/messages/pt/admin.json +219 -0
  294. package/messages/pt/aiUsage.json +36 -0
  295. package/messages/pt/buttons.json +19 -0
  296. package/messages/pt/categories.json +35 -0
  297. package/messages/pt/common.json +16 -0
  298. package/messages/pt/dev.json +101 -0
  299. package/messages/pt/docs.json +27 -0
  300. package/messages/pt/entities.json +7 -0
  301. package/messages/pt/features.json +119 -0
  302. package/messages/pt/footer.json +22 -0
  303. package/messages/pt/home.json +57 -0
  304. package/messages/pt/index.ts +39 -0
  305. package/messages/pt/mobileNav.json +13 -0
  306. package/messages/pt/navigation.json +8 -0
  307. package/messages/pt/observability.json +74 -0
  308. package/messages/pt/posts.json +54 -0
  309. package/messages/pt/pricing.json +102 -0
  310. package/messages/pt/support.json +9 -0
  311. package/messages/pt/teams.json +8 -0
  312. package/migrations/089_add_editor_team_role.sql +39 -0
  313. package/migrations/090_demo_users_teams.sql +540 -0
  314. package/migrations/091_greek_teams_billing.sql +523 -0
  315. package/migrations/092_billing_sample_data.sql +774 -0
  316. package/migrations/093_pages_sample_data.sql +1158 -0
  317. package/migrations/094_posts_sample_data.sql +278 -0
  318. package/migrations/095_tasks_sample_data.sql +440 -0
  319. package/migrations/096_customers_sample_data.sql +358 -0
  320. package/migrations/097_scheduled_actions_sample_data.sql +111 -0
  321. package/package.json +22 -0
  322. package/public/docs/desktop-layout-example.png +0 -0
  323. package/styles/components.css +11 -0
  324. package/styles/globals.css +179 -0
  325. package/templates/(public)/blog/[slug]/page.tsx +65 -0
  326. package/templates/(public)/layout.tsx +25 -0
  327. package/templates/(public)/page.tsx +200 -0
  328. package/templates/(public)/support/page.tsx +321 -0
  329. package/templates/dashboard/(main)/agent-multi/page.tsx +63 -0
  330. package/templates/dashboard/(main)/agent-single/page.tsx +142 -0
  331. package/templates/dashboard/(main)/settings/ai-usage/page.tsx +157 -0
  332. package/templates/superadmin/ai-observability/[traceId]/page.tsx +27 -0
  333. package/templates/superadmin/ai-observability/page.tsx +17 -0
@@ -0,0 +1,176 @@
1
+ import { z } from 'zod'
2
+ import { ToolDefinition } from '@/plugins/langchain/lib/tools-builder'
3
+ import { CustomersService } from '@/themes/default/entities/customers/customers.service'
4
+ import type { DayOfWeek } from '@/themes/default/entities/customers/customers.types'
5
+
6
+ /**
7
+ * Tool context for customer operations
8
+ */
9
+ export interface CustomerToolContext {
10
+ userId: string
11
+ teamId: string
12
+ }
13
+
14
+ /**
15
+ * Create customer management tools for the AI agent
16
+ *
17
+ * @param context - User and team context for RLS
18
+ * @returns Array of customer-related tool definitions
19
+ */
20
+ export function createCustomerTools(context: CustomerToolContext): ToolDefinition<any>[] {
21
+ const { userId, teamId } = context
22
+
23
+ return [
24
+ {
25
+ name: 'list_customers',
26
+ description: 'List all customers with optional pagination and sorting.',
27
+ schema: z.object({
28
+ limit: z.number().optional().default(20).describe('Max customers to return'),
29
+ offset: z.number().optional().default(0).describe('Offset for pagination'),
30
+ orderBy: z.enum(['name', 'account', 'office', 'salesRep', 'createdAt'])
31
+ .optional()
32
+ .describe('Field to order by'),
33
+ orderDir: z.enum(['asc', 'desc'])
34
+ .optional()
35
+ .describe('Order direction'),
36
+ }),
37
+ func: async (params) => {
38
+ try {
39
+ const result = await CustomersService.list(userId, params)
40
+ return JSON.stringify({
41
+ customers: result.customers.map(c => ({
42
+ id: c.id,
43
+ name: c.name,
44
+ account: c.account,
45
+ office: c.office,
46
+ salesRep: c.salesRep,
47
+ phone: c.phone,
48
+ })),
49
+ total: result.total,
50
+ }, null, 2)
51
+ } catch (error) {
52
+ return `Error listing customers: ${error instanceof Error ? error.message : 'Unknown error'}`
53
+ }
54
+ },
55
+ },
56
+ {
57
+ name: 'search_customers',
58
+ description: 'Search customers by name, account number, office, or sales representative.',
59
+ schema: z.object({
60
+ query: z.string().describe('Search term to match against customer fields'),
61
+ limit: z.number().optional().default(10).describe('Max results to return'),
62
+ }),
63
+ func: async (params) => {
64
+ try {
65
+ const results = await CustomersService.search(userId, params)
66
+ return JSON.stringify(results.map(c => ({
67
+ id: c.id,
68
+ name: c.name,
69
+ account: c.account,
70
+ office: c.office,
71
+ salesRep: c.salesRep,
72
+ phone: c.phone,
73
+ })), null, 2)
74
+ } catch (error) {
75
+ return `Error searching customers: ${error instanceof Error ? error.message : 'Unknown error'}`
76
+ }
77
+ },
78
+ },
79
+ {
80
+ name: 'get_customer',
81
+ description: 'Get full details of a specific customer by ID.',
82
+ schema: z.object({
83
+ customerId: z.string().describe('The customer ID to retrieve'),
84
+ }),
85
+ func: async ({ customerId }) => {
86
+ try {
87
+ const customer = await CustomersService.getById(customerId, userId)
88
+ if (!customer) {
89
+ return JSON.stringify({ error: 'Customer not found' })
90
+ }
91
+ return JSON.stringify(customer, null, 2)
92
+ } catch (error) {
93
+ return `Error getting customer: ${error instanceof Error ? error.message : 'Unknown error'}`
94
+ }
95
+ },
96
+ },
97
+ {
98
+ name: 'create_customer',
99
+ description: 'Create a new customer. Name, account number, and office are required.',
100
+ schema: z.object({
101
+ name: z.string().describe('Customer or company name'),
102
+ account: z.number().describe('Unique account number'),
103
+ office: z.string().describe('Office location or branch'),
104
+ phone: z.string().optional().describe('Contact phone number'),
105
+ salesRep: z.string().optional().describe('Assigned sales representative'),
106
+ visitDays: z.array(z.enum(['lun', 'mar', 'mie', 'jue', 'vie']))
107
+ .optional()
108
+ .describe('Days for in-person visits'),
109
+ contactDays: z.array(z.enum(['lun', 'mar', 'mie', 'jue', 'vie']))
110
+ .optional()
111
+ .describe('Days for phone/email contact'),
112
+ }),
113
+ func: async (data) => {
114
+ try {
115
+ const customer = await CustomersService.create(userId, {
116
+ ...data,
117
+ visitDays: data.visitDays as DayOfWeek[] | undefined,
118
+ contactDays: data.contactDays as DayOfWeek[] | undefined,
119
+ teamId,
120
+ })
121
+ return JSON.stringify(customer, null, 2)
122
+ } catch (error) {
123
+ return `Error creating customer: ${error instanceof Error ? error.message : 'Unknown error'}`
124
+ }
125
+ },
126
+ },
127
+ {
128
+ name: 'update_customer',
129
+ description: 'Update an existing customer. Only specify fields you want to change.',
130
+ schema: z.object({
131
+ customerId: z.string().describe('The customer ID to update'),
132
+ name: z.string().optional().describe('New customer name'),
133
+ account: z.number().optional().describe('New account number'),
134
+ office: z.string().optional().describe('New office location'),
135
+ phone: z.string().optional().describe('New phone number'),
136
+ salesRep: z.string().optional().describe('New sales representative'),
137
+ visitDays: z.array(z.enum(['lun', 'mar', 'mie', 'jue', 'vie']))
138
+ .optional()
139
+ .describe('New visit days'),
140
+ contactDays: z.array(z.enum(['lun', 'mar', 'mie', 'jue', 'vie']))
141
+ .optional()
142
+ .describe('New contact days'),
143
+ }),
144
+ func: async ({ customerId, ...updates }) => {
145
+ try {
146
+ const customer = await CustomersService.update(userId, customerId, {
147
+ ...updates,
148
+ visitDays: updates.visitDays as DayOfWeek[] | undefined,
149
+ contactDays: updates.contactDays as DayOfWeek[] | undefined,
150
+ })
151
+ return JSON.stringify(customer, null, 2)
152
+ } catch (error) {
153
+ return `Error updating customer: ${error instanceof Error ? error.message : 'Unknown error'}`
154
+ }
155
+ },
156
+ },
157
+ {
158
+ name: 'delete_customer',
159
+ description: 'Delete a customer permanently. This action cannot be undone.',
160
+ schema: z.object({
161
+ customerId: z.string().describe('The customer ID to delete'),
162
+ }),
163
+ func: async ({ customerId }) => {
164
+ try {
165
+ const success = await CustomersService.delete(userId, customerId)
166
+ return JSON.stringify({
167
+ success,
168
+ message: success ? 'Customer deleted successfully' : 'Failed to delete customer',
169
+ })
170
+ } catch (error) {
171
+ return `Error deleting customer: ${error instanceof Error ? error.message : 'Unknown error'}`
172
+ }
173
+ },
174
+ },
175
+ ]
176
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * LangChain Tools Index
3
+ *
4
+ * Central export point for all theme-specific AI agent tools.
5
+ */
6
+
7
+ export { createTaskTools, type TaskToolContext } from './tasks'
8
+ export { createCustomerTools, type CustomerToolContext } from './customers'
9
+ export { createPageTools, type PageToolContext } from './pages'
10
+ export { createOrchestratorTools, type AgentType, type RoutingResult, type ClarificationResult } from './orchestrator'
@@ -0,0 +1,92 @@
1
+ import { z } from 'zod'
2
+ import { ToolDefinition } from '@/plugins/langchain/lib/tools-builder'
3
+
4
+ /**
5
+ * Agent types that can be routed to
6
+ */
7
+ export type AgentType = 'task' | 'customer' | 'page'
8
+
9
+ /**
10
+ * Routing result structure
11
+ */
12
+ export interface RoutingResult {
13
+ agent: AgentType
14
+ message: string
15
+ }
16
+
17
+ /**
18
+ * Clarification result structure
19
+ */
20
+ export interface ClarificationResult {
21
+ action: 'clarify'
22
+ question: string
23
+ options: Array<{ label: string; description: string }>
24
+ }
25
+
26
+ /**
27
+ * Create orchestrator routing tools
28
+ *
29
+ * These tools don't execute operations directly; they return routing decisions
30
+ * that the orchestrator handler uses to delegate to specialized agents.
31
+ */
32
+ export function createOrchestratorTools(): ToolDefinition<any>[] {
33
+ return [
34
+ {
35
+ name: 'route_to_task',
36
+ description: 'Route the request to the task management agent. Use when the user wants to manage tasks, to-dos, work items, deadlines, or project-related items.',
37
+ schema: z.object({
38
+ message: z.string().describe('The user message to forward to the task agent'),
39
+ }),
40
+ func: async ({ message }) => {
41
+ return JSON.stringify({
42
+ agent: 'task',
43
+ message,
44
+ } as RoutingResult)
45
+ },
46
+ },
47
+ {
48
+ name: 'route_to_customer',
49
+ description: 'Route the request to the customer management agent. Use when the user wants to manage customers, clients, accounts, contacts, offices, sales representatives, or sales-related data.',
50
+ schema: z.object({
51
+ message: z.string().describe('The user message to forward to the customer agent'),
52
+ }),
53
+ func: async ({ message }) => {
54
+ return JSON.stringify({
55
+ agent: 'customer',
56
+ message,
57
+ } as RoutingResult)
58
+ },
59
+ },
60
+ {
61
+ name: 'route_to_page',
62
+ description: 'Route the request to the page/content management agent. Use when the user wants to manage pages, website content, blocks, landing pages, SEO, or publishing.',
63
+ schema: z.object({
64
+ message: z.string().describe('The user message to forward to the page agent'),
65
+ }),
66
+ func: async ({ message }) => {
67
+ return JSON.stringify({
68
+ agent: 'page',
69
+ message,
70
+ } as RoutingResult)
71
+ },
72
+ },
73
+ {
74
+ name: 'ask_clarification',
75
+ description: 'Ask the user for clarification when the request is ambiguous and you cannot determine which agent should handle it. Provide 2-3 specific options.',
76
+ schema: z.object({
77
+ question: z.string().describe('The clarification question to ask the user'),
78
+ options: z.array(z.object({
79
+ label: z.string().describe('Short label for the option (e.g., "Tarea", "Cliente", "Página")'),
80
+ description: z.string().describe('Brief description of what this option means'),
81
+ })).min(2).max(4).describe('Options to present to the user'),
82
+ }),
83
+ func: async ({ question, options }) => {
84
+ return JSON.stringify({
85
+ action: 'clarify',
86
+ question,
87
+ options,
88
+ } as ClarificationResult)
89
+ },
90
+ },
91
+ ]
92
+ }
@@ -0,0 +1,289 @@
1
+ import { z } from 'zod'
2
+ import { ToolDefinition } from '@/plugins/langchain/lib/tools-builder'
3
+ import { PagesManagementService } from '@/themes/default/entities/pages/pages-management.service'
4
+ import { BLOCK_REGISTRY } from '@nextsparkjs/registries/block-registry'
5
+
6
+ /**
7
+ * Tool context for page operations
8
+ */
9
+ export interface PageToolContext {
10
+ userId: string
11
+ teamId: string
12
+ }
13
+
14
+ /**
15
+ * Create page management tools for the AI agent
16
+ *
17
+ * @param context - User and team context for RLS
18
+ * @returns Array of page-related tool definitions
19
+ */
20
+ export function createPageTools(context: PageToolContext): ToolDefinition<any>[] {
21
+ const { userId, teamId } = context
22
+
23
+ return [
24
+ // ============================================
25
+ // PAGE CRUD
26
+ // ============================================
27
+ {
28
+ name: 'list_pages',
29
+ description: 'List all pages with optional status filter.',
30
+ schema: z.object({
31
+ status: z.enum(['draft', 'published', 'all'])
32
+ .optional()
33
+ .default('all')
34
+ .describe('Filter by page status'),
35
+ limit: z.number().optional().default(20).describe('Max pages to return'),
36
+ offset: z.number().optional().default(0).describe('Offset for pagination'),
37
+ locale: z.string().optional().describe('Filter by locale'),
38
+ }),
39
+ func: async (params) => {
40
+ try {
41
+ const result = await PagesManagementService.list(userId, { ...params, teamId })
42
+ return JSON.stringify({
43
+ pages: result.pages.map(p => ({
44
+ id: p.id,
45
+ title: p.title,
46
+ slug: p.slug,
47
+ status: p.status,
48
+ blockCount: p.blocks.length,
49
+ locale: p.locale,
50
+ })),
51
+ total: result.total,
52
+ }, null, 2)
53
+ } catch (error) {
54
+ return `Error listing pages: ${error instanceof Error ? error.message : 'Unknown error'}`
55
+ }
56
+ },
57
+ },
58
+ {
59
+ name: 'get_page',
60
+ description: 'Get full page details including all blocks.',
61
+ schema: z.object({
62
+ pageId: z.string().describe('The page ID to retrieve'),
63
+ }),
64
+ func: async ({ pageId }) => {
65
+ try {
66
+ const page = await PagesManagementService.getById(userId, pageId)
67
+ if (!page) {
68
+ return JSON.stringify({ error: 'Page not found' })
69
+ }
70
+ return JSON.stringify(page, null, 2)
71
+ } catch (error) {
72
+ return `Error getting page: ${error instanceof Error ? error.message : 'Unknown error'}`
73
+ }
74
+ },
75
+ },
76
+ {
77
+ name: 'create_page',
78
+ description: 'Create a new page. Title and slug are required.',
79
+ schema: z.object({
80
+ title: z.string().describe('Page title'),
81
+ slug: z.string().describe('URL-friendly slug (lowercase, hyphens only)'),
82
+ locale: z.string().optional().default('en').describe('Page locale'),
83
+ status: z.enum(['draft', 'published'])
84
+ .optional()
85
+ .default('draft')
86
+ .describe('Initial page status'),
87
+ seoTitle: z.string().optional().describe('SEO meta title'),
88
+ seoDescription: z.string().optional().describe('SEO meta description'),
89
+ }),
90
+ func: async (data) => {
91
+ try {
92
+ const page = await PagesManagementService.create(userId, { ...data, teamId })
93
+ return JSON.stringify(page, null, 2)
94
+ } catch (error) {
95
+ return `Error creating page: ${error instanceof Error ? error.message : 'Unknown error'}`
96
+ }
97
+ },
98
+ },
99
+ {
100
+ name: 'update_page',
101
+ description: 'Update page metadata (title, slug, SEO). Does not modify blocks.',
102
+ schema: z.object({
103
+ pageId: z.string().describe('The page ID to update'),
104
+ title: z.string().optional().describe('New page title'),
105
+ slug: z.string().optional().describe('New URL slug'),
106
+ seoTitle: z.string().optional().describe('New SEO title'),
107
+ seoDescription: z.string().optional().describe('New SEO description'),
108
+ }),
109
+ func: async ({ pageId, ...updates }) => {
110
+ try {
111
+ const page = await PagesManagementService.update(userId, pageId, updates)
112
+ return JSON.stringify(page, null, 2)
113
+ } catch (error) {
114
+ return `Error updating page: ${error instanceof Error ? error.message : 'Unknown error'}`
115
+ }
116
+ },
117
+ },
118
+ {
119
+ name: 'delete_page',
120
+ description: 'Delete a page permanently. This cannot be undone.',
121
+ schema: z.object({
122
+ pageId: z.string().describe('The page ID to delete'),
123
+ }),
124
+ func: async ({ pageId }) => {
125
+ try {
126
+ const success = await PagesManagementService.delete(userId, pageId)
127
+ return JSON.stringify({
128
+ success,
129
+ message: success ? 'Page deleted successfully' : 'Failed to delete page',
130
+ })
131
+ } catch (error) {
132
+ return `Error deleting page: ${error instanceof Error ? error.message : 'Unknown error'}`
133
+ }
134
+ },
135
+ },
136
+
137
+ // ============================================
138
+ // BLOCK OPERATIONS
139
+ // ============================================
140
+ {
141
+ name: 'add_block',
142
+ description: 'Add a new block to a page. Use list_available_blocks to see available block types.',
143
+ schema: z.object({
144
+ pageId: z.string().describe('The page ID to add the block to'),
145
+ blockSlug: z.string().describe('Block type slug (e.g., hero, cta-section, features-grid)'),
146
+ props: z.record(z.string(), z.unknown())
147
+ .optional()
148
+ .default({})
149
+ .describe('Block properties (title, content, etc.)'),
150
+ position: z.number()
151
+ .optional()
152
+ .describe('Position in the page (0 = first). Appends to end if not specified.'),
153
+ }),
154
+ func: async ({ pageId, blockSlug, props, position }) => {
155
+ try {
156
+ const page = await PagesManagementService.addBlock(
157
+ userId, pageId, blockSlug, props || {}, position
158
+ )
159
+ return JSON.stringify(page, null, 2)
160
+ } catch (error) {
161
+ return `Error adding block: ${error instanceof Error ? error.message : 'Unknown error'}`
162
+ }
163
+ },
164
+ },
165
+ {
166
+ name: 'update_block',
167
+ description: 'Update a block properties. Only specify properties you want to change.',
168
+ schema: z.object({
169
+ pageId: z.string().describe('The page ID containing the block'),
170
+ blockId: z.string().describe('The block instance ID to update'),
171
+ props: z.record(z.string(), z.unknown()).describe('Properties to update (merged with existing)'),
172
+ }),
173
+ func: async ({ pageId, blockId, props }) => {
174
+ try {
175
+ const page = await PagesManagementService.updateBlock(userId, pageId, blockId, props)
176
+ return JSON.stringify(page, null, 2)
177
+ } catch (error) {
178
+ return `Error updating block: ${error instanceof Error ? error.message : 'Unknown error'}`
179
+ }
180
+ },
181
+ },
182
+ {
183
+ name: 'remove_block',
184
+ description: 'Remove a block from a page.',
185
+ schema: z.object({
186
+ pageId: z.string().describe('The page ID containing the block'),
187
+ blockId: z.string().describe('The block instance ID to remove'),
188
+ }),
189
+ func: async ({ pageId, blockId }) => {
190
+ try {
191
+ const page = await PagesManagementService.removeBlock(userId, pageId, blockId)
192
+ return JSON.stringify(page, null, 2)
193
+ } catch (error) {
194
+ return `Error removing block: ${error instanceof Error ? error.message : 'Unknown error'}`
195
+ }
196
+ },
197
+ },
198
+ {
199
+ name: 'reorder_blocks',
200
+ description: 'Reorder blocks in a page by providing the block IDs in the new order.',
201
+ schema: z.object({
202
+ pageId: z.string().describe('The page ID to reorder blocks in'),
203
+ blockIds: z.array(z.string()).describe('Block IDs in the desired order'),
204
+ }),
205
+ func: async ({ pageId, blockIds }) => {
206
+ try {
207
+ const page = await PagesManagementService.reorderBlocks(userId, pageId, blockIds)
208
+ return JSON.stringify(page, null, 2)
209
+ } catch (error) {
210
+ return `Error reordering blocks: ${error instanceof Error ? error.message : 'Unknown error'}`
211
+ }
212
+ },
213
+ },
214
+
215
+ // ============================================
216
+ // PUBLICATION
217
+ // ============================================
218
+ {
219
+ name: 'publish_page',
220
+ description: 'Publish a draft page to make it live and accessible.',
221
+ schema: z.object({
222
+ pageId: z.string().describe('The page ID to publish'),
223
+ }),
224
+ func: async ({ pageId }) => {
225
+ try {
226
+ const page = await PagesManagementService.publish(userId, pageId)
227
+ return JSON.stringify({
228
+ ...page,
229
+ message: `Page published successfully. View at: /p/${page.slug}`,
230
+ }, null, 2)
231
+ } catch (error) {
232
+ return `Error publishing page: ${error instanceof Error ? error.message : 'Unknown error'}`
233
+ }
234
+ },
235
+ },
236
+ {
237
+ name: 'unpublish_page',
238
+ description: 'Unpublish a page (set to draft). It will no longer be publicly accessible.',
239
+ schema: z.object({
240
+ pageId: z.string().describe('The page ID to unpublish'),
241
+ }),
242
+ func: async ({ pageId }) => {
243
+ try {
244
+ const page = await PagesManagementService.unpublish(userId, pageId)
245
+ return JSON.stringify({
246
+ ...page,
247
+ message: 'Page unpublished successfully. It is now a draft.',
248
+ }, null, 2)
249
+ } catch (error) {
250
+ return `Error unpublishing page: ${error instanceof Error ? error.message : 'Unknown error'}`
251
+ }
252
+ },
253
+ },
254
+
255
+ // ============================================
256
+ // DISCOVERY
257
+ // ============================================
258
+ {
259
+ name: 'list_available_blocks',
260
+ description: 'Get information about available block types that can be added to pages.',
261
+ schema: z.object({
262
+ category: z.string()
263
+ .optional()
264
+ .describe('Filter by category (hero, content, features, cta, testimonials, etc.)'),
265
+ }),
266
+ func: async ({ category }) => {
267
+ try {
268
+ const allBlocks = Object.values(BLOCK_REGISTRY)
269
+ const filteredBlocks = category
270
+ ? allBlocks.filter(b => b.category === category)
271
+ : allBlocks
272
+
273
+ return JSON.stringify({
274
+ blocks: filteredBlocks.map(b => ({
275
+ slug: b.slug,
276
+ name: b.name,
277
+ description: b.description,
278
+ category: b.category,
279
+ })),
280
+ total: filteredBlocks.length,
281
+ categories: [...new Set(allBlocks.map(b => b.category))],
282
+ }, null, 2)
283
+ } catch (error) {
284
+ return `Error listing available blocks: ${error instanceof Error ? error.message : 'Unknown error'}`
285
+ }
286
+ },
287
+ },
288
+ ]
289
+ }