134 lines
4.2 KiB
TypeScript
134 lines
4.2 KiB
TypeScript
// Utility functions for OpenAI API key management
|
|
|
|
// Store the OpenAI API key in localStorage
|
|
export const storeOpenAIKey = (apiKey: string): void => {
|
|
if (typeof window !== "undefined") {
|
|
localStorage.setItem("soloLevelUpOpenAIKey", apiKey)
|
|
}
|
|
}
|
|
|
|
// Retrieve the OpenAI API key from localStorage
|
|
export const getOpenAIKey = (): string | null => {
|
|
if (typeof window !== "undefined") {
|
|
return localStorage.getItem("soloLevelUpOpenAIKey")
|
|
}
|
|
return null
|
|
}
|
|
|
|
// Check if the OpenAI API key exists
|
|
export const hasOpenAIKey = (): boolean => {
|
|
return getOpenAIKey() !== null
|
|
}
|
|
|
|
// Remove the OpenAI API key from localStorage
|
|
export const removeOpenAIKey = (): void => {
|
|
if (typeof window !== "undefined") {
|
|
localStorage.removeItem("soloLevelUpOpenAIKey")
|
|
}
|
|
}
|
|
|
|
// Interface for AI-generated quest data
|
|
export interface AIQuestData {
|
|
title: string
|
|
description: string
|
|
difficulty: "S" | "A" | "B" | "C" | "D" | "E"
|
|
expiry: string
|
|
expReward: number
|
|
statPointsReward: number
|
|
goldReward: number
|
|
statRewards: {
|
|
str?: number
|
|
agi?: number
|
|
per?: number
|
|
int?: number
|
|
vit?: number
|
|
}
|
|
itemRewards?: {
|
|
name: string
|
|
type: string
|
|
description: string
|
|
}[]
|
|
}
|
|
|
|
// Generate quest data using OpenAI API
|
|
export const generateQuestData = async (description: string): Promise<AIQuestData> => {
|
|
const apiKey = getOpenAIKey()
|
|
|
|
if (!apiKey) {
|
|
throw new Error("OpenAI API key not found")
|
|
}
|
|
|
|
try {
|
|
const response = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Authorization: `Bearer ${apiKey}`,
|
|
},
|
|
body: JSON.stringify({
|
|
model: "gpt-3.5-turbo",
|
|
messages: [
|
|
{
|
|
role: "system",
|
|
content: `You are an AI assistant for a Solo Leveling themed self-improvement app.
|
|
The user will provide a quest description, and you need to generate appropriate quest data.
|
|
Format your response as a valid JSON object with the following structure:
|
|
{
|
|
"title": "Short, catchy title for the quest",
|
|
"description": "Refined, motivational description of the quest",
|
|
"difficulty": "One of: S, A, B, C, D, E (S is hardest, E is easiest)",
|
|
"expiry": "One of: Daily, Weekly, Monthly, One-time",
|
|
"expReward": number (10-500 based on difficulty),
|
|
"statPointsReward": number (1-10 based on difficulty),
|
|
"goldReward": number (10-1000 based on difficulty),
|
|
"statRewards": {
|
|
"str": number (optional),
|
|
"agi": number (optional),
|
|
"per": number (optional),
|
|
"int": number (optional),
|
|
"vit": number (optional)
|
|
},
|
|
"itemRewards": [
|
|
{
|
|
"name": "Item name",
|
|
"type": "One of: Material, Consumable, Weapon, Armor, Accessory, Rune",
|
|
"description": "Brief description of the item"
|
|
}
|
|
] (optional)
|
|
}
|
|
Analyze the description to determine appropriate stats to reward based on the activity.
|
|
For example, physical activities should reward STR and VIT, mental activities should reward INT and PER, etc.
|
|
The difficulty should be based on how challenging the task seems.
|
|
Only include 1-2 item rewards for difficult quests (S, A, B), and none for easier quests.`,
|
|
},
|
|
{
|
|
role: "user",
|
|
content: description,
|
|
},
|
|
],
|
|
temperature: 0.7,
|
|
max_tokens: 800,
|
|
}),
|
|
})
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`API request failed with status ${response.status}`)
|
|
}
|
|
|
|
const data = await response.json()
|
|
const content = data.choices[0].message.content
|
|
|
|
// Parse the JSON response
|
|
try {
|
|
const questData = JSON.parse(content) as AIQuestData
|
|
return questData
|
|
} catch (error) {
|
|
console.error("Failed to parse OpenAI response:", content)
|
|
throw new Error("Failed to parse AI response")
|
|
}
|
|
} catch (error) {
|
|
console.error("Error generating quest data:", error)
|
|
throw error
|
|
}
|
|
}
|