@tellet/create 0.8.0

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 (64) hide show
  1. package/README.md +195 -0
  2. package/dist/ai/generate.d.ts +33 -0
  3. package/dist/ai/generate.js +108 -0
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.js +337 -0
  6. package/dist/scaffold/project.d.ts +44 -0
  7. package/dist/scaffold/project.js +318 -0
  8. package/package.json +48 -0
  9. package/template/Dockerfile +35 -0
  10. package/template/app/(dashboard)/agents/page.tsx +14 -0
  11. package/template/app/(dashboard)/conversations/[id]/page.tsx +103 -0
  12. package/template/app/(dashboard)/conversations/page.tsx +50 -0
  13. package/template/app/(dashboard)/dashboard/page.tsx +102 -0
  14. package/template/app/(dashboard)/layout.tsx +15 -0
  15. package/template/app/(dashboard)/settings/page.tsx +46 -0
  16. package/template/app/(site)/layout.tsx +3 -0
  17. package/template/app/(site)/page.tsx +25 -0
  18. package/template/app/api/chat/route.ts +129 -0
  19. package/template/app/api/cron/route.ts +29 -0
  20. package/template/app/api/orchestrator/route.ts +139 -0
  21. package/template/app/globals.css +30 -0
  22. package/template/app/layout.tsx +18 -0
  23. package/template/components/chat/ChatWidget.tsx +109 -0
  24. package/template/components/chat/Markdown.tsx +136 -0
  25. package/template/components/dashboard/AgentChat.tsx +192 -0
  26. package/template/components/dashboard/AgentsListClient.tsx +86 -0
  27. package/template/components/dashboard/DashboardAgentGrid.tsx +73 -0
  28. package/template/components/dashboard/OrchestratorChat.tsx +251 -0
  29. package/template/components/dashboard/Sidebar.tsx +44 -0
  30. package/template/components/dashboard/StatsCards.tsx +40 -0
  31. package/template/components/dashboard/Welcome.tsx +139 -0
  32. package/template/components/sections/Agents.tsx +67 -0
  33. package/template/components/sections/CTA.tsx +46 -0
  34. package/template/components/sections/FAQ.tsx +81 -0
  35. package/template/components/sections/Features.tsx +51 -0
  36. package/template/components/sections/Footer.tsx +22 -0
  37. package/template/components/sections/Hero.tsx +86 -0
  38. package/template/components/sections/Icons.tsx +29 -0
  39. package/template/components/ui/Button.tsx +26 -0
  40. package/template/docker-compose.yml +32 -0
  41. package/template/infra/bin/app.ts +16 -0
  42. package/template/infra/cdk.json +6 -0
  43. package/template/infra/lib/tellet-stack.ts +216 -0
  44. package/template/infra/package.json +20 -0
  45. package/template/infra/tsconfig.json +16 -0
  46. package/template/lib/db.ts +37 -0
  47. package/template/lib/engine/default.ts +227 -0
  48. package/template/lib/engine/index.ts +17 -0
  49. package/template/lib/mcp/client.ts +97 -0
  50. package/template/lib/mcp/knowledge.ts +84 -0
  51. package/template/lib/mcp/registry.ts +106 -0
  52. package/template/lib/orchestrator/executor.ts +202 -0
  53. package/template/lib/orchestrator/tools.ts +245 -0
  54. package/template/lib/providers/anthropic.ts +41 -0
  55. package/template/lib/providers/index.ts +36 -0
  56. package/template/lib/providers/openai.ts +46 -0
  57. package/template/lib/scheduler.ts +115 -0
  58. package/template/lib/supabase.ts +30 -0
  59. package/template/lib/tellet.ts +45 -0
  60. package/template/lib/utils.ts +6 -0
  61. package/template/next.config.ts +7 -0
  62. package/template/public/widget.js +172 -0
  63. package/template/railway.toml +9 -0
  64. package/template/tsconfig.json +21 -0
