mirror of
https://github.com/multipleof4/devsune.git
synced 2026-01-13 16:07:55 +00:00
This build was committed by a bot.
This commit is contained in:
3
dist/index.html
vendored
3
dist/index.html
vendored
@@ -12,6 +12,7 @@
|
||||
.msg-avatar{font-size:16px}
|
||||
.menu-card{position:fixed;z-index:60;min-width:12rem;border-radius:0.75rem;border:1px solid #e5e7eb;background:#fff;box-shadow:0 10px 20px rgba(0,0,0,.08)}
|
||||
.menu-item{width:100%;text-align:left;padding:.5rem .75rem;font-size:0.875rem;display:flex;align-items:center;gap:.5rem}
|
||||
#htmlEditor{outline:none;white-space:pre!important}
|
||||
</style>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
|
||||
<meta charset="utf-8">
|
||||
@@ -20,7 +21,7 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/tiny-ripple@0.2.0"></script>
|
||||
<style>:root{--safe-bottom:env(safe-area-inset-bottom)}::-webkit-scrollbar{height:8px;width:8px}::-webkit-scrollbar-thumb{background:#e5e7eb;border-radius:999px}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}</style>
|
||||
<style>html,body{overscroll-behavior-y:contain}</style>
|
||||
<style>#htmlEditor{outline:none;white-space:pre!important}</style>
|
||||
<style></style>
|
||||
<link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
|
||||
<body class="bg-white text-gray-900 selection:bg-black/10" hx-on="click: if(!document.getElementById('historyMenu').contains(event.target)&&!event.target.closest('[data-thread-menu]')) hideHistoryMenu(); if(!document.getElementById('suneMenu').contains(event.target)&&!event.target.closest('[data-sune-menu]')) hideSuneMenu(); if(!document.getElementById('userMenu').contains(event.target)&&!document.getElementById('userMenuBtn').contains(event.target)) document.getElementById('userMenu').classList.add('hidden')">
|
||||
<div class="flex flex-col h-dvh max-h-dvh">
|
||||
|
||||
2
dist/sw.js
vendored
2
dist/sw.js
vendored
@@ -1 +1 @@
|
||||
if(!self.define){let e,i={};const t=(t,n)=>(t=new URL(t+".js",n).href,i[t]||new Promise(i=>{if("document"in self){const e=document.createElement("script");e.src=t,e.onload=i,document.head.appendChild(e)}else e=t,importScripts(t),i()}).then(()=>{let e=i[t];if(!e)throw new Error(`Module ${t} didn’t register its module`);return e}));self.define=(n,r)=>{const s=e||("document"in self?document.currentScript.src:"")||location.href;if(i[s])return;let o={};const d=e=>t(e,s),c={module:{uri:s},exports:o,require:d};i[s]=Promise.all(n.map(e=>c[e]||d(e))).then(e=>(r(...e),o))}}define(["./workbox-5ffe50d4"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"index.html",revision:"412032a1d197f46e4f856ace87b5b16d"},{url:"registerSW.js",revision:"1872c500de691dce40960bb85481de07"},{url:"manifest.webmanifest",revision:"7a6c5c6ab9cb5d3605d21df44c6b17a2"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html")))});
|
||||
if(!self.define){let e,i={};const t=(t,n)=>(t=new URL(t+".js",n).href,i[t]||new Promise(i=>{if("document"in self){const e=document.createElement("script");e.src=t,e.onload=i,document.head.appendChild(e)}else e=t,importScripts(t),i()}).then(()=>{let e=i[t];if(!e)throw new Error(`Module ${t} didn’t register its module`);return e}));self.define=(n,r)=>{const s=e||("document"in self?document.currentScript.src:"")||location.href;if(i[s])return;let o={};const d=e=>t(e,s),c={module:{uri:s},exports:o,require:d};i[s]=Promise.all(n.map(e=>c[e]||d(e))).then(e=>(r(...e),o))}}define(["./workbox-5ffe50d4"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"index.html",revision:"f6172270f99df5a9dae074fb3eb3fca4"},{url:"registerSW.js",revision:"1872c500de691dce40960bb85481de07"},{url:"manifest.webmanifest",revision:"7a6c5c6ab9cb5d3605d21df44c6b17a2"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html")))});
|
||||
|
||||
29
index.html
29
index.html
@@ -12,6 +12,7 @@
|
||||
.msg-avatar{font-size:16px}
|
||||
.menu-card{position:fixed;z-index:60;min-width:12rem;border-radius:0.75rem;border:1px solid #e5e7eb;background:#fff;box-shadow:0 10px 20px rgba(0,0,0,.08)}
|
||||
.menu-item{width:100%;text-align:left;padding:.5rem .75rem;font-size:0.875rem;display:flex;align-items:center;gap:.5rem}
|
||||
#htmlEditor{outline:none;white-space:pre!important}
|
||||
</style>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
|
||||
</head>
|
||||
@@ -96,13 +97,7 @@
|
||||
<div><label class="block text-gray-700 font-medium mb-1">System Prompt</label><textarea id="set_system_prompt" rows="8" class="w-full rounded-xl border border-gray-300 px-3 py-2" placeholder="Enter a system prompt to guide the sune"></textarea><div class="mt-2 flex gap-2"><button type="button" id="copySystemPrompt" class="px-3 py-1.5 rounded-lg bg-gray-100 hover:bg-gray-200">Copy</button><button type="button" id="pasteSystemPrompt" class="px-3 py-1.5 rounded-lg bg-gray-100 hover:bg-gray-200">Paste</button></div><p class="mt-1 text-xs text-gray-500">Saved per sune.</p></div>
|
||||
</div>
|
||||
<div id="panelScript" class="p-4 hidden">
|
||||
<div class="border-b flex text-xs font-medium pt-0 mt-0"><button type="button" id="htmlTab_index" class="flex-1 py-2 px-3 text-center border-b-2"></button><button type="button" id="htmlTab_extension" class="flex-1 py-2 px-3 text-center border-b-2"></button></div>
|
||||
<div class="pt-0 space-y-4">
|
||||
<pre id="htmlEditor" class="w-full h-[50vh] p-3 rounded-xl border border-gray-300 bg-white overflow-auto font-mono text-[12px] leading-5" contenteditable="plaintext-only" spellcheck="false"></pre>
|
||||
<pre id="extensionHtmlEditor" class="w-full h-[50vh] p-3 rounded-xl border border-gray-300 bg-white overflow-auto font-mono text-[12px] leading-5 hidden" contenteditable="plaintext-only" spellcheck="false"></pre>
|
||||
</div>
|
||||
<div class="mt-2 flex gap-2"><button type="button" id="copyHTML" class="px-3 py-1.5 rounded-lg bg-gray-100 hover:bg-gray-200">Copy</button><button type="button" id="pasteHTML" class="px-3 py-1.5 rounded-lg bg-gray-100 hover:bg-gray-200">Paste</button></div>
|
||||
<p class="mt-1 text-xs text-gray-500">Scripts also run. extension.html runs after index.html.</p>
|
||||
<pre id="htmlEditor" class="w-full h-[50vh] p-3 rounded-xl border border-gray-300 bg-white overflow-auto font-mono text-[12px] leading-5" contenteditable="plaintext-only" spellcheck="false"></pre><div class="mt-2 flex gap-2"><button type="button" id="copyHTML" class="px-3 py-1.5 rounded-lg bg-gray-100 hover:bg-gray-200">Copy</button><button type="button" id="pasteHTML" class="px-3 py-1.5 rounded-lg bg-gray-100 hover:bg-gray-200">Paste</button></div><p class="mt-1 text-xs text-gray-500">Scripts also run.</p>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-2 px-4 py-3 border-t">
|
||||
<button type="button" id="deleteSuneBtn" class="inline-flex items-center gap-2 px-3 py-2 rounded-xl border border-red-200 text-red-700 hover:bg-red-50"><svg viewBox="0 0 24 24" class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 6h18M8 6v12a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2V6m-9 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg><span>Delete sune</span></button>
|
||||
@@ -144,7 +139,7 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/localforage@1.10.0/dist/localforage.min.js"></script>
|
||||
<script>
|
||||
const DEFAULT_MODEL='openai/gpt-5',DEFAULT_API_KEY=''
|
||||
const el=Object.fromEntries(['chat','messages','composer','input','sendBtn','settingsBtnTop','settingsModal','settingsForm','closeSettings','cancelSettings','tabModel','tabPrompt','tabScript','panelModel','panelPrompt','panelScript','set_model','set_temperature','set_top_p','set_top_k','set_frequency_penalty','set_presence_penalty','set_repetition_penalty','set_min_p','set_top_a','set_max_tokens','set_verbosity','set_reasoning_effort','set_system_prompt','deleteSuneBtn','sidebar','sidebarOverlay','sidebarBtn','suneList','newSuneBtn','userMenuBtn','userMenu','accountSettingsOption','sunesImportOption','sunesExportOption','threadsImportOption','threadsExportOption','importInput','historyBtn','historyPanel','historyOverlay','historyList','closeHistory','historyMenu','suneMenu','footer','attachBtn','attachBadge','fileInput','htmlEditor','extensionHtmlEditor','htmlTab_index','htmlTab_extension','suneHtml','accountSettingsModal','accountSettingsForm','closeAccountSettings','cancelAccountSettings','set_master_prompt','set_provider','set_api_key_or','set_api_key_oai','set_title_model','copySystemPrompt','pasteSystemPrompt','copyHTML','pasteHTML','accountTabGeneral','accountTabAPI','accountPanelGeneral','accountPanelAPI','set_gh_token','importAccountSettings','exportAccountSettings','importAccountSettingsInput'].map(id=>[id,document.getElementById(id)]))
|
||||
const el=Object.fromEntries(['chat','messages','composer','input','sendBtn','settingsBtnTop','settingsModal','settingsForm','closeSettings','cancelSettings','tabModel','tabPrompt','tabScript','panelModel','panelPrompt','panelScript','set_model','set_temperature','set_top_p','set_top_k','set_frequency_penalty','set_presence_penalty','set_repetition_penalty','set_min_p','set_top_a','set_max_tokens','set_verbosity','set_reasoning_effort','set_system_prompt','deleteSuneBtn','sidebar','sidebarOverlay','sidebarBtn','suneList','newSuneBtn','userMenuBtn','userMenu','accountSettingsOption','sunesImportOption','sunesExportOption','threadsImportOption','threadsExportOption','importInput','historyBtn','historyPanel','historyOverlay','historyList','closeHistory','historyMenu','suneMenu','footer','attachBtn','attachBadge','fileInput','htmlEditor','suneHtml','accountSettingsModal','accountSettingsForm','closeAccountSettings','cancelAccountSettings','set_master_prompt','set_provider','set_api_key_or','set_api_key_oai','set_title_model','copySystemPrompt','pasteSystemPrompt','copyHTML','pasteHTML','accountTabGeneral','accountTabAPI','accountPanelGeneral','accountPanelAPI','set_gh_token','importAccountSettings','exportAccountSettings','importAccountSettingsInput'].map(id=>[id,document.getElementById(id)]))
|
||||
const icons=()=>window.lucide&&lucide.createIcons()
|
||||
const clamp=(v,min,max)=>Math.max(min,Math.min(max,v)),num=(v,d)=>v==null||v===''||isNaN(+v)?d:+v,int=(v,d)=>v==null||v===''||isNaN(parseInt(v))?d:parseInt(v),gid=()=>Math.random().toString(36).slice(2,9),esc=s=>String(s).replace(/[&<>'"`]/g,c=>({"&":"&","<":"<",">":">","\"":""","'":"'","`":"`"}[c]))
|
||||
const sid=()=>Date.now().toString(36)+Math.random().toString(36).slice(2,6)
|
||||
@@ -153,7 +148,7 @@ const asDataURL=f=>new Promise(r=>{const fr=new FileReader();fr.onload=()=>r(Str
|
||||
const b64=x=>x.split(',')[1]||''
|
||||
const globalStore={get provider(){return localStorage.getItem('provider')||'openrouter'},set provider(v){localStorage.setItem('provider',v==='openai'?'openai':'openrouter')},get apiKeyOR(){return localStorage.getItem('openrouter_api_key')||DEFAULT_API_KEY||''},set apiKeyOR(v){localStorage.setItem('openrouter_api_key',v||'')},get apiKeyOAI(){return localStorage.getItem('openai_api_key')||''},set apiKeyOAI(v){localStorage.setItem('openai_api_key',v||'')},get masterPrompt(){return localStorage.getItem('master_prompt')||''},set masterPrompt(v){localStorage.setItem('master_prompt',v||'')},get titleModel(){return localStorage.getItem('title_model')??'or:meta-llama/llama-3.2-3b-instruct'},set titleModel(v){localStorage.setItem('title_model',v||'')},get ghToken(){return localStorage.getItem('gh_token')||''},set ghToken(v){localStorage.setItem('gh_token',v||'')}}
|
||||
const su={key:'sunes_v1',activeKey:'active_sune_id',load(){try{return JSON.parse(localStorage.getItem(this.key)||'[]')}catch{return[]}},save(list){localStorage.setItem(this.key,JSON.stringify(list||[]))},getActiveId(){return localStorage.getItem(this.activeKey)||null},setActiveId(id){localStorage.setItem(this.activeKey,id||'')}}
|
||||
const defaultSettings={model:DEFAULT_MODEL,temperature:1,top_p:0.97,top_k:0,frequency_penalty:0,presence_penalty:0,repetition_penalty:1,min_p:0,top_a:0,max_tokens:0,verbosity:'',reasoning_effort:'default',system_prompt:'',html:'',extension_html:''}
|
||||
const defaultSettings={model:DEFAULT_MODEL,temperature:1,top_p:0.97,top_k:0,frequency_penalty:0,presence_penalty:0,repetition_penalty:1,min_p:0,top_a:0,max_tokens:0,verbosity:'',reasoning_effort:'default',system_prompt:'',html:''}
|
||||
const makeSune=(p={})=>({id:p.id||gid(),name:p.name?.trim()||'Default',pinned:!!p.pinned,avatar:p.avatar||'',updatedAt:p.updatedAt||Date.now(),settings:Object.assign({},defaultSettings,p.settings||{})})
|
||||
let sunes=(su.load()||[]).map(makeSune)
|
||||
if(!sunes.length){const def=makeSune({name:'Default'});sunes=[def];su.save(sunes);su.setActiveId(def.id)}
|
||||
@@ -161,7 +156,7 @@ const getActiveSune=()=>sunes.find(a=>a.id===su.getActiveId())||sunes[0],createD
|
||||
const store=new Proxy({},{get(_,p){if(p==='provider')return globalStore.provider;if(p==='apiKey')return globalStore.provider==='openai'?globalStore.apiKeyOAI:globalStore.apiKeyOR;if(p==='apiKeyOR')return globalStore.apiKeyOR;if(p==='apiKeyOAI')return globalStore.apiKeyOAI;if(p==='masterPrompt')return globalStore.masterPrompt;if(p==='titleModel')return globalStore.titleModel;const a=getActiveSune();if(p==='model')return a.settings.model;if(p in a.settings)return a.settings[p];if(p==='system_prompt')return a.settings.system_prompt},set(_,p,v){if(p==='provider'){globalStore.provider=v;return true}if(p==='apiKey'){if(globalStore.provider==='openai')globalStore.apiKeyOAI=v;else globalStore.apiKeyOR=v;return true}if(p==='apiKeyOR'){globalStore.apiKeyOR=v;return true}if(p==='apiKeyOAI'){globalStore.apiKeyOAI=v;return true}if(p==='masterPrompt'){globalStore.masterPrompt=v;return true}if(p==='titleModel'){globalStore.titleModel=v;return true}const i=sunes.findIndex(a=>a.id===getActiveSune().id);if(i>=0){if(p==='model')sunes[i].settings.model=v||DEFAULT_MODEL;else if(p==='system_prompt')sunes[i].settings.system_prompt=v||'';else sunes[i].settings[p]=v;sunes[i].updatedAt=Date.now();su.save(sunes);return true}return false}})
|
||||
const state={messages:[],busy:false,controller:null,currentThreadId:null,abortRequested:false,attachments:[],stream:{rid:null,bubble:null,meta:null,text:'',done:false}}
|
||||
const getModelShort=m=>{const mm=m||store.model||'';return mm.includes('/')?mm.split('/').pop():mm}
|
||||
const renderSuneHTML=()=>{const s=getActiveSune().settings,c=[s.html,s.extension_html].map(x=>(x||'').trim()).join('\n'),m=el.suneHtml;m.innerHTML='';m.classList.toggle('hidden',!c);if(!c)return;m.insertAdjacentHTML('afterbegin',c);m.querySelectorAll('script').forEach(s=>{const n=document.createElement('script');[...s.attributes].forEach(a=>n.setAttribute(a.name,a.value));n.text=s.text;s.replaceWith(n)})}
|
||||
const renderSuneHTML=()=>{const m=el.suneHtml,h=(getActiveSune().settings.html||'').trim();m.innerHTML='';m.classList.toggle('hidden',!h);if(!h)return;m.insertAdjacentHTML('afterbegin',h);m.querySelectorAll('script').forEach(s=>{const n=document.createElement('script');[...s.attributes].forEach(a=>n.setAttribute(a.name,a.value));n.text=s.text; s.replaceWith(n)})}
|
||||
const reflectActiveSune=()=>{const a=getActiveSune();el.settingsBtnTop.title=`Settings — ${a.name}`;el.settingsBtnTop.innerHTML=a.avatar?`<img src="${esc(a.avatar)}" alt="" class="h-8 w-8 rounded-full object-cover"/>`:'✺';icons();renderSuneHTML()}
|
||||
const suneRow=a=>`<div class="relative flex items-center gap-2 px-3 py-2 ${a.pinned?'bg-yellow-50':''}"><button data-sune-id="${a.id}" class="flex-1 text-left flex items-center gap-2 ${a.id===su.getActiveId()?'font-medium':''}">${a.avatar?`<img src="${esc(a.avatar)}" alt="" class="h-6 w-6 rounded-full object-cover"/>`:`<span class="h-6 w-6 rounded-full bg-gray-200 flex items-center justify-center">✺</span>`}<span class="truncate">${a.pinned?'📌 ':''}${esc(a.name)}</span></button><button data-sune-menu="${a.id}" class="h-8 w-8 rounded hover:bg-gray-100 flex items-center justify-center" title="More"><i data-lucide="more-horizontal" class="h-4 w-4"></i></button></div>`
|
||||
const renderSidebar=()=>{const list=[...sunes].sort((a,b)=>(b.pinned-a.pinned));el.suneList.innerHTML=list.map(suneRow).join('');icons()}
|
||||
@@ -201,12 +196,12 @@ el.attachBtn.addEventListener('click',()=>{if(state.busy)return;if(state.attachm
|
||||
el.fileInput.addEventListener('change',async()=>{const files=[...(el.fileInput.files||[])];if(!files.length)return;for(const f of files){const at=await toAttach(f).catch(()=>null);if(at)state.attachments.push(at)}updateAttachBadge()})
|
||||
el.messages.addEventListener('click',async e=>{const a=e.target.closest('a[href^="#dl-"]');if(!a)return; e.preventDefault();const m=a.getAttribute('href').match(/^#dl-([^-]+)-(\d+)$/);if(!m)return;const id=m[1],i=+m[2];const msg=state.messages.find(x=>x.id===id),meta=msg?.attachmentsMeta?.[i];if(!meta)return;let blob;if(meta.mode==='dataURL'){blob=await (await fetch(meta.data)).blob()}else{const bin=Uint8Array.from(atob(meta.data),c=>c.charCodeAt(0));blob=new Blob([bin],{type:meta.mime||'application/octet-stream'})}const url=URL.createObjectURL(blob),dl=document.createElement('a');dl.href=url;dl.download=meta.name||'download';document.body.appendChild(dl);dl.click();dl.remove();URL.revokeObjectURL(url)})
|
||||
el.composer.addEventListener('submit',async e=>{e.preventDefault();if(state.busy)return;const text=el.input.value.trim();if(!text&&!state.attachments.length)return;if(state.messages.length===0)state.currentThreadId=null;await ensureThreadOnFirstUser(text||'(attachments)');el.input.value='';const parts=[];if(text)parts.push({type:'text',text});state.attachments.forEach(a=>parts.push(a.part));addMessage({role:'user',content:parts.length?parts:[{type:'text',text:text||'(sent attachments)'}]});if(state.attachments.length)addAttachmentTree('user',state.attachments);state.busy=true;setBtnStop();const a=getActiveSune();const suneMeta={sune_name:a.name,model:store.model,avatar:a.avatar||''};const suneBubble=addSuneBubbleStreaming(suneMeta);const streamId=sid();suneBubble.dataset.mid=streamId;const assistantMsg=Object.assign({id:streamId,role:'assistant',content:[{type:'text',text:''}]},suneMeta);state.messages.push(assistantMsg);persistThread(false);state.stream={rid:streamId,bubble:suneBubble,meta:suneMeta,text:'',done:false};let buf='',completed=false;const onDelta=(delta,done)=>{buf+=delta;state.stream.text=buf;renderMarkdown(suneBubble,buf,{enhance:false});assistantMsg.content[0].text=buf;if(done&&!completed){completed=true;setBtnSend();state.busy=false;enhanceCodeBlocks(suneBubble,true);persistThread(true);state.stream={rid:null,bubble:null,meta:null,text:'',done:false}}else if(!done)persistThread(false)};await askOpenRouterStreaming(onDelta,streamId);state.attachments=[];updateAttachBadge()})
|
||||
let jars={html:null,extension:null};const ensureJars=async()=>{if(jars.html&&jars.extension)return jars;const mod=await import('https://medv.io/codejar/codejar.js'),CodeJar=mod.CodeJar||mod.default,hl=e=>e.innerHTML=hljs.highlight(e.textContent,{language:'xml'}).value;if(!jars.html)jars.html=CodeJar(el.htmlEditor,hl,{tab:' '});if(!jars.extension)jars.extension=CodeJar(el.extensionHtmlEditor,hl,{tab:' '});return jars}
|
||||
let jars={html:null};const ensureJars=async()=>{if(jars.html)return jars;const mod=await import('https://medv.io/codejar/codejar.js'),CodeJar=mod.CodeJar||mod.default;jars.html=CodeJar(el.htmlEditor,ed=>ed.innerHTML=hljs.highlight(ed.textContent,{language:'xml'}).value,{tab:' '});return jars}
|
||||
let openedHTML=false
|
||||
function openSettings(){const a=getActiveSune(),s=a.settings;openedHTML=false;el.set_model.value=s.model;el.set_temperature.value=s.temperature;el.set_top_p.value=s.top_p;el.set_top_k.value=s.top_k;el.set_frequency_penalty.value=s.frequency_penalty;el.set_presence_penalty.value=s.presence_penalty;el.set_repetition_penalty.value=s.repetition_penalty;el.set_min_p.value=s.min_p;el.set_top_a.value=s.top_a;el.set_max_tokens.value=s.max_tokens||'';el.set_verbosity.value=s.verbosity||'';el.set_reasoning_effort.value=s.reasoning_effort||'default';el.set_system_prompt.value=s.system_prompt;showTab('Model');el.settingsModal.classList.remove('hidden')}
|
||||
const closeSettings=()=>{el.settingsModal.classList.add('hidden')}
|
||||
const tabs={Model:['tabModel','panelModel'],Prompt:['tabPrompt','panelPrompt'],Script:['tabScript','panelScript']}
|
||||
function showTab(key){Object.entries(tabs).forEach(([k,[tb,pn]])=>{el[tb].classList.toggle('border-black',k===key);el[pn].classList.toggle('hidden',k!==key)});if(key==='Script'){openedHTML=true;showHtmlTab('index');ensureJars().then(({html,extension})=>{const s=getActiveSune().settings;html.updateCode(s.html||'');extension.updateCode(s.extension_html||'')})}}
|
||||
function showTab(key){Object.entries(tabs).forEach(([k,[tb,pn]])=>{el[tb].classList.toggle('border-black',k===key);el[pn].classList.toggle('hidden',k!==key)});if(key==='Script'){openedHTML=true;ensureJars().then(({html})=>{html.updateCode(getActiveSune().settings.html||'')})}}
|
||||
el.settingsBtnTop.addEventListener('click',openSettings)
|
||||
el.closeSettings?.addEventListener('click',closeSettings)
|
||||
el.cancelSettings.addEventListener('click',closeSettings)
|
||||
@@ -214,7 +209,7 @@ el.settingsModal.addEventListener('click',e=>{if(e.target===el.settingsModal||e.
|
||||
el.tabModel.addEventListener('click',()=>showTab('Model'))
|
||||
el.tabPrompt.addEventListener('click',()=>showTab('Prompt'))
|
||||
el.tabScript.addEventListener('click',()=>showTab('Script'))
|
||||
el.settingsForm.addEventListener('submit',e=>{e.preventDefault();const a=getActiveSune(),s=a.settings;s.model=(el.set_model.value||DEFAULT_MODEL).trim();s.temperature=clamp(num(el.set_temperature.value,1.0),0,2);s.top_p=clamp(num(el.set_top_p.value,1.0),0,1);s.top_k=Math.max(0,int(el.set_top_k.value,0));s.frequency_penalty=clamp(num(el.set_frequency_penalty.value,0.0),-2,2);s.presence_penalty=clamp(num(el.set_presence_penalty.value,0.0),-2,2);s.repetition_penalty=clamp(num(el.set_repetition_penalty.value,1.0),0,2);s.min_p=clamp(num(el.set_min_p.value,0.0),0,1);s.top_a=clamp(num(el.set_top_a.value,0.0),0,1);s.max_tokens=Math.max(0,int(el.set_max_tokens.value,0));s.verbosity=(el.set_verbosity.value||'');s.reasoning_effort=(el.set_reasoning_effort.value||'default');s.system_prompt=el.set_system_prompt.value.trim();if(openedHTML){s.html=el.htmlEditor.textContent;s.extension_html=el.extensionHtmlEditor.textContent}a.updatedAt=Date.now();su.save(sunes);closeSettings();reflectActiveSune()})
|
||||
el.settingsForm.addEventListener('submit',e=>{e.preventDefault();const a=getActiveSune(),s=a.settings;s.model=(el.set_model.value||DEFAULT_MODEL).trim();s.temperature=clamp(num(el.set_temperature.value,1.0),0,2);s.top_p=clamp(num(el.set_top_p.value,1.0),0,1);s.top_k=Math.max(0,int(el.set_top_k.value,0));s.frequency_penalty=clamp(num(el.set_frequency_penalty.value,0.0),-2,2);s.presence_penalty=clamp(num(el.set_presence_penalty.value,0.0),-2,2);s.repetition_penalty=clamp(num(el.set_repetition_penalty.value,1.0),0,2);s.min_p=clamp(num(el.set_min_p.value,0.0),0,1);s.top_a=clamp(num(el.set_top_a.value,0.0),0,1);s.max_tokens=Math.max(0,int(el.set_max_tokens.value,0));s.verbosity=(el.set_verbosity.value||'');s.reasoning_effort=(el.set_reasoning_effort.value||'default');s.system_prompt=el.set_system_prompt.value.trim();if(openedHTML)s.html=el.htmlEditor.textContent;a.updatedAt=Date.now();su.save(sunes);closeSettings();reflectActiveSune()})
|
||||
el.deleteSuneBtn.addEventListener('click',()=>{const activeId=su.getActiveId(),active=getActiveSune(),name=active?.name||'this sune';if(!confirm(`Delete "${name}"?`))return;sunes=sunes.filter(a=>a.id!==activeId);su.save(sunes);if(sunes.length===0){const def=createDefaultSune();sunes=[def];su.save(sunes);su.setActiveId(def.id)}else{su.setActiveId(sunes[0].id)}renderSidebar();reflectActiveSune();state.currentThreadId=null;clearChat();closeSettings()})
|
||||
el.newSuneBtn.addEventListener('click',()=>{const name=prompt('Name your sune:');if(!name)return;const id=gid();sunes.unshift({id,name:name.trim(),pinned:false,avatar:'',updatedAt:Date.now(),settings:Object.assign({},defaultSettings)});su.save(sunes);su.setActiveId(id);renderSidebar();reflectActiveSune();state.currentThreadId=null;clearChat();document.getElementById('sidebar').classList.add('-translate-x-full');document.getElementById('sidebarOverlay').classList.add('hidden')})
|
||||
function dl(name,obj){const blob=new Blob([JSON.stringify(obj,null,2)],{type:'application/json'}),url=URL.createObjectURL(blob),a=document.createElement('a');a.href=url;a.download=name;document.body.appendChild(a);a.click();a.remove();URL.revokeObjectURL(url)}
|
||||
@@ -232,9 +227,6 @@ window.SUNE={attach:async(files,opts={})=>{const arr=[];for(const f of files||[]
|
||||
window.USER={log:async s=>{const t=String(s??'').trim();if(!t)return;await ensureThreadOnFirstUser(t);addMessage({role:'user',content:[{type:'text',text:t}]});await persistThread()}}
|
||||
async function init(){threads=await tload();await renderHistory();renderSidebar();reflectActiveSune();clearChat();icons();kbBind();kbUpdate()}
|
||||
window.addEventListener('resize',()=>{hideHistoryMenu();hideSuneMenu()})
|
||||
const htmlTabs={index:['htmlTab_index','htmlEditor'],extension:['htmlTab_extension','extensionHtmlEditor']};function showHtmlTab(key){Object.entries(htmlTabs).forEach(([k,[tb,pn]])=>{const a=k===key;el[tb].classList.toggle('border-black',a);el[tb].classList.toggle('border-transparent',!a);el[tb].classList.toggle('hover:border-gray-300',!a);el[pn].classList.toggle('hidden',!a)})}
|
||||
el.htmlTab_index.textContent='index.html';el.htmlTab_extension.textContent='extension.html';
|
||||
el.htmlTab_index.onclick=()=>showHtmlTab('index');el.htmlTab_extension.onclick=()=>showHtmlTab('extension');
|
||||
init()
|
||||
const HTTP_BASE='https://orp.awww.workers.dev/ws'
|
||||
const buildBody=()=>{const msgs=[];if(store.masterPrompt)msgs.push({role:'system',content:[{type:'text',text:store.masterPrompt}]});if(store.system_prompt)msgs.push({role:'system',content:[{type:'text',text:store.system_prompt}]});msgs.push(...state.messages.filter(m=>m.role!=='system').map(m=>({role:m.role,content:m.content})));const b=payloadWithSampling({model:store.model.replace(/^(or:|oai:)/,''),messages:msgs,stream:true});if(store.reasoning_effort&&store.reasoning_effort!=='default')b.reasoning={effort:store.reasoning_effort};if(store.verbosity)b.verbosity=store.verbosity;return b}
|
||||
@@ -260,9 +252,8 @@ const onForeground=()=>{if(document.visibilityState!=='visible')return;state.con
|
||||
document.addEventListener('visibilitychange',onForeground)
|
||||
el.copySystemPrompt.addEventListener('click',async()=>{try{await navigator.clipboard.writeText(el.set_system_prompt.value||'')}catch{}})
|
||||
el.pasteSystemPrompt.addEventListener('click',async()=>{try{el.set_system_prompt.value=await navigator.clipboard.readText()}catch{}})
|
||||
const getActiveHtmlParts=()=>!el.htmlEditor.classList.contains('hidden')?[el.htmlEditor,jars.html]:[el.extensionHtmlEditor,jars.extension]
|
||||
el.copyHTML.addEventListener('click',async()=>{try{await navigator.clipboard.writeText(getActiveHtmlParts()[0].textContent||'')}catch{}})
|
||||
el.pasteHTML.addEventListener('click',async()=>{try{const t=await navigator.clipboard.readText();const[editor,jar]=getActiveHtmlParts();if(jar&&jar.updateCode)jar.updateCode(t);else if(editor)editor.textContent=t}catch{}})
|
||||
el.copyHTML.addEventListener('click',async()=>{try{await navigator.clipboard.writeText(el.htmlEditor.textContent||'')}catch{}})
|
||||
el.pasteHTML.addEventListener('click',async()=>{try{const t=await navigator.clipboard.readText();const j=(await ensureJars()).html;j.updateCode?j.updateCode(t):el.htmlEditor.textContent=t}catch{}})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -32,7 +32,7 @@ export default defineConfig({
|
||||
{ tag:'script', attrs:{ src:'https://cdn.jsdelivr.net/npm/tiny-ripple@0.2.0' }, injectTo:'head' },
|
||||
{ tag:'style', children:':root{--safe-bottom:env(safe-area-inset-bottom)}::-webkit-scrollbar{height:8px;width:8px}::-webkit-scrollbar-thumb{background:#e5e7eb;border-radius:999px}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}', injectTo:'head' },
|
||||
{ tag:'style', children:'html,body{overscroll-behavior-y:contain}', injectTo:'head' },
|
||||
{ tag:'style', children:'#htmlEditor{outline:none;white-space:pre!important}', injectTo:'head' }
|
||||
{ tag:'style', children:'', injectTo:'head' }
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user