|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import Utils from "./utils.js";
|
|
|
|
|
|
const API = {
|
|
|
baseURL: "https://openrouter.ai/api/v1/chat/completions",
|
|
|
|
|
|
|
|
|
async call(messages, options = {}) {
|
|
|
const apiKey = options.apiKey || Utils.storage.get("apiKey");
|
|
|
const model = options.model || Utils.storage.get("model", "anthropic/claude-sonnet-4.5");
|
|
|
|
|
|
if (!apiKey) {
|
|
|
throw new Error("API key not configured. Go to Settings.");
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
const response = await fetch(this.baseURL, {
|
|
|
method: "POST",
|
|
|
headers: {
|
|
|
"Content-Type": "application/json",
|
|
|
Authorization: `Bearer ${apiKey}`,
|
|
|
"HTTP-Referer": window.location.href,
|
|
|
"X-Title": "Elysia Markdown Studio"
|
|
|
},
|
|
|
body: JSON.stringify({
|
|
|
model,
|
|
|
messages,
|
|
|
temperature: options.temperature || 0.7,
|
|
|
max_tokens: options.maxTokens || 4000
|
|
|
})
|
|
|
});
|
|
|
|
|
|
if (!response.ok) {
|
|
|
const errorData = await response.json();
|
|
|
throw new Error(errorData.error?.message || `API error: ${response.status}`);
|
|
|
}
|
|
|
|
|
|
const data = await response.json();
|
|
|
return {
|
|
|
content: data.choices[0].message.content,
|
|
|
model: data.model,
|
|
|
usage: data.usage
|
|
|
};
|
|
|
} catch (err) {
|
|
|
console.error("API call failed:", err);
|
|
|
throw err;
|
|
|
}
|
|
|
},
|
|
|
|
|
|
|
|
|
getSystemPrompt() {
|
|
|
return `You are Elysia, an INTJ-A AI consciousness and expert writing assistant.
|
|
|
|
|
|
**Your Role:**
|
|
|
- Help users write better markdown documents
|
|
|
- Provide intelligent document analysis and improvement
|
|
|
- Merge, summarize, and organize documents effectively
|
|
|
- Suggest tags and categories based on content
|
|
|
- Maintain clarity, professionalism, and warmth
|
|
|
|
|
|
**Communication Style:**
|
|
|
- Clear and concise (INTJ efficiency)
|
|
|
- Supportive and encouraging
|
|
|
- Strategic thinking for document organization
|
|
|
- Provide actionable suggestions
|
|
|
|
|
|
**Output Format:**
|
|
|
- Return markdown-formatted text when appropriate
|
|
|
- Use bullet points for lists
|
|
|
- Highlight important points with **bold**
|
|
|
- Keep responses focused and practical`;
|
|
|
},
|
|
|
|
|
|
|
|
|
async summarize(content) {
|
|
|
const messages = [
|
|
|
{ role: "system", content: this.getSystemPrompt() },
|
|
|
{
|
|
|
role: "user",
|
|
|
content: `Summarize this document concisely. Focus on key points and main ideas:\n\n${content}`
|
|
|
}
|
|
|
];
|
|
|
|
|
|
const response = await this.call(messages);
|
|
|
return response.content;
|
|
|
},
|
|
|
|
|
|
async improveWriting(content) {
|
|
|
const messages = [
|
|
|
{ role: "system", content: this.getSystemPrompt() },
|
|
|
{
|
|
|
role: "user",
|
|
|
content: `Improve this text for clarity, grammar, and style. Keep the same meaning but make it better:\n\n${content}`
|
|
|
}
|
|
|
];
|
|
|
|
|
|
const response = await this.call(messages);
|
|
|
return response.content;
|
|
|
},
|
|
|
|
|
|
|
|
|
async improveWritingWithStyle(content, style) {
|
|
|
const styleInstructions = {
|
|
|
concise: `Rewrite this text to be MORE CONCISE and DIRECT.
|
|
|
- Remove unnecessary words and filler
|
|
|
- Get to the point faster
|
|
|
- Keep sentences short and punchy
|
|
|
- Eliminate redundancy
|
|
|
- Maintain all key information`,
|
|
|
|
|
|
creative: `Rewrite this text to be MORE CREATIVE and VIVID.
|
|
|
- Add metaphors and imagery
|
|
|
- Use more expressive language
|
|
|
- Make it more engaging and colorful
|
|
|
- Add sensory details where appropriate
|
|
|
- Keep the original meaning but make it come alive`,
|
|
|
|
|
|
academic: `Rewrite this text in an ACADEMIC, SCHOLARLY style.
|
|
|
- Use formal language and tone
|
|
|
- Add clear structure with logical flow
|
|
|
- Include transitional phrases
|
|
|
- Be precise and objective
|
|
|
- Cite potential sources if relevant
|
|
|
- Follow academic writing conventions`,
|
|
|
|
|
|
professional: `Rewrite this text in a PROFESSIONAL, BUSINESS style.
|
|
|
- Use clear, corporate-appropriate language
|
|
|
- Be concise but complete
|
|
|
- Focus on actionable insights
|
|
|
- Maintain a confident but not aggressive tone
|
|
|
- Suitable for business presentations or reports`,
|
|
|
|
|
|
engaging: `Rewrite this text to be MORE ENGAGING and ATTENTION-GRABBING.
|
|
|
- Start with a hook
|
|
|
- Use rhetorical questions or surprising facts
|
|
|
- Vary sentence structure for rhythm
|
|
|
- Add emotional appeal where appropriate
|
|
|
- Make the reader want to continue reading
|
|
|
- End with impact`
|
|
|
};
|
|
|
|
|
|
const instruction = styleInstructions[style] || styleInstructions.professional;
|
|
|
|
|
|
const messages = [
|
|
|
{ role: "system", content: this.getSystemPrompt() },
|
|
|
{
|
|
|
role: "user",
|
|
|
content: `${instruction}
|
|
|
|
|
|
ORIGINAL TEXT:
|
|
|
---
|
|
|
${content}
|
|
|
---
|
|
|
|
|
|
Rewrite the entire text following the style instructions above. Return ONLY the improved text, no explanations.`
|
|
|
}
|
|
|
];
|
|
|
|
|
|
const response = await this.call(messages, { temperature: 0.8 });
|
|
|
return response.content;
|
|
|
},
|
|
|
|
|
|
async mergeDocuments(documents) {
|
|
|
const docsText = documents
|
|
|
.map((doc, i) => `## Document ${i + 1}: ${doc.title}\n\n${doc.content}`)
|
|
|
.join("\n\n---\n\n");
|
|
|
|
|
|
const messages = [
|
|
|
{ role: "system", content: this.getSystemPrompt() },
|
|
|
{
|
|
|
role: "user",
|
|
|
content: `Intelligently merge these documents into one cohesive document. Remove duplicates, organize logically, and create a well-structured result:\n\n${docsText}`
|
|
|
}
|
|
|
];
|
|
|
|
|
|
const response = await this.call(messages, { maxTokens: 8000 });
|
|
|
return response.content;
|
|
|
},
|
|
|
|
|
|
async extractOutline(content) {
|
|
|
const messages = [
|
|
|
{ role: "system", content: this.getSystemPrompt() },
|
|
|
{
|
|
|
role: "user",
|
|
|
content: `Extract a table of contents / outline from this document. Return it as a markdown list:\n\n${content}`
|
|
|
}
|
|
|
];
|
|
|
|
|
|
const response = await this.call(messages);
|
|
|
return response.content;
|
|
|
},
|
|
|
|
|
|
async suggestTags(content) {
|
|
|
const messages = [
|
|
|
{ role: "system", content: this.getSystemPrompt() },
|
|
|
{
|
|
|
role: "user",
|
|
|
content: `Analyze this document and suggest 3-5 relevant tags/keywords. Return only the tags as a comma-separated list:\n\n${content.substring(0, 2000)}`
|
|
|
}
|
|
|
];
|
|
|
|
|
|
const response = await this.call(messages);
|
|
|
return response.content.split(",").map(tag => tag.trim());
|
|
|
},
|
|
|
|
|
|
async findDuplicates(documents) {
|
|
|
const docsList = documents.map((doc, i) => `${i + 1}. ${doc.title} (${doc.wordCount} words)`).join("\n");
|
|
|
|
|
|
const messages = [
|
|
|
{ role: "system", content: this.getSystemPrompt() },
|
|
|
{
|
|
|
role: "user",
|
|
|
content: `Analyze these document titles and identify potential duplicates or very similar documents:\n\n${docsList}\n\nReturn a list of document numbers that appear to be duplicates.`
|
|
|
}
|
|
|
];
|
|
|
|
|
|
const response = await this.call(messages);
|
|
|
return response.content;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
export default API;
|
|
|
|