@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/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Tell it. Let it.
|
|
2
2
|
|
|
3
|
-
> AI agents that run your business —
|
|
3
|
+
> AI agents that run your business — create, manage, and deploy. One CLI.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npx @tellet/create
|
|
@@ -12,6 +12,56 @@ Or start instantly at [tellet.com](https://tellet.com) — no setup required.
|
|
|
12
12
|
|
|
13
13
|
tellet generates an AI agent team for your business. Agents don't just chat — they send emails, delegate tasks to each other, run scheduled automations, and serve customers through an embeddable widget.
|
|
14
14
|
|
|
15
|
+
## CLI commands
|
|
16
|
+
|
|
17
|
+
After creating a project, manage it with the `tellet` CLI:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Install globally (optional — or use npx @tellet/create <command>)
|
|
21
|
+
npm i -g @tellet/create
|
|
22
|
+
|
|
23
|
+
# Inside your tellet project:
|
|
24
|
+
tellet dev # Start dev server
|
|
25
|
+
tellet build # Build for production
|
|
26
|
+
tellet status # Show project info
|
|
27
|
+
tellet agent list # List all agents
|
|
28
|
+
tellet agent add # Add a new agent interactively
|
|
29
|
+
tellet agent remove # Remove an agent
|
|
30
|
+
tellet deploy # Guided deployment (Vercel, Railway, Docker, AWS)
|
|
31
|
+
tellet mcp # Start MCP server (for Claude Code / Cursor)
|
|
32
|
+
tellet help # Show all commands
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## MCP Server (Claude Code / Cursor / Codex)
|
|
36
|
+
|
|
37
|
+
Use tellet from Claude Code, Cursor, or any MCP-compatible AI tool:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"mcpServers": {
|
|
42
|
+
"tellet": {
|
|
43
|
+
"command": "npx",
|
|
44
|
+
"args": ["@tellet/create", "mcp"],
|
|
45
|
+
"cwd": "/path/to/your-tellet-project"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Available MCP tools:
|
|
52
|
+
|
|
53
|
+
| Tool | Description |
|
|
54
|
+
|------|-------------|
|
|
55
|
+
| `project_status` | Company info, agents, channels, environment health |
|
|
56
|
+
| `agent_list` | List all agents with details |
|
|
57
|
+
| `agent_add` | Add a new agent (name, role, description) |
|
|
58
|
+
| `agent_remove` | Remove an agent by ID |
|
|
59
|
+
| `config_read` | Read full tellet.json |
|
|
60
|
+
| `dev_start` | Start Next.js dev server |
|
|
61
|
+
| `deploy_info` | Show deployment options |
|
|
62
|
+
|
|
63
|
+
Then just ask your AI: *"Add a marketing agent called Nova"* or *"Show me the project status"*.
|
|
64
|
+
|
|
15
65
|
## What agents can do
|
|
16
66
|
|
|
17
67
|
- **Email customers** — Send follow-ups, confirmations, and outreach via Resend
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
const COMMANDS = {
|
|
4
|
+
dev: { description: "Start development server", module: "./commands/dev.js" },
|
|
5
|
+
build: { description: "Build for production", module: "./commands/build.js" },
|
|
6
|
+
status: { description: "Show project status", module: "./commands/status.js" },
|
|
7
|
+
agent: { description: "Manage agents (list, add, remove)", module: "./commands/agent.js" },
|
|
8
|
+
deploy: { description: "Deploy your project", module: "./commands/deploy.js" },
|
|
9
|
+
mcp: { description: "Start MCP server (for Claude Code / Cursor)", module: "./commands/mcp.js" },
|
|
10
|
+
};
|
|
11
|
+
function printBanner() {
|
|
12
|
+
console.log();
|
|
13
|
+
console.log(chalk.bold(` ${chalk.white("tel")}${chalk.yellow("let")} ${chalk.dim("CLI")}`));
|
|
14
|
+
console.log();
|
|
15
|
+
}
|
|
16
|
+
function printHelp() {
|
|
17
|
+
printBanner();
|
|
18
|
+
console.log(chalk.bold(" Usage:"));
|
|
19
|
+
console.log(` ${chalk.cyan("tellet")} ${chalk.dim("<command>")}`);
|
|
20
|
+
console.log(` ${chalk.cyan("npx @tellet/create")} ${chalk.dim("<command>")}`);
|
|
21
|
+
console.log();
|
|
22
|
+
console.log(chalk.bold(" Commands:"));
|
|
23
|
+
const padLen = Math.max(...Object.keys(COMMANDS).map((k) => k.length)) + 2;
|
|
24
|
+
for (const [name, cmd] of Object.entries(COMMANDS)) {
|
|
25
|
+
console.log(` ${chalk.cyan(name.padEnd(padLen))} ${chalk.dim(cmd.description)}`);
|
|
26
|
+
}
|
|
27
|
+
console.log();
|
|
28
|
+
console.log(` ${chalk.cyan("(no command)".padEnd(padLen))} ${chalk.dim("Create a new tellet project")}`);
|
|
29
|
+
console.log();
|
|
30
|
+
console.log(chalk.dim(" Run tellet <command> --help for command-specific help."));
|
|
31
|
+
console.log();
|
|
32
|
+
}
|
|
33
|
+
export async function run(args) {
|
|
34
|
+
const command = args[0];
|
|
35
|
+
// No command or help → check if we should scaffold or show help
|
|
36
|
+
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
37
|
+
// If no command and no tellet.json in CWD, run scaffold
|
|
38
|
+
if (!command) {
|
|
39
|
+
const { main: scaffold } = await import("./scaffold-flow.js");
|
|
40
|
+
return scaffold();
|
|
41
|
+
}
|
|
42
|
+
printHelp();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const cmd = COMMANDS[command];
|
|
46
|
+
if (!cmd) {
|
|
47
|
+
console.error(chalk.red(` Unknown command: ${command}`));
|
|
48
|
+
console.log(chalk.dim(` Run ${chalk.cyan("tellet help")} to see available commands.`));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
const subArgs = args.slice(1);
|
|
52
|
+
const mod = await import(cmd.module);
|
|
53
|
+
await mod.default(subArgs);
|
|
54
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function agent(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import fs from "fs-extra";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { loadConfigOrExit, saveConfig, nameToId, generateAgentFile, updateAgentRegistry, } from "./shared.js";
|
|
6
|
+
const VALID_ROLES = [
|
|
7
|
+
"customer_support",
|
|
8
|
+
"sales",
|
|
9
|
+
"marketing",
|
|
10
|
+
"operations",
|
|
11
|
+
"analytics",
|
|
12
|
+
"development",
|
|
13
|
+
];
|
|
14
|
+
export default async function agent(args) {
|
|
15
|
+
const sub = args[0];
|
|
16
|
+
switch (sub) {
|
|
17
|
+
case "list":
|
|
18
|
+
case "ls":
|
|
19
|
+
return agentList();
|
|
20
|
+
case "add":
|
|
21
|
+
return agentAdd();
|
|
22
|
+
case "remove":
|
|
23
|
+
case "rm":
|
|
24
|
+
return agentRemove(args.slice(1));
|
|
25
|
+
default:
|
|
26
|
+
console.log();
|
|
27
|
+
console.log(chalk.bold(" Usage:"));
|
|
28
|
+
console.log(` tellet agent list ${chalk.dim("List all agents")}`);
|
|
29
|
+
console.log(` tellet agent add ${chalk.dim("Add a new agent")}`);
|
|
30
|
+
console.log(` tellet agent remove ${chalk.dim("Remove an agent")}`);
|
|
31
|
+
console.log();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function agentList() {
|
|
35
|
+
const config = await loadConfigOrExit();
|
|
36
|
+
console.log();
|
|
37
|
+
console.log(chalk.bold(` Agents (${config.agents.length})`));
|
|
38
|
+
console.log();
|
|
39
|
+
for (const agent of config.agents) {
|
|
40
|
+
const channels = agent.channels.join(", ");
|
|
41
|
+
const tools = agent.tools.length > 0 ? agent.tools.join(", ") : chalk.dim("none");
|
|
42
|
+
console.log(` ${chalk.hex("#8b5cf6").bold(agent.name)}`);
|
|
43
|
+
console.log(` ID: ${chalk.dim(agent.id)}`);
|
|
44
|
+
console.log(` Role: ${chalk.dim(agent.role)}`);
|
|
45
|
+
console.log(` Model: ${chalk.dim(agent.model)}`);
|
|
46
|
+
console.log(` Channels: ${chalk.dim(channels)}`);
|
|
47
|
+
console.log(` Tools: ${tools}`);
|
|
48
|
+
console.log();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function agentAdd() {
|
|
52
|
+
const config = await loadConfigOrExit();
|
|
53
|
+
console.log();
|
|
54
|
+
p.intro(chalk.bgHex("#8b5cf6").white(" Add Agent "));
|
|
55
|
+
const info = await p.group({
|
|
56
|
+
name: () => p.text({
|
|
57
|
+
message: "Agent name:",
|
|
58
|
+
placeholder: "Luna",
|
|
59
|
+
validate: (v) => {
|
|
60
|
+
if (!v)
|
|
61
|
+
return "Name is required";
|
|
62
|
+
const id = nameToId(v);
|
|
63
|
+
if (!id)
|
|
64
|
+
return "Name must contain at least one letter or number";
|
|
65
|
+
return undefined;
|
|
66
|
+
},
|
|
67
|
+
}),
|
|
68
|
+
role: () => p.select({
|
|
69
|
+
message: "Role:",
|
|
70
|
+
options: VALID_ROLES.map((r) => ({ value: r, label: r.replace(/_/g, " ") })),
|
|
71
|
+
}),
|
|
72
|
+
description: () => p.text({
|
|
73
|
+
message: "What does this agent do?",
|
|
74
|
+
placeholder: "Handles billing inquiries and payment processing",
|
|
75
|
+
validate: (v) => (!v ? "Description is required" : undefined),
|
|
76
|
+
}),
|
|
77
|
+
}, {
|
|
78
|
+
onCancel: () => {
|
|
79
|
+
p.cancel("Cancelled.");
|
|
80
|
+
process.exit(0);
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
const name = info.name;
|
|
84
|
+
const role = info.role;
|
|
85
|
+
const description = info.description;
|
|
86
|
+
const id = nameToId(name);
|
|
87
|
+
if (config.agents.some((a) => a.id === id)) {
|
|
88
|
+
p.log.error(`Agent with ID "${id}" already exists.`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
const model = config.llm.defaultModel;
|
|
92
|
+
const systemPrompt = `You are ${name}, the ${role.replace(/_/g, " ")} agent for ${config.company.name}. ${description}`;
|
|
93
|
+
config.agents.push({
|
|
94
|
+
id,
|
|
95
|
+
name,
|
|
96
|
+
role,
|
|
97
|
+
model,
|
|
98
|
+
channels: ["web_chat"],
|
|
99
|
+
tools: role === "customer_support" ? ["search_knowledge"] : [],
|
|
100
|
+
});
|
|
101
|
+
await saveConfig(config);
|
|
102
|
+
const agentsDir = path.resolve(process.cwd(), "agents");
|
|
103
|
+
await fs.mkdirp(agentsDir);
|
|
104
|
+
await fs.writeFile(path.join(agentsDir, `${id}.ts`), generateAgentFile({ id, name, role, model, systemPrompt }));
|
|
105
|
+
await updateAgentRegistry(config);
|
|
106
|
+
p.log.success(`Added ${chalk.bold(name)} (${role})`);
|
|
107
|
+
p.outro(chalk.dim(`Agent file: agents/${id}.ts`));
|
|
108
|
+
}
|
|
109
|
+
async function agentRemove(args) {
|
|
110
|
+
const config = await loadConfigOrExit();
|
|
111
|
+
const force = args.includes("--yes") || args.includes("-y");
|
|
112
|
+
const idArg = args.find((a) => !a.startsWith("-"));
|
|
113
|
+
if (config.agents.length === 0) {
|
|
114
|
+
p.log.error("No agents to remove.");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
let targetId = idArg;
|
|
118
|
+
if (!targetId) {
|
|
119
|
+
console.log();
|
|
120
|
+
const choice = await p.select({
|
|
121
|
+
message: "Which agent to remove?",
|
|
122
|
+
options: config.agents.map((a) => ({
|
|
123
|
+
value: a.id,
|
|
124
|
+
label: `${a.name} (${a.role})`,
|
|
125
|
+
})),
|
|
126
|
+
});
|
|
127
|
+
if (p.isCancel(choice)) {
|
|
128
|
+
p.cancel("Cancelled.");
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
targetId = choice;
|
|
132
|
+
}
|
|
133
|
+
const agent = config.agents.find((a) => a.id === targetId);
|
|
134
|
+
if (!agent) {
|
|
135
|
+
p.log.error(`Agent "${targetId}" not found.`);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
if (!force) {
|
|
139
|
+
const confirm = await p.confirm({
|
|
140
|
+
message: `Remove ${agent.name} (${agent.role})?`,
|
|
141
|
+
initialValue: false,
|
|
142
|
+
});
|
|
143
|
+
if (p.isCancel(confirm) || !confirm) {
|
|
144
|
+
p.cancel("Cancelled.");
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
config.agents = config.agents.filter((a) => a.id !== targetId);
|
|
149
|
+
await saveConfig(config);
|
|
150
|
+
const agentPath = path.resolve(process.cwd(), "agents", `${targetId}.ts`);
|
|
151
|
+
if (await fs.pathExists(agentPath)) {
|
|
152
|
+
await fs.remove(agentPath);
|
|
153
|
+
}
|
|
154
|
+
await updateAgentRegistry(config);
|
|
155
|
+
p.log.success(`Removed ${chalk.bold(agent.name)}`);
|
|
156
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function build(_args: string[]): Promise<void>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { spawnSync } from "child_process";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { loadConfigOrExit } from "./shared.js";
|
|
4
|
+
export default async function build(_args) {
|
|
5
|
+
const config = await loadConfigOrExit();
|
|
6
|
+
console.log();
|
|
7
|
+
console.log(chalk.bold(` ${chalk.white("tel")}${chalk.yellow("let")} ${chalk.dim("build")} — ${config.company.name}`));
|
|
8
|
+
console.log();
|
|
9
|
+
const result = spawnSync("npx", ["next", "build"], {
|
|
10
|
+
cwd: process.cwd(),
|
|
11
|
+
stdio: "inherit",
|
|
12
|
+
});
|
|
13
|
+
process.exit(result.status ?? 1);
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function deploy(_args: string[]): Promise<void>;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { spawnSync } from "child_process";
|
|
2
|
+
import * as p from "@clack/prompts";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { loadConfigOrExit } from "./shared.js";
|
|
5
|
+
export default async function deploy(_args) {
|
|
6
|
+
const config = await loadConfigOrExit();
|
|
7
|
+
console.log();
|
|
8
|
+
console.log(chalk.bold(` ${chalk.white("tel")}${chalk.yellow("let")} ${chalk.dim("deploy")} — ${config.company.name}`));
|
|
9
|
+
console.log();
|
|
10
|
+
// Detect tier from project structure
|
|
11
|
+
const fs = await import("fs-extra");
|
|
12
|
+
const path = await import("path");
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
const hasInfra = await fs.default.pathExists(path.default.join(cwd, "infra"));
|
|
15
|
+
const hasDockerCompose = await fs.default.pathExists(path.default.join(cwd, "docker-compose.yml"));
|
|
16
|
+
const hasRailwayToml = await fs.default.pathExists(path.default.join(cwd, "railway.toml"));
|
|
17
|
+
const targets = [];
|
|
18
|
+
targets.push({
|
|
19
|
+
value: "vercel",
|
|
20
|
+
label: "Vercel",
|
|
21
|
+
hint: "Recommended for Quick Start — free, instant",
|
|
22
|
+
});
|
|
23
|
+
if (hasRailwayToml || hasDockerCompose) {
|
|
24
|
+
targets.push({
|
|
25
|
+
value: "railway",
|
|
26
|
+
label: "Railway",
|
|
27
|
+
hint: "Docker-based, $5-20/mo",
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (hasDockerCompose) {
|
|
31
|
+
targets.push({
|
|
32
|
+
value: "docker",
|
|
33
|
+
label: "Docker (manual)",
|
|
34
|
+
hint: "Any Docker host — Render, Fly.io, etc.",
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (hasInfra) {
|
|
38
|
+
targets.push({
|
|
39
|
+
value: "aws",
|
|
40
|
+
label: "AWS CDK",
|
|
41
|
+
hint: "Lambda + RDS + CloudFront",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const choice = await p.select({
|
|
45
|
+
message: "Deploy target:",
|
|
46
|
+
options: targets,
|
|
47
|
+
});
|
|
48
|
+
if (p.isCancel(choice)) {
|
|
49
|
+
p.cancel("Cancelled.");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const target = choice;
|
|
53
|
+
switch (target) {
|
|
54
|
+
case "vercel":
|
|
55
|
+
return deployVercel();
|
|
56
|
+
case "railway":
|
|
57
|
+
return deployRailway();
|
|
58
|
+
case "docker":
|
|
59
|
+
return deployDocker();
|
|
60
|
+
case "aws":
|
|
61
|
+
return deployAws(cwd);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function deployVercel() {
|
|
65
|
+
console.log(chalk.dim(" Launching Vercel deploy..."));
|
|
66
|
+
console.log();
|
|
67
|
+
const result = spawnSync("npx", ["vercel"], {
|
|
68
|
+
cwd: process.cwd(),
|
|
69
|
+
stdio: "inherit",
|
|
70
|
+
});
|
|
71
|
+
if (result.status !== 0) {
|
|
72
|
+
console.log();
|
|
73
|
+
console.log(chalk.dim(" If Vercel CLI is not installed:"));
|
|
74
|
+
console.log(chalk.cyan(" npm i -g vercel && vercel"));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function deployRailway() {
|
|
78
|
+
console.log();
|
|
79
|
+
console.log(chalk.bold(" Railway deployment:"));
|
|
80
|
+
console.log();
|
|
81
|
+
console.log(` ${chalk.dim("1.")} ${chalk.cyan("railway login")}`);
|
|
82
|
+
console.log(` ${chalk.dim("2.")} ${chalk.cyan("railway init")}`);
|
|
83
|
+
console.log(` ${chalk.dim("3.")} ${chalk.cyan("railway add --plugin postgresql")}`);
|
|
84
|
+
console.log(` ${chalk.dim("4.")} ${chalk.cyan("railway up")}`);
|
|
85
|
+
console.log();
|
|
86
|
+
console.log(chalk.dim(" Set environment variables in Railway dashboard after deploy."));
|
|
87
|
+
console.log();
|
|
88
|
+
}
|
|
89
|
+
function deployDocker() {
|
|
90
|
+
console.log();
|
|
91
|
+
console.log(chalk.bold(" Docker deployment:"));
|
|
92
|
+
console.log();
|
|
93
|
+
console.log(` ${chalk.dim("Build:")} ${chalk.cyan("docker build -t tellet .")}`);
|
|
94
|
+
console.log(` ${chalk.dim("Run:")} ${chalk.cyan("docker compose up -d")}`);
|
|
95
|
+
console.log();
|
|
96
|
+
console.log(chalk.dim(" Works with Render, Fly.io, DigitalOcean, or any Docker host."));
|
|
97
|
+
console.log();
|
|
98
|
+
console.log(chalk.bold(" Fly.io:"));
|
|
99
|
+
console.log(` ${chalk.cyan(" fly launch && fly deploy")}`);
|
|
100
|
+
console.log();
|
|
101
|
+
console.log(chalk.bold(" Render:"));
|
|
102
|
+
console.log(chalk.dim(" Connect your GitHub repo at render.com → New Web Service → Docker"));
|
|
103
|
+
console.log();
|
|
104
|
+
}
|
|
105
|
+
function deployAws(cwd) {
|
|
106
|
+
console.log();
|
|
107
|
+
console.log(chalk.bold(" AWS CDK deployment:"));
|
|
108
|
+
console.log();
|
|
109
|
+
console.log(` ${chalk.cyan("cd infra")}`);
|
|
110
|
+
console.log(` ${chalk.cyan("npm install")}`);
|
|
111
|
+
console.log(` ${chalk.cyan("npx cdk bootstrap")} ${chalk.dim("(first time only)")}`);
|
|
112
|
+
console.log(` ${chalk.cyan("npx cdk deploy")}`);
|
|
113
|
+
console.log();
|
|
114
|
+
console.log(chalk.dim(" CloudFront URL will be in the output."));
|
|
115
|
+
console.log(chalk.dim(" API keys are stored in AWS Secrets Manager."));
|
|
116
|
+
console.log();
|
|
117
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function dev(_args: string[]): Promise<void>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { spawnSync } from "child_process";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { loadConfigOrExit } from "./shared.js";
|
|
4
|
+
export default async function dev(_args) {
|
|
5
|
+
const config = await loadConfigOrExit();
|
|
6
|
+
console.log();
|
|
7
|
+
console.log(chalk.bold(` ${chalk.white("tel")}${chalk.yellow("let")} ${chalk.dim("dev")} — ${config.company.name}`));
|
|
8
|
+
console.log(chalk.dim(` ${config.agents.length} agents · ${config.llm.provider} · ${config.storage}`));
|
|
9
|
+
console.log();
|
|
10
|
+
const result = spawnSync("npx", ["next", "dev"], {
|
|
11
|
+
cwd: process.cwd(),
|
|
12
|
+
stdio: "inherit",
|
|
13
|
+
});
|
|
14
|
+
process.exit(result.status ?? 1);
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function mcp(_args: string[]): Promise<void>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export interface TelletConfig {
|
|
2
|
+
version: string;
|
|
3
|
+
company: {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
industry: string;
|
|
7
|
+
};
|
|
8
|
+
engine: string;
|
|
9
|
+
llm: {
|
|
10
|
+
provider: string;
|
|
11
|
+
defaultModel: string;
|
|
12
|
+
fallback: string | null;
|
|
13
|
+
};
|
|
14
|
+
agents: {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
role: string;
|
|
18
|
+
model: string;
|
|
19
|
+
channels: string[];
|
|
20
|
+
tools: string[];
|
|
21
|
+
}[];
|
|
22
|
+
tools: Record<string, {
|
|
23
|
+
type: string;
|
|
24
|
+
description: string;
|
|
25
|
+
}>;
|
|
26
|
+
channels: Record<string, {
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
}>;
|
|
29
|
+
mode: string;
|
|
30
|
+
storage: string;
|
|
31
|
+
integrations: string[];
|
|
32
|
+
websiteUrl?: string;
|
|
33
|
+
site?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Load tellet.json from CWD. Throws if not found.
|
|
37
|
+
*/
|
|
38
|
+
export declare function loadConfig(): Promise<TelletConfig>;
|
|
39
|
+
/**
|
|
40
|
+
* Load tellet.json from CWD with pretty error + exit (for CLI commands only).
|
|
41
|
+
*/
|
|
42
|
+
export declare function loadConfigOrExit(): Promise<TelletConfig>;
|
|
43
|
+
/**
|
|
44
|
+
* Save tellet.json back to CWD.
|
|
45
|
+
*/
|
|
46
|
+
export declare function saveConfig(config: TelletConfig): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Normalize a display name to a safe identifier.
|
|
49
|
+
* Returns empty string if input has no alphanumeric characters.
|
|
50
|
+
*/
|
|
51
|
+
export declare function nameToId(name: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* Generate an agent .ts file with properly escaped values.
|
|
54
|
+
*/
|
|
55
|
+
export declare function generateAgentFile(agent: {
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
role: string;
|
|
59
|
+
model: string;
|
|
60
|
+
systemPrompt: string;
|
|
61
|
+
}): string;
|
|
62
|
+
/**
|
|
63
|
+
* Rewrite agents/index.ts registry to match config.
|
|
64
|
+
*/
|
|
65
|
+
export declare function updateAgentRegistry(config: {
|
|
66
|
+
agents: {
|
|
67
|
+
id: string;
|
|
68
|
+
}[];
|
|
69
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
/**
|
|
5
|
+
* Load tellet.json from CWD. Throws if not found.
|
|
6
|
+
*/
|
|
7
|
+
export async function loadConfig() {
|
|
8
|
+
const configPath = path.resolve(process.cwd(), "tellet.json");
|
|
9
|
+
if (!(await fs.pathExists(configPath))) {
|
|
10
|
+
throw new Error("No tellet.json found in current directory.");
|
|
11
|
+
}
|
|
12
|
+
return fs.readJSON(configPath);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Load tellet.json from CWD with pretty error + exit (for CLI commands only).
|
|
16
|
+
*/
|
|
17
|
+
export async function loadConfigOrExit() {
|
|
18
|
+
try {
|
|
19
|
+
return await loadConfig();
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
console.error(chalk.red(" No tellet.json found in current directory.\n") +
|
|
23
|
+
chalk.dim(" Run this command from inside a tellet project, or create one:\n") +
|
|
24
|
+
chalk.cyan(" npx @tellet/create"));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Save tellet.json back to CWD.
|
|
30
|
+
*/
|
|
31
|
+
export async function saveConfig(config) {
|
|
32
|
+
const configPath = path.resolve(process.cwd(), "tellet.json");
|
|
33
|
+
await fs.writeJSON(configPath, config, { spaces: 2 });
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Normalize a display name to a safe identifier.
|
|
37
|
+
* Returns empty string if input has no alphanumeric characters.
|
|
38
|
+
*/
|
|
39
|
+
export function nameToId(name) {
|
|
40
|
+
return name
|
|
41
|
+
.toLowerCase()
|
|
42
|
+
.replace(/[^a-z0-9]+/g, "_")
|
|
43
|
+
.replace(/^_|_$/g, "");
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Generate an agent .ts file with properly escaped values.
|
|
47
|
+
*/
|
|
48
|
+
export function generateAgentFile(agent) {
|
|
49
|
+
return `import { defineAgent } from "@/lib/engine";
|
|
50
|
+
|
|
51
|
+
export default defineAgent({
|
|
52
|
+
id: ${JSON.stringify(agent.id)},
|
|
53
|
+
name: ${JSON.stringify(agent.name)},
|
|
54
|
+
role: ${JSON.stringify(agent.role)},
|
|
55
|
+
model: ${JSON.stringify(agent.model)},
|
|
56
|
+
systemPrompt: ${JSON.stringify(agent.systemPrompt)},
|
|
57
|
+
channels: ["web_chat"],
|
|
58
|
+
tools: [],
|
|
59
|
+
});
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Rewrite agents/index.ts registry to match config.
|
|
64
|
+
*/
|
|
65
|
+
export async function updateAgentRegistry(config) {
|
|
66
|
+
const agentsDir = path.resolve(process.cwd(), "agents");
|
|
67
|
+
const indexPath = path.join(agentsDir, "index.ts");
|
|
68
|
+
const imports = config.agents
|
|
69
|
+
.map((a) => `import ${a.id} from "./${a.id}.js";`)
|
|
70
|
+
.join("\n");
|
|
71
|
+
const exports = config.agents.map((a) => ` ${a.id}`).join(",\n");
|
|
72
|
+
await fs.writeFile(indexPath, `${imports}\n\nexport const agents = {\n${exports},\n};\n`);
|
|
73
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function status(_args: string[]): Promise<void>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { loadConfigOrExit } from "./shared.js";
|
|
5
|
+
export default async function status(_args) {
|
|
6
|
+
const config = await loadConfigOrExit();
|
|
7
|
+
console.log();
|
|
8
|
+
console.log(chalk.bold(` ${chalk.white("tel")}${chalk.yellow("let")} ${chalk.dim("status")}`));
|
|
9
|
+
console.log();
|
|
10
|
+
// Company
|
|
11
|
+
console.log(chalk.bold(" Company"));
|
|
12
|
+
console.log(` Name: ${chalk.white(config.company.name)}`);
|
|
13
|
+
console.log(` Industry: ${chalk.dim(config.company.industry)}`);
|
|
14
|
+
console.log(` Mode: ${chalk.dim(config.mode)}`);
|
|
15
|
+
console.log();
|
|
16
|
+
// LLM
|
|
17
|
+
console.log(chalk.bold(" LLM"));
|
|
18
|
+
console.log(` Provider: ${chalk.white(config.llm.provider)}`);
|
|
19
|
+
console.log(` Model: ${chalk.dim(config.llm.defaultModel)}`);
|
|
20
|
+
console.log();
|
|
21
|
+
// Agents
|
|
22
|
+
console.log(chalk.bold(` Agents (${config.agents.length})`));
|
|
23
|
+
for (const agent of config.agents) {
|
|
24
|
+
const tools = agent.tools.length > 0 ? chalk.dim(` [${agent.tools.join(", ")}]`) : "";
|
|
25
|
+
console.log(` ${chalk.hex("#8b5cf6")(agent.name)} ${chalk.dim(`(${agent.role})`)}${tools}`);
|
|
26
|
+
}
|
|
27
|
+
console.log();
|
|
28
|
+
// Channels
|
|
29
|
+
const enabledChannels = Object.entries(config.channels)
|
|
30
|
+
.filter(([, v]) => v.enabled)
|
|
31
|
+
.map(([k]) => k);
|
|
32
|
+
const disabledChannels = Object.entries(config.channels)
|
|
33
|
+
.filter(([, v]) => !v.enabled)
|
|
34
|
+
.map(([k]) => k);
|
|
35
|
+
console.log(chalk.bold(" Channels"));
|
|
36
|
+
if (enabledChannels.length > 0) {
|
|
37
|
+
console.log(` Enabled: ${chalk.green(enabledChannels.join(", "))}`);
|
|
38
|
+
}
|
|
39
|
+
if (disabledChannels.length > 0) {
|
|
40
|
+
console.log(` Disabled: ${chalk.dim(disabledChannels.join(", "))}`);
|
|
41
|
+
}
|
|
42
|
+
console.log();
|
|
43
|
+
// Environment check
|
|
44
|
+
console.log(chalk.bold(" Environment"));
|
|
45
|
+
const envPath = path.resolve(process.cwd(), ".env.local");
|
|
46
|
+
const envExists = await fs.pathExists(envPath);
|
|
47
|
+
console.log(` .env.local: ${envExists ? chalk.green("found") : chalk.red("missing")}`);
|
|
48
|
+
const nodeModules = await fs.pathExists(path.resolve(process.cwd(), "node_modules"));
|
|
49
|
+
console.log(` node_modules: ${nodeModules ? chalk.green("installed") : chalk.yellow("not installed — run npm install")}`);
|
|
50
|
+
const hasPackageLock = await fs.pathExists(path.resolve(process.cwd(), "package-lock.json"));
|
|
51
|
+
console.log(` lock file: ${hasPackageLock ? chalk.green("found") : chalk.dim("none")}`);
|
|
52
|
+
console.log();
|
|
53
|
+
}
|