Mike0021 commited on
Commit
0d68e9e
·
verified ·
1 Parent(s): 3a32466

Rename local folder action to Link a folder with a link icon

Browse files
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 **Open local 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
 
 
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">Open local folder</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 &amp; 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 &amp; 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 Open local folder. Browsers cannot grant folder access inside this embedded Space.');
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 Open local 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(); },
 
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 Open local 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 Open local 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();
 
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-BVBC2sd0.js"></script>
25
- <link rel="stylesheet" crossorigin href="./assets/index-Uy7sEXBC.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,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">Open local folder</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 &amp; 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 &amp; 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 Open local 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.
 
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.