Shublub commited on
Commit
d115904
·
verified ·
1 Parent(s): 510cf95

Remove image support; inform users model does not support image input

Browse files
Files changed (2) hide show
  1. README.md +2 -2
  2. index.html +6 -68
README.md CHANGED
@@ -12,13 +12,13 @@ license: other
12
 
13
  A lightweight chat interface for [Moonshot AI's Kimi K3](https://huggingface.co/moonshotai/Kimi-K3) — a 2.8T-parameter native multimodal agentic model.
14
 
15
- Built with vanilla HTML/CSS/JS. No backend required — connects directly to the Kimi API from your browser.
16
 
17
  ## Usage
18
 
19
  1. Get an API key from [platform.kimi.ai](https://platform.kimi.ai)
20
  2. Enter it in the settings panel
21
- 3. Chat with text, images, or both
22
 
23
  ## Links
24
 
 
12
 
13
  A lightweight chat interface for [Moonshot AI's Kimi K3](https://huggingface.co/moonshotai/Kimi-K3) — a 2.8T-parameter native multimodal agentic model.
14
 
15
+ Built with vanilla HTML/CSS/JS. No backend required — connects directly to the Kimi API from your browser. Text only — this model does not support image input.
16
 
17
  ## Usage
18
 
19
  1. Get an API key from [platform.kimi.ai](https://platform.kimi.ai)
20
  2. Enter it in the settings panel
21
+ 3. Start chatting
22
 
23
  ## Links
24
 
index.html CHANGED
@@ -66,7 +66,6 @@
66
  padding: 8px 12px; border-radius: 6px; margin: 8px 0; font-size: 0.88em; color: #9999cc;
67
  }
68
  .msg .thinking-label { font-weight: 600; color: var(--primary); margin-bottom: 4px; font-size: 0.85em; }
69
- .msg img { max-width: 100%; max-height: 200px; border-radius: 8px; margin: 4px 0; }
70
  .typing { display: flex; gap: 4px; padding: 4px 0; }
71
  .typing span { width: 6px; height: 6px; background: var(--text-muted); border-radius: 50%; animation: bounce 1.4s infinite; }
72
  .typing span:nth-child(2) { animation-delay: 0.2s; }
@@ -88,13 +87,6 @@
88
  }
89
  .input-row button:hover { background: var(--primary-hover); }
90
  .input-row button:disabled { opacity: 0.5; cursor: not-allowed; }
91
- .input-row .image-btn {
92
- background: var(--surface-2); border: 1px solid var(--border); padding: 8px 10px;
93
- border-radius: 8px; cursor: pointer; font-size: 1.1em; line-height: 1; transition: 0.2s;
94
- }
95
- .input-row .image-btn:hover { border-color: var(--primary); }
96
- #imagePreview { display: none; max-width: 60px; max-height: 60px; border-radius: 6px; border: 1px solid var(--border); }
97
-
98
  pre { background: #1a1a2e; border: 1px solid var(--border); border-radius: 6px; padding: 8px 12px; overflow-x: auto; margin: 8px 0; font-size: 0.85em; }
99
  code { background: var(--surface-2); padding: 2px 4px; border-radius: 4px; font-size: 0.9em; }
100
  pre code { background: none; padding: 0; }
@@ -137,12 +129,9 @@
137
  <div class="chat">
138
  <div class="messages" id="messages">
139
  <div class="msg system">Welcome! Enter your Kimi API key above, then start chatting.</div>
140
- <div class="msg system">Kimi K3 supports text and images. Use the 📷 button to attach an image.</div>
141
  </div>
142
  <div class="input-row">
143
- <label class="image-btn" title="Attach image" id="imageLabel">📷</label>
144
- <input type="file" id="imageInput" accept="image/*" style="display:none" />
145
- <img id="imagePreview" />
146
  <textarea id="messageInput" placeholder="Type a message..." rows="1"></textarea>
147
  <button id="sendBtn">Send</button>
148
  </div>
@@ -163,14 +152,9 @@ const reasoningSelect = document.getElementById("reasoningEffort");
163
  const messagesEl = document.getElementById("messages");
164
  const messageInput = document.getElementById("messageInput");
165
  const sendBtn = document.getElementById("sendBtn");
166
- const imageInput = document.getElementById("imageInput");
167
- const imagePreview = document.getElementById("imagePreview");
168
- const imageLabel = document.getElementById("imageLabel");
169
  const statusDot = document.getElementById("statusDot");
170
  const statusText = document.getElementById("statusText");
171
 
172
- let selectedImage = null;
173
-
174
  apiKeyInput.addEventListener("input", () => {
175
  if (apiKeyInput.value.startsWith("sk-")) {
176
  statusDot.className = "status-dot on";
@@ -184,35 +168,6 @@ apiKeyInput.addEventListener("input", () => {
184
  }
185
  });
186
 
187
- imageLabel.addEventListener("click", () => imageInput.click());
188
- imageInput.addEventListener("change", (e) => {
189
- const file = e.target.files[0];
190
- if (file) {
191
- selectedImage = file;
192
- const reader = new FileReader();
193
- reader.onload = (ev) => { imagePreview.src = ev.target.result; imagePreview.style.display = "block"; };
194
- reader.readAsDataURL(file);
195
- imageLabel.textContent = "✕";
196
- } else {
197
- clearImage();
198
- }
199
- });
200
-
201
- imageLabel.addEventListener("click", (e) => {
202
- if (imageLabel.textContent === "✕") {
203
- e.preventDefault();
204
- clearImage();
205
- }
206
- });
207
-
208
- function clearImage() {
209
- selectedImage = null;
210
- imageInput.value = "";
211
- imagePreview.style.display = "none";
212
- imagePreview.src = "";
213
- imageLabel.textContent = "📷";
214
- }
215
-
216
  function addMessage(role, content, thinking) {
217
  const div = document.createElement("div");
218
  div.className = `msg ${role}`;
@@ -294,29 +249,19 @@ function markedParse(text) {
294
 
295
  async function sendMessage() {
296
  const text = messageInput.value.trim();
297
- if (!text && !selectedImage) return;
298
  const apiKey = apiKeyInput.value.trim();
299
  if (!apiKey || !apiKey.startsWith("sk-")) {
300
  addMessage("system", "Please enter a valid Kimi API key (sk-...) in the settings.");
301
  return;
302
  }
303
 
304
- addMessage("user", text || (selectedImage ? "[Image attached]" : ""));
305
  messageInput.value = "";
306
- const currentImage = selectedImage;
307
- clearImage();
308
  showTyping();
309
 
310
  try {
311
- const messages = [];
312
-
313
- const userContent = [];
314
- if (text) userContent.push({ type: "text", text });
315
- if (currentImage) {
316
- const b64 = await toBase64(currentImage);
317
- userContent.push({ type: "image_url", image_url: { url: b64 } });
318
- }
319
- messages.push({ role: "user", content: userContent });
320
 
321
  const response = await fetch(`${KIMI_API}/chat/completions`, {
322
  method: "POST",
@@ -388,20 +333,13 @@ async function sendMessage() {
388
  msg = "Invalid API key. Check your key at platform.kimi.ai.";
389
  } else if (msg.includes("402")) {
390
  msg = "Payment required. Add credits at platform.kimi.ai.";
 
 
391
  }
392
  addMessage("system", `Error: ${msg}`);
393
  }
394
  }
395
 
396
- function toBase64(file) {
397
- return new Promise((resolve, reject) => {
398
- const reader = new FileReader();
399
- reader.onload = () => resolve(reader.result);
400
- reader.onerror = reject;
401
- reader.readAsDataURL(file);
402
- });
403
- }
404
-
405
  sendBtn.addEventListener("click", sendMessage);
406
  messageInput.addEventListener("keydown", (e) => {
407
  if (e.key === "Enter" && !e.shiftKey) {
 
66
  padding: 8px 12px; border-radius: 6px; margin: 8px 0; font-size: 0.88em; color: #9999cc;
67
  }
68
  .msg .thinking-label { font-weight: 600; color: var(--primary); margin-bottom: 4px; font-size: 0.85em; }
 
69
  .typing { display: flex; gap: 4px; padding: 4px 0; }
70
  .typing span { width: 6px; height: 6px; background: var(--text-muted); border-radius: 50%; animation: bounce 1.4s infinite; }
71
  .typing span:nth-child(2) { animation-delay: 0.2s; }
 
87
  }
88
  .input-row button:hover { background: var(--primary-hover); }
89
  .input-row button:disabled { opacity: 0.5; cursor: not-allowed; }
 
 
 
 
 
 
 
90
  pre { background: #1a1a2e; border: 1px solid var(--border); border-radius: 6px; padding: 8px 12px; overflow-x: auto; margin: 8px 0; font-size: 0.85em; }
91
  code { background: var(--surface-2); padding: 2px 4px; border-radius: 4px; font-size: 0.9em; }
92
  pre code { background: none; padding: 0; }
 
129
  <div class="chat">
130
  <div class="messages" id="messages">
131
  <div class="msg system">Welcome! Enter your Kimi API key above, then start chatting.</div>
132
+ <div class="msg system">Text only. This model does not support image input.</div>
133
  </div>
134
  <div class="input-row">
 
 
 
135
  <textarea id="messageInput" placeholder="Type a message..." rows="1"></textarea>
136
  <button id="sendBtn">Send</button>
137
  </div>
 
152
  const messagesEl = document.getElementById("messages");
153
  const messageInput = document.getElementById("messageInput");
154
  const sendBtn = document.getElementById("sendBtn");
 
 
 
155
  const statusDot = document.getElementById("statusDot");
156
  const statusText = document.getElementById("statusText");
157
 
 
 
158
  apiKeyInput.addEventListener("input", () => {
159
  if (apiKeyInput.value.startsWith("sk-")) {
160
  statusDot.className = "status-dot on";
 
168
  }
169
  });
170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  function addMessage(role, content, thinking) {
172
  const div = document.createElement("div");
173
  div.className = `msg ${role}`;
 
249
 
250
  async function sendMessage() {
251
  const text = messageInput.value.trim();
252
+ if (!text) return;
253
  const apiKey = apiKeyInput.value.trim();
254
  if (!apiKey || !apiKey.startsWith("sk-")) {
255
  addMessage("system", "Please enter a valid Kimi API key (sk-...) in the settings.");
256
  return;
257
  }
258
 
259
+ addMessage("user", text);
260
  messageInput.value = "";
 
 
261
  showTyping();
262
 
263
  try {
264
+ const messages = [{ role: "user", content: text }];
 
 
 
 
 
 
 
 
265
 
266
  const response = await fetch(`${KIMI_API}/chat/completions`, {
267
  method: "POST",
 
333
  msg = "Invalid API key. Check your key at platform.kimi.ai.";
334
  } else if (msg.includes("402")) {
335
  msg = "Payment required. Add credits at platform.kimi.ai.";
336
+ } else if (msg.includes("not support image") || msg.includes("image.png")) {
337
+ msg = "Cannot read image. This model does not support image input.";
338
  }
339
  addMessage("system", `Error: ${msg}`);
340
  }
341
  }
342
 
 
 
 
 
 
 
 
 
 
343
  sendBtn.addEventListener("click", sendMessage);
344
  messageInput.addEventListener("keydown", (e) => {
345
  if (e.key === "Enter" && !e.shiftKey) {