@krmxd/onegpt 0.0.0-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/preview.js ADDED
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+
3
+ const path = require("path");
4
+
5
+ const EXT_LANG = {
6
+ ".py": "python", ".js": "javascript", ".ts": "typescript", ".jsx": "jsx",
7
+ ".tsx": "tsx", ".html": "html", ".css": "css", ".json": "json",
8
+ ".sh": "bash", ".go": "go", ".rs": "rust", ".java": "java",
9
+ ".c": "c", ".cpp": "cpp", ".h": "c", ".rb": "ruby",
10
+ ".sql": "sql", ".yaml": "yaml", ".yml": "yaml", ".toml": "toml",
11
+ ".md": "markdown", ".xml": "xml",
12
+ };
13
+
14
+ const B = "\x1b[1m", D = "\x1b[2m", R = "\x1b[0m";
15
+ const C = "\x1b[36m", G = "\x1b[32m", W = "\x1b[97m";
16
+
17
+ function detectLang(filePath) {
18
+ const p = path.parse(filePath);
19
+ const name = p.base.toLowerCase();
20
+ if (name === "dockerfile") return "dockerfile";
21
+ if (name === "makefile") return "makefile";
22
+ return EXT_LANG[p.ext.toLowerCase()] || "";
23
+ }
24
+
25
+ function countLines(content) {
26
+ if (!content) return 0;
27
+ const n = content.split("\n").length;
28
+ return content.endsWith("\n") ? n - 1 : n;
29
+ }
30
+
31
+ function showPreview(filePath, content, isEdit = false) {
32
+ const lang = detectLang(filePath);
33
+ const lineCount = countLines(content);
34
+ const byteSize = Buffer.byteLength(content, "utf-8");
35
+ const lines = content.split("\n");
36
+ const maxLines = 40;
37
+ const truncated = lines.length > maxLines;
38
+ const preview = truncated ? lines.slice(0, maxLines) : lines;
39
+
40
+ const sizeLabel = byteSize >= 1024 * 1024
41
+ ? `${(byteSize / (1024 * 1024)).toFixed(1)} MB`
42
+ : byteSize >= 1024
43
+ ? `${(byteSize / 1024).toFixed(1)} KB`
44
+ : `${byteSize} B`;
45
+
46
+ const action = isEdit ? "EDITED" : "CREATED";
47
+ const sep = `${C}${"━".repeat(60)}${R}`;
48
+ const line = `${C}${"─".repeat(60)}${R}`;
49
+
50
+ let out = `\n${B}${C}${sep}${R}`;
51
+ out += `\n${B}${G} ${action}: ${filePath}${R}`;
52
+ out += `\n${D} ${lineCount} lines | ${sizeLabel} | ${lang || "text"}${R}`;
53
+ out += `\n${line}`;
54
+
55
+ for (let i = 0; i < preview.length; i++) {
56
+ const ln = `${D}${String(i + 1).padStart(4)}${R}`;
57
+ const display = preview[i].length > 120 ? preview[i].slice(0, 120) + "..." : preview[i];
58
+ out += `\n ${ln} ${W}${display}${R}`;
59
+ }
60
+
61
+ if (truncated) {
62
+ const remaining = lines.length - preview.length;
63
+ out += `\n${D} ... ${remaining} more lines${R}`;
64
+ }
65
+ out += `\n${C}${sep}${R}\n`;
66
+
67
+ process.stdout.write(out + "\n");
68
+ return out;
69
+ }
70
+
71
+ module.exports = { showPreview, detectLang };
package/src/static.js ADDED
@@ -0,0 +1,2 @@
1
+ // Single-file token dashboard UI - identical to the Python build.
2
+ module.exports = "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>OGPT \u00b7 Token Dashboard</title>\n<script src=\"https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js\"></script>\n<style>\n:root{\n --bg:#0d0f14; --panel:#141822; --panel2:#181d2a; --line:#232a3a;\n --text:#e8ecf4; --dim:#8b93a7; --mag:#e34fd0; --cyan:#39c6e3;\n --green:#3ddc84; --red:#ff5c69; --amber:#ffc857; --radius:14px;\n --mono:\"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,monospace;\n}\n*{box-sizing:border-box}\nbody{margin:0;background:\n radial-gradient(1200px 500px at 80% -10%, #1a1030 0%, transparent 60%),\n radial-gradient(900px 400px at -10% 110%, #06202b 0%, transparent 55%),\n var(--bg);\n color:var(--text);font:15px/1.5 -apple-system,\"Segoe UI\",Roboto,sans-serif;}\n.wrap{max-width:1180px;margin:0 auto;padding:18px 20px 40px}\n\n/* topbar */\n.topbar{display:flex;align-items:center;gap:12px;padding:14px 4px;border-bottom:1px solid var(--line)}\n.logo{font-weight:800;font-size:19px;letter-spacing:.3px;color:var(--mag)}\n.logo .dot{color:var(--cyan)}\n.chip{background:var(--panel);border:1px solid var(--line);border-radius:999px;\n padding:4px 12px;font-size:12.5px;color:var(--dim)}\n.chip b{color:var(--text)}\n.live{margin-left:auto;display:flex;align-items:center;gap:7px;font-size:12px;color:var(--green)}\n.live i{width:9px;height:9px;border-radius:50%;background:var(--green);\n box-shadow:0 0 0 0 rgba(61,220,132,.6);animation:pulse 1.6s infinite}\n@keyframes pulse{70%{box-shadow:0 0 0 8px rgba(61,220,132,0)}100%{box-shadow:0 0 0 0 rgba(61,220,132,0)}}\n\n/* cards */\n.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin:18px 0}\n.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:14px 16px}\n.card .k{font-size:11.5px;text-transform:uppercase;letter-spacing:.08em;color:var(--dim)}\n.card .v{font-family:var(--mono);font-size:24px;font-weight:700;margin-top:4px}\n.card .s{font-size:11.5px;color:var(--dim);margin-top:2px}\n.v.mag{color:var(--mag)} .v.cyan{color:var(--cyan)} .v.green{color:var(--green)} .v.amber{color:var(--amber)}\n\n/* panels & charts */\n.grid2{display:grid;grid-template-columns:2fr 1fr;gap:12px;margin-bottom:12px}\n.panel{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:14px 16px}\n.panel h3{margin:0 0 10px;font-size:13px;color:var(--dim);text-transform:uppercase;letter-spacing:.07em}\ncanvas{width:100%!important;height:240px!important}\n\n/* main columns */\n.main{display:grid;grid-template-columns:1fr 380px;gap:12px}\n@media(max-width:900px){.main,.grid2{grid-template-columns:1fr}}\n#feed{height:430px;overflow-y:auto;display:flex;flex-direction:column;gap:10px;padding-right:6px}\n.msg{border:1px solid var(--line);border-left:3px solid var(--cyan);border-radius:10px;\n background:var(--panel2);padding:10px 12px}\n.msg.user{border-left-color:var(--mag)}\n.msg .who{font-size:11.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--dim);margin-bottom:3px}\n.msg.user .who{color:var(--mag)} .msg.bot .who{color:var(--cyan)}\n.msg .txt{white-space:pre-wrap;word-wrap:break-word;font-size:14px}\n.meta{font-size:11px;color:var(--dim);font-family:var(--mono);margin-top:6px}\n.empty{color:var(--dim);text-align:center;padding:30px 0}\n\n/* chat composer */\n.composer{display:flex;flex-direction:column;gap:8px}\n#chat-in{width:100%;min-height:74px;resize:vertical;background:var(--panel2);color:var(--text);\n border:1px solid var(--line);border-radius:10px;padding:10px 12px;font:inherit}\n#chat-in:focus{outline:none;border-color:var(--mag)}\n.rowbtn{display:flex;gap:8px;align-items:center}\nbutton.send{background:linear-gradient(135deg,var(--mag),#8a4fe3);border:0;color:#fff;font-weight:700;\n padding:9px 20px;border-radius:999px;cursor:pointer;font-size:14px}\nbutton.send:disabled{opacity:.45;cursor:not-allowed}\n.hint{font-size:11.5px;color:var(--dim)}\n\n/* bottom tables */\n.bottom{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:12px}\n@media(max-width:900px){.bottom{grid-template-columns:1fr}}\ntable{width:100%;border-collapse:collapse;font-size:13px}\ntd,th{padding:7px 8px;border-bottom:1px solid var(--line);text-align:left}\nth{color:var(--dim);font-weight:600;font-size:11.5px;text-transform:uppercase;letter-spacing:.06em}\n.tools{display:flex;flex-wrap:wrap;gap:7px}\n.toolchip{background:var(--panel2);border:1px solid var(--line);border-radius:999px;\n padding:4px 11px;font-size:12px;color:var(--cyan);font-family:var(--mono)}\nfooter{margin-top:22px;color:var(--dim);font-size:12px;display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px}\nfooter code{font-family:var(--mono);color:var(--cyan)}\n</style>\n</head>\n<body>\n<div class=\"wrap\">\n\n <div class=\"topbar\">\n <span class=\"logo\">\u25c6 OGPT<span class=\"dot\"> \u00b7 </span>Token Dashboard</span>\n <span class=\"chip\" id=\"chip-model\"><b>\u2014</b></span>\n <span class=\"chip\" id=\"chip-provider\">provider \u2014</span>\n <span class=\"live\"><i></i> LIVE</span>\n </div>\n\n <div class=\"cards\">\n <div class=\"card\"><div class=\"k\">Total tokens</div><div class=\"v mag\" id=\"c-total\">0</div><div class=\"s\" id=\"c-total-s\">prompt + completion</div></div>\n <div class=\"card\"><div class=\"k\">Prompt tokens</div><div class=\"v\" id=\"c-prompt\">0</div></div>\n <div class=\"card\"><div class=\"k\">Completion tokens</div><div class=\"v cyan\" id=\"c-completion\">0</div></div>\n <div class=\"card\"><div class=\"k\">Avg speed</div><div class=\"v green\" id=\"c-avgtps\">\u2013</div><div class=\"s\">tokens/sec</div></div>\n <div class=\"card\"><div class=\"k\">Best speed</div><div class=\"v green\" id=\"c-besttps\">\u2013</div></div>\n <div class=\"card\"><div class=\"k\">Last TTFT</div><div class=\"v amber\" id=\"c-ttft\">\u2013</div><div class=\"s\">time to first token</div></div>\n <div class=\"card\"><div class=\"k\">Messages</div><div class=\"v\" id=\"c-msgs\">0</div><div class=\"s\" id=\"c-runs\">0 runs tracked</div></div>\n <div class=\"card\"><div class=\"k\">Uptime</div><div class=\"v\" id=\"c-uptime\">0:00</div><div class=\"s\" id=\"c-session\">no session</div></div>\n </div>\n\n <div class=\"grid2\">\n <div class=\"panel\"><h3>Tokens per run</h3><canvas id=\"ch-runs\"></canvas></div>\n <div class=\"panel\"><h3>Token split</h3><canvas id=\"ch-split\"></canvas></div>\n </div>\n\n <div class=\"main\">\n <div class=\"panel\"><h3>Conversation</h3><div id=\"feed\"><div class=\"empty\">No messages yet.</div></div></div>\n <div class=\"panel composer-panel\">\n <h3>Chat with this agent</h3>\n <div class=\"composer\">\n <textarea id=\"chat-in\" placeholder=\"Ask anything\u2026 (shares the same brain as the terminal session)\"></textarea>\n <div class=\"rowbtn\">\n <button class=\"send\" id=\"chat-send\">Send \u23ce</button>\n <span class=\"hint\" id=\"chat-hint\">Streams from the live model.</span>\n </div>\n <div class=\"hint\">Enter to send \u00b7 Shift+Enter newline</div>\n </div>\n </div>\n </div>\n\n <div class=\"bottom\">\n <div class=\"panel\"><h3>Sessions</h3>\n <table><thead><tr><th>ID</th><th>Title</th><th>Msgs</th><th>Updated</th></tr></thead>\n <tbody id=\"sess-rows\"><tr><td colspan=\"4\" style=\"color:var(--dim)\">\u2014</td></tr></tbody></table>\n </div>\n <div class=\"panel\"><h3>Registered tools (<span id=\"tool-count\">0</span>)</h3>\n <div class=\"tools\" id=\"tools-list\"><span style=\"color:var(--dim)\">\u2014</span></div>\n </div>\n </div>\n\n <footer>\n <span>OGPT v1.1.0 \u00b7 dashboard bound to <code>127.0.0.1</code> only</span>\n <span>polling every 1.5s \u00b7 <code>/api/stats</code></span>\n </footer>\n</div>\n\n<script>\nconst $=id=>document.getElementById(id);\nconst fmt=n=>Number(n||0).toLocaleString();\nlet runsChart=null, splitChart=null;\nlet lastHistoryKey=\"\", busy=false;\n\nfunction fmtDur(s){s=Math.floor(s||0);const h=Math.floor(s/3600),m=Math.floor(s%3600/60),\n x=s%60;return (h?h+\":\":\"\")+m+\":\"+String(x).padStart(2,\"0\");}\nfunction setText(id,v){$(id).textContent=v;}\n\nasync function poll(){\n try{\n const d=await (await fetch(\"/api/stats\")).json();\n setText(\"chip-model\",\"\");$(\"chip-model\").innerHTML=\"<b>\"+d.model+\"</b>\";\n $(\"chip-provider\").textContent=\"provider \"+d.provider+\" \u00b7 \"+d.cwd;\n setText(\"c-total\",fmt(d.tokens.total));\n setText(\"c-total-s\",fmt(d.tokens.prompt)+\" prompt + \"+fmt(d.tokens.completion)+\" completion\");\n setText(\"c-prompt\",fmt(d.tokens.prompt));\n setText(\"c-completion\",fmt(d.tokens.completion));\n setText(\"c-avgtps\",d.avg_tps?d.avg_tps.toFixed(1):\"\u2013\");\n setText(\"c-besttps\",d.best_tps?d.best_tps.toFixed(1):\"\u2013\");\n const lr=d.last_run||{};\n setText(\"c-ttft\",(lr.ttft!=null)?lr.ttft.toFixed(2)+\"s\":\"\u2013\");\n setText(\"c-msgs\",fmt(d.messages));\n setText(\"c-runs\",fmt(d.runs_count)+\" runs tracked\");\n setText(\"c-uptime\",fmtDur(d.uptime_s));\n setText(\"c-session\",d.session?(\"session \"+d.session):\"no session\");\n updateCharts(d);\n }catch(e){/* server gone quiet */}\n}\n\nfunction ensureCharts(){\n if(!window.Chart||runsChart)return;\n Chart.defaults.color=\"#8b93a7\";Chart.defaults.borderColor=\"#232a3a\";\n runsChart=new Chart($(\"ch-runs\"),{type:\"line\",\n data:{labels:[],datasets:[{label:\"tokens\",data:[],borderColor:\"#e34fd0\",\n backgroundColor:\"rgba(227,79,208,.15)\",fill:true,tension:.35,pointRadius:2}]},\n options:{animation:false,maintainAspectRatio:false,\n scales:{y:{beginAtZero:true},x:{ticks:{maxTicksLimit:10}}}}});\n splitChart=new Chart($(\"ch-split\"),{type:\"doughnut\",\n data:{labels:[\"prompt\",\"completion\"],\n datasets:[{data:[0,0],backgroundColor:[\"#39c6e3\",\"#e34fd0\"],borderWidth:0}]},\n options:{animation:false,maintainAspectRatio:false,cutout:\"62%\",\n plugins:{legend:{position:\"bottom\"}}}});\n}\nfunction updateCharts(d){\n ensureCharts();if(!runsChart)return;\n const rs=d.runs||[];\n runsChart.data.labels=rs.map(r=>new Date(r.ts*1000).toLocaleTimeString());\n runsChart.data.datasets[0].data=rs.map(r=>r.tokens);\n runsChart.update(\"none\");\n splitChart.data.datasets[0].data=[d.tokens.prompt,d.tokens.completion];\n splitChart.update(\"none\");\n}\n\nasync function loadHistory(force){\n try{\n const msgs=await (await fetch(\"/api/history\")).json();\n const key=msgs.length+\":\"+((msgs[msgs.length-1]||{}).ts||0);\n if(!force&&key===lastHistoryKey)return;\n lastHistoryKey=key;\n const feed=$(\"feed\");feed.textContent=\"\";\n if(!msgs.length){feed.innerHTML='<div class=\"empty\">No messages yet.</div>';return;}\n for(const m of msgs){\n const div=document.createElement(\"div\");\n div.className=\"msg \"+(m.role===\"user\"?\"user\":\"bot\");\n const who=document.createElement(\"div\");who.className=\"who\";\n who.textContent=m.role===\"user\"?\"\u276f You\":\"\u25cf oGPT\";\n const txt=document.createElement(\"div\");txt.className=\"txt\";\n txt.textContent=m.content;\n div.append(who,txt);\n if(m.ts){const meta=document.createElement(\"div\");meta.className=\"meta\";\n meta.textContent=new Date(m.ts*1000).toLocaleString();div.append(meta);}\n feed.appendChild(div);\n }\n feed.scrollTop=feed.scrollHeight;\n }catch(e){}\n}\n\nfunction addBubble(kind){\n const div=document.createElement(\"div\");\n div.className=\"msg \"+kind;\n const who=document.createElement(\"div\");who.className=\"who\";\n who.textContent=kind===\"user\"?\"\u276f You\":\"\u25cf oGPT\";\n const txt=document.createElement(\"div\");txt.className=\"txt\";\n if(kind!==\"user\"){const m=document.createElement(\"div\");m.className=\"meta\";\n m.textContent=\"streaming\u2026\";txt.dataset.meta=m;txt.append(m);}\n div.append(who,txt);$(\"feed\").appendChild(div);\n $(\"feed\").scrollTop=$(\"feed\").scrollHeight;\n return txt;\n}\nfunction sendChat(){\n if(busy)return;\n const inp=$(\"chat-in\"),msg=inp.value.trim();\n if(!msg)return;\n inp.value=\"\";busy=true;$(\"chat-send\").disabled=true;\n addBubble(\"user\");\n const bot=addBubble(\"bot\");\n let acc=\"\";\n const es=new EventSource(\"/api/chat/stream?msg=\"+encodeURIComponent(msg));\n es.onmessage=e=>{\n let d;try{d=JSON.parse(e.data);}catch(_){return;}\n if(d.t){acc+=d.t;bot.textContent=acc;\n $(\"feed\").scrollTop=$(\"feed\").scrollHeight;}\n if(d.error){acc+=\"\\n[error] \"+d.error;bot.textContent=acc;}\n if(d.done){es.close();\n const s=d.stats||{};const bits=[];\n if(s.tokens)bits.push(s.tokens+\" tok\");\n if(s.tps)bits.push(s.tps+\" tok/s\");\n bot.dataset.meta&&(bot.querySelector(\".meta\")||{}).remove;\n const meta=document.createElement(\"div\");meta.className=\"meta\";\n meta.textContent=bits.length?bits.join(\" \u00b7 \"):\"done\";\n bot.parentElement.appendChild(meta);\n busy=false;$(\"chat-send\").disabled=false;loadHistory(true);}\n };\n es.onerror=()=>{es.close();busy=false;$(\"chat-send\").disabled=false;};\n}\n$(\"chat-send\").addEventListener(\"click\",sendChat);\n$(\"chat-in\").addEventListener(\"keydown\",ev=>{\n if(ev.key===\"Enter\"&&!ev.shiftKey){ev.preventDefault();sendChat();}\n});\n\nasync function loadBottom(){\n try{\n const rows=await (await fetch(\"/api/sessions\")).json();\n const tb=$(\"sess-rows\");tb.textContent=\"\";\n if(!rows.length){tb.innerHTML='<tr><td colspan=\"4\" style=\"color:var(--dim)\">\u2014</td></tr>';return;}\n for(const s of rows){\n const tr=document.createElement(\"tr\");\n [s.id,s.title,s.msgs,new Date((s.updated||0)*1000).toLocaleString()].forEach(v=>{\n const td=document.createElement(\"td\");td.textContent=v??\"\";tr.appendChild(td);});\n tb.appendChild(tr);\n }\n }catch(e){}\n try{\n const names=await (await fetch(\"/api/tools\")).json();\n $(\"tool-count\").textContent=names.length;\n const list=$(\"tools-list\");list.textContent=\"\";\n for(const n of names){const c=document.createElement(\"span\");\n c.className=\"toolchip\";c.textContent=n;list.appendChild(c);}\n }catch(e){}\n}\n\npoll();loadHistory();loadBottom();\nsetInterval(poll,1500);\nsetInterval(()=>loadHistory(false),5000);\nsetInterval(loadBottom,20000);\nensureCharts();\n</script>\n</body>\n</html>\n";