AnesKAM commited on
Commit
2a51ba7
·
verified ·
1 Parent(s): 501607d

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +435 -152
index.html CHANGED
@@ -3,32 +3,38 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>MiniMax + Kimi Dual AI</title>
7
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
 
8
  <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
9
 
10
  <style>
11
  :root {
12
  --bg: #0d1117;
13
  --sidebar: #161b22;
14
- --fast: #ff6b6b; /* أحمر مميز لـ MiniMax */
15
- --think: #a371f7; /* بنفسجي لـ Kimi */
16
  --border: #30363d;
17
- --text: #c9d1d9;
 
 
 
 
18
  }
19
 
20
  * { box-sizing: border-box; margin: 0; padding: 0; }
 
21
  body {
22
  background: var(--bg);
23
  color: var(--text);
24
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
25
  display: flex;
26
  height: 100vh;
27
  overflow: hidden;
 
28
  }
29
 
30
  .sidebar {
31
- width: 280px;
32
  background: var(--sidebar);
33
  border-left: 1px solid var(--border);
34
  padding: 24px;
@@ -36,201 +42,403 @@
36
  flex-direction: column;
37
  }
38
 
39
- .brand { font-size: 22px; font-weight: 800; color: white; margin-bottom: 30px; }
 
 
 
 
 
 
 
 
40
 
41
  .mode-selector {
42
  display: flex;
43
- gap: 10px;
44
- margin-bottom: 20px;
45
  background: var(--bg);
46
  padding: 4px;
47
  border-radius: 8px;
48
  border: 1px solid var(--border);
 
49
  }
50
 
51
  .mode-btn {
52
  flex: 1;
53
- padding: 10px;
54
  border: none;
55
  border-radius: 6px;
56
- cursor: pointer;
 
57
  font-size: 13px;
58
  font-weight: 600;
59
- transition: 0.2s;
60
- background: transparent;
61
- color: var(--text);
 
 
 
62
  }
63
 
64
- .mode-btn.active.fast { background: var(--fast); color: white; }
65
- .mode-btn.active.think { background: var(--think); color: white; }
 
 
 
 
 
 
 
 
 
66
 
67
- .model-status {
68
- font-size: 12px;
69
- padding: 12px;
70
- border-radius: 8px;
71
- margin-bottom: 20px;
 
 
72
  line-height: 1.6;
73
  }
74
- .model-status.fast { background: rgba(255,107,107,0.1); border: 1px solid var(--fast); }
75
- .model-status.think { background: rgba(163,113,247,0.1); border: 1px solid var(--think); }
76
 
77
- .chat-container { flex: 1; display: flex; flex-direction: column; position: relative; }
78
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  #chat-flow {
80
  flex: 1;
81
- padding: 40px 15% 120px;
82
  overflow-y: auto;
83
  display: flex;
84
  flex-direction: column;
85
- gap: 24px;
86
  }
87
 
88
  .message {
89
  display: flex;
90
  gap: 16px;
91
- max-width: 85%;
92
  animation: fadeIn 0.3s ease;
93
  }
94
 
95
- @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
 
 
 
96
 
97
  .message.user { align-self: flex-end; flex-direction: row-reverse; }
98
- .message.ai { align-self: flex-start; }
99
 
100
  .avatar {
101
- width: 36px; height: 36px; border-radius: 8px;
 
102
  display: flex; align-items: center; justify-content: center;
103
  flex-shrink: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  }
105
- .message.fast .avatar { background: var(--fast); color: white; }
106
- .message.think .avatar { background: var(--think); color: white; }
107
 
