@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,49 @@
|
|
|
1
|
+
# Business Overview
|
|
2
|
+
|
|
3
|
+
## Product Name
|
|
4
|
+
|
|
5
|
+
**NextSpark - Default Theme**
|
|
6
|
+
|
|
7
|
+
## Description
|
|
8
|
+
|
|
9
|
+
Generic multi-tenant SaaS application demonstrating a complete foundation for building business management software. Serves as both a reference implementation and starting point for custom projects.
|
|
10
|
+
|
|
11
|
+
## Value Proposition
|
|
12
|
+
|
|
13
|
+
Accelerate SaaS development by providing a production-ready foundation with authentication, team management, permissions, and extensible entity system out of the box.
|
|
14
|
+
|
|
15
|
+
## Target Users
|
|
16
|
+
|
|
17
|
+
- **Development Teams** building custom SaaS applications
|
|
18
|
+
- **Agencies** needing rapid project bootstrapping
|
|
19
|
+
- **Startups** creating MVPs and prototypes
|
|
20
|
+
|
|
21
|
+
## Business Model
|
|
22
|
+
|
|
23
|
+
Open-source boilerplate / Template-based licensing
|
|
24
|
+
|
|
25
|
+
## Key Differentiators
|
|
26
|
+
|
|
27
|
+
1. **True Multi-Tenancy** - Complete team isolation with role-based permissions
|
|
28
|
+
2. **Entity System** - Flexible, extensible data model with built-in CRUD
|
|
29
|
+
3. **Theme Architecture** - Full customization without touching core
|
|
30
|
+
4. **Registry System** - High-performance dynamic configuration
|
|
31
|
+
|
|
32
|
+
## Demo Scenario
|
|
33
|
+
|
|
34
|
+
The default theme demonstrates a generic business management tool where:
|
|
35
|
+
- Multiple companies (teams) share the platform
|
|
36
|
+
- Users can belong to multiple organizations with different roles
|
|
37
|
+
- Each team has isolated data (tasks, customers, invoices)
|
|
38
|
+
- Permissions vary by role (owner, admin, member, viewer)
|
|
39
|
+
|
|
40
|
+
## Core Capabilities
|
|
41
|
+
|
|
42
|
+
- User authentication (email/password, OAuth)
|
|
43
|
+
- Team management with invitations
|
|
44
|
+
- Role-based access control
|
|
45
|
+
- Task and customer management
|
|
46
|
+
- Billing/invoices (owner-only)
|
|
47
|
+
- Public pages (landing, pricing, features)
|
|
48
|
+
- Internationalization (EN/ES)
|
|
49
|
+
- Plugin system (AI plugin included)
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"lastUpdated": "2024-12-18",
|
|
4
|
+
"features": {
|
|
5
|
+
"authentication": {
|
|
6
|
+
"id": "authentication",
|
|
7
|
+
"name": "Authentication",
|
|
8
|
+
"description": "User identity and access management",
|
|
9
|
+
"status": "stable",
|
|
10
|
+
"testTags": ["@feat-auth"],
|
|
11
|
+
"components": {
|
|
12
|
+
"email": {
|
|
13
|
+
"name": "Email Authentication",
|
|
14
|
+
"description": "Registration and login with email/password",
|
|
15
|
+
"testTags": ["@feat-auth", "@crud"],
|
|
16
|
+
"routes": ["/login", "/register", "/forgot-password", "/reset-password"]
|
|
17
|
+
},
|
|
18
|
+
"oauth-google": {
|
|
19
|
+
"name": "Google OAuth",
|
|
20
|
+
"description": "Social login with Google account",
|
|
21
|
+
"testTags": ["@feat-auth"],
|
|
22
|
+
"routes": ["/login"]
|
|
23
|
+
},
|
|
24
|
+
"email-verification": {
|
|
25
|
+
"name": "Email Verification",
|
|
26
|
+
"description": "Verify user email after registration",
|
|
27
|
+
"testTags": ["@feat-auth", "@workflow"],
|
|
28
|
+
"routes": ["/verify-email"]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"teams": {
|
|
33
|
+
"id": "teams-management",
|
|
34
|
+
"name": "Teams & Permissions",
|
|
35
|
+
"description": "Multi-tenant team management and RBAC",
|
|
36
|
+
"status": "stable",
|
|
37
|
+
"testTags": ["@feat-teams"],
|
|
38
|
+
"components": {
|
|
39
|
+
"management": {
|
|
40
|
+
"name": "Team Management",
|
|
41
|
+
"description": "Create, edit, and manage teams",
|
|
42
|
+
"testTags": ["@feat-teams", "@crud"],
|
|
43
|
+
"routes": ["/dashboard/settings/team"]
|
|
44
|
+
},
|
|
45
|
+
"switcher": {
|
|
46
|
+
"name": "Team Switcher",
|
|
47
|
+
"description": "Switch between multiple teams",
|
|
48
|
+
"testTags": ["@feat-teams", "@workflow"],
|
|
49
|
+
"routes": ["/dashboard"]
|
|
50
|
+
},
|
|
51
|
+
"invitations": {
|
|
52
|
+
"name": "Invitations",
|
|
53
|
+
"description": "Invite users to join a team",
|
|
54
|
+
"testTags": ["@feat-teams", "@workflow"],
|
|
55
|
+
"routes": ["/dashboard/settings/team/members", "/accept-invitation"]
|
|
56
|
+
},
|
|
57
|
+
"roles": {
|
|
58
|
+
"name": "Role-Based Permissions",
|
|
59
|
+
"description": "Assign roles (owner, admin, member, viewer)",
|
|
60
|
+
"testTags": ["@feat-teams", "@feat-permissions", "@security"],
|
|
61
|
+
"routes": ["/dashboard/settings/team/members"]
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"entities": {
|
|
66
|
+
"id": "entities-management",
|
|
67
|
+
"name": "Entities",
|
|
68
|
+
"description": "Business data management with CRUD operations",
|
|
69
|
+
"status": "stable",
|
|
70
|
+
"testTags": ["@crud"],
|
|
71
|
+
"components": {
|
|
72
|
+
"tasks": {
|
|
73
|
+
"name": "Tasks",
|
|
74
|
+
"description": "Task management with search, filter, and bulk actions",
|
|
75
|
+
"testTags": ["@feat-tasks", "@crud", "@metas", "@search"],
|
|
76
|
+
"routes": ["/dashboard/tasks"]
|
|
77
|
+
},
|
|
78
|
+
"customers": {
|
|
79
|
+
"name": "Customers",
|
|
80
|
+
"description": "Customer records with contact info and metadata",
|
|
81
|
+
"testTags": ["@feat-customers", "@crud", "@metas", "@search"],
|
|
82
|
+
"routes": ["/dashboard/customers"]
|
|
83
|
+
},
|
|
84
|
+
"invoices": {
|
|
85
|
+
"name": "Invoices",
|
|
86
|
+
"description": "Billing invoices (owner-only access)",
|
|
87
|
+
"testTags": ["@crud", "@security"],
|
|
88
|
+
"routes": ["/dashboard/invoices"]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"settings": {
|
|
93
|
+
"id": "settings",
|
|
94
|
+
"name": "Settings",
|
|
95
|
+
"description": "User and team configuration",
|
|
96
|
+
"status": "stable",
|
|
97
|
+
"testTags": [],
|
|
98
|
+
"components": {
|
|
99
|
+
"profile": {
|
|
100
|
+
"name": "User Profile",
|
|
101
|
+
"description": "Edit personal information and preferences",
|
|
102
|
+
"testTags": ["@feat-users", "@crud"],
|
|
103
|
+
"routes": ["/dashboard/settings/profile"]
|
|
104
|
+
},
|
|
105
|
+
"security": {
|
|
106
|
+
"name": "Security",
|
|
107
|
+
"description": "Password change, sessions management",
|
|
108
|
+
"testTags": ["@feat-users", "@security"],
|
|
109
|
+
"routes": ["/dashboard/settings/security"]
|
|
110
|
+
},
|
|
111
|
+
"api-keys": {
|
|
112
|
+
"name": "API Keys",
|
|
113
|
+
"description": "Generate and manage API keys for programmatic access",
|
|
114
|
+
"testTags": ["@feat-api-keys", "@crud", "@security"],
|
|
115
|
+
"routes": ["/dashboard/settings/api-keys"]
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"public-pages": {
|
|
120
|
+
"id": "public-pages",
|
|
121
|
+
"name": "Public Pages",
|
|
122
|
+
"description": "Marketing and informational pages",
|
|
123
|
+
"status": "stable",
|
|
124
|
+
"testTags": [],
|
|
125
|
+
"components": {
|
|
126
|
+
"landing": {
|
|
127
|
+
"name": "Landing Page",
|
|
128
|
+
"description": "Home page with marketing content",
|
|
129
|
+
"testTags": [],
|
|
130
|
+
"routes": ["/"]
|
|
131
|
+
},
|
|
132
|
+
"pricing": {
|
|
133
|
+
"name": "Pricing",
|
|
134
|
+
"description": "Pricing plans display",
|
|
135
|
+
"testTags": [],
|
|
136
|
+
"routes": ["/pricing"]
|
|
137
|
+
},
|
|
138
|
+
"support": {
|
|
139
|
+
"name": "Support",
|
|
140
|
+
"description": "Support information",
|
|
141
|
+
"testTags": [],
|
|
142
|
+
"routes": ["/support"]
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
"content": {
|
|
147
|
+
"id": "content-management",
|
|
148
|
+
"name": "Content Management",
|
|
149
|
+
"description": "Pages, posts, and dynamic content",
|
|
150
|
+
"status": "in-development",
|
|
151
|
+
"testTags": ["@feat-pages"],
|
|
152
|
+
"components": {
|
|
153
|
+
"page-builder": {
|
|
154
|
+
"name": "Page Builder",
|
|
155
|
+
"description": "Visual page builder with drag-and-drop blocks",
|
|
156
|
+
"testTags": ["@feat-pages", "@page-builder", "@block-crud", "@workflow"],
|
|
157
|
+
"routes": ["/dashboard/pages"]
|
|
158
|
+
},
|
|
159
|
+
"posts": {
|
|
160
|
+
"name": "Blog Posts",
|
|
161
|
+
"description": "Blog/content management system",
|
|
162
|
+
"testTags": ["@crud", "@workflow"],
|
|
163
|
+
"routes": ["/dashboard/posts", "/blog"]
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
"core": {
|
|
168
|
+
"id": "core-platform",
|
|
169
|
+
"name": "Core Platform",
|
|
170
|
+
"description": "Fundamental platform capabilities",
|
|
171
|
+
"status": "stable",
|
|
172
|
+
"testTags": [],
|
|
173
|
+
"components": {
|
|
174
|
+
"i18n": {
|
|
175
|
+
"name": "Internationalization",
|
|
176
|
+
"description": "Multi-language support (EN/ES)",
|
|
177
|
+
"testTags": [],
|
|
178
|
+
"routes": []
|
|
179
|
+
},
|
|
180
|
+
"mobile-nav": {
|
|
181
|
+
"name": "Mobile Navigation",
|
|
182
|
+
"description": "Touch-optimized bottom navigation bar",
|
|
183
|
+
"testTags": [],
|
|
184
|
+
"routes": ["/dashboard"]
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
"plugins": {
|
|
189
|
+
"id": "plugins",
|
|
190
|
+
"name": "Plugins",
|
|
191
|
+
"description": "Extended functionality via plugin system",
|
|
192
|
+
"status": "stable",
|
|
193
|
+
"testTags": [],
|
|
194
|
+
"components": {
|
|
195
|
+
"ai": {
|
|
196
|
+
"name": "AI Plugin",
|
|
197
|
+
"description": "Artificial intelligence features integration",
|
|
198
|
+
"testTags": [],
|
|
199
|
+
"routes": []
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
"flows": {
|
|
205
|
+
"onboarding": {
|
|
206
|
+
"id": "user-onboarding",
|
|
207
|
+
"name": "User Onboarding",
|
|
208
|
+
"description": "Complete flow from registration to first task creation",
|
|
209
|
+
"testTags": ["@flow-onboarding", "@smoke"],
|
|
210
|
+
"steps": [
|
|
211
|
+
"Register with email or Google",
|
|
212
|
+
"Verify email (if email registration)",
|
|
213
|
+
"Create or join a team",
|
|
214
|
+
"Explore dashboard",
|
|
215
|
+
"Create first task"
|
|
216
|
+
],
|
|
217
|
+
"features": [
|
|
218
|
+
"authentication.email",
|
|
219
|
+
"authentication.oauth-google",
|
|
220
|
+
"authentication.email-verification",
|
|
221
|
+
"teams.management",
|
|
222
|
+
"entities.tasks"
|
|
223
|
+
]
|
|
224
|
+
},
|
|
225
|
+
"team-collaboration": {
|
|
226
|
+
"id": "team-collaboration",
|
|
227
|
+
"name": "Team Collaboration",
|
|
228
|
+
"description": "Invite members and collaborate on tasks",
|
|
229
|
+
"testTags": ["@feat-teams", "@workflow"],
|
|
230
|
+
"steps": [
|
|
231
|
+
"Access team settings",
|
|
232
|
+
"Send invitation to new member",
|
|
233
|
+
"Member accepts invitation",
|
|
234
|
+
"Assign appropriate role",
|
|
235
|
+
"Member accesses shared tasks"
|
|
236
|
+
],
|
|
237
|
+
"features": [
|
|
238
|
+
"teams.invitations",
|
|
239
|
+
"teams.roles",
|
|
240
|
+
"entities.tasks"
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
"multi-team": {
|
|
244
|
+
"id": "multi-team-management",
|
|
245
|
+
"name": "Multi-Team Management",
|
|
246
|
+
"description": "User managing multiple organizations",
|
|
247
|
+
"testTags": ["@flow-team-switch", "@feat-teams", "@workflow"],
|
|
248
|
+
"steps": [
|
|
249
|
+
"Create additional team",
|
|
250
|
+
"Switch between teams",
|
|
251
|
+
"Manage different data per team",
|
|
252
|
+
"Configure separate permissions"
|
|
253
|
+
],
|
|
254
|
+
"features": [
|
|
255
|
+
"teams.management",
|
|
256
|
+
"teams.switcher",
|
|
257
|
+
"teams.roles"
|
|
258
|
+
]
|
|
259
|
+
},
|
|
260
|
+
"customer-lifecycle": {
|
|
261
|
+
"id": "customer-lifecycle",
|
|
262
|
+
"name": "Customer Lifecycle",
|
|
263
|
+
"description": "Managing customer relationships",
|
|
264
|
+
"testTags": ["@feat-customers", "@crud", "@workflow"],
|
|
265
|
+
"steps": [
|
|
266
|
+
"Add new customer",
|
|
267
|
+
"Add customer metadata",
|
|
268
|
+
"Create tasks related to customer",
|
|
269
|
+
"Generate invoice (owner only)"
|
|
270
|
+
],
|
|
271
|
+
"features": [
|
|
272
|
+
"entities.customers",
|
|
273
|
+
"entities.tasks",
|
|
274
|
+
"entities.invoices"
|
|
275
|
+
]
|
|
276
|
+
},
|
|
277
|
+
"api-integration": {
|
|
278
|
+
"id": "api-integration",
|
|
279
|
+
"name": "API Integration",
|
|
280
|
+
"description": "Programmatic access via API",
|
|
281
|
+
"testTags": ["@api", "@feat-api-keys", "@crud"],
|
|
282
|
+
"steps": [
|
|
283
|
+
"Generate API key",
|
|
284
|
+
"Authenticate API requests",
|
|
285
|
+
"Perform CRUD operations",
|
|
286
|
+
"Handle API responses"
|
|
287
|
+
],
|
|
288
|
+
"features": [
|
|
289
|
+
"settings.api-keys",
|
|
290
|
+
"entities.tasks",
|
|
291
|
+
"entities.customers"
|
|
292
|
+
]
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
"statusDefinitions": {
|
|
296
|
+
"stable": "Production-ready, fully tested",
|
|
297
|
+
"beta": "Feature complete, in testing",
|
|
298
|
+
"in-development": "Currently being implemented",
|
|
299
|
+
"planned": "Scheduled for future development",
|
|
300
|
+
"deprecated": "Being phased out"
|
|
301
|
+
}
|
|
302
|
+
}
|
package/about/team.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Default Theme
|
|
2
|
+
|
|
3
|
+
> **Note:** This file contains fictional test data for development and QA purposes only. Users, teams, and credentials listed here are sample data used for testing the application.
|
|
4
|
+
|
|
5
|
+
## Objetivo
|
|
6
|
+
|
|
7
|
+
Demo genérico del boilerplate mostrando el modo `multi-tenant` con múltiples empresas, usuarios con diferentes roles, y aislamiento de datos por team.
|
|
8
|
+
|
|
9
|
+
## Producto
|
|
10
|
+
|
|
11
|
+
**Boilerplate** - Aplicación base para gestión de tareas y clientes con sistema completo de teams y permisos.
|
|
12
|
+
|
|
13
|
+
## Teams Mode
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
multi-tenant
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- Usuarios pueden pertenecer a múltiples teams
|
|
20
|
+
- Team Switcher habilitado
|
|
21
|
+
- Crear teams habilitado
|
|
22
|
+
- Invitaciones habilitadas
|
|
23
|
+
|
|
24
|
+
## Entidades
|
|
25
|
+
|
|
26
|
+
| Entidad | Descripción |
|
|
27
|
+
|---------|-------------|
|
|
28
|
+
| tasks | Tareas con título, descripción, estado |
|
|
29
|
+
| customers | Clientes con datos de contacto y metadata |
|
|
30
|
+
| invoices | Facturas del sistema de billing (solo owners) |
|
|
31
|
+
|
|
32
|
+
## Permisos
|
|
33
|
+
|
|
34
|
+
### tasks
|
|
35
|
+
|
|
36
|
+
| Action | owner | admin | member | viewer |
|
|
37
|
+
|--------|:-----:|:-----:|:------:|:------:|
|
|
38
|
+
| create | ✅ | ✅ | ✅ | ❌ |
|
|
39
|
+
| read | ✅ | ✅ | ✅ | ✅ |
|
|
40
|
+
| update | ✅ | ✅ | ✅ | ❌ |
|
|
41
|
+
| delete | ✅ | ✅ | ❌ | ❌ |
|
|
42
|
+
|
|
43
|
+
### customers
|
|
44
|
+
|
|
45
|
+
| Action | owner | admin | member | viewer |
|
|
46
|
+
|--------|:-----:|:-----:|:------:|:------:|
|
|
47
|
+
| create | ✅ | ✅ | ❌ | ❌ |
|
|
48
|
+
| read | ✅ | ✅ | ✅ | ✅ |
|
|
49
|
+
| update | ✅ | ✅ | ❌ | ❌ |
|
|
50
|
+
| delete | ✅ | ❌ | ❌ | ❌ |
|
|
51
|
+
|
|
52
|
+
## Usuarios de Prueba
|
|
53
|
+
|
|
54
|
+
| Email | Nombre | Teams |
|
|
55
|
+
|-------|--------|-------|
|
|
56
|
+
| carlos.mendoza@nextspark.dev | Carlos Mendoza | Everpoint (owner), Riverstone (member) |
|
|
57
|
+
| james.wilson@nextspark.dev | James Wilson | Everpoint (admin) |
|
|
58
|
+
| ana.garcia@nextspark.dev | Ana García | Ironvale (owner) |
|
|
59
|
+
| sofia.lopez@nextspark.dev | Sofia López | Riverstone (owner), Ironvale (admin) |
|
|
60
|
+
| emily.johnson@nextspark.dev | Emily Johnson | Everpoint (member), Riverstone (admin) |
|
|
61
|
+
| diego.ramirez@nextspark.dev | Diego Ramírez | Everpoint (member) |
|
|
62
|
+
| michael.brown@nextspark.dev | Michael Brown | Ironvale (member) |
|
|
63
|
+
| sarah.davis@nextspark.dev | Sarah Davis | Ironvale (viewer) |
|
|
64
|
+
|
|
65
|
+
**Password:** `Test1234`
|
|
66
|
+
|
|
67
|
+
## Teams
|
|
68
|
+
|
|
69
|
+
| Team | Industria | Miembros |
|
|
70
|
+
|------|-----------|----------|
|
|
71
|
+
| Everpoint Labs | Technology | 4 |
|
|
72
|
+
| Ironvale Global | Consulting | 4 |
|
|
73
|
+
| Riverstone Ventures | Investment | 3 |
|
|
74
|
+
|
|
75
|
+
## Casos de Uso
|
|
76
|
+
|
|
77
|
+
1. Equipos de diferentes industrias compartiendo la misma plataforma
|
|
78
|
+
2. Usuarios con diferentes roles en diferentes empresas
|
|
79
|
+
3. Aislamiento completo de datos entre teams
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================================
|
|
3
|
+
* STREAMING CHAT API ENDPOINT
|
|
4
|
+
* ============================================================================
|
|
5
|
+
*
|
|
6
|
+
* Provides token-by-token streaming for AI chat using Server-Sent Events (SSE).
|
|
7
|
+
* Supports cancellation via AbortSignal and tracks token usage.
|
|
8
|
+
*
|
|
9
|
+
* POST /api/ai/chat/stream
|
|
10
|
+
* Body:
|
|
11
|
+
* - message: string (required) - User message
|
|
12
|
+
* - sessionId: string (optional) - Conversation session ID
|
|
13
|
+
* - agentName: string (required) - Agent to use (from langchain.config.ts)
|
|
14
|
+
*
|
|
15
|
+
* Returns: Server-Sent Events stream
|
|
16
|
+
* Event types:
|
|
17
|
+
* - token: { type: 'token', content: string }
|
|
18
|
+
* - done: { type: 'done', fullContent: string, tokenUsage?: {...} }
|
|
19
|
+
* - error: { type: 'error', error: string }
|
|
20
|
+
* - tool_start: { type: 'tool_start', toolName: string }
|
|
21
|
+
* - tool_end: { type: 'tool_end', toolName: string, result: unknown }
|
|
22
|
+
*
|
|
23
|
+
* ============================================================================
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { NextRequest } from 'next/server'
|
|
27
|
+
import { z } from 'zod'
|
|
28
|
+
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
29
|
+
import { streamChat } from '@/plugins/langchain/lib/agent-factory'
|
|
30
|
+
import { createSSEEncoder } from '@/plugins/langchain/lib/streaming'
|
|
31
|
+
import { loadSystemPrompt } from '@/themes/default/lib/langchain/agents'
|
|
32
|
+
import {
|
|
33
|
+
getAgentConfig,
|
|
34
|
+
getAgentModelConfig,
|
|
35
|
+
getAgentTools,
|
|
36
|
+
getAgentPromptName,
|
|
37
|
+
} from '@/themes/default/lib/langchain/langchain.config'
|
|
38
|
+
|
|
39
|
+
// Request validation schema
|
|
40
|
+
const StreamChatRequestSchema = z.object({
|
|
41
|
+
message: z.string().min(1).max(2000),
|
|
42
|
+
sessionId: z.string().optional(),
|
|
43
|
+
agentName: z.string().min(1),
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* POST - Stream chat response
|
|
48
|
+
*/
|
|
49
|
+
export async function POST(request: NextRequest) {
|
|
50
|
+
try {
|
|
51
|
+
// 1. Authentication
|
|
52
|
+
const authResult = await authenticateRequest(request)
|
|
53
|
+
if (!authResult.success || !authResult.user) {
|
|
54
|
+
return new Response(
|
|
55
|
+
JSON.stringify({ success: false, error: 'Unauthorized' }),
|
|
56
|
+
{
|
|
57
|
+
status: 401,
|
|
58
|
+
headers: { 'Content-Type': 'application/json' },
|
|
59
|
+
}
|
|
60
|
+
) as any
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 2. Team context
|
|
64
|
+
const teamId = request.headers.get('x-team-id')
|
|
65
|
+
if (!teamId) {
|
|
66
|
+
return new Response(
|
|
67
|
+
JSON.stringify({
|
|
68
|
+
success: false,
|
|
69
|
+
error: 'Team context required',
|
|
70
|
+
code: 'TEAM_CONTEXT_REQUIRED',
|
|
71
|
+
}),
|
|
72
|
+
{
|
|
73
|
+
status: 400,
|
|
74
|
+
headers: { 'Content-Type': 'application/json' },
|
|
75
|
+
}
|
|
76
|
+
) as any
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const userId = authResult.user.id
|
|
80
|
+
const context = { userId, teamId }
|
|
81
|
+
|
|
82
|
+
// 3. Validate request body
|
|
83
|
+
const body = await request.json()
|
|
84
|
+
const validation = StreamChatRequestSchema.safeParse(body)
|
|
85
|
+
|
|
86
|
+
if (!validation.success) {
|
|
87
|
+
return new Response(
|
|
88
|
+
JSON.stringify({
|
|
89
|
+
success: false,
|
|
90
|
+
error: 'Invalid request',
|
|
91
|
+
details: validation.error.issues,
|
|
92
|
+
}),
|
|
93
|
+
{
|
|
94
|
+
status: 400,
|
|
95
|
+
headers: { 'Content-Type': 'application/json' },
|
|
96
|
+
}
|
|
97
|
+
) as any
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const { message, sessionId, agentName } = validation.data
|
|
101
|
+
|
|
102
|
+
// 4. Get agent configuration
|
|
103
|
+
const agentConfig = getAgentConfig(agentName)
|
|
104
|
+
if (!agentConfig) {
|
|
105
|
+
return new Response(
|
|
106
|
+
JSON.stringify({
|
|
107
|
+
success: false,
|
|
108
|
+
error: `Agent '${agentName}' not found`,
|
|
109
|
+
code: 'AGENT_NOT_FOUND',
|
|
110
|
+
}),
|
|
111
|
+
{
|
|
112
|
+
status: 404,
|
|
113
|
+
headers: { 'Content-Type': 'application/json' },
|
|
114
|
+
}
|
|
115
|
+
) as any
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 5. Load system prompt
|
|
119
|
+
const promptName = getAgentPromptName(agentName)
|
|
120
|
+
if (!promptName) {
|
|
121
|
+
return new Response(
|
|
122
|
+
JSON.stringify({
|
|
123
|
+
success: false,
|
|
124
|
+
error: `No system prompt configured for agent '${agentName}'`,
|
|
125
|
+
}),
|
|
126
|
+
{
|
|
127
|
+
status: 500,
|
|
128
|
+
headers: { 'Content-Type': 'application/json' },
|
|
129
|
+
}
|
|
130
|
+
) as any
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const systemPrompt = loadSystemPrompt(promptName as any)
|
|
134
|
+
|
|
135
|
+
// 6. Build agent configuration for streaming
|
|
136
|
+
const streamConfig = {
|
|
137
|
+
name: agentName,
|
|
138
|
+
systemPrompt,
|
|
139
|
+
tools: getAgentTools(agentName, context),
|
|
140
|
+
modelConfig: getAgentModelConfig(agentName),
|
|
141
|
+
guardrails: agentConfig.guardrails,
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 7. Create SSE stream
|
|
145
|
+
const encoder = createSSEEncoder()
|
|
146
|
+
|
|
147
|
+
const stream = new ReadableStream({
|
|
148
|
+
async start(controller) {
|
|
149
|
+
try {
|
|
150
|
+
// Create streaming generator
|
|
151
|
+
const generator = streamChat(message, context, streamConfig, {
|
|
152
|
+
sessionId,
|
|
153
|
+
agentName,
|
|
154
|
+
signal: request.signal,
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
// Stream chunks
|
|
158
|
+
for await (const chunk of generator) {
|
|
159
|
+
controller.enqueue(encoder.encode(chunk))
|
|
160
|
+
|
|
161
|
+
// Stop streaming on done or error
|
|
162
|
+
if (chunk.type === 'done' || chunk.type === 'error') {
|
|
163
|
+
break
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Send final marker
|
|
168
|
+
controller.enqueue(encoder.encodeDone())
|
|
169
|
+
controller.close()
|
|
170
|
+
} catch (error) {
|
|
171
|
+
// Stream error to client
|
|
172
|
+
controller.enqueue(
|
|
173
|
+
encoder.encode({
|
|
174
|
+
type: 'error',
|
|
175
|
+
error: error instanceof Error ? error.message : 'Streaming error',
|
|
176
|
+
})
|
|
177
|
+
)
|
|
178
|
+
controller.close()
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
// Handle client cancellation
|
|
183
|
+
cancel() {
|
|
184
|
+
console.log('[Streaming Chat] Stream cancelled by client')
|
|
185
|
+
},
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
// 8. Return SSE response
|
|
189
|
+
// Note: Returning raw Response (not NextResponse) for SSE streaming compatibility
|
|
190
|
+
return new Response(stream, {
|
|
191
|
+
headers: {
|
|
192
|
+
'Content-Type': 'text/event-stream',
|
|
193
|
+
'Cache-Control': 'no-cache, no-transform',
|
|
194
|
+
'Connection': 'keep-alive',
|
|
195
|
+
'X-Accel-Buffering': 'no', // Disable nginx buffering
|
|
196
|
+
},
|
|
197
|
+
}) as any // Type assertion needed - Response is compatible with NextResponse
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.error('[Streaming Chat] Error:', error)
|
|
200
|
+
return new Response(
|
|
201
|
+
JSON.stringify({
|
|
202
|
+
success: false,
|
|
203
|
+
error: 'Failed to start streaming',
|
|
204
|
+
details: error instanceof Error ? error.message : 'Unknown error',
|
|
205
|
+
}),
|
|
206
|
+
{
|
|
207
|
+
status: 500,
|
|
208
|
+
headers: { 'Content-Type': 'application/json' },
|
|
209
|
+
}
|
|
210
|
+
) as any
|
|
211
|
+
}
|
|
212
|
+
}
|