diff --git a/README.md b/README.md
index 798f9be..483262f 100644
--- a/README.md
+++ b/README.md
@@ -16,11 +16,13 @@
## Технологии
### Frontend
+
- React 18 + TypeScript
- Vite
- CSS (без фреймворков)
### Backend
+
- Express.js (прокси-сервер)
- DeepSeek API (модель deepseek-chat V3)
diff --git a/package.json b/package.json
index c5f4ac1..c5d3749 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "resekai",
"private": true,
- "version": "0.0.0",
+ "version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/src/components/Footer.css b/src/components/Footer.css
index acd8e1a..322be92 100644
--- a/src/components/Footer.css
+++ b/src/components/Footer.css
@@ -26,6 +26,14 @@
color: #888;
}
+.footer-version {
+ font-size: 0.75rem;
+ color: #555;
+ padding: 0.15rem 0.5rem;
+ background: rgba(255, 255, 255, 0.05);
+ border-radius: 4px;
+}
+
.footer-copyright {
font-size: 0.8rem;
color: #555;
diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx
index a2ea5f1..f0755ae 100644
--- a/src/components/Footer.tsx
+++ b/src/components/Footer.tsx
@@ -30,6 +30,7 @@ export function Footer() {
⚔️ ReSekai
+ v{__APP_VERSION__}
© 2026
diff --git a/src/pages/GamePage.tsx b/src/pages/GamePage.tsx
index b59c524..7cbdfd3 100644
--- a/src/pages/GamePage.tsx
+++ b/src/pages/GamePage.tsx
@@ -88,11 +88,11 @@ export default function GamePage() {
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
if (hasUnsavedChangesRef.current || isLoading) {
e.preventDefault();
- e.returnValue = '';
+ e.returnValue = "";
}
};
- window.addEventListener('beforeunload', handleBeforeUnload);
- return () => window.removeEventListener('beforeunload', handleBeforeUnload);
+ window.addEventListener("beforeunload", handleBeforeUnload);
+ return () => window.removeEventListener("beforeunload", handleBeforeUnload);
}, [isLoading]);
// Throttled streaming update (every 50ms instead of every chunk)
diff --git a/src/services/deepseek.ts b/src/services/deepseek.ts
index c76aa52..c259d2e 100644
--- a/src/services/deepseek.ts
+++ b/src/services/deepseek.ts
@@ -271,7 +271,10 @@ ${story.plot}`;
/**
* Builds dynamic context (state + summary + rule reminders)
*/
-export function buildDynamicContext(session: GameSession, messageCount?: number): string {
+export function buildDynamicContext(
+ session: GameSession,
+ messageCount?: number,
+): string {
const state = session.currentState;
const summary = session.storySummary || "The story just began.";
const keyEvents = session.keyEvents?.length
@@ -279,13 +282,16 @@ export function buildDynamicContext(session: GameSession, messageCount?: number)
: "No significant events yet.";
// Add rule reminders after 10+ messages to prevent drift
- const ruleReminder = (messageCount && messageCount >= 10) ? `
+ const ruleReminder =
+ messageCount && messageCount >= 10
+ ? `
=== REMINDER ===
• Do NOT act for the player — only describe reactions and consequences
• Do NOT ask "What do you do?" — end with atmosphere, not questions
• Format dialogue: **"text"** (double asterisks = bold)
-• React to player's words explicitly` : '';
+• React to player's words explicitly`
+ : "";
return `
=== CURRENT STATE ===
@@ -327,7 +333,9 @@ export async function generateStoryResponse(
const worldContext = buildWorldContext(story);
// 3. Dynamic context (state + summary + rule reminders after 10+ messages)
- const dynamicContext = session ? buildDynamicContext(session, chatHistory.length) : "";
+ const dynamicContext = session
+ ? buildDynamicContext(session, chatHistory.length)
+ : "";
// 4. Last N messages (not the full history!)
const recentMessages = chatHistory.slice(-RECENT_MESSAGES_COUNT);
@@ -362,7 +370,9 @@ export async function generateStoryResponseStream(
): Promise
{
const styleRules = buildStyleRules(story, player);
const worldContext = buildWorldContext(story);
- const dynamicContext = session ? buildDynamicContext(session, chatHistory.length) : "";
+ const dynamicContext = session
+ ? buildDynamicContext(session, chatHistory.length)
+ : "";
const recentMessages = chatHistory.slice(-RECENT_MESSAGES_COUNT);
const systemPrompt = styleRules + "\n" + worldContext + "\n" + dynamicContext;
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
new file mode 100644
index 0000000..dbb4c62
--- /dev/null
+++ b/src/vite-env.d.ts
@@ -0,0 +1,3 @@
+///
+
+declare const __APP_VERSION__: string;
diff --git a/vite.config.ts b/vite.config.ts
index 8b0f57b..df04b69 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,7 +1,13 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
+import { readFileSync } from 'fs'
+
+const pkg = JSON.parse(readFileSync('./package.json', 'utf-8'))
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
+ define: {
+ __APP_VERSION__: JSON.stringify(pkg.version),
+ },
})