package/README.md ADDED
@@ -0,0 +1,195 @@
1
+ # @tellet/create
2
+
3
+ > The open-source platform for running an Agentic Company.
4
+
5
+ ```bash
6
+ npx @tellet/create
7
+ ```
8
+
9
+ tellet is a management platform for AI-powered companies. One command generates your AI agent team, website, dashboard, Knowledge Base, and Orchestrator — ready to deploy anywhere.
10
+
11
+ ## What you get
12
+
13
+ - **AI Agent Team** — 3-5 agents auto-generated for your business (CS, marketing, sales, ops)
14
+ - **Orchestrator** — Manage your entire company through conversation
15
+ - **Knowledge Base** — pgvector-powered, agents reference it for accurate answers
16
+ - **Dashboard** — Stats, agent chat, conversations, onboarding
17
+ - **Tool Marketplace** — Stripe, Email, GitHub, Slack, Notion via MCP
18
+ - **Embeddable Widget** — One script tag to add AI chat to any website
19
+ - **3-Tier Deployment** — Free (Vercel) / Cloud (Railway) / Enterprise (AWS)
20
+
21
+ ## How it works
22
+
23
+ ```
24
+ npx @tellet/create
25
+
26
+ ? New or Connect? → New business or add AI to existing
27
+ ? Deployment? → Quick Start / Cloud / Enterprise
28
+ ? AI Provider? → Anthropic / OpenAI
29
+ ? Company name? → Sunny Coffee
30
+ ? Describe your business → We sell specialty coffee...
31
+
32
+ Generating your AI team and website...
33
+
34
+ Your team:
35
+ Barista (customer_support)
36
+ Roaster (marketing)
37
+ Grinder (sales)
38
+
39
+ Your website:
40
+ "Coffee worth waking up for"
41
+
42
+ ✓ Project created!
43
+ ```
44
+
45
+ ## Quick start
46
+
47
+ ```bash
48
+ # Quick Start (Vercel + Supabase, free)
49
+ npx @tellet/create
50
+ cd your-company
51
+ npm install && npm run dev
52
+
53
+ # Cloud (Docker + Railway, $5/mo)
54
+ npx @tellet/create # choose "Cloud"
55
+ cd your-company
56
+ docker compose up # local dev
57
+ railway up # deploy
58
+
59
+ # Enterprise (AWS CDK, $5-15/mo)
60
+ npx @tellet/create # choose "Enterprise"
61
+ cd your-company/infra
62
+ npm install && npx cdk deploy
63
+ ```
64
+
65
+ ## Architecture
66
+
67
+ ```
68
+ ┌─ tellet Platform ─────────────────────────┐
69
+ │ Owner ↔ Orchestrator │
70
+ │ ↕ │
71
+ │ Agent Team (CS · Marketing · Sales · Ops) │
72
+ │ ↕ │
73
+ │ MCP Bridge Layer │
74
+ │ (KB, Stripe, DB, Email, Custom API...) │
75
+ └────────────────────────────────────────────┘
76
+ ```
77
+
78
+ ## Project structure
79
+
80
+ ```
81
+ your-company/
82
+ ├── agents/ # AI agent definitions (auto-generated)
83
+ ├── app/
84
+ │ ├── (site)/ # Public website with chat widget
85
+ │ ├── (dashboard)/ # Management dashboard + Orchestrator
86
+ │ └── api/
87
+ │ ├── chat/ # Streaming chat API (tool use)
88
+ │ ├── orchestrator/ # Orchestrator API (tool use loop)
89
+ │ └── cron/ # Scheduled agent tasks
90
+ ├── components/
91
+ │ ├── chat/ # ChatWidget, Markdown
92
+ │ ├── dashboard/ # Sidebar, Stats, AgentChat, Orchestrator
93
+ │ └── sections/ # Landing page sections
94
+ ├── lib/
95
+ │ ├── engine/ # Agent runtime with tool use agentic loop
96
+ │ ├── providers/ # LLM providers (Anthropic, OpenAI)
97
+ │ ├── mcp/ # MCP client, Knowledge Base, tool registry
98
+ │ ├── orchestrator/ # Orchestrator tools + executor
99
+ │ └── scheduler.ts # Cron/heartbeat agent scheduler
100
+ ├── public/widget.js # Embeddable chat widget
101
+ ├── tellet.json # Configuration (single source of truth)
102
+ ├── Dockerfile # Docker deployment (Cloud/Enterprise)
103
+ ├── docker-compose.yml # Local dev with PostgreSQL + pgvector
104
+ ├── railway.toml # Railway auto-deploy
105
+ └── infra/ # AWS CDK (Enterprise only)
106
+ ```
107
+
108
+ ## Orchestrator
109
+
110
+ The Orchestrator is your AI company manager. Talk to it from the dashboard:
111
+
112
+ - "Show my stats" — conversations, messages, costs
113
+ - "Update the website tagline" — modifies site content
114
+ - "Add Stripe to my agents" — installs tools from marketplace
115
+ - "Schedule marketing to post daily at 9am" — sets up cron tasks
116
+ - "Add our refund policy to the Knowledge Base" — agents reference it
117
+
118
+ ## Tool Marketplace
119
+
120
+ Connect tools via the Orchestrator or `tellet.json`:
121
+
122
+ | Tool | Package | Use case |
123
+ |------|---------|----------|
124
+ | Stripe | `@stripe/mcp` | Payments, invoices, subscriptions |
125
+ | Email | `resend-mcp` | Send emails, campaigns |
126
+ | GitHub | `@modelcontextprotocol/server-github` | Issues, PRs, repos |
127
+ | Slack | `@anthropic-ai/mcp-server-slack` | Messages, channels |
128
+ | Notion | `@anthropic-ai/mcp-server-notion` | Docs, databases |
129
+
130
+ 19,000+ MCP servers available via the [MCP Registry](https://registry.modelcontextprotocol.io/).
131
+
132
+ ## Deployment options
133
+
134
+ | Tier | Provider | Cost | Best for |
135
+ |------|----------|------|----------|
136
+ | Quick Start | Vercel + Supabase | $0 | Prototyping, new business |
137
+ | Cloud | Railway / Render / Fly.io | $5-20/mo | Production, startups |
138
+ | Enterprise | AWS CDK (Lambda + RDS) | $5-15/mo | Scale, existing AWS |
139
+
140
+ ## Connect mode
141
+
142
+ Already have a business? Use Connect mode:
143
+
144
+ ```bash
145
+ npx @tellet/create # choose "Connect"
146
+ ```
147
+
148
+ - Skips site generation, keeps dashboard + API
149
+ - Embeddable widget for your existing site:
150
+
151
+ ```html
152
+ <script src="https://your-tellet.com/widget.js"
153
+ data-agent="support"
154
+ data-api="https://your-tellet.com"></script>
155
+ ```
156
+
157
+ ## Configuration
158
+
159
+ All configuration lives in `tellet.json`:
160
+
161
+ ```json
162
+ {
163
+ "company": { "name": "Sunny Coffee", "industry": "Food & Beverage" },
164
+ "mode": "new",
165
+ "llm": { "provider": "anthropic", "defaultModel": "claude-sonnet-4-6" },
166
+ "agents": [
167
+ { "id": "barista", "role": "customer_support", "tools": ["search_knowledge"] },
168
+ { "id": "roaster", "role": "marketing", "tools": ["email"] }
169
+ ],
170
+ "tools": {
171
+ "search_knowledge": { "type": "builtin" },
172
+ "email": { "type": "mcp", "package": "resend-mcp" }
173
+ },
174
+ "site": { "tagline": "Coffee worth waking up for", "..." : "..." }
175
+ }
176
+ ```
177
+
178
+ ## Tech stack
179
+
180
+ - [Next.js 16](https://nextjs.org/) — App framework
181
+ - [PostgreSQL + pgvector](https://github.com/pgvector/pgvector) — Database + vector search
182
+ - [MCP](https://modelcontextprotocol.io/) — Tool integration protocol
183
+ - [Anthropic Claude](https://anthropic.com/) / [OpenAI](https://openai.com/) — AI models
184
+ - [Tailwind CSS 4](https://tailwindcss.com/) — Styling
185
+ - [Framer Motion](https://www.framer.com/motion/) — Animations
186
+
187
+ ## License
188
+
189
+ MIT
190
+
191
+ ## Links
192
+
193
+ - [tellet.com](https://tellet.com) — Website
194
+ - [GitHub](https://github.com/agentic-company/create-tellet) — Source code
195
+ - [npm](https://www.npmjs.com/package/@tellet/create) — Package
@@ -0,0 +1,33 @@
1
+ export type Provider = "anthropic" | "openai";
2
+ interface GeneratedAgent {
3
+ id: string;
4
+ name: string;
5
+ role: string;
6
+ description: string;
7
+ systemPrompt: string;
8
+ model: string;
9
+ }
10
+ interface SiteFeature {
11
+ title: string;
12
+ description: string;
13
+ icon: string;
14
+ }
15
+ interface SiteFAQ {
16
+ question: string;
17
+ answer: string;
18
+ }
19
+ interface SiteContent {
20
+ tagline: string;
21
+ subtitle: string;
22
+ features: SiteFeature[];
23
+ faq: SiteFAQ[];
24
+ cta: string;
25
+ }
26
+ export interface GenerateResult {
27
+ industry: string;
28
+ summary: string;
29
+ agents: GeneratedAgent[];
30
+ site: SiteContent;
31
+ }
32
+ export declare function generateAgents(companyName: string, businessDescription: string, provider?: Provider): Promise<GenerateResult>;
33
+ export {};
@@ -0,0 +1,108 @@
1
+ import Anthropic from "@anthropic-ai/sdk";
2
+ import OpenAI from "openai";
3
+ function buildSystemPrompt(provider) {
4
+ const modelExamples = provider === "anthropic"
5
+ ? 'use "claude-haiku-4-5" for high-volume simple tasks (CS), "claude-sonnet-4-6" for creative/complex tasks (marketing, sales)'
6
+ : 'use "gpt-4.1-mini" for high-volume simple tasks (CS), "gpt-4.1" for creative/complex tasks (marketing, sales)';
7
+ return `You are an AI company architect. Given a business description, generate a team of AI agents AND website content tailored for that specific business.
8
+
9
+ Rules for AGENTS:
10
+ 1. Generate 3-5 agents appropriate for the business
11
+ 2. Always include a customer_support agent
12
+ 3. Each agent needs a unique, memorable name related to the business theme
13
+ 4. Each system_prompt must be detailed (200+ words) and specific to THIS business — include the company name, products, customer demographics, tone of voice
14
+ 5. Assign appropriate models: ${modelExamples}
15
+ 6. The id should be lowercase, no spaces
16
+
17
+ Rules for SITE CONTENT:
18
+ 1. tagline: a punchy one-liner (max 8 words) that captures the business value
19
+ 2. subtitle: 1-2 sentences expanding on the tagline, mentioning who the business serves
20
+ 3. features: 4-6 business features/benefits (NOT technical features). Each needs a title (3-5 words), description (1 sentence), and icon (one of: sparkles, shield, zap, heart, globe, chart, clock, users, star, target)
21
+ 4. faq: 4-5 frequently asked questions a customer would ask, with concise answers
22
+ 5. cta: a short call-to-action phrase (e.g. "Start your journey today")
23
+
24
+ Output ONLY valid JSON matching this schema:
25
+ {
26
+ "industry": "string",
27
+ "summary": "string — one-line business summary",
28
+ "agents": [
29
+ {
30
+ "id": "string",
31
+ "name": "string",
32
+ "role": "string — one of: customer_support, marketing, sales, operations, development, analytics",
33
+ "description": "string — one sentence",
34
+ "systemPrompt": "string — detailed system prompt",
35
+ "model": "string"
36
+ }
37
+ ],
38
+ "site": {
39
+ "tagline": "string",
40
+ "subtitle": "string",
41
+ "features": [
42
+ { "title": "string", "description": "string", "icon": "string" }
43
+ ],
44
+ "faq": [
45
+ { "question": "string", "answer": "string" }
46
+ ],
47
+ "cta": "string"
48
+ }
49
+ }`;
50
+ }
51
+ async function generateWithAnthropic(companyName, businessDescription) {
52
+ const client = new Anthropic();
53
+ const message = await client.messages.create({
54
+ model: "claude-sonnet-4-6",
55
+ max_tokens: 8192,
56
+ system: buildSystemPrompt("anthropic"),
57
+ messages: [
58
+ {
59
+ role: "user",
60
+ content: `Company: ${companyName}\n\nBusiness Description: ${businessDescription}`,
61
+ },
62
+ ],
63
+ });
64
+ return message.content[0].type === "text" ? message.content[0].text : "";
65
+ }
66
+ async function generateWithOpenAI(companyName, businessDescription) {
67
+ const client = new OpenAI();
68
+ const response = await client.chat.completions.create({
69
+ model: "gpt-4.1",
70
+ max_tokens: 8192,
71
+ messages: [
72
+ { role: "system", content: buildSystemPrompt("openai") },
73
+ {
74
+ role: "user",
75
+ content: `Company: ${companyName}\n\nBusiness Description: ${businessDescription}`,
76
+ },
77
+ ],
78
+ });
79
+ return response.choices[0]?.message?.content || "";
80
+ }
81
+ export async function generateAgents(companyName, businessDescription, provider = "anthropic") {
82
+ const text = provider === "openai"
83
+ ? await generateWithOpenAI(companyName, businessDescription)
84
+ : await generateWithAnthropic(companyName, businessDescription);
85
+ // Extract JSON from response (handle markdown code blocks)
86
+ const jsonMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/) || [null, text];
87
+ const jsonStr = (jsonMatch[1] || text).trim();
88
+ try {
89
+ const result = JSON.parse(jsonStr);
90
+ if (!result.agents || result.agents.length === 0) {
91
+ throw new Error("No agents generated");
92
+ }
93
+ // Ensure site content exists with defaults
94
+ if (!result.site) {
95
+ result.site = {
96
+ tagline: `${companyName} — Powered by AI`,
97
+ subtitle: result.summary || businessDescription,
98
+ features: [],
99
+ faq: [],
100
+ cta: "Get started today",
101
+ };
102
+ }
103
+ return result;
104
+ }
105
+ catch {
106
+ throw new Error("Failed to parse AI response. Please try again.");
107
+ }
108
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,337 @@
1
+ #!/usr/bin/env node
2
+ import * as p from "@clack/prompts";
3
+ import chalk from "chalk";
4
+ import { generateAgents } from "./ai/generate.js";
5
+ import { scaffoldProject } from "./scaffold/project.js";
6
+ async function main() {
7
+ console.clear();
8
+ console.log();
9
+ console.log(chalk.bold(` ${chalk.white("tel")}${chalk.yellow("let")} ${chalk.dim("— Build Your AI Company")}`));
10
+ console.log();
11
+ p.intro(chalk.bgHex("#8b5cf6").white(" @tellet/create "));
12
+ // Step 0: New or Connect
13
+ const modeChoice = await p.select({
14
+ message: "What would you like to do?",
15
+ options: [
16
+ {
17
+ value: "new",
18
+ label: "New",
19
+ hint: "Build a new AI company from scratch",
20
+ },
21
+ {
22
+ value: "connect",
23
+ label: "Connect",
24
+ hint: "Add AI agents to your existing business",
25
+ },
26
+ ],
27
+ });
28
+ if (p.isCancel(modeChoice)) {
29
+ p.cancel("Setup cancelled.");
30
+ process.exit(0);
31
+ }
32
+ const mode = modeChoice;
33
+ // Step 1: Company info
34
+ const company = await p.group({
35
+ name: () => p.text({
36
+ message: "What's your company name?",
37
+ placeholder: "Sunny Coffee",
38
+ validate: (v) => (!v ? "Company name is required" : undefined),
39
+ }),
40
+ description: () => p.text({
41
+ message: "Describe your business (what you do, who your customers are, what help you need):",
42
+ placeholder: "We sell specialty coffee subscriptions. Customers are coffee enthusiasts aged 25-45...",
43
+ validate: (v) => !v || v.length < 20
44
+ ? "Please provide at least a few sentences"
45
+ : undefined,
46
+ }),
47
+ }, {
48
+ onCancel: () => {
49
+ p.cancel("Setup cancelled.");
50
+ process.exit(0);
51
+ },
52
+ });
53
+ // Step 2: Deployment tier
54
+ const tierChoice = await p.select({
55
+ message: "Deployment mode:",
56
+ options: [
57
+ {
58
+ value: "quickstart",
59
+ label: "Quick Start",
60
+ hint: "Vercel + Supabase — free, instant deploy",
61
+ },
62
+ {
63
+ value: "cloud",
64
+ label: "Cloud",
65
+ hint: "Railway / Render / Fly.io — Docker, $5-20/mo",
66
+ },
67
+ {
68
+ value: "enterprise",
69
+ label: "Enterprise",
70
+ hint: "AWS CDK — auto-provision Lambda + RDS + CloudFront",
71
+ },
72
+ ],
73
+ });
74
+ if (p.isCancel(tierChoice)) {
75
+ p.cancel("Setup cancelled.");
76
+ process.exit(0);
77
+ }
78
+ const tier = tierChoice;
79
+ // Step 3: Choose AI provider
80
+ const providerChoice = await p.select({
81
+ message: "Choose your AI provider:",
82
+ options: [
83
+ {
84
+ value: "anthropic",
85
+ label: "Anthropic (Claude)",
86
+ hint: "recommended — also powers the Orchestrator",
87
+ },
88
+ {
89
+ value: "openai",
90
+ label: "OpenAI (GPT)",
91
+ hint: "uses gpt-4.1 for generation",
92
+ },
93
+ ],
94
+ });
95
+ if (p.isCancel(providerChoice)) {
96
+ p.cancel("Setup cancelled.");
97
+ process.exit(0);
98
+ }
99
+ const provider = providerChoice;
100
+ // Step 4: Get API key
101
+ const envKey = provider === "anthropic"
102
+ ? process.env.ANTHROPIC_API_KEY
103
+ : process.env.OPENAI_API_KEY;
104
+ const envName = provider === "anthropic" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
105
+ const keyPrefix = provider === "anthropic" ? "sk-ant-" : "sk-";
106
+ const keyPlaceholder = provider === "anthropic" ? "sk-ant-..." : "sk-...";
107
+ let apiKey = envKey || "";
108
+ if (!apiKey) {
109
+ const keyInput = await p.text({
110
+ message: `Your ${provider === "anthropic" ? "Anthropic" : "OpenAI"} API key:`,
111
+ placeholder: keyPlaceholder,
112
+ validate: (v) => !v || !v.startsWith(keyPrefix)
113
+ ? `Please enter a valid key (starts with ${keyPrefix})`
114
+ : undefined,
115
+ });
116
+ if (p.isCancel(keyInput)) {
117
+ p.cancel("Setup cancelled.");
118
+ process.exit(0);
119
+ }
120
+ apiKey = keyInput;
121
+ process.env[envName] = apiKey;
122
+ }
123
+ else {
124
+ p.log.info(chalk.dim(`Using ${envName} from environment.`));
125
+ }
126
+ // Orchestrator always needs Anthropic
127
+ let anthropicKey = "";
128
+ if (provider === "anthropic") {
129
+ anthropicKey = apiKey;
130
+ }
131
+ else {
132
+ const existingKey = process.env.ANTHROPIC_API_KEY || "";
133
+ if (existingKey) {
134
+ anthropicKey = existingKey;
135
+ p.log.info(chalk.dim("Using ANTHROPIC_API_KEY for Orchestrator."));
136
+ }
137
+ else {
138
+ p.log.info(chalk.dim("The Orchestrator requires an Anthropic API key (Claude tool use)."));
139
+ const orchKeyInput = await p.text({
140
+ message: "Anthropic API key for Orchestrator:",
141
+ placeholder: "sk-ant-...",
142
+ validate: (v) => !v || !v.startsWith("sk-ant-")
143
+ ? "Please enter a valid Anthropic key (starts with sk-ant-)"
144
+ : undefined,
145
+ });
146
+ if (p.isCancel(orchKeyInput)) {
147
+ p.cancel("Setup cancelled.");
148
+ process.exit(0);
149
+ }
150
+ anthropicKey = orchKeyInput;
151
+ }
152
+ }
153
+ // Step 5: Generate agents + site content
154
+ const s = p.spinner();
155
+ s.start("Generating your AI team and website...");
156
+ let agents;
157
+ try {
158
+ agents = await generateAgents(company.name, company.description, provider);
159
+ s.stop("Your AI team is ready!");
160
+ }
161
+ catch (err) {
162
+ s.stop("Failed to generate agents.");
163
+ p.log.error(err instanceof Error ? err.message : "Check your API key");
164
+ p.cancel("Setup failed.");
165
+ process.exit(1);
166
+ }
167
+ // Step 6: Show agents + site preview
168
+ p.log.info(chalk.bold("Meet your team:"));
169
+ console.log();
170
+ for (const agent of agents.agents) {
171
+ console.log(` ${chalk.hex("#8b5cf6").bold(agent.name)} ${chalk.dim(`(${agent.role})`)}`);
172
+ console.log(` ${chalk.dim(agent.description)}`);
173
+ console.log();
174
+ }
175
+ if (agents.site && mode === "new") {
176
+ p.log.info(chalk.bold("Your website:"));
177
+ console.log(` ${chalk.hex("#f59e0b")(agents.site.tagline)}`);
178
+ console.log(` ${chalk.dim(agents.site.subtitle)}`);
179
+ console.log();
180
+ }
181
+ const confirm = await p.confirm({
182
+ message: "Looks good?",
183
+ initialValue: true,
184
+ });
185
+ if (p.isCancel(confirm) || !confirm) {
186
+ p.cancel("Setup cancelled.");
187
+ process.exit(0);
188
+ }
189
+ // Step 7a: Connect mode — website URL for KB
190
+ let websiteUrl = "";
191
+ if (mode === "connect") {
192
+ const urlInput = await p.text({
193
+ message: "Your existing website URL (for Knowledge Base crawling):",
194
+ placeholder: "https://my-business.com",
195
+ });
196
+ if (!p.isCancel(urlInput) && urlInput) {
197
+ websiteUrl = urlInput;
198
+ }
199
+ }
200
+ // Step 7b: Infrastructure setup (tier-dependent)
201
+ let supabaseUrl = "";
202
+ let supabaseKey = "";
203
+ if (tier === "quickstart") {
204
+ p.log.info(`${chalk.bold("Supabase setup")} ${chalk.dim("(free tier works fine)")}\n` +
205
+ ` ${chalk.dim("1.")} Create a project at ${chalk.cyan("https://supabase.com/dashboard/new")}\n` +
206
+ ` ${chalk.dim("2.")} Go to Settings → API to find your URL and keys`);
207
+ const supabase = await p.group({
208
+ url: () => p.text({
209
+ message: "Your Supabase project URL:",
210
+ placeholder: "https://xxx.supabase.co",
211
+ validate: (v) => !v || !v.includes("supabase")
212
+ ? "Please enter a valid Supabase URL"
213
+ : undefined,
214
+ }),
215
+ key: () => p.text({
216
+ message: "Your Supabase publishable key (anon/public):",
217
+ placeholder: "sb_publishable_...",
218
+ validate: (v) => (!v ? "Key is required" : undefined),
219
+ }),
220
+ }, {
221
+ onCancel: () => {
222
+ p.cancel("Setup cancelled.");
223
+ process.exit(0);
224
+ },
225
+ });
226
+ supabaseUrl = supabase.url;
227
+ supabaseKey = supabase.key;
228
+ }
229
+ else if (tier === "cloud") {
230
+ p.log.info(chalk.dim("Cloud mode: PostgreSQL runs in Docker. No Supabase needed."));
231
+ }
232
+ else {
233
+ p.log.info(`${chalk.bold("AWS Enterprise setup")}\n` +
234
+ ` ${chalk.dim("Requires:")} AWS CLI configured + CDK bootstrapped\n` +
235
+ ` ${chalk.dim("Cost:")} ~$5-15/mo (Lambda + RDS free tier)`);
236
+ }
237
+ // Step 8: Scaffold project
238
+ s.start("Creating your project...");
239
+ try {
240
+ const projectDir = await scaffoldProject({
241
+ company: {
242
+ name: company.name,
243
+ description: company.description,
244
+ industry: agents.industry,
245
+ },
246
+ agents: agents.agents,
247
+ site: agents.site,
248
+ provider,
249
+ tier,
250
+ mode,
251
+ websiteUrl,
252
+ infra: {
253
+ anthropicKey,
254
+ openaiKey: provider === "openai" ? apiKey : undefined,
255
+ supabaseUrl,
256
+ supabaseKey,
257
+ },
258
+ });
259
+ s.stop("Project created!");
260
+ const slug = company.name
261
+ .toLowerCase()
262
+ .replace(/[^a-z0-9]+/g, "-")
263
+ .replace(/^-|-$/g, "");
264
+ const widgetSnippet = mode === "connect"
265
+ ? [
266
+ ``,
267
+ `${chalk.bold("Embed in your existing site:")}`,
268
+ `${chalk.cyan('<script src="https://YOUR_URL/widget.js"')}`,
269
+ `${chalk.cyan(' data-agent="' + agents.agents[0].id + '"')}`,
270
+ `${chalk.cyan(' data-api="https://YOUR_URL"></script>')}`,
271
+ ]
272
+ : [];
273
+ if (tier === "quickstart") {
274
+ p.note([
275
+ `cd ${slug}`,
276
+ `npm install`,
277
+ `npm run dev ${chalk.dim("→ http://localhost:3000")}`,
278
+ ``,
279
+ `Dashboard: ${chalk.dim("/dashboard")}`,
280
+ `Orchestrator: ${chalk.dim("floating button in dashboard")}`,
281
+ `Agents: ${chalk.dim(`${agents.agents.length} active`)}`,
282
+ ...widgetSnippet,
283
+ ].join("\n"), mode === "connect" ? "Your AI agents are ready" : "Your AI company is ready");
284
+ p.outro(`Deploy: ${chalk.cyan("vercel deploy")}`);
285
+ }
286
+ else if (tier === "cloud") {
287
+ p.note([
288
+ `cd ${slug}`,
289
+ ``,
290
+ `${chalk.bold("Local development:")}`,
291
+ `docker compose up ${chalk.dim("→ http://localhost:3000")}`,
292
+ ``,
293
+ `${chalk.bold("Deploy to Railway:")}`,
294
+ `railway login`,
295
+ `railway init`,
296
+ `railway add --plugin postgresql`,
297
+ `railway up`,
298
+ ``,
299
+ `Dashboard: ${chalk.dim("/dashboard")}`,
300
+ `Orchestrator: ${chalk.dim("floating button in dashboard")}`,
301
+ `Agents: ${chalk.dim(`${agents.agents.length} active`)}`,
302
+ ].join("\n"), "Your AI company is ready");
303
+ p.outro(`Or deploy to ${chalk.cyan("Render")}, ${chalk.cyan("Fly.io")}, or any Docker host`);
304
+ }
305
+ else {
306
+ p.note([
307
+ `cd ${slug}`,
308
+ ``,
309
+ `${chalk.bold("Local development:")}`,
310
+ `docker compose up ${chalk.dim("→ http://localhost:3000")}`,
311
+ ``,
312
+ `${chalk.bold("Deploy to AWS:")}`,
313
+ `cd infra`,
314
+ `npm install`,
315
+ `npx cdk bootstrap ${chalk.dim("(first time only)")}`,
316
+ `npx cdk deploy ${chalk.dim("→ CloudFront URL in output")}`,
317
+ ``,
318
+ `${chalk.bold("Update API keys:")}`,
319
+ `aws secretsmanager put-secret-value \\`,
320
+ ` --secret-id ${slug}/api-keys \\`,
321
+ ` --secret-string '{"ANTHROPIC_API_KEY":"sk-ant-..."}'`,
322
+ ``,
323
+ `Dashboard: ${chalk.dim("/dashboard")}`,
324
+ `Orchestrator: ${chalk.dim("floating button in dashboard")}`,
325
+ `Agents: ${chalk.dim(`${agents.agents.length} active`)}`,
326
+ `Est. cost: ${chalk.dim("$5-15/mo")}`,
327
+ ].join("\n"), "Your AI company is ready (AWS)");
328
+ p.outro(`Run ${chalk.cyan("cd infra && npx cdk deploy")} to provision AWS infrastructure`);
329
+ }
330
+ }
331
+ catch (err) {
332
+ s.stop("Failed to create project.");
333
+ p.log.error(err instanceof Error ? err.message : String(err));
334
+ process.exit(1);
335
+ }
336
+ }
337
+ main().catch(console.error);