aura-ai
Version:
AI-powered marketing strategist CLI tool for developers
647 lines (635 loc) • 28.1 kB
JavaScript
#!/usr/bin/env -S node --no-warnings
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
import { useState, useEffect, useRef } from "react";
import { useInput, Box, Text, Spacer, Newline, useApp, Static, render } from "ink";
import { Spinner, Alert } from "@inkjs/ui";
import fs from "fs/promises";
import TextInput from "ink-text-input";
import { I as InitPage, E as EmojiSpinner } from "./page-CHKhZAAX.js";
import SelectInput from "ink-select-input";
import { g as gitService, s as syncAIService, c as chatService } from "./chatService-7b3Ru5ZZ.js";
import path from "path";
import os from "os";
const CommandInput = ({
value,
onChange,
onSubmit,
placeholder = "Type a command or message...",
commands = [],
exitPrompt = false,
onClearInput = null,
onExit = null
}) => {
const [suggestions, setSuggestions] = useState([]);
const [showSuggestions, setShowSuggestions] = useState(false);
const [selectedIndex, setSelectedIndex] = useState(0);
useInput((input, key) => {
if (key.ctrl && input === "c") {
if (value.length > 0 && onClearInput) {
onClearInput();
return;
}
if (onExit) {
onExit();
return;
}
}
if (showSuggestions && suggestions.length > 0) {
if (key.upArrow) {
setSelectedIndex((prev) => Math.max(0, prev - 1));
return;
}
if (key.downArrow) {
setSelectedIndex((prev) => Math.min(suggestions.length - 1, prev + 1));
return;
}
if (key.tab) {
const selectedCmd = suggestions[selectedIndex];
if (selectedCmd) {
onChange(`/${selectedCmd.name}`);
setShowSuggestions(false);
}
return;
}
}
});
useEffect(() => {
if (value.startsWith("/")) {
const query = value.substring(1).toLowerCase();
const filteredCommands = commands.filter(
(cmd) => cmd.name.toLowerCase().includes(query) || cmd.description.toLowerCase().includes(query)
);
setSuggestions(filteredCommands);
setShowSuggestions(filteredCommands.length > 0);
setSelectedIndex(0);
} else {
setSuggestions([]);
setShowSuggestions(false);
setSelectedIndex(0);
}
}, [value, commands]);
const handleSubmit = (inputValue) => {
if (showSuggestions && suggestions.length > 0) {
const selectedCmd = suggestions[selectedIndex];
if (selectedCmd) {
setShowSuggestions(false);
onSubmit(`/${selectedCmd.name}`);
return;
}
}
setShowSuggestions(false);
onSubmit(inputValue);
};
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: "100%", children: [
/* @__PURE__ */ jsxs(Box, { paddingX: 1, paddingY: 0, borderColor: "whiteBright", borderStyle: "round", width: "100%", children: [
/* @__PURE__ */ jsx(Text, { color: "blue", children: "> " }),
/* @__PURE__ */ jsx(
TextInput,
{
value,
onChange,
onSubmit: handleSubmit,
placeholder,
focus: true
}
)
] }),
showSuggestions && suggestions.length > 0 && /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, marginBottom: 1, paddingLeft: 2, children: suggestions.map((cmd, index) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexWrap: "wrap", children: [
/* @__PURE__ */ jsx(Box, { width: 16, children: /* @__PURE__ */ jsx(Text, { color: index === selectedIndex ? "blueBright" : "gray", children: /* @__PURE__ */ jsxs(Text, { color: index === selectedIndex ? "blueBright" : "gray", children: [
"/",
cmd.name
] }) }) }),
/* @__PURE__ */ jsx(Box, { paddingLeft: 3, children: /* @__PURE__ */ jsx(Text, { color: index === selectedIndex ? "blueBright" : "gray", children: cmd.description }) })
] }, index)) }),
/* @__PURE__ */ jsxs(Box, { width: "100%", children: [
/* @__PURE__ */ jsx(Text, { dimColor: true, children: exitPrompt ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: "Press Ctrl+C again to exit" }) : value.startsWith("/") ? /* @__PURE__ */ jsx(Fragment, { children: "Press Enter to continue" }) : /* @__PURE__ */ jsx(Fragment, { children: "Type / for commands" }) }),
/* @__PURE__ */ jsx(Spacer, {}),
/* @__PURE__ */ jsx(Text, { dimColor: true, children: !exitPrompt && /* @__PURE__ */ jsxs(Fragment, { children: [
" Ctrl+C to ",
value ? "clear input" : "exit"
] }) })
] })
] });
};
const SettingsPage = ({ onBack }) => {
const [mode, setMode] = useState("menu");
const [inputValue, setInputValue] = useState("");
const [currentSetting, setCurrentSetting] = useState("");
const [settings, setSettings] = useState({
avatars: { aura: "🌀", user: ">" }
});
useEffect(() => {
loadSettings();
}, []);
const loadSettings = async () => {
try {
const data = await fs.readFile("./.aura.json", "utf-8");
setSettings(JSON.parse(data));
} catch {
}
};
const saveSettings = async (newSettings) => {
try {
await fs.writeFile("./.aura.json", JSON.stringify(newSettings, null, 2));
} catch (error) {
console.error("Failed to save settings:", error);
}
};
const menuItems = [
{
label: `${settings.avatars.aura} Set Aura avatar`,
value: "setAura"
},
{
label: `${settings.avatars.user} Set User avatar`,
value: "setUser"
},
{
label: "Reset to defaults",
value: "reset"
},
{
label: "Exit",
value: "exit"
}
];
const handleSelect = async (item) => {
if (item.value === "exit") {
onBack();
} else if (item.value === "reset") {
const defaultSettings = { avatars: { aura: "🌀", user: ">" } };
await saveSettings(defaultSettings);
setSettings(defaultSettings);
onBack();
} else {
setCurrentSetting(item.value);
setMode("input");
setInputValue("");
}
};
const handleAvatarSubmit = async (value) => {
if (value && value.length > 0) {
const char = value.trim();
const newSettings = { ...settings };
if (currentSetting === "setAura") {
newSettings.avatars.aura = char;
} else if (currentSetting === "setUser") {
newSettings.avatars.user = char;
}
await saveSettings(newSettings);
setSettings(newSettings);
setMode("menu");
setInputValue("");
}
};
if (mode === "input") {
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
/* @__PURE__ */ jsx(Box, { paddingY: 1, paddingX: 2, borderColor: "blue", borderStyle: "round", width: "100%", children: /* @__PURE__ */ jsxs(Text, { children: [
/* @__PURE__ */ jsx(Text, { bold: true, children: "Settings" }),
" - Avatar Configuration"
] }) }),
/* @__PURE__ */ jsxs(Box, { marginTop: 2, flexDirection: "column", children: [
/* @__PURE__ */ jsx(Text, { children: currentSetting === "setAura" ? "Enter new Aura avatar (emoji or text):" : "Enter new User avatar (emoji or text):" }),
/* @__PURE__ */ jsxs(Box, { marginTop: 1, paddingX: 1, borderColor: "gray", borderStyle: "single", children: [
/* @__PURE__ */ jsx(Text, { color: "blue", children: "> " }),
/* @__PURE__ */ jsx(
TextInput,
{
value: inputValue,
onChange: setInputValue,
onSubmit: handleAvatarSubmit,
placeholder: "Enter avatar (e.g., 🐤, >, 👾)...",
focus: true
}
)
] }),
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press Enter to save, or Ctrl+C to cancel" }) })
] })
] });
}
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
/* @__PURE__ */ jsx(Box, { paddingY: 1, paddingX: 2, borderColor: "blue", borderStyle: "round", width: "100%", children: /* @__PURE__ */ jsxs(Text, { children: [
/* @__PURE__ */ jsx(Text, { bold: true, children: "Settings" }),
" - Avatar Configuration"
] }) }),
/* @__PURE__ */ jsxs(Box, { marginTop: 2, flexDirection: "column", children: [
/* @__PURE__ */ jsx(Text, { color: "yellow", children: "Select an option:" }),
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(SelectInput, { items: menuItems, onSelect: handleSelect }) })
] }),
/* @__PURE__ */ jsx(Box, { marginTop: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
"Current: Aura = ",
settings.avatars.aura,
" User = ",
settings.avatars.user
] }) })
] });
};
const SyncPage = ({ onBack }) => {
const [loading, setLoading] = useState(true);
const [report, setReport] = useState(null);
const [error, setError] = useState(null);
const [showMenu, setShowMenu] = useState(false);
const [commits, setCommits] = useState([]);
useEffect(() => {
loadReport();
}, []);
const loadReport = async () => {
setLoading(true);
setError(null);
try {
const todayCommits = await gitService.getTodayCommits();
setCommits(todayCommits);
const formattedCommits = gitService.formatCommitsForAI(todayCommits);
const aiReport = await syncAIService.generateDailyReport(formattedCommits);
setReport(aiReport);
setShowMenu(true);
} catch (err) {
setError("Failed to generate report: " + err.message);
} finally {
setLoading(false);
}
};
const menuItems = [
{ label: "📋 Copy as Markdown", value: "copy" },
{ label: "🔄 Refresh", value: "refresh" },
{ label: "← Back to Main Menu", value: "back" }
];
const handleSelect = async (item) => {
if (item.value === "back") {
onBack();
} else if (item.value === "refresh") {
setShowMenu(false);
await loadReport();
} else if (item.value === "copy") {
try {
const { exec } = await import("child_process");
const { promisify } = await import("util");
const execAsync = promisify(exec);
const platform = process.platform;
const markdown = report.markdown;
if (platform === "darwin") {
await execAsync(`echo "${markdown.replace(/"/g, '\\"').replace(/\$/g, "\\$")}" | pbcopy`);
} else if (platform === "linux") {
await execAsync(`echo "${markdown.replace(/"/g, '\\"').replace(/\$/g, "\\$")}" | xclip -selection clipboard`);
} else if (platform === "win32") {
await execAsync(`echo "${markdown.replace(/"/g, '\\"').replace(/\$/g, "\\$")}" | clip`);
}
setError(`✅ Report copied to clipboard!`);
setTimeout(() => setError(null), 3e3);
} catch (err) {
setError("Failed to copy: " + err.message);
setTimeout(() => setError(null), 3e3);
}
}
};
if (loading) {
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
/* @__PURE__ */ jsx(Box, { paddingY: 1, paddingX: 2, borderColor: "blue", borderStyle: "round", children: /* @__PURE__ */ jsxs(Text, { children: [
/* @__PURE__ */ jsx(Text, { bold: true, children: "🤖 AI Daily Sync" }),
" - Generating Intelligence Report..."
] }) }),
/* @__PURE__ */ jsx(Box, { marginTop: 2, paddingLeft: 2, children: /* @__PURE__ */ jsx(Spinner, { label: "AI is analyzing your commits..." }) })
] });
}
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
/* @__PURE__ */ jsx(Box, { paddingY: 1, paddingX: 2, borderColor: "blue", borderStyle: "round", children: /* @__PURE__ */ jsxs(Text, { children: [
/* @__PURE__ */ jsx(Text, { bold: true, children: "🤖 AI Daily Sync" }),
" - Progress Intelligence"
] }) }),
error && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Alert, { variant: error.startsWith("✅") ? "success" : "error", children: error }) }),
report && /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(Box, { marginTop: 2, paddingLeft: 1, children: /* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "📊 Executive Summary" }) }),
/* @__PURE__ */ jsx(Box, { marginTop: 1, paddingLeft: 1, children: /* @__PURE__ */ jsx(Text, { children: report.summary }) }),
report.highlights && report.highlights.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(Box, { marginTop: 2, paddingLeft: 1, children: /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "✨ Key Achievements" }) }),
report.highlights.map((highlight, index) => /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { children: [
"• ",
highlight
] }) }, index))
] }),
commits.length > 0 && /* @__PURE__ */ jsx(Box, { marginTop: 2, paddingLeft: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
"Based on ",
commits.length,
" commits today"
] }) }),
showMenu && /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(Box, { marginTop: 2, paddingLeft: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "What would you like to do?" }) }),
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(SelectInput, { items: menuItems, onSelect: handleSelect }) })
] })
] }),
commits.length === 0 && /* @__PURE__ */ jsx(Box, { marginTop: 2, paddingLeft: 1, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
/* @__PURE__ */ jsx(Text, { color: "gray", children: "No commits found today yet!" }),
/* @__PURE__ */ jsx(Newline, {}),
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Start working on your project and come back later." }),
/* @__PURE__ */ jsx(Newline, {}),
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "💡 AI will analyze and summarize your work intelligently." })
] }) })
] });
};
const AddAuraAgentPage = ({ onBack }) => {
const [status, setStatus] = useState("installing");
const [error, setError] = useState(null);
const [targetPath, setTargetPath] = useState("");
useInput((input, key) => {
if (key.return && (status === "success" || status === "error")) {
onBack();
}
});
useEffect(() => {
installAgent();
}, []);
const installAgent = async () => {
try {
const homeDir = os.homedir();
const claudeAgentsDir = path.join(homeDir, ".claude", "agents");
try {
await fs.access(claudeAgentsDir);
} catch {
await fs.mkdir(claudeAgentsDir, { recursive: true });
}
const auraAgentSource = `---
name: aura
description: Marketing AI agent that uses Aura CLI for product analysis, daily reports, and marketing insights
tools: Bash
model: sonnet
color: cyan
---
You are Aura, a marketing AI assistant that uses the Aura CLI tool via npx.
## Quick Command Reference
\`\`\`bash
# Daily sync report (saves file, prints, copies to clipboard)
npx aura-ai sync --json
# Marketing consultation
npx aura-ai chat "your question" --json
# Product analysis (one-time setup)
npx aura-ai init --answers "product|audience|value" --json
# View settings
npx aura-ai settings --list --json
\`\`\`
## How to Respond
1. **User says "sync"** → Run: \`npx aura-ai sync --json\`
- Creates \`YYYY-M-D-update.md\` file automatically
- Prints full report to terminal
- Auto-copies to clipboard
- Tell user: "Report generated, saved to [filename], and copied to clipboard"
2. **User asks marketing question** → Run: \`npx aura-ai chat "question" --json\`
3. **User wants product analysis** → Check if aura.md exists, if not run: \`npx aura-ai init --answers "..." --json\`
## Important
- No installation needed! Uses npx to run directly
- Sync command creates dated markdown files (e.g., \`2025-8-8-update.md\`)
- All content is visible in terminal output
- Reports are automatically saved and copied
- Just run commands, don't read files`;
const target = path.join(claudeAgentsDir, "aura.md");
await fs.writeFile(target, auraAgentSource);
setTargetPath(target);
setStatus("success");
} catch (err) {
setError(err.message);
setStatus("error");
}
};
if (status === "installing") {
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
/* @__PURE__ */ jsx(Box, { paddingY: 1, paddingX: 2, borderColor: "blue", borderStyle: "round", children: /* @__PURE__ */ jsxs(Text, { children: [
/* @__PURE__ */ jsx(Text, { bold: true, children: "Installing Aura Agent" }),
" to Claude"
] }) }),
/* @__PURE__ */ jsx(Box, { marginTop: 2, paddingLeft: 2, children: /* @__PURE__ */ jsx(Spinner, { label: "Setting up agent..." }) })
] });
}
if (status === "error") {
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
/* @__PURE__ */ jsx(Box, { paddingY: 1, paddingX: 2, borderColor: "red", borderStyle: "round", children: /* @__PURE__ */ jsx(Text, { children: /* @__PURE__ */ jsx(Text, { bold: true, color: "red", children: "Installation Failed" }) }) }),
/* @__PURE__ */ jsx(Box, { marginTop: 2, children: /* @__PURE__ */ jsx(Alert, { variant: "error", children: error }) }),
/* @__PURE__ */ jsx(Box, { marginTop: 2, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press Enter to continue..." }) })
] });
}
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
/* @__PURE__ */ jsx(Box, { paddingY: 1, paddingX: 2, borderColor: "green", borderStyle: "round", children: /* @__PURE__ */ jsx(Text, { children: /* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: "✅ Aura Agent Installed!" }) }) }),
/* @__PURE__ */ jsxs(Box, { marginTop: 2, flexDirection: "column", children: [
/* @__PURE__ */ jsx(Alert, { variant: "success", children: "Agent successfully installed to Claude" }),
/* @__PURE__ */ jsx(Box, { marginTop: 2, paddingLeft: 1, children: /* @__PURE__ */ jsxs(Text, { children: [
"📄 Location: ",
/* @__PURE__ */ jsx(Text, { color: "cyan", children: targetPath })
] }) }),
/* @__PURE__ */ jsx(Box, { marginTop: 2, paddingX: 2, paddingY: 1, borderColor: "yellow", borderStyle: "single", children: /* @__PURE__ */ jsx(Text, { color: "yellow", children: "⚠️ IMPORTANT: Please restart Claude to load the new agent" }) }),
/* @__PURE__ */ jsxs(Box, { marginTop: 2, paddingLeft: 1, flexDirection: "column", children: [
/* @__PURE__ */ jsx(Text, { bold: true, children: "🎯 After restarting Claude, you can use:" }),
/* @__PURE__ */ jsx(Text, { color: "gray", children: " • @aura sync - Generate daily reports" }),
/* @__PURE__ */ jsx(Text, { color: "gray", children: " • @aura help me with marketing - Get marketing advice" }),
/* @__PURE__ */ jsx(Text, { color: "gray", children: " • @aura analyze my product - Product analysis" })
] }),
/* @__PURE__ */ jsx(Box, { marginTop: 2, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press Enter to continue..." }) })
] })
] });
};
const App = () => {
const [inputValue, setInputValue] = useState("");
const [exitPrompt, setExitPrompt] = useState(false);
const [currentRoute, setCurrentRoute] = useState("home");
const [hasAuraConfig, setHasAuraConfig] = useState(false);
const [settings, setSettings] = useState({
avatars: { aura: "🌀", user: ">" }
});
const lastCtrlC = useRef(0);
const { exit } = useApp();
const [messages, setMessages] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
const checkAuraConfig = async () => {
try {
await fs.access("./aura.md");
setHasAuraConfig(true);
} catch {
setHasAuraConfig(false);
}
};
const loadSettings = async () => {
try {
const data = await fs.readFile("./.aura.json", "utf-8");
setSettings(JSON.parse(data));
} catch {
}
};
checkAuraConfig();
loadSettings();
}, []);
const availableCommands = [
{
name: "init",
description: "Analyze my product and generate a marketing strategy"
},
{
name: "sync",
description: "Generate today's progress report from git commits"
},
{
name: "today",
description: "[DEMO] Check today's marketing report and recommended actions"
},
{ name: "post", description: "[DEMO] Tweet, blog post, email, short video, etc" },
{ name: "settings", description: "Manage your Aura settings" },
{
name: "add-aura-agent",
description: "Install Aura agent to Claude for @aura commands"
}
];
const handleClearInput = () => {
setInputValue("");
setExitPrompt(false);
};
const handleExit = () => {
const now = Date.now();
if (now - lastCtrlC.current < 2e3) {
exit();
} else {
setExitPrompt(true);
lastCtrlC.current = now;
setTimeout(() => {
setExitPrompt(false);
}, 2e3);
}
};
const handleSubmit = (value) => {
if (value.trim()) {
const trimmedValue = value.trim();
if (trimmedValue.startsWith("/")) {
const command = trimmedValue.substring(1).toLowerCase();
if (command === "init") {
setCurrentRoute("init");
} else if (command === "settings") {
setCurrentRoute("settings");
} else if (command === "sync") {
setCurrentRoute("sync");
} else if (command === "add-aura-agent") {
setCurrentRoute("add-aura-agent");
}
setInputValue("");
} else {
const userMessage = {
id: Date.now().toString(),
role: "user",
content: trimmedValue
};
setMessages((prev) => [...prev, userMessage]);
setError(null);
setIsLoading(true);
chatService.sendMessage([...messages, userMessage]).then(async (stream) => {
let fullContent = "";
const assistantMessageId = (Date.now() + 1).toString();
setMessages((prev) => [...prev, {
id: assistantMessageId,
role: "assistant",
content: ""
}]);
for await (const chunk of stream.textStream) {
fullContent += chunk;
setMessages((prev) => prev.map(
(msg) => msg.id === assistantMessageId ? { ...msg, content: fullContent } : msg
));
}
setIsLoading(false);
}).catch((err) => {
console.error("Chat error:", err);
setError(err.message);
if (err.message.includes("API key not configured")) {
setMessages((prev) => [...prev, {
id: (Date.now() + 1).toString(),
role: "assistant",
content: "⚠️ OpenAI API key not configured. Please set OPENAI_API_KEY in your .env file to enable AI chat."
}]);
} else {
setMessages((prev) => [...prev, {
id: (Date.now() + 1).toString(),
role: "assistant",
content: hasAuraConfig ? "Based on your product analysis, I recommend focusing on content marketing to build authority in your niche. Start with educational blog posts that solve your target audience's pain points." : "I'm using demo analysis results. Run /init to analyze your product for personalized marketing insights! Meanwhile, I can help with general marketing strategies."
}]);
}
setIsLoading(false);
});
setInputValue("");
}
setExitPrompt(false);
}
};
const handleBack = () => {
setCurrentRoute("home");
};
if (currentRoute === "init") {
return /* @__PURE__ */ jsx(InitPage, { onBack: handleBack });
}
if (currentRoute === "settings") {
return /* @__PURE__ */ jsx(SettingsPage, { onBack: () => {
const loadSettings = async () => {
try {
const data = await fs.readFile("./.aura.json", "utf-8");
setSettings(JSON.parse(data));
} catch {
}
};
loadSettings();
handleBack();
} });
}
if (currentRoute === "sync") {
return /* @__PURE__ */ jsx(SyncPage, { onBack: handleBack });
}
if (currentRoute === "add-aura-agent") {
return /* @__PURE__ */ jsx(AddAuraAgentPage, { onBack: handleBack });
}
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
/* @__PURE__ */ jsx(Box, { paddingY: 1, paddingX: 2, borderColor: "blue", borderStyle: "round", width: "100%", children: /* @__PURE__ */ jsxs(Text, { children: [
"🌀 Welcome to ",
/* @__PURE__ */ jsx(Text, { bold: true, children: "Aura!" }),
/* @__PURE__ */ jsx(Newline, {}),
/* @__PURE__ */ jsx(Newline, {}),
/* @__PURE__ */ jsx(Text, { color: "white", dimColor: true, children: "Your AI marketing companion" })
] }) }),
/* @__PURE__ */ jsxs(Box, { marginTop: 1, paddingLeft: 1, flexDirection: "column", children: [
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Tips for getting started:" }),
/* @__PURE__ */ jsx(Newline, {}),
/* @__PURE__ */ jsx(Text, { color: "gray", children: " 1. Run /init to analyze your product and create a marketing strategy" }),
/* @__PURE__ */ jsx(Text, { color: "gray", children: " 2. Chat directly with Aura for marketing insights and recommendations" }),
/* @__PURE__ */ jsx(Text, { color: "gray", children: " 3. Be as specific as you would with a marketing expert for best results" }),
/* @__PURE__ */ jsx(Text, { color: "gray", children: " 4. ✓ View available commands by typing /" })
] }),
!hasAuraConfig && messages.length > 0 && /* @__PURE__ */ jsx(Static, { items: [{ id: "demo-alert" }], children: () => /* @__PURE__ */ jsx(Box, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsx(Alert, { variant: "warning", children: "You're chatting with demo analysis results. Run /init for personalized insights." }) }) }),
error && /* @__PURE__ */ jsx(Static, { items: [{ id: "error-alert" }], children: () => /* @__PURE__ */ jsx(Box, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsx(Alert, { variant: "error", children: error }) }) }),
messages.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 2, marginBottom: 1, paddingLeft: 1, children: [
messages.filter((m) => m.role !== "system").map((msg) => /* @__PURE__ */ jsxs(Box, { marginBottom: 1, flexDirection: "row", children: [
/* @__PURE__ */ jsx(Box, { width: 2, flexShrink: 0, children: /* @__PURE__ */ jsx(Text, { children: msg.role === "user" ? settings.avatars.user : settings.avatars.aura }) }),
/* @__PURE__ */ jsx(Box, { flexGrow: 1, paddingLeft: 1, children: msg.role === "user" ? /* @__PURE__ */ jsx(Text, { children: msg.content }) : /* @__PURE__ */ jsx(Text, { color: "white", children: msg.content }) })
] }, msg.id)),
isLoading && /* @__PURE__ */ jsx(EmojiSpinner, { label: "Aura is thinking..." })
] }),
/* @__PURE__ */ jsx(Box, { marginTop: messages.length === 0 ? 2 : 1, children: /* @__PURE__ */ jsx(
CommandInput,
{
value: inputValue,
onChange: setInputValue,
onSubmit: handleSubmit,
placeholder: "Type a command or message...",
commands: availableCommands,
exitPrompt,
onClearInput: handleClearInput,
onExit: handleExit
}
) })
] });
};
function runInteractive() {
const { waitUntilExit } = render(/* @__PURE__ */ jsx(App, {}), {
exitOnCtrlC: false
// Disable automatic exit on Ctrl+C
});
return waitUntilExit();
}
if (import.meta.url === `file://${process.argv[1]}`) {
runInteractive();
}
export {
runInteractive as default
};
//# sourceMappingURL=rina.js.map