PageSourceSearch

https://ornith-ai-ornith-1-0-9b.hf.space/

html ornith-ai-ornith-1-0-9b.hf.space collected 2026-10-03 10:20:01 UTC 13,164 bytes, 335 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3<head>
4<meta charset="UTF-8" />
5<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6<title>Ornith-1.0-9B · Terminal</title>
7<style>
8  :root {
9    --bg: #0a0a0a;
10    --panel: #111111;
11    --panel-2: #171717;
12    --border: #2a2a2a;
13    --text: #e0e0e0;
14    --muted: #6b6b6b;
15    --green: #4ade80;
16    --green-dim: #22c55e;
17    --yellow: #facc15;
18    --red: #f87171;
19    --blue: #60a5fa;
20    --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
21  }
22
23  * { box-sizing: border-box; }
24  html, body { height: 100%; margin: 0; }
25  body {
26    background: var(--bg);
27    color: var(--text);
28    font-family: var(--mono);
29    font-size: 14px;
30    line-height: 1.6;
31    display: flex;
32    flex-direction: column;
33  }
34
35  header {
36    display: flex;
37    align-items: center;
38    gap: 12px;
39    padding: 10px 16px;
40    background: var(--panel);
41    border-bottom: 1px solid var(--border);
42  }
43  header img { height: 28px; width: auto; }
44  header .title { font-weight: 600; font-size: 13px; color: var(--text); }
45  header .title span { color: var(--muted); font-weight: 400; }
46  header .spacer { flex: 1; }
47  header .badge {
48    font-size: 11px; color: var(--muted); border: 1px solid var(--border);
49    padding: 2px 8px; border-radius: 4px; cursor: pointer; user-select: none;
50  }
51  header .badge:hover { color: var(--text); border-color: var(--muted); }
52
53  #chat {
54    flex: 1;
55    overflow-y: auto;
56    padding: 0 16px;
57  }
58  .turn { max-width: 900px; margin: 0 auto; padding: 10px 0; border-bottom: 1px solid var(--border); }
59  .turn:last-child { border-bottom: none; }
60
61  .prompt-line { display: flex; align-items: flex-start; gap: 10px; }
62  .prompt { color: var(--green); white-space: nowrap; font-weight: 600; user-select: none; }
63  .prompt.user::before { content: "❯"; }
64  .prompt.assistant::before { content: "◆"; color: var(--green-dim); }
65  .content { flex: 1; min-width: 0; }
66
67  .user-input { color: var(--text); white-space: pre-wrap; }
68
69  .thinking { margin: 6px 0 10px; }
70  .thinking summary {
71    cursor: pointer; color: var(--muted); font-size: 12px; list-style: none;
72    display: flex; align-items: center; gap: 6px;
73  }
74  .thinking summary::-webkit-details-marker { display: none; }
75  .thinking summary::before { content: "▸"; color: var(--green-dim); }
76  .thinking[open] summary::before { content: "▾"; }
77  .thinking pre {
78    margin: 6px 0 0; padding: 10px 12px; background: var(--panel-2);
79    border-left: 2px solid var(--green-dim); color: var(--muted);
80    font: inherit; white-space: pre-wrap; word-wrap: break-word;
81    max-height: 300px; overflow-y: auto;
82  }
83
84  .answer { color: var(--text); }
85  .answer p { margin: 0 0 8px; }
86  .answer p:last-child { margin-bottom: 0; }
87  .answer pre {
88    background: var(--panel-2); border: 1px solid var(--border); border-radius: 4px;
89    padding: 12px 14px; overflow-x: auto; margin: 10px 0; font: inherit;
90  }
91  .answer code { font-family: inherit; }
92  .answer :not(pre) > code { background: var(--panel-2); padding: 1px 4px; border-radius: 3px; color: var(--yellow); }
93  .answer ul, .answer ol { padding-left: 22px; margin: 6px 0; }
94  .answer a { color: var(--green); }
95  .answer blockquote { margin: 8px 0; padding-left: 12px; border-left: 2px solid var(--muted); color: var(--muted); }
96  .answer h1,.answer h2,.answer h3 { margin: 14px 0 6px; font-size: inherit; color: var(--green); }
97  .answer h1 { font-size: 16px; }
98  .answer h2 { font-size: 15px; }
99
100  .status { max-width: 900px; margin: 0 auto; padding: 4px 0; color: var(--muted); font-size: 12px; min-height: 18px; }
101  .status .err { color: var(--red); }
102
103  .composer {
104    border-top: 1px solid var(--border); background: var(--panel); padding: 12px 16px 16px;
105  }
106  .composer-inner { max-width: 900px; margin: 0 auto; }
107
108  #settings {
109    display: none; gap: 18px; flex-wrap: wrap; margin-bottom: 10px; color: var(--muted); font-size: 12px;
110  }
111  #settings.open { display: flex; }
112  #settings label { display: flex; flex-direction: column; gap: 4px; }
113  #settings input[type=range] { width: 150px; accent-color: var(--green); }
114
115  .input-row { display: flex; align-items: flex-end; gap: 8px; }
116  #text {
117    flex: 1; resize: none; min-height: 42px; max-height: 160px;
118    background: var(--bg); color: var(--text); border: 1px solid var(--border);
119    border-radius: 6px; padding: 10px 12px; font: inherit; outline: none;
120  }
121  #text:focus { border-color: var(--green); }
122  button {
123    background: var(--green); color: #052e16; border: none; border-radius: 6px;
124    padding: 10px 16px; font: 600 13px inherit; cursor: pointer;
125  }
126  button:disabled { opacity: .5;
126 cursor: not-allowed; }
127  #stop { background: var(--panel-2); color: var(--text); border: 1px solid var(--border); display: none; }
128  .icon-btn { background: var(--panel-2); color: var(--text); border: 1px solid var(--border); padding: 10px 12px; font-size: 14px; }
129
130  .hint { color: var(--muted); font-size: 11px; margin-top: 8px; text-align: center; }
131
132  /* Empty state */
133  .welcome { max-width: 900px; margin: 24px auto; color: var(--muted); }
134  .welcome h2 { color: var(--green); margin: 0 0 8px; font-size: 14px; }
135  .welcome p { margin: 0; }
136  .welcome .cmd { color: var(--yellow); }
137</style>
138</head>
139<body>
140
141<header>
142  <img src="https://us.aws.cdn.hf.co/xet-bridge-us/6a37681bb57803e616606089/2430ce5755ccaa545def0292cb0f1068d4af99d5093c299b8167c9bfc1128dab?X-Xet-Cas-Uid=60f1abe7544c2adfd699860c&response-content-disposition=inline%3B+filename*%3DUTF-8%27%27ornith_logo.png%3B+filename%3D%22ornith_logo.png%22%3B&response-content-type=image%2Fpng&user_id=60f1abe7544c2adfd699860c&Expires=1782415346&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly91cy5hd3MuY2RuLmhmLmNvL3hldC1icmlkZ2UtdXMvNmEzNzY4MWJiNTc4MDNlNjE2NjA2MDg5LzI0MzBjZTU3NTVjY2FhNTQ1ZGVmMDI5MmNiMGYxMDY4ZDRhZjk5ZDUwOTNjMjk5YjgxNjdjOWJmYzExMjhkYWJcXD9YLVhldC1DYXMtVWlkPTYwZjFhYmU3NTQ0YzJhZGZkNjk5ODYwYyZyZXNwb25zZS1jb250ZW50LWRpc3Bvc2l0aW9uPWlubGluZSUzQitmaWxlbmFtZSUyQSUzRFVURi04JTI3JTI3b3JuaXRoX2xvZ28ucG5nJTNCK2ZpbGVuYW1lJTNEJTIyb3JuaXRoX2xvZ28ucG5nJTIyJTNCJnJlc3BvbnNlLWNvbnRlbnQtdHlwZT1pbWFnZSUyRnBuZyZ1c2VyX2lkPTYwZjFhYmU3NTQ0YzJhZGZkNjk5ODYwYyIsIkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiRXBvY2hUaW1lIjoxNzgyNDE1MzQ2fX19XX0_&Signature=MEUCIQCJDHCuf325VtWk4Lr7BrnsQw9LL9RPIuQzcVq7xPY7vAIgXghesfcDb0xuVJm-bq8mkneN1tG5zTgpzIY6NdpDehw_&Key-Pair-Id=01KAYHXK2CBJSW0YZTMNXK9W1M" alt="Ornith" />
143  <div class="spacer"></div>
144  <div class="badge" id="settings-toggle">⚙ settings</div>
145</header>
146
147<div id="chat">
148  <div class="welcome">
149    <h2>Welcome to Ornith-1.0-9B</h2>
150    <p>Agentic coding assistant. Ask me to write, debug, or explain code.</p>
151  </div>
152</div>
153<div class="status" id="status"></div>
154
155<div class="composer">
156  <div class="composer-inner">
157    <div id="settings">
158      <label>Temperature <input type="range" id="temp" min="0.1" max="1.5" step="0.1" value="0.6" /><span id="temp-v">0.6</span></label>
159      <label>Max tokens <input type="range" id="maxtok" min="256" max="8192" step="256" value="2048" /><span id="maxtok-v">2048</span></label>
160    </div>
161    <div class="input-row">
162      <textarea id="text" placeholder="Ask Ornith to write code, explain, or debug…"></textarea>
163      <button id="send">Send</button>
164      <button id="stop">Stop</button>
165    </div>
166    <div class="hint">Shift+Enter for newline · Enter to send</div>
167  </div>
168</div>
169
170<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
vendor: 1 bytes, line 170
170
171<script src="https://cdn.jsdelivr.net/npm/dompurify@3/dist/purify.min.js"></script>
vendor: 1 bytes, line 171
171
172<script type="module">
173import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";
174
175const chatEl   = document.getElementById("chat");
176const statusEl = document.getElementById("status");
177const textEl   = document.getElementById("text");
178const sendBtn  = document.getElementById("send");
179const stopBtn  = document.getElementById("stop");
180const setToggle= document.getElementById("settings-toggle");
181const settings = document.getElementById("settings");
182const tempEl   = document.getElementById("temp");
183const tempV    = document.getElementById("temp-v");
184const maxEl    = document.getElementById("maxtok");
185const maxV     = document.getElementById("maxtok-v");
186
187let conversation = [];
188let client = null;
189let job = null;
190
191const connect = async () => {
192  if (!client) client = await Client.connect(window.location.origin, { events: ["status", "data"] });
193  return client;
194};
195
196setToggle.addEventListener("click", () => settings.classList.toggle("open"));
197tempEl.addEventListener("input", () => tempV.textContent = tempEl.value);
198maxEl.addEventListener("input", () => maxV.textContent = maxEl.value);
199
200textEl.addEventListener("input", () => {
201  textEl.style.height = "auto";
202  textEl.style.height = Math.min(textEl.scrollHeight, 160) + "px";
203});
204textEl.addEventListener("keydown", (e) => {
205  if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); }
206});
207sendBtn.addEventListener("click", send);
208stopBtn.addEventListener("click", () => { if (job) job.cancel(); });
209
210function scrollIfNear() {
211  const near = chatEl.scrollHeight - chatEl.scrollTop - chatEl.clientHeight < 120;
212  if (near) chatEl.scrollTop = chatEl.scrollHeight;
213}
214
215function addTurn(role) {
216  const turn = document.createElement("div");
217  turn.className = "turn";
218  const line = document.createElement("div");
219  line.className = "prompt-line";
220  const prompt = document.createElement("div");
221  prompt.className = "prompt " + role;
222  const content = document.createElement("div");
223  content.className = "content";
224  line.appendChild(prompt); line.appendChild(content);
225  turn.appendChild(line);
226
227  // Remove welcome message on first real turn.
228  const welcome = chatEl.querySelector(".welcome");
229  if (welcome) welcome.remove();
230
231  chatEl.appendChild(turn);
232  chatEl.scrollTop = chatEl.scrollHeight;
233  return content;
234}
235
236async function send() {
237  const message = textEl.value.trim();
238  if (!message) return;
239  if (job) return;
240
241  const userContent = addTurn("user");
242  userContent.innerHTML = `<div class="user-input">${escapeHtml(message)}</div>`;
243  textEl.value = ""; textEl.style.height = "auto";
244
245  const history = conversation.slice();
246  conversation.push({ role: "user", content: message });
247
248  const assistantContent = addTurn("assistant");
249  assistantContent.innerHTML = `<span style="color:var(--muted)">…</span>`;
250
251  setBusy(true);
252  statusEl.textContent = "connecting…";
253
254  try {
255    const c = await connect();
256    const payload = {
257      message,
258      history,
259      max_new_tokens: parseInt(maxEl.value, 10),
260      temperature: parseFloat(tempEl.value),
261    };
262    job = c.submit("/generate", payload);
263
264    let latestReasoning = "";
265    let latestAnswer = "";
266    let complete = false;
267
268    for await (const msg of job) {
269      if (msg.type === "status") {
270        const s = msg.status || msg.data?.status;
271        if (s === "pending") statusEl.textContent = `queued…${msg.position != null ? " (#" + msg.position + ")" : ""}`;
272        else if (s === "generating") statusEl.textContent = "generating…";
273        else if (s === "complete" || s === "error") statusEl.textContent = "";
274        continue;
275      }
276      if (msg.type !== "data") continue;
277      const raw = Array.isArray(msg.data) ? msg.data[0] : msg.data;
278      let d = raw;
279      if (typeof raw === "string") { try { d = JSON.parse(raw); } catch { d = { answer: raw }; } }
280      if (d?.error) {
281        renderAssistant(assistantContent, latestReasoning, latestAnswer, d.error);
282        statusEl.innerHTML = `<span class="err">error: ${escapeHtml(d.error)}</span>`;
283        break;
284      }
285      latestReasoning = d?.reasoning || "";
286      latestAnswer = d?.answer || "";
287      complete = d?.status === "complete";
288      renderAssistant(assistantContent, latestReasoning, latestAnswer);
289      scrollIfNear();
290    }
291
292    if (complete && latestAnswer) {
293      conversation.push({ role: "assistant", content: latestAnswer });
294    }
295  } catch (e) {
296    renderAssistant(assistantContent, "", "", String(e));
297    statusEl.innerHTML = `<span class="err">${escapeHtml(String(e))}</span>`;
298  } finally {
299    job = null;
300    setBusy(false);
301    statusEl.textContent = "";
302  }
303}
304
305function renderAssistant(el, reasoning, answer, error) {
306  let h = "";
307  if (reasoning && reasoning.trim()) {
308    h += `<details class="thinking"${answer ? "" : " open"}><summary>thinking</summary><pre>${escapeHtml(reasoning)}</pre></details>`;
309  }
310  if (error) {
311    h += `<div class="err">⚠ ${escapeHtml(error)}</div>`;
312  } else if (answer && answer.trim()) {
313    h += `<div class="answer">${DOMPurify.sanitize(marked.parse(answer))}</div>`;
314  } else if (!reasoning) {
315    h += `<span style="color:var(--muted)">…</span>`;
316  }
317  el.innerHTML = h;
318}
319
320function setBusy(busy) {
321  sendBtn.disabled = busy;
322  sendBtn.style.display = busy ? "none" : "";
323  stopBtn.style.display = busy ? "" : "none";
324}
325
326function escapeHtml(s) {
327  return String(s ?? "")
328    .replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
329    .replace(/"/g, "&quot;").replace(/'/g, "&#39;");
330}
331
332textEl.focus();
333</script>
333
334</body>
335</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.