Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 11 additions & 13 deletions src/__tests__/bot-commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,35 +49,33 @@ describe("parseCommand", () => {
});

describe("bot messages", () => {
it("createdMessage (ru) has bootstrap and npm run agent only (no preview links yet)", () => {
it("createdMessage (ru) has spawn link and command", () => {
const message = createdMessage(
"ru",
"demo-app",
"npx -y @spawn-dock/create@beta --token pair_demo",
"spawn-dock spawn --token pair_demo",
"spawndock://spawn?token=pair_demo",
);

expect(message).not.toContain("Preview URL:");
expect(message).not.toContain("Telegram Link:");
expect(message).not.toContain("TMA URL:");
expect(message).not.toContain("Ссылки:");
expect(message).not.toContain("Pairing Token:");
expect(message).toContain("1. Запусти bootstrap-команду локально:");
expect(message).toContain("Эту команду можно запускать повторно для этого проекта.");
expect(message).toContain("2. После bootstrap запусти агента и превью одной командой:");
expect(message).toContain("<code>npm run agent</code>");
expect(message).not.toContain("pnpm");
expect(message).toContain("Нажми на ссылку, чтобы открыть рабочее окружение:");
expect(message).toContain("spawndock://spawn?token=pair_demo");
expect(message).toContain("Или запусти команду локально в терминале:");
expect(message).toContain("spawn-dock spawn --token pair_demo");
});

it("createdMessage (en) uses English copy", () => {
const message = createdMessage(
"en",
"demo-app",
"npx -y @spawn-dock/create@beta --token pair_demo",
"spawn-dock spawn --token pair_demo",
"spawndock://spawn?token=pair_demo",
);

expect(message).toContain("Project");
expect(message).toContain("1. Run the bootstrap command locally:");
expect(message).toContain("<code>npm run agent</code>");
expect(message).toContain("Click the link to open the workspace:");
expect(message).toContain("spawndock://spawn?token=pair_demo");
});

it("includes TMA and preview links in launchMessage", () => {
Expand Down
28 changes: 13 additions & 15 deletions src/bot/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function welcomeMessage(locale: BotLocale): string {
"SpawnDock бот готов.",
"",
"Команды:",
"/new &lt;название проекта&gt; — создать TMA и получить bootstrap-команду",
"/new &lt;название проекта&gt; — создать проект и получить ссылку (или команду) для spawn-dock",
"/launch &lt;slug&gt; — получить TMA и preview ссылки проекта",
"/gettoken — показать общий API_TOKEN для MCP и dev tunnel",
"/lang &lt;en|ru&gt; — язык интерфейса",
Expand All @@ -48,7 +48,7 @@ export function welcomeMessage(locale: BotLocale): string {
"SpawnDock bot is ready.",
"",
"Commands:",
"/new &lt;project title&gt; — create a TMA and get the bootstrap command",
"/new &lt;project title&gt; — create a project and get the spawn-dock link (or command)",
"/launch &lt;slug&gt; — get TMA and preview links for the project",
"/gettoken — show shared API_TOKEN for MCP and dev tunnel",
"/lang &lt;en|ru&gt; — interface language",
Expand Down Expand Up @@ -96,28 +96,26 @@ export function launchUsageMessage(locale: BotLocale): string {
return "Use /launch &lt;slug&gt; to get the preview URL and current tunnel status.";
}

export function createdMessage(locale: BotLocale, slug: string, bootstrapCmd: string): string {
export function createdMessage(locale: BotLocale, slug: string, spawnCmd: string, spawnLink: string): string {
if (locale === "ru") {
return [
`Проект <b>${esc(slug)}</b> создан.`,
"",
"1. Запусти bootstrap-команду локально:",
`<code>${esc(bootstrapCmd)}</code>`,
"Эту команду можно запускать повторно для этого проекта.",
"Нажми на ссылку, чтобы открыть рабочее окружение:",
renderLink(spawnLink),
"",
"2. После bootstrap запусти агента и превью одной командой:",
"<code>npm run agent</code>",
"Или запусти команду локально в терминале:",
`<code>${esc(spawnCmd)}</code>`
].join("\n");
}
return [
`Project <b>${esc(slug)}</b> created.`,
"",
"1. Run the bootstrap command locally:",
`<code>${esc(bootstrapCmd)}</code>`,
"You can run this command again for this project.",
"Click the link to open the workspace:",
renderLink(spawnLink),
"",
"2. After bootstrap, start the agent and preview with one command:",
"<code>npm run agent</code>",
"Or run this command locally in your terminal:",
`<code>${esc(spawnCmd)}</code>`
].join("\n");
}

Expand Down Expand Up @@ -148,8 +146,8 @@ export function launchMessage(

export function ackCreatingProject(locale: BotLocale): string {
return locale === "ru"
? "Создаю проект и готовлю bootstrap-команду..."
: "Creating the project and preparing the bootstrap command...";
? "Создаю проект и готовлю ссылку на рабочее окружение..."
: "Creating the project and preparing the workspace link...";
}

export function ackCheckingLaunch(locale: BotLocale): string {
Expand Down
5 changes: 3 additions & 2 deletions src/bot/polling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,9 @@ async function processUpdate(cfg: ReturnType<typeof readBotConfig>, update: Tele
clearTimeout(ackTimeout);
const slug = data.project.slug;
const token = data.pairingToken.token;
const bootstrapCmd = `npx -y @spawn-dock/create@beta --token ${token}`;
await sendMessage(cfg.telegramBotToken, msg.chat.id, createdMessage(locale, slug, bootstrapCmd));
const spawnCmd = `spawn-dock spawn --token ${token}`;
const spawnLink = `spawndock://spawn?token=${token}`;
await sendMessage(cfg.telegramBotToken, msg.chat.id, createdMessage(locale, slug, spawnCmd, spawnLink));
return;
}

Expand Down