108
- .thinking .avatar { animation: pulse 2s infinite; }
109
  @keyframes pulse {
110
- 0%, 100% { box-shadow: 0 0 0 0 rgba(163,113,247,0.4); }
111
- 50% { box-shadow: 0 0 0 10px rgba(163,113,247,0); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  }
113
 
114
- .bubble {
115
- padding: 16px; border-radius: 12px; line-height: 1.6;
116
- border: 1px solid var(--border); word-wrap: break-word;
117
  }
118
- .user .bubble { background: #21262d; }
119
- .ai.fast .bubble { border-color: var(--fast); }
120
- .ai.think .bubble { border-color: var(--think); }
121
 
122
- .thinking-indicator {
123
- display: flex; align-items: center; gap: 8px;
124
- color: var(--think); font-size: 13px; margin-bottom: 8px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
126
- .thinking-indicator i { animation: spin 1s linear infinite; }
127
- @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
128
 
 
129
  .input-wrapper {
130
  position: absolute;
131
  bottom: 30px;
132
  left: 50%;
133
  transform: translateX(-50%);
134
- width: 75%; max-width: 800px;
 
135
  background: var(--sidebar);
136
  border: 1px solid var(--border);
137
- border-radius: 12px;
138
- padding: 12px;
139
- display: flex; align-items: center; gap: 12px;
 
 
 
140
  }
141
 
142
  #userInput {
143
- flex: 1; background: transparent; border: none;
144
- color: white; padding: 10px; font-size: 16px; outline: none;
 
 
 
 
 
 
145
  }
146
 
147
  .send-btn {
148
- width: 36px; height: 36px; border-radius: 6px;
149
- border: none; cursor: pointer; color: white; transition: 0.2s;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  }
151
- .send-btn.fast { background: var(--fast); }
152
- .send-btn.think { background: var(--think); }
153
- .send-btn:disabled { background: #30363d !important; cursor: not-allowed; }
154
 
155
- .model-badge {
156
- font-size: 11px; padding: 2px 8px; border-radius: 4px;
157
- background: rgba(255,255,255,0.1); margin-bottom: 6px; display: inline-block;
 
 
 
158
  }
 
 
 
 
 
 
 
 
159
  </style>
160
  </head>
161
  <body>
162
 
163
  <aside class="sidebar">
164
- <div class="brand"><i class="fas fa-robot"></i> MiniMax + Kimi</div>
 
 
 
165
 
166
  <div class="mode-selector">
167
- <button class="mode-btn fast active" onclick="setMode('fast')">
168
- <i class="fas fa-bolt"></i> ⚡ سريع
 
169
  </button>
170
- <button class="mode-btn think" onclick="setMode('think')">
171
- <i class="fas fa-brain"></i> 🧠 مفكر
 
172
  </button>
173
  </div>
174
 
175
- <div class="model-status fast" id="modelStatus">
176
- <strong> MiniMax M2.5</strong><br>
177
- Hugging Face Space<br>
178
- ردود فورية بدون تفكير
179
- </div>
180
-
181
- <div style="margin-top: auto; font-size: 11px; color: #8b949e;">
182
- <div id="currentMode">الوضع الحالي: MiniMax (HF)</div>
183
  </div>
184
  </aside>
185
 
186
  <main class="chat-container">
187
  <div id="chat-flow">
188
- <div class="message ai fast">
189
  <div class="avatar"><i class="fas fa-robot"></i></div>
190
- <div>
191
- <div class="model-badge">MiniMax-M2.5-Chat</div>
192
- <div class="bubble">
193
- مرحباً! اختر الوضع:<br><br>
194
- <strong>MiniMax M2.5:</strong> ردود سريعة من Hugging Face<br>
195
- 🧠 <strong>Kimi K2.5:</strong> تحليل عميق مع تفكير
 
 
 
 
 
 
 
 
 
 
196
  </div>
197
  </div>
198
  </div>
199
  </div>
200
 
201
  <div class="input-wrapper">
202
- <input type="text" id="userInput" placeholder="اكتب رسالتك..." autocomplete="off">
203
- <button class="send-btn fast" id="sendBtn" onclick="handleSend()">
204
  <i class="fas fa-paper-plane"></i>
205
  </button>
206
  </div>
207
  </main>
208
 
209
  <script>
210
- let currentMode = 'fast';
211
 
212
  function setMode(mode) {
213
  currentMode = mode;
214
  document.querySelectorAll('.mode-btn').forEach(btn => btn.classList.remove('active'));
215
  document.querySelector(`.mode-btn.${mode}`).classList.add('active');
216
 
217
- const status = document.getElementById('modelStatus');
218
  const btn = document.getElementById('sendBtn');
219
- const current = document.getElementById('currentMode');
220
 
221
- if (mode === 'fast') {
222
- status.className = 'model-status fast';
223
- status.innerHTML = '<strong>⚡ MiniMax M2.5</strong><br>Hugging Face Space<br>ردود فورية بدون تفكير';
224
- btn.className = 'send-btn fast';
225
- current.textContent = 'الوضع الحالي: MiniMax (HF)';
226
- } else {
227
- status.className = 'model-status think';
228
- status.innerHTML = '<strong>🧠 Kimi K2.5 FW</strong><br>Poe API<br>مع تفكير وتحليل عميق';
229
  btn.className = 'send-btn think';
230
- current.textContent = 'الوضع الحالي: Kimi (Poe)';
 
 
 
231
  }
232
  }
233
 
 
 
 
 
 
234
  async function handleSend() {
235
  const input = document.getElementById('userInput');
236
  const btn = document.getElementById('sendBtn');
@@ -243,10 +451,10 @@
243
  input.disabled = true;
244
  btn.disabled = true;
245
 
246
- if (currentMode === 'fast') {
247
- await sendFast(text);
248
  } else {
249
- await sendThink(text);
250
  }
251
 
252
  input.disabled = false;
@@ -254,53 +462,136 @@
254
  input.focus();
255
  }
256
 
257
- // ✅ الوضع السريع: MiniMax عبر الباكاند
258
- async function sendFast(text) {
259
- const msgId = addMessage('', 'ai', 'fast');
260
- const container = document.getElementById(msgId);
261
- const bubble = container.querySelector('.bubble');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
 
263
- bubble.innerHTML = '<i class="fas fa-circle-notch fa-spin"></i> MiniMax يكتب...';
 
264
 
 
 
 
 
 
265
  try {
266
- const response = await fetch('/api/fast', {
267
  method: 'POST',
268
  headers: { 'Content-Type': 'application/json' },
269
  body: JSON.stringify({ message: text })
270
  });
271
-
272
- const data = await response.json();
273
-
274
- if (data.success) {
275
- bubble.innerHTML = marked.parse(data.content);
276
- } else {
277
- throw new Error(data.error);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  }
279
 
 
 
 
 
280
  } catch (err) {
281
- bubble.innerHTML = `<span style="color:#f85149">خطأ في MiniMax: ${err.message}</span>`;
 
282
  }
283
  }
284
 
285
- // الوضع المفكر: Kimi (Streaming)
286
- async function sendThink(text) {
287
- const msgId = addMessage('', 'ai', 'think');
288
- const msgElement = document.getElementById(msgId);
289
- const bubble = msgElement.querySelector('.bubble');
 
 
 
 
 
 
 
 
 
 
 
290
 
291
- msgElement.classList.add('thinking');
292
- const indicator = document.createElement('div');
293
- indicator.className = 'thinking-indicator';
294
- indicator.innerHTML = '<i class="fas fa-circle-notch"></i> يفكر...';
295
- bubble.parentNode.insertBefore(indicator, bubble);
296
-
297
  try {
298
- const res = await fetch('/api/think', {
299
  method: 'POST',
300
  headers: { 'Content-Type': 'application/json' },
301
  body: JSON.stringify({ message: text })
302
  });
303
-
304
  const reader = res.body.getReader();
305
  const decoder = new TextDecoder();
306
  let fullText = "";
@@ -319,47 +610,39 @@
319
 
320
  try {
321
  const json = JSON.parse(data);
322
- if (json.status === 'responding') {
323
- indicator.style.display = 'none';
324
- msgElement.classList.remove('thinking');
325
- }
326
- if (json.content) {
327
  fullText += json.content;
328
- bubble.innerHTML = marked.parse(fullText);
 
329
  }
330
  } catch (e) {}
331
  }
332
  }
 
 
 
 
333
  } catch (err) {
334
  bubble.innerHTML = `<span style="color:#f85149">خطأ: ${err.message}</span>`;
335
- } finally {
336
- indicator.style.display = 'none';
337
- msgElement.classList.remove('thinking');
338
  }
339
  }
340
 
341
- function addMessage(text, role, mode = 'fast') {
342
- const flow = document.getElementById('chat-flow');
343
- const id = 'msg-' + Date.now();
344
- const icon = role === 'user' ? 'fa-user' : 'fa-robot';
345
- const modeClass = role === 'ai' ? mode : '';
346
-
347
- const badge = role === 'ai' ?
348
- `<div class="model-badge">${mode === 'fast' ? 'MiniMax-M2.5' : 'Kimi K2.5'}</div>` : '';
349
-
350
  const html = `
351
- <div class="message ${role} ${modeClass}" id="${id}">
352
- <div class="avatar"><i class="fas ${icon}"></i></div>
353
- <div style="max-width: 100%;">
354
- ${badge}
355
- <div class="bubble">${text}</div>
356
  </div>
 
357
  </div>
358
  `;
359
-
360
- flow.insertAdjacentHTML('beforeend', html);
 
 
 
 
361
  flow.scrollTop = flow.scrollHeight;
362
- return id;
363
  }
364
 
365
  document.getElementById('userInput').addEventListener('keypress', (e) => {
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Kimi Reasoning Interface</title>
7
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
8
+ <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
9
  <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
10
 
11
  <style>
12
  :root {
13
  --bg: #0d1117;
14
  --sidebar: #161b22;
15
+ --surface: #21262d;
 
16
  --border: #30363d;
17
+ --text: #e6edf3;
18
+ --text-secondary: #8b949e;
19
+ --accent-think: #a371f7; /* بنفسجي للتفكير */
20
+ --accent-fast: #238636; /* أخضر للسريع */
21
+ --reasoning-bg: #1f242c; /* خلفية صندوق التفكير */
22
  }
23
 
24
  * { box-sizing: border-box; margin: 0; padding: 0; }
25
+
26
  body {
27
  background: var(--bg);
28
  color: var(--text);
29
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
30
  display: flex;
31
  height: 100vh;
32
  overflow: hidden;
33
+ line-height: 1.6;
34
  }
35
 
36
  .sidebar {
37
+ width: 300px;
38
  background: var(--sidebar);
39
  border-left: 1px solid var(--border);
40
  padding: 24px;
 
42
  flex-direction: column;
43
  }
44
 
45
+ .brand {
46
+ font-size: 20px;
47
+ font-weight: 700;
48
+ margin-bottom: 32px;
49
+ display: flex;
50
+ align-items: center;
51
+ gap: 12px;
52
+ color: white;
53
+ }
54
 
55
  .mode-selector {
56
  display: flex;
57
+ gap: 8px;
 
58
  background: var(--bg);
59
  padding: 4px;
60
  border-radius: 8px;
61
  border: 1px solid var(--border);
62
+ margin-bottom: 24px;
63
  }
64
 
65
  .mode-btn {
66
  flex: 1;
67
+ padding: 10px 14px;
68
  border: none;
69
  border-radius: 6px;
70
+ background: transparent;
71
+ color: var(--text-secondary);
72
  font-size: 13px;
73
  font-weight: 600;
74
+ cursor: pointer;
75
+ transition: all 0.2s;
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ gap: 6px;
80
  }
81
 
82
+ .mode-btn.active.think {
83
+ background: rgba(163, 113, 247, 0.15);
84
+ color: var(--accent-think);
85
+ box-shadow: 0 0 0 1px rgba(163, 113, 247, 0.3);
86
+ }
87
+
88
+ .mode-btn.active.fast {
89
+ background: rgba(35, 134, 54, 0.15);
90
+ color: var(--accent-fast);
91
+ box-shadow: 0 0 0 1px rgba(35, 134, 54, 0.3);
92
+ }
93
 
94
+ .info-card {
95
+ background: rgba(163, 113, 247, 0.08);
96
+ border: 1px solid rgba(163, 113, 247, 0.2);
97
+ border-radius: 12px;
98
+ padding: 16px;
99
+ font-size: 13px;
100
+ color: var(--text-secondary);
101
  line-height: 1.6;
102
  }
 
 
103
 
104
+ .info-card h4 {
105
+ color: var(--accent-think);
106
+ margin-bottom: 8px;
107
+ font-size: 14px;
108
+ display: flex;
109
+ align-items: center;
110
+ gap: 8px;
111
+ }
112
+
113
+ .chat-container {
114
+ flex: 1;
115
+ display: flex;
116
+ flex-direction: column;
117
+ position: relative;
118
+ background: var(--bg);
119
+ }
120
+
121
  #chat-flow {
122
  flex: 1;
123
+ padding: 40px 10% 140px;
124
  overflow-y: auto;
125
  display: flex;
126
  flex-direction: column;
127
+ gap: 32px;
128
  }
129
 
130
  .message {
131
  display: flex;
132
  gap: 16px;
133
+ max-width: 90%;
134
  animation: fadeIn 0.3s ease;
135
  }
136
 
137
+ @keyframes fadeIn {
138
+ from { opacity: 0; transform: translateY(10px); }
139
+ to { opacity: 1; transform: translateY(0); }
140
+ }
141
 
142
  .message.user { align-self: flex-end; flex-direction: row-reverse; }
143
+ .message.ai { align-self: flex-start; width: 100%; }
144
 
145
  .avatar {
146
+ width: 36px; height: 36px;
147
+ border-radius: 8px;
148
  display: flex; align-items: center; justify-content: center;
149
  flex-shrink: 0;
150
+ font-size: 16px;
151
+ }
152
+
153
+ .user .avatar { background: #1f6feb; color: white; }
154
+ .ai.think .avatar {
155
+ background: var(--accent-think);
156
+ color: white;
157
+ box-shadow: 0 0 0 2px rgba(163, 113, 247, 0.3);
158
+ }
159
+ .ai.fast .avatar { background: var(--accent-fast); color: white; }
160
+
161
+ /* ✅ صندوق التفكير (Reasoning Box) */
162
+ .reasoning-container {
163
+ background: var(--reasoning-bg);
164
+ border: 1px solid var(--border);
165
+ border-radius: 12px;
166
+ margin-bottom: 12px;
167
+ overflow: hidden;
168
+ font-family: 'JetBrains Mono', monospace;
169
+ font-size: 13px;
170
+ }
171
+
172
+ .reasoning-header {
173
+ padding: 12px 16px;
174
+ background: rgba(163, 113, 247, 0.1);
175
+ border-bottom: 1px solid var(--border);
176
+ display: flex;
177
+ align-items: center;
178
+ justify-content: space-between;
179
+ cursor: pointer;
180
+ user-select: none;
181
+ transition: background 0.2s;
182
+ }
183
+
184
+ .reasoning-header:hover {
185
+ background: rgba(163, 113, 247, 0.15);
186
+ }
187
+
188
+ .reasoning-title {
189
+ display: flex;
190
+ align-items: center;
191
+ gap: 10px;
192
+ color: var(--accent-think);
193
+ font-weight: 600;
194
+ font-family: 'Inter', sans-serif;
195
+ }
196
+
197
+ .reasoning-icon {
198
+ animation: pulse 2s infinite;
199
  }
 
 
200
 
 
201
  @keyframes pulse {
202
+ 0%, 100% { opacity: 1; }
203
+ 50% { opacity: 0.5; }
204
+ }
205
+
206
+ .reasoning-toggle {
207
+ color: var(--text-secondary);
208
+ transition: transform 0.3s;
209
+ font-size: 12px;
210
+ }
211
+
212
+ .reasoning-container.expanded .reasoning-toggle {
213
+ transform: rotate(180deg);
214
+ }
215
+
216
+ .reasoning-content {
217
+ padding: 16px;
218
+ color: var(--text-secondary);
219
+ line-height: 1.7;
220
+ max-height: 0;
221
+ overflow: hidden;
222
+ transition: max-height 0.3s ease, padding 0.3s;
223
+ white-space: pre-wrap;
224
+ overflow-y: auto;
225
+ }
226
+
227
+ .reasoning-container.expanded .reasoning-content {
228
+ max-height: 400px;
229
+ padding: 16px;
230
  }
231
 
232
+ .reasoning-content.streaming {
233
+ max-height: 400px;
234
+ padding: 16px;
235
  }
 
 
 
236
 
237
+ /* ✅ فقاعة الجواب النهائي */
238
+ .answer-bubble {
239
+ background: var(--surface);
240
+ border: 1px solid var(--border);
241
+ border-radius: 12px;
242
+ padding: 20px;
243
+ line-height: 1.8;
244
+ font-size: 15px;
245
+ position: relative;
246
+ }
247
+
248
+ .answer-bubble::before {
249
+ content: "الإجابة النهائية";
250
+ position: absolute;
251
+ top: -10px;
252
+ right: 16px;
253
+ background: var(--bg);
254
+ padding: 0 8px;
255
+ font-size: 11px;
256
+ color: var(--accent-think);
257
+ font-weight: 600;
258
+ border: 1px solid var(--border);
259
+ border-radius: 4px;
260
+ }
261
+
262
+ .bubble.user {
263
+ background: var(--surface);
264
+ border: 1px solid var(--border);
265
+ padding: 14px 18px;
266
+ border-radius: 12px;
267
  }
 
 
268
 
269
+ /* Input */
270
  .input-wrapper {
271
  position: absolute;
272
  bottom: 30px;
273
  left: 50%;
274
  transform: translateX(-50%);
275
+ width: 80%;
276
+ max-width: 900px;
277
  background: var(--sidebar);
278
  border: 1px solid var(--border);
279
+ border-radius: 16px;
280
+ padding: 14px;
281
+ display: flex;
282
+ align-items: center;
283
+ gap: 12px;
284
+ box-shadow: 0 8px 32px rgba(0,0,0,0.4);
285
  }
286
 
287
  #userInput {
288
+ flex: 1;
289
+ background: transparent;
290
+ border: none;
291
+ color: white;
292
+ padding: 10px;
293
+ font-size: 16px;
294
+ outline: none;
295
+ font-family: inherit;
296
  }
297
 
298
  .send-btn {
299
+ width: 36px; height: 36px;
300
+ border-radius: 8px;
301
+ border: none;
302
+ cursor: pointer;
303
+ color: white;
304
+ transition: all 0.2s;
305
+ display: flex; align-items: center; justify-content: center;
306
+ }
307
+
308
+ .send-btn.think { background: var(--accent-think); }
309
+ .send-btn.fast { background: var(--accent-fast); }
310
+ .send-btn:disabled {
311
+ background: #30363d !important;
312
+ cursor: not-allowed;
313
+ opacity: 0.6;
314
+ }
315
+
316
+ .typing-cursor {
317
+ display: inline-block;
318
+ width: 2px;
319
+ height: 18px;
320
+ background: var(--accent-think);
321
+ animation: blink 1s infinite;
322
+ vertical-align: middle;
323
+ margin-right: 4px;
324
+ }
325
+
326
+ @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
327
+
328
+ /* Markdown Styles */
329
+ .answer-bubble pre {
330
+ background: #161b22;
331
+ padding: 16px;
332
+ border-radius: 8px;
333
+ overflow-x: auto;
334
+ margin: 12px 0;
335
+ border: 1px solid var(--border);
336
+ font-family: 'JetBrains Mono', monospace;
337
+ font-size: 13px;
338
  }
 
 
 
339
 
340
+ .answer-bubble code {
341
+ font-family: 'JetBrains Mono', monospace;
342
+ background: rgba(255,255,255,0.1);
343
+ padding: 2px 6px;
344
+ border-radius: 4px;
345
+ font-size: 13px;
346
  }
347
+
348
+ .answer-bubble p { margin-bottom: 12px; }
349
+ .answer-bubble p:last-child { margin-bottom: 0; }
350
+
351
+ ::-webkit-scrollbar { width: 8px; }
352
+ ::-webkit-scrollbar-track { background: var(--bg); }
353
+ ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
354
+ ::-webkit-scrollbar-thumb:hover { background: #484f58; }
355
  </style>
356
  </head>
357
  <body>
358
 
359
  <aside class="sidebar">
360
+ <div class="brand">
361
+ <i class="fas fa-brain"></i>
362
+ <span>Kimi Reasoning</span>
363
+ </div>
364
 
365
  <div class="mode-selector">
366
+ <button class="mode-btn think active" onclick="setMode('think')">
367
+ <i class="fas fa-brain"></i>
368
+ <span>وضيف التفكير</span>
369
  </button>
370
+ <button class="mode-btn fast" onclick="setMode('fast')">
371
+ <i class="fas fa-bolt"></i>
372
+ <span>سريع</span>
373
  </button>
374
  </div>
375
 
376
+ <div class="info-card">
377
+ <h4><i class="fas fa-lightbulb"></i> مميزات وضيف التفكير</h4>
378
+ يعرض خطوات التفكير المنطقي<br>
379
+ • يحل المسائل المعقدة خطوة بخطوة<br>
380
+ • يُظهر صندوق "🧠 عرض التفكير" قابل للطي
 
 
 
381
  </div>
382
  </aside>
383
 
384
  <main class="chat-container">
385
  <div id="chat-flow">
386
+ <div class="message ai think">
387
  <div class="avatar"><i class="fas fa-robot"></i></div>
388
+ <div style="flex: 1;">
389
+ <!-- ✅ مثال على صندوق التفكير -->
390
+ <div class="reasoning-container expanded">
391
+ <div class="reasoning-header" onclick="toggleReasoning(this)">
392
+ <div class="reasoning-title">
393
+ <i class="fas fa-circle-notch reasoning-icon fa-spin"></i>
394
+ <span>جاري التفكير...</span>
395
+ </div>
396
+ <i class="fas fa-chevron-down reasoning-toggle"></i>
397
+ </div>
398
+ <div class="reasoning-content streaming">
399
+ انتظر رسالتك لأبدأ التفكير فيها خطوة بخطوة...
400
+ </div>
401
+ </div>
402
+ <div class="answer-bubble">
403
+ مرحباً! أنا Kimi K2.5 في وضيف التفكير. سأُظهر لك كيف أفكر قبل أن أُعطيك الإجابة النهائية.
404
  </div>
405
  </div>
406
  </div>
407
  </div>
408
 
409
  <div class="input-wrapper">
410
+ <input type="text" id="userInput" placeholder="اكتب سؤالاً يحتاج تفكيراً عميقاً..." autocomplete="off">
411
+ <button class="send-btn think" id="sendBtn" onclick="handleSend()">
412
  <i class="fas fa-paper-plane"></i>
413
  </button>
414
  </div>
415
  </main>
416
 
417
  <script>
418
+ let currentMode = 'think';
419
 
420
  function setMode(mode) {
421
  currentMode = mode;
422
  document.querySelectorAll('.mode-btn').forEach(btn => btn.classList.remove('active'));
423
  document.querySelector(`.mode-btn.${mode}`).classList.add('active');
424
 
 
425
  const btn = document.getElementById('sendBtn');
426
+ const input = document.getElementById('userInput');
427
 
428
+ if (mode === 'think') {
 
 
 
 
 
 
 
429
  btn.className = 'send-btn think';
430
+ input.placeholder = "اكتب سؤالاً يحتاج تفكيراً عميقاً...";
431
+ } else {
432
+ btn.className = 'send-btn fast';
433
+ input.placeholder = "اكتب رسالتك السريعة...";
434
  }
435
  }
436
 
437
+ function toggleReasoning(header) {
438
+ const container = header.parentElement;
439
+ container.classList.toggle('expanded');
440
+ }
441
+
442
  async function handleSend() {
443
  const input = document.getElementById('userInput');
444
  const btn = document.getElementById('sendBtn');
 
451
  input.disabled = true;
452
  btn.disabled = true;
453
 
454
+ if (currentMode === 'think') {
455
+ await sendWithReasoning(text);
456
  } else {
457
+ await sendFast(text);
458
  }
459
 
460
  input.disabled = false;
 
462
  input.focus();
463
  }
464
 
465
+ // ✅ الوضيف المتقدم: عرض التفكير + الإجابة
466
+ async function sendWithReasoning(text) {
467
+ const msgId = 'msg-' + Date.now();
468
+ const html = `
469
+ <div class="message ai think" id="${msgId}">
470
+ <div class="avatar"><i class="fas fa-robot"></i></div>
471
+ <div style="flex: 1;">
472
+ <div class="reasoning-container expanded" id="reasoning-${msgId}">
473
+ <div class="reasoning-header" onclick="toggleReasoning(this)">
474
+ <div class="reasoning-title">
475
+ <i class="fas fa-circle-notch reasoning-icon fa-spin" id="icon-${msgId}"></i>
476
+ <span id="title-${msgId}">جاري التفكير...</span>
477
+ </div>
478
+ <i class="fas fa-chevron-down reasoning-toggle"></i>
479
+ </div>
480
+ <div class="reasoning-content streaming" id="reasoning-content-${msgId}">
481
+ <span class="typing-cursor"></span>
482
+ </div>
483
+ </div>
484
+ <div class="answer-bubble" id="answer-${msgId}" style="display: none;">
485
+ <span class="typing-cursor"></span>
486
+ </div>
487
+ </div>
488
+ </div>
489
+ `;
490
 
491
+ document.getElementById('chat-flow').insertAdjacentHTML('beforeend', html);
492
+ scrollToBottom();
493
 
494
+ const reasoningContent = document.getElementById(`reasoning-content-${msgId}`);
495
+ const answerBubble = document.getElementById(`answer-${msgId}`);
496
+ const titleText = document.getElementById(`title-${msgId}`);
497
+ const icon = document.getElementById(`icon-${msgId}`);
498
+
499
  try {
500
+ const res = await fetch('/api/think', {
501
  method: 'POST',
502
  headers: { 'Content-Type': 'application/json' },
503
  body: JSON.stringify({ message: text })
504
  });
505
+
506
+ const reader = res.body.getReader();
507
+ const decoder = new TextDecoder();
508
+ let reasoningText = "";
509
+ let answerText = "";
510
+ let isAnswering = false;
511
+
512
+ while (true) {
513
+ const { done, value } = await reader.read();
514
+ if (done) break;
515
+
516
+ const chunk = decoder.decode(value);
517
+ const lines = chunk.split('\n');
518
+
519
+ for (const line of lines) {
520
+ if (!line.startsWith('data: ')) continue;
521
+ const data = line.replace('data: ', '').trim();
522
+ if (data === '[DONE]') break;
523
+
524
+ try {
525
+ const json = JSON.parse(data);
526
+
527
+ if (json.type === 'reasoning') {
528
+ // ✅ عرض نص التفكير
529
+ reasoningText += json.content;
530
+ reasoningContent.innerHTML = reasoningText + '<span class="typing-cursor"></span>';
531
+ scrollToBottom();
532
+ }
533
+ else if (json.type === 'content') {
534
+ // ✅ الانتقال للإجابة النهائية
535
+ if (!isAnswering) {
536
+ isAnswering = true;
537
+ titleText.textContent = "اكتمل التفكير";
538
+ icon.className = "fas fa-check reasoning-icon";
539
+ icon.style.color = "var(--accent-think)";
540
+
541
+ // إخفا�� صندوق التفكير تلقائياً بعد ثانية (اختياري)
542
+ setTimeout(() => {
543
+ document.getElementById(`reasoning-${msgId}`).classList.remove('expanded');
544
+ }, 1000);
545
+
546
+ answerBubble.style.display = 'block';
547
+ }
548
+
549
+ answerText += json.content;
550
+ answerBubble.innerHTML = marked.parse(answerText) + '<span class="typing-cursor"></span>';
551
+ scrollToBottom();
552
+ }
553
+ else if (json.type === 'error') {
554
+ answerBubble.style.display = 'block';
555
+ answerBubble.innerHTML = `<span style="color:#f85149">${json.error}</span>`;
556
+ }
557
+ } catch (e) {}
558
+ }
559
  }
560
 
561
+ // إزالة المؤشر النهائي
562
+ const cursor = answerBubble.querySelector('.typing-cursor');
563
+ if (cursor) cursor.remove();
564
+
565
  } catch (err) {
566
+ answerBubble.style.display = 'block';
567
+ answerBubble.innerHTML = `<span style="color:#f85149">فشل الاتصال: ${err.message}</span>`;
568
  }
569
  }
570
 
571
+ // الوضع السريع (بدون تفكير مرئي)
572
+ async function sendFast(text) {
573
+ const msgId = 'msg-' + Date.now();
574
+ const html = `
575
+ <div class="message ai fast" id="${msgId}">
576
+ <div class="avatar"><i class="fas fa-robot"></i></div>
577
+ <div style="flex: 1;">
578
+ <div class="answer-bubble" id="answer-${msgId}">
579
+ <span class="typing-cursor"></span>
580
+ </div>
581
+ </div>
582
+ </div>
583
+ `;
584
+
585
+ document.getElementById('chat-flow').insertAdjacentHTML('beforeend', html);
586
+ const bubble = document.getElementById(`answer-${msgId}`);
587
 
 
 
 
 
 
 
588
  try {
589
+ const res = await fetch('/api/fast', {
590
  method: 'POST',
591
  headers: { 'Content-Type': 'application/json' },
592
  body: JSON.stringify({ message: text })
593
  });
594
+
595
  const reader = res.body.getReader();
596
  const decoder = new TextDecoder();
597
  let fullText = "";
 
610
 
611
  try {
612
  const json = JSON.parse(data);
613
+ if (json.type === 'content') {
 
 
 
 
614
  fullText += json.content;
615
+ bubble.innerHTML = marked.parse(fullText) + '<span class="typing-cursor"></span>';
616
+ scrollToBottom();
617
  }
618
  } catch (e) {}
619
  }
620
  }
621
+
622
+ const cursor = bubble.querySelector('.typing-cursor');
623
+ if (cursor) cursor.remove();
624
+
625
  } catch (err) {
626
  bubble.innerHTML = `<span style="color:#f85149">خطأ: ${err.message}</span>`;
 
 
 
627
  }
628
  }
629
 
630
+ function addMessage(text, role) {
 
 
 
 
 
 
 
 
631
  const html = `
632
+ <div class="message ${role}">
633
+ <div class="avatar">
634
+ <i class="fas ${role === 'user' ? 'fa-user' : 'fa-robot'}"></i>
 
 
635
  </div>
636
+ <div class="bubble ${role}">${text}</div>
637
  </div>
638
  `;
639
+ document.getElementById('chat-flow').insertAdjacentHTML('beforeend', html);
640
+ scrollToBottom();
641
+ }
642
+
643
+ function scrollToBottom() {
644
+ const flow = document.getElementById('chat-flow');
645
  flow.scrollTop = flow.scrollHeight;
 
646
  }
647
 
648
  document.getElementById('userInput').addEventListener('keypress', (e) => {