CoolFace
Apppublic

Carter-123/North-Mini-Code-1.0

sourceHugging Faceupdated 4mo agoView on Hugging Face
0likes
index.html1831 linesDownload Raw Back to root
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>North Mini Code 1.0</title>7<meta name="description" content="Terminal-style coding assistant powered by North Mini Code 1.0">8<link rel="preconnect" href="https://fonts.googleapis.com">9<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>10<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&display=swap" rel="stylesheet">11<style>12/* ═══════════════════════════════════════════════════════13   RESET & BASE14   ═══════════════════════════════════════════════════════ */15*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }16 17:root {18  --bg-deep: #0a0e14;19  --bg-panel: #0d1117;20  --bg-code: #161b22;21  --border: #1e2a3a;22  --border-focus: #2d4a6a;23  --green: #39ff14;24  --green-dim: #1a7a0a;25  --cyan: #00d4ff;26  --amber: #ffb300;27  --gray-light: #e0e0e0;28  --gray-mid: #8b949e;29  --gray-dim: #484f58;30  --red: #ff5555;31  --success: #50fa7b;32  --code-text: #f8f8f2;33  --glow-green: 0 0 8px rgba(57,255,20,0.3);34  --glow-cyan: 0 0 8px rgba(0,212,255,0.3);35  --glow-amber: 0 0 8px rgba(255,179,0,0.2);36  --font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;37  --radius: 4px;38  --transition: 0.2s ease;39}40 41html, body {42  height: 100%;43  background: var(--bg-deep);44  color: var(--gray-light);45  font-family: var(--font-mono);46  font-size: 13px;47  line-height: 1.6;48  overflow: hidden;49}50 51/* CRT scanline overlay */52body::after {53  content: '';54  position: fixed;55  inset: 0;56  pointer-events: none;57  z-index: 9999;58  background: repeating-linear-gradient(59    0deg,60    transparent,61    transparent 2px,62    rgba(0, 0, 0, 0.03) 2px,63    rgba(0, 0, 0, 0.03) 4px64  );65}66 67::selection {68  background: rgba(57, 255, 20, 0.25);69  color: #fff;70}71 72::-webkit-scrollbar { width: 6px; height: 6px; }73::-webkit-scrollbar-track { background: transparent; }74::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }75::-webkit-scrollbar-thumb:hover { background: var(--gray-dim); }76 77a { color: var(--cyan); text-decoration: none; }78a:hover { text-decoration: underline; text-shadow: var(--glow-cyan); }79 80/* ═══════════════════════════════════════════════════════81   APP SHELL82   ═══════════════════════════════════════════════════════ */83#app {84  display: flex;85  flex-direction: column;86  height: 100vh;87  max-height: 100vh;88}89 90/* ═══════════════════════════════════════════════════════91   CONFIG WARNING92   ═══════════════════════════════════════════════════════ */93#config-warning {94  display: none;95  background: linear-gradient(90deg, rgba(255,85,85,0.1), rgba(255,179,0,0.1));96  border-bottom: 1px solid var(--red);97  padding: 8px 16px;98  font-size: 12px;99  color: var(--amber);100  text-align: center;101  text-shadow: var(--glow-amber);102}103#config-warning.visible { display: block; }104 105#playground-banner {106  background: linear-gradient(90deg, rgba(0,212,255,0.08), rgba(57,255,20,0.05));107  border-bottom: 1px solid var(--border);108  color: var(--gray-mid);109  font-size: 12px;110  padding: 7px 18px;111  text-align: center;112  flex-shrink: 0;113}114#playground-banner strong {115  color: var(--gray-light);116  font-weight: 600;117}118#playground-banner a {119  color: var(--cyan);120  font-weight: 600;121}122 123/* ═══════════════════════════════════════════════════════124   HEADER125   ═══════════════════════════════════════════════════════ */126#header {127  display: flex;128  align-items: center;129  justify-content: space-between;130  padding: 12px 20px;131  background: var(--bg-panel);132  border-bottom: 1px solid var(--border);133  flex-shrink: 0;134  gap: 16px;135}136 137.header-title {138  display: flex;139  flex-direction: column;140  gap: 2px;141}142 143.header-ascii {144  color: var(--green);145  font-size: 11px;146  line-height: 1.3;147  text-shadow: var(--glow-green);148  white-space: pre;149  letter-spacing: 0.5px;150}151 152.header-subtitle {153  color: var(--gray-mid);154  font-size: 11px;155  padding-left: 3px;156}157 158.header-actions {159  display: flex;160  align-items: center;161  gap: 10px;162  flex-shrink: 0;163}164 165.pill {166  display: inline-flex;167  align-items: center;168  gap: 5px;169  padding: 4px 10px;170  border: 1px solid var(--border);171  border-radius: 12px;172  font-size: 11px;173  color: var(--gray-mid);174  text-decoration: none;175  transition: all var(--transition);176}177.pill:hover {178  border-color: var(--cyan);179  color: var(--cyan);180  text-decoration: none;181  text-shadow: var(--glow-cyan);182}183.pill .dot {184  width: 6px;185  height: 6px;186  border-radius: 50%;187  background: var(--success);188  box-shadow: 0 0 6px var(--success);189}190 191#btn-new-chat {192  background: transparent;193  border: 1px solid var(--border);194  color: var(--amber);195  font-family: var(--font-mono);196  font-size: 11px;197  padding: 5px 12px;198  border-radius: var(--radius);199  cursor: pointer;200  transition: all var(--transition);201  letter-spacing: 1px;202}203#btn-new-chat:hover {204  border-color: var(--amber);205  background: rgba(255,179,0,0.08);206  text-shadow: var(--glow-amber);207}208 209/* ═══════════════════════════════════════════════════════210   MAIN LAYOUT211   ═══════════════════════════════════════════════════════ */212#main {213  display: flex;214  flex: 1;215  min-height: 0;216  overflow: hidden;217}218 219/* ═══════════════════════════════════════════════════════220   TERMINAL (LEFT PANEL)221   ═══════════════════════════════════════════════════════ */222#terminal-panel {223  display: flex;224  flex-direction: column;225  flex: 1;226  min-width: 0;227  border-right: 1px solid var(--border);228}229 230.panel-label {231  padding: 6px 16px;232  font-size: 10px;233  letter-spacing: 2px;234  color: var(--gray-dim);235  border-bottom: 1px solid var(--border);236  background: rgba(13,17,23,0.6);237  text-transform: uppercase;238  flex-shrink: 0;239}240 241#chat-messages {242  flex: 1;243  overflow-y: auto;244  padding: 16px;245  scroll-behavior: smooth;246}247 248/* Message styles */249.msg {250  margin-bottom: 14px;251  line-height: 1.65;252  animation: msgFadeIn 0.25s ease;253}254 255@keyframes msgFadeIn {256  from { opacity: 0; transform: translateY(6px); }257  to { opacity: 1; transform: translateY(0); }258}259 260.msg-prefix {261  font-weight: 600;262  margin-right: 4px;263}264 265.msg-user .msg-prefix {266  color: var(--green);267  text-shadow: var(--glow-green);268}269.msg-user .msg-content {270  color: var(--green);271  text-shadow: var(--glow-green);272}273 274.msg-assistant .msg-prefix {275  color: var(--cyan);276  text-shadow: var(--glow-cyan);277}278.msg-assistant .msg-content {279  color: var(--gray-light);280}281 282.msg-system .msg-prefix {283  color: var(--amber);284  text-shadow: var(--glow-amber);285}286.msg-system .msg-content {287  color: var(--amber);288  opacity: 0.85;289}290 291/* Markdown elements */292.msg-content strong { color: #fff; font-weight: 600; }293.msg-content em { font-style: italic; color: var(--gray-mid); }294.msg-content code:not(pre code) {295  background: var(--bg-code);296  color: var(--code-text);297  padding: 1px 5px;298  border-radius: 3px;299  font-size: 12px;300  border: 1px solid var(--border);301}302.msg-content a { color: var(--cyan); }303.msg-content ul, .msg-content ol {304  margin: 6px 0 6px 20px;305}306.msg-content li { margin-bottom: 3px; }307.msg-content h1, .msg-content h2, .msg-content h3 {308  color: var(--cyan);309  margin: 10px 0 6px;310  font-size: 14px;311  text-shadow: var(--glow-cyan);312}313.msg-content h1 { font-size: 16px; }314.msg-content h2 { font-size: 15px; }315.msg-content p { margin: 4px 0; }316 317/* Code blocks */318.code-block-wrap {319  margin: 8px 0;320  border: 1px solid var(--border);321  border-radius: var(--radius);322  overflow: hidden;323  background: var(--bg-code);324}325.code-block-header {326  display: flex;327  align-items: center;328  justify-content: space-between;329  padding: 4px 10px;330  background: rgba(30,42,58,0.5);331  border-bottom: 1px solid var(--border);332  font-size: 11px;333}334.code-lang {335  color: var(--amber);336  text-transform: uppercase;337  letter-spacing: 1px;338}339.btn-copy {340  background: transparent;341  border: 1px solid var(--border);342  color: var(--gray-mid);343  font-family: var(--font-mono);344  font-size: 10px;345  padding: 2px 8px;346  border-radius: 3px;347  cursor: pointer;348  transition: all var(--transition);349}350.btn-copy:hover {351  border-color: var(--green);352  color: var(--green);353}354.btn-copy.copied {355  border-color: var(--success);356  color: var(--success);357}358.code-block-wrap pre {359  margin: 0;360  padding: 10px 12px;361  overflow-x: auto;362  font-size: 12px;363  line-height: 1.5;364  color: var(--code-text);365}366.code-block-wrap pre code {367  font-family: var(--font-mono);368  background: none;369  border: none;370  padding: 0;371}372 373/* Thinking blocks */374.think-block {375  margin: 8px 0;376  border: 1px solid rgba(255,179,0,0.15);377  border-radius: var(--radius);378  background: rgba(255,179,0,0.03);379}380.think-summary {381  display: block;382  width: 100%;383  background: transparent;384  border: none;385  padding: 6px 10px;386  cursor: pointer;387  font-size: 12px;388  font-family: var(--font-mono);389  text-align: left;390  color: var(--gray-dim);391  user-select: none;392  transition: color var(--transition);393}394.think-summary:hover { color: var(--amber); }395.think-block .think-content {396  padding: 6px 12px 10px;397  font-size: 12px;398  color: var(--gray-dim);399  line-height: 1.55;400  border-top: 1px solid rgba(255,179,0,0.1);401}402.think-block:not(.open) .think-content {403  display: none;404}405 406/* Streaming cursor */407.streaming-cursor::after {408  content: '█';409  animation: blink 0.8s step-end infinite;410  color: var(--green);411  margin-left: 2px;412}413@keyframes blink {414  50% { opacity: 0; }415}416 417/* ═══════════════════════════════════════════════════════418   INPUT AREA419   ═══════════════════════════════════════════════════════ */420#input-area {421  flex-shrink: 0;422  border-top: 1px solid var(--border);423  background: var(--bg-panel);424  padding: 10px 16px 8px;425}426 427/* Target toggle */428#target-toggle {429  display: flex;430  gap: 14px;431  margin-bottom: 8px;432  align-items: center;433}434 435.target-label {436  font-size: 10px;437  color: var(--gray-dim);438  letter-spacing: 1px;439  text-transform: uppercase;440}441 442.target-btn {443  background: transparent;444  border: none;445  font-family: var(--font-mono);446  font-size: 12px;447  color: var(--gray-dim);448  cursor: pointer;449  padding: 2px 0;450  border-bottom: 2px solid transparent;451  transition: all var(--transition);452  letter-spacing: 0.5px;453}454.target-btn:hover { color: var(--gray-mid); }455.target-btn.active {456  color: var(--green);457  border-bottom-color: var(--green);458  text-shadow: var(--glow-green);459}460 461#input-row {462  display: flex;463  gap: 8px;464  align-items: flex-end;465}466 467.input-prompt-symbol {468  color: var(--green);469  font-weight: 700;470  font-size: 14px;471  line-height: 36px;472  text-shadow: var(--glow-green);473  flex-shrink: 0;474}475 476#chat-input {477  flex: 1;478  background: var(--bg-deep);479  border: 1px solid var(--border);480  border-radius: var(--radius);481  color: var(--green);482  font-family: var(--font-mono);483  font-size: 13px;484  padding: 8px 12px;485  resize: none;486  outline: none;487  min-height: 36px;488  max-height: 120px;489  line-height: 1.5;490  transition: border-color var(--transition);491  caret-color: var(--green);492  text-shadow: var(--glow-green);493}494#chat-input::placeholder {495  color: var(--gray-dim);496  text-shadow: none;497}498#chat-input:focus {499  border-color: var(--border-focus);500}501 502#btn-send, #btn-stop {503  font-family: var(--font-mono);504  font-size: 12px;505  padding: 8px 14px;506  border-radius: var(--radius);507  cursor: pointer;508  transition: all var(--transition);509  letter-spacing: 1px;510  flex-shrink: 0;511  height: 36px;512  display: flex;513  align-items: center;514  gap: 4px;515}516 517#btn-send {518  background: transparent;519  border: 1px solid var(--green);520  color: var(--green);521}522#btn-send:hover:not(:disabled) {523  background: var(--green);524  color: var(--bg-deep);525  box-shadow: 0 0 12px rgba(57,255,20,0.3);526}527#btn-send:disabled {528  opacity: 0.3;529  cursor: not-allowed;530}531 532#btn-stop {533  background: transparent;534  border: 1px solid var(--red);535  color: var(--red);536  display: none;537}538#btn-stop:hover {539  background: var(--red);540  color: var(--bg-deep);541  box-shadow: 0 0 12px rgba(255,85,85,0.3);542}543 544/* Examples */545#examples-row {546  display: flex;547  align-items: center;548  gap: 8px;549  margin-top: 8px;550  flex-wrap: wrap;551}552.examples-label {553  font-size: 10px;554  color: var(--gray-dim);555  letter-spacing: 1px;556  text-transform: uppercase;557  flex-shrink: 0;558}559.example-chip {560  background: rgba(30,42,58,0.4);561  border: 1px solid var(--border);562  border-radius: 12px;563  padding: 3px 10px;564  font-family: var(--font-mono);565  font-size: 11px;566  color: var(--gray-mid);567  cursor: pointer;568  transition: all var(--transition);569  white-space: nowrap;570}571.example-chip:hover {572  border-color: var(--cyan);573  color: var(--cyan);574  background: rgba(0,212,255,0.05);575  text-shadow: var(--glow-cyan);576}577 578/* ═══════════════════════════════════════════════════════579   OUTPUT PANEL (RIGHT)580   ═══════════════════════════════════════════════════════ */581#output-panel {582  display: flex;583  flex-direction: column;584  width: 45%;585  min-width: 340px;586  max-width: 55%;587  min-height: 0;588  background: var(--bg-panel);589}590 591#output-tabs {592  display: flex;593  border-bottom: 1px solid var(--border);594  background: rgba(13,17,23,0.6);595  flex-shrink: 0;596}597 598.output-tab {599  flex: 1;600  background: transparent;601  border: none;602  border-bottom: 2px solid transparent;603  color: var(--gray-dim);604  font-family: var(--font-mono);605  font-size: 11px;606  padding: 8px 12px;607  cursor: pointer;608  transition: all var(--transition);609  letter-spacing: 1px;610  text-transform: uppercase;611}612.output-tab:hover { color: var(--gray-mid); }613.output-tab.active {614  color: var(--cyan);615  border-bottom-color: var(--cyan);616  text-shadow: var(--glow-cyan);617}618 619#output-content {620  flex: 1;621  min-height: 0;622  overflow: hidden;623  position: relative;624}625 626/* Tab panes */627.tab-pane { display: none; height: 100%; min-height: 0; }628.tab-pane.active { display: flex; flex-direction: column; }629 630/* Preview tab */631#pane-preview {632  align-items: stretch;633  justify-content: stretch;634  position: relative;635  min-height: 0;636  overflow: hidden;637}638 639.preview-placeholder {640  align-self: center;641  margin: auto;642  text-align: center;643  color: var(--gray-dim);644  padding: 40px 20px;645}646.preview-placeholder .ascii-art {647  font-size: 11px;648  line-height: 1.3;649  margin-bottom: 16px;650  color: var(--border-focus);651}652.preview-placeholder .placeholder-text {653  font-size: 12px;654  letter-spacing: 0.5px;655}656 657#preview-image {658  display: none;659  max-width: 100%;660  max-height: 100%;661  object-fit: contain;662  padding: 12px;663}664 665#preview-iframe {666  display: none;667  position: absolute;668  inset: 0;669  width: 100%;670  height: 100%;671  min-height: 0;672  border: none;673  background: #fff;674}675 676#btn-fullscreen {677  display: none;678  position: absolute;679  top: 8px;680  right: 8px;681  background: rgba(13,17,23,0.8);682  border: 1px solid var(--border);683  color: var(--gray-mid);684  font-family: var(--font-mono);685  font-size: 11px;686  padding: 4px 10px;687  border-radius: var(--radius);688  cursor: pointer;689  z-index: 5;690  transition: all var(--transition);691}692#btn-fullscreen:hover {693  border-color: var(--cyan);694  color: var(--cyan);695}696 697/* Console tab */698#pane-console { padding: 12px 16px; gap: 12px; overflow-y: auto; }699 700.console-section { margin-bottom: 8px; }701.console-label {702  font-size: 10px;703  letter-spacing: 2px;704  color: var(--gray-dim);705  margin-bottom: 4px;706  text-transform: uppercase;707}708.console-output {709  background: var(--bg-deep);710  border: 1px solid var(--border);711  border-radius: var(--radius);712  padding: 10px 12px;713  font-size: 12px;714  line-height: 1.5;715  white-space: pre-wrap;716  word-break: break-word;717  min-height: 40px;718  max-height: 280px;719  overflow-y: auto;720}721#console-stdout { color: var(--success); }722#console-stderr { color: var(--red); }723 724/* Code tab */725#pane-code { padding: 0; }726 727.code-tab-header {728  display: flex;729  align-items: center;730  justify-content: space-between;731  padding: 8px 12px;732  border-bottom: 1px solid var(--border);733  background: rgba(30,42,58,0.3);734  flex-shrink: 0;735}736.code-tab-lang {737  font-size: 11px;738  color: var(--amber);739  letter-spacing: 1px;740  text-transform: uppercase;741}742.code-tab-actions {743  display: flex;744  gap: 8px;745}746.code-tab-btn {747  background: transparent;748  border: 1px solid var(--border);749  color: var(--gray-mid);750  font-family: var(--font-mono);751  font-size: 10px;752  padding: 3px 8px;753  border-radius: 3px;754  cursor: pointer;755  text-decoration: none;756  transition: all var(--transition);757  display: inline-flex;758  align-items: center;759  gap: 4px;760}761.code-tab-btn:hover {762  border-color: var(--cyan);763  color: var(--cyan);764  text-decoration: none;765}766 767#code-display {768  flex: 1;769  overflow: auto;770  padding: 12px;771  background: var(--bg-code);772}773#code-display pre {774  margin: 0;775  font-size: 12px;776  line-height: 1.5;777  color: var(--code-text);778}779 780.code-placeholder {781  display: flex;782  align-items: center;783  justify-content: center;784  height: 100%;785  color: var(--gray-dim);786  font-size: 12px;787}788 789/* ═══════════════════════════════════════════════════════790   STATUS BAR791   ═══════════════════════════════════════════════════════ */792#status-bar {793  display: flex;794  align-items: center;795  gap: 8px;796  padding: 5px 16px;797  border-top: 1px solid var(--border);798  background: var(--bg-panel);799  font-size: 11px;800  flex-shrink: 0;801}802 803.status-indicator {804  display: inline-flex;805  align-items: center;806  gap: 6px;807}808 809.status-dot {810  font-size: 10px;811  line-height: 1;812}813 814#status-text {815  letter-spacing: 1px;816  text-transform: uppercase;817}818 819.status-idle { color: var(--gray-dim); }820.status-working { color: var(--amber); text-shadow: var(--glow-amber); }821.status-success { color: var(--success); text-shadow: 0 0 8px rgba(80,250,123,0.3); }822.status-error { color: var(--red); text-shadow: 0 0 8px rgba(255,85,85,0.3); }823.status-info { color: var(--cyan); text-shadow: var(--glow-cyan); }824 825@keyframes spin {826  to { transform: rotate(360deg); }827}828.status-working .status-dot {829  display: inline-block;830  animation: spin 1s linear infinite;831}832 833/* ═══════════════════════════════════════════════════════834   FULLSCREEN OVERLAY835   ═══════════════════════════════════════════════════════ */836#fullscreen-overlay {837  display: none;838  position: fixed;839  inset: 0;840  z-index: 1000;841  background: var(--bg-deep);842  flex-direction: column;843}844#fullscreen-overlay.active { display: flex; }845 846#fullscreen-bar {847  display: flex;848  align-items: center;849  justify-content: space-between;850  padding: 8px 16px;851  border-bottom: 1px solid var(--border);852  background: var(--bg-panel);853}854#fullscreen-bar span {855  color: var(--cyan);856  font-size: 12px;857  letter-spacing: 1px;858}859#btn-exit-fullscreen {860  background: transparent;861  border: 1px solid var(--border);862  color: var(--gray-mid);863  font-family: var(--font-mono);864  font-size: 11px;865  padding: 4px 12px;866  border-radius: var(--radius);867  cursor: pointer;868  transition: all var(--transition);869}870#btn-exit-fullscreen:hover {871  border-color: var(--red);872  color: var(--red);873}874#fullscreen-iframe {875  flex: 1;876  border: none;877  background: #fff;878}879 880/* ═══════════════════════════════════════════════════════881   RESPONSIVE882   ═══════════════════════════════════════════════════════ */883@media (max-width: 900px) {884  #main {885    flex-direction: column;886  }887  #terminal-panel {888    border-right: none;889    border-bottom: 1px solid var(--border);890    max-height: 55vh;891  }892  #output-panel {893    width: 100%;894    max-width: 100%;895    min-width: 0;896    flex: 1;897  }898  .header-ascii { font-size: 10px; }899  #chat-input { font-size: 12px; }900  #preview-iframe { min-height: 400px; }901}902 903@media (max-width: 600px) {904  #header { padding: 8px 12px; gap: 8px; }905  .header-ascii { display: none; }906  .header-subtitle { display: none; }907  .pill { font-size: 10px; padding: 3px 8px; }908  #chat-messages { padding: 10px; }909  #input-area { padding: 8px 10px 6px; }910  #examples-row { display: none; }911}912</style>913</head>914<body>915<div id="app">916  <!-- Config Warning -->917  <div id="config-warning">⚠ WARNING: COHERE_API_KEY not configured. Set it as a Space secret to enable the model.</div>918 919  <!-- Header -->920  <header id="header">921    <div class="header-title">922      <div class="header-ascii" id="header-ascii-art">╔═══ NORTH MINI CODE 1.0 ═══╗</div>923      <div class="header-subtitle" id="header-subtitle">Terminal Coding Assistant</div>924    </div>925    <div class="header-actions">926      <a class="pill" id="model-pill" href="#" target="_blank" rel="noopener">927        <span class="dot"></span>928        <span id="model-pill-text">north-mini-code-1-0</span>929      </a>930      <a class="pill" id="opencode-pill" href="#" target="_blank" rel="noopener">OpenCode</a>931      <button id="btn-new-chat" onclick="newChat()" title="Start a new chat session">[NEW]</button>932    </div>933  </header>934 935  <div id="playground-banner">936    <a id="banner-model-link" href="https://huggingface.co/CohereLabs/North-Mini-Code-1.0" target="_blank" rel="noopener"><strong>North-Mini-Code-1.0</strong></a>937    is built for agentic coding and works best in your terminal with938    <a id="opencode-banner-link" href="#" target="_blank" rel="noopener">OpenCode ↗</a>.939    This Space is a browser playground for trying the model.940  </div>941 942  <!-- Main Layout -->943  <div id="main">944    <!-- Terminal Panel -->945    <div id="terminal-panel">946      <div class="panel-label">Terminal</div>947      <div id="chat-messages"></div>948      <div id="input-area">949        <div id="target-toggle">950          <span class="target-label">Mode:</span>951          <button class="target-btn active" data-target="Python" onclick="setTarget('Python')">[ Python ● ]</button>952          <button class="target-btn" data-target="Web" onclick="setTarget('Web')">[ Web ○ ]</button>953        </div>954        <div id="input-row">955          <span class="input-prompt-symbol">❯</span>956          <textarea id="chat-input" rows="1" placeholder="Ask a coding question or describe what to build…" spellcheck="false"></textarea>957          <button id="btn-send" onclick="handleSend()" title="Send message (Shift+Enter)">➤</button>958          <button id="btn-stop" onclick="stopGeneration()" title="Stop generation">■ STOP</button>959        </div>960        <div id="examples-row"></div>961      </div>962    </div>963 964    <!-- Output Panel -->965    <div id="output-panel">966      <div id="output-tabs">967        <button class="output-tab active" data-tab="preview" onclick="switchTab('preview')">Preview</button>968        <button class="output-tab" data-tab="console" onclick="switchTab('console')">Console</button>969        <button class="output-tab" data-tab="code" onclick="switchTab('code')">Code</button>970      </div>971      <div id="output-content">972        <!-- Preview Pane -->973        <div class="tab-pane active" id="pane-preview">974          <div class="preview-placeholder" id="preview-placeholder">975            <div class="ascii-art">976  ┌──────────────────────┐977  │   ╭━━━╮              │978  │   ┃ ▶ ┃  OUTPUT      │979  │   ╰━━━╯              │980  └──────────────────────┘</div>981            <div class="placeholder-text">Run code to see output here</div>982          </div>983          <img id="preview-image" alt="Generated output">984          <iframe id="preview-iframe" sandbox="allow-scripts"></iframe>985          <button id="btn-fullscreen" onclick="openFullscreen()">⤢ FULLSCREEN</button>986        </div>987 988        <!-- Console Pane -->989        <div class="tab-pane" id="pane-console">990          <div class="console-section">991            <div class="console-label">stdout:</div>992            <div class="console-output" id="console-stdout">No output yet.</div>993          </div>994          <div class="console-section">995            <div class="console-label">stderr:</div>996            <div class="console-output" id="console-stderr">No errors.</div>997          </div>998        </div>999 1000        <!-- Code Pane -->1001        <div class="tab-pane" id="pane-code">1002          <div class="code-tab-header">1003            <span class="code-tab-lang" id="code-tab-lang">—</span>1004            <div class="code-tab-actions">1005              <button class="code-tab-btn" id="btn-copy-code" onclick="copyCode()">📋 Copy</button>1006              <a class="code-tab-btn" id="btn-download" href="#" style="display:none;">⬇ Download</a>1007            </div>1008          </div>1009          <div id="code-display">1010            <div class="code-placeholder">No code generated yet.</div>1011          </div>1012        </div>1013      </div>1014    </div>1015  </div>1016 1017  <!-- Status Bar -->1018  <div id="status-bar">1019    <div class="status-indicator status-idle" id="status-indicator">1020      <span class="status-dot">●</span>1021      <span id="status-text">IDLE</span>1022    </div>1023  </div>1024</div>1025 1026<!-- Fullscreen Overlay -->1027<div id="fullscreen-overlay">1028  <div id="fullscreen-bar">1029    <span>WEB PREVIEW</span>1030    <button id="btn-exit-fullscreen" onclick="closeFullscreen()">[✕ CLOSE]</button>1031  </div>1032  <iframe id="fullscreen-iframe" sandbox="allow-scripts"></iframe>1033</div>1034 1035<script>1036// ═══════════════════════════════════════════════════════1037// CONFIG1038// ═══════════════════════════════════════════════════════1039const CONFIG = __RUNTIME_CONFIG__;1040 1041// ═══════════════════════════════════════════════════════1042// STATE1043// ═══════════════════════════════════════════════════════1044const state = {1045  history: [],1046  executionContext: {},1047  targetLanguage: 'Python',1048  isGenerating: false,1049  currentEventSource: null,1050  activeTab: 'preview',1051  lastExecution: null,1052  lastCode: '',1053  lastCodeLang: '',1054  pendingWebPreviewCode: '',1055  loadedWebPreviewCode: '',1056  scheduledWebPreviewCode: '',1057  reasoningExpanded: false,1058  lastReasoningPressAt: 01059};1060 1061// ═══════════════════════════════════════════════════════1062// INITIALIZATION1063// ═══════════════════════════════════════════════════════1064document.addEventListener('DOMContentLoaded', () => {1065  // Apply config1066  document.title = CONFIG.app_title || 'North Mini Code 1.0';1067 1068  if (CONFIG.model_url) {1069    document.getElementById('model-pill').href = CONFIG.model_url;1070    document.getElementById('banner-model-link').href = CONFIG.model_url;1071  }1072  if (CONFIG.model_id) {1073    document.getElementById('model-pill-text').textContent = CONFIG.model_id;1074  }1075  if (CONFIG.opencode_url) {1076    document.getElementById('opencode-pill').href = CONFIG.opencode_url;1077    document.getElementById('opencode-banner-link').href = CONFIG.opencode_url;1078  }1079 1080  // Config warning1081  if (!CONFIG.api_key_configured) {1082    document.getElementById('config-warning').classList.add('visible');1083  }1084 1085  // Render examples1086  renderExamples();1087 1088  // Welcome message1089  addSystemMessage(`Welcome to ${CONFIG.app_title || 'North Mini Code 1.0'}. Type a coding question or select an example below to get started.`);1090 1091  // Input auto-resize & keybinding1092  const input = document.getElementById('chat-input');1093  input.addEventListener('input', autoResize);1094  input.addEventListener('keydown', (e) => {1095    if (e.key === 'Enter' && e.shiftKey) {1096      e.preventDefault();1097      handleSend();1098    }1099  });1100 1101  document.addEventListener('pointerdown', handleReasoningPress, true);1102  document.addEventListener('mousedown', handleReasoningPress, true);1103  document.addEventListener('keydown', handleReasoningKeydown, true);1104  document.addEventListener('keydown', handleFullscreenKeydown);1105  observePreviewSize();1106});1107 1108function autoResize() {1109  const el = document.getElementById('chat-input');1110  el.style.height = 'auto';1111  el.style.height = Math.min(el.scrollHeight, 120) + 'px';1112}1113 1114// ═══════════════════════════════════════════════════════1115// EXAMPLES1116// ═══════════════════════════════════════════════════════1117function renderExamples() {1118  const row = document.getElementById('examples-row');1119  if (!CONFIG.examples || CONFIG.examples.length === 0) {1120    row.style.display = 'none';1121    return;1122  }1123  row.innerHTML = '<span class="examples-label">Try:</span>';1124  CONFIG.examples.forEach((ex) => {1125    const chip = document.createElement('button');1126    chip.className = 'example-chip';1127    chip.textContent = ex.label;1128    chip.title = ex.prompt;1129    chip.addEventListener('click', () => {1130      if (state.isGenerating) return;1131      resetConversation();1132      if (ex.target) setTarget(ex.target);1133      sendMessage(ex.prompt);1134    });1135    row.appendChild(chip);1136  });1137}1138 1139// ═══════════════════════════════════════════════════════1140// TARGET LANGUAGE1141// ═══════════════════════════════════════════════════════1142function setTarget(target) {1143  state.targetLanguage = target;1144  document.querySelectorAll('.target-btn').forEach((btn) => {1145    const isActive = btn.dataset.target === target;1146    btn.classList.toggle('active', isActive);1147    btn.textContent = `[ ${btn.dataset.target} ${isActive ? '●' : '○'} ]`;1148  });1149}1150 1151// ═══════════════════════════════════════════════════════1152// CHAT MESSAGES1153// ═══════════════════════════════════════════════════════1154function addSystemMessage(text) {1155  const container = document.getElementById('chat-messages');1156  const div = document.createElement('div');1157  div.className = 'msg msg-system';1158  div.innerHTML = `<span class="msg-prefix">system&gt;</span><span class="msg-content">${escapeHtml(text)}</span>`;1159  container.appendChild(div);1160  scrollToBottom();1161}1162 1163function addUserMessage(text) {1164  const container = document.getElementById('chat-messages');1165  const div = document.createElement('div');1166  div.className = 'msg msg-user';1167  div.innerHTML = `<span class="msg-prefix">user&gt;</span><span class="msg-content">${escapeHtml(text)}</span>`;1168  container.appendChild(div);1169  scrollToBottom();1170}1171 1172function addAssistantMessage() {1173  const container = document.getElementById('chat-messages');1174  const div = document.createElement('div');1175  div.className = 'msg msg-assistant';1176  div.id = 'current-assistant-msg';1177  div.innerHTML = `<span class="msg-prefix">north&gt;</span><span class="msg-content streaming-cursor"></span>`;1178  container.appendChild(div);1179  state.reasoningExpanded = false;1180  scrollToBottom();1181  return div;1182}1183 1184function updateAssistantMessage(content, isStreaming) {1185  const div = document.getElementById('current-assistant-msg');1186  if (!div) return;1187  const contentEl = div.querySelector('.msg-content');1188  const keepReasoningExpanded = state.reasoningExpanded || Boolean(contentEl.querySelector('.think-block.open'));1189  state.reasoningExpanded = keepReasoningExpanded;1190  contentEl.innerHTML = parseMarkdown(content);1191  contentEl.querySelectorAll('.think-block').forEach((block) => {1192    setReasoningBlockOpen(block, keepReasoningExpanded);1193  });1194  if (isStreaming) {1195    contentEl.classList.add('streaming-cursor');1196  } else {1197    contentEl.classList.remove('streaming-cursor');1198  }1199  scrollToBottom();1200}

Showing the first 1,200 of 1831 lines. Download the file for the rest.