@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.
- package/about/business.md +49 -0
- package/about/features.json +302 -0
- package/about/team.md +79 -0
- package/api/ai/chat/stream/route.ts +212 -0
- package/api/ai/orchestrator/route.ts +226 -0
- package/api/ai/single-agent/route.ts +291 -0
- package/api/ai/usage/route.ts +122 -0
- package/blocks/benefits/component.tsx +100 -0
- package/blocks/benefits/config.ts +11 -0
- package/blocks/benefits/examples.ts +85 -0
- package/blocks/benefits/fields.ts +156 -0
- package/blocks/benefits/schema.ts +33 -0
- package/blocks/cta-section/component.tsx +100 -0
- package/blocks/cta-section/config.ts +11 -0
- package/blocks/cta-section/examples.ts +41 -0
- package/blocks/cta-section/fields.ts +89 -0
- package/blocks/cta-section/index.ts +6 -0
- package/blocks/cta-section/schema.ts +32 -0
- package/blocks/cta-section/thumbnail.png +1 -0
- package/blocks/faq-accordion/component.tsx +156 -0
- package/blocks/faq-accordion/config.ts +11 -0
- package/blocks/faq-accordion/examples.ts +77 -0
- package/blocks/faq-accordion/fields.ts +119 -0
- package/blocks/faq-accordion/index.ts +6 -0
- package/blocks/faq-accordion/schema.ts +45 -0
- package/blocks/features-grid/component.tsx +112 -0
- package/blocks/features-grid/config.ts +11 -0
- package/blocks/features-grid/examples.ts +63 -0
- package/blocks/features-grid/fields.ts +97 -0
- package/blocks/features-grid/index.ts +6 -0
- package/blocks/features-grid/schema.ts +40 -0
- package/blocks/features-grid/thumbnail.png +1 -0
- package/blocks/hero/component.tsx +100 -0
- package/blocks/hero/config.ts +11 -0
- package/blocks/hero/examples.ts +35 -0
- package/blocks/hero/fields.ts +60 -0
- package/blocks/hero/index.ts +6 -0
- package/blocks/hero/schema.ts +32 -0
- package/blocks/hero/thumbnail.png +1 -0
- package/blocks/hero/thumbnail.png.txt +6 -0
- package/blocks/hero-with-form/component.tsx +232 -0
- package/blocks/hero-with-form/config.ts +11 -0
- package/blocks/hero-with-form/examples.ts +16 -0
- package/blocks/hero-with-form/fields.ts +207 -0
- package/blocks/hero-with-form/index.ts +6 -0
- package/blocks/hero-with-form/schema.ts +54 -0
- package/blocks/jumbotron/component.tsx +136 -0
- package/blocks/jumbotron/config.ts +11 -0
- package/blocks/jumbotron/examples.ts +36 -0
- package/blocks/jumbotron/fields.ts +202 -0
- package/blocks/jumbotron/index.ts +6 -0
- package/blocks/jumbotron/schema.ts +55 -0
- package/blocks/logo-cloud/component.tsx +154 -0
- package/blocks/logo-cloud/config.ts +11 -0
- package/blocks/logo-cloud/examples.ts +34 -0
- package/blocks/logo-cloud/fields.ts +133 -0
- package/blocks/logo-cloud/index.ts +6 -0
- package/blocks/logo-cloud/schema.ts +46 -0
- package/blocks/post-content/component.tsx +197 -0
- package/blocks/post-content/config.ts +11 -0
- package/blocks/post-content/examples.ts +33 -0
- package/blocks/post-content/fields.ts +165 -0
- package/blocks/post-content/index.ts +4 -0
- package/blocks/post-content/schema.ts +46 -0
- package/blocks/pricing-table/component.tsx +154 -0
- package/blocks/pricing-table/config.ts +11 -0
- package/blocks/pricing-table/examples.ts +96 -0
- package/blocks/pricing-table/fields.ts +161 -0
- package/blocks/pricing-table/index.ts +4 -0
- package/blocks/pricing-table/schema.ts +50 -0
- package/blocks/split-content/component.tsx +135 -0
- package/blocks/split-content/config.ts +11 -0
- package/blocks/split-content/examples.ts +38 -0
- package/blocks/split-content/fields.ts +198 -0
- package/blocks/split-content/index.ts +6 -0
- package/blocks/split-content/schema.ts +67 -0
- package/blocks/stats-counter/component.tsx +124 -0
- package/blocks/stats-counter/config.ts +11 -0
- package/blocks/stats-counter/examples.ts +61 -0
- package/blocks/stats-counter/fields.ts +134 -0
- package/blocks/stats-counter/index.ts +6 -0
- package/blocks/stats-counter/schema.ts +47 -0
- package/blocks/testimonials/component.tsx +114 -0
- package/blocks/testimonials/config.ts +11 -0
- package/blocks/testimonials/examples.ts +65 -0
- package/blocks/testimonials/fields.ts +105 -0
- package/blocks/testimonials/index.ts +6 -0
- package/blocks/testimonials/schema.ts +41 -0
- package/blocks/testimonials/thumbnail.png +1 -0
- package/blocks/text-content/component.tsx +97 -0
- package/blocks/text-content/config.ts +11 -0
- package/blocks/text-content/examples.ts +30 -0
- package/blocks/text-content/fields.ts +88 -0
- package/blocks/text-content/index.ts +6 -0
- package/blocks/text-content/schema.ts +30 -0
- package/blocks/text-content/thumbnail.png +1 -0
- package/blocks/timeline/component.tsx +267 -0
- package/blocks/timeline/config.ts +11 -0
- package/blocks/timeline/examples.ts +68 -0
- package/blocks/timeline/fields.ts +147 -0
- package/blocks/timeline/index.ts +6 -0
- package/blocks/timeline/schema.ts +49 -0
- package/blocks/video-hero/component.tsx +270 -0
- package/blocks/video-hero/config.ts +11 -0
- package/blocks/video-hero/examples.ts +24 -0
- package/blocks/video-hero/fields.ts +98 -0
- package/blocks/video-hero/index.ts +6 -0
- package/blocks/video-hero/schema.ts +39 -0
- package/components/ai-chat/ChatPanel.tsx +575 -0
- package/components/ai-chat/ConversationItem.tsx +266 -0
- package/components/ai-chat/ConversationSidebar.tsx +99 -0
- package/components/ai-chat/MarkdownRenderer.tsx +15 -0
- package/components/ai-chat/Message.tsx +42 -0
- package/components/ai-chat/MessageInput.tsx +49 -0
- package/components/ai-chat/MessageList.tsx +46 -0
- package/components/ai-chat/TypingIndicator.tsx +11 -0
- package/config/app.config.ts +367 -0
- package/config/billing.config.ts +349 -0
- package/config/dashboard.config.ts +506 -0
- package/config/dev.config.ts +104 -0
- package/config/features.config.ts +203 -0
- package/config/flows.config.ts +129 -0
- package/config/permissions.config.ts +245 -0
- package/config/theme.config.ts +74 -0
- package/docs/01-overview/01-introduction.md +335 -0
- package/docs/01-overview/02-customization.md +671 -0
- package/docs/02-features/01-components.md +155 -0
- package/docs/02-features/02-styling.md +139 -0
- package/docs/02-features/03-tasks-entity.md +407 -0
- package/docs/03-ai/01-overview.md +211 -0
- package/docs/03-ai/02-customization.md +436 -0
- package/entities/customers/customers.config.ts +75 -0
- package/entities/customers/customers.fields.ts +165 -0
- package/entities/customers/customers.service.ts +516 -0
- package/entities/customers/customers.types.ts +83 -0
- package/entities/customers/messages/en.json +66 -0
- package/entities/customers/messages/es.json +66 -0
- package/entities/customers/migrations/001_customers_table.sql +102 -0
- package/entities/customers/migrations/002_customers_metas.sql +92 -0
- package/entities/pages/messages/en.json +41 -0
- package/entities/pages/messages/es.json +41 -0
- package/entities/pages/migrations/001_pages_table.sql +112 -0
- package/entities/pages/migrations/002_pages_metas.sql +56 -0
- package/entities/pages/migrations/003_add_status.sql +50 -0
- package/entities/pages/pages-management.service.ts +610 -0
- package/entities/pages/pages.config.ts +94 -0
- package/entities/pages/pages.fields.ts +101 -0
- package/entities/pages/pages.service.ts +290 -0
- package/entities/pages/pages.types.ts +124 -0
- package/entities/posts/components/post-header.tsx +97 -0
- package/entities/posts/messages/en.json +55 -0
- package/entities/posts/messages/es.json +55 -0
- package/entities/posts/migrations/001_posts_table.sql +115 -0
- package/entities/posts/migrations/003_add_status.sql +44 -0
- package/entities/posts/migrations/004_entity_taxonomy_relations.sql +129 -0
- package/entities/posts/migrations/006_posts_metas.sql +56 -0
- package/entities/posts/posts.config.ts +101 -0
- package/entities/posts/posts.fields.ts +116 -0
- package/entities/posts/posts.service.ts +376 -0
- package/entities/posts/posts.types.ts +74 -0
- package/entities/tasks/messages/en.json +204 -0
- package/entities/tasks/messages/es.json +204 -0
- package/entities/tasks/migrations/001_tasks_table.sql +105 -0
- package/entities/tasks/migrations/002_task_metas.sql +85 -0
- package/entities/tasks/migrations/sample_data.json +77 -0
- package/entities/tasks/tasks.config.ts +79 -0
- package/entities/tasks/tasks.fields.ts +196 -0
- package/entities/tasks/tasks.service.ts +541 -0
- package/entities/tasks/tasks.types.ts +56 -0
- package/lib/hooks/useAiChat.ts +114 -0
- package/lib/hooks/useConversations.ts +376 -0
- package/lib/hooks/useOrchestratorChat.ts +122 -0
- package/lib/hooks/usePersistentChat.ts +315 -0
- package/lib/hooks/useStreamingChat.ts +127 -0
- package/lib/hooks/useTokenUsage.ts +63 -0
- package/lib/langchain/agents/customer-assistant.md +69 -0
- package/lib/langchain/agents/index.ts +61 -0
- package/lib/langchain/agents/orchestrator.md +59 -0
- package/lib/langchain/agents/page-assistant.md +85 -0
- package/lib/langchain/agents/single-agent.md +46 -0
- package/lib/langchain/agents/task-assistant.md +55 -0
- package/lib/langchain/config.ts +45 -0
- package/lib/langchain/handlers/customer-handler.ts +338 -0
- package/lib/langchain/handlers/page-handler.ts +232 -0
- package/lib/langchain/handlers/task-handler.ts +323 -0
- package/lib/langchain/langchain.config.ts +223 -0
- package/lib/langchain/observability.config.ts +30 -0
- package/lib/langchain/orchestrator.ts +562 -0
- package/lib/langchain/tools/customers.ts +176 -0
- package/lib/langchain/tools/index.ts +10 -0
- package/lib/langchain/tools/orchestrator.ts +92 -0
- package/lib/langchain/tools/pages.ts +289 -0
- package/lib/langchain/tools/tasks.ts +167 -0
- package/lib/scheduled-actions/billing.ts +149 -0
- package/lib/scheduled-actions/index.ts +170 -0
- package/lib/scheduled-actions/webhook.ts +231 -0
- package/lib/selectors.ts +197 -0
- package/messages/de/admin.json +219 -0
- package/messages/de/aiUsage.json +36 -0
- package/messages/de/buttons.json +19 -0
- package/messages/de/categories.json +35 -0
- package/messages/de/common.json +16 -0
- package/messages/de/dev.json +101 -0
- package/messages/de/docs.json +27 -0
- package/messages/de/entities.json +7 -0
- package/messages/de/features.json +119 -0
- package/messages/de/footer.json +22 -0
- package/messages/de/home.json +57 -0
- package/messages/de/index.ts +39 -0
- package/messages/de/mobileNav.json +13 -0
- package/messages/de/navigation.json +8 -0
- package/messages/de/observability.json +74 -0
- package/messages/de/posts.json +54 -0
- package/messages/de/pricing.json +102 -0
- package/messages/de/support.json +9 -0
- package/messages/de/teams.json +8 -0
- package/messages/en/admin.json +219 -0
- package/messages/en/aiUsage.json +36 -0
- package/messages/en/buttons.json +19 -0
- package/messages/en/categories.json +35 -0
- package/messages/en/common.json +16 -0
- package/messages/en/dev.json +106 -0
- package/messages/en/docs.json +27 -0
- package/messages/en/entities.json +7 -0
- package/messages/en/features.json +119 -0
- package/messages/en/footer.json +22 -0
- package/messages/en/home.json +57 -0
- package/messages/en/index.ts +39 -0
- package/messages/en/mobileNav.json +13 -0
- package/messages/en/navigation.json +8 -0
- package/messages/en/observability.json +74 -0
- package/messages/en/posts.json +54 -0
- package/messages/en/pricing.json +102 -0
- package/messages/en/support.json +9 -0
- package/messages/en/teams.json +8 -0
- package/messages/es/admin.json +219 -0
- package/messages/es/aiUsage.json +36 -0
- package/messages/es/buttons.json +19 -0
- package/messages/es/categories.json +35 -0
- package/messages/es/common.json +16 -0
- package/messages/es/dev.json +101 -0
- package/messages/es/docs.json +27 -0
- package/messages/es/entities.json +7 -0
- package/messages/es/features.json +119 -0
- package/messages/es/footer.json +22 -0
- package/messages/es/home.json +57 -0
- package/messages/es/index.ts +39 -0
- package/messages/es/mobileNav.json +13 -0
- package/messages/es/navigation.json +8 -0
- package/messages/es/observability.json +74 -0
- package/messages/es/posts.json +54 -0
- package/messages/es/pricing.json +102 -0
- package/messages/es/support.json +9 -0
- package/messages/es/teams.json +8 -0
- package/messages/fr/admin.json +219 -0
- package/messages/fr/aiUsage.json +36 -0
- package/messages/fr/buttons.json +19 -0
- package/messages/fr/categories.json +35 -0
- package/messages/fr/common.json +16 -0
- package/messages/fr/dev.json +101 -0
- package/messages/fr/docs.json +27 -0
- package/messages/fr/entities.json +7 -0
- package/messages/fr/features.json +119 -0
- package/messages/fr/footer.json +22 -0
- package/messages/fr/home.json +57 -0
- package/messages/fr/index.ts +39 -0
- package/messages/fr/mobileNav.json +13 -0
- package/messages/fr/navigation.json +8 -0
- package/messages/fr/observability.json +74 -0
- package/messages/fr/posts.json +54 -0
- package/messages/fr/pricing.json +102 -0
- package/messages/fr/support.json +9 -0
- package/messages/fr/teams.json +8 -0
- package/messages/it/admin.json +219 -0
- package/messages/it/aiUsage.json +36 -0
- package/messages/it/buttons.json +19 -0
- package/messages/it/categories.json +35 -0
- package/messages/it/common.json +16 -0
- package/messages/it/dev.json +101 -0
- package/messages/it/docs.json +27 -0
- package/messages/it/entities.json +7 -0
- package/messages/it/features.json +119 -0
- package/messages/it/footer.json +22 -0
- package/messages/it/home.json +57 -0
- package/messages/it/index.ts +39 -0
- package/messages/it/mobileNav.json +13 -0
- package/messages/it/navigation.json +8 -0
- package/messages/it/observability.json +74 -0
- package/messages/it/posts.json +54 -0
- package/messages/it/pricing.json +102 -0
- package/messages/it/support.json +9 -0
- package/messages/it/teams.json +8 -0
- package/messages/pt/admin.json +219 -0
- package/messages/pt/aiUsage.json +36 -0
- package/messages/pt/buttons.json +19 -0
- package/messages/pt/categories.json +35 -0
- package/messages/pt/common.json +16 -0
- package/messages/pt/dev.json +101 -0
- package/messages/pt/docs.json +27 -0
- package/messages/pt/entities.json +7 -0
- package/messages/pt/features.json +119 -0
- package/messages/pt/footer.json +22 -0
- package/messages/pt/home.json +57 -0
- package/messages/pt/index.ts +39 -0
- package/messages/pt/mobileNav.json +13 -0
- package/messages/pt/navigation.json +8 -0
- package/messages/pt/observability.json +74 -0
- package/messages/pt/posts.json +54 -0
- package/messages/pt/pricing.json +102 -0
- package/messages/pt/support.json +9 -0
- package/messages/pt/teams.json +8 -0
- package/migrations/089_add_editor_team_role.sql +39 -0
- package/migrations/090_demo_users_teams.sql +540 -0
- package/migrations/091_greek_teams_billing.sql +523 -0
- package/migrations/092_billing_sample_data.sql +774 -0
- package/migrations/093_pages_sample_data.sql +1158 -0
- package/migrations/094_posts_sample_data.sql +278 -0
- package/migrations/095_tasks_sample_data.sql +440 -0
- package/migrations/096_customers_sample_data.sql +358 -0
- package/migrations/097_scheduled_actions_sample_data.sql +111 -0
- package/package.json +22 -0
- package/public/docs/desktop-layout-example.png +0 -0
- package/styles/components.css +11 -0
- package/styles/globals.css +179 -0
- package/templates/(public)/blog/[slug]/page.tsx +65 -0
- package/templates/(public)/layout.tsx +25 -0
- package/templates/(public)/page.tsx +200 -0
- package/templates/(public)/support/page.tsx +321 -0
- package/templates/dashboard/(main)/agent-multi/page.tsx +63 -0
- package/templates/dashboard/(main)/agent-single/page.tsx +142 -0
- package/templates/dashboard/(main)/settings/ai-usage/page.tsx +157 -0
- package/templates/superadmin/ai-observability/[traceId]/page.tsx +27 -0
- package/templates/superadmin/ai-observability/page.tsx +17 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# AI Assistant - Overview
|
|
2
|
+
|
|
3
|
+
This theme includes an AI-powered assistant that helps users manage tasks, customers, and pages through natural language.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
### Multi-Agent Architecture
|
|
8
|
+
|
|
9
|
+
The assistant uses a graph-based orchestrator that routes requests to specialized handlers:
|
|
10
|
+
|
|
11
|
+
| Intent | Handler | Description |
|
|
12
|
+
|--------|---------|-------------|
|
|
13
|
+
| `task` | Task Handler | Manage tasks (create, update, list, delete) |
|
|
14
|
+
| `customer` | Customer Handler | Manage customers (CRUD, search) |
|
|
15
|
+
| `page` | Page Handler | Manage pages and blocks |
|
|
16
|
+
| `greeting` | Greeting Handler | Respond to casual greetings |
|
|
17
|
+
| `unclear` | Clarification | Ask for more details |
|
|
18
|
+
|
|
19
|
+
### Key Capabilities
|
|
20
|
+
|
|
21
|
+
- **Natural Language**: Talk to the assistant in plain English
|
|
22
|
+
- **Multi-Intent**: Handle multiple requests in one message
|
|
23
|
+
- **Context-Aware**: Remembers conversation history
|
|
24
|
+
- **Real-Time Streaming**: See responses as they're generated
|
|
25
|
+
- **Tool Execution**: Automatically executes CRUD operations
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
### Accessing the Assistant
|
|
32
|
+
|
|
33
|
+
The AI assistant is available at:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
/dashboard/ai-assistant
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Example Interactions
|
|
40
|
+
|
|
41
|
+
**Task Management:**
|
|
42
|
+
```
|
|
43
|
+
User: Show my tasks for this week
|
|
44
|
+
Assistant: I found 5 tasks due this week...
|
|
45
|
+
|
|
46
|
+
User: Create a new task to review the quarterly report
|
|
47
|
+
Assistant: Done! Created task "Review quarterly report" with default settings.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Customer Management:**
|
|
51
|
+
```
|
|
52
|
+
User: Find customers from California
|
|
53
|
+
Assistant: Found 3 customers in California...
|
|
54
|
+
|
|
55
|
+
User: Show me John Smith's details
|
|
56
|
+
Assistant: Here are the details for John Smith...
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Page Management:**
|
|
60
|
+
```
|
|
61
|
+
User: List all published pages
|
|
62
|
+
Assistant: You have 12 published pages...
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Configuration
|
|
68
|
+
|
|
69
|
+
### Theme Configuration
|
|
70
|
+
|
|
71
|
+
The AI assistant is configured in `langchain.config.ts`:
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
// contents/themes/default/langchain.config.ts
|
|
75
|
+
export const langchainConfig: LangChainConfig = {
|
|
76
|
+
observability: {
|
|
77
|
+
enabled: true,
|
|
78
|
+
retention: { traces: 30 },
|
|
79
|
+
sampling: { rate: 1.0, alwaysTraceErrors: true },
|
|
80
|
+
pii: { maskInputs: false, maskOutputs: false, truncateAt: 10000 },
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Environment Variables
|
|
86
|
+
|
|
87
|
+
Required environment variables:
|
|
88
|
+
|
|
89
|
+
```env
|
|
90
|
+
# Enable the LangChain plugin
|
|
91
|
+
LANGCHAIN_PLUGIN_ENABLED=true
|
|
92
|
+
|
|
93
|
+
# Choose your LLM provider
|
|
94
|
+
LANGCHAIN_OLLAMA_MODEL=qwen2.5:7b # For local development
|
|
95
|
+
# OR
|
|
96
|
+
OPENAI_API_KEY=sk-... # For production
|
|
97
|
+
LANGCHAIN_OPENAI_MODEL=gpt-4o-mini
|
|
98
|
+
|
|
99
|
+
# Enable graph orchestrator (recommended)
|
|
100
|
+
LANGCHAIN_USE_GRAPH_ORCHESTRATOR=true
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Architecture
|
|
106
|
+
|
|
107
|
+
### Graph Orchestrator
|
|
108
|
+
|
|
109
|
+
The theme uses the graph-based orchestrator for efficient multi-intent handling:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
User Message → Router → Handlers → Combiner → Response
|
|
113
|
+
│
|
|
114
|
+
├─→ Task Handler (0 LLM calls)
|
|
115
|
+
├─→ Customer Handler (0 LLM calls)
|
|
116
|
+
├─→ Page Handler (0 LLM calls)
|
|
117
|
+
└─→ Greeting Handler (0 LLM calls)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Benefits:**
|
|
121
|
+
- 1-2 LLM calls per request (vs 50+ with ReAct)
|
|
122
|
+
- 2-3 second response time
|
|
123
|
+
- No recursion limit issues
|
|
124
|
+
- ~$0.001 per request
|
|
125
|
+
|
|
126
|
+
### Available Agents
|
|
127
|
+
|
|
128
|
+
| Agent | Purpose | Tools |
|
|
129
|
+
|-------|---------|-------|
|
|
130
|
+
| `orchestrator` | Main entry point | Intent routing |
|
|
131
|
+
| `task-assistant` | Task management | Task CRUD |
|
|
132
|
+
| `customer-assistant` | Customer management | Customer CRUD |
|
|
133
|
+
| `page-assistant` | Page/block management | Page CRUD |
|
|
134
|
+
| `single-agent` | Unified agent | All tools |
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Monitoring
|
|
139
|
+
|
|
140
|
+
### Token Usage Dashboard
|
|
141
|
+
|
|
142
|
+
Track AI usage at:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
/dashboard/settings/ai-usage
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Shows:
|
|
149
|
+
- Total tokens used
|
|
150
|
+
- Cost breakdown by model
|
|
151
|
+
- Daily usage charts
|
|
152
|
+
- Request counts
|
|
153
|
+
|
|
154
|
+
### Observability Dashboard (Admin)
|
|
155
|
+
|
|
156
|
+
For superadmins, detailed traces at:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
/sector7/ai-observability
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Shows:
|
|
163
|
+
- Request traces with timing
|
|
164
|
+
- Individual LLM/tool spans
|
|
165
|
+
- Error debugging
|
|
166
|
+
- Performance metrics
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Security
|
|
171
|
+
|
|
172
|
+
### Built-in Protections
|
|
173
|
+
|
|
174
|
+
The assistant includes guardrails for:
|
|
175
|
+
|
|
176
|
+
- **Prompt Injection Detection**: Blocks manipulation attempts
|
|
177
|
+
- **PII Masking**: Redacts sensitive data in traces
|
|
178
|
+
- **Content Filtering**: Filters inappropriate outputs
|
|
179
|
+
|
|
180
|
+
### Data Isolation
|
|
181
|
+
|
|
182
|
+
All data is isolated by user and team through Row-Level Security (RLS).
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Troubleshooting
|
|
187
|
+
|
|
188
|
+
### Common Issues
|
|
189
|
+
|
|
190
|
+
**Assistant not responding:**
|
|
191
|
+
1. Check `LANGCHAIN_PLUGIN_ENABLED=true`
|
|
192
|
+
2. Verify LLM provider is configured
|
|
193
|
+
3. Check browser console for errors
|
|
194
|
+
|
|
195
|
+
**Slow responses:**
|
|
196
|
+
1. Enable graph orchestrator: `LANGCHAIN_USE_GRAPH_ORCHESTRATOR=true`
|
|
197
|
+
2. Use faster model (gpt-4o-mini, claude-3-haiku)
|
|
198
|
+
3. Check network latency to LLM provider
|
|
199
|
+
|
|
200
|
+
**Wrong tool called:**
|
|
201
|
+
1. Be more specific in your request
|
|
202
|
+
2. Try rephrasing the question
|
|
203
|
+
3. Check agent prompts for clarity
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Related Documentation
|
|
208
|
+
|
|
209
|
+
- [Plugin Overview](../../../plugins/langchain/docs/01-overview.md)
|
|
210
|
+
- [Graph Orchestrator](../../../plugins/langchain/docs/11-graph-orchestrator.md)
|
|
211
|
+
- [Configuration](../../../plugins/langchain/docs/04-configuration.md)
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
# AI Assistant - Customization
|
|
2
|
+
|
|
3
|
+
This guide covers how to customize and extend the AI assistant for your specific needs.
|
|
4
|
+
|
|
5
|
+
## Creating Custom Tools
|
|
6
|
+
|
|
7
|
+
### Tool Structure
|
|
8
|
+
|
|
9
|
+
Tools are defined with a name, description, schema, and function:
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// contents/themes/default/lib/langchain/tools/my-entity.ts
|
|
13
|
+
|
|
14
|
+
import { z } from 'zod'
|
|
15
|
+
import type { ToolDefinition } from '@/contents/plugins/langchain/types/langchain.types'
|
|
16
|
+
import type { ToolContext } from '@/contents/plugins/langchain/types/langchain.types'
|
|
17
|
+
import { MyEntityService } from '@/contents/themes/default/entities/my-entity/my-entity.service'
|
|
18
|
+
|
|
19
|
+
export function createMyEntityTools(context: ToolContext): ToolDefinition<any>[] {
|
|
20
|
+
return [
|
|
21
|
+
{
|
|
22
|
+
name: 'list_my_entities',
|
|
23
|
+
description: 'List all my entities for the current user',
|
|
24
|
+
schema: z.object({
|
|
25
|
+
limit: z.number().optional().describe('Maximum number of results'),
|
|
26
|
+
status: z.string().optional().describe('Filter by status'),
|
|
27
|
+
}),
|
|
28
|
+
func: async ({ limit, status }) => {
|
|
29
|
+
const entities = await MyEntityService.list(context.userId, {
|
|
30
|
+
limit: limit || 10,
|
|
31
|
+
status,
|
|
32
|
+
})
|
|
33
|
+
return JSON.stringify(entities)
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'create_my_entity',
|
|
38
|
+
description: 'Create a new entity',
|
|
39
|
+
schema: z.object({
|
|
40
|
+
name: z.string().describe('Entity name'),
|
|
41
|
+
description: z.string().optional().describe('Entity description'),
|
|
42
|
+
}),
|
|
43
|
+
func: async ({ name, description }) => {
|
|
44
|
+
const entity = await MyEntityService.create(context.userId, {
|
|
45
|
+
name,
|
|
46
|
+
description,
|
|
47
|
+
})
|
|
48
|
+
return JSON.stringify(entity)
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Tool Best Practices
|
|
56
|
+
|
|
57
|
+
1. **Clear Descriptions**: The LLM reads descriptions to decide which tool to use
|
|
58
|
+
2. **Zod Schemas**: Use `.describe()` for parameter documentation
|
|
59
|
+
3. **JSON Output**: Always return `JSON.stringify()` results
|
|
60
|
+
4. **Context Usage**: Use `context.userId` and `context.teamId` for data isolation
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Creating Custom Agents
|
|
65
|
+
|
|
66
|
+
### Agent Definition
|
|
67
|
+
|
|
68
|
+
Define agents in the theme's langchain configuration:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// contents/themes/default/lib/langchain/agents.config.ts
|
|
72
|
+
|
|
73
|
+
import type { AgentDefinition, AgentContext } from '@/contents/plugins/langchain/types/langchain.types'
|
|
74
|
+
import { createMyEntityTools } from './tools/my-entity'
|
|
75
|
+
|
|
76
|
+
export const CUSTOM_AGENTS: Record<string, AgentDefinition> = {
|
|
77
|
+
'my-entity-assistant': {
|
|
78
|
+
provider: 'ollama', // or 'openai', 'anthropic'
|
|
79
|
+
temperature: 0.3,
|
|
80
|
+
description: 'Specialized agent for my entity management',
|
|
81
|
+
systemPrompt: 'my-entity-assistant', // loads agents/my-entity-assistant.md
|
|
82
|
+
createTools: (context: AgentContext) => createMyEntityTools(context),
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### System Prompt
|
|
88
|
+
|
|
89
|
+
Create the agent's system prompt:
|
|
90
|
+
|
|
91
|
+
```markdown
|
|
92
|
+
<!-- contents/themes/default/lib/langchain/agents/my-entity-assistant.md -->
|
|
93
|
+
|
|
94
|
+
You are a helpful assistant specialized in managing entities.
|
|
95
|
+
|
|
96
|
+
## Your Capabilities
|
|
97
|
+
- List entities with filters
|
|
98
|
+
- Create new entities
|
|
99
|
+
- Update existing entities
|
|
100
|
+
- Delete entities
|
|
101
|
+
|
|
102
|
+
## Guidelines
|
|
103
|
+
1. Always confirm destructive actions before proceeding
|
|
104
|
+
2. Format lists in a readable way
|
|
105
|
+
3. Ask clarifying questions when the request is ambiguous
|
|
106
|
+
4. Be concise but helpful
|
|
107
|
+
|
|
108
|
+
## Available Tools
|
|
109
|
+
- `list_my_entities`: Get entities with optional filters
|
|
110
|
+
- `create_my_entity`: Create a new entity
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Adding Graph Handlers
|
|
116
|
+
|
|
117
|
+
### Handler Structure
|
|
118
|
+
|
|
119
|
+
For the graph orchestrator, add custom handlers:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// contents/themes/default/lib/langchain/handlers/my-entity-handler.ts
|
|
123
|
+
|
|
124
|
+
import type { OrchestratorState, HandlerResult } from '@/contents/plugins/langchain/lib/graph/types'
|
|
125
|
+
import { MyEntityService } from '@/contents/themes/default/entities/my-entity/my-entity.service'
|
|
126
|
+
|
|
127
|
+
export async function myEntityHandler(
|
|
128
|
+
state: OrchestratorState
|
|
129
|
+
): Promise<Partial<OrchestratorState>> {
|
|
130
|
+
const context = state.context
|
|
131
|
+
const intent = state.intents.find(i => i.type === 'my_entity')
|
|
132
|
+
|
|
133
|
+
if (!intent) {
|
|
134
|
+
return {}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
// Determine action from intent parameters
|
|
139
|
+
const action = intent.parameters?.action || 'list'
|
|
140
|
+
|
|
141
|
+
let result: HandlerResult
|
|
142
|
+
|
|
143
|
+
switch (action) {
|
|
144
|
+
case 'list':
|
|
145
|
+
const entities = await MyEntityService.list(context.userId, {})
|
|
146
|
+
result = {
|
|
147
|
+
handler: 'my_entity',
|
|
148
|
+
success: true,
|
|
149
|
+
data: entities,
|
|
150
|
+
message: `Found ${entities.length} entities`,
|
|
151
|
+
}
|
|
152
|
+
break
|
|
153
|
+
|
|
154
|
+
case 'create':
|
|
155
|
+
const newEntity = await MyEntityService.create(context.userId, {
|
|
156
|
+
name: intent.parameters?.name,
|
|
157
|
+
})
|
|
158
|
+
result = {
|
|
159
|
+
handler: 'my_entity',
|
|
160
|
+
success: true,
|
|
161
|
+
data: newEntity,
|
|
162
|
+
message: `Created entity "${newEntity.name}"`,
|
|
163
|
+
}
|
|
164
|
+
break
|
|
165
|
+
|
|
166
|
+
default:
|
|
167
|
+
result = {
|
|
168
|
+
handler: 'my_entity',
|
|
169
|
+
success: false,
|
|
170
|
+
error: `Unknown action: ${action}`,
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
handlerResults: [...state.handlerResults, result],
|
|
176
|
+
completedHandlers: [...state.completedHandlers, 'my_entity'],
|
|
177
|
+
}
|
|
178
|
+
} catch (error) {
|
|
179
|
+
return {
|
|
180
|
+
handlerResults: [
|
|
181
|
+
...state.handlerResults,
|
|
182
|
+
{
|
|
183
|
+
handler: 'my_entity',
|
|
184
|
+
success: false,
|
|
185
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
completedHandlers: [...state.completedHandlers, 'my_entity'],
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Router Integration
|
|
195
|
+
|
|
196
|
+
Update the router to recognize your new intent:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
// The router uses structured output to classify intents
|
|
200
|
+
// Add your intent type to the schema:
|
|
201
|
+
|
|
202
|
+
const intentSchema = z.object({
|
|
203
|
+
type: z.enum([
|
|
204
|
+
'task',
|
|
205
|
+
'customer',
|
|
206
|
+
'page',
|
|
207
|
+
'my_entity', // Add your intent
|
|
208
|
+
'greeting',
|
|
209
|
+
'unclear',
|
|
210
|
+
]),
|
|
211
|
+
confidence: z.number(),
|
|
212
|
+
parameters: z.object({
|
|
213
|
+
action: z.string().optional(),
|
|
214
|
+
// Add entity-specific parameters
|
|
215
|
+
}).optional(),
|
|
216
|
+
})
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Customizing Prompts
|
|
222
|
+
|
|
223
|
+
### Template Variables
|
|
224
|
+
|
|
225
|
+
System prompts support Handlebars templates:
|
|
226
|
+
|
|
227
|
+
```markdown
|
|
228
|
+
<!-- agents/my-assistant.md -->
|
|
229
|
+
|
|
230
|
+
You are assisting {{user.name}} with their {{team.name}} account.
|
|
231
|
+
|
|
232
|
+
{{#if user.isAdmin}}
|
|
233
|
+
As an admin, you can also manage team settings.
|
|
234
|
+
{{/if}}
|
|
235
|
+
|
|
236
|
+
Today's date is {{today}}.
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Context Enrichment
|
|
240
|
+
|
|
241
|
+
Provide data for templates:
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
'my-assistant': {
|
|
245
|
+
provider: 'openai',
|
|
246
|
+
systemPrompt: 'my-assistant',
|
|
247
|
+
enrichContext: async ({ userId, teamId }) => {
|
|
248
|
+
const user = await UsersService.getById(userId)
|
|
249
|
+
const team = await TeamsService.getById(teamId)
|
|
250
|
+
return {
|
|
251
|
+
userId,
|
|
252
|
+
teamId,
|
|
253
|
+
user: { name: user.name, isAdmin: user.role === 'admin' },
|
|
254
|
+
team: { name: team.name },
|
|
255
|
+
today: new Date().toLocaleDateString(),
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## UI Integration
|
|
264
|
+
|
|
265
|
+
### Using the Chat Hook
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import { useStreamingChat } from '@/contents/plugins/langchain/hooks/useStreamingChat'
|
|
269
|
+
|
|
270
|
+
function MyAIChat() {
|
|
271
|
+
const {
|
|
272
|
+
isStreaming,
|
|
273
|
+
streamContent,
|
|
274
|
+
error,
|
|
275
|
+
sendMessage,
|
|
276
|
+
cancelStream,
|
|
277
|
+
} = useStreamingChat({
|
|
278
|
+
sessionId: 'my-session-id',
|
|
279
|
+
agentName: 'my-entity-assistant',
|
|
280
|
+
onComplete: (fullContent, tokenUsage) => {
|
|
281
|
+
console.log('Response complete:', fullContent)
|
|
282
|
+
console.log('Tokens used:', tokenUsage)
|
|
283
|
+
},
|
|
284
|
+
onError: (error) => {
|
|
285
|
+
console.error('Chat error:', error)
|
|
286
|
+
},
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
return (
|
|
290
|
+
<div>
|
|
291
|
+
{isStreaming && <TypingIndicator content={streamContent} />}
|
|
292
|
+
<button onClick={() => sendMessage('Show my entities')}>
|
|
293
|
+
Send
|
|
294
|
+
</button>
|
|
295
|
+
{isStreaming && (
|
|
296
|
+
<button onClick={cancelStream}>Cancel</button>
|
|
297
|
+
)}
|
|
298
|
+
</div>
|
|
299
|
+
)
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Token Usage Hook
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
import { useTokenUsage } from '@/contents/plugins/langchain/hooks/useTokenUsage'
|
|
307
|
+
|
|
308
|
+
function UsageDisplay() {
|
|
309
|
+
const { data, isLoading } = useTokenUsage({ period: '30d' })
|
|
310
|
+
|
|
311
|
+
if (isLoading) return <Loading />
|
|
312
|
+
|
|
313
|
+
return (
|
|
314
|
+
<div>
|
|
315
|
+
<p>Tokens: {data.totalTokens.toLocaleString()}</p>
|
|
316
|
+
<p>Cost: ${data.totalCost.toFixed(2)}</p>
|
|
317
|
+
</div>
|
|
318
|
+
)
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Testing
|
|
325
|
+
|
|
326
|
+
### Testing Tools
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
// tests/langchain/my-entity-tools.test.ts
|
|
330
|
+
|
|
331
|
+
import { createMyEntityTools } from '../lib/langchain/tools/my-entity'
|
|
332
|
+
|
|
333
|
+
describe('My Entity Tools', () => {
|
|
334
|
+
const context = { userId: 'test-user', teamId: 'test-team' }
|
|
335
|
+
|
|
336
|
+
it('should list entities', async () => {
|
|
337
|
+
const tools = createMyEntityTools(context)
|
|
338
|
+
const listTool = tools.find(t => t.name === 'list_my_entities')
|
|
339
|
+
|
|
340
|
+
const result = await listTool.func({ limit: 5 })
|
|
341
|
+
const parsed = JSON.parse(result)
|
|
342
|
+
|
|
343
|
+
expect(Array.isArray(parsed)).toBe(true)
|
|
344
|
+
})
|
|
345
|
+
})
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Testing Handlers
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
// tests/langchain/my-entity-handler.test.ts
|
|
352
|
+
|
|
353
|
+
import { myEntityHandler } from '../lib/langchain/handlers/my-entity-handler'
|
|
354
|
+
|
|
355
|
+
describe('My Entity Handler', () => {
|
|
356
|
+
it('should handle list intent', async () => {
|
|
357
|
+
const state = {
|
|
358
|
+
context: { userId: 'test-user', teamId: 'test-team' },
|
|
359
|
+
intents: [{ type: 'my_entity', parameters: { action: 'list' } }],
|
|
360
|
+
handlerResults: [],
|
|
361
|
+
completedHandlers: [],
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const result = await myEntityHandler(state)
|
|
365
|
+
|
|
366
|
+
expect(result.completedHandlers).toContain('my_entity')
|
|
367
|
+
expect(result.handlerResults[0].success).toBe(true)
|
|
368
|
+
})
|
|
369
|
+
})
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Best Practices
|
|
375
|
+
|
|
376
|
+
### 1. Keep Handlers Simple
|
|
377
|
+
|
|
378
|
+
Handlers should do minimal work (0 LLM calls):
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
// Good: Direct service call
|
|
382
|
+
const data = await Service.list(userId)
|
|
383
|
+
|
|
384
|
+
// Bad: Additional LLM call in handler
|
|
385
|
+
const agent = await createAgent(...)
|
|
386
|
+
const result = await agent.chat(...)
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### 2. Use Structured Output
|
|
390
|
+
|
|
391
|
+
For router customization, use Zod schemas for type-safe output:
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
const schema = z.object({
|
|
395
|
+
intent: z.enum(['task', 'customer', 'my_entity']),
|
|
396
|
+
confidence: z.number().min(0).max(1),
|
|
397
|
+
})
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### 3. Handle Errors Gracefully
|
|
401
|
+
|
|
402
|
+
Always return meaningful error messages:
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
try {
|
|
406
|
+
const result = await riskyOperation()
|
|
407
|
+
return { success: true, data: result }
|
|
408
|
+
} catch (error) {
|
|
409
|
+
return {
|
|
410
|
+
success: false,
|
|
411
|
+
error: `Failed to process: ${error.message}`,
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### 4. Document Your Tools
|
|
417
|
+
|
|
418
|
+
Clear descriptions help the LLM choose correctly:
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
{
|
|
422
|
+
name: 'search_products',
|
|
423
|
+
description: 'Search products by name, category, or price range. ' +
|
|
424
|
+
'Use this when the user wants to find specific products. ' +
|
|
425
|
+
'Returns up to 20 matching products.',
|
|
426
|
+
// ...
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## Related Documentation
|
|
433
|
+
|
|
434
|
+
- [Plugin Tools Guide](../../../plugins/langchain/docs/06-tools.md)
|
|
435
|
+
- [Graph Orchestrator](../../../plugins/langchain/docs/11-graph-orchestrator.md)
|
|
436
|
+
- [Agent Configuration](../../../plugins/langchain/docs/04-configuration.md)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Customers Entity Configuration - REFACTORED
|
|
3
|
+
*
|
|
4
|
+
* Updated according to new 5-section structure from refactoring plan.
|
|
5
|
+
* All table names, API paths, and metadata are now derived automatically from slug.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Users } from 'lucide-react'
|
|
9
|
+
import type { EntityConfig } from '@nextsparkjs/core/lib/entities/types'
|
|
10
|
+
import { customersFields } from './customers.fields'
|
|
11
|
+
|
|
12
|
+
export const customerEntityConfig: EntityConfig = {
|
|
13
|
+
// ==========================================
|
|
14
|
+
// 1. BASIC IDENTIFICATION
|
|
15
|
+
// ==========================================
|
|
16
|
+
slug: 'customers', // Single source of truth - derives tableName, apiPath, metaTableName, i18nNamespace
|
|
17
|
+
enabled: true,
|
|
18
|
+
names: {
|
|
19
|
+
singular: 'customer',
|
|
20
|
+
plural: 'Customers'
|
|
21
|
+
},
|
|
22
|
+
icon: Users,
|
|
23
|
+
|
|
24
|
+
// ==========================================
|
|
25
|
+
// 2. ACCESS AND SCOPE CONFIGURATION
|
|
26
|
+
// ==========================================
|
|
27
|
+
access: {
|
|
28
|
+
public: false, // Not accessible without authentication
|
|
29
|
+
api: true, // Has external API endpoints
|
|
30
|
+
metadata: true, // Supports metadata system
|
|
31
|
+
shared: true // CASE 2: Any authenticated user can access all records (no userId filter)
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
// ==========================================
|
|
35
|
+
// 3. UI/UX FEATURES
|
|
36
|
+
// ==========================================
|
|
37
|
+
ui: {
|
|
38
|
+
dashboard: {
|
|
39
|
+
showInMenu: true, // Based on showInMenu: true
|
|
40
|
+
showInTopbar: true // Based on showInTopbar: true
|
|
41
|
+
},
|
|
42
|
+
public: {
|
|
43
|
+
hasArchivePage: true, // Based on original hasArchivePage
|
|
44
|
+
hasSinglePage: true // Based on original hasSinglePage
|
|
45
|
+
},
|
|
46
|
+
features: {
|
|
47
|
+
searchable: true, // Based on searchable: true
|
|
48
|
+
sortable: true, // Based on sortable: true
|
|
49
|
+
filterable: true, // Based on filterable: true
|
|
50
|
+
bulkOperations: true, // Based on supportsBulkOperations: true
|
|
51
|
+
importExport: false // Based on supportsImportExport: false
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
// ==========================================
|
|
56
|
+
// 4. PERMISSIONS SYSTEM
|
|
57
|
+
// ==========================================
|
|
58
|
+
// Permissions are now centralized in permissions.config.ts
|
|
59
|
+
// See: contents/themes/default/permissions.config.ts -> entities.customers
|
|
60
|
+
|
|
61
|
+
// ==========================================
|
|
62
|
+
// FIELDS (imported from separate file)
|
|
63
|
+
// ==========================================
|
|
64
|
+
fields: customersFields,
|
|
65
|
+
|
|
66
|
+
// ==========================================
|
|
67
|
+
// AUTOMATIC SYSTEM DERIVATIONS
|
|
68
|
+
// ==========================================
|
|
69
|
+
// The following properties are automatically derived from the slug:
|
|
70
|
+
// - tableName: 'customers' (slug)
|
|
71
|
+
// - metaTableName: 'customers_metas' (slug + '_metas')
|
|
72
|
+
// - apiPath: '/api/v1/customers' (slug API Route)
|
|
73
|
+
// - i18nNamespace: 'customers' (slug as namespace)
|
|
74
|
+
// - foreignKey in metadata: 'entityId' (generic for all entities)
|
|
75
|
+
}
|