@tellet/create 0.10.0 → 0.12.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.
- package/README.md +51 -1
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +54 -0
- package/dist/commands/agent.d.ts +1 -0
- package/dist/commands/agent.js +156 -0
- package/dist/commands/build.d.ts +1 -0
- package/dist/commands/build.js +14 -0
- package/dist/commands/deploy.d.ts +1 -0
- package/dist/commands/deploy.js +117 -0
- package/dist/commands/dev.d.ts +1 -0
- package/dist/commands/dev.js +15 -0
- package/dist/commands/mcp.d.ts +1 -0
- package/dist/commands/mcp.js +4 -0
- package/dist/commands/shared.d.ts +69 -0
- package/dist/commands/shared.js +73 -0
- package/dist/commands/status.d.ts +1 -0
- package/dist/commands/status.js +53 -0
- package/dist/index.js +8 -421
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +25 -0
- package/dist/mcp/tools.d.ts +2 -0
- package/dist/mcp/tools.js +264 -0
- package/dist/scaffold-flow.d.ts +1 -0
- package/dist/scaffold-flow.js +402 -0
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -1,422 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
console.log();
|
|
11
|
-
console.log(chalk.bold(` ${chalk.white("tel")}${chalk.yellow("let")} ${chalk.dim("— Build Your AI Company")}`));
|
|
12
|
-
console.log();
|
|
13
|
-
p.intro(chalk.bgHex("#8b5cf6").white(" @tellet/create "));
|
|
14
|
-
// Step 0: New or Connect
|
|
15
|
-
const modeChoice = await p.select({
|
|
16
|
-
message: "What would you like to do?",
|
|
17
|
-
options: [
|
|
18
|
-
{
|
|
19
|
-
value: "new",
|
|
20
|
-
label: "New",
|
|
21
|
-
hint: "Build a new AI company from scratch",
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
value: "connect",
|
|
25
|
-
label: "Connect",
|
|
26
|
-
hint: "Add AI agents to your existing business",
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
});
|
|
30
|
-
if (p.isCancel(modeChoice)) {
|
|
31
|
-
p.cancel("Setup cancelled.");
|
|
32
|
-
process.exit(0);
|
|
33
|
-
}
|
|
34
|
-
const mode = modeChoice;
|
|
35
|
-
// Step 1: Company info
|
|
36
|
-
const company = await p.group({
|
|
37
|
-
name: () => p.text({
|
|
38
|
-
message: "What's your company name?",
|
|
39
|
-
placeholder: "Sunny Coffee",
|
|
40
|
-
validate: (v) => (!v ? "Company name is required" : undefined),
|
|
41
|
-
}),
|
|
42
|
-
description: () => p.text({
|
|
43
|
-
message: "Describe your business (what you do, who your customers are, what help you need):",
|
|
44
|
-
placeholder: "We sell specialty coffee subscriptions. Customers are coffee enthusiasts aged 25-45...",
|
|
45
|
-
validate: (v) => !v || v.length < 20
|
|
46
|
-
? "Please provide at least a few sentences"
|
|
47
|
-
: undefined,
|
|
48
|
-
}),
|
|
49
|
-
}, {
|
|
50
|
-
onCancel: () => {
|
|
51
|
-
p.cancel("Setup cancelled.");
|
|
52
|
-
process.exit(0);
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
// Step 2: Deployment tier
|
|
56
|
-
const tierChoice = await p.select({
|
|
57
|
-
message: "Deployment mode:",
|
|
58
|
-
options: [
|
|
59
|
-
{
|
|
60
|
-
value: "quickstart",
|
|
61
|
-
label: "Quick Start",
|
|
62
|
-
hint: "Vercel + Supabase — free, instant deploy",
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
value: "cloud",
|
|
66
|
-
label: "Cloud",
|
|
67
|
-
hint: "Railway / Render / Fly.io — Docker, $5-20/mo",
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
value: "enterprise",
|
|
71
|
-
label: "Enterprise",
|
|
72
|
-
hint: "AWS CDK — auto-provision Lambda + RDS + CloudFront",
|
|
73
|
-
},
|
|
74
|
-
],
|
|
75
|
-
});
|
|
76
|
-
if (p.isCancel(tierChoice)) {
|
|
77
|
-
p.cancel("Setup cancelled.");
|
|
78
|
-
process.exit(0);
|
|
79
|
-
}
|
|
80
|
-
const tier = tierChoice;
|
|
81
|
-
// Step 3: Choose AI provider
|
|
82
|
-
const providerChoice = await p.select({
|
|
83
|
-
message: "Choose your AI provider:",
|
|
84
|
-
options: [
|
|
85
|
-
{
|
|
86
|
-
value: "anthropic",
|
|
87
|
-
label: "Anthropic (Claude)",
|
|
88
|
-
hint: "recommended — also powers the Orchestrator",
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
value: "openai",
|
|
92
|
-
label: "OpenAI (GPT)",
|
|
93
|
-
hint: "uses gpt-4.1 for generation",
|
|
94
|
-
},
|
|
95
|
-
],
|
|
96
|
-
});
|
|
97
|
-
if (p.isCancel(providerChoice)) {
|
|
98
|
-
p.cancel("Setup cancelled.");
|
|
99
|
-
process.exit(0);
|
|
100
|
-
}
|
|
101
|
-
const provider = providerChoice;
|
|
102
|
-
// Step 4: Get API key
|
|
103
|
-
const envKey = provider === "anthropic"
|
|
104
|
-
? process.env.ANTHROPIC_API_KEY
|
|
105
|
-
: process.env.OPENAI_API_KEY;
|
|
106
|
-
const envName = provider === "anthropic" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
|
|
107
|
-
const keyPrefix = provider === "anthropic" ? "sk-ant-" : "sk-";
|
|
108
|
-
const keyPlaceholder = provider === "anthropic" ? "sk-ant-..." : "sk-...";
|
|
109
|
-
let apiKey = envKey || "";
|
|
110
|
-
if (!apiKey) {
|
|
111
|
-
const keyInput = await p.text({
|
|
112
|
-
message: `Your ${provider === "anthropic" ? "Anthropic" : "OpenAI"} API key:`,
|
|
113
|
-
placeholder: keyPlaceholder,
|
|
114
|
-
validate: (v) => !v || !v.startsWith(keyPrefix)
|
|
115
|
-
? `Please enter a valid key (starts with ${keyPrefix})`
|
|
116
|
-
: undefined,
|
|
117
|
-
});
|
|
118
|
-
if (p.isCancel(keyInput)) {
|
|
119
|
-
p.cancel("Setup cancelled.");
|
|
120
|
-
process.exit(0);
|
|
121
|
-
}
|
|
122
|
-
apiKey = keyInput;
|
|
123
|
-
process.env[envName] = apiKey;
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
p.log.info(chalk.dim(`Using ${envName} from environment.`));
|
|
127
|
-
}
|
|
128
|
-
// Orchestrator always needs Anthropic
|
|
129
|
-
let anthropicKey = "";
|
|
130
|
-
if (provider === "anthropic") {
|
|
131
|
-
anthropicKey = apiKey;
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
const existingKey = process.env.ANTHROPIC_API_KEY || "";
|
|
135
|
-
if (existingKey) {
|
|
136
|
-
anthropicKey = existingKey;
|
|
137
|
-
p.log.info(chalk.dim("Using ANTHROPIC_API_KEY for Orchestrator."));
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
p.log.info(chalk.dim("The Orchestrator requires an Anthropic API key (Claude tool use)."));
|
|
141
|
-
const orchKeyInput = await p.text({
|
|
142
|
-
message: "Anthropic API key for Orchestrator:",
|
|
143
|
-
placeholder: "sk-ant-...",
|
|
144
|
-
validate: (v) => !v || !v.startsWith("sk-ant-")
|
|
145
|
-
? "Please enter a valid Anthropic key (starts with sk-ant-)"
|
|
146
|
-
: undefined,
|
|
147
|
-
});
|
|
148
|
-
if (p.isCancel(orchKeyInput)) {
|
|
149
|
-
p.cancel("Setup cancelled.");
|
|
150
|
-
process.exit(0);
|
|
151
|
-
}
|
|
152
|
-
anthropicKey = orchKeyInput;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
// Step 5: Generate agents + site content
|
|
156
|
-
const s = p.spinner();
|
|
157
|
-
s.start("Generating your AI team and website...");
|
|
158
|
-
let agents;
|
|
159
|
-
try {
|
|
160
|
-
agents = await generateAgents(company.name, company.description, provider);
|
|
161
|
-
s.stop("Your AI team is ready!");
|
|
162
|
-
}
|
|
163
|
-
catch (err) {
|
|
164
|
-
s.stop("Failed to generate agents.");
|
|
165
|
-
p.log.error(err instanceof Error ? err.message : "Check your API key");
|
|
166
|
-
p.cancel("Setup failed.");
|
|
167
|
-
process.exit(1);
|
|
168
|
-
}
|
|
169
|
-
// Step 6: Show agents + site preview
|
|
170
|
-
p.log.info(chalk.bold("Meet your team:"));
|
|
171
|
-
console.log();
|
|
172
|
-
for (const agent of agents.agents) {
|
|
173
|
-
console.log(` ${chalk.hex("#8b5cf6").bold(agent.name)} ${chalk.dim(`(${agent.role})`)}`);
|
|
174
|
-
console.log(` ${chalk.dim(agent.description)}`);
|
|
175
|
-
console.log();
|
|
176
|
-
}
|
|
177
|
-
if (agents.site && mode === "new") {
|
|
178
|
-
p.log.info(chalk.bold("Your website:"));
|
|
179
|
-
console.log(` ${chalk.hex("#f59e0b")(agents.site.tagline)}`);
|
|
180
|
-
console.log(` ${chalk.dim(agents.site.subtitle)}`);
|
|
181
|
-
console.log();
|
|
182
|
-
}
|
|
183
|
-
const confirm = await p.confirm({
|
|
184
|
-
message: "Looks good?",
|
|
185
|
-
initialValue: true,
|
|
186
|
-
});
|
|
187
|
-
if (p.isCancel(confirm) || !confirm) {
|
|
188
|
-
p.cancel("Setup cancelled.");
|
|
189
|
-
process.exit(0);
|
|
190
|
-
}
|
|
191
|
-
// Step 7a: Connect mode — website URL for KB
|
|
192
|
-
let websiteUrl = "";
|
|
193
|
-
if (mode === "connect") {
|
|
194
|
-
const urlInput = await p.text({
|
|
195
|
-
message: "Your existing website URL (for Knowledge Base crawling):",
|
|
196
|
-
placeholder: "https://my-business.com",
|
|
197
|
-
});
|
|
198
|
-
if (!p.isCancel(urlInput) && urlInput) {
|
|
199
|
-
websiteUrl = urlInput;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
// Step 7b: Infrastructure setup (tier-dependent)
|
|
203
|
-
// For quickstart: we'll collect Supabase info now, but may override
|
|
204
|
-
// with automated setup after scaffolding
|
|
205
|
-
let supabaseUrl = "";
|
|
206
|
-
let supabaseKey = "";
|
|
207
|
-
let useAutomatedSupabase = false;
|
|
208
|
-
if (tier === "quickstart") {
|
|
209
|
-
// We'll handle Supabase setup after scaffold for CLI automation
|
|
210
|
-
// For now, just mark that we need it
|
|
211
|
-
useAutomatedSupabase = true;
|
|
212
|
-
}
|
|
213
|
-
else if (tier === "cloud") {
|
|
214
|
-
p.log.info(chalk.dim("Cloud mode: PostgreSQL runs in Docker. No Supabase needed."));
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
p.log.info(`${chalk.bold("AWS Enterprise setup")}\n` +
|
|
218
|
-
` ${chalk.dim("Requires:")} AWS CLI configured + CDK bootstrapped\n` +
|
|
219
|
-
` ${chalk.dim("Cost:")} ~$5-15/mo (Lambda + RDS free tier)`);
|
|
220
|
-
}
|
|
221
|
-
// Step 8: Scaffold project
|
|
222
|
-
s.start("Creating your project...");
|
|
223
|
-
const slug = company.name
|
|
224
|
-
.toLowerCase()
|
|
225
|
-
.replace(/[^a-z0-9]+/g, "-")
|
|
226
|
-
.replace(/^-|-$/g, "");
|
|
227
|
-
try {
|
|
228
|
-
const projectDir = await scaffoldProject({
|
|
229
|
-
company: {
|
|
230
|
-
name: company.name,
|
|
231
|
-
description: company.description,
|
|
232
|
-
industry: agents.industry,
|
|
233
|
-
},
|
|
234
|
-
agents: agents.agents,
|
|
235
|
-
site: agents.site,
|
|
236
|
-
provider,
|
|
237
|
-
tier,
|
|
238
|
-
mode,
|
|
239
|
-
websiteUrl,
|
|
240
|
-
infra: {
|
|
241
|
-
anthropicKey,
|
|
242
|
-
openaiKey: provider === "openai" ? apiKey : undefined,
|
|
243
|
-
supabaseUrl: supabaseUrl || "PLACEHOLDER",
|
|
244
|
-
supabaseKey: supabaseKey || "PLACEHOLDER",
|
|
245
|
-
},
|
|
246
|
-
});
|
|
247
|
-
s.stop("Project created!");
|
|
248
|
-
// ─────────────────────────────────────────────────────────
|
|
249
|
-
// Post-scaffold automation
|
|
250
|
-
// ─────────────────────────────────────────────────────────
|
|
251
|
-
// Step 9: Supabase setup (quickstart only)
|
|
252
|
-
if (tier === "quickstart" && useAutomatedSupabase) {
|
|
253
|
-
const result = await setupSupabase(projectDir);
|
|
254
|
-
if (result.method === "local" && result.credentials) {
|
|
255
|
-
// Auto-detected credentials from local Supabase
|
|
256
|
-
supabaseUrl = result.credentials.url;
|
|
257
|
-
supabaseKey = result.credentials.anonKey;
|
|
258
|
-
// Rewrite .env.local with real credentials
|
|
259
|
-
const { writeEnvFile } = await import("./setup/env.js");
|
|
260
|
-
await writeEnvFile(projectDir, {
|
|
261
|
-
anthropicKey,
|
|
262
|
-
openaiKey: provider === "openai" ? apiKey : undefined,
|
|
263
|
-
supabaseUrl,
|
|
264
|
-
supabaseKey,
|
|
265
|
-
serviceRoleKey: result.credentials.serviceRoleKey,
|
|
266
|
-
});
|
|
267
|
-
p.log.success(chalk.green("Supabase configured automatically!") +
|
|
268
|
-
chalk.dim(` → ${supabaseUrl}`));
|
|
269
|
-
}
|
|
270
|
-
else if (result.method === "remote") {
|
|
271
|
-
// Remote linked — user needs to provide URL/key for .env
|
|
272
|
-
p.log.info(chalk.dim("Project linked. Get your URL and key from Settings → API."));
|
|
273
|
-
const supabase = await p.group({
|
|
274
|
-
url: () => p.text({
|
|
275
|
-
message: "Your Supabase project URL:",
|
|
276
|
-
placeholder: "https://xxx.supabase.co",
|
|
277
|
-
validate: (v) => !v || !v.includes("supabase")
|
|
278
|
-
? "Please enter a valid Supabase URL"
|
|
279
|
-
: undefined,
|
|
280
|
-
}),
|
|
281
|
-
key: () => p.text({
|
|
282
|
-
message: "Your Supabase publishable key (anon/public):",
|
|
283
|
-
placeholder: "sb_publishable_...",
|
|
284
|
-
validate: (v) => (!v ? "Key is required" : undefined),
|
|
285
|
-
}),
|
|
286
|
-
}, {
|
|
287
|
-
onCancel: () => {
|
|
288
|
-
p.cancel("Setup cancelled.");
|
|
289
|
-
process.exit(0);
|
|
290
|
-
},
|
|
291
|
-
});
|
|
292
|
-
supabaseUrl = supabase.url;
|
|
293
|
-
supabaseKey = supabase.key;
|
|
294
|
-
const { writeEnvFile } = await import("./setup/env.js");
|
|
295
|
-
await writeEnvFile(projectDir, {
|
|
296
|
-
anthropicKey,
|
|
297
|
-
openaiKey: provider === "openai" ? apiKey : undefined,
|
|
298
|
-
supabaseUrl,
|
|
299
|
-
supabaseKey,
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
else {
|
|
303
|
-
// Manual fallback — same as before
|
|
304
|
-
p.log.info(`${chalk.bold("Supabase setup")} ${chalk.dim("(free tier works fine)")}\n` +
|
|
305
|
-
` ${chalk.dim("1.")} Create a project at ${chalk.cyan("https://supabase.com/dashboard/new")}\n` +
|
|
306
|
-
` ${chalk.dim("2.")} Go to Settings → API to find your URL and keys`);
|
|
307
|
-
const supabase = await p.group({
|
|
308
|
-
url: () => p.text({
|
|
309
|
-
message: "Your Supabase project URL:",
|
|
310
|
-
placeholder: "https://xxx.supabase.co",
|
|
311
|
-
validate: (v) => !v || !v.includes("supabase")
|
|
312
|
-
? "Please enter a valid Supabase URL"
|
|
313
|
-
: undefined,
|
|
314
|
-
}),
|
|
315
|
-
key: () => p.text({
|
|
316
|
-
message: "Your Supabase publishable key (anon/public):",
|
|
317
|
-
placeholder: "sb_publishable_...",
|
|
318
|
-
validate: (v) => (!v ? "Key is required" : undefined),
|
|
319
|
-
}),
|
|
320
|
-
}, {
|
|
321
|
-
onCancel: () => {
|
|
322
|
-
p.cancel("Setup cancelled.");
|
|
323
|
-
process.exit(0);
|
|
324
|
-
},
|
|
325
|
-
});
|
|
326
|
-
supabaseUrl = supabase.url;
|
|
327
|
-
supabaseKey = supabase.key;
|
|
328
|
-
const { writeEnvFile } = await import("./setup/env.js");
|
|
329
|
-
await writeEnvFile(projectDir, {
|
|
330
|
-
anthropicKey,
|
|
331
|
-
openaiKey: provider === "openai" ? apiKey : undefined,
|
|
332
|
-
supabaseUrl,
|
|
333
|
-
supabaseKey,
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
// Step 10: Install dependencies
|
|
338
|
-
const installConfirm = await p.confirm({
|
|
339
|
-
message: "Install dependencies now? (npm install)",
|
|
340
|
-
initialValue: true,
|
|
341
|
-
});
|
|
342
|
-
if (!p.isCancel(installConfirm) && installConfirm) {
|
|
343
|
-
await installDependencies(projectDir);
|
|
344
|
-
}
|
|
345
|
-
// ─────────────────────────────────────────────────────────
|
|
346
|
-
// Final output
|
|
347
|
-
// ─────────────────────────────────────────────────────────
|
|
348
|
-
const widgetSnippet = mode === "connect"
|
|
349
|
-
? [
|
|
350
|
-
``,
|
|
351
|
-
`${chalk.bold("Embed in your existing site:")}`,
|
|
352
|
-
`${chalk.cyan('<script src="https://YOUR_URL/widget.js"')}`,
|
|
353
|
-
`${chalk.cyan(' data-agent="' + agents.agents[0].id + '"')}`,
|
|
354
|
-
`${chalk.cyan(' data-api="https://YOUR_URL"></script>')}`,
|
|
355
|
-
]
|
|
356
|
-
: [];
|
|
357
|
-
const didInstall = !p.isCancel(installConfirm) && installConfirm === true;
|
|
358
|
-
const devCmd = didInstall ? "npm run dev" : "npm install && npm run dev";
|
|
359
|
-
if (tier === "quickstart") {
|
|
360
|
-
p.note([
|
|
361
|
-
`cd ${slug}`,
|
|
362
|
-
`${devCmd} ${chalk.dim("→ http://localhost:3000")}`,
|
|
363
|
-
``,
|
|
364
|
-
`Dashboard: ${chalk.dim("/dashboard")}`,
|
|
365
|
-
`Orchestrator: ${chalk.dim("floating button in dashboard")}`,
|
|
366
|
-
`Agents: ${chalk.dim(`${agents.agents.length} active`)}`,
|
|
367
|
-
...widgetSnippet,
|
|
368
|
-
].join("\n"), mode === "connect" ? "Your AI agents are ready" : "Your AI company is ready");
|
|
369
|
-
p.outro(`Deploy: ${chalk.cyan("vercel deploy")}`);
|
|
370
|
-
}
|
|
371
|
-
else if (tier === "cloud") {
|
|
372
|
-
p.note([
|
|
373
|
-
`cd ${slug}`,
|
|
374
|
-
``,
|
|
375
|
-
`${chalk.bold("Local development:")}`,
|
|
376
|
-
`docker compose up ${chalk.dim("→ http://localhost:3000")}`,
|
|
377
|
-
``,
|
|
378
|
-
`${chalk.bold("Deploy to Railway:")}`,
|
|
379
|
-
`railway login`,
|
|
380
|
-
`railway init`,
|
|
381
|
-
`railway add --plugin postgresql`,
|
|
382
|
-
`railway up`,
|
|
383
|
-
``,
|
|
384
|
-
`Dashboard: ${chalk.dim("/dashboard")}`,
|
|
385
|
-
`Orchestrator: ${chalk.dim("floating button in dashboard")}`,
|
|
386
|
-
`Agents: ${chalk.dim(`${agents.agents.length} active`)}`,
|
|
387
|
-
].join("\n"), "Your AI company is ready");
|
|
388
|
-
p.outro(`Or deploy to ${chalk.cyan("Render")}, ${chalk.cyan("Fly.io")}, or any Docker host`);
|
|
389
|
-
}
|
|
390
|
-
else {
|
|
391
|
-
p.note([
|
|
392
|
-
`cd ${slug}`,
|
|
393
|
-
``,
|
|
394
|
-
`${chalk.bold("Local development:")}`,
|
|
395
|
-
`docker compose up ${chalk.dim("→ http://localhost:3000")}`,
|
|
396
|
-
``,
|
|
397
|
-
`${chalk.bold("Deploy to AWS:")}`,
|
|
398
|
-
`cd infra`,
|
|
399
|
-
`npm install`,
|
|
400
|
-
`npx cdk bootstrap ${chalk.dim("(first time only)")}`,
|
|
401
|
-
`npx cdk deploy ${chalk.dim("→ CloudFront URL in output")}`,
|
|
402
|
-
``,
|
|
403
|
-
`${chalk.bold("Update API keys:")}`,
|
|
404
|
-
`aws secretsmanager put-secret-value \\`,
|
|
405
|
-
` --secret-id ${slug}/api-keys \\`,
|
|
406
|
-
` --secret-string '{"ANTHROPIC_API_KEY":"sk-ant-..."}'`,
|
|
407
|
-
``,
|
|
408
|
-
`Dashboard: ${chalk.dim("/dashboard")}`,
|
|
409
|
-
`Orchestrator: ${chalk.dim("floating button in dashboard")}`,
|
|
410
|
-
`Agents: ${chalk.dim(`${agents.agents.length} active`)}`,
|
|
411
|
-
`Est. cost: ${chalk.dim("$5-15/mo")}`,
|
|
412
|
-
].join("\n"), "Your AI company is ready (AWS)");
|
|
413
|
-
p.outro(`Run ${chalk.cyan("cd infra && npx cdk deploy")} to provision AWS infrastructure`);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
catch (err) {
|
|
417
|
-
s.stop("Failed to create project.");
|
|
418
|
-
p.log.error(err instanceof Error ? err.message : String(err));
|
|
419
|
-
process.exit(1);
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
main().catch(console.error);
|
|
2
|
+
// Entry point for both `npx @tellet/create` and `tellet <command>`
|
|
3
|
+
// Delegates to cli.ts which handles routing.
|
|
4
|
+
import { run } from "./cli.js";
|
|
5
|
+
const args = process.argv.slice(2);
|
|
6
|
+
run(args).catch((err) => {
|
|
7
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
8
|
+
process.exit(1);
|
|
9
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function startMcpServer(): Promise<void>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import fs from "fs-extra";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { registerTools } from "./tools.js";
|
|
7
|
+
async function getVersion() {
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const pkg = await fs.readJSON(path.resolve(__dirname, "..", "..", "package.json"));
|
|
10
|
+
return pkg.version;
|
|
11
|
+
}
|
|
12
|
+
export async function startMcpServer() {
|
|
13
|
+
const version = await getVersion();
|
|
14
|
+
const server = new McpServer({
|
|
15
|
+
name: "tellet",
|
|
16
|
+
version,
|
|
17
|
+
}, {
|
|
18
|
+
instructions: "Tellet MCP server — manage AI agent projects. " +
|
|
19
|
+
"Use these tools inside a tellet project directory (one containing tellet.json). " +
|
|
20
|
+
"Tools: project_status, agent_list, agent_add, agent_remove, config_read, dev_start, deploy_info.",
|
|
21
|
+
});
|
|
22
|
+
registerTools(server);
|
|
23
|
+
const transport = new StdioServerTransport();
|
|
24
|
+
await server.connect(transport);
|
|
25
|
+
}
|