Rename local folder action to Link a folder with a link icon
Browse files- README.md +1 -1
- app/index.html +1 -1
- app/src/local-folder-ui.mjs +2 -2
- app/src/style.css +2 -0
- assets/{index-BVBC2sd0.js → index-CdBuZzGZ.js} +2 -2
- assets/{index-Uy7sEXBC.css → index-D2YMAIXb.css} +1 -1
- index.html +3 -3
- validation/LOCAL-FOLDER.md +1 -1
README.md
CHANGED
|
@@ -25,7 +25,7 @@ An independent duplicate of [victor/MiniCPM5-2B-WebGPU-Pi](https://huggingface.c
|
|
| 25 |
|
| 26 |
## Local folder experiment
|
| 27 |
|
| 28 |
-
The demo remains the default. In the [standalone app](https://mike0021-minicpm5-2b-webgpu-pi-http.static.hf.space/), choose **
|
| 29 |
|
| 30 |
This uses the File System Access API, available in supported Chromium browsers. The Hugging Face iframe offers a link to the standalone app because cross-origin frames cannot request folder permissions. Safari and Firefox retain the existing Import/Export workflow for copies of individual files; they cannot save directly to a selected folder.
|
| 31 |
|
|
|
|
| 25 |
|
| 26 |
## Local folder experiment
|
| 27 |
|
| 28 |
+
The demo remains the default. In the [standalone app](https://mike0021-minicpm5-2b-webgpu-pi-http.static.hf.space/), choose **Link a folder**. The selected folder replaces `/workspace` in the existing file panel and agent tools. Edits from Pi, the Shell, and the editor are staged. **Review & apply → Apply to folder** shows a diff and requests write permission before saving to disk. **Back to demo** restores the demo files and conversation; **Reconnect folder** resumes the local session, including staged edits saved separately in browser storage.
|
| 29 |
|
| 30 |
This uses the File System Access API, available in supported Chromium browsers. The Hugging Face iframe offers a link to the standalone app because cross-origin frames cannot request folder permissions. Safari and Firefox retain the existing Import/Export workflow for copies of individual files; they cannot save directly to a selected folder.
|
| 31 |
|
app/index.html
CHANGED
|
@@ -53,7 +53,7 @@
|
|
| 53 |
<div id="column-resizer" class="column-resizer" role="separator" tabindex="0" aria-label="Resize chat and workspace" aria-orientation="vertical" aria-controls="conversation-panel workspace-panel" aria-valuemin="0" aria-valuemax="100" aria-valuenow="55" title="Drag to resize · Arrow keys to adjust · Double-click or Enter to reset"></div>
|
| 54 |
<aside id="workspace-panel" class="workspace" aria-label="Workspace">
|
| 55 |
<div class="workspace-heading"><h2>Workspace</h2><div><button id="add-file" class="quiet">+ File</button><label class="button quiet" for="upload">Import</label><input id="upload" type="file" multiple hidden><button id="export" class="quiet">Export</button></div></div>
|
| 56 |
-
<div class="folder-controls"><button id="open-folder" type="button" class="quiet">
|
| 57 |
<div id="local-folder-bar" hidden>
|
| 58 |
<strong id="local-folder-name"></strong><span id="local-folder-hint" role="status"></span>
|
| 59 |
<div class="folder-actions"><button id="review-changes" type="button">Review & apply</button><button id="refresh-folder" type="button" class="quiet" title="Reload files from disk and start a fresh chat">Refresh</button><button id="disconnect-folder" type="button" class="quiet">Back to demo</button></div>
|
|
|
|
| 53 |
<div id="column-resizer" class="column-resizer" role="separator" tabindex="0" aria-label="Resize chat and workspace" aria-orientation="vertical" aria-controls="conversation-panel workspace-panel" aria-valuemin="0" aria-valuemax="100" aria-valuenow="55" title="Drag to resize · Arrow keys to adjust · Double-click or Enter to reset"></div>
|
| 54 |
<aside id="workspace-panel" class="workspace" aria-label="Workspace">
|
| 55 |
<div class="workspace-heading"><h2>Workspace</h2><div><button id="add-file" class="quiet">+ File</button><label class="button quiet" for="upload">Import</label><input id="upload" type="file" multiple hidden><button id="export" class="quiet">Export</button></div></div>
|
| 56 |
+
<div class="folder-controls"><button id="open-folder" type="button" class="quiet"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg><span>Link a folder</span></button><button id="reconnect-folder" type="button" class="quiet" hidden>Reconnect folder</button></div>
|
| 57 |
<div id="local-folder-bar" hidden>
|
| 58 |
<strong id="local-folder-name"></strong><span id="local-folder-hint" role="status"></span>
|
| 59 |
<div class="folder-actions"><button id="review-changes" type="button">Review & apply</button><button id="refresh-folder" type="button" class="quiet" title="Reload files from disk and start a fresh chat">Refresh</button><button id="disconnect-folder" type="button" class="quiet">Back to demo</button></div>
|
app/src/local-folder-ui.mjs
CHANGED
|
@@ -34,7 +34,7 @@ export function createLocalFolderUI({ rpc, notice, canSwitch, onSwitch }) {
|
|
| 34 |
function available() {
|
| 35 |
if (embedded) {
|
| 36 |
$('#open-tab').href = new URL('?local-folder', location.href).href; $('#open-tab').hidden = false;
|
| 37 |
-
notice('Open the workspace in a new tab, then choose
|
| 38 |
return false;
|
| 39 |
}
|
| 40 |
if (!supported) {
|
|
@@ -131,7 +131,7 @@ export function createLocalFolderUI({ rpc, notice, canSwitch, onSwitch }) {
|
|
| 131 |
window.addEventListener('beforeunload', event => {
|
| 132 |
if (current?.count) { event.preventDefault(); event.returnValue = ''; }
|
| 133 |
});
|
| 134 |
-
if (new URLSearchParams(location.search).has('local-folder')) notice('Choose
|
| 135 |
return {
|
| 136 |
setBusy(value) { busy = value; controls(); },
|
| 137 |
setState(value) { current = value; if (saved && value) saved.count = value.count; controls(); },
|
|
|
|
| 34 |
function available() {
|
| 35 |
if (embedded) {
|
| 36 |
$('#open-tab').href = new URL('?local-folder', location.href).href; $('#open-tab').hidden = false;
|
| 37 |
+
notice('Open the workspace in a new tab, then choose Link a folder. Browsers cannot grant folder access inside this embedded Space.');
|
| 38 |
return false;
|
| 39 |
}
|
| 40 |
if (!supported) {
|
|
|
|
| 131 |
window.addEventListener('beforeunload', event => {
|
| 132 |
if (current?.count) { event.preventDefault(); event.returnValue = ''; }
|
| 133 |
});
|
| 134 |
+
if (new URLSearchParams(location.search).has('local-folder')) notice('Choose Link a folder to select the project you want Pi to work on.');
|
| 135 |
return {
|
| 136 |
setBusy(value) { busy = value; controls(); },
|
| 137 |
setState(value) { current = value; if (saved && value) saved.count = value.count; controls(); },
|
app/src/style.css
CHANGED
|
@@ -181,6 +181,8 @@ footer { display: flex; align-items: center; justify-content: space-between; gap
|
|
| 181 |
.folder-controls:has(> button:not([hidden])) { min-height: 30px; }
|
| 182 |
.folder-controls:not(:has(> button:not([hidden]))) { display: none; }
|
| 183 |
#open-folder { color: var(--accent, #8abeb7); background: #8abeb710; }
|
|
|
|
|
|
|
| 184 |
#local-folder-bar { margin: 0 8px 8px; padding: 10px; border-radius: 10px; background: #8abeb710; font-size: 11px; }
|
| 185 |
#local-folder-name { display: block; color: var(--accent, #8abeb7); overflow-wrap: anywhere; }
|
| 186 |
#local-folder-hint { display: block; margin: 4px 0 8px; color: var(--muted); line-height: 1.5; }
|
|
|
|
| 181 |
.folder-controls:has(> button:not([hidden])) { min-height: 30px; }
|
| 182 |
.folder-controls:not(:has(> button:not([hidden]))) { display: none; }
|
| 183 |
#open-folder { color: var(--accent, #8abeb7); background: #8abeb710; }
|
| 184 |
+
#open-folder:not([hidden]) { display: inline-flex; align-items: center; gap: 6px; }
|
| 185 |
+
#open-folder svg { flex: none; }
|
| 186 |
#local-folder-bar { margin: 0 8px 8px; padding: 10px; border-radius: 10px; background: #8abeb710; font-size: 11px; }
|
| 187 |
#local-folder-name { display: block; color: var(--accent, #8abeb7); overflow-wrap: anywhere; }
|
| 188 |
#local-folder-hint { display: block; margin: 4px 0 8px; color: var(--muted); line-height: 1.5; }
|
assets/{index-BVBC2sd0.js → index-CdBuZzGZ.js}
RENAMED
|
@@ -169,8 +169,8 @@ Node CLI extensions, npm, Python and native binaries are unavailable.`);else if(
|
|
| 169 |
`}function N_(e,t,n,r,i,a,o){if(typeof o==`function`&&(o={callback:o}),o?.callback){let{callback:s}=o;j_(e,t,n,r,i,a,Object.assign(Object.assign({},o),{callback:e=>{s(e?M_(e,o.headerOptions):void 0)}}))}else{let s=j_(e,t,n,r,i,a,o);return s?M_(s,o?.headerOptions):void 0}}function P_(e){let t=e.endsWith(`
|
| 170 |
`),n=e.split(`
|
| 171 |
`).map(e=>e+`
|
| 172 |
-
`);return t?n.pop():n.push(n.pop().slice(0,-1)),n}var Q=e=>document.querySelector(e),F_=e=>{if(e===null)return``;let t=new TextDecoder(`utf-8`,{fatal:!0}).decode(Uint8Array.from(atob(e),e=>e.charCodeAt(0)));if(t.includes(`\0`))throw Error(`Binary file`);return t};function I_({rpc:e,notice:t,canSwitch:n,onSwitch:r}){let i,a,o,s=!1,c=!1,l=[],u=Q(`#local-review`),d=window.self!==window.top,f=typeof window.showDirectoryPicker==`function`;function p(){Q(`#open-folder`).hidden=!!o,Q(`#reconnect-folder`).hidden=!!o||!a,Q(`#local-folder-bar`).hidden=!o;for(let e of[`open-folder`,`reconnect-folder`,`review-changes`,`refresh-folder`,`disconnect-folder`])Q(`#`+e).disabled=s||c;Q(`#review-changes`).disabled||=!o?.count,Q(`#refresh-folder`).disabled||=!!o?.count,Q(`#review-apply`).disabled=s||!l.length,Q(`#review-discard`).disabled=s||!l.length,Q(`#review-close`).disabled=s,o&&(Q(`#local-folder-name`).textContent=o.name,Q(`#local-folder-hint`).textContent=o.count?`${o.count} staged change${o.count===1?``:`s`} · original files unchanged until Apply`:`Local folder · edits are staged until you apply them`,Q(`#review-changes`).textContent=o.count?`Review & apply (${o.count})`:`Review & apply`),Q(`#export`).textContent=o?`Export changes`:`Export`,Q(`#save`).textContent=o?`Stage edit`:`Save`}function m(){return d?(Q(`#open-tab`).href=new URL(`?local-folder`,location.href).href,Q(`#open-tab`).hidden=!1,t(`Open the workspace in a new tab, then choose
|
| 173 |
`)){let t=document.createElement(`span`);t.textContent=e+`
|
| 174 |
-
`,e.startsWith(`+`)&&(t.className=`diff-add`),e.startsWith(`-`)&&(t.className=`diff-remove`),i.append(t)}}}catch{i.textContent=`Binary file · ${t.before===null?0:atob(t.before).length} → ${t.after===null?0:atob(t.after).length} bytes`}n.append(i)}Q(`#review-files`).append(n)}p()}return Q(`#review-changes`).onclick=async()=>{try{n(),g(await e(`local_changes`)),u.showModal()}catch(e){t(e.message)}},Q(`#review-close`).onclick=()=>u.close(),u.addEventListener(`cancel`,e=>{s&&e.preventDefault()}),Q(`#review-apply`).onclick=async()=>{try{if(await i.requestPermission({mode:`readwrite`})!==`granted`)throw Error(`Write access was not granted. Changes are still staged.`);let n=await e(`local_apply`);u.close(),t(`Applied ${n.applied} change${n.applied===1?``:`s`} to ${i.name}.`)}catch(t){try{g(await e(`local_changes`))}catch{}Q(`#review-error`).textContent=t.message}},Q(`#review-discard`).onclick=async()=>{if(window.confirm(`Discard all staged changes and reload files from disk? Your local files will not be changed.`))try{r(await e(`local_discard`)),u.close(),t(`Staged edits discarded. Folder refreshed and chat reset.`)}catch(e){Q(`#review-error`).textContent=e.message}},window.addEventListener(`beforeunload`,e=>{o?.count&&(e.preventDefault(),e.returnValue=``)}),new URLSearchParams(location.search).has(`local-folder`)&&t(`Choose
|
| 175 |
This file is binary or isn’t UTF-8 text.`:n.code===`FILE_TOO_LARGE`?`File too large to preview (1 MiB limit).`:`Unable to preview this file.
|
| 176 |
`+n.message;$_.setFile(e,``,r)}finally{t===J_&&sv()}}function uv(e){if(q_=void 0,U_){av(`Save the open file before selecting another file.`);return}H_=e,$(`#filename`).textContent=rv.folderName?e.replace(/^\/workspace(?=\/|$)/,()=>`/`+rv.folderName):e,$(`#filetype`).replaceChildren(t_(e)),cv(),sv()}function dv(){if(U_){q_=void 0;return}if(!q_||!Object.hasOwn(W_,q_))return;let e=q_,t=e!==H_;uv(e),t&&($(`#editor`).scrollTop=0,$(`#editor`).scrollLeft=0);let n=[...$(`#files`).children].find(t=>t.title===e);if(n){let e=n.getBoundingClientRect(),t=$(`#files`).getBoundingClientRect();e.top<t.top?$(`#files`).scrollTop+=e.top-t.top:e.bottom>t.bottom&&($(`#files`).scrollTop+=e.bottom-t.bottom)}}function fv(){ev.setMessages(G_)}function pv(e){Z_.contextUsage=e,ev.setState({contextUsage:e})}L_.onmessage=({data:e})=>{if(Q_.update(e),e.type===`inference_activity`&&(Z_.runtimeSamples.push(e),Z_.runtimeSamples.length>160&&Z_.runtimeSamples.shift()),e.type===`reply`){let t=R_.get(e.id);R_.delete(e.id),e.error?t?.reject(Object.assign(Error(e.error),{name:e.errorName||`Error`,code:e.errorCode})):t?.resolve(e.value)}else if(e.type===`initialized`)rv.restore(e.savedLocal),rv.setState(e.localFolder),W_=e.files,G_=e.messages,cv(),fv(),pv(Ng(G_)),W_[`/workspace/README.md`]&&uv(`/workspace/README.md`),document.activeElement===document.body&&ev.focus(),K_();else if(e.type===`busy`)e.action===`load`&&($(`#load`).textContent=`Loading…`),B_=!0,$(`#activity`).textContent=e.action===`prompt`?`Pi is working…`:e.action===`load`?e.cachedOnly?`Loading local model…`:`Loading model…`:`Working…`,sv();else if(e.type===`idle`)B_=!1,$(`#progress`).hidden=!0,$(`#activity`).textContent=rv.active?`Local folder · review & apply to save changes to disk`:V_?`Ready · running on your device`:`Files and chat are saved on this device.`,sv();else if(e.type===`workspace`)W_=e.files,rv.setState(e.localFolder),cv(),dv();else if(e.type===`device`)Z_.device=e.device;else if(e.type===`load_progress`)$(`#progress`).hidden=!1,e.phase===`download`?($(`#progress`).hidden=!1,$(`#progress`).value=e.loaded/e.total*100,$(`#load-status`).textContent=e.loaded===e.total?`Download verified. Preparing model…`:`Downloading model weights from Hugging Face…`,$(`#load-detail`).textContent=`${(e.loaded/1e9).toFixed(2)} / ${(e.total/1e9).toFixed(2)} GB · ${Math.round(e.loaded/e.total*100)}%${e.cached?` · ${(e.cached/1e9).toFixed(2)} GB cached`:``}`,$(`#load`).textContent=`Loading ${Math.round(e.loaded/e.total*100)}%`):($(`#load-status`).textContent=e.phase===`compile`?`Preparing WebGPU session…`:`Warming up GPU shaders…`,$(`#load-detail`).textContent=``,$(`#progress`).removeAttribute(`value`),$(`#load`).textContent=e.phase===`compile`?`Preparing…`:`Almost ready…`),$(`#load`).title=$(`#load-status`).textContent+` `+$(`#load-detail`).textContent;else if(e.type===`loaded`)V_=!0,Z_.device=e.device,$(`#progress`).hidden=!0,$(`#load`).textContent=`Loaded`,$(`#load-status`).textContent=`Ready. Model inference and tools run entirely in this browser.`,$(`#load-detail`).textContent=e.cachedBytes?`Verified model restored from browser storage.`:`SHA-256 verified · model cached for next time.`,sv();else if(e.type===`agent_event`){let t=e.event;if(Z_.events.push(t.type),Z_.events.length>500&&Z_.events.shift(),t.message){let e=G_.findIndex(e=>e.timestamp===t.message.timestamp&&e.role===t.message.role&&e.toolCallId===t.message.toolCallId);e<0?G_.push(t.message):G_[e]=t.message,fv()}t.type===`tool_execution_start`&&($(`#activity`).textContent=`Running ${t.toolName}…`),t.type===`tool_execution_end`&&t.toolName===`read`&&!t.isError&&typeof t.result?.details?.path==`string`&&(q_=t.result.details.path,dv()),t.type===`turn_start`&&($(`#activity`).textContent=`Pi is thinking…`),ev.setState({activity:$(`#activity`).textContent})}else e.type===`context_usage`?pv({inputTokens:e.inputTokens,outputTokens:e.outputTokens}):e.type===`generation`?(Z_.generations.push(e),Z_.generations.length>100&&Z_.generations.shift()):e.type===`context_trim`?av(`Older turns were left out of the model context. Your full chat remains saved.`):e.type===`notice`?av(e.text):e.type===`persistence_error`?av(ov(e.error)):e.type===`fatal`&&(V_=!1,av(e.error),sv())},L_.onerror=e=>{Q_.update({type:`fatal`});let t=Error(e.message||`The worker stopped. Reload to restore your saved workspace.`);av(t.message);for(let e of R_.values())e.reject(t);R_.clear(),B_=!1,V_=!1,$(`#progress`).hidden=!0,sv()};var mv=e=>async t=>{t?.preventDefault();try{await X_,await e(t)}catch(e){av(e.message)}};async function hv({cachedOnly:e=!1}={}){if(B_)throw Error(`Wait for the current operation or stop it first.`);av(``);let t=new URLSearchParams(location.search);B_=!0,$(`#load`).textContent=`Loading…`,$(`#activity`).textContent=e?`Loading local model…`:`Loading model…`,$(`#load-status`).textContent=e?`Loading local model…`:`Checking your browser and saved model…`,$(`#load-detail`).textContent=``,$(`#progress`).hidden=!1,$(`#progress`).removeAttribute(`value`),Q_.update({type:`busy`,action:`load`,cachedOnly:e}),sv();try{return await iv(`load`,{runtimeURL:new URL(`./runtime/`,location.href).href,local:t.get(`source`)===`local`,origin:location.origin,limit128:t.has(`limit128`),cachedOnly:e})}catch(e){throw e.message=ov(e.message),$(`#load-status`).textContent=e.message,$(`#progress`).hidden=!0,e}}async function gv(e){if(e.trim()){if(U_)throw Error(`Save your file edits before asking Pi to work on them.`);try{if(!V_){let t;if(await iv(`cache_status`))try{ev.setQueuedPrompt(e),await hv({cachedOnly:!0})}catch(e){if(e.name===`AbortError`)throw e;e.code!==`MODEL_CACHE_MISS`&&(t=e.message)}for(;!V_;){if(ev.setQueuedPrompt(``),!await tv.request(e,{errorMessage:t}))throw new DOMException(`Message kept for later.`,`AbortError`);ev.setQueuedPrompt(e);try{await hv()}catch(e){if(e.name===`AbortError`)throw e;t=e.message}}}ev.setQueuedPrompt(``),av(``);let t=await iv(`prompt`,{text:e});return G_=t.messages,fv(),t}finally{ev.setQueuedPrompt(``)}}}$(`#load`).onclick=mv(hv),$(`#send`).onclick=()=>{ev.submit(),ev.focus()},$(`#newline`).onclick=()=>ev.newline(),$(`#stop`).onclick=mv(()=>iv(`stop`)),$(`.terminal-panel`).addEventListener(`click`,e=>{!e.defaultPrevented&&e.button===0&&e.target instanceof Element&&(e.target.closest(`#pi-terminal, button, a, input, textarea, select, label, summary, [role="button"], [contenteditable]`)||window.getSelection()?.isCollapsed!==!1&&ev.focus())});async function _v(){q_=void 0,G_=(await iv(`new_chat`)).messages,pv(Ng(G_)),ev.setMessages(G_,{reset:!0}),av(``),ev.focus()}$(`#new-chat`).onclick=mv(_v),$(`#editor`).oninput=()=>{U_=!0,sv()},$(`#save`).onclick=mv(async()=>{await iv(`write`,{path:H_,content:$(`#editor`).value}),U_=!1,cv(),sv(),av(``)}),$(`#add-file`).onclick=mv(async()=>{if(U_)throw Error(`Save the open file first.`);let e=window.prompt(`File path, relative to /workspace:`);if(!e?.trim())return;let t=e.startsWith(`/`)?e:`/workspace/`+e;if(Object.hasOwn(W_,t))throw Error(`That file already exists.`);await iv(`write`,{path:t,content:``}),uv(t)}),$(`#upload`).onchange=mv(async()=>{if(U_)throw Error(`Save the open file first.`);for(let e of $(`#upload`).files){if(e.size>1024**2)throw Error(`Import text files of 1 MiB or less.`);let t=await e.text();if(t.includes(`\0`))throw Error(`Import supports text files only.`);let n=`/workspace/`+e.name;if(Object.hasOwn(W_,n))throw Error(e.name+` already exists. Rename it before importing.`);await iv(`write`,{path:n,content:t}),uv(n)}$(`#upload`).value=``}),$(`#export`).onclick=mv(async()=>{let e=rv.active?{version:1,patches:await iv(`local_changes`)}:await iv(`snapshot`),t=URL.createObjectURL(new Blob([JSON.stringify(e,null,2)],{type:`application/json`})),n=document.createElement(`a`);n.href=t,n.download=rv.active?`pi-staged-changes.json`:`pi-workspace.json`,n.click(),setTimeout(()=>URL.revokeObjectURL(t),1e3)}),window.browserPi={ready:X_,load:hv,prompt:gv,rpc:iv,diagnostics:Z_,terminal:ev,runtimeMeter:Q_,get loaded(){return V_},get busy(){return B_}},sv();
|
|
|
|
| 169 |
`}function N_(e,t,n,r,i,a,o){if(typeof o==`function`&&(o={callback:o}),o?.callback){let{callback:s}=o;j_(e,t,n,r,i,a,Object.assign(Object.assign({},o),{callback:e=>{s(e?M_(e,o.headerOptions):void 0)}}))}else{let s=j_(e,t,n,r,i,a,o);return s?M_(s,o?.headerOptions):void 0}}function P_(e){let t=e.endsWith(`
|
| 170 |
`),n=e.split(`
|
| 171 |
`).map(e=>e+`
|
| 172 |
+
`);return t?n.pop():n.push(n.pop().slice(0,-1)),n}var Q=e=>document.querySelector(e),F_=e=>{if(e===null)return``;let t=new TextDecoder(`utf-8`,{fatal:!0}).decode(Uint8Array.from(atob(e),e=>e.charCodeAt(0)));if(t.includes(`\0`))throw Error(`Binary file`);return t};function I_({rpc:e,notice:t,canSwitch:n,onSwitch:r}){let i,a,o,s=!1,c=!1,l=[],u=Q(`#local-review`),d=window.self!==window.top,f=typeof window.showDirectoryPicker==`function`;function p(){Q(`#open-folder`).hidden=!!o,Q(`#reconnect-folder`).hidden=!!o||!a,Q(`#local-folder-bar`).hidden=!o;for(let e of[`open-folder`,`reconnect-folder`,`review-changes`,`refresh-folder`,`disconnect-folder`])Q(`#`+e).disabled=s||c;Q(`#review-changes`).disabled||=!o?.count,Q(`#refresh-folder`).disabled||=!!o?.count,Q(`#review-apply`).disabled=s||!l.length,Q(`#review-discard`).disabled=s||!l.length,Q(`#review-close`).disabled=s,o&&(Q(`#local-folder-name`).textContent=o.name,Q(`#local-folder-hint`).textContent=o.count?`${o.count} staged change${o.count===1?``:`s`} · original files unchanged until Apply`:`Local folder · edits are staged until you apply them`,Q(`#review-changes`).textContent=o.count?`Review & apply (${o.count})`:`Review & apply`),Q(`#export`).textContent=o?`Export changes`:`Export`,Q(`#save`).textContent=o?`Stage edit`:`Save`}function m(){return d?(Q(`#open-tab`).href=new URL(`?local-folder`,location.href).href,Q(`#open-tab`).hidden=!1,t(`Open the workspace in a new tab, then choose Link a folder. Browsers cannot grant folder access inside this embedded Space.`),!1):f?!0:(t(`Direct local-folder access needs a supported browser, such as Chrome or Edge. In this browser, use Import and Export to work with copies of your files.`),!1)}async function h(o){if(!(!m()||s||c))try{n(),c=!0,p();let s;if(o){if(s=a.handle,await s.requestPermission({mode:`read`})!==`granted`)throw Error(`Folder access was not granted.`)}else{if(a?.count&&!window.confirm(`Opening another folder replaces the saved staged edits for the previous folder. Reconnect to review them first, or continue?`))return;s=await window.showDirectoryPicker({id:`pi-workspace`,mode:`read`})}let l=await e(`local_open`,{handle:s,restore:o});i=s,a={handle:s,count:l.localFolder.count},r(l),t(`Opened ${s.name}. Review & apply writes staged changes to disk. Files load on demand; Refresh picks up external edits.`)}catch(e){e.name!==`AbortError`&&t(e.message)}finally{c=!1,p()}}Q(`#open-folder`).onclick=()=>h(!1),Q(`#reconnect-folder`).onclick=()=>h(!0),Q(`#disconnect-folder`).onclick=async()=>{try{n(),a={handle:i,count:o.count},r(await e(`local_close`)),t(`Demo workspace restored. Reconnect to continue with your local folder and staged edits.`)}catch(e){t(e.message)}},Q(`#refresh-folder`).onclick=async()=>{try{n(),r(await e(`local_refresh`)),t(`Folder refreshed from disk. Started a new chat with the current files.`)}catch(e){t(e.message)}};function g(e){l=e,Q(`#review-files`).replaceChildren(),Q(`#review-error`).textContent=``,Q(`#review-description`).textContent=`Review changes to ${o.name}. Applying writes them to your local folder.`;for(let t of e){let n=document.createElement(`details`),r=document.createElement(`summary`),i=document.createElement(`pre`);if(r.textContent=`${t.kind===`directory`?`New folder`:t.after===null?`Delete`:t.before===null?`Create`:`Edit`} · ${t.path.slice(1)}`,n.append(r),n.open=e.length<5,t.kind!==`directory`){try{let e=F_(t.before),n=F_(t.after);if(e.length+n.length>16e4)i.textContent=`Large text change. Inspect the file in the editor before applying.`;else{let r=N_(t.path,t.path,e,n,`on disk when read`,`staged`,{context:3});for(let e of r.split(`
|
| 173 |
`)){let t=document.createElement(`span`);t.textContent=e+`
|
| 174 |
+
`,e.startsWith(`+`)&&(t.className=`diff-add`),e.startsWith(`-`)&&(t.className=`diff-remove`),i.append(t)}}}catch{i.textContent=`Binary file · ${t.before===null?0:atob(t.before).length} → ${t.after===null?0:atob(t.after).length} bytes`}n.append(i)}Q(`#review-files`).append(n)}p()}return Q(`#review-changes`).onclick=async()=>{try{n(),g(await e(`local_changes`)),u.showModal()}catch(e){t(e.message)}},Q(`#review-close`).onclick=()=>u.close(),u.addEventListener(`cancel`,e=>{s&&e.preventDefault()}),Q(`#review-apply`).onclick=async()=>{try{if(await i.requestPermission({mode:`readwrite`})!==`granted`)throw Error(`Write access was not granted. Changes are still staged.`);let n=await e(`local_apply`);u.close(),t(`Applied ${n.applied} change${n.applied===1?``:`s`} to ${i.name}.`)}catch(t){try{g(await e(`local_changes`))}catch{}Q(`#review-error`).textContent=t.message}},Q(`#review-discard`).onclick=async()=>{if(window.confirm(`Discard all staged changes and reload files from disk? Your local files will not be changed.`))try{r(await e(`local_discard`)),u.close(),t(`Staged edits discarded. Folder refreshed and chat reset.`)}catch(e){Q(`#review-error`).textContent=e.message}},window.addEventListener(`beforeunload`,e=>{o?.count&&(e.preventDefault(),e.returnValue=``)}),new URLSearchParams(location.search).has(`local-folder`)&&t(`Choose Link a folder to select the project you want Pi to work on.`),{setBusy(e){s=e,p()},setState(e){o=e,a&&e&&(a.count=e.count),p()},restore(e){a=e,p()},get folderName(){return o?.name},get active(){return!!o}}}var $=e=>document.querySelector(e);c_($(`main`),$(`#column-resizer`));var L_=new Worker(new URL(new URL(`agent.worker-yyKS-x2c.js`,import.meta.url).href,``+import.meta.url),{type:`module`}),R_=new Map,z_=1,B_=!1,V_=!1,H_,U_=!1,W_={},G_=[],K_,q_,J_=0,Y_=!0,X_=new Promise(e=>{K_=e}),Z_={events:[],generations:[],runtimeSamples:[],device:null,contextUsage:Ng([])},Q_=Zg($(`#runtime-meter`)),$_=a_($(`.editor-input`)),ev=Ug($(`#pi-terminal`),{onInput:e=>$(`#send`).classList.toggle(`has-input`,!!e.trim()),load:()=>X_.then(hv),prompt:e=>X_.then(()=>gv(e)),newChat:()=>X_.then(_v),stop:()=>iv(`stop`),shell:e=>{if(U_)throw Error(`Save your file edits before running commands.`);return iv(`shell`,{command:e})}}),tv=Wg($(`#model-dialog`),{onClose:()=>ev.focus()}),nv=Xg($(`.workspace > .terminal`),{run:async e=>{if(await X_,U_)throw Error(`Save your file edits before running commands.`);if(B_)throw Error(`Wait for Pi to finish or stop the current task first.`);return iv(`shell`,{command:e})}}),rv=I_({rpc:iv,notice:av,canSwitch(){if(B_)throw Error(`Wait for Pi to finish or stop the current task first.`);if(U_)throw Error(`Save or stage the open file first.`)},onSwitch(e){q_=void 0,H_=void 0,U_=!1,J_++,Y_=!1,W_=e.files,G_=e.messages,rv.setState(e.localFolder),$(`#filename`).textContent=`Select a file`,$(`#filetype`).replaceChildren(),$_.setFile(``,``),ev.setMessages(G_,{reset:!0}),pv(Ng(G_)),$(`#shell-clear`).click(),cv();let t=Object.hasOwn(W_,`/workspace/README.md`)?`/workspace/README.md`:Object.keys(W_).sort()[0];t&&uv(t),sv()}});function iv(e,t){return new Promise((n,r)=>{let i=z_++;R_.set(i,{resolve:n,reject:r}),L_.postMessage({id:i,action:e,args:t})})}function av(e){$(`#notice`).textContent=e,$(`#notice`).hidden=!e}function ov(e){return window.self===window.top||!/denied|storage directory access/i.test(e)?e:($(`#open-tab`).href=location.href,$(`#open-tab`).hidden=!1,`Your browser blocked storage in this embedded app. Open the workspace in a new tab to load the model and save files.`)}function sv(){$(`#load`).disabled=B_||V_,$(`#load`).classList.toggle(`is-loaded`,V_),V_?$(`#load`).textContent=`Loaded`:B_||($(`#load`).textContent=`Load model`),$(`#load`).title=$(`#load-status`).textContent+` `+$(`#load-detail`).textContent,$(`#send`).disabled=B_,$(`#newline`).disabled=B_,ev.setState({busy:B_,loaded:V_,activity:$(`#activity`).textContent}),$(`#stop`).hidden=!B_;for(let e of[`#new-chat`,`#add-file`,`#upload`])$(e).disabled=B_;nv.setBusy(B_),rv.setBusy(B_),$(`#save`).disabled=B_||!H_||!U_,$(`#editor`).disabled=B_||!H_||!Y_}function cv(){ev.setFiles(W_),$(`#files`).replaceChildren();for(let e of Object.keys(W_).sort()){let t=document.createElement(`button`),n=document.createElement(`span`);n.className=`file-name`,n.textContent=e.replace(/^\/workspace\//,``),t.append(t_(e),n),t.title=e,t.classList.toggle(`selected`,e===H_),t.onclick=()=>uv(e),$(`#files`).append(t)}H_&&!Object.hasOwn(W_,H_)&&!U_&&(H_=void 0,J_++,Y_=!1,$(`#filename`).textContent=`Select a file`,$(`#filetype`).replaceChildren(),$_.setFile(``,``),sv()),H_&&!U_&&(W_[H_]===null?lv(H_):(Y_=!0,$_.setFile(H_,W_[H_]??``)))}async function lv(e){let t=++J_;Y_=!1,$_.setFile(e,``,`Loading file…`),sv();try{let n=await iv(`preview`,{path:e});if(t!==J_||e!==H_||U_)return;$_.setFile(e,n),Y_=!0}catch(n){if(t!==J_||e!==H_)return;let r=n.code===`BINARY_FILE`?`No text preview available.
|
| 175 |
This file is binary or isn’t UTF-8 text.`:n.code===`FILE_TOO_LARGE`?`File too large to preview (1 MiB limit).`:`Unable to preview this file.
|
| 176 |
`+n.message;$_.setFile(e,``,r)}finally{t===J_&&sv()}}function uv(e){if(q_=void 0,U_){av(`Save the open file before selecting another file.`);return}H_=e,$(`#filename`).textContent=rv.folderName?e.replace(/^\/workspace(?=\/|$)/,()=>`/`+rv.folderName):e,$(`#filetype`).replaceChildren(t_(e)),cv(),sv()}function dv(){if(U_){q_=void 0;return}if(!q_||!Object.hasOwn(W_,q_))return;let e=q_,t=e!==H_;uv(e),t&&($(`#editor`).scrollTop=0,$(`#editor`).scrollLeft=0);let n=[...$(`#files`).children].find(t=>t.title===e);if(n){let e=n.getBoundingClientRect(),t=$(`#files`).getBoundingClientRect();e.top<t.top?$(`#files`).scrollTop+=e.top-t.top:e.bottom>t.bottom&&($(`#files`).scrollTop+=e.bottom-t.bottom)}}function fv(){ev.setMessages(G_)}function pv(e){Z_.contextUsage=e,ev.setState({contextUsage:e})}L_.onmessage=({data:e})=>{if(Q_.update(e),e.type===`inference_activity`&&(Z_.runtimeSamples.push(e),Z_.runtimeSamples.length>160&&Z_.runtimeSamples.shift()),e.type===`reply`){let t=R_.get(e.id);R_.delete(e.id),e.error?t?.reject(Object.assign(Error(e.error),{name:e.errorName||`Error`,code:e.errorCode})):t?.resolve(e.value)}else if(e.type===`initialized`)rv.restore(e.savedLocal),rv.setState(e.localFolder),W_=e.files,G_=e.messages,cv(),fv(),pv(Ng(G_)),W_[`/workspace/README.md`]&&uv(`/workspace/README.md`),document.activeElement===document.body&&ev.focus(),K_();else if(e.type===`busy`)e.action===`load`&&($(`#load`).textContent=`Loading…`),B_=!0,$(`#activity`).textContent=e.action===`prompt`?`Pi is working…`:e.action===`load`?e.cachedOnly?`Loading local model…`:`Loading model…`:`Working…`,sv();else if(e.type===`idle`)B_=!1,$(`#progress`).hidden=!0,$(`#activity`).textContent=rv.active?`Local folder · review & apply to save changes to disk`:V_?`Ready · running on your device`:`Files and chat are saved on this device.`,sv();else if(e.type===`workspace`)W_=e.files,rv.setState(e.localFolder),cv(),dv();else if(e.type===`device`)Z_.device=e.device;else if(e.type===`load_progress`)$(`#progress`).hidden=!1,e.phase===`download`?($(`#progress`).hidden=!1,$(`#progress`).value=e.loaded/e.total*100,$(`#load-status`).textContent=e.loaded===e.total?`Download verified. Preparing model…`:`Downloading model weights from Hugging Face…`,$(`#load-detail`).textContent=`${(e.loaded/1e9).toFixed(2)} / ${(e.total/1e9).toFixed(2)} GB · ${Math.round(e.loaded/e.total*100)}%${e.cached?` · ${(e.cached/1e9).toFixed(2)} GB cached`:``}`,$(`#load`).textContent=`Loading ${Math.round(e.loaded/e.total*100)}%`):($(`#load-status`).textContent=e.phase===`compile`?`Preparing WebGPU session…`:`Warming up GPU shaders…`,$(`#load-detail`).textContent=``,$(`#progress`).removeAttribute(`value`),$(`#load`).textContent=e.phase===`compile`?`Preparing…`:`Almost ready…`),$(`#load`).title=$(`#load-status`).textContent+` `+$(`#load-detail`).textContent;else if(e.type===`loaded`)V_=!0,Z_.device=e.device,$(`#progress`).hidden=!0,$(`#load`).textContent=`Loaded`,$(`#load-status`).textContent=`Ready. Model inference and tools run entirely in this browser.`,$(`#load-detail`).textContent=e.cachedBytes?`Verified model restored from browser storage.`:`SHA-256 verified · model cached for next time.`,sv();else if(e.type===`agent_event`){let t=e.event;if(Z_.events.push(t.type),Z_.events.length>500&&Z_.events.shift(),t.message){let e=G_.findIndex(e=>e.timestamp===t.message.timestamp&&e.role===t.message.role&&e.toolCallId===t.message.toolCallId);e<0?G_.push(t.message):G_[e]=t.message,fv()}t.type===`tool_execution_start`&&($(`#activity`).textContent=`Running ${t.toolName}…`),t.type===`tool_execution_end`&&t.toolName===`read`&&!t.isError&&typeof t.result?.details?.path==`string`&&(q_=t.result.details.path,dv()),t.type===`turn_start`&&($(`#activity`).textContent=`Pi is thinking…`),ev.setState({activity:$(`#activity`).textContent})}else e.type===`context_usage`?pv({inputTokens:e.inputTokens,outputTokens:e.outputTokens}):e.type===`generation`?(Z_.generations.push(e),Z_.generations.length>100&&Z_.generations.shift()):e.type===`context_trim`?av(`Older turns were left out of the model context. Your full chat remains saved.`):e.type===`notice`?av(e.text):e.type===`persistence_error`?av(ov(e.error)):e.type===`fatal`&&(V_=!1,av(e.error),sv())},L_.onerror=e=>{Q_.update({type:`fatal`});let t=Error(e.message||`The worker stopped. Reload to restore your saved workspace.`);av(t.message);for(let e of R_.values())e.reject(t);R_.clear(),B_=!1,V_=!1,$(`#progress`).hidden=!0,sv()};var mv=e=>async t=>{t?.preventDefault();try{await X_,await e(t)}catch(e){av(e.message)}};async function hv({cachedOnly:e=!1}={}){if(B_)throw Error(`Wait for the current operation or stop it first.`);av(``);let t=new URLSearchParams(location.search);B_=!0,$(`#load`).textContent=`Loading…`,$(`#activity`).textContent=e?`Loading local model…`:`Loading model…`,$(`#load-status`).textContent=e?`Loading local model…`:`Checking your browser and saved model…`,$(`#load-detail`).textContent=``,$(`#progress`).hidden=!1,$(`#progress`).removeAttribute(`value`),Q_.update({type:`busy`,action:`load`,cachedOnly:e}),sv();try{return await iv(`load`,{runtimeURL:new URL(`./runtime/`,location.href).href,local:t.get(`source`)===`local`,origin:location.origin,limit128:t.has(`limit128`),cachedOnly:e})}catch(e){throw e.message=ov(e.message),$(`#load-status`).textContent=e.message,$(`#progress`).hidden=!0,e}}async function gv(e){if(e.trim()){if(U_)throw Error(`Save your file edits before asking Pi to work on them.`);try{if(!V_){let t;if(await iv(`cache_status`))try{ev.setQueuedPrompt(e),await hv({cachedOnly:!0})}catch(e){if(e.name===`AbortError`)throw e;e.code!==`MODEL_CACHE_MISS`&&(t=e.message)}for(;!V_;){if(ev.setQueuedPrompt(``),!await tv.request(e,{errorMessage:t}))throw new DOMException(`Message kept for later.`,`AbortError`);ev.setQueuedPrompt(e);try{await hv()}catch(e){if(e.name===`AbortError`)throw e;t=e.message}}}ev.setQueuedPrompt(``),av(``);let t=await iv(`prompt`,{text:e});return G_=t.messages,fv(),t}finally{ev.setQueuedPrompt(``)}}}$(`#load`).onclick=mv(hv),$(`#send`).onclick=()=>{ev.submit(),ev.focus()},$(`#newline`).onclick=()=>ev.newline(),$(`#stop`).onclick=mv(()=>iv(`stop`)),$(`.terminal-panel`).addEventListener(`click`,e=>{!e.defaultPrevented&&e.button===0&&e.target instanceof Element&&(e.target.closest(`#pi-terminal, button, a, input, textarea, select, label, summary, [role="button"], [contenteditable]`)||window.getSelection()?.isCollapsed!==!1&&ev.focus())});async function _v(){q_=void 0,G_=(await iv(`new_chat`)).messages,pv(Ng(G_)),ev.setMessages(G_,{reset:!0}),av(``),ev.focus()}$(`#new-chat`).onclick=mv(_v),$(`#editor`).oninput=()=>{U_=!0,sv()},$(`#save`).onclick=mv(async()=>{await iv(`write`,{path:H_,content:$(`#editor`).value}),U_=!1,cv(),sv(),av(``)}),$(`#add-file`).onclick=mv(async()=>{if(U_)throw Error(`Save the open file first.`);let e=window.prompt(`File path, relative to /workspace:`);if(!e?.trim())return;let t=e.startsWith(`/`)?e:`/workspace/`+e;if(Object.hasOwn(W_,t))throw Error(`That file already exists.`);await iv(`write`,{path:t,content:``}),uv(t)}),$(`#upload`).onchange=mv(async()=>{if(U_)throw Error(`Save the open file first.`);for(let e of $(`#upload`).files){if(e.size>1024**2)throw Error(`Import text files of 1 MiB or less.`);let t=await e.text();if(t.includes(`\0`))throw Error(`Import supports text files only.`);let n=`/workspace/`+e.name;if(Object.hasOwn(W_,n))throw Error(e.name+` already exists. Rename it before importing.`);await iv(`write`,{path:n,content:t}),uv(n)}$(`#upload`).value=``}),$(`#export`).onclick=mv(async()=>{let e=rv.active?{version:1,patches:await iv(`local_changes`)}:await iv(`snapshot`),t=URL.createObjectURL(new Blob([JSON.stringify(e,null,2)],{type:`application/json`})),n=document.createElement(`a`);n.href=t,n.download=rv.active?`pi-staged-changes.json`:`pi-workspace.json`,n.click(),setTimeout(()=>URL.revokeObjectURL(t),1e3)}),window.browserPi={ready:X_,load:hv,prompt:gv,rpc:iv,diagnostics:Z_,terminal:ev,runtimeMeter:Q_,get loaded(){return V_},get busy(){return B_}},sv();
|
assets/{index-Uy7sEXBC.css → index-D2YMAIXb.css}
RENAMED
|
@@ -1 +1 @@
|
|
| 1 |
-
:root{font-synthesis:none;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;color:var(--text);background:var(--background);--background:#18181e;--surface:#1e1e24;--panel:#22222b;--control:#282832;--hover:#343541;--selected:#3a3a4a;--line:#393942;--line-strong:#50505c;--text:#d4d4d4;--muted:#b0b0bd;--accent:#8abeb7;--surface-inset:8px;--radius-small:8px;--radius:calc(var(--radius-small) + var(--surface-inset));--radius-large:calc(var(--radius) + var(--surface-inset));--content-width:1800px;--content-gutter:14px;--header-inset:12px;--header-control-height:32px;--header-height:calc(var(--header-control-height) + 2 * var(--surface-inset));scrollbar-color:var(--line-strong) var(--background);font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:13px}*{box-sizing:border-box}body{margin:0}button,input,textarea{font:inherit;color:inherit}::selection{background:var(--selected);color:var(--text)}input::placeholder,textarea::placeholder{color:var(--muted);opacity:1}button,.button{cursor:pointer;border-radius:var(--radius-small);background:var(--control);min-height:28px;color:inherit;white-space:nowrap;border:1px solid #0000;padding:5px 9px;font-size:12px;line-height:1.4}button:hover,.button:hover{background:var(--hover)}button:disabled{opacity:.45;cursor:default}.primary{background:var(--hover);color:var(--text)}.primary:hover{background:var(--selected)}#send.has-input:not(:disabled){color:#18181e;background:#fff}#send.has-input:not(:disabled):hover{background:#e8e8ed}.quiet{background:0 0;border-color:#0000;font-size:11px}textarea,input{outline:none}textarea:focus,input:focus{box-shadow:inset 0 0 0 1px var(--accent)}button:focus-visible,.button:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}[hidden]{display:none!important}header{width:calc(100% - 2 * var(--content-gutter));max-width:calc(var(--content-width) - 2 * var(--content-gutter));height:var(--header-height);margin:var(--header-inset) auto 0;padding:var(--surface-inset);justify-content:space-between;align-items:center;gap:var(--surface-inset) 16px;background:var(--surface);border-radius:var(--radius);grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);display:grid;position:relative;overflow:hidden}.brand{color:inherit;align-items:center;gap:8px;font-size:15px;font-weight:600;text-decoration:none;display:flex}.pi-logo{flex:none;width:18px;height:18px;display:block}.brand{justify-self:start;padding:0 4px}.runtime-meter{--runtime-padding:10px;width:max-content;max-width:100%;height:var(--header-control-height);padding:5px var(--runtime-padding);border-radius:var(--radius-small);background:var(--control);white-space:nowrap;justify-self:center;align-items:center;font-size:11px;transition:width .22s cubic-bezier(.2,.8,.2,1);display:flex;overflow:clip}.runtime-content{flex:none;align-items:center;gap:8px;width:max-content;height:100%;display:flex}.runtime-location{flex:none;align-items:center;gap:6px;display:flex}.runtime-dot{background:var(--muted);border-radius:50%;width:5px;height:5px}.runtime-meter[data-state=generating] .runtime-dot,.runtime-meter[data-state=tool] .runtime-dot{background:var(--accent)}.runtime-meter[data-state=error] .runtime-dot{background:#d98c8c}.runtime-divider{background:var(--line);flex:0 0 1px;align-self:stretch;margin:2px 0}.runtime-sparkline{color:var(--accent);flex:none}.runtime-value{color:var(--muted);font-variant-numeric:tabular-nums;flex:none}.runtime-meter[data-state=generating] .runtime-value{color:var(--accent)}@media (prefers-reduced-motion:reduce){.runtime-meter{transition:none}}main{--conversation-min:420px;--workspace-min:370px;grid-template-columns:minmax(var(--conversation-min), var(--conversation-width,1.20482fr)) 0 minmax(var(--workspace-min), 1fr);height:calc(100dvh - var(--header-height) - var(--header-inset));max-width:var(--content-width);margin:auto;display:grid}.column-resizer{left:calc(-1 * var(--content-gutter));z-index:2;width:var(--content-gutter);cursor:col-resize;touch-action:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;outline:none;justify-content:center;align-items:center;margin:12px 0 8px;display:flex;position:relative}.column-resizer:after{content:"";background:var(--line-strong);border-radius:999px;flex:none;width:3px;height:44px;transition:background-color .12s}.column-resizer:hover:after{background:var(--text)}.column-resizer:focus-visible:after{background:var(--accent);outline:2px solid var(--accent);outline-offset:4px}.is-resizing-columns,.is-resizing-columns *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}.is-resizing-columns .column-resizer:after{background:var(--accent)}@media (prefers-reduced-motion:reduce){.column-resizer:after{transition:none}}@media (forced-colors:active){.column-resizer:after{background:buttontext}}.conversation{min-width:0;min-height:0;padding:12px var(--content-gutter) 8px;flex-direction:column;display:flex}.model-panel{background:var(--surface);margin-left:auto}.model-heading{justify-content:space-between;align-items:center;gap:8px;display:flex}.model-heading>div{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.model-heading strong{font-size:12px;font-weight:600}.header-model-source{color:inherit;white-space:nowrap;border-radius:3px;flex:none;align-items:center;gap:6px;text-decoration:none;display:inline-flex}.header-model-source img{border-radius:50%;flex:none;width:16px;height:16px;display:block}.header-model-source:hover{color:var(--accent)}.header-model-source:focus-visible{outline:2px solid var(--accent);outline-offset:3px}.badge{border-radius:var(--radius-small);background:var(--control);color:var(--muted);padding:3px 7px;font-size:10px}#load{min-width:90px;height:var(--header-control-height);flex-shrink:0}#load.is-loaded{opacity:1;min-width:0;height:28px;min-height:28px;color:var(--accent);background:#25312f;border-radius:6px;justify-content:center;align-items:center;gap:6px;padding:4px 8px;display:inline-flex}#load.is-loaded:before{content:"";background:currentColor;border-radius:50%;flex:none;width:5px;height:5px}progress{width:100%;height:5px;accent-color:var(--accent);margin-top:8px}header #progress{bottom:3px;left:var(--radius);width:calc(100% - 2 * var(--radius));appearance:none;background:var(--line);--progress-fade:clamp(24px, 5vw, 72px);--progress-mask:linear-gradient(90deg, transparent 2px, #000 var(--progress-fade), #000 calc(100% - var(--progress-fade)), transparent calc(100% - 2px));height:2px;-webkit-mask-image:var(--progress-mask);mask-image:var(--progress-mask);-webkit-mask-image:var(--progress-mask);border:0;border-radius:999px;margin:0;position:absolute;overflow:hidden}header #progress::-webkit-progress-bar{background:var(--line);border-radius:999px}header #progress::-webkit-progress-value{background:var(--accent);border-radius:999px}header #progress::-moz-progress-bar{background:var(--accent);border-radius:999px}header #progress:indeterminate{background:linear-gradient(90deg, transparent, var(--accent), transparent) 0 0 / 35% 100% no-repeat var(--line);animation:1.4s ease-in-out infinite alternate header-progress}header #progress:indeterminate::-webkit-progress-bar{background:0 0}header #progress:indeterminate::-webkit-progress-value{background:0 0}header #progress:indeterminate::-moz-progress-bar{background:0 0}@keyframes header-progress{0%{background-position:0 0}to{background-position:100% 0}}@media (prefers-reduced-motion:reduce){header #progress:indeterminate{background-position:50% 0;animation:none}}.muted{color:var(--muted);margin-top:4px;font-size:11px}.muted:empty{display:none}.terminal-panel{background:var(--background);border-radius:var(--radius-large);border:1px solid #0000;flex-direction:column;flex:1;min-height:0;padding:8px;display:flex}@media (width>=851px){.terminal-panel{padding-right:0}}#pi-terminal{isolation:isolate;background:var(--background);flex:1;min-width:0;min-height:120px;position:relative;overflow:hidden}#pi-terminal .pi-terminal-mount,#pi-terminal .xterm{height:100%}#pi-terminal .xterm-viewport{background-color:var(--background)!important}#pi-terminal textarea:focus{box-shadow:none}.terminal-paws{pointer-events:none;-webkit-user-select:none;user-select:none;position:absolute;overflow:hidden}.terminal-paws i{background:var(--muted);opacity:0;width:24px;height:24px;position:absolute;transform:rotate(28deg);-webkit-mask:url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3e%3cg%20fill='black'%3e%3cpath%20d='M2%207h4v5H2zM7%202h4v6H7zM13%202h4v6h-4zM18%207h4v5h-4zM8%2012h8v2h3v6h-4v-1H9v1H5v-6h3z'/%3e%3c/g%3e%3c/svg%3e") 50%/contain no-repeat;mask:url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3e%3cg%20fill='black'%3e%3cpath%20d='M2%207h4v5H2zM7%202h4v6H7zM13%202h4v6h-4zM18%207h4v5h-4zM8%2012h8v2h3v6h-4v-1H9v1H5v-6h3z'/%3e%3c/g%3e%3c/svg%3e") 50%/contain no-repeat}.terminal-paws:not([hidden]) i{animation:3.2s ease-in-out both terminal-paw;animation-delay:var(--delay)}.terminal-paws i:first-child{left:calc(18% + var(--trail-shift));--delay:0s;top:85%}.terminal-paws i:nth-child(2){left:calc(26% + var(--trail-shift));--delay:.65s;top:78%}.terminal-paws i:nth-child(3){left:calc(27% + var(--trail-shift));--delay:1.3s;top:68%}.terminal-paws i:nth-child(4){left:calc(35% + var(--trail-shift));--delay:1.95s;top:61%}.terminal-paws i:nth-child(5){left:calc(36% + var(--trail-shift));--delay:2.6s;top:51%}.terminal-paws i:nth-child(6){left:calc(44% + var(--trail-shift));--delay:3.25s;top:44%}@keyframes terminal-paw{0%,to{opacity:0}15%,40%{opacity:.14}}@media (width<=600px){.terminal-paws i{width:18px;height:18px}}@media (prefers-reduced-motion:reduce){.terminal-paws{display:none}}.empty-mascot{pointer-events:none;flex-direction:column;align-items:flex-end;gap:10px;width:196px;max-width:calc(100% - 24px);display:flex;position:absolute;right:12px}.mascot-cat{pointer-events:auto;cursor:pointer;background:0 0;border:0;border-radius:0;flex:none;min-height:0;padding:0;line-height:0;display:block;position:relative}.mascot-cat:hover{background:0 0}.mascot-cat,.setup-cat{-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;outline:none}.mascot-cat,.mascot-cat *,.setup-cat,.setup-cat *{-webkit-user-select:none;user-select:none;-webkit-user-drag:none}.mascot-cat>*,.setup-cat>*{pointer-events:none}.empty-mascot img{object-fit:contain;width:100%;height:100%;image-rendering:pixelated;-webkit-user-select:none;user-select:none;clip-path:polygon(16.906% 6.22%,26.077% 6.22%,26.077% 9.729%,30.861% 9.729%,30.861% 14.274%,35.407% 14.274%,35.407% 20.175%,56.539% 20.175%,56.539% 14.274%,61.404% 14.274%,61.404% 9.729%,65.71% 9.729%,65.71% 6.22%,75.04% 6.22%,75.04% 44.498%,68.82% 44.498%,68.82% 48.166%,75.04% 48.166%,75.04% 52.073%,68.82% 52.073%,68.82% 57.576%,65.152% 57.576%,65.152% 61.324%,68.979% 61.324%,68.979% 67.225%,73.285% 67.225%,73.285% 77.033%,77.671% 77.033%,77.671% 55.742%,81.818% 55.742%,81.818% 51.595%,91.228% 51.595%,91.228% 63.397%,86.124% 63.397%,86.124% 85.566%,81.579% 85.566%,81.579% 92.265%,25.04% 92.265%,25.04% 85.566%,28.07% 85.566%,28.07% 57.576%,19.856% 57.576%,19.856% 52.073%,12.52% 52.073%,12.52% 48.166%,19.856% 48.166%,19.856% 44.498%,12.52% 44.498%,12.52% 41.467%,16.906% 41.467%);display:block}.mascot-eyelids{opacity:0;position:absolute;inset:0}.mascot-eyelids:before,.mascot-eyelids:after{content:"";background:linear-gradient(to bottom, #f6f0e1 70%, var(--background) 70%, var(--background) 86%, #f6f0e1 86%);width:7%;height:7.4%;position:absolute;top:39.3%}.mascot-eyelids:before{left:28.5%}.mascot-eyelids:after{left:54%}.mascot-suggestion{pointer-events:auto;color:#24242c;text-align:left;white-space:normal;background:#f5efdf;border:0;border-radius:8px;padding:10px 12px;font:12px/1.45 ui-monospace,SFMono-Regular,Consolas,monospace;position:relative;box-shadow:0 3px #0c0c10}.mascot-suggestion:after{content:"";background:inherit;clip-path:polygon(0 0,100% 0,100% 50%,50% 50%,50% 100%,0 100%);width:12px;height:8px;position:absolute;bottom:-8px;right:52px}.mascot-suggestion:hover{background:#fffaf0}.terminal-controls{justify-content:flex-end;align-items:center;gap:8px;padding-top:4px;display:flex}.terminal-controls,.terminal-panel>footer{cursor:text}#new-chat{margin-right:auto}#newline:not(:hover){background:0 0}#notice{border-radius:var(--radius-small);background:var(--control);margin:6px 0;padding:8px 10px;font-size:12px}footer{color:var(--muted);justify-content:space-between;align-items:center;gap:8px;padding-top:8px;font-size:10px;display:flex}.workspace{min-width:0;min-height:0;margin:12px var(--content-gutter) 8px 0;background:var(--panel);border-radius:20px;flex-direction:column;display:flex;overflow:hidden}.workspace-heading{justify-content:space-between;align-items:center;min-height:40px;padding:5px 10px;display:flex}.workspace-heading h2{margin:0;font-size:12px;font-weight:600}.workspace-heading>div{gap:0;display:flex}.workspace-heading{flex-wrap:wrap}.folder-controls{flex-wrap:wrap;gap:4px;padding:0 10px 7px;display:flex}.folder-controls:has(>button:not([hidden])){min-height:30px}.folder-controls:not(:has(>button:not([hidden]))){display:none}#open-folder{color:var(--accent,#8abeb7);background:#8abeb710}#local-folder-bar{background:#8abeb710;border-radius:10px;margin:0 8px 8px;padding:10px;font-size:11px}#local-folder-name{color:var(--accent,#8abeb7);overflow-wrap:anywhere;display:block}#local-folder-hint{color:var(--muted);margin:4px 0 8px;line-height:1.5;display:block}.folder-actions{flex-wrap:wrap;gap:5px;display:flex}.folder-actions button{padding:6px 9px;font-size:11px}#local-review{box-sizing:border-box;background:var(--bg,#18181e);width:min(820px,100vw - 24px);max-height:calc(100dvh - 32px);color:var(--text);border:1px solid #8abeb740;border-radius:18px;padding:20px}#local-review::backdrop{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#0009}.review-heading{justify-content:space-between;align-items:center;gap:12px;display:flex}.review-heading h2{margin:0;font-size:20px}#review-close{padding:2px 10px;font-size:24px}#review-description{color:var(--muted);font-size:13px;line-height:1.5}#review-files{max-height:55dvh;overflow:auto}#review-files details{border:1px solid #ffffff18;border-radius:8px;margin:8px 0;overflow:hidden}#review-files summary{cursor:pointer;overflow-wrap:anywhere;padding:10px;font:12px ui-monospace,monospace}#review-files pre{tab-size:2;background:#0003;margin:0;padding:10px;font:12px/1.55 ui-monospace,monospace;overflow:auto}.diff-add{color:#98dfb4}.diff-remove{color:#f2a6a6}#review-error{color:#f2a6a6;font-size:13px;line-height:1.5}.review-actions{flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:16px;display:flex}.button{display:inline-block}.file-area{flex:1;grid-template-columns:140px minmax(0,1fr);min-height:180px;display:grid}#files{padding:5px 4px;overflow:auto}#files button{border-radius:var(--radius-small);text-align:left;white-space:normal;overflow-wrap:anywhere;background:0 0;border:none;align-items:center;gap:6px;width:100%;padding:5px 7px;font-family:ui-monospace,monospace;font-size:11px;line-height:1.45;display:flex}.file-name{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.file-icon{background-color:var(--file-color);width:16px;height:16px;-webkit-mask:var(--file-icon) center / 90% 90% no-repeat;mask:var(--file-icon) center / 90% 90% no-repeat;-webkit-mask:var(--file-icon) center / 90% 90% no-repeat;flex:0 0 16px;display:inline-block}.editor-file{align-items:center;gap:6px;min-width:0;display:flex}#filetype{flex:none;display:flex}#filetype:empty{display:none}@media (forced-colors:active){.file-icon{background-color:canvastext}}#files button:hover{background:var(--hover)}#files button.selected{background:var(--selected);color:var(--text)}.editor-area{border-radius:var(--radius);background:var(--surface);flex-direction:column;min-width:0;min-height:0;margin:0 8px 8px 0;display:flex;overflow:hidden}.editor-heading{background:#282832;justify-content:space-between;align-items:center;gap:6px;height:32px;padding:0 6px 0 10px;transition:background-color .14s,box-shadow .14s;display:flex}.editor-area:focus-within .editor-heading{background:#30323a;box-shadow:inset 0 -1px #8abeb74d}@media (prefers-reduced-motion:reduce){.editor-heading{transition:none}}@media (forced-colors:active){.editor-area:focus-within .editor-heading{outline-offset:-1px;outline:1px solid highlight}}#filename{text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,monospace;font-size:11px;overflow:hidden}.editor-heading{flex-shrink:0}.editor-input{flex:1;min-width:0;min-height:140px;position:relative;overflow:hidden}#editor,#editor-highlight{width:100%;height:100%;color:var(--text);font-variant-ligatures:none;letter-spacing:normal;tab-size:2;white-space:pre;overflow-wrap:normal;border:0;border-radius:0;margin:0;padding:10px 12px;font:12px/1.6 ui-monospace,SFMono-Regular,Consolas,monospace;position:absolute;top:0;left:0}#editor{resize:none;caret-color:var(--text);background:0 0;overflow:auto}#editor-highlight{visibility:hidden;pointer-events:none;overflow:hidden}.is-highlighted #editor-highlight{visibility:visible}.is-highlighted #editor{color:#0000}.is-highlighted #editor::selection{color:#0000}#editor::selection{background:#8abeb740}#editor:focus{box-shadow:none}#editor-highlight .token{font-style:normal;font-weight:400}#editor-highlight .token.comment,#editor-highlight .token.prolog,#editor-highlight .token.doctype{color:#9292a3}#editor-highlight .token.punctuation{color:#b0b0bd}#editor-highlight .token.tag,#editor-highlight .token.deleted{color:#e29a9a}#editor-highlight .token.keyword,#editor-highlight .token.selector,#editor-highlight .token.important{color:#c4a7d5}#editor-highlight .token.string,#editor-highlight .token.attr-value,#editor-highlight .token.inserted{color:#b5bd68}#editor-highlight .token.function,#editor-highlight .token.builtin,#editor-highlight .token.class-name{color:#8abeb7}#editor-highlight .token.attr-name,#editor-highlight .token.property,#editor-highlight .token.variable{color:#9db9d4}#editor-highlight .token.number,#editor-highlight .token.boolean,#editor-highlight .token.constant,#editor-highlight .token.operator,#editor-highlight .token.entity,#editor-highlight .token.url{color:#f0c674}@media (forced-colors:active){.is-highlighted #editor-highlight{visibility:hidden}.is-highlighted #editor{color:canvastext}.is-highlighted #editor::selection{color:canvastext}}.workspace>.terminal{border-radius:var(--radius);background:var(--background);flex-shrink:0;margin:0 8px;padding:0 8px 8px}.terminal summary{cursor:pointer;padding:6px 0;font-size:11px;font-weight:500}.terminal summary span{float:right;color:var(--muted);font-size:10px;font-weight:400}.shell-toolbar{color:var(--accent);justify-content:space-between;align-items:center;font:11px/1.5 ui-monospace,monospace;display:flex}.shell-toolbar button{color:var(--muted)}#terminal-output{resize:vertical;scrollbar-width:thin;overflow-wrap:anywhere;height:132px;min-height:84px;max-height:min(480px,45dvh);margin:0 0 6px;padding:2px 0;font:12px/1.5 ui-monospace,SFMono-Regular,Consolas,monospace;overflow:auto}#terminal-output:focus-visible{outline:1px solid var(--accent);outline-offset:2px;border-radius:var(--radius-small)}.shell-empty{color:var(--muted);flex-direction:column;gap:4px;padding:8px 2px;display:flex}.shell-empty strong{color:var(--text);font-weight:500}.shell-empty code{color:var(--accent)}.shell-entry{border-radius:var(--radius-small);background:var(--surface);margin-bottom:6px;padding:8px}.shell-entry:last-child{margin-bottom:0}.shell-entry-heading{align-items:baseline;gap:8px;display:flex}.shell-entry pre{font:inherit;white-space:pre-wrap;overflow-wrap:anywhere;margin:0}.shell-code{flex:1;min-width:0}.shell-status{color:var(--muted);flex-shrink:0;font-size:10px}.shell-status.success{color:#b5bd68}.shell-status.error,.shell-stderr{color:#e29a9a}.shell-entry .shell-stdout,.shell-entry .shell-stderr{margin:6px 0 0 16px}#shell-form{border-radius:var(--radius-small);background:var(--control);align-items:flex-start;gap:8px;padding:4px;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;display:flex}#shell-form:focus-within{box-shadow:0 0 0 1px var(--accent)}.shell-prompt{color:var(--accent);flex-shrink:0}#shell-form>.shell-prompt{padding-top:6px;line-height:20px}.shell-input{flex:1;min-width:0;position:relative}#command,#command-highlight{font-variant-ligatures:none;letter-spacing:normal;tab-size:2;white-space:pre-wrap;overflow-wrap:anywhere;border:0;border-radius:0;width:100%;margin:0;padding:6px 0;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace}#command-highlight{pointer-events:none;position:absolute;inset:0;overflow:hidden}#command{resize:none;color:#0000;min-height:32px;max-height:104px;caret-color:var(--text);scrollbar-width:thin;background:0 0;display:block;position:relative}#command:focus{box-shadow:none}#command::selection{color:#0000;background:#8abeb740}#command::placeholder{color:var(--muted)}#shell-run{border-radius:4px;min-height:32px}#shell-hint{color:var(--muted);flex-wrap:wrap;justify-content:space-between;gap:2px 12px;padding-top:5px;font-size:10px;line-height:1.5;display:flex}.shell-code .token,#command-highlight .token{font-style:normal;font-weight:400}.shell-code .token.comment,#command-highlight .token.comment{color:#aaaab7}.shell-code .token.string,#command-highlight .token.string{color:#b5bd68}.shell-code .token.function,.shell-code .token.builtin,#command-highlight .token.function,#command-highlight .token.builtin{color:#8abeb7}.shell-code .token.variable,.shell-code .token.assign-left,#command-highlight .token.variable,#command-highlight .token.assign-left{color:#c4a7d5}.shell-code .token.keyword,.shell-code .token.operator,.shell-code .token.number,#command-highlight .token.keyword,#command-highlight .token.operator,#command-highlight .token.number{color:#f0c674}.shell-code .token.parameter,#command-highlight .token.parameter{color:#9db9d4}@media (forced-colors:active){#command-highlight{display:none}#command{color:canvastext}#command::selection{color:canvastext}}.workspace-note{color:var(--muted);margin:6px 10px;font-size:10px;line-height:1.45}.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border:0;width:1px;height:1px;padding:0;position:absolute;overflow:hidden}#open-tab{color:var(--accent);white-space:normal;margin-top:8px;font-size:12px;text-decoration:none}#model-dialog{--dialog-inset:24px;--cat-size:152px;--cat-rise:calc(var(--cat-size) * .58);width:min(460px,100% - 32px);max-height:calc(100dvh - 32px - var(--cat-rise));padding:var(--dialog-inset);border-radius:calc(var(--radius-small) + var(--dialog-inset));background:var(--surface);color:var(--text);transform:translateY(calc(var(--cat-rise) / 2));border:0;overflow:visible;box-shadow:0 24px 80px #0008}#model-dialog[open]{flex-direction:column;display:flex}.setup-paws{--modal-half:min(230px, calc(50vw - 16px));left:50%;top:calc(50% - var(--cat-rise) / 2);pointer-events:none;-webkit-user-select:none;user-select:none;z-index:-1;width:100vw;height:100dvh;position:absolute;overflow:hidden;transform:translate(-50%,-50%)}.setup-paws i{background:var(--muted);opacity:0;width:28px;height:28px;transform:rotate(var(--angle));position:absolute;-webkit-mask:url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3e%3cg%20fill='black'%3e%3cpath%20d='M2%207h4v5H2zM7%202h4v6H7zM13%202h4v6h-4zM18%207h4v5h-4zM8%2012h8v2h3v6h-4v-1H9v1H5v-6h3z'/%3e%3c/g%3e%3c/svg%3e") 50%/contain no-repeat;mask:url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3e%3cg%20fill='black'%3e%3cpath%20d='M2%207h4v5H2zM7%202h4v6H7zM13%202h4v6h-4zM18%207h4v5h-4zM8%2012h8v2h3v6h-4v-1H9v1H5v-6h3z'/%3e%3c/g%3e%3c/svg%3e") 50%/contain no-repeat}#model-dialog[open] .setup-paws i{animation:10s ease-in-out infinite setup-paw;animation-delay:var(--delay);animation-play-state:var(--cat-play-state,running)}.setup-paws i:first-child{left:calc(50% - var(--modal-half) - clamp(48px, 9vw, 136px));--angle:-34deg;--delay:-1s;top:68%}.setup-paws i:nth-child(2){left:calc(50% - var(--modal-half) - clamp(30px, 6vw, 88px));--angle:-24deg;--delay:-.3s;top:60%}.setup-paws i:nth-child(3){left:calc(50% - var(--modal-half) - clamp(45px, 8vw, 120px));--angle:-12deg;--delay:.4s;top:52%}.setup-paws i:nth-child(4){left:calc(50% + var(--modal-half) + clamp(25px, 4vw, 64px));--angle:28deg;--delay:4s;top:46%}.setup-paws i:nth-child(5){left:calc(50% + var(--modal-half) + clamp(50px, 8vw, 120px));--angle:35deg;--delay:4.7s;top:38%}.setup-paws i:nth-child(6){left:calc(50% + var(--modal-half) + clamp(35px, 7vw, 100px));--angle:25deg;--delay:5.4s;top:30%}@keyframes setup-paw{0%,5%,38%,to{opacity:0}14%,24%{opacity:.16}}@media (width<=600px){.setup-paws i{width:18px;height:18px}.setup-paws i:first-child{--angle:65deg;top:22px;left:8%}.setup-paws i:nth-child(2){--angle:75deg;top:14px;left:19%}.setup-paws i:nth-child(3){--angle:65deg;top:22px;left:30%}.setup-paws i:nth-child(n+4){display:none}}@media (prefers-reduced-motion:reduce){#model-dialog[open] .setup-paws i{animation:none}.setup-paws i:first-child,.setup-paws i:nth-child(2){opacity:.1}}.setup-cat{top:calc(-1 * var(--cat-rise));right:var(--dialog-inset);width:var(--cat-size);height:calc(var(--cat-size) * .66);pointer-events:auto;cursor:pointer;touch-action:manipulation;-webkit-user-select:none;user-select:none;position:absolute;overflow:hidden}.setup-cat img,.setup-cat-tail,.setup-cat-eyelids{top:calc(var(--cat-size) * -.23);width:100%;height:auto;image-rendering:pixelated;opacity:0;display:block;position:absolute;left:0}.setup-cat img{clip-path:inset(0 22% 0 0)}.setup-cat-tail{aspect-ratio:1;background:var(--cat-sprite) 0 0 / 100% 100% no-repeat;clip-path:polygon(78% 40%,100% 40%,100% 82%,77% 82%,77% 77%,78% 77%);transform-origin:78% 80%}.setup-cat.is-ready img,.setup-cat.is-ready .setup-cat-tail{opacity:1}.setup-cat-eyelids{aspect-ratio:1}.setup-cat-eyelids:before,.setup-cat-eyelids:after{content:"";background:linear-gradient(#080709,#080709) 50% 80%/78% 14% no-repeat,#f6efdf;width:8.4%;height:8.7%;position:absolute;top:55.6%}.setup-cat-eyelids:before{left:28%}.setup-cat-eyelids:after{left:54.3%}#model-dialog[open] .setup-cat.is-ready .setup-cat-tail{animation:9s ease-in-out infinite setup-tail-swish;animation-play-state:var(--cat-play-state,running)}#model-dialog[open] .setup-cat.is-ready .setup-cat-eyelids{animation:7.4s step-end infinite setup-cat-blink;animation-play-state:var(--cat-play-state,running)}@keyframes setup-cat-blink{0%,45%,to{opacity:0}43%{opacity:1}}@keyframes setup-tail-swish{0%,24%,50%,to{transform:rotate(0)}33%{transform:rotate(-4deg)}41%{transform:rotate(2.5deg)}46%{transform:rotate(-.6deg)}}@media (prefers-reduced-motion:reduce){#model-dialog[open] .setup-cat.is-ready .setup-cat-tail,#model-dialog[open] .setup-cat.is-ready .setup-cat-eyelids{animation:none}}.setup-heading{flex-shrink:0;align-items:flex-start;gap:8px;display:flex}#model-cancel{width:32px;height:32px;min-height:32px;color:var(--muted);background:0 0;flex:none;place-items:center;padding:0;display:grid}#model-cancel:hover:not(:disabled){background:var(--control);color:var(--text)}.setup-body{min-height:0;overflow:auto}#model-dialog::backdrop{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#08080dbd}#model-title{letter-spacing:-.5px;flex:1;min-width:0;margin:0 0 8px;font-size:27px;font-weight:650;line-height:1.2}#model-description{color:var(--muted);margin:0;line-height:1.6}.setup-runtime{grid-template-columns:minmax(max-content,1fr) 1fr 1.2fr;gap:8px;margin:18px 0;display:grid}.setup-runtime>div{border-radius:var(--radius-small);background:var(--control);padding:10px}.setup-runtime dt{color:var(--accent);font-size:12px;font-weight:600}.setup-runtime dd{margin:5px 0 0;font-size:11px;line-height:1.5}.setup-model{align-items:center;gap:6px;display:flex}.model-org{border-radius:50%;flex:none;display:inline-flex}.model-org img{border-radius:inherit;width:18px;height:18px;display:block}.model-source{color:inherit;-webkit-text-decoration-color:var(--muted);text-decoration-color:var(--muted);text-underline-offset:3px;white-space:nowrap}.model-source:hover{color:var(--accent)}.setup-model a:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:3px}.setup-facts{border-radius:var(--radius-small);background:var(--panel);flex-direction:column;gap:5px;margin:18px 0;padding:12px;line-height:1.45;display:flex}.setup-facts strong{font-size:12px;font-weight:600}.setup-facts span,.setup-label{color:var(--muted);font-size:11px;line-height:1.5}.setup-label{margin:16px 0 6px}#model-preview{white-space:pre-wrap;overflow-wrap:anywhere;border-radius:var(--radius-small);background:var(--control);max-height:84px;padding:10px 12px;font-size:12px;line-height:1.5;overflow:auto}#model-error{border-radius:var(--radius-small);overflow-wrap:anywhere;background:#3c2828;padding:10px 12px;line-height:1.5}#model-open-tab{color:var(--accent);white-space:normal;text-decoration:none}.setup-credits{color:var(--muted);flex-wrap:wrap;align-items:center;gap:6px 10px;margin:18px 0;font-size:11px;line-height:1.6;display:flex}.setup-credits a{color:inherit;white-space:nowrap;align-items:center;gap:4px;text-decoration:none;display:inline-flex}.setup-credits a:hover{color:var(--text);text-underline-offset:3px;text-decoration:underline}.setup-credits a:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:3px}.setup-credits img,.setup-credits svg{object-fit:contain;flex:none;width:14px;height:14px}.setup-credits .credit-pi{padding:2px}.setup-actions{flex-shrink:0;padding-top:4px;display:flex}.setup-actions button{width:100%;min-height:44px;padding:10px 16px}#model-confirm{color:#18181e;background:#fff;font-size:14px;font-weight:600}#model-confirm:hover{background:#e8e8ed}@media (width<=420px){#model-dialog{--dialog-inset:16px;--cat-size:116px}#model-title{font-size:24px}.setup-runtime{grid-template-columns:1fr;gap:5px;margin:14px 0}.setup-runtime>div{align-items:baseline;gap:12px;padding:8px 10px;display:flex}.setup-runtime dt{flex:0 0 64px}.setup-runtime dd{margin:0}.setup-facts{margin:14px 0}.setup-credits{margin:12px 0}}@media (width>=851px) and (width<=1000px){header{grid-template-columns:auto minmax(0,1fr) auto}}@media (height<=620px){#model-dialog{--cat-size:72px}.setup-runtime,.setup-facts{margin:12px 0}}@media (width<=420px) and (height<=620px){.setup-runtime{grid-template-columns:minmax(0,1fr) max-content}.setup-runtime>div:first-child{grid-column:1/-1}.setup-runtime>div:not(:first-child){padding:6px 10px;display:block}.setup-runtime>div:not(:first-child) dd{margin-top:2px}}@media (width<=850px){:root{--header-height:calc(2 * var(--header-control-height) + 3 * var(--surface-inset));--header-inset:10px;--content-gutter:10px}header{grid-template-columns:auto minmax(0,1fr);grid-template-rows:repeat(2, var(--header-control-height));gap:var(--surface-inset);grid-template-areas:"brand runtime""model model"}.brand{grid-area:brand;justify-self:start}.runtime-meter{grid-area:runtime;justify-self:end}.model-panel{grid-area:model;margin:0}main{flex-direction:column;height:auto;display:flex}.column-resizer{display:none}.conversation{height:calc(100dvh - var(--header-height) - var(--header-inset));min-height:320px;padding:10px var(--content-gutter)}.workspace{min-height:520px;margin:0 var(--content-gutter) 10px}.file-area{grid-template-columns:115px minmax(0,1fr);min-height:280px}h1{font-size:20px}.badge,footer{font-size:9px}}@media (pointer:coarse){:root{--header-control-height:38px}button,.button,#files button{min-height:38px}.editor-heading{min-height:40px}.terminal summary{padding-top:11px;padding-bottom:11px}#command,#command-highlight,#pi-terminal .xterm-helper-textarea{font-size:16px}}.xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}
|
|
|
|
| 1 |
+
:root{font-synthesis:none;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;color:var(--text);background:var(--background);--background:#18181e;--surface:#1e1e24;--panel:#22222b;--control:#282832;--hover:#343541;--selected:#3a3a4a;--line:#393942;--line-strong:#50505c;--text:#d4d4d4;--muted:#b0b0bd;--accent:#8abeb7;--surface-inset:8px;--radius-small:8px;--radius:calc(var(--radius-small) + var(--surface-inset));--radius-large:calc(var(--radius) + var(--surface-inset));--content-width:1800px;--content-gutter:14px;--header-inset:12px;--header-control-height:32px;--header-height:calc(var(--header-control-height) + 2 * var(--surface-inset));scrollbar-color:var(--line-strong) var(--background);font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:13px}*{box-sizing:border-box}body{margin:0}button,input,textarea{font:inherit;color:inherit}::selection{background:var(--selected);color:var(--text)}input::placeholder,textarea::placeholder{color:var(--muted);opacity:1}button,.button{cursor:pointer;border-radius:var(--radius-small);background:var(--control);min-height:28px;color:inherit;white-space:nowrap;border:1px solid #0000;padding:5px 9px;font-size:12px;line-height:1.4}button:hover,.button:hover{background:var(--hover)}button:disabled{opacity:.45;cursor:default}.primary{background:var(--hover);color:var(--text)}.primary:hover{background:var(--selected)}#send.has-input:not(:disabled){color:#18181e;background:#fff}#send.has-input:not(:disabled):hover{background:#e8e8ed}.quiet{background:0 0;border-color:#0000;font-size:11px}textarea,input{outline:none}textarea:focus,input:focus{box-shadow:inset 0 0 0 1px var(--accent)}button:focus-visible,.button:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}[hidden]{display:none!important}header{width:calc(100% - 2 * var(--content-gutter));max-width:calc(var(--content-width) - 2 * var(--content-gutter));height:var(--header-height);margin:var(--header-inset) auto 0;padding:var(--surface-inset);justify-content:space-between;align-items:center;gap:var(--surface-inset) 16px;background:var(--surface);border-radius:var(--radius);grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);display:grid;position:relative;overflow:hidden}.brand{color:inherit;align-items:center;gap:8px;font-size:15px;font-weight:600;text-decoration:none;display:flex}.pi-logo{flex:none;width:18px;height:18px;display:block}.brand{justify-self:start;padding:0 4px}.runtime-meter{--runtime-padding:10px;width:max-content;max-width:100%;height:var(--header-control-height);padding:5px var(--runtime-padding);border-radius:var(--radius-small);background:var(--control);white-space:nowrap;justify-self:center;align-items:center;font-size:11px;transition:width .22s cubic-bezier(.2,.8,.2,1);display:flex;overflow:clip}.runtime-content{flex:none;align-items:center;gap:8px;width:max-content;height:100%;display:flex}.runtime-location{flex:none;align-items:center;gap:6px;display:flex}.runtime-dot{background:var(--muted);border-radius:50%;width:5px;height:5px}.runtime-meter[data-state=generating] .runtime-dot,.runtime-meter[data-state=tool] .runtime-dot{background:var(--accent)}.runtime-meter[data-state=error] .runtime-dot{background:#d98c8c}.runtime-divider{background:var(--line);flex:0 0 1px;align-self:stretch;margin:2px 0}.runtime-sparkline{color:var(--accent);flex:none}.runtime-value{color:var(--muted);font-variant-numeric:tabular-nums;flex:none}.runtime-meter[data-state=generating] .runtime-value{color:var(--accent)}@media (prefers-reduced-motion:reduce){.runtime-meter{transition:none}}main{--conversation-min:420px;--workspace-min:370px;grid-template-columns:minmax(var(--conversation-min), var(--conversation-width,1.20482fr)) 0 minmax(var(--workspace-min), 1fr);height:calc(100dvh - var(--header-height) - var(--header-inset));max-width:var(--content-width);margin:auto;display:grid}.column-resizer{left:calc(-1 * var(--content-gutter));z-index:2;width:var(--content-gutter);cursor:col-resize;touch-action:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;outline:none;justify-content:center;align-items:center;margin:12px 0 8px;display:flex;position:relative}.column-resizer:after{content:"";background:var(--line-strong);border-radius:999px;flex:none;width:3px;height:44px;transition:background-color .12s}.column-resizer:hover:after{background:var(--text)}.column-resizer:focus-visible:after{background:var(--accent);outline:2px solid var(--accent);outline-offset:4px}.is-resizing-columns,.is-resizing-columns *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}.is-resizing-columns .column-resizer:after{background:var(--accent)}@media (prefers-reduced-motion:reduce){.column-resizer:after{transition:none}}@media (forced-colors:active){.column-resizer:after{background:buttontext}}.conversation{min-width:0;min-height:0;padding:12px var(--content-gutter) 8px;flex-direction:column;display:flex}.model-panel{background:var(--surface);margin-left:auto}.model-heading{justify-content:space-between;align-items:center;gap:8px;display:flex}.model-heading>div{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.model-heading strong{font-size:12px;font-weight:600}.header-model-source{color:inherit;white-space:nowrap;border-radius:3px;flex:none;align-items:center;gap:6px;text-decoration:none;display:inline-flex}.header-model-source img{border-radius:50%;flex:none;width:16px;height:16px;display:block}.header-model-source:hover{color:var(--accent)}.header-model-source:focus-visible{outline:2px solid var(--accent);outline-offset:3px}.badge{border-radius:var(--radius-small);background:var(--control);color:var(--muted);padding:3px 7px;font-size:10px}#load{min-width:90px;height:var(--header-control-height);flex-shrink:0}#load.is-loaded{opacity:1;min-width:0;height:28px;min-height:28px;color:var(--accent);background:#25312f;border-radius:6px;justify-content:center;align-items:center;gap:6px;padding:4px 8px;display:inline-flex}#load.is-loaded:before{content:"";background:currentColor;border-radius:50%;flex:none;width:5px;height:5px}progress{width:100%;height:5px;accent-color:var(--accent);margin-top:8px}header #progress{bottom:3px;left:var(--radius);width:calc(100% - 2 * var(--radius));appearance:none;background:var(--line);--progress-fade:clamp(24px, 5vw, 72px);--progress-mask:linear-gradient(90deg, transparent 2px, #000 var(--progress-fade), #000 calc(100% - var(--progress-fade)), transparent calc(100% - 2px));height:2px;-webkit-mask-image:var(--progress-mask);mask-image:var(--progress-mask);-webkit-mask-image:var(--progress-mask);border:0;border-radius:999px;margin:0;position:absolute;overflow:hidden}header #progress::-webkit-progress-bar{background:var(--line);border-radius:999px}header #progress::-webkit-progress-value{background:var(--accent);border-radius:999px}header #progress::-moz-progress-bar{background:var(--accent);border-radius:999px}header #progress:indeterminate{background:linear-gradient(90deg, transparent, var(--accent), transparent) 0 0 / 35% 100% no-repeat var(--line);animation:1.4s ease-in-out infinite alternate header-progress}header #progress:indeterminate::-webkit-progress-bar{background:0 0}header #progress:indeterminate::-webkit-progress-value{background:0 0}header #progress:indeterminate::-moz-progress-bar{background:0 0}@keyframes header-progress{0%{background-position:0 0}to{background-position:100% 0}}@media (prefers-reduced-motion:reduce){header #progress:indeterminate{background-position:50% 0;animation:none}}.muted{color:var(--muted);margin-top:4px;font-size:11px}.muted:empty{display:none}.terminal-panel{background:var(--background);border-radius:var(--radius-large);border:1px solid #0000;flex-direction:column;flex:1;min-height:0;padding:8px;display:flex}@media (width>=851px){.terminal-panel{padding-right:0}}#pi-terminal{isolation:isolate;background:var(--background);flex:1;min-width:0;min-height:120px;position:relative;overflow:hidden}#pi-terminal .pi-terminal-mount,#pi-terminal .xterm{height:100%}#pi-terminal .xterm-viewport{background-color:var(--background)!important}#pi-terminal textarea:focus{box-shadow:none}.terminal-paws{pointer-events:none;-webkit-user-select:none;user-select:none;position:absolute;overflow:hidden}.terminal-paws i{background:var(--muted);opacity:0;width:24px;height:24px;position:absolute;transform:rotate(28deg);-webkit-mask:url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3e%3cg%20fill='black'%3e%3cpath%20d='M2%207h4v5H2zM7%202h4v6H7zM13%202h4v6h-4zM18%207h4v5h-4zM8%2012h8v2h3v6h-4v-1H9v1H5v-6h3z'/%3e%3c/g%3e%3c/svg%3e") 50%/contain no-repeat;mask:url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3e%3cg%20fill='black'%3e%3cpath%20d='M2%207h4v5H2zM7%202h4v6H7zM13%202h4v6h-4zM18%207h4v5h-4zM8%2012h8v2h3v6h-4v-1H9v1H5v-6h3z'/%3e%3c/g%3e%3c/svg%3e") 50%/contain no-repeat}.terminal-paws:not([hidden]) i{animation:3.2s ease-in-out both terminal-paw;animation-delay:var(--delay)}.terminal-paws i:first-child{left:calc(18% + var(--trail-shift));--delay:0s;top:85%}.terminal-paws i:nth-child(2){left:calc(26% + var(--trail-shift));--delay:.65s;top:78%}.terminal-paws i:nth-child(3){left:calc(27% + var(--trail-shift));--delay:1.3s;top:68%}.terminal-paws i:nth-child(4){left:calc(35% + var(--trail-shift));--delay:1.95s;top:61%}.terminal-paws i:nth-child(5){left:calc(36% + var(--trail-shift));--delay:2.6s;top:51%}.terminal-paws i:nth-child(6){left:calc(44% + var(--trail-shift));--delay:3.25s;top:44%}@keyframes terminal-paw{0%,to{opacity:0}15%,40%{opacity:.14}}@media (width<=600px){.terminal-paws i{width:18px;height:18px}}@media (prefers-reduced-motion:reduce){.terminal-paws{display:none}}.empty-mascot{pointer-events:none;flex-direction:column;align-items:flex-end;gap:10px;width:196px;max-width:calc(100% - 24px);display:flex;position:absolute;right:12px}.mascot-cat{pointer-events:auto;cursor:pointer;background:0 0;border:0;border-radius:0;flex:none;min-height:0;padding:0;line-height:0;display:block;position:relative}.mascot-cat:hover{background:0 0}.mascot-cat,.setup-cat{-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;outline:none}.mascot-cat,.mascot-cat *,.setup-cat,.setup-cat *{-webkit-user-select:none;user-select:none;-webkit-user-drag:none}.mascot-cat>*,.setup-cat>*{pointer-events:none}.empty-mascot img{object-fit:contain;width:100%;height:100%;image-rendering:pixelated;-webkit-user-select:none;user-select:none;clip-path:polygon(16.906% 6.22%,26.077% 6.22%,26.077% 9.729%,30.861% 9.729%,30.861% 14.274%,35.407% 14.274%,35.407% 20.175%,56.539% 20.175%,56.539% 14.274%,61.404% 14.274%,61.404% 9.729%,65.71% 9.729%,65.71% 6.22%,75.04% 6.22%,75.04% 44.498%,68.82% 44.498%,68.82% 48.166%,75.04% 48.166%,75.04% 52.073%,68.82% 52.073%,68.82% 57.576%,65.152% 57.576%,65.152% 61.324%,68.979% 61.324%,68.979% 67.225%,73.285% 67.225%,73.285% 77.033%,77.671% 77.033%,77.671% 55.742%,81.818% 55.742%,81.818% 51.595%,91.228% 51.595%,91.228% 63.397%,86.124% 63.397%,86.124% 85.566%,81.579% 85.566%,81.579% 92.265%,25.04% 92.265%,25.04% 85.566%,28.07% 85.566%,28.07% 57.576%,19.856% 57.576%,19.856% 52.073%,12.52% 52.073%,12.52% 48.166%,19.856% 48.166%,19.856% 44.498%,12.52% 44.498%,12.52% 41.467%,16.906% 41.467%);display:block}.mascot-eyelids{opacity:0;position:absolute;inset:0}.mascot-eyelids:before,.mascot-eyelids:after{content:"";background:linear-gradient(to bottom, #f6f0e1 70%, var(--background) 70%, var(--background) 86%, #f6f0e1 86%);width:7%;height:7.4%;position:absolute;top:39.3%}.mascot-eyelids:before{left:28.5%}.mascot-eyelids:after{left:54%}.mascot-suggestion{pointer-events:auto;color:#24242c;text-align:left;white-space:normal;background:#f5efdf;border:0;border-radius:8px;padding:10px 12px;font:12px/1.45 ui-monospace,SFMono-Regular,Consolas,monospace;position:relative;box-shadow:0 3px #0c0c10}.mascot-suggestion:after{content:"";background:inherit;clip-path:polygon(0 0,100% 0,100% 50%,50% 50%,50% 100%,0 100%);width:12px;height:8px;position:absolute;bottom:-8px;right:52px}.mascot-suggestion:hover{background:#fffaf0}.terminal-controls{justify-content:flex-end;align-items:center;gap:8px;padding-top:4px;display:flex}.terminal-controls,.terminal-panel>footer{cursor:text}#new-chat{margin-right:auto}#newline:not(:hover){background:0 0}#notice{border-radius:var(--radius-small);background:var(--control);margin:6px 0;padding:8px 10px;font-size:12px}footer{color:var(--muted);justify-content:space-between;align-items:center;gap:8px;padding-top:8px;font-size:10px;display:flex}.workspace{min-width:0;min-height:0;margin:12px var(--content-gutter) 8px 0;background:var(--panel);border-radius:20px;flex-direction:column;display:flex;overflow:hidden}.workspace-heading{justify-content:space-between;align-items:center;min-height:40px;padding:5px 10px;display:flex}.workspace-heading h2{margin:0;font-size:12px;font-weight:600}.workspace-heading>div{gap:0;display:flex}.workspace-heading{flex-wrap:wrap}.folder-controls{flex-wrap:wrap;gap:4px;padding:0 10px 7px;display:flex}.folder-controls:has(>button:not([hidden])){min-height:30px}.folder-controls:not(:has(>button:not([hidden]))){display:none}#open-folder{color:var(--accent,#8abeb7);background:#8abeb710}#open-folder:not([hidden]){align-items:center;gap:6px;display:inline-flex}#open-folder svg{flex:none}#local-folder-bar{background:#8abeb710;border-radius:10px;margin:0 8px 8px;padding:10px;font-size:11px}#local-folder-name{color:var(--accent,#8abeb7);overflow-wrap:anywhere;display:block}#local-folder-hint{color:var(--muted);margin:4px 0 8px;line-height:1.5;display:block}.folder-actions{flex-wrap:wrap;gap:5px;display:flex}.folder-actions button{padding:6px 9px;font-size:11px}#local-review{box-sizing:border-box;background:var(--bg,#18181e);width:min(820px,100vw - 24px);max-height:calc(100dvh - 32px);color:var(--text);border:1px solid #8abeb740;border-radius:18px;padding:20px}#local-review::backdrop{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#0009}.review-heading{justify-content:space-between;align-items:center;gap:12px;display:flex}.review-heading h2{margin:0;font-size:20px}#review-close{padding:2px 10px;font-size:24px}#review-description{color:var(--muted);font-size:13px;line-height:1.5}#review-files{max-height:55dvh;overflow:auto}#review-files details{border:1px solid #ffffff18;border-radius:8px;margin:8px 0;overflow:hidden}#review-files summary{cursor:pointer;overflow-wrap:anywhere;padding:10px;font:12px ui-monospace,monospace}#review-files pre{tab-size:2;background:#0003;margin:0;padding:10px;font:12px/1.55 ui-monospace,monospace;overflow:auto}.diff-add{color:#98dfb4}.diff-remove{color:#f2a6a6}#review-error{color:#f2a6a6;font-size:13px;line-height:1.5}.review-actions{flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:16px;display:flex}.button{display:inline-block}.file-area{flex:1;grid-template-columns:140px minmax(0,1fr);min-height:180px;display:grid}#files{padding:5px 4px;overflow:auto}#files button{border-radius:var(--radius-small);text-align:left;white-space:normal;overflow-wrap:anywhere;background:0 0;border:none;align-items:center;gap:6px;width:100%;padding:5px 7px;font-family:ui-monospace,monospace;font-size:11px;line-height:1.45;display:flex}.file-name{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.file-icon{background-color:var(--file-color);width:16px;height:16px;-webkit-mask:var(--file-icon) center / 90% 90% no-repeat;mask:var(--file-icon) center / 90% 90% no-repeat;-webkit-mask:var(--file-icon) center / 90% 90% no-repeat;flex:0 0 16px;display:inline-block}.editor-file{align-items:center;gap:6px;min-width:0;display:flex}#filetype{flex:none;display:flex}#filetype:empty{display:none}@media (forced-colors:active){.file-icon{background-color:canvastext}}#files button:hover{background:var(--hover)}#files button.selected{background:var(--selected);color:var(--text)}.editor-area{border-radius:var(--radius);background:var(--surface);flex-direction:column;min-width:0;min-height:0;margin:0 8px 8px 0;display:flex;overflow:hidden}.editor-heading{background:#282832;justify-content:space-between;align-items:center;gap:6px;height:32px;padding:0 6px 0 10px;transition:background-color .14s,box-shadow .14s;display:flex}.editor-area:focus-within .editor-heading{background:#30323a;box-shadow:inset 0 -1px #8abeb74d}@media (prefers-reduced-motion:reduce){.editor-heading{transition:none}}@media (forced-colors:active){.editor-area:focus-within .editor-heading{outline-offset:-1px;outline:1px solid highlight}}#filename{text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,monospace;font-size:11px;overflow:hidden}.editor-heading{flex-shrink:0}.editor-input{flex:1;min-width:0;min-height:140px;position:relative;overflow:hidden}#editor,#editor-highlight{width:100%;height:100%;color:var(--text);font-variant-ligatures:none;letter-spacing:normal;tab-size:2;white-space:pre;overflow-wrap:normal;border:0;border-radius:0;margin:0;padding:10px 12px;font:12px/1.6 ui-monospace,SFMono-Regular,Consolas,monospace;position:absolute;top:0;left:0}#editor{resize:none;caret-color:var(--text);background:0 0;overflow:auto}#editor-highlight{visibility:hidden;pointer-events:none;overflow:hidden}.is-highlighted #editor-highlight{visibility:visible}.is-highlighted #editor{color:#0000}.is-highlighted #editor::selection{color:#0000}#editor::selection{background:#8abeb740}#editor:focus{box-shadow:none}#editor-highlight .token{font-style:normal;font-weight:400}#editor-highlight .token.comment,#editor-highlight .token.prolog,#editor-highlight .token.doctype{color:#9292a3}#editor-highlight .token.punctuation{color:#b0b0bd}#editor-highlight .token.tag,#editor-highlight .token.deleted{color:#e29a9a}#editor-highlight .token.keyword,#editor-highlight .token.selector,#editor-highlight .token.important{color:#c4a7d5}#editor-highlight .token.string,#editor-highlight .token.attr-value,#editor-highlight .token.inserted{color:#b5bd68}#editor-highlight .token.function,#editor-highlight .token.builtin,#editor-highlight .token.class-name{color:#8abeb7}#editor-highlight .token.attr-name,#editor-highlight .token.property,#editor-highlight .token.variable{color:#9db9d4}#editor-highlight .token.number,#editor-highlight .token.boolean,#editor-highlight .token.constant,#editor-highlight .token.operator,#editor-highlight .token.entity,#editor-highlight .token.url{color:#f0c674}@media (forced-colors:active){.is-highlighted #editor-highlight{visibility:hidden}.is-highlighted #editor{color:canvastext}.is-highlighted #editor::selection{color:canvastext}}.workspace>.terminal{border-radius:var(--radius);background:var(--background);flex-shrink:0;margin:0 8px;padding:0 8px 8px}.terminal summary{cursor:pointer;padding:6px 0;font-size:11px;font-weight:500}.terminal summary span{float:right;color:var(--muted);font-size:10px;font-weight:400}.shell-toolbar{color:var(--accent);justify-content:space-between;align-items:center;font:11px/1.5 ui-monospace,monospace;display:flex}.shell-toolbar button{color:var(--muted)}#terminal-output{resize:vertical;scrollbar-width:thin;overflow-wrap:anywhere;height:132px;min-height:84px;max-height:min(480px,45dvh);margin:0 0 6px;padding:2px 0;font:12px/1.5 ui-monospace,SFMono-Regular,Consolas,monospace;overflow:auto}#terminal-output:focus-visible{outline:1px solid var(--accent);outline-offset:2px;border-radius:var(--radius-small)}.shell-empty{color:var(--muted);flex-direction:column;gap:4px;padding:8px 2px;display:flex}.shell-empty strong{color:var(--text);font-weight:500}.shell-empty code{color:var(--accent)}.shell-entry{border-radius:var(--radius-small);background:var(--surface);margin-bottom:6px;padding:8px}.shell-entry:last-child{margin-bottom:0}.shell-entry-heading{align-items:baseline;gap:8px;display:flex}.shell-entry pre{font:inherit;white-space:pre-wrap;overflow-wrap:anywhere;margin:0}.shell-code{flex:1;min-width:0}.shell-status{color:var(--muted);flex-shrink:0;font-size:10px}.shell-status.success{color:#b5bd68}.shell-status.error,.shell-stderr{color:#e29a9a}.shell-entry .shell-stdout,.shell-entry .shell-stderr{margin:6px 0 0 16px}#shell-form{border-radius:var(--radius-small);background:var(--control);align-items:flex-start;gap:8px;padding:4px;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;display:flex}#shell-form:focus-within{box-shadow:0 0 0 1px var(--accent)}.shell-prompt{color:var(--accent);flex-shrink:0}#shell-form>.shell-prompt{padding-top:6px;line-height:20px}.shell-input{flex:1;min-width:0;position:relative}#command,#command-highlight{font-variant-ligatures:none;letter-spacing:normal;tab-size:2;white-space:pre-wrap;overflow-wrap:anywhere;border:0;border-radius:0;width:100%;margin:0;padding:6px 0;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace}#command-highlight{pointer-events:none;position:absolute;inset:0;overflow:hidden}#command{resize:none;color:#0000;min-height:32px;max-height:104px;caret-color:var(--text);scrollbar-width:thin;background:0 0;display:block;position:relative}#command:focus{box-shadow:none}#command::selection{color:#0000;background:#8abeb740}#command::placeholder{color:var(--muted)}#shell-run{border-radius:4px;min-height:32px}#shell-hint{color:var(--muted);flex-wrap:wrap;justify-content:space-between;gap:2px 12px;padding-top:5px;font-size:10px;line-height:1.5;display:flex}.shell-code .token,#command-highlight .token{font-style:normal;font-weight:400}.shell-code .token.comment,#command-highlight .token.comment{color:#aaaab7}.shell-code .token.string,#command-highlight .token.string{color:#b5bd68}.shell-code .token.function,.shell-code .token.builtin,#command-highlight .token.function,#command-highlight .token.builtin{color:#8abeb7}.shell-code .token.variable,.shell-code .token.assign-left,#command-highlight .token.variable,#command-highlight .token.assign-left{color:#c4a7d5}.shell-code .token.keyword,.shell-code .token.operator,.shell-code .token.number,#command-highlight .token.keyword,#command-highlight .token.operator,#command-highlight .token.number{color:#f0c674}.shell-code .token.parameter,#command-highlight .token.parameter{color:#9db9d4}@media (forced-colors:active){#command-highlight{display:none}#command{color:canvastext}#command::selection{color:canvastext}}.workspace-note{color:var(--muted);margin:6px 10px;font-size:10px;line-height:1.45}.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border:0;width:1px;height:1px;padding:0;position:absolute;overflow:hidden}#open-tab{color:var(--accent);white-space:normal;margin-top:8px;font-size:12px;text-decoration:none}#model-dialog{--dialog-inset:24px;--cat-size:152px;--cat-rise:calc(var(--cat-size) * .58);width:min(460px,100% - 32px);max-height:calc(100dvh - 32px - var(--cat-rise));padding:var(--dialog-inset);border-radius:calc(var(--radius-small) + var(--dialog-inset));background:var(--surface);color:var(--text);transform:translateY(calc(var(--cat-rise) / 2));border:0;overflow:visible;box-shadow:0 24px 80px #0008}#model-dialog[open]{flex-direction:column;display:flex}.setup-paws{--modal-half:min(230px, calc(50vw - 16px));left:50%;top:calc(50% - var(--cat-rise) / 2);pointer-events:none;-webkit-user-select:none;user-select:none;z-index:-1;width:100vw;height:100dvh;position:absolute;overflow:hidden;transform:translate(-50%,-50%)}.setup-paws i{background:var(--muted);opacity:0;width:28px;height:28px;transform:rotate(var(--angle));position:absolute;-webkit-mask:url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3e%3cg%20fill='black'%3e%3cpath%20d='M2%207h4v5H2zM7%202h4v6H7zM13%202h4v6h-4zM18%207h4v5h-4zM8%2012h8v2h3v6h-4v-1H9v1H5v-6h3z'/%3e%3c/g%3e%3c/svg%3e") 50%/contain no-repeat;mask:url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3e%3cg%20fill='black'%3e%3cpath%20d='M2%207h4v5H2zM7%202h4v6H7zM13%202h4v6h-4zM18%207h4v5h-4zM8%2012h8v2h3v6h-4v-1H9v1H5v-6h3z'/%3e%3c/g%3e%3c/svg%3e") 50%/contain no-repeat}#model-dialog[open] .setup-paws i{animation:10s ease-in-out infinite setup-paw;animation-delay:var(--delay);animation-play-state:var(--cat-play-state,running)}.setup-paws i:first-child{left:calc(50% - var(--modal-half) - clamp(48px, 9vw, 136px));--angle:-34deg;--delay:-1s;top:68%}.setup-paws i:nth-child(2){left:calc(50% - var(--modal-half) - clamp(30px, 6vw, 88px));--angle:-24deg;--delay:-.3s;top:60%}.setup-paws i:nth-child(3){left:calc(50% - var(--modal-half) - clamp(45px, 8vw, 120px));--angle:-12deg;--delay:.4s;top:52%}.setup-paws i:nth-child(4){left:calc(50% + var(--modal-half) + clamp(25px, 4vw, 64px));--angle:28deg;--delay:4s;top:46%}.setup-paws i:nth-child(5){left:calc(50% + var(--modal-half) + clamp(50px, 8vw, 120px));--angle:35deg;--delay:4.7s;top:38%}.setup-paws i:nth-child(6){left:calc(50% + var(--modal-half) + clamp(35px, 7vw, 100px));--angle:25deg;--delay:5.4s;top:30%}@keyframes setup-paw{0%,5%,38%,to{opacity:0}14%,24%{opacity:.16}}@media (width<=600px){.setup-paws i{width:18px;height:18px}.setup-paws i:first-child{--angle:65deg;top:22px;left:8%}.setup-paws i:nth-child(2){--angle:75deg;top:14px;left:19%}.setup-paws i:nth-child(3){--angle:65deg;top:22px;left:30%}.setup-paws i:nth-child(n+4){display:none}}@media (prefers-reduced-motion:reduce){#model-dialog[open] .setup-paws i{animation:none}.setup-paws i:first-child,.setup-paws i:nth-child(2){opacity:.1}}.setup-cat{top:calc(-1 * var(--cat-rise));right:var(--dialog-inset);width:var(--cat-size);height:calc(var(--cat-size) * .66);pointer-events:auto;cursor:pointer;touch-action:manipulation;-webkit-user-select:none;user-select:none;position:absolute;overflow:hidden}.setup-cat img,.setup-cat-tail,.setup-cat-eyelids{top:calc(var(--cat-size) * -.23);width:100%;height:auto;image-rendering:pixelated;opacity:0;display:block;position:absolute;left:0}.setup-cat img{clip-path:inset(0 22% 0 0)}.setup-cat-tail{aspect-ratio:1;background:var(--cat-sprite) 0 0 / 100% 100% no-repeat;clip-path:polygon(78% 40%,100% 40%,100% 82%,77% 82%,77% 77%,78% 77%);transform-origin:78% 80%}.setup-cat.is-ready img,.setup-cat.is-ready .setup-cat-tail{opacity:1}.setup-cat-eyelids{aspect-ratio:1}.setup-cat-eyelids:before,.setup-cat-eyelids:after{content:"";background:linear-gradient(#080709,#080709) 50% 80%/78% 14% no-repeat,#f6efdf;width:8.4%;height:8.7%;position:absolute;top:55.6%}.setup-cat-eyelids:before{left:28%}.setup-cat-eyelids:after{left:54.3%}#model-dialog[open] .setup-cat.is-ready .setup-cat-tail{animation:9s ease-in-out infinite setup-tail-swish;animation-play-state:var(--cat-play-state,running)}#model-dialog[open] .setup-cat.is-ready .setup-cat-eyelids{animation:7.4s step-end infinite setup-cat-blink;animation-play-state:var(--cat-play-state,running)}@keyframes setup-cat-blink{0%,45%,to{opacity:0}43%{opacity:1}}@keyframes setup-tail-swish{0%,24%,50%,to{transform:rotate(0)}33%{transform:rotate(-4deg)}41%{transform:rotate(2.5deg)}46%{transform:rotate(-.6deg)}}@media (prefers-reduced-motion:reduce){#model-dialog[open] .setup-cat.is-ready .setup-cat-tail,#model-dialog[open] .setup-cat.is-ready .setup-cat-eyelids{animation:none}}.setup-heading{flex-shrink:0;align-items:flex-start;gap:8px;display:flex}#model-cancel{width:32px;height:32px;min-height:32px;color:var(--muted);background:0 0;flex:none;place-items:center;padding:0;display:grid}#model-cancel:hover:not(:disabled){background:var(--control);color:var(--text)}.setup-body{min-height:0;overflow:auto}#model-dialog::backdrop{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#08080dbd}#model-title{letter-spacing:-.5px;flex:1;min-width:0;margin:0 0 8px;font-size:27px;font-weight:650;line-height:1.2}#model-description{color:var(--muted);margin:0;line-height:1.6}.setup-runtime{grid-template-columns:minmax(max-content,1fr) 1fr 1.2fr;gap:8px;margin:18px 0;display:grid}.setup-runtime>div{border-radius:var(--radius-small);background:var(--control);padding:10px}.setup-runtime dt{color:var(--accent);font-size:12px;font-weight:600}.setup-runtime dd{margin:5px 0 0;font-size:11px;line-height:1.5}.setup-model{align-items:center;gap:6px;display:flex}.model-org{border-radius:50%;flex:none;display:inline-flex}.model-org img{border-radius:inherit;width:18px;height:18px;display:block}.model-source{color:inherit;-webkit-text-decoration-color:var(--muted);text-decoration-color:var(--muted);text-underline-offset:3px;white-space:nowrap}.model-source:hover{color:var(--accent)}.setup-model a:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:3px}.setup-facts{border-radius:var(--radius-small);background:var(--panel);flex-direction:column;gap:5px;margin:18px 0;padding:12px;line-height:1.45;display:flex}.setup-facts strong{font-size:12px;font-weight:600}.setup-facts span,.setup-label{color:var(--muted);font-size:11px;line-height:1.5}.setup-label{margin:16px 0 6px}#model-preview{white-space:pre-wrap;overflow-wrap:anywhere;border-radius:var(--radius-small);background:var(--control);max-height:84px;padding:10px 12px;font-size:12px;line-height:1.5;overflow:auto}#model-error{border-radius:var(--radius-small);overflow-wrap:anywhere;background:#3c2828;padding:10px 12px;line-height:1.5}#model-open-tab{color:var(--accent);white-space:normal;text-decoration:none}.setup-credits{color:var(--muted);flex-wrap:wrap;align-items:center;gap:6px 10px;margin:18px 0;font-size:11px;line-height:1.6;display:flex}.setup-credits a{color:inherit;white-space:nowrap;align-items:center;gap:4px;text-decoration:none;display:inline-flex}.setup-credits a:hover{color:var(--text);text-underline-offset:3px;text-decoration:underline}.setup-credits a:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:3px}.setup-credits img,.setup-credits svg{object-fit:contain;flex:none;width:14px;height:14px}.setup-credits .credit-pi{padding:2px}.setup-actions{flex-shrink:0;padding-top:4px;display:flex}.setup-actions button{width:100%;min-height:44px;padding:10px 16px}#model-confirm{color:#18181e;background:#fff;font-size:14px;font-weight:600}#model-confirm:hover{background:#e8e8ed}@media (width<=420px){#model-dialog{--dialog-inset:16px;--cat-size:116px}#model-title{font-size:24px}.setup-runtime{grid-template-columns:1fr;gap:5px;margin:14px 0}.setup-runtime>div{align-items:baseline;gap:12px;padding:8px 10px;display:flex}.setup-runtime dt{flex:0 0 64px}.setup-runtime dd{margin:0}.setup-facts{margin:14px 0}.setup-credits{margin:12px 0}}@media (width>=851px) and (width<=1000px){header{grid-template-columns:auto minmax(0,1fr) auto}}@media (height<=620px){#model-dialog{--cat-size:72px}.setup-runtime,.setup-facts{margin:12px 0}}@media (width<=420px) and (height<=620px){.setup-runtime{grid-template-columns:minmax(0,1fr) max-content}.setup-runtime>div:first-child{grid-column:1/-1}.setup-runtime>div:not(:first-child){padding:6px 10px;display:block}.setup-runtime>div:not(:first-child) dd{margin-top:2px}}@media (width<=850px){:root{--header-height:calc(2 * var(--header-control-height) + 3 * var(--surface-inset));--header-inset:10px;--content-gutter:10px}header{grid-template-columns:auto minmax(0,1fr);grid-template-rows:repeat(2, var(--header-control-height));gap:var(--surface-inset);grid-template-areas:"brand runtime""model model"}.brand{grid-area:brand;justify-self:start}.runtime-meter{grid-area:runtime;justify-self:end}.model-panel{grid-area:model;margin:0}main{flex-direction:column;height:auto;display:flex}.column-resizer{display:none}.conversation{height:calc(100dvh - var(--header-height) - var(--header-inset));min-height:320px;padding:10px var(--content-gutter)}.workspace{min-height:520px;margin:0 var(--content-gutter) 10px}.file-area{grid-template-columns:115px minmax(0,1fr);min-height:280px}h1{font-size:20px}.badge,footer{font-size:9px}}@media (pointer:coarse){:root{--header-control-height:38px}button,.button,#files button{min-height:38px}.editor-heading{min-height:40px}.terminal summary{padding-top:11px;padding-bottom:11px}#command,#command-highlight,#pi-terminal .xterm-helper-textarea{font-size:16px}}.xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}
|
index.html
CHANGED
|
@@ -21,8 +21,8 @@
|
|
| 21 |
<meta name="twitter:image" content="https://huggingface.co/spaces/Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP/resolve/main/social-thumbnail-v3.png">
|
| 22 |
<meta name="twitter:image:alt" content="A coding agent running entirely in your browser, above the Pi terminal and its pixel cat mascot.">
|
| 23 |
<title>Pi · Coding agent in your browser</title>
|
| 24 |
-
<script type="module" crossorigin src="./assets/index-
|
| 25 |
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
| 26 |
</head>
|
| 27 |
<body>
|
| 28 |
<header><a class="brand" href="./" aria-label="Pi"><svg class="pi-logo" viewBox="165.29 165.29 469.43 469.43" width="18" height="18" aria-hidden="true" focusable="false"><path fill="currentColor" fill-rule="evenodd" d="M165.29 165.29H517.36V400H400V517.36H282.65V634.72H165.29ZM282.65 282.65V400H400V282.65Z"/><path fill="currentColor" d="M517.36 400H634.72V634.72H517.36Z"/></svg></a>
|
|
@@ -55,7 +55,7 @@
|
|
| 55 |
<div id="column-resizer" class="column-resizer" role="separator" tabindex="0" aria-label="Resize chat and workspace" aria-orientation="vertical" aria-controls="conversation-panel workspace-panel" aria-valuemin="0" aria-valuemax="100" aria-valuenow="55" title="Drag to resize · Arrow keys to adjust · Double-click or Enter to reset"></div>
|
| 56 |
<aside id="workspace-panel" class="workspace" aria-label="Workspace">
|
| 57 |
<div class="workspace-heading"><h2>Workspace</h2><div><button id="add-file" class="quiet">+ File</button><label class="button quiet" for="upload">Import</label><input id="upload" type="file" multiple hidden><button id="export" class="quiet">Export</button></div></div>
|
| 58 |
-
<div class="folder-controls"><button id="open-folder" type="button" class="quiet">
|
| 59 |
<div id="local-folder-bar" hidden>
|
| 60 |
<strong id="local-folder-name"></strong><span id="local-folder-hint" role="status"></span>
|
| 61 |
<div class="folder-actions"><button id="review-changes" type="button">Review & apply</button><button id="refresh-folder" type="button" class="quiet" title="Reload files from disk and start a fresh chat">Refresh</button><button id="disconnect-folder" type="button" class="quiet">Back to demo</button></div>
|
|
|
|
| 21 |
<meta name="twitter:image" content="https://huggingface.co/spaces/Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP/resolve/main/social-thumbnail-v3.png">
|
| 22 |
<meta name="twitter:image:alt" content="A coding agent running entirely in your browser, above the Pi terminal and its pixel cat mascot.">
|
| 23 |
<title>Pi · Coding agent in your browser</title>
|
| 24 |
+
<script type="module" crossorigin src="./assets/index-CdBuZzGZ.js"></script>
|
| 25 |
+
<link rel="stylesheet" crossorigin href="./assets/index-D2YMAIXb.css">
|
| 26 |
</head>
|
| 27 |
<body>
|
| 28 |
<header><a class="brand" href="./" aria-label="Pi"><svg class="pi-logo" viewBox="165.29 165.29 469.43 469.43" width="18" height="18" aria-hidden="true" focusable="false"><path fill="currentColor" fill-rule="evenodd" d="M165.29 165.29H517.36V400H400V517.36H282.65V634.72H165.29ZM282.65 282.65V400H400V282.65Z"/><path fill="currentColor" d="M517.36 400H634.72V634.72H517.36Z"/></svg></a>
|
|
|
|
| 55 |
<div id="column-resizer" class="column-resizer" role="separator" tabindex="0" aria-label="Resize chat and workspace" aria-orientation="vertical" aria-controls="conversation-panel workspace-panel" aria-valuemin="0" aria-valuemax="100" aria-valuenow="55" title="Drag to resize · Arrow keys to adjust · Double-click or Enter to reset"></div>
|
| 56 |
<aside id="workspace-panel" class="workspace" aria-label="Workspace">
|
| 57 |
<div class="workspace-heading"><h2>Workspace</h2><div><button id="add-file" class="quiet">+ File</button><label class="button quiet" for="upload">Import</label><input id="upload" type="file" multiple hidden><button id="export" class="quiet">Export</button></div></div>
|
| 58 |
+
<div class="folder-controls"><button id="open-folder" type="button" class="quiet"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg><span>Link a folder</span></button><button id="reconnect-folder" type="button" class="quiet" hidden>Reconnect folder</button></div>
|
| 59 |
<div id="local-folder-bar" hidden>
|
| 60 |
<strong id="local-folder-name"></strong><span id="local-folder-hint" role="status"></span>
|
| 61 |
<div class="folder-actions"><button id="review-changes" type="button">Review & apply</button><button id="refresh-folder" type="button" class="quiet" title="Reload files from disk and start a fresh chat">Refresh</button><button id="disconnect-folder" type="button" class="quiet">Back to demo</button></div>
|
validation/LOCAL-FOLDER.md
CHANGED
|
@@ -9,6 +9,6 @@ September 16, 2026. Duplicate only: `Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP`.
|
|
| 9 |
- The browser integration suite also passed against the deployed duplicate (`local-folder-live.json`). Existing editor and read-following regression suites passed on the production build.
|
| 10 |
- Actual MiniCPM5-2B WebGPU trial on the deployed duplicate: read app.js, change its exported greeting from Hello to Bonjour, leave other files unchanged, and verify. The model completed in **9.935 seconds** after a **5.499-second** cached model load. Exactly one file was staged, the real OPFS file remained unchanged before Apply, and the reviewed Apply wrote the expected contents. The actual model/tool messages are in `local-folder-agent-live.json`. This trial used an actual browser directory handle with a supplied picker; OS folder permissions and host-disk writes were tested separately above.
|
| 11 |
|
| 12 |
-
Native reproduction: open the standalone app in Chrome, select a small disposable project with
|
| 13 |
|
| 14 |
These checks validate the adapter and UI. They are not a general model reliability benchmark. Multi-file application has no OS transaction and can partially succeed; errors retain pending changes and report the count applied.
|
|
|
|
| 9 |
- The browser integration suite also passed against the deployed duplicate (`local-folder-live.json`). Existing editor and read-following regression suites passed on the production build.
|
| 10 |
- Actual MiniCPM5-2B WebGPU trial on the deployed duplicate: read app.js, change its exported greeting from Hello to Bonjour, leave other files unchanged, and verify. The model completed in **9.935 seconds** after a **5.499-second** cached model load. Exactly one file was staged, the real OPFS file remained unchanged before Apply, and the reviewed Apply wrote the expected contents. The actual model/tool messages are in `local-folder-agent-live.json`. This trial used an actual browser directory handle with a supplied picker; OS folder permissions and host-disk writes were tested separately above.
|
| 11 |
|
| 12 |
+
Native reproduction: open the standalone app in Chrome, select a small disposable project with Link a folder, allow read access, edit a file and Stage edit. Verify the original file is unchanged. Open Review & apply, inspect the diff, click Apply to folder, allow write access, and verify the file on disk. Back to demo restores the original demo; reload then Reconnect folder restores the local session. Change a previously read file externally before applying a staged edit to check conflict handling.
|
| 13 |
|
| 14 |
These checks validate the adapter and UI. They are not a general model reliability benchmark. Multi-file application has no OS transaction and can partially succeed; errors retain pending changes and report the count applied.
|