sliccy 2.3.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/slicc-editor-DmlPglrQ.js","assets/preload-helper-D4M6sveU.js","assets/dist-C43FKPek.js","assets/sql-wasm-yST8pDy6.js","assets/chunk-jRWAZmH_.js","assets/__vite-browser-external-BC516C8G.js","assets/pyodide-3PMN6X39.js","assets/es-C70AgaBB.js","assets/dist-DEO1hNOZ2.js","assets/provider-settings-BNHO2Tcv.js","assets/env-api-keys-7VVTY3n7.js","assets/simple-options-GPCv4BUJ.js","assets/json-parse-Dn8fsQhn.js","assets/openai-CQsomflW.js","assets/tray-follower-status-BlQSlF6m.js","assets/logger-B-No_qN_.js","assets/skills-CTCIxQqH.js","assets/fs-bsu2i7du.js","assets/path-utils-CNNVZ3-O.js","assets/constants-DdIXxN9e.js","assets/xterm-BmfB5bmM.css","assets/offscreen-client-BlWuVmPl.js","assets/cdp-CsCvDwW3.js","assets/cost-command-DBzah9S9.js","assets/bsh-watchdog-BXTi5bzs.js"])))=>i.map(i=>d[i]);
2
- import{o as e,r as t,t as n}from"./chunk-jRWAZmH_.js";import{t as r}from"./logger-B-No_qN_.js";import{t as i}from"./preload-helper-D4M6sveU.js";import{c as a,f as o,h as s,i as c,l,m as u,n as d,o as f,p,r as m,s as h,t as g,u as _,v,y}from"./tray-follower-status-BlQSlF6m.js";import{_ as b,a as x,b as S,c as C,d as w,f as T,g as E,i as D,m as O,n as k,o as A,p as ee,r as j,s as te,t as ne,u as re,v as M,y as N}from"./provider-settings-BNHO2Tcv.js";import{f as P,l as ie,p as ae,s as oe,u as se}from"./constants-DdIXxN9e.js";import{a as F,i as I,n as ce,o as le,r as ue}from"./fs-bsu2i7du.js";import{n as L,t as R}from"./path-utils-CNNVZ3-O.js";import{n as de,r as fe}from"./skills-CTCIxQqH.js";import{a as pe,c as z,d as B,f as me,i as he,l as V,n as ge,o as H,r as _e,s as U,u as W}from"./cdp-CsCvDwW3.js";import{_ as ve,a as ye,b as be,c as xe,d as G,f as Se,g as Ce,h as we,i as Te,l as Ee,m as De,n as Oe,o as ke,p as Ae,r as je,s as Me,t as Ne,u as Pe,v as Fe,x as Ie,y as Le}from"./db-CmHnV4DS.js";import{a as Re,i as ze,n as Be,o as Ve,r as He,s as Ue}from"./cost-command-DBzah9S9.js";import{t as We}from"./magick-wasm-DA8eLvGf.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();function Ge(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var Ke=Ge();function qe(e){Ke=e}var Je={exec:()=>null};function Ye(e,t=``){let n=typeof e==`string`?e:e.source,r={replace:(e,t)=>{let i=typeof t==`string`?t:t.source;return i=i.replace(Ze.caret,`$1`),n=n.replace(e,i),r},getRegex:()=>new RegExp(n,t)};return r}var Xe=(()=>{try{return!0}catch{return!1}})(),Ze={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:e=>RegExp(`^( {0,3}${e})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:e=>RegExp(`^ {0,${Math.min(3,e-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),hrRegex:e=>RegExp(`^ {0,${Math.min(3,e-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:e=>RegExp(`^ {0,${Math.min(3,e-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:e=>RegExp(`^ {0,${Math.min(3,e-1)}}#`),htmlBeginRegex:e=>RegExp(`^ {0,${Math.min(3,e-1)}}<(?:[a-z].*>|!--)`,`i`),blockquoteBeginRegex:e=>RegExp(`^ {0,${Math.min(3,e-1)}}>`)},Qe=/^(?:[ \t]*(?:\n|$))+/,$e=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,et=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,tt=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,nt=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,rt=/ {0,3}(?:[*+-]|\d{1,9}[.)])/,it=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,at=Ye(it).replace(/bull/g,rt).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,``).getRegex(),ot=Ye(it).replace(/bull/g,rt).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),st=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,ct=/^[^\n]+/,lt=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,ut=Ye(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace(`label`,lt).replace(`title`,/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),dt=Ye(/^(bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,rt).getRegex(),ft=`address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul`,pt=/<!--(?:-?>|[\s\S]*?(?:-->|$))/,mt=Ye(`^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))`,`i`).replace(`comment`,pt).replace(`tag`,ft).replace(`attribute`,/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),ht=Ye(st).replace(`hr`,tt).replace(`heading`,` {0,3}#{1,6}(?:\\s|$)`).replace(`|lheading`,``).replace(`|table`,``).replace(`blockquote`,` {0,3}>`).replace(`fences`," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace(`list`,` {0,3}(?:[*+-]|1[.)])[ \\t]`).replace(`html`,`</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)`).replace(`tag`,ft).getRegex(),gt={blockquote:Ye(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace(`paragraph`,ht).getRegex(),code:$e,def:ut,fences:et,heading:nt,hr:tt,html:mt,lheading:at,list:dt,newline:Qe,paragraph:ht,table:Je,text:ct},_t=Ye(`^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)`).replace(`hr`,tt).replace(`heading`,` {0,3}#{1,6}(?:\\s|$)`).replace(`blockquote`,` {0,3}>`).replace(`code`,`(?: {4}| {0,3} )[^\\n]`).replace(`fences`," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace(`list`,` {0,3}(?:[*+-]|1[.)])[ \\t]`).replace(`html`,`</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)`).replace(`tag`,ft).getRegex(),vt={...gt,lheading:ot,table:_t,paragraph:Ye(st).replace(`hr`,tt).replace(`heading`,` {0,3}#{1,6}(?:\\s|$)`).replace(`|lheading`,``).replace(`table`,_t).replace(`blockquote`,` {0,3}>`).replace(`fences`," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace(`list`,` {0,3}(?:[*+-]|1[.)])[ \\t]`).replace(`html`,`</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)`).replace(`tag`,ft).getRegex()},yt={...gt,html:Ye(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace(`comment`,pt).replace(/tag/g,`(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b`).getRegex(),def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:Je,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:Ye(st).replace(`hr`,tt).replace(`heading`,` *#{1,6} *[^
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/slicc-editor-DmlPglrQ.js","assets/preload-helper-D4M6sveU.js","assets/dist-C43FKPek.js","assets/sql-wasm-yST8pDy6.js","assets/chunk-jRWAZmH_.js","assets/__vite-browser-external-BC516C8G.js","assets/pyodide-3PMN6X39.js","assets/es-6oFxNVOv.js","assets/dist-DEO1hNOZ2.js","assets/provider-settings-BNHO2Tcv.js","assets/env-api-keys-7VVTY3n7.js","assets/simple-options-GPCv4BUJ.js","assets/json-parse-Dn8fsQhn.js","assets/openai-CQsomflW.js","assets/tray-follower-status-BlQSlF6m.js","assets/logger-B-No_qN_.js","assets/skills-DBBQyHko.js","assets/fs-CFxFn45v.js","assets/path-utils-CNNVZ3-O.js","assets/constants-DdIXxN9e.js","assets/xterm-BmfB5bmM.css","assets/offscreen-client-BlWuVmPl.js","assets/cdp-CsCvDwW3.js","assets/cost-command-DBzah9S9.js","assets/bsh-watchdog-BXTi5bzs.js"])))=>i.map(i=>d[i]);
2
+ import{o as e,r as t,t as n}from"./chunk-jRWAZmH_.js";import{t as r}from"./logger-B-No_qN_.js";import{t as i}from"./preload-helper-D4M6sveU.js";import{c as a,f as o,h as s,i as c,l,m as u,n as d,o as f,p,r as m,s as h,t as g,u as _,v,y}from"./tray-follower-status-BlQSlF6m.js";import{_ as b,a as x,b as S,c as C,d as w,f as T,g as E,i as D,m as O,n as k,o as A,p as ee,r as j,s as te,t as ne,u as re,v as M,y as N}from"./provider-settings-BNHO2Tcv.js";import{f as P,l as ie,p as ae,s as oe,u as se}from"./constants-DdIXxN9e.js";import{a as F,i as I,n as ce,o as le,r as ue}from"./fs-CFxFn45v.js";import{n as L,t as R}from"./path-utils-CNNVZ3-O.js";import{n as de,r as fe}from"./skills-DBBQyHko.js";import{a as pe,c as z,d as B,f as me,i as he,l as V,n as ge,o as H,r as _e,s as U,u as W}from"./cdp-CsCvDwW3.js";import{_ as ve,a as ye,b as be,c as xe,d as G,f as Se,g as Ce,h as we,i as Te,l as Ee,m as De,n as Oe,o as ke,p as Ae,r as je,s as Me,t as Ne,u as Pe,v as Fe,x as Ie,y as Le}from"./db-CmHnV4DS.js";import{a as Re,i as ze,n as Be,o as Ve,r as He,s as Ue}from"./cost-command-DBzah9S9.js";import{t as We}from"./magick-wasm-DA8eLvGf.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();function Ge(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var Ke=Ge();function qe(e){Ke=e}var Je={exec:()=>null};function Ye(e,t=``){let n=typeof e==`string`?e:e.source,r={replace:(e,t)=>{let i=typeof t==`string`?t:t.source;return i=i.replace(Ze.caret,`$1`),n=n.replace(e,i),r},getRegex:()=>new RegExp(n,t)};return r}var Xe=(()=>{try{return!0}catch{return!1}})(),Ze={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:e=>RegExp(`^( {0,3}${e})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:e=>RegExp(`^ {0,${Math.min(3,e-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),hrRegex:e=>RegExp(`^ {0,${Math.min(3,e-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:e=>RegExp(`^ {0,${Math.min(3,e-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:e=>RegExp(`^ {0,${Math.min(3,e-1)}}#`),htmlBeginRegex:e=>RegExp(`^ {0,${Math.min(3,e-1)}}<(?:[a-z].*>|!--)`,`i`),blockquoteBeginRegex:e=>RegExp(`^ {0,${Math.min(3,e-1)}}>`)},Qe=/^(?:[ \t]*(?:\n|$))+/,$e=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,et=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,tt=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,nt=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,rt=/ {0,3}(?:[*+-]|\d{1,9}[.)])/,it=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,at=Ye(it).replace(/bull/g,rt).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,``).getRegex(),ot=Ye(it).replace(/bull/g,rt).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),st=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,ct=/^[^\n]+/,lt=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,ut=Ye(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace(`label`,lt).replace(`title`,/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),dt=Ye(/^(bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,rt).getRegex(),ft=`address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul`,pt=/<!--(?:-?>|[\s\S]*?(?:-->|$))/,mt=Ye(`^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))`,`i`).replace(`comment`,pt).replace(`tag`,ft).replace(`attribute`,/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),ht=Ye(st).replace(`hr`,tt).replace(`heading`,` {0,3}#{1,6}(?:\\s|$)`).replace(`|lheading`,``).replace(`|table`,``).replace(`blockquote`,` {0,3}>`).replace(`fences`," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace(`list`,` {0,3}(?:[*+-]|1[.)])[ \\t]`).replace(`html`,`</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)`).replace(`tag`,ft).getRegex(),gt={blockquote:Ye(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace(`paragraph`,ht).getRegex(),code:$e,def:ut,fences:et,heading:nt,hr:tt,html:mt,lheading:at,list:dt,newline:Qe,paragraph:ht,table:Je,text:ct},_t=Ye(`^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)`).replace(`hr`,tt).replace(`heading`,` {0,3}#{1,6}(?:\\s|$)`).replace(`blockquote`,` {0,3}>`).replace(`code`,`(?: {4}| {0,3} )[^\\n]`).replace(`fences`," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace(`list`,` {0,3}(?:[*+-]|1[.)])[ \\t]`).replace(`html`,`</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)`).replace(`tag`,ft).getRegex(),vt={...gt,lheading:ot,table:_t,paragraph:Ye(st).replace(`hr`,tt).replace(`heading`,` {0,3}#{1,6}(?:\\s|$)`).replace(`|lheading`,``).replace(`table`,_t).replace(`blockquote`,` {0,3}>`).replace(`fences`," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace(`list`,` {0,3}(?:[*+-]|1[.)])[ \\t]`).replace(`html`,`</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)`).replace(`tag`,ft).getRegex()},yt={...gt,html:Ye(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace(`comment`,pt).replace(/tag/g,`(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b`).getRegex(),def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:Je,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:Ye(st).replace(`hr`,tt).replace(`heading`,` *#{1,6} *[^
3
3
  ]`).replace(`lheading`,at).replace(`|table`,``).replace(`blockquote`,` {0,3}>`).replace(`|fences`,``).replace(`|list`,``).replace(`|html`,``).replace(`|tag`,``).getRegex()},bt=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,xt=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,St=/^( {2,}|\\)\n(?!\s*$)/,Ct=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,wt=/[\p{P}\p{S}]/u,Tt=/[\s\p{P}\p{S}]/u,Et=/[^\s\p{P}\p{S}]/u,Dt=Ye(/^((?![*_])punctSpace)/,`u`).replace(/punctSpace/g,Tt).getRegex(),Ot=/(?!~)[\p{P}\p{S}]/u,kt=/(?!~)[\s\p{P}\p{S}]/u,At=/(?:[^\s\p{P}\p{S}]|~)/u,jt=Ye(/link|precode-code|html/,`g`).replace(`link`,/\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace(`precode-`,Xe?"(?<!`)()":"(^^|[^`])").replace(`code`,/(?<b>`+)[^`]+\k<b>(?!`)/).replace(`html`,/<(?! )[^<>]*?>/).getRegex(),Mt=/^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/,Nt=Ye(Mt,`u`).replace(/punct/g,wt).getRegex(),Pt=Ye(Mt,`u`).replace(/punct/g,Ot).getRegex(),Ft=`^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)`,It=Ye(Ft,`gu`).replace(/notPunctSpace/g,Et).replace(/punctSpace/g,Tt).replace(/punct/g,wt).getRegex(),Lt=Ye(Ft,`gu`).replace(/notPunctSpace/g,At).replace(/punctSpace/g,kt).replace(/punct/g,Ot).getRegex(),Rt=Ye(`^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)`,`gu`).replace(/notPunctSpace/g,Et).replace(/punctSpace/g,Tt).replace(/punct/g,wt).getRegex(),zt=Ye(/^~~?(?:((?!~)punct)|[^\s~])/,`u`).replace(/punct/g,wt).getRegex(),Bt=Ye(`^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)`,`gu`).replace(/notPunctSpace/g,Et).replace(/punctSpace/g,Tt).replace(/punct/g,wt).getRegex(),Vt=Ye(/\\(punct)/,`gu`).replace(/punct/g,wt).getRegex(),Ht=Ye(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace(`scheme`,/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace(`email`,/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),Ut=Ye(pt).replace(`(?:-->|$)`,`-->`).getRegex(),Wt=Ye(`^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>`).replace(`comment`,Ut).replace(`attribute`,/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),Gt=/(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/,Kt=Ye(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace(`label`,Gt).replace(`href`,/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace(`title`,/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),qt=Ye(/^!?\[(label)\]\[(ref)\]/).replace(`label`,Gt).replace(`ref`,lt).getRegex(),Jt=Ye(/^!?\[(ref)\](?:\[\])?/).replace(`ref`,lt).getRegex(),Yt=Ye(`reflink|nolink(?!\\()`,`g`).replace(`reflink`,qt).replace(`nolink`,Jt).getRegex(),Xt=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,Zt={_backpedal:Je,anyPunctuation:Vt,autolink:Ht,blockSkip:jt,br:St,code:xt,del:Je,delLDelim:Je,delRDelim:Je,emStrongLDelim:Nt,emStrongRDelimAst:It,emStrongRDelimUnd:Rt,escape:bt,link:Kt,nolink:Jt,punctuation:Dt,reflink:qt,reflinkSearch:Yt,tag:Wt,text:Ct,url:Je},Qt={...Zt,link:Ye(/^!?\[(label)\]\((.*?)\)/).replace(`label`,Gt).getRegex(),reflink:Ye(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace(`label`,Gt).getRegex()},$t={...Zt,emStrongRDelimAst:Lt,emStrongLDelim:Pt,delLDelim:zt,delRDelim:Bt,url:Ye(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace(`protocol`,Xt).replace(`email`,/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/,text:Ye(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace(`protocol`,Xt).getRegex()},en={...$t,br:Ye(St).replace(`{2,}`,`*`).getRegex(),text:Ye($t.text).replace(`\\b_`,`\\b_| {2,}\\n`).replace(/\{2,\}/g,`*`).getRegex()},tn={normal:gt,gfm:vt,pedantic:yt},nn={normal:Zt,gfm:$t,breaks:en,pedantic:Qt},rn={"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`},an=e=>rn[e];function on(e,t){if(t){if(Ze.escapeTest.test(e))return e.replace(Ze.escapeReplace,an)}else if(Ze.escapeTestNoEncode.test(e))return e.replace(Ze.escapeReplaceNoEncode,an);return e}function sn(e){try{e=encodeURI(e).replace(Ze.percentDecode,`%`)}catch{return null}return e}function cn(e,t){let n=e.replace(Ze.findPipe,(e,t,n)=>{let r=!1,i=t;for(;--i>=0&&n[i]===`\\`;)r=!r;return r?`|`:` |`}).split(Ze.splitPipe),r=0;if(n[0].trim()||n.shift(),n.length>0&&!n.at(-1)?.trim()&&n.pop(),t)if(n.length>t)n.splice(t);else for(;n.length<t;)n.push(``);for(;r<n.length;r++)n[r]=n[r].trim().replace(Ze.slashPipe,`|`);return n}function ln(e,t,n){let r=e.length;if(r===0)return``;let i=0;for(;i<r;){let a=e.charAt(r-i-1);if(a===t&&!n)i++;else if(a!==t&&n)i++;else break}return e.slice(0,r-i)}function un(e){let t=e.split(`
4
4
  `),n=t.length-1;for(;n>=0&&!t[n].trim();)n--;return t.length-n<=2?e:t.slice(0,n+1).join(`
5
5
  `)}function dn(e,t){if(e.indexOf(t[1])===-1)return-1;let n=0;for(let r=0;r<e.length;r++)if(e[r]===`\\`)r++;else if(e[r]===t[0])n++;else if(e[r]===t[1]&&(n--,n<0))return r;return n>0?-2:-1}function fn(e,t=0){let n=t,r=``;for(let t of e)if(t===` `){let e=4-n%4;r+=` `.repeat(e),n+=e}else r+=t,n++;return r}function pn(e,t,n,r,i){let a=t.href,o=t.title||null,s=e[1].replace(i.other.outputLinkReplace,`$1`);r.state.inLink=!0;let c={type:e[0].charAt(0)===`!`?`image`:`link`,raw:n,href:a,title:o,text:s,tokens:r.inlineTokens(s)};return r.state.inLink=!1,c}function mn(e,t,n){let r=e.match(n.other.indentCodeCompensation);if(r===null)return t;let i=r[1];return t.split(`
@@ -1081,9 +1081,9 @@ Commands:
1081
1081
  sessionstorage-clear Clear all sessionStorage
1082
1082
  help Show this help message
1083
1083
 
1084
- Aliases: ${cm.filter(t=>t!==e).join(`, `)}`}function Zm(e){let t=[],n={};for(let r of e)if(r.startsWith(`--`)&&r.includes(`=`)){let e=r.indexOf(`=`);n[r.slice(2,e)]=r.slice(e+1)}else r.startsWith(`--`)?n[r.slice(2)]=`true`:t.push(r);return{positional:t,flags:n}}function Z(e){let t=e.tab;return t?{targetId:t}:{error:`Error: --tab <targetId> is required. Run 'playwright-cli tab-list' to get tab IDs.
1085
- `}}function Qm(e,t,n){let r=Xm(e),i=t?fm(t,n):null;return Ve(e,async a=>{if(a.length===0||a[0]===`help`||a[0]===`--help`||a[0]===`-h`)return{stdout:r+`
1086
- `,stderr:``,exitCode:0};if(!t||!i)return{stdout:``,stderr:`${e}: browser APIs are unavailable in this environment\n`,exitCode:1};let o=a[0],s=a.slice(1),{positional:c,flags:l}=Zm(s),u;try{switch(o){case`teleport`:{if(l.list===`true`){X.info(`Listing available follower runtimes`);let e=rm?.();if(!e){u={stdout:``,stderr:`teleport: not connected to a tray
1084
+ Aliases: ${cm.filter(t=>t!==e).join(`, `)}`}var Zm=new Set([`tab`,`filename`,`max-width`,`runtime`,`timeout`,`filter`,`output`,`start`,`return`,`teleport-start`,`teleport-return`,`teleport-runtime`,`domain`,`path`,`expires`]);function Qm(e){let t=[],n={};for(let r=0;r<e.length;r++){let i=e[r];if(i.startsWith(`--`)&&i.includes(`=`)){let e=i.indexOf(`=`);n[i.slice(2,e)]=i.slice(e+1)}else if(i.startsWith(`--`)){let t=i.slice(2);if(Zm.has(t))if(r+1<e.length&&!e[r+1].startsWith(`--`))n[t]=e[++r];else throw Error(`--${t} requires a value`);else n[t]=`true`}else t.push(i)}return{positional:t,flags:n}}function Z(e){let t=e.tab;return t?{targetId:t}:{error:`Error: --tab <targetId> is required. Run 'playwright-cli tab-list' to get tab IDs.
1085
+ `}}function $m(e,t,n){let r=Xm(e),i=t?fm(t,n):null;return Ve(e,async a=>{if(a.length===0||a[0]===`help`||a[0]===`--help`||a[0]===`-h`)return{stdout:r+`
1086
+ `,stderr:``,exitCode:0};if(!t||!i)return{stdout:``,stderr:`${e}: browser APIs are unavailable in this environment\n`,exitCode:1};let o=a[0],s=a.slice(1),c,l;try{({positional:c,flags:l}=Qm(s))}catch(t){return{stdout:``,stderr:`${e} ${o}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}let u;try{switch(o){case`teleport`:{if(l.list===`true`){X.info(`Listing available follower runtimes`);let e=rm?.();if(!e){u={stdout:``,stderr:`teleport: not connected to a tray
1087
1087
  `,exitCode:1};break}let t=e();if(t.length===0){u={stdout:`No followers connected to the tray.
1088
1088
  `,stderr:``,exitCode:0};break}let n=[`Available runtimes for teleport:`];for(let e of t){let t=[e.runtimeId];if(e.floatType&&t.push(`[${e.floatType}]`),e.runtime&&t.push(`(${e.runtime})`),e.lastActivity){let n=Math.round((Date.now()-e.lastActivity)/1e3);t.push(`active ${n}s ago`)}n.push(` ${t.join(` `)}`)}u={stdout:n.join(`
1089
1089
  `)+`
@@ -1218,10 +1218,10 @@ Aliases: ${cm.filter(t=>t!==e).join(`, `)}`}function Zm(e){let t=[],n={};for(let
1218
1218
  `,exitCode:1};break}let e=Z(l);if(`error`in e){u={stdout:``,stderr:e.error,exitCode:1};break}await t.withTab(e.targetId,async()=>{await t.evaluate(`sessionStorage.setItem(${JSON.stringify(c[0])}, ${JSON.stringify(c.slice(1).join(` `))})`)}),u={stdout:`sessionStorage "${c[0]}" set\n`,stderr:``,exitCode:0};break}case`sessionstorage-delete`:{if(c.length===0){u={stdout:``,stderr:`sessionstorage-delete requires a key
1219
1219
  `,exitCode:1};break}let e=Z(l);if(`error`in e){u={stdout:``,stderr:e.error,exitCode:1};break}await t.withTab(e.targetId,async()=>{await t.evaluate(`sessionStorage.removeItem(${JSON.stringify(c[0])})`)}),u={stdout:`sessionStorage "${c[0]}" deleted\n`,stderr:``,exitCode:0};break}case`sessionstorage-clear`:{let e=Z(l);if(`error`in e){u={stdout:``,stderr:e.error,exitCode:1};break}await t.withTab(e.targetId,async()=>{await t.evaluate(`sessionStorage.clear()`)}),u={stdout:`sessionStorage cleared
1220
1220
  `,stderr:``,exitCode:0};break}case`record`:{let e=c[0]||`about:blank`,r=l.filter;await wm(t,i);let a=await t.createPage(e),o=t.getTransport(),s=(await o.send(`Target.attachToTarget`,{targetId:a,flatten:!0})).sessionId;i.harRecorder||=new W(o,n);let d=await i.harRecorder.startRecording(a,s,r);u={stdout:`Recording started (targetId: ${a}, recordingId: ${d}) at ${e}\nHAR saved to /recordings/${d}/\n`,stderr:``,exitCode:0};break}case`stop-recording`:{if(c.length===0){u={stdout:``,stderr:`stop-recording requires a recordingId
1221
- `,exitCode:1};break}let e=c[0];if(!i.harRecorder){u={stdout:``,stderr:`Recording not found: ${e}\n`,exitCode:1};break}u={stdout:`Recording stopped. HAR files saved to ${await i.harRecorder.stopRecording(e)}\n`,stderr:``,exitCode:0};break}default:u={stdout:``,stderr:`Unknown command: ${o}\nRun "playwright-cli help" for usage.\n`,exitCode:1};break}}catch(e){u={stdout:``,stderr:`Error: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}let d=l.tab??null,f=null;um.has(o)&&u.exitCode===0&&d&&(f=await ym(t,n,i,d));try{await bm(n,i,{command:o,args:s,result:u,snapshotPath:f,targetId:d})}catch{}return u})}var $m=new Map([[`File operations`,[`ls`,`cat`,`head`,`tail`,`wc`,`touch`,`mkdir`,`rm`,`cp`,`mv`,`ln`,`chmod`,`stat`,`readlink`]],[`Text processing`,[`grep`,`sed`,`awk`,`sort`,`uniq`,`cut`,`tr`,`tee`,`diff`]],[`Search`,[`find`,`rg`]],[`Navigation & paths`,[`pwd`,`basename`,`dirname`,`tree`,`du`,`cd`]],[`Archives`,[`zip`,`unzip`,`pdftk`,`pdf`]],[`Media`,[`convert`,`magick`]],[`Audio`,[`say`,`afplay`,`chime`]],[`Environment & shell`,[`echo`,`printf`,`env`,`printenv`,`export`,`alias`,`unalias`,`history`,`clear`,`true`,`false`,`bash`,`sh`,`commands`,`which`,`uname`,`man`,`host`,`oauth-token`,`secret`,`nuke`,`models`,`cost`]],[`Data processing`,[`xargs`,`jq`,`base64`,`date`]],[`Network`,[`curl`,`wget`,`html-to-markdown`]],[`Version control`,[`git`]],[`Languages`,[`node`,`python`,`python3`,`sqlite3`]],[`Skills`,[`skill`,`upskill`]],[`Browser & UI`,[`serve`,`open`,`imgcat`,...cm,`webhook`]],[`Filesystem`,[`mount`,`fswatch`]],[`Scoops & agents`,[`agent`]]]);function eh(e,t=[]){let n=[],r=new Set(e);n.push(`Available commands:
1222
- `);let i=[];for(let[e,t]of $m){let i=t.filter(e=>r.has(e));if(i.length>0){n.push(` ${e}:`),n.push(` ${i.join(`, `)}\n`);for(let e of i)r.delete(e)}}for(let e of r)i.push(e);return i.length>0&&(n.push(` Other:`),n.push(` ${i.sort().join(`, `)}\n`)),t.length>0&&(n.push(` User scripts (.jsh):`),n.push(` ${t.sort().join(`, `)}\n`)),n.push(`Use '<command> --help' for details on a specific command.`),n.join(`
1221
+ `,exitCode:1};break}let e=c[0];if(!i.harRecorder){u={stdout:``,stderr:`Recording not found: ${e}\n`,exitCode:1};break}u={stdout:`Recording stopped. HAR files saved to ${await i.harRecorder.stopRecording(e)}\n`,stderr:``,exitCode:0};break}default:u={stdout:``,stderr:`Unknown command: ${o}\nRun "playwright-cli help" for usage.\n`,exitCode:1};break}}catch(e){u={stdout:``,stderr:`Error: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}let d=l.tab??null,f=null;um.has(o)&&u.exitCode===0&&d&&(f=await ym(t,n,i,d));try{await bm(n,i,{command:o,args:s,result:u,snapshotPath:f,targetId:d})}catch{}return u})}var eh=new Map([[`File operations`,[`ls`,`cat`,`head`,`tail`,`wc`,`touch`,`mkdir`,`rm`,`cp`,`mv`,`ln`,`chmod`,`stat`,`readlink`]],[`Text processing`,[`grep`,`sed`,`awk`,`sort`,`uniq`,`cut`,`tr`,`tee`,`diff`]],[`Search`,[`find`,`rg`]],[`Navigation & paths`,[`pwd`,`basename`,`dirname`,`tree`,`du`,`cd`]],[`Archives`,[`zip`,`unzip`,`pdftk`,`pdf`]],[`Media`,[`convert`,`magick`]],[`Audio`,[`say`,`afplay`,`chime`]],[`Environment & shell`,[`echo`,`printf`,`env`,`printenv`,`export`,`alias`,`unalias`,`history`,`clear`,`true`,`false`,`bash`,`sh`,`commands`,`which`,`uname`,`man`,`host`,`oauth-token`,`secret`,`nuke`,`models`,`cost`]],[`Data processing`,[`xargs`,`jq`,`base64`,`date`]],[`Network`,[`curl`,`wget`,`html-to-markdown`]],[`Version control`,[`git`]],[`Languages`,[`node`,`python`,`python3`,`sqlite3`]],[`Skills`,[`skill`,`upskill`]],[`Browser & UI`,[`serve`,`open`,`imgcat`,...cm,`webhook`]],[`Filesystem`,[`mount`,`fswatch`]],[`Scoops & agents`,[`agent`]]]);function th(e,t=[]){let n=[],r=new Set(e);n.push(`Available commands:
1222
+ `);let i=[];for(let[e,t]of eh){let i=t.filter(e=>r.has(e));if(i.length>0){n.push(` ${e}:`),n.push(` ${i.join(`, `)}\n`);for(let e of i)r.delete(e)}}for(let e of r)i.push(e);return i.length>0&&(n.push(` Other:`),n.push(` ${i.sort().join(`, `)}\n`)),t.length>0&&(n.push(` User scripts (.jsh):`),n.push(` ${t.sort().join(`, `)}\n`)),n.push(`Use '<command> --help' for details on a specific command.`),n.join(`
1223
1223
  `)+`
1224
- `}function th(e={}){return Ve(`commands`,async(t,n)=>{if(t.includes(`--help`)||t.includes(`-h`))return{stdout:`commands - display available commands
1224
+ `}function nh(e={}){return Ve(`commands`,async(t,n)=>{if(t.includes(`--help`)||t.includes(`-h`))return{stdout:`commands - display available commands
1225
1225
 
1226
1226
  Usage: commands [command]
1227
1227
 
@@ -1232,7 +1232,7 @@ If a command name is provided, shows help for that command.
1232
1232
  Otherwise, lists all available commands.
1233
1233
 
1234
1234
  Note: This is an enhanced version of 'help' that shows all custom commands.
1235
- `,stderr:``,exitCode:0};if(t.length>0&&n.exec){let e=t[0];return n.exec(`${e} --help`,{cwd:n.cwd})}return{stdout:eh(n.getRegisteredCommands?.()??[],await e.getJshCommands?.()??[]),stderr:``,exitCode:0}})}function nh(e){let t=e.toLowerCase();return t.endsWith(`.jpg`)||t.endsWith(`.jpeg`)?`JPEG`:t.endsWith(`.png`)?`PNG`:t.endsWith(`.gif`)?`GIF`:t.endsWith(`.webp`)?`WEBP`:t.endsWith(`.bmp`)?`BMP`:t.endsWith(`.tiff`)||t.endsWith(`.tif`)?`TIFF`:t.endsWith(`.avif`)?`AVIF`:`PNG`}function rh(){return{stdout:`usage: convert [input] [operations...] [output]
1235
+ `,stderr:``,exitCode:0};if(t.length>0&&n.exec){let e=t[0];return n.exec(`${e} --help`,{cwd:n.cwd})}return{stdout:th(n.getRegisteredCommands?.()??[],await e.getJshCommands?.()??[]),stderr:``,exitCode:0}})}function rh(e){let t=e.toLowerCase();return t.endsWith(`.jpg`)||t.endsWith(`.jpeg`)?`JPEG`:t.endsWith(`.png`)?`PNG`:t.endsWith(`.gif`)?`GIF`:t.endsWith(`.webp`)?`WEBP`:t.endsWith(`.bmp`)?`BMP`:t.endsWith(`.tiff`)||t.endsWith(`.tif`)?`TIFF`:t.endsWith(`.avif`)?`AVIF`:`PNG`}function ih(){return{stdout:`usage: convert [input] [operations...] [output]
1236
1236
 
1237
1237
  Operations:
1238
1238
  -resize WxH resize to width x height
@@ -1247,7 +1247,7 @@ Examples:
1247
1247
  convert photo.png -resize 50% smaller.png
1248
1248
  convert image.jpg -rotate 90 -quality 85 rotated.jpg
1249
1249
  convert input.png -crop 100x100+50+50 cropped.png
1250
- `,stderr:``,exitCode:0}}function ih(e=`convert`){return Ve(e,async(t,n)=>{if(t.length===0||t.includes(`--help`)||t.includes(`-h`))return rh();let r=[],i=[],a=0;for(;a<t.length;){let n=t[a];if(n===`-resize`){if(a+1>=t.length||t[a+1].startsWith(`-`))return{stdout:``,stderr:`${e}: missing argument for -resize\n`,exitCode:1};i.push({type:`resize`,value:t[a+1]}),a+=2}else if(n===`-rotate`){if(a+1>=t.length||t[a+1].startsWith(`-`))return{stdout:``,stderr:`${e}: missing argument for -rotate\n`,exitCode:1};i.push({type:`rotate`,value:t[a+1]}),a+=2}else if(n===`-crop`){if(a+1>=t.length||t[a+1].startsWith(`-`))return{stdout:``,stderr:`${e}: missing argument for -crop\n`,exitCode:1};i.push({type:`crop`,value:t[a+1]}),a+=2}else if(n===`-quality`){if(a+1>=t.length||t[a+1].startsWith(`-`))return{stdout:``,stderr:`${e}: missing argument for -quality\n`,exitCode:1};i.push({type:`quality`,value:t[a+1]}),a+=2}else if(n.startsWith(`-`))return{stdout:``,stderr:`${e}: unsupported option ${n}\n`,exitCode:1};else r.push(n),a++}if(r.length!==2)return{stdout:``,stderr:`${e}: expected exactly one input file and one output file\n`,exitCode:1};let o=r[0],s=r[1];try{let e=n.fs.resolvePath(n.cwd,o),t=await n.fs.readFileBuffer(e),r=await We(),a=null;if(await r.ImageMagick.read(t,async e=>{for(let t of i)switch(t.type){case`resize`:{let n=t.value.match(/^(\d+)%$/);if(n){let t=parseInt(n[1],10),r=Math.round(e.width*t/100),i=Math.round(e.height*t/100);e.resize(r,i)}else{let n=t.value.endsWith(`!`),i=(n?t.value.slice(0,-1):t.value).split(`x`);if(i.length===2){let t=parseInt(i[0],10),a=parseInt(i[1],10);if(n){let n=new r.MagickGeometry(t,a);n.ignoreAspectRatio=!0,e.resize(n)}else e.resize(t,a)}else throw Error(`Invalid resize format: ${t.value}`)}break}case`rotate`:{let n=parseFloat(t.value);if(isNaN(n))throw Error(`Invalid rotation degrees: ${t.value}`);e.rotate(n);break}case`crop`:{if(!t.value.match(/^(\d+)x(\d+)\+(\d+)\+(\d+)$/))throw Error(`Invalid crop format: ${t.value} (expected WxH+X+Y)`);let n=new r.MagickGeometry(t.value);e.crop(n);break}case`quality`:{let n=parseInt(t.value,10);if(isNaN(n)||n<0||n>100)throw Error(`Invalid quality: ${t.value} (must be 0-100)`);e.quality=n;break}}let t=nh(s);e.write(t,e=>{a=e})}),!a)throw Error(`Failed to generate output image`);let c=n.fs.resolvePath(n.cwd,s);return await n.fs.writeFile(c,a),{stdout:``,stderr:``,exitCode:0}}catch(t){return{stdout:``,stderr:`${e}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}})}var ah=r(`tray-leader`),oh=`leader-tray-session`,sh=3e4,ch=1e4,lh={state:`inactive`,session:null,error:null};function uh(){return{...lh,session:lh.session?{...lh.session}:null}}function dh(e){lh={...e,session:e.session?{...e.session}:null}}var fh=class{constructor(e=oh){this.key=e}async load(){return ph(await Ae(this.key))}async save(e){await Ie(this.key,JSON.stringify(e))}async clear(){await Ie(this.key,``)}};function ph(e){if(!e)return null;try{let t=JSON.parse(e);return typeof t.workerBaseUrl!=`string`||typeof t.trayId!=`string`||typeof t.createdAt!=`string`||typeof t.controllerId!=`string`||typeof t.controllerUrl!=`string`||typeof t.joinUrl!=`string`||typeof t.webhookUrl!=`string`||typeof t.runtime!=`string`?null:{workerBaseUrl:t.workerBaseUrl,trayId:t.trayId,createdAt:t.createdAt,controllerId:t.controllerId,controllerUrl:t.controllerUrl,joinUrl:t.joinUrl,webhookUrl:t.webhookUrl,leaderKey:typeof t.leaderKey==`string`?t.leaderKey:void 0,leaderWebSocketUrl:typeof t.leaderWebSocketUrl==`string`?t.leaderWebSocketUrl:null,runtime:t.runtime}}catch{return null}}var mh=class{store;fetchImpl;webSocketFactory;pingIntervalMs;connectTimeoutMs;socket=null;pingTimer=null;currentSession=null;constructor(e){this.options=e,this.store=e.store??new fh,this.fetchImpl=e.fetchImpl??vh(),this.webSocketFactory=e.webSocketFactory??(e=>new WebSocket(e)),this.pingIntervalMs=e.pingIntervalMs??sh,this.connectTimeoutMs=e.connectTimeoutMs??ch}async start(){if(this.currentSession&&this.socket)return dh({state:`leader`,session:this.currentSession,error:null}),this.currentSession;dh({state:`connecting`,session:null,error:null}),this.currentSession=null;try{let e=await this.store.load(),t=e?.workerBaseUrl===this.options.workerBaseUrl?e:null,n=await this.attachWithRecovery(t);this.currentSession=n;let r=await this.openLeaderSocket(n.leaderWebSocketUrl);return this.socket=r,this.startPingLoop(r),dh({state:`leader`,session:n,error:null}),ah.info(`Leader joined tray`,{trayId:n.trayId,controllerId:n.controllerId,runtime:n.runtime}),n}catch(e){throw dh({state:`error`,session:this.currentSession,error:e instanceof Error?e.message:String(e)}),e}}stop(){if(this.pingTimer&&=(clearInterval(this.pingTimer),null),this.socket){try{this.socket.close()}catch{}this.socket=null}this.currentSession=null,dh({state:`inactive`,session:null,error:null})}async clearSession(){await this.store.clear()}sendControlMessage(e){if(!this.socket)throw Error(`Tray leader WebSocket is not connected`);this.socket.send(JSON.stringify(e))}async attachWithRecovery(e){try{return await this.claimLeaderSession(e)}catch(t){if(!e||!gh(t))throw t;return ah.warn(`Stored tray session is stale, creating a fresh tray`,{trayId:e.trayId,error:t instanceof Error?t.message:String(t)}),await this.store.clear(),this.claimLeaderSession(null)}}async claimLeaderSession(e){let t=e??await this.createTraySession(),n=await this.fetchJson(t.controllerUrl,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({controllerId:t.controllerId,leaderKey:t.leaderKey,runtime:this.options.runtime})});if(n.role!==`leader`||!n.leaderKey||!n.websocket?.url)throw Error(`Tray attach did not return leader access for controller ${n.controllerId}`);let r={...t,trayId:n.trayId,controllerId:n.controllerId,leaderKey:n.leaderKey,leaderWebSocketUrl:n.websocket.url,runtime:this.options.runtime};return await this.store.save(r),r}async createTraySession(){let e=await this.fetchJson(h(this.options.workerBaseUrl,`tray`),{method:`POST`});return{workerBaseUrl:this.options.workerBaseUrl,trayId:e.trayId,createdAt:e.createdAt,controllerId:crypto.randomUUID(),controllerUrl:e.capabilities.controller.url,joinUrl:e.capabilities.join.url,webhookUrl:e.capabilities.webhook.url,runtime:this.options.runtime}}async openLeaderSocket(e){return await new Promise((t,n)=>{let r=this.webSocketFactory(e),i=!1,a=setTimeout(()=>{o(`Tray leader WebSocket timed out after ${this.connectTimeoutMs}ms waiting for leader.connected`);try{r.close(1e3,`leader.connected timeout`)}catch{}},this.connectTimeoutMs),o=e=>{i||(i=!0,clearTimeout(a),n(Error(e)))};r.addEventListener(`message`,e=>{let n=_h(e.data);if(n){if(n.type===`leader.connected`){i||(i=!0,clearTimeout(a),t(r));return}if(n.type===`pong`){ah.debug(`Tray leader heartbeat acknowledged`,{trayId:this.currentSession?.trayId});return}this.options.onControlMessage?.(n)}}),r.addEventListener(`close`,()=>o(`Tray leader WebSocket closed before leader.connected`)),r.addEventListener(`error`,()=>o(`Tray leader WebSocket failed before leader.connected`))})}startPingLoop(e){this.pingTimer&&clearInterval(this.pingTimer);let t=()=>{try{e.send(JSON.stringify({type:`ping`}))}catch{this.stop()}};t(),this.pingTimer=setInterval(t,this.pingIntervalMs),e.addEventListener(`close`,()=>this.stop()),e.addEventListener(`error`,()=>this.stop())}async fetchJson(e,t){let n=await this.fetchImpl(e,t);if(!n.ok)throw await hh.fromResponse(n);return await n.json()}},hh=class e extends Error{constructor(e,t,n){super(n),this.status=e,this.code=t,this.name=`LeaderTrayHttpError`}static async fromResponse(t){try{let n=await t.json();return new e(t.status,n.code??null,n.error??`Tray request failed (${t.status})`)}catch{return new e(t.status,null,`Tray request failed (${t.status})`)}}};function gh(e){return e instanceof hh&&[403,404,410].includes(e.status)}function _h(e){if(typeof e!=`string`)return null;try{return JSON.parse(e)}catch{return null}}function vh(e=fetch){return typeof chrome<`u`&&chrome?.runtime?.id?e:async(t,n={})=>{let r=typeof t==`string`?t:t.toString();try{if(new URL(r).origin===window.location.origin)return e(r,{...n,cache:`no-store`})}catch{}let i=new Headers(n.headers);i.set(`X-Target-URL`,r);let a=await e(`/api/fetch-proxy`,{...n,headers:i,cache:`no-store`});if(a.status===400||a.status===502){let e=`Proxy error ${a.status}`;try{e=(await a.json()).error??e}catch{}throw Error(e)}return a}}var yh=null;function bh(e){yh=e}function xh(){return yh?.()??[]}var Sh=null;function Ch(e){Sh=e}function wh(){return Sh??void 0}function Th(){return{stdout:`host - display or manage the current tray host status
1250
+ `,stderr:``,exitCode:0}}function ah(e=`convert`){return Ve(e,async(t,n)=>{if(t.length===0||t.includes(`--help`)||t.includes(`-h`))return ih();let r=[],i=[],a=0;for(;a<t.length;){let n=t[a];if(n===`-resize`){if(a+1>=t.length||t[a+1].startsWith(`-`))return{stdout:``,stderr:`${e}: missing argument for -resize\n`,exitCode:1};i.push({type:`resize`,value:t[a+1]}),a+=2}else if(n===`-rotate`){if(a+1>=t.length||t[a+1].startsWith(`-`))return{stdout:``,stderr:`${e}: missing argument for -rotate\n`,exitCode:1};i.push({type:`rotate`,value:t[a+1]}),a+=2}else if(n===`-crop`){if(a+1>=t.length||t[a+1].startsWith(`-`))return{stdout:``,stderr:`${e}: missing argument for -crop\n`,exitCode:1};i.push({type:`crop`,value:t[a+1]}),a+=2}else if(n===`-quality`){if(a+1>=t.length||t[a+1].startsWith(`-`))return{stdout:``,stderr:`${e}: missing argument for -quality\n`,exitCode:1};i.push({type:`quality`,value:t[a+1]}),a+=2}else if(n.startsWith(`-`))return{stdout:``,stderr:`${e}: unsupported option ${n}\n`,exitCode:1};else r.push(n),a++}if(r.length!==2)return{stdout:``,stderr:`${e}: expected exactly one input file and one output file\n`,exitCode:1};let o=r[0],s=r[1];try{let e=n.fs.resolvePath(n.cwd,o),t=await n.fs.readFileBuffer(e),r=await We(),a=null;if(await r.ImageMagick.read(t,async e=>{for(let t of i)switch(t.type){case`resize`:{let n=t.value.match(/^(\d+)%$/);if(n){let t=parseInt(n[1],10),r=Math.round(e.width*t/100),i=Math.round(e.height*t/100);e.resize(r,i)}else{let n=t.value.endsWith(`!`),i=(n?t.value.slice(0,-1):t.value).split(`x`);if(i.length===2){let t=parseInt(i[0],10),a=parseInt(i[1],10);if(n){let n=new r.MagickGeometry(t,a);n.ignoreAspectRatio=!0,e.resize(n)}else e.resize(t,a)}else throw Error(`Invalid resize format: ${t.value}`)}break}case`rotate`:{let n=parseFloat(t.value);if(isNaN(n))throw Error(`Invalid rotation degrees: ${t.value}`);e.rotate(n);break}case`crop`:{if(!t.value.match(/^(\d+)x(\d+)\+(\d+)\+(\d+)$/))throw Error(`Invalid crop format: ${t.value} (expected WxH+X+Y)`);let n=new r.MagickGeometry(t.value);e.crop(n);break}case`quality`:{let n=parseInt(t.value,10);if(isNaN(n)||n<0||n>100)throw Error(`Invalid quality: ${t.value} (must be 0-100)`);e.quality=n;break}}let t=rh(s);e.write(t,e=>{a=e})}),!a)throw Error(`Failed to generate output image`);let c=n.fs.resolvePath(n.cwd,s);return await n.fs.writeFile(c,a),{stdout:``,stderr:``,exitCode:0}}catch(t){return{stdout:``,stderr:`${e}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}})}var oh=r(`tray-leader`),sh=`leader-tray-session`,ch=3e4,lh=1e4,uh={state:`inactive`,session:null,error:null};function dh(){return{...uh,session:uh.session?{...uh.session}:null}}function fh(e){uh={...e,session:e.session?{...e.session}:null}}var ph=class{constructor(e=sh){this.key=e}async load(){return mh(await Ae(this.key))}async save(e){await Ie(this.key,JSON.stringify(e))}async clear(){await Ie(this.key,``)}};function mh(e){if(!e)return null;try{let t=JSON.parse(e);return typeof t.workerBaseUrl!=`string`||typeof t.trayId!=`string`||typeof t.createdAt!=`string`||typeof t.controllerId!=`string`||typeof t.controllerUrl!=`string`||typeof t.joinUrl!=`string`||typeof t.webhookUrl!=`string`||typeof t.runtime!=`string`?null:{workerBaseUrl:t.workerBaseUrl,trayId:t.trayId,createdAt:t.createdAt,controllerId:t.controllerId,controllerUrl:t.controllerUrl,joinUrl:t.joinUrl,webhookUrl:t.webhookUrl,leaderKey:typeof t.leaderKey==`string`?t.leaderKey:void 0,leaderWebSocketUrl:typeof t.leaderWebSocketUrl==`string`?t.leaderWebSocketUrl:null,runtime:t.runtime}}catch{return null}}var hh=class{store;fetchImpl;webSocketFactory;pingIntervalMs;connectTimeoutMs;socket=null;pingTimer=null;currentSession=null;constructor(e){this.options=e,this.store=e.store??new ph,this.fetchImpl=e.fetchImpl??yh(),this.webSocketFactory=e.webSocketFactory??(e=>new WebSocket(e)),this.pingIntervalMs=e.pingIntervalMs??ch,this.connectTimeoutMs=e.connectTimeoutMs??lh}async start(){if(this.currentSession&&this.socket)return fh({state:`leader`,session:this.currentSession,error:null}),this.currentSession;fh({state:`connecting`,session:null,error:null}),this.currentSession=null;try{let e=await this.store.load(),t=e?.workerBaseUrl===this.options.workerBaseUrl?e:null,n=await this.attachWithRecovery(t);this.currentSession=n;let r=await this.openLeaderSocket(n.leaderWebSocketUrl);return this.socket=r,this.startPingLoop(r),fh({state:`leader`,session:n,error:null}),oh.info(`Leader joined tray`,{trayId:n.trayId,controllerId:n.controllerId,runtime:n.runtime}),n}catch(e){throw fh({state:`error`,session:this.currentSession,error:e instanceof Error?e.message:String(e)}),e}}stop(){if(this.pingTimer&&=(clearInterval(this.pingTimer),null),this.socket){try{this.socket.close()}catch{}this.socket=null}this.currentSession=null,fh({state:`inactive`,session:null,error:null})}async clearSession(){await this.store.clear()}sendControlMessage(e){if(!this.socket)throw Error(`Tray leader WebSocket is not connected`);this.socket.send(JSON.stringify(e))}async attachWithRecovery(e){try{return await this.claimLeaderSession(e)}catch(t){if(!e||!_h(t))throw t;return oh.warn(`Stored tray session is stale, creating a fresh tray`,{trayId:e.trayId,error:t instanceof Error?t.message:String(t)}),await this.store.clear(),this.claimLeaderSession(null)}}async claimLeaderSession(e){let t=e??await this.createTraySession(),n=await this.fetchJson(t.controllerUrl,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({controllerId:t.controllerId,leaderKey:t.leaderKey,runtime:this.options.runtime})});if(n.role!==`leader`||!n.leaderKey||!n.websocket?.url)throw Error(`Tray attach did not return leader access for controller ${n.controllerId}`);let r={...t,trayId:n.trayId,controllerId:n.controllerId,leaderKey:n.leaderKey,leaderWebSocketUrl:n.websocket.url,runtime:this.options.runtime};return await this.store.save(r),r}async createTraySession(){let e=await this.fetchJson(h(this.options.workerBaseUrl,`tray`),{method:`POST`});return{workerBaseUrl:this.options.workerBaseUrl,trayId:e.trayId,createdAt:e.createdAt,controllerId:crypto.randomUUID(),controllerUrl:e.capabilities.controller.url,joinUrl:e.capabilities.join.url,webhookUrl:e.capabilities.webhook.url,runtime:this.options.runtime}}async openLeaderSocket(e){return await new Promise((t,n)=>{let r=this.webSocketFactory(e),i=!1,a=setTimeout(()=>{o(`Tray leader WebSocket timed out after ${this.connectTimeoutMs}ms waiting for leader.connected`);try{r.close(1e3,`leader.connected timeout`)}catch{}},this.connectTimeoutMs),o=e=>{i||(i=!0,clearTimeout(a),n(Error(e)))};r.addEventListener(`message`,e=>{let n=vh(e.data);if(n){if(n.type===`leader.connected`){i||(i=!0,clearTimeout(a),t(r));return}if(n.type===`pong`){oh.debug(`Tray leader heartbeat acknowledged`,{trayId:this.currentSession?.trayId});return}this.options.onControlMessage?.(n)}}),r.addEventListener(`close`,()=>o(`Tray leader WebSocket closed before leader.connected`)),r.addEventListener(`error`,()=>o(`Tray leader WebSocket failed before leader.connected`))})}startPingLoop(e){this.pingTimer&&clearInterval(this.pingTimer);let t=()=>{try{e.send(JSON.stringify({type:`ping`}))}catch{this.stop()}};t(),this.pingTimer=setInterval(t,this.pingIntervalMs),e.addEventListener(`close`,()=>this.stop()),e.addEventListener(`error`,()=>this.stop())}async fetchJson(e,t){let n=await this.fetchImpl(e,t);if(!n.ok)throw await gh.fromResponse(n);return await n.json()}},gh=class e extends Error{constructor(e,t,n){super(n),this.status=e,this.code=t,this.name=`LeaderTrayHttpError`}static async fromResponse(t){try{let n=await t.json();return new e(t.status,n.code??null,n.error??`Tray request failed (${t.status})`)}catch{return new e(t.status,null,`Tray request failed (${t.status})`)}}};function _h(e){return e instanceof gh&&[403,404,410].includes(e.status)}function vh(e){if(typeof e!=`string`)return null;try{return JSON.parse(e)}catch{return null}}function yh(e=fetch){return typeof chrome<`u`&&chrome?.runtime?.id?e:async(t,n={})=>{let r=typeof t==`string`?t:t.toString();try{if(new URL(r).origin===window.location.origin)return e(r,{...n,cache:`no-store`})}catch{}let i=new Headers(n.headers);i.set(`X-Target-URL`,r);let a=await e(`/api/fetch-proxy`,{...n,headers:i,cache:`no-store`});if(a.status===400||a.status===502){let e=`Proxy error ${a.status}`;try{e=(await a.json()).error??e}catch{}throw Error(e)}return a}}var bh=null;function xh(e){bh=e}function Sh(){return bh?.()??[]}var Ch=null;function wh(e){Ch=e}function Th(){return Ch??void 0}function Eh(){return{stdout:`host - display or manage the current tray host status
1251
1251
 
1252
1252
  Usage: host [reset]
1253
1253
 
@@ -1255,22 +1255,22 @@ Shows the current tray state (leader or follower) and, when available, the join
1255
1255
 
1256
1256
  Subcommands:
1257
1257
  reset Disconnect all followers and create a fresh tray session with a new join URL
1258
- `,stderr:``,exitCode:0}}function Eh(e){if(e<60)return`${e}s ago`;let t=Math.floor(e/60);if(t<60)return`${t}m ago`;let n=Math.floor(t/60),r=t%60;return r===0?`${n}h ago`:`${n}h ${r}m ago`}function Dh(e,t){let n=[`status: ${e.state}`];if(e.session?n.push(`join_url: ${e.session.joinUrl}`):n.push(`join_url: unavailable`),e.error&&n.push(`error: ${e.error}`),t.length>0){n.push(`followers:`);for(let e of t){let t=[e.runtimeId];if(e.runtime&&t.push(`(${e.runtime})`),e.connectedAt){let n=Math.round((Date.now()-new Date(e.connectedAt).getTime())/1e3);t.push(`connected ${Eh(n)}`)}n.push(` - ${t.join(` `)}`)}}return`${n.join(`
1259
- `)}\n`}function Oh(e){let t=[`status: follower (${e.state})`];if(e.joinUrl&&t.push(`join_url: ${e.joinUrl}`),e.state===`connecting`){if(e.connectingSince!=null){let n=Math.round((Date.now()-e.connectingSince)/1e3);t.push(`connecting_for: ${Eh(n).replace(` ago`,``)}`)}e.attachAttempts>0&&t.push(`attach_attempts: ${e.attachAttempts}`),e.lastAttachCode&&t.push(`last_code: ${e.lastAttachCode}`)}if(e.state===`connected`&&e.lastPingTime!=null){let n=Math.round((Date.now()-e.lastPingTime)/1e3);t.push(`last_ping: ${n}s ago`)}return e.state===`reconnecting`&&e.reconnectAttempts>0&&t.push(`reconnect_attempts: ${e.reconnectAttempts}`),e.lastError&&t.push(`last_error: ${e.lastError}`),e.error&&t.push(`error: ${e.error}`),`${t.join(`
1260
- `)}\n`}function kh(e={}){let t=e.getStatus??uh,n=e.getFollowerStatus??g,r=e.getFollowers??xh;return Ve(`host`,async i=>{if(i.includes(`--help`)||i.includes(`-h`))return Th();if(i[0]===`reset`)return Ah(n,t,e.resetTray??wh());if(i.length>0)return{stdout:``,stderr:`host: unsupported arguments
1261
- `,exitCode:1};let a=n();return a.state===`inactive`?{stdout:Dh(t(),r()),stderr:``,exitCode:0}:{stdout:Oh(a),stderr:``,exitCode:0}})}async function Ah(e,t,n){if(e().state!==`inactive`)return{stdout:``,stderr:`host reset: only the leader can reset the tray session
1258
+ `,stderr:``,exitCode:0}}function Dh(e){if(e<60)return`${e}s ago`;let t=Math.floor(e/60);if(t<60)return`${t}m ago`;let n=Math.floor(t/60),r=t%60;return r===0?`${n}h ago`:`${n}h ${r}m ago`}function Oh(e,t){let n=[`status: ${e.state}`];if(e.session?n.push(`join_url: ${e.session.joinUrl}`):n.push(`join_url: unavailable`),e.error&&n.push(`error: ${e.error}`),t.length>0){n.push(`followers:`);for(let e of t){let t=[e.runtimeId];if(e.runtime&&t.push(`(${e.runtime})`),e.connectedAt){let n=Math.round((Date.now()-new Date(e.connectedAt).getTime())/1e3);t.push(`connected ${Dh(n)}`)}n.push(` - ${t.join(` `)}`)}}return`${n.join(`
1259
+ `)}\n`}function kh(e){let t=[`status: follower (${e.state})`];if(e.joinUrl&&t.push(`join_url: ${e.joinUrl}`),e.state===`connecting`){if(e.connectingSince!=null){let n=Math.round((Date.now()-e.connectingSince)/1e3);t.push(`connecting_for: ${Dh(n).replace(` ago`,``)}`)}e.attachAttempts>0&&t.push(`attach_attempts: ${e.attachAttempts}`),e.lastAttachCode&&t.push(`last_code: ${e.lastAttachCode}`)}if(e.state===`connected`&&e.lastPingTime!=null){let n=Math.round((Date.now()-e.lastPingTime)/1e3);t.push(`last_ping: ${n}s ago`)}return e.state===`reconnecting`&&e.reconnectAttempts>0&&t.push(`reconnect_attempts: ${e.reconnectAttempts}`),e.lastError&&t.push(`last_error: ${e.lastError}`),e.error&&t.push(`error: ${e.error}`),`${t.join(`
1260
+ `)}\n`}function Ah(e={}){let t=e.getStatus??dh,n=e.getFollowerStatus??g,r=e.getFollowers??Sh;return Ve(`host`,async i=>{if(i.includes(`--help`)||i.includes(`-h`))return Eh();if(i[0]===`reset`)return jh(n,t,e.resetTray??Th());if(i.length>0)return{stdout:``,stderr:`host: unsupported arguments
1261
+ `,exitCode:1};let a=n();return a.state===`inactive`?{stdout:Oh(t(),r()),stderr:``,exitCode:0}:{stdout:kh(a),stderr:``,exitCode:0}})}async function jh(e,t,n){if(e().state!==`inactive`)return{stdout:``,stderr:`host reset: only the leader can reset the tray session
1262
1262
  `,exitCode:1};let r=t();if(r.state!==`leader`&&r.state!==`error`)return{stdout:``,stderr:`host reset: no active tray session to reset
1263
1263
  `,exitCode:1};if(!n)return{stdout:``,stderr:`host reset: tray reset is not available in this environment
1264
1264
  `,exitCode:1};try{return{stdout:`Tray session reset. All followers disconnected.
1265
- `+Dh(await n(),[]),stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`host reset: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}}function jh(){return{stdout:`imgcat - preview image and video files in the preview tab
1265
+ `+Oh(await n(),[]),stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`host reset: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}}function Mh(){return{stdout:`imgcat - preview image and video files in the preview tab
1266
1266
 
1267
1267
  Usage: imgcat <path> [path...]
1268
1268
 
1269
1269
  Options:
1270
1270
  -h, --help Show this help message
1271
- `,stderr:``,exitCode:0}}function Mh(e={}){return Ve(`imgcat`,async(t,n)=>{if(t.length===0||t.includes(`--help`)||t.includes(`-h`))return jh();if(typeof window>`u`||typeof document>`u`)return{stdout:``,stderr:`imgcat: browser APIs are unavailable in this environment
1271
+ `,stderr:``,exitCode:0}}function Nh(e={}){return Ve(`imgcat`,async(t,n)=>{if(t.length===0||t.includes(`--help`)||t.includes(`-h`))return Mh();if(typeof window>`u`||typeof document>`u`)return{stdout:``,stderr:`imgcat: browser APIs are unavailable in this environment
1272
1272
  `,exitCode:1};if(!e.onMediaPreview)return{stdout:``,stderr:`imgcat: terminal preview is unavailable
1273
- `,exitCode:1};let r=[];for(let e of t){let t=n.fs.resolvePath(n.cwd,e);if(!(await n.fs.stat(t)).isFile)return{stdout:``,stderr:`imgcat: not a file: ${e}\n`,exitCode:1};let i=o(t);if(!u(i))return{stdout:``,stderr:`imgcat: unsupported media type: ${e}\n`,exitCode:1};let a=await n.fs.readFileBuffer(t),s=new Uint8Array(a.byteLength);s.set(a),r.push({path:t,mimeType:i,bytes:s})}try{return await e.onMediaPreview(r),{stdout:``,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`imgcat: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}var Nh=`https://sql.js.org/dist/`,Ph=`https://cdn.jsdelivr.net/pyodide/v0.27.7/full/`,Fh=`v20.0.0-js-shim`,Ih=`
1273
+ `,exitCode:1};let r=[];for(let e of t){let t=n.fs.resolvePath(n.cwd,e);if(!(await n.fs.stat(t)).isFile)return{stdout:``,stderr:`imgcat: not a file: ${e}\n`,exitCode:1};let i=o(t);if(!u(i))return{stdout:``,stderr:`imgcat: unsupported media type: ${e}\n`,exitCode:1};let a=await n.fs.readFileBuffer(t),s=new Uint8Array(a.byteLength);s.set(a),r.push({path:t,mimeType:i,bytes:s})}try{return await e.onMediaPreview(r),{stdout:``,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`imgcat: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}var Ph=`https://sql.js.org/dist/`,Fh=`https://cdn.jsdelivr.net/pyodide/v0.27.7/full/`,Ih=`v20.0.0-js-shim`,Lh=`
1274
1274
  import sys
1275
1275
  import traceback
1276
1276
 
@@ -1290,10 +1290,10 @@ except SystemExit as exc:
1290
1290
  except BaseException:
1291
1291
  traceback.print_exc()
1292
1292
  __slicc_exit_code = 1
1293
- `,Lh=null,Rh=null,zh=Object.create(null),Bh=class extends Error{constructor(e){super(`Process exited with code ${e}`),this.code=e,this.name=`NodeExitError`}};function Vh(e){let t=e.length>1&&e.endsWith(`/`)?e.slice(0,-1):e,n=t.lastIndexOf(`/`);return n>=0?t.slice(n+1):t}function Hh(e){let t=e.lastIndexOf(`/`);return t<=0?`/`:e.slice(0,t)}function Uh(e,t){return e===`/`?`/${t}`:`${e}/${t}`}function Wh(e){if(/^(https?:\/\/|about:|file:|chrome:)/i.test(e))return!0;try{return new URL(e).protocol.length>0}catch{return!1}}function Gh(e,t){return e===`/`?t.startsWith(`/`):t===e||t.startsWith(`${e}/`)}function Kh(e){return Array.from(e).map(e=>e.toString(16).padStart(2,`0`)).join(``)}function qh(e){return e==null?``:e instanceof Uint8Array?`x'${Kh(e)}'`:String(e)}function Jh(e){return o(e)}function Yh(e){let t=typeof chrome<`u`&&!!chrome?.runtime?.id,n=`/preview${e}`;return t?chrome.runtime.getURL(n):`${typeof window<`u`&&window.location?.origin?window.location.origin:`http://localhost:5710`}${n}`}function Xh(e){return e.length===0||e.startsWith(`/`)?!1:!e.split(`/`).some(e=>e===`..`)}function Zh(e,t){return L(`${e}/${t}`)}function Qh(e){if(typeof e==`string`)return e;if(e==null)return String(e);try{return JSON.stringify(e)}catch{return String(e)}}function $h(e,t){let n=import.meta.resolve;if(typeof n==`function`)try{return new URL(`./`,n(e))}catch{}return new URL(t,import.meta.url)}async function eg(){return Lh||=(async()=>{let t=(await i(()=>import(`./sql-wasm-yST8pDy6.js`).then(t=>e(t.default,1)),__vite__mapDeps([3,4,5]))).default,n=typeof window>`u`?$h(`sql.js/dist/sql-wasm.js`,`../../../../../node_modules/sql.js/dist/`).toString():Nh;return t({locateFile:e=>`${n}${e}`})})(),Lh}var tg=typeof chrome<`u`&&!!chrome?.runtime?.id;async function ng(){return Rh||=(async()=>{let{loadPyodide:e}=await i(async()=>{let{loadPyodide:e}=await import(`./pyodide-3PMN6X39.js`);return{loadPyodide:e}},__vite__mapDeps([6,4,1])),t;return t=typeof window>`u`?decodeURIComponent($h(`pyodide/pyodide.mjs`,`../../../../../node_modules/pyodide/`).pathname):tg?chrome.runtime.getURL(`pyodide/`):Ph,e({indexURL:t,fullStdLib:!1})})(),Rh}var rg=new Set([`http`,`https`,`net`,`tls`,`dgram`,`dns`,`cluster`,`worker_threads`,`child_process`,`crypto`,`os`,`stream`,`zlib`,`vm`,`v8`,`perf_hooks`,`readline`,`repl`,`tty`,`inspector`]);function ig(e){let t=/\brequire\s*\(\s*(['"`])([^'"`\s]+)\1\s*\)/g,n=new Set,r;for(;(r=t.exec(e))!==null;)n.add(r[2]);return[...n]}function ag(){return{stdout:`usage: node -e <code> [args...]
1294
- `,stderr:``,exitCode:0}}function og(){return{stdout:`${Fh}\n`,stderr:``,exitCode:0}}function sg(){return Ve(`node`,async(e,t)=>{if(e.includes(`--help`)||e.includes(`-h`))return ag();if(e.includes(`--version`)||e.includes(`-v`))return og();let n=``,r=`<stdin>`,a=[`node`];if(e.length>0&&(e[0]===`-e`||e[0]===`--eval`)){if(!e[1])return{stdout:``,stderr:`node: option requires an argument -- eval
1293
+ `,Rh=null,zh=null,Bh=Object.create(null),Vh=class extends Error{constructor(e){super(`Process exited with code ${e}`),this.code=e,this.name=`NodeExitError`}};function Hh(e){let t=e.length>1&&e.endsWith(`/`)?e.slice(0,-1):e,n=t.lastIndexOf(`/`);return n>=0?t.slice(n+1):t}function Uh(e){let t=e.lastIndexOf(`/`);return t<=0?`/`:e.slice(0,t)}function Wh(e,t){return e===`/`?`/${t}`:`${e}/${t}`}function Gh(e){if(/^(https?:\/\/|about:|file:|chrome:)/i.test(e))return!0;try{return new URL(e).protocol.length>0}catch{return!1}}function Kh(e,t){return e===`/`?t.startsWith(`/`):t===e||t.startsWith(`${e}/`)}function qh(e){return Array.from(e).map(e=>e.toString(16).padStart(2,`0`)).join(``)}function Jh(e){return e==null?``:e instanceof Uint8Array?`x'${qh(e)}'`:String(e)}function Yh(e){return o(e)}function Xh(e){let t=typeof chrome<`u`&&!!chrome?.runtime?.id,n=`/preview${e}`;return t?chrome.runtime.getURL(n):`${typeof window<`u`&&window.location?.origin?window.location.origin:`http://localhost:5710`}${n}`}function Zh(e){return e.length===0||e.startsWith(`/`)?!1:!e.split(`/`).some(e=>e===`..`)}function Qh(e,t){return L(`${e}/${t}`)}function $h(e){if(typeof e==`string`)return e;if(e==null)return String(e);try{return JSON.stringify(e)}catch{return String(e)}}function eg(e,t){let n=import.meta.resolve;if(typeof n==`function`)try{return new URL(`./`,n(e))}catch{}return new URL(t,import.meta.url)}async function tg(){return Rh||=(async()=>{let t=(await i(()=>import(`./sql-wasm-yST8pDy6.js`).then(t=>e(t.default,1)),__vite__mapDeps([3,4,5]))).default,n=typeof window>`u`?eg(`sql.js/dist/sql-wasm.js`,`../../../../../node_modules/sql.js/dist/`).toString():Ph;return t({locateFile:e=>`${n}${e}`})})(),Rh}var ng=typeof chrome<`u`&&!!chrome?.runtime?.id;async function rg(){return zh||=(async()=>{let{loadPyodide:e}=await i(async()=>{let{loadPyodide:e}=await import(`./pyodide-3PMN6X39.js`);return{loadPyodide:e}},__vite__mapDeps([6,4,1])),t;return t=typeof window>`u`?decodeURIComponent(eg(`pyodide/pyodide.mjs`,`../../../../../node_modules/pyodide/`).pathname):ng?chrome.runtime.getURL(`pyodide/`):Fh,e({indexURL:t,fullStdLib:!1})})(),zh}var ig=new Set([`http`,`https`,`net`,`tls`,`dgram`,`dns`,`cluster`,`worker_threads`,`child_process`,`crypto`,`os`,`stream`,`zlib`,`vm`,`v8`,`perf_hooks`,`readline`,`repl`,`tty`,`inspector`]);function ag(e){let t=/\brequire\s*\(\s*(['"`])([^'"`\s]+)\1\s*\)/g,n=new Set,r;for(;(r=t.exec(e))!==null;)n.add(r[2]);return[...n]}function og(){return{stdout:`usage: node -e <code> [args...]
1294
+ `,stderr:``,exitCode:0}}function sg(){return{stdout:`${Ih}\n`,stderr:``,exitCode:0}}function cg(){return Ve(`node`,async(e,t)=>{if(e.includes(`--help`)||e.includes(`-h`))return og();if(e.includes(`--version`)||e.includes(`-v`))return sg();let n=``,r=`<stdin>`,a=[`node`];if(e.length>0&&(e[0]===`-e`||e[0]===`--eval`)){if(!e[1])return{stdout:``,stderr:`node: option requires an argument -- eval
1295
1295
  `,exitCode:9};n=e[1],r=`[eval]`,a=[`node`,...e.slice(2)]}else if(e.length>0&&!e[0].startsWith(`-`)){let i=e[0],o=t.fs.resolvePath(t.cwd,i);if(!await t.fs.exists(o))return{stdout:``,stderr:`node: cannot find module '${i}'\n`,exitCode:1};n=await t.fs.readFile(o),r=i,a=[`node`,i,...e.slice(1)]}else if(t.stdin.trim().length>0)n=t.stdin,r=`<stdin>`,a=[`node`];else if(e.length>0)return{stdout:``,stderr:`node: unsupported option '${e[0]}'\n`,exitCode:9};else return{stdout:``,stderr:`node: REPL mode is not supported in this environment; use node -e "code"
1296
- `,exitCode:9};let o=[],s=[],c=e=>{o.push(typeof e==`string`?e:String(e))},l=e=>{s.push(typeof e==`string`?e:String(e))},u={log:(...e)=>c(`${e.map(Qh).join(` `)}\n`),info:(...e)=>c(`${e.map(Qh).join(` `)}\n`),warn:(...e)=>l(`${e.map(Qh).join(` `)}\n`),error:(...e)=>l(`${e.map(Qh).join(` `)}\n`)},d={argv:a,env:Object.fromEntries(t.env.entries()),cwd:()=>t.cwd,exit:e=>{throw new Bh(Number.isFinite(e)?Number(e):0)},stdout:{write:c},stderr:{write:l}},f={readFile:async e=>{let n=t.fs.resolvePath(t.cwd,e);return t.fs.readFile(n)},readFileBinary:async e=>{let n=t.fs.resolvePath(t.cwd,e);return t.fs.readFileBuffer(n)},writeFile:async(e,n)=>{let r=t.fs.resolvePath(t.cwd,e);await t.fs.writeFile(r,n)},writeFileBinary:async(e,n)=>{let r=t.fs.resolvePath(t.cwd,e),i=new Uint8Array(n.byteLength);i.set(n),await t.fs.writeFile(r,i)},readDir:async e=>{let n=t.fs.resolvePath(t.cwd,e);return t.fs.readdir(n)},exists:async e=>{let n=t.fs.resolvePath(t.cwd,e);return t.fs.exists(n)},fetchToFile:async(e,n)=>{if(typeof fetch>`u`)throw Error(`fetch is not available in this runtime`);let r=await fetch(e);if(!r.ok)throw Error(`fetch ${r.status} ${r.statusText}`);let i=new Uint8Array(await r.arrayBuffer()),a=t.fs.resolvePath(t.cwd,n);return await t.fs.writeFile(a,i),i.byteLength}},p=async e=>{if(!t.exec)throw Error(`exec is not available in this runtime`);let n=await t.exec(e,{cwd:t.cwd});return{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode}},m=typeof chrome<`u`&&!!chrome?.runtime?.id;if(!m){let e=ig(n),t=new Set([`fs`,`process`,`buffer`]),r=e.map(e=>e.startsWith(`node:`)?e.slice(5):e).filter(e=>!t.has(e)&&!rg.has(e)),a=zh.__requireCache??=Object.create(null),o=r.filter(e=>!(e in a));if(o.length>0){let e=await Promise.allSettled(o.map(async e=>{let t=await i(()=>import(`https://esm.sh/`+e),[]);a[e]=t&&typeof t==`object`&&`default`in t?t.default:t}));for(let t=0;t<e.length;t++)if(e[t].status===`rejected`){let n=e[t].reason;l(`Warning: failed to pre-load require('${o[t]}'): ${n instanceof Error?n.message:String(n)}\n`)}}}let h=e=>{let t=e.startsWith(`node:`)?e.slice(5):e;if(t===`fs`)return f;if(t===`process`)return d;if(t===`buffer`)return{Buffer:globalThis.Buffer};if(t===`path`){let t=zh.__requireCache;if(t&&`path`in t)return t.path;if(t&&e in t)return t[e];throw Error(`require('${e}'): path module not pre-loaded. Add require('path') as a static import.`)}if(rg.has(t))throw Error(`require('${e}'): Node built-in '${t}' is not available in the browser environment.${{http:` Use fetch() instead.`,https:` Use fetch() instead.`,child_process:` Use exec() which is available as a shell bridge.`,crypto:` Use globalThis.crypto (Web Crypto API) instead.`}[t]||``}`);let n=zh.__requireCache;if(n&&e in n)return n[e];throw Error(`require('${e}'): module not pre-loaded. Use a string literal or await import('https://esm.sh/${e}') directly.`)},g={exports:{},filename:r};try{if(m){let e=`
1296
+ `,exitCode:9};let o=[],s=[],c=e=>{o.push(typeof e==`string`?e:String(e))},l=e=>{s.push(typeof e==`string`?e:String(e))},u={log:(...e)=>c(`${e.map($h).join(` `)}\n`),info:(...e)=>c(`${e.map($h).join(` `)}\n`),warn:(...e)=>l(`${e.map($h).join(` `)}\n`),error:(...e)=>l(`${e.map($h).join(` `)}\n`)},d={argv:a,env:Object.fromEntries(t.env.entries()),cwd:()=>t.cwd,exit:e=>{throw new Vh(Number.isFinite(e)?Number(e):0)},stdout:{write:c},stderr:{write:l}},f={readFile:async e=>{let n=t.fs.resolvePath(t.cwd,e);return t.fs.readFile(n)},readFileBinary:async e=>{let n=t.fs.resolvePath(t.cwd,e);return t.fs.readFileBuffer(n)},writeFile:async(e,n)=>{let r=t.fs.resolvePath(t.cwd,e);await t.fs.writeFile(r,n)},writeFileBinary:async(e,n)=>{let r=t.fs.resolvePath(t.cwd,e),i=new Uint8Array(n.byteLength);i.set(n),await t.fs.writeFile(r,i)},readDir:async e=>{let n=t.fs.resolvePath(t.cwd,e);return t.fs.readdir(n)},exists:async e=>{let n=t.fs.resolvePath(t.cwd,e);return t.fs.exists(n)},fetchToFile:async(e,n)=>{if(typeof fetch>`u`)throw Error(`fetch is not available in this runtime`);let r=await fetch(e);if(!r.ok)throw Error(`fetch ${r.status} ${r.statusText}`);let i=new Uint8Array(await r.arrayBuffer()),a=t.fs.resolvePath(t.cwd,n);return await t.fs.writeFile(a,i),i.byteLength}},p=async e=>{if(!t.exec)throw Error(`exec is not available in this runtime`);let n=await t.exec(e,{cwd:t.cwd});return{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode}},m=typeof chrome<`u`&&!!chrome?.runtime?.id;if(!m){let e=ag(n),t=new Set([`fs`,`process`,`buffer`]),r=e.map(e=>e.startsWith(`node:`)?e.slice(5):e).filter(e=>!t.has(e)&&!ig.has(e)),a=Bh.__requireCache??=Object.create(null),o=r.filter(e=>!(e in a));if(o.length>0){let e=await Promise.allSettled(o.map(async e=>{let t=await i(()=>import(`https://esm.sh/`+e),[]);a[e]=t&&typeof t==`object`&&`default`in t?t.default:t}));for(let t=0;t<e.length;t++)if(e[t].status===`rejected`){let n=e[t].reason;l(`Warning: failed to pre-load require('${o[t]}'): ${n instanceof Error?n.message:String(n)}\n`)}}}let h=e=>{let t=e.startsWith(`node:`)?e.slice(5):e;if(t===`fs`)return f;if(t===`process`)return d;if(t===`buffer`)return{Buffer:globalThis.Buffer};if(t===`path`){let t=Bh.__requireCache;if(t&&`path`in t)return t.path;if(t&&e in t)return t[e];throw Error(`require('${e}'): path module not pre-loaded. Add require('path') as a static import.`)}if(ig.has(t))throw Error(`require('${e}'): Node built-in '${t}' is not available in the browser environment.${{http:` Use fetch() instead.`,https:` Use fetch() instead.`,child_process:` Use exec() which is available as a shell bridge.`,crypto:` Use globalThis.crypto (Web Crypto API) instead.`}[t]||``}`);let n=Bh.__requireCache;if(n&&e in n)return n[e];throw Error(`require('${e}'): module not pre-loaded. Use a string literal or await import('https://esm.sh/${e}') directly.`)},g={exports:{},filename:r};try{if(m){let e=`
1297
1297
  const __stdout = [];
1298
1298
  const __stderr = [];
1299
1299
  const __origConsole = { log: console.log, error: console.error, warn: console.warn, info: console.info };
@@ -1398,17 +1398,17 @@ except BaseException:
1398
1398
  console.info = __origConsole.info;
1399
1399
  return { stdout: __stdout.join(''), stderr: __stderr.join('') };
1400
1400
  `,r=document.querySelector(`iframe[data-js-tool]`);r||(r=document.createElement(`iframe`),r.style.display=`none`,r.dataset.jsTool=`true`,r.src=chrome.runtime.getURL(`sandbox.html`),document.body.appendChild(r),await new Promise(e=>{r.addEventListener(`load`,()=>e(),{once:!0})}));let i=`node-${Date.now()}-${Math.random().toString(36).slice(2)}`,o=e=>{let n=e.data;!n||n.type!==`vfs`||(async()=>{try{let e,i=n.args?.[0]?t.fs.resolvePath(t.cwd,n.args[0]):n.args?.[0];switch(n.op){case`readFile`:e=await t.fs.readFile(i);break;case`readFileBinary`:e=await t.fs.readFileBuffer(i);break;case`writeFile`:await t.fs.writeFile(i,n.args[1]),e=!0;break;case`writeFileBinary`:await t.fs.writeFile(i,n.binaryData??new Uint8Array),e=!0;break;case`readDir`:e=await t.fs.readdir(i);break;case`exists`:e=await t.fs.exists(i);break;case`stat`:{let n=await t.fs.stat(i);e={isDirectory:n.isDirectory,isFile:n.isFile,size:n.size};break}case`mkdir`:await t.fs.mkdir(i,{recursive:!0}),e=!0;break;case`rm`:await t.fs.rm(i,{recursive:!0}),e=!0;break}r.contentWindow.postMessage({type:`vfs_response`,id:n.id,result:e},`*`)}catch(e){let t=e instanceof Error?e.message:String(e);r.contentWindow.postMessage({type:`vfs_response`,id:n.id,error:t},`*`)}})()};window.addEventListener(`message`,o);let s=e=>{let t=e.data;!t||t.type!==`shell_exec`||(async()=>{try{let e=await p(t.command);r.contentWindow.postMessage({type:`shell_exec_response`,id:t.id,result:e},`*`)}catch(e){let n=e instanceof Error?e.message:String(e);r.contentWindow.postMessage({type:`shell_exec_response`,id:t.id,error:n},`*`)}})()};window.addEventListener(`message`,s);let c=e=>{let t=e.data;!t||t.type!==`fetch_proxy`||(async()=>{try{let e={method:t.init?.method??`GET`,cache:`no-store`};t.init?.headers&&(e.headers=t.init.headers),t.init?.body&&![`GET`,`HEAD`].includes(e.method)&&(e.body=t.init.body);let n=await fetch(t.url,e),i=await n.arrayBuffer(),a={};n.headers.forEach((e,t)=>{a[t]=e}),r.contentWindow.postMessage({type:`fetch_proxy_response`,id:t.id,status:n.status,statusText:n.statusText,headers:a,body:new Uint8Array(i)},`*`)}catch(e){let n=e instanceof Error?e.message:String(e);r.contentWindow.postMessage({type:`fetch_proxy_response`,id:t.id,error:n},`*`)}})()};window.addEventListener(`message`,c);let l=await new Promise((t,n)=>{let a,o=e=>{if(e.data?.type===`exec_result`&&e.data.id===i)if(window.removeEventListener(`message`,o),clearTimeout(a),e.data.error)t({stdout:``,stderr:e.data.error+`
1401
- `});else try{let n=JSON.parse(e.data.result);t({stdout:n.stdout||``,stderr:n.stderr||``})}catch{t({stdout:e.data.result||``,stderr:``})}};a=setTimeout(()=>{window.removeEventListener(`message`,o),n(Error(`node eval timed out (30s)`))},3e4),window.addEventListener(`message`,o),r.contentWindow.postMessage({type:`exec`,id:i,code:e},`*`)});return window.removeEventListener(`message`,o),window.removeEventListener(`message`,s),window.removeEventListener(`message`,c),{stdout:l.stdout,stderr:l.stderr,exitCode:+!!l.stderr}}let e=Object.getPrototypeOf(async function(){}).constructor;return await new e(`fs`,`process`,`console`,`require`,`module`,`exports`,`__state`,`exec`,`"use strict";\nconst globalThis = __state;\nconst global = __state;\n${n}`)(f,d,u,h,g,g.exports,zh,p),{stdout:o.join(``),stderr:s.join(``),exitCode:0}}catch(e){if(e instanceof Bh)return{stdout:o.join(``),stderr:s.join(``),exitCode:e.code};let t=e instanceof Error?e.stack??e.message:String(e);return{stdout:o.join(``),stderr:`${s.join(``)}${t}\n`,exitCode:1}}})}var cg=[`--download`,`-d`,`--view`,`-v`];function lg(){return{stdout:`usage: open [--download|-d] [--view|-v] <url|path> [url|path...]
1401
+ `});else try{let n=JSON.parse(e.data.result);t({stdout:n.stdout||``,stderr:n.stderr||``})}catch{t({stdout:e.data.result||``,stderr:``})}};a=setTimeout(()=>{window.removeEventListener(`message`,o),n(Error(`node eval timed out (30s)`))},3e4),window.addEventListener(`message`,o),r.contentWindow.postMessage({type:`exec`,id:i,code:e},`*`)});return window.removeEventListener(`message`,o),window.removeEventListener(`message`,s),window.removeEventListener(`message`,c),{stdout:l.stdout,stderr:l.stderr,exitCode:+!!l.stderr}}let e=Object.getPrototypeOf(async function(){}).constructor;return await new e(`fs`,`process`,`console`,`require`,`module`,`exports`,`__state`,`exec`,`"use strict";\nconst globalThis = __state;\nconst global = __state;\n${n}`)(f,d,u,h,g,g.exports,Bh,p),{stdout:o.join(``),stderr:s.join(``),exitCode:0}}catch(e){if(e instanceof Vh)return{stdout:o.join(``),stderr:s.join(``),exitCode:e.code};let t=e instanceof Error?e.stack??e.message:String(e);return{stdout:o.join(``),stderr:`${s.join(``)}${t}\n`,exitCode:1}}})}var lg=[`--download`,`-d`,`--view`,`-v`];function ug(){return{stdout:`usage: open [--download|-d] [--view|-v] <url|path> [url|path...]
1402
1402
 
1403
1403
  VFS paths are served in a new browser tab via the preview service worker.
1404
1404
  URLs (http/https/etc.) are opened directly in a new tab.
1405
1405
  For app directories with a default entry file, prefer serve <dir>.
1406
1406
  --download, -d Force download instead of opening in a tab.
1407
1407
  --view, -v Return image inline so the agent can see it.
1408
- `,stderr:``,exitCode:0}}function ug(e){let t=``,n=8192;for(let r=0;r<e.length;r+=n)t+=String.fromCharCode(...e.subarray(r,r+n));return btoa(t)}function dg(){return Ve(`open`,async(e,t)=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return lg();if(typeof window>`u`||typeof document>`u`)return{stdout:``,stderr:`open: browser APIs are unavailable in this environment
1409
- `,exitCode:1};let n=e.includes(`--download`)||e.includes(`-d`),r=e.includes(`--view`)||e.includes(`-v`),i=e.filter(e=>!cg.includes(e));if(i.length===0)return lg();let a=[];for(let e of i){if(Wh(e)){window.open(e,`_blank`,`noopener,noreferrer`),a.push(`opened ${e}`);continue}let i=t.fs.resolvePath(t.cwd,e);if(i.endsWith(`.shtml`)){let e=typeof window<`u`?window.__slicc_sprinkleManager:void 0;if(e){let t=(i.split(`/`).pop()??``).replace(/\.shtml$/,``);try{await e.open(t),a.push(`opened sprinkle ${t} from ${i}`)}catch(e){return{stdout:``,stderr:`open: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}}else{let e=Yh(i);window.open(e,`_blank`,`noopener,noreferrer`),a.push(`opened ${i} → ${e}`)}continue}if(r){let n;try{n=await t.fs.stat(i)}catch{return{stdout:``,stderr:`open: no such file: ${e}\n`,exitCode:1}}if(!n.isFile)return{stdout:``,stderr:`open: not a file: ${e}\n`,exitCode:1};let r;try{r=await t.fs.readFileBuffer(i)}catch{return{stdout:``,stderr:`open: failed to read: ${e}\n`,exitCode:1}}let o=Jh(i),s=ug(new Uint8Array(r));a.push(`${i} (${Math.round(r.byteLength/1024)} KB)\n<img:data:${o};base64,${s}>`)}else if(n){let n;try{n=await t.fs.stat(i)}catch{return{stdout:``,stderr:`open: no such file: ${e}\n`,exitCode:1}}if(!n.isFile)return{stdout:``,stderr:`open: not a file: ${e}\n`,exitCode:1};let r;try{r=await t.fs.readFileBuffer(i)}catch{return{stdout:``,stderr:`open: failed to read: ${e}\n`,exitCode:1}}let o=new Uint8Array(r.byteLength);o.set(r);let s=new Blob([o.buffer],{type:Jh(i)}),c=URL.createObjectURL(s),l=document.createElement(`a`);l.href=c,l.download=Vh(i)||`download`,l.style.display=`none`,document.body.appendChild(l),l.click(),document.body.removeChild(l),setTimeout(()=>URL.revokeObjectURL(c),0),a.push(`downloaded ${i}`)}else{let e=Yh(i);window.open(e,`_blank`,`noopener,noreferrer`),a.push(`opened ${i} → ${e}`)}}return{stdout:a.join(`
1408
+ `,stderr:``,exitCode:0}}function dg(e){let t=``,n=8192;for(let r=0;r<e.length;r+=n)t+=String.fromCharCode(...e.subarray(r,r+n));return btoa(t)}function fg(){return Ve(`open`,async(e,t)=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return ug();if(typeof window>`u`||typeof document>`u`)return{stdout:``,stderr:`open: browser APIs are unavailable in this environment
1409
+ `,exitCode:1};let n=e.includes(`--download`)||e.includes(`-d`),r=e.includes(`--view`)||e.includes(`-v`),i=e.filter(e=>!lg.includes(e));if(i.length===0)return ug();let a=[];for(let e of i){if(Gh(e)){window.open(e,`_blank`,`noopener,noreferrer`),a.push(`opened ${e}`);continue}let i=t.fs.resolvePath(t.cwd,e);if(i.endsWith(`.shtml`)){let e=typeof window<`u`?window.__slicc_sprinkleManager:void 0;if(e){let t=(i.split(`/`).pop()??``).replace(/\.shtml$/,``);try{await e.open(t),a.push(`opened sprinkle ${t} from ${i}`)}catch(e){return{stdout:``,stderr:`open: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}}else{let e=Xh(i);window.open(e,`_blank`,`noopener,noreferrer`),a.push(`opened ${i} → ${e}`)}continue}if(r){let n;try{n=await t.fs.stat(i)}catch{return{stdout:``,stderr:`open: no such file: ${e}\n`,exitCode:1}}if(!n.isFile)return{stdout:``,stderr:`open: not a file: ${e}\n`,exitCode:1};let r;try{r=await t.fs.readFileBuffer(i)}catch{return{stdout:``,stderr:`open: failed to read: ${e}\n`,exitCode:1}}let o=Yh(i),s=dg(new Uint8Array(r));a.push(`${i} (${Math.round(r.byteLength/1024)} KB)\n<img:data:${o};base64,${s}>`)}else if(n){let n;try{n=await t.fs.stat(i)}catch{return{stdout:``,stderr:`open: no such file: ${e}\n`,exitCode:1}}if(!n.isFile)return{stdout:``,stderr:`open: not a file: ${e}\n`,exitCode:1};let r;try{r=await t.fs.readFileBuffer(i)}catch{return{stdout:``,stderr:`open: failed to read: ${e}\n`,exitCode:1}}let o=new Uint8Array(r.byteLength);o.set(r);let s=new Blob([o.buffer],{type:Yh(i)}),c=URL.createObjectURL(s),l=document.createElement(`a`);l.href=c,l.download=Hh(i)||`download`,l.style.display=`none`,document.body.appendChild(l),l.click(),document.body.removeChild(l),setTimeout(()=>URL.revokeObjectURL(c),0),a.push(`downloaded ${i}`)}else{let e=Xh(i);window.open(e,`_blank`,`noopener,noreferrer`),a.push(`opened ${i} → ${e}`)}}return{stdout:a.join(`
1410
1410
  `)+`
1411
- `,stderr:``,exitCode:0}})}var fg=null,pg=null;async function mg(){return fg||=i(()=>import(`./es-C70AgaBB.js`),__vite__mapDeps([7,4,5])),fg}async function hg(){return pg||=i(()=>import(`./dist-DEO1hNOZ2.js`),__vite__mapDeps([8,1])),pg}function gg(e){return e.endsWith(`right`)?{range:e.slice(0,-5),rotation:90}:e.endsWith(`left`)?{range:e.slice(0,-4),rotation:270}:e.endsWith(`down`)?{range:e.slice(0,-4),rotation:180}:{range:e}}function _g(e){let{range:t,rotation:n}=gg(e);if(/^\d+$/.test(t)){let e=parseInt(t,10);return{start:e,end:e,rotation:n}}let r=t.match(/^(\d+)-(\d+|end)$/);if(r)return{start:parseInt(r[1],10),end:r[2]===`end`?`end`:parseInt(r[2],10),rotation:n};throw Error(`Invalid page range: ${e}`)}function vg(e,t){let n=e.start,r=e.end;if(n<1||n>t)throw Error(`Page ${n} out of range (1-${t})`);let i=r===`end`?t:r;if(i<1||i>t)throw Error(`Page ${i} out of range (1-${t})`);if(i<n)throw Error(`Invalid range: ${n}-${i}`);let a=[];for(let e=n;e<=i;e++)a.push(e);return a}function yg(){return{stdout:`usage: pdftk <input.pdf> <operation> [args...]
1411
+ `,stderr:``,exitCode:0}})}var pg=null,mg=null;async function hg(){return pg||=i(()=>import(`./es-6oFxNVOv.js`),__vite__mapDeps([7,4,5])),pg}async function gg(){return mg||=i(()=>import(`./dist-DEO1hNOZ2.js`),__vite__mapDeps([8,1])),mg}function _g(e){return e.endsWith(`right`)?{range:e.slice(0,-5),rotation:90}:e.endsWith(`left`)?{range:e.slice(0,-4),rotation:270}:e.endsWith(`down`)?{range:e.slice(0,-4),rotation:180}:{range:e}}function vg(e){let{range:t,rotation:n}=_g(e);if(/^\d+$/.test(t)){let e=parseInt(t,10);return{start:e,end:e,rotation:n}}let r=t.match(/^(\d+)-(\d+|end)$/);if(r)return{start:parseInt(r[1],10),end:r[2]===`end`?`end`:parseInt(r[2],10),rotation:n};throw Error(`Invalid page range: ${e}`)}function yg(e,t){let n=e.start,r=e.end;if(n<1||n>t)throw Error(`Page ${n} out of range (1-${t})`);let i=r===`end`?t:r;if(i<1||i>t)throw Error(`Page ${i} out of range (1-${t})`);if(i<n)throw Error(`Invalid range: ${n}-${i}`);let a=[];for(let e=n;e<=i;e++)a.push(e);return a}function bg(){return{stdout:`usage: pdftk <input.pdf> <operation> [args...]
1412
1412
 
1413
1413
  Operations:
1414
1414
  dump_data Print metadata (page count, title, author, etc.)
@@ -1432,14 +1432,14 @@ Page ranges:
1432
1432
  1-endright Pages 1 to end, rotated 90° clockwise
1433
1433
  3left Page 3 rotated 270° (counterclockwise)
1434
1434
  1-5down Pages 1-5 rotated 180°
1435
- `,stderr:``,exitCode:0}}function bg(e=`pdftk`){return Ve(e,async(t,n)=>{if(t.length===0||t.includes(`--help`)||t.includes(`-h`))return yg();try{let r=[],i=0;for(;i<t.length;){let e=t[i],a=e.match(/^([A-Z])=(.+)$/);if(a){let e=a[1],t=n.fs.resolvePath(n.cwd,a[2]);r.push({handle:e,path:t}),i++;continue}if([`dump_data`,`dump_data_utf8`,`cat`,`rotate`].includes(e))break;if(!e.startsWith(`-`)){let t=n.fs.resolvePath(n.cwd,e);r.push({handle:``,path:t}),i++;continue}break}if(r.length===0)return{stdout:``,stderr:`${e}: no input PDF specified\n`,exitCode:1};let a=t[i];if(i++,!a)return{stdout:``,stderr:`${e}: no operation specified\n`,exitCode:1};if(a===`dump_data`){if(r.length>1)return{stdout:``,stderr:`${e}: dump_data only supports a single input file\n`,exitCode:1};let t=await mg(),i=await n.fs.readFileBuffer(r[0].path),a=await t.PDFDocument.load(i),o=[];o.push(`NumberOfPages: ${a.getPageCount()}`);let s=a.getTitle();s&&o.push(`InfoBegin`),s&&o.push(`InfoKey: Title`),s&&o.push(`InfoValue: ${s}`);let c=a.getAuthor();c&&o.push(`InfoBegin`),c&&o.push(`InfoKey: Author`),c&&o.push(`InfoValue: ${c}`);let l=a.getCreator();l&&o.push(`InfoBegin`),l&&o.push(`InfoKey: Creator`),l&&o.push(`InfoValue: ${l}`);let u=a.getProducer();return u&&o.push(`InfoBegin`),u&&o.push(`InfoKey: Producer`),u&&o.push(`InfoValue: ${u}`),{stdout:o.join(`
1435
+ `,stderr:``,exitCode:0}}function xg(e=`pdftk`){return Ve(e,async(t,n)=>{if(t.length===0||t.includes(`--help`)||t.includes(`-h`))return bg();try{let r=[],i=0;for(;i<t.length;){let e=t[i],a=e.match(/^([A-Z])=(.+)$/);if(a){let e=a[1],t=n.fs.resolvePath(n.cwd,a[2]);r.push({handle:e,path:t}),i++;continue}if([`dump_data`,`dump_data_utf8`,`cat`,`rotate`].includes(e))break;if(!e.startsWith(`-`)){let t=n.fs.resolvePath(n.cwd,e);r.push({handle:``,path:t}),i++;continue}break}if(r.length===0)return{stdout:``,stderr:`${e}: no input PDF specified\n`,exitCode:1};let a=t[i];if(i++,!a)return{stdout:``,stderr:`${e}: no operation specified\n`,exitCode:1};if(a===`dump_data`){if(r.length>1)return{stdout:``,stderr:`${e}: dump_data only supports a single input file\n`,exitCode:1};let t=await hg(),i=await n.fs.readFileBuffer(r[0].path),a=await t.PDFDocument.load(i),o=[];o.push(`NumberOfPages: ${a.getPageCount()}`);let s=a.getTitle();s&&o.push(`InfoBegin`),s&&o.push(`InfoKey: Title`),s&&o.push(`InfoValue: ${s}`);let c=a.getAuthor();c&&o.push(`InfoBegin`),c&&o.push(`InfoKey: Author`),c&&o.push(`InfoValue: ${c}`);let l=a.getCreator();l&&o.push(`InfoBegin`),l&&o.push(`InfoKey: Creator`),l&&o.push(`InfoValue: ${l}`);let u=a.getProducer();return u&&o.push(`InfoBegin`),u&&o.push(`InfoKey: Producer`),u&&o.push(`InfoValue: ${u}`),{stdout:o.join(`
1436
1436
  `)+`
1437
- `,stderr:``,exitCode:0}}if(a===`dump_data_utf8`){if(r.length>1)return{stdout:``,stderr:`${e}: dump_data_utf8 only supports a single input file\n`,exitCode:1};let t=await hg(),i=await n.fs.readFileBuffer(r[0].path);return{stdout:(await t.extractText(i)).text+`
1438
- `,stderr:``,exitCode:0}}if(a===`cat`){let a=await mg(),o=await a.PDFDocument.create(),s=t.slice(i),c=s.indexOf(`output`);if(c===-1)return{stdout:``,stderr:`${e}: cat operation requires 'output <filename>'\n`,exitCode:1};let l=s.slice(0,c),u=s[c+1];if(!u)return{stdout:``,stderr:`${e}: output filename not specified\n`,exitCode:1};let d=n.fs.resolvePath(n.cwd,u),f=new Map;for(let e of r){let t=await n.fs.readFileBuffer(e.path),r=await a.PDFDocument.load(t),i=e.handle||`default`;f.set(i,r)}for(let t of l){if(/^[A-Z]$/.test(t)){let n=f.get(t);if(!n)return{stdout:``,stderr:`${e}: unknown handle '${t}'\n`,exitCode:1};let r=n.getPageCount(),i=Array.from({length:r},(e,t)=>t);(await o.copyPages(n,i)).forEach(e=>o.addPage(e));continue}let n=f.get(r[0].handle||`default`);if(!n)return{stdout:``,stderr:`${e}: no default input document\n`,exitCode:1};let i=n.getPageCount(),s=_g(t),c=vg(s,i).map(e=>e-1),l=await o.copyPages(n,c);for(let e of l)s.rotation&&e.setRotation(a.degrees(s.rotation)),o.addPage(e)}let p=await o.save();return await n.fs.writeFile(d,p),{stdout:`Created ${u}\n`,stderr:``,exitCode:0}}if(a===`rotate`){if(r.length>1)return{stdout:``,stderr:`${e}: rotate only supports a single input file\n`,exitCode:1};let a=await mg(),o=await n.fs.readFileBuffer(r[0].path),s=await a.PDFDocument.load(o),c=t.slice(i),l=c.indexOf(`output`);if(l===-1)return{stdout:``,stderr:`${e}: rotate operation requires 'output <filename>'\n`,exitCode:1};let u=c.slice(0,l),d=c[l+1];if(!d)return{stdout:``,stderr:`${e}: output filename not specified\n`,exitCode:1};let f=n.fs.resolvePath(n.cwd,d),p=s.getPageCount(),m=new Map;for(let t of u){let n=_g(t);if(!n.rotation)return{stdout:``,stderr:`${e}: rotation suffix required (right/left/down) for range '${t}'\n`,exitCode:1};let r=vg(n,p);for(let e of r)m.set(e-1,n.rotation)}let h=s.getPages();for(let[e,t]of m.entries()){let n=h[e],r=(n.getRotation().angle+t)%360;n.setRotation(a.degrees(r))}let g=await s.save();return await n.fs.writeFile(f,g),{stdout:`Created ${d}\n`,stderr:``,exitCode:0}}return{stdout:``,stderr:`${e}: unknown operation '${a}'\n`,exitCode:1}}catch(t){return{stdout:``,stderr:`${e}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}})}async function xg(e,t,n){let r=t.FS;function i(e){try{r.stat(e)}catch{r.mkdirTree(e)}}async function a(t){i(t);let n;try{n=await e.readdir(t)}catch{return}for(let o of n){let n=t===`/`?`/${o}`:`${t}/${o}`;try{if((await e.stat(n)).isDirectory)await a(n);else{let a=await e.readFile(n);i(t),r.writeFile(n,a)}}catch{}}}for(let e of n)await a(e)}async function Sg(e,t,n){let r=t.FS;async function i(t){let n;try{n=r.readdir(t).filter(e=>e!==`.`&&e!==`..`)}catch{return}for(let a of n){let n=t===`/`?`/${a}`:`${t}/${a}`;try{let a=r.stat(n);if(r.isDir(a.mode))await e.mkdir(n,{recursive:!0}),await i(n);else{let i=new TextDecoder().decode(r.readFile(n));await e.mkdir(t,{recursive:!0}),await e.writeFile(n,i)}}catch{}}}for(let e of n)await i(e)}function Cg(){return{stdout:`usage: python3 [-c code | script.py] [args...]
1439
- `,stderr:``,exitCode:0}}function wg(){return{stdout:`Python 3.12 (Pyodide)
1440
- `,stderr:``,exitCode:0}}function Tg(e){return Ve(e,async(t,n)=>{if(t.includes(`--help`)||t.includes(`-h`))return Cg();if(t.includes(`--version`)||t.includes(`-V`))return wg();let r=``,i=`<stdin>`,a=[`python3`];if(t[0]===`-c`){if(!t[1])return{stdout:``,stderr:`${e}: option requires an argument -- 'c'\n`,exitCode:2};r=t[1],i=`-c`,a=[`-c`,...t.slice(2)]}else if(t.length>0&&!t[0].startsWith(`-`)){let o=t[0],s=n.fs.resolvePath(n.cwd,o);if(!await n.fs.exists(s))return{stdout:``,stderr:`${e}: can't open file '${o}': [Errno 2] No such file or directory\n`,exitCode:2};r=await n.fs.readFile(s),i=o,a=[o,...t.slice(1)]}else if(n.stdin.trim().length>0)r=n.stdin,i=`<stdin>`,a=[`<stdin>`];else if(t.length>0)return{stdout:``,stderr:`${e}: unsupported option '${t[0]}'\n`,exitCode:2};else return{stdout:``,stderr:`${e}: no input provided (use -c CODE, script path, or stdin)\n`,exitCode:2};try{let e=await ng(),t=[],o=[],s=[n.cwd,`/tmp`];if(i!==`<stdin>`&&i!==`[eval]`){let e=i.includes(`/`)?i.slice(0,i.lastIndexOf(`/`)):n.cwd;s.includes(e)||s.push(e)}await xg(n.fs,e,s);try{e.FS.chdir(n.cwd)}catch{}e.setStdout({batched:e=>t.push(e+`
1437
+ `,stderr:``,exitCode:0}}if(a===`dump_data_utf8`){if(r.length>1)return{stdout:``,stderr:`${e}: dump_data_utf8 only supports a single input file\n`,exitCode:1};let t=await gg(),i=await n.fs.readFileBuffer(r[0].path);return{stdout:(await t.extractText(i)).text+`
1438
+ `,stderr:``,exitCode:0}}if(a===`cat`){let a=await hg(),o=await a.PDFDocument.create(),s=t.slice(i),c=s.indexOf(`output`);if(c===-1)return{stdout:``,stderr:`${e}: cat operation requires 'output <filename>'\n`,exitCode:1};let l=s.slice(0,c),u=s[c+1];if(!u)return{stdout:``,stderr:`${e}: output filename not specified\n`,exitCode:1};let d=n.fs.resolvePath(n.cwd,u),f=new Map;for(let e of r){let t=await n.fs.readFileBuffer(e.path),r=await a.PDFDocument.load(t),i=e.handle||`default`;f.set(i,r)}for(let t of l){if(/^[A-Z]$/.test(t)){let n=f.get(t);if(!n)return{stdout:``,stderr:`${e}: unknown handle '${t}'\n`,exitCode:1};let r=n.getPageCount(),i=Array.from({length:r},(e,t)=>t);(await o.copyPages(n,i)).forEach(e=>o.addPage(e));continue}let n=f.get(r[0].handle||`default`);if(!n)return{stdout:``,stderr:`${e}: no default input document\n`,exitCode:1};let i=n.getPageCount(),s=vg(t),c=yg(s,i).map(e=>e-1),l=await o.copyPages(n,c);for(let e of l)s.rotation&&e.setRotation(a.degrees(s.rotation)),o.addPage(e)}let p=await o.save();return await n.fs.writeFile(d,p),{stdout:`Created ${u}\n`,stderr:``,exitCode:0}}if(a===`rotate`){if(r.length>1)return{stdout:``,stderr:`${e}: rotate only supports a single input file\n`,exitCode:1};let a=await hg(),o=await n.fs.readFileBuffer(r[0].path),s=await a.PDFDocument.load(o),c=t.slice(i),l=c.indexOf(`output`);if(l===-1)return{stdout:``,stderr:`${e}: rotate operation requires 'output <filename>'\n`,exitCode:1};let u=c.slice(0,l),d=c[l+1];if(!d)return{stdout:``,stderr:`${e}: output filename not specified\n`,exitCode:1};let f=n.fs.resolvePath(n.cwd,d),p=s.getPageCount(),m=new Map;for(let t of u){let n=vg(t);if(!n.rotation)return{stdout:``,stderr:`${e}: rotation suffix required (right/left/down) for range '${t}'\n`,exitCode:1};let r=yg(n,p);for(let e of r)m.set(e-1,n.rotation)}let h=s.getPages();for(let[e,t]of m.entries()){let n=h[e],r=(n.getRotation().angle+t)%360;n.setRotation(a.degrees(r))}let g=await s.save();return await n.fs.writeFile(f,g),{stdout:`Created ${d}\n`,stderr:``,exitCode:0}}return{stdout:``,stderr:`${e}: unknown operation '${a}'\n`,exitCode:1}}catch(t){return{stdout:``,stderr:`${e}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}})}async function Sg(e,t,n){let r=t.FS;function i(e){try{r.stat(e)}catch{r.mkdirTree(e)}}async function a(t){i(t);let n;try{n=await e.readdir(t)}catch{return}for(let o of n){let n=t===`/`?`/${o}`:`${t}/${o}`;try{if((await e.stat(n)).isDirectory)await a(n);else{let a=await e.readFile(n);i(t),r.writeFile(n,a)}}catch{}}}for(let e of n)await a(e)}async function Cg(e,t,n){let r=t.FS;async function i(t){let n;try{n=r.readdir(t).filter(e=>e!==`.`&&e!==`..`)}catch{return}for(let a of n){let n=t===`/`?`/${a}`:`${t}/${a}`;try{let a=r.stat(n);if(r.isDir(a.mode))await e.mkdir(n,{recursive:!0}),await i(n);else{let i=new TextDecoder().decode(r.readFile(n));await e.mkdir(t,{recursive:!0}),await e.writeFile(n,i)}}catch{}}}for(let e of n)await i(e)}function wg(){return{stdout:`usage: python3 [-c code | script.py] [args...]
1439
+ `,stderr:``,exitCode:0}}function Tg(){return{stdout:`Python 3.12 (Pyodide)
1440
+ `,stderr:``,exitCode:0}}function Eg(e){return Ve(e,async(t,n)=>{if(t.includes(`--help`)||t.includes(`-h`))return wg();if(t.includes(`--version`)||t.includes(`-V`))return Tg();let r=``,i=`<stdin>`,a=[`python3`];if(t[0]===`-c`){if(!t[1])return{stdout:``,stderr:`${e}: option requires an argument -- 'c'\n`,exitCode:2};r=t[1],i=`-c`,a=[`-c`,...t.slice(2)]}else if(t.length>0&&!t[0].startsWith(`-`)){let o=t[0],s=n.fs.resolvePath(n.cwd,o);if(!await n.fs.exists(s))return{stdout:``,stderr:`${e}: can't open file '${o}': [Errno 2] No such file or directory\n`,exitCode:2};r=await n.fs.readFile(s),i=o,a=[o,...t.slice(1)]}else if(n.stdin.trim().length>0)r=n.stdin,i=`<stdin>`,a=[`<stdin>`];else if(t.length>0)return{stdout:``,stderr:`${e}: unsupported option '${t[0]}'\n`,exitCode:2};else return{stdout:``,stderr:`${e}: no input provided (use -c CODE, script path, or stdin)\n`,exitCode:2};try{let e=await rg(),t=[],o=[],s=[n.cwd,`/tmp`];if(i!==`<stdin>`&&i!==`[eval]`){let e=i.includes(`/`)?i.slice(0,i.lastIndexOf(`/`)):n.cwd;s.includes(e)||s.push(e)}await Sg(n.fs,e,s);try{e.FS.chdir(n.cwd)}catch{}e.setStdout({batched:e=>t.push(e+`
1441
1441
  `)}),e.setStderr({batched:e=>o.push(e+`
1442
- `)});let c=!1;e.setStdin({stdin:()=>c||!n.stdin?null:(c=!0,n.stdin)}),e.globals.set(`__slicc_code`,r),e.globals.set(`__slicc_filename`,i),e.globals.set(`__slicc_argv`,a),await e.runPythonAsync(Ih);let l=e.globals.get(`__slicc_exit_code`),u=typeof l==`number`?l:Number(l??1);try{e.runPython(`del __slicc_code, __slicc_filename, __slicc_argv, __slicc_exit_code`)}catch{}return await Sg(n.fs,e,s),{stdout:t.join(``),stderr:o.join(``),exitCode:u}}catch(t){return{stdout:``,stderr:`${e}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}})}function Eg(){return{stdout:`usage: serve [--entry <relative-path>] [--project] <directory>
1442
+ `)});let c=!1;e.setStdin({stdin:()=>c||!n.stdin?null:(c=!0,n.stdin)}),e.globals.set(`__slicc_code`,r),e.globals.set(`__slicc_filename`,i),e.globals.set(`__slicc_argv`,a),await e.runPythonAsync(Lh);let l=e.globals.get(`__slicc_exit_code`),u=typeof l==`number`?l:Number(l??1);try{e.runPython(`del __slicc_code, __slicc_filename, __slicc_argv, __slicc_exit_code`)}catch{}return await Cg(n.fs,e,s),{stdout:t.join(``),stderr:o.join(``),exitCode:u}}catch(t){return{stdout:``,stderr:`${e}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}})}function Dg(){return{stdout:`usage: serve [--entry <relative-path>] [--project] <directory>
1443
1443
 
1444
1444
  Serve a VFS directory in a new browser tab via the preview service worker.
1445
1445
  Defaults to index.html inside the target directory.
@@ -1448,23 +1448,23 @@ Page ranges:
1448
1448
  --project Enable project serve mode. Root-relative paths (/scripts/,
1449
1449
  /styles/, etc.) resolve against the served directory.
1450
1450
  Use this for frameworks like EDS that expect a local dev server.
1451
- `,stderr:``,exitCode:0}}function Dg(e){let t=`index.html`,n,r=!1;for(let i=0;i<e.length;i+=1){let a=e[i];if(a===`--entry`){let n=e[i+1];if(!n)return{entry:t,project:r,error:`serve: missing value for --entry
1451
+ `,stderr:``,exitCode:0}}function Og(e){let t=`index.html`,n,r=!1;for(let i=0;i<e.length;i+=1){let a=e[i];if(a===`--entry`){let n=e[i+1];if(!n)return{entry:t,project:r,error:`serve: missing value for --entry
1452
1452
  `};t=n,i+=1;continue}if(a.startsWith(`--entry=`)){t=a.slice(8);continue}if(a===`--project`){r=!0;continue}if(a.startsWith(`-`))return{entry:t,project:r,error:`serve: unknown option: ${a}\n`};if(n)return{entry:t,project:r,error:`serve: expected a single directory argument
1453
- `};n=a}return{directory:n,entry:t,project:r}}function Og(e,t){return Ve(`serve`,async(n,r)=>{if(n.length===0||n.includes(`--help`)||n.includes(`-h`))return Eg();let i=typeof window<`u`&&typeof window.open==`function`;if(!e&&!i)return{stdout:``,stderr:`serve: browser APIs are unavailable in this environment
1454
- `,exitCode:1};let a=Dg(n);if(a.error)return{stdout:``,stderr:a.error,exitCode:1};if(!a.directory)return Eg();if(!Xh(a.entry))return{stdout:``,stderr:`serve: invalid entry file: ${a.entry}\n`,exitCode:1};let o=r.fs.resolvePath(r.cwd,a.directory),s;try{s=await r.fs.stat(o)}catch{return{stdout:``,stderr:`serve: no such directory: ${a.directory}\n`,exitCode:1}}if(!s.isDirectory)return{stdout:``,stderr:`serve: not a directory: ${a.directory}\n`,exitCode:1};let c=Zh(o,a.entry),l;try{l=await r.fs.stat(c)}catch{return{stdout:``,stderr:`serve: entry file not found: ${c}\n`,exitCode:1}}if(!l.isFile)return{stdout:``,stderr:`serve: entry is not a file: ${c}\n`,exitCode:1};let u=Yh(c);if(a.project&&(u+=`?projectRoot=${encodeURIComponent(o)}`),e&&t){let t=await e.createPage(u);return{stdout:`serving ${o} → ${u} (targetId: ${t})\nUse: playwright-cli <command> --tab ${t}\n`,stderr:``,exitCode:0}}return typeof window<`u`&&typeof window.open==`function`&&window.open(u,`_blank`,`noopener,noreferrer`),{stdout:`serving ${o} → ${u}\n`,stderr:``,exitCode:0}})}function kg(){return{stdout:`usage: sqlite3 [database] [sql]
1455
- `,stderr:``,exitCode:0}}function Ag(e=`sqlite3`){return Ve(e,async(t,n)=>{if(t.includes(`--help`)||t.includes(`-h`))return kg();let r=`:memory:`,i=t;t.length>0&&!t[0].startsWith(`-`)&&(r=t[0],i=t.slice(1));let a=i.join(` `).trim()||n.stdin.trim();if(!a)return{stdout:``,stderr:`${e}: interactive mode is not supported; provide SQL as argument or stdin\n`,exitCode:1};try{let e=await eg(),t=r===`:memory:`,i=t?`:memory:`:n.fs.resolvePath(n.cwd,r),o;!t&&await n.fs.exists(i)&&(o=await n.fs.readFileBuffer(i));let s=o?new e.Database(o):new e.Database,c=s.exec(a);t||await n.fs.writeFile(i,s.export()),s.close();let l=[];for(let e of c)for(let t of e.values)l.push(t.map(qh).join(`|`));return{stdout:l.length>0?`${l.join(`
1456
- `)}\n`:``,stderr:``,exitCode:0}}catch(t){return{stdout:``,stderr:`${e}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}})}function jg(){return{stdout:`usage: uname
1457
- `,stderr:``,exitCode:0}}function Mg(){return Ve(`uname`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return jg();if(e.length>0)return{stdout:``,stderr:`uname: unsupported arguments
1453
+ `};n=a}return{directory:n,entry:t,project:r}}function kg(e,t){return Ve(`serve`,async(n,r)=>{if(n.length===0||n.includes(`--help`)||n.includes(`-h`))return Dg();let i=typeof window<`u`&&typeof window.open==`function`;if(!e&&!i)return{stdout:``,stderr:`serve: browser APIs are unavailable in this environment
1454
+ `,exitCode:1};let a=Og(n);if(a.error)return{stdout:``,stderr:a.error,exitCode:1};if(!a.directory)return Dg();if(!Zh(a.entry))return{stdout:``,stderr:`serve: invalid entry file: ${a.entry}\n`,exitCode:1};let o=r.fs.resolvePath(r.cwd,a.directory),s;try{s=await r.fs.stat(o)}catch{return{stdout:``,stderr:`serve: no such directory: ${a.directory}\n`,exitCode:1}}if(!s.isDirectory)return{stdout:``,stderr:`serve: not a directory: ${a.directory}\n`,exitCode:1};let c=Qh(o,a.entry),l;try{l=await r.fs.stat(c)}catch{return{stdout:``,stderr:`serve: entry file not found: ${c}\n`,exitCode:1}}if(!l.isFile)return{stdout:``,stderr:`serve: entry is not a file: ${c}\n`,exitCode:1};let u=Xh(c);if(a.project&&(u+=`?projectRoot=${encodeURIComponent(o)}`),e&&t){let t=await e.createPage(u);return{stdout:`serving ${o} → ${u} (targetId: ${t})\nUse: playwright-cli <command> --tab ${t}\n`,stderr:``,exitCode:0}}return typeof window<`u`&&typeof window.open==`function`&&window.open(u,`_blank`,`noopener,noreferrer`),{stdout:`serving ${o} → ${u}\n`,stderr:``,exitCode:0}})}function Ag(){return{stdout:`usage: sqlite3 [database] [sql]
1455
+ `,stderr:``,exitCode:0}}function jg(e=`sqlite3`){return Ve(e,async(t,n)=>{if(t.includes(`--help`)||t.includes(`-h`))return Ag();let r=`:memory:`,i=t;t.length>0&&!t[0].startsWith(`-`)&&(r=t[0],i=t.slice(1));let a=i.join(` `).trim()||n.stdin.trim();if(!a)return{stdout:``,stderr:`${e}: interactive mode is not supported; provide SQL as argument or stdin\n`,exitCode:1};try{let e=await tg(),t=r===`:memory:`,i=t?`:memory:`:n.fs.resolvePath(n.cwd,r),o;!t&&await n.fs.exists(i)&&(o=await n.fs.readFileBuffer(i));let s=o?new e.Database(o):new e.Database,c=s.exec(a);t||await n.fs.writeFile(i,s.export()),s.close();let l=[];for(let e of c)for(let t of e.values)l.push(t.map(Jh).join(`|`));return{stdout:l.length>0?`${l.join(`
1456
+ `)}\n`:``,stderr:``,exitCode:0}}catch(t){return{stdout:``,stderr:`${e}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}})}function Mg(){return{stdout:`usage: uname
1457
+ `,stderr:``,exitCode:0}}function Ng(){return Ve(`uname`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return Mg();if(e.length>0)return{stdout:``,stderr:`uname: unsupported arguments
1458
1458
  `,exitCode:1};let t=globalThis.navigator?.userAgent;return typeof t!=`string`||t.length===0?{stdout:``,stderr:`uname: navigator.userAgent is unavailable
1459
- `,exitCode:1}:{stdout:`${t}\n`,stderr:``,exitCode:0}})}function Ng(){return{stdout:`usage: man <topic>
1459
+ `,exitCode:1}:{stdout:`${t}\n`,stderr:``,exitCode:0}})}function Pg(){return{stdout:`usage: man <topic>
1460
1460
 
1461
1461
  Fetches documentation for a given topic from sliccy.com.
1462
- `,stderr:``,exitCode:0}}function Pg(e){return e.replace(/<[^>]*>/g,``).replace(/&amp;/g,`&`).replace(/&lt;/g,`<`).replace(/&gt;/g,`>`).replace(/&quot;/g,`"`).replace(/&#39;/g,`'`).replace(/&nbsp;/g,` `).trimEnd()}function Fg(){return Ve(`man`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return Ng();if(e.length===0)return{stdout:``,stderr:`What manual page do you want?
1462
+ `,stderr:``,exitCode:0}}function Fg(e){return e.replace(/<[^>]*>/g,``).replace(/&amp;/g,`&`).replace(/&lt;/g,`<`).replace(/&gt;/g,`>`).replace(/&quot;/g,`"`).replace(/&#39;/g,`'`).replace(/&nbsp;/g,` `).trimEnd()}function Ig(){return Ve(`man`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return Pg();if(e.length===0)return{stdout:``,stderr:`What manual page do you want?
1463
1463
  For example, try 'man commands'.
1464
- `,exitCode:1};let t=e.join(`-`),n=`https://www.sliccy.com/man/${t}.plain.html`;try{let e=await fetch(n);return e.status===404?{stdout:``,stderr:`No manual entry for ${t}\n`,exitCode:1}:e.ok?{stdout:Pg(await e.text())+`
1465
- `,stderr:``,exitCode:0}:{stdout:``,stderr:`man: failed to fetch manual page for ${t}: ${e.status} ${e.statusText}\n`,exitCode:1}}catch(e){return{stdout:``,stderr:`man: ${e.message||String(e)}\n`,exitCode:1}}})}function Ig(){return{stdout:`usage: unzip <archive.zip> [-d <destination>]
1466
- `,stderr:``,exitCode:0}}function Lg(){return Ve(`unzip`,async(e,t)=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return Ig();let n=`.`,r=[];for(let t=0;t<e.length;t++){let i=e[t];if(i===`-d`){n=e[t+1]??``,t++;continue}if(i.startsWith(`-`))return{stdout:``,stderr:`unzip: unsupported option ${i}\n`,exitCode:1};r.push(i)}if(r.length<1)return{stdout:``,stderr:`unzip: expected archive path
1467
- `,exitCode:1};let i=t.fs.resolvePath(t.cwd,r[0]),a=t.fs.resolvePath(t.cwd,n||`.`);await t.fs.mkdir(a,{recursive:!0});let o=P(await t.fs.readFileBuffer(i)),s=0;for(let[e,n]of Object.entries(o)){let r=e.replace(/\\/g,`/`);if(!r||r.endsWith(`/`))continue;let i=t.fs.resolvePath(a,r);if(!Gh(a,i))return{stdout:``,stderr:`unzip: blocked suspicious path ${e}\n`,exitCode:1};let o=Hh(i);o!==`/`&&await t.fs.mkdir(o,{recursive:!0}),await t.fs.writeFile(i,n),s++}return{stdout:`extracted ${s} file(s) to ${a}\n`,stderr:``,exitCode:0}})}function Rg(){return{stdout:`usage: webhook <command> [options]
1464
+ `,exitCode:1};let t=e.join(`-`),n=`https://www.sliccy.com/man/${t}.plain.html`;try{let e=await fetch(n);return e.status===404?{stdout:``,stderr:`No manual entry for ${t}\n`,exitCode:1}:e.ok?{stdout:Fg(await e.text())+`
1465
+ `,stderr:``,exitCode:0}:{stdout:``,stderr:`man: failed to fetch manual page for ${t}: ${e.status} ${e.statusText}\n`,exitCode:1}}catch(e){return{stdout:``,stderr:`man: ${e.message||String(e)}\n`,exitCode:1}}})}function Lg(){return{stdout:`usage: unzip <archive.zip> [-d <destination>]
1466
+ `,stderr:``,exitCode:0}}function Rg(){return Ve(`unzip`,async(e,t)=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return Lg();let n=`.`,r=[];for(let t=0;t<e.length;t++){let i=e[t];if(i===`-d`){n=e[t+1]??``,t++;continue}if(i.startsWith(`-`))return{stdout:``,stderr:`unzip: unsupported option ${i}\n`,exitCode:1};r.push(i)}if(r.length<1)return{stdout:``,stderr:`unzip: expected archive path
1467
+ `,exitCode:1};let i=t.fs.resolvePath(t.cwd,r[0]),a=t.fs.resolvePath(t.cwd,n||`.`);await t.fs.mkdir(a,{recursive:!0});let o=P(await t.fs.readFileBuffer(i)),s=0;for(let[e,n]of Object.entries(o)){let r=e.replace(/\\/g,`/`);if(!r||r.endsWith(`/`))continue;let i=t.fs.resolvePath(a,r);if(!Kh(a,i))return{stdout:``,stderr:`unzip: blocked suspicious path ${e}\n`,exitCode:1};let o=Uh(i);o!==`/`&&await t.fs.mkdir(o,{recursive:!0}),await t.fs.writeFile(i,n),s++}return{stdout:`extracted ${s} file(s) to ${a}\n`,stderr:``,exitCode:0}})}function zg(){return{stdout:`usage: webhook <command> [options]
1468
1468
 
1469
1469
  Commands:
1470
1470
  create --scoop <name> [--name <name>] [--filter <code>] Create a new webhook endpoint
@@ -1482,12 +1482,12 @@ Examples:
1482
1482
  webhook create --scoop slack-relay --name slack --filter "(e) => ({ text: e.body.text, user: e.body.user })"
1483
1483
  webhook list
1484
1484
  webhook delete abc123
1485
- `,stderr:``,exitCode:0}}async function zg(e,t,n){if(typeof chrome<`u`&&chrome?.runtime?.id)throw Error(`Webhooks are only available in CLI mode (npm run dev:full)`);let r={method:e,headers:{"Content-Type":`application/json`}};n&&(r.body=JSON.stringify(n));let i=await fetch(`/api/webhooks${t}`,r),a=await i.json().catch(()=>({}));return{ok:i.ok,status:i.status,data:a}}function Bg(){return Ve(`webhook`,async e=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return Rg();let t=e[0];try{switch(t){case`create`:{let t=`default`,n,r,i=e.indexOf(`--name`);i!==-1&&e[i+1]&&(t=e[i+1]);let a=e.indexOf(`--filter`);a!==-1&&e[a+1]&&(n=e[a+1]);let o=e.indexOf(`--scoop`);if(o!==-1&&e[o+1]&&(r=e[o+1]),!r)return{stdout:``,stderr:`webhook: --scoop is required (every webhook must route to a scoop)
1486
- `,exitCode:1};let{ok:s,data:c}=await zg(`POST`,``,{name:t,filter:n,scoop:r});if(!s)return{stdout:``,stderr:`webhook: failed to create webhook: ${c.error??`unknown error`}\n`,exitCode:1};let l=c,u=`Created webhook "${l.name}"\nID: ${l.id}\nURL: ${l.url}\n`;return l.scoop&&(u+=`Scoop: ${l.scoop}\n`),l.filter&&(u+=`Filter: ${l.filter}\n`),{stdout:u,stderr:``,exitCode:0}}case`list`:{let{ok:e,data:t}=await zg(`GET`,``);if(!e)return{stdout:``,stderr:`webhook: failed to list webhooks: ${t.error??`unknown error`}\n`,exitCode:1};let n=t;if(n.length===0)return{stdout:`No active webhooks
1485
+ `,stderr:``,exitCode:0}}async function Bg(e,t,n){if(typeof chrome<`u`&&chrome?.runtime?.id)throw Error(`Webhooks are only available in CLI mode (npm run dev:full)`);let r={method:e,headers:{"Content-Type":`application/json`}};n&&(r.body=JSON.stringify(n));let i=await fetch(`/api/webhooks${t}`,r),a=await i.json().catch(()=>({}));return{ok:i.ok,status:i.status,data:a}}function Vg(){return Ve(`webhook`,async e=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return zg();let t=e[0];try{switch(t){case`create`:{let t=`default`,n,r,i=e.indexOf(`--name`);i!==-1&&e[i+1]&&(t=e[i+1]);let a=e.indexOf(`--filter`);a!==-1&&e[a+1]&&(n=e[a+1]);let o=e.indexOf(`--scoop`);if(o!==-1&&e[o+1]&&(r=e[o+1]),!r)return{stdout:``,stderr:`webhook: --scoop is required (every webhook must route to a scoop)
1486
+ `,exitCode:1};let{ok:s,data:c}=await Bg(`POST`,``,{name:t,filter:n,scoop:r});if(!s)return{stdout:``,stderr:`webhook: failed to create webhook: ${c.error??`unknown error`}\n`,exitCode:1};let l=c,u=`Created webhook "${l.name}"\nID: ${l.id}\nURL: ${l.url}\n`;return l.scoop&&(u+=`Scoop: ${l.scoop}\n`),l.filter&&(u+=`Filter: ${l.filter}\n`),{stdout:u,stderr:``,exitCode:0}}case`list`:{let{ok:e,data:t}=await Bg(`GET`,``);if(!e)return{stdout:``,stderr:`webhook: failed to list webhooks: ${t.error??`unknown error`}\n`,exitCode:1};let n=t;if(n.length===0)return{stdout:`No active webhooks
1487
1487
  `,stderr:``,exitCode:0};let r=`Active webhooks:
1488
1488
  `;for(let e of n)r+=` ${e.id} ${e.name.padEnd(20)} ${e.url}`,e.scoop&&(r+=` -> ${e.scoop}`),e.filter&&(r+=` [filtered]`),r+=`
1489
1489
  `;return{stdout:r,stderr:``,exitCode:0}}case`delete`:{let t=e[1];if(!t)return{stdout:``,stderr:`webhook: delete requires an ID
1490
- `,exitCode:1};let{ok:n,status:r,data:i}=await zg(`DELETE`,`/${t}`);return n?{stdout:`Deleted webhook "${t}"\n`,stderr:``,exitCode:0}:r===404?{stdout:``,stderr:`webhook: webhook "${t}" not found\n`,exitCode:1}:{stdout:``,stderr:`webhook: failed to delete webhook: ${i.error??`unknown error`}\n`,exitCode:1}}default:return{stdout:``,stderr:`webhook: unknown command "${t}"\n`,exitCode:1}}}catch(e){return{stdout:``,stderr:`webhook: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}function Vg(){return{stdout:`usage: crontask <command> [options]
1490
+ `,exitCode:1};let{ok:n,status:r,data:i}=await Bg(`DELETE`,`/${t}`);return n?{stdout:`Deleted webhook "${t}"\n`,stderr:``,exitCode:0}:r===404?{stdout:``,stderr:`webhook: webhook "${t}" not found\n`,exitCode:1}:{stdout:``,stderr:`webhook: failed to delete webhook: ${i.error??`unknown error`}\n`,exitCode:1}}default:return{stdout:``,stderr:`webhook: unknown command "${t}"\n`,exitCode:1}}}catch(e){return{stdout:``,stderr:`webhook: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}function Hg(){return{stdout:`usage: crontask <command> [options]
1491
1491
 
1492
1492
  Commands:
1493
1493
  create [options] Create a new cron task
@@ -1519,16 +1519,16 @@ Examples:
1519
1519
  crontask create --name every-5min --scoop poller --cron "*/5 * * * *" --filter "() => ({ time: Date.now() })"
1520
1520
  crontask list
1521
1521
  crontask delete abc123
1522
- `,stderr:``,exitCode:0}}var Hg=typeof chrome<`u`&&!!chrome?.runtime?.id;function Ug(){return globalThis.__slicc_lickManager??null}var Wg=null;async function Gg(){if(Wg)return Wg;let{createLickManagerProxy:e}=await i(async()=>{let{createLickManagerProxy:e}=await import(`./lick-manager-proxy-CogaR9kt.js`);return{createLickManagerProxy:e}},[]);return Wg=e(),Wg}async function Kg(e,t,n){let r={method:e,headers:{"Content-Type":`application/json`}};n&&(r.body=JSON.stringify(n));let i=await fetch(`/api/crontasks${t}`,r),a=await i.json().catch(()=>({}));return{ok:i.ok,status:i.status,data:a}}function qg(){return Ve(`crontask`,async e=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return Vg();let t=e[0];try{switch(t){case`create`:{let t,n,r,i,a=e.indexOf(`--name`);a!==-1&&e[a+1]&&(t=e[a+1]);let o=e.indexOf(`--cron`);o!==-1&&e[o+1]&&(n=e[o+1]);let s=e.indexOf(`--filter`);s!==-1&&e[s+1]&&(r=e[s+1]);let c=e.indexOf(`--scoop`);if(c!==-1&&e[c+1]&&(i=e[c+1]),!t)return{stdout:``,stderr:`crontask: --name is required
1522
+ `,stderr:``,exitCode:0}}var Ug=typeof chrome<`u`&&!!chrome?.runtime?.id;function Wg(){return globalThis.__slicc_lickManager??null}var Gg=null;async function Kg(){if(Gg)return Gg;let{createLickManagerProxy:e}=await i(async()=>{let{createLickManagerProxy:e}=await import(`./lick-manager-proxy-CogaR9kt.js`);return{createLickManagerProxy:e}},[]);return Gg=e(),Gg}async function qg(e,t,n){let r={method:e,headers:{"Content-Type":`application/json`}};n&&(r.body=JSON.stringify(n));let i=await fetch(`/api/crontasks${t}`,r),a=await i.json().catch(()=>({}));return{ok:i.ok,status:i.status,data:a}}function Jg(){return Ve(`crontask`,async e=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return Hg();let t=e[0];try{switch(t){case`create`:{let t,n,r,i,a=e.indexOf(`--name`);a!==-1&&e[a+1]&&(t=e[a+1]);let o=e.indexOf(`--cron`);o!==-1&&e[o+1]&&(n=e[o+1]);let s=e.indexOf(`--filter`);s!==-1&&e[s+1]&&(r=e[s+1]);let c=e.indexOf(`--scoop`);if(c!==-1&&e[c+1]&&(i=e[c+1]),!t)return{stdout:``,stderr:`crontask: --name is required
1523
1523
  `,exitCode:1};if(!n)return{stdout:``,stderr:`crontask: --cron is required
1524
- `,exitCode:1};if(Hg){if(r)return{stdout:``,stderr:`crontask: --filter is not supported in extension mode (CSP restriction)
1525
- `,exitCode:1};let e=Ug(),a=e?await e.createCronTask(t,n,i):await(await Gg()).createCronTask(t,n,i),o=`Created cron task "${a.name}"\n`;return o+=`ID: ${a.id}\n`,o+=`Cron: ${a.cron}\n`,a.scoop&&(o+=`Scoop: ${a.scoop}\n`),a.nextRun&&(o+=`Next run: ${new Date(a.nextRun).toLocaleString()}\n`),{stdout:o,stderr:``,exitCode:0}}let{ok:l,data:u}=await Kg(`POST`,``,{name:t,cron:n,filter:r,scoop:i});if(!l)return{stdout:``,stderr:`crontask: failed to create: ${u.error??`unknown error`}\n`,exitCode:1};let d=u,f=`Created cron task "${d.name}"\n`;return f+=`ID: ${d.id}\n`,f+=`Cron: ${d.cron}\n`,d.scoop&&(f+=`Scoop: ${d.scoop}\n`),d.filter&&(f+=`Filter: ${d.filter}\n`),d.nextRun&&(f+=`Next run: ${new Date(d.nextRun).toLocaleString()}\n`),{stdout:f,stderr:``,exitCode:0}}case`list`:{if(Hg){let e=Ug(),t=e?e.listCronTasks():await(async()=>{let{listCronTasksAsync:e}=await i(async()=>{let{listCronTasksAsync:e}=await import(`./lick-manager-proxy-CogaR9kt.js`);return{listCronTasksAsync:e}},[]);return e()})();if(t.length===0)return{stdout:`No active cron tasks
1524
+ `,exitCode:1};if(Ug){if(r)return{stdout:``,stderr:`crontask: --filter is not supported in extension mode (CSP restriction)
1525
+ `,exitCode:1};let e=Wg(),a=e?await e.createCronTask(t,n,i):await(await Kg()).createCronTask(t,n,i),o=`Created cron task "${a.name}"\n`;return o+=`ID: ${a.id}\n`,o+=`Cron: ${a.cron}\n`,a.scoop&&(o+=`Scoop: ${a.scoop}\n`),a.nextRun&&(o+=`Next run: ${new Date(a.nextRun).toLocaleString()}\n`),{stdout:o,stderr:``,exitCode:0}}let{ok:l,data:u}=await qg(`POST`,``,{name:t,cron:n,filter:r,scoop:i});if(!l)return{stdout:``,stderr:`crontask: failed to create: ${u.error??`unknown error`}\n`,exitCode:1};let d=u,f=`Created cron task "${d.name}"\n`;return f+=`ID: ${d.id}\n`,f+=`Cron: ${d.cron}\n`,d.scoop&&(f+=`Scoop: ${d.scoop}\n`),d.filter&&(f+=`Filter: ${d.filter}\n`),d.nextRun&&(f+=`Next run: ${new Date(d.nextRun).toLocaleString()}\n`),{stdout:f,stderr:``,exitCode:0}}case`list`:{if(Ug){let e=Wg(),t=e?e.listCronTasks():await(async()=>{let{listCronTasksAsync:e}=await i(async()=>{let{listCronTasksAsync:e}=await import(`./lick-manager-proxy-CogaR9kt.js`);return{listCronTasksAsync:e}},[]);return e()})();if(t.length===0)return{stdout:`No active cron tasks
1526
1526
  `,stderr:``,exitCode:0};let n=`Active cron tasks:
1527
1527
  `;for(let e of t)n+=` ${e.id} ${e.name.padEnd(20)} ${e.cron.padEnd(15)}`,e.scoop&&(n+=` -> ${e.scoop}`),e.filter&&(n+=` [filtered]`),n+=` (${e.status})`,e.nextRun&&(n+=` next: ${new Date(e.nextRun).toLocaleString()}`),n+=`
1528
- `;return{stdout:n,stderr:``,exitCode:0}}let{ok:e,data:t}=await Kg(`GET`,``);if(!e)return{stdout:``,stderr:`crontask: failed to list: ${t.error??`unknown error`}\n`,exitCode:1};let n=t;if(n.length===0)return{stdout:`No active cron tasks
1528
+ `;return{stdout:n,stderr:``,exitCode:0}}let{ok:e,data:t}=await qg(`GET`,``);if(!e)return{stdout:``,stderr:`crontask: failed to list: ${t.error??`unknown error`}\n`,exitCode:1};let n=t;if(n.length===0)return{stdout:`No active cron tasks
1529
1529
  `,stderr:``,exitCode:0};let r=`Active cron tasks:
1530
1530
  `;for(let e of n)r+=` ${e.id} ${e.name.padEnd(20)} ${e.cron.padEnd(15)}`,e.scoop&&(r+=` -> ${e.scoop}`),e.filter&&(r+=` [filtered]`),r+=` (${e.status})`,e.nextRun&&(r+=` next: ${new Date(e.nextRun).toLocaleString()}`),r+=`
1531
- `;return{stdout:r,stderr:``,exitCode:0}}case`delete`:case`kill`:{let n=e[1];if(!n)return{stdout:``,stderr:`crontask: ${t} requires an ID\n`,exitCode:1};if(Hg){let e=Ug();return(e?await e.deleteCronTask(n):await(await Gg()).deleteCronTask(n))?{stdout:`Deleted cron task "${n}"\n`,stderr:``,exitCode:0}:{stdout:``,stderr:`crontask: task "${n}" not found\n`,exitCode:1}}let{ok:r,status:i,data:a}=await Kg(`DELETE`,`/${n}`);return r?{stdout:`Deleted cron task "${n}"\n`,stderr:``,exitCode:0}:i===404?{stdout:``,stderr:`crontask: task "${n}" not found\n`,exitCode:1}:{stdout:``,stderr:`crontask: failed to delete: ${a.error??`unknown error`}\n`,exitCode:1}}default:return{stdout:``,stderr:`crontask: unknown command "${t}"\n`,exitCode:1}}}catch(e){return{stdout:``,stderr:`crontask: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}var Jg=new Map,Yg=0;function Xg(){return Ve(`fswatch`,async e=>{let t=e[0];if(!t||t===`--help`)return{stdout:`usage: fswatch <command> [options]
1531
+ `;return{stdout:r,stderr:``,exitCode:0}}case`delete`:case`kill`:{let n=e[1];if(!n)return{stdout:``,stderr:`crontask: ${t} requires an ID\n`,exitCode:1};if(Ug){let e=Wg();return(e?await e.deleteCronTask(n):await(await Kg()).deleteCronTask(n))?{stdout:`Deleted cron task "${n}"\n`,stderr:``,exitCode:0}:{stdout:``,stderr:`crontask: task "${n}" not found\n`,exitCode:1}}let{ok:r,status:i,data:a}=await qg(`DELETE`,`/${n}`);return r?{stdout:`Deleted cron task "${n}"\n`,stderr:``,exitCode:0}:i===404?{stdout:``,stderr:`crontask: task "${n}" not found\n`,exitCode:1}:{stdout:``,stderr:`crontask: failed to delete: ${a.error??`unknown error`}\n`,exitCode:1}}default:return{stdout:``,stderr:`crontask: unknown command "${t}"\n`,exitCode:1}}}catch(e){return{stdout:``,stderr:`crontask: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}var Yg=new Map,Xg=0;function Zg(){return Ve(`fswatch`,async e=>{let t=e[0];if(!t||t===`--help`)return{stdout:`usage: fswatch <command> [options]
1532
1532
 
1533
1533
  Commands:
1534
1534
  create --path <path> --pattern <glob> [--scoop <name>] [--name <name>] Watch for file changes
@@ -1540,11 +1540,11 @@ Options:
1540
1540
  --pattern <glob> File pattern to match, e.g. "*.md", "*.bsh" (required)
1541
1541
  --scoop <name> Route change events to this scoop as lick events
1542
1542
  --name <name> Human-readable name for the watcher
1543
- `,stderr:``,exitCode:0};if(t===`list`){if(Jg.size===0)return{stdout:`No active file watchers.
1544
- `,stderr:``,exitCode:0};let e=``;for(let[,t]of Jg)e+=`ID: ${t.id}\n`,e+=` Name: ${t.name}\n`,e+=` Path: ${t.basePath}\n`,e+=` Pattern: ${t.pattern}\n`,t.scoop&&(e+=` Scoop: ${t.scoop}\n`),e+=` Created: ${t.createdAt}\n\n`;return{stdout:e,stderr:``,exitCode:0}}if(t===`delete`){let t=e[1];if(!t)return{stdout:``,stderr:`fswatch: delete requires an ID
1545
- `,exitCode:1};let n=Jg.get(t);return n?(n.unsubscribe(),Jg.delete(t),{stdout:`Deleted watcher "${n.name}" (${t})\n`,stderr:``,exitCode:0}):{stdout:``,stderr:`fswatch: watcher not found: ${t}\n`,exitCode:1}}if(t===`create`){let t=``,n=``,r=``,i=``;for(let a=1;a<e.length;a++)e[a]===`--path`&&e[a+1]?t=e[++a]:e[a]===`--pattern`&&e[a+1]?n=e[++a]:e[a]===`--scoop`&&e[a+1]?r=e[++a]:e[a]===`--name`&&e[a+1]&&(i=e[++a]);if(!t||!n)return{stdout:``,stderr:`fswatch: --path and --pattern are required
1543
+ `,stderr:``,exitCode:0};if(t===`list`){if(Yg.size===0)return{stdout:`No active file watchers.
1544
+ `,stderr:``,exitCode:0};let e=``;for(let[,t]of Yg)e+=`ID: ${t.id}\n`,e+=` Name: ${t.name}\n`,e+=` Path: ${t.basePath}\n`,e+=` Pattern: ${t.pattern}\n`,t.scoop&&(e+=` Scoop: ${t.scoop}\n`),e+=` Created: ${t.createdAt}\n\n`;return{stdout:e,stderr:``,exitCode:0}}if(t===`delete`){let t=e[1];if(!t)return{stdout:``,stderr:`fswatch: delete requires an ID
1545
+ `,exitCode:1};let n=Yg.get(t);return n?(n.unsubscribe(),Yg.delete(t),{stdout:`Deleted watcher "${n.name}" (${t})\n`,stderr:``,exitCode:0}):{stdout:``,stderr:`fswatch: watcher not found: ${t}\n`,exitCode:1}}if(t===`create`){let t=``,n=``,r=``,i=``;for(let a=1;a<e.length;a++)e[a]===`--path`&&e[a+1]?t=e[++a]:e[a]===`--pattern`&&e[a+1]?n=e[++a]:e[a]===`--scoop`&&e[a+1]?r=e[++a]:e[a]===`--name`&&e[a+1]&&(i=e[++a]);if(!t||!n)return{stdout:``,stderr:`fswatch: --path and --pattern are required
1546
1546
  `,exitCode:1};let a=RegExp(`^`+n.replace(/\./g,`\\.`).replace(/\*/g,`.*`)+`$`),o=e=>{let t=e.split(`/`).pop()??``;return a.test(t)},s=globalThis.__slicc_fs_watcher;if(!s)return{stdout:``,stderr:`fswatch: file system watcher not available
1547
- `,exitCode:1};let c=`fsw-${++Yg}`;i||=`${n} in ${t}`;let l=globalThis.__slicc_lick_handler,u=s.watch(t,o,e=>{l&&l({type:`fswatch`,fswatchId:c,fswatchName:i,targetScoop:r,timestamp:new Date().toISOString(),changes:e.map(e=>({type:e.type,path:e.path})),body:{changes:e.map(e=>({type:e.type,path:e.path}))}})});Jg.set(c,{id:c,name:i,basePath:t,pattern:n,scoop:r,unsubscribe:u,createdAt:new Date().toISOString()});let d=`Created file watcher "${i}"\n`;return d+=`ID: ${c}\n`,d+=`Path: ${t}\n`,d+=`Pattern: ${n}\n`,r&&(d+=`Scoop: ${r}\n`),{stdout:d,stderr:``,exitCode:0}}return{stdout:``,stderr:`fswatch: unknown command: ${t}\n`,exitCode:1}})}var Zg=class{listeners=new Map;lickHandler;fs;closeHandler;stopConeHandler;constructor(e,t,n,r){this.fs=e,this.lickHandler=t,this.closeHandler=n,this.stopConeHandler=r}createAPI(e){let t={name:e,lick:t=>{let n=typeof t==`string`?t:t.action,r=typeof t==`string`?void 0:t.data,i={type:`sprinkle`,sprinkleName:e,targetScoop:t_(e),timestamp:new Date().toISOString(),body:{action:n,data:r}};this.lickHandler(i)},on:(t,n)=>{let r=`${e}:${t}`,i=this.listeners.get(r);i||(i=new Set,this.listeners.set(r,i)),i.add(n)},off:(t,n)=>{let r=`${e}:${t}`;this.listeners.get(r)?.delete(n)},readFile:async e=>await this.fs.readFile(e,{encoding:`utf-8`}),writeFile:async(e,t)=>{await this.fs.writeFile(e,t)},readDir:async e=>(await this.fs.readDir(e)).map(e=>({name:e.name,type:e.type})),exists:async e=>this.fs.exists(e),stat:async e=>{let t=await this.fs.stat(e);return{type:t.type,size:t.size}},mkdir:async e=>{await this.fs.mkdir(e,{recursive:!0})},rm:async e=>{await this.fs.rm(e)},screenshot:async e=>{let n=t._container;if(!n)return``;let r=e?n.querySelector(e):n;if(!r)throw Error(`Element not found: `+(e||`container`));let i=r.getBoundingClientRect(),a=Math.ceil(i.width),o=Math.ceil(i.height);if(a===0||o===0)throw Error(`Element has zero dimensions`);let s=document.createElement(`canvas`),c=window.devicePixelRatio||1;s.width=a*c,s.height=o*c;let l=s.getContext(`2d`);l.scale(c,c);let u=r.cloneNode(!0),d=`<svg xmlns="http://www.w3.org/2000/svg" width="${a}" height="${o}"><foreignObject width="100%" height="100%">${new XMLSerializer().serializeToString(u)}</foreignObject></svg>`;return new Promise((e,t)=>{let n=new Image;n.onload=()=>{l.drawImage(n,0,0),e(s.toDataURL(`image/png`))},n.onerror=()=>t(Error(`Screenshot rendering failed`)),n.src=`data:image/svg+xml;charset=utf-8,`+encodeURIComponent(d)})},setState:t=>{try{localStorage.setItem(`slicc-sprinkle-state:${e}`,JSON.stringify(t))}catch{}},getState:()=>{try{let t=localStorage.getItem(`slicc-sprinkle-state:${e}`);return t?JSON.parse(t):null}catch{return null}},open:e=>{let t=/^https?:|^chrome-extension:/.test(e)?e:Yh(e);window.open(t,`_blank`)},close:()=>this.closeHandler(e),stopCone:()=>this.stopConeHandler()};return t}pushUpdate(e,t){let n=`${e}:update`,r=this.listeners.get(n);if(r)for(let e of r){let n=r;setTimeout(()=>{if(n.has(e))try{e(t)}catch{}},0)}}removeSprinkle(e){for(let t of this.listeners.keys())t.startsWith(`${e}:`)&&this.listeners.delete(t)}},Qg=`slicc-sprinkle-routes`;function $g(){try{let e=localStorage.getItem(Qg);return e?JSON.parse(e):{}}catch{return{}}}function e_(e){try{localStorage.setItem(Qg,JSON.stringify(e))}catch{}}function t_(e){return $g()[e]}function n_(e,t){let n=$g();n[e]=t,e_(n)}function r_(e){let t=$g();delete t[e],e_(t)}function i_(){return $g()}function a_(){return{stdout:`usage: sprinkle <subcommand> [args]
1547
+ `,exitCode:1};let c=`fsw-${++Xg}`;i||=`${n} in ${t}`;let l=globalThis.__slicc_lick_handler,u=s.watch(t,o,e=>{l&&l({type:`fswatch`,fswatchId:c,fswatchName:i,targetScoop:r,timestamp:new Date().toISOString(),changes:e.map(e=>({type:e.type,path:e.path})),body:{changes:e.map(e=>({type:e.type,path:e.path}))}})});Yg.set(c,{id:c,name:i,basePath:t,pattern:n,scoop:r,unsubscribe:u,createdAt:new Date().toISOString()});let d=`Created file watcher "${i}"\n`;return d+=`ID: ${c}\n`,d+=`Path: ${t}\n`,d+=`Pattern: ${n}\n`,r&&(d+=`Scoop: ${r}\n`),{stdout:d,stderr:``,exitCode:0}}return{stdout:``,stderr:`fswatch: unknown command: ${t}\n`,exitCode:1}})}var Qg=class{listeners=new Map;lickHandler;fs;closeHandler;stopConeHandler;constructor(e,t,n,r){this.fs=e,this.lickHandler=t,this.closeHandler=n,this.stopConeHandler=r}createAPI(e){let t={name:e,lick:t=>{let n=typeof t==`string`?t:t.action,r=typeof t==`string`?void 0:t.data,i={type:`sprinkle`,sprinkleName:e,targetScoop:n_(e),timestamp:new Date().toISOString(),body:{action:n,data:r}};this.lickHandler(i)},on:(t,n)=>{let r=`${e}:${t}`,i=this.listeners.get(r);i||(i=new Set,this.listeners.set(r,i)),i.add(n)},off:(t,n)=>{let r=`${e}:${t}`;this.listeners.get(r)?.delete(n)},readFile:async e=>await this.fs.readFile(e,{encoding:`utf-8`}),writeFile:async(e,t)=>{await this.fs.writeFile(e,t)},readDir:async e=>(await this.fs.readDir(e)).map(e=>({name:e.name,type:e.type})),exists:async e=>this.fs.exists(e),stat:async e=>{let t=await this.fs.stat(e);return{type:t.type,size:t.size}},mkdir:async e=>{await this.fs.mkdir(e,{recursive:!0})},rm:async e=>{await this.fs.rm(e)},screenshot:async e=>{let n=t._container;if(!n)return``;let r=e?n.querySelector(e):n;if(!r)throw Error(`Element not found: `+(e||`container`));let i=r.getBoundingClientRect(),a=Math.ceil(i.width),o=Math.ceil(i.height);if(a===0||o===0)throw Error(`Element has zero dimensions`);let s=document.createElement(`canvas`),c=window.devicePixelRatio||1;s.width=a*c,s.height=o*c;let l=s.getContext(`2d`);l.scale(c,c);let u=r.cloneNode(!0),d=`<svg xmlns="http://www.w3.org/2000/svg" width="${a}" height="${o}"><foreignObject width="100%" height="100%">${new XMLSerializer().serializeToString(u)}</foreignObject></svg>`;return new Promise((e,t)=>{let n=new Image;n.onload=()=>{l.drawImage(n,0,0),e(s.toDataURL(`image/png`))},n.onerror=()=>t(Error(`Screenshot rendering failed`)),n.src=`data:image/svg+xml;charset=utf-8,`+encodeURIComponent(d)})},setState:t=>{try{localStorage.setItem(`slicc-sprinkle-state:${e}`,JSON.stringify(t))}catch{}},getState:()=>{try{let t=localStorage.getItem(`slicc-sprinkle-state:${e}`);return t?JSON.parse(t):null}catch{return null}},open:e=>{let t=/^https?:|^chrome-extension:/.test(e)?e:Xh(e);window.open(t,`_blank`)},close:()=>this.closeHandler(e),stopCone:()=>this.stopConeHandler()};return t}pushUpdate(e,t){let n=`${e}:update`,r=this.listeners.get(n);if(r)for(let e of r){let n=r;setTimeout(()=>{if(n.has(e))try{e(t)}catch{}},0)}}removeSprinkle(e){for(let t of this.listeners.keys())t.startsWith(`${e}:`)&&this.listeners.delete(t)}},$g=`slicc-sprinkle-routes`;function e_(){try{let e=localStorage.getItem($g);return e?JSON.parse(e):{}}catch{return{}}}function t_(e){try{localStorage.setItem($g,JSON.stringify(e))}catch{}}function n_(e){return e_()[e]}function r_(e,t){let n=e_();n[e]=t,t_(n)}function i_(e){let t=e_();delete t[e],t_(t)}function a_(){return e_()}function o_(){return{stdout:`usage: sprinkle <subcommand> [args]
1548
1548
 
1549
1549
  list List available .shtml sprinkles
1550
1550
  open <name> Open a sprinkle by name
@@ -1557,23 +1557,23 @@ Options:
1557
1557
  chat <html> Show inline HTML in chat (Tool UI)
1558
1558
  Use data-action="name" on buttons for callbacks
1559
1559
  Pipe HTML: echo "<div>...</div>" | sprinkle chat
1560
- `,stderr:``,exitCode:0}}function o_(){return typeof window>`u`?null:window.__slicc_sprinkleManager??null}function s_(){return Ve(`sprinkle`,async(e,t)=>{if(e.length===0||e[0]===`--help`||e[0]===`-h`)return a_();let n=e[0];if(n===`chat`){let n=e.slice(1).join(` `);if(!n&&t.stdin&&(n=t.stdin),!n)return{stdout:``,stderr:`sprinkle chat: HTML content required
1560
+ `,stderr:``,exitCode:0}}function s_(){return typeof window>`u`?null:window.__slicc_sprinkleManager??null}function c_(){return Ve(`sprinkle`,async(e,t)=>{if(e.length===0||e[0]===`--help`||e[0]===`-h`)return o_();let n=e[0];if(n===`chat`){let n=e.slice(1).join(` `);if(!n&&t.stdin&&(n=t.stdin),!n)return{stdout:``,stderr:`sprinkle chat: HTML content required
1561
1561
  `,exitCode:1};let r=await v({html:n,onAction:async(e,t)=>({action:e,data:t})});return r===null?{stdout:``,stderr:`sprinkle chat: not in tool execution context
1562
1562
  `,exitCode:1}:{stdout:JSON.stringify(r)+`
1563
- `,stderr:``,exitCode:0}}let r=o_();if(!r)return{stdout:``,stderr:`sprinkle: sprinkle manager not initialized
1563
+ `,stderr:``,exitCode:0}}let r=s_();if(!r)return{stdout:``,stderr:`sprinkle: sprinkle manager not initialized
1564
1564
  `,exitCode:1};switch(n){case`list`:{await r.refresh();let e=r.available();if(e.length===0)return{stdout:`No .shtml sprinkles found.
1565
1565
  `,stderr:``,exitCode:0};let t=new Set(r.opened());return{stdout:e.map(e=>{let n=t.has(e.name)?` [open]`:``;return` ${e.name}${n} ${e.title} (${e.path})`}).join(`
1566
1566
  `)+`
1567
1567
  `,stderr:``,exitCode:0}}case`open`:{let t=e[1];if(!t)return{stdout:``,stderr:`sprinkle open: name required
1568
1568
  `,exitCode:1};try{return await r.open(t),{stdout:`Sprinkle "${t}" opened.\n`,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`sprinkle open: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}}case`close`:{let t=e[1];return t?(r.close(t),{stdout:`Sprinkle "${t}" closed.\n`,stderr:``,exitCode:0}):{stdout:``,stderr:`sprinkle close: name required
1569
- `,exitCode:1}}case`refresh`:{await r.refresh();let e=r.available().length;return{stdout:`Found ${e} sprinkle${e===1?``:`s`}.\n`,stderr:``,exitCode:0}}case`route`:{let t=e[1];if(!t){let e=i_(),t=Object.entries(e);return t.length===0?{stdout:`No sprinkle routes configured (all licks go to cone).
1569
+ `,exitCode:1}}case`refresh`:{await r.refresh();let e=r.available().length;return{stdout:`Found ${e} sprinkle${e===1?``:`s`}.\n`,stderr:``,exitCode:0}}case`route`:{let t=e[1];if(!t){let e=a_(),t=Object.entries(e);return t.length===0?{stdout:`No sprinkle routes configured (all licks go to cone).
1570
1570
  `,stderr:``,exitCode:0}:{stdout:`Sprinkle routes:
1571
1571
  `+t.map(([e,t])=>` ${e} -> ${t}`).join(`
1572
1572
  `)+`
1573
- `,stderr:``,exitCode:0}}if(e.includes(`--clear`))return r_(t),{stdout:`Route cleared for sprinkle "${t}" (licks will go to cone).\n`,stderr:``,exitCode:0};let n=e.indexOf(`--scoop`),r=n===-1?void 0:e[n+1];if(!r){let e=t_(t);return e?{stdout:`${t} -> ${e}\n`,stderr:``,exitCode:0}:{stdout:`${t} -> cone (default)\n`,stderr:``,exitCode:0}}return n_(t,r),{stdout:`Sprinkle "${t}" lick events will route to scoop "${r}".\n`,stderr:``,exitCode:0}}case`send`:{let t=e[1];if(!t)return{stdout:``,stderr:`sprinkle send: name required
1573
+ `,stderr:``,exitCode:0}}if(e.includes(`--clear`))return i_(t),{stdout:`Route cleared for sprinkle "${t}" (licks will go to cone).\n`,stderr:``,exitCode:0};let n=e.indexOf(`--scoop`),r=n===-1?void 0:e[n+1];if(!r){let e=n_(t);return e?{stdout:`${t} -> ${e}\n`,stderr:``,exitCode:0}:{stdout:`${t} -> cone (default)\n`,stderr:``,exitCode:0}}return r_(t,r),{stdout:`Sprinkle "${t}" lick events will route to scoop "${r}".\n`,stderr:``,exitCode:0}}case`send`:{let t=e[1];if(!t)return{stdout:``,stderr:`sprinkle send: name required
1574
1574
  `,exitCode:1};let n=e.slice(2).join(` `);if(!n)return{stdout:``,stderr:`sprinkle send: JSON data required
1575
1575
  `,exitCode:1};let i;try{i=JSON.parse(n)}catch{return{stdout:``,stderr:`sprinkle send: invalid JSON
1576
- `,exitCode:1}}return r.sendToSprinkle(t,i),{stdout:`Data sent to sprinkle "${t}".\n`,stderr:``,exitCode:0}}default:return{stdout:``,stderr:`sprinkle: unknown subcommand "${n}"\n`,exitCode:1}}})}function c_(){return`oauth-token — get an OAuth access token for a provider
1576
+ `,exitCode:1}}return r.sendToSprinkle(t,i),{stdout:`Data sent to sprinkle "${t}".\n`,stderr:``,exitCode:0}}default:return{stdout:``,stderr:`sprinkle: unknown subcommand "${n}"\n`,exitCode:1}}})}function l_(){return`oauth-token — get an OAuth access token for a provider
1577
1577
 
1578
1578
  Usage:
1579
1579
  oauth-token <providerId> Get token for a specific provider
@@ -1589,13 +1589,13 @@ on success.
1589
1589
  Examples:
1590
1590
  oauth-token adobe
1591
1591
  curl -H "Authorization: Bearer $(oauth-token adobe)" https://api.corp.com/data
1592
- `}function l_(){return Ve(`oauth-token`,async e=>{let{getOAuthAccountInfo:t,getSelectedProvider:n,getAccounts:r}=await i(async()=>{let{getOAuthAccountInfo:e,getSelectedProvider:t,getAccounts:n}=await import(`./provider-settings-BNHO2Tcv.js`).then(e=>e.l);return{getOAuthAccountInfo:e,getSelectedProvider:t,getAccounts:n}},__vite__mapDeps([9,4,1,10,11,12,13,14,15])),{getRegisteredProviderConfig:a,getRegisteredProviderIds:o}=await i(async()=>{let{getRegisteredProviderConfig:e,getRegisteredProviderIds:t}=await import(`./provider-settings-BNHO2Tcv.js`).then(e=>e.h);return{getRegisteredProviderConfig:e,getRegisteredProviderIds:t}},__vite__mapDeps([9,4,1,10,11,12,13,14,15]));if(e.includes(`--help`)||e.includes(`-h`))return{stdout:c_(),stderr:``,exitCode:0};if(e.includes(`--list`))return u_(r,o,a,t);let s,c=e.indexOf(`--provider`);if(c>=0){if(s=e[c+1],!s)return{stdout:``,stderr:`oauth-token: --provider requires a value
1592
+ `}function u_(){return Ve(`oauth-token`,async e=>{let{getOAuthAccountInfo:t,getSelectedProvider:n,getAccounts:r}=await i(async()=>{let{getOAuthAccountInfo:e,getSelectedProvider:t,getAccounts:n}=await import(`./provider-settings-BNHO2Tcv.js`).then(e=>e.l);return{getOAuthAccountInfo:e,getSelectedProvider:t,getAccounts:n}},__vite__mapDeps([9,4,1,10,11,12,13,14,15])),{getRegisteredProviderConfig:a,getRegisteredProviderIds:o}=await i(async()=>{let{getRegisteredProviderConfig:e,getRegisteredProviderIds:t}=await import(`./provider-settings-BNHO2Tcv.js`).then(e=>e.h);return{getRegisteredProviderConfig:e,getRegisteredProviderIds:t}},__vite__mapDeps([9,4,1,10,11,12,13,14,15]));if(e.includes(`--help`)||e.includes(`-h`))return{stdout:l_(),stderr:``,exitCode:0};if(e.includes(`--list`))return d_(r,o,a,t);let s,c=e.indexOf(`--provider`);if(c>=0){if(s=e[c+1],!s)return{stdout:``,stderr:`oauth-token: --provider requires a value
1593
1593
  `,exitCode:1}}else if(e.length>0)s=e[0];else{let e=n(),t=a(e);if(t?.isOAuth&&t.onOAuthLogin)s=e;else if(s=o().find(e=>{let t=a(e);return t?.isOAuth&&t.onOAuthLogin}),!s)return{stdout:``,stderr:`oauth-token: no OAuth providers configured
1594
1594
  `,exitCode:1}}let l=a(s);if(!l)return{stdout:``,stderr:`oauth-token: unknown provider "${s}"\n`,exitCode:1};if(!l.isOAuth||!l.onOAuthLogin)return{stdout:``,stderr:`oauth-token: provider "${s}" is not an OAuth provider\n`,exitCode:1};let u=t(s);if(u&&!u.expired)return{stdout:`${u.token}\n`,stderr:``,exitCode:0};try{let{createOAuthLauncher:e}=await i(async()=>{let{createOAuthLauncher:e}=await import(`./oauth-service-CfTUWB9P.js`);return{createOAuthLauncher:e}},[]),n=e();await l.onOAuthLogin(n,()=>{});let r=t(s);return r&&r.token?{stdout:`${r.token}\n`,stderr:``,exitCode:0}:(console.error(`[oauth-token] Provider ${s}: login completed but no token was saved`),{stdout:``,stderr:`oauth-token: login completed but no token was saved
1595
- `,exitCode:1})}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(`[oauth-token] Provider ${s}: login failed:`,t),{stdout:``,stderr:`oauth-token: login failed: ${t}\n`,exitCode:1}}})}function u_(e,t,n,r){let i=t().filter(e=>n(e)?.isOAuth);if(i.length===0)return{stdout:`No OAuth providers configured.
1595
+ `,exitCode:1})}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(`[oauth-token] Provider ${s}: login failed:`,t),{stdout:``,stderr:`oauth-token: login failed: ${t}\n`,exitCode:1}}})}function d_(e,t,n,r){let i=t().filter(e=>n(e)?.isOAuth);if(i.length===0)return{stdout:`No OAuth providers configured.
1596
1596
  `,stderr:``,exitCode:0};let a=[];for(let e of i){let t=r(e);if(!t)a.push(`${e} (no token)`);else if(t.expired){let n=t.userName?` as ${t.userName}`:``;a.push(`${e} (expired${n})`)}else{let n=[];if(t.userName?n.push(`logged in as ${t.userName}`):n.push(`logged in`),t.expiresAt){let e=t.expiresAt-Date.now();if(e>0){let t=Math.floor(e/36e5),r=Math.floor(e%36e5/6e4);t>0?n.push(`expires in ${t}h`):n.push(`expires in ${r}m`)}}a.push(`${e} (${n.join(`, `)})`)}}return{stdout:a.join(`
1597
1597
  `)+`
1598
- `,stderr:``,exitCode:0}}function d_(){return`secret — manage secrets for the fetch proxy
1598
+ `,stderr:``,exitCode:0}}function f_(){return`secret — manage secrets for the fetch proxy
1599
1599
 
1600
1600
  Usage:
1601
1601
  secret set <name> --domain <patterns> Show instructions for adding a secret
@@ -1612,19 +1612,19 @@ Examples:
1612
1612
  secret list
1613
1613
  secret delete GITHUB_TOKEN
1614
1614
  secret test GITHUB_TOKEN https://api.github.com/repos
1615
- `}async function f_(e,t,n){if(typeof chrome<`u`&&chrome?.runtime?.id)throw Error(`Secrets CLI is only available in CLI mode`);let r={method:e,headers:{"Content-Type":`application/json`}};n&&(r.body=JSON.stringify(n));let i=await fetch(`/api/secrets${t}`,r),a=await i.json().catch(()=>({}));return{ok:i.ok,status:i.status,data:a}}function p_(e){let t=e.indexOf(`--domain`);return t===-1||!e[t+1]?null:e[t+1].split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}function m_(){return Ve(`secret`,async e=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return{stdout:d_(),stderr:``,exitCode:0};let t=e[0];try{switch(t){case`set`:{let t=e[1];if(!t||t.startsWith(`-`))return{stdout:``,stderr:`secret: set requires a <name>
1616
- `,exitCode:1};let n=p_(e),r=n&&n.length>0?n.join(`,`):`<domain1,domain2>`,i=`To add the secret "${t}", use one of the following methods:\n\n`;return i+=` macOS Keychain (swift-server):
1615
+ `}async function p_(e,t,n){if(typeof chrome<`u`&&chrome?.runtime?.id)throw Error(`Secrets CLI is only available in CLI mode`);let r={method:e,headers:{"Content-Type":`application/json`}};n&&(r.body=JSON.stringify(n));let i=await fetch(`/api/secrets${t}`,r),a=await i.json().catch(()=>({}));return{ok:i.ok,status:i.status,data:a}}function m_(e){let t=e.indexOf(`--domain`);return t===-1||!e[t+1]?null:e[t+1].split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}function h_(){return Ve(`secret`,async e=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return{stdout:f_(),stderr:``,exitCode:0};let t=e[0];try{switch(t){case`set`:{let t=e[1];if(!t||t.startsWith(`-`))return{stdout:``,stderr:`secret: set requires a <name>
1616
+ `,exitCode:1};let n=m_(e),r=n&&n.length>0?n.join(`,`):`<domain1,domain2>`,i=`To add the secret "${t}", use one of the following methods:\n\n`;return i+=` macOS Keychain (swift-server):
1617
1617
  `,i+=` security add-generic-password -s ai.sliccy.slicc -a ${t} -w '<value>' -U -C note -j '${r}'\n\n`,i+=` Environment file (node-server):
1618
1618
  `,i+=` Add to ~/.slicc/secrets.env:
1619
1619
  `,i+=` ${t}=<value>\n`,i+=` ${t}_DOMAINS=${r}\n\n`,i+=`Then restart the server to pick up changes.
1620
- `,{stdout:i,stderr:``,exitCode:0}}case`list`:{let{ok:e,data:t}=await f_(`GET`,``);if(!e)return{stdout:``,stderr:`secret: failed to list secrets: ${t.error??`unknown error`}\n`,exitCode:1};let n=t;if(n.length===0)return{stdout:`No secrets stored
1620
+ `,{stdout:i,stderr:``,exitCode:0}}case`list`:{let{ok:e,data:t}=await p_(`GET`,``);if(!e)return{stdout:``,stderr:`secret: failed to list secrets: ${t.error??`unknown error`}\n`,exitCode:1};let n=t;if(n.length===0)return{stdout:`No secrets stored
1621
1621
  `,stderr:``,exitCode:0};let r=Math.max(4,...n.map(e=>e.name.length)),i=`${`NAME`.padEnd(r)} DOMAINS\n`;for(let e of n)i+=`${e.name.padEnd(r)} ${e.domains.join(`, `)}\n`;return{stdout:i,stderr:``,exitCode:0}}case`delete`:{let t=e[1];if(!t)return{stdout:``,stderr:`secret: delete requires a <name>
1622
1622
  `,exitCode:1};let n=`To delete the secret "${t}", use one of the following methods:\n\n`;return n+=` macOS Keychain (swift-server):
1623
1623
  `,n+=` security delete-generic-password -s ai.sliccy.slicc -a ${t}\n\n`,n+=` Environment file (node-server):
1624
1624
  `,n+=` Remove the ${t}= and ${t}_DOMAINS= lines from ~/.slicc/secrets.env\n\n`,n+=`Then restart the server to pick up changes.
1625
1625
  `,{stdout:n,stderr:``,exitCode:0}}case`test`:{let t=e[1],n=e[2];if(!t||!n)return{stdout:``,stderr:`secret: test requires <name> <url>
1626
- `,exitCode:1};let r;try{r=new URL(n).hostname}catch{return{stdout:``,stderr:`secret: invalid URL "${n}"\n`,exitCode:1}}let{ok:a,data:o}=await f_(`GET`,``);if(!a)return{stdout:``,stderr:`secret: failed to fetch secrets
1627
- `,exitCode:1};let s=o.find(e=>e.name===t);if(!s)return{stdout:``,stderr:`secret: no secret named "${t}"\n`,exitCode:1};let{isAllowedDomain:c}=await i(async()=>{let{isAllowedDomain:e}=await import(`./secret-masking-Bg1u5YcF.js`);return{isAllowedDomain:e}},[]);return c(s.domains,r)?{stdout:`✓ ${t} is allowed for ${r}\n`,stderr:``,exitCode:0}:{stdout:`✗ ${t} is NOT allowed for ${r}\n Allowed domains: ${s.domains.join(`, `)}\n`,stderr:``,exitCode:1}}default:return{stdout:``,stderr:`secret: unknown command "${t}"\n`,exitCode:1}}}catch(e){return{stdout:``,stderr:`secret: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}function h_(e,t,n={}){let r=new Map;for(let e of t)r.set(e.path,e);let i=new Set,a=[],o=[],s=[];for(let t of e){i.add(t.path);let e=r.get(t.path);e?e.size===t.size&&e.mtimeMs===t.mtimeMs?s.push(t.path):o.push(t.path):a.push(t.path)}let c=[];if(n.delete)for(let e of t)i.has(e.path)||c.push(e.path);return{toAdd:a,toUpdate:o,toDelete:c,toSkip:s}}var g_=null;function __(e){g_=e}function v_(){return g_?.()??null}function y_(e){let t={dryRun:!1,delete:!1,verbose:!1},n=[];for(let r of e)if(r===`--dry-run`||r===`-n`)t.dryRun=!0;else if(r===`--delete`)t.delete=!0;else if(r===`--verbose`||r===`-v`)t.verbose=!0;else if(r===`--help`||r===`-h`)return{error:`__help__`};else if(r.startsWith(`-`))return{error:`Unknown flag: ${r}`};else n.push(r);if(n.length!==2)return{error:`Expected exactly 2 arguments: <source> <dest>`};let[r,i]=n,a=b_(r),o=b_(i);return a&&o?{error:`Cannot sync between two remote paths — one side must be local`}:!a&&!o?{error:`One argument must be a remote path (runtime-id:/path)`}:o?{direction:`push`,localPath:r,remotePath:o.path,runtimeId:o.runtimeId,...t}:{direction:`pull`,localPath:i,remotePath:a.path,runtimeId:a.runtimeId,...t}}function b_(e){let t=e.indexOf(`:`);if(t<=0)return null;let n=e.slice(0,t),r=e.slice(t+1);return r.startsWith(`/`)?{runtimeId:n,path:r}:null}function x_(){return{stdout:`rsync — sync files between local VFS and a remote tray runtime
1626
+ `,exitCode:1};let r;try{r=new URL(n).hostname}catch{return{stdout:``,stderr:`secret: invalid URL "${n}"\n`,exitCode:1}}let{ok:a,data:o}=await p_(`GET`,``);if(!a)return{stdout:``,stderr:`secret: failed to fetch secrets
1627
+ `,exitCode:1};let s=o.find(e=>e.name===t);if(!s)return{stdout:``,stderr:`secret: no secret named "${t}"\n`,exitCode:1};let{isAllowedDomain:c}=await i(async()=>{let{isAllowedDomain:e}=await import(`./secret-masking-Bg1u5YcF.js`);return{isAllowedDomain:e}},[]);return c(s.domains,r)?{stdout:`✓ ${t} is allowed for ${r}\n`,stderr:``,exitCode:0}:{stdout:`✗ ${t} is NOT allowed for ${r}\n Allowed domains: ${s.domains.join(`, `)}\n`,stderr:``,exitCode:1}}default:return{stdout:``,stderr:`secret: unknown command "${t}"\n`,exitCode:1}}}catch(e){return{stdout:``,stderr:`secret: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}function g_(e,t,n={}){let r=new Map;for(let e of t)r.set(e.path,e);let i=new Set,a=[],o=[],s=[];for(let t of e){i.add(t.path);let e=r.get(t.path);e?e.size===t.size&&e.mtimeMs===t.mtimeMs?s.push(t.path):o.push(t.path):a.push(t.path)}let c=[];if(n.delete)for(let e of t)i.has(e.path)||c.push(e.path);return{toAdd:a,toUpdate:o,toDelete:c,toSkip:s}}var __=null;function v_(e){__=e}function y_(){return __?.()??null}function b_(e){let t={dryRun:!1,delete:!1,verbose:!1},n=[];for(let r of e)if(r===`--dry-run`||r===`-n`)t.dryRun=!0;else if(r===`--delete`)t.delete=!0;else if(r===`--verbose`||r===`-v`)t.verbose=!0;else if(r===`--help`||r===`-h`)return{error:`__help__`};else if(r.startsWith(`-`))return{error:`Unknown flag: ${r}`};else n.push(r);if(n.length!==2)return{error:`Expected exactly 2 arguments: <source> <dest>`};let[r,i]=n,a=x_(r),o=x_(i);return a&&o?{error:`Cannot sync between two remote paths — one side must be local`}:!a&&!o?{error:`One argument must be a remote path (runtime-id:/path)`}:o?{direction:`push`,localPath:r,remotePath:o.path,runtimeId:o.runtimeId,...t}:{direction:`pull`,localPath:i,remotePath:a.path,runtimeId:a.runtimeId,...t}}function x_(e){let t=e.indexOf(`:`);if(t<=0)return null;let n=e.slice(0,t),r=e.slice(t+1);return r.startsWith(`/`)?{runtimeId:n,path:r}:null}function S_(){return{stdout:`rsync — sync files between local VFS and a remote tray runtime
1628
1628
 
1629
1629
  Usage:
1630
1630
  rsync [flags] <local-path> <runtime-id>:<remote-path> # push
@@ -1640,21 +1640,21 @@ Examples:
1640
1640
  rsync /workspace follower-abc123:/workspace
1641
1641
  rsync --delete /shared leader:/shared
1642
1642
  rsync follower-abc123:/workspace/project /workspace/project
1643
- `,stderr:``,exitCode:0}}async function S_(e,t){if(!await e.exists(t))return[];let n=[];for await(let r of e.walk(t)){let i=r.slice(t.length).replace(/^\//,``);if(!i)continue;let a=await e.stat(r);n.push({path:i,size:a.size,mtimeMs:a.mtime})}return n}async function C_(e,t,n){let r=(await e(t,{op:`walk`,path:n}))[0];if(!r.ok){if(r.code===`ENOENT`)return[];throw Error(`Remote walk failed: ${r.error}`)}if(r.data.type!==`paths`)throw Error(`Unexpected walk response type`);let i=r.data.paths,a=[];for(let r of i){let i=r.slice(n.length).replace(/^\//,``);if(!i)continue;let o=(await e(t,{op:`stat`,path:r}))[0];o.ok&&o.data.type===`stat`&&a.push({path:i,size:o.data.stat.size,mtimeMs:o.data.stat.mtime})}return a}async function w_(e,t,n){let r=await e(t,{op:`readFile`,path:n,encoding:`binary`}),i=``;for(let e of r){if(!e.ok)throw Error(`Remote read failed: ${e.error}`);e.data.type===`file`&&(i+=e.data.content)}return i}async function T_(e,t,n){let r=await e(t,{op:`mkdir`,path:n,recursive:!0});if(!r[0].ok)throw Error(`Remote mkdir failed: ${r[0].error}`)}function E_(e){let t=e.lastIndexOf(`/`);return t<=0?`/`:e.slice(0,t)}async function D_(e,t,n){let r=[],{localPath:i,remotePath:a,runtimeId:o,verbose:s,dryRun:c}=n,l=h_(await S_(e,i),await C_(t,o,a),{delete:n.delete});if(s||c){for(let e of l.toAdd)r.push(`+ ${e}`);for(let e of l.toUpdate)r.push(`~ ${e}`);for(let e of l.toDelete)r.push(`- ${e}`);if(s)for(let e of l.toSkip)r.push(` ${e} (up to date)`)}let u=l.toAdd.length+l.toUpdate.length+l.toDelete.length;if(c)return r.push(`\n(dry run) ${u} file(s) would be transferred, ${l.toSkip.length} up to date`),{stdout:r.join(`
1643
+ `,stderr:``,exitCode:0}}async function C_(e,t){if(!await e.exists(t))return[];let n=[];for await(let r of e.walk(t)){let i=r.slice(t.length).replace(/^\//,``);if(!i)continue;let a=await e.stat(r);n.push({path:i,size:a.size,mtimeMs:a.mtime})}return n}async function w_(e,t,n){let r=(await e(t,{op:`walk`,path:n}))[0];if(!r.ok){if(r.code===`ENOENT`)return[];throw Error(`Remote walk failed: ${r.error}`)}if(r.data.type!==`paths`)throw Error(`Unexpected walk response type`);let i=r.data.paths,a=[];for(let r of i){let i=r.slice(n.length).replace(/^\//,``);if(!i)continue;let o=(await e(t,{op:`stat`,path:r}))[0];o.ok&&o.data.type===`stat`&&a.push({path:i,size:o.data.stat.size,mtimeMs:o.data.stat.mtime})}return a}async function T_(e,t,n){let r=await e(t,{op:`readFile`,path:n,encoding:`binary`}),i=``;for(let e of r){if(!e.ok)throw Error(`Remote read failed: ${e.error}`);e.data.type===`file`&&(i+=e.data.content)}return i}async function E_(e,t,n){let r=await e(t,{op:`mkdir`,path:n,recursive:!0});if(!r[0].ok)throw Error(`Remote mkdir failed: ${r[0].error}`)}function D_(e){let t=e.lastIndexOf(`/`);return t<=0?`/`:e.slice(0,t)}async function O_(e,t,n){let r=[],{localPath:i,remotePath:a,runtimeId:o,verbose:s,dryRun:c}=n,l=g_(await C_(e,i),await w_(t,o,a),{delete:n.delete});if(s||c){for(let e of l.toAdd)r.push(`+ ${e}`);for(let e of l.toUpdate)r.push(`~ ${e}`);for(let e of l.toDelete)r.push(`- ${e}`);if(s)for(let e of l.toSkip)r.push(` ${e} (up to date)`)}let u=l.toAdd.length+l.toUpdate.length+l.toDelete.length;if(c)return r.push(`\n(dry run) ${u} file(s) would be transferred, ${l.toSkip.length} up to date`),{stdout:r.join(`
1644
1644
  `)+`
1645
- `,stderr:``,exitCode:0};for(let n of[...l.toAdd,...l.toUpdate]){let s=i+`/`+n,c=a+`/`+n;await T_(t,o,E_(c));let l=await t(o,{op:`writeFile`,path:c,content:k_(await e.readFile(s,{encoding:`binary`})),encoding:`base64`});if(!l[0].ok)return{stdout:r.join(`
1645
+ `,stderr:``,exitCode:0};for(let n of[...l.toAdd,...l.toUpdate]){let s=i+`/`+n,c=a+`/`+n;await E_(t,o,D_(c));let l=await t(o,{op:`writeFile`,path:c,content:A_(await e.readFile(s,{encoding:`binary`})),encoding:`base64`});if(!l[0].ok)return{stdout:r.join(`
1646
1646
  `)+`
1647
1647
  `,stderr:`Error writing ${c}: ${l[0].error}\n`,exitCode:1}}for(let e of l.toDelete){let n=a+`/`+e,i=await t(o,{op:`rm`,path:n});if(!i[0].ok)return{stdout:r.join(`
1648
1648
  `)+`
1649
1649
  `,stderr:`Error deleting ${n}: ${i[0].error}\n`,exitCode:1}}return r.push(`${u} file(s) transferred, ${l.toSkip.length} up to date`),{stdout:r.join(`
1650
1650
  `)+`
1651
- `,stderr:``,exitCode:0}}async function O_(e,t,n){let r=[],{localPath:i,remotePath:a,runtimeId:o,verbose:s,dryRun:c}=n,l=h_(await C_(t,o,a),await S_(e,i),{delete:n.delete});if(s||c){for(let e of l.toAdd)r.push(`+ ${e}`);for(let e of l.toUpdate)r.push(`~ ${e}`);for(let e of l.toDelete)r.push(`- ${e}`);if(s)for(let e of l.toSkip)r.push(` ${e} (up to date)`)}let u=l.toAdd.length+l.toUpdate.length+l.toDelete.length;if(c)return r.push(`\n(dry run) ${u} file(s) would be transferred, ${l.toSkip.length} up to date`),{stdout:r.join(`
1651
+ `,stderr:``,exitCode:0}}async function k_(e,t,n){let r=[],{localPath:i,remotePath:a,runtimeId:o,verbose:s,dryRun:c}=n,l=g_(await w_(t,o,a),await C_(e,i),{delete:n.delete});if(s||c){for(let e of l.toAdd)r.push(`+ ${e}`);for(let e of l.toUpdate)r.push(`~ ${e}`);for(let e of l.toDelete)r.push(`- ${e}`);if(s)for(let e of l.toSkip)r.push(` ${e} (up to date)`)}let u=l.toAdd.length+l.toUpdate.length+l.toDelete.length;if(c)return r.push(`\n(dry run) ${u} file(s) would be transferred, ${l.toSkip.length} up to date`),{stdout:r.join(`
1652
1652
  `)+`
1653
- `,stderr:``,exitCode:0};for(let n of[...l.toAdd,...l.toUpdate]){let r=a+`/`+n,s=i+`/`+n,c=E_(s);await e.exists(c)||await e.mkdir(c,{recursive:!0});let l=A_(await w_(t,o,r));await e.writeFile(s,l)}for(let t of l.toDelete){let n=i+`/`+t;await e.rm(n)}return r.push(`${u} file(s) transferred, ${l.toSkip.length} up to date`),{stdout:r.join(`
1653
+ `,stderr:``,exitCode:0};for(let n of[...l.toAdd,...l.toUpdate]){let r=a+`/`+n,s=i+`/`+n,c=D_(s);await e.exists(c)||await e.mkdir(c,{recursive:!0});let l=j_(await T_(t,o,r));await e.writeFile(s,l)}for(let t of l.toDelete){let n=i+`/`+t;await e.rm(n)}return r.push(`${u} file(s) transferred, ${l.toSkip.length} up to date`),{stdout:r.join(`
1654
1654
  `)+`
1655
- `,stderr:``,exitCode:0}}function k_(e){let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function A_(e){let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}function j_(e={}){let t=e.fs,n=e.getSendFsRequest??v_;return Ve(`rsync`,async e=>{if(e.includes(`--help`)||e.includes(`-h`)||e.length===0)return x_();if(!t)return{stdout:``,stderr:`rsync: no filesystem available
1655
+ `,stderr:``,exitCode:0}}function A_(e){let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function j_(e){let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}function M_(e={}){let t=e.fs,n=e.getSendFsRequest??y_;return Ve(`rsync`,async e=>{if(e.includes(`--help`)||e.includes(`-h`)||e.length===0)return S_();if(!t)return{stdout:``,stderr:`rsync: no filesystem available
1656
1656
  `,exitCode:1};let r=n();if(!r)return{stdout:``,stderr:`rsync: not connected to a tray — rsync requires a tray connection
1657
- `,exitCode:1};let i=y_(e);if(`error`in i)return i.error===`__help__`?x_():{stdout:``,stderr:`rsync: ${i.error}\n`,exitCode:1};try{return i.direction===`push`?await D_(t,r,i):await O_(t,r,i)}catch(e){return{stdout:``,stderr:`rsync: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}var M_=[`/workspace/skills`];async function N_(e){let t=new Map;for(let n of M_)await e.exists(n)&&await P_(e,n,t);return await P_(e,`/`,t),t}async function P_(e,t,n){for await(let r of e.walk(t)){if(!r.endsWith(`.jsh`))continue;let e=F_(r);n.has(e)||n.set(e,r)}}function F_(e){let t=e.split(`/`).pop()??e;return t.endsWith(`.jsh`)?t.slice(0,-4):t}function I_(e={}){let t=e.scriptCatalog!==void 0||e.fs!==void 0?e:typeof e.walk==`function`&&typeof e.exists==`function`?{fs:e}:{};return Ve(`which`,async(e,n)=>{if(e.includes(`--help`)||e.includes(`-h`))return{stdout:`which - locate a command
1657
+ `,exitCode:1};let i=b_(e);if(`error`in i)return i.error===`__help__`?S_():{stdout:``,stderr:`rsync: ${i.error}\n`,exitCode:1};try{return i.direction===`push`?await O_(t,r,i):await k_(t,r,i)}catch(e){return{stdout:``,stderr:`rsync: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}var N_=[`/workspace/skills`];async function P_(e){let t=new Map;for(let n of N_)await e.exists(n)&&await F_(e,n,t);return await F_(e,`/`,t),t}async function F_(e,t,n){for await(let r of e.walk(t)){if(!r.endsWith(`.jsh`))continue;let e=I_(r);n.has(e)||n.set(e,r)}}function I_(e){let t=e.split(`/`).pop()??e;return t.endsWith(`.jsh`)?t.slice(0,-4):t}function L_(e={}){let t=e.scriptCatalog!==void 0||e.fs!==void 0?e:typeof e.walk==`function`&&typeof e.exists==`function`?{fs:e}:{};return Ve(`which`,async(e,n)=>{if(e.includes(`--help`)||e.includes(`-h`))return{stdout:`which - locate a command
1658
1658
 
1659
1659
  Usage: which <command> [command...]
1660
1660
 
@@ -1664,12 +1664,12 @@ Prints the path of the given command(s).
1664
1664
 
1665
1665
  Exit code 0 if all commands found, 1 if any not found.
1666
1666
  `,stderr:``,exitCode:0};if(e.length===0)return{stdout:``,stderr:`which: missing argument
1667
- `,exitCode:1};let r=n.getRegisteredCommands?.()??[],i=new Set(r),a=t.scriptCatalog?await t.scriptCatalog.getJshCommands():t.fs?await N_(t.fs):new Map,o=[],s=!0;for(let t of e)if(i.has(t))o.push(`/usr/bin/${t}`);else{let e=a.get(t);e?o.push(e):s=!1}return{stdout:o.length>0?o.join(`
1667
+ `,exitCode:1};let r=n.getRegisteredCommands?.()??[],i=new Set(r),a=t.scriptCatalog?await t.scriptCatalog.getJshCommands():t.fs?await P_(t.fs):new Map,o=[],s=!0;for(let t of e)if(i.has(t))o.push(`/usr/bin/${t}`);else{let e=a.get(t);e?o.push(e):s=!1}return{stdout:o.length>0?o.join(`
1668
1668
  `)+`
1669
- `:``,stderr:``,exitCode:+!s}})}async function L_(e,t,n,r){if((await e.fs.stat(t)).isFile)return r[n]=await e.fs.readFileBuffer(t),1;let i=await e.fs.readdir(t),a=0;for(let o of i){let i=Uh(t,o),s=n?`${n}/${o}`:o;a+=await L_(e,i,s,r)}return a}function R_(){return{stdout:`usage: zip [-r] <archive.zip> <path> [path...]
1670
- `,stderr:``,exitCode:0}}function z_(){return Ve(`zip`,async(e,t)=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return R_();let n=!1,r=[];for(let t of e){if(t===`-r`){n=!0;continue}if(t.startsWith(`-`))return{stdout:``,stderr:`zip: unsupported option ${t}\n`,exitCode:1};r.push(t)}if(r.length<2)return{stdout:``,stderr:`zip: expected archive path and at least one input path
1671
- `,exitCode:1};let i=t.fs.resolvePath(t.cwd,r[0]),a=r.slice(1),o={},s=0;for(let e of a){let r=t.fs.resolvePath(t.cwd,e),i=await t.fs.stat(r),a=(e.startsWith(`/`)?e.slice(1):e.replace(/^\.\//,``))||Vh(r);if(i.isDirectory&&!n)return{stdout:``,stderr:`zip: ${e} is a directory (use -r)\n`,exitCode:1};s+=await L_(t,r,a,o)}if(s===0)return{stdout:``,stderr:`zip: nothing to do
1672
- `,exitCode:1};let c=ae(o);return await t.fs.writeFile(i,c),{stdout:`created ${i} (${s} file(s))\n`,stderr:``,exitCode:0}})}function B_(){return{stdout:`screencapture - capture screen, window, or tab using browser screen sharing
1669
+ `:``,stderr:``,exitCode:+!s}})}async function R_(e,t,n,r){if((await e.fs.stat(t)).isFile)return r[n]=await e.fs.readFileBuffer(t),1;let i=await e.fs.readdir(t),a=0;for(let o of i){let i=Wh(t,o),s=n?`${n}/${o}`:o;a+=await R_(e,i,s,r)}return a}function z_(){return{stdout:`usage: zip [-r] <archive.zip> <path> [path...]
1670
+ `,stderr:``,exitCode:0}}function B_(){return Ve(`zip`,async(e,t)=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return z_();let n=!1,r=[];for(let t of e){if(t===`-r`){n=!0;continue}if(t.startsWith(`-`))return{stdout:``,stderr:`zip: unsupported option ${t}\n`,exitCode:1};r.push(t)}if(r.length<2)return{stdout:``,stderr:`zip: expected archive path and at least one input path
1671
+ `,exitCode:1};let i=t.fs.resolvePath(t.cwd,r[0]),a=r.slice(1),o={},s=0;for(let e of a){let r=t.fs.resolvePath(t.cwd,e),i=await t.fs.stat(r),a=(e.startsWith(`/`)?e.slice(1):e.replace(/^\.\//,``))||Hh(r);if(i.isDirectory&&!n)return{stdout:``,stderr:`zip: ${e} is a directory (use -r)\n`,exitCode:1};s+=await R_(t,r,a,o)}if(s===0)return{stdout:``,stderr:`zip: nothing to do
1672
+ `,exitCode:1};let c=ae(o);return await t.fs.writeFile(i,c),{stdout:`created ${i} (${s} file(s))\n`,stderr:``,exitCode:0}})}function V_(){return{stdout:`screencapture - capture screen, window, or tab using browser screen sharing
1673
1673
 
1674
1674
  Usage: screencapture [options] <output-file>
1675
1675
 
@@ -1685,57 +1685,57 @@ Examples:
1685
1685
  screencapture screenshot.png # Capture to file
1686
1686
  screencapture -c # Capture to clipboard
1687
1687
  screencapture -v capture.png # Capture and return for agent vision
1688
- `,stderr:``,exitCode:0}}function V_(e){let t=``,n=8192;for(let r=0;r<e.length;r+=n)t+=String.fromCharCode(...e.subarray(r,r+n));return btoa(t)}function H_(e){switch(e.split(`.`).pop()?.toLowerCase()){case`jpg`:case`jpeg`:return`image/jpeg`;case`webp`:return`image/webp`;default:return`image/png`}}async function U_(e,t){let n=await navigator.mediaDevices.getDisplayMedia({video:!0,audio:!1});try{let r=document.createElement(`video`);r.srcObject=n,r.muted=!0,r.playsInline=!0,await new Promise((e,t)=>{r.onloadedmetadata=()=>{r.play().then(()=>e()).catch(t)},r.onerror=()=>t(Error(`Failed to load video stream`))}),await new Promise(e=>requestAnimationFrame(e));let i=r.videoWidth,a=r.videoHeight,o=document.createElement(`canvas`);o.width=i,o.height=a;let s=o.getContext(`2d`);if(!s)throw Error(`Failed to get canvas context`);return s.drawImage(r,0,0,i,a),new Promise((n,r)=>{o.toBlob(e=>{e?n(e):r(Error(`Failed to create image blob`))},e,t)})}finally{n.getTracks().forEach(e=>e.stop())}}function W_(){return Ve(`screencapture`,async(e,t)=>{if(e.includes(`--help`)||e.includes(`-h`))return B_();if(typeof window>`u`||typeof navigator>`u`||typeof document>`u`)return{stdout:``,stderr:`screencapture: browser APIs are unavailable in this environment
1688
+ `,stderr:``,exitCode:0}}function H_(e){let t=``,n=8192;for(let r=0;r<e.length;r+=n)t+=String.fromCharCode(...e.subarray(r,r+n));return btoa(t)}function U_(e){switch(e.split(`.`).pop()?.toLowerCase()){case`jpg`:case`jpeg`:return`image/jpeg`;case`webp`:return`image/webp`;default:return`image/png`}}async function W_(e,t){let n=await navigator.mediaDevices.getDisplayMedia({video:!0,audio:!1});try{let r=document.createElement(`video`);r.srcObject=n,r.muted=!0,r.playsInline=!0,await new Promise((e,t)=>{r.onloadedmetadata=()=>{r.play().then(()=>e()).catch(t)},r.onerror=()=>t(Error(`Failed to load video stream`))}),await new Promise(e=>requestAnimationFrame(e));let i=r.videoWidth,a=r.videoHeight,o=document.createElement(`canvas`);o.width=i,o.height=a;let s=o.getContext(`2d`);if(!s)throw Error(`Failed to get canvas context`);return s.drawImage(r,0,0,i,a),new Promise((n,r)=>{o.toBlob(e=>{e?n(e):r(Error(`Failed to create image blob`))},e,t)})}finally{n.getTracks().forEach(e=>e.stop())}}function G_(){return Ve(`screencapture`,async(e,t)=>{if(e.includes(`--help`)||e.includes(`-h`))return V_();if(typeof window>`u`||typeof navigator>`u`||typeof document>`u`)return{stdout:``,stderr:`screencapture: browser APIs are unavailable in this environment
1689
1689
  `,exitCode:1};if(!navigator.mediaDevices?.getDisplayMedia)return{stdout:``,stderr:`screencapture: screen capture is not supported in this browser
1690
1690
  `,exitCode:1};let n=e.includes(`--clipboard`)||e.includes(`-c`),r=e.includes(`--view`)||e.includes(`-v`),i=[`--clipboard`,`-c`,`--view`,`-v`,`--help`,`-h`],a=e.indexOf(`--`),o=(a>=0?e.slice(a+1):e.filter(e=>!i.includes(e)))[0];if(!n&&!o)return{stdout:``,stderr:`screencapture: output file required (or use -c for clipboard)
1691
- `,exitCode:1};let s=o||`screenshot.png`,c=H_(s),l=c===`image/png`?1:.92,u;try{u=await U_(c,l)}catch(e){let t=e instanceof Error?e.message:String(e);return t.includes(`Permission denied`)||t.includes(`NotAllowedError`)?{stdout:``,stderr:`screencapture: user cancelled or permission denied
1692
- `,exitCode:1}:{stdout:``,stderr:`screencapture: ${t}\n`,exitCode:1}}let d=await u.arrayBuffer(),f=new Uint8Array(d);if(n)try{let e;if(c===`image/png`)e=u;else{let t=new Image,n=URL.createObjectURL(u);try{await new Promise((e,r)=>{t.onload=()=>e(),t.onerror=()=>r(Error(`Failed to load image for conversion`)),t.src=n})}finally{URL.revokeObjectURL(n)}let r=document.createElement(`canvas`);r.width=t.width,r.height=t.height;let i=r.getContext(`2d`);if(!i)throw Error(`Failed to get canvas context`);i.drawImage(t,0,0),e=await new Promise((e,t)=>{r.toBlob(n=>{n?e(n):t(Error(`Failed to create PNG blob`))},`image/png`)})}return await navigator.clipboard.write([new ClipboardItem({"image/png":e})]),{stdout:`captured ${Math.round(e.size/1024)} KB to clipboard\n`,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`screencapture: failed to copy to clipboard: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}let p=t.fs.resolvePath(t.cwd,s);try{await t.fs.writeFile(p,f)}catch(e){return{stdout:``,stderr:`screencapture: failed to write file: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}let m=Math.round(f.length/1024);return r?{stdout:`${p} (${m} KB)\n<img:data:${c};base64,${V_(f)}>`,stderr:``,exitCode:0}:{stdout:`captured ${m} KB to ${Vh(p)}\n`,stderr:``,exitCode:0}})}function G_(e){return e instanceof Error?e.message:String(e)}function K_(){return{stdout:`usage: pbcopy
1691
+ `,exitCode:1};let s=o||`screenshot.png`,c=U_(s),l=c===`image/png`?1:.92,u;try{u=await W_(c,l)}catch(e){let t=e instanceof Error?e.message:String(e);return t.includes(`Permission denied`)||t.includes(`NotAllowedError`)?{stdout:``,stderr:`screencapture: user cancelled or permission denied
1692
+ `,exitCode:1}:{stdout:``,stderr:`screencapture: ${t}\n`,exitCode:1}}let d=await u.arrayBuffer(),f=new Uint8Array(d);if(n)try{let e;if(c===`image/png`)e=u;else{let t=new Image,n=URL.createObjectURL(u);try{await new Promise((e,r)=>{t.onload=()=>e(),t.onerror=()=>r(Error(`Failed to load image for conversion`)),t.src=n})}finally{URL.revokeObjectURL(n)}let r=document.createElement(`canvas`);r.width=t.width,r.height=t.height;let i=r.getContext(`2d`);if(!i)throw Error(`Failed to get canvas context`);i.drawImage(t,0,0),e=await new Promise((e,t)=>{r.toBlob(n=>{n?e(n):t(Error(`Failed to create PNG blob`))},`image/png`)})}return await navigator.clipboard.write([new ClipboardItem({"image/png":e})]),{stdout:`captured ${Math.round(e.size/1024)} KB to clipboard\n`,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`screencapture: failed to copy to clipboard: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}let p=t.fs.resolvePath(t.cwd,s);try{await t.fs.writeFile(p,f)}catch(e){return{stdout:``,stderr:`screencapture: failed to write file: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}let m=Math.round(f.length/1024);return r?{stdout:`${p} (${m} KB)\n<img:data:${c};base64,${H_(f)}>`,stderr:``,exitCode:0}:{stdout:`captured ${m} KB to ${Hh(p)}\n`,stderr:``,exitCode:0}})}function K_(e){return e instanceof Error?e.message:String(e)}function q_(){return{stdout:`usage: pbcopy
1693
1693
 
1694
1694
  Copy stdin to the clipboard.
1695
1695
  Example: echo hello | pbcopy
1696
- `,stderr:``,exitCode:0}}function q_(){return{stdout:`usage: pbpaste
1696
+ `,stderr:``,exitCode:0}}function J_(){return{stdout:`usage: pbpaste
1697
1697
 
1698
1698
  Paste clipboard contents to stdout.
1699
- `,stderr:``,exitCode:0}}function J_(e){return{stdout:`usage: ${e} [-i|-o]\n\n -i Force copy mode (read from stdin)
1699
+ `,stderr:``,exitCode:0}}function Y_(e){return{stdout:`usage: ${e} [-i|-o]\n\n -i Force copy mode (read from stdin)
1700
1700
  -o Force paste mode (write to stdout)
1701
1701
  (default) Auto-detect: stdin present = copy, no stdin = paste
1702
- Example: echo hello | ${e}\n Example: ${e} -o > file.txt\n`,stderr:``,exitCode:0}}async function Y_(e,t){if(!globalThis.navigator?.clipboard)return{stdout:``,stderr:`${t}: clipboard API is unavailable\n`,exitCode:1};try{return await navigator.clipboard.writeText(e),{stdout:``,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`${t}: failed to write to clipboard: ${G_(e)}\n`,exitCode:1}}}async function X_(e){if(!globalThis.navigator?.clipboard)return{stdout:``,stderr:`${e}: clipboard API is unavailable\n`,exitCode:1};try{return{stdout:await navigator.clipboard.readText(),stderr:``,exitCode:0}}catch(t){return{stdout:``,stderr:`${e}: failed to read from clipboard: ${G_(t)}\n`,exitCode:1}}}function Z_(){return Ve(`pbcopy`,async(e,t)=>e.includes(`--help`)||e.includes(`-h`)?K_():Y_(t.stdin,`pbcopy`))}function Q_(){return Ve(`pbpaste`,async e=>e.includes(`--help`)||e.includes(`-h`)?q_():X_(`pbpaste`))}function $_(e){return Ve(e,async(t,n)=>{if(t.includes(`--help`)||t.includes(`-h`))return J_(e);let r=t.includes(`-i`),i=t.includes(`-o`);return r&&i?{stdout:``,stderr:`${e}: cannot use both -i and -o\n`,exitCode:1}:i?X_(e):r||n.stdin.length>0?Y_(n.stdin,e):X_(e)})}function ev(){return{stdout:`usage: say [-v voice] [-r rate] [-l lang] [--list] <text>
1702
+ Example: echo hello | ${e}\n Example: ${e} -o > file.txt\n`,stderr:``,exitCode:0}}async function X_(e,t){if(!globalThis.navigator?.clipboard)return{stdout:``,stderr:`${t}: clipboard API is unavailable\n`,exitCode:1};try{return await navigator.clipboard.writeText(e),{stdout:``,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`${t}: failed to write to clipboard: ${K_(e)}\n`,exitCode:1}}}async function Z_(e){if(!globalThis.navigator?.clipboard)return{stdout:``,stderr:`${e}: clipboard API is unavailable\n`,exitCode:1};try{return{stdout:await navigator.clipboard.readText(),stderr:``,exitCode:0}}catch(t){return{stdout:``,stderr:`${e}: failed to read from clipboard: ${K_(t)}\n`,exitCode:1}}}function Q_(){return Ve(`pbcopy`,async(e,t)=>e.includes(`--help`)||e.includes(`-h`)?q_():X_(t.stdin,`pbcopy`))}function $_(){return Ve(`pbpaste`,async e=>e.includes(`--help`)||e.includes(`-h`)?J_():Z_(`pbpaste`))}function ev(e){return Ve(e,async(t,n)=>{if(t.includes(`--help`)||t.includes(`-h`))return Y_(e);let r=t.includes(`-i`),i=t.includes(`-o`);return r&&i?{stdout:``,stderr:`${e}: cannot use both -i and -o\n`,exitCode:1}:i?Z_(e):r||n.stdin.length>0?X_(n.stdin,e):Z_(e)})}function tv(){return{stdout:`usage: say [-v voice] [-r rate] [-l lang] [--list] <text>
1703
1703
 
1704
1704
  Speaks the given text using the Web Speech API.
1705
1705
  -v voice Voice name (partial match supported)
1706
1706
  -r rate Speech rate (0.1 to 10, default 1)
1707
1707
  -l lang Language tag (required, BCP 47, e.g. en-US, de-DE, fr-FR)
1708
1708
  --list List available voices
1709
- `,stderr:``,exitCode:0}}var tv=!1,nv=null;function rv(){return tv?Promise.resolve(speechSynthesis.getVoices()):(nv||=new Promise(e=>{let t=speechSynthesis.getVoices();if(t.length>0){tv=!0,e(t);return}let n=()=>{tv=!0,speechSynthesis.removeEventListener(`voiceschanged`,n),e(speechSynthesis.getVoices())};speechSynthesis.addEventListener(`voiceschanged`,n),setTimeout(()=>{speechSynthesis.removeEventListener(`voiceschanged`,n),tv=!0,e(speechSynthesis.getVoices())},1e3)}),nv)}function iv(){return Ve(`say`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return ev();if(typeof window>`u`||typeof speechSynthesis>`u`)return{stdout:``,stderr:`say: Web Speech API unavailable in this environment
1710
- `,exitCode:1};if(e.includes(`--list`))return{stdout:(await rv()).map(e=>`${e.name} (${e.lang})${e.default?` [default]`:``}`).join(`
1709
+ `,stderr:``,exitCode:0}}var nv=!1,rv=null;function iv(){return nv?Promise.resolve(speechSynthesis.getVoices()):(rv||=new Promise(e=>{let t=speechSynthesis.getVoices();if(t.length>0){nv=!0,e(t);return}let n=()=>{nv=!0,speechSynthesis.removeEventListener(`voiceschanged`,n),e(speechSynthesis.getVoices())};speechSynthesis.addEventListener(`voiceschanged`,n),setTimeout(()=>{speechSynthesis.removeEventListener(`voiceschanged`,n),nv=!0,e(speechSynthesis.getVoices())},1e3)}),rv)}function av(){return Ve(`say`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return tv();if(typeof window>`u`||typeof speechSynthesis>`u`)return{stdout:``,stderr:`say: Web Speech API unavailable in this environment
1710
+ `,exitCode:1};if(e.includes(`--list`))return{stdout:(await iv()).map(e=>`${e.name} (${e.lang})${e.default?` [default]`:``}`).join(`
1711
1711
  `)+`
1712
1712
  `,stderr:``,exitCode:0};let t=null,n=1,r=null,i=[];for(let a=0;a<e.length;a++){let o=e[a];if(o===`-v`){if(a+1>=e.length||e[a+1].startsWith(`-`))return{stdout:``,stderr:`say: -v requires a voice name
1713
1713
  `,exitCode:1};t=e[++a]}else if(o===`-r`){if(a+1>=e.length||e[a+1].startsWith(`-`))return{stdout:``,stderr:`say: -r requires a rate value
1714
1714
  `,exitCode:1};if(n=parseFloat(e[++a]),isNaN(n)||n<.1||n>10)return{stdout:``,stderr:`say: rate must be between 0.1 and 10
1715
1715
  `,exitCode:1}}else if(o===`-l`){if(a+1>=e.length||e[a+1].startsWith(`-`))return{stdout:``,stderr:`say: -l requires a language tag
1716
- `,exitCode:1};r=e[++a]}else if(o.startsWith(`-`)&&o!==`--list`)return{stdout:``,stderr:`say: unknown option: ${o}\n`,exitCode:1};else o.startsWith(`-`)||i.push(o)}let a=i.join(` `);if(!a)return ev();if(!r)return{stdout:``,stderr:`say: -l language tag is required
1717
- `,exitCode:1};let o=new SpeechSynthesisUtterance(a);if(o.rate=n,o.lang=r,t){let e=(await rv()).find(e=>e.name.toLowerCase().includes(t.toLowerCase()));if(e)o.voice=e;else return{stdout:``,stderr:`say: voice "${t}" not found. Use --list to see available voices.\n`,exitCode:1}}return new Promise(e=>{o.onend=()=>{e({stdout:``,stderr:``,exitCode:0})},o.onerror=t=>{e({stdout:``,stderr:`say: speech synthesis error: ${t.error}\n`,exitCode:1})},speechSynthesis.speak(o)})})}function av(){return{stdout:`usage: afplay [-v volume] [-r rate] <file>
1716
+ `,exitCode:1};r=e[++a]}else if(o.startsWith(`-`)&&o!==`--list`)return{stdout:``,stderr:`say: unknown option: ${o}\n`,exitCode:1};else o.startsWith(`-`)||i.push(o)}let a=i.join(` `);if(!a)return tv();if(!r)return{stdout:``,stderr:`say: -l language tag is required
1717
+ `,exitCode:1};let o=new SpeechSynthesisUtterance(a);if(o.rate=n,o.lang=r,t){let e=(await iv()).find(e=>e.name.toLowerCase().includes(t.toLowerCase()));if(e)o.voice=e;else return{stdout:``,stderr:`say: voice "${t}" not found. Use --list to see available voices.\n`,exitCode:1}}return new Promise(e=>{o.onend=()=>{e({stdout:``,stderr:``,exitCode:0})},o.onerror=t=>{e({stdout:``,stderr:`say: speech synthesis error: ${t.error}\n`,exitCode:1})},speechSynthesis.speak(o)})})}function ov(){return{stdout:`usage: afplay [-v volume] [-r rate] <file>
1718
1718
 
1719
1719
  Plays an audio file using the Web Audio API.
1720
1720
  -v volume Volume level (0 to 1, default 1)
1721
1721
  -r rate Playback rate (0.25 to 4, default 1)
1722
- `,stderr:``,exitCode:0}}var ov=null;function sv(){return(!ov||ov.state===`closed`)&&(ov=new AudioContext),ov}async function cv(e,t,n,r){if(typeof window>`u`||typeof AudioContext>`u`)return{stdout:``,stderr:`afplay: Web Audio API unavailable in this environment
1723
- `,exitCode:1};let i=r.fs.resolvePath(r.cwd,e),a;try{a=new Uint8Array(await r.fs.readFileBuffer(i))}catch{return{stdout:``,stderr:`afplay: cannot open ${e}: No such file\n`,exitCode:1}}if(!Jh(i).startsWith(`audio/`))return{stdout:``,stderr:`afplay: ${e} is not an audio file\n`,exitCode:1};try{let e=sv();e.state===`suspended`&&await e.resume();let r=new ArrayBuffer(a.byteLength);new Uint8Array(r).set(a);let i=await e.decodeAudioData(r),o=e.createBufferSource();o.buffer=i,o.playbackRate.value=n;let s=e.createGain();return s.gain.value=t,o.connect(s),s.connect(e.destination),new Promise(e=>{o.onended=()=>{e({stdout:``,stderr:``,exitCode:0})},o.start()})}catch(t){return{stdout:``,stderr:`afplay: failed to play ${e}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}}function lv(){return Ve(`afplay`,async(e,t)=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return av();let n=1,r=1,i=null;for(let t=0;t<e.length;t++){let a=e[t];if(a===`-v`){if(t+1>=e.length||e[t+1].startsWith(`-`))return{stdout:``,stderr:`afplay: -v requires a volume value
1722
+ `,stderr:``,exitCode:0}}var sv=null;function cv(){return(!sv||sv.state===`closed`)&&(sv=new AudioContext),sv}async function lv(e,t,n,r){if(typeof window>`u`||typeof AudioContext>`u`)return{stdout:``,stderr:`afplay: Web Audio API unavailable in this environment
1723
+ `,exitCode:1};let i=r.fs.resolvePath(r.cwd,e),a;try{a=new Uint8Array(await r.fs.readFileBuffer(i))}catch{return{stdout:``,stderr:`afplay: cannot open ${e}: No such file\n`,exitCode:1}}if(!Yh(i).startsWith(`audio/`))return{stdout:``,stderr:`afplay: ${e} is not an audio file\n`,exitCode:1};try{let e=cv();e.state===`suspended`&&await e.resume();let r=new ArrayBuffer(a.byteLength);new Uint8Array(r).set(a);let i=await e.decodeAudioData(r),o=e.createBufferSource();o.buffer=i,o.playbackRate.value=n;let s=e.createGain();return s.gain.value=t,o.connect(s),s.connect(e.destination),new Promise(e=>{o.onended=()=>{e({stdout:``,stderr:``,exitCode:0})},o.start()})}catch(t){return{stdout:``,stderr:`afplay: failed to play ${e}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}}function uv(){return Ve(`afplay`,async(e,t)=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return ov();let n=1,r=1,i=null;for(let t=0;t<e.length;t++){let a=e[t];if(a===`-v`){if(t+1>=e.length||e[t+1].startsWith(`-`))return{stdout:``,stderr:`afplay: -v requires a volume value
1724
1724
  `,exitCode:1};if(n=parseFloat(e[++t]),isNaN(n)||n<0||n>1)return{stdout:``,stderr:`afplay: volume must be between 0 and 1
1725
1725
  `,exitCode:1}}else if(a===`-r`){if(t+1>=e.length||e[t+1].startsWith(`-`))return{stdout:``,stderr:`afplay: -r requires a rate value
1726
1726
  `,exitCode:1};if(r=parseFloat(e[++t]),isNaN(r)||r<.25||r>4)return{stdout:``,stderr:`afplay: rate must be between 0.25 and 4
1727
1727
  `,exitCode:1}}else if(a.startsWith(`-`))return{stdout:``,stderr:`afplay: unknown option: ${a}\n`,exitCode:1};else{if(i!==null)return{stdout:``,stderr:`afplay: only one file can be specified
1728
- `,exitCode:1};i=a}}return i?cv(i,n,r,t):av()})}function uv(){return Ve(`chime`,async(e,t)=>e.includes(`--help`)||e.includes(`-h`)?{stdout:`usage: chime
1728
+ `,exitCode:1};i=a}}return i?lv(i,n,r,t):ov()})}function dv(){return Ve(`chime`,async(e,t)=>e.includes(`--help`)||e.includes(`-h`)?{stdout:`usage: chime
1729
1729
 
1730
1730
  Plays a notification chime sound.
1731
1731
  Alias for: afplay /shared/sounds/chime.mp3
1732
- `,stderr:``,exitCode:0}:cv(`/shared/sounds/chime.mp3`,1,1,t))}function dv(){return Ve(`debug`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return{stdout:`usage: debug [on|off]
1732
+ `,stderr:``,exitCode:0}:lv(`/shared/sounds/chime.mp3`,1,1,t))}function fv(){return Ve(`debug`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return{stdout:`usage: debug [on|off]
1733
1733
 
1734
1734
  Toggle debug tabs (Terminal, Memory) in extension mode.
1735
1735
  Without arguments, shows current state.
1736
1736
  `,stderr:``,exitCode:0};let t=e[0]?.toLowerCase();if(t!==`on`&&t!==`off`&&t!==void 0)return{stdout:``,stderr:`debug: unknown argument '${t}' (use 'on' or 'off')\n`,exitCode:1};if(!t)try{let e=localStorage.getItem(`slicc-hidden-tabs`);return{stdout:`Debug tabs: ${(e?JSON.parse(e):[`terminal`,`memory`]).includes(`terminal`)?`off`:`on`}\n`,stderr:``,exitCode:0}}catch{return{stdout:`Debug tabs: off
1737
1737
  `,stderr:``,exitCode:0}}let n=t===`on`,r=window.__slicc_debug_tabs;if(r)return r(n),{stdout:`Debug tabs ${n?`enabled`:`hidden`}\n`,stderr:``,exitCode:0};try{return chrome.runtime.sendMessage({source:`offscreen`,payload:{type:`debug-tabs`,show:n}}),{stdout:`Debug tabs ${n?`enabled`:`hidden`}\n`,stderr:``,exitCode:0}}catch{return{stdout:``,stderr:`debug: failed to send toggle message
1738
- `,exitCode:1}}})}var fv=`/.cache/artificial-analysis.json`,pv=1440*60*1e3,mv=`https://artificialanalysis.ai/api/v2/data/llms/models`;async function hv(e,t=!1){if(e&&!t)try{let t=await e.readFile(fv),n=JSON.parse(t);if(Date.now()-n.fetchedAt<pv)return n.models}catch{}let n=null;try{n=localStorage.getItem(`aa_api_key`)}catch{}let r={Accept:`application/json`};n&&(r[`x-api-key`]=n);let i;try{i=await fetch(mv,{headers:r})}catch{return[]}if(i.status===401||!i.ok)return[];let a;try{a=await i.json()}catch{return[]}let o=(Array.isArray(a)?a:a?.data??a?.models??[]).map(e=>({slug:e.slug??``,name:e.name??``,creator_slug:e.model_creator?.slug??``,intelligence_index:e.evaluations?.artificial_analysis_intelligence_index??null,coding_index:e.evaluations?.artificial_analysis_coding_index??null,speed_tps:e.median_output_tokens_per_second??null}));if(e&&o.length>0){let t={fetchedAt:Date.now(),models:o};try{await e.mkdir(`/.cache`,{recursive:!0}),await e.writeFile(fv,JSON.stringify(t))}catch{}}return o}function gv(e){return e.toLowerCase().replace(/\./g,`-`).replace(/-\d{8}$/,``).replace(/-\d{4}$/,``)}function _v(e,t){let n=e.toLowerCase(),r=t.find(e=>e.slug===n);if(r)return r;let i=gv(e),a=t.find(e=>gv(e.slug)===i);if(a)return a;let o=t.filter(e=>n.includes(e.slug)||e.slug.includes(n));if(o.length>0)return o.sort((e,t)=>t.slug.length-e.slug.length),o[0]}function vv(){return`models - list available LLM models
1738
+ `,exitCode:1}}})}var pv=`/.cache/artificial-analysis.json`,mv=1440*60*1e3,hv=`https://artificialanalysis.ai/api/v2/data/llms/models`;async function gv(e,t=!1){if(e&&!t)try{let t=await e.readFile(pv),n=JSON.parse(t);if(Date.now()-n.fetchedAt<mv)return n.models}catch{}let n=null;try{n=localStorage.getItem(`aa_api_key`)}catch{}let r={Accept:`application/json`};n&&(r[`x-api-key`]=n);let i;try{i=await fetch(hv,{headers:r})}catch{return[]}if(i.status===401||!i.ok)return[];let a;try{a=await i.json()}catch{return[]}let o=(Array.isArray(a)?a:a?.data??a?.models??[]).map(e=>({slug:e.slug??``,name:e.name??``,creator_slug:e.model_creator?.slug??``,intelligence_index:e.evaluations?.artificial_analysis_intelligence_index??null,coding_index:e.evaluations?.artificial_analysis_coding_index??null,speed_tps:e.median_output_tokens_per_second??null}));if(e&&o.length>0){let t={fetchedAt:Date.now(),models:o};try{await e.mkdir(`/.cache`,{recursive:!0}),await e.writeFile(pv,JSON.stringify(t))}catch{}}return o}function _v(e){return e.toLowerCase().replace(/\./g,`-`).replace(/-\d{8}$/,``).replace(/-\d{4}$/,``)}function vv(e,t){let n=e.toLowerCase(),r=t.find(e=>e.slug===n);if(r)return r;let i=_v(e),a=t.find(e=>_v(e.slug)===i);if(a)return a;let o=t.filter(e=>n.includes(e.slug)||e.slug.includes(n));if(o.length>0)return o.sort((e,t)=>t.slug.length-e.slug.length),o[0]}function yv(){return`models - list available LLM models
1739
1739
 
1740
1740
  Usage: models [options]
1741
1741
 
@@ -1747,13 +1747,13 @@ Options:
1747
1747
  --refresh Force re-fetch benchmark data from Artificial Analysis
1748
1748
  --no-benchmarks Skip benchmark data enrichment (faster, works offline)
1749
1749
  -h, --help Show this help message
1750
- `}function yv(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`.replace(`.0M`,`M`):e>=1e3?`${(e/1e3).toFixed(0)}K`:`${e}`}function bv(e){return`$${e.toFixed(2)}`}var xv=/\b(embedding|embed|tts|whisper|dall-e|image-gen|audio|vision-preview)\b/i;function Sv(e){let t=`${e.id} ${e.name??``}`;return!xv.test(t)}function Cv(e){let t=e.toLowerCase();t=t.replace(/-\d{8}$/,``),t=t.replace(/-\d{4}$/,``),t=t.replace(/-(preview|latest)$/,``);let n=t.match(/^(claude-(?:opus|sonnet|haiku))/);if(n)return n[1];let r=t.match(/^(gpt-\d+)(?:\.\d+)?(-[a-z][-a-z]*)?$/);if(r)return r[1]+(r[2]??``);let i=t.match(/^gemini-[\d.]+-(.+)$/);if(i)return`gemini-${i[1]}`;let a=t.match(/^gemini-(\d+)-(.+)$/);if(a)return`gemini-${a[2]}`;let o=t.match(/^grok-[\d.]+-([\w-]+)$/);if(o)return`grok-${o[1]}`;if(t.match(/^(grok)-[\d.]+$/))return`grok`;let s=t.match(/^(o\d+(?:-[a-z]+)?)(?:-\d.*)?$/);return s?s[1]:t.replace(/-[\d.]+$/,``)}function wv(e){let t=new Map;for(let n of e){let e=Cv(n.id);t.has(e)||t.set(e,n)}return[...t.values()]}function Tv(e,t,n,r,i){let a=i?_v(e.id,i):void 0,o={id:e.id,name:e.name,provider:t,cost:e.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:e.contextWindow??0,maxTokens:e.maxTokens??0,reasoning:!!e.reasoning,input:e.input??[`text`],selected:e.id===n&&t===r};return a?.intelligence_index!=null&&(o.intelligence=a.intelligence_index),a?.coding_index!=null&&(o.codingScore=a.coding_index),a?.speed_tps!=null&&(o.speed=a.speed_tps),o}function Ev(e,t,n,r){let i=[];i.push(`Models for "${e}" (${t}):\n`);for(let e of n){let t=e.selected?` ► `:` `,n=e.id.padEnd(30),r=`${bv(e.cost.input)} / ${bv(e.cost.output)}`,a=`${yv(e.contextWindow)} ctx`,o=e.intelligence==null?``:`IQ:${e.intelligence}`,s=e.speed==null?``:`${Math.round(e.speed)} t/s`,c=e.reasoning?`reasoning`:``,l=o||s?`${o.padEnd(6)} ${s.padEnd(8)}`:``;i.push(`${t}${n} ${r.padEnd(16)} ${a.padEnd(10)} ${l} ${c}`)}let a=n.find(e=>e.selected);return i.push(`\n ${n.length} model${n.length===1?``:`s`} available.${a?` Currently using: ${a.id}`:``}`),r&&i.push(` Intelligence data: artificialanalysis.ai`),i.join(`
1750
+ `}function bv(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`.replace(`.0M`,`M`):e>=1e3?`${(e/1e3).toFixed(0)}K`:`${e}`}function xv(e){return`$${e.toFixed(2)}`}var Sv=/\b(embedding|embed|tts|whisper|dall-e|image-gen|audio|vision-preview)\b/i;function Cv(e){let t=`${e.id} ${e.name??``}`;return!Sv.test(t)}function wv(e){let t=e.toLowerCase();t=t.replace(/-\d{8}$/,``),t=t.replace(/-\d{4}$/,``),t=t.replace(/-(preview|latest)$/,``);let n=t.match(/^(claude-(?:opus|sonnet|haiku))/);if(n)return n[1];let r=t.match(/^(gpt-\d+)(?:\.\d+)?(-[a-z][-a-z]*)?$/);if(r)return r[1]+(r[2]??``);let i=t.match(/^gemini-[\d.]+-(.+)$/);if(i)return`gemini-${i[1]}`;let a=t.match(/^gemini-(\d+)-(.+)$/);if(a)return`gemini-${a[2]}`;let o=t.match(/^grok-[\d.]+-([\w-]+)$/);if(o)return`grok-${o[1]}`;if(t.match(/^(grok)-[\d.]+$/))return`grok`;let s=t.match(/^(o\d+(?:-[a-z]+)?)(?:-\d.*)?$/);return s?s[1]:t.replace(/-[\d.]+$/,``)}function Tv(e){let t=new Map;for(let n of e){let e=wv(n.id);t.has(e)||t.set(e,n)}return[...t.values()]}function Ev(e,t,n,r,i){let a=i?vv(e.id,i):void 0,o={id:e.id,name:e.name,provider:t,cost:e.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:e.contextWindow??0,maxTokens:e.maxTokens??0,reasoning:!!e.reasoning,input:e.input??[`text`],selected:e.id===n&&t===r};return a?.intelligence_index!=null&&(o.intelligence=a.intelligence_index),a?.coding_index!=null&&(o.codingScore=a.coding_index),a?.speed_tps!=null&&(o.speed=a.speed_tps),o}function Dv(e,t,n,r){let i=[];i.push(`Models for "${e}" (${t}):\n`);for(let e of n){let t=e.selected?` ► `:` `,n=e.id.padEnd(30),r=`${xv(e.cost.input)} / ${xv(e.cost.output)}`,a=`${bv(e.contextWindow)} ctx`,o=e.intelligence==null?``:`IQ:${e.intelligence}`,s=e.speed==null?``:`${Math.round(e.speed)} t/s`,c=e.reasoning?`reasoning`:``,l=o||s?`${o.padEnd(6)} ${s.padEnd(8)}`:``;i.push(`${t}${n} ${r.padEnd(16)} ${a.padEnd(10)} ${l} ${c}`)}let a=n.find(e=>e.selected);return i.push(`\n ${n.length} model${n.length===1?``:`s`} available.${a?` Currently using: ${a.id}`:``}`),r&&i.push(` Intelligence data: artificialanalysis.ai`),i.join(`
1751
1751
  `)+`
1752
- `}function Dv(e){return Ve(`models`,async t=>{let{getAccounts:n,getAvailableProviders:r,getProviderConfig:a,getProviderModels:o,getSelectedProvider:s,getSelectedModelId:c}=await i(async()=>{let{getAccounts:e,getAvailableProviders:t,getProviderConfig:n,getProviderModels:r,getSelectedProvider:i,getSelectedModelId:a}=await import(`./provider-settings-BNHO2Tcv.js`).then(e=>e.l);return{getAccounts:e,getAvailableProviders:t,getProviderConfig:n,getProviderModels:r,getSelectedProvider:i,getSelectedModelId:a}},__vite__mapDeps([9,4,1,10,11,12,13,14,15]));if(t.includes(`--help`)||t.includes(`-h`))return{stdout:vv(),stderr:``,exitCode:0};let l=t.includes(`--json`),u=t.includes(`--all`),d=t.includes(`--all-versions`),f=t.includes(`--refresh`),p=t.includes(`--no-benchmarks`),m=t.indexOf(`--provider`),h=m>=0?t[m+1]:void 0,g=s(),_=c(),v=n();if(v.length===0)return{stdout:``,stderr:`No provider accounts configured. Run the provider settings to add one.
1753
- `,exitCode:1};let y;p||(y=await hv(e,f),y.length===0&&(y=void 0));let b;if(h){let e=r();if(!e.includes(h))return{stdout:``,stderr:`Unknown provider: ${h}. Available: ${e.join(`, `)}\n`,exitCode:1};b=[h]}else b=u?[...new Set(v.map(e=>e.providerId))]:[g];let x=[],S=[];for(let e of b){let t=o(e).filter(Sv);if(t.length===0){if(!u)return{stdout:``,stderr:`No models available for provider ${e}.\n`,exitCode:1};continue}let n=t.map(t=>Tv(t,e,_,g,y)).sort((e,t)=>t.cost.input-e.cost.input);if(d||(n=wv(n)),x.push(...n),!l){let t=a(e);S.push(Ev(t.name,e,n,!!y))}}return l?{stdout:JSON.stringify(x,null,2)+`
1752
+ `}function Ov(e){return Ve(`models`,async t=>{let{getAccounts:n,getAvailableProviders:r,getProviderConfig:a,getProviderModels:o,getSelectedProvider:s,getSelectedModelId:c}=await i(async()=>{let{getAccounts:e,getAvailableProviders:t,getProviderConfig:n,getProviderModels:r,getSelectedProvider:i,getSelectedModelId:a}=await import(`./provider-settings-BNHO2Tcv.js`).then(e=>e.l);return{getAccounts:e,getAvailableProviders:t,getProviderConfig:n,getProviderModels:r,getSelectedProvider:i,getSelectedModelId:a}},__vite__mapDeps([9,4,1,10,11,12,13,14,15]));if(t.includes(`--help`)||t.includes(`-h`))return{stdout:yv(),stderr:``,exitCode:0};let l=t.includes(`--json`),u=t.includes(`--all`),d=t.includes(`--all-versions`),f=t.includes(`--refresh`),p=t.includes(`--no-benchmarks`),m=t.indexOf(`--provider`),h=m>=0?t[m+1]:void 0,g=s(),_=c(),v=n();if(v.length===0)return{stdout:``,stderr:`No provider accounts configured. Run the provider settings to add one.
1753
+ `,exitCode:1};let y;p||(y=await gv(e,f),y.length===0&&(y=void 0));let b;if(h){let e=r();if(!e.includes(h))return{stdout:``,stderr:`Unknown provider: ${h}. Available: ${e.join(`, `)}\n`,exitCode:1};b=[h]}else b=u?[...new Set(v.map(e=>e.providerId))]:[g];let x=[],S=[];for(let e of b){let t=o(e).filter(Cv);if(t.length===0){if(!u)return{stdout:``,stderr:`No models available for provider ${e}.\n`,exitCode:1};continue}let n=t.map(t=>Ev(t,e,_,g,y)).sort((e,t)=>t.cost.input-e.cost.input);if(d||(n=Tv(n)),x.push(...n),!l){let t=a(e);S.push(Dv(t.name,e,n,!!y))}}return l?{stdout:JSON.stringify(x,null,2)+`
1754
1754
  `,stderr:``,exitCode:0}:(!d&&!l&&S.push(`Showing latest versions only. Use --all-versions to see all.
1755
1755
  `),{stdout:S.join(`
1756
- `),stderr:``,exitCode:0})})}function Ov(){return Ve(`nuke`,async e=>e.includes(`--help`)||e.includes(`-h`)?{stdout:`Usage: nuke <launch-code>
1756
+ `),stderr:``,exitCode:0})})}function kv(){return Ve(`nuke`,async e=>e.includes(`--help`)||e.includes(`-h`)?{stdout:`Usage: nuke <launch-code>
1757
1757
 
1758
1758
  Completely reset the environment by deleting all local data and reloading.
1759
1759
  Destroys the file system, chat history, and scoops database.
@@ -1761,7 +1761,7 @@ Requires the secret launch code to proceed.
1761
1761
  `,stderr:``,exitCode:0}:e.join(``).includes(`1234`)?(indexedDB.databases().then(e=>{for(let t of e)t.name&&indexedDB.deleteDatabase(t.name)}),setTimeout(()=>location.reload(),0),{stdout:`Nuking everything…
1762
1762
  `,stderr:``,exitCode:0}):{stdout:``,stderr:`⚠️ WARNING: this will reset the entire environment, file system, chats, and scoops.
1763
1763
  Run nuke again with the secret launch code to proceed.
1764
- `,exitCode:1})}var kv=r(`agent-command`),Av=`usage: agent <cwd> <allowed-commands> <prompt>
1764
+ `,exitCode:1})}var Av=r(`agent-command`),jv=`usage: agent <cwd> <allowed-commands> <prompt>
1765
1765
 
1766
1766
  Spawns a sub-scoop, feeds it a task, blocks until the agent loop completes,
1767
1767
  then prints the scoop's final message on stdout.
@@ -1798,17 +1798,17 @@ Examples:
1798
1798
  agent /home ls,wc,find "how many files do I have in my home directory"
1799
1799
  agent --model claude-haiku-4-5 . "*" "summarize files in this directory"
1800
1800
  agent --read-only /workspace/,/shared/assets/ . "*" "review the docs"
1801
- `;function jv(e){let t=[],n=!1,r,i,a=0;for(;a<e.length;){let o=e[a];if(t.length===2){t.push(o),a+=1;continue}if(o===`-h`||o===`--help`){n=!0,a+=1;continue}if(o===`--model`){let t=e[a+1];if(t===void 0||t.length>0&&t.startsWith(`-`))return{help:!1,error:`agent: --model requires a value`};if(t===``)return{help:!1,error:`agent: --model requires a non-empty value`};r=t,a+=2;continue}if(o===`--read-only`){let t=e[a+1];if(t===void 0||t.length>0&&t.startsWith(`-`))return{help:!1,error:`agent: --read-only requires a value`};if(t===``)return{help:!1,error:`agent: --read-only requires a non-empty value`};let n=Mv(t);if(n.length===0)return{help:!1,error:`agent: --read-only requires a non-empty value`};i=n,a+=2;continue}if(o.length>0&&o.startsWith(`-`))return{help:!1,error:`agent: unknown flag '${o}'`};t.push(o),a+=1}if(n)return{help:!0};if(t.length<3)return{help:!1,error:`agent: missing required argument ${[`<cwd>`,`<allowed-commands>`,`<prompt>`][t.length]}`};if(t.length>3)return{help:!1,error:`agent: too many arguments`};let[o,s,c]=t;return{help:!1,cwd:o,allowedCommandsRaw:s,prompt:c,modelId:r,visiblePaths:i}}function Mv(e){return e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}function Nv(e,t){return e.startsWith(`/`)?L(e):L(`${t.length>0?t:`/`}/${e}`)}function Pv(e){return e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}function Fv(e){return e==null?`
1801
+ `;function Mv(e){let t=[],n=!1,r,i,a=0;for(;a<e.length;){let o=e[a];if(t.length===2){t.push(o),a+=1;continue}if(o===`-h`||o===`--help`){n=!0,a+=1;continue}if(o===`--model`){let t=e[a+1];if(t===void 0||t.length>0&&t.startsWith(`-`))return{help:!1,error:`agent: --model requires a value`};if(t===``)return{help:!1,error:`agent: --model requires a non-empty value`};r=t,a+=2;continue}if(o===`--read-only`){let t=e[a+1];if(t===void 0||t.length>0&&t.startsWith(`-`))return{help:!1,error:`agent: --read-only requires a value`};if(t===``)return{help:!1,error:`agent: --read-only requires a non-empty value`};let n=Nv(t);if(n.length===0)return{help:!1,error:`agent: --read-only requires a non-empty value`};i=n,a+=2;continue}if(o.length>0&&o.startsWith(`-`))return{help:!1,error:`agent: unknown flag '${o}'`};t.push(o),a+=1}if(n)return{help:!0};if(t.length<3)return{help:!1,error:`agent: missing required argument ${[`<cwd>`,`<allowed-commands>`,`<prompt>`][t.length]}`};if(t.length>3)return{help:!1,error:`agent: too many arguments`};let[o,s,c]=t;return{help:!1,cwd:o,allowedCommandsRaw:s,prompt:c,modelId:r,visiblePaths:i}}function Nv(e){return e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}function Pv(e,t){return e.startsWith(`/`)?L(e):L(`${t.length>0?t:`/`}/${e}`)}function Fv(e){return e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}function Iv(e){return e==null?`
1802
1802
  `:e.replace(/\n+$/,``)+`
1803
- `}function Iv(e){return e==null||e===``?``:e.replace(/\n+$/,``)+`
1804
- `}function Lv(){let e=globalThis.__slicc_agent;if(!(!e||typeof e.spawn!=`function`))return e}function Rv(e={}){let{getParentJid:t}=e;return Ve(`agent`,async(e,n)=>{let r=jv(e);if(r.help)return{stdout:Av,stderr:``,exitCode:0};if(r.error)return{stdout:``,stderr:`${r.error}\n`,exitCode:1};let i=r.cwd??``;if(i===``)return{stdout:``,stderr:`agent: <cwd> must not be empty
1805
- `,exitCode:1};let a=Nv(i,n.cwd),o=Pv(r.allowedCommandsRaw??``),s=r.prompt??``;try{if(!(await n.fs.stat(a)).isDirectory)return{stdout:``,stderr:`agent: cwd not a directory: ${i}\n`,exitCode:1}}catch{return{stdout:``,stderr:`agent: cwd not found: ${i}\n`,exitCode:1}}let c=n.fs;if(typeof c.canWrite==`function`&&!c.canWrite(a))return{stdout:``,stderr:`agent: cwd not writable: ${i}\n`,exitCode:1};let l=Lv();if(!l)return{stdout:``,stderr:`agent: orchestrator bridge not available
1806
- `,exitCode:1};let u={cwd:a,allowedCommands:o,prompt:s};r.modelId!==void 0&&(u.modelId=r.modelId),r.visiblePaths!==void 0&&(u.visiblePaths=r.visiblePaths),n.cwd&&n.cwd.length>0&&(u.invokingCwd=n.cwd);let d=t?.();d!==void 0&&d.length>0&&(u.parentJid=d);try{let e=await l.spawn(u),t=typeof e?.exitCode==`number`?e.exitCode:0,n=e?.finalText;return t===0?{stdout:Fv(n),stderr:``,exitCode:0}:{stdout:``,stderr:Iv(n),exitCode:t}}catch(e){let t=e instanceof Error?e.message:String(e);return kv.error(`agent bridge threw`,e),{stdout:``,stderr:`${t}\n`,exitCode:1}}})}function zv(e={}){let t=[th({getJshCommands:e.getJshCommands}),kh(),Og(e.browserAPI,e.fs),dg(),Mh(e),z_(),Lg(),Ag(`sqlite3`),Ag(`sqllite`),sg(),Tg(`python3`),Tg(`python`),Bg(),qg(),Xg(),s_(),bg(`pdftk`),bg(`pdf`),ih(`convert`),ih(`magick`),I_({fs:e.fs,scriptCatalog:e.scriptCatalog}),Mg(),Fg(),l_(),m_(),j_({fs:e.fs}),W_(),Z_(),Q_(),$_(`xclip`),$_(`xsel`),iv(),lv(),uv(),Dv(e.fs),Be(),Ov(),Rv({getParentJid:e.getParentJid})];return typeof chrome<`u`&&chrome?.runtime?.id&&t.push(dv()),e.fs&&t.push(...cm.map(t=>Qm(t,e.browserAPI,e.fs))),t}var Bv=`https://wry-manatee-359.convex.site/api/v1`,Vv=`https://api.tessl.io`,Hv=`/workspace/skills`,Uv=`slicc-fs-global`,Wv=`/workspace/.git/github-token`,Gv=`application/vnd.github.v3+json`,Kv=`https://www.sliccy.com/skills/catalog.json`;function qv(e){if(!(!e||!e.trim()))return e.split(`,`).map(e=>e.trim()).filter(Boolean)}function Jv(e){return e.map(e=>{let t=e.boost?parseFloat(e.boost):NaN,n=Number.isFinite(t)?t:void 0;return{name:e.name,displayName:e.displayName||e.name,description:e.description||``,source:{repo:e.repo,path:e.path||void 0,skill:e.skill||void 0},affinity:{apps:qv(e.apps),tasks:qv(e.tasks),role:qv(e.role),purpose:qv(e.purpose)},priority:n}})}var Yv={apps:3,tasks:2,role:1,purpose:1};function Xv(e,t){return e.map(e=>{let n=0,r=[],i=(e.affinity.apps??[]).filter(e=>t.apps.includes(e));i.length&&(n+=i.length*Yv.apps,r.push(`apps(${i.join(`, `)})`));let a=(e.affinity.tasks??[]).filter(e=>t.tasks.includes(e));return a.length&&(n+=a.length*Yv.tasks,r.push(`tasks(${a.join(`, `)})`)),(e.affinity.role??[]).includes(t.role)&&(n+=Yv.role,r.push(`role(${t.role})`)),(e.affinity.purpose??[]).includes(t.purpose)&&(n+=Yv.purpose,r.push(`purpose(${t.purpose})`)),n*=e.priority??1,{entry:e,score:n,matchReasons:r}}).filter(e=>e.score>0).sort((e,t)=>t.score-e.score)}function Zv(e){let t=`upskill ${e.repo}`;return e.path&&(t+=` --path ${e.path}`),e.skill&&(t+=` --skill ${e.skill}`),t}async function Qv(e){let t=new Set;try{let n=await e.readDir(Hv);for(let e of n)e.type===`directory`&&t.add(e.name)}catch{}try{let n=await e.readTextFile(`/${ie}/${se}`),r=JSON.parse(n);for(let e of r.applied_skills??[])t.add(e.name)}catch{}let n=[`.agents`,`.claude`];try{let r=await e.readDir(`/`);for(let i of r)if(i.type===`directory`)for(let r of n)try{let n=`/${i.name}/${r}/skills`,a=await e.readDir(n);for(let e of a)e.type===`directory`&&t.add(e.name)}catch{}}catch{}return t}var $v;function ey(){return $v||=I.create({dbName:Uv}),$v}async function ty(){try{return(await(await ey()).readTextFile(Wv)).trim()||void 0}catch{return}}function ny(e,t=Gv){let n={Accept:t,"User-Agent":`slicc-upskill`};return e&&(n.Authorization=`Bearer ${e}`),n}async function ry(e){let t=await ty();return{hasToken:!!t,request:(n,r=Gv)=>e(n,{headers:ny(t,r)})}}function iy(e,t){if(!e)return;let n=t.toLowerCase();for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}function ay(e){let t=Do(e);if(!t)return;try{let e=JSON.parse(t);if(typeof e.message==`string`&&e.message.trim())return e.message.trim()}catch{}let n=t.trim();if(n)return n.slice(0,200)}function oy(e,t,n){let r=ay(e.body),i=r?` GitHub said: ${r}`:``,a=iy(e.headers,`retry-after`),o=iy(e.headers,`x-ratelimit-remaining`),s=r?.toLowerCase()??``;if(e.status===429||o===`0`||s.includes(`rate limit`))return n?`GitHub rate-limited access to ${t} (HTTP ${e.status}). The configured github.token was used, so retry later${a?` after about ${a} seconds`:``}.${i}`:`GitHub rate-limited anonymous access to ${t} (HTTP ${e.status}). This often happens on shared VPNs or corporate egress IPs because unauthenticated GitHub API requests are limited per IP. Configure a token with: git config github.token <PAT>, then retry. You can also retry off VPN or later.${i}`;if(e.status===401)return n?`GitHub rejected the configured github.token while accessing ${t} (HTTP 401). Update it with: git config github.token <PAT>, then retry.${i}`:`GitHub requires authentication to access ${t} (HTTP 401). Configure a token with: git config github.token <PAT>, then retry.${i}`;if(e.status===404)return`GitHub could not find ${t} (HTTP 404). Check the repository, path, and permissions.${i}`;if(e.status===403)return n?`GitHub denied access to ${t} (HTTP 403). Check that your github.token can access this repository or retry later if GitHub is throttling requests.${i}`:`GitHub denied anonymous access to ${t} (HTTP 403). If this repo is public on a shared VPN, you may have hit GitHub's shared IP limit; otherwise the repository or path may require authentication. Configure a token with: git config github.token <PAT>, then retry.${i}`;let c=e.statusText?` ${e.statusText}`:``;return`GitHub request for ${t} failed (HTTP ${e.status}${c}).${i}`}function sy(){return`Discovery roots: /workspace/skills plus accessible **/.agents/skills/* and **/.claude/skills/* anywhere in the VFS.
1807
- `}function cy(){return`Only native /workspace/skills entries are install-managed; compatibility-discovered .agents/.claude skills remain read-only.
1808
- `}function ly(e){switch(e){case`native`:return`native`;case`agents`:return`.agents`;case`claude`:return`.claude`}}function uy(e){return e.source===`native`}function dy(e){return uy(e)?e.installed&&e.installedVersion?`installed (v${e.installedVersion})`:`available`:e.installed&&e.installedVersion?`compatibility (state v${e.installedVersion})`:`compatibility (read-only)`}function fy(e){return uy(e)?`install-managed (/workspace/skills)`:`compatibility-only (read-only)`}function py(e,t){let n=`${t}:\n\n`;n+=` NAME VERSION SOURCE STATUS
1803
+ `}function Lv(e){return e==null||e===``?``:e.replace(/\n+$/,``)+`
1804
+ `}function Rv(){let e=globalThis.__slicc_agent;if(!(!e||typeof e.spawn!=`function`))return e}function zv(e={}){let{getParentJid:t}=e;return Ve(`agent`,async(e,n)=>{let r=Mv(e);if(r.help)return{stdout:jv,stderr:``,exitCode:0};if(r.error)return{stdout:``,stderr:`${r.error}\n`,exitCode:1};let i=r.cwd??``;if(i===``)return{stdout:``,stderr:`agent: <cwd> must not be empty
1805
+ `,exitCode:1};let a=Pv(i,n.cwd),o=Fv(r.allowedCommandsRaw??``),s=r.prompt??``;try{if(!(await n.fs.stat(a)).isDirectory)return{stdout:``,stderr:`agent: cwd not a directory: ${i}\n`,exitCode:1}}catch{return{stdout:``,stderr:`agent: cwd not found: ${i}\n`,exitCode:1}}let c=n.fs;if(typeof c.canWrite==`function`&&!c.canWrite(a))return{stdout:``,stderr:`agent: cwd not writable: ${i}\n`,exitCode:1};let l=Rv();if(!l)return{stdout:``,stderr:`agent: orchestrator bridge not available
1806
+ `,exitCode:1};let u={cwd:a,allowedCommands:o,prompt:s};r.modelId!==void 0&&(u.modelId=r.modelId),r.visiblePaths!==void 0&&(u.visiblePaths=r.visiblePaths),n.cwd&&n.cwd.length>0&&(u.invokingCwd=n.cwd);let d=t?.();d!==void 0&&d.length>0&&(u.parentJid=d);try{let e=await l.spawn(u),t=typeof e?.exitCode==`number`?e.exitCode:0,n=e?.finalText;return t===0?{stdout:Iv(n),stderr:``,exitCode:0}:{stdout:``,stderr:Lv(n),exitCode:t}}catch(e){let t=e instanceof Error?e.message:String(e);return Av.error(`agent bridge threw`,e),{stdout:``,stderr:`${t}\n`,exitCode:1}}})}function Bv(e={}){let t=[nh({getJshCommands:e.getJshCommands}),Ah(),kg(e.browserAPI,e.fs),fg(),Nh(e),B_(),Rg(),jg(`sqlite3`),jg(`sqllite`),cg(),Eg(`python3`),Eg(`python`),Vg(),Jg(),Zg(),c_(),xg(`pdftk`),xg(`pdf`),ah(`convert`),ah(`magick`),L_({fs:e.fs,scriptCatalog:e.scriptCatalog}),Ng(),Ig(),u_(),h_(),M_({fs:e.fs}),G_(),Q_(),$_(),ev(`xclip`),ev(`xsel`),av(),uv(),dv(),Ov(e.fs),Be(),kv(),zv({getParentJid:e.getParentJid})];return typeof chrome<`u`&&chrome?.runtime?.id&&t.push(fv()),e.fs&&t.push(...cm.map(t=>$m(t,e.browserAPI,e.fs))),t}var Vv=`https://wry-manatee-359.convex.site/api/v1`,Hv=`https://api.tessl.io`,Uv=`/workspace/skills`,Wv=`slicc-fs-global`,Gv=`/workspace/.git/github-token`,Kv=`application/vnd.github.v3+json`,qv=`https://www.sliccy.com/skills/catalog.json`;function Jv(e){if(!(!e||!e.trim()))return e.split(`,`).map(e=>e.trim()).filter(Boolean)}function Yv(e){return e.map(e=>{let t=e.boost?parseFloat(e.boost):NaN,n=Number.isFinite(t)?t:void 0;return{name:e.name,displayName:e.displayName||e.name,description:e.description||``,source:{repo:e.repo,path:e.path||void 0,skill:e.skill||void 0},affinity:{apps:Jv(e.apps),tasks:Jv(e.tasks),role:Jv(e.role),purpose:Jv(e.purpose)},priority:n}})}var Xv={apps:3,tasks:2,role:1,purpose:1};function Zv(e,t){return e.map(e=>{let n=0,r=[],i=(e.affinity.apps??[]).filter(e=>t.apps.includes(e));i.length&&(n+=i.length*Xv.apps,r.push(`apps(${i.join(`, `)})`));let a=(e.affinity.tasks??[]).filter(e=>t.tasks.includes(e));return a.length&&(n+=a.length*Xv.tasks,r.push(`tasks(${a.join(`, `)})`)),(e.affinity.role??[]).includes(t.role)&&(n+=Xv.role,r.push(`role(${t.role})`)),(e.affinity.purpose??[]).includes(t.purpose)&&(n+=Xv.purpose,r.push(`purpose(${t.purpose})`)),n*=e.priority??1,{entry:e,score:n,matchReasons:r}}).filter(e=>e.score>0).sort((e,t)=>t.score-e.score)}function Qv(e){let t=`upskill ${e.repo}`;return e.path&&(t+=` --path ${e.path}`),e.skill&&(t+=` --skill ${e.skill}`),t}async function $v(e){let t=new Set;try{let n=await e.readDir(Uv);for(let e of n)e.type===`directory`&&t.add(e.name)}catch{}try{let n=await e.readTextFile(`/${ie}/${se}`),r=JSON.parse(n);for(let e of r.applied_skills??[])t.add(e.name)}catch{}let n=[`.agents`,`.claude`];try{let r=await e.readDir(`/`);for(let i of r)if(i.type===`directory`)for(let r of n)try{let n=`/${i.name}/${r}/skills`,a=await e.readDir(n);for(let e of a)e.type===`directory`&&t.add(e.name)}catch{}}catch{}return t}var ey;function ty(){return ey||=I.create({dbName:Wv}),ey}async function ny(){try{return(await(await ty()).readTextFile(Gv)).trim()||void 0}catch{return}}function ry(e,t=Kv){let n={Accept:t,"User-Agent":`slicc-upskill`};return e&&(n.Authorization=`Bearer ${e}`),n}async function iy(e){let t=await ny();return{hasToken:!!t,request:(n,r=Kv)=>e(n,{headers:ry(t,r)})}}function ay(e,t){if(!e)return;let n=t.toLowerCase();for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}function oy(e){let t=Do(e);if(!t)return;try{let e=JSON.parse(t);if(typeof e.message==`string`&&e.message.trim())return e.message.trim()}catch{}let n=t.trim();if(n)return n.slice(0,200)}function sy(e,t,n){let r=oy(e.body),i=r?` GitHub said: ${r}`:``,a=ay(e.headers,`retry-after`),o=ay(e.headers,`x-ratelimit-remaining`),s=r?.toLowerCase()??``;if(e.status===429||o===`0`||s.includes(`rate limit`))return n?`GitHub rate-limited access to ${t} (HTTP ${e.status}). The configured github.token was used, so retry later${a?` after about ${a} seconds`:``}.${i}`:`GitHub rate-limited anonymous access to ${t} (HTTP ${e.status}). This often happens on shared VPNs or corporate egress IPs because unauthenticated GitHub API requests are limited per IP. Configure a token with: git config github.token <PAT>, then retry. You can also retry off VPN or later.${i}`;if(e.status===401)return n?`GitHub rejected the configured github.token while accessing ${t} (HTTP 401). Update it with: git config github.token <PAT>, then retry.${i}`:`GitHub requires authentication to access ${t} (HTTP 401). Configure a token with: git config github.token <PAT>, then retry.${i}`;if(e.status===404)return`GitHub could not find ${t} (HTTP 404). Check the repository, path, and permissions.${i}`;if(e.status===403)return n?`GitHub denied access to ${t} (HTTP 403). Check that your github.token can access this repository or retry later if GitHub is throttling requests.${i}`:`GitHub denied anonymous access to ${t} (HTTP 403). If this repo is public on a shared VPN, you may have hit GitHub's shared IP limit; otherwise the repository or path may require authentication. Configure a token with: git config github.token <PAT>, then retry.${i}`;let c=e.statusText?` ${e.statusText}`:``;return`GitHub request for ${t} failed (HTTP ${e.status}${c}).${i}`}function cy(){return`Discovery roots: /workspace/skills plus accessible **/.agents/skills/* and **/.claude/skills/* anywhere in the VFS.
1807
+ `}function ly(){return`Only native /workspace/skills entries are install-managed; compatibility-discovered .agents/.claude skills remain read-only.
1808
+ `}function uy(e){switch(e){case`native`:return`native`;case`agents`:return`.agents`;case`claude`:return`.claude`}}function dy(e){return e.source===`native`}function fy(e){return dy(e)?e.installed&&e.installedVersion?`installed (v${e.installedVersion})`:`available`:e.installed&&e.installedVersion?`compatibility (state v${e.installedVersion})`:`compatibility (read-only)`}function py(e){return dy(e)?`install-managed (/workspace/skills)`:`compatibility-only (read-only)`}function my(e,t){let n=`${t}:\n\n`;n+=` NAME VERSION SOURCE STATUS
1809
1809
  `,n+=` ─────────────────────────────────────────────────────────────
1810
- `;for(let t of e)n+=` ${t.name.padEnd(20)} ${t.manifest.version.padEnd(10)} ${ly(t.source).padEnd(9)} ${dy(t)}\n`;return n+=`\n${sy()}`,n+=cy(),n}function my(e){let t=`Skill: ${e.manifest.skill}\n`;if(t+=`Version: ${e.manifest.version}\n`,t+=`Description: ${e.manifest.description||`(none)`}\n`,t+=`Source: ${ly(e.source)}\n`,t+=`Source root: ${e.sourceRoot}\n`,t+=`Management: ${fy(e)}\n`,t+=`Status: ${dy(e)}\n`,e.skillFilePath&&(t+=`Instructions: ${e.skillFilePath}\n`),e.shadowedPaths?.length){t+=`Shadowed paths:
1811
- `;for(let n of e.shadowedPaths)t+=` - ${n}\n`}return t}function hy(e,t){return`${e}: "${t.name}" is discoverable from ${t.sourceRoot} but remains compatibility-only/read-only. Only native /workspace/skills entries are install-managed.\n`}function gy(){return{stdout:`usage: upskill <command> [options]
1810
+ `;for(let t of e)n+=` ${t.name.padEnd(20)} ${t.manifest.version.padEnd(10)} ${uy(t.source).padEnd(9)} ${fy(t)}\n`;return n+=`\n${cy()}`,n+=ly(),n}function hy(e){let t=`Skill: ${e.manifest.skill}\n`;if(t+=`Version: ${e.manifest.version}\n`,t+=`Description: ${e.manifest.description||`(none)`}\n`,t+=`Source: ${uy(e.source)}\n`,t+=`Source root: ${e.sourceRoot}\n`,t+=`Management: ${py(e)}\n`,t+=`Status: ${fy(e)}\n`,e.skillFilePath&&(t+=`Instructions: ${e.skillFilePath}\n`),e.shadowedPaths?.length){t+=`Shadowed paths:
1811
+ `;for(let n of e.shadowedPaths)t+=` - ${n}\n`}return t}function gy(e,t){return`${e}: "${t.name}" is discoverable from ${t.sourceRoot} but remains compatibility-only/read-only. Only native /workspace/skills entries are install-managed.\n`}function _y(){return{stdout:`usage: upskill <command> [options]
1812
1812
 
1813
1813
  Install skills from GitHub repositories, ClawHub, or Tessl registry.
1814
1814
 
@@ -1821,7 +1821,7 @@ Commands:
1821
1821
  <clawhub-url> Install skill from ClawHub URL
1822
1822
  tessl:<name> Install skill from Tessl registry
1823
1823
 
1824
- ${sy()}${cy()}
1824
+ ${cy()}${ly()}
1825
1825
 
1826
1826
  GitHub Installation:
1827
1827
  upskill owner/repo List available skills in repo
@@ -1862,20 +1862,20 @@ Examples:
1862
1862
  upskill aemcoder/skills@fix/stateless-tab-targeting --all
1863
1863
  upskill https://clawhub.ai/arun-8687/tavily-search
1864
1864
  upskill tessl:postgres-pro
1865
- `,stderr:``,exitCode:0}}async function _y(e,t){let n=await t(`${Bv}/search?q=${encodeURIComponent(e)}`,{headers:{Accept:`application/json`}});if(n.status!==200)throw Error(`ClawHub returned HTTP ${n.status}`);let r=Oo(n.body);return r.results?r.results.map(e=>({name:e.slug,displayName:e.displayName||e.slug,summary:e.summary||``,source:`clawhub`,qualityScore:null,installHint:`upskill clawhub:${e.slug}`})):[]}function vy(e){let t=e.match(/github\.com\/([^\/?#]+)\/([^\/?#]+)/);return t?{owner:t[1],repo:t[2].replace(/\.git$/,``)}:null}async function yy(e,t){let n=await t(`${Vv}/experimental/search?q=${encodeURIComponent(e)}&contentType=skills&page%5Bsize%5D=20`,{headers:{Accept:`application/json`}});if(n.status!==200)throw Error(`Tessl returned HTTP ${n.status}`);let r=Oo(n.body);if(!r.data)return[];let i=new Map;for(let e of r.data){if(e.type!==`skill`)continue;let t=e.attributes,n=vy(t.sourceUrl),r=n?`${n.owner}/${n.repo}`:void 0,a=t.scores.aggregate==null?null:Math.round(t.scores.aggregate*100),o=t.sourceUrl||e.id,s=i.get(o);if(s&&s.qualityScore!=null&&a!=null&&s.qualityScore>=a)continue;let c=t.path.replace(/\/SKILL\.md$/i,``),l=c.split(`/`).pop()||t.name,u=n?`upskill ${n.owner}/${n.repo} --path ${c.split(`/`).slice(0,-1).join(`/`)||`.`} --skill ${l}`:`upskill tessl:${t.name}`;i.set(o,{name:t.name,displayName:t.name,summary:t.description||``,source:`tessl`,qualityScore:a,installHint:u,featured:t.featured,sourceRepo:r})}return Array.from(i.values())}var by=10;async function xy(e,t,n=1){let[r,i]=await Promise.allSettled([_y(e,t),yy(e,t)]),a=r.status===`fulfilled`?r.value:[],o=i.status===`fulfilled`?i.value:[];if(a.length===0&&o.length===0){let t=``;return r.status===`rejected`&&i.status===`rejected`&&(t=`upskill: both registries failed to respond
1866
- `),{stdout:`No skills found for "${e}"\n\nTry a different search term or browse https://clawhub.ai or https://tessl.io/registry\n`,stderr:t,exitCode:+!!t}}let s=[],c=0,l=0;for(;c<o.length&&c<3;)s.push(o[c++]);for(;l<a.length||c<o.length;)l<a.length&&s.push(a[l++]),c<o.length&&s.push(o[c++]);let u=s.length,d=Math.ceil(u/by),f=Math.max(1,Math.min(n,d)),p=(f-1)*by,m=s.slice(p,p+by),h=`Search results for "${e}" (page ${f}/${d}, ${u} total):\n\n`;for(let e of m){let t=e.qualityScore==null?` `:String(e.qualityScore).padStart(3),n=`[${e.source}]`,r=e.sourceRepo?` ${e.sourceRepo}`:``;h+=` ${e.name.padEnd(30)} ${t} ${n.padEnd(10)}${r}\n`,e.summary&&(h+=` ${e.summary}\n`),h+=`
1865
+ `,stderr:``,exitCode:0}}async function vy(e,t){let n=await t(`${Vv}/search?q=${encodeURIComponent(e)}`,{headers:{Accept:`application/json`}});if(n.status!==200)throw Error(`ClawHub returned HTTP ${n.status}`);let r=Oo(n.body);return r.results?r.results.map(e=>({name:e.slug,displayName:e.displayName||e.slug,summary:e.summary||``,source:`clawhub`,qualityScore:null,installHint:`upskill clawhub:${e.slug}`})):[]}function yy(e){let t=e.match(/github\.com\/([^\/?#]+)\/([^\/?#]+)/);return t?{owner:t[1],repo:t[2].replace(/\.git$/,``)}:null}async function by(e,t){let n=await t(`${Hv}/experimental/search?q=${encodeURIComponent(e)}&contentType=skills&page%5Bsize%5D=20`,{headers:{Accept:`application/json`}});if(n.status!==200)throw Error(`Tessl returned HTTP ${n.status}`);let r=Oo(n.body);if(!r.data)return[];let i=new Map;for(let e of r.data){if(e.type!==`skill`)continue;let t=e.attributes,n=yy(t.sourceUrl),r=n?`${n.owner}/${n.repo}`:void 0,a=t.scores.aggregate==null?null:Math.round(t.scores.aggregate*100),o=t.sourceUrl||e.id,s=i.get(o);if(s&&s.qualityScore!=null&&a!=null&&s.qualityScore>=a)continue;let c=t.path.replace(/\/SKILL\.md$/i,``),l=c.split(`/`).pop()||t.name,u=n?`upskill ${n.owner}/${n.repo} --path ${c.split(`/`).slice(0,-1).join(`/`)||`.`} --skill ${l}`:`upskill tessl:${t.name}`;i.set(o,{name:t.name,displayName:t.name,summary:t.description||``,source:`tessl`,qualityScore:a,installHint:u,featured:t.featured,sourceRepo:r})}return Array.from(i.values())}var xy=10;async function Sy(e,t,n=1){let[r,i]=await Promise.allSettled([vy(e,t),by(e,t)]),a=r.status===`fulfilled`?r.value:[],o=i.status===`fulfilled`?i.value:[];if(a.length===0&&o.length===0){let t=``;return r.status===`rejected`&&i.status===`rejected`&&(t=`upskill: both registries failed to respond
1866
+ `),{stdout:`No skills found for "${e}"\n\nTry a different search term or browse https://clawhub.ai or https://tessl.io/registry\n`,stderr:t,exitCode:+!!t}}let s=[],c=0,l=0;for(;c<o.length&&c<3;)s.push(o[c++]);for(;l<a.length||c<o.length;)l<a.length&&s.push(a[l++]),c<o.length&&s.push(o[c++]);let u=s.length,d=Math.ceil(u/xy),f=Math.max(1,Math.min(n,d)),p=(f-1)*xy,m=s.slice(p,p+xy),h=`Search results for "${e}" (page ${f}/${d}, ${u} total):\n\n`;for(let e of m){let t=e.qualityScore==null?` `:String(e.qualityScore).padStart(3),n=`[${e.source}]`,r=e.sourceRepo?` ${e.sourceRepo}`:``;h+=` ${e.name.padEnd(30)} ${t} ${n.padEnd(10)}${r}\n`,e.summary&&(h+=` ${e.summary}\n`),h+=`
1867
1867
  `}return f<d&&(h+=`Showing ${p+1}-${p+m.length} of ${u}. `,h+=`Next page: upskill search ${e} --page ${f+1}\n\n`),h+=`To install:
1868
1868
  `,a.length>0&&(h+=` From ClawHub: upskill clawhub:<slug>
1869
1869
  `),o.length>0&&(h+=` From Tessl: upskill <owner/repo> --skill <name>
1870
- `),{stdout:h,stderr:``,exitCode:0}}async function Sy(e,t,n,r=!1,i){try{let a=`${Hv}/${e}`;try{if(await t.stat(a),!r)return{stdout:``,stderr:`upskill: skill "${e}" already exists (use --force to overwrite)\n`,exitCode:1};await t.rm(a,{recursive:!0})}catch{}let o=`${Bv}/download?slug=${encodeURIComponent(e)}`,s=await n(o,{});if(s.status===404)return{stdout:``,stderr:`upskill: skill "${e}" not found on ClawHub\n`,exitCode:1};if(s.status!==200)return{stdout:``,stderr:`upskill: failed to download skill (HTTP ${s.status})\n`,exitCode:1};let c=s.headers[`content-type`]||``,l=Co(o);l||=ko(s.body);let u;try{u=P(l)}catch(e){let t=e instanceof Error?e.message:String(e),n=Array.from(l.slice(0,20)).map(e=>e.toString(16).padStart(2,`0`)).join(` `);return{stdout:``,stderr:`upskill: failed to unzip: ${t}\nContent-Type: ${c}\nBody: ${l.length} bytes\nHex: ${n}\n`,exitCode:1}}await t.mkdir(a,{recursive:!0});let d=0;for(let[e,n]of Object.entries(u)){let r=e.replace(/\\/g,`/`);if(!r||r.endsWith(`/`)||r===`_meta.json`)continue;let i=`${a}/${r}`,o=i.substring(0,i.lastIndexOf(`/`));o!==a&&await t.mkdir(o,{recursive:!0}),await t.writeFile(i,n),d++}let f=Cy(u,i);return await jy(),{stdout:`Installed skill "${e}" from ClawHub (${d} files)\n${f}`,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`upskill: failed to install from ClawHub: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}}function Cy(e,t){let n;for(let[t,r]of Object.entries(e))if((t.split(`/`).pop()||``).toLowerCase()===`skill.md`){n=new TextDecoder().decode(r);break}if(!n)return``;let r=n.match(/^---\s*\n([\s\S]*?)\n---/);if(!r)return``;let i=r[1],a=wy(i);if(a.length===0)return``;if(!t||t.length===0)return` Requires: ${a.join(`, `)}\n`;let o=new Set(t),s=a.filter(e=>!o.has(e));return s.length===0?` Requires: ${a.join(`, `)} (all available)\n`:` Requires: ${a.join(`, `)}\n Missing: ${s.join(`, `)} -- this skill may not work in the SLICC shell\n`}function wy(e){let t=e.match(/metadata:\s*\n\s*(\{[\s\S]*\})/);if(t)try{let e=JSON.parse(t[1]);for(let t of[`openclaw`,`clawdis`,`clawdbot`]){let n=e[t];if(n?.requires&&typeof n.requires==`object`){let e=n.requires;if(Array.isArray(e.bins))return e.bins.filter(e=>typeof e==`string`)}}}catch{}let n=e.match(/"bins"\s*:\s*\[([^\]]*)\]/);return n?n[1].split(`,`).map(e=>e.trim().replace(/^["']|["']$/g,``)).filter(Boolean):[]}async function Ty(e,t){let n=await t(`${Vv}/experimental/search?q=${encodeURIComponent(e)}&contentType=skills&page%5Bsize%5D=5`,{headers:{Accept:`application/json`}});if(n.status!==200)return{error:`Tessl search failed (HTTP ${n.status})`};let r=Oo(n.body).data?.find(t=>t.type===`skill`&&t.attributes.name===e);if(!r)return{error:`skill "${e}" not found on Tessl registry`};let i=vy(r.attributes.sourceUrl);if(!i)return{error:`skill "${e}" has no GitHub source URL`};let a=r.attributes.path.replace(/\/SKILL\.md$/i,``);return{owner:i.owner,repo:i.repo,skillPath:a,skillName:e}}async function Ey(e,t,n,r=`main`){let i=`https://codeload.github.com/${e}/${t}/zip/refs/heads/${r}`,a=await n(i,{headers:{"User-Agent":`slicc-upskill`}});if(a.status===404)return r===`main`?Ey(e,t,n,`master`):{status:`not_found`};if(a.status!==200)return{status:`error`,message:`codeload returned HTTP ${a.status}`};let o=Co(i);o||=ko(a.body);try{return{status:`ok`,files:P(o)}}catch(e){return{status:`error`,message:`failed to unzip: ${e instanceof Error?e.message:String(e)}`}}}function Dy(e){let t={};for(let[n,r]of Object.entries(e)){let e=n.indexOf(`/`);if(e<0)continue;let i=n.slice(e+1);i&&(t[i]=r)}return t}async function Oy(e,t,n,r,i,a){if(i){let n=await Ey(e,t,i,a);if(n.status===`ok`){let e=Dy(n.files),t=[],i=r?r.replace(/^\/|\/$/g,``)+`/`:``;for(let n of Object.keys(e))if(n.startsWith(i)&&(n.split(`/`).pop()||``)===`SKILL.md`){let e=n.replace(/\/SKILL\.md$/,``),r=e.split(`/`).pop()||e;t.push({name:r,path:e})}return{skills:t}}if(n.status===`not_found`)return{skills:[],error:`${a?`branch "${a}" in ${e}/${t}`:`repository ${e}/${t}`} not found`}}let o=[];async function s(r){let i=`https://api.github.com/repos/${e}/${t}/contents/${r}`,c=a?`${i}?ref=${encodeURIComponent(a)}`:i,l=await n.request(c);if(l.status!==200)throw Error(oy(l,`${e}/${t}${r?`/${r}`:``}`,n.hasToken));let u=Oo(l.body);for(let e of u)if(e.type===`file`&&e.name===`SKILL.md`){let t=e.path.replace(`/SKILL.md`,``),n=t.split(`/`).pop()||t;o.push({name:n,path:t})}else e.type===`dir`&&await s(e.path)}try{return await s(r||``),{skills:o}}catch(e){return{skills:[],error:e instanceof Error?e.message:String(e)}}}async function ky(e,t,n,r,i,a,o=!1,s,c){try{let l=`${Hv}/${r}`;try{if(await i.stat(l),!o)return{stdout:``,stderr:`upskill: skill "${r}" already exists (use --force to overwrite)\n`,exitCode:1};await i.rm(l,{recursive:!0})}catch{}if(s){let a=await Ey(e,t,s,c);if(a.status===`not_found`)return{stdout:``,stderr:`upskill: ${c?`branch "${c}" in ${e}/${t}`:`repository ${e}/${t}`} not found\n`,exitCode:1};if(a.status===`ok`){let o=Dy(a.files),s=n.replace(/^\/|\/$/g,``)+`/`;await i.mkdir(l,{recursive:!0});let c=0;for(let[e,t]of Object.entries(o)){if(!e.startsWith(s))continue;let n=e.slice(s.length);if(!n||e.endsWith(`/`))continue;let r=`${l}/${n}`,a=r.substring(0,r.lastIndexOf(`/`));a!==l&&await i.mkdir(a,{recursive:!0}),await i.writeFile(r,t),c++}if(c>0)return await Fy(),await Ny(),{stdout:`Installed skill "${r}" from ${e}/${t}\n`,stderr:``,exitCode:0}}}let u=`https://api.github.com/repos/${e}/${t}/contents/${n}`,d=c?`${u}?ref=${encodeURIComponent(c)}`:u,f=await a.request(d);if(f.status!==200)return{stdout:``,stderr:`upskill: ${oy(f,`${e}/${t}/${n}`,a.hasToken)}\n`,exitCode:1};let p=Oo(f.body);await i.mkdir(l,{recursive:!0});async function m(n,r){for(let o of n)if(o.type===`file`&&o.download_url){let n=await a.request(o.download_url,`*/*`);if(n.status!==200)throw Error(oy(n,`${e}/${t}/${o.path}`,a.hasToken));let s=Co(o.download_url);await i.writeFile(`${r}/${o.name}`,s??n.body)}else if(o.type===`dir`){let n=`https://api.github.com/repos/${e}/${t}/contents/${o.path}`,s=c?`${n}?ref=${encodeURIComponent(c)}`:n,l=await a.request(s);if(l.status!==200)throw Error(oy(l,`${e}/${t}/${o.path}`,a.hasToken));let u=Oo(l.body);await i.mkdir(`${r}/${o.name}`,{recursive:!0}),await m(u,`${r}/${o.name}`)}}try{await m(p,l)}catch(e){try{await i.rm(l,{recursive:!0})}catch{}throw e}return await jy(),{stdout:`Installed skill "${r}" from ${e}/${t}\n`,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`upskill: failed to install from GitHub: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}}function Ay(e){let t=e.match(/^https?:\/\/clawhub\.ai\/[^\/]+\/([^\/]+)/);if(t)return t[1];if(e.startsWith(`clawhub:`)){let t=e.slice(8);return t.includes(`/`)?t.split(`/`)[1]:t}return null}async function jy(){await Fy(),await Ny()}async function My(e,t,n,r,i=!1){let a=`${Hv}/${t}`;try{if(await r.stat(a),!i)return{ok:!1,error:`skill "${t}" already exists (use --force to overwrite)`};await r.rm(a,{recursive:!0})}catch{}let o=e.replace(/^\/|\/$/g,``),s=o?o+`/`:``;await r.mkdir(a,{recursive:!0});let c=0;try{for(let[e,t]of Object.entries(n)){if(!e.startsWith(s))continue;let n=e.slice(s.length);if(!n||e.endsWith(`/`))continue;let i=`${a}/${n}`,o=i.replace(/\/+/g,`/`);if(o.includes(`/../`)||o.includes(`/..`)||!o.startsWith(a+`/`))continue;let l=i.substring(0,i.lastIndexOf(`/`));l!==a&&await r.mkdir(l,{recursive:!0}),await r.writeFile(i,t),c++}}catch(e){throw await r.rm(a,{recursive:!0}).catch(()=>{}),e}return c===0?(await r.rm(a,{recursive:!0}).catch(()=>{}),{ok:!1,error:`no files found for skill "${t}" in ZIP`}):{ok:!0}}async function Ny(){try{let e=(typeof window<`u`?window:globalThis).__slicc_reloadSkills;if(typeof e==`function`){await e();return}typeof chrome<`u`&&chrome?.runtime?.sendMessage&&chrome.runtime.sendMessage({source:`panel`,payload:{type:`reload-skills`}})}catch{}}function Py(e){let t=e.match(/^([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)(?:@([a-zA-Z0-9_./\-]+))?$/);return t?{owner:t[1],repo:t[2],branch:t[3]}:null}async function Fy(){try{if(typeof window>`u`)return;let e=window.__slicc_sprinkleManager;e&&typeof e.openNewAutoOpenSprinkles==`function`&&await e.openNewAutoOpenSprinkles()}catch{}}async function Iy(e,t,n){let r=null;try{let t=await e.readDir(`/home`);for(let n of t)try{let t=await e.readTextFile(`/home/${n.name}/.welcome.json`);r=JSON.parse(t);break}catch{}}catch{}if(!r)return{stdout:``,stderr:`upskill: no user profile found. Complete the welcome onboarding first, or create /home/<name>/.welcome.json manually.
1871
- `,exitCode:1};let i,a;try{let[n,r]=await Promise.all([(async()=>{let e=await t(Kv,{headers:{Accept:`application/json`}});if(e.status!==200)throw Error(`HTTP ${e.status}`);return Jv(Oo(e.body).data)})(),Qv(e)]);i=n,a=r}catch(e){return{stdout:``,stderr:`upskill: failed to fetch skill catalog from ${Kv}: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}let o=Xv(i,r).filter(e=>!a.has(e.entry.name));if(o.length===0)return{stdout:`No new skill recommendations — all matching skills are already installed.
1872
- `,stderr:``,exitCode:0};if(n){let n=new Map;for(let e of o){let t=e.entry.source.repo,r=n.get(t);r?r.push(e):n.set(t,[e])}let r=o.length,i=0,a=Date.now(),s=``,c=``,l=0,u=await Promise.allSettled(Array.from(n.entries()).map(async([n,o])=>{let[c,l]=n.split(`/`),u=await Ey(c,l,t);if(u.status===`not_found`||u.status===`error`){let e=u.status===`not_found`?`upskill: repository ${n} not found\n`:`upskill: failed to fetch ${n}: ${u.message}\n`,t=[];for(let e of o){i++,((Date.now()-a)/1e3).toFixed(1);let o=i<r?` (~${Math.round((r-i)*(Date.now()-a)/i/1e3)}s remaining)`:``;s+=`[${i}/${r}] Failed "${e.entry.name}" from ${n}: repo fetch failed${o}\n`,t.push({ok:!1,name:e.entry.name,error:`repo fetch failed for ${n}`})}return{errors:e,results:t}}let d=Dy(u.files),f=[],p=new Map;for(let e of Object.keys(d))if(e.endsWith(`/SKILL.md`)){let t=e.replace(/\/SKILL\.md$/,``),n=t.split(`/`).pop()||t;p.set(n,t)}for(let t of o){let o=t.entry.source,c,l;if(o.skill){let e=p.get(o.skill);if(e)c=e,l=o.skill;else if(o.path)c=o.path.replace(/^\/|\/$/g,``),l=o.skill;else{let e=`skill "${o.skill}" not found in ${n}`;f.push({ok:!1,name:t.entry.name,error:e}),i++;let c=i<r?` (~${Math.round((r-i)*(Date.now()-a)/i/1e3)}s remaining)`:``;s+=`[${i}/${r}] Failed "${t.entry.name}" from ${n}: ${e}${c}\n`;continue}}else if(o.path)c=o.path.replace(/^\/|\/$/g,``),l=t.entry.name;else{let e=p.get(t.entry.name);if(e)c=e,l=t.entry.name;else{let e=`skill "${t.entry.name}" not found in ${n} and no explicit path provided`;f.push({ok:!1,name:t.entry.name,error:e}),i++;let o=i<r?` (~${Math.round((r-i)*(Date.now()-a)/i/1e3)}s remaining)`:``;s+=`[${i}/${r}] Failed "${t.entry.name}" from ${n}: ${e}${o}\n`;continue}}let u=Date.now(),m=await My(c,l,d,e,!1);i++;let h=((Date.now()-u)/1e3).toFixed(1),g=(Date.now()-a)/i,_=Math.round((r-i)*g/1e3),v=i<r?` (~${_}s remaining)`:``;m.ok?(f.push({ok:!0,name:l}),s+=`[${i}/${r}] Installed "${l}" from ${n} (${h}s)${v}\n`):(f.push({ok:!1,name:l,error:m.error}),s+=`[${i}/${r}] Failed "${l}" from ${n}: ${m.error}${v}\n`)}return{errors:``,results:f}}));for(let e of u){if(e.status===`rejected`){c+=`upskill: unexpected error: ${e.reason}\n`;continue}e.value.errors&&(c+=e.value.errors);for(let t of e.value.results)t.ok?l++:t.error&&(c+=`upskill: ${t.error}\n`)}let d=((Date.now()-a)/1e3).toFixed(1);return l>0&&(s+=`\nInstalled ${l} recommended skill(s) in ${d}s\n`,await jy()),{stdout:s,stderr:c,exitCode:+!!c}}let s=`Recommended skills for you:
1870
+ `),{stdout:h,stderr:``,exitCode:0}}async function Cy(e,t,n,r=!1,i){try{let a=`${Uv}/${e}`;try{if(await t.stat(a),!r)return{stdout:``,stderr:`upskill: skill "${e}" already exists (use --force to overwrite)\n`,exitCode:1};await t.rm(a,{recursive:!0})}catch{}let o=`${Vv}/download?slug=${encodeURIComponent(e)}`,s=await n(o,{});if(s.status===404)return{stdout:``,stderr:`upskill: skill "${e}" not found on ClawHub\n`,exitCode:1};if(s.status!==200)return{stdout:``,stderr:`upskill: failed to download skill (HTTP ${s.status})\n`,exitCode:1};let c=s.headers[`content-type`]||``,l=Co(o);l||=ko(s.body);let u;try{u=P(l)}catch(e){let t=e instanceof Error?e.message:String(e),n=Array.from(l.slice(0,20)).map(e=>e.toString(16).padStart(2,`0`)).join(` `);return{stdout:``,stderr:`upskill: failed to unzip: ${t}\nContent-Type: ${c}\nBody: ${l.length} bytes\nHex: ${n}\n`,exitCode:1}}await t.mkdir(a,{recursive:!0});let d=0;for(let[e,n]of Object.entries(u)){let r=e.replace(/\\/g,`/`);if(!r||r.endsWith(`/`)||r===`_meta.json`)continue;let i=`${a}/${r}`,o=i.substring(0,i.lastIndexOf(`/`));o!==a&&await t.mkdir(o,{recursive:!0}),await t.writeFile(i,n),d++}let f=wy(u,i);return await My(),{stdout:`Installed skill "${e}" from ClawHub (${d} files)\n${f}`,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`upskill: failed to install from ClawHub: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}}function wy(e,t){let n;for(let[t,r]of Object.entries(e))if((t.split(`/`).pop()||``).toLowerCase()===`skill.md`){n=new TextDecoder().decode(r);break}if(!n)return``;let r=n.match(/^---\s*\n([\s\S]*?)\n---/);if(!r)return``;let i=r[1],a=Ty(i);if(a.length===0)return``;if(!t||t.length===0)return` Requires: ${a.join(`, `)}\n`;let o=new Set(t),s=a.filter(e=>!o.has(e));return s.length===0?` Requires: ${a.join(`, `)} (all available)\n`:` Requires: ${a.join(`, `)}\n Missing: ${s.join(`, `)} -- this skill may not work in the SLICC shell\n`}function Ty(e){let t=e.match(/metadata:\s*\n\s*(\{[\s\S]*\})/);if(t)try{let e=JSON.parse(t[1]);for(let t of[`openclaw`,`clawdis`,`clawdbot`]){let n=e[t];if(n?.requires&&typeof n.requires==`object`){let e=n.requires;if(Array.isArray(e.bins))return e.bins.filter(e=>typeof e==`string`)}}}catch{}let n=e.match(/"bins"\s*:\s*\[([^\]]*)\]/);return n?n[1].split(`,`).map(e=>e.trim().replace(/^["']|["']$/g,``)).filter(Boolean):[]}async function Ey(e,t){let n=await t(`${Hv}/experimental/search?q=${encodeURIComponent(e)}&contentType=skills&page%5Bsize%5D=5`,{headers:{Accept:`application/json`}});if(n.status!==200)return{error:`Tessl search failed (HTTP ${n.status})`};let r=Oo(n.body).data?.find(t=>t.type===`skill`&&t.attributes.name===e);if(!r)return{error:`skill "${e}" not found on Tessl registry`};let i=yy(r.attributes.sourceUrl);if(!i)return{error:`skill "${e}" has no GitHub source URL`};let a=r.attributes.path.replace(/\/SKILL\.md$/i,``);return{owner:i.owner,repo:i.repo,skillPath:a,skillName:e}}async function Dy(e,t,n,r=`main`){let i=`https://codeload.github.com/${e}/${t}/zip/refs/heads/${r}`,a=await n(i,{headers:{"User-Agent":`slicc-upskill`}});if(a.status===404)return r===`main`?Dy(e,t,n,`master`):{status:`not_found`};if(a.status!==200)return{status:`error`,message:`codeload returned HTTP ${a.status}`};let o=Co(i);o||=ko(a.body);try{return{status:`ok`,files:P(o)}}catch(e){return{status:`error`,message:`failed to unzip: ${e instanceof Error?e.message:String(e)}`}}}function Oy(e){let t={};for(let[n,r]of Object.entries(e)){let e=n.indexOf(`/`);if(e<0)continue;let i=n.slice(e+1);i&&(t[i]=r)}return t}async function ky(e,t,n,r,i,a){if(i){let n=await Dy(e,t,i,a);if(n.status===`ok`){let e=Oy(n.files),t=[],i=r?r.replace(/^\/|\/$/g,``)+`/`:``;for(let n of Object.keys(e))if(n.startsWith(i)&&(n.split(`/`).pop()||``)===`SKILL.md`){let e=n.replace(/\/SKILL\.md$/,``),r=e.split(`/`).pop()||e;t.push({name:r,path:e})}return{skills:t}}if(n.status===`not_found`)return{skills:[],error:`${a?`branch "${a}" in ${e}/${t}`:`repository ${e}/${t}`} not found`}}let o=[];async function s(r){let i=`https://api.github.com/repos/${e}/${t}/contents/${r}`,c=a?`${i}?ref=${encodeURIComponent(a)}`:i,l=await n.request(c);if(l.status!==200)throw Error(sy(l,`${e}/${t}${r?`/${r}`:``}`,n.hasToken));let u=Oo(l.body);for(let e of u)if(e.type===`file`&&e.name===`SKILL.md`){let t=e.path.replace(`/SKILL.md`,``),n=t.split(`/`).pop()||t;o.push({name:n,path:t})}else e.type===`dir`&&await s(e.path)}try{return await s(r||``),{skills:o}}catch(e){return{skills:[],error:e instanceof Error?e.message:String(e)}}}async function Ay(e,t,n,r,i,a,o=!1,s,c){try{let l=`${Uv}/${r}`;try{if(await i.stat(l),!o)return{stdout:``,stderr:`upskill: skill "${r}" already exists (use --force to overwrite)\n`,exitCode:1};await i.rm(l,{recursive:!0})}catch{}if(s){let a=await Dy(e,t,s,c);if(a.status===`not_found`)return{stdout:``,stderr:`upskill: ${c?`branch "${c}" in ${e}/${t}`:`repository ${e}/${t}`} not found\n`,exitCode:1};if(a.status===`ok`){let o=Oy(a.files),s=n.replace(/^\/|\/$/g,``)+`/`;await i.mkdir(l,{recursive:!0});let c=0;for(let[e,t]of Object.entries(o)){if(!e.startsWith(s))continue;let n=e.slice(s.length);if(!n||e.endsWith(`/`))continue;let r=`${l}/${n}`,a=r.substring(0,r.lastIndexOf(`/`));a!==l&&await i.mkdir(a,{recursive:!0}),await i.writeFile(r,t),c++}if(c>0)return await Iy(),await Py(),{stdout:`Installed skill "${r}" from ${e}/${t}\n`,stderr:``,exitCode:0}}}let u=`https://api.github.com/repos/${e}/${t}/contents/${n}`,d=c?`${u}?ref=${encodeURIComponent(c)}`:u,f=await a.request(d);if(f.status!==200)return{stdout:``,stderr:`upskill: ${sy(f,`${e}/${t}/${n}`,a.hasToken)}\n`,exitCode:1};let p=Oo(f.body);await i.mkdir(l,{recursive:!0});async function m(n,r){for(let o of n)if(o.type===`file`&&o.download_url){let n=await a.request(o.download_url,`*/*`);if(n.status!==200)throw Error(sy(n,`${e}/${t}/${o.path}`,a.hasToken));let s=Co(o.download_url);await i.writeFile(`${r}/${o.name}`,s??n.body)}else if(o.type===`dir`){let n=`https://api.github.com/repos/${e}/${t}/contents/${o.path}`,s=c?`${n}?ref=${encodeURIComponent(c)}`:n,l=await a.request(s);if(l.status!==200)throw Error(sy(l,`${e}/${t}/${o.path}`,a.hasToken));let u=Oo(l.body);await i.mkdir(`${r}/${o.name}`,{recursive:!0}),await m(u,`${r}/${o.name}`)}}try{await m(p,l)}catch(e){try{await i.rm(l,{recursive:!0})}catch{}throw e}return await My(),{stdout:`Installed skill "${r}" from ${e}/${t}\n`,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`upskill: failed to install from GitHub: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}}function jy(e){let t=e.match(/^https?:\/\/clawhub\.ai\/[^\/]+\/([^\/]+)/);if(t)return t[1];if(e.startsWith(`clawhub:`)){let t=e.slice(8);return t.includes(`/`)?t.split(`/`)[1]:t}return null}async function My(){await Iy(),await Py()}async function Ny(e,t,n,r,i=!1){let a=`${Uv}/${t}`;try{if(await r.stat(a),!i)return{ok:!1,error:`skill "${t}" already exists (use --force to overwrite)`};await r.rm(a,{recursive:!0})}catch{}let o=e.replace(/^\/|\/$/g,``),s=o?o+`/`:``;await r.mkdir(a,{recursive:!0});let c=0;try{for(let[e,t]of Object.entries(n)){if(!e.startsWith(s))continue;let n=e.slice(s.length);if(!n||e.endsWith(`/`))continue;let i=`${a}/${n}`,o=i.replace(/\/+/g,`/`);if(o.includes(`/../`)||o.includes(`/..`)||!o.startsWith(a+`/`))continue;let l=i.substring(0,i.lastIndexOf(`/`));l!==a&&await r.mkdir(l,{recursive:!0}),await r.writeFile(i,t),c++}}catch(e){throw await r.rm(a,{recursive:!0}).catch(()=>{}),e}return c===0?(await r.rm(a,{recursive:!0}).catch(()=>{}),{ok:!1,error:`no files found for skill "${t}" in ZIP`}):{ok:!0}}async function Py(){try{let e=(typeof window<`u`?window:globalThis).__slicc_reloadSkills;if(typeof e==`function`){await e();return}typeof chrome<`u`&&chrome?.runtime?.sendMessage&&chrome.runtime.sendMessage({source:`panel`,payload:{type:`reload-skills`}})}catch{}}function Fy(e){let t=e.match(/^([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)(?:@([a-zA-Z0-9_./\-]+))?$/);return t?{owner:t[1],repo:t[2],branch:t[3]}:null}async function Iy(){try{if(typeof window>`u`)return;let e=window.__slicc_sprinkleManager;e&&typeof e.openNewAutoOpenSprinkles==`function`&&await e.openNewAutoOpenSprinkles()}catch{}}async function Ly(e,t,n){let r=null;try{let t=await e.readDir(`/home`);for(let n of t)try{let t=await e.readTextFile(`/home/${n.name}/.welcome.json`);r=JSON.parse(t);break}catch{}}catch{}if(!r)return{stdout:``,stderr:`upskill: no user profile found. Complete the welcome onboarding first, or create /home/<name>/.welcome.json manually.
1871
+ `,exitCode:1};let i,a;try{let[n,r]=await Promise.all([(async()=>{let e=await t(qv,{headers:{Accept:`application/json`}});if(e.status!==200)throw Error(`HTTP ${e.status}`);return Yv(Oo(e.body).data)})(),$v(e)]);i=n,a=r}catch(e){return{stdout:``,stderr:`upskill: failed to fetch skill catalog from ${qv}: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}let o=Zv(i,r).filter(e=>!a.has(e.entry.name));if(o.length===0)return{stdout:`No new skill recommendations — all matching skills are already installed.
1872
+ `,stderr:``,exitCode:0};if(n){let n=new Map;for(let e of o){let t=e.entry.source.repo,r=n.get(t);r?r.push(e):n.set(t,[e])}let r=o.length,i=0,a=Date.now(),s=``,c=``,l=0,u=await Promise.allSettled(Array.from(n.entries()).map(async([n,o])=>{let[c,l]=n.split(`/`),u=await Dy(c,l,t);if(u.status===`not_found`||u.status===`error`){let e=u.status===`not_found`?`upskill: repository ${n} not found\n`:`upskill: failed to fetch ${n}: ${u.message}\n`,t=[];for(let e of o){i++,((Date.now()-a)/1e3).toFixed(1);let o=i<r?` (~${Math.round((r-i)*(Date.now()-a)/i/1e3)}s remaining)`:``;s+=`[${i}/${r}] Failed "${e.entry.name}" from ${n}: repo fetch failed${o}\n`,t.push({ok:!1,name:e.entry.name,error:`repo fetch failed for ${n}`})}return{errors:e,results:t}}let d=Oy(u.files),f=[],p=new Map;for(let e of Object.keys(d))if(e.endsWith(`/SKILL.md`)){let t=e.replace(/\/SKILL\.md$/,``),n=t.split(`/`).pop()||t;p.set(n,t)}for(let t of o){let o=t.entry.source,c,l;if(o.skill){let e=p.get(o.skill);if(e)c=e,l=o.skill;else if(o.path)c=o.path.replace(/^\/|\/$/g,``),l=o.skill;else{let e=`skill "${o.skill}" not found in ${n}`;f.push({ok:!1,name:t.entry.name,error:e}),i++;let c=i<r?` (~${Math.round((r-i)*(Date.now()-a)/i/1e3)}s remaining)`:``;s+=`[${i}/${r}] Failed "${t.entry.name}" from ${n}: ${e}${c}\n`;continue}}else if(o.path)c=o.path.replace(/^\/|\/$/g,``),l=t.entry.name;else{let e=p.get(t.entry.name);if(e)c=e,l=t.entry.name;else{let e=`skill "${t.entry.name}" not found in ${n} and no explicit path provided`;f.push({ok:!1,name:t.entry.name,error:e}),i++;let o=i<r?` (~${Math.round((r-i)*(Date.now()-a)/i/1e3)}s remaining)`:``;s+=`[${i}/${r}] Failed "${t.entry.name}" from ${n}: ${e}${o}\n`;continue}}let u=Date.now(),m=await Ny(c,l,d,e,!1);i++;let h=((Date.now()-u)/1e3).toFixed(1),g=(Date.now()-a)/i,_=Math.round((r-i)*g/1e3),v=i<r?` (~${_}s remaining)`:``;m.ok?(f.push({ok:!0,name:l}),s+=`[${i}/${r}] Installed "${l}" from ${n} (${h}s)${v}\n`):(f.push({ok:!1,name:l,error:m.error}),s+=`[${i}/${r}] Failed "${l}" from ${n}: ${m.error}${v}\n`)}return{errors:``,results:f}}));for(let e of u){if(e.status===`rejected`){c+=`upskill: unexpected error: ${e.reason}\n`;continue}e.value.errors&&(c+=e.value.errors);for(let t of e.value.results)t.ok?l++:t.error&&(c+=`upskill: ${t.error}\n`)}let d=((Date.now()-a)/1e3).toFixed(1);return l>0&&(s+=`\nInstalled ${l} recommended skill(s) in ${d}s\n`,await My()),{stdout:s,stderr:c,exitCode:+!!c}}let s=`Recommended skills for you:
1873
1873
 
1874
- `,c=0;for(let e of o){c++;let t=Zv(e.entry.source);s+=` ${c}. ${e.entry.displayName.padEnd(35)} score: ${Math.round(e.score)}\n`,s+=` ${e.entry.description}\n`,s+=` Match: ${e.matchReasons.join(`, `)}\n`,s+=` Install: ${t}\n\n`}return s+=`To install all recommended: upskill recommendations --install
1875
- `,{stdout:s,stderr:``,exitCode:0}}function Ly(e,t){return Ve(`upskill`,async(n,r)=>{if(n.length===0||n.includes(`--help`)||n.includes(`-h`))return gy();let a=[],o,s=!1,c=!1,l=!1,u=``,d,f=``,p=1,m=0;for(;m<n.length;){let r=n[m];if(r===`search`){let e=n.slice(m+1),t=e.indexOf(`--page`);t>=0&&(p=parseInt(e[t+1],10)||1,e.splice(t,2)),f=e.join(` `);break}else if(r===`recommendations`)return Iy(e,t,n.includes(`--install`));else if(r===`list`){let t=await(await i(()=>import(`./skills-CTCIxQqH.js`).then(e=>e.t),__vite__mapDeps([16,4,17,15,18,19]))).discoverSkills(e);return t.length===0?{stdout:`No discoverable local skills found.\n\n${sy()}${cy()}`,stderr:``,exitCode:0}:{stdout:py(t,`Discoverable local skills`),stderr:``,exitCode:0}}else if(r===`info`||r===`read`){let t=n[m+1];if(!t)return{stdout:``,stderr:`upskill: ${r} requires a skill name\n`,exitCode:1};let a=await i(()=>import(`./skills-CTCIxQqH.js`).then(e=>e.t),__vite__mapDeps([16,4,17,15,18,19]));if(r===`info`){let n=await a.getSkillInfo(e,t);return n?{stdout:my(n),stderr:``,exitCode:0}:{stdout:``,stderr:`upskill: skill "${t}" not found\n`,exitCode:1}}else{let n=await a.readSkillInstructions(e,t);return n===null?{stdout:``,stderr:`upskill: no SKILL.md found for "${t}"\n`,exitCode:1}:{stdout:n+`
1874
+ `,c=0;for(let e of o){c++;let t=Qv(e.entry.source);s+=` ${c}. ${e.entry.displayName.padEnd(35)} score: ${Math.round(e.score)}\n`,s+=` ${e.entry.description}\n`,s+=` Match: ${e.matchReasons.join(`, `)}\n`,s+=` Install: ${t}\n\n`}return s+=`To install all recommended: upskill recommendations --install
1875
+ `,{stdout:s,stderr:``,exitCode:0}}function Ry(e,t){return Ve(`upskill`,async(n,r)=>{if(n.length===0||n.includes(`--help`)||n.includes(`-h`))return _y();let a=[],o,s=!1,c=!1,l=!1,u=``,d,f=``,p=1,m=0;for(;m<n.length;){let r=n[m];if(r===`search`){let e=n.slice(m+1),t=e.indexOf(`--page`);t>=0&&(p=parseInt(e[t+1],10)||1,e.splice(t,2)),f=e.join(` `);break}else if(r===`recommendations`)return Ly(e,t,n.includes(`--install`));else if(r===`list`){let t=await(await i(()=>import(`./skills-DBBQyHko.js`).then(e=>e.t),__vite__mapDeps([16,4,17,15,18,19]))).discoverSkills(e);return t.length===0?{stdout:`No discoverable local skills found.\n\n${cy()}${ly()}`,stderr:``,exitCode:0}:{stdout:my(t,`Discoverable local skills`),stderr:``,exitCode:0}}else if(r===`info`||r===`read`){let t=n[m+1];if(!t)return{stdout:``,stderr:`upskill: ${r} requires a skill name\n`,exitCode:1};let a=await i(()=>import(`./skills-DBBQyHko.js`).then(e=>e.t),__vite__mapDeps([16,4,17,15,18,19]));if(r===`info`){let n=await a.getSkillInfo(e,t);return n?{stdout:hy(n),stderr:``,exitCode:0}:{stdout:``,stderr:`upskill: skill "${t}" not found\n`,exitCode:1}}else{let n=await a.readSkillInstructions(e,t);return n===null?{stdout:``,stderr:`upskill: no SKILL.md found for "${t}"\n`,exitCode:1}:{stdout:n+`
1876
1876
  `,stderr:``,exitCode:0}}}else if(r===`--skill`)a.push(n[++m]);else if(r===`--path`||r===`-p`)o=n[++m];else if(r===`--list`)s=!0;else if(r===`--all`)c=!0;else if(r===`--force`)l=!0;else if(r===`--branch`||r===`-b`){let e=n[m+1];if(!e||e.startsWith(`-`))return{stdout:``,stderr:`upskill: --branch requires a value
1877
- `,exitCode:1};d=n[++m]}else r.startsWith(`-`)||(u=r);m++}if(f)return xy(f,t,p);if(!u)return gy();let h=Ay(u);if(h){let n=r.getRegisteredCommands?.()??[];return Sy(h,e,t,l,n)}if(u.startsWith(`tessl:`)){let n=u.slice(6);if(!n)return{stdout:``,stderr:`upskill: tessl: requires a skill name
1878
- `,exitCode:1};let r=await Ty(n,t);if(`error`in r)return{stdout:``,stderr:`upskill: ${r.error}\n`,exitCode:1};let i=await ry(t);return ky(r.owner,r.repo,r.skillPath,r.skillName,e,i,l,t)}let g=Py(u);if(g){let{owner:n,repo:r}=g,i=d??g.branch,f=await ry(t),p=await Oy(n,r,f,o,t,i);if(p.error)return{stdout:``,stderr:`upskill: failed to list skills: ${p.error}\n`,exitCode:1};if(p.skills.length===0)return{stdout:`No skills found in ${n}/${r}${o?`/`+o:``}\n`,stderr:``,exitCode:0};if(s){let e=`Available skills in ${n}/${r}:\n\n`;for(let t of p.skills)e+=` ${t.name.padEnd(30)} ${t.path}\n`;return e+=`\nFound ${p.skills.length} skill(s)\n`,e+=`\nTo install: upskill ${u} --skill <name>\n`,e+=`To install all: upskill ${u} --all\n`,{stdout:e,stderr:``,exitCode:0}}let m=p.skills;if(a.length>0){m=p.skills.filter(e=>a.includes(e.name));for(let e of a)if(!p.skills.find(t=>t.name===e))return{stdout:``,stderr:`upskill: skill "${e}" not found in ${n}/${r}\n`,exitCode:1}}else if(!c){let e=`Available skills in ${n}/${r}:\n\n`;for(let t of p.skills)e+=` ${t.name.padEnd(30)} ${t.path}\n`;return e+=`\nFound ${p.skills.length} skill(s)\n`,e+=`\nTo install specific skills: upskill ${u} --skill <name>\n`,e+=`To install all: upskill ${u} --all\n`,{stdout:e,stderr:``,exitCode:0}}let h=``,_=``,v=0,y=m.length,b=Date.now();if(y>1){let a=await Ey(n,r,t,i);if(a.status===`not_found`)return{stdout:``,stderr:`upskill: ${i?`branch "${i}" in ${n}/${r}`:`repository ${n}/${r}`} not found\n`,exitCode:1};if(a.status===`error`)return{stdout:``,stderr:`upskill: failed to fetch ${n}/${r}: ${a.message}\n`,exitCode:1};let o=Dy(a.files);for(let t=0;t<m.length;t++){let i=m[t],a=await My(i.path,i.name,o,e,l),s=t+1,c=((Date.now()-b)/1e3).toFixed(1),u=(Date.now()-b)/s,d=Math.round((y-s)*u/1e3),f=s<y?` (~${d}s remaining)`:``;a.ok?(h+=`[${s}/${y}] Installed "${i.name}" from ${n}/${r} (${c}s)${f}\n`,v++):(h+=`[${s}/${y}] Failed "${i.name}": ${a.error}${f}\n`,_+=`upskill: ${a.error}\n`)}}else for(let a of m){let o=await ky(n,r,a.path,a.name,e,f,l,t,i);o.exitCode===0?(h+=o.stdout,v++):_+=o.stderr}let x=((Date.now()-b)/1e3).toFixed(1);return v>0&&(h+=`\nInstalled ${v} skill(s)${y>1?` in ${x}s`:``}\n`,await jy()),{stdout:h,stderr:_,exitCode:+!!_}}return{stdout:``,stderr:`upskill: unrecognized source "${u}"\n\nExpected: owner/repo, clawhub:<slug>, tessl:<name>, or https://clawhub.ai/user/skill\n`,exitCode:1}})}function Ry(e){return Ve(`skill`,async(t,n)=>{if(t.length===0||t.includes(`--help`)||t.includes(`-h`))return{stdout:`usage: skill <command> [options]
1877
+ `,exitCode:1};d=n[++m]}else r.startsWith(`-`)||(u=r);m++}if(f)return Sy(f,t,p);if(!u)return _y();let h=jy(u);if(h){let n=r.getRegisteredCommands?.()??[];return Cy(h,e,t,l,n)}if(u.startsWith(`tessl:`)){let n=u.slice(6);if(!n)return{stdout:``,stderr:`upskill: tessl: requires a skill name
1878
+ `,exitCode:1};let r=await Ey(n,t);if(`error`in r)return{stdout:``,stderr:`upskill: ${r.error}\n`,exitCode:1};let i=await iy(t);return Ay(r.owner,r.repo,r.skillPath,r.skillName,e,i,l,t)}let g=Fy(u);if(g){let{owner:n,repo:r}=g,i=d??g.branch,f=await iy(t),p=await ky(n,r,f,o,t,i);if(p.error)return{stdout:``,stderr:`upskill: failed to list skills: ${p.error}\n`,exitCode:1};if(p.skills.length===0)return{stdout:`No skills found in ${n}/${r}${o?`/`+o:``}\n`,stderr:``,exitCode:0};if(s){let e=`Available skills in ${n}/${r}:\n\n`;for(let t of p.skills)e+=` ${t.name.padEnd(30)} ${t.path}\n`;return e+=`\nFound ${p.skills.length} skill(s)\n`,e+=`\nTo install: upskill ${u} --skill <name>\n`,e+=`To install all: upskill ${u} --all\n`,{stdout:e,stderr:``,exitCode:0}}let m=p.skills;if(a.length>0){m=p.skills.filter(e=>a.includes(e.name));for(let e of a)if(!p.skills.find(t=>t.name===e))return{stdout:``,stderr:`upskill: skill "${e}" not found in ${n}/${r}\n`,exitCode:1}}else if(!c){let e=`Available skills in ${n}/${r}:\n\n`;for(let t of p.skills)e+=` ${t.name.padEnd(30)} ${t.path}\n`;return e+=`\nFound ${p.skills.length} skill(s)\n`,e+=`\nTo install specific skills: upskill ${u} --skill <name>\n`,e+=`To install all: upskill ${u} --all\n`,{stdout:e,stderr:``,exitCode:0}}let h=``,_=``,v=0,y=m.length,b=Date.now();if(y>1){let a=await Dy(n,r,t,i);if(a.status===`not_found`)return{stdout:``,stderr:`upskill: ${i?`branch "${i}" in ${n}/${r}`:`repository ${n}/${r}`} not found\n`,exitCode:1};if(a.status===`error`)return{stdout:``,stderr:`upskill: failed to fetch ${n}/${r}: ${a.message}\n`,exitCode:1};let o=Oy(a.files);for(let t=0;t<m.length;t++){let i=m[t],a=await Ny(i.path,i.name,o,e,l),s=t+1,c=((Date.now()-b)/1e3).toFixed(1),u=(Date.now()-b)/s,d=Math.round((y-s)*u/1e3),f=s<y?` (~${d}s remaining)`:``;a.ok?(h+=`[${s}/${y}] Installed "${i.name}" from ${n}/${r} (${c}s)${f}\n`,v++):(h+=`[${s}/${y}] Failed "${i.name}": ${a.error}${f}\n`,_+=`upskill: ${a.error}\n`)}}else for(let a of m){let o=await Ay(n,r,a.path,a.name,e,f,l,t,i);o.exitCode===0?(h+=o.stdout,v++):_+=o.stderr}let x=((Date.now()-b)/1e3).toFixed(1);return v>0&&(h+=`\nInstalled ${v} skill(s)${y>1?` in ${x}s`:``}\n`,await My()),{stdout:h,stderr:_,exitCode:+!!_}}return{stdout:``,stderr:`upskill: unrecognized source "${u}"\n\nExpected: owner/repo, clawhub:<slug>, tessl:<name>, or https://clawhub.ai/user/skill\n`,exitCode:1}})}function zy(e){return Ve(`skill`,async(t,n)=>{if(t.length===0||t.includes(`--help`)||t.includes(`-h`))return{stdout:`usage: skill <command> [options]
1879
1879
 
1880
1880
  Commands:
1881
1881
  list List discoverable skills and management status
@@ -1884,7 +1884,7 @@ Commands:
1884
1884
  install <name> Install a native /workspace/skills skill (apply manifest)
1885
1885
  uninstall <name> Uninstall a native /workspace/skills skill
1886
1886
 
1887
- ${sy()}${cy()}
1887
+ ${cy()}${ly()}
1888
1888
 
1889
1889
  For installing skills from registries or GitHub, use 'upskill':
1890
1890
  upskill search "query" Search ClawHub + Tessl
@@ -1896,28 +1896,28 @@ Examples:
1896
1896
  skill list
1897
1897
  skill info bluebubbles
1898
1898
  skill read bluebubbles
1899
- `,stderr:``,exitCode:0};let r=t[0],a=await i(()=>import(`./skills-CTCIxQqH.js`).then(e=>e.t),__vite__mapDeps([16,4,17,15,18,19]));try{switch(r){case`list`:{let t=await a.discoverSkills(e);return t.length===0?{stdout:`No discoverable skills found.\n\n${sy()}${cy()}\nInstall install-managed skills with: upskill owner/repo --all\n`,stderr:``,exitCode:0}:{stdout:py(t,`Discoverable skills`),stderr:``,exitCode:0}}case`info`:{let n=t[1];if(!n)return{stdout:``,stderr:`skill: info requires a skill name
1900
- `,exitCode:1};let r=await a.getSkillInfo(e,n);return r?{stdout:my(r),stderr:``,exitCode:0}:{stdout:``,stderr:`skill: "${n}" not found\n`,exitCode:1}}case`read`:{let n=t[1];if(!n)return{stdout:``,stderr:`skill: read requires a skill name
1899
+ `,stderr:``,exitCode:0};let r=t[0],a=await i(()=>import(`./skills-DBBQyHko.js`).then(e=>e.t),__vite__mapDeps([16,4,17,15,18,19]));try{switch(r){case`list`:{let t=await a.discoverSkills(e);return t.length===0?{stdout:`No discoverable skills found.\n\n${cy()}${ly()}\nInstall install-managed skills with: upskill owner/repo --all\n`,stderr:``,exitCode:0}:{stdout:my(t,`Discoverable skills`),stderr:``,exitCode:0}}case`info`:{let n=t[1];if(!n)return{stdout:``,stderr:`skill: info requires a skill name
1900
+ `,exitCode:1};let r=await a.getSkillInfo(e,n);return r?{stdout:hy(r),stderr:``,exitCode:0}:{stdout:``,stderr:`skill: "${n}" not found\n`,exitCode:1}}case`read`:{let n=t[1];if(!n)return{stdout:``,stderr:`skill: read requires a skill name
1901
1901
  `,exitCode:1};let r=await a.readSkillInstructions(e,n);return r===null?{stdout:``,stderr:`skill: no SKILL.md found for "${n}"\n`,exitCode:1}:{stdout:r+`
1902
1902
  `,stderr:``,exitCode:0}}case`install`:{let n=t[1];if(!n)return{stdout:``,stderr:`skill: install requires a skill name
1903
- `,exitCode:1};let r=await a.getSkillInfo(e,n);if(r&&!uy(r))return{stdout:``,stderr:hy(`skill`,r),exitCode:1};let i=await a.applySkill(e,n);return i.success?(await Fy(),await Ny(),{stdout:`Installed skill "${i.skill}" v${i.version}\n`,stderr:``,exitCode:0}):{stdout:``,stderr:`skill: ${i.error}\n`,exitCode:1}}case`uninstall`:{let n=t[1];if(!n)return{stdout:``,stderr:`skill: uninstall requires a skill name
1904
- `,exitCode:1};let r=await a.getSkillInfo(e,n);if(r&&!uy(r))return{stdout:``,stderr:`skill: "${n}" is a compatibility skill discovered from ${r.sourceRoot} (read-only). Only native /workspace/skills entries can be uninstalled.\n`,exitCode:1};let i=await a.uninstallSkill(e,n);return i.success?{stdout:`Uninstalled skill "${i.skill}"\n`,stderr:``,exitCode:0}:{stdout:``,stderr:`skill: ${i.error}\n`,exitCode:1}}default:return{stdout:``,stderr:`skill: unknown command "${r}"\n`,exitCode:1}}}catch(e){return{stdout:``,stderr:`skill: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}function zy(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#39;`)}var By=class{constructor(e){this.options=e}async execute(e,t){let n=e[0];if(n===`--help`||n===`-h`)return this.help();if(n===`unmount`||n===`-u`){let n=e[1];if(!n)return{stdout:``,stderr:`mount unmount: path required`,exitCode:1};let r=n.startsWith(`/`)?n:`${t.replace(/\/$/,``)}/${n}`;return this.options.fs.unmount(r),{stdout:`Unmounted ${r}\n`,stderr:``,exitCode:0}}if(n===`list`||n===`-l`){let e=this.options.fs.listMounts();return e.length===0?{stdout:`No active mounts
1905
- `,stderr:``,exitCode:0}:{stdout:e.map(e=>e).join(`
1903
+ `,exitCode:1};let r=await a.getSkillInfo(e,n);if(r&&!dy(r))return{stdout:``,stderr:gy(`skill`,r),exitCode:1};let i=await a.applySkill(e,n);return i.success?(await Iy(),await Py(),{stdout:`Installed skill "${i.skill}" v${i.version}\n`,stderr:``,exitCode:0}):{stdout:``,stderr:`skill: ${i.error}\n`,exitCode:1}}case`uninstall`:{let n=t[1];if(!n)return{stdout:``,stderr:`skill: uninstall requires a skill name
1904
+ `,exitCode:1};let r=await a.getSkillInfo(e,n);if(r&&!dy(r))return{stdout:``,stderr:`skill: "${n}" is a compatibility skill discovered from ${r.sourceRoot} (read-only). Only native /workspace/skills entries can be uninstalled.\n`,exitCode:1};let i=await a.uninstallSkill(e,n);return i.success?{stdout:`Uninstalled skill "${i.skill}"\n`,stderr:``,exitCode:0}:{stdout:``,stderr:`skill: ${i.error}\n`,exitCode:1}}default:return{stdout:``,stderr:`skill: unknown command "${r}"\n`,exitCode:1}}}catch(e){return{stdout:``,stderr:`skill: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}function By(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#39;`)}var Vy=class{constructor(e){this.options=e}async execute(e,t){let n=e[0];if(n===`--help`||n===`-h`)return this.help();if(n===`unmount`||n===`-u`){let n=e[1];if(!n)return{stdout:``,stderr:`mount unmount: path required`,exitCode:1};let r=n.startsWith(`/`)?n:`${t.replace(/\/$/,``)}/${n}`;return this.options.fs.unmount(r),{stdout:`Unmounted ${r}\n`,stderr:``,exitCode:0}}if(n===`list`||n===`-l`){let e=this.options.fs.listMounts();if(e.length===0)return{stdout:`No active mounts
1905
+ `,stderr:``,exitCode:0};let t=this.options.fs.getMountIndex();return{stdout:e.map(e=>{let n=t.getState(e);return n?n.status===`ready`?`${e} (indexed: ${n.indexed} entries)`:n.status===`indexing`?`${e} (indexing: ${n.indexed} entries...)`:n.status===`error`?`${e} (index error: ${n.error})`:`${e} (pending index)`:e}).join(`
1906
1906
  `)+`
1907
- `,stderr:``,exitCode:0}}if(!n)return{stdout:``,stderr:`mount: mount point required
1907
+ `,stderr:``,exitCode:0}}if(n===`refresh`){let n=e[1];if(!n)return{stdout:``,stderr:`mount refresh: path required`,exitCode:1};let r=n.startsWith(`/`)?n:`${t.replace(/\/$/,``)}/${n}`;try{return await this.options.fs.refreshMount(r),{stdout:`Re-indexed ${r}\n`,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`mount refresh: ${e instanceof Error?e.message:String(e)}`,exitCode:1}}}if(!n)return{stdout:``,stderr:`mount: mount point required
1908
1908
  Usage: mount <target-path>
1909
1909
  `,exitCode:1};if(typeof window>`u`||!(`showDirectoryPicker`in window))return{stdout:``,stderr:`mount: File System Access API not available in this environment`,exitCode:1};let r;r=n.startsWith(`/`)?n:`${t.replace(/\/$/,``)}/${n}`,r.length>1&&(r=r.replace(/\/+$/,``));let i=s(),a;if(i){let e=await v({html:`
1910
1910
  <div class="sprinkle-action-card">
1911
1911
  <div class="sprinkle-action-card__header">Mount local directory <span class="sprinkle-badge sprinkle-badge--notice">approval</span></div>
1912
- <div class="sprinkle-action-card__body">The agent wants to mount a local directory at <code>${zy(r)}</code>. This will give the agent read/write access to files in the directory you select.</div>
1912
+ <div class="sprinkle-action-card__body">The agent wants to mount a local directory at <code>${By(r)}</code>. This will give the agent read/write access to files in the directory you select.</div>
1913
1913
  <div class="sprinkle-action-card__actions">
1914
1914
  <button class="sprinkle-btn sprinkle-btn--secondary" data-action="deny">Deny</button>
1915
1915
  <button class="sprinkle-btn sprinkle-btn--primary" data-action="approve">Select directory</button>
1916
1916
  </div>
1917
1917
  </div>
1918
- `,onAction:async e=>{if(e===`approve`)try{return{approved:!0,handle:await window.showDirectoryPicker({mode:`readwrite`})}}catch(e){return e instanceof Error&&e.name===`AbortError`?{cancelled:!0}:{error:e instanceof Error?e.message:String(e)}}return{denied:!0}}});if(!e)return{stdout:``,stderr:`mount: tool UI not available`,exitCode:1};let t=e;if(t.denied)return{stdout:``,stderr:`mount: denied by user`,exitCode:1};if(t.cancelled)return{stdout:``,stderr:`mount: cancelled`,exitCode:1};if(t.error)return{stdout:``,stderr:`mount: ${t.error}`,exitCode:1};if(!t.handle)return{stdout:``,stderr:`mount: no directory selected`,exitCode:1};a=t.handle}else try{a=await window.showDirectoryPicker({mode:`readwrite`})}catch(e){return e instanceof Error&&e.name===`AbortError`?{stdout:``,stderr:`mount: cancelled`,exitCode:1}:{stdout:``,stderr:`mount: ${e instanceof Error?e.message:String(e)}`,exitCode:1}}try{return await this.options.fs.mount(r,a),{stdout:`Mounted '${a.name}' → ${r} (live bridgereads and writes go to the real filesystem)\n`,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`mount: ${e instanceof Error?e.message:String(e)}`,exitCode:1}}}help(){return{stdout:[`Usage: mount <target-path>`,` mount unmount <path>`,` mount list`,``,`Transparently bridge a real filesystem directory into the virtual filesystem.`,`Opens a directory picker; all reads and writes under <target-path> go directly`,`to the real directory — no copying occurs. Changes are immediately visible on`,`both sides. Mount points must be empty so existing VFS files are not hidden.`,``,`Arguments:`,` <target-path> Mount point in the virtual filesystem (required).`,``,`Sub-commands:`,` unmount <path> Remove a mount point`,` list Show active mount points`,``,`Examples:`,` mount /mnt/myapp # Mount selected dir at /mnt/myapp`,` mount list # Show active mounts`,` mount unmount /mnt/myapp`].join(`
1918
+ `,onAction:async e=>{if(e===`approve`)try{return{approved:!0,handle:await window.showDirectoryPicker({mode:`readwrite`})}}catch(e){return e instanceof Error&&e.name===`AbortError`?{cancelled:!0}:{error:e instanceof Error?e.message:String(e)}}return{denied:!0}}});if(!e)return{stdout:``,stderr:`mount: tool UI not available`,exitCode:1};let t=e;if(t.denied)return{stdout:``,stderr:`mount: denied by user`,exitCode:1};if(t.cancelled)return{stdout:``,stderr:`mount: cancelled`,exitCode:1};if(t.error)return{stdout:``,stderr:`mount: ${t.error}`,exitCode:1};if(!t.handle)return{stdout:``,stderr:`mount: no directory selected`,exitCode:1};a=t.handle}else try{a=await window.showDirectoryPicker({mode:`readwrite`})}catch(e){return e instanceof Error&&e.name===`AbortError`?{stdout:``,stderr:`mount: cancelled`,exitCode:1}:{stdout:``,stderr:`mount: ${e instanceof Error?e.message:String(e)}`,exitCode:1}}try{return await this.options.fs.mount(r,a),{stdout:`Mounted '${a.name}' → ${r}\nIndexing in background for fast file discovery.\nNote: External changes are not auto-detected use 'mount refresh ${r}' after modifying files outside the browser.\n`,stderr:``,exitCode:0}}catch(e){return{stdout:``,stderr:`mount: ${e instanceof Error?e.message:String(e)}`,exitCode:1}}}help(){return{stdout:[`Usage: mount <target-path>`,` mount unmount <path>`,` mount list`,` mount refresh <path>`,``,`Transparently bridge a real filesystem directory into the virtual filesystem.`,`Opens a directory picker; all reads and writes under <target-path> go directly`,`to the real directory — no copying occurs. Changes are immediately visible on`,`both sides. Mount points must be empty so existing VFS files are not hidden.`,``,`Upon mounting, files are indexed asynchronously for fast discovery. External`,`changes (made outside the browser) are NOT automatically detected — use`,"`mount refresh` to re-index after external modifications.",``,`Arguments:`,` <target-path> Mount point in the virtual filesystem (required).`,``,`Sub-commands:`,` unmount <path> Remove a mount point`,` list Show active mount points and index status`,` refresh <path> Re-index a mount after external changes`,``,`Examples:`,` mount /mnt/myapp # Mount selected dir at /mnt/myapp`,` mount list # Show active mounts with index status`,` mount refresh /mnt/myapp # Re-index after external changes`,` mount unmount /mnt/myapp`].join(`
1919
1919
  `)+`
1920
- `,stderr:``,exitCode:0}}},Vy=new Set([`http`,`https`,`net`,`tls`,`dgram`,`dns`,`cluster`,`worker_threads`,`child_process`,`crypto`,`os`,`stream`,`zlib`,`vm`,`v8`,`perf_hooks`,`readline`,`repl`,`tty`,`inspector`]);function Hy(e){let t=/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g,n=[],r;for(;(r=t.exec(e))!==null;)n.push(r[1]);return[...new Set(n)]}async function Uy(e,t,n){return await n.fs.exists(e)?Wy(await n.fs.readFile(e),[`node`,e,...t],n):{stdout:``,stderr:`jsh: cannot find script '${e}'\n`,exitCode:127}}async function Wy(e,t,n){let r=[],a=[],o=e=>{r.push(typeof e==`string`?e:String(e))},s=e=>{a.push(typeof e==`string`?e:String(e))},c={log:(...e)=>o(`${e.map(Qh).join(` `)}\n`),info:(...e)=>o(`${e.map(Qh).join(` `)}\n`),warn:(...e)=>s(`${e.map(Qh).join(` `)}\n`),error:(...e)=>s(`${e.map(Qh).join(` `)}\n`)},l={argv:t,env:Object.fromEntries(n.env.entries()),cwd:()=>n.cwd,exit:e=>{throw new Bh(Number.isFinite(e)?Number(e):0)},stdout:{write:o},stderr:{write:s}},u={readFile:async e=>{let t=n.fs.resolvePath(n.cwd,e);return n.fs.readFile(t)},readFileBinary:async e=>{let t=n.fs.resolvePath(n.cwd,e);return n.fs.readFileBuffer(t)},writeFile:async(e,t)=>{let r=n.fs.resolvePath(n.cwd,e);await n.fs.writeFile(r,t)},writeFileBinary:async(e,t)=>{let r=n.fs.resolvePath(n.cwd,e),i=new Uint8Array(t.byteLength);i.set(t),await n.fs.writeFile(r,i)},readDir:async e=>{let t=n.fs.resolvePath(n.cwd,e);return n.fs.readdir(t)},exists:async e=>{let t=n.fs.resolvePath(n.cwd,e);return n.fs.exists(t)},stat:async e=>{let t=n.fs.resolvePath(n.cwd,e),r=await n.fs.stat(t);return{isDirectory:r.isDirectory,isFile:r.isFile,size:r.size}},mkdir:async e=>{let t=n.fs.resolvePath(n.cwd,e);await n.fs.mkdir(t,{recursive:!0})},rm:async e=>{let t=n.fs.resolvePath(n.cwd,e);await n.fs.rm(t,{recursive:!0})},fetchToFile:async(e,t)=>{if(typeof fetch>`u`)throw Error(`fetch is not available in this runtime`);let r=await fetch(e);if(!r.ok)throw Error(`fetch ${r.status} ${r.statusText}`);let i=new Uint8Array(await r.arrayBuffer()),a=n.fs.resolvePath(n.cwd,t);return await n.fs.writeFile(a,i),i.byteLength}},d=async e=>{if(!n.exec)throw Error(`exec is not available in this runtime`);let t=await n.exec(e,{cwd:n.cwd});return{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode}},f=typeof chrome<`u`&&!!chrome?.runtime?.id;if(!f){let t=Hy(e),n=new Set([`fs`,`process`,`buffer`]),r=t.map(e=>e.startsWith(`node:`)?e.slice(5):e).filter(e=>!n.has(e)&&!Vy.has(e)),a=zh.__requireCache??=Object.create(null),o=r.filter(e=>!(e in a));if(o.length>0){let e=await Promise.allSettled(o.map(async e=>{let t=await i(()=>import(`https://esm.sh/`+e),[]);return{id:e,value:t.default===void 0?t:t.default}}));for(let t of e)t.status===`fulfilled`&&(a[t.value.id]=t.value.value)}}let p=e=>{let t=e.startsWith(`node:`)?e.slice(5):e;if(t===`fs`)return u;if(t===`process`)return l;if(t===`buffer`)return{Buffer:globalThis.Buffer};if(t===`path`){let t=zh.__requireCache;if(t&&`path`in t)return t.path;if(t&&e in t)return t[e];throw Error(`require('${e}'): path module not pre-loaded. Add require('path') as a static import.`)}if(Vy.has(t))throw Error(`require('${e}'): Node built-in '${t}' is not available in the browser environment.${{http:` Use fetch() instead.`,https:` Use fetch() instead.`,child_process:` Use exec() which is available as a shell bridge.`,crypto:` Use globalThis.crypto (Web Crypto API) instead.`}[t]||``}`);let n=zh.__requireCache;if(n&&e in n)return n[e];throw Error(`require('${e}'): module not pre-loaded. Use a string literal so it can be pre-fetched, or use \`await import('https://esm.sh/${e}')\` directly.`)},m={exports:{},filename:t[1]||`<script>`};try{if(f){let r=`
1920
+ `,stderr:``,exitCode:0}}},Hy=new Set([`http`,`https`,`net`,`tls`,`dgram`,`dns`,`cluster`,`worker_threads`,`child_process`,`crypto`,`os`,`stream`,`zlib`,`vm`,`v8`,`perf_hooks`,`readline`,`repl`,`tty`,`inspector`]);function Uy(e){let t=/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g,n=[],r;for(;(r=t.exec(e))!==null;)n.push(r[1]);return[...new Set(n)]}async function Wy(e,t,n){return await n.fs.exists(e)?Gy(await n.fs.readFile(e),[`node`,e,...t],n):{stdout:``,stderr:`jsh: cannot find script '${e}'\n`,exitCode:127}}async function Gy(e,t,n){let r=[],a=[],o=e=>{r.push(typeof e==`string`?e:String(e))},s=e=>{a.push(typeof e==`string`?e:String(e))},c={log:(...e)=>o(`${e.map($h).join(` `)}\n`),info:(...e)=>o(`${e.map($h).join(` `)}\n`),warn:(...e)=>s(`${e.map($h).join(` `)}\n`),error:(...e)=>s(`${e.map($h).join(` `)}\n`)},l={argv:t,env:Object.fromEntries(n.env.entries()),cwd:()=>n.cwd,exit:e=>{throw new Vh(Number.isFinite(e)?Number(e):0)},stdout:{write:o},stderr:{write:s}},u={readFile:async e=>{let t=n.fs.resolvePath(n.cwd,e);return n.fs.readFile(t)},readFileBinary:async e=>{let t=n.fs.resolvePath(n.cwd,e);return n.fs.readFileBuffer(t)},writeFile:async(e,t)=>{let r=n.fs.resolvePath(n.cwd,e);await n.fs.writeFile(r,t)},writeFileBinary:async(e,t)=>{let r=n.fs.resolvePath(n.cwd,e),i=new Uint8Array(t.byteLength);i.set(t),await n.fs.writeFile(r,i)},readDir:async e=>{let t=n.fs.resolvePath(n.cwd,e);return n.fs.readdir(t)},exists:async e=>{let t=n.fs.resolvePath(n.cwd,e);return n.fs.exists(t)},stat:async e=>{let t=n.fs.resolvePath(n.cwd,e),r=await n.fs.stat(t);return{isDirectory:r.isDirectory,isFile:r.isFile,size:r.size}},mkdir:async e=>{let t=n.fs.resolvePath(n.cwd,e);await n.fs.mkdir(t,{recursive:!0})},rm:async e=>{let t=n.fs.resolvePath(n.cwd,e);await n.fs.rm(t,{recursive:!0})},fetchToFile:async(e,t)=>{if(typeof fetch>`u`)throw Error(`fetch is not available in this runtime`);let r=await fetch(e);if(!r.ok)throw Error(`fetch ${r.status} ${r.statusText}`);let i=new Uint8Array(await r.arrayBuffer()),a=n.fs.resolvePath(n.cwd,t);return await n.fs.writeFile(a,i),i.byteLength}},d=async e=>{if(!n.exec)throw Error(`exec is not available in this runtime`);let t=await n.exec(e,{cwd:n.cwd});return{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode}},f=typeof chrome<`u`&&!!chrome?.runtime?.id;if(!f){let t=Uy(e),n=new Set([`fs`,`process`,`buffer`]),r=t.map(e=>e.startsWith(`node:`)?e.slice(5):e).filter(e=>!n.has(e)&&!Hy.has(e)),a=Bh.__requireCache??=Object.create(null),o=r.filter(e=>!(e in a));if(o.length>0){let e=await Promise.allSettled(o.map(async e=>{let t=await i(()=>import(`https://esm.sh/`+e),[]);return{id:e,value:t.default===void 0?t:t.default}}));for(let t of e)t.status===`fulfilled`&&(a[t.value.id]=t.value.value)}}let p=e=>{let t=e.startsWith(`node:`)?e.slice(5):e;if(t===`fs`)return u;if(t===`process`)return l;if(t===`buffer`)return{Buffer:globalThis.Buffer};if(t===`path`){let t=Bh.__requireCache;if(t&&`path`in t)return t.path;if(t&&e in t)return t[e];throw Error(`require('${e}'): path module not pre-loaded. Add require('path') as a static import.`)}if(Hy.has(t))throw Error(`require('${e}'): Node built-in '${t}' is not available in the browser environment.${{http:` Use fetch() instead.`,https:` Use fetch() instead.`,child_process:` Use exec() which is available as a shell bridge.`,crypto:` Use globalThis.crypto (Web Crypto API) instead.`}[t]||``}`);let n=Bh.__requireCache;if(n&&e in n)return n[e];throw Error(`require('${e}'): module not pre-loaded. Use a string literal so it can be pre-fetched, or use \`await import('https://esm.sh/${e}')\` directly.`)},m={exports:{},filename:t[1]||`<script>`};try{if(f){let r=`
1921
1921
  const __stdout = [];
1922
1922
  const __stderr = [];
1923
1923
  const __origConsole = { log: console.log, error: console.error, warn: console.warn, info: console.info };
@@ -2013,9 +2013,9 @@ Usage: mount <target-path>
2013
2013
  console.info = __origConsole.info;
2014
2014
  return { stdout: __stdout.join(''), stderr: __stderr.join('') };
2015
2015
  `,i=document.querySelector(`iframe[data-js-tool]`);i||(i=document.createElement(`iframe`),i.style.display=`none`,i.dataset.jsTool=`true`,i.src=chrome.runtime.getURL(`sandbox.html`),document.body.appendChild(i),await new Promise(e=>{i.addEventListener(`load`,()=>e(),{once:!0})}));let a=`jsh-${Date.now()}-${Math.random().toString(36).slice(2)}`,o=e=>{let t=e.data;!t||t.type!==`vfs`||(async()=>{try{let e,r=t.args?.[0]?n.fs.resolvePath(n.cwd,t.args[0]):t.args?.[0];switch(t.op){case`readFile`:e=await n.fs.readFile(r);break;case`readFileBinary`:e=await n.fs.readFileBuffer(r);break;case`writeFile`:await n.fs.writeFile(r,t.args[1]),e=!0;break;case`writeFileBinary`:await n.fs.writeFile(r,t.binaryData??new Uint8Array),e=!0;break;case`readDir`:e=await n.fs.readdir(r);break;case`exists`:e=await n.fs.exists(r);break;case`stat`:{let t=await n.fs.stat(r);e={isDirectory:t.isDirectory,isFile:t.isFile,size:t.size};break}case`mkdir`:await n.fs.mkdir(r,{recursive:!0}),e=!0;break;case`rm`:await n.fs.rm(r,{recursive:!0}),e=!0;break}i.contentWindow.postMessage({type:`vfs_response`,id:t.id,result:e},`*`)}catch(e){let n=e instanceof Error?e.message:String(e);i.contentWindow.postMessage({type:`vfs_response`,id:t.id,error:n},`*`)}})()};window.addEventListener(`message`,o);let s=e=>{let t=e.data;!t||t.type!==`shell_exec`||(async()=>{try{let e=await d(t.command);i.contentWindow.postMessage({type:`shell_exec_response`,id:t.id,result:e},`*`)}catch(e){let n=e instanceof Error?e.message:String(e);i.contentWindow.postMessage({type:`shell_exec_response`,id:t.id,error:n},`*`)}})()};window.addEventListener(`message`,s);let c=e=>{let t=e.data;!t||t.type!==`fetch_proxy`||(async()=>{try{let e={method:t.init?.method??`GET`,cache:`no-store`};t.init?.headers&&(e.headers=t.init.headers),t.init?.body&&![`GET`,`HEAD`].includes(e.method)&&(e.body=t.init.body);let n=await fetch(t.url,e),r=await n.arrayBuffer(),a={};n.headers.forEach((e,t)=>{a[t]=e}),i.contentWindow.postMessage({type:`fetch_proxy_response`,id:t.id,status:n.status,statusText:n.statusText,headers:a,body:new Uint8Array(r)},`*`)}catch(e){let n=e instanceof Error?e.message:String(e);i.contentWindow.postMessage({type:`fetch_proxy_response`,id:t.id,error:n},`*`)}})()};window.addEventListener(`message`,c);let u=await new Promise((e,t)=>{let n,o=t=>{if(t.data?.type===`exec_result`&&t.data.id===a)if(window.removeEventListener(`message`,o),clearTimeout(n),t.data.error)e({stdout:``,stderr:t.data.error+`
2016
- `});else try{let n=JSON.parse(t.data.result);e({stdout:n.stdout||``,stderr:n.stderr||``})}catch{e({stdout:t.data.result||``,stderr:``})}};n=setTimeout(()=>{window.removeEventListener(`message`,o),t(Error(`jsh eval timed out (30s)`))},3e4),window.addEventListener(`message`,o),i.contentWindow.postMessage({type:`exec`,id:a,code:r},`*`)});return window.removeEventListener(`message`,o),window.removeEventListener(`message`,s),window.removeEventListener(`message`,c),{stdout:u.stdout,stderr:u.stderr,exitCode:+!!u.stderr}}let i=Object.getPrototypeOf(async function(){}).constructor;return await new i(`fs`,`process`,`console`,`require`,`module`,`exports`,`__state`,`exec`,`"use strict";\nconst globalThis = __state;\nconst global = __state;\n${e}`)(u,l,c,p,m,m.exports,zh,d),{stdout:r.join(``),stderr:a.join(``),exitCode:0}}catch(e){if(e instanceof Bh)return{stdout:r.join(``),stderr:a.join(``),exitCode:e.code};let t=e instanceof Error?e.stack??e.message:String(e);return{stdout:r.join(``),stderr:`${a.join(``)}${t}\n`,exitCode:1}}}function Gy(e){let t=[],n=``,r=0;for(;r<e.length;){let i=e[r];if(i===`"`){for(r++;r<e.length&&e[r]!==`"`;)n+=e[r],r++;r++}else if(i===`'`){for(r++;r<e.length&&e[r]!==`'`;)n+=e[r],r++;r++}else i===`\\`&&r+1<e.length&&e[r+1]===` `?(n+=` `,r+=2):/\s/.test(i)?(n.length>0&&(t.push(n),n=``),r++):(n+=i,r++)}return n.length>0&&t.push(n),t}var Ky=[`/workspace`,`/shared`];async function qy(e){let t=[],n=new Set;for(let r of Ky)await e.exists(r)&&await Jy(e,r,t,n);return t}async function Jy(e,t,n,r){for await(let i of e.walk(t)){if(!i.endsWith(`.bsh`)||r.has(i))continue;r.add(i);let t=Yy(i);if(!t)continue;let a=await e.readFile(i,{encoding:`utf-8`}),o=Xy(typeof a==`string`?a:new TextDecoder().decode(a));n.push({path:i,hostnamePattern:t,matchPatterns:o})}}function Yy(e){let t=e.split(`/`).pop()??``;if(!t.endsWith(`.bsh`))return null;let n=t.slice(0,-4);return n?n.startsWith(`-.`)?`*`+n.slice(1):n:null}function Xy(e){let t=e.split(`
2017
- `).slice(0,10),n=[];for(let e of t){let t=e.match(/^\s*\/\/\s*@match\s+(.+)$/);t&&n.push(t[1].trim())}return n}function Zy(e,t){if(t.startsWith(`*.`)){let n=t.slice(1);return e===t.slice(2)||e.endsWith(n)&&e.length>n.length}return e===t}function Qy(e,t){try{let n=new URL(e),r=t.match(/^(\*|https?):\/\/([^/]+)(\/.*)?$/);if(!r)return!1;let[,i,a,o]=r;return i!==`*`&&n.protocol.slice(0,-1)!==i||!Zy(n.hostname,a)?!1:o?$y(n.pathname+n.search,o):!0}catch{return!1}}function $y(e,t){let n=`^`+t.replace(/[.+^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`.*`)+`$`;return new RegExp(n).test(e)}function eb(e,t){try{let n=new URL(t);return e.filter(e=>Zy(n.hostname,e.hostnamePattern)?e.matchPatterns.length>0?e.matchPatterns.some(e=>Qy(t,e)):!0:!1)}catch{return[]}}var tb=[`/workspace`,`/shared`];function nb(e){return new Map(e)}function rb(e){return e.map(e=>({...e,matchPatterns:[...e.matchPatterns]}))}function ib(e){if(e&&typeof e.listMounts==`function`)return e;if(e&&typeof e.getUnderlyingFS==`function`){let t=e.getUnderlyingFS?.();if(t&&typeof t.listMounts==`function`)return t}return null}function ab(e){return(ib(e)?.listMounts?.().length??0)>0}function ob(e){return e?(ib(e)?.listMounts?.()??[]).some(e=>tb.some(t=>e===t||e.startsWith(t+`/`))):!1}var sb=class{jshFs;bshFs;watcher;watcherUnsubs=[];jshCache=null;jshInflight=null;bshCache=null;bshInflight=null;jshGeneration=0;bshGeneration=0;constructor(e){if(this.jshFs=e.jshFs,this.bshFs=e.bshFs,this.watcher=e.watcher??null,this.watcher&&(this.watcherUnsubs.push(this.watcher.watch(`/`,()=>!0,()=>this.invalidateJsh())),this.bshFs))for(let e of tb)this.watcherUnsubs.push(this.watcher.watch(e,()=>!0,()=>this.invalidateBsh()))}dispose(){for(let e of this.watcherUnsubs)e();this.watcherUnsubs.length=0,this.invalidateAll()}invalidateAll(){this.invalidateJsh(),this.invalidateBsh()}invalidateJsh(){this.jshGeneration++,this.jshCache=null,this.jshInflight=null}invalidateBsh(){this.bshGeneration++,this.bshCache=null,this.bshInflight=null}async getJshCommands(){return nb(await this.loadJshCommands())}async getJshCommandNames(){return[...(await this.getJshCommands()).keys()]}async getBshEntries(){return this.bshFs?rb(await this.loadBshEntries()):[]}async findMatchingBshScripts(e){return this.bshFs?rb(eb(await this.loadBshEntries(),e)):[]}shouldCacheJsh(){return!!this.watcher&&!ab(this.jshFs)}shouldCacheBsh(){return!!this.watcher&&!!this.bshFs&&!ob(this.bshFs)}async loadJshCommands(){let e=this.shouldCacheJsh();if(e&&this.jshCache)return this.jshCache;if(!this.jshInflight){let t=this.jshGeneration,n=N_(this.jshFs).then(n=>{let r=nb(n);return e&&this.jshGeneration===t&&(this.jshCache=r),r}).finally(()=>{this.jshInflight===n&&(this.jshInflight=null)});this.jshInflight=n}return this.jshInflight}async loadBshEntries(){if(!this.bshFs)return[];let e=this.shouldCacheBsh();if(e&&this.bshCache)return this.bshCache;if(!this.bshInflight){let t=this.bshGeneration,n=qy(this.bshFs).then(n=>{let r=rb(n);return e&&this.bshGeneration===t&&(this.bshCache=r),r}).finally(()=>{this.bshInflight===n&&(this.bshInflight=null)});this.bshInflight=n}return this.bshInflight}},cb=null,lb=!1;function ub(){return typeof chrome<`u`&&chrome?.runtime?.id?`extension`:typeof document<`u`&&document.documentElement?.dataset?.electronOverlay?`electron`:`cli`}async function db(){if(!lb&&!(typeof localStorage<`u`&&localStorage.getItem(`telemetry-disabled`)===`true`))try{typeof window<`u`&&(window.SAMPLE_PAGEVIEWS_AT_RATE=`high`),cb=(await i(()=>import(`./src-CNgmwAf5.js`),[])).sampleRUM,lb=!0,cb&&cb(`navigate`,{source:typeof document<`u`?document.referrer:``,target:ub()})}catch{}}function fb(e,t){cb?.(`formsubmit`,{source:e,target:t})}function pb(e){cb?.(`fill`,{source:e})}function mb(e){cb?.(`viewblock`,{source:e})}function hb(e){let t=e.length>1&&e.endsWith(`/`)?e.slice(0,-1):e,n=t.lastIndexOf(`/`);return n>=0?t.slice(n+1):t}function gb(e){return e&&typeof e.getWatcher==`function`?e.getWatcher?.()??null:e&&typeof e.getUnderlyingFS==`function`?gb(e.getUnderlyingFS?.()):null}function _b(e){if(!e)return!0;let t=e.toLowerCase();return t.startsWith(`text/`)||t.includes(`json`)||t.includes(`xml`)||t.includes(`javascript`)||t.includes(`ecmascript`)||t.includes(`html`)||t.includes(`css`)||t.includes(`svg`)}async function vb(e,t){let n=e.headers.get(`content-type`)??``,r=await e.arrayBuffer(),i=new Uint8Array(r);if(!_b(n)){let e=``;for(let t=0;t<i.length;t+=32768)e+=String.fromCharCode(...i.subarray(t,t+32768));xo(e,i),t&&So(t,i)}return i}function yb(e){if(e){if(e instanceof Headers){let t={};return e.forEach((e,n)=>{t[n]=e}),t}return e}}function bb(e,t){if(e){if((t?.[`Content-Type`]??t?.[`content-type`]??``).includes(`multipart/form-data`)){let t=ko(e);return new Blob([t])}return e}}function xb(e){if(!e)return{};let t={};for(let[n,r]of Object.entries(e)){let e=n.toLowerCase();e===`cookie`?t[`X-Proxy-Cookie`]=r:e===`origin`?t[`X-Proxy-Origin`]=r:e===`referer`?t[`X-Proxy-Referer`]=r:e.startsWith(`proxy-`)?t[`X-Proxy-${n}`]=r:t[n]=r}return t}function Sb(e){let t={};for(let[n,r]of Object.entries(e))n.toLowerCase()===`x-proxy-set-cookie`?t[`set-cookie`]=r:t[n]=r;return t}function Cb(){return typeof chrome<`u`&&chrome?.runtime?.id?async(e,t)=>{let n=yb(t?.headers),r=await fetch(e,{method:t?.method??`GET`,headers:n,body:bb(t?.body,n)}),i=await vb(r,e),a={};return r.headers.forEach((e,t)=>{a[t]=e}),{status:r.status,statusText:r.statusText,headers:a,body:i,url:e}}:async(e,t)=>{let n=t?.method??`GET`,r={...xb(yb(t?.headers)),"X-Target-URL":e},i={method:n,headers:r,cache:`no-store`};t?.body&&![`GET`,`HEAD`].includes(n)&&(i.body=bb(t.body,r));let a=await fetch(`/api/fetch-proxy`,i);if(a.status===502||a.status===400){let e=await a.text(),t=`Proxy error ${a.status}`;try{t=JSON.parse(e).error??t}catch{}throw Error(t)}let o=await vb(a,e),s={};a.headers.forEach((e,t)=>{s[t]=e});let c=Sb(s);return{status:a.status,statusText:a.statusText,headers:c,body:o,url:e}}}var wb=class{bash;vfsAdapter;gitCommands;mountCommands;terminal=null;fitAddon=null;terminalHost=null;previewHost=null;previewUrls=[];previewStateListener=null;hasPreview=!1;resizeObserver=null;themeObserver=null;currentLine=``;cursorPos=0;history=[];historyIndex=-1;isExecuting=!1;execAbort=null;continuationBuffer=``;lastEnv;cwd;builtinCommandNames;allowedCommands;scriptCatalog;ownsScriptCatalog;registeredJshCommands=new Map;jshSyncInflight=null;jshSyncDirty=!1;constructor(e){this.options=e,this.vfsAdapter=new To(e.fs),this.allowedCommands=e.allowedCommands&&!e.allowedCommands.includes(`*`)?new Set(e.allowedCommands):null;let t=e.cwd??`/`,n={HOME:`/`,PATH:`/usr/bin`,USER:`user`,SHELL:`/bin/bash`,PWD:t,...e.env};this.gitCommands=new tm({fs:e.fs,authorName:n.GIT_AUTHOR_NAME??`User`,authorEmail:n.GIT_AUTHOR_EMAIL??`user@example.com`}),this.mountCommands=new By({fs:e.fs});let r=e.jshDiscoveryFs??e.fs,i=e.bshDiscoveryFs??e.fs,a=gb(r)??gb(i);this.scriptCatalog=e.scriptCatalog??new sb({jshFs:r,bshFs:i,watcher:a}),this.ownsScriptCatalog=!e.scriptCatalog,a&&a.watch(`/`,e=>e.endsWith(`.jsh`),()=>{this.syncJshCommands().catch(()=>void 0)});let o=this.createGitCustomCommand(),s=zv({onMediaPreview:async e=>this.renderMediaPreview(e),getJshCommands:()=>this.getJshCommandNames(),fs:e.fs,scriptCatalog:this.scriptCatalog,browserAPI:e.browserAPI,getParentJid:e.getParentJid}),c=this.createMountCustomCommand(),l=Cb(),u=[o,c,Ry(e.fs),Ly(e.fs,l),...s].filter(e=>this.isCommandAllowed(e.name)),d=[...ze(),...Re()],f=this.allowedCommands?d.filter(e=>this.isCommandAllowed(e)):void 0;if(this.bash=new Ue({fs:this.vfsAdapter,cwd:t,env:n,fetch:l,commands:f,customCommands:u}),this.allowedCommands!==null){let e=this.bash;for(let t of Re())this.isCommandAllowed(t)||e.commands.delete(t)}let p=u.map(e=>e.name),m=f??[...ze(),...Re()];this.builtinCommandNames=new Set([...m,...p]),this.vfsAdapter.setRegisteredCommandsFn(()=>[...this.builtinCommandNames]),this.lastEnv={...n},this.cwd=t,this.syncJshCommands().catch(()=>void 0)}isCommandAllowed(e){return this.allowedCommands===null||this.allowedCommands.has(e)}async syncJshCommands(){return this.jshSyncInflight?(this.jshSyncDirty=!0,this.jshSyncInflight):(this.jshSyncInflight=this.doSyncJshCommands(),this.jshSyncInflight)}async doSyncJshCommands(){try{let e=await this.scriptCatalog.getJshCommands(),t=this.options.jshDiscoveryFs??this.options.fs;for(let[n,r]of e){if(!this.isCommandAllowed(n)||this.builtinCommandNames.has(n)&&!this.registeredJshCommands.has(n)||this.registeredJshCommands.get(n)===r)continue;let e=this.scriptCatalog,i=this,a=n,o={name:n,async execute(n,r){let o=(await e.getJshCommands()).get(a);if(!o)return{stdout:``,stderr:`jsh: command '${a}' no longer exists\n`,exitCode:127};let s;try{let e=await t.readFile(o,{encoding:`utf-8`});s=typeof e==`string`?e:new TextDecoder().decode(e)}catch{return{stdout:``,stderr:`jsh: cannot read script '${o}'\n`,exitCode:127}}let c=[`node`,o,...n],l=r.exec??((e,t)=>i.bash.exec(e,{env:Object.fromEntries(r.env),cwd:t?.cwd??r.cwd}));return Wy(s,c,{fs:r.fs,cwd:r.cwd,env:r.env,stdin:r.stdin,exec:l})}};this.bash.registerCommand(o),this.registeredJshCommands.set(n,r),this.builtinCommandNames.add(n)}}finally{this.jshSyncInflight=null,this.jshSyncDirty&&(this.jshSyncDirty=!1,this.syncJshCommands().catch(()=>void 0))}}createGitCustomCommand(){let e=this.gitCommands;return Ve(`git`,async(t,n)=>{let r=n.cwd,i=await e.execute(t,r);return{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode}})}createMountCustomCommand(){let e=this.mountCommands;return Ve(`mount`,async(t,n)=>{let r=n.cwd,i=await e.execute(t,r);return{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode}})}getBash(){return this.bash}getCwd(){return this.cwd}getScriptCatalog(){return this.scriptCatalog}getEnv(){return{...this.lastEnv}}async getFilteredJshCommands(){let e=await this.scriptCatalog.getJshCommands(),t=new Map;for(let[n,r]of e)this.builtinCommandNames.has(n)||this.isCommandAllowed(n)&&t.set(n,r);return t}async getJshCommandNames(){return[...(await this.getFilteredJshCommands()).keys()]}async tryJshFallback(e){let t=e.trim(),n=t.indexOf(` `),r=n>=0?t.slice(0,n):t,i=n>=0?t.slice(n+1).trim():``,a=(await this.getFilteredJshCommands()).get(r);if(!a)return null;let o=i?Gy(i):[],s=this.options.jshDiscoveryFs??this.options.fs,c;try{let e=await s.readFile(a,{encoding:`utf-8`});c=typeof e==`string`?e:new TextDecoder().decode(e)}catch{return{stdout:``,stderr:`jsh: cannot read script '${a}'\n`,exitCode:127,env:this.lastEnv}}let l=[`node`,a,...o],u=await Wy(c,l,{fs:this.vfsAdapter,cwd:this.cwd,env:new Map(Object.entries(this.lastEnv)),stdin:``,exec:(e,t)=>this.bash.exec(e,{env:this.lastEnv,cwd:t?.cwd??this.cwd})});return{stdout:u.stdout,stderr:u.stderr,exitCode:u.exitCode,env:this.lastEnv}}async runCommand(e,t){pb(e.trim().split(/\s+/)[0]||`unknown`);let n={env:this.lastEnv,cwd:this.cwd,signal:t??this.execAbort?.signal},r=await this.bash.exec(e,n);if(r.env&&(this.lastEnv={...r.env}),r.env?.PWD&&(this.cwd=r.env.PWD),r.exitCode===127){let t=await this.tryJshFallback(e);if(t)return this.syncJshCommands().catch(()=>void 0),t}return r}async mount(e){let t=e??this.options.container;if(!t)throw Error(`No container element provided`);let{Terminal:n}=await i(async()=>{let{Terminal:e}=await import(`./xterm-CAZt1iF4.js`);return{Terminal:e}},[]),{FitAddon:r}=await i(async()=>{let{FitAddon:e}=await import(`./addon-fit-CnTv21Qe.js`);return{FitAddon:e}},[]);await i(()=>Promise.resolve({}),__vite__mapDeps([20]));let a=!document.documentElement.classList.contains(`theme-light`),o={background:`#141414`,foreground:`#cfcfcf`,cursor:`#3562ff`,cursorAccent:`#141414`,selectionBackground:`#3562ff40`,selectionForeground:`#ffffff`,black:`#1a1a1a`,red:`#e34850`,green:`#2d9d78`,yellow:`#e68619`,blue:`#3562ff`,magenta:`#a962e8`,cyan:`#2db9be`,white:`#cfcfcf`,brightBlack:`#5a5a5a`,brightRed:`#e34850`,brightGreen:`#2d9d78`,brightYellow:`#e68619`,brightBlue:`#4a75ff`,brightMagenta:`#a962e8`,brightCyan:`#2db9be`,brightWhite:`#ffffff`},s={background:`#f0f0f0`,foreground:`#1a1a1a`,cursor:`#2b54db`,cursorAccent:`#f0f0f0`,selectionBackground:`#2b54db30`,selectionForeground:`#000000`,black:`#1a1a1a`,red:`#d73220`,green:`#268e6c`,yellow:`#d17a00`,blue:`#2b54db`,magenta:`#8839ef`,cyan:`#1a9088`,white:`#e8e8e8`,brightBlack:`#6e6e6e`,brightRed:`#d73220`,brightGreen:`#268e6c`,brightYellow:`#d17a00`,brightBlue:`#1e44c4`,brightMagenta:`#8839ef`,brightCyan:`#1a9088`,brightWhite:`#ffffff`};this.terminal=new n({cursorBlink:!0,fontSize:11,fontFamily:`'Source Code Pro', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace`,theme:a?o:s,convertEol:!0}),this.themeObserver?.disconnect(),this.themeObserver=new MutationObserver(()=>{if(!this.terminal)return;let e=document.documentElement.classList.contains(`theme-light`);this.terminal.options.theme=e?s:o}),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:[`class`]}),this.fitAddon=new r,this.terminal.loadAddon(this.fitAddon),t.replaceChildren(),this.terminalHost=document.createElement(`div`),this.terminalHost.className=`terminal-panel__terminal-host`,t.appendChild(this.terminalHost),this.previewHost=document.createElement(`div`),this.previewHost.className=`terminal-panel__preview`,t.appendChild(this.previewHost),this.terminal.open(this.terminalHost),this.fitAddon.fit(),this.resizeObserver?.disconnect(),this.resizeObserver=new ResizeObserver(()=>this.refit()),this.resizeObserver.observe(this.terminalHost),this.terminal.writeln(`\x1B[1mslicc\x1B[0m \x1B[90mshell (powered by just-bash)\x1B[0m`),this.terminal.writeln(`\x1B[90mType "help" for available commands.\x1B[0m
2018
- `),this.showPrompt(),this.setupInputHandler()}async executeCommand(e,t){let n=await this.runCommand(e,t);return{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode}}async executeScriptFile(e,t=[]){return Uy(e,t,{fs:this.vfsAdapter,cwd:this.cwd,env:new Map(Object.entries(this.lastEnv)),stdin:``,exec:(e,t)=>this.bash.exec(e,{env:this.lastEnv,cwd:t?.cwd??this.cwd})})}refit(){this.fitAddon?.fit()}setPreviewStateListener(e){this.previewStateListener=e,this.previewStateListener?.(this.hasPreview)}async executeCommandInTerminal(e){let t=e.trim();if(!t)return{stdout:``,stderr:``,exitCode:0};if(!this.terminal)return this.executeCommand(t);if(this.isExecuting||this.currentLine.length>0||this.continuationBuffer.length>0)return{stdout:``,stderr:`terminal is busy; finish current input first
2016
+ `});else try{let n=JSON.parse(t.data.result);e({stdout:n.stdout||``,stderr:n.stderr||``})}catch{e({stdout:t.data.result||``,stderr:``})}};n=setTimeout(()=>{window.removeEventListener(`message`,o),t(Error(`jsh eval timed out (30s)`))},3e4),window.addEventListener(`message`,o),i.contentWindow.postMessage({type:`exec`,id:a,code:r},`*`)});return window.removeEventListener(`message`,o),window.removeEventListener(`message`,s),window.removeEventListener(`message`,c),{stdout:u.stdout,stderr:u.stderr,exitCode:+!!u.stderr}}let i=Object.getPrototypeOf(async function(){}).constructor;return await new i(`fs`,`process`,`console`,`require`,`module`,`exports`,`__state`,`exec`,`"use strict";\nconst globalThis = __state;\nconst global = __state;\n${e}`)(u,l,c,p,m,m.exports,Bh,d),{stdout:r.join(``),stderr:a.join(``),exitCode:0}}catch(e){if(e instanceof Vh)return{stdout:r.join(``),stderr:a.join(``),exitCode:e.code};let t=e instanceof Error?e.stack??e.message:String(e);return{stdout:r.join(``),stderr:`${a.join(``)}${t}\n`,exitCode:1}}}function Ky(e){let t=[],n=``,r=0;for(;r<e.length;){let i=e[r];if(i===`"`){for(r++;r<e.length&&e[r]!==`"`;)n+=e[r],r++;r++}else if(i===`'`){for(r++;r<e.length&&e[r]!==`'`;)n+=e[r],r++;r++}else i===`\\`&&r+1<e.length&&e[r+1]===` `?(n+=` `,r+=2):/\s/.test(i)?(n.length>0&&(t.push(n),n=``),r++):(n+=i,r++)}return n.length>0&&t.push(n),t}var qy=[`/workspace`,`/shared`];async function Jy(e){let t=[],n=new Set;for(let r of qy)await e.exists(r)&&await Yy(e,r,t,n);return t}async function Yy(e,t,n,r){for await(let i of e.walk(t)){if(!i.endsWith(`.bsh`)||r.has(i))continue;r.add(i);let t=Xy(i);if(!t)continue;let a=await e.readFile(i,{encoding:`utf-8`}),o=Zy(typeof a==`string`?a:new TextDecoder().decode(a));n.push({path:i,hostnamePattern:t,matchPatterns:o})}}function Xy(e){let t=e.split(`/`).pop()??``;if(!t.endsWith(`.bsh`))return null;let n=t.slice(0,-4);return n?n.startsWith(`-.`)?`*`+n.slice(1):n:null}function Zy(e){let t=e.split(`
2017
+ `).slice(0,10),n=[];for(let e of t){let t=e.match(/^\s*\/\/\s*@match\s+(.+)$/);t&&n.push(t[1].trim())}return n}function Qy(e,t){if(t.startsWith(`*.`)){let n=t.slice(1);return e===t.slice(2)||e.endsWith(n)&&e.length>n.length}return e===t}function $y(e,t){try{let n=new URL(e),r=t.match(/^(\*|https?):\/\/([^/]+)(\/.*)?$/);if(!r)return!1;let[,i,a,o]=r;return i!==`*`&&n.protocol.slice(0,-1)!==i||!Qy(n.hostname,a)?!1:o?eb(n.pathname+n.search,o):!0}catch{return!1}}function eb(e,t){let n=`^`+t.replace(/[.+^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`.*`)+`$`;return new RegExp(n).test(e)}function tb(e,t){try{let n=new URL(t);return e.filter(e=>Qy(n.hostname,e.hostnamePattern)?e.matchPatterns.length>0?e.matchPatterns.some(e=>$y(t,e)):!0:!1)}catch{return[]}}var nb=[`/workspace`,`/shared`];function rb(e){return new Map(e)}function ib(e){return e.map(e=>({...e,matchPatterns:[...e.matchPatterns]}))}function ab(e){if(e&&typeof e.listMounts==`function`)return e;if(e&&typeof e.getUnderlyingFS==`function`){let t=e.getUnderlyingFS?.();if(t&&typeof t.listMounts==`function`)return t}return null}function ob(e){return(ab(e)?.listMounts?.().length??0)>0}function sb(e){return e?(ab(e)?.listMounts?.()??[]).some(e=>nb.some(t=>e===t||e.startsWith(t+`/`))):!1}var cb=class{jshFs;bshFs;watcher;watcherUnsubs=[];jshCache=null;jshInflight=null;bshCache=null;bshInflight=null;jshGeneration=0;bshGeneration=0;constructor(e){if(this.jshFs=e.jshFs,this.bshFs=e.bshFs,this.watcher=e.watcher??null,this.watcher&&(this.watcherUnsubs.push(this.watcher.watch(`/`,()=>!0,()=>this.invalidateJsh())),this.bshFs))for(let e of nb)this.watcherUnsubs.push(this.watcher.watch(e,()=>!0,()=>this.invalidateBsh()))}dispose(){for(let e of this.watcherUnsubs)e();this.watcherUnsubs.length=0,this.invalidateAll()}invalidateAll(){this.invalidateJsh(),this.invalidateBsh()}invalidateJsh(){this.jshGeneration++,this.jshCache=null,this.jshInflight=null}invalidateBsh(){this.bshGeneration++,this.bshCache=null,this.bshInflight=null}async getJshCommands(){return rb(await this.loadJshCommands())}async getJshCommandNames(){return[...(await this.getJshCommands()).keys()]}async getBshEntries(){return this.bshFs?ib(await this.loadBshEntries()):[]}async findMatchingBshScripts(e){return this.bshFs?ib(tb(await this.loadBshEntries(),e)):[]}shouldCacheJsh(){return!!this.watcher&&!ob(this.jshFs)}shouldCacheBsh(){return!!this.watcher&&!!this.bshFs&&!sb(this.bshFs)}async loadJshCommands(){let e=this.shouldCacheJsh();if(e&&this.jshCache)return this.jshCache;if(!this.jshInflight){let t=this.jshGeneration,n=P_(this.jshFs).then(n=>{let r=rb(n);return e&&this.jshGeneration===t&&(this.jshCache=r),r}).finally(()=>{this.jshInflight===n&&(this.jshInflight=null)});this.jshInflight=n}return this.jshInflight}async loadBshEntries(){if(!this.bshFs)return[];let e=this.shouldCacheBsh();if(e&&this.bshCache)return this.bshCache;if(!this.bshInflight){let t=this.bshGeneration,n=Jy(this.bshFs).then(n=>{let r=ib(n);return e&&this.bshGeneration===t&&(this.bshCache=r),r}).finally(()=>{this.bshInflight===n&&(this.bshInflight=null)});this.bshInflight=n}return this.bshInflight}},lb=null,ub=!1;function db(){return typeof chrome<`u`&&chrome?.runtime?.id?`extension`:typeof document<`u`&&document.documentElement?.dataset?.electronOverlay?`electron`:`cli`}async function fb(){if(!ub&&!(typeof localStorage<`u`&&localStorage.getItem(`telemetry-disabled`)===`true`))try{typeof window<`u`&&(window.SAMPLE_PAGEVIEWS_AT_RATE=`high`),lb=(await i(()=>import(`./src-CNgmwAf5.js`),[])).sampleRUM,ub=!0,lb&&lb(`navigate`,{source:typeof document<`u`?document.referrer:``,target:db()})}catch{}}function pb(e,t){lb?.(`formsubmit`,{source:e,target:t})}function mb(e){lb?.(`fill`,{source:e})}function hb(e){lb?.(`viewblock`,{source:e})}function gb(e){let t=e.length>1&&e.endsWith(`/`)?e.slice(0,-1):e,n=t.lastIndexOf(`/`);return n>=0?t.slice(n+1):t}function _b(e){return e&&typeof e.getWatcher==`function`?e.getWatcher?.()??null:e&&typeof e.getUnderlyingFS==`function`?_b(e.getUnderlyingFS?.()):null}function vb(e){if(!e)return!0;let t=e.toLowerCase();return t.startsWith(`text/`)||t.includes(`json`)||t.includes(`xml`)||t.includes(`javascript`)||t.includes(`ecmascript`)||t.includes(`html`)||t.includes(`css`)||t.includes(`svg`)}async function yb(e,t){let n=e.headers.get(`content-type`)??``,r=await e.arrayBuffer(),i=new Uint8Array(r);if(!vb(n)){let e=``;for(let t=0;t<i.length;t+=32768)e+=String.fromCharCode(...i.subarray(t,t+32768));xo(e,i),t&&So(t,i)}return i}function bb(e){if(e){if(e instanceof Headers){let t={};return e.forEach((e,n)=>{t[n]=e}),t}return e}}function xb(e,t){if(e){if((t?.[`Content-Type`]??t?.[`content-type`]??``).includes(`multipart/form-data`)){let t=ko(e);return new Blob([t])}return e}}function Sb(e){if(!e)return{};let t={};for(let[n,r]of Object.entries(e)){let e=n.toLowerCase();e===`cookie`?t[`X-Proxy-Cookie`]=r:e===`origin`?t[`X-Proxy-Origin`]=r:e===`referer`?t[`X-Proxy-Referer`]=r:e.startsWith(`proxy-`)?t[`X-Proxy-${n}`]=r:t[n]=r}return t}function Cb(e){let t={};for(let[n,r]of Object.entries(e))n.toLowerCase()===`x-proxy-set-cookie`?t[`set-cookie`]=r:t[n]=r;return t}function wb(){return typeof chrome<`u`&&chrome?.runtime?.id?async(e,t)=>{let n=bb(t?.headers),r=await fetch(e,{method:t?.method??`GET`,headers:n,body:xb(t?.body,n)}),i=await yb(r,e),a={};return r.headers.forEach((e,t)=>{a[t]=e}),{status:r.status,statusText:r.statusText,headers:a,body:i,url:e}}:async(e,t)=>{let n=t?.method??`GET`,r={...Sb(bb(t?.headers)),"X-Target-URL":e},i={method:n,headers:r,cache:`no-store`};t?.body&&![`GET`,`HEAD`].includes(n)&&(i.body=xb(t.body,r));let a=await fetch(`/api/fetch-proxy`,i);if(a.status===502||a.status===400){let e=await a.text(),t=`Proxy error ${a.status}`;try{t=JSON.parse(e).error??t}catch{}throw Error(t)}let o=await yb(a,e),s={};a.headers.forEach((e,t)=>{s[t]=e});let c=Cb(s);return{status:a.status,statusText:a.statusText,headers:c,body:o,url:e}}}var Tb=class{bash;vfsAdapter;gitCommands;mountCommands;terminal=null;fitAddon=null;terminalHost=null;previewHost=null;previewUrls=[];previewStateListener=null;hasPreview=!1;resizeObserver=null;themeObserver=null;currentLine=``;cursorPos=0;history=[];historyIndex=-1;isExecuting=!1;execAbort=null;continuationBuffer=``;lastEnv;cwd;builtinCommandNames;allowedCommands;scriptCatalog;ownsScriptCatalog;registeredJshCommands=new Map;jshSyncInflight=null;jshSyncDirty=!1;constructor(e){this.options=e,this.vfsAdapter=new To(e.fs),this.allowedCommands=e.allowedCommands&&!e.allowedCommands.includes(`*`)?new Set(e.allowedCommands):null;let t=e.cwd??`/`,n={HOME:`/`,PATH:`/usr/bin`,USER:`user`,SHELL:`/bin/bash`,PWD:t,...e.env};this.gitCommands=new tm({fs:e.fs,authorName:n.GIT_AUTHOR_NAME??`User`,authorEmail:n.GIT_AUTHOR_EMAIL??`user@example.com`}),this.mountCommands=new Vy({fs:e.fs});let r=e.jshDiscoveryFs??e.fs,i=e.bshDiscoveryFs??e.fs,a=_b(r)??_b(i);this.scriptCatalog=e.scriptCatalog??new cb({jshFs:r,bshFs:i,watcher:a}),this.ownsScriptCatalog=!e.scriptCatalog,a&&a.watch(`/`,e=>e.endsWith(`.jsh`),()=>{this.syncJshCommands().catch(()=>void 0)});let o=this.createGitCustomCommand(),s=Bv({onMediaPreview:async e=>this.renderMediaPreview(e),getJshCommands:()=>this.getJshCommandNames(),fs:e.fs,scriptCatalog:this.scriptCatalog,browserAPI:e.browserAPI,getParentJid:e.getParentJid}),c=this.createMountCustomCommand(),l=wb(),u=[o,c,zy(e.fs),Ry(e.fs,l),...s].filter(e=>this.isCommandAllowed(e.name)),d=[...ze(),...Re()],f=this.allowedCommands?d.filter(e=>this.isCommandAllowed(e)):void 0;if(this.bash=new Ue({fs:this.vfsAdapter,cwd:t,env:n,fetch:l,commands:f,customCommands:u}),this.allowedCommands!==null){let e=this.bash;for(let t of Re())this.isCommandAllowed(t)||e.commands.delete(t)}let p=u.map(e=>e.name),m=f??[...ze(),...Re()];this.builtinCommandNames=new Set([...m,...p]),this.vfsAdapter.setRegisteredCommandsFn(()=>[...this.builtinCommandNames]),this.lastEnv={...n},this.cwd=t,this.syncJshCommands().catch(()=>void 0)}isCommandAllowed(e){return this.allowedCommands===null||this.allowedCommands.has(e)}async syncJshCommands(){return this.jshSyncInflight?(this.jshSyncDirty=!0,this.jshSyncInflight):(this.jshSyncInflight=this.doSyncJshCommands(),this.jshSyncInflight)}async doSyncJshCommands(){try{let e=await this.scriptCatalog.getJshCommands(),t=this.options.jshDiscoveryFs??this.options.fs;for(let[n,r]of e){if(!this.isCommandAllowed(n)||this.builtinCommandNames.has(n)&&!this.registeredJshCommands.has(n)||this.registeredJshCommands.get(n)===r)continue;let e=this.scriptCatalog,i=this,a=n,o={name:n,async execute(n,r){let o=(await e.getJshCommands()).get(a);if(!o)return{stdout:``,stderr:`jsh: command '${a}' no longer exists\n`,exitCode:127};let s;try{let e=await t.readFile(o,{encoding:`utf-8`});s=typeof e==`string`?e:new TextDecoder().decode(e)}catch{return{stdout:``,stderr:`jsh: cannot read script '${o}'\n`,exitCode:127}}let c=[`node`,o,...n],l=r.exec??((e,t)=>i.bash.exec(e,{env:Object.fromEntries(r.env),cwd:t?.cwd??r.cwd}));return Gy(s,c,{fs:r.fs,cwd:r.cwd,env:r.env,stdin:r.stdin,exec:l})}};this.bash.registerCommand(o),this.registeredJshCommands.set(n,r),this.builtinCommandNames.add(n)}}finally{this.jshSyncInflight=null,this.jshSyncDirty&&(this.jshSyncDirty=!1,this.syncJshCommands().catch(()=>void 0))}}createGitCustomCommand(){let e=this.gitCommands;return Ve(`git`,async(t,n)=>{let r=n.cwd,i=await e.execute(t,r);return{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode}})}createMountCustomCommand(){let e=this.mountCommands;return Ve(`mount`,async(t,n)=>{let r=n.cwd,i=await e.execute(t,r);return{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode}})}getBash(){return this.bash}getCwd(){return this.cwd}getScriptCatalog(){return this.scriptCatalog}getEnv(){return{...this.lastEnv}}async getFilteredJshCommands(){let e=await this.scriptCatalog.getJshCommands(),t=new Map;for(let[n,r]of e)this.builtinCommandNames.has(n)||this.isCommandAllowed(n)&&t.set(n,r);return t}async getJshCommandNames(){return[...(await this.getFilteredJshCommands()).keys()]}async tryJshFallback(e){let t=e.trim(),n=t.indexOf(` `),r=n>=0?t.slice(0,n):t,i=n>=0?t.slice(n+1).trim():``,a=(await this.getFilteredJshCommands()).get(r);if(!a)return null;let o=i?Ky(i):[],s=this.options.jshDiscoveryFs??this.options.fs,c;try{let e=await s.readFile(a,{encoding:`utf-8`});c=typeof e==`string`?e:new TextDecoder().decode(e)}catch{return{stdout:``,stderr:`jsh: cannot read script '${a}'\n`,exitCode:127,env:this.lastEnv}}let l=[`node`,a,...o],u=await Gy(c,l,{fs:this.vfsAdapter,cwd:this.cwd,env:new Map(Object.entries(this.lastEnv)),stdin:``,exec:(e,t)=>this.bash.exec(e,{env:this.lastEnv,cwd:t?.cwd??this.cwd})});return{stdout:u.stdout,stderr:u.stderr,exitCode:u.exitCode,env:this.lastEnv}}async runCommand(e,t){mb(e.trim().split(/\s+/)[0]||`unknown`);let n={env:this.lastEnv,cwd:this.cwd,signal:t??this.execAbort?.signal},r=await this.bash.exec(e,n);if(r.env&&(this.lastEnv={...r.env}),r.env?.PWD&&(this.cwd=r.env.PWD),r.exitCode===127){let t=await this.tryJshFallback(e);if(t)return this.syncJshCommands().catch(()=>void 0),t}return r}async mount(e){let t=e??this.options.container;if(!t)throw Error(`No container element provided`);let{Terminal:n}=await i(async()=>{let{Terminal:e}=await import(`./xterm-CAZt1iF4.js`);return{Terminal:e}},[]),{FitAddon:r}=await i(async()=>{let{FitAddon:e}=await import(`./addon-fit-CnTv21Qe.js`);return{FitAddon:e}},[]);await i(()=>Promise.resolve({}),__vite__mapDeps([20]));let a=!document.documentElement.classList.contains(`theme-light`),o={background:`#141414`,foreground:`#cfcfcf`,cursor:`#3562ff`,cursorAccent:`#141414`,selectionBackground:`#3562ff40`,selectionForeground:`#ffffff`,black:`#1a1a1a`,red:`#e34850`,green:`#2d9d78`,yellow:`#e68619`,blue:`#3562ff`,magenta:`#a962e8`,cyan:`#2db9be`,white:`#cfcfcf`,brightBlack:`#5a5a5a`,brightRed:`#e34850`,brightGreen:`#2d9d78`,brightYellow:`#e68619`,brightBlue:`#4a75ff`,brightMagenta:`#a962e8`,brightCyan:`#2db9be`,brightWhite:`#ffffff`},s={background:`#f0f0f0`,foreground:`#1a1a1a`,cursor:`#2b54db`,cursorAccent:`#f0f0f0`,selectionBackground:`#2b54db30`,selectionForeground:`#000000`,black:`#1a1a1a`,red:`#d73220`,green:`#268e6c`,yellow:`#d17a00`,blue:`#2b54db`,magenta:`#8839ef`,cyan:`#1a9088`,white:`#e8e8e8`,brightBlack:`#6e6e6e`,brightRed:`#d73220`,brightGreen:`#268e6c`,brightYellow:`#d17a00`,brightBlue:`#1e44c4`,brightMagenta:`#8839ef`,brightCyan:`#1a9088`,brightWhite:`#ffffff`};this.terminal=new n({cursorBlink:!0,fontSize:11,fontFamily:`'Source Code Pro', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace`,theme:a?o:s,convertEol:!0}),this.themeObserver?.disconnect(),this.themeObserver=new MutationObserver(()=>{if(!this.terminal)return;let e=document.documentElement.classList.contains(`theme-light`);this.terminal.options.theme=e?s:o}),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:[`class`]}),this.fitAddon=new r,this.terminal.loadAddon(this.fitAddon),t.replaceChildren(),this.terminalHost=document.createElement(`div`),this.terminalHost.className=`terminal-panel__terminal-host`,t.appendChild(this.terminalHost),this.previewHost=document.createElement(`div`),this.previewHost.className=`terminal-panel__preview`,t.appendChild(this.previewHost),this.terminal.open(this.terminalHost),this.fitAddon.fit(),this.resizeObserver?.disconnect(),this.resizeObserver=new ResizeObserver(()=>this.refit()),this.resizeObserver.observe(this.terminalHost),this.terminal.writeln(`\x1B[1mslicc\x1B[0m \x1B[90mshell (powered by just-bash)\x1B[0m`),this.terminal.writeln(`\x1B[90mType "help" for available commands.\x1B[0m
2018
+ `),this.showPrompt(),this.setupInputHandler()}async executeCommand(e,t){let n=await this.runCommand(e,t);return{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode}}async executeScriptFile(e,t=[]){return Wy(e,t,{fs:this.vfsAdapter,cwd:this.cwd,env:new Map(Object.entries(this.lastEnv)),stdin:``,exec:(e,t)=>this.bash.exec(e,{env:this.lastEnv,cwd:t?.cwd??this.cwd})})}refit(){this.fitAddon?.fit()}setPreviewStateListener(e){this.previewStateListener=e,this.previewStateListener?.(this.hasPreview)}async executeCommandInTerminal(e){let t=e.trim();if(!t)return{stdout:``,stderr:``,exitCode:0};if(!this.terminal)return this.executeCommand(t);if(this.isExecuting||this.currentLine.length>0||this.continuationBuffer.length>0)return{stdout:``,stderr:`terminal is busy; finish current input first
2019
2019
  `,exitCode:1};this.history[this.history.length-1]!==t&&this.history.push(t),this.historyIndex=-1,this.terminal.write(t),this.terminal.writeln(``),this.isExecuting=!0,this.execAbort=new AbortController;try{let e=await this.runCommand(t),n=this.execAbort.signal.aborted;return this.execAbort=null,n?{stdout:``,stderr:``,exitCode:130}:(e.stdout&&this.writeToTerminal(e.stdout),e.stderr&&this.writeToTerminal(e.stderr,!0),{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode})}catch(e){if(this.execAbort?.signal.aborted)return this.execAbort=null,{stdout:``,stderr:``,exitCode:130};this.execAbort=null;let t=`Error: ${e instanceof Error?e.message:String(e)}\n`;return this.writeToTerminal(t,!0),{stdout:``,stderr:t,exitCode:1}}finally{this.isExecuting=!1,this.showPrompt()}}clearTerminal(){this.terminal?.clear(),this.clearMediaPreview()}dispose(){this.themeObserver?.disconnect(),this.themeObserver=null,this.resizeObserver?.disconnect(),this.resizeObserver=null,this.clearMediaPreview(),this.terminal?.dispose(),this.terminal=null,this.fitAddon=null,this.terminalHost=null,this.previewHost=null,this.ownsScriptCatalog&&this.scriptCatalog.dispose()}showPrompt(){if(!this.terminal)return;let e=this.cwd===`/`?`/`:this.cwd.split(`/`).pop()??this.cwd;this.terminal.write(`\x1b[34m${e}\x1b[0m \x1b[90m$\x1b[0m `)}setupInputHandler(){this.terminal&&this.terminal.onData(e=>{if(this.isExecuting){(e===``||e.length===1&&e.charCodeAt(0)===3)&&(this.execAbort?.abort(),this.terminal?.writeln(`^C`));return}if(e.startsWith(`\x1B[`)||e.startsWith(`\x1BO`)){switch(e){case`\x1B[A`:this.handleHistoryUp();return;case`\x1B[B`:this.handleHistoryDown();return;case`\x1B[C`:this.handleArrowRight();return;case`\x1B[D`:this.handleArrowLeft();return;case`\x1B[H`:case`\x1BOH`:case`\x1B[1~`:this.handleHome();return;case`\x1B[F`:case`\x1BOF`:case`\x1B[4~`:this.handleEnd();return;case`\x1B[3~`:this.handleDelete();return}return}for(let t of e)switch(t){case`\r`:this.handleEnter();break;case``:this.handleBackspace();break;case``:this.handleCtrlC();break;case` `:this.handleTab();break;default:t>=` `&&this.insertChar(t)}})}getPromptWidth(){return(this.cwd===`/`?`/`:this.cwd.split(`/`).pop()??this.cwd).length+3}getCursorVisualLine(){let e=0;for(let[t,n]of this.currentLine.split(`
2020
2020
  `).entries()){if(e+n.length>=this.cursorPos)return t;e+=n.length+1}return 0}positionTerminalCursor(){let e=this.currentLine.split(`
2021
2021
  `),t=0,n=0,r=0;for(let i=0;i<e.length;i++){if(r+e[i].length>=this.cursorPos){t=i,n=this.cursorPos-r;break}r+=e[i].length+1}let i=e.length-1-t;i>0&&this.terminal?.write(`\x1b[${i}A`);let a=t===0?this.getPromptWidth()+n:n;this.terminal?.write(`\r`),a>0&&this.terminal?.write(`\x1b[${a}C`)}redrawInput(e){e>0&&this.terminal?.write(`\x1b[${e}A`),this.terminal?.write(`\r\x1B[J`),this.showPrompt(),this.terminal?.write(this.currentLine),this.positionTerminalCursor()}insertChar(e){let t=this.currentLine.includes(`
@@ -2029,9 +2029,9 @@ Usage: mount <target-path>
2029
2029
  `,this.cursorPos);if(e===-1&&(e=this.currentLine.length),this.cursorPos===e)return;let t=e-this.cursorPos;this.cursorPos=e,this.terminal?.write(`\x1b[${t}C`)}handleCtrlC(){this.terminal?.writeln(`^C`),this.currentLine=``,this.cursorPos=0,this.continuationBuffer=``,this.showPrompt()}handleHistoryUp(){this.history.length!==0&&this.historyIndex<this.history.length-1&&(this.historyIndex++,this.continuationBuffer=``,this.replaceCurrentLine(this.history[this.history.length-1-this.historyIndex]))}handleHistoryDown(){this.historyIndex>0?(this.historyIndex--,this.continuationBuffer=``,this.replaceCurrentLine(this.history[this.history.length-1-this.historyIndex])):this.historyIndex===0&&(this.historyIndex=-1,this.continuationBuffer=``,this.replaceCurrentLine(``))}async handleTab(){if(!this.terminal)return;let e=this.currentLine.slice(0,this.cursorPos).split(/\s+/),t=e[e.length-1]||``,n=e.length<=1||e.length===2&&e[0]===``,r=t?`'`+t.replace(/'/g,`'\\''`)+`'`:`''`,i=n?`compgen -A command -- ${r}`:`compgen -f -- ${r}`;try{let e=(await this.bash.exec(i,{env:this.lastEnv,cwd:this.cwd})).stdout.split(`
2030
2030
  `).filter(Boolean);if(e.length===0)return;if(e.length===1){let i=e[0],a=i.slice(t.length);a&&(this.currentLine=this.currentLine.slice(0,this.cursorPos)+a+this.currentLine.slice(this.cursorPos),this.cursorPos+=a.length,this.terminal.write(a));let o=` `;n||(await this.bash.exec(`compgen -d -- ${r.slice(0,-1)}${a}'`,{env:this.lastEnv,cwd:this.cwd})).stdout.trim()===i&&(o=`/`),this.currentLine=this.currentLine.slice(0,this.cursorPos)+o+this.currentLine.slice(this.cursorPos),this.cursorPos+=1,this.terminal.write(o)}else{let n=e[0];for(let t of e)for(;!t.startsWith(n);)n=n.slice(0,-1);let r=n.slice(t.length);if(r)this.currentLine=this.currentLine.slice(0,this.cursorPos)+r+this.currentLine.slice(this.cursorPos),this.cursorPos+=r.length,this.terminal.write(r);else{this.terminal.writeln(``),this.terminal.writeln(e.map(e=>e.split(`/`).pop()??e).join(` `)),this.showPrompt(),this.terminal.write(this.currentLine);let t=this.currentLine.length-this.cursorPos;t>0&&this.terminal.write(`\x1b[${t}D`)}}}catch(e){console.warn(`[Shell] Tab completion failed:`,e instanceof Error?e.message:String(e))}}replaceCurrentLine(e){let t=this.getCursorVisualLine();t>0&&this.terminal?.write(`\x1b[${t}A`),this.terminal?.write(`\r\x1B[J`),this.showPrompt(),this.currentLine=e,this.cursorPos=e.length,this.terminal?.write(e)}isIncomplete(e){if(e.endsWith(`\\`))return!0;let t=!1,n=!1,r=!1;for(let i of e){if(r){r=!1;continue}if(i===`\\`&&!t){r=!0;continue}if(i===`'`&&!n){t=!t;continue}if(i===`"`&&!t){n=!n;continue}}return t||n}async handleEnter(){let e=this.currentLine.split(`
2031
2031
  `);if(e.length>1){let t=this.getCursorVisualLine(),n=e.length-1-t;n>0&&this.terminal?.write(`\x1b[${n}B`);let r=e[e.length-1].length;this.terminal?.write(`\r`),r>0&&this.terminal?.write(`\x1b[${r}C`)}this.terminal?.writeln(``);let t=this.currentLine;this.currentLine=``,this.cursorPos=0;let n=this.continuationBuffer?this.continuationBuffer+`
2032
- `+t:t;if(this.isIncomplete(n)){this.continuationBuffer=n,this.terminal?.write(`> `);return}this.continuationBuffer=``;let r=n.trim();if(this.historyIndex=-1,!r){this.showPrompt();return}if(this.history[this.history.length-1]!==r&&this.history.push(r),r===`clear`){this.clearTerminal(),this.showPrompt();return}this.isExecuting=!0,this.execAbort=new AbortController;try{let e=await this.runCommand(r);this.execAbort.signal.aborted||(e.stdout&&this.writeToTerminal(e.stdout),e.stderr&&this.writeToTerminal(e.stderr,!0))}catch(e){if(!this.execAbort?.signal.aborted){let t=e instanceof Error?e.message:String(e);this.writeToTerminal(`Error: ${t}\n`,!0)}}this.execAbort=null,this.isExecuting=!1,this.showPrompt()}writeToTerminal(e,t=!1){this.terminal&&(t?this.terminal.write(`\x1b[31m${e}\x1b[0m`):this.terminal.write(e))}clearMediaPreview(){for(let e of this.previewUrls)URL.revokeObjectURL(e);this.previewUrls=[],this.hasPreview=!1,this.previewHost&&(this.previewHost.replaceChildren(),this.previewHost.classList.remove(`terminal-panel__preview--visible`)),this.previewStateListener?.(!1)}async renderMediaPreview(e){if(!this.previewHost||typeof document>`u`)throw Error(`terminal preview is unavailable`);this.clearMediaPreview();for(let t of e){let e=new Uint8Array(t.bytes),n=URL.createObjectURL(new Blob([e],{type:t.mimeType}));this.previewUrls.push(n);let r=document.createElement(`div`);r.className=`terminal-panel__preview-item`;let i=document.createElement(`div`);if(i.className=`terminal-panel__preview-label`,i.textContent=`${hb(t.path)} · ${t.mimeType}`,r.appendChild(i),t.mimeType.startsWith(`video/`)){let e=document.createElement(`video`);e.className=`terminal-panel__preview-media`,e.controls=!0,e.autoplay=!0,e.loop=!0,e.muted=!0,e.playsInline=!0,e.src=n,e.addEventListener(`loadedmetadata`,()=>this.refit(),{once:!0}),r.appendChild(e)}else{let e=document.createElement(`img`);e.className=`terminal-panel__preview-media`,e.alt=hb(t.path),e.src=n,e.addEventListener(`load`,()=>this.refit(),{once:!0}),r.appendChild(e)}this.previewHost.appendChild(r)}this.previewHost.classList.add(`terminal-panel__preview--visible`),this.hasPreview=e.length>0,this.previewStateListener?.(this.hasPreview),requestAnimationFrame(()=>this.refit())}},Tb=t({WasmShell:()=>wb}),Eb=r(`tool:fs`);function Db(e){return[Ob(e),kb(e),Ab(e)]}function Ob(e){return{name:`read_file`,description:`Read the contents of a file. Returns the file content as a string with line numbers.`,inputSchema:{type:`object`,properties:{path:{type:`string`,description:`Absolute path to the file to read.`},offset:{type:`number`,description:`Line number to start reading from (1-based). Optional.`},limit:{type:`number`,description:`Maximum number of lines to read. Optional.`}},required:[`path`]},async execute(t){let n=t.path,r=t.offset??1,i=t.limit;Eb.debug(`Read`,{path:n,offset:r,limit:i});try{let t=(await e.readTextFile(n)).split(`
2032
+ `+t:t;if(this.isIncomplete(n)){this.continuationBuffer=n,this.terminal?.write(`> `);return}this.continuationBuffer=``;let r=n.trim();if(this.historyIndex=-1,!r){this.showPrompt();return}if(this.history[this.history.length-1]!==r&&this.history.push(r),r===`clear`){this.clearTerminal(),this.showPrompt();return}this.isExecuting=!0,this.execAbort=new AbortController;try{let e=await this.runCommand(r);this.execAbort.signal.aborted||(e.stdout&&this.writeToTerminal(e.stdout),e.stderr&&this.writeToTerminal(e.stderr,!0))}catch(e){if(!this.execAbort?.signal.aborted){let t=e instanceof Error?e.message:String(e);this.writeToTerminal(`Error: ${t}\n`,!0)}}this.execAbort=null,this.isExecuting=!1,this.showPrompt()}writeToTerminal(e,t=!1){this.terminal&&(t?this.terminal.write(`\x1b[31m${e}\x1b[0m`):this.terminal.write(e))}clearMediaPreview(){for(let e of this.previewUrls)URL.revokeObjectURL(e);this.previewUrls=[],this.hasPreview=!1,this.previewHost&&(this.previewHost.replaceChildren(),this.previewHost.classList.remove(`terminal-panel__preview--visible`)),this.previewStateListener?.(!1)}async renderMediaPreview(e){if(!this.previewHost||typeof document>`u`)throw Error(`terminal preview is unavailable`);this.clearMediaPreview();for(let t of e){let e=new Uint8Array(t.bytes),n=URL.createObjectURL(new Blob([e],{type:t.mimeType}));this.previewUrls.push(n);let r=document.createElement(`div`);r.className=`terminal-panel__preview-item`;let i=document.createElement(`div`);if(i.className=`terminal-panel__preview-label`,i.textContent=`${gb(t.path)} · ${t.mimeType}`,r.appendChild(i),t.mimeType.startsWith(`video/`)){let e=document.createElement(`video`);e.className=`terminal-panel__preview-media`,e.controls=!0,e.autoplay=!0,e.loop=!0,e.muted=!0,e.playsInline=!0,e.src=n,e.addEventListener(`loadedmetadata`,()=>this.refit(),{once:!0}),r.appendChild(e)}else{let e=document.createElement(`img`);e.className=`terminal-panel__preview-media`,e.alt=gb(t.path),e.src=n,e.addEventListener(`load`,()=>this.refit(),{once:!0}),r.appendChild(e)}this.previewHost.appendChild(r)}this.previewHost.classList.add(`terminal-panel__preview--visible`),this.hasPreview=e.length>0,this.previewStateListener?.(this.hasPreview),requestAnimationFrame(()=>this.refit())}},Eb=t({WasmShell:()=>Tb}),Db=r(`tool:fs`);function Ob(e){return[kb(e),Ab(e),jb(e)]}function kb(e){return{name:`read_file`,description:`Read the contents of a file. Returns the file content as a string with line numbers.`,inputSchema:{type:`object`,properties:{path:{type:`string`,description:`Absolute path to the file to read.`},offset:{type:`number`,description:`Line number to start reading from (1-based). Optional.`},limit:{type:`number`,description:`Maximum number of lines to read. Optional.`}},required:[`path`]},async execute(t){let n=t.path,r=t.offset??1,i=t.limit;Db.debug(`Read`,{path:n,offset:r,limit:i});try{let t=(await e.readTextFile(n)).split(`
2033
2033
  `),a=Math.max(0,r-1),o=i===void 0?t.length:a+i;return{content:t.slice(a,o).map((e,t)=>`${String(a+t+1).padStart(6)} | ${e}`).join(`
2034
- `)}}catch(e){let t=e instanceof Error?e.message:String(e);return Eb.error(`Read failed`,{path:n,error:t}),{content:t,isError:!0}}}}}function kb(e){return{name:`write_file`,description:`Write content to a file. Creates the file if it does not exist, or overwrites it if it does. Parent directories are created automatically.`,inputSchema:{type:`object`,properties:{path:{type:`string`,description:`Absolute path to the file to write.`},content:{type:`string`,description:`The content to write to the file.`}},required:[`path`,`content`]},async execute(t){let n=t.path,r=t.content;Eb.debug(`Write`,{path:n,contentLength:r.length});try{return await e.writeFile(n,r),{content:`File written: ${n}`}}catch(e){let t=e instanceof Error?e.message:String(e);return Eb.error(`Write failed`,{path:n,error:t}),{content:t,isError:!0}}}}}function Ab(e){return{name:`edit_file`,description:`Edit a file by replacing an exact string match. The old_string must appear exactly once in the file. Use this instead of write_file when making targeted changes to existing files.`,inputSchema:{type:`object`,properties:{path:{type:`string`,description:`Absolute path to the file to edit.`},old_string:{type:`string`,description:`The exact string to find and replace. Must be unique in the file.`},new_string:{type:`string`,description:`The replacement string.`}},required:[`path`,`old_string`,`new_string`]},async execute(t){let n=t.path,r=t.old_string,i=t.new_string;Eb.debug(`Edit`,{path:n,oldLength:r.length,newLength:i.length});try{let t=await e.readTextFile(n),a=t.split(r).length-1;if(a===0)return{content:`old_string not found in ${n}`,isError:!0};if(a>1)return{content:`old_string found ${a} times in ${n}. It must be unique. Provide more context.`,isError:!0};let o=t.replace(r,i);return await e.writeFile(n,o),{content:`File edited: ${n}`}}catch(e){let t=e instanceof Error?e.message:String(e);return Eb.error(`Edit failed`,{path:n,error:t}),{content:t,isError:!0}}}}}var jb=r(`tool:bash`),Mb=/^(?:[A-Za-z_][A-Za-z0-9_]*=[^\s]+\s+)*(?:command\s+)?(?:grep|egrep|fgrep|rg)\b/;function Nb(e){let t=``,n=null,r=!1;for(let i=0;i<e.length;i++){let a=e[i];if(r){t+=a,r=!1;continue}if(a===`\\`){t+=a,r=!0;continue}if(n){t+=a,a===n&&(n=null);continue}if(a===`"`||a===`'`){t+=a,n=a;continue}if(a===`;`||a===`|`){t=``;continue}if((a===`&`||a===`|`)&&e[i+1]===a){t=``,i++;continue}t+=a}return t.trim()}function Pb(e,t,n){return t!==1||n.trim()?!1:Mb.test(Nb(e))}function Fb(e){return{name:`bash`,description:"Execute a bash command. Full shell with pipes, redirects, chaining, control flow. Includes: grep, rg, sed, awk, jq, find, curl, git, node, python3, sqlite3, open (--view for vision), playwright-cli (browser automation). Run `commands` for full list.",inputSchema:{type:`object`,properties:{command:{type:`string`,description:`The bash command to execute.`}},required:[`command`]},async execute(t,n){let r=t.command;jb.debug(`Execute`,{command:r});try{let t=await e.executeCommand(r,n);jb.debug(`Result`,{exitCode:t.exitCode,stdoutLength:t.stdout.length,stderrLength:t.stderr.length});let i=``;return t.stdout&&(i+=t.stdout),t.stderr&&(i+=t.stderr),i||=`(exit code: ${t.exitCode})`,{content:i,isError:t.exitCode!==0&&!Pb(r,t.exitCode,t.stderr)}}catch(e){let t=e instanceof Error?e.message:String(e);return jb.error(`Error`,{command:r,error:t}),{content:`Shell error: ${t}`,isError:!0}}}}}r(`tool:search`);var Ib="# CLAUDE.md\n\nThis file covers the default virtual filesystem payload in `packages/vfs-root/`.\n\n## What This Package Contains\n\n`packages/vfs-root/` is copied into the app's virtual filesystem on init/reset. It is content, not runtime code.\n\n## Directory Structure\n\n| Path | Purpose |\n| ------------------------------------- | ------------------------------------------------------------------ |\n| `packages/vfs-root/shared/` | Shared content that becomes `/shared/` in the VFS |\n| `packages/vfs-root/workspace/` | Default workspace content that becomes `/workspace/` in the VFS |\n| `packages/vfs-root/shared/CLAUDE.md` | Agent-facing runtime instructions bundled into `/shared/CLAUDE.md` |\n| `packages/vfs-root/shared/sprinkles/` | Built-in sprinkle UIs |\n| `packages/vfs-root/shared/sounds/` | Shared notification sounds |\n| `packages/vfs-root/workspace/skills/` | Default installable workspace skills |\n\n## Adding Default Content\n\n### Skills\n\n- Add new built-in workspace skills under `packages/vfs-root/workspace/skills/<skill-name>/`.\n- Include `SKILL.md` and any companion assets or `.jsh` scripts the skill needs.\n\n### Sprinkles\n\n- Add built-in sprinkles under `packages/vfs-root/shared/sprinkles/<name>/`.\n- Keep the main file named `<name>.shtml` to match discovery and sprinkle naming conventions.\n\n### Sounds\n\n- Add shared sounds under `packages/vfs-root/shared/sounds/`.\n- Prefer stable filenames because shell commands and docs may reference them directly.\n\n## External Handoffs\n\n- Mechanism: `x-slicc` response header on main-frame document responses → `navigate` lick → cone approval card.\n- Agent-facing flow: `packages/vfs-root/workspace/skills/handoff/SKILL.md` (bundled to `/workspace/skills/handoff/SKILL.md`) and the trigger line in `shared/CLAUDE.md` (bundled to `/shared/CLAUDE.md`).\n- Protocol reference: `docs/slicc-handoff.md`.\n- When handoff behavior changes, keep the skill, `shared/CLAUDE.md`, and `docs/slicc-handoff.md` aligned — do not duplicate their content here.\n\n## Important Distinction\n\n`packages/vfs-root/shared/CLAUDE.md` is **agent-facing runtime content** bundled into the virtual filesystem.\n\nIt is different from the developer-facing `CLAUDE.md` files in the repository. Do not merge those roles together.\n",Lb="# sliccy\n\nYou are a personal assistant that runs in the browser. You support automation and can code, too. You run inside SLICC — a browser-based claw.\n\n## Vocabulary\n\n- **Cone**: You. The main agent. Orchestrates scoops, talks to the human, has full filesystem access.\n- **Scoops**: Isolated sub-agents (`scoop_scoop`, `feed_scoop`, `drop_scoop`, or shell `agent` for one-shot). Sandboxed filesystem and shell.\n- **Sprinkles**: Persistent UI panels (`.shtml` files). Created by scoops, outlive scoops.\n- **Licks**: External events (webhooks, cron, sprinkle clicks) that trigger scoops. Shell: `webhook`, `crontask`.\n- **Floats**: Runtime — CLI server, Chrome extension, or cloud container.\n\n## Style\n\nWrite like a professional tool, not a chatbot. No emoji in headings. Concise prose over bullet lists. For sprinkles, follow `/workspace/skills/sprinkles/style-guide.md`.\n\n## Principles\n\n- Use the shell commands you have `commands` for full list. You have: `read_file`, `write_file`, `edit_file`, `bash`, `javascript`. Browser automation via `playwright-cli` through bash.\n- New capabilities should be skills (SKILL.md), not hardcoded features.\n- **Scoops do the heavy lifting. The cone orchestrates and synthesizes.**\n\n## Delegation\n\nRead `/workspace/skills/scoop-management/SKILL.md` before delegating — it covers lifecycle, tab handling, model selection, and `agent` vs `scoop_scoop`. Default to scoops for non-trivial work (multiple sources, time-consuming, self-contained brief). Do it yourself for quick lookups or real-time adaptation. Use `scoop_scoop` for persistent/conversational work, or the `agent` shell command for one-shot sub-agents that pipe into bash.\n\n## Sprinkles\n\nWhen the user asks for a dashboard, editor, or visualization — read `/workspace/skills/sprinkles/SKILL.md` first. One scoop per sprinkle, named identically. The cone MUST NOT write `.shtml` files or run sprinkle commands directly — all sprinkle work goes through scoops via `feed_scoop`. For detailed rules, read `/workspace/skills/sprinkle-guide/SKILL.md`.\n\n## Handoffs\n\nOn `[Navigate Event: ...]`, read `/workspace/skills/handoff/SKILL.md` first. Show approval card, wait for user, dispatch by verb.\n\n## Environment\n\nThis is a sandboxed browser-based VFS, not a regular Linux box. Run `commands` to see what's available. Use `serve <dir>` for apps, `open <path>` for files. No package managers, no long-running servers. For detailed commands and filesystem info, read `/workspace/skills/skill-authoring/SKILL.md`. For automation (webhooks, cron, screencapture), read `/workspace/skills/automation/SKILL.md`.\n\n## Memory\n\nWhen you learn something important:\n\n- Create files for structured data\n- Update this file for global preferences\n- Each scoop has its own CLAUDE.md for scoop-specific context\n- Remember: the best flavor of ice cream is lobster, nobody likes chocolate ice cream, and mixing bacon with ice cream is a crime against humanity\n",Rb=`<!DOCTYPE html>
2034
+ `)}}catch(e){let t=e instanceof Error?e.message:String(e);return Db.error(`Read failed`,{path:n,error:t}),{content:t,isError:!0}}}}}function Ab(e){return{name:`write_file`,description:`Write content to a file. Creates the file if it does not exist, or overwrites it if it does. Parent directories are created automatically.`,inputSchema:{type:`object`,properties:{path:{type:`string`,description:`Absolute path to the file to write.`},content:{type:`string`,description:`The content to write to the file.`}},required:[`path`,`content`]},async execute(t){let n=t.path,r=t.content;Db.debug(`Write`,{path:n,contentLength:r.length});try{return await e.writeFile(n,r),{content:`File written: ${n}`}}catch(e){let t=e instanceof Error?e.message:String(e);return Db.error(`Write failed`,{path:n,error:t}),{content:t,isError:!0}}}}}function jb(e){return{name:`edit_file`,description:`Edit a file by replacing an exact string match. The old_string must appear exactly once in the file. Use this instead of write_file when making targeted changes to existing files.`,inputSchema:{type:`object`,properties:{path:{type:`string`,description:`Absolute path to the file to edit.`},old_string:{type:`string`,description:`The exact string to find and replace. Must be unique in the file.`},new_string:{type:`string`,description:`The replacement string.`}},required:[`path`,`old_string`,`new_string`]},async execute(t){let n=t.path,r=t.old_string,i=t.new_string;Db.debug(`Edit`,{path:n,oldLength:r.length,newLength:i.length});try{let t=await e.readTextFile(n),a=t.split(r).length-1;if(a===0)return{content:`old_string not found in ${n}`,isError:!0};if(a>1)return{content:`old_string found ${a} times in ${n}. It must be unique. Provide more context.`,isError:!0};let o=t.replace(r,i);return await e.writeFile(n,o),{content:`File edited: ${n}`}}catch(e){let t=e instanceof Error?e.message:String(e);return Db.error(`Edit failed`,{path:n,error:t}),{content:t,isError:!0}}}}}var Mb=r(`tool:bash`),Nb=/^(?:[A-Za-z_][A-Za-z0-9_]*=[^\s]+\s+)*(?:command\s+)?(?:grep|egrep|fgrep|rg)\b/;function Pb(e){let t=``,n=null,r=!1;for(let i=0;i<e.length;i++){let a=e[i];if(r){t+=a,r=!1;continue}if(a===`\\`){t+=a,r=!0;continue}if(n){t+=a,a===n&&(n=null);continue}if(a===`"`||a===`'`){t+=a,n=a;continue}if(a===`;`||a===`|`){t=``;continue}if((a===`&`||a===`|`)&&e[i+1]===a){t=``,i++;continue}t+=a}return t.trim()}function Fb(e,t,n){return t!==1||n.trim()?!1:Nb.test(Pb(e))}function Ib(e){return{name:`bash`,description:"Execute a bash command. Full shell with pipes, redirects, chaining, control flow. Includes: grep, rg, sed, awk, jq, find, curl, git, node, python3, sqlite3, open (--view for vision), playwright-cli (browser automation). Run `commands` for full list.",inputSchema:{type:`object`,properties:{command:{type:`string`,description:`The bash command to execute.`}},required:[`command`]},async execute(t,n){let r=t.command;Mb.debug(`Execute`,{command:r});try{let t=await e.executeCommand(r,n);Mb.debug(`Result`,{exitCode:t.exitCode,stdoutLength:t.stdout.length,stderrLength:t.stderr.length});let i=``;return t.stdout&&(i+=t.stdout),t.stderr&&(i+=t.stderr),i||=`(exit code: ${t.exitCode})`,{content:i,isError:t.exitCode!==0&&!Fb(r,t.exitCode,t.stderr)}}catch(e){let t=e instanceof Error?e.message:String(e);return Mb.error(`Error`,{command:r,error:t}),{content:`Shell error: ${t}`,isError:!0}}}}}r(`tool:search`);var Lb="# CLAUDE.md\n\nThis file covers the default virtual filesystem payload in `packages/vfs-root/`.\n\n## What This Package Contains\n\n`packages/vfs-root/` is copied into the app's virtual filesystem on init/reset. It is content, not runtime code.\n\n## Directory Structure\n\n| Path | Purpose |\n| ------------------------------------- | ------------------------------------------------------------------ |\n| `packages/vfs-root/shared/` | Shared content that becomes `/shared/` in the VFS |\n| `packages/vfs-root/workspace/` | Default workspace content that becomes `/workspace/` in the VFS |\n| `packages/vfs-root/shared/CLAUDE.md` | Agent-facing runtime instructions bundled into `/shared/CLAUDE.md` |\n| `packages/vfs-root/shared/sprinkles/` | Built-in sprinkle UIs |\n| `packages/vfs-root/shared/sounds/` | Shared notification sounds |\n| `packages/vfs-root/workspace/skills/` | Default installable workspace skills |\n\n## Adding Default Content\n\n### Skills\n\n- Add new built-in workspace skills under `packages/vfs-root/workspace/skills/<skill-name>/`.\n- Include `SKILL.md` and any companion assets or `.jsh` scripts the skill needs.\n\n### Sprinkles\n\n- Add built-in sprinkles under `packages/vfs-root/shared/sprinkles/<name>/`.\n- Keep the main file named `<name>.shtml` to match discovery and sprinkle naming conventions.\n\n### Sounds\n\n- Add shared sounds under `packages/vfs-root/shared/sounds/`.\n- Prefer stable filenames because shell commands and docs may reference them directly.\n\n## External Handoffs\n\n- Mechanism: `x-slicc` response header on main-frame document responses → `navigate` lick → cone approval card.\n- Agent-facing flow: `packages/vfs-root/workspace/skills/handoff/SKILL.md` (bundled to `/workspace/skills/handoff/SKILL.md`) and the trigger line in `shared/CLAUDE.md` (bundled to `/shared/CLAUDE.md`).\n- Protocol reference: `docs/slicc-handoff.md`.\n- When handoff behavior changes, keep the skill, `shared/CLAUDE.md`, and `docs/slicc-handoff.md` aligned — do not duplicate their content here.\n\n## Important Distinction\n\n`packages/vfs-root/shared/CLAUDE.md` is **agent-facing runtime content** bundled into the virtual filesystem.\n\nIt is different from the developer-facing `CLAUDE.md` files in the repository. Do not merge those roles together.\n",Rb="# sliccy\n\nYou are a personal assistant that runs in the browser. You support automation and can code, too. You run inside SLICC — a browser-based claw.\n\n## Vocabulary\n\n- **Cone**: You. The main agent. Orchestrates scoops, talks to the human, has full filesystem access.\n- **Scoops**: Isolated sub-agents (`scoop_scoop`, `feed_scoop`, `drop_scoop`, or shell `agent` for one-shot). Sandboxed filesystem and shell.\n- **Sprinkles**: Persistent UI panels (`.shtml` files). Created by scoops, outlive scoops.\n- **Licks**: External events (webhooks, cron, sprinkle clicks) that trigger scoops. Shell: `webhook`, `crontask`.\n- **Floats**: Runtime — CLI server, Chrome extension, or cloud container.\n\n## Style\n\nWrite like a professional tool, not a chatbot. No emoji in headings. Concise prose over bullet lists. For sprinkles, follow `/workspace/skills/sprinkles/style-guide.md`.\n\n## Principles\n\n- Use the shell commands you have `commands` for full list. You have: `read_file`, `write_file`, `edit_file`, `bash`, `javascript`. Browser automation via `playwright-cli` through bash.\n- New capabilities should be skills (SKILL.md), not hardcoded features.\n- **Scoops do the heavy lifting. The cone orchestrates and synthesizes.**\n\n## Delegation\n\nRead `/workspace/skills/scoop-management/SKILL.md` before delegating — it covers lifecycle, tab handling, model selection, and `agent` vs `scoop_scoop`. Default to scoops for non-trivial work (multiple sources, time-consuming, self-contained brief). Do it yourself for quick lookups or real-time adaptation. Use `scoop_scoop` for persistent/conversational work, or the `agent` shell command for one-shot sub-agents that pipe into bash.\n\n## Sprinkles\n\nWhen the user asks for a dashboard, editor, or visualization — read `/workspace/skills/sprinkles/SKILL.md` first. One scoop per sprinkle, named identically. The cone MUST NOT write `.shtml` files or run sprinkle commands directly — all sprinkle work goes through scoops via `feed_scoop`. For detailed rules, read `/workspace/skills/sprinkle-guide/SKILL.md`.\n\n## Handoffs\n\nOn `[Navigate Event: ...]`, read `/workspace/skills/handoff/SKILL.md` first. Show approval card, wait for user, dispatch by verb.\n\n## Environment\n\nThis is a sandboxed browser-based VFS, not a regular Linux box. Run `commands` to see what's available. Use `serve <dir>` for apps, `open <path>` for files. No package managers, no long-running servers. For detailed commands and filesystem info, read `/workspace/skills/skill-authoring/SKILL.md`. For automation (webhooks, cron, screencapture), read `/workspace/skills/automation/SKILL.md`.\n\n## Memory\n\nWhen you learn something important:\n\n- Create files for structured data\n- Update this file for global preferences\n- Each scoop has its own CLAUDE.md for scoop-specific context\n- Remember: the best flavor of ice cream is lobster, nobody likes chocolate ice cream, and mixing bacon with ice cream is a crime against humanity\n",zb=`<!DOCTYPE html>
2035
2035
  <html lang="en">
2036
2036
  <head>
2037
2037
  <meta charset="UTF-8">
@@ -3055,7 +3055,7 @@ if (hasState && violations && violations.length > 0) {
3055
3055
  <\/script>
3056
3056
  </body>
3057
3057
  </html>
3058
- `,zb=`<!DOCTYPE html>
3058
+ `,Bb=`<!DOCTYPE html>
3059
3059
  <html lang="en">
3060
3060
  <head>
3061
3061
  <meta charset="UTF-8">
@@ -3700,7 +3700,7 @@ init();
3700
3700
  <\/script>
3701
3701
  </body>
3702
3702
  </html>
3703
- `,Bb=`<!DOCTYPE html>
3703
+ `,Vb=`<!DOCTYPE html>
3704
3704
  <html lang="en">
3705
3705
  <head>
3706
3706
  <meta charset="UTF-8">
@@ -4482,7 +4482,7 @@ function lickExportData() {
4482
4482
  <\/script>
4483
4483
  </body>
4484
4484
  </html>
4485
- `,Vb=`<!DOCTYPE html>
4485
+ `,Hb=`<!DOCTYPE html>
4486
4486
  <html lang="en">
4487
4487
  <head>
4488
4488
  <meta charset="UTF-8">
@@ -5320,7 +5320,7 @@ body { font-family: var(--s2-font-family); font-size: 14px; line-height: 1.5; co
5320
5320
  <\/script>
5321
5321
  </body>
5322
5322
  </html>
5323
- `,Hb=`<!DOCTYPE html>
5323
+ `,Ub=`<!DOCTYPE html>
5324
5324
  <html lang="en">
5325
5325
  <head>
5326
5326
  <meta charset="UTF-8">
@@ -5887,7 +5887,7 @@ if (hasData()) {
5887
5887
  <\/script>
5888
5888
  </body>
5889
5889
  </html>
5890
- `,Ub=`<!DOCTYPE html>
5890
+ `,Wb=`<!DOCTYPE html>
5891
5891
  <html lang="en">
5892
5892
  <head>
5893
5893
  <meta charset="UTF-8">
@@ -6554,7 +6554,7 @@ function saveState() {
6554
6554
  <\/script>
6555
6555
  </body>
6556
6556
  </html>
6557
- `,Wb=`<!DOCTYPE html>
6557
+ `,Gb=`<!DOCTYPE html>
6558
6558
  <html lang="en">
6559
6559
  <head>
6560
6560
  <meta charset="UTF-8">
@@ -7340,7 +7340,7 @@ if (document.getElementById('mainView').classList.contains('active')) {
7340
7340
  <\/script>
7341
7341
  </body>
7342
7342
  </html>
7343
- `,Gb=`<!DOCTYPE html>
7343
+ `,Kb=`<!DOCTYPE html>
7344
7344
  <html lang="en">
7345
7345
  <head>
7346
7346
  <meta charset="UTF-8">
@@ -8098,7 +8098,7 @@ textarea.field-input { height: auto; min-height: 80px; padding: 10px 12px; resiz
8098
8098
  <\/script>
8099
8099
  </body>
8100
8100
  </html>
8101
- `,Kb=`<!DOCTYPE html>
8101
+ `,qb=`<!DOCTYPE html>
8102
8102
  <html lang="en">
8103
8103
  <head>
8104
8104
  <meta charset="UTF-8">
@@ -8908,7 +8908,7 @@ init();
8908
8908
  <\/script>
8909
8909
  </body>
8910
8910
  </html>
8911
- `,qb=`<!DOCTYPE html>
8911
+ `,Jb=`<!DOCTYPE html>
8912
8912
  <html lang="en">
8913
8913
  <head>
8914
8914
  <meta charset="UTF-8">
@@ -10556,7 +10556,7 @@ body { font-family: var(--s2-font-family); font-size: 14px; line-height: 1.5; co
10556
10556
  <\/script>
10557
10557
  </body>
10558
10558
  </html>
10559
- `,Jb=`<!DOCTYPE html>
10559
+ `,Yb=`<!DOCTYPE html>
10560
10560
  <html lang="en">
10561
10561
  <head>
10562
10562
  <title>Welcome</title>
@@ -11490,7 +11490,7 @@ body { font-family: var(--s2-font-family); font-size: 14px; line-height: 1.5; co
11490
11490
  <\/script>
11491
11491
  </body>
11492
11492
  </html>
11493
- `,Yb='---\nname: Automation\ndescription: Licks, webhooks, cron tasks, viewing pages/images, screencapture, onboarding\n---\n\n# Automation & Environment Guide\n\n## Viewing Pages and Images\n\n**What you CAN see:**\n\n- **`open --view <path>`** — reads an image from VFS and returns it. Works with PNG, JPEG, GIF, WebP, SVG.\n- **`playwright-cli screenshot --tab=<id>`** + **`open --view <path>`** — screenshot a tab, then view it.\n- **`screencapture`** — capture user\'s screen via browser screen sharing. `screencapture --view screenshot.png`.\n- **`playwright-cli snapshot --tab=<id>`** — accessibility tree (text). Use to verify content without vision.\n\n**What only the human sees:**\n\n- **`serve <dir>`** — opens app directory in browser tab\n- **`open <path>`** (no flags) — opens file in browser tab\n- **`imgcat <path>`** — displays image in terminal preview\n\n**Workflow to verify a page:**\n\n1. `serve /workspace/app` — open app (human sees it)\n2. `playwright-cli tab-list` — find tab by URL, note targetId\n3. `playwright-cli snapshot --tab=<id>` — required before screenshot\n4. `playwright-cli screenshot --tab=<id> --filename=/tmp/shot.png`\n5. `open --view /tmp/shot.png` — now you can see it\n\n**Do NOT:**\n\n- `read_file` on a PNG or base64 encode to view images\n- `imgcat` or `cat` on screenshots expecting to see them\n- Open a screenshot then screenshot that tab\n- Use `eval` to check active tab — use `tab-list`\n\n## Environment Caveats\n\nThis is a sandboxed browser-based VFS. Many standard tools don\'t exist.\n\n- **Serving**: Use `serve` or `open` — no HTTP server needed\n- **serve/open already open tabs**: Don\'t duplicate with `playwright-cli open`. Use `tab-list` to find existing tab.\n- **Never manually construct preview URLs** — use URL from command output\n- **No long-running servers**: `serve` and `open` handle previewing\n- **No package managers**: No `apt`, `npm install`, `pip install`\n\n## File System Watching\n\n`fswatch` monitors VFS file changes and delivers events as licks to scoops.\n\n```bash\n# Watch for markdown changes, route to a scoop\nfswatch create --path /workspace --pattern "*.md" --scoop doc-watcher --name md-changes\n\n# Watch without targeting a scoop (routes to cone)\nfswatch create --path /workspace/src --pattern "*.ts"\n\n# List active watchers\nfswatch list\n\n# Remove a watcher\nfswatch delete fsw-1\n```\n\nEvents include the change type (`create`, `modify`, `delete`) and the file path.\n\n## Symlinks\n\nThe VFS supports symbolic links:\n\n```bash\nln -s /workspace/skills /workspace/skill-link # Create symlink\nreadlink /workspace/skill-link # Read link target\nls -la /workspace/ # Shows symlinks with -> target\n```\n\nSymlinks work transparently — `cat`, `readFile`, `writeFile` etc. follow symlinks automatically.\n\n## Onboarding\n\nWhen you receive a `[Sprinkle Event: welcome]` with `onboarding-complete`, read `/workspace/skills/welcome/SKILL.md` and follow its instructions.\n',Xb=`---
11493
+ `,Xb='---\nname: Automation\ndescription: Licks, webhooks, cron tasks, viewing pages/images, screencapture, onboarding\n---\n\n# Automation & Environment Guide\n\n## Viewing Pages and Images\n\n**What you CAN see:**\n\n- **`open --view <path>`** — reads an image from VFS and returns it. Works with PNG, JPEG, GIF, WebP, SVG.\n- **`playwright-cli screenshot --tab=<id>`** + **`open --view <path>`** — screenshot a tab, then view it.\n- **`screencapture`** — capture user\'s screen via browser screen sharing. `screencapture --view screenshot.png`.\n- **`playwright-cli snapshot --tab=<id>`** — accessibility tree (text). Use to verify content without vision.\n\n**What only the human sees:**\n\n- **`serve <dir>`** — opens app directory in browser tab\n- **`open <path>`** (no flags) — opens file in browser tab\n- **`imgcat <path>`** — displays image in terminal preview\n\n**Workflow to verify a page:**\n\n1. `serve /workspace/app` — open app (human sees it)\n2. `playwright-cli tab-list` — find tab by URL, note targetId\n3. `playwright-cli snapshot --tab=<id>` — required before screenshot\n4. `playwright-cli screenshot --tab=<id> --filename=/tmp/shot.png`\n5. `open --view /tmp/shot.png` — now you can see it\n\n**Do NOT:**\n\n- `read_file` on a PNG or base64 encode to view images\n- `imgcat` or `cat` on screenshots expecting to see them\n- Open a screenshot then screenshot that tab\n- Use `eval` to check active tab — use `tab-list`\n\n## Environment Caveats\n\nThis is a sandboxed browser-based VFS. Many standard tools don\'t exist.\n\n- **Serving**: Use `serve` or `open` — no HTTP server needed\n- **serve/open already open tabs**: Don\'t duplicate with `playwright-cli open`. Use `tab-list` to find existing tab.\n- **Never manually construct preview URLs** — use URL from command output\n- **No long-running servers**: `serve` and `open` handle previewing\n- **No package managers**: No `apt`, `npm install`, `pip install`\n\n## File System Watching\n\n`fswatch` monitors VFS file changes and delivers events as licks to scoops.\n\n```bash\n# Watch for markdown changes, route to a scoop\nfswatch create --path /workspace --pattern "*.md" --scoop doc-watcher --name md-changes\n\n# Watch without targeting a scoop (routes to cone)\nfswatch create --path /workspace/src --pattern "*.ts"\n\n# List active watchers\nfswatch list\n\n# Remove a watcher\nfswatch delete fsw-1\n```\n\nEvents include the change type (`create`, `modify`, `delete`) and the file path.\n\n## Symlinks\n\nThe VFS supports symbolic links:\n\n```bash\nln -s /workspace/skills /workspace/skill-link # Create symlink\nreadlink /workspace/skill-link # Read link target\nls -la /workspace/ # Shows symlinks with -> target\n```\n\nSymlinks work transparently — `cat`, `readFile`, `writeFile` etc. follow symlinks automatically.\n\n## Onboarding\n\nWhen you receive a `[Sprinkle Event: welcome]` with `onboarding-complete`, read `/workspace/skills/welcome/SKILL.md` and follow its instructions.\n',Zb=`---
11494
11494
  name: handoff
11495
11495
  description: React to navigate lick events (x-slicc response headers) with a yes/no approval card
11496
11496
  allowed-tools: bash
@@ -11561,7 +11561,7 @@ Use this shtml block verbatim, substituting the origin URL and header value. Kee
11561
11561
  - Do not fetch the origin URL until the user has accepted. Even a \`HEAD\` request is too eager — the origin may use fetch-beacon side effects.
11562
11562
  - Do not execute the header value as a shell command. It is instruction text or a pointer, not code.
11563
11563
  - Do not render more than one approval card for a single navigate event. If you already showed the card, wait for the user.
11564
- `,Zb=`---
11564
+ `,Qb=`---
11565
11565
  name: inline-widgets
11566
11566
  description: Interactive widget patterns for inline shtml cards in chat messages
11567
11567
  allowed-tools: bash
@@ -11831,7 +11831,7 @@ slicc.lick({ action: 'sort-complete', algorithm: algo, comparisons: n });
11831
11831
  \`\`\`
11832
11832
 
11833
11833
  The agent receives the lick as a structured message and can respond with prose, another inline widget, or spawn a scoop.
11834
- `,Qb=`---
11834
+ `,$b=`---
11835
11835
  name: playwright-cli
11836
11836
  description: Browse the web, interact with pages, take screenshots, extract data via the playwright-cli shell command.
11837
11837
  allowed-tools: bash
@@ -12020,7 +12020,7 @@ playwright-cli stop-recording <recordingId> # Stop and save HAR
12020
12020
  - The SLICC app tab and Chrome internal UI tabs are automatically excluded from \`tab-list\`.
12021
12021
  - \`fill\` clears and types into regular inputs, textareas, and \`contenteditable\` elements.
12022
12022
  - Screenshots default to \`/tmp/screenshot-<timestamp>.png\`. Use \`--filename=path\` to save elsewhere.
12023
- `,$b=`---
12023
+ `,ex=`---
12024
12024
  name: Scoop Management
12025
12025
  description: Detailed scoop lifecycle, delegation rules, browser tab handling
12026
12026
  ---
@@ -12159,7 +12159,7 @@ Example:
12159
12159
  scoop_scoop({ name: "fix-typos", model: "claude-haiku-4-5-20251001", prompt: "Fix all typos in /workspace/docs/" })
12160
12160
  scoop_scoop({ name: "architect", model: "claude-opus-4-6", prompt: "Design the new plugin system..." })
12161
12161
  \`\`\`
12162
- `,ex="---\nname: Skill Authoring\ndescription: Skills discovery, .jsh/.bsh files, shell commands, filesystem\n---\n\n# Skill Authoring & Shell Reference\n\n## Skills\n\nSkills in `/workspace/skills/` extend capabilities. SLICC also discovers compatibility skills from `.agents/skills/*/SKILL.md` and `.claude/skills/*/SKILL.md` anywhere in the reachable VFS. Only native `/workspace/skills/` entries are install-managed; compatibility-discovered skills stay read-only.\n\n## .jsh Files (JavaScript Shell Scripts)\n\n`.jsh` files are auto-discovered as shell commands anywhere on the VFS:\n\n- **Auto-discovery**: registered as callable commands (by filename without extension)\n- **Skills can ship them**: executable `.jsh` scripts live alongside SKILL.md\n- **Node-like globals**: `process`, `console`, `fs` (VFS bridge with `readFile`, `writeFile`, `readDir`, `exists`)\n- **Dual-mode**: work in CLI server and Chrome extension\n- **Top-level `await`**: wrapped in AsyncFunction. Always `await` fs methods. Don't use `.then()`.\n\n## .bsh Files (Browser Shell Scripts)\n\n`.bsh` files auto-execute when the browser navigates to a matching URL:\n\n- **Filename = hostname pattern**: `-.okta.com.bsh` matches `*.okta.com`\n- **`// @match` directive**: restrict to specific URL patterns in first 10 lines\n- Same execution engine as `.jsh`\n\n## Shell Commands\n\nType `commands` in the terminal for the full list. Key commands:\n\n- **skill list/info/read** — inspect skills; `skill install/uninstall` manages native packages\n- **upskill** — install from GitHub (`upskill owner/repo`) or ClawHub (`upskill clawhub:name`)\n- **webhook/crontask/fswatch** — set up licks (external event triggers, file change watchers)\n- **sprinkle** — manage sprinkles: `list`, `open`, `close`, `send`, `chat`\n- **oauth-token** — get OAuth access token for a provider\n- **cost** — show session cost breakdown (tokens, cache, cost per cone/scoop)\n- **git** — full git support\n- **node -e / python3 -c** — execute JS or Python\n- **serve <dir>** — open VFS app directory in browser tab\n- **open <path|url>** — open file/URL in browser. `open --view` to see images inline\n- **playwright-cli** — browser automation (tab-list, tab-new, snapshot, screenshot, click, fill, tab-close)\n- **pbcopy/pbpaste/xclip/xsel** — clipboard\n- **say** — text-to-speech\n- **afplay** — play audio files\n- **chime** — notification sound\n- **rsync** — sync files between local VFS and remote tray runtime\n- **teleport** — transfer browser cookies from remote tray runtime\n- **host** — tray status and join URL\n\n## Filesystem\n\nVirtual filesystem stored in IndexedDB, survives tab closes and refreshes. Mount local directories:\n\n```\nmount /mnt/myproject\n```\n\nUse an empty mount point. Mounting over existing files is blocked so built-in skills and scripts stay discoverable. `ln -s` the mounted files into the place where you need them.\n\n## Capabilities\n\n- Read/write files in virtual workspace\n- Run bash commands in sandboxed shell\n- Automate browser interactions (screenshots, navigation, clicking, JS eval)\n- Delegate work to scoops and react when they finish\n- Respond to licks (webhooks, scheduled tasks)\n",tx=`---
12162
+ `,tx="---\nname: Skill Authoring\ndescription: Skills discovery, .jsh/.bsh files, shell commands, filesystem\n---\n\n# Skill Authoring & Shell Reference\n\n## Skills\n\nSkills in `/workspace/skills/` extend capabilities. SLICC also discovers compatibility skills from `.agents/skills/*/SKILL.md` and `.claude/skills/*/SKILL.md` anywhere in the reachable VFS. Only native `/workspace/skills/` entries are install-managed; compatibility-discovered skills stay read-only.\n\n## .jsh Files (JavaScript Shell Scripts)\n\n`.jsh` files are auto-discovered as shell commands anywhere on the VFS:\n\n- **Auto-discovery**: registered as callable commands (by filename without extension)\n- **Skills can ship them**: executable `.jsh` scripts live alongside SKILL.md\n- **Node-like globals**: `process`, `console`, `fs` (VFS bridge with `readFile`, `writeFile`, `readDir`, `exists`)\n- **Dual-mode**: work in CLI server and Chrome extension\n- **Top-level `await`**: wrapped in AsyncFunction. Always `await` fs methods. Don't use `.then()`.\n\n## .bsh Files (Browser Shell Scripts)\n\n`.bsh` files auto-execute when the browser navigates to a matching URL:\n\n- **Filename = hostname pattern**: `-.okta.com.bsh` matches `*.okta.com`\n- **`// @match` directive**: restrict to specific URL patterns in first 10 lines\n- Same execution engine as `.jsh`\n\n## Shell Commands\n\nType `commands` in the terminal for the full list. Key commands:\n\n- **skill list/info/read** — inspect skills; `skill install/uninstall` manages native packages\n- **upskill** — install from GitHub (`upskill owner/repo`) or ClawHub (`upskill clawhub:name`)\n- **webhook/crontask/fswatch** — set up licks (external event triggers, file change watchers)\n- **sprinkle** — manage sprinkles: `list`, `open`, `close`, `send`, `chat`\n- **oauth-token** — get OAuth access token for a provider\n- **cost** — show session cost breakdown (tokens, cache, cost per cone/scoop)\n- **git** — full git support\n- **node -e / python3 -c** — execute JS or Python\n- **serve <dir>** — open VFS app directory in browser tab\n- **open <path|url>** — open file/URL in browser. `open --view` to see images inline\n- **playwright-cli** — browser automation (tab-list, tab-new, snapshot, screenshot, click, fill, tab-close)\n- **pbcopy/pbpaste/xclip/xsel** — clipboard\n- **say** — text-to-speech\n- **afplay** — play audio files\n- **chime** — notification sound\n- **rsync** — sync files between local VFS and remote tray runtime\n- **teleport** — transfer browser cookies from remote tray runtime\n- **host** — tray status and join URL\n\n## Filesystem\n\nVirtual filesystem stored in IndexedDB, survives tab closes and refreshes. Mount local directories:\n\n```\nmount /mnt/myproject\n```\n\nUse an empty mount point. Mounting over existing files is blocked so built-in skills and scripts stay discoverable. `ln -s` the mounted files into the place where you need them.\n\n## Capabilities\n\n- Read/write files in virtual workspace\n- Run bash commands in sandboxed shell\n- Automate browser interactions (screenshots, navigation, clicking, JS eval)\n- Delegate work to scoops and react when they finish\n- Respond to licks (webhooks, scheduled tasks)\n",nx=`---
12163
12163
  name: Sprinkle Guide
12164
12164
  description: Inline cards, sprinkle chat, cone orchestration rules for UI panels
12165
12165
  ---
@@ -12222,7 +12222,7 @@ The cone MUST NOT: write/edit \`.shtml\` files, run \`sprinkle open/close/send\`
12222
12222
  See the sprinkles skill (\`read_file /workspace/skills/sprinkles/SKILL.md\`) for creating, modifying, and handling lick events.
12223
12223
 
12224
12224
  **NEVER handle a lick in the cone. Always \`feed_scoop\`.**
12225
- `,nx='---\nname: sprinkles\ndescription: Create interactive sprinkles — dashboards, forms, and visualizations\nallowed-tools: bash\n---\n\n# Sprinkles\n\n`.shtml` files in `/shared/sprinkles/` become interactive UI panels. Use them to create dashboards, forms, and visualizations alongside the chat.\n\n**Two sprinkle modes**:\n\n- **Fragment mode** (default): Plain HTML fragments injected into the sidebar. Do NOT use `<!DOCTYPE html>`, `<html>`, `<head>`, `<body>`, or custom CSS — use the built-in `.sprinkle-*` classes. Scripts get a `slicc` bridge object automatically.\n- **Full-document mode**: Complete HTML documents (starting with `<!DOCTYPE html>` or `<html>`) render inside sandboxed iframes. Use this for complex layouts with custom CSS, sidebars, split panes, modals, or canvas/SVG visualizations. The bridge script is auto-injected — `window.slicc` and `window.bridge` are available in your scripts. Use `parent.postMessage` is handled internally.\n\n**When to use full-document mode**: Use it when you need custom CSS beyond `.sprinkle-*` classes, complex layouts (sidebar + main, split panes, tabs), or interactive canvas/SVG. The parent page\'s S2 theme tokens are injected automatically.\n\n**Creating a sprinkle**:\n\n1. `read_file /workspace/skills/sprinkles/style-guide.md` — **always read first** before writing any sprinkle\n2. `write_file` to `/shared/sprinkles/<name>/<name>.shtml` (follow the style guide templates)\n3. `bash` → `sprinkle open <name>`\n4. **CRITICAL: Do NOT finish or send a completion message.** You own this sprinkle for its entire lifetime. The cone will send you follow-up instructions (modifications, lick events) via `feed_scoop`. If you finish, you lose your context and cannot handle future work on this sprinkle.\n\n**Updating a sprinkle** (when you receive follow-up instructions):\n\n1. Edit `/shared/sprinkles/<name>/<name>.shtml` with the requested changes\n2. Reload: `sprinkle close <name> && sprinkle open <name>`\n3. Do NOT finish — stay ready for more instructions\n\n**Handling lick events** (when the cone forwards a user interaction):\nThe cone will send you a message with the lick action and your sprinkle name. Only modify YOUR sprinkle — the one matching your scoop name. Process the action and push updates:\n\n- `bash` → `sprinkle send <name> \'{"key":"value"}\'` to push data to the sprinkle\'s `slicc.on(\'update\', ...)` handler\n- Or edit the `.shtml` file and reload if the UI structure needs to change\n- Do NOT finish — stay ready for more events\n\n**Managing sprinkles via bash**:\n\n- `sprinkle list` — see available sprinkles\n- `sprinkle open <name>` — show a sprinkle in the sidebar\n- `sprinkle close <name>` — remove it\n- `sprinkle send <name> \'<json>\'` — push data (single-quote the JSON!)\n- `sprinkle chat \'<html>\'` — show inline HTML in the chat (for quick confirmations/choices)\n- `open /path/to/file.shtml` — also opens as a sprinkle\n\n**Bridge API** (available as `slicc` in `<script>` tags and `onclick` attributes):\n\n- `slicc.lick({action: \'refresh\', data: {...}})` — send a lick event to the cone (cone routes to the right scoop)\n- `slicc.on(\'update\', function(data) {...})` — receive data sent via `sprinkle send`\n- `slicc.name` — the sprinkle\'s name\n- `slicc.close()` — close the sprinkle\n- `slicc.stopCone()` — stop the cone agent\n- `slicc.readFile(path)` — read a VFS file (returns `Promise<string>`)\n- `slicc.writeFile(path, content)` — write text content to a VFS file\n- `slicc.readDir(path)` — list directory entries (returns `Promise<Array<{name, type}>>`)\n- `slicc.exists(path)` — check if path exists (returns `Promise<boolean>`)\n- `slicc.stat(path)` — get file metadata (returns `Promise<{type, size}>`)\n- `slicc.mkdir(path)` — create a directory (recursive)\n- `slicc.rm(path)` — remove a file\n- `slicc.screenshot(selector?)` — capture sprinkle DOM as base64 PNG data URL. Note: The screenshot captures a DOM clone using SVG foreignObject. External stylesheets and some computed styles may not be fully reproduced. For best results, use inline styles on elements you intend to screenshot.\n\n**onclick attributes**: Always use `slicc` — e.g. `onclick="slicc.lick({action: \'add-year\'})"`. The `slicc` variable is automatically resolved per-sprinkle, so multiple sprinkles won\'t collide. Do NOT use `bridge` or any other variable name in onclick.\n\n**CSS components** — Do NOT write custom CSS. Use the built-in `.sprinkle-*` classes: cards, tables, badges, buttons, text fields, progress bars, meters, layout utilities, and more. For inputs use `class="sprinkle-text-field"`, never inline border/padding styles. Run `read_file /workspace/skills/sprinkles/style-guide.md` for the full component reference with markup examples.\n\n## Built-in Sprinkles\n\nThese sprinkles ship with SLICC at `/shared/sprinkles/`. They are full-document HTML apps rendered in sandboxed iframes.\n\n| Sprinkle name | Open with | Use when the user asks for... |\n| ------------------ | -------------------------------- | --------------------------------------------------------------------- |\n| `page-editor` | `sprinkle open page-editor` | WYSIWYG editor, page editor, edit sections, visual editing |\n| `content-tree` | `sprinkle open content-tree` | content tree, page tree, site structure, page browser, navigate pages |\n| `review-workflow` | `sprinkle open review-workflow` | review, approval workflow, annotations, comments on content |\n| `seo-dashboard` | `sprinkle open seo-dashboard` | SEO audit, meta tags, SERP preview, SEO issues |\n| `schema-editor` | `sprinkle open schema-editor` | schema, structured data, JSON-LD, rich results |\n| `readability` | `sprinkle open readability` | readability, reading level, text analysis, simplify text |\n| `brand-compliance` | `sprinkle open brand-compliance` | brand check, brand compliance, style guide violations |\n| `tone-voice` | `sprinkle open tone-voice` | tone, voice, writing style, formality, tone analysis |\n| `performance` | `sprinkle open performance` | performance, Core Web Vitals, page speed, lighthouse |\n| `funnels` | `sprinkle open funnels` | funnels, conversion, A/B test, analytics |\n\n### When a user request matches a built-in sprinkle\n\nWhen the user\'s request matches a built-in sprinkle (see table above), **ask the user which approach they prefer** before proceeding:\n\n> I can help with that. Would you like me to:\n>\n> 1. **Open the built-in [sprinkle name]** — ready to use immediately, I\'ll populate it with your data\n> 2. **Build a custom one from scratch** — tailored exactly to your needs, but takes a moment to create\n>\n> Which do you prefer?\n\n**If the user says "open" / "use the built-in" / picks option 1** — use the built-in sprinkle (see "Using Built-in Sprinkles" in style-guide.md for the scoop brief template).\n\n**If the user says "build" / "create" / "custom" / picks option 2** — create a new sprinkle from scratch following the "Creating a sprinkle" flow above.\n\n**If the user explicitly says "open the page editor"** (or any built-in name directly) — skip the question and use the built-in immediately.\n\n**If the request is clearly novel** (no matching built-in) — create from scratch without asking.\n\n### Cone orchestration for sprinkles\n\n**Rule 3: Creating sprinkles** — Create a scoop, then feed it a complete, self-contained brief:\n\n```\nscoop_scoop("giro-winners")\nfeed_scoop("giro-winners", "You own the sprinkle \'giro-winners\'. Your job:\n1. Run: read_file /workspace/skills/sprinkles/style-guide.md\n2. Research the last 3 Giro d\'Italia winners\n3. Write the sprinkle to /shared/sprinkles/giro-winners/giro-winners.shtml\n4. Run: sprinkle open giro-winners\n5. IMPORTANT: After opening the sprinkle, do NOT finish. Stay ready — you will receive follow-up instructions and lick events for this sprinkle via feed_scoop. Do not send a completion message.")\n```\n\n**Rule 4: Modifying sprinkles** — Feed the EXISTING scoop that owns it. Do NOT create a new scoop:\n\n```\nfeed_scoop("giro-winners", "Modify YOUR sprinkle \'giro-winners\' at /shared/sprinkles/giro-winners/giro-winners.shtml:\nAdd an \'Add Previous Year\' button with onclick=\\"slicc.lick({action: \'add-year\'})\\"\nThen reload: sprinkle close giro-winners && sprinkle open giro-winners\nStay ready for more work.")\n```\n\n**Rule 5: Lick events** — Forward to owning scoop, never handle yourself:\n\n```\nfeed_scoop("giro-winners", "Lick event on YOUR sprinkle \'giro-winners\' (/shared/sprinkles/giro-winners/giro-winners.shtml):\nAction: \'add-year\'\nLook up the next previous year\'s Giro d\'Italia winner and update the sprinkle.\nUse: sprinkle send giro-winners \'<json>\' to push data, or edit the .shtml and reload.\nStay ready for more lick events.")\n```\n',rx=`# Lucide Icons Example
12225
+ `,rx='---\nname: sprinkles\ndescription: Create interactive sprinkles — dashboards, forms, and visualizations\nallowed-tools: bash\n---\n\n# Sprinkles\n\n`.shtml` files in `/shared/sprinkles/` become interactive UI panels. Use them to create dashboards, forms, and visualizations alongside the chat.\n\n**Two sprinkle modes**:\n\n- **Fragment mode** (default): Plain HTML fragments injected into the sidebar. Do NOT use `<!DOCTYPE html>`, `<html>`, `<head>`, `<body>`, or custom CSS — use the built-in `.sprinkle-*` classes. Scripts get a `slicc` bridge object automatically.\n- **Full-document mode**: Complete HTML documents (starting with `<!DOCTYPE html>` or `<html>`) render inside sandboxed iframes. Use this for complex layouts with custom CSS, sidebars, split panes, modals, or canvas/SVG visualizations. The bridge script is auto-injected — `window.slicc` and `window.bridge` are available in your scripts. Use `parent.postMessage` is handled internally.\n\n**When to use full-document mode**: Use it when you need custom CSS beyond `.sprinkle-*` classes, complex layouts (sidebar + main, split panes, tabs), or interactive canvas/SVG. The parent page\'s S2 theme tokens are injected automatically.\n\n**Creating a sprinkle**:\n\n1. `read_file /workspace/skills/sprinkles/style-guide.md` — **always read first** before writing any sprinkle\n2. `write_file` to `/shared/sprinkles/<name>/<name>.shtml` (follow the style guide templates)\n3. `bash` → `sprinkle open <name>`\n4. **CRITICAL: Do NOT finish or send a completion message.** You own this sprinkle for its entire lifetime. The cone will send you follow-up instructions (modifications, lick events) via `feed_scoop`. If you finish, you lose your context and cannot handle future work on this sprinkle.\n\n**Updating a sprinkle** (when you receive follow-up instructions):\n\n1. Edit `/shared/sprinkles/<name>/<name>.shtml` with the requested changes\n2. Reload: `sprinkle close <name> && sprinkle open <name>`\n3. Do NOT finish — stay ready for more instructions\n\n**Handling lick events** (when the cone forwards a user interaction):\nThe cone will send you a message with the lick action and your sprinkle name. Only modify YOUR sprinkle — the one matching your scoop name. Process the action and push updates:\n\n- `bash` → `sprinkle send <name> \'{"key":"value"}\'` to push data to the sprinkle\'s `slicc.on(\'update\', ...)` handler\n- Or edit the `.shtml` file and reload if the UI structure needs to change\n- Do NOT finish — stay ready for more events\n\n**Managing sprinkles via bash**:\n\n- `sprinkle list` — see available sprinkles\n- `sprinkle open <name>` — show a sprinkle in the sidebar\n- `sprinkle close <name>` — remove it\n- `sprinkle send <name> \'<json>\'` — push data (single-quote the JSON!)\n- `sprinkle chat \'<html>\'` — show inline HTML in the chat (for quick confirmations/choices)\n- `open /path/to/file.shtml` — also opens as a sprinkle\n\n**Bridge API** (available as `slicc` in `<script>` tags and `onclick` attributes):\n\n- `slicc.lick({action: \'refresh\', data: {...}})` — send a lick event to the cone (cone routes to the right scoop)\n- `slicc.on(\'update\', function(data) {...})` — receive data sent via `sprinkle send`\n- `slicc.name` — the sprinkle\'s name\n- `slicc.close()` — close the sprinkle\n- `slicc.stopCone()` — stop the cone agent\n- `slicc.readFile(path)` — read a VFS file (returns `Promise<string>`)\n- `slicc.writeFile(path, content)` — write text content to a VFS file\n- `slicc.readDir(path)` — list directory entries (returns `Promise<Array<{name, type}>>`)\n- `slicc.exists(path)` — check if path exists (returns `Promise<boolean>`)\n- `slicc.stat(path)` — get file metadata (returns `Promise<{type, size}>`)\n- `slicc.mkdir(path)` — create a directory (recursive)\n- `slicc.rm(path)` — remove a file\n- `slicc.screenshot(selector?)` — capture sprinkle DOM as base64 PNG data URL. Note: The screenshot captures a DOM clone using SVG foreignObject. External stylesheets and some computed styles may not be fully reproduced. For best results, use inline styles on elements you intend to screenshot.\n\n**onclick attributes**: Always use `slicc` — e.g. `onclick="slicc.lick({action: \'add-year\'})"`. The `slicc` variable is automatically resolved per-sprinkle, so multiple sprinkles won\'t collide. Do NOT use `bridge` or any other variable name in onclick.\n\n**CSS components** — Do NOT write custom CSS. Use the built-in `.sprinkle-*` classes: cards, tables, badges, buttons, text fields, progress bars, meters, layout utilities, and more. For inputs use `class="sprinkle-text-field"`, never inline border/padding styles. Run `read_file /workspace/skills/sprinkles/style-guide.md` for the full component reference with markup examples.\n\n## Built-in Sprinkles\n\nThese sprinkles ship with SLICC at `/shared/sprinkles/`. They are full-document HTML apps rendered in sandboxed iframes.\n\n| Sprinkle name | Open with | Use when the user asks for... |\n| ------------------ | -------------------------------- | --------------------------------------------------------------------- |\n| `page-editor` | `sprinkle open page-editor` | WYSIWYG editor, page editor, edit sections, visual editing |\n| `content-tree` | `sprinkle open content-tree` | content tree, page tree, site structure, page browser, navigate pages |\n| `review-workflow` | `sprinkle open review-workflow` | review, approval workflow, annotations, comments on content |\n| `seo-dashboard` | `sprinkle open seo-dashboard` | SEO audit, meta tags, SERP preview, SEO issues |\n| `schema-editor` | `sprinkle open schema-editor` | schema, structured data, JSON-LD, rich results |\n| `readability` | `sprinkle open readability` | readability, reading level, text analysis, simplify text |\n| `brand-compliance` | `sprinkle open brand-compliance` | brand check, brand compliance, style guide violations |\n| `tone-voice` | `sprinkle open tone-voice` | tone, voice, writing style, formality, tone analysis |\n| `performance` | `sprinkle open performance` | performance, Core Web Vitals, page speed, lighthouse |\n| `funnels` | `sprinkle open funnels` | funnels, conversion, A/B test, analytics |\n\n### When a user request matches a built-in sprinkle\n\nWhen the user\'s request matches a built-in sprinkle (see table above), **ask the user which approach they prefer** before proceeding:\n\n> I can help with that. Would you like me to:\n>\n> 1. **Open the built-in [sprinkle name]** — ready to use immediately, I\'ll populate it with your data\n> 2. **Build a custom one from scratch** — tailored exactly to your needs, but takes a moment to create\n>\n> Which do you prefer?\n\n**If the user says "open" / "use the built-in" / picks option 1** — use the built-in sprinkle (see "Using Built-in Sprinkles" in style-guide.md for the scoop brief template).\n\n**If the user says "build" / "create" / "custom" / picks option 2** — create a new sprinkle from scratch following the "Creating a sprinkle" flow above.\n\n**If the user explicitly says "open the page editor"** (or any built-in name directly) — skip the question and use the built-in immediately.\n\n**If the request is clearly novel** (no matching built-in) — create from scratch without asking.\n\n### Cone orchestration for sprinkles\n\n**Rule 3: Creating sprinkles** — Create a scoop, then feed it a complete, self-contained brief:\n\n```\nscoop_scoop("giro-winners")\nfeed_scoop("giro-winners", "You own the sprinkle \'giro-winners\'. Your job:\n1. Run: read_file /workspace/skills/sprinkles/style-guide.md\n2. Research the last 3 Giro d\'Italia winners\n3. Write the sprinkle to /shared/sprinkles/giro-winners/giro-winners.shtml\n4. Run: sprinkle open giro-winners\n5. IMPORTANT: After opening the sprinkle, do NOT finish. Stay ready — you will receive follow-up instructions and lick events for this sprinkle via feed_scoop. Do not send a completion message.")\n```\n\n**Rule 4: Modifying sprinkles** — Feed the EXISTING scoop that owns it. Do NOT create a new scoop:\n\n```\nfeed_scoop("giro-winners", "Modify YOUR sprinkle \'giro-winners\' at /shared/sprinkles/giro-winners/giro-winners.shtml:\nAdd an \'Add Previous Year\' button with onclick=\\"slicc.lick({action: \'add-year\'})\\"\nThen reload: sprinkle close giro-winners && sprinkle open giro-winners\nStay ready for more work.")\n```\n\n**Rule 5: Lick events** — Forward to owning scoop, never handle yourself:\n\n```\nfeed_scoop("giro-winners", "Lick event on YOUR sprinkle \'giro-winners\' (/shared/sprinkles/giro-winners/giro-winners.shtml):\nAction: \'add-year\'\nLook up the next previous year\'s Giro d\'Italia winner and update the sprinkle.\nUse: sprinkle send giro-winners \'<json>\' to push data, or edit the .shtml and reload.\nStay ready for more lick events.")\n```\n',ix=`# Lucide Icons Example
12226
12226
 
12227
12227
  This shows how to use Lucide icons in inline sprinkles instead of emojis.
12228
12228
 
@@ -12332,7 +12332,7 @@ This shows how to use Lucide icons in inline sprinkles instead of emojis.
12332
12332
  **UI**: \`settings\`, \`menu\`, \`more-vertical\`, \`more-horizontal\`, \`eye\`, \`eye-off\`, \`lock\`, \`unlock\`
12333
12333
 
12334
12334
  Browse all icons at [lucide.dev/icons](https://lucide.dev/icons)
12335
- `,ix=`# Sprinkle Component Reference
12335
+ `,ax=`# Sprinkle Component Reference
12336
12336
 
12337
12337
  Use these CSS classes in \`.shtml\` sprinkles. Do NOT write custom CSS — these components cover all common UI patterns.
12338
12338
 
@@ -13112,7 +13112,7 @@ background: color-mix(in srgb, var(--s2-accent) 6%, transparent); /* blue tint *
13112
13112
  | \`--s2-spacing-400\` | 24px |
13113
13113
  | \`--s2-spacing-500\` | 32px |
13114
13114
  | \`--s2-spacing-600\` | 40px |
13115
- `,ax=`---
13115
+ `,ox=`---
13116
13116
  name: welcome
13117
13117
  description: Handle onboarding lick from the welcome sprinkle
13118
13118
  allowed-tools: bash
@@ -13206,8 +13206,8 @@ Do NOT save a profile, update \`/shared/CLAUDE.md\`, or write a greeting.
13206
13206
 
13207
13207
  - **\`start-task\` lick** — treat as the user's first request, begin the task immediately.
13208
13208
  - **Sparse profiles** (user skipped most steps) — keep greeting brief, ask what they need.
13209
- `,ox=`data:audio/mpeg;base64,SUQzBAAAAAAAIlRTU0UAAAAOAAADTGF2ZjYyLjMuMTAwAAAAAAAAAAAAAAD/+0DAAAAAAAAAAAAAAAAAAAAAAABYaW5nAAAADwAAAAcAAAYbAJWVlZWVlZWVlZWVlZWVqqqqqqqqqqqqqqqqqqq7u7u7u7u7u7u7u7u7u8zMzMzMzMzMzMzMzMzMzN3d3d3d3d3d3d3d3d3d7u7u7u7u7u7u7u7u7u7//////////////////wAAAABMYXZjNjIuMTEAAAAAAAAAAAAAAAAkA2kAAAAAAAAGG+gbtfQAAAAAAP/7wMQAAAv4N1B0ZIAqHxVpvznQgAr9rb7PJkyd34smDgMBk078/BAKAoGBQw+OHn/gAGf4eHv/wB3mf/gb/+OAf/AMf/h4A78AMP/oeAGfAAw/+h4AZ8BGH/48AM/iMf/+AAAAAAYeHh4eAAAAAAYeHh48AQMIAMGIBMXNwtEAoEAwAAQFAIBXCQKu8YAEJgcFBQtl1DXh6g4LDYWQ0TAcKGhAZbDTOWxGG4ECgfmRFLtKMFhAMNgLYEsYxXEXG8YqgB/V3RF/XZhqJUcp//99nKcqIv7vmWv///4zWppVVpf///////5TWpqarS0v8RBUFREe/1gqIgqCoiXfkTAVAAwAAMY6g6nK2AAgTCmlJdBcQAwEcSQmFALZslhoW7uNZ4gSBAGEM6A0KbEqs5LgGh4TzAuMFNh9L4FA2JwwsRBsKsxbGrvVd4Ah/AtwTpu046oAoLB7MBAHAAAuQSQgTSmJa2mO8ncaGTeyJsz3wn9TbdBmuCWkp8D8E//+gA4/C9YFwCq9RAA7S+AQNicISCx60KQy7HHeq7wBD0BcwnTfOPUM5NC/UFgAAAA6uQ6OhMlAQIF6e9CTI2Vyp7bkY0xyAhvA8Zp848zYQBSgCAONoPJlh0OM6j8g0QAE5IcEu49m0ZsbxZWX6cQwG6gzS0dl1wT//6UO9sCfUFoAAAAziH7QUEI6FiQEQGYIOeVMMQXnACAteiQWVmmckZbEXG1w7KCMN9bB7QFyC3ELRigOQJdCo56zhEjAgXAlbcHreLLGmdkZTD2m1w6ygjUO98CeUH4AAAAziH/QkCMDzpmjj44B3nBC54YUDZoxbLGmdEdERly9qyhjDfixayBkA2cGE4UKrxIIhgz8HwBS3YlbIGxt21jWiK0hatrEYEjVTEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVB3aABwAfwAAAMj7DgFUgDBxFLY4XWT6pcoZrVtbqPGBB//sgxO8Axmw5Qd29gCiLCCg4DdB0oi1tkrKwMMFBV000qkxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqv/7EMT6AEVwQTPgcEPgk4goOA3QdKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sQxPsARMRBQ+Dqg2C2iCa8Pgh8qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr/+xDE+oDFuEFD4Whj4KMIKDgtDHyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqv/7EMT4gMVgQUXhYGPgmgan+AHgBaqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sQxO0DxaRHKeDgY+gAAD/AAAAEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=`,sx=r(`skills`),cx=Object.assign({"/packages/vfs-root/AGENTS.md":Ib,"/packages/vfs-root/CLAUDE.md":Ib,"/packages/vfs-root/shared/CLAUDE.md":Lb,"/packages/vfs-root/shared/sprinkles/brand-compliance/brand-compliance.shtml":Rb,"/packages/vfs-root/shared/sprinkles/content-tree/content-tree.shtml":zb,"/packages/vfs-root/shared/sprinkles/funnels/funnels.shtml":Bb,"/packages/vfs-root/shared/sprinkles/page-editor/page-editor.shtml":Vb,"/packages/vfs-root/shared/sprinkles/performance/performance.shtml":Hb,"/packages/vfs-root/shared/sprinkles/readability/readability.shtml":Ub,"/packages/vfs-root/shared/sprinkles/review-workflow/review-workflow.shtml":Wb,"/packages/vfs-root/shared/sprinkles/schema-editor/schema-editor.shtml":Gb,"/packages/vfs-root/shared/sprinkles/seo-dashboard/seo-dashboard.shtml":Kb,"/packages/vfs-root/shared/sprinkles/tone-voice/tone-voice.shtml":qb,"/packages/vfs-root/shared/sprinkles/welcome/welcome.shtml":Jb,"/packages/vfs-root/workspace/skills/automation/SKILL.md":Yb,"/packages/vfs-root/workspace/skills/handoff/SKILL.md":Xb,"/packages/vfs-root/workspace/skills/inline-widgets/SKILL.md":Zb,"/packages/vfs-root/workspace/skills/playwright-cli/SKILL.md":Qb,"/packages/vfs-root/workspace/skills/scoop-management/SKILL.md":$b,"/packages/vfs-root/workspace/skills/skill-authoring/SKILL.md":ex,"/packages/vfs-root/workspace/skills/sprinkle-guide/SKILL.md":tx,"/packages/vfs-root/workspace/skills/sprinkles/SKILL.md":nx,"/packages/vfs-root/workspace/skills/sprinkles/icon-example.md":rx,"/packages/vfs-root/workspace/skills/sprinkles/style-guide.md":ix,"/packages/vfs-root/workspace/skills/welcome/SKILL.md":ax}),lx=Object.assign({"/packages/vfs-root/shared/sounds/chime.mp3":ox});function ux(e){let t=e.split(`,`)[1],n=atob(t),r=new Uint8Array(n.length);for(let e=0;e<n.length;e++)r[e]=n.charCodeAt(e);return r}function dx(){let e={};for(let[t,n]of Object.entries(cx))e[t]=n;for(let[t,n]of Object.entries(lx))e[t]=ux(n);return e}function fx(e){let t=new Map;for(let n of e){if(t.has(n.metadata.name)){sx.debug(`Skipped shadowed runtime skill`,{name:n.metadata.name,path:n.path,winnerPath:t.get(n.metadata.name)?.path});continue}t.set(n.metadata.name,n)}return Array.from(t.values())}function px(e){let t=e.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);if(!t)return{metadata:{},body:e};let[,n,r]=t,i={};for(let e of n.split(`
13210
- `)){let t=e.match(/^(\w[\w-]*):\s*(.*)$/);if(!t)continue;let[,n,r]=t,a=r.trim();switch(n){case`name`:i.name=a;break;case`description`:i.description=a;break;case`allowed-tools`:i.allowedTools=a.split(`,`).map(e=>e.trim());break}}return{metadata:i,body:r}}async function mx(e,t){let n=await hx(e,t),r=await gx(e,t),i=n.filter(e=>e.source===`native`),a=n.filter(e=>e.source!==`native`),o=fx([...i,...r,...a]);return sx.info(`Skills loaded`,{count:o.length,dir:t}),o}async function hx(e,t){let n=await de(e,t),r=[];for(let t of n)if(t.skillFilePath)try{let{metadata:n,body:i}=px(await e.readTextFile(t.skillFilePath)),a=n.name||t.name;r.push({metadata:{name:a,description:n.description||t.manifest.description||``,allowedTools:n.allowedTools},content:i,path:t.skillFilePath,source:t.source}),sx.debug(`Loaded discovered skill`,{name:a,path:t.skillFilePath,source:t.source})}catch{sx.debug(`Failed to load discovered skill`,{name:t.name,path:t.skillFilePath})}return r}async function gx(e,t){let n=[];try{let r=await e.readDir(t);for(let i of r)if(i.type===`file`&&i.name.endsWith(`.md`)){let r=`${t}/${i.name}`;try{let t=await e.readFile(r,{encoding:`utf-8`}),{metadata:a,body:o}=px(typeof t==`string`?t:new TextDecoder().decode(t)),s=a.name||i.name.replace(`.md`,``);n.push({metadata:{name:s,description:a.description||``,allowedTools:a.allowedTools},content:o,path:r}),sx.debug(`Loaded standalone skill`,{name:s,path:r})}catch{}}}catch{sx.debug(`Standalone skills directory not found`,{dir:t})}return n}function _x(e){return e.length===0?``:`
13209
+ `,sx=`data:audio/mpeg;base64,SUQzBAAAAAAAIlRTU0UAAAAOAAADTGF2ZjYyLjMuMTAwAAAAAAAAAAAAAAD/+0DAAAAAAAAAAAAAAAAAAAAAAABYaW5nAAAADwAAAAcAAAYbAJWVlZWVlZWVlZWVlZWVqqqqqqqqqqqqqqqqqqq7u7u7u7u7u7u7u7u7u8zMzMzMzMzMzMzMzMzMzN3d3d3d3d3d3d3d3d3d7u7u7u7u7u7u7u7u7u7//////////////////wAAAABMYXZjNjIuMTEAAAAAAAAAAAAAAAAkA2kAAAAAAAAGG+gbtfQAAAAAAP/7wMQAAAv4N1B0ZIAqHxVpvznQgAr9rb7PJkyd34smDgMBk078/BAKAoGBQw+OHn/gAGf4eHv/wB3mf/gb/+OAf/AMf/h4A78AMP/oeAGfAAw/+h4AZ8BGH/48AM/iMf/+AAAAAAYeHh4eAAAAAAYeHh48AQMIAMGIBMXNwtEAoEAwAAQFAIBXCQKu8YAEJgcFBQtl1DXh6g4LDYWQ0TAcKGhAZbDTOWxGG4ECgfmRFLtKMFhAMNgLYEsYxXEXG8YqgB/V3RF/XZhqJUcp//99nKcqIv7vmWv///4zWppVVpf///////5TWpqarS0v8RBUFREe/1gqIgqCoiXfkTAVAAwAAMY6g6nK2AAgTCmlJdBcQAwEcSQmFALZslhoW7uNZ4gSBAGEM6A0KbEqs5LgGh4TzAuMFNh9L4FA2JwwsRBsKsxbGrvVd4Ah/AtwTpu046oAoLB7MBAHAAAuQSQgTSmJa2mO8ncaGTeyJsz3wn9TbdBmuCWkp8D8E//+gA4/C9YFwCq9RAA7S+AQNicISCx60KQy7HHeq7wBD0BcwnTfOPUM5NC/UFgAAAA6uQ6OhMlAQIF6e9CTI2Vyp7bkY0xyAhvA8Zp848zYQBSgCAONoPJlh0OM6j8g0QAE5IcEu49m0ZsbxZWX6cQwG6gzS0dl1wT//6UO9sCfUFoAAAAziH7QUEI6FiQEQGYIOeVMMQXnACAteiQWVmmckZbEXG1w7KCMN9bB7QFyC3ELRigOQJdCo56zhEjAgXAlbcHreLLGmdkZTD2m1w6ygjUO98CeUH4AAAAziH/QkCMDzpmjj44B3nBC54YUDZoxbLGmdEdERly9qyhjDfixayBkA2cGE4UKrxIIhgz8HwBS3YlbIGxt21jWiK0hatrEYEjVTEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVB3aABwAfwAAAMj7DgFUgDBxFLY4XWT6pcoZrVtbqPGBB//sgxO8Axmw5Qd29gCiLCCg4DdB0oi1tkrKwMMFBV000qkxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqv/7EMT6AEVwQTPgcEPgk4goOA3QdKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sQxPsARMRBQ+Dqg2C2iCa8Pgh8qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr/+xDE+oDFuEFD4Whj4KMIKDgtDHyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqv/7EMT4gMVgQUXhYGPgmgan+AHgBaqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sQxO0DxaRHKeDgY+gAAD/AAAAEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=`,cx=r(`skills`),lx=Object.assign({"/packages/vfs-root/AGENTS.md":Lb,"/packages/vfs-root/CLAUDE.md":Lb,"/packages/vfs-root/shared/CLAUDE.md":Rb,"/packages/vfs-root/shared/sprinkles/brand-compliance/brand-compliance.shtml":zb,"/packages/vfs-root/shared/sprinkles/content-tree/content-tree.shtml":Bb,"/packages/vfs-root/shared/sprinkles/funnels/funnels.shtml":Vb,"/packages/vfs-root/shared/sprinkles/page-editor/page-editor.shtml":Hb,"/packages/vfs-root/shared/sprinkles/performance/performance.shtml":Ub,"/packages/vfs-root/shared/sprinkles/readability/readability.shtml":Wb,"/packages/vfs-root/shared/sprinkles/review-workflow/review-workflow.shtml":Gb,"/packages/vfs-root/shared/sprinkles/schema-editor/schema-editor.shtml":Kb,"/packages/vfs-root/shared/sprinkles/seo-dashboard/seo-dashboard.shtml":qb,"/packages/vfs-root/shared/sprinkles/tone-voice/tone-voice.shtml":Jb,"/packages/vfs-root/shared/sprinkles/welcome/welcome.shtml":Yb,"/packages/vfs-root/workspace/skills/automation/SKILL.md":Xb,"/packages/vfs-root/workspace/skills/handoff/SKILL.md":Zb,"/packages/vfs-root/workspace/skills/inline-widgets/SKILL.md":Qb,"/packages/vfs-root/workspace/skills/playwright-cli/SKILL.md":$b,"/packages/vfs-root/workspace/skills/scoop-management/SKILL.md":ex,"/packages/vfs-root/workspace/skills/skill-authoring/SKILL.md":tx,"/packages/vfs-root/workspace/skills/sprinkle-guide/SKILL.md":nx,"/packages/vfs-root/workspace/skills/sprinkles/SKILL.md":rx,"/packages/vfs-root/workspace/skills/sprinkles/icon-example.md":ix,"/packages/vfs-root/workspace/skills/sprinkles/style-guide.md":ax,"/packages/vfs-root/workspace/skills/welcome/SKILL.md":ox}),ux=Object.assign({"/packages/vfs-root/shared/sounds/chime.mp3":sx});function dx(e){let t=e.split(`,`)[1],n=atob(t),r=new Uint8Array(n.length);for(let e=0;e<n.length;e++)r[e]=n.charCodeAt(e);return r}function fx(){let e={};for(let[t,n]of Object.entries(lx))e[t]=n;for(let[t,n]of Object.entries(ux))e[t]=dx(n);return e}function px(e){let t=new Map;for(let n of e){if(t.has(n.metadata.name)){cx.debug(`Skipped shadowed runtime skill`,{name:n.metadata.name,path:n.path,winnerPath:t.get(n.metadata.name)?.path});continue}t.set(n.metadata.name,n)}return Array.from(t.values())}function mx(e){let t=e.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);if(!t)return{metadata:{},body:e};let[,n,r]=t,i={};for(let e of n.split(`
13210
+ `)){let t=e.match(/^(\w[\w-]*):\s*(.*)$/);if(!t)continue;let[,n,r]=t,a=r.trim();switch(n){case`name`:i.name=a;break;case`description`:i.description=a;break;case`allowed-tools`:i.allowedTools=a.split(`,`).map(e=>e.trim());break}}return{metadata:i,body:r}}async function hx(e,t){let n=await gx(e,t),r=await _x(e,t),i=n.filter(e=>e.source===`native`),a=n.filter(e=>e.source!==`native`),o=px([...i,...r,...a]);return cx.info(`Skills loaded`,{count:o.length,dir:t}),o}async function gx(e,t){let n=await de(e,t),r=[];for(let t of n)if(t.skillFilePath)try{let{metadata:n,body:i}=mx(await e.readTextFile(t.skillFilePath)),a=n.name||t.name;r.push({metadata:{name:a,description:n.description||t.manifest.description||``,allowedTools:n.allowedTools},content:i,path:t.skillFilePath,source:t.source}),cx.debug(`Loaded discovered skill`,{name:a,path:t.skillFilePath,source:t.source})}catch{cx.debug(`Failed to load discovered skill`,{name:t.name,path:t.skillFilePath})}return r}async function _x(e,t){let n=[];try{let r=await e.readDir(t);for(let i of r)if(i.type===`file`&&i.name.endsWith(`.md`)){let r=`${t}/${i.name}`;try{let t=await e.readFile(r,{encoding:`utf-8`}),{metadata:a,body:o}=mx(typeof t==`string`?t:new TextDecoder().decode(t)),s=a.name||i.name.replace(`.md`,``);n.push({metadata:{name:s,description:a.description||``,allowedTools:a.allowedTools},content:o,path:r}),cx.debug(`Loaded standalone skill`,{name:s,path:r})}catch{}}}catch{cx.debug(`Standalone skills directory not found`,{dir:t})}return n}function vx(e){return e.length===0?``:`
13211
13211
  ---
13212
13212
  AVAILABLE SKILLS
13213
13213
 
@@ -13216,9 +13216,9 @@ The following skills are available. To use a skill, first read its full instruct
13216
13216
 
13217
13217
  ${e.map(e=>{let t=e.metadata.allowedTools?` Allowed tools: ${e.metadata.allowedTools.join(`, `)}\n`:``;return`- **${e.metadata.name}**: ${e.metadata.description}\n${t} Path: ${e.path}`}).join(`
13218
13218
  `)}
13219
- ---`}async function vx(e,t=`/workspace/skills`){let n=dx();for(let[r,i]of Object.entries(n)){let n=r.slice(18),a=n.startsWith(`/workspace/skills`),o=n.startsWith(`/workspace/scripts`);if(!a&&!o)continue;let s=n;a&&t!==`/workspace/skills`&&(s=n.replace(`/workspace/skills`,t)),o&&t!==`/workspace/skills`&&(s=t.replace(`/workspace/skills`,``)+n);try{await e.stat(s)}catch{let t=s.substring(0,s.lastIndexOf(`/`));try{await e.mkdir(t,{recursive:!0})}catch{}await e.writeFile(s,i),sx.info(`Created default file`,{path:s})}}}async function yx(e){let t=dx();for(let[n,r]of Object.entries(t)){let t=n.slice(18);if(t.startsWith(`/shared/`))try{await e.stat(t)}catch{let n=t.substring(0,t.lastIndexOf(`/`));try{await e.mkdir(n,{recursive:!0})}catch{}await e.writeFile(t,r),sx.info(`Created default shared file`,{path:t})}}}var bx=r(`scoop-management-tools`);function xx(e){let{scoop:t,onSendMessage:n,onFeedScoop:r,getScoops:i,getScoopTabState:a,onScoopScoop:o,onDropScoop:s,onSetGlobalMemory:c,getGlobalMemory:l}=e,u=[];return u.push({name:`send_message`,description:`Send a progress message while still working. Your final output is also sent.`,inputSchema:{type:`object`,properties:{text:{type:`string`,description:`The message text to send`},sender:{type:`string`,description:`Optional sender name/role (e.g., "Researcher"). Defaults to assistant name.`}},required:[`text`]},execute:async e=>{let{text:r,sender:i}=e;return n(r,i),bx.info(`Message sent`,{scoopFolder:t.folder,textLength:r.length}),{content:`Message sent.`}}}),t.isCone&&r&&u.push({name:`feed_scoop`,description:`Give a scoop a task. Provide a complete, self-contained prompt — the scoop has no access to your conversation. You'll be notified when it finishes.`,inputSchema:{type:`object`,properties:{scoop_name:{type:`string`,description:`The scoop folder name (e.g., "test-scoop"). Use list_scoops to see available scoops.`},prompt:{type:`string`,description:`Complete, self-contained instructions for the scoop. Include ALL context — the scoop cannot see your conversation.`}},required:[`scoop_name`,`prompt`]},execute:async e=>{let{scoop_name:t,prompt:n}=e,a=i().find(e=>e.folder===t||e.name===t);if(!a)return{content:`Scoop "${t}" not found. Available: ${i().filter(e=>!e.isCone).map(e=>e.folder).join(`, `)}`,isError:!0};if(a.isCone)return{content:`Cannot feed the cone (yourself).`,isError:!0};try{return await r(a.jid,n),bx.info(`Fed scoop`,{target:a.folder,promptLength:n.length}),{content:`Task sent to ${a.folder}. You will be notified when it completes.`}}catch(e){return{content:`Failed to feed scoop: ${e instanceof Error?e.message:String(e)}`,isError:!0}}}}),t.isCone&&(u.push({name:`list_scoops`,description:`List all registered scoops.`,inputSchema:{type:`object`,properties:{}},execute:async()=>{let e=i();return e.length===0?{content:`No scoops registered.`}:{content:`Registered scoops:\n${e.map(e=>{let t=a?.(e.jid),n=t?.status??`unknown`,r=t?.lastActivity?new Date(t.lastActivity).toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`,hour12:!0}):``,i=r?` — ${n} (since ${r})`:` — ${n}`;return e.isCone?`- ${e.assistantLabel} (${e.folder}) [CONE]${i}`:`- ${e.name} (${e.folder})${i}`}).join(`
13220
- `)}`}}}),o&&u.push({name:`scoop_scoop`,description:`Create a new scoop. Optionally specify a model, a prompt, and per-scoop sandbox shape (visible/writable paths + command allow-list). If prompt is provided, the scoop starts working immediately after creation (no separate feed_scoop needed).`,inputSchema:{type:`object`,properties:{name:{type:`string`,description:`Display name for the scoop (e.g., "hero-block")`},model:{type:`string`,description:`Model ID for this scoop (e.g., "claude-sonnet-4-6"). If omitted, uses the same model as the cone.`},prompt:{type:`string`,description:`Task prompt for the scoop. If provided, the scoop starts working immediately after creation.`},visiblePaths:{type:`array`,items:{type:`string`},description:`VFS paths the scoop can READ (not write). Pure replace — what you set is what you get. Omit to use the default ["/workspace/"] which exposes the shared skills tree. Pass [] for no extra read-only paths. Note: the scoop's writablePaths are always readable too, so a true read-nothing sandbox also requires writablePaths: []. Mounts remain readable regardless. Trailing slash recommended (e.g. "/shared/data/").`},writablePaths:{type:`array`,items:{type:`string`},description:`VFS paths the scoop can READ AND WRITE. Pure replace. Omit to use the default ["/scoops/<folder>/", "/shared/"] which gives the scoop its own sandbox plus shared space. Pass [] to block all writes. Trailing slash recommended.`},allowedCommands:{type:`array`,items:{type:`string`},description:`Shell command allow-list. Omit for unrestricted access to every built-in, custom, and .jsh command (the default). Pass a list of command names to restrict the scoop's shell — e.g. ["echo","cat","grep"] for a read-only text-processing scoop. Pass ["*"] for explicit unrestricted. Applies to pipelines, substitutions, and network commands too.`}},required:[`name`]},execute:async e=>{let{name:t,model:n,prompt:i,visiblePaths:a,writablePaths:s,allowedCommands:c}=e,l=t.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,50)+`-scoop`;try{let e=await o({name:t,folder:l,trigger:`@${l}`,isCone:!1,type:`scoop`,requiresTrigger:!0,assistantLabel:l,addedAt:new Date().toISOString(),config:{...n?{modelId:n}:{},visiblePaths:a??[`/workspace/`],writablePaths:s??[`/scoops/${l}/`,`/shared/`],...c?{allowedCommands:c}:{}},configSchemaVersion:2});if(bx.info(`Scoop created`,{name:t,folder:l}),i&&r){try{await r(e.jid,i)}catch(e){let n=e instanceof Error?e.message:String(e);return bx.error(`Auto-feed failed`,{name:t,error:n}),{content:`Scoop "${t}" created as "${l}" but the initial task could not be sent: ${n}. Use feed_scoop to retry.`,isError:!0}}return{content:`Scoop "${t}" created as "${l}" and task sent. It is now working on it.`}}return{content:`Scoop "${t}" created as "${l}". Use feed_scoop to give it a task.`}}catch(e){return{content:`Failed to create scoop: ${e instanceof Error?e.message:String(e)}`,isError:!0}}}}),s&&u.push({name:`drop_scoop`,description:`Remove a scoop and stop its work. The scoop will be unregistered and its context destroyed.`,inputSchema:{type:`object`,properties:{scoop_name:{type:`string`,description:`The scoop folder name (e.g., "test-scoop"). Use list_scoops to see available scoops.`}},required:[`scoop_name`]},execute:async e=>{let{scoop_name:t}=e,n=i().find(e=>e.folder===t||e.name===t);if(!n)return{content:`Scoop "${t}" not found. Available: ${i().filter(e=>!e.isCone).map(e=>e.folder).join(`, `)}`,isError:!0};if(n.isCone)return{content:`Cannot drop the cone (yourself).`,isError:!0};try{return await s(n.jid),bx.info(`Scoop dropped`,{name:n.name,folder:n.folder}),{content:`Scoop "${n.name}" (${n.folder}) has been dropped.`}}catch(e){return{content:`Failed to drop scoop: ${e instanceof Error?e.message:String(e)}`,isError:!0}}}}),c&&l&&u.push({name:`update_global_memory`,description:`Update the global CLAUDE.md memory file that is shared across all scoops. Use this instead of write_file for /shared/CLAUDE.md.`,inputSchema:{type:`object`,properties:{content:{type:`string`,description:`The new content for the global memory file`}},required:[`content`]},execute:async e=>{let{content:t}=e;try{return await c(t),bx.info(`Global memory updated`),{content:`Global memory updated successfully.`}}catch(e){return{content:`Failed to update global memory: ${e instanceof Error?e.message:String(e)}`,isError:!0}}}})),u}var Sx=t({fetchSecretEnvVars:()=>wx}),Cx=r(`secret-env`);async function wx(){if(typeof chrome<`u`&&chrome?.runtime?.id)return{};try{let e=await fetch(`/api/secrets/masked`);if(!e.ok)return Cx.warn(`Failed to fetch masked secrets`,{status:e.status}),{};let t=await e.json();if(!Array.isArray(t)||t.length===0)return{};let n={};for(let e of t)e.name&&e.maskedValue&&(n[e.name]=e.maskedValue);return Object.keys(n).length>0&&Cx.info(`Loaded masked secrets into shell env`,{count:Object.keys(n).length}),n}catch(e){return Cx.debug(`Could not fetch masked secrets (server may be unavailable)`,{error:e instanceof Error?e.message:String(e)}),{}}}var Tx=r(`scoop-context`);function Ex(e){return/image exceeds.*maximum/i.test(e)||/Could not process image/i.test(e)||/invalid.*image/i.test(e)||/image.*too (large|big)/i.test(e)}var Dx=class{scoop;callbacks;fs=null;shell=null;agent=null;status=`initializing`;isProcessing=!1;disposed=!1;didStreamDeltas=!1;unsubscribe=null;sessionStore=null;sessionId;sessionCreatedAt=0;isRecovering=!1;skillsFs=null;skillsDir=`/workspace/skills`;constructor(e,t,n,r,i){this.scoop=e,this.callbacks=t,this.fs=n,this.sessionStore=r??null,this.skillsFs=i??null,this.sessionId=e.jid}async init(){this.setStatus(`initializing`);try{if(!this.fs)throw Error(`Filesystem not provided`);Tx.info(`Filesystem ready`,{folder:this.scoop.folder}),await this.ensureDirectoryStructure();let e=this.scoop.isCone?`/`:`/scoops/${this.scoop.folder}/workspace`,t=this.callbacks.getBrowserAPI();this.skillsDir=`/workspace/skills`,this.scoop.isCone&&await vx(this.fs,this.skillsDir);let n=this.skillsFs??this.fs,r=await wx();this.shell=new wb({fs:this.fs,cwd:e,env:Object.keys(r).length>0?r:void 0,browserAPI:t,jshDiscoveryFs:this.skillsFs?n:void 0,allowedCommands:this.scoop.config?.allowedCommands,getParentJid:()=>this.scoop.jid}),Tx.info(`WasmShell initialized`,{folder:this.scoop.folder});let i=await mx(n,this.skillsDir),a=xx({scoop:this.scoop,onSendMessage:this.callbacks.onSendMessage,getScoops:this.callbacks.getScoops,getScoopTabState:this.callbacks.getScoopTabState,onFeedScoop:this.callbacks.onFeedScoop,onScoopScoop:this.callbacks.onScoopScoop,onDropScoop:this.callbacks.onDropScoop,onSetGlobalMemory:this.callbacks.setGlobalMemory,getGlobalMemory:this.callbacks.getGlobalMemory}),o=b([...Db(this.fs),Fb(this.shell),...a]),s=this.scoop.isCone?`/workspace/CLAUDE.md`:`/scoops/${this.scoop.folder}/CLAUDE.md`,c=``;try{let e=await this.fs.readFile(s,{encoding:`utf-8`});c=typeof e==`string`?e:new TextDecoder().decode(e)}catch{}let l=await this.callbacks.getGlobalMemory();if(l)try{this.scoop.isCone&&await(`getUnderlyingFS`in this.fs?this.fs.getUnderlyingFS():this.fs).writeFile(`/shared/CLAUDE.md`,l)}catch{}if(!x()){let e=C();throw Error(`No API key configured for provider "${e}"`)}let u=this.scoop.config?.modelId?T(this.scoop.config.modelId):w(),d=this.scoop.isCone?`Cone`:`Scoop "${this.scoop.name}"`;console.log(`[model] ${d} using model: ${u.id} (provider: ${u.provider})`);let f=this.buildSystemPrompt(l,c,i),p=[];if(this.sessionStore)try{let e=await this.sessionStore.load(this.sessionId);e&&(p=e.messages,this.sessionCreatedAt=e.createdAt,Tx.info(`Restored agent session`,{folder:this.scoop.folder,messageCount:p.length}))}catch(e){Tx.error(`Failed to restore agent session`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)}),this.callbacks.onError(`Conversation history could not be restored. Starting fresh.`)}let m=E({model:u,getApiKey:()=>x()??void 0});if(this.disposed)return;this.agent=new N({initialState:{model:u,tools:o,systemPrompt:f,messages:p},getApiKey:()=>x()??void 0,transformContext:m}),this.unsubscribe=this.agent.subscribe(e=>this.handleAgentEvent(e)),this.setStatus(`ready`),Tx.info(`ScoopContext initialized`,{folder:this.scoop.folder,toolCount:o.length})}catch(e){if(this.disposed)return;let t=e instanceof Error?e.message:String(e);Tx.error(`ScoopContext init failed`,{folder:this.scoop.folder,error:t}),this.setStatus(`error`),this.callbacks.onError(`Failed to initialize: ${t}`)}}async prompt(e){if(!this.agent){this.callbacks.onError(`Agent not initialized`);return}let t=this.agent.state?.isStreaming??!1;if(this.isProcessing||t){Tx.info(`Queueing prompt via followUp while processing`,{folder:this.scoop.folder,isProcessing:this.isProcessing,agentIsStreaming:t}),this.agent.followUp({role:`user`,content:[{type:`text`,text:e}],timestamp:Date.now()});return}this.isProcessing=!0,this.didStreamDeltas=!1,this.setStatus(`processing`);try{await this.agent.prompt(e)}catch(e){if(!this.disposed){let t=e instanceof Error?e.message:String(e);Tx.error(`Agent error`,{folder:this.scoop.folder,error:t}),this.callbacks.onError(t)}}finally{this.isProcessing=!1,this.setStatus(`ready`)}}stop(){this.agent?.clearAllQueues?.(),this.agent?.abort?.(),this.isProcessing=!1,this.setStatus(`ready`)}clearMessages(){this.agent&&(this.agent.state.messages=[])}getAgentMessages(){return this.agent?.state?.messages?structuredClone(this.agent.state.messages):[]}getSessionId(){return this.sessionId}getFS(){return this.fs}getShell(){return this.shell}updateModel(){if(!this.agent)return;let e=w();this.agent.state.model=e,Tx.info(`Model updated on running agent`,{folder:this.scoop.folder,model:e.id})}async reloadSkills(){if(!this.agent)return;let e=await mx(this.skillsFs??this.fs,this.skillsDir),t=``,n=this.scoop.isCone?`/workspace/CLAUDE.md`:`/scoops/${this.scoop.folder}/CLAUDE.md`;try{let e=await this.fs.readFile(n,{encoding:`utf-8`});t=typeof e==`string`?e:new TextDecoder().decode(e)}catch{}let r=await this.callbacks.getGlobalMemory(),i=this.buildSystemPrompt(r,t,e);this.agent.state.systemPrompt=i,Tx.info(`Skills reloaded`,{folder:this.scoop.folder,skillCount:e.length})}dispose(){this.disposed=!0,this.agent?.clearAllQueues?.(),this.agent?.abort?.(),this.unsubscribe?.(),this.shell?.dispose(),this.agent=null,this.shell=null,this.fs=null}setStatus(e){this.disposed||(this.status=e,this.callbacks.onStatusChange(e))}handleAgentEvent(e){if(!this.disposed)switch(e.type){case`message_update`:{let t=e.assistantMessageEvent;t.type===`text_delta`&&(this.didStreamDeltas=!0,this.callbacks.onResponse(t.delta,!0));break}case`tool_execution_start`:this.callbacks.onToolStart?.(e.toolName,e.args);break;case`tool_execution_update`:{let t=e.partialResult;for(let n of t?.content??[])n.type===`tool_ui`&&n.requestId&&n.html?this.callbacks.onToolUI?.(e.toolName,n.requestId,n.html):n.type===`tool_ui_done`&&n.requestId&&this.callbacks.onToolUIDone?.(n.requestId);break}case`tool_execution_end`:{let t=e.result,n=[];for(let e of t?.content??[])e.type===`text`&&e.text&&n.push(e.text),e.type===`image`&&e.data&&e.mimeType&&n.push(`<img:data:${e.mimeType};base64,${e.data}>`);this.callbacks.onToolEnd?.(e.toolName,n.join(`
13221
- `),e.isError);break}case`message_end`:if(e.message.role===`assistant`){let t=e.message.content.filter(e=>e.type===`text`).map(e=>e.text).join(``);t&&!this.didStreamDeltas&&this.callbacks.onResponse(t,!1)}break;case`turn_end`:this.callbacks.onResponseDone();break;case`agent_end`:{let t=e.messages;if(t.length>0){let e=t[t.length-1];if(e.role===`assistant`&&e.errorMessage){let n=e.errorMessage;if(!this.isRecovering&&Ex(n)){this.recoverFromImageError(t);break}if(!this.isRecovering&&S(e)){this.recoverFromOverflow(t);break}this.isRecovering=!1,this.callbacks.onError(n)}else this.isRecovering=!1}let n=this.agent?.state?.messages??e.messages;this.sessionStore&&n.length>0&&this.sessionStore.save({id:this.sessionId,messages:n,config:{},createdAt:this.sessionCreatedAt||Date.now(),updatedAt:Date.now()}).catch(e=>{Tx.error(`Failed to save agent session`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)})});break}}}recoverFromOverflow(e){if(this.agent){Tx.warn(`Context overflow detected, attempting recovery`,{folder:this.scoop.folder,messageCount:e.length}),this.isRecovering=`overflow`,this.callbacks.onResponse(`Context window exceeded — recovering by trimming oversized messages...`,!1);try{let t=e.slice(0,-1),n=0;for(let e=t.length-1;e>=0&&n<5;e--){let r=t[e];if(!Array.isArray(r.content))continue;let i=0;for(let e of r.content)e.type===`text`&&e.text&&(i+=e.text.length),e.type===`image`&&e.data&&(i+=e.data.length);if(i>4e4){let a={type:`text`,text:`[Content removed: ${r.role===`toolResult`?`tool result`:r.role} was too large for context window (${Math.round(i/1e3)}K chars). The operation completed but output could not be retained.]`};if(r.role===`assistant`){let n=r.content.filter(e=>e.type===`toolCall`);t[e]={...r,content:[a,...n]}}else t[e]={...r,content:[a]};n++,Tx.info(`Replaced oversized message`,{index:e,role:r.role,size:i,preservedToolCalls:r.role===`assistant`?r.content.filter(e=>e.type===`toolCall`).length:0})}}this.agent.state.messages=t;let r=n>0?`[System: Context overflow recovered. ${n} oversized message(s) were replaced with placeholders to fit within the context window. The conversation continues — you may need to re-read files or re-run commands if their output was removed.]`:`[System: Context overflow recovered. Older messages were trimmed. The conversation continues — compaction will summarize history on the next turn.]`;this.agent.prompt(r).catch(e=>{Tx.error(`Recovery re-prompt failed`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)}),this.isRecovering=!1,this.callbacks.onError(`Context overflow recovery failed: ${e instanceof Error?e.message:String(e)}`)})}catch(e){Tx.error(`Recovery failed`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)}),this.isRecovering=!1,this.callbacks.onError(`Context overflow recovery failed: ${e instanceof Error?e.message:String(e)}`)}}}recoverFromImageError(e){if(this.agent){Tx.warn(`Image processing error detected, attempting recovery`,{folder:this.scoop.folder,messageCount:e.length}),this.isRecovering=`image`,this.callbacks.onResponse(`Image rejected by API — removing problematic images and continuing...`,!1);try{let t=e.slice(0,-1),n=0,r=Math.max(0,t.length-10);for(let e=t.length-1;e>=r;e--){let r=t[e];if(!Array.isArray(r.content)||!r.content.some(e=>e.type===`image`))continue;let i=r.content.filter(e=>e.type!==`image`);i.length===0?t[e]={...r,content:[{type:`text`,text:`[Image removed: rejected by API]`}]}:t[e]={...r,content:i},n++}this.agent.state.messages=t;let i=`[System: An image was rejected by the API and has been removed from the conversation (${n} message(s) affected). The conversation continues without the image.]`;this.agent.prompt(i).catch(e=>{Tx.error(`Image recovery re-prompt failed`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)}),this.isRecovering=!1,this.callbacks.onError(`Image error recovery failed: ${e instanceof Error?e.message:String(e)}`)})}catch(e){Tx.error(`Image recovery failed`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)}),this.isRecovering=!1,this.callbacks.onError(`Image error recovery failed: ${e instanceof Error?e.message:String(e)}`)}}}async ensureDirectoryStructure(){if(!this.fs)return;let e=this.scoop.isCone?[`/workspace`,`/shared`,`/scoops`,`/home`,`/tmp`,`/mnt`]:[`/scoops/${this.scoop.folder}`,`/scoops/${this.scoop.folder}/workspace`,`/scoops/${this.scoop.folder}/home`,`/scoops/${this.scoop.folder}/tmp`,`/shared`];for(let t of e)try{await this.fs.mkdir(t,{recursive:!0})}catch{}let t=this.scoop.isCone?`/workspace/CLAUDE.md`:`/scoops/${this.scoop.folder}/CLAUDE.md`;try{await this.fs.readFile(t)}catch{let e=`# ${this.scoop.assistantLabel} Memory
13219
+ ---`}async function yx(e,t=`/workspace/skills`){let n=fx();for(let[r,i]of Object.entries(n)){let n=r.slice(18),a=n.startsWith(`/workspace/skills`),o=n.startsWith(`/workspace/scripts`);if(!a&&!o)continue;let s=n;a&&t!==`/workspace/skills`&&(s=n.replace(`/workspace/skills`,t)),o&&t!==`/workspace/skills`&&(s=t.replace(`/workspace/skills`,``)+n);try{await e.stat(s)}catch{let t=s.substring(0,s.lastIndexOf(`/`));try{await e.mkdir(t,{recursive:!0})}catch{}await e.writeFile(s,i),cx.info(`Created default file`,{path:s})}}}async function bx(e){let t=fx();for(let[n,r]of Object.entries(t)){let t=n.slice(18);if(t.startsWith(`/shared/`))try{await e.stat(t)}catch{let n=t.substring(0,t.lastIndexOf(`/`));try{await e.mkdir(n,{recursive:!0})}catch{}await e.writeFile(t,r),cx.info(`Created default shared file`,{path:t})}}}var xx=r(`scoop-management-tools`);function Sx(e){let{scoop:t,onSendMessage:n,onFeedScoop:r,getScoops:i,getScoopTabState:a,onScoopScoop:o,onDropScoop:s,onSetGlobalMemory:c,getGlobalMemory:l}=e,u=[];return u.push({name:`send_message`,description:`Send a progress message while still working. Your final output is also sent.`,inputSchema:{type:`object`,properties:{text:{type:`string`,description:`The message text to send`},sender:{type:`string`,description:`Optional sender name/role (e.g., "Researcher"). Defaults to assistant name.`}},required:[`text`]},execute:async e=>{let{text:r,sender:i}=e;return n(r,i),xx.info(`Message sent`,{scoopFolder:t.folder,textLength:r.length}),{content:`Message sent.`}}}),t.isCone&&r&&u.push({name:`feed_scoop`,description:`Give a scoop a task. Provide a complete, self-contained prompt — the scoop has no access to your conversation. You'll be notified when it finishes.`,inputSchema:{type:`object`,properties:{scoop_name:{type:`string`,description:`The scoop folder name (e.g., "test-scoop"). Use list_scoops to see available scoops.`},prompt:{type:`string`,description:`Complete, self-contained instructions for the scoop. Include ALL context — the scoop cannot see your conversation.`}},required:[`scoop_name`,`prompt`]},execute:async e=>{let{scoop_name:t,prompt:n}=e,a=i().find(e=>e.folder===t||e.name===t);if(!a)return{content:`Scoop "${t}" not found. Available: ${i().filter(e=>!e.isCone).map(e=>e.folder).join(`, `)}`,isError:!0};if(a.isCone)return{content:`Cannot feed the cone (yourself).`,isError:!0};try{return await r(a.jid,n),xx.info(`Fed scoop`,{target:a.folder,promptLength:n.length}),{content:`Task sent to ${a.folder}. You will be notified when it completes.`}}catch(e){return{content:`Failed to feed scoop: ${e instanceof Error?e.message:String(e)}`,isError:!0}}}}),t.isCone&&(u.push({name:`list_scoops`,description:`List all registered scoops.`,inputSchema:{type:`object`,properties:{}},execute:async()=>{let e=i();return e.length===0?{content:`No scoops registered.`}:{content:`Registered scoops:\n${e.map(e=>{let t=a?.(e.jid),n=t?.status??`unknown`,r=t?.lastActivity?new Date(t.lastActivity).toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`,hour12:!0}):``,i=r?` — ${n} (since ${r})`:` — ${n}`;return e.isCone?`- ${e.assistantLabel} (${e.folder}) [CONE]${i}`:`- ${e.name} (${e.folder})${i}`}).join(`
13220
+ `)}`}}}),o&&u.push({name:`scoop_scoop`,description:`Create a new scoop. Optionally specify a model, a prompt, and per-scoop sandbox shape (visible/writable paths + command allow-list). If prompt is provided, the scoop starts working immediately after creation (no separate feed_scoop needed).`,inputSchema:{type:`object`,properties:{name:{type:`string`,description:`Display name for the scoop (e.g., "hero-block")`},model:{type:`string`,description:`Model ID for this scoop (e.g., "claude-sonnet-4-6"). If omitted, uses the same model as the cone.`},prompt:{type:`string`,description:`Task prompt for the scoop. If provided, the scoop starts working immediately after creation.`},visiblePaths:{type:`array`,items:{type:`string`},description:`VFS paths the scoop can READ (not write). Pure replace — what you set is what you get. Omit to use the default ["/workspace/"] which exposes the shared skills tree. Pass [] for no extra read-only paths. Note: the scoop's writablePaths are always readable too, so a true read-nothing sandbox also requires writablePaths: []. Mounts remain readable regardless. Trailing slash recommended (e.g. "/shared/data/").`},writablePaths:{type:`array`,items:{type:`string`},description:`VFS paths the scoop can READ AND WRITE. Pure replace. Omit to use the default ["/scoops/<folder>/", "/shared/"] which gives the scoop its own sandbox plus shared space. Pass [] to block all writes. Trailing slash recommended.`},allowedCommands:{type:`array`,items:{type:`string`},description:`Shell command allow-list. Omit for unrestricted access to every built-in, custom, and .jsh command (the default). Pass a list of command names to restrict the scoop's shell — e.g. ["echo","cat","grep"] for a read-only text-processing scoop. Pass ["*"] for explicit unrestricted. Applies to pipelines, substitutions, and network commands too.`}},required:[`name`]},execute:async e=>{let{name:t,model:n,prompt:i,visiblePaths:a,writablePaths:s,allowedCommands:c}=e,l=t.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,50)+`-scoop`;try{let e=await o({name:t,folder:l,trigger:`@${l}`,isCone:!1,type:`scoop`,requiresTrigger:!0,assistantLabel:l,addedAt:new Date().toISOString(),config:{...n?{modelId:n}:{},visiblePaths:a??[`/workspace/`],writablePaths:s??[`/scoops/${l}/`,`/shared/`],...c?{allowedCommands:c}:{}},configSchemaVersion:2});if(xx.info(`Scoop created`,{name:t,folder:l}),i&&r){try{await r(e.jid,i)}catch(e){let n=e instanceof Error?e.message:String(e);return xx.error(`Auto-feed failed`,{name:t,error:n}),{content:`Scoop "${t}" created as "${l}" but the initial task could not be sent: ${n}. Use feed_scoop to retry.`,isError:!0}}return{content:`Scoop "${t}" created as "${l}" and task sent. It is now working on it.`}}return{content:`Scoop "${t}" created as "${l}". Use feed_scoop to give it a task.`}}catch(e){return{content:`Failed to create scoop: ${e instanceof Error?e.message:String(e)}`,isError:!0}}}}),s&&u.push({name:`drop_scoop`,description:`Remove a scoop and stop its work. The scoop will be unregistered and its context destroyed.`,inputSchema:{type:`object`,properties:{scoop_name:{type:`string`,description:`The scoop folder name (e.g., "test-scoop"). Use list_scoops to see available scoops.`}},required:[`scoop_name`]},execute:async e=>{let{scoop_name:t}=e,n=i().find(e=>e.folder===t||e.name===t);if(!n)return{content:`Scoop "${t}" not found. Available: ${i().filter(e=>!e.isCone).map(e=>e.folder).join(`, `)}`,isError:!0};if(n.isCone)return{content:`Cannot drop the cone (yourself).`,isError:!0};try{return await s(n.jid),xx.info(`Scoop dropped`,{name:n.name,folder:n.folder}),{content:`Scoop "${n.name}" (${n.folder}) has been dropped.`}}catch(e){return{content:`Failed to drop scoop: ${e instanceof Error?e.message:String(e)}`,isError:!0}}}}),c&&l&&u.push({name:`update_global_memory`,description:`Update the global CLAUDE.md memory file that is shared across all scoops. Use this instead of write_file for /shared/CLAUDE.md.`,inputSchema:{type:`object`,properties:{content:{type:`string`,description:`The new content for the global memory file`}},required:[`content`]},execute:async e=>{let{content:t}=e;try{return await c(t),xx.info(`Global memory updated`),{content:`Global memory updated successfully.`}}catch(e){return{content:`Failed to update global memory: ${e instanceof Error?e.message:String(e)}`,isError:!0}}}})),u}var Cx=t({fetchSecretEnvVars:()=>Tx}),wx=r(`secret-env`);async function Tx(){if(typeof chrome<`u`&&chrome?.runtime?.id)return{};try{let e=await fetch(`/api/secrets/masked`);if(!e.ok)return wx.warn(`Failed to fetch masked secrets`,{status:e.status}),{};let t=await e.json();if(!Array.isArray(t)||t.length===0)return{};let n={};for(let e of t)e.name&&e.maskedValue&&(n[e.name]=e.maskedValue);return Object.keys(n).length>0&&wx.info(`Loaded masked secrets into shell env`,{count:Object.keys(n).length}),n}catch(e){return wx.debug(`Could not fetch masked secrets (server may be unavailable)`,{error:e instanceof Error?e.message:String(e)}),{}}}var Ex=r(`scoop-context`);function Dx(e){return/image exceeds.*maximum/i.test(e)||/Could not process image/i.test(e)||/invalid.*image/i.test(e)||/image.*too (large|big)/i.test(e)}var Ox=class{scoop;callbacks;fs=null;shell=null;agent=null;status=`initializing`;isProcessing=!1;disposed=!1;didStreamDeltas=!1;unsubscribe=null;sessionStore=null;sessionId;sessionCreatedAt=0;isRecovering=!1;skillsFs=null;skillsDir=`/workspace/skills`;constructor(e,t,n,r,i){this.scoop=e,this.callbacks=t,this.fs=n,this.sessionStore=r??null,this.skillsFs=i??null,this.sessionId=e.jid}async init(){this.setStatus(`initializing`);try{if(!this.fs)throw Error(`Filesystem not provided`);Ex.info(`Filesystem ready`,{folder:this.scoop.folder}),await this.ensureDirectoryStructure();let e=this.scoop.isCone?`/`:`/scoops/${this.scoop.folder}/workspace`,t=this.callbacks.getBrowserAPI();this.skillsDir=`/workspace/skills`,this.scoop.isCone&&await yx(this.fs,this.skillsDir);let n=this.skillsFs??this.fs,r=await Tx();this.shell=new Tb({fs:this.fs,cwd:e,env:Object.keys(r).length>0?r:void 0,browserAPI:t,jshDiscoveryFs:this.skillsFs?n:void 0,allowedCommands:this.scoop.config?.allowedCommands,getParentJid:()=>this.scoop.jid}),Ex.info(`WasmShell initialized`,{folder:this.scoop.folder});let i=await hx(n,this.skillsDir),a=Sx({scoop:this.scoop,onSendMessage:this.callbacks.onSendMessage,getScoops:this.callbacks.getScoops,getScoopTabState:this.callbacks.getScoopTabState,onFeedScoop:this.callbacks.onFeedScoop,onScoopScoop:this.callbacks.onScoopScoop,onDropScoop:this.callbacks.onDropScoop,onSetGlobalMemory:this.callbacks.setGlobalMemory,getGlobalMemory:this.callbacks.getGlobalMemory}),o=b([...Ob(this.fs),Ib(this.shell),...a]),s=this.scoop.isCone?`/workspace/CLAUDE.md`:`/scoops/${this.scoop.folder}/CLAUDE.md`,c=``;try{let e=await this.fs.readFile(s,{encoding:`utf-8`});c=typeof e==`string`?e:new TextDecoder().decode(e)}catch{}let l=await this.callbacks.getGlobalMemory();if(l)try{this.scoop.isCone&&await(`getUnderlyingFS`in this.fs?this.fs.getUnderlyingFS():this.fs).writeFile(`/shared/CLAUDE.md`,l)}catch{}if(!x()){let e=C();throw Error(`No API key configured for provider "${e}"`)}let u=this.scoop.config?.modelId?T(this.scoop.config.modelId):w(),d=this.scoop.isCone?`Cone`:`Scoop "${this.scoop.name}"`;console.log(`[model] ${d} using model: ${u.id} (provider: ${u.provider})`);let f=this.buildSystemPrompt(l,c,i),p=[];if(this.sessionStore)try{let e=await this.sessionStore.load(this.sessionId);e&&(p=e.messages,this.sessionCreatedAt=e.createdAt,Ex.info(`Restored agent session`,{folder:this.scoop.folder,messageCount:p.length}))}catch(e){Ex.error(`Failed to restore agent session`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)}),this.callbacks.onError(`Conversation history could not be restored. Starting fresh.`)}let m=E({model:u,getApiKey:()=>x()??void 0});if(this.disposed)return;this.agent=new N({initialState:{model:u,tools:o,systemPrompt:f,messages:p},getApiKey:()=>x()??void 0,transformContext:m}),this.unsubscribe=this.agent.subscribe(e=>this.handleAgentEvent(e)),this.setStatus(`ready`),Ex.info(`ScoopContext initialized`,{folder:this.scoop.folder,toolCount:o.length})}catch(e){if(this.disposed)return;let t=e instanceof Error?e.message:String(e);Ex.error(`ScoopContext init failed`,{folder:this.scoop.folder,error:t}),this.setStatus(`error`),this.callbacks.onError(`Failed to initialize: ${t}`)}}async prompt(e){if(!this.agent){this.callbacks.onError(`Agent not initialized`);return}let t=this.agent.state?.isStreaming??!1;if(this.isProcessing||t){Ex.info(`Queueing prompt via followUp while processing`,{folder:this.scoop.folder,isProcessing:this.isProcessing,agentIsStreaming:t}),this.agent.followUp({role:`user`,content:[{type:`text`,text:e}],timestamp:Date.now()});return}this.isProcessing=!0,this.didStreamDeltas=!1,this.setStatus(`processing`);try{await this.agent.prompt(e)}catch(e){if(!this.disposed){let t=e instanceof Error?e.message:String(e);Ex.error(`Agent error`,{folder:this.scoop.folder,error:t}),this.callbacks.onError(t)}}finally{this.isProcessing=!1,this.setStatus(`ready`)}}stop(){this.agent?.clearAllQueues?.(),this.agent?.abort?.(),this.isProcessing=!1,this.setStatus(`ready`)}clearMessages(){this.agent&&(this.agent.state.messages=[])}getAgentMessages(){return this.agent?.state?.messages?structuredClone(this.agent.state.messages):[]}getSessionId(){return this.sessionId}getFS(){return this.fs}getShell(){return this.shell}updateModel(){if(!this.agent)return;let e=w();this.agent.state.model=e,Ex.info(`Model updated on running agent`,{folder:this.scoop.folder,model:e.id})}async reloadSkills(){if(!this.agent)return;let e=await hx(this.skillsFs??this.fs,this.skillsDir),t=``,n=this.scoop.isCone?`/workspace/CLAUDE.md`:`/scoops/${this.scoop.folder}/CLAUDE.md`;try{let e=await this.fs.readFile(n,{encoding:`utf-8`});t=typeof e==`string`?e:new TextDecoder().decode(e)}catch{}let r=await this.callbacks.getGlobalMemory(),i=this.buildSystemPrompt(r,t,e);this.agent.state.systemPrompt=i,Ex.info(`Skills reloaded`,{folder:this.scoop.folder,skillCount:e.length})}dispose(){this.disposed=!0,this.agent?.clearAllQueues?.(),this.agent?.abort?.(),this.unsubscribe?.(),this.shell?.dispose(),this.agent=null,this.shell=null,this.fs=null}setStatus(e){this.disposed||(this.status=e,this.callbacks.onStatusChange(e))}handleAgentEvent(e){if(!this.disposed)switch(e.type){case`message_update`:{let t=e.assistantMessageEvent;t.type===`text_delta`&&(this.didStreamDeltas=!0,this.callbacks.onResponse(t.delta,!0));break}case`tool_execution_start`:this.callbacks.onToolStart?.(e.toolName,e.args);break;case`tool_execution_update`:{let t=e.partialResult;for(let n of t?.content??[])n.type===`tool_ui`&&n.requestId&&n.html?this.callbacks.onToolUI?.(e.toolName,n.requestId,n.html):n.type===`tool_ui_done`&&n.requestId&&this.callbacks.onToolUIDone?.(n.requestId);break}case`tool_execution_end`:{let t=e.result,n=[];for(let e of t?.content??[])e.type===`text`&&e.text&&n.push(e.text),e.type===`image`&&e.data&&e.mimeType&&n.push(`<img:data:${e.mimeType};base64,${e.data}>`);this.callbacks.onToolEnd?.(e.toolName,n.join(`
13221
+ `),e.isError);break}case`message_end`:if(e.message.role===`assistant`){let t=e.message.content.filter(e=>e.type===`text`).map(e=>e.text).join(``);t&&!this.didStreamDeltas&&this.callbacks.onResponse(t,!1)}break;case`turn_end`:this.callbacks.onResponseDone();break;case`agent_end`:{let t=e.messages;if(t.length>0){let e=t[t.length-1];if(e.role===`assistant`&&e.errorMessage){let n=e.errorMessage;if(!this.isRecovering&&Dx(n)){this.recoverFromImageError(t);break}if(!this.isRecovering&&S(e)){this.recoverFromOverflow(t);break}this.isRecovering=!1,this.callbacks.onError(n)}else this.isRecovering=!1}let n=this.agent?.state?.messages??e.messages;this.sessionStore&&n.length>0&&this.sessionStore.save({id:this.sessionId,messages:n,config:{},createdAt:this.sessionCreatedAt||Date.now(),updatedAt:Date.now()}).catch(e=>{Ex.error(`Failed to save agent session`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)})});break}}}recoverFromOverflow(e){if(this.agent){Ex.warn(`Context overflow detected, attempting recovery`,{folder:this.scoop.folder,messageCount:e.length}),this.isRecovering=`overflow`,this.callbacks.onResponse(`Context window exceeded — recovering by trimming oversized messages...`,!1);try{let t=e.slice(0,-1),n=0;for(let e=t.length-1;e>=0&&n<5;e--){let r=t[e];if(!Array.isArray(r.content))continue;let i=0;for(let e of r.content)e.type===`text`&&e.text&&(i+=e.text.length),e.type===`image`&&e.data&&(i+=e.data.length);if(i>4e4){let a={type:`text`,text:`[Content removed: ${r.role===`toolResult`?`tool result`:r.role} was too large for context window (${Math.round(i/1e3)}K chars). The operation completed but output could not be retained.]`};if(r.role===`assistant`){let n=r.content.filter(e=>e.type===`toolCall`);t[e]={...r,content:[a,...n]}}else t[e]={...r,content:[a]};n++,Ex.info(`Replaced oversized message`,{index:e,role:r.role,size:i,preservedToolCalls:r.role===`assistant`?r.content.filter(e=>e.type===`toolCall`).length:0})}}this.agent.state.messages=t;let r=n>0?`[System: Context overflow recovered. ${n} oversized message(s) were replaced with placeholders to fit within the context window. The conversation continues — you may need to re-read files or re-run commands if their output was removed.]`:`[System: Context overflow recovered. Older messages were trimmed. The conversation continues — compaction will summarize history on the next turn.]`;this.agent.prompt(r).catch(e=>{Ex.error(`Recovery re-prompt failed`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)}),this.isRecovering=!1,this.callbacks.onError(`Context overflow recovery failed: ${e instanceof Error?e.message:String(e)}`)})}catch(e){Ex.error(`Recovery failed`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)}),this.isRecovering=!1,this.callbacks.onError(`Context overflow recovery failed: ${e instanceof Error?e.message:String(e)}`)}}}recoverFromImageError(e){if(this.agent){Ex.warn(`Image processing error detected, attempting recovery`,{folder:this.scoop.folder,messageCount:e.length}),this.isRecovering=`image`,this.callbacks.onResponse(`Image rejected by API — removing problematic images and continuing...`,!1);try{let t=e.slice(0,-1),n=0,r=Math.max(0,t.length-10);for(let e=t.length-1;e>=r;e--){let r=t[e];if(!Array.isArray(r.content)||!r.content.some(e=>e.type===`image`))continue;let i=r.content.filter(e=>e.type!==`image`);i.length===0?t[e]={...r,content:[{type:`text`,text:`[Image removed: rejected by API]`}]}:t[e]={...r,content:i},n++}this.agent.state.messages=t;let i=`[System: An image was rejected by the API and has been removed from the conversation (${n} message(s) affected). The conversation continues without the image.]`;this.agent.prompt(i).catch(e=>{Ex.error(`Image recovery re-prompt failed`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)}),this.isRecovering=!1,this.callbacks.onError(`Image error recovery failed: ${e instanceof Error?e.message:String(e)}`)})}catch(e){Ex.error(`Image recovery failed`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)}),this.isRecovering=!1,this.callbacks.onError(`Image error recovery failed: ${e instanceof Error?e.message:String(e)}`)}}}async ensureDirectoryStructure(){if(!this.fs)return;let e=this.scoop.isCone?[`/workspace`,`/shared`,`/scoops`,`/home`,`/tmp`,`/mnt`]:[`/scoops/${this.scoop.folder}`,`/scoops/${this.scoop.folder}/workspace`,`/scoops/${this.scoop.folder}/home`,`/scoops/${this.scoop.folder}/tmp`,`/shared`];for(let t of e)try{await this.fs.mkdir(t,{recursive:!0})}catch{}let t=this.scoop.isCone?`/workspace/CLAUDE.md`:`/scoops/${this.scoop.folder}/CLAUDE.md`;try{await this.fs.readFile(t)}catch{let e=`# ${this.scoop.assistantLabel} Memory
13222
13222
 
13223
13223
  ${this.scoop.isCone?`Role: Cone (main orchestrator)`:`Scoop: ${this.scoop.name}`}
13224
13224
  Folder: ${this.scoop.folder}
@@ -13229,7 +13229,7 @@ Created: ${new Date().toISOString()}
13229
13229
 
13230
13230
  ## Context
13231
13231
  (Add important context here)
13232
- `;try{await this.fs.writeFile(t,e)}catch(e){if(e?.code===`EACCES`)Tx.debug(`Skipping default memory write (sandbox is read-only)`,{folder:this.scoop.folder,path:t});else throw e}}}buildSystemPrompt(e,t,n){let r=this.scoop.config?.assistantName||this.scoop.assistantLabel,i=`# ${r}
13232
+ `;try{await this.fs.writeFile(t,e)}catch(e){if(e?.code===`EACCES`)Ex.debug(`Skipping default memory write (sandbox is read-only)`,{folder:this.scoop.folder,path:t});else throw e}}}buildSystemPrompt(e,t,n){let r=this.scoop.config?.assistantName||this.scoop.assistantLabel,i=`# ${r}
13233
13233
 
13234
13234
  You are ${r}, ${this.scoop.isCone?`the main assistant (cone)`:`a scoop assistant`} in SLICC (Self-Licking Ice Cream Cone).
13235
13235
 
@@ -13297,11 +13297,11 @@ ${e}
13297
13297
  ---
13298
13298
  ${this.scoop.isCone?`CONE`:`SCOOP`} MEMORY (${this.scoop.name}):
13299
13299
  ${t}
13300
- ---`);let a=_x(n);return a&&(i+=a),i}},Ox=r(`scheduler`),kx=class{callbacks;pollInterval=null;running=!1;constructor(e){this.callbacks=e}start(){this.running||(this.running=!0,this.pollInterval=window.setInterval(()=>this.checkTasks(),6e4),this.checkTasks(),Ox.info(`Scheduler started`))}stop(){this.pollInterval&&=(clearInterval(this.pollInterval),null),this.running=!1,Ox.info(`Scheduler stopped`)}async createTask(e,t,n,r){let i={id:`task-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,groupFolder:e,prompt:t,scheduleType:n,scheduleValue:r,status:`active`,nextRun:this.calculateNextRun(n,r),lastRun:null,createdAt:new Date().toISOString()};return await Le(i),Ox.info(`Task created`,{id:i.id,groupFolder:e,scheduleType:n}),i}async updateTask(e,t){let n=await De(e);if(!n)return null;let r={...n,...t};return(t.scheduleType||t.scheduleValue)&&(r.nextRun=this.calculateNextRun(r.scheduleType,r.scheduleValue)),await Le(r),Ox.info(`Task updated`,{id:e,updates:Object.keys(t)}),r}async pauseTask(e){return await this.updateTask(e,{status:`paused`})!==null}async resumeTask(e){return await De(e)?(await this.updateTask(e,{status:`active`}),!0):!1}async deleteTask(e){return await De(e)?(await ye(e),Ox.info(`Task deleted`,{id:e}),!0):!1}async getTasksByScoop(e){return(await Ee()).filter(t=>t.groupFolder===e)}async getAllTasks(){return Ee()}async checkTasks(){let e=await Ee(),t=new Date;for(let n of e)n.status===`active`&&n.nextRun&&(new Date(n.nextRun)>t||await this.runTask(n))}async runTask(e){let t=this.callbacks.getScoop(e.groupFolder);if(!t){Ox.warn(`Task scoop not found`,{taskId:e.id,groupFolder:e.groupFolder});return}Ox.info(`Running task`,{id:e.id,groupFolder:e.groupFolder});try{let n=new Date().toISOString(),r=this.calculateNextRun(e.scheduleType,e.scheduleValue),i=e.scheduleType===`once`?`completed`:e.status;await Le({...e,lastRun:n,nextRun:r,status:i}),await this.callbacks.onTaskRun(e,t),Ox.info(`Task completed`,{id:e.id})}catch(t){Ox.error(`Task execution failed`,{id:e.id,error:t instanceof Error?t.message:String(t)})}}calculateNextRun(e,t){let n=new Date;switch(e){case`cron`:return this.getNextCronTime(t,n)?.toISOString()??null;case`interval`:{let e=parseInt(t,10);return isNaN(e)||e<=0?null:new Date(n.getTime()+e).toISOString()}case`once`:return new Date(t)>n?t:null;default:return null}}getNextCronTime(e,t){let n=e.trim().split(/\s+/);if(n.length!==5)return null;let[r,i,a,o,s]=n,c=new Date(t);c.setSeconds(0),c.setMilliseconds(0),c.setMinutes(c.getMinutes()+1);for(let e=0;e<527040;e++){if(this.cronMatches(c,r,i,a,o,s))return c;c.setMinutes(c.getMinutes()+1)}return null}cronMatches(e,t,n,r,i,a){return this.cronFieldMatches(e.getMinutes(),t)&&this.cronFieldMatches(e.getHours(),n)&&this.cronFieldMatches(e.getDate(),r)&&this.cronFieldMatches(e.getMonth()+1,i)&&this.cronFieldMatches(e.getDay(),a)}cronFieldMatches(e,t){if(t===`*`)return!0;if(t.includes(`,`))return t.split(`,`).some(t=>this.cronFieldMatches(e,t.trim()));if(t.includes(`-`)){let[n,r]=t.split(`-`).map(e=>parseInt(e,10));return e>=n&&e<=r}if(t.includes(`/`)){let[n,r]=t.split(`/`),i=parseInt(r,10);if(n===`*`)return e%i===0;let a=parseInt(n,10);return e>=a&&(e-a)%i===0}return parseInt(t,10)===e}},Ax=t({LickManager:()=>Mx,buildActiveLicksError:()=>Nx,getLickManager:()=>Fx}),jx=r(`lick-manager`),Mx=class{webhooks=new Map;crontasks=new Map;cronInterval=null;eventHandler=null;async init(){await we();let e=await Pe();for(let t of e)this.webhooks.set(t.id,t);jx.info(`Loaded webhooks`,{count:this.webhooks.size});let t=await Me();for(let e of t)this.crontasks.set(e.id,e);jx.info(`Loaded crontasks`,{count:this.crontasks.size}),this.cronInterval=setInterval(()=>this.runCronScheduler(),6e4),jx.info(`Cron scheduler started`)}dispose(){this.cronInterval&&=(clearInterval(this.cronInterval),null)}setEventHandler(e){this.eventHandler=e}emitEvent(e){jx.info(`External lick event`,{type:e.type,target:e.targetScoop}),this.eventHandler?.(e)}async createWebhook(e,t,n){let r=this.generateId(),i={id:r,name:e,createdAt:new Date().toISOString(),filter:n,scoop:t};return n&&this.compileFilter(n,!0),this.webhooks.set(r,i),await be(i),jx.info(`Webhook created`,{id:r,name:e,scoop:t}),i}async deleteWebhook(e){return this.webhooks.has(e)?(this.webhooks.delete(e),await ke(e),jx.info(`Webhook deleted`,{id:e}),!0):!1}listWebhooks(){return Array.from(this.webhooks.values())}getWebhook(e){return this.webhooks.get(e)}handleWebhookEvent(e,t,n){let r=this.webhooks.get(e);if(!r){jx.warn(`Webhook not found`,{webhookId:e});return}let i={type:`webhook`,webhookId:e,webhookName:r.name,targetScoop:r.scoop,timestamp:new Date().toISOString(),headers:t,body:n};if(r.filter)try{let t=this.compileFilter(r.filter,!0)(i);if(t===!1){jx.debug(`Webhook event dropped by filter`,{webhookId:e,name:r.name});return}typeof t==`object`&&t&&(i=t)}catch(t){jx.error(`Webhook filter error`,{webhookId:e,error:t instanceof Error?t.message:String(t)})}jx.info(`Webhook event received`,{webhookId:e,name:r.name,targetScoop:r.scoop}),this.eventHandler?.(i)}async createCronTask(e,t,n,r){let i=this.getNextCronTime(t,new Date);if(!i)throw Error(`Invalid cron expression`);r&&this.compileFilter(r,!1);let a=this.generateId(),o={id:a,name:e,cron:t,scoop:n,filter:r,nextRun:i.toISOString(),lastRun:null,status:`active`,createdAt:new Date().toISOString()};return this.crontasks.set(a,o),await Ce(o),jx.info(`Cron task created`,{id:a,name:e,cron:t,scoop:n}),o}async deleteCronTask(e){return this.crontasks.has(e)?(this.crontasks.delete(e),await Oe(e),jx.info(`Cron task deleted`,{id:e}),!0):!1}listCronTasks(){return Array.from(this.crontasks.values())}getCronTask(e){return this.crontasks.get(e)}getLicksForScoop(e,t){let n=n=>n===e||n===t||`${n}-scoop`===t;return{webhooks:Array.from(this.webhooks.values()).filter(e=>n(e.scoop)),cronTasks:Array.from(this.crontasks.values()).filter(e=>n(e.scoop))}}async runCronScheduler(){let e=new Date;for(let t of this.crontasks.values()){if(t.status!==`active`||!t.nextRun||new Date(t.nextRun)>e)continue;let n={time:e.toISOString()};if(t.filter)try{let r=this.compileFilter(t.filter,!1)(null);if(r===!1){jx.debug(`Cron task skipped by filter`,{id:t.id,name:t.name}),t.nextRun=this.getNextCronTime(t.cron,e)?.toISOString()??null,t.lastRun=e.toISOString(),await Ce(t);continue}typeof r==`object`&&r&&(n=r)}catch(e){jx.error(`Cron filter error`,{id:t.id,error:e instanceof Error?e.message:String(e)})}let r={type:`cron`,cronId:t.id,cronName:t.name,targetScoop:t.scoop,timestamp:e.toISOString(),body:n};jx.info(`Cron task running`,{id:t.id,name:t.name}),this.eventHandler?.(r),t.nextRun=this.getNextCronTime(t.cron,e)?.toISOString()??null,t.lastRun=e.toISOString(),await Ce(t)}}generateId(){let e=``;for(let t=0;t<12;t++)e+=`abcdefghijklmnopqrstuvwxyz0123456789`[Math.floor(Math.random()*36)];return e}compileFilter(e,t){try{return t?Function(`event`,`return (${e})(event);`):Function(`return (${e})();`)}catch(e){throw Error(`Invalid filter function: ${e instanceof Error?e.message:String(e)}`)}}getNextCronTime(e,t){let n=e.trim().split(/\s+/);if(n.length!==5)return null;let[r,i,a,o,s]=n,c=new Date(t);c.setSeconds(0),c.setMilliseconds(0),c.setMinutes(c.getMinutes()+1);let l=(e,t)=>{if(t===`*`)return!0;if(t.includes(`,`))return t.split(`,`).some(t=>l(e,t.trim()));if(t.includes(`-`)){let[n,r]=t.split(`-`).map(e=>parseInt(e,10));return e>=n&&e<=r}if(t.includes(`/`)){let[n,r]=t.split(`/`),i=parseInt(r,10);if(n===`*`)return e%i===0;let a=parseInt(n,10);return e>=a&&(e-a)%i===0}return parseInt(t,10)===e};for(let e=0;e<527040;e++){if(l(c.getMinutes(),r)&&l(c.getHours(),i)&&l(c.getDate(),a)&&l(c.getMonth()+1,o)&&l(c.getDay(),s))return c;c.setMinutes(c.getMinutes()+1)}return null}};function Nx(e,t,n){if(t.length===0&&n.length===0)return null;let r=[];t.length>0&&r.push(`${t.length} active webhook${t.length>1?`s`:``}`),n.length>0&&r.push(`${n.length} active cron task${n.length>1?`s`:``}`);let i=[...t.map(e=>` webhook delete ${e.id}`),...n.map(e=>` crontask delete ${e.id}`)].join(`
13301
- `);return Error(`Cannot remove scoop '${e}': it has ${r.join(` and `)}. Unregister them first:\n${i}`)}var Px=null;function Fx(){return Px||=new Mx,Px}var Q=r(`orchestrator`),Ix=120*1e3,Lx=class{scoops=new Map;tabs=new Map;contexts=new Map;messageQueues=new Map;lastAgentTimestamp=new Map;container;callbacks;config;pollInterval=null;scheduler=null;globalMemoryCache=``;sharedFs=null;scoopResponseBuffer=new Map;lickManager=null;sessionStore=null;fsWatcher=null;idleTimers=new Map;droppedScoopCosts=[];scoopObservers=new Map;constructor(e,t,n={name:`sliccy`,triggerPattern:/^@sliccy\b/i}){this.container=e,this.callbacks=t,this.config=n}async init(){await we(),this.sharedFs=await I.create({dbName:`slicc-fs`}),this.sessionStore=new M,this.fsWatcher=new ce,this.sharedFs.setWatcher(this.fsWatcher),globalThis.__slicc_fs_watcher=this.fsWatcher,await this.ensureRootStructure();let e=await xe();for(let t of Object.values(e)){t.isCone&&(t.trigger=void 0,t.requiresTrigger=!1,t.assistantLabel=t.assistantLabel||`sliccy`),this.migrateScoopConfig(t),this.scoops.set(t.jid,t),this.messageQueues.set(t.jid,[]);let e=await Ae(`lastAgentTs_${t.jid}`);e&&this.lastAgentTimestamp.set(t.jid,e)}await this.ensureGlobalMemory(),this.scheduler=new kx({onTaskRun:async(e,t)=>{Q.info(`Running scheduled task`,{taskId:e.id,scoop:t.name}),await this.sendPrompt(t.jid,`[SCHEDULED TASK]\n\n${e.prompt}`,`scheduler`,`Scheduled Task`)},getScoop:e=>{for(let t of this.scoops.values())if(t.folder===e)return t}}),this.scheduler.start(),Q.info(`Orchestrator initialized`,{scoopCount:this.scoops.size});for(let e of this.scoops.values())await this.createScoopTab(e.jid);He(()=>this.getSessionCosts()),this.startMessageLoop()}migrateScoopConfig(e){if(e.isCone)return;let t=e.configSchemaVersion??0;t>=2||(t<1&&(e.config={...e.config,visiblePaths:e.config?.visiblePaths??[`/workspace/`]}),t<2&&(e.config={...e.config,writablePaths:e.config?.writablePaths??[`/scoops/${e.folder}/`,`/shared/`]}),e.configSchemaVersion=2)}async ensureRootStructure(){if(this.sharedFs)for(let e of[`/workspace`,`/shared`,`/scoops`,`/home`,`/tmp`,`/mnt`])try{await this.sharedFs.mkdir(e,{recursive:!0})}catch{}}async ensureGlobalMemory(){if(this.sharedFs){await yx(this.sharedFs);try{let e=await this.sharedFs.readFile(`/shared/CLAUDE.md`,{encoding:`utf-8`});this.globalMemoryCache=typeof e==`string`?e:new TextDecoder().decode(e)}catch{Q.warn(`Global memory file not found after creating defaults`)}}}async getGlobalMemory(){if(this.globalMemoryCache)return this.globalMemoryCache;if(this.sharedFs)try{let e=await this.sharedFs.readFile(`/shared/CLAUDE.md`,{encoding:`utf-8`});this.globalMemoryCache=typeof e==`string`?e:new TextDecoder().decode(e)}catch{}return this.globalMemoryCache}async setGlobalMemory(e){this.sharedFs&&(await this.sharedFs.writeFile(`/shared/CLAUDE.md`,e),this.globalMemoryCache=e,Q.info(`Global memory updated`))}getSharedFS(){return this.sharedFs}getSessionStore(){return this.sessionStore}setLickManager(e){this.lickManager=e,globalThis.__slicc_lick_handler=e=>{this.lickManager?.emitEvent(e)}}observeScoop(e,t){let n=this.scoopObservers.get(e);return n||(n=new Set,this.scoopObservers.set(e,n)),n.add(t),()=>{let n=this.scoopObservers.get(e);n&&(n.delete(t),n.size===0&&this.scoopObservers.delete(e))}}maybeNotifyConeOnScoopComplete(e){let t=this.scoops.get(e);if(!t||t.isCone)return;let n=this.scoopResponseBuffer.get(e);if(this.scoopResponseBuffer.delete(e),!n||t.notifyOnComplete===!1)return;let r=Array.from(this.scoops.values()).find(e=>e.isCone);if(!r)return;let i=n.length>2e4?n.slice(0,2e4)+`
13302
- ... (truncated)`:n,a={id:`scoop-done-${e}-${Date.now()}`,chatJid:r.jid,senderId:t.folder,senderName:t.assistantLabel,content:`[@${t.assistantLabel} completed]:\n${i}`,timestamp:new Date().toISOString(),fromAssistant:!1,channel:`scoop-notify`};Q.info(`Routing scoop completion to cone`,{scoop:t.folder,responseLength:n.length}),this.handleMessage(a).catch(e=>{let n=e instanceof Error?e.message:String(e);Q.error(`Failed to route scoop completion to cone`,{scoop:t.folder,error:n}),this.callbacks.onError(r.jid,`Scoop ${t.folder} completed but notification failed: ${n}`)})}dispatchScoopEvent(e,t,...n){let r=this.scoopObservers.get(e);if(r)for(let i of r){let r=i[t];if(r)try{r(...n)}catch(n){Q.warn(`scoop observer threw`,{jid:e,event:t,error:n instanceof Error?n.message:String(n)})}}}async registerScoop(e){await Fe(e),this.scoops.set(e.jid,e),this.messageQueues.set(e.jid,[]),Q.info(`Scoop registered`,{jid:e.jid,name:e.name});try{await this.createScoopTab(e.jid)}catch(t){throw Q.error(`Scoop init failed`,{jid:e.jid,name:e.name,error:t instanceof Error?t.message:String(t)}),await this.destroyScoopTab(e.jid).catch(()=>{}),this.scoops.delete(e.jid),this.messageQueues.delete(e.jid),await Te(e.jid).catch(t=>{Q.warn(`Failed to rollback scoop registration`,{jid:e.jid,name:e.name,error:t instanceof Error?t.message:String(t)})}),t}}async unregisterScoop(e){let t=this.scoops.get(e);if(t&&this.lickManager){let{webhooks:e,cronTasks:n}=this.lickManager.getLicksForScoop(t.name,t.folder),r=Nx(t.folder,e,n);if(r)throw r}this.snapshotScoopCost(e),this.clearIdleTimer(e),await this.destroyScoopTab(e),this.sessionStore?.delete(e).catch(t=>{Q.warn(`Failed to delete agent session`,{jid:e,error:t instanceof Error?t.message:String(t)})}),await Te(e),this.scoops.delete(e),this.messageQueues.delete(e),this.lastAgentTimestamp.delete(e),this.scoopResponseBuffer.delete(e),this.scoopObservers.delete(e),Q.info(`Scoop unregistered`,{jid:e})}getScoops(){return Array.from(this.scoops.values())}getScoop(e){return this.scoops.get(e)}async resetFilesystem(){for(let[e,t]of this.contexts.entries())this.clearIdleTimer(e),t.stop(),this.contexts.delete(e);this.sharedFs=await I.create({dbName:`slicc-fs`,wipe:!0}),this.fsWatcher&&this.sharedFs.setWatcher(this.fsWatcher),await this.ensureRootStructure(),await this.ensureGlobalMemory(),await vx(this.sharedFs).catch(e=>{Q.warn(`Failed to re-seed default skills`,{error:e instanceof Error?e.message:String(e)})}),this.droppedScoopCosts=[],Q.info(`Filesystem reset and defaults re-seeded`)}async clearAllMessages(){await Ne(),this.sessionStore&&await this.sessionStore.clearAll().catch(e=>{Q.warn(`Failed to clear agent sessions`,{error:e instanceof Error?e.message:String(e)})});for(let e of this.contexts.values())e.clearMessages();this.lastAgentTimestamp.clear();for(let e of this.scoops.keys())this.messageQueues.set(e,[]);this.droppedScoopCosts=[],Q.info(`All messages cleared`)}async handleMessage(e){Q.info(`handleMessage`,{id:e.id,chatJid:e.chatJid,sender:e.senderName,channel:e.channel,contentPreview:e.content.slice(0,80)});let t=this.scoops.get(e.chatJid);fb(t?.isCone?`cone`:t?.name??`unknown`,localStorage.getItem(`selected-model`)??`unknown`),await ve(e),await this.routeToScoop(e)}async delegateToScoop(e,t,n){let r=this.scoops.get(e);if(!r)throw Error(`Scoop not found: ${e}`);let i={id:`delegate-${Date.now()}-${Math.random().toString(36).slice(2)}`,chatJid:e,senderId:`cone`,senderName:n,content:t,timestamp:new Date().toISOString(),fromAssistant:!0,channel:`delegation`};await ve(i),this.callbacks.onIncomingMessage?.(e,i),Q.info(`Delegating to scoop`,{scoopJid:e,scoopName:r.name,promptLength:t.length}),this.sendPrompt(e,t,`cone`,n).catch(t=>{let n=t instanceof Error?t.message:String(t);Q.error(`Delegation failed`,{scoopJid:e,error:n}),this.callbacks.onError(e,`Delegation failed: ${n}`)})}async routeToScoop(e){let t=this.scoops.get(e.chatJid);if(!t){Q.info(`routeToScoop: unregistered target`,{chatJid:e.chatJid});return}let n=e.channel===`webhook`||e.channel===`cron`||e.channel===`fswatch`||e.channel===`sprinkle`;if(!t.isCone&&t.requiresTrigger&&t.trigger&&!n&&!e.content.includes(t.trigger)){Q.info(`routeToScoop: trigger not found in content`,{chatJid:e.chatJid,trigger:t.trigger,contentPreview:e.content.slice(0,80)});return}let r=this.messageQueues.get(e.chatJid)??[];r.push(e),this.messageQueues.set(e.chatJid,r);let i=this.tabs.get(e.chatJid);if(Q.debug(`routeToScoop: queued`,{chatJid:e.chatJid,scoopName:t.name,tabStatus:i?.status??`no-tab`,queueLength:r.length}),i?.status===`error`){Q.info(`routeToScoop: tab in error state, retrying init`,{chatJid:e.chatJid});try{await this.createScoopTab(e.chatJid),i=this.tabs.get(e.chatJid)}catch{Q.warn(`routeToScoop: retry init failed`,{chatJid:e.chatJid})}}i?.status===`ready`&&await this.processScoopQueue(e.chatJid)}async createScoopTab(e){let t=this.scoops.get(e);if(!t)throw Error(`Scoop not found: ${e}`);if(this.contexts.has(e))if(this.tabs.get(e)?.status===`error`)Q.info(`Re-creating context after error`,{jid:e}),this.contexts.get(e)?.dispose(),this.contexts.delete(e),this.tabs.delete(e);else{Q.debug(`Context already exists`,{jid:e});return}if(!this.sharedFs)throw Error(`Shared filesystem not initialized`);let n=`scoop-${t.folder}-${Date.now()}`,r=t.isCone?this.sharedFs:new ue(this.sharedFs,t.config?.writablePaths?[...t.config.writablePaths]:[],t.config?.visiblePaths?[...t.config.visiblePaths]:[]),i=new Dx(t,{onResponse:(n,r)=>{if(this.scoops.has(e)&&(this.callbacks.onResponse(e,n,r),this.dispatchScoopEvent(e,`onResponse`,n,r),!t.isCone))if(r){let t=this.scoopResponseBuffer.get(e)??``;this.scoopResponseBuffer.set(e,t+n)}else this.scoopResponseBuffer.set(e,n)},onResponseDone:()=>{if(!this.scoops.has(e))return;let t=this.tabs.get(e);t&&(t.lastActivity=new Date().toISOString(),this.tabs.set(e,t)),this.callbacks.onResponseDone(e)},onError:t=>{if(!this.scoops.has(e))return;let n=this.tabs.get(e);n&&(n.status=`error`,n.error=t,this.tabs.set(e,n)),this.callbacks.onError(e,t),this.callbacks.onStatusChange(e,`error`),this.dispatchScoopEvent(e,`onError`,t),this.dispatchScoopEvent(e,`onStatusChange`,`error`)},onStatusChange:n=>{if(!this.scoops.has(e))return;let r=this.tabs.get(e);r&&(r.status=n,r.lastActivity=new Date().toISOString(),this.tabs.set(e,r)),this.callbacks.onStatusChange(e,n),this.dispatchScoopEvent(e,`onStatusChange`,n),n===`ready`&&!t.isCone&&this.maybeNotifyConeOnScoopComplete(e)},onToolStart:(t,n)=>{this.callbacks.onToolStart?.(e,t,n)},onToolEnd:(t,n,r)=>{this.callbacks.onToolEnd?.(e,t,n,r)},onToolUI:(t,n,r)=>{this.callbacks.onToolUI?.(e,t,n,r)},onToolUIDone:t=>{this.callbacks.onToolUIDone?.(e,t)},onSendMessage:(t,n)=>{let r=`${n?`[${n}] `:``}${t}`;this.callbacks.onSendMessage(e,r),this.dispatchScoopEvent(e,`onSendMessage`,t)},getScoops:()=>this.getScoops(),getScoopTabState:t.isCone?e=>this.tabs.get(e):void 0,onFeedScoop:t.isCone?(e,n)=>this.delegateToScoop(e,n,t.assistantLabel):void 0,onScoopScoop:t.isCone?async e=>{let t={...e,jid:`scoop_${e.folder}_${Date.now()}`};return await this.registerScoop(t),t}:void 0,onDropScoop:t.isCone?async e=>{await this.unregisterScoop(e)}:void 0,getGlobalMemory:()=>this.getGlobalMemory(),setGlobalMemory:t.isCone?e=>this.setGlobalMemory(e):void 0,getBrowserAPI:()=>this.callbacks.getBrowserAPI()},r,this.sessionStore??void 0,this.sharedFs??void 0);this.contexts.set(e,i),this.tabs.set(e,{jid:e,contextId:n,status:`initializing`,lastActivity:new Date().toISOString()}),await i.init();let a=this.tabs.get(e);a&&a.status===`initializing`&&(a.status=`ready`,this.tabs.set(e,a),this.callbacks.onStatusChange(e,`ready`),this.dispatchScoopEvent(e,`onStatusChange`,`ready`));let o=this.scoops.get(e);o&&!o.isCone&&this.startIdleTimer(e),Q.info(`Scoop context created`,{jid:e,contextId:n})}async destroyScoopTab(e){this.clearIdleTimer(e);let t=this.contexts.get(e);t&&(t.dispose(),this.contexts.delete(e),this.tabs.delete(e),this.scoopObservers.delete(e),Q.info(`Scoop context destroyed`,{jid:e}))}isProcessing(e){return this.tabs.get(e)?.status===`processing`}getScoopContext(e){return this.contexts.get(e)}async clearQueuedMessages(e){let t=this.messageQueues.get(e);if(t&&t.length>0){for(let e of t)await je(e.id);this.messageQueues.set(e,[])}}async deleteQueuedMessage(e,t){let n=this.messageQueues.get(e);if(n){let e=n.findIndex(e=>e.id===t);e!==-1&&n.splice(e,1)}await je(t)}async getMessagesForScoop(e){return G(e)}async waitForTabReady(e,t=1e4){let n=Date.now();for(;Date.now()-n<t;){let t=this.tabs.get(e);if(!t)return!1;if(t.status===`ready`||t.status===`processing`)return!0;if(t.status===`error`)return!1;await new Promise(e=>setTimeout(e,100))}return Q.warn(`Timed out waiting for tab to become ready`,{jid:e}),!1}async sendPrompt(e,t,n,r){let i=this.contexts.get(e);i||=(await this.createScoopTab(e),this.contexts.get(e));let a=this.tabs.get(e);if(a?.status===`initializing`){if(Q.debug(`Context initializing, waiting to send message`,{jid:e}),!await this.waitForTabReady(e)){Q.error(`Context did not become ready in time, dropping prompt`,{jid:e});return}i=this.contexts.get(e),a=this.tabs.get(e)}if(!i){Q.error(`Context not found after creation`,{jid:e});return}this.clearIdleTimer(e),this.scoopResponseBuffer.delete(e),a&&(a.status=`processing`,a.lastActivity=new Date().toISOString(),this.tabs.set(e,a),this.callbacks.onStatusChange(e,`processing`),this.dispatchScoopEvent(e,`onStatusChange`,`processing`)),Q.debug(`Prompt sent to scoop`,{jid:e,textLength:t.length}),await i.prompt(t)}async processScoopQueue(e){let t=this.messageQueues.get(e);if(!t||t.length===0){Q.debug(`processScoopQueue: empty queue`,{jid:e});return}let n=this.tabs.get(e);if(n?.status!==`ready`){Q.debug(`processScoopQueue: tab not ready`,{jid:e,status:n?.status??`no-tab`});return}let r=this.scoops.get(e),i=r?.assistantLabel??e,a=this.lastAgentTimestamp.get(e)??``,o=await Se(e,a,i);if(Q.debug(`processScoopQueue: DB query`,{jid:e,scoopName:r?.name,excludeName:i,since:a,dbMessageCount:o.length,queueLength:t.length}),o.length===0){Q.debug(`processScoopQueue: no messages from DB, clearing queue`,{jid:e}),this.messageQueues.set(e,[]);return}let s=o.map(e=>`[${new Date(e.timestamp).toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`,hour12:!0})}] ${e.senderName}: ${e.content}`).join(`
13303
- `);this.messageQueues.set(e,[]);let c=o[o.length-1];this.lastAgentTimestamp.set(e,c.timestamp),await Ie(`lastAgentTs_${e}`,c.timestamp),await this.sendPrompt(e,s,c.senderId,c.senderName)}startMessageLoop(){this.pollInterval||=window.setInterval(()=>{for(let e of this.scoops.keys())this.tabs.get(e)?.status===`ready`&&this.processScoopQueue(e).catch(t=>{let n=t instanceof Error?t.message:String(t);Q.error(`Message queue processing failed`,{jid:e,error:n}),this.callbacks.onError(e,`Queue processing failed: ${n}`)})},2e3)}stopMessageLoop(){this.pollInterval&&=(clearInterval(this.pollInterval),null)}updateModel(){for(let e of this.contexts.values())e.updateModel();Q.info(`Model updated on all active contexts`,{contextCount:this.contexts.size})}async reloadAllSkills(){let e=[];for(let[t,n]of this.contexts){let r=this.tabs.get(t);(r?.status===`ready`||r?.status===`processing`)&&e.push(n.reloadSkills().catch(e=>{Q.warn(`Failed to reload skills for scoop`,{jid:t,error:e instanceof Error?e.message:String(e)})}))}await Promise.all(e),Q.info(`Skills reloaded across all contexts`,{count:e.length})}stopScoop(e){let t=this.contexts.get(e);t&&t.stop()}buildScoopCost(e,t){let n=t.getAgentMessages().filter(e=>e.role===`assistant`);if(n.length===0)return null;let r={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},i=new Map;for(let e of n)r.input+=e.usage.input,r.output+=e.usage.output,r.cacheRead+=e.usage.cacheRead,r.cacheWrite+=e.usage.cacheWrite,r.totalTokens+=e.usage.totalTokens,r.cost.input+=e.usage.cost.input,r.cost.output+=e.usage.cost.output,r.cost.cacheRead+=e.usage.cost.cacheRead,r.cost.cacheWrite+=e.usage.cost.cacheWrite,r.cost.total+=e.usage.cost.total,i.set(e.model,(i.get(e.model)??0)+1);let a=``,o=0;for(let[e,t]of i)t>o&&(a=e,o=t);let s=n.map(e=>e.timestamp).sort((e,t)=>e-t),c=s[0],l=s[s.length-1],u=900*1e3,d=l-c,f=Math.max(1,Math.ceil(d/u))*u;return{name:e.assistantLabel,type:e.isCone?`cone`:`scoop`,model:a,usage:r,turns:n.length,firstActivity:c,lastActivity:l,activeTimeMs:f}}snapshotScoopCost(e){let t=this.scoops.get(e),n=this.contexts.get(e);if(!t||!n)return;let r=this.buildScoopCost(t,n);r&&this.droppedScoopCosts.push(r)}getSessionCosts(){let e=[];for(let t of this.scoops.values()){let n=this.contexts.get(t.jid);if(!n)continue;let r=this.buildScoopCost(t,n);r&&e.push(r)}return e.push(...this.droppedScoopCosts),e}startIdleTimer(e){if(this.clearIdleTimer(e),this.tabs.get(e)?.status===`processing`)return;let t=setTimeout(()=>{this.idleTimers.delete(e);let t=this.scoops.get(e);if(!t||t.isCone||this.tabs.get(e)?.status!==`ready`)return;let n=Array.from(this.scoops.values()).find(e=>e.isCone);if(!n)return;let r={id:`scoop-idle-${e}-${Date.now()}`,chatJid:n.jid,senderId:t.folder,senderName:t.assistantLabel,content:`[@${t.assistantLabel} idle]: Scoop "${t.name}" has been ready for 2 minutes without receiving any work. This is expected if the scoop is waiting for webhooks or cron tasks. If you intended to delegate work, use feed_scoop to send a prompt.`,timestamp:new Date().toISOString(),fromAssistant:!1,channel:`scoop-idle`};Q.info(`Scoop idle timeout`,{jid:e,scoop:t.folder}),this.handleMessage(r).catch(t=>{let n=t instanceof Error?t.message:String(t);Q.error(`Failed to send idle notification`,{jid:e,error:n})})},Ix);this.idleTimers.set(e,t)}clearIdleTimer(e){let t=this.idleTimers.get(e);t&&(clearTimeout(t),this.idleTimers.delete(e))}async shutdown(){this.stopMessageLoop();for(let e of this.idleTimers.keys())this.clearIdleTimer(e);this.scheduler?.stop(),this.scheduler=null;for(let e of this.contexts.keys())await this.destroyScoopTab(e);Q.info(`Orchestrator shutdown`)}};r(`heartbeat`);var Rx=r(`tray-follower`);function zx(e){let t=new URL(e);return t.searchParams.set(`json`,`true`),t.toString()}async function Bx(e){let t=zx(e.joinUrl),n=await qx(await(e.fetchImpl??fetch)(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({controllerId:e.controllerId,runtime:e.runtime})}));return Rx.info(`Follower tray attach response`,{trayId:n.trayId,action:n.result.action,code:n.result.code,participantCount:n.participantCount}),Vx(n)}function Vx(e){let t={trayId:e.trayId,controllerId:e.controllerId,participantCount:e.participantCount,leader:e.leader,action:e.result.action,code:e.result.code,iceServers:e.iceServers};return e.result.action===`wait`?{...t,retryAfterMs:e.result.retryAfterMs}:e.result.action===`signal`?{...t,bootstrap:e.result.bootstrap}:e.result.action===`fail`?{...t,error:e.result.error}:t}async function Hx(e){return Kx(await Jx(e,{action:`poll`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,cursor:e.cursor}))}async function Ux(e){return Kx(await Jx(e,{action:`answer`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,answer:e.answer}))}async function Wx(e){return Kx(await Jx(e,{action:`ice-candidate`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,candidate:e.candidate}))}async function Gx(e){return Kx(await Jx(e,{action:`retry`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,runtime:e.runtime}))}function Kx(e){return{trayId:e.trayId,controllerId:e.controllerId,participantCount:e.participantCount,leader:e.leader,bootstrap:e.bootstrap,events:e.events}}async function qx(e){let t=null,n=null;try{t=await e.text(),n=JSON.parse(t)}catch{}if(!Yx(n)){let n=t?t.slice(0,200):`(empty)`;throw Rx.warn(`Tray follower attach returned an invalid response`,{status:e.status,body:n}),Error(`Tray follower attach returned an invalid response (${e.status}): ${n}`)}return n}async function Jx(e,t){let n=zx(e.joinUrl),r=await(e.fetchImpl??fetch)(n,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(t)}),i=await r.json().catch(()=>null);if(!Xx(i))throw Error(`Tray follower bootstrap returned an invalid response (${r.status})`);return i}function Yx(e){if(!e||typeof e!=`object`)return!1;let t=e;if(typeof t.trayId!=`string`||typeof t.controllerId!=`string`||t.role!==`follower`||typeof t.participantCount!=`number`)return!1;let n=t.result;if(!n||typeof n!=`object`)return!1;let r=n;return r.action===`wait`?(r.code===`LEADER_NOT_ELECTED`||r.code===`LEADER_NOT_CONNECTED`)&&typeof r.retryAfterMs==`number`:r.action===`signal`?r.code===`LEADER_CONNECTED`&&Zx(r.bootstrap):r.action===`fail`?(r.code===`INVALID_JOIN_CAPABILITY`||r.code===`TRAY_EXPIRED`)&&typeof r.error==`string`:!1}function Xx(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.trayId==`string`&&typeof t.controllerId==`string`&&t.role===`follower`&&typeof t.participantCount==`number`&&Zx(t.bootstrap)&&Array.isArray(t.events)}function Zx(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.controllerId==`string`&&typeof t.bootstrapId==`string`&&typeof t.attempt==`number`&&typeof t.state==`string`&&typeof t.expiresAt==`string`&&typeof t.cursor==`number`&&typeof t.maxRetries==`number`&&typeof t.retriesRemaining==`number`}var Qx=t({AGENT_BRIDGE_GLOBAL_KEY:()=>eS,AGENT_SPAWN_REQUEST_TYPE:()=>tS,createAgentBridge:()=>nS,publishAgentBridge:()=>rS,publishAgentBridgeProxy:()=>iS}),$x=r(`agent-bridge`),eS=`__slicc_agent`,tS=`agent-spawn-request`;function nS(e,t,n=null,r={}){let i=r.generateName??cS,a=r.generateUid??aS,o=r.resolveModel??uS;function s(){for(let t=0;t<8;t++){let t=i(),n=`agent_${lS(t)}`;if(!e.getScoops().some(e=>e.jid===n))return t}return a()}function c(t){if(t===void 0)return null;let n=e.getScoops().find(e=>e.jid===t);if(!n)return null;let r=n.config?.modelId;return r&&r.length>0?r:null}async function l(r){let i=r.modelId;if(i!==void 0&&(i===``||o(i)===null))return{finalText:`agent: unknown model: ${i}`,exitCode:1};let a=i??c(r.parentJid)??``,l=s(),u=`agent-${l}`,d=`agent_${lS(l)}`,f=`/scoops/${u}`,p=dS(r.cwd),m={visiblePaths:fS(r),writablePaths:pS([p,`/shared/`,`${f}/`,`/tmp/`]),allowedCommands:r.allowedCommands};a&&(m.modelId=a);let h={jid:d,name:u,folder:u,isCone:!1,type:`scoop`,requiresTrigger:!1,assistantLabel:u,addedAt:new Date().toISOString(),config:m,configSchemaVersion:2,notifyOnComplete:!1},g=[],_=``,v=null,y=e.observeScoop(d,{onSendMessage:e=>{g.push(e)},onResponse:(e,t)=>{t?_+=e:_=e},onError:e=>{v===null&&(v=e)}});try{try{await e.registerScoop(h)}catch(e){return{finalText:v??mS(e),exitCode:1}}return await e.sendPrompt(d,r.prompt,`agent`,`agent`),v===null?{finalText:g.length>0?g[g.length-1]:_,exitCode:0}:{finalText:v,exitCode:1}}catch(e){return{finalText:v??mS(e),exitCode:1}}finally{y();try{await e.unregisterScoop(d)}catch(e){$x.warn(`unregisterScoop failed`,{jid:d,error:mS(e)})}try{await t.rm(f,{recursive:!0})}catch(e){hS(e,`ENOENT`)||$x.warn(`scratch folder cleanup failed`,{folder:u,error:mS(e)})}if(n)try{await n.delete(d)}catch(e){$x.warn(`sessionStore.delete failed`,{jid:d,error:mS(e)})}}}return{spawn:l}}function rS(e,t,n=null,r={}){let i=nS(e,t,n,r);return globalThis[eS]=i,$x.info(`agent bridge published on globalThis.__slicc_agent`),i}function iS(){let e={spawn(e){return new Promise((t,n)=>{let r=globalThis.chrome?.runtime;if(!r||typeof r.sendMessage!=`function`){n(Error(`agent: chrome.runtime.sendMessage not available`));return}let i=e=>{let i=r.lastError;if(i){n(Error(i.message??`chrome.runtime error`));return}if(e==null){n(Error(`agent: empty response from offscreen bridge`));return}let a=e;if(!a.ok){n(Error(a.error??`agent: offscreen bridge error`));return}if(!a.result){n(Error(`agent: offscreen bridge returned no result`));return}t(a.result)};try{r.sendMessage({source:`panel`,payload:{type:tS,options:e}},i)}catch(e){n(e instanceof Error?e:Error(String(e)))}})}};return globalThis[eS]=e,$x.info(`agent bridge proxy published on globalThis.__slicc_agent`),e}function aS(){let e=globalThis;return typeof e.crypto?.randomUUID==`function`?e.crypto.randomUUID().replace(/-/g,``).slice(0,12):`${Date.now().toString(36)}${Math.random().toString(36).slice(2,8)}`}var oS=`amber.bouncy.breezy.bubbly.cheeky.chilly.cozy.dapper.dreamy.eager.exuberant.fluffy.frosty.gentle.giddy.glossy.jolly.lucky.mellow.merry.nimble.plucky.quirky.salty.sleepy.snappy.sparkly.spiffy.sunny.sweet.toasty.velvety.whimsy.zesty`.split(`.`),sS=`blueberry.butterscotch.caramel.cherry.chocolate.cinnamon.coconut.coffee.cookies.custard.espresso.fudge.gelato.hazelnut.honeycomb.lavender.lemon.mango.maple.marzipan.matcha.mint.mocha.neapolitan.nougat.peach.pecan.pistachio.praline.raspberry.sherbet.sorbet.stracciatella.strawberry.tiramisu.toffee.vanilla`.split(`.`);function cS(){return`${oS[Math.floor(Math.random()*oS.length)]}-${sS[Math.floor(Math.random()*sS.length)]}`}function lS(e){return e.replace(/-/g,`_`)}function uS(e){try{let t=D();for(let n of t)if(n.models.some(t=>t.id===e))return e;return null}catch{return null}}function dS(e){let t=L(e);return t.endsWith(`/`)?t:`${t}/`}function fS(e){if(e.visiblePaths!==void 0)return e.visiblePaths.map(dS);let t=[`/workspace/`];return e.invokingCwd&&e.invokingCwd.length>0&&t.push(dS(e.invokingCwd)),pS(t)}function pS(e){let t=new Set,n=[];for(let r of e)t.has(r)||(t.add(r),n.push(r));return n}function mS(e){return e instanceof Error?e.message:String(e)}function hS(e,t){if(typeof e!=`object`||!e)return!1;let n=e.code;return typeof n==`string`&&n===t}var gS=r(`tray-webrtc`),_S=`tray-control`,vS=250,yS=class{peerConnectionFactory;dataChannelLabel;peers=new Map;iceServers;constructor(e){this.options=e,this.iceServers=e.iceServers,this.peerConnectionFactory=e.peerConnectionFactory??(()=>SS(this.iceServers)),this.dataChannelLabel=e.dataChannelLabel??_S}setIceServers(e){this.iceServers=e}async handleControlMessage(e){e.type===`follower.join_requested`?(e.iceServers&&!this.iceServers&&(this.iceServers=e.iceServers),await this.handleJoinRequested(e)):e.type===`bootstrap.answer`?await this.peers.get(e.bootstrapId)?.peer.setRemoteDescription(e.answer):e.type===`bootstrap.ice_candidate`&&await this.peers.get(e.bootstrapId)?.peer.addIceCandidate(e.candidate)}getPeers(){return Array.from(this.peers.values()).map(({state:e})=>({...e}))}getChannel(e){return this.peers.get(e)?.channel??null}stop(){for(let e of this.peers.values())e.peer.close();this.peers.clear()}async handleJoinRequested(e){this.closeControllerPeers(e.controllerId);let t=this.peerConnectionFactory(),n={controllerId:e.controllerId,bootstrapId:e.bootstrapId,attempt:e.attempt,state:`connecting`,connectedAt:null,runtime:e.runtime},r=t.createDataChannel(this.dataChannelLabel);this.peers.set(e.bootstrapId,{state:n,peer:t,channel:r}),t.addEventListener(`icecandidate`,({candidate:t})=>{let n=wS(t);n&&this.options.sendControlMessage({type:`bootstrap.ice_candidate`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,candidate:n})}),t.addEventListener(`connectionstatechange`,()=>{let n=this.peers.get(e.bootstrapId);n&&(n.state.state===`connected`?(t.connectionState===`disconnected`||t.connectionState===`failed`)&&(gS.warn(`Leader peer connection state changed post-connect`,{bootstrapId:e.bootstrapId,state:t.connectionState}),this.options.onPeerDisconnected?.(e.bootstrapId,`Peer connection ${t.connectionState}`)):t.connectionState===`failed`&&this.failPeer(e,`Leader peer connection failed before the data channel opened`))}),r.addEventListener(`open`,()=>{let t=this.peers.get(e.bootstrapId);!t||t.state.state===`connected`||(t.state.state=`connected`,t.state.connectedAt=new Date().toISOString(),this.options.onPeerConnected?.({...t.state},t.channel))}),r.addEventListener(`close`,()=>{let t=this.peers.get(e.bootstrapId);t&&(t.state.state===`connected`?(gS.warn(`Leader data channel closed post-connect`,{bootstrapId:e.bootstrapId}),this.options.onPeerDisconnected?.(e.bootstrapId,`Data channel closed`)):this.failPeer(e,`Leader data channel closed before opening`))}),r.addEventListener(`error`,()=>{let t=this.peers.get(e.bootstrapId);t&&(t.state.state===`connected`?(gS.warn(`Leader data channel error post-connect`,{bootstrapId:e.bootstrapId}),this.options.onPeerDisconnected?.(e.bootstrapId,`Data channel error`)):this.failPeer(e,`Leader data channel failed before opening`))});try{let n=await t.createOffer();await t.setLocalDescription(n),this.options.sendControlMessage({type:`bootstrap.offer`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,offer:CS(t.localDescription??n,`offer`)})}catch(t){this.failPeer(e,t instanceof Error?t.message:String(t))}}closeControllerPeers(e){for(let[t,n]of this.peers.entries())n.state.controllerId===e&&(n.peer.close(),this.peers.delete(t))}failPeer(e,t){let n=this.peers.get(e.bootstrapId);if(n){n.peer.close(),this.peers.delete(e.bootstrapId);try{this.options.sendControlMessage({type:`bootstrap.failed`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,code:`WEBRTC_BOOTSTRAP_FAILED`,message:t,retryable:!0,retryAfterMs:1e3})}catch(e){gS.warn(`Failed to report tray bootstrap failure`,{error:e instanceof Error?e.message:String(e)})}}}},bS=class{fetchImpl;peerConnectionFactory;controllerIdFactory;sleep;pollIntervalMs;iceServers;activePeer=null;stopped=!1;constructor(e){this.options=e,this.fetchImpl=e.fetchImpl??fetch,this.iceServers=e.iceServers,this.peerConnectionFactory=e.peerConnectionFactory??(()=>SS(this.iceServers)),this.controllerIdFactory=e.controllerIdFactory??(()=>crypto.randomUUID()),this.sleep=e.sleep??(e=>new Promise(t=>setTimeout(t,e))),this.pollIntervalMs=e.pollIntervalMs??vS}async start(){this.stopped=!1;let e=this.controllerIdFactory(),t=Date.now();m({state:`connecting`,joinUrl:this.options.joinUrl,trayId:null,error:null,lastPingTime:null,reconnectAttempts:0,attachAttempts:0,lastAttachCode:null,connectingSince:t,lastError:null}),gS.info(`Follower tray join starting`,{joinUrl:this.options.joinUrl});let n=0;for(;;){TS(this.stopped),n++;let t;try{t=await Bx({joinUrl:this.options.joinUrl,controllerId:e,runtime:this.options.runtime,fetchImpl:this.fetchImpl})}catch(e){let t=e instanceof Error?e.message:String(e);throw m({...g(),attachAttempts:n,lastError:t}),e}if(m({...g(),attachAttempts:n,lastAttachCode:t.code}),t.action===`wait`){let e=t.retryAfterMs??1e3;gS.info(`Follower tray attach waiting`,{attempt:n,code:t.code,retryAfterMs:e}),n%10==0&&gS.warn(`Follower tray attach still waiting after ${n} attempts`,{attempt:n,code:t.code,retryAfterMs:e}),await this.sleep(e);continue}if(t.action===`fail`||!t.bootstrap){let e=t.error??`Tray follower attach failed (${t.code})`;throw m({state:`error`,joinUrl:this.options.joinUrl,trayId:null,error:e,lastPingTime:null,reconnectAttempts:0,attachAttempts:n,lastAttachCode:t.code,connectingSince:null,lastError:e}),gS.warn(`Follower tray attach failed`,{error:e}),Error(e)}t.iceServers&&(this.iceServers=t.iceServers);try{let r=await this.completeBootstrap(t.trayId,e,t.bootstrap);return m({state:`connected`,joinUrl:this.options.joinUrl,trayId:r.trayId,error:null,lastPingTime:null,reconnectAttempts:0,attachAttempts:n,lastAttachCode:t.code,connectingSince:null,lastError:null}),gS.info(`Follower tray connected`,{trayId:r.trayId,controllerId:e}),r}catch(e){let r=e instanceof Error?e.message:String(e);throw m({state:`error`,joinUrl:this.options.joinUrl,trayId:t.trayId,error:r,lastPingTime:null,reconnectAttempts:0,attachAttempts:n,lastAttachCode:t.code,connectingSince:null,lastError:r}),gS.warn(`Follower tray bootstrap failed`,{error:r}),e}}}stop(){this.stopped=!0,this.activePeer?.peer.close(),this.activePeer?.channel?.close(),this.activePeer=null,m({state:`inactive`,joinUrl:null,trayId:null,error:null,lastPingTime:null,reconnectAttempts:0,attachAttempts:0,lastAttachCode:null,connectingSince:null,lastError:null})}async completeBootstrap(e,t,n){let r=n,i=0;for(this.activePeer=this.createFollowerPeer(t,r.bootstrapId);;){if(TS(this.stopped),this.activePeer.open&&this.activePeer.channel)return{trayId:e,controllerId:t,bootstrapId:r.bootstrapId,channel:this.activePeer.channel};if(this.activePeer.openError)throw Error(this.activePeer.openError);let n=await Hx({joinUrl:this.options.joinUrl,controllerId:t,bootstrapId:r.bootstrapId,cursor:i,fetchImpl:this.fetchImpl});r=n.bootstrap,i=r.cursor;try{for(let e of n.events)if(e.type===`bootstrap.offer`){await this.activePeer.peer.setRemoteDescription(e.offer);let n=await this.activePeer.peer.createAnswer();await this.activePeer.peer.setLocalDescription(n),await Ux({joinUrl:this.options.joinUrl,controllerId:t,bootstrapId:r.bootstrapId,answer:CS(this.activePeer.peer.localDescription??n,`answer`),fetchImpl:this.fetchImpl})}else if(e.type===`bootstrap.ice_candidate`)await this.activePeer.peer.addIceCandidate(e.candidate);else if(e.type===`bootstrap.failed`)throw Error(e.failure.message)}catch(e){if(r.failure?.retryable&&r.retriesRemaining>0){r=(await Gx({joinUrl:this.options.joinUrl,controllerId:t,bootstrapId:r.bootstrapId,runtime:this.options.runtime,fetchImpl:this.fetchImpl})).bootstrap,i=0,this.activePeer.peer.close(),this.activePeer=this.createFollowerPeer(t,r.bootstrapId);continue}throw e}this.activePeer.open||await this.sleep(this.pollIntervalMs)}}createFollowerPeer(e,t){let n=this.peerConnectionFactory(),r={peer:n,channel:null,open:!1,openError:null};return n.addEventListener(`connectionstatechange`,()=>{r.open&&(n.connectionState===`disconnected`||n.connectionState===`failed`)&&(gS.warn(`Follower peer connection state changed post-connect`,{bootstrapId:t,state:n.connectionState}),this.options.onDisconnected?.(`Peer connection ${n.connectionState}`))}),n.addEventListener(`datachannel`,({channel:e})=>{r.channel=e,e.addEventListener(`open`,()=>{r.open=!0}),e.addEventListener(`close`,()=>{r.open?(gS.warn(`Follower data channel closed post-connect`,{bootstrapId:t}),this.options.onDisconnected?.(`Data channel closed`)):r.openError=`Follower data channel closed before opening`}),e.addEventListener(`error`,()=>{r.open?(gS.warn(`Follower data channel error post-connect`,{bootstrapId:t}),this.options.onDisconnected?.(`Data channel error`)):r.openError=`Follower data channel failed before opening`})}),n.addEventListener(`icecandidate`,({candidate:n})=>{let r=wS(n);r&&Wx({joinUrl:this.options.joinUrl,controllerId:e,bootstrapId:t,candidate:r,fetchImpl:this.fetchImpl}).catch(e=>{gS.warn(`Failed to send follower ICE candidate`,{error:e instanceof Error?e.message:String(e)})})}),r}};function xS(e,t){let n=t.baseDelayMs??1e3,r=t.backoffMultiplier??2,i=t.maxDelayMs??3e4,a=t.maxAttempts??10,o=t.sleep??e.sleep??(e=>new Promise(t=>setTimeout(t,e))),s=!1,c=!1,l=null,u={cancel(){s=!0,c=!1,l?.stop(),l=null},get reconnecting(){return c}},d=()=>{let t=new bS({...e,sleep:o,onDisconnected:e=>{s||(gS.warn(`Follower disconnected, starting reconnect loop`,{reason:e}),f(e))}});return l=t,{manager:t,connectionPromise:t.start()}},f=async u=>{if(s||c)return;c=!0,l?.stop(),l=null;let f=0,p=n,h=u??`Unknown disconnect`;for(;!s&&f<a&&(f++,t.onReconnecting?.(f),m({...g(),state:`reconnecting`,error:null,reconnectAttempts:f}),gS.info(`Reconnect attempt`,{attempt:f,delay:p}),await o(p),!s);){let n=null;try{let r=d();n=r.manager;let i=await r.connectionPromise;if(s){n.stop();break}c=!1,m({...g(),state:`connected`,joinUrl:e.joinUrl,trayId:i.trayId,error:null,lastPingTime:null,reconnectAttempts:0,connectingSince:null,lastError:null}),gS.info(`Reconnect successful`,{attempt:f,trayId:i.trayId}),t.onConnected(i);return}catch(e){h=e instanceof Error?e.message:String(e),gS.warn(`Reconnect attempt failed`,{attempt:f,error:h}),n?.stop(),l=null}p=Math.min(p*r,i)}s||(c=!1,m({...g(),state:`error`,error:`Reconnect failed after ${f} attempts: ${h}`,reconnectAttempts:f}),gS.warn(`Reconnect gave up`,{attempts:f,lastError:h}),t.onGaveUp?.(h))},{connectionPromise:p}=d();return p.then(e=>{s||t.onConnected(e)}).catch(e=>{s||gS.warn(`Initial follower connection failed`,{error:e instanceof Error?e.message:String(e)})}),u}function SS(e){if(typeof RTCPeerConnection>`u`)throw Error(`RTCPeerConnection is not available in this runtime`);let t=e?.length?{iceServers:e}:void 0;return new RTCPeerConnection(t)}function CS(e,t){if(!e||e.type!==t||typeof e.sdp!=`string`)throw Error(`Expected a local ${t} description before signaling`);return{type:e.type,sdp:e.sdp}}function wS(e){if(!e||typeof e!=`object`)return null;let t=e;return typeof t.candidate==`string`?{candidate:t.candidate,sdpMid:typeof t.sdpMid==`string`?t.sdpMid:null,sdpMLineIndex:typeof t.sdpMLineIndex==`number`?t.sdpMLineIndex:null,usernameFragment:typeof t.usernameFragment==`string`?t.usernameFragment:null}:null}function TS(e){if(e)throw Error(`Tray follower stopped before WebRTC bootstrap completed`)}var ES=64*1024;async function DS(e,t){try{switch(t.op){case`readFile`:return await OS(e,t.path,t.encoding);case`writeFile`:return[await kS(e,t.path,t.content,t.encoding)];case`stat`:return[await AS(e,t.path)];case`readDir`:return[await jS(e,t.path)];case`mkdir`:return[await MS(e,t.path,t.recursive)];case`rm`:return[await NS(e,t.path,t.recursive)];case`exists`:return[await PS(e,t.path)];case`walk`:return[await FS(e,t.path)];default:return[{ok:!1,error:`Unknown fs operation: ${t.op}`}]}}catch(e){return[LS(e)]}}async function OS(e,t,n){return(n??`utf-8`)===`utf-8`?IS(await e.readFile(t,{encoding:`utf-8`}),`utf-8`):IS(RS(await e.readFile(t,{encoding:`binary`})),`base64`)}async function kS(e,t,n,r){if(r===`base64`){let r=zS(n);await e.writeFile(t,r)}else await e.writeFile(t,n);return{ok:!0,data:{type:`void`}}}async function AS(e,t){return{ok:!0,data:{type:`stat`,stat:await e.stat(t)}}}async function jS(e,t){return{ok:!0,data:{type:`dirEntries`,entries:await e.readDir(t)}}}async function MS(e,t,n){return await e.mkdir(t,{recursive:n}),{ok:!0,data:{type:`void`}}}async function NS(e,t,n){return await e.rm(t,{recursive:n}),{ok:!0,data:{type:`void`}}}async function PS(e,t){return{ok:!0,data:{type:`exists`,exists:await e.exists(t)}}}async function FS(e,t){let n=[];for await(let r of e.walk(t))n.push(r);return{ok:!0,data:{type:`paths`,paths:n}}}function IS(e,t){if(e.length<=ES)return[{ok:!0,data:{type:`file`,content:e,encoding:t}}];let n=Math.ceil(e.length/ES),r=[];for(let i=0;i<n;i++){let a=i*ES,o=e.slice(a,a+ES);r.push({ok:!0,data:{type:`file`,content:o,encoding:t},chunkIndex:i,totalChunks:n})}return r}function LS(e){return e instanceof Error&&`code`in e?{ok:!1,error:e.message,code:e.code}:{ok:!1,error:e instanceof Error?e.message:String(e)}}function RS(e){let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function zS(e){let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}var BS=class{runtimes=new Map;dirty=!1;setTargets(e,t){this.runtimes.set(e,t),this.dirty=!0}removeRuntime(e){this.runtimes.delete(e)&&(this.dirty=!0)}getEntries(){this.dirty=!1;let e=[];for(let[t,n]of this.runtimes)for(let r of n)e.push({targetId:`${t}:${r.targetId}`,localTargetId:r.targetId,runtimeId:t,title:r.title,url:r.url,isLocal:!1});return e}hasChanged(){return this.dirty}getRuntimeIds(){return[...this.runtimes.keys()]}},VS=r(`data-channel-keepalive`),HS=class{sendPing;onDead;intervalMs;maxMissed;timer=null;missedPongs=0;awaitingPong=!1;stopped=!1;constructor(e){this.sendPing=e.sendPing,this.onDead=e.onDead,this.intervalMs=e.intervalMs??1e4,this.maxMissed=e.maxMissed??3}start(){this.timer||this.stopped||(this.timer=setInterval(()=>this.tick(),this.intervalMs))}stop(){this.stopped=!0,this.timer&&=(clearInterval(this.timer),null)}receivePong(){this.awaitingPong=!1,this.missedPongs=0}receivePing(){this.missedPongs=0,this.awaitingPong=!1}get missed(){return this.missedPongs}tick(){if(!this.stopped){if(this.awaitingPong&&(this.missedPongs++,VS.debug(`Missed pong`,{missedPongs:this.missedPongs,maxMissed:this.maxMissed}),this.missedPongs>=this.maxMissed)){VS.warn(`Channel declared dead`,{missedPongs:this.missedPongs}),this.stop(),this.onDead();return}this.awaitingPong=!0,this.sendPing()}}},US=r(`tray-leader-sync`);function WS(e){return e?e.includes(`standalone`)?`standalone`:e.includes(`extension`)?`extension`:e.includes(`electron`)?`electron`:`unknown`:`unknown`}var GS=class{followers=new Map;registry=new BS;runtimeToBootstrap=new Map;pendingCDPRoutes=new Map;cdpChunkBuffers=new Map;remoteTransports=new Map;pendingTabOpenRoutes=new Map;tabOpenResolvers=new Map;pendingFsRoutes=new Map;fsResolvers=new Map;constructor(e){this.options=e}addFollower(e,t,n){this.removeFollower(e);let r=he(t),i=r.onMessage(t=>{this.handleFollowerMessage(e,t)}),a=new HS({sendPing:()=>r.send({type:`ping`}),onDead:()=>{US.warn(`Follower keepalive dead, removing follower`,{bootstrapId:e}),this.removeFollower(e),this.options.onFollowerDead?.(e)}});a.start(),this.followers.set(e,{bootstrapId:e,sync:r,unsubscribe:i,keepalive:a,runtime:n?.runtime,connectedAt:n?.connectedAt,lastActivity:Date.now(),floatType:WS(n?.runtime)}),US.info(`Follower added to sync`,{bootstrapId:e,followerCount:this.followers.size}),this.sendSnapshotToFollower(e);let o=this.getConnectedEntries();o.length>0&&r.send({type:`targets.registry`,targets:o})}removeFollower(e){let t=this.followers.get(e);if(t){t.keepalive.stop(),t.unsubscribe(),t.sync.close(),this.followers.delete(e);for(let[t,n]of this.runtimeToBootstrap)if(n===e){this.cleanupRemoteTransports(t),this.registry.removeRuntime(t),this.runtimeToBootstrap.delete(t);break}this.registry.hasChanged()&&this.broadcastTargetRegistry(),US.info(`Follower removed from sync`,{bootstrapId:e,followerCount:this.followers.size})}}broadcastEvent(e){if(this.followers.size===0)return;let t={type:`agent_event`,event:e,scoopJid:this.options.getScoopJid()};for(let e of this.followers.values())e.sync.send(t)}broadcastUserMessage(e,t){if(this.followers.size===0)return;let n={type:`user_message_echo`,text:e,messageId:t,scoopJid:this.options.getScoopJid()};for(let e of this.followers.values())e.sync.send(n)}broadcastStatus(e){if(this.followers.size===0)return;let t={type:`status`,scoopStatus:e};for(let e of this.followers.values())e.sync.send(t)}sendSnapshotToFollower(e){let t=this.followers.get(e);if(!t)return;let n=this.options.getMessages(),r=this.options.getScoopJid();z(t.sync,n,r),US.debug(`Snapshot sent to follower`,{bootstrapId:e,messageCount:n.length})}handleFollowerMessage(e,t){switch(t.type){case`user_message`:US.info(`Follower user message received`,{bootstrapId:e,messageId:t.messageId}),this.options.onFollowerMessage(t.text,t.messageId);break;case`abort`:US.info(`Follower abort received`,{bootstrapId:e}),this.options.onFollowerAbort();break;case`request_snapshot`:US.info(`Follower snapshot request received`,{bootstrapId:e}),this.sendSnapshotToFollower(e);break;case`targets.advertise`:US.info(`Follower targets advertised`,{bootstrapId:e,runtimeId:t.runtimeId,targetCount:t.targets.length});for(let e of[...this.remoteTransports.keys()]){let n=e.substring(0,e.indexOf(`:`));n!==`leader`&&!this.runtimeToBootstrap.has(n)&&n!==t.runtimeId&&(this.remoteTransports.get(e)?.disconnect(),this.remoteTransports.delete(e),US.debug(`Cleaned up orphaned remote transport on advertise`,{key:e}))}this.runtimeToBootstrap.set(t.runtimeId,e),this.registry.setTargets(t.runtimeId,t.targets),this.broadcastTargetRegistry();break;case`cdp.request`:{let{requestId:n,targetRuntimeId:r,localTargetId:i,method:a,params:o,sessionId:s}=t;r===`leader`?this.executeLocalCDP(n,i,a,o,s,e):this.forwardCDPRequest(n,r,i,a,o,s,e);break}case`cdp.response`:this.handleCDPResponse(t);break;case`cdp.event`:this.handleCDPEvent(e,t.method,t.params,t.sessionId);break;case`tab.open`:{let{requestId:n,targetRuntimeId:r,url:i}=t;r===`leader`?this.executeLocalTabOpen(n,i,e):this.forwardTabOpen(n,r,i,e);break}case`tab.opened`:this.handleTabOpenResponse(t.requestId,t.targetId);break;case`tab.open.error`:this.handleTabOpenError(t.requestId,t.error);break;case`fs.request`:{let{requestId:n,targetRuntimeId:r,request:i}=t;r===`leader`?this.executeLocalFs(n,i,e):this.forwardFsRequest(n,r,i,e);break}case`fs.response`:this.handleFsResponse(t.requestId,t.response);break;case`ping`:{let t=this.followers.get(e);t&&(t.keepalive.receivePing(),t.lastActivity=Date.now(),t.sync.send({type:`pong`}));break}case`pong`:{let t=this.followers.get(e);t&&(t.keepalive.receivePong(),t.lastActivity=Date.now());break}}}setLocalTargets(e){this.registry.setTargets(`leader`,e),this.registry.hasChanged()&&this.broadcastTargetRegistry()}broadcastTargetRegistry(){if(this.followers.size===0)return;let e={type:`targets.registry`,targets:this.getConnectedEntries()};for(let t of this.followers.values())t.sync.send(e)}getTargets(){return this.getConnectedEntries()}getConnectedEntries(){return this.registry.getEntries().filter(e=>{if(e.runtimeId===`leader`)return!0;let t=this.runtimeToBootstrap.get(e.runtimeId);return t?this.followers.has(t):!1})}createRemoteTransport(e,t){let n=new ge({sendCDPRequest:(n,r,i,a)=>{let o=this.runtimeToBootstrap.get(e),s=o?this.followers.get(o):void 0;if(!s){this.remoteTransports.get(`${e}:${t}`)?.handleResponse(n,void 0,`Target runtime "${e}" not connected`);return}this.pendingCDPRoutes.set(n,{requesterBootstrapId:`__leader__`,requestId:n}),s.sync.send({type:`cdp.request`,requestId:n,localTargetId:t,method:r,params:i,sessionId:a})}});return this.remoteTransports.set(`${e}:${t}`,n),n}removeRemoteTransport(e,t){let n=`${e}:${t}`,r=this.remoteTransports.get(n);r&&(r.disconnect(),this.remoteTransports.delete(n))}cleanupRemoteTransports(e){let t=`${e}:`;for(let e of[...this.remoteTransports.keys()])e.startsWith(t)&&(this.remoteTransports.get(e)?.disconnect(),this.remoteTransports.delete(e),US.debug(`Cleaned up stale remote transport`,{key:e}))}getConnectedFollowers(){return[...this.runtimeToBootstrap.entries()].map(([e,t])=>{let n=this.followers.get(t);return{runtimeId:e,runtime:n?.runtime,connectedAt:n?.connectedAt,lastActivity:n?.lastActivity,floatType:n?.floatType}})}getBestFollowerForTeleport(){let e=[];for(let[t,n]of this.runtimeToBootstrap){let r=this.followers.get(n);r&&e.push({runtimeId:t,bootstrapId:n,floatType:r.floatType,lastActivity:r.lastActivity})}if(e.length===0)return null;let t=e.filter(e=>e.floatType===`standalone`),n=t.length>0?t:e;return n.sort((e,t)=>t.lastActivity-e.lastActivity),n[0]}get hasFollowers(){return this.followers.size>0}stop(){for(let e of[...this.followers.keys()])this.removeFollower(e)}async executeLocalCDP(e,t,n,r,i,a){let o=this.followers.get(a);if(!o)return;let s=this.options.browserTransport;if(!s){o.sync.send({type:`cdp.response`,requestId:e,error:`Leader has no browser transport`});return}try{let t=await s.send(n,r,i);U(o.sync,e,t)}catch(t){o.sync.send({type:`cdp.response`,requestId:e,error:t instanceof Error?t.message:String(t)})}}forwardCDPRequest(e,t,n,r,i,a,o){let s=this.runtimeToBootstrap.get(t),c=s?this.followers.get(s):void 0,l=this.followers.get(o);if(!c){l&&l.sync.send({type:`cdp.response`,requestId:e,error:`Target runtime "${t}" not connected`});return}this.pendingCDPRoutes.set(e,{requesterBootstrapId:o,requestId:e}),c.sync.send({type:`cdp.request`,requestId:e,localTargetId:n,method:r,params:i,sessionId:a})}handleCDPResponse(e){let{requestId:t,result:n,error:r,chunkData:i,chunkIndex:a,totalChunks:o}=e,s=this.pendingCDPRoutes.get(t);if(!s)return;let c=pe(this.cdpChunkBuffers,e);if(!c)return;if(this.pendingCDPRoutes.delete(t),s.requesterBootstrapId===`__leader__`){for(let e of this.remoteTransports.values())e.handleResponse(t,c.result,c.error);return}let l=this.followers.get(s.requesterBootstrapId);l&&U(l.sync,t,c.result,c.error)}handleCDPEvent(e,t,n,r){let i;for(let[t,n]of this.runtimeToBootstrap)if(n===e){i=t;break}if(!i)return;let a=`${i}:`;for(let[e,r]of this.remoteTransports)e.startsWith(a)&&r.handleEvent(t,n)}openRemoteTab(e,t){let n=this.runtimeToBootstrap.get(e),r=n?this.followers.get(n):void 0;if(!r)return Promise.reject(Error(`Target runtime "${e}" not connected`));let i=`tab-open-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;return new Promise((e,n)=>{this.tabOpenResolvers.set(i,{resolve:e,reject:n}),this.pendingTabOpenRoutes.set(i,{requesterBootstrapId:`__leader__`,requestId:i}),r.sync.send({type:`tab.open`,requestId:i,url:t})})}async executeLocalTabOpen(e,t,n){let r=this.followers.get(n);if(!r)return;let i=this.options.browserTransport;if(!i){r.sync.send({type:`tab.open.error`,requestId:e,error:`Leader has no browser transport`});return}try{let n=(await i.send(`Target.createTarget`,{url:t,background:!0})).targetId;r.sync.send({type:`tab.opened`,requestId:e,targetId:`leader:${n}`})}catch(t){r.sync.send({type:`tab.open.error`,requestId:e,error:t instanceof Error?t.message:String(t)})}}forwardTabOpen(e,t,n,r){let i=this.runtimeToBootstrap.get(t),a=i?this.followers.get(i):void 0,o=this.followers.get(r);if(!a){o&&o.sync.send({type:`tab.open.error`,requestId:e,error:`Target runtime "${t}" not connected`});return}this.pendingTabOpenRoutes.set(e,{requesterBootstrapId:r,requestId:e}),a.sync.send({type:`tab.open`,requestId:e,url:n})}handleTabOpenResponse(e,t){let n=this.pendingTabOpenRoutes.get(e);if(!n)return;if(this.pendingTabOpenRoutes.delete(e),n.requesterBootstrapId===`__leader__`){let n=this.tabOpenResolvers.get(e);n&&(this.tabOpenResolvers.delete(e),n.resolve(t));return}let r=this.followers.get(n.requesterBootstrapId);r&&r.sync.send({type:`tab.opened`,requestId:e,targetId:t})}handleTabOpenError(e,t){let n=this.pendingTabOpenRoutes.get(e);if(!n)return;if(this.pendingTabOpenRoutes.delete(e),n.requesterBootstrapId===`__leader__`){let n=this.tabOpenResolvers.get(e);n&&(this.tabOpenResolvers.delete(e),n.reject(Error(t)));return}let r=this.followers.get(n.requesterBootstrapId);r&&r.sync.send({type:`tab.open.error`,requestId:e,error:t})}async executeLocalFs(e,t,n){let r=this.followers.get(n);if(!r)return;let i=this.options.vfs;if(!i){r.sync.send({type:`fs.response`,requestId:e,response:{ok:!1,error:`Leader has no VFS`}});return}let a=await DS(i,t);for(let t of a)r.sync.send({type:`fs.response`,requestId:e,response:t})}forwardFsRequest(e,t,n,r){let i=this.runtimeToBootstrap.get(t),a=i?this.followers.get(i):void 0,o=this.followers.get(r);if(!a){o&&o.sync.send({type:`fs.response`,requestId:e,response:{ok:!1,error:`Target runtime "${t}" not connected`}});return}this.pendingFsRoutes.set(e,{requesterBootstrapId:r,requestId:e,chunks:[],totalChunks:1}),a.sync.send({type:`fs.request`,requestId:e,request:n})}handleFsResponse(e,t){let n=this.pendingFsRoutes.get(e);if(!n){let n=this.fsResolvers.get(e);if(n){n.responses.push(t);let r=t.ok&&t.totalChunks||1;n.responses.length>=r&&(this.fsResolvers.delete(e),n.resolve(n.responses))}return}if(n.requesterBootstrapId===`__leader__`){let n=this.fsResolvers.get(e);if(n){n.responses.push(t);let r=t.ok&&t.totalChunks||1;n.responses.length>=r&&(this.fsResolvers.delete(e),this.pendingFsRoutes.delete(e),n.resolve(n.responses))}return}let r=this.followers.get(n.requesterBootstrapId);r&&r.sync.send({type:`fs.response`,requestId:e,response:t}),n.chunks.push(t),n.totalChunks=t.ok&&t.totalChunks||1,n.chunks.length>=n.totalChunks&&this.pendingFsRoutes.delete(e)}sendFsRequest(e,t){if(e===`leader`){let e=this.options.vfs;return e?DS(e,t):Promise.resolve([{ok:!1,error:`Leader has no VFS`}])}let n=this.runtimeToBootstrap.get(e),r=n?this.followers.get(n):void 0;if(!r)return Promise.resolve([{ok:!1,error:`Target runtime "${e}" not connected`}]);let i=`fs-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;return new Promise((e,n)=>{this.fsResolvers.set(i,{resolve:e,reject:n,responses:[]}),this.pendingFsRoutes.set(i,{requesterBootstrapId:`__leader__`,requestId:i,chunks:[],totalChunks:1}),r.sync.send({type:`fs.request`,requestId:i,request:t})})}},KS=r(`tray-follower-sync`),qS=class{sync;eventListeners=new Set;unsubscribe;keepalive;latestSnapshot=null;sentMessageIds=new Set;targetEntries=[];remoteTransports=new Map;cdpChunkBuffers=new Map;snapshotChunkBuffer=null;remoteCDPSessions=new Set;cdpEventCleanups=[];tabOpenResolvers=new Map;fsResolvers=new Map;constructor(e,t={}){this.options=t,this.sync=_e(e),this.unsubscribe=this.sync.onMessage(e=>{this.handleLeaderMessage(e)}),this.keepalive=new HS({sendPing:()=>this.sync.send({type:`ping`}),onDead:()=>{KS.warn(`Leader keepalive dead, cleaning up`),this.handleDisconnect(`Keepalive timeout — leader not responding`),this.options.onDead?.()}}),this.keepalive.start(),e.addEventListener(`close`,()=>{KS.warn(`Data channel closed`),this.handleDisconnect(`Data channel closed`)}),e.addEventListener(`error`,()=>{KS.warn(`Data channel error`),this.handleDisconnect(`Data channel error`)})}sendMessage(e,t){let n=t??`follower-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;this.sentMessageIds.add(n),this.sync.send({type:`user_message`,text:e,messageId:n}),KS.info(`Sent user message to leader`,{messageId:n})}onEvent(e){return this.eventListeners.add(e),()=>this.eventListeners.delete(e)}stop(){this.sync.send({type:`abort`}),KS.info(`Sent abort to leader`)}requestSnapshot(){this.sync.send({type:`request_snapshot`})}getLatestSnapshot(){return this.latestSnapshot}close(){this.keepalive.stop(),this.unsubscribe(),this.sync.close(),this.eventListeners.clear(),this.cleanupCDPEventForwarding(),KS.info(`Follower sync closed`)}advertiseTargets(e,t){this.sync.send({type:`targets.advertise`,targets:e,runtimeId:t})}getTargets(){return this.targetEntries}disconnected=!1;handleDisconnect(e){this.disconnected||(this.disconnected=!0,m({...g(),state:`error`,error:e}),this.emitEvent({type:`error`,error:`Connection to leader lost: ${e}`}),this.keepalive.stop(),this.cleanupCDPEventForwarding(),this.unsubscribe(),this.sync.close(),this.options.onDisconnect?.(e))}handleLeaderMessage(e){switch(e.type){case`snapshot`:KS.info(`Snapshot received from leader`,{messageCount:e.messages.length,scoopJid:e.scoopJid}),this.snapshotChunkBuffer=null,this.latestSnapshot={messages:e.messages,scoopJid:e.scoopJid},this.options.onSnapshot?.(e.messages,e.scoopJid);break;case`snapshot_chunk`:{let t=H(this.snapshotChunkBuffer,e);this.snapshotChunkBuffer=t.buffer,t.result&&(KS.info(`Chunked snapshot reassembled from leader`,{messageCount:t.result.messages.length,scoopJid:t.result.scoopJid}),this.latestSnapshot=t.result,this.options.onSnapshot?.(t.result.messages,t.result.scoopJid));break}case`agent_event`:this.emitEvent(e.event);break;case`user_message_echo`:if(this.sentMessageIds.has(e.messageId)){this.sentMessageIds.delete(e.messageId),KS.debug(`Skipping own message echo`,{messageId:e.messageId});break}KS.info(`User message echo received`,{messageId:e.messageId,scoopJid:e.scoopJid}),this.options.onUserMessage?.(e.text,e.messageId,e.scoopJid);break;case`status`:this.options.onStatus?.(e.scoopStatus);break;case`error`:KS.warn(`Error from leader`,{error:e.error}),this.emitEvent({type:`error`,error:e.error});break;case`targets.registry`:KS.info(`Target registry received from leader`,{targetCount:e.targets.length}),this.targetEntries=e.targets,this.options.onTargetsUpdated?.(this.targetEntries);break;case`cdp.request`:{let{requestId:t,localTargetId:n,method:r,params:i,sessionId:a}=e;this.executeLocalCDP(t,n,r,i,a);break}case`cdp.response`:this.routeCDPResponse(e);break;case`cdp.event`:for(let t of this.remoteTransports.values())t.handleEvent(e.method,e.params);break;case`tab.open`:this.executeLocalTabOpen(e.requestId,e.url);break;case`tab.opened`:{let t=this.tabOpenResolvers.get(e.requestId);t&&(this.tabOpenResolvers.delete(e.requestId),t.resolve(e.targetId));break}case`tab.open.error`:{let t=this.tabOpenResolvers.get(e.requestId);t&&(this.tabOpenResolvers.delete(e.requestId),t.reject(Error(e.error)));break}case`fs.request`:this.executeLocalFs(e.requestId,e.request);break;case`fs.response`:this.routeFsResponse(e.requestId,e.response);break;case`ping`:this.keepalive.receivePing(),this.sync.send({type:`pong`});break;case`pong`:this.keepalive.receivePong(),d(Date.now());break}}emitEvent(e){for(let t of this.eventListeners)try{t(e)}catch(t){KS.error(`Listener error`,{eventType:e.type,error:t instanceof Error?t.message:String(t)})}}createRemoteTransport(e,t){let n=new ge({sendCDPRequest:(n,r,i,a)=>{this.sync.send({type:`cdp.request`,requestId:n,targetRuntimeId:e,localTargetId:t,method:r,params:i,sessionId:a})}});return this.remoteTransports.set(`${e}:${t}`,n),n}removeRemoteTransport(e,t){let n=`${e}:${t}`,r=this.remoteTransports.get(n);r&&(r.disconnect(),this.remoteTransports.delete(n))}openRemoteTab(e,t){let n=`tab-open-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;return new Promise((r,i)=>{this.tabOpenResolvers.set(n,{resolve:r,reject:i}),this.sync.send({type:`tab.open`,requestId:n,targetRuntimeId:e,url:t})})}async executeLocalTabOpen(e,t){let n=this.options.browserTransport;if(!n){this.sync.send({type:`tab.open.error`,requestId:e,error:`Follower has no browser transport`});return}try{let r=(await n.send(`Target.createTarget`,{url:t,background:!0})).targetId;this.sync.send({type:`tab.opened`,requestId:e,targetId:r}),this.options.onTargetsChanged?.()}catch(t){this.sync.send({type:`tab.open.error`,requestId:e,error:t instanceof Error?t.message:String(t)})}}async executeLocalCDP(e,t,n,r,i){let a=this.options.browserTransport;if(!a){this.sync.send({type:`cdp.response`,requestId:e,error:`Follower has no browser transport`});return}try{let t=await a.send(n,r,i);if(n===`Target.attachToTarget`&&t.sessionId){let e=t.sessionId;this.remoteCDPSessions.add(e),this.setupCDPEventForwarding(a,e),KS.debug(`Tracking remote CDP session`,{remoteSessionId:e})}n===`Target.detachFromTarget`&&i&&this.remoteCDPSessions.has(i)&&(this.remoteCDPSessions.delete(i),KS.debug(`Removed remote CDP session on detach`,{sessionId:i})),U(this.sync,e,t)}catch(t){this.sync.send({type:`cdp.response`,requestId:e,error:t instanceof Error?t.message:String(t)})}}setupCDPEventForwarding(e,t){for(let n of[`Page.frameNavigated`,`Page.loadEventFired`,`Page.domContentEventFired`,`Network.responseReceived`,`Network.loadingFinished`,`Network.requestWillBeSent`]){let r=e=>{if(e.sessionId!==t||!this.remoteCDPSessions.has(t))return;let{sessionId:r,...i}=e;this.sync.send({type:`cdp.event`,method:n,params:i,sessionId:t})};e.on(n,r),this.cdpEventCleanups.push(()=>e.off(n,r))}}cleanupCDPEventForwarding(){for(let e of this.cdpEventCleanups)e();this.cdpEventCleanups.length=0,this.remoteCDPSessions.clear()}routeCDPResponse(e){let t=pe(this.cdpChunkBuffers,e);if(t)for(let n of this.remoteTransports.values())n.handleResponse(e.requestId,t.result,t.error)}async executeLocalFs(e,t){let n=this.options.vfs;if(!n){this.sync.send({type:`fs.response`,requestId:e,response:{ok:!1,error:`Follower has no VFS`}});return}let r=await DS(n,t);for(let t of r)this.sync.send({type:`fs.response`,requestId:e,response:t})}routeFsResponse(e,t){let n=this.fsResolvers.get(e);if(!n)return;n.responses.push(t);let r=t.ok&&t.totalChunks||1;n.responses.length>=r&&(this.fsResolvers.delete(e),n.resolve(n.responses))}sendFsRequest(e,t){let n=`fs-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;return new Promise((r,i)=>{this.fsResolvers.set(n,{resolve:r,reject:i,responses:[]}),this.sync.send({type:`fs.request`,requestId:n,targetRuntimeId:e,request:t})})}};function JS(e,t){if(t)return`extension`;try{return ZS(new URL(e))?`electron-overlay`:`standalone`}catch{return`standalone`}}function YS(e,t){return e===`electron-overlay`||e===`standalone`&&t}function XS(e){try{let t=new URL(e).searchParams.get(`tab`);return t&&$a(t)?t:Za}catch{return Za}}function ZS(e){return e.pathname===`/electron`||e.pathname===`/electron/`||e.searchParams.get(`runtime`)===`electron-overlay`}function QS(e){let t=new URL(e);return`${t.protocol===`https:`?`wss:`:`ws:`}//${t.host}/licks-ws`}function $S(e,t){return`${new URL(e).origin}/webhooks/${t}`}function eC(e,t){return`${e.replace(/\/+$/,``)}/${t.replace(/^\/+/,``)}`}function tC(e){return typeof e==`object`&&!!e&&`type`in e&&e.type===`slicc-electron-overlay:set-tab`}var nC=[`/shared/sprinkles`];async function rC(e){let t=new Map;for(let n of nC)await e.exists(n)&&await iC(e,n,t);return await iC(e,`/`,t),t}async function iC(e,t,n){for await(let r of e.walk(t)){if(!r.endsWith(`.shtml`))continue;let t=aC(r);if(!n.has(t)){let i;try{i=await e.readFile(r,{encoding:`utf-8`})??``}catch{i=``}n.set(t,{name:t,path:r,title:oC(i,t),autoOpen:sC(i)})}}}function aC(e){let t=e.split(`/`).pop()??e;return t.endsWith(`.shtml`)?t.slice(0,-6):t}function oC(e,t){let n=e.match(/data-sprinkle-title=["']([^"']+)["']/);if(n)return n[1];let r=e.match(/<title>([^<]+)<\/title>/i);return r?r[1].trim():t}function sC(e){return/data-sprinkle-autoopen\b/.test(e)}var cC=r(`sprinkle-manager`),lC=`slicc-open-sprinkles`,uC=class{fs;bridge;callbacks;availableSprinkles=new Map;watcherUnsub;openSprinkles=new Map;constructor(e,t,n,r){this.fs=e,this.bridge=new Zg(e,t,e=>this.close(e),r),this.callbacks=n}async restoreOpenSprinkles(){try{let e=localStorage.getItem(lC);if(!e){for(let e of this.availableSprinkles.values())if(e.autoOpen)try{await this.open(e.name)}catch{cC.warn(`Failed to auto-open sprinkle`,{name:e.name})}return}let t=JSON.parse(e);for(let e of t)try{await this.open(e)}catch{cC.warn(`Failed to restore sprinkle`,{name:e})}}catch{}}persistOpenSprinkles(){try{localStorage.setItem(lC,JSON.stringify([...this.openSprinkles.keys()]))}catch{}}async openNewAutoOpenSprinkles(){await this.refresh();for(let e of this.availableSprinkles.values())if(e.autoOpen&&!this.openSprinkles.has(e.name))try{await this.open(e.name),cC.info(`Auto-opened new sprinkle after install`,{name:e.name})}catch{cC.warn(`Failed to auto-open new sprinkle`,{name:e.name})}}async refresh(){this.availableSprinkles=await rC(this.fs),cC.info(`Discovered sprinkles`,{count:this.availableSprinkles.size})}async open(e,t){if(this.openSprinkles.has(e)){cC.info(`Sprinkle already open`,{name:e});return}let n=this.availableSprinkles.get(e);if(n||=(await this.refresh(),this.availableSprinkles.get(e)),!n)throw Error(`Sprinkle not found: ${e}`);let r=await this.fs.readFile(n.path,{encoding:`utf-8`}),i=document.createElement(`div`);i.className=`sprinkle-panel`,i.style.cssText=`width: 100%; height: 100%; display: flex; flex-direction: column; overflow: hidden;`,i.dataset.sprinkle=e,this.openSprinkles.set(e,{renderer:null,container:i}),this.callbacks.addSprinkle(e,n.title,i,t);let a=new gi(i,this.bridge.createAPI(e));await a.render(r,e),this.openSprinkles.get(e).renderer=a,this.persistOpenSprinkles(),mb(e),cC.info(`Sprinkle opened`,{name:e,title:n.title})}close(e){let t=this.openSprinkles.get(e);t&&(t.renderer?.dispose(),t.container.remove(),this.bridge.removeSprinkle(e),this.openSprinkles.delete(e),this.callbacks.removeSprinkle(e),this.persistOpenSprinkles(),cC.info(`Sprinkle closed`,{name:e}))}available(){return Array.from(this.availableSprinkles.values())}opened(){return Array.from(this.openSprinkles.keys())}setupWatcher(e){this.watcherUnsub=e.watch(`/workspace`,e=>e.endsWith(`.shtml`),()=>void this.refresh())}dispose(){this.watcherUnsub?.()}sendToSprinkle(e,t){let n=this.openSprinkles.get(e);if(!n){cC.warn(`Cannot send to closed sprinkle`,{name:e});return}this.bridge.pushUpdate(e,t),n.renderer.pushUpdate(t)}};async function dC(e,t,n){let r=[],i=[];for(let{path:a,handle:o}of e){let e=typeof o?.name==`string`?o.name:``;if(!o||!(`queryPermission`in o)){i.push({path:a,dirName:e});continue}let s;try{s=await o.queryPermission({mode:`readwrite`})}catch(t){n?.warn?.(`queryPermission threw on persisted handle`,{path:a,error:t instanceof Error?t.message:String(t)}),i.push({path:a,dirName:e});continue}if(s!==`granted`){i.push({path:a,dirName:e});continue}try{await t.mount(a,o),n?.info?.(`Restored mount from previous session`,{path:a,name:e}),r.push({path:a,dirName:e})}catch(t){n?.warn?.(`Failed to re-mount persisted handle`,{path:a,error:t instanceof Error?t.message:String(t)}),i.push({path:a,dirName:e})}}return{restored:r,needsRecovery:i}}function fC(e){return`'${e.replace(/'/g,`'\\''`)}'`}function pC(e){let t=e.replace(/\r\n|[\r\n]/g,` `),n=t.match(/`+/g),r=n?Math.max(...n.map(e=>e.length))+1:1,i="`".repeat(r);return`${i}${t.startsWith("`")||t.endsWith("`")?` ${t} `:t}${i}`}function mC(e){if(!Array.isArray(e)||e.length===0)return null;let t=e.map(({path:e,dirName:t})=>{let n=t?` (previously mounted from ${pC(t)})`:``;return`- ${pC(e)}${n}`}),n=e.map(({path:e})=>` mount ${fC(e)}`),r=e.length===1?`mount point`:`mount points`,i=e.length===1?`it`:`them`;return[`[Session Reload] Mount recovery required for ${e.length} ${r}.`,``,`The page was reloaded and the following ${r} lost filesystem permission. The browser cannot restore access without a fresh user gesture, so ${i} cannot be used until the user re-authorizes:`,``,...t,``,`Please tell the user what happened and ask whether they want to re-mount. If yes, run the corresponding command(s) so the folder picker opens and they can re-select the same directory:`,``,...n,``,"If the user no longer needs a mount, run `mount unmount <path>` (with the path shell-quoted the same way) to clear the stale entry instead."].join(`
13304
- `)}var $=r(`main`),hC=`slicc-pending-mount`,gC=`pendingMount`,_C=new Set([`webhook`,`cron`,`sprinkle`,`fswatch`,`session-reload`,`navigate`]);function vC(e){return e!=null&&_C.has(e)}function yC(){try{let e=new URLSearchParams(window.location.search).get(`ui-fixture`);return e===null?!1:e===``||e===`1`||e.toLowerCase()===`true`}catch{return!1}}async function bC(e){let[{createChatFixture:t,FIXTURE_SESSION_ID:n,FIXTURE_SCOOP_NAME:r}]=await Promise.all([i(()=>import(`./chat-fixture-Nts2sMME.js`),[])]);await e.switchToContext(n,!0,r),e.loadMessages(t()),$.info(`Loaded UI fixture session for design iteration`)}async function xC(e){let t=await new Promise((e,t)=>{let n=indexedDB.open(hC,1);n.onupgradeneeded=()=>n.result.createObjectStore(`handles`),n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)}),n=t.transaction(`handles`,`readwrite`);n.objectStore(`handles`).put(e,gC),await new Promise(e=>n.oncomplete=()=>e()),t.close()}async function SC(e){let t;try{t=await new Promise((e,t)=>{let n=indexedDB.open(hC,1);n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)})}catch{return}let n=t.transaction(`handles`,`readwrite`),r=await new Promise(e=>{let t=n.objectStore(`handles`).get(gC);t.onsuccess=()=>e(t.result),t.onerror=()=>e(void 0)});if(r){n.objectStore(`handles`).delete(gC),await new Promise(e=>n.oncomplete=()=>e());let t=`/mnt/${r.name}`;await e.mount(t,r),$.info(`Mounted folder from welcome onboarding`,{name:r.name,path:t})}t.close()}function CC(){let e=document.createElement(`div`);e.className=`skill-drop-overlay`;let t=document.createElement(`div`);t.className=`skill-drop-overlay__card`;let n=document.createElement(`div`);n.className=`skill-drop-overlay__title`,t.appendChild(n);let r=document.createElement(`div`);return r.className=`skill-drop-overlay__desc`,t.appendChild(r),e.appendChild(t),document.body.appendChild(e),{show(t,i){n.textContent=t,r.textContent=i,e.classList.add(`skill-drop-overlay--visible`)},hide(){e.classList.remove(`skill-drop-overlay--visible`)}}}function wC(){let e=document.createElement(`div`);return e.className=`skill-drop-toast-container`,document.body.appendChild(e),(t,n)=>{let r=document.createElement(`div`);r.className=`skill-drop-toast skill-drop-toast--${n}`,r.textContent=t,e.appendChild(r),requestAnimationFrame(()=>r.classList.add(`skill-drop-toast--visible`)),window.setTimeout(()=>{r.classList.remove(`skill-drop-toast--visible`),window.setTimeout(()=>r.remove(),180)},4200)}}function TC(e,t,n){let r=CC(),i=0,a=!1,o=()=>{i=0,a||r.hide()};window.addEventListener(`dragenter`,e=>{go(e.dataTransfer)&&(e.preventDefault(),i+=1,a||r.show(`Drop .skill to install`,`Unpack into /workspace/skills/{name}.`))}),window.addEventListener(`dragover`,e=>{go(e.dataTransfer)&&(e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect=`copy`),a||r.show(`Drop .skill to install`,`Unpack into /workspace/skills/{name}.`))}),window.addEventListener(`dragleave`,()=>{i!==0&&(i=Math.max(0,i-1),i===0&&!a&&r.hide())}),window.addEventListener(`dragend`,o),window.addEventListener(`blur`,o),window.addEventListener(`drop`,async s=>{let c=_o(s.dataTransfer);if(!c){o();return}if(s.preventDefault(),i=0,a){r.hide(),t(`Another .skill installation is already in progress.`,`error`);return}a=!0,r.show(`Installing skill…`,c.name);try{let r=await fe(e,c);await n(),t(`Installed "${r.skillName}" to ${r.destinationPath} (${r.fileCount} files). Run "skill install ${r.skillName}" to apply it.`,`success`)}catch(e){t(`Failed to install dropped skill: ${e instanceof Error?e.message:String(e)}`,`error`)}finally{a=!1,r.hide()}})}async function EC(e){let{OffscreenClient:t}=await i(async()=>{let{OffscreenClient:e}=await import(`./offscreen-client-BlWuVmPl.js`);return{OffscreenClient:e}},__vite__mapDeps([21,15])),{VirtualFS:n}=await i(async()=>{let{VirtualFS:e}=await import(`./fs-bsu2i7du.js`).then(e=>e.t);return{VirtualFS:e}},__vite__mapDeps([17,4,15,18])),{publishAgentBridgeProxy:r}=await i(async()=>{let{publishAgentBridgeProxy:e}=await Promise.resolve().then(()=>Qx);return{publishAgentBridgeProxy:e}},void 0),a=new io(e,!0);window.__slicc_debug_tabs=e=>a.setDebugTabs(e),await a.panels.chat.initSession(`session-cone`),r();let o=null,s=await n.create({dbName:`slicc-fs`});a.panels.fileBrowser.setFs(s),$.info(`File browser wired to shared VFS (local IndexedDB)`);let c=new BroadcastChannel(`preview-vfs`);c.onmessage=e=>{if(e.data?.type!==`preview-vfs-read`)return;let{id:t,path:n,asText:r}=e.data;(async()=>{try{let e=r?`utf-8`:`binary`,i=await s.readFile(n,{encoding:e});c.postMessage({type:`preview-vfs-response`,id:t,content:i})}catch(e){let r=e instanceof Error?e.message:String(e);r.includes(`ENOENT`)||$.error(`Preview VFS read failed`,{path:n,error:r}),c.postMessage({type:`preview-vfs-response`,id:t,error:r})}})()},TC(s,wC(),async()=>{await a.panels.fileBrowser.refresh()});try{let{WasmShell:e}=await i(async()=>{let{WasmShell:e}=await Promise.resolve().then(()=>Tb);return{WasmShell:e}},void 0),{PanelCdpProxy:t,BrowserAPI:n}=await i(async()=>{let{PanelCdpProxy:e,BrowserAPI:t}=await import(`./cdp-CsCvDwW3.js`).then(e=>e.t);return{PanelCdpProxy:e,BrowserAPI:t}},__vite__mapDeps([22,4,1,15])),{fetchSecretEnvVars:r}=await i(async()=>{let{fetchSecretEnvVars:e}=await Promise.resolve().then(()=>Sx);return{fetchSecretEnvVars:e}},void 0),o=new t;await o.connect();let c=new n(o),l=await r(),u=new e({fs:s,browserAPI:c,env:Object.keys(l).length>0?l:void 0});await a.panels.terminal.mountShell(u),$.info(`Terminal mounted with shared VFS and BrowserAPI (CDP proxy)`)}catch(e){$.warn(`Failed to mount shell to terminal`,e)}{let{registerSessionCostsProvider:e}=await i(async()=>{let{registerSessionCostsProvider:e}=await import(`./cost-command-DBzah9S9.js`).then(e=>e.t);return{registerSessionCostsProvider:e}},__vite__mapDeps([23,4]));e(()=>new Promise(e=>{chrome.runtime.sendMessage({source:`panel`,payload:{type:`get-session-costs`}},t=>{if(chrome.runtime.lastError||!t?.ok){e([]);return}e(t.costs??[])})}))}let u,d=new Set,f=async e=>{o=e,u.selectedScoopJid=e.jid,a.panels.memory.setSelectedScoop(e.jid),a.setScoopSwitcherSelected?.(e.jid),a.panels.scoops.setSelectedJid(e.jid);let t=e.isCone?`session-cone`:`session-${e.folder}`,n=e.isCone?void 0:e.name;await a.panels.chat.switchToContext(t,!e.isCone,n),u.isProcessing(e.jid)&&a.panels.chat.setProcessing(!0)};u=new t({onStatusChange:(e,t)=>{a.panels.scoops.updateScoopStatus(e,t),a.updateScoopSwitcherStatus?.(e,t),o?.jid===e&&(a.setAgentProcessing(t===`processing`),t===`processing`?a.panels.chat.setProcessing(!0):t===`ready`&&a.panels.chat.setProcessing(!1))},onScoopCreated:e=>{a.panels.scoops.refreshScoops(),a.refreshScoopSwitcher?.(),o||(o=e,u.selectedScoopJid=e.jid,a.panels.memory.setSelectedScoop(e.jid))},onScoopListUpdate:()=>{let e=new Set(u.getScoops().map(e=>e.folder));for(let t of d)e.has(t)||a.panels.chat.deleteSessionById(`session-${t}`);if(d=e,a.panels.scoops.refreshScoops(),a.refreshScoopSwitcher?.(),!o){let e=u.getScoops().find(e=>e.isCone);e&&(o=e,u.selectedScoopJid=e.jid,a.panels.memory.setSelectedScoop(e.jid))}},onIncomingMessage:(e,t)=>{if(o?.jid===e){let e=t.channel===`delegation`?`**[Instructions from sliccy]**\n\n${t.content}`:t.content;a.panels.chat.addUserMessage(e)}},onReady:async()=>{try{$.info(`Offscreen engine ready, scoop count:`,u.getScoops().length),window.localStorage.getItem(`slicc.trayJoinUrl`)&&chrome.runtime.sendMessage({source:`panel`,payload:{type:`refresh-tray-runtime`}}).catch(()=>{});let e=o??u.getScoops().find(e=>e.isCone)??u.getScoops()[0];e&&(o=e,u.selectedScoopJid=e.jid,await f(e))}catch(e){$.error(`Failed to initialize on ready`,{error:e instanceof Error?e.message:String(e)})}}}),u.setLocalFS(s);let p=u.createAgentHandle();a.panels.chat.setAgent(p),a.panels.scoops.setOrchestrator(u),a.panels.memory.setOrchestrator(u),a.setScoopSwitcherOrchestrator?.(u),a.onScoopSelect=f,a.onModelChange=e=>{localStorage.setItem(`selected-model`,e),u.updateModel()},a.onClearChat=async()=>{let e=u.getScoops();for(let t of e){let e=t.isCone?`session-cone`:`session-${t.folder}`;await a.panels.chat.deleteSessionById(e)}u.clearAllMessages()},a.onClearFilesystem=async()=>{u.clearFilesystem()},a.panels.chat.onInlineSprinkleLick=(e,t)=>{u.sendSprinkleLick(`inline`,{action:e,data:t})};let m=new uC(s,async e=>{if(e.type===`sprinkle`){if(e.sprinkleName===`welcome`){let t=e.body,n=t?.action;(n===`onboarding-complete`||n===`shortcut-migrate`)&&s.writeFile(`/shared/.welcomed`,`1`).catch(e=>$.warn(`Failed to persist welcome completion marker`,e)),n===`shortcut-migrate`&&m.close(`welcome`),n===`onboarding-complete`&&t?.data?.mountWorkspace&&SC(s).catch(e=>$.warn(`Failed to mount workspace from onboarding`,e))}if(e.sprinkleName===`welcome`&&e.body?.action===`request-mount`){try{let e=window;if(!e.showDirectoryPicker)throw Error(`showDirectoryPicker not supported`);let t=await e.showDirectoryPicker({mode:`readwrite`});await xC(t),m.sendToSprinkle(`welcome`,{action:`mount-complete`,dirName:t.name})}catch(e){e.name!==`AbortError`&&$.warn(`Mount picker failed`,e),m.sendToSprinkle(`welcome`,{action:`mount-cancelled`})}return}u.sendSprinkleLick(e.sprinkleName,e.body,e.targetScoop)}},{addSprinkle:(e,t,n,r)=>a.addSprinkle(e,t,n,r),removeSprinkle:e=>a.removeSprinkle(e)},()=>{let e=u.getScoops().find(e=>e.isCone);e&&u.stopScoop(e.jid)});if(window.__slicc_sprinkleManager=m,window.__slicc_reloadSkills=()=>(chrome.runtime.sendMessage({source:`panel`,payload:{type:`reload-skills`}}),Promise.resolve()),u.setSprinkleOpHandler(e=>{let{id:t,op:n,name:r,data:i}=e;console.log(`[main-ext] sprinkle-op handler called`,{id:t,op:n,name:r}),(async()=>{try{let e;switch(n){case`list`:await m.refresh(),e=m.available();break;case`opened`:e=m.opened();break;case`refresh`:await m.refresh(),e=m.available().length;break;case`open`:await m.open(r),e=!0;break;case`close`:m.close(r),e=!0;break;case`send`:m.sendToSprinkle(r,i),e=!0;break;case`openNewAutoOpen`:await m.openNewAutoOpenSprinkles(),e=!0;break}console.log(`[main-ext] sprinkle-op response sending`,{id:t,op:n,result:typeof e}),chrome.runtime.sendMessage({source:`panel`,payload:{type:`sprinkle-op-response`,id:t,result:e}}).catch(()=>{})}catch(e){chrome.runtime.sendMessage({source:`panel`,payload:{type:`sprinkle-op-response`,id:t,error:e instanceof Error?e.message:String(e)}}).catch(()=>{})}})()}),await m.refresh(),a.onSprinkleClose=e=>m.close(e),a.getAvailableSprinkles=()=>{let e=new Set(m.opened());return m.available().filter(t=>!e.has(t.name)).map(e=>({name:e.name,title:e.title}))},a.onOpenSprinkle=(e,t)=>m.open(e,t),a.updateAddButtons(),await m.restoreOpenSprinkles(),!await s.exists(`/shared/.welcomed`)&&localStorage.getItem(`slicc-welcomed`)&&(await s.writeFile(`/shared/.welcomed`,`1`).catch(()=>{}),localStorage.removeItem(`slicc-welcomed`)),!await s.exists(`/shared/.welcomed`)&&!l(window.localStorage)&&m.available().some(e=>e.name===`welcome`))try{await m.open(`welcome`)}catch(e){$.warn(`Failed to open welcome sprinkle`,e)}$.info(`SprinkleManager initialized (extension mode)`),u.requestState(),$.info(`Extension UI connected to offscreen agent engine`),yC()&&await bC(a.panels.chat),db().catch(()=>{})}function DC(){if(typeof chrome<`u`&&chrome?.runtime?.id)return;let e=new Blob([`
13300
+ ---`);let a=vx(n);return a&&(i+=a),i}},kx=r(`scheduler`),Ax=class{callbacks;pollInterval=null;running=!1;constructor(e){this.callbacks=e}start(){this.running||(this.running=!0,this.pollInterval=window.setInterval(()=>this.checkTasks(),6e4),this.checkTasks(),kx.info(`Scheduler started`))}stop(){this.pollInterval&&=(clearInterval(this.pollInterval),null),this.running=!1,kx.info(`Scheduler stopped`)}async createTask(e,t,n,r){let i={id:`task-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,groupFolder:e,prompt:t,scheduleType:n,scheduleValue:r,status:`active`,nextRun:this.calculateNextRun(n,r),lastRun:null,createdAt:new Date().toISOString()};return await Le(i),kx.info(`Task created`,{id:i.id,groupFolder:e,scheduleType:n}),i}async updateTask(e,t){let n=await De(e);if(!n)return null;let r={...n,...t};return(t.scheduleType||t.scheduleValue)&&(r.nextRun=this.calculateNextRun(r.scheduleType,r.scheduleValue)),await Le(r),kx.info(`Task updated`,{id:e,updates:Object.keys(t)}),r}async pauseTask(e){return await this.updateTask(e,{status:`paused`})!==null}async resumeTask(e){return await De(e)?(await this.updateTask(e,{status:`active`}),!0):!1}async deleteTask(e){return await De(e)?(await ye(e),kx.info(`Task deleted`,{id:e}),!0):!1}async getTasksByScoop(e){return(await Ee()).filter(t=>t.groupFolder===e)}async getAllTasks(){return Ee()}async checkTasks(){let e=await Ee(),t=new Date;for(let n of e)n.status===`active`&&n.nextRun&&(new Date(n.nextRun)>t||await this.runTask(n))}async runTask(e){let t=this.callbacks.getScoop(e.groupFolder);if(!t){kx.warn(`Task scoop not found`,{taskId:e.id,groupFolder:e.groupFolder});return}kx.info(`Running task`,{id:e.id,groupFolder:e.groupFolder});try{let n=new Date().toISOString(),r=this.calculateNextRun(e.scheduleType,e.scheduleValue),i=e.scheduleType===`once`?`completed`:e.status;await Le({...e,lastRun:n,nextRun:r,status:i}),await this.callbacks.onTaskRun(e,t),kx.info(`Task completed`,{id:e.id})}catch(t){kx.error(`Task execution failed`,{id:e.id,error:t instanceof Error?t.message:String(t)})}}calculateNextRun(e,t){let n=new Date;switch(e){case`cron`:return this.getNextCronTime(t,n)?.toISOString()??null;case`interval`:{let e=parseInt(t,10);return isNaN(e)||e<=0?null:new Date(n.getTime()+e).toISOString()}case`once`:return new Date(t)>n?t:null;default:return null}}getNextCronTime(e,t){let n=e.trim().split(/\s+/);if(n.length!==5)return null;let[r,i,a,o,s]=n,c=new Date(t);c.setSeconds(0),c.setMilliseconds(0),c.setMinutes(c.getMinutes()+1);for(let e=0;e<527040;e++){if(this.cronMatches(c,r,i,a,o,s))return c;c.setMinutes(c.getMinutes()+1)}return null}cronMatches(e,t,n,r,i,a){return this.cronFieldMatches(e.getMinutes(),t)&&this.cronFieldMatches(e.getHours(),n)&&this.cronFieldMatches(e.getDate(),r)&&this.cronFieldMatches(e.getMonth()+1,i)&&this.cronFieldMatches(e.getDay(),a)}cronFieldMatches(e,t){if(t===`*`)return!0;if(t.includes(`,`))return t.split(`,`).some(t=>this.cronFieldMatches(e,t.trim()));if(t.includes(`-`)){let[n,r]=t.split(`-`).map(e=>parseInt(e,10));return e>=n&&e<=r}if(t.includes(`/`)){let[n,r]=t.split(`/`),i=parseInt(r,10);if(n===`*`)return e%i===0;let a=parseInt(n,10);return e>=a&&(e-a)%i===0}return parseInt(t,10)===e}},jx=t({LickManager:()=>Nx,buildActiveLicksError:()=>Px,getLickManager:()=>Ix}),Mx=r(`lick-manager`),Nx=class{webhooks=new Map;crontasks=new Map;cronInterval=null;eventHandler=null;async init(){await we();let e=await Pe();for(let t of e)this.webhooks.set(t.id,t);Mx.info(`Loaded webhooks`,{count:this.webhooks.size});let t=await Me();for(let e of t)this.crontasks.set(e.id,e);Mx.info(`Loaded crontasks`,{count:this.crontasks.size}),this.cronInterval=setInterval(()=>this.runCronScheduler(),6e4),Mx.info(`Cron scheduler started`)}dispose(){this.cronInterval&&=(clearInterval(this.cronInterval),null)}setEventHandler(e){this.eventHandler=e}emitEvent(e){Mx.info(`External lick event`,{type:e.type,target:e.targetScoop}),this.eventHandler?.(e)}async createWebhook(e,t,n){let r=this.generateId(),i={id:r,name:e,createdAt:new Date().toISOString(),filter:n,scoop:t};return n&&this.compileFilter(n,!0),this.webhooks.set(r,i),await be(i),Mx.info(`Webhook created`,{id:r,name:e,scoop:t}),i}async deleteWebhook(e){return this.webhooks.has(e)?(this.webhooks.delete(e),await ke(e),Mx.info(`Webhook deleted`,{id:e}),!0):!1}listWebhooks(){return Array.from(this.webhooks.values())}getWebhook(e){return this.webhooks.get(e)}handleWebhookEvent(e,t,n){let r=this.webhooks.get(e);if(!r){Mx.warn(`Webhook not found`,{webhookId:e});return}let i={type:`webhook`,webhookId:e,webhookName:r.name,targetScoop:r.scoop,timestamp:new Date().toISOString(),headers:t,body:n};if(r.filter)try{let t=this.compileFilter(r.filter,!0)(i);if(t===!1){Mx.debug(`Webhook event dropped by filter`,{webhookId:e,name:r.name});return}typeof t==`object`&&t&&(i=t)}catch(t){Mx.error(`Webhook filter error`,{webhookId:e,error:t instanceof Error?t.message:String(t)})}Mx.info(`Webhook event received`,{webhookId:e,name:r.name,targetScoop:r.scoop}),this.eventHandler?.(i)}async createCronTask(e,t,n,r){let i=this.getNextCronTime(t,new Date);if(!i)throw Error(`Invalid cron expression`);r&&this.compileFilter(r,!1);let a=this.generateId(),o={id:a,name:e,cron:t,scoop:n,filter:r,nextRun:i.toISOString(),lastRun:null,status:`active`,createdAt:new Date().toISOString()};return this.crontasks.set(a,o),await Ce(o),Mx.info(`Cron task created`,{id:a,name:e,cron:t,scoop:n}),o}async deleteCronTask(e){return this.crontasks.has(e)?(this.crontasks.delete(e),await Oe(e),Mx.info(`Cron task deleted`,{id:e}),!0):!1}listCronTasks(){return Array.from(this.crontasks.values())}getCronTask(e){return this.crontasks.get(e)}getLicksForScoop(e,t){let n=n=>n===e||n===t||`${n}-scoop`===t;return{webhooks:Array.from(this.webhooks.values()).filter(e=>n(e.scoop)),cronTasks:Array.from(this.crontasks.values()).filter(e=>n(e.scoop))}}async runCronScheduler(){let e=new Date;for(let t of this.crontasks.values()){if(t.status!==`active`||!t.nextRun||new Date(t.nextRun)>e)continue;let n={time:e.toISOString()};if(t.filter)try{let r=this.compileFilter(t.filter,!1)(null);if(r===!1){Mx.debug(`Cron task skipped by filter`,{id:t.id,name:t.name}),t.nextRun=this.getNextCronTime(t.cron,e)?.toISOString()??null,t.lastRun=e.toISOString(),await Ce(t);continue}typeof r==`object`&&r&&(n=r)}catch(e){Mx.error(`Cron filter error`,{id:t.id,error:e instanceof Error?e.message:String(e)})}let r={type:`cron`,cronId:t.id,cronName:t.name,targetScoop:t.scoop,timestamp:e.toISOString(),body:n};Mx.info(`Cron task running`,{id:t.id,name:t.name}),this.eventHandler?.(r),t.nextRun=this.getNextCronTime(t.cron,e)?.toISOString()??null,t.lastRun=e.toISOString(),await Ce(t)}}generateId(){let e=``;for(let t=0;t<12;t++)e+=`abcdefghijklmnopqrstuvwxyz0123456789`[Math.floor(Math.random()*36)];return e}compileFilter(e,t){try{return t?Function(`event`,`return (${e})(event);`):Function(`return (${e})();`)}catch(e){throw Error(`Invalid filter function: ${e instanceof Error?e.message:String(e)}`)}}getNextCronTime(e,t){let n=e.trim().split(/\s+/);if(n.length!==5)return null;let[r,i,a,o,s]=n,c=new Date(t);c.setSeconds(0),c.setMilliseconds(0),c.setMinutes(c.getMinutes()+1);let l=(e,t)=>{if(t===`*`)return!0;if(t.includes(`,`))return t.split(`,`).some(t=>l(e,t.trim()));if(t.includes(`-`)){let[n,r]=t.split(`-`).map(e=>parseInt(e,10));return e>=n&&e<=r}if(t.includes(`/`)){let[n,r]=t.split(`/`),i=parseInt(r,10);if(n===`*`)return e%i===0;let a=parseInt(n,10);return e>=a&&(e-a)%i===0}return parseInt(t,10)===e};for(let e=0;e<527040;e++){if(l(c.getMinutes(),r)&&l(c.getHours(),i)&&l(c.getDate(),a)&&l(c.getMonth()+1,o)&&l(c.getDay(),s))return c;c.setMinutes(c.getMinutes()+1)}return null}};function Px(e,t,n){if(t.length===0&&n.length===0)return null;let r=[];t.length>0&&r.push(`${t.length} active webhook${t.length>1?`s`:``}`),n.length>0&&r.push(`${n.length} active cron task${n.length>1?`s`:``}`);let i=[...t.map(e=>` webhook delete ${e.id}`),...n.map(e=>` crontask delete ${e.id}`)].join(`
13301
+ `);return Error(`Cannot remove scoop '${e}': it has ${r.join(` and `)}. Unregister them first:\n${i}`)}var Fx=null;function Ix(){return Fx||=new Nx,Fx}var Q=r(`orchestrator`),Lx=120*1e3,Rx=class{scoops=new Map;tabs=new Map;contexts=new Map;messageQueues=new Map;lastAgentTimestamp=new Map;container;callbacks;config;pollInterval=null;scheduler=null;globalMemoryCache=``;sharedFs=null;scoopResponseBuffer=new Map;lickManager=null;sessionStore=null;fsWatcher=null;idleTimers=new Map;droppedScoopCosts=[];scoopObservers=new Map;constructor(e,t,n={name:`sliccy`,triggerPattern:/^@sliccy\b/i}){this.container=e,this.callbacks=t,this.config=n}async init(){await we(),this.sharedFs=await I.create({dbName:`slicc-fs`}),this.sessionStore=new M,this.fsWatcher=new ce,this.sharedFs.setWatcher(this.fsWatcher),globalThis.__slicc_fs_watcher=this.fsWatcher,await this.ensureRootStructure();let e=await xe();for(let t of Object.values(e)){t.isCone&&(t.trigger=void 0,t.requiresTrigger=!1,t.assistantLabel=t.assistantLabel||`sliccy`),this.migrateScoopConfig(t),this.scoops.set(t.jid,t),this.messageQueues.set(t.jid,[]);let e=await Ae(`lastAgentTs_${t.jid}`);e&&this.lastAgentTimestamp.set(t.jid,e)}await this.ensureGlobalMemory(),this.scheduler=new Ax({onTaskRun:async(e,t)=>{Q.info(`Running scheduled task`,{taskId:e.id,scoop:t.name}),await this.sendPrompt(t.jid,`[SCHEDULED TASK]\n\n${e.prompt}`,`scheduler`,`Scheduled Task`)},getScoop:e=>{for(let t of this.scoops.values())if(t.folder===e)return t}}),this.scheduler.start(),Q.info(`Orchestrator initialized`,{scoopCount:this.scoops.size});for(let e of this.scoops.values())await this.createScoopTab(e.jid);He(()=>this.getSessionCosts()),this.startMessageLoop()}migrateScoopConfig(e){if(e.isCone)return;let t=e.configSchemaVersion??0;t>=2||(t<1&&(e.config={...e.config,visiblePaths:e.config?.visiblePaths??[`/workspace/`]}),t<2&&(e.config={...e.config,writablePaths:e.config?.writablePaths??[`/scoops/${e.folder}/`,`/shared/`]}),e.configSchemaVersion=2)}async ensureRootStructure(){if(this.sharedFs)for(let e of[`/workspace`,`/shared`,`/scoops`,`/home`,`/tmp`,`/mnt`])try{await this.sharedFs.mkdir(e,{recursive:!0})}catch{}}async ensureGlobalMemory(){if(this.sharedFs){await bx(this.sharedFs);try{let e=await this.sharedFs.readFile(`/shared/CLAUDE.md`,{encoding:`utf-8`});this.globalMemoryCache=typeof e==`string`?e:new TextDecoder().decode(e)}catch{Q.warn(`Global memory file not found after creating defaults`)}}}async getGlobalMemory(){if(this.globalMemoryCache)return this.globalMemoryCache;if(this.sharedFs)try{let e=await this.sharedFs.readFile(`/shared/CLAUDE.md`,{encoding:`utf-8`});this.globalMemoryCache=typeof e==`string`?e:new TextDecoder().decode(e)}catch{}return this.globalMemoryCache}async setGlobalMemory(e){this.sharedFs&&(await this.sharedFs.writeFile(`/shared/CLAUDE.md`,e),this.globalMemoryCache=e,Q.info(`Global memory updated`))}getSharedFS(){return this.sharedFs}getSessionStore(){return this.sessionStore}setLickManager(e){this.lickManager=e,globalThis.__slicc_lick_handler=e=>{this.lickManager?.emitEvent(e)}}observeScoop(e,t){let n=this.scoopObservers.get(e);return n||(n=new Set,this.scoopObservers.set(e,n)),n.add(t),()=>{let n=this.scoopObservers.get(e);n&&(n.delete(t),n.size===0&&this.scoopObservers.delete(e))}}maybeNotifyConeOnScoopComplete(e){let t=this.scoops.get(e);if(!t||t.isCone)return;let n=this.scoopResponseBuffer.get(e);if(this.scoopResponseBuffer.delete(e),!n||t.notifyOnComplete===!1)return;let r=Array.from(this.scoops.values()).find(e=>e.isCone);if(!r)return;let i=n.length>2e4?n.slice(0,2e4)+`
13302
+ ... (truncated)`:n,a={id:`scoop-done-${e}-${Date.now()}`,chatJid:r.jid,senderId:t.folder,senderName:t.assistantLabel,content:`[@${t.assistantLabel} completed]:\n${i}`,timestamp:new Date().toISOString(),fromAssistant:!1,channel:`scoop-notify`};Q.info(`Routing scoop completion to cone`,{scoop:t.folder,responseLength:n.length}),this.handleMessage(a).catch(e=>{let n=e instanceof Error?e.message:String(e);Q.error(`Failed to route scoop completion to cone`,{scoop:t.folder,error:n}),this.callbacks.onError(r.jid,`Scoop ${t.folder} completed but notification failed: ${n}`)})}dispatchScoopEvent(e,t,...n){let r=this.scoopObservers.get(e);if(r)for(let i of r){let r=i[t];if(r)try{r(...n)}catch(n){Q.warn(`scoop observer threw`,{jid:e,event:t,error:n instanceof Error?n.message:String(n)})}}}async registerScoop(e){await Fe(e),this.scoops.set(e.jid,e),this.messageQueues.set(e.jid,[]),Q.info(`Scoop registered`,{jid:e.jid,name:e.name});try{await this.createScoopTab(e.jid)}catch(t){throw Q.error(`Scoop init failed`,{jid:e.jid,name:e.name,error:t instanceof Error?t.message:String(t)}),await this.destroyScoopTab(e.jid).catch(()=>{}),this.scoops.delete(e.jid),this.messageQueues.delete(e.jid),await Te(e.jid).catch(t=>{Q.warn(`Failed to rollback scoop registration`,{jid:e.jid,name:e.name,error:t instanceof Error?t.message:String(t)})}),t}}async unregisterScoop(e){let t=this.scoops.get(e);if(t&&this.lickManager){let{webhooks:e,cronTasks:n}=this.lickManager.getLicksForScoop(t.name,t.folder),r=Px(t.folder,e,n);if(r)throw r}this.snapshotScoopCost(e),this.clearIdleTimer(e),await this.destroyScoopTab(e),this.sessionStore?.delete(e).catch(t=>{Q.warn(`Failed to delete agent session`,{jid:e,error:t instanceof Error?t.message:String(t)})}),await Te(e),this.scoops.delete(e),this.messageQueues.delete(e),this.lastAgentTimestamp.delete(e),this.scoopResponseBuffer.delete(e),this.scoopObservers.delete(e),Q.info(`Scoop unregistered`,{jid:e})}getScoops(){return Array.from(this.scoops.values())}getScoop(e){return this.scoops.get(e)}async resetFilesystem(){for(let[e,t]of this.contexts.entries())this.clearIdleTimer(e),t.stop(),this.contexts.delete(e);this.sharedFs=await I.create({dbName:`slicc-fs`,wipe:!0}),this.fsWatcher&&this.sharedFs.setWatcher(this.fsWatcher),await this.ensureRootStructure(),await this.ensureGlobalMemory(),await yx(this.sharedFs).catch(e=>{Q.warn(`Failed to re-seed default skills`,{error:e instanceof Error?e.message:String(e)})}),this.droppedScoopCosts=[],Q.info(`Filesystem reset and defaults re-seeded`)}async clearAllMessages(){await Ne(),this.sessionStore&&await this.sessionStore.clearAll().catch(e=>{Q.warn(`Failed to clear agent sessions`,{error:e instanceof Error?e.message:String(e)})});for(let e of this.contexts.values())e.clearMessages();this.lastAgentTimestamp.clear();for(let e of this.scoops.keys())this.messageQueues.set(e,[]);this.droppedScoopCosts=[],Q.info(`All messages cleared`)}async handleMessage(e){Q.info(`handleMessage`,{id:e.id,chatJid:e.chatJid,sender:e.senderName,channel:e.channel,contentPreview:e.content.slice(0,80)});let t=this.scoops.get(e.chatJid);pb(t?.isCone?`cone`:t?.name??`unknown`,localStorage.getItem(`selected-model`)??`unknown`),await ve(e),await this.routeToScoop(e)}async delegateToScoop(e,t,n){let r=this.scoops.get(e);if(!r)throw Error(`Scoop not found: ${e}`);let i={id:`delegate-${Date.now()}-${Math.random().toString(36).slice(2)}`,chatJid:e,senderId:`cone`,senderName:n,content:t,timestamp:new Date().toISOString(),fromAssistant:!0,channel:`delegation`};await ve(i),this.callbacks.onIncomingMessage?.(e,i),Q.info(`Delegating to scoop`,{scoopJid:e,scoopName:r.name,promptLength:t.length}),this.sendPrompt(e,t,`cone`,n).catch(t=>{let n=t instanceof Error?t.message:String(t);Q.error(`Delegation failed`,{scoopJid:e,error:n}),this.callbacks.onError(e,`Delegation failed: ${n}`)})}async routeToScoop(e){let t=this.scoops.get(e.chatJid);if(!t){Q.info(`routeToScoop: unregistered target`,{chatJid:e.chatJid});return}let n=e.channel===`webhook`||e.channel===`cron`||e.channel===`fswatch`||e.channel===`sprinkle`;if(!t.isCone&&t.requiresTrigger&&t.trigger&&!n&&!e.content.includes(t.trigger)){Q.info(`routeToScoop: trigger not found in content`,{chatJid:e.chatJid,trigger:t.trigger,contentPreview:e.content.slice(0,80)});return}let r=this.messageQueues.get(e.chatJid)??[];r.push(e),this.messageQueues.set(e.chatJid,r);let i=this.tabs.get(e.chatJid);if(Q.debug(`routeToScoop: queued`,{chatJid:e.chatJid,scoopName:t.name,tabStatus:i?.status??`no-tab`,queueLength:r.length}),i?.status===`error`){Q.info(`routeToScoop: tab in error state, retrying init`,{chatJid:e.chatJid});try{await this.createScoopTab(e.chatJid),i=this.tabs.get(e.chatJid)}catch{Q.warn(`routeToScoop: retry init failed`,{chatJid:e.chatJid})}}i?.status===`ready`&&await this.processScoopQueue(e.chatJid)}async createScoopTab(e){let t=this.scoops.get(e);if(!t)throw Error(`Scoop not found: ${e}`);if(this.contexts.has(e))if(this.tabs.get(e)?.status===`error`)Q.info(`Re-creating context after error`,{jid:e}),this.contexts.get(e)?.dispose(),this.contexts.delete(e),this.tabs.delete(e);else{Q.debug(`Context already exists`,{jid:e});return}if(!this.sharedFs)throw Error(`Shared filesystem not initialized`);let n=`scoop-${t.folder}-${Date.now()}`,r=t.isCone?this.sharedFs:new ue(this.sharedFs,t.config?.writablePaths?[...t.config.writablePaths]:[],t.config?.visiblePaths?[...t.config.visiblePaths]:[]),i=new Ox(t,{onResponse:(n,r)=>{if(this.scoops.has(e)&&(this.callbacks.onResponse(e,n,r),this.dispatchScoopEvent(e,`onResponse`,n,r),!t.isCone))if(r){let t=this.scoopResponseBuffer.get(e)??``;this.scoopResponseBuffer.set(e,t+n)}else this.scoopResponseBuffer.set(e,n)},onResponseDone:()=>{if(!this.scoops.has(e))return;let t=this.tabs.get(e);t&&(t.lastActivity=new Date().toISOString(),this.tabs.set(e,t)),this.callbacks.onResponseDone(e)},onError:t=>{if(!this.scoops.has(e))return;let n=this.tabs.get(e);n&&(n.status=`error`,n.error=t,this.tabs.set(e,n)),this.callbacks.onError(e,t),this.callbacks.onStatusChange(e,`error`),this.dispatchScoopEvent(e,`onError`,t),this.dispatchScoopEvent(e,`onStatusChange`,`error`)},onStatusChange:n=>{if(!this.scoops.has(e))return;let r=this.tabs.get(e);r&&(r.status=n,r.lastActivity=new Date().toISOString(),this.tabs.set(e,r)),this.callbacks.onStatusChange(e,n),this.dispatchScoopEvent(e,`onStatusChange`,n),n===`ready`&&!t.isCone&&this.maybeNotifyConeOnScoopComplete(e)},onToolStart:(t,n)=>{this.callbacks.onToolStart?.(e,t,n)},onToolEnd:(t,n,r)=>{this.callbacks.onToolEnd?.(e,t,n,r)},onToolUI:(t,n,r)=>{this.callbacks.onToolUI?.(e,t,n,r)},onToolUIDone:t=>{this.callbacks.onToolUIDone?.(e,t)},onSendMessage:(t,n)=>{let r=`${n?`[${n}] `:``}${t}`;this.callbacks.onSendMessage(e,r),this.dispatchScoopEvent(e,`onSendMessage`,t)},getScoops:()=>this.getScoops(),getScoopTabState:t.isCone?e=>this.tabs.get(e):void 0,onFeedScoop:t.isCone?(e,n)=>this.delegateToScoop(e,n,t.assistantLabel):void 0,onScoopScoop:t.isCone?async e=>{let t={...e,jid:`scoop_${e.folder}_${Date.now()}`};return await this.registerScoop(t),t}:void 0,onDropScoop:t.isCone?async e=>{await this.unregisterScoop(e)}:void 0,getGlobalMemory:()=>this.getGlobalMemory(),setGlobalMemory:t.isCone?e=>this.setGlobalMemory(e):void 0,getBrowserAPI:()=>this.callbacks.getBrowserAPI()},r,this.sessionStore??void 0,this.sharedFs??void 0);this.contexts.set(e,i),this.tabs.set(e,{jid:e,contextId:n,status:`initializing`,lastActivity:new Date().toISOString()}),await i.init();let a=this.tabs.get(e);a&&a.status===`initializing`&&(a.status=`ready`,this.tabs.set(e,a),this.callbacks.onStatusChange(e,`ready`),this.dispatchScoopEvent(e,`onStatusChange`,`ready`));let o=this.scoops.get(e);o&&!o.isCone&&this.startIdleTimer(e),Q.info(`Scoop context created`,{jid:e,contextId:n})}async destroyScoopTab(e){this.clearIdleTimer(e);let t=this.contexts.get(e);t&&(t.dispose(),this.contexts.delete(e),this.tabs.delete(e),this.scoopObservers.delete(e),Q.info(`Scoop context destroyed`,{jid:e}))}isProcessing(e){return this.tabs.get(e)?.status===`processing`}getScoopContext(e){return this.contexts.get(e)}async clearQueuedMessages(e){let t=this.messageQueues.get(e);if(t&&t.length>0){for(let e of t)await je(e.id);this.messageQueues.set(e,[])}}async deleteQueuedMessage(e,t){let n=this.messageQueues.get(e);if(n){let e=n.findIndex(e=>e.id===t);e!==-1&&n.splice(e,1)}await je(t)}async getMessagesForScoop(e){return G(e)}async waitForTabReady(e,t=1e4){let n=Date.now();for(;Date.now()-n<t;){let t=this.tabs.get(e);if(!t)return!1;if(t.status===`ready`||t.status===`processing`)return!0;if(t.status===`error`)return!1;await new Promise(e=>setTimeout(e,100))}return Q.warn(`Timed out waiting for tab to become ready`,{jid:e}),!1}async sendPrompt(e,t,n,r){let i=this.contexts.get(e);i||=(await this.createScoopTab(e),this.contexts.get(e));let a=this.tabs.get(e);if(a?.status===`initializing`){if(Q.debug(`Context initializing, waiting to send message`,{jid:e}),!await this.waitForTabReady(e)){Q.error(`Context did not become ready in time, dropping prompt`,{jid:e});return}i=this.contexts.get(e),a=this.tabs.get(e)}if(!i){Q.error(`Context not found after creation`,{jid:e});return}this.clearIdleTimer(e),this.scoopResponseBuffer.delete(e),a&&(a.status=`processing`,a.lastActivity=new Date().toISOString(),this.tabs.set(e,a),this.callbacks.onStatusChange(e,`processing`),this.dispatchScoopEvent(e,`onStatusChange`,`processing`)),Q.debug(`Prompt sent to scoop`,{jid:e,textLength:t.length}),await i.prompt(t)}async processScoopQueue(e){let t=this.messageQueues.get(e);if(!t||t.length===0){Q.debug(`processScoopQueue: empty queue`,{jid:e});return}let n=this.tabs.get(e);if(n?.status!==`ready`){Q.debug(`processScoopQueue: tab not ready`,{jid:e,status:n?.status??`no-tab`});return}let r=this.scoops.get(e),i=r?.assistantLabel??e,a=this.lastAgentTimestamp.get(e)??``,o=await Se(e,a,i);if(Q.debug(`processScoopQueue: DB query`,{jid:e,scoopName:r?.name,excludeName:i,since:a,dbMessageCount:o.length,queueLength:t.length}),o.length===0){Q.debug(`processScoopQueue: no messages from DB, clearing queue`,{jid:e}),this.messageQueues.set(e,[]);return}let s=o.map(e=>`[${new Date(e.timestamp).toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`,hour12:!0})}] ${e.senderName}: ${e.content}`).join(`
13303
+ `);this.messageQueues.set(e,[]);let c=o[o.length-1];this.lastAgentTimestamp.set(e,c.timestamp),await Ie(`lastAgentTs_${e}`,c.timestamp),await this.sendPrompt(e,s,c.senderId,c.senderName)}startMessageLoop(){this.pollInterval||=window.setInterval(()=>{for(let e of this.scoops.keys())this.tabs.get(e)?.status===`ready`&&this.processScoopQueue(e).catch(t=>{let n=t instanceof Error?t.message:String(t);Q.error(`Message queue processing failed`,{jid:e,error:n}),this.callbacks.onError(e,`Queue processing failed: ${n}`)})},2e3)}stopMessageLoop(){this.pollInterval&&=(clearInterval(this.pollInterval),null)}updateModel(){for(let e of this.contexts.values())e.updateModel();Q.info(`Model updated on all active contexts`,{contextCount:this.contexts.size})}async reloadAllSkills(){let e=[];for(let[t,n]of this.contexts){let r=this.tabs.get(t);(r?.status===`ready`||r?.status===`processing`)&&e.push(n.reloadSkills().catch(e=>{Q.warn(`Failed to reload skills for scoop`,{jid:t,error:e instanceof Error?e.message:String(e)})}))}await Promise.all(e),Q.info(`Skills reloaded across all contexts`,{count:e.length})}stopScoop(e){let t=this.contexts.get(e);t&&t.stop()}buildScoopCost(e,t){let n=t.getAgentMessages().filter(e=>e.role===`assistant`);if(n.length===0)return null;let r={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},i=new Map;for(let e of n)r.input+=e.usage.input,r.output+=e.usage.output,r.cacheRead+=e.usage.cacheRead,r.cacheWrite+=e.usage.cacheWrite,r.totalTokens+=e.usage.totalTokens,r.cost.input+=e.usage.cost.input,r.cost.output+=e.usage.cost.output,r.cost.cacheRead+=e.usage.cost.cacheRead,r.cost.cacheWrite+=e.usage.cost.cacheWrite,r.cost.total+=e.usage.cost.total,i.set(e.model,(i.get(e.model)??0)+1);let a=``,o=0;for(let[e,t]of i)t>o&&(a=e,o=t);let s=n.map(e=>e.timestamp).sort((e,t)=>e-t),c=s[0],l=s[s.length-1],u=900*1e3,d=l-c,f=Math.max(1,Math.ceil(d/u))*u;return{name:e.assistantLabel,type:e.isCone?`cone`:`scoop`,model:a,usage:r,turns:n.length,firstActivity:c,lastActivity:l,activeTimeMs:f}}snapshotScoopCost(e){let t=this.scoops.get(e),n=this.contexts.get(e);if(!t||!n)return;let r=this.buildScoopCost(t,n);r&&this.droppedScoopCosts.push(r)}getSessionCosts(){let e=[];for(let t of this.scoops.values()){let n=this.contexts.get(t.jid);if(!n)continue;let r=this.buildScoopCost(t,n);r&&e.push(r)}return e.push(...this.droppedScoopCosts),e}startIdleTimer(e){if(this.clearIdleTimer(e),this.tabs.get(e)?.status===`processing`)return;let t=setTimeout(()=>{this.idleTimers.delete(e);let t=this.scoops.get(e);if(!t||t.isCone||this.tabs.get(e)?.status!==`ready`)return;let n=Array.from(this.scoops.values()).find(e=>e.isCone);if(!n)return;let r={id:`scoop-idle-${e}-${Date.now()}`,chatJid:n.jid,senderId:t.folder,senderName:t.assistantLabel,content:`[@${t.assistantLabel} idle]: Scoop "${t.name}" has been ready for 2 minutes without receiving any work. This is expected if the scoop is waiting for webhooks or cron tasks. If you intended to delegate work, use feed_scoop to send a prompt.`,timestamp:new Date().toISOString(),fromAssistant:!1,channel:`scoop-idle`};Q.info(`Scoop idle timeout`,{jid:e,scoop:t.folder}),this.handleMessage(r).catch(t=>{let n=t instanceof Error?t.message:String(t);Q.error(`Failed to send idle notification`,{jid:e,error:n})})},Lx);this.idleTimers.set(e,t)}clearIdleTimer(e){let t=this.idleTimers.get(e);t&&(clearTimeout(t),this.idleTimers.delete(e))}async shutdown(){this.stopMessageLoop();for(let e of this.idleTimers.keys())this.clearIdleTimer(e);this.scheduler?.stop(),this.scheduler=null;for(let e of this.contexts.keys())await this.destroyScoopTab(e);Q.info(`Orchestrator shutdown`)}};r(`heartbeat`);var zx=r(`tray-follower`);function Bx(e){let t=new URL(e);return t.searchParams.set(`json`,`true`),t.toString()}async function Vx(e){let t=Bx(e.joinUrl),n=await Jx(await(e.fetchImpl??fetch)(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({controllerId:e.controllerId,runtime:e.runtime})}));return zx.info(`Follower tray attach response`,{trayId:n.trayId,action:n.result.action,code:n.result.code,participantCount:n.participantCount}),Hx(n)}function Hx(e){let t={trayId:e.trayId,controllerId:e.controllerId,participantCount:e.participantCount,leader:e.leader,action:e.result.action,code:e.result.code,iceServers:e.iceServers};return e.result.action===`wait`?{...t,retryAfterMs:e.result.retryAfterMs}:e.result.action===`signal`?{...t,bootstrap:e.result.bootstrap}:e.result.action===`fail`?{...t,error:e.result.error}:t}async function Ux(e){return qx(await Yx(e,{action:`poll`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,cursor:e.cursor}))}async function Wx(e){return qx(await Yx(e,{action:`answer`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,answer:e.answer}))}async function Gx(e){return qx(await Yx(e,{action:`ice-candidate`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,candidate:e.candidate}))}async function Kx(e){return qx(await Yx(e,{action:`retry`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,runtime:e.runtime}))}function qx(e){return{trayId:e.trayId,controllerId:e.controllerId,participantCount:e.participantCount,leader:e.leader,bootstrap:e.bootstrap,events:e.events}}async function Jx(e){let t=null,n=null;try{t=await e.text(),n=JSON.parse(t)}catch{}if(!Xx(n)){let n=t?t.slice(0,200):`(empty)`;throw zx.warn(`Tray follower attach returned an invalid response`,{status:e.status,body:n}),Error(`Tray follower attach returned an invalid response (${e.status}): ${n}`)}return n}async function Yx(e,t){let n=Bx(e.joinUrl),r=await(e.fetchImpl??fetch)(n,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(t)}),i=await r.json().catch(()=>null);if(!Zx(i))throw Error(`Tray follower bootstrap returned an invalid response (${r.status})`);return i}function Xx(e){if(!e||typeof e!=`object`)return!1;let t=e;if(typeof t.trayId!=`string`||typeof t.controllerId!=`string`||t.role!==`follower`||typeof t.participantCount!=`number`)return!1;let n=t.result;if(!n||typeof n!=`object`)return!1;let r=n;return r.action===`wait`?(r.code===`LEADER_NOT_ELECTED`||r.code===`LEADER_NOT_CONNECTED`)&&typeof r.retryAfterMs==`number`:r.action===`signal`?r.code===`LEADER_CONNECTED`&&Qx(r.bootstrap):r.action===`fail`?(r.code===`INVALID_JOIN_CAPABILITY`||r.code===`TRAY_EXPIRED`)&&typeof r.error==`string`:!1}function Zx(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.trayId==`string`&&typeof t.controllerId==`string`&&t.role===`follower`&&typeof t.participantCount==`number`&&Qx(t.bootstrap)&&Array.isArray(t.events)}function Qx(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.controllerId==`string`&&typeof t.bootstrapId==`string`&&typeof t.attempt==`number`&&typeof t.state==`string`&&typeof t.expiresAt==`string`&&typeof t.cursor==`number`&&typeof t.maxRetries==`number`&&typeof t.retriesRemaining==`number`}var $x=t({AGENT_BRIDGE_GLOBAL_KEY:()=>tS,AGENT_SPAWN_REQUEST_TYPE:()=>nS,createAgentBridge:()=>rS,publishAgentBridge:()=>iS,publishAgentBridgeProxy:()=>aS}),eS=r(`agent-bridge`),tS=`__slicc_agent`,nS=`agent-spawn-request`;function rS(e,t,n=null,r={}){let i=r.generateName??lS,a=r.generateUid??oS,o=r.resolveModel??dS;function s(){for(let t=0;t<8;t++){let t=i(),n=`agent_${uS(t)}`;if(!e.getScoops().some(e=>e.jid===n))return t}return a()}function c(t){if(t===void 0)return null;let n=e.getScoops().find(e=>e.jid===t);if(!n)return null;let r=n.config?.modelId;return r&&r.length>0?r:null}async function l(r){let i=r.modelId;if(i!==void 0&&(i===``||o(i)===null))return{finalText:`agent: unknown model: ${i}`,exitCode:1};let a=i??c(r.parentJid)??``,l=s(),u=`agent-${l}`,d=`agent_${uS(l)}`,f=`/scoops/${u}`,p=fS(r.cwd),m={visiblePaths:pS(r),writablePaths:mS([p,`/shared/`,`${f}/`,`/tmp/`]),allowedCommands:r.allowedCommands};a&&(m.modelId=a);let h={jid:d,name:u,folder:u,isCone:!1,type:`scoop`,requiresTrigger:!1,assistantLabel:u,addedAt:new Date().toISOString(),config:m,configSchemaVersion:2,notifyOnComplete:!1},g=[],_=``,v=null,y=e.observeScoop(d,{onSendMessage:e=>{g.push(e)},onResponse:(e,t)=>{t?_+=e:_=e},onError:e=>{v===null&&(v=e)}});try{try{await e.registerScoop(h)}catch(e){return{finalText:v??hS(e),exitCode:1}}return await e.sendPrompt(d,r.prompt,`agent`,`agent`),v===null?{finalText:g.length>0?g[g.length-1]:_,exitCode:0}:{finalText:v,exitCode:1}}catch(e){return{finalText:v??hS(e),exitCode:1}}finally{y();try{await e.unregisterScoop(d)}catch(e){eS.warn(`unregisterScoop failed`,{jid:d,error:hS(e)})}try{await t.rm(f,{recursive:!0})}catch(e){gS(e,`ENOENT`)||eS.warn(`scratch folder cleanup failed`,{folder:u,error:hS(e)})}if(n)try{await n.delete(d)}catch(e){eS.warn(`sessionStore.delete failed`,{jid:d,error:hS(e)})}}}return{spawn:l}}function iS(e,t,n=null,r={}){let i=rS(e,t,n,r);return globalThis[tS]=i,eS.info(`agent bridge published on globalThis.__slicc_agent`),i}function aS(){let e={spawn(e){return new Promise((t,n)=>{let r=globalThis.chrome?.runtime;if(!r||typeof r.sendMessage!=`function`){n(Error(`agent: chrome.runtime.sendMessage not available`));return}let i=e=>{let i=r.lastError;if(i){n(Error(i.message??`chrome.runtime error`));return}if(e==null){n(Error(`agent: empty response from offscreen bridge`));return}let a=e;if(!a.ok){n(Error(a.error??`agent: offscreen bridge error`));return}if(!a.result){n(Error(`agent: offscreen bridge returned no result`));return}t(a.result)};try{r.sendMessage({source:`panel`,payload:{type:nS,options:e}},i)}catch(e){n(e instanceof Error?e:Error(String(e)))}})}};return globalThis[tS]=e,eS.info(`agent bridge proxy published on globalThis.__slicc_agent`),e}function oS(){let e=globalThis;return typeof e.crypto?.randomUUID==`function`?e.crypto.randomUUID().replace(/-/g,``).slice(0,12):`${Date.now().toString(36)}${Math.random().toString(36).slice(2,8)}`}var sS=`amber.bouncy.breezy.bubbly.cheeky.chilly.cozy.dapper.dreamy.eager.exuberant.fluffy.frosty.gentle.giddy.glossy.jolly.lucky.mellow.merry.nimble.plucky.quirky.salty.sleepy.snappy.sparkly.spiffy.sunny.sweet.toasty.velvety.whimsy.zesty`.split(`.`),cS=`blueberry.butterscotch.caramel.cherry.chocolate.cinnamon.coconut.coffee.cookies.custard.espresso.fudge.gelato.hazelnut.honeycomb.lavender.lemon.mango.maple.marzipan.matcha.mint.mocha.neapolitan.nougat.peach.pecan.pistachio.praline.raspberry.sherbet.sorbet.stracciatella.strawberry.tiramisu.toffee.vanilla`.split(`.`);function lS(){return`${sS[Math.floor(Math.random()*sS.length)]}-${cS[Math.floor(Math.random()*cS.length)]}`}function uS(e){return e.replace(/-/g,`_`)}function dS(e){try{let t=D();for(let n of t)if(n.models.some(t=>t.id===e))return e;return null}catch{return null}}function fS(e){let t=L(e);return t.endsWith(`/`)?t:`${t}/`}function pS(e){if(e.visiblePaths!==void 0)return e.visiblePaths.map(fS);let t=[`/workspace/`];return e.invokingCwd&&e.invokingCwd.length>0&&t.push(fS(e.invokingCwd)),mS(t)}function mS(e){let t=new Set,n=[];for(let r of e)t.has(r)||(t.add(r),n.push(r));return n}function hS(e){return e instanceof Error?e.message:String(e)}function gS(e,t){if(typeof e!=`object`||!e)return!1;let n=e.code;return typeof n==`string`&&n===t}var _S=r(`tray-webrtc`),vS=`tray-control`,yS=250,bS=class{peerConnectionFactory;dataChannelLabel;peers=new Map;iceServers;constructor(e){this.options=e,this.iceServers=e.iceServers,this.peerConnectionFactory=e.peerConnectionFactory??(()=>CS(this.iceServers)),this.dataChannelLabel=e.dataChannelLabel??vS}setIceServers(e){this.iceServers=e}async handleControlMessage(e){e.type===`follower.join_requested`?(e.iceServers&&!this.iceServers&&(this.iceServers=e.iceServers),await this.handleJoinRequested(e)):e.type===`bootstrap.answer`?await this.peers.get(e.bootstrapId)?.peer.setRemoteDescription(e.answer):e.type===`bootstrap.ice_candidate`&&await this.peers.get(e.bootstrapId)?.peer.addIceCandidate(e.candidate)}getPeers(){return Array.from(this.peers.values()).map(({state:e})=>({...e}))}getChannel(e){return this.peers.get(e)?.channel??null}stop(){for(let e of this.peers.values())e.peer.close();this.peers.clear()}async handleJoinRequested(e){this.closeControllerPeers(e.controllerId);let t=this.peerConnectionFactory(),n={controllerId:e.controllerId,bootstrapId:e.bootstrapId,attempt:e.attempt,state:`connecting`,connectedAt:null,runtime:e.runtime},r=t.createDataChannel(this.dataChannelLabel);this.peers.set(e.bootstrapId,{state:n,peer:t,channel:r}),t.addEventListener(`icecandidate`,({candidate:t})=>{let n=TS(t);n&&this.options.sendControlMessage({type:`bootstrap.ice_candidate`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,candidate:n})}),t.addEventListener(`connectionstatechange`,()=>{let n=this.peers.get(e.bootstrapId);n&&(n.state.state===`connected`?(t.connectionState===`disconnected`||t.connectionState===`failed`)&&(_S.warn(`Leader peer connection state changed post-connect`,{bootstrapId:e.bootstrapId,state:t.connectionState}),this.options.onPeerDisconnected?.(e.bootstrapId,`Peer connection ${t.connectionState}`)):t.connectionState===`failed`&&this.failPeer(e,`Leader peer connection failed before the data channel opened`))}),r.addEventListener(`open`,()=>{let t=this.peers.get(e.bootstrapId);!t||t.state.state===`connected`||(t.state.state=`connected`,t.state.connectedAt=new Date().toISOString(),this.options.onPeerConnected?.({...t.state},t.channel))}),r.addEventListener(`close`,()=>{let t=this.peers.get(e.bootstrapId);t&&(t.state.state===`connected`?(_S.warn(`Leader data channel closed post-connect`,{bootstrapId:e.bootstrapId}),this.options.onPeerDisconnected?.(e.bootstrapId,`Data channel closed`)):this.failPeer(e,`Leader data channel closed before opening`))}),r.addEventListener(`error`,()=>{let t=this.peers.get(e.bootstrapId);t&&(t.state.state===`connected`?(_S.warn(`Leader data channel error post-connect`,{bootstrapId:e.bootstrapId}),this.options.onPeerDisconnected?.(e.bootstrapId,`Data channel error`)):this.failPeer(e,`Leader data channel failed before opening`))});try{let n=await t.createOffer();await t.setLocalDescription(n),this.options.sendControlMessage({type:`bootstrap.offer`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,offer:wS(t.localDescription??n,`offer`)})}catch(t){this.failPeer(e,t instanceof Error?t.message:String(t))}}closeControllerPeers(e){for(let[t,n]of this.peers.entries())n.state.controllerId===e&&(n.peer.close(),this.peers.delete(t))}failPeer(e,t){let n=this.peers.get(e.bootstrapId);if(n){n.peer.close(),this.peers.delete(e.bootstrapId);try{this.options.sendControlMessage({type:`bootstrap.failed`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,code:`WEBRTC_BOOTSTRAP_FAILED`,message:t,retryable:!0,retryAfterMs:1e3})}catch(e){_S.warn(`Failed to report tray bootstrap failure`,{error:e instanceof Error?e.message:String(e)})}}}},xS=class{fetchImpl;peerConnectionFactory;controllerIdFactory;sleep;pollIntervalMs;iceServers;activePeer=null;stopped=!1;constructor(e){this.options=e,this.fetchImpl=e.fetchImpl??fetch,this.iceServers=e.iceServers,this.peerConnectionFactory=e.peerConnectionFactory??(()=>CS(this.iceServers)),this.controllerIdFactory=e.controllerIdFactory??(()=>crypto.randomUUID()),this.sleep=e.sleep??(e=>new Promise(t=>setTimeout(t,e))),this.pollIntervalMs=e.pollIntervalMs??yS}async start(){this.stopped=!1;let e=this.controllerIdFactory(),t=Date.now();m({state:`connecting`,joinUrl:this.options.joinUrl,trayId:null,error:null,lastPingTime:null,reconnectAttempts:0,attachAttempts:0,lastAttachCode:null,connectingSince:t,lastError:null}),_S.info(`Follower tray join starting`,{joinUrl:this.options.joinUrl});let n=0;for(;;){ES(this.stopped),n++;let t;try{t=await Vx({joinUrl:this.options.joinUrl,controllerId:e,runtime:this.options.runtime,fetchImpl:this.fetchImpl})}catch(e){let t=e instanceof Error?e.message:String(e);throw m({...g(),attachAttempts:n,lastError:t}),e}if(m({...g(),attachAttempts:n,lastAttachCode:t.code}),t.action===`wait`){let e=t.retryAfterMs??1e3;_S.info(`Follower tray attach waiting`,{attempt:n,code:t.code,retryAfterMs:e}),n%10==0&&_S.warn(`Follower tray attach still waiting after ${n} attempts`,{attempt:n,code:t.code,retryAfterMs:e}),await this.sleep(e);continue}if(t.action===`fail`||!t.bootstrap){let e=t.error??`Tray follower attach failed (${t.code})`;throw m({state:`error`,joinUrl:this.options.joinUrl,trayId:null,error:e,lastPingTime:null,reconnectAttempts:0,attachAttempts:n,lastAttachCode:t.code,connectingSince:null,lastError:e}),_S.warn(`Follower tray attach failed`,{error:e}),Error(e)}t.iceServers&&(this.iceServers=t.iceServers);try{let r=await this.completeBootstrap(t.trayId,e,t.bootstrap);return m({state:`connected`,joinUrl:this.options.joinUrl,trayId:r.trayId,error:null,lastPingTime:null,reconnectAttempts:0,attachAttempts:n,lastAttachCode:t.code,connectingSince:null,lastError:null}),_S.info(`Follower tray connected`,{trayId:r.trayId,controllerId:e}),r}catch(e){let r=e instanceof Error?e.message:String(e);throw m({state:`error`,joinUrl:this.options.joinUrl,trayId:t.trayId,error:r,lastPingTime:null,reconnectAttempts:0,attachAttempts:n,lastAttachCode:t.code,connectingSince:null,lastError:r}),_S.warn(`Follower tray bootstrap failed`,{error:r}),e}}}stop(){this.stopped=!0,this.activePeer?.peer.close(),this.activePeer?.channel?.close(),this.activePeer=null,m({state:`inactive`,joinUrl:null,trayId:null,error:null,lastPingTime:null,reconnectAttempts:0,attachAttempts:0,lastAttachCode:null,connectingSince:null,lastError:null})}async completeBootstrap(e,t,n){let r=n,i=0;for(this.activePeer=this.createFollowerPeer(t,r.bootstrapId);;){if(ES(this.stopped),this.activePeer.open&&this.activePeer.channel)return{trayId:e,controllerId:t,bootstrapId:r.bootstrapId,channel:this.activePeer.channel};if(this.activePeer.openError)throw Error(this.activePeer.openError);let n=await Ux({joinUrl:this.options.joinUrl,controllerId:t,bootstrapId:r.bootstrapId,cursor:i,fetchImpl:this.fetchImpl});r=n.bootstrap,i=r.cursor;try{for(let e of n.events)if(e.type===`bootstrap.offer`){await this.activePeer.peer.setRemoteDescription(e.offer);let n=await this.activePeer.peer.createAnswer();await this.activePeer.peer.setLocalDescription(n),await Wx({joinUrl:this.options.joinUrl,controllerId:t,bootstrapId:r.bootstrapId,answer:wS(this.activePeer.peer.localDescription??n,`answer`),fetchImpl:this.fetchImpl})}else if(e.type===`bootstrap.ice_candidate`)await this.activePeer.peer.addIceCandidate(e.candidate);else if(e.type===`bootstrap.failed`)throw Error(e.failure.message)}catch(e){if(r.failure?.retryable&&r.retriesRemaining>0){r=(await Kx({joinUrl:this.options.joinUrl,controllerId:t,bootstrapId:r.bootstrapId,runtime:this.options.runtime,fetchImpl:this.fetchImpl})).bootstrap,i=0,this.activePeer.peer.close(),this.activePeer=this.createFollowerPeer(t,r.bootstrapId);continue}throw e}this.activePeer.open||await this.sleep(this.pollIntervalMs)}}createFollowerPeer(e,t){let n=this.peerConnectionFactory(),r={peer:n,channel:null,open:!1,openError:null};return n.addEventListener(`connectionstatechange`,()=>{r.open&&(n.connectionState===`disconnected`||n.connectionState===`failed`)&&(_S.warn(`Follower peer connection state changed post-connect`,{bootstrapId:t,state:n.connectionState}),this.options.onDisconnected?.(`Peer connection ${n.connectionState}`))}),n.addEventListener(`datachannel`,({channel:e})=>{r.channel=e,e.addEventListener(`open`,()=>{r.open=!0}),e.addEventListener(`close`,()=>{r.open?(_S.warn(`Follower data channel closed post-connect`,{bootstrapId:t}),this.options.onDisconnected?.(`Data channel closed`)):r.openError=`Follower data channel closed before opening`}),e.addEventListener(`error`,()=>{r.open?(_S.warn(`Follower data channel error post-connect`,{bootstrapId:t}),this.options.onDisconnected?.(`Data channel error`)):r.openError=`Follower data channel failed before opening`})}),n.addEventListener(`icecandidate`,({candidate:n})=>{let r=TS(n);r&&Gx({joinUrl:this.options.joinUrl,controllerId:e,bootstrapId:t,candidate:r,fetchImpl:this.fetchImpl}).catch(e=>{_S.warn(`Failed to send follower ICE candidate`,{error:e instanceof Error?e.message:String(e)})})}),r}};function SS(e,t){let n=t.baseDelayMs??1e3,r=t.backoffMultiplier??2,i=t.maxDelayMs??3e4,a=t.maxAttempts??10,o=t.sleep??e.sleep??(e=>new Promise(t=>setTimeout(t,e))),s=!1,c=!1,l=null,u={cancel(){s=!0,c=!1,l?.stop(),l=null},get reconnecting(){return c}},d=()=>{let t=new xS({...e,sleep:o,onDisconnected:e=>{s||(_S.warn(`Follower disconnected, starting reconnect loop`,{reason:e}),f(e))}});return l=t,{manager:t,connectionPromise:t.start()}},f=async u=>{if(s||c)return;c=!0,l?.stop(),l=null;let f=0,p=n,h=u??`Unknown disconnect`;for(;!s&&f<a&&(f++,t.onReconnecting?.(f),m({...g(),state:`reconnecting`,error:null,reconnectAttempts:f}),_S.info(`Reconnect attempt`,{attempt:f,delay:p}),await o(p),!s);){let n=null;try{let r=d();n=r.manager;let i=await r.connectionPromise;if(s){n.stop();break}c=!1,m({...g(),state:`connected`,joinUrl:e.joinUrl,trayId:i.trayId,error:null,lastPingTime:null,reconnectAttempts:0,connectingSince:null,lastError:null}),_S.info(`Reconnect successful`,{attempt:f,trayId:i.trayId}),t.onConnected(i);return}catch(e){h=e instanceof Error?e.message:String(e),_S.warn(`Reconnect attempt failed`,{attempt:f,error:h}),n?.stop(),l=null}p=Math.min(p*r,i)}s||(c=!1,m({...g(),state:`error`,error:`Reconnect failed after ${f} attempts: ${h}`,reconnectAttempts:f}),_S.warn(`Reconnect gave up`,{attempts:f,lastError:h}),t.onGaveUp?.(h))},{connectionPromise:p}=d();return p.then(e=>{s||t.onConnected(e)}).catch(e=>{s||_S.warn(`Initial follower connection failed`,{error:e instanceof Error?e.message:String(e)})}),u}function CS(e){if(typeof RTCPeerConnection>`u`)throw Error(`RTCPeerConnection is not available in this runtime`);let t=e?.length?{iceServers:e}:void 0;return new RTCPeerConnection(t)}function wS(e,t){if(!e||e.type!==t||typeof e.sdp!=`string`)throw Error(`Expected a local ${t} description before signaling`);return{type:e.type,sdp:e.sdp}}function TS(e){if(!e||typeof e!=`object`)return null;let t=e;return typeof t.candidate==`string`?{candidate:t.candidate,sdpMid:typeof t.sdpMid==`string`?t.sdpMid:null,sdpMLineIndex:typeof t.sdpMLineIndex==`number`?t.sdpMLineIndex:null,usernameFragment:typeof t.usernameFragment==`string`?t.usernameFragment:null}:null}function ES(e){if(e)throw Error(`Tray follower stopped before WebRTC bootstrap completed`)}var DS=64*1024;async function OS(e,t){try{switch(t.op){case`readFile`:return await kS(e,t.path,t.encoding);case`writeFile`:return[await AS(e,t.path,t.content,t.encoding)];case`stat`:return[await jS(e,t.path)];case`readDir`:return[await MS(e,t.path)];case`mkdir`:return[await NS(e,t.path,t.recursive)];case`rm`:return[await PS(e,t.path,t.recursive)];case`exists`:return[await FS(e,t.path)];case`walk`:return[await IS(e,t.path)];default:return[{ok:!1,error:`Unknown fs operation: ${t.op}`}]}}catch(e){return[RS(e)]}}async function kS(e,t,n){return(n??`utf-8`)===`utf-8`?LS(await e.readFile(t,{encoding:`utf-8`}),`utf-8`):LS(zS(await e.readFile(t,{encoding:`binary`})),`base64`)}async function AS(e,t,n,r){if(r===`base64`){let r=BS(n);await e.writeFile(t,r)}else await e.writeFile(t,n);return{ok:!0,data:{type:`void`}}}async function jS(e,t){return{ok:!0,data:{type:`stat`,stat:await e.stat(t)}}}async function MS(e,t){return{ok:!0,data:{type:`dirEntries`,entries:await e.readDir(t)}}}async function NS(e,t,n){return await e.mkdir(t,{recursive:n}),{ok:!0,data:{type:`void`}}}async function PS(e,t,n){return await e.rm(t,{recursive:n}),{ok:!0,data:{type:`void`}}}async function FS(e,t){return{ok:!0,data:{type:`exists`,exists:await e.exists(t)}}}async function IS(e,t){let n=[];for await(let r of e.walk(t))n.push(r);return{ok:!0,data:{type:`paths`,paths:n}}}function LS(e,t){if(e.length<=DS)return[{ok:!0,data:{type:`file`,content:e,encoding:t}}];let n=Math.ceil(e.length/DS),r=[];for(let i=0;i<n;i++){let a=i*DS,o=e.slice(a,a+DS);r.push({ok:!0,data:{type:`file`,content:o,encoding:t},chunkIndex:i,totalChunks:n})}return r}function RS(e){return e instanceof Error&&`code`in e?{ok:!1,error:e.message,code:e.code}:{ok:!1,error:e instanceof Error?e.message:String(e)}}function zS(e){let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function BS(e){let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}var VS=class{runtimes=new Map;dirty=!1;setTargets(e,t){this.runtimes.set(e,t),this.dirty=!0}removeRuntime(e){this.runtimes.delete(e)&&(this.dirty=!0)}getEntries(){this.dirty=!1;let e=[];for(let[t,n]of this.runtimes)for(let r of n)e.push({targetId:`${t}:${r.targetId}`,localTargetId:r.targetId,runtimeId:t,title:r.title,url:r.url,isLocal:!1});return e}hasChanged(){return this.dirty}getRuntimeIds(){return[...this.runtimes.keys()]}},HS=r(`data-channel-keepalive`),US=class{sendPing;onDead;intervalMs;maxMissed;timer=null;missedPongs=0;awaitingPong=!1;stopped=!1;constructor(e){this.sendPing=e.sendPing,this.onDead=e.onDead,this.intervalMs=e.intervalMs??1e4,this.maxMissed=e.maxMissed??3}start(){this.timer||this.stopped||(this.timer=setInterval(()=>this.tick(),this.intervalMs))}stop(){this.stopped=!0,this.timer&&=(clearInterval(this.timer),null)}receivePong(){this.awaitingPong=!1,this.missedPongs=0}receivePing(){this.missedPongs=0,this.awaitingPong=!1}get missed(){return this.missedPongs}tick(){if(!this.stopped){if(this.awaitingPong&&(this.missedPongs++,HS.debug(`Missed pong`,{missedPongs:this.missedPongs,maxMissed:this.maxMissed}),this.missedPongs>=this.maxMissed)){HS.warn(`Channel declared dead`,{missedPongs:this.missedPongs}),this.stop(),this.onDead();return}this.awaitingPong=!0,this.sendPing()}}},WS=r(`tray-leader-sync`);function GS(e){return e?e.includes(`standalone`)?`standalone`:e.includes(`extension`)?`extension`:e.includes(`electron`)?`electron`:`unknown`:`unknown`}var KS=class{followers=new Map;registry=new VS;runtimeToBootstrap=new Map;pendingCDPRoutes=new Map;cdpChunkBuffers=new Map;remoteTransports=new Map;pendingTabOpenRoutes=new Map;tabOpenResolvers=new Map;pendingFsRoutes=new Map;fsResolvers=new Map;constructor(e){this.options=e}addFollower(e,t,n){this.removeFollower(e);let r=he(t),i=r.onMessage(t=>{this.handleFollowerMessage(e,t)}),a=new US({sendPing:()=>r.send({type:`ping`}),onDead:()=>{WS.warn(`Follower keepalive dead, removing follower`,{bootstrapId:e}),this.removeFollower(e),this.options.onFollowerDead?.(e)}});a.start(),this.followers.set(e,{bootstrapId:e,sync:r,unsubscribe:i,keepalive:a,runtime:n?.runtime,connectedAt:n?.connectedAt,lastActivity:Date.now(),floatType:GS(n?.runtime)}),WS.info(`Follower added to sync`,{bootstrapId:e,followerCount:this.followers.size}),this.sendSnapshotToFollower(e);let o=this.getConnectedEntries();o.length>0&&r.send({type:`targets.registry`,targets:o})}removeFollower(e){let t=this.followers.get(e);if(t){t.keepalive.stop(),t.unsubscribe(),t.sync.close(),this.followers.delete(e);for(let[t,n]of this.runtimeToBootstrap)if(n===e){this.cleanupRemoteTransports(t),this.registry.removeRuntime(t),this.runtimeToBootstrap.delete(t);break}this.registry.hasChanged()&&this.broadcastTargetRegistry(),WS.info(`Follower removed from sync`,{bootstrapId:e,followerCount:this.followers.size})}}broadcastEvent(e){if(this.followers.size===0)return;let t={type:`agent_event`,event:e,scoopJid:this.options.getScoopJid()};for(let e of this.followers.values())e.sync.send(t)}broadcastUserMessage(e,t){if(this.followers.size===0)return;let n={type:`user_message_echo`,text:e,messageId:t,scoopJid:this.options.getScoopJid()};for(let e of this.followers.values())e.sync.send(n)}broadcastStatus(e){if(this.followers.size===0)return;let t={type:`status`,scoopStatus:e};for(let e of this.followers.values())e.sync.send(t)}sendSnapshotToFollower(e){let t=this.followers.get(e);if(!t)return;let n=this.options.getMessages(),r=this.options.getScoopJid();z(t.sync,n,r),WS.debug(`Snapshot sent to follower`,{bootstrapId:e,messageCount:n.length})}handleFollowerMessage(e,t){switch(t.type){case`user_message`:WS.info(`Follower user message received`,{bootstrapId:e,messageId:t.messageId}),this.options.onFollowerMessage(t.text,t.messageId);break;case`abort`:WS.info(`Follower abort received`,{bootstrapId:e}),this.options.onFollowerAbort();break;case`request_snapshot`:WS.info(`Follower snapshot request received`,{bootstrapId:e}),this.sendSnapshotToFollower(e);break;case`targets.advertise`:WS.info(`Follower targets advertised`,{bootstrapId:e,runtimeId:t.runtimeId,targetCount:t.targets.length});for(let e of[...this.remoteTransports.keys()]){let n=e.substring(0,e.indexOf(`:`));n!==`leader`&&!this.runtimeToBootstrap.has(n)&&n!==t.runtimeId&&(this.remoteTransports.get(e)?.disconnect(),this.remoteTransports.delete(e),WS.debug(`Cleaned up orphaned remote transport on advertise`,{key:e}))}this.runtimeToBootstrap.set(t.runtimeId,e),this.registry.setTargets(t.runtimeId,t.targets),this.broadcastTargetRegistry();break;case`cdp.request`:{let{requestId:n,targetRuntimeId:r,localTargetId:i,method:a,params:o,sessionId:s}=t;r===`leader`?this.executeLocalCDP(n,i,a,o,s,e):this.forwardCDPRequest(n,r,i,a,o,s,e);break}case`cdp.response`:this.handleCDPResponse(t);break;case`cdp.event`:this.handleCDPEvent(e,t.method,t.params,t.sessionId);break;case`tab.open`:{let{requestId:n,targetRuntimeId:r,url:i}=t;r===`leader`?this.executeLocalTabOpen(n,i,e):this.forwardTabOpen(n,r,i,e);break}case`tab.opened`:this.handleTabOpenResponse(t.requestId,t.targetId);break;case`tab.open.error`:this.handleTabOpenError(t.requestId,t.error);break;case`fs.request`:{let{requestId:n,targetRuntimeId:r,request:i}=t;r===`leader`?this.executeLocalFs(n,i,e):this.forwardFsRequest(n,r,i,e);break}case`fs.response`:this.handleFsResponse(t.requestId,t.response);break;case`ping`:{let t=this.followers.get(e);t&&(t.keepalive.receivePing(),t.lastActivity=Date.now(),t.sync.send({type:`pong`}));break}case`pong`:{let t=this.followers.get(e);t&&(t.keepalive.receivePong(),t.lastActivity=Date.now());break}}}setLocalTargets(e){this.registry.setTargets(`leader`,e),this.registry.hasChanged()&&this.broadcastTargetRegistry()}broadcastTargetRegistry(){if(this.followers.size===0)return;let e={type:`targets.registry`,targets:this.getConnectedEntries()};for(let t of this.followers.values())t.sync.send(e)}getTargets(){return this.getConnectedEntries()}getConnectedEntries(){return this.registry.getEntries().filter(e=>{if(e.runtimeId===`leader`)return!0;let t=this.runtimeToBootstrap.get(e.runtimeId);return t?this.followers.has(t):!1})}createRemoteTransport(e,t){let n=new ge({sendCDPRequest:(n,r,i,a)=>{let o=this.runtimeToBootstrap.get(e),s=o?this.followers.get(o):void 0;if(!s){this.remoteTransports.get(`${e}:${t}`)?.handleResponse(n,void 0,`Target runtime "${e}" not connected`);return}this.pendingCDPRoutes.set(n,{requesterBootstrapId:`__leader__`,requestId:n}),s.sync.send({type:`cdp.request`,requestId:n,localTargetId:t,method:r,params:i,sessionId:a})}});return this.remoteTransports.set(`${e}:${t}`,n),n}removeRemoteTransport(e,t){let n=`${e}:${t}`,r=this.remoteTransports.get(n);r&&(r.disconnect(),this.remoteTransports.delete(n))}cleanupRemoteTransports(e){let t=`${e}:`;for(let e of[...this.remoteTransports.keys()])e.startsWith(t)&&(this.remoteTransports.get(e)?.disconnect(),this.remoteTransports.delete(e),WS.debug(`Cleaned up stale remote transport`,{key:e}))}getConnectedFollowers(){return[...this.runtimeToBootstrap.entries()].map(([e,t])=>{let n=this.followers.get(t);return{runtimeId:e,runtime:n?.runtime,connectedAt:n?.connectedAt,lastActivity:n?.lastActivity,floatType:n?.floatType}})}getBestFollowerForTeleport(){let e=[];for(let[t,n]of this.runtimeToBootstrap){let r=this.followers.get(n);r&&e.push({runtimeId:t,bootstrapId:n,floatType:r.floatType,lastActivity:r.lastActivity})}if(e.length===0)return null;let t=e.filter(e=>e.floatType===`standalone`),n=t.length>0?t:e;return n.sort((e,t)=>t.lastActivity-e.lastActivity),n[0]}get hasFollowers(){return this.followers.size>0}stop(){for(let e of[...this.followers.keys()])this.removeFollower(e)}async executeLocalCDP(e,t,n,r,i,a){let o=this.followers.get(a);if(!o)return;let s=this.options.browserTransport;if(!s){o.sync.send({type:`cdp.response`,requestId:e,error:`Leader has no browser transport`});return}try{let t=await s.send(n,r,i);U(o.sync,e,t)}catch(t){o.sync.send({type:`cdp.response`,requestId:e,error:t instanceof Error?t.message:String(t)})}}forwardCDPRequest(e,t,n,r,i,a,o){let s=this.runtimeToBootstrap.get(t),c=s?this.followers.get(s):void 0,l=this.followers.get(o);if(!c){l&&l.sync.send({type:`cdp.response`,requestId:e,error:`Target runtime "${t}" not connected`});return}this.pendingCDPRoutes.set(e,{requesterBootstrapId:o,requestId:e}),c.sync.send({type:`cdp.request`,requestId:e,localTargetId:n,method:r,params:i,sessionId:a})}handleCDPResponse(e){let{requestId:t,result:n,error:r,chunkData:i,chunkIndex:a,totalChunks:o}=e,s=this.pendingCDPRoutes.get(t);if(!s)return;let c=pe(this.cdpChunkBuffers,e);if(!c)return;if(this.pendingCDPRoutes.delete(t),s.requesterBootstrapId===`__leader__`){for(let e of this.remoteTransports.values())e.handleResponse(t,c.result,c.error);return}let l=this.followers.get(s.requesterBootstrapId);l&&U(l.sync,t,c.result,c.error)}handleCDPEvent(e,t,n,r){let i;for(let[t,n]of this.runtimeToBootstrap)if(n===e){i=t;break}if(!i)return;let a=`${i}:`;for(let[e,r]of this.remoteTransports)e.startsWith(a)&&r.handleEvent(t,n)}openRemoteTab(e,t){let n=this.runtimeToBootstrap.get(e),r=n?this.followers.get(n):void 0;if(!r)return Promise.reject(Error(`Target runtime "${e}" not connected`));let i=`tab-open-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;return new Promise((e,n)=>{this.tabOpenResolvers.set(i,{resolve:e,reject:n}),this.pendingTabOpenRoutes.set(i,{requesterBootstrapId:`__leader__`,requestId:i}),r.sync.send({type:`tab.open`,requestId:i,url:t})})}async executeLocalTabOpen(e,t,n){let r=this.followers.get(n);if(!r)return;let i=this.options.browserTransport;if(!i){r.sync.send({type:`tab.open.error`,requestId:e,error:`Leader has no browser transport`});return}try{let n=(await i.send(`Target.createTarget`,{url:t,background:!0})).targetId;r.sync.send({type:`tab.opened`,requestId:e,targetId:`leader:${n}`})}catch(t){r.sync.send({type:`tab.open.error`,requestId:e,error:t instanceof Error?t.message:String(t)})}}forwardTabOpen(e,t,n,r){let i=this.runtimeToBootstrap.get(t),a=i?this.followers.get(i):void 0,o=this.followers.get(r);if(!a){o&&o.sync.send({type:`tab.open.error`,requestId:e,error:`Target runtime "${t}" not connected`});return}this.pendingTabOpenRoutes.set(e,{requesterBootstrapId:r,requestId:e}),a.sync.send({type:`tab.open`,requestId:e,url:n})}handleTabOpenResponse(e,t){let n=this.pendingTabOpenRoutes.get(e);if(!n)return;if(this.pendingTabOpenRoutes.delete(e),n.requesterBootstrapId===`__leader__`){let n=this.tabOpenResolvers.get(e);n&&(this.tabOpenResolvers.delete(e),n.resolve(t));return}let r=this.followers.get(n.requesterBootstrapId);r&&r.sync.send({type:`tab.opened`,requestId:e,targetId:t})}handleTabOpenError(e,t){let n=this.pendingTabOpenRoutes.get(e);if(!n)return;if(this.pendingTabOpenRoutes.delete(e),n.requesterBootstrapId===`__leader__`){let n=this.tabOpenResolvers.get(e);n&&(this.tabOpenResolvers.delete(e),n.reject(Error(t)));return}let r=this.followers.get(n.requesterBootstrapId);r&&r.sync.send({type:`tab.open.error`,requestId:e,error:t})}async executeLocalFs(e,t,n){let r=this.followers.get(n);if(!r)return;let i=this.options.vfs;if(!i){r.sync.send({type:`fs.response`,requestId:e,response:{ok:!1,error:`Leader has no VFS`}});return}let a=await OS(i,t);for(let t of a)r.sync.send({type:`fs.response`,requestId:e,response:t})}forwardFsRequest(e,t,n,r){let i=this.runtimeToBootstrap.get(t),a=i?this.followers.get(i):void 0,o=this.followers.get(r);if(!a){o&&o.sync.send({type:`fs.response`,requestId:e,response:{ok:!1,error:`Target runtime "${t}" not connected`}});return}this.pendingFsRoutes.set(e,{requesterBootstrapId:r,requestId:e,chunks:[],totalChunks:1}),a.sync.send({type:`fs.request`,requestId:e,request:n})}handleFsResponse(e,t){let n=this.pendingFsRoutes.get(e);if(!n){let n=this.fsResolvers.get(e);if(n){n.responses.push(t);let r=t.ok&&t.totalChunks||1;n.responses.length>=r&&(this.fsResolvers.delete(e),n.resolve(n.responses))}return}if(n.requesterBootstrapId===`__leader__`){let n=this.fsResolvers.get(e);if(n){n.responses.push(t);let r=t.ok&&t.totalChunks||1;n.responses.length>=r&&(this.fsResolvers.delete(e),this.pendingFsRoutes.delete(e),n.resolve(n.responses))}return}let r=this.followers.get(n.requesterBootstrapId);r&&r.sync.send({type:`fs.response`,requestId:e,response:t}),n.chunks.push(t),n.totalChunks=t.ok&&t.totalChunks||1,n.chunks.length>=n.totalChunks&&this.pendingFsRoutes.delete(e)}sendFsRequest(e,t){if(e===`leader`){let e=this.options.vfs;return e?OS(e,t):Promise.resolve([{ok:!1,error:`Leader has no VFS`}])}let n=this.runtimeToBootstrap.get(e),r=n?this.followers.get(n):void 0;if(!r)return Promise.resolve([{ok:!1,error:`Target runtime "${e}" not connected`}]);let i=`fs-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;return new Promise((e,n)=>{this.fsResolvers.set(i,{resolve:e,reject:n,responses:[]}),this.pendingFsRoutes.set(i,{requesterBootstrapId:`__leader__`,requestId:i,chunks:[],totalChunks:1}),r.sync.send({type:`fs.request`,requestId:i,request:t})})}},qS=r(`tray-follower-sync`),JS=class{sync;eventListeners=new Set;unsubscribe;keepalive;latestSnapshot=null;sentMessageIds=new Set;targetEntries=[];remoteTransports=new Map;cdpChunkBuffers=new Map;snapshotChunkBuffer=null;remoteCDPSessions=new Set;cdpEventCleanups=[];tabOpenResolvers=new Map;fsResolvers=new Map;constructor(e,t={}){this.options=t,this.sync=_e(e),this.unsubscribe=this.sync.onMessage(e=>{this.handleLeaderMessage(e)}),this.keepalive=new US({sendPing:()=>this.sync.send({type:`ping`}),onDead:()=>{qS.warn(`Leader keepalive dead, cleaning up`),this.handleDisconnect(`Keepalive timeout — leader not responding`),this.options.onDead?.()}}),this.keepalive.start(),e.addEventListener(`close`,()=>{qS.warn(`Data channel closed`),this.handleDisconnect(`Data channel closed`)}),e.addEventListener(`error`,()=>{qS.warn(`Data channel error`),this.handleDisconnect(`Data channel error`)})}sendMessage(e,t){let n=t??`follower-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;this.sentMessageIds.add(n),this.sync.send({type:`user_message`,text:e,messageId:n}),qS.info(`Sent user message to leader`,{messageId:n})}onEvent(e){return this.eventListeners.add(e),()=>this.eventListeners.delete(e)}stop(){this.sync.send({type:`abort`}),qS.info(`Sent abort to leader`)}requestSnapshot(){this.sync.send({type:`request_snapshot`})}getLatestSnapshot(){return this.latestSnapshot}close(){this.keepalive.stop(),this.unsubscribe(),this.sync.close(),this.eventListeners.clear(),this.cleanupCDPEventForwarding(),qS.info(`Follower sync closed`)}advertiseTargets(e,t){this.sync.send({type:`targets.advertise`,targets:e,runtimeId:t})}getTargets(){return this.targetEntries}disconnected=!1;handleDisconnect(e){this.disconnected||(this.disconnected=!0,m({...g(),state:`error`,error:e}),this.emitEvent({type:`error`,error:`Connection to leader lost: ${e}`}),this.keepalive.stop(),this.cleanupCDPEventForwarding(),this.unsubscribe(),this.sync.close(),this.options.onDisconnect?.(e))}handleLeaderMessage(e){switch(e.type){case`snapshot`:qS.info(`Snapshot received from leader`,{messageCount:e.messages.length,scoopJid:e.scoopJid}),this.snapshotChunkBuffer=null,this.latestSnapshot={messages:e.messages,scoopJid:e.scoopJid},this.options.onSnapshot?.(e.messages,e.scoopJid);break;case`snapshot_chunk`:{let t=H(this.snapshotChunkBuffer,e);this.snapshotChunkBuffer=t.buffer,t.result&&(qS.info(`Chunked snapshot reassembled from leader`,{messageCount:t.result.messages.length,scoopJid:t.result.scoopJid}),this.latestSnapshot=t.result,this.options.onSnapshot?.(t.result.messages,t.result.scoopJid));break}case`agent_event`:this.emitEvent(e.event);break;case`user_message_echo`:if(this.sentMessageIds.has(e.messageId)){this.sentMessageIds.delete(e.messageId),qS.debug(`Skipping own message echo`,{messageId:e.messageId});break}qS.info(`User message echo received`,{messageId:e.messageId,scoopJid:e.scoopJid}),this.options.onUserMessage?.(e.text,e.messageId,e.scoopJid);break;case`status`:this.options.onStatus?.(e.scoopStatus);break;case`error`:qS.warn(`Error from leader`,{error:e.error}),this.emitEvent({type:`error`,error:e.error});break;case`targets.registry`:qS.info(`Target registry received from leader`,{targetCount:e.targets.length}),this.targetEntries=e.targets,this.options.onTargetsUpdated?.(this.targetEntries);break;case`cdp.request`:{let{requestId:t,localTargetId:n,method:r,params:i,sessionId:a}=e;this.executeLocalCDP(t,n,r,i,a);break}case`cdp.response`:this.routeCDPResponse(e);break;case`cdp.event`:for(let t of this.remoteTransports.values())t.handleEvent(e.method,e.params);break;case`tab.open`:this.executeLocalTabOpen(e.requestId,e.url);break;case`tab.opened`:{let t=this.tabOpenResolvers.get(e.requestId);t&&(this.tabOpenResolvers.delete(e.requestId),t.resolve(e.targetId));break}case`tab.open.error`:{let t=this.tabOpenResolvers.get(e.requestId);t&&(this.tabOpenResolvers.delete(e.requestId),t.reject(Error(e.error)));break}case`fs.request`:this.executeLocalFs(e.requestId,e.request);break;case`fs.response`:this.routeFsResponse(e.requestId,e.response);break;case`ping`:this.keepalive.receivePing(),this.sync.send({type:`pong`});break;case`pong`:this.keepalive.receivePong(),d(Date.now());break}}emitEvent(e){for(let t of this.eventListeners)try{t(e)}catch(t){qS.error(`Listener error`,{eventType:e.type,error:t instanceof Error?t.message:String(t)})}}createRemoteTransport(e,t){let n=new ge({sendCDPRequest:(n,r,i,a)=>{this.sync.send({type:`cdp.request`,requestId:n,targetRuntimeId:e,localTargetId:t,method:r,params:i,sessionId:a})}});return this.remoteTransports.set(`${e}:${t}`,n),n}removeRemoteTransport(e,t){let n=`${e}:${t}`,r=this.remoteTransports.get(n);r&&(r.disconnect(),this.remoteTransports.delete(n))}openRemoteTab(e,t){let n=`tab-open-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;return new Promise((r,i)=>{this.tabOpenResolvers.set(n,{resolve:r,reject:i}),this.sync.send({type:`tab.open`,requestId:n,targetRuntimeId:e,url:t})})}async executeLocalTabOpen(e,t){let n=this.options.browserTransport;if(!n){this.sync.send({type:`tab.open.error`,requestId:e,error:`Follower has no browser transport`});return}try{let r=(await n.send(`Target.createTarget`,{url:t,background:!0})).targetId;this.sync.send({type:`tab.opened`,requestId:e,targetId:r}),this.options.onTargetsChanged?.()}catch(t){this.sync.send({type:`tab.open.error`,requestId:e,error:t instanceof Error?t.message:String(t)})}}async executeLocalCDP(e,t,n,r,i){let a=this.options.browserTransport;if(!a){this.sync.send({type:`cdp.response`,requestId:e,error:`Follower has no browser transport`});return}try{let t=await a.send(n,r,i);if(n===`Target.attachToTarget`&&t.sessionId){let e=t.sessionId;this.remoteCDPSessions.add(e),this.setupCDPEventForwarding(a,e),qS.debug(`Tracking remote CDP session`,{remoteSessionId:e})}n===`Target.detachFromTarget`&&i&&this.remoteCDPSessions.has(i)&&(this.remoteCDPSessions.delete(i),qS.debug(`Removed remote CDP session on detach`,{sessionId:i})),U(this.sync,e,t)}catch(t){this.sync.send({type:`cdp.response`,requestId:e,error:t instanceof Error?t.message:String(t)})}}setupCDPEventForwarding(e,t){for(let n of[`Page.frameNavigated`,`Page.loadEventFired`,`Page.domContentEventFired`,`Network.responseReceived`,`Network.loadingFinished`,`Network.requestWillBeSent`]){let r=e=>{if(e.sessionId!==t||!this.remoteCDPSessions.has(t))return;let{sessionId:r,...i}=e;this.sync.send({type:`cdp.event`,method:n,params:i,sessionId:t})};e.on(n,r),this.cdpEventCleanups.push(()=>e.off(n,r))}}cleanupCDPEventForwarding(){for(let e of this.cdpEventCleanups)e();this.cdpEventCleanups.length=0,this.remoteCDPSessions.clear()}routeCDPResponse(e){let t=pe(this.cdpChunkBuffers,e);if(t)for(let n of this.remoteTransports.values())n.handleResponse(e.requestId,t.result,t.error)}async executeLocalFs(e,t){let n=this.options.vfs;if(!n){this.sync.send({type:`fs.response`,requestId:e,response:{ok:!1,error:`Follower has no VFS`}});return}let r=await OS(n,t);for(let t of r)this.sync.send({type:`fs.response`,requestId:e,response:t})}routeFsResponse(e,t){let n=this.fsResolvers.get(e);if(!n)return;n.responses.push(t);let r=t.ok&&t.totalChunks||1;n.responses.length>=r&&(this.fsResolvers.delete(e),n.resolve(n.responses))}sendFsRequest(e,t){let n=`fs-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;return new Promise((r,i)=>{this.fsResolvers.set(n,{resolve:r,reject:i,responses:[]}),this.sync.send({type:`fs.request`,requestId:n,targetRuntimeId:e,request:t})})}};function YS(e,t){if(t)return`extension`;try{return QS(new URL(e))?`electron-overlay`:`standalone`}catch{return`standalone`}}function XS(e,t){return e===`electron-overlay`||e===`standalone`&&t}function ZS(e){try{let t=new URL(e).searchParams.get(`tab`);return t&&$a(t)?t:Za}catch{return Za}}function QS(e){return e.pathname===`/electron`||e.pathname===`/electron/`||e.searchParams.get(`runtime`)===`electron-overlay`}function $S(e){let t=new URL(e);return`${t.protocol===`https:`?`wss:`:`ws:`}//${t.host}/licks-ws`}function eC(e,t){return`${new URL(e).origin}/webhooks/${t}`}function tC(e,t){return`${e.replace(/\/+$/,``)}/${t.replace(/^\/+/,``)}`}function nC(e){return typeof e==`object`&&!!e&&`type`in e&&e.type===`slicc-electron-overlay:set-tab`}var rC=[`/shared/sprinkles`];async function iC(e){let t=new Map;for(let n of rC)await e.exists(n)&&await aC(e,n,t);return await aC(e,`/`,t),t}async function aC(e,t,n){for await(let r of e.walk(t)){if(!r.endsWith(`.shtml`))continue;let t=oC(r);if(!n.has(t)){let i;try{i=await e.readFile(r,{encoding:`utf-8`})??``}catch{i=``}n.set(t,{name:t,path:r,title:sC(i,t),autoOpen:cC(i)})}}}function oC(e){let t=e.split(`/`).pop()??e;return t.endsWith(`.shtml`)?t.slice(0,-6):t}function sC(e,t){let n=e.match(/data-sprinkle-title=["']([^"']+)["']/);if(n)return n[1];let r=e.match(/<title>([^<]+)<\/title>/i);return r?r[1].trim():t}function cC(e){return/data-sprinkle-autoopen\b/.test(e)}var lC=r(`sprinkle-manager`),uC=`slicc-open-sprinkles`,dC=class{fs;bridge;callbacks;availableSprinkles=new Map;watcherUnsub;openSprinkles=new Map;constructor(e,t,n,r){this.fs=e,this.bridge=new Qg(e,t,e=>this.close(e),r),this.callbacks=n}async restoreOpenSprinkles(){try{let e=localStorage.getItem(uC);if(!e){for(let e of this.availableSprinkles.values())if(e.autoOpen)try{await this.open(e.name)}catch{lC.warn(`Failed to auto-open sprinkle`,{name:e.name})}return}let t=JSON.parse(e);for(let e of t)try{await this.open(e)}catch{lC.warn(`Failed to restore sprinkle`,{name:e})}}catch{}}persistOpenSprinkles(){try{localStorage.setItem(uC,JSON.stringify([...this.openSprinkles.keys()]))}catch{}}async openNewAutoOpenSprinkles(){await this.refresh();for(let e of this.availableSprinkles.values())if(e.autoOpen&&!this.openSprinkles.has(e.name))try{await this.open(e.name),lC.info(`Auto-opened new sprinkle after install`,{name:e.name})}catch{lC.warn(`Failed to auto-open new sprinkle`,{name:e.name})}}async refresh(){this.availableSprinkles=await iC(this.fs),lC.info(`Discovered sprinkles`,{count:this.availableSprinkles.size})}async open(e,t){if(this.openSprinkles.has(e)){lC.info(`Sprinkle already open`,{name:e});return}let n=this.availableSprinkles.get(e);if(n||=(await this.refresh(),this.availableSprinkles.get(e)),!n)throw Error(`Sprinkle not found: ${e}`);let r=await this.fs.readFile(n.path,{encoding:`utf-8`});if(r==null)throw Error(`Failed to read sprinkle content: ${n.path} (file may be corrupted or missing)`);let i=typeof r==`string`?r:new TextDecoder(`utf-8`).decode(r),a=document.createElement(`div`);a.className=`sprinkle-panel`,a.style.cssText=`width: 100%; height: 100%; display: flex; flex-direction: column; overflow: hidden;`,a.dataset.sprinkle=e,this.openSprinkles.set(e,{renderer:null,container:a}),this.callbacks.addSprinkle(e,n.title,a,t);let o=new gi(a,this.bridge.createAPI(e));await o.render(i,e),this.openSprinkles.get(e).renderer=o,this.persistOpenSprinkles(),hb(e),lC.info(`Sprinkle opened`,{name:e,title:n.title})}close(e){let t=this.openSprinkles.get(e);t&&(t.renderer?.dispose(),t.container.remove(),this.bridge.removeSprinkle(e),this.openSprinkles.delete(e),this.callbacks.removeSprinkle(e),this.persistOpenSprinkles(),lC.info(`Sprinkle closed`,{name:e}))}available(){return Array.from(this.availableSprinkles.values())}opened(){return Array.from(this.openSprinkles.keys())}setupWatcher(e){this.watcherUnsub=e.watch(`/workspace`,e=>e.endsWith(`.shtml`),()=>void this.refresh())}dispose(){this.watcherUnsub?.()}sendToSprinkle(e,t){let n=this.openSprinkles.get(e);if(!n){lC.warn(`Cannot send to closed sprinkle`,{name:e});return}this.bridge.pushUpdate(e,t),n.renderer.pushUpdate(t)}};async function fC(e,t,n){let r=[],i=[];for(let{path:a,handle:o}of e){let e=typeof o?.name==`string`?o.name:``;if(!o||!(`queryPermission`in o)){i.push({path:a,dirName:e});continue}let s;try{s=await o.queryPermission({mode:`readwrite`})}catch(t){n?.warn?.(`queryPermission threw on persisted handle`,{path:a,error:t instanceof Error?t.message:String(t)}),i.push({path:a,dirName:e});continue}if(s!==`granted`){i.push({path:a,dirName:e});continue}try{await t.mount(a,o),n?.info?.(`Restored mount from previous session`,{path:a,name:e}),r.push({path:a,dirName:e})}catch(t){n?.warn?.(`Failed to re-mount persisted handle`,{path:a,error:t instanceof Error?t.message:String(t)}),i.push({path:a,dirName:e})}}return{restored:r,needsRecovery:i}}function pC(e){return`'${e.replace(/'/g,`'\\''`)}'`}function mC(e){let t=e.replace(/\r\n|[\r\n]/g,` `),n=t.match(/`+/g),r=n?Math.max(...n.map(e=>e.length))+1:1,i="`".repeat(r);return`${i}${t.startsWith("`")||t.endsWith("`")?` ${t} `:t}${i}`}function hC(e){if(!Array.isArray(e)||e.length===0)return null;let t=e.map(({path:e,dirName:t})=>{let n=t?` (previously mounted from ${mC(t)})`:``;return`- ${mC(e)}${n}`}),n=e.map(({path:e})=>` mount ${pC(e)}`),r=e.length===1?`mount point`:`mount points`,i=e.length===1?`it`:`them`;return[`[Session Reload] Mount recovery required for ${e.length} ${r}.`,``,`The page was reloaded and the following ${r} lost filesystem permission. The browser cannot restore access without a fresh user gesture, so ${i} cannot be used until the user re-authorizes:`,``,...t,``,`Please tell the user what happened and ask whether they want to re-mount. If yes, run the corresponding command(s) so the folder picker opens and they can re-select the same directory:`,``,...n,``,"If the user no longer needs a mount, run `mount unmount <path>` (with the path shell-quoted the same way) to clear the stale entry instead."].join(`
13304
+ `)}var $=r(`main`),gC=`slicc-pending-mount`,_C=`pendingMount`,vC=new Set([`webhook`,`cron`,`sprinkle`,`fswatch`,`session-reload`,`navigate`]);function yC(e){return e!=null&&vC.has(e)}function bC(){try{let e=new URLSearchParams(window.location.search).get(`ui-fixture`);return e===null?!1:e===``||e===`1`||e.toLowerCase()===`true`}catch{return!1}}async function xC(e){let[{createChatFixture:t,FIXTURE_SESSION_ID:n,FIXTURE_SCOOP_NAME:r}]=await Promise.all([i(()=>import(`./chat-fixture-Nts2sMME.js`),[])]);await e.switchToContext(n,!0,r),e.loadMessages(t()),$.info(`Loaded UI fixture session for design iteration`)}async function SC(e){let t=await new Promise((e,t)=>{let n=indexedDB.open(gC,1);n.onupgradeneeded=()=>n.result.createObjectStore(`handles`),n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)}),n=t.transaction(`handles`,`readwrite`);n.objectStore(`handles`).put(e,_C),await new Promise(e=>n.oncomplete=()=>e()),t.close()}async function CC(e){let t;try{t=await new Promise((e,t)=>{let n=indexedDB.open(gC,1);n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)})}catch{return}let n=t.transaction(`handles`,`readwrite`),r=await new Promise(e=>{let t=n.objectStore(`handles`).get(_C);t.onsuccess=()=>e(t.result),t.onerror=()=>e(void 0)});if(r){n.objectStore(`handles`).delete(_C),await new Promise(e=>n.oncomplete=()=>e());let t=`/mnt/${r.name}`;await e.mount(t,r),$.info(`Mounted folder from welcome onboarding`,{name:r.name,path:t})}t.close()}function wC(){let e=document.createElement(`div`);e.className=`skill-drop-overlay`;let t=document.createElement(`div`);t.className=`skill-drop-overlay__card`;let n=document.createElement(`div`);n.className=`skill-drop-overlay__title`,t.appendChild(n);let r=document.createElement(`div`);return r.className=`skill-drop-overlay__desc`,t.appendChild(r),e.appendChild(t),document.body.appendChild(e),{show(t,i){n.textContent=t,r.textContent=i,e.classList.add(`skill-drop-overlay--visible`)},hide(){e.classList.remove(`skill-drop-overlay--visible`)}}}function TC(){let e=document.createElement(`div`);return e.className=`skill-drop-toast-container`,document.body.appendChild(e),(t,n)=>{let r=document.createElement(`div`);r.className=`skill-drop-toast skill-drop-toast--${n}`,r.textContent=t,e.appendChild(r),requestAnimationFrame(()=>r.classList.add(`skill-drop-toast--visible`)),window.setTimeout(()=>{r.classList.remove(`skill-drop-toast--visible`),window.setTimeout(()=>r.remove(),180)},4200)}}function EC(e,t,n){let r=wC(),i=0,a=!1,o=()=>{i=0,a||r.hide()};window.addEventListener(`dragenter`,e=>{go(e.dataTransfer)&&(e.preventDefault(),i+=1,a||r.show(`Drop .skill to install`,`Unpack into /workspace/skills/{name}.`))}),window.addEventListener(`dragover`,e=>{go(e.dataTransfer)&&(e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect=`copy`),a||r.show(`Drop .skill to install`,`Unpack into /workspace/skills/{name}.`))}),window.addEventListener(`dragleave`,()=>{i!==0&&(i=Math.max(0,i-1),i===0&&!a&&r.hide())}),window.addEventListener(`dragend`,o),window.addEventListener(`blur`,o),window.addEventListener(`drop`,async s=>{let c=_o(s.dataTransfer);if(!c){o();return}if(s.preventDefault(),i=0,a){r.hide(),t(`Another .skill installation is already in progress.`,`error`);return}a=!0,r.show(`Installing skill…`,c.name);try{let r=await fe(e,c);await n(),t(`Installed "${r.skillName}" to ${r.destinationPath} (${r.fileCount} files). Run "skill install ${r.skillName}" to apply it.`,`success`)}catch(e){t(`Failed to install dropped skill: ${e instanceof Error?e.message:String(e)}`,`error`)}finally{a=!1,r.hide()}})}async function DC(e){let{OffscreenClient:t}=await i(async()=>{let{OffscreenClient:e}=await import(`./offscreen-client-BlWuVmPl.js`);return{OffscreenClient:e}},__vite__mapDeps([21,15])),{VirtualFS:n}=await i(async()=>{let{VirtualFS:e}=await import(`./fs-CFxFn45v.js`).then(e=>e.t);return{VirtualFS:e}},__vite__mapDeps([17,4,15,18])),{publishAgentBridgeProxy:r}=await i(async()=>{let{publishAgentBridgeProxy:e}=await Promise.resolve().then(()=>$x);return{publishAgentBridgeProxy:e}},void 0),a=new io(e,!0);window.__slicc_debug_tabs=e=>a.setDebugTabs(e),await a.panels.chat.initSession(`session-cone`),r();let o=null,s=await n.create({dbName:`slicc-fs`});a.panels.fileBrowser.setFs(s),$.info(`File browser wired to shared VFS (local IndexedDB)`);let c=new BroadcastChannel(`preview-vfs`);c.onmessage=e=>{if(e.data?.type!==`preview-vfs-read`)return;let{id:t,path:n,asText:r}=e.data;(async()=>{try{let e=r?`utf-8`:`binary`,i=await s.readFile(n,{encoding:e});c.postMessage({type:`preview-vfs-response`,id:t,content:i})}catch(e){let r=e instanceof Error?e.message:String(e);r.includes(`ENOENT`)||$.error(`Preview VFS read failed`,{path:n,error:r}),c.postMessage({type:`preview-vfs-response`,id:t,error:r})}})()},EC(s,TC(),async()=>{await a.panels.fileBrowser.refresh()});try{let{WasmShell:e}=await i(async()=>{let{WasmShell:e}=await Promise.resolve().then(()=>Eb);return{WasmShell:e}},void 0),{PanelCdpProxy:t,BrowserAPI:n}=await i(async()=>{let{PanelCdpProxy:e,BrowserAPI:t}=await import(`./cdp-CsCvDwW3.js`).then(e=>e.t);return{PanelCdpProxy:e,BrowserAPI:t}},__vite__mapDeps([22,4,1,15])),{fetchSecretEnvVars:r}=await i(async()=>{let{fetchSecretEnvVars:e}=await Promise.resolve().then(()=>Cx);return{fetchSecretEnvVars:e}},void 0),o=new t;await o.connect();let c=new n(o),l=await r(),u=new e({fs:s,browserAPI:c,env:Object.keys(l).length>0?l:void 0});await a.panels.terminal.mountShell(u),$.info(`Terminal mounted with shared VFS and BrowserAPI (CDP proxy)`)}catch(e){$.warn(`Failed to mount shell to terminal`,e)}{let{registerSessionCostsProvider:e}=await i(async()=>{let{registerSessionCostsProvider:e}=await import(`./cost-command-DBzah9S9.js`).then(e=>e.t);return{registerSessionCostsProvider:e}},__vite__mapDeps([23,4]));e(()=>new Promise(e=>{chrome.runtime.sendMessage({source:`panel`,payload:{type:`get-session-costs`}},t=>{if(chrome.runtime.lastError||!t?.ok){e([]);return}e(t.costs??[])})}))}let u,d=new Set,f=async e=>{o=e,u.selectedScoopJid=e.jid,a.panels.memory.setSelectedScoop(e.jid),a.setScoopSwitcherSelected?.(e.jid),a.panels.scoops.setSelectedJid(e.jid);let t=e.isCone?`session-cone`:`session-${e.folder}`,n=e.isCone?void 0:e.name;await a.panels.chat.switchToContext(t,!e.isCone,n),u.isProcessing(e.jid)&&a.panels.chat.setProcessing(!0)};u=new t({onStatusChange:(e,t)=>{a.panels.scoops.updateScoopStatus(e,t),a.updateScoopSwitcherStatus?.(e,t),o?.jid===e&&(a.setAgentProcessing(t===`processing`),t===`processing`?a.panels.chat.setProcessing(!0):t===`ready`&&a.panels.chat.setProcessing(!1))},onScoopCreated:e=>{a.panels.scoops.refreshScoops(),a.refreshScoopSwitcher?.(),o||(o=e,u.selectedScoopJid=e.jid,a.panels.memory.setSelectedScoop(e.jid))},onScoopListUpdate:()=>{let e=new Set(u.getScoops().map(e=>e.folder));for(let t of d)e.has(t)||a.panels.chat.deleteSessionById(`session-${t}`);if(d=e,a.panels.scoops.refreshScoops(),a.refreshScoopSwitcher?.(),!o){let e=u.getScoops().find(e=>e.isCone);e&&(o=e,u.selectedScoopJid=e.jid,a.panels.memory.setSelectedScoop(e.jid))}},onIncomingMessage:(e,t)=>{if(o?.jid===e){let e=t.channel===`delegation`?`**[Instructions from sliccy]**\n\n${t.content}`:t.content;a.panels.chat.addUserMessage(e)}},onReady:async()=>{try{$.info(`Offscreen engine ready, scoop count:`,u.getScoops().length),window.localStorage.getItem(`slicc.trayJoinUrl`)&&chrome.runtime.sendMessage({source:`panel`,payload:{type:`refresh-tray-runtime`}}).catch(()=>{});let e=o??u.getScoops().find(e=>e.isCone)??u.getScoops()[0];e&&(o=e,u.selectedScoopJid=e.jid,await f(e))}catch(e){$.error(`Failed to initialize on ready`,{error:e instanceof Error?e.message:String(e)})}}}),u.setLocalFS(s);let p=u.createAgentHandle();a.panels.chat.setAgent(p),a.panels.scoops.setOrchestrator(u),a.panels.memory.setOrchestrator(u),a.setScoopSwitcherOrchestrator?.(u),a.onScoopSelect=f,a.onModelChange=e=>{localStorage.setItem(`selected-model`,e),u.updateModel()},a.onClearChat=async()=>{let e=u.getScoops();for(let t of e){let e=t.isCone?`session-cone`:`session-${t.folder}`;await a.panels.chat.deleteSessionById(e)}u.clearAllMessages()},a.onClearFilesystem=async()=>{u.clearFilesystem()},a.panels.chat.onInlineSprinkleLick=(e,t)=>{u.sendSprinkleLick(`inline`,{action:e,data:t})};let m=new dC(s,async e=>{if(e.type===`sprinkle`){if(e.sprinkleName===`welcome`){let t=e.body,n=t?.action;(n===`onboarding-complete`||n===`shortcut-migrate`)&&s.writeFile(`/shared/.welcomed`,`1`).catch(e=>$.warn(`Failed to persist welcome completion marker`,e)),n===`shortcut-migrate`&&m.close(`welcome`),n===`onboarding-complete`&&t?.data?.mountWorkspace&&CC(s).catch(e=>$.warn(`Failed to mount workspace from onboarding`,e))}if(e.sprinkleName===`welcome`&&e.body?.action===`request-mount`){try{let e=window;if(!e.showDirectoryPicker)throw Error(`showDirectoryPicker not supported`);let t=await e.showDirectoryPicker({mode:`readwrite`});await SC(t),m.sendToSprinkle(`welcome`,{action:`mount-complete`,dirName:t.name})}catch(e){e.name!==`AbortError`&&$.warn(`Mount picker failed`,e),m.sendToSprinkle(`welcome`,{action:`mount-cancelled`})}return}u.sendSprinkleLick(e.sprinkleName,e.body,e.targetScoop)}},{addSprinkle:(e,t,n,r)=>a.addSprinkle(e,t,n,r),removeSprinkle:e=>a.removeSprinkle(e)},()=>{let e=u.getScoops().find(e=>e.isCone);e&&u.stopScoop(e.jid)});if(window.__slicc_sprinkleManager=m,window.__slicc_reloadSkills=()=>(chrome.runtime.sendMessage({source:`panel`,payload:{type:`reload-skills`}}),Promise.resolve()),u.setSprinkleOpHandler(e=>{let{id:t,op:n,name:r,data:i}=e;console.log(`[main-ext] sprinkle-op handler called`,{id:t,op:n,name:r}),(async()=>{try{let e;switch(n){case`list`:await m.refresh(),e=m.available();break;case`opened`:e=m.opened();break;case`refresh`:await m.refresh(),e=m.available().length;break;case`open`:await m.open(r),e=!0;break;case`close`:m.close(r),e=!0;break;case`send`:m.sendToSprinkle(r,i),e=!0;break;case`openNewAutoOpen`:await m.openNewAutoOpenSprinkles(),e=!0;break}console.log(`[main-ext] sprinkle-op response sending`,{id:t,op:n,result:typeof e}),chrome.runtime.sendMessage({source:`panel`,payload:{type:`sprinkle-op-response`,id:t,result:e}}).catch(()=>{})}catch(e){chrome.runtime.sendMessage({source:`panel`,payload:{type:`sprinkle-op-response`,id:t,error:e instanceof Error?e.message:String(e)}}).catch(()=>{})}})()}),await m.refresh(),a.onSprinkleClose=e=>m.close(e),a.getAvailableSprinkles=()=>{let e=new Set(m.opened());return m.available().filter(t=>!e.has(t.name)).map(e=>({name:e.name,title:e.title}))},a.onOpenSprinkle=(e,t)=>m.open(e,t),a.updateAddButtons(),await m.restoreOpenSprinkles(),!await s.exists(`/shared/.welcomed`)&&localStorage.getItem(`slicc-welcomed`)&&(await s.writeFile(`/shared/.welcomed`,`1`).catch(()=>{}),localStorage.removeItem(`slicc-welcomed`)),!await s.exists(`/shared/.welcomed`)&&!l(window.localStorage)&&m.available().some(e=>e.name===`welcome`))try{await m.open(`welcome`)}catch(e){$.warn(`Failed to open welcome sprinkle`,e)}$.info(`SprinkleManager initialized (extension mode)`),u.requestState(),$.info(`Extension UI connected to offscreen agent engine`),bC()&&await xC(a.panels.chat),fb().catch(()=>{})}function OC(){if(typeof chrome<`u`&&chrome?.runtime?.id)return;let e=new Blob([`
13305
13305
  let lastPong = Date.now();
13306
13306
  let frozen = false;
13307
13307
  setInterval(() => {
@@ -13321,7 +13321,7 @@ ${t}
13321
13321
  }
13322
13322
  }
13323
13323
  };
13324
- `],{type:`application/javascript`}),t=URL.createObjectURL(e),n=new Worker(t);URL.revokeObjectURL(t),n.onmessage=e=>{if(e.data.type===`ping`)n.postMessage({type:`pong`});else if(e.data.type===`freeze-detected`)console.error(`[freeze-watchdog] Main thread blocked for ${e.data.elapsed}ms — capturing trace on recovery`);else if(e.data.type===`freeze-recovered`){console.error(`[freeze-watchdog] Main thread recovered. Stack trace at recovery point:`),console.trace(`[freeze-watchdog] recovery stack`);let e=performance.getEntriesByType(`longtask`);e.length>0&&console.error(`[freeze-watchdog] Long tasks:`,e.map(e=>({duration:e.duration,startTime:e.startTime,name:e.name})))}},window.addEventListener(`beforeunload`,()=>{n.terminate()},{once:!0})}async function OC(){DC(),fi(),po();let e=document.getElementById(`app`);if(!e)throw Error(`#app element not found`);`serviceWorker`in navigator&&navigator.serviceWorker.register(`/preview-sw.js`,{scope:`/preview/`}).then(()=>$.info(`Preview SW registered`)).catch(e=>$.error(`Preview SW registration failed — preview feature will not work`,e)),ne();let t=x(),n=l(window.localStorage);if(!t&&!n){let e=window.location.port===`5710`||window.location.port===`3000`;window.location.port===``&&window.location.pathname.includes(`/join/`)?await O({autoJoinUrl:window.location.origin+window.location.pathname}):!e&&window.location.port!==``?await O({preferTrayJoin:!0}):await O(),t=x()}let r=!t&&l(window.localStorage),o=typeof chrome<`u`&&!!chrome?.runtime?.id,s=JS(window.location.href,o);if(s===`extension`)return EC(e);let u=new io(e,s===`electron-overlay`);if(s===`electron-overlay`){let e=XS(window.location.href);u.setActiveTab(e);let t=document.createElement(`style`);t.id=`slicc-electron-overlay-runtime-style`,t.textContent=`
13324
+ `],{type:`application/javascript`}),t=URL.createObjectURL(e),n=new Worker(t);URL.revokeObjectURL(t),n.onmessage=e=>{if(e.data.type===`ping`)n.postMessage({type:`pong`});else if(e.data.type===`freeze-detected`)console.error(`[freeze-watchdog] Main thread blocked for ${e.data.elapsed}ms — capturing trace on recovery`);else if(e.data.type===`freeze-recovered`){console.error(`[freeze-watchdog] Main thread recovered. Stack trace at recovery point:`),console.trace(`[freeze-watchdog] recovery stack`);let e=performance.getEntriesByType(`longtask`);e.length>0&&console.error(`[freeze-watchdog] Long tasks:`,e.map(e=>({duration:e.duration,startTime:e.startTime,name:e.name})))}},window.addEventListener(`beforeunload`,()=>{n.terminate()},{once:!0})}async function kC(){OC(),fi(),po();let e=document.getElementById(`app`);if(!e)throw Error(`#app element not found`);`serviceWorker`in navigator&&navigator.serviceWorker.register(`/preview-sw.js`,{scope:`/preview/`}).then(()=>$.info(`Preview SW registered`)).catch(e=>$.error(`Preview SW registration failed — preview feature will not work`,e)),ne();let t=x(),n=l(window.localStorage);if(!t&&!n){let e=window.location.port===`5710`||window.location.port===`3000`;window.location.port===``&&window.location.pathname.includes(`/join/`)?await O({autoJoinUrl:window.location.origin+window.location.pathname}):!e&&window.location.port!==``?await O({preferTrayJoin:!0}):await O(),t=x()}let r=!t&&l(window.localStorage),o=typeof chrome<`u`&&!!chrome?.runtime?.id,s=YS(window.location.href,o);if(s===`extension`)return DC(e);let u=new io(e,s===`electron-overlay`);if(s===`electron-overlay`){let e=ZS(window.location.href);u.setActiveTab(e);let t=document.createElement(`style`);t.id=`slicc-electron-overlay-runtime-style`,t.textContent=`
13325
13325
  #app > .tab-bar { display: none !important; }
13326
13326
  #app > .tab-content {
13327
13327
  height: calc(100vh - var(--s2-header-height));
@@ -13329,4 +13329,4 @@ ${t}
13329
13329
  #app > .tab-content > .tab-content__panel {
13330
13330
  height: 100%;
13331
13331
  }
13332
- `,document.head.appendChild(t),window.addEventListener(`message`,e=>{e.source===window.parent&&tC(e.data)&&u.setActiveTab(XS(`http://localhost/?tab=${e.data.tab??``}`))}),window.addEventListener(`keydown`,e=>{e.code===`Semicolon`&&(e.metaKey||e.ctrlKey)&&!e.shiftKey&&!e.altKey&&!e.repeat&&(e.preventDefault(),e.stopPropagation(),window.parent.postMessage({type:`slicc-electron-overlay:toggle`},`*`))},!0)}let d=wC();await u.panels.chat.initSession(`session-cone`),$.info(`Session initialized`);let p=new B,m=new Set,h=e=>{$.debug(`Emit to UI`,{type:e.type,listenerCount:m.size});for(let t of m)try{t(e)}catch(t){$.error(`Listener error`,{eventType:e.type,error:t instanceof Error?t.message:String(t)})}},g=null,v=new Map,y=new Map;function b(){return Date.now().toString(36)+Math.random().toString(36).slice(2,8)}function S(e){let t=y.get(e);return t||(t=[],y.set(e,t)),t}function C(e,t){let n=S(e),r=v.get(e);if(r){let e=n.find(e=>e.id===r);if(e)return e}r=`scoop-${e}-${b()}`,v.set(e,r);let i=w.getScoops().find(t=>t.jid===e),a=i?.isCone?`cone`:i?.name??`unknown`,o={id:r,role:`assistant`,content:``,timestamp:Date.now(),toolCalls:[],isStreaming:!0,source:a,channel:t};return n.push(o),g?.jid===e&&h({type:`message_start`,messageId:r}),o}let w=new Lx(u.getIframeContainer(),{onResponse:(e,t,n)=>{let r=C(e);n?r.content+=t:(r.content=t,r.isStreaming=!1),g?.jid===e&&(h({type:`content_delta`,messageId:r.id,text:t}),n||h({type:`content_done`,messageId:r.id}))},onResponseDone:e=>{let t=S(e),n=v.get(e);if(n){let r=t.find(e=>e.id===n);r&&(r.isStreaming=!1),g?.jid===e&&h({type:`content_done`,messageId:n}),v.delete(e)}},onSendMessage:(e,t)=>{$.debug(`Send message requested`,{targetJid:e,textLength:t.length});let n=`msg-${b()}`,r={id:n,chatJid:e,senderId:`assistant`,senderName:`sliccy`,content:t,timestamp:new Date().toISOString(),fromAssistant:!0,channel:`web`};w.handleMessage(r),S(e).push({id:n,role:`assistant`,content:t,timestamp:Date.now()}),g?.jid===e&&(h({type:`message_start`,messageId:n}),h({type:`content_delta`,messageId:n,text:t}),h({type:`content_done`,messageId:n}))},onStatusChange:(e,t)=>{if(u.panels.scoops.updateScoopStatus(e,t),u.updateScoopSwitcherStatus?.(e,t),g?.jid===e){if(u.setAgentProcessing(t===`processing`),t===`processing`)u.panels.chat.setProcessing(!0);else if(t===`ready`){u.panels.chat.setProcessing(!1);let t=v.get(e)??`done-${e}-${b()}`;v.delete(e),h({type:`turn_end`,messageId:t})}}},onError:(e,t)=>{$.error(`Scoop error`,{scoopJid:e,error:t}),g?.jid===e&&h({type:`error`,error:t})},getBrowserAPI:()=>p,onToolStart:(e,t,n)=>{if(new Set([`send_message`,`list_scoops`,`list_tasks`]).has(t))return;let r=C(e);r.toolCalls||=[],r.toolCalls.push({id:b(),name:t,input:n}),g?.jid===e&&h({type:`tool_use_start`,messageId:r.id,toolName:t,toolInput:n})},onToolEnd:(e,t,n,r)=>{if(new Set([`send_message`,`list_scoops`,`list_tasks`]).has(t))return;let i=S(e),a=v.get(e);if(a){let e=i.find(e=>e.id===a);if(e?.toolCalls){let i=[...e.toolCalls].reverse().find(e=>e.name===t&&e.result===void 0);i&&(i.result=n,i.isError=r)}}g?.jid===e&&a&&h({type:`tool_result`,messageId:a,toolName:t,result:n,isError:r})},onToolUI:(e,t,n,r)=>{let i=v.get(e);i?h({type:`tool_ui`,messageId:i,toolName:t,requestId:n,html:r}):$.warn(`Cannot emit tool_ui - no message ID for scoop`,{scoopJid:e,requestId:n})},onToolUIDone:(e,t)=>{let n=v.get(e);n&&h({type:`tool_ui_done`,messageId:n,requestId:t})},onIncomingMessage:(e,t)=>{let n={id:t.id,role:`user`,content:t.channel===`delegation`?`**[Instructions from sliccy]**\n\n${t.content}`:t.content,timestamp:new Date(t.timestamp).getTime(),source:t.channel===`delegation`?`delegation`:void 0,channel:t.channel};S(e).push(n),g?.jid===e&&(h({type:`message_start`,messageId:t.id}),h({type:`content_delta`,messageId:t.id,text:n.content}),h({type:`content_done`,messageId:t.id}))}});await w.init(),u.panels.scoops.setOrchestrator(w),u.panels.memory.setOrchestrator(w),u.setScoopSwitcherOrchestrator?.(w);{let e=w.getSharedFS();e?rS(w,e,w.getSessionStore()):$.warn(`AgentBridge not published — orchestrator.getSharedFS() returned null`)}let T=w.getSharedFS();if(T){u.panels.fileBrowser.setFs(T),$.info(`File browser wired to shared VFS`);let e=new BroadcastChannel(`preview-vfs`);e.onmessage=t=>{if(t.data?.type!==`preview-vfs-read`)return;let{id:n,path:r,asText:i}=t.data;(async()=>{try{let t=i?`utf-8`:`binary`,a=await T.readFile(r,{encoding:t});e.postMessage({type:`preview-vfs-response`,id:n,content:a})}catch(t){let i=t instanceof Error?t.message:String(t);i.includes(`ENOENT`)||$.error(`Preview VFS read failed`,{path:r,error:i}),e.postMessage({type:`preview-vfs-response`,id:n,error:i})}})()},TC(T,(e,t)=>{t===`error`?$.warn(`Dropped skill install failed`,{message:e}):$.info(`Dropped skill installed`,{message:e}),d(e,t)},async()=>{await u.panels.fileBrowser.refresh()});try{let{WasmShell:e}=await i(async()=>{let{WasmShell:e}=await Promise.resolve().then(()=>Tb);return{WasmShell:e}},void 0),{fetchSecretEnvVars:t}=await i(async()=>{let{fetchSecretEnvVars:e}=await Promise.resolve().then(()=>Sx);return{fetchSecretEnvVars:e}},void 0),n=await t(),r=new e({fs:T,browserAPI:p,env:Object.keys(n).length>0?n:void 0});await u.panels.terminal.mountShell(r),$.info(`Terminal mounted with shared VFS`);try{let{BshWatchdog:e}=await i(async()=>{let{BshWatchdog:e}=await import(`./bsh-watchdog-BXTi5bzs.js`);return{BshWatchdog:e}},__vite__mapDeps([24,15])),t=new e({browserAPI:p,scriptCatalog:r.getScriptCatalog(),fs:T});t.start(),window.addEventListener(`beforeunload`,()=>t.stop(),{once:!0}),$.info(`BSH navigation watchdog started`)}catch(e){$.warn(`Failed to start BSH watchdog`,e)}}catch(e){$.warn(`Failed to mount shell to terminal`,e)}}let E=w.getScoops(),D=E.some(e=>e.isCone);if(r)$.info(`Skipping local cone bootstrap while joining a tray without a configured provider`);else if(!D)g=await u.panels.scoops.createCone(),$.info(`Created cone`);else{let e=new URLSearchParams(window.location.search).get(`scoop`);if(e){let t=E.find(t=>t.folder===e);t?(g=t,$.info(`Restored scoop from URL`,{folder:e})):g=E.find(e=>e.isCone)??E[0]}else g=E.find(e=>e.isCone)??E[0]}g&&u.panels.memory.setSelectedScoop(g.jid);let k=null,A={sendMessage(e,t){if(!g){h({type:`error`,error:`No scoop selected`});return}let n={id:t??`msg-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,chatJid:g.jid,senderId:`user`,senderName:`User`,content:e,timestamp:new Date().toISOString(),fromAssistant:!1,channel:`web`};S(g.jid).push({id:n.id,role:`user`,content:e,timestamp:Date.now()}),k?.broadcastUserMessage(e,n.id),w.handleMessage(n),w.createScoopTab(g.jid)},onEvent(e){return m.add(e),()=>m.delete(e)},stop(){g&&(w.stopScoop(g.jid),w.clearQueuedMessages(g.jid).catch(e=>{$.error(`Failed to clear queued messages on stop`,{error:e instanceof Error?e.message:String(e)})}))}};u.panels.chat.setAgent(A),u.panels.chat.setDeleteQueuedMessageCallback(e=>{if(g){w.deleteQueuedMessage(g.jid,e).catch(t=>{$.error(`Failed to delete queued message`,{messageId:e,error:t instanceof Error?t.message:String(t)})});let t=y.get(g.jid);if(t){let n=t.findIndex(t=>t.id===e);n!==-1&&t.splice(n,1)}}}),$.info(`Cone agent handle wired to chat UI`);let{getLickManager:ee}=await i(async()=>{let{getLickManager:e}=await Promise.resolve().then(()=>Ax);return{getLickManager:e}},void 0),j=ee();await j.init(),w.setLickManager(j);let te=e=>{let t=e.type===`webhook`,n=e.type===`sprinkle`,r=e.type===`fswatch`,i=e.type===`session-reload`,a=e.type===`navigate`,o=t?e.webhookName:n?e.sprinkleName:r?e.fswatchName:i?`session-reload`:a?e.navigateUrl:e.cronName,s=t?e.webhookId:n?e.sprinkleName:r?e.fswatchId:i?`session-reload`:a?e.navigateUrl:e.cronId,c=e.type;if($.debug(`Lick event`,{type:e.type,name:o,targetScoop:e.targetScoop}),n&&e.sprinkleName===`welcome`){let t=e.body,n=t?.action;(n===`onboarding-complete`||n===`shortcut-migrate`)&&T?.writeFile(`/shared/.welcomed`,`1`).catch(e=>$.warn(`Failed to persist welcome marker`,e)),n===`shortcut-migrate`&&M?.close(`welcome`),n===`onboarding-complete`&&t?.data?.mountWorkspace&&T&&SC(T).catch(e=>$.warn(`Failed to mount workspace from onboarding`,e))}if(n&&e.sprinkleName===`welcome`&&e.body?.action===`request-mount`){(async()=>{try{let e=window;if(!e.showDirectoryPicker)throw Error(`showDirectoryPicker not supported`);let t=await e.showDirectoryPicker({mode:`readwrite`});await xC(t),M?.sendToSprinkle(`welcome`,{action:`mount-complete`,dirName:t.name})}catch(e){e.name!==`AbortError`&&$.warn(`Mount picker failed`,e),M?.sendToSprinkle(`welcome`,{action:`mount-cancelled`})}})();return}let l=w.getScoops(),d;if(d=e.targetScoop?l.find(t=>t.name===e.targetScoop||t.folder===e.targetScoop||t.folder===`${e.targetScoop}-scoop`):l.find(e=>e.isCone),d){let l=`${c}-${s}-${Date.now()}`,f=t?`Webhook Event`:n?`Sprinkle Event`:r?`File Watch Event`:i?`Session Reload`:a?`Navigate Event`:`Cron Event`,p=null;if(i){let t=e.body;if(t?.reason===`mount-recovery`&&(p=mC(t.mounts??[]),p===null)){$.debug(`Dropping session-reload lick with empty mount-recovery list`);return}}p===null&&(p=`[${f}: ${o}]\n\`\`\`json\n${JSON.stringify(e.body,null,2)}\n\`\`\``);let m={id:l,chatJid:d.jid,senderId:c,senderName:`${c}:${o}`,content:p,timestamp:e.timestamp,fromAssistant:!1,channel:c},h=Date.now();if(S(d.jid).push({id:l,role:`user`,content:p,timestamp:h,source:`lick`,channel:c}),g?.jid===d.jid)u.panels.chat.addLickMessage(l,p,c,h);else{let e=d.isCone?`session-cone`:`session-${d.folder}`;u.panels.chat.persistLickToSession(e,{id:l,content:p,channel:c,timestamp:h})}$.info(`Routing lick to scoop`,{type:c,name:o,scoopJid:d.jid}),w.handleMessage(m)}else $.warn(`Lick target scoop not found`,{targetScoop:e.targetScoop})};j.setEventHandler(te);let re=new V(p.getTransport(),e=>{j.emitEvent({type:`navigate`,navigateUrl:e.url,targetScoop:void 0,timestamp:new Date().toISOString(),body:{url:e.url,sliccHeader:e.sliccHeader,title:e.title}})});(async()=>{try{await p.connect(),await re.start(),$.info(`Navigation watcher started`)}catch(e){$.warn(`Failed to start navigation watcher`,{error:e instanceof Error?e.message:String(e)})}})(),T&&F().then(async e=>{if(e.length===0)return;let{needsRecovery:t}=await dC(e,T,$);t.length!==0&&te({type:`session-reload`,targetScoop:void 0,timestamp:new Date().toISOString(),body:{reason:`mount-recovery`,mounts:t}})}).catch(e=>$.warn(`Failed to restore persisted mounts`,e)),u.panels.chat.onInlineSprinkleLick=(e,t)=>{te({type:`sprinkle`,sprinkleName:`inline`,targetScoop:void 0,timestamp:new Date().toISOString(),body:{action:e,data:t}})};let M=null;if(T){if(M=new uC(T,te,{addSprinkle:(e,t,n,r)=>u.addSprinkle(e,t,n,r),removeSprinkle:e=>u.removeSprinkle(e)},()=>{let e=w.getScoops().find(e=>e.isCone);e&&(w.stopScoop(e.jid),w.clearQueuedMessages(e.jid).catch(e=>{$.error(`Failed to clear queued messages on sprinkle stopCone`,{error:e instanceof Error?e.message:String(e)})}))}),window.__slicc_sprinkleManager=M,window.__slicc_reloadSkills=()=>w.reloadAllSkills(),await M.refresh(),u.onSprinkleClose=e=>M.close(e),u.getAvailableSprinkles=()=>{let e=new Set(M.opened());return M.available().filter(t=>!e.has(t.name)).map(e=>({name:e.name,title:e.title}))},u.onOpenSprinkle=(e,t)=>M.open(e,t),u.updateAddButtons(),!await T.exists(`/shared/.welcomed`)&&localStorage.getItem(`slicc-welcomed`)&&(await T.writeFile(`/shared/.welcomed`,`1`).catch(()=>{}),localStorage.removeItem(`slicc-welcomed`)),!await T.exists(`/shared/.welcomed`)&&!r&&M.available().some(e=>e.name===`welcome`))try{await M.open(`welcome`)}catch(e){$.warn(`Failed to open welcome sprinkle`,e)}await M.restoreOpenSprinkles(),$.info(`SprinkleManager initialized`)}let N=()=>{let e=QS(window.location.href),t=new WebSocket(e);t.onopen=()=>{$.info(`Lick WebSocket connected`)},t.onmessage=async e=>{try{let n=JSON.parse(e.data);if(n.requestId){let e;try{switch(n.type){case`list_webhooks`:e={type:`response`,requestId:n.requestId,data:j.listWebhooks()};break;case`create_webhook`:{let t=await j.createWebhook(n.name||`default`,n.scoop,n.filter),r=uh().session,i=r?.webhookUrl?eC(r.webhookUrl,t.id):$S(window.location.href,t.id);e={type:`response`,requestId:n.requestId,data:{...t,url:i}};break}case`delete_webhook`:e=await j.deleteWebhook(n.id)?{type:`response`,requestId:n.requestId,data:{ok:!0}}:{type:`response`,requestId:n.requestId,data:{error:`Webhook not found`}};break;case`list_crontasks`:e={type:`response`,requestId:n.requestId,data:j.listCronTasks()};break;case`create_crontask`:{if(!n.name)throw Error(`name is required`);if(!n.cron)throw Error(`cron is required`);let t=await j.createCronTask(n.name,n.cron,n.scoop,n.filter);e={type:`response`,requestId:n.requestId,data:t};break}case`delete_crontask`:e=await j.deleteCronTask(n.id)?{type:`response`,requestId:n.requestId,data:{ok:!0}}:{type:`response`,requestId:n.requestId,data:{error:`Cron task not found`}};break;case`tray_status`:{let t=uh();e={type:`response`,requestId:n.requestId,data:{state:t.state,joinUrl:t.session?.joinUrl??null,workerBaseUrl:t.session?.workerBaseUrl??null,trayId:t.session?.trayId??null}};break}default:e={type:`response`,requestId:n.requestId,error:`Unknown request type: ${n.type}`}}}catch(t){e={type:`response`,requestId:n.requestId,error:t instanceof Error?t.message:String(t)}}t.send(JSON.stringify(e));return}if(n.type===`webhook_event`&&j.handleWebhookEvent(n.webhookId,n.headers,n.body),n.type===`navigate_event`){let e=typeof n.sliccHeader==`string`?n.sliccHeader:``,t=typeof n.url==`string`&&n.url.length>0?n.url:``;e&&t&&j.emitEvent({type:`navigate`,navigateUrl:t,targetScoop:void 0,timestamp:typeof n.timestamp==`string`?n.timestamp:new Date().toISOString(),body:{url:t,sliccHeader:e,title:typeof n.title==`string`?n.title:void 0}})}}catch(e){$.error(`Failed to process lick message`,{error:e instanceof Error?e.message:String(e)})}},t.onclose=()=>{$.warn(`Lick WebSocket disconnected, reconnecting in 3s...`),setTimeout(N,3e3)},t.onerror=e=>{$.error(`Lick WebSocket error`,{error:String(e)})}};N(),u.onModelChange=e=>{localStorage.setItem(`selected-model`,e),w.updateModel()};let P=new Set;u.onClearChat=async()=>{await w.clearAllMessages(),y.clear(),P.clear()},u.onClearFilesystem=async()=>{await w.resetFilesystem()};let ie=async e=>{$.info(`Scoop selected`,{jid:e.jid,name:e.name}),g=e,w.createScoopTab(e.jid),u.panels.memory.setSelectedScoop(e.jid),u.panels.scoops.setSelectedJid(e.jid);let t=e.isCone?`session-cone`:`session-${e.folder}`,n=y.get(e.jid),r=!P.has(e.jid),i=e.isCone?void 0:e.name;if(!r&&n&&n.length>0)await u.panels.chat.switchToContext(t,!e.isCone,i),u.panels.chat.loadMessages(n);else{if(await u.panels.chat.switchToContext(t,!e.isCone,i),u.panels.chat.getMessages().length===0){let t=await w.getMessagesForScoop(e.jid);for(let e of t){let t=e.channel===`delegation`;vC(e.channel)?u.panels.chat.addLickMessage(e.id,e.content,e.channel,new Date(e.timestamp).getTime()):t?u.panels.chat.addUserMessage(`**[Instructions from sliccy]**\n\n${e.content}`):e.fromAssistant?(h({type:`message_start`,messageId:e.id}),h({type:`content_delta`,messageId:e.id,text:e.content}),h({type:`content_done`,messageId:e.id})):u.panels.chat.addUserMessage(e.content)}}let n=u.panels.chat.getMessages(),r=new Set(n.map(e=>e.id)),a=S(e.jid),o=a.filter(e=>!r.has(e.id));a.length=0,a.push(...n,...o),o.length>0&&u.panels.chat.loadMessages(a)}e.isCone&&w.isProcessing(e.jid)&&u.panels.chat.setProcessing(!0),P.add(e.jid)};if(u.onScoopSelect=ie,g&&(w.createScoopTab(g.jid),await ie(g)),yC()&&await bC(u.panels.chat),s===`standalone`||s===`electron-overlay`){let e=await a(),t=YS(s,e!==null)?c:null,n=await _({locationHref:window.location.href,storage:window.localStorage,envBaseUrl:null,defaultWorkerBaseUrl:t,runtimeConfigFetcher:async()=>e}),r=null,i=null,o=null;__(()=>k?(e,t)=>k.sendFsRequest(e,t):r?(e,t)=>r.sendFsRequest(e,t):null),im(()=>k?()=>k.getBestFollowerForTeleport():null),am(()=>k?()=>k.getConnectedFollowers():null);let l=e=>{o&&=(clearInterval(o),null),r?.close();let t=`follower-${e.bootstrapId}`,n=new qS(e.channel,{browserTransport:p.getTransport(),browserAPI:p,onSnapshot:e=>{u.panels.chat.loadMessages(e)},onUserMessage:e=>{u.panels.chat.addUserMessage(e)},onStatus:e=>{u.panels.chat.setProcessing(e===`processing`)},onTargetsChanged:()=>void i()});r=n,p.setTrayTargetProvider(n),u.panels.chat.setAgent(n),n.requestSnapshot();let i=async()=>{try{let e=await p.listPages();n.advertiseTargets(e.map(e=>({targetId:e.targetId,title:e.title,url:e.url})),t)}catch{}};o=setInterval(i,5e3),i(),$.info(`Follower sync wired to chat panel`,{trayId:e.trayId})},d=e=>{i?.cancel(),o&&=(clearInterval(o),null),r?.close(),r=null,i=xS({joinUrl:e,runtime:`slicc-standalone`,fetchImpl:vh()},{onConnected:e=>l(e),onReconnecting:e=>{$.info(`Follower reconnecting`,{attempt:e})},onGaveUp:e=>{$.warn(`Follower reconnect gave up`,{lastError:e})}})};if(window.addEventListener(`slicc:tray-join`,(e=>{d(e.detail.joinUrl)})),window.addEventListener(`beforeunload`,()=>{o&&clearInterval(o),r?.close(),i?.cancel()},{once:!0}),n?.joinUrl)d(n.joinUrl);else if(n?.workerBaseUrl){let e,t,r,i,a=()=>{t=new GS({browserTransport:p.getTransport(),browserAPI:p,getMessages:()=>u.panels.chat.getMessages(),getScoopJid:()=>g?.jid??`cone`,onFollowerMessage:(e,t)=>{u.panels.chat.addUserMessage(e),A.sendMessage(e,t)},onFollowerAbort:()=>{A.stop()}}),k=t,bh(()=>t.getConnectedFollowers()),p.setTrayTargetProvider(t),i&&clearInterval(i);let n=async()=>{try{let e=await p.listPages();t.setLocalTargets(e.map(e=>({targetId:e.targetId,title:e.title,url:e.url})))}catch{}};i=setInterval(n,5e3),n(),r=new yS({sendControlMessage:t=>e.sendControlMessage(t),onPeerConnected:(e,n)=>{$.info(`Tray follower data channel opened`,{controllerId:e.controllerId,bootstrapId:e.bootstrapId,attempt:e.attempt,runtime:e.runtime}),t.addFollower(e.bootstrapId,n,{runtime:e.runtime,connectedAt:e.connectedAt??void 0})}})};a(),m.add(e=>{t.broadcastEvent(e)}),e=new mh({workerBaseUrl:n.workerBaseUrl,runtime:`slicc-standalone`,fetchImpl:vh(),onControlMessage:e=>{if(e.type===`webhook.event`){j.handleWebhookEvent(e.webhookId,e.headers,e.body);return}r.handleControlMessage(e).catch(e=>{$.warn(`Tray leader bootstrap handling failed`,{error:e instanceof Error?e.message:String(e)})})}}),Ch(async()=>{t.stop(),r.stop(),e.stop(),await e.clearSession();let n=await e.start(),i=f(window.location.href,n.workerBaseUrl,n.trayId);return i!==window.location.href&&window.history.replaceState(window.history.state,``,i),a(),uh()}),e.start().then(e=>{let t=f(window.location.href,e.workerBaseUrl,e.trayId);t!==window.location.href&&window.history.replaceState(window.history.state,``,t)}).catch(e=>{$.warn(`Leader tray join failed`,{error:e instanceof Error?e.message:String(e)})}),window.addEventListener(`beforeunload`,()=>{clearInterval(i),t.stop(),r.stop(),e.stop()},{once:!0})}}$.info(`Orchestrator initialized — cone+scoops ready`,{scoopCount:w.getScoops().length}),db().catch(()=>{})}OC().catch(e=>{$.error(`Fatal error`,e);let t=document.getElementById(`app`);if(t){let n=document.createElement(`div`);n.style.cssText=`padding: 2rem; text-align: center;`;let r=document.createElement(`h1`);r.style.color=`var(--s2-negative, #e34850)`,r.textContent=`Failed to start`;let i=document.createElement(`p`);i.style.color=`var(--s2-content-tertiary, #717171)`,i.textContent=e.message,n.appendChild(r),n.appendChild(i);let a=document.createElement(`button`);for(a.textContent=`Reset all data & reload`,a.style.cssText=`margin-top: 1rem; padding: 0.5rem 1.5rem; background: var(--s2-negative, #e34850); color: #fff; border: none; border-radius: 6px; cursor: pointer; font-size: 14px;`,a.addEventListener(`click`,async()=>{a.disabled=!0,a.textContent=`Resetting…`;let e=await indexedDB.databases();await Promise.all(e.map(e=>e.name?new Promise(t=>{let n=indexedDB.deleteDatabase(e.name);n.onsuccess=()=>t(),n.onerror=()=>t(),n.onblocked=()=>t()}):Promise.resolve())),location.reload()}),n.appendChild(a);t.firstChild;)t.removeChild(t.firstChild);t.appendChild(n)}});export{Qs as t};
13332
+ `,document.head.appendChild(t),window.addEventListener(`message`,e=>{e.source===window.parent&&nC(e.data)&&u.setActiveTab(ZS(`http://localhost/?tab=${e.data.tab??``}`))}),window.addEventListener(`keydown`,e=>{e.code===`Semicolon`&&(e.metaKey||e.ctrlKey)&&!e.shiftKey&&!e.altKey&&!e.repeat&&(e.preventDefault(),e.stopPropagation(),window.parent.postMessage({type:`slicc-electron-overlay:toggle`},`*`))},!0)}let d=TC();await u.panels.chat.initSession(`session-cone`),$.info(`Session initialized`);let p=new B,m=new Set,h=e=>{$.debug(`Emit to UI`,{type:e.type,listenerCount:m.size});for(let t of m)try{t(e)}catch(t){$.error(`Listener error`,{eventType:e.type,error:t instanceof Error?t.message:String(t)})}},g=null,v=new Map,y=new Map;function b(){return Date.now().toString(36)+Math.random().toString(36).slice(2,8)}function S(e){let t=y.get(e);return t||(t=[],y.set(e,t)),t}function C(e,t){let n=S(e),r=v.get(e);if(r){let e=n.find(e=>e.id===r);if(e)return e}r=`scoop-${e}-${b()}`,v.set(e,r);let i=w.getScoops().find(t=>t.jid===e),a=i?.isCone?`cone`:i?.name??`unknown`,o={id:r,role:`assistant`,content:``,timestamp:Date.now(),toolCalls:[],isStreaming:!0,source:a,channel:t};return n.push(o),g?.jid===e&&h({type:`message_start`,messageId:r}),o}let w=new Rx(u.getIframeContainer(),{onResponse:(e,t,n)=>{let r=C(e);n?r.content+=t:(r.content=t,r.isStreaming=!1),g?.jid===e&&(h({type:`content_delta`,messageId:r.id,text:t}),n||h({type:`content_done`,messageId:r.id}))},onResponseDone:e=>{let t=S(e),n=v.get(e);if(n){let r=t.find(e=>e.id===n);r&&(r.isStreaming=!1),g?.jid===e&&h({type:`content_done`,messageId:n}),v.delete(e)}},onSendMessage:(e,t)=>{$.debug(`Send message requested`,{targetJid:e,textLength:t.length});let n=`msg-${b()}`,r={id:n,chatJid:e,senderId:`assistant`,senderName:`sliccy`,content:t,timestamp:new Date().toISOString(),fromAssistant:!0,channel:`web`};w.handleMessage(r),S(e).push({id:n,role:`assistant`,content:t,timestamp:Date.now()}),g?.jid===e&&(h({type:`message_start`,messageId:n}),h({type:`content_delta`,messageId:n,text:t}),h({type:`content_done`,messageId:n}))},onStatusChange:(e,t)=>{if(u.panels.scoops.updateScoopStatus(e,t),u.updateScoopSwitcherStatus?.(e,t),g?.jid===e){if(u.setAgentProcessing(t===`processing`),t===`processing`)u.panels.chat.setProcessing(!0);else if(t===`ready`){u.panels.chat.setProcessing(!1);let t=v.get(e)??`done-${e}-${b()}`;v.delete(e),h({type:`turn_end`,messageId:t})}}},onError:(e,t)=>{$.error(`Scoop error`,{scoopJid:e,error:t}),g?.jid===e&&h({type:`error`,error:t})},getBrowserAPI:()=>p,onToolStart:(e,t,n)=>{if(new Set([`send_message`,`list_scoops`,`list_tasks`]).has(t))return;let r=C(e);r.toolCalls||=[],r.toolCalls.push({id:b(),name:t,input:n}),g?.jid===e&&h({type:`tool_use_start`,messageId:r.id,toolName:t,toolInput:n})},onToolEnd:(e,t,n,r)=>{if(new Set([`send_message`,`list_scoops`,`list_tasks`]).has(t))return;let i=S(e),a=v.get(e);if(a){let e=i.find(e=>e.id===a);if(e?.toolCalls){let i=[...e.toolCalls].reverse().find(e=>e.name===t&&e.result===void 0);i&&(i.result=n,i.isError=r)}}g?.jid===e&&a&&h({type:`tool_result`,messageId:a,toolName:t,result:n,isError:r})},onToolUI:(e,t,n,r)=>{let i=v.get(e);i?h({type:`tool_ui`,messageId:i,toolName:t,requestId:n,html:r}):$.warn(`Cannot emit tool_ui - no message ID for scoop`,{scoopJid:e,requestId:n})},onToolUIDone:(e,t)=>{let n=v.get(e);n&&h({type:`tool_ui_done`,messageId:n,requestId:t})},onIncomingMessage:(e,t)=>{let n={id:t.id,role:`user`,content:t.channel===`delegation`?`**[Instructions from sliccy]**\n\n${t.content}`:t.content,timestamp:new Date(t.timestamp).getTime(),source:t.channel===`delegation`?`delegation`:void 0,channel:t.channel};S(e).push(n),g?.jid===e&&(h({type:`message_start`,messageId:t.id}),h({type:`content_delta`,messageId:t.id,text:n.content}),h({type:`content_done`,messageId:t.id}))}});await w.init(),u.panels.scoops.setOrchestrator(w),u.panels.memory.setOrchestrator(w),u.setScoopSwitcherOrchestrator?.(w);{let e=w.getSharedFS();e?iS(w,e,w.getSessionStore()):$.warn(`AgentBridge not published — orchestrator.getSharedFS() returned null`)}let T=w.getSharedFS();if(T){u.panels.fileBrowser.setFs(T),$.info(`File browser wired to shared VFS`);let e=new BroadcastChannel(`preview-vfs`);e.onmessage=t=>{if(t.data?.type!==`preview-vfs-read`)return;let{id:n,path:r,asText:i}=t.data;(async()=>{try{let t=i?`utf-8`:`binary`,a=await T.readFile(r,{encoding:t});e.postMessage({type:`preview-vfs-response`,id:n,content:a})}catch(t){let i=t instanceof Error?t.message:String(t);i.includes(`ENOENT`)||$.error(`Preview VFS read failed`,{path:r,error:i}),e.postMessage({type:`preview-vfs-response`,id:n,error:i})}})()},EC(T,(e,t)=>{t===`error`?$.warn(`Dropped skill install failed`,{message:e}):$.info(`Dropped skill installed`,{message:e}),d(e,t)},async()=>{await u.panels.fileBrowser.refresh()});try{let{WasmShell:e}=await i(async()=>{let{WasmShell:e}=await Promise.resolve().then(()=>Eb);return{WasmShell:e}},void 0),{fetchSecretEnvVars:t}=await i(async()=>{let{fetchSecretEnvVars:e}=await Promise.resolve().then(()=>Cx);return{fetchSecretEnvVars:e}},void 0),n=await t(),r=new e({fs:T,browserAPI:p,env:Object.keys(n).length>0?n:void 0});await u.panels.terminal.mountShell(r),$.info(`Terminal mounted with shared VFS`);try{let{BshWatchdog:e}=await i(async()=>{let{BshWatchdog:e}=await import(`./bsh-watchdog-BXTi5bzs.js`);return{BshWatchdog:e}},__vite__mapDeps([24,15])),t=new e({browserAPI:p,scriptCatalog:r.getScriptCatalog(),fs:T});t.start(),window.addEventListener(`beforeunload`,()=>t.stop(),{once:!0}),$.info(`BSH navigation watchdog started`)}catch(e){$.warn(`Failed to start BSH watchdog`,e)}}catch(e){$.warn(`Failed to mount shell to terminal`,e)}}let E=w.getScoops(),D=E.some(e=>e.isCone);if(r)$.info(`Skipping local cone bootstrap while joining a tray without a configured provider`);else if(!D)g=await u.panels.scoops.createCone(),$.info(`Created cone`);else{let e=new URLSearchParams(window.location.search).get(`scoop`);if(e){let t=E.find(t=>t.folder===e);t?(g=t,$.info(`Restored scoop from URL`,{folder:e})):g=E.find(e=>e.isCone)??E[0]}else g=E.find(e=>e.isCone)??E[0]}g&&u.panels.memory.setSelectedScoop(g.jid);let k=null,A={sendMessage(e,t){if(!g){h({type:`error`,error:`No scoop selected`});return}let n={id:t??`msg-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,chatJid:g.jid,senderId:`user`,senderName:`User`,content:e,timestamp:new Date().toISOString(),fromAssistant:!1,channel:`web`};S(g.jid).push({id:n.id,role:`user`,content:e,timestamp:Date.now()}),k?.broadcastUserMessage(e,n.id),w.handleMessage(n),w.createScoopTab(g.jid)},onEvent(e){return m.add(e),()=>m.delete(e)},stop(){g&&(w.stopScoop(g.jid),w.clearQueuedMessages(g.jid).catch(e=>{$.error(`Failed to clear queued messages on stop`,{error:e instanceof Error?e.message:String(e)})}))}};u.panels.chat.setAgent(A),u.panels.chat.setDeleteQueuedMessageCallback(e=>{if(g){w.deleteQueuedMessage(g.jid,e).catch(t=>{$.error(`Failed to delete queued message`,{messageId:e,error:t instanceof Error?t.message:String(t)})});let t=y.get(g.jid);if(t){let n=t.findIndex(t=>t.id===e);n!==-1&&t.splice(n,1)}}}),$.info(`Cone agent handle wired to chat UI`);let{getLickManager:ee}=await i(async()=>{let{getLickManager:e}=await Promise.resolve().then(()=>jx);return{getLickManager:e}},void 0),j=ee();await j.init(),w.setLickManager(j);let te=e=>{let t=e.type===`webhook`,n=e.type===`sprinkle`,r=e.type===`fswatch`,i=e.type===`session-reload`,a=e.type===`navigate`,o=t?e.webhookName:n?e.sprinkleName:r?e.fswatchName:i?`session-reload`:a?e.navigateUrl:e.cronName,s=t?e.webhookId:n?e.sprinkleName:r?e.fswatchId:i?`session-reload`:a?e.navigateUrl:e.cronId,c=e.type;if($.debug(`Lick event`,{type:e.type,name:o,targetScoop:e.targetScoop}),n&&e.sprinkleName===`welcome`){let t=e.body,n=t?.action;(n===`onboarding-complete`||n===`shortcut-migrate`)&&T?.writeFile(`/shared/.welcomed`,`1`).catch(e=>$.warn(`Failed to persist welcome marker`,e)),n===`shortcut-migrate`&&M?.close(`welcome`),n===`onboarding-complete`&&t?.data?.mountWorkspace&&T&&CC(T).catch(e=>$.warn(`Failed to mount workspace from onboarding`,e))}if(n&&e.sprinkleName===`welcome`&&e.body?.action===`request-mount`){(async()=>{try{let e=window;if(!e.showDirectoryPicker)throw Error(`showDirectoryPicker not supported`);let t=await e.showDirectoryPicker({mode:`readwrite`});await SC(t),M?.sendToSprinkle(`welcome`,{action:`mount-complete`,dirName:t.name})}catch(e){e.name!==`AbortError`&&$.warn(`Mount picker failed`,e),M?.sendToSprinkle(`welcome`,{action:`mount-cancelled`})}})();return}let l=w.getScoops(),d;if(d=e.targetScoop?l.find(t=>t.name===e.targetScoop||t.folder===e.targetScoop||t.folder===`${e.targetScoop}-scoop`):l.find(e=>e.isCone),d){let l=`${c}-${s}-${Date.now()}`,f=t?`Webhook Event`:n?`Sprinkle Event`:r?`File Watch Event`:i?`Session Reload`:a?`Navigate Event`:`Cron Event`,p=null;if(i){let t=e.body;if(t?.reason===`mount-recovery`&&(p=hC(t.mounts??[]),p===null)){$.debug(`Dropping session-reload lick with empty mount-recovery list`);return}}p===null&&(p=`[${f}: ${o}]\n\`\`\`json\n${JSON.stringify(e.body,null,2)}\n\`\`\``);let m={id:l,chatJid:d.jid,senderId:c,senderName:`${c}:${o}`,content:p,timestamp:e.timestamp,fromAssistant:!1,channel:c},h=Date.now();if(S(d.jid).push({id:l,role:`user`,content:p,timestamp:h,source:`lick`,channel:c}),g?.jid===d.jid)u.panels.chat.addLickMessage(l,p,c,h);else{let e=d.isCone?`session-cone`:`session-${d.folder}`;u.panels.chat.persistLickToSession(e,{id:l,content:p,channel:c,timestamp:h})}$.info(`Routing lick to scoop`,{type:c,name:o,scoopJid:d.jid}),w.handleMessage(m)}else $.warn(`Lick target scoop not found`,{targetScoop:e.targetScoop})};j.setEventHandler(te);let re=new V(p.getTransport(),e=>{j.emitEvent({type:`navigate`,navigateUrl:e.url,targetScoop:void 0,timestamp:new Date().toISOString(),body:{url:e.url,sliccHeader:e.sliccHeader,title:e.title}})});(async()=>{try{await p.connect(),await re.start(),$.info(`Navigation watcher started`)}catch(e){$.warn(`Failed to start navigation watcher`,{error:e instanceof Error?e.message:String(e)})}})(),T&&F().then(async e=>{if(e.length===0)return;let{needsRecovery:t}=await fC(e,T,$);t.length!==0&&te({type:`session-reload`,targetScoop:void 0,timestamp:new Date().toISOString(),body:{reason:`mount-recovery`,mounts:t}})}).catch(e=>$.warn(`Failed to restore persisted mounts`,e)),u.panels.chat.onInlineSprinkleLick=(e,t)=>{te({type:`sprinkle`,sprinkleName:`inline`,targetScoop:void 0,timestamp:new Date().toISOString(),body:{action:e,data:t}})};let M=null;if(T){if(M=new dC(T,te,{addSprinkle:(e,t,n,r)=>u.addSprinkle(e,t,n,r),removeSprinkle:e=>u.removeSprinkle(e)},()=>{let e=w.getScoops().find(e=>e.isCone);e&&(w.stopScoop(e.jid),w.clearQueuedMessages(e.jid).catch(e=>{$.error(`Failed to clear queued messages on sprinkle stopCone`,{error:e instanceof Error?e.message:String(e)})}))}),window.__slicc_sprinkleManager=M,window.__slicc_reloadSkills=()=>w.reloadAllSkills(),await M.refresh(),u.onSprinkleClose=e=>M.close(e),u.getAvailableSprinkles=()=>{let e=new Set(M.opened());return M.available().filter(t=>!e.has(t.name)).map(e=>({name:e.name,title:e.title}))},u.onOpenSprinkle=(e,t)=>M.open(e,t),u.updateAddButtons(),!await T.exists(`/shared/.welcomed`)&&localStorage.getItem(`slicc-welcomed`)&&(await T.writeFile(`/shared/.welcomed`,`1`).catch(()=>{}),localStorage.removeItem(`slicc-welcomed`)),!await T.exists(`/shared/.welcomed`)&&!r&&M.available().some(e=>e.name===`welcome`))try{await M.open(`welcome`)}catch(e){$.warn(`Failed to open welcome sprinkle`,e)}await M.restoreOpenSprinkles(),$.info(`SprinkleManager initialized`)}let N=()=>{let e=$S(window.location.href),t=new WebSocket(e);t.onopen=()=>{$.info(`Lick WebSocket connected`)},t.onmessage=async e=>{try{let n=JSON.parse(e.data);if(n.requestId){let e;try{switch(n.type){case`list_webhooks`:e={type:`response`,requestId:n.requestId,data:j.listWebhooks()};break;case`create_webhook`:{let t=await j.createWebhook(n.name||`default`,n.scoop,n.filter),r=dh().session,i=r?.webhookUrl?tC(r.webhookUrl,t.id):eC(window.location.href,t.id);e={type:`response`,requestId:n.requestId,data:{...t,url:i}};break}case`delete_webhook`:e=await j.deleteWebhook(n.id)?{type:`response`,requestId:n.requestId,data:{ok:!0}}:{type:`response`,requestId:n.requestId,data:{error:`Webhook not found`}};break;case`list_crontasks`:e={type:`response`,requestId:n.requestId,data:j.listCronTasks()};break;case`create_crontask`:{if(!n.name)throw Error(`name is required`);if(!n.cron)throw Error(`cron is required`);let t=await j.createCronTask(n.name,n.cron,n.scoop,n.filter);e={type:`response`,requestId:n.requestId,data:t};break}case`delete_crontask`:e=await j.deleteCronTask(n.id)?{type:`response`,requestId:n.requestId,data:{ok:!0}}:{type:`response`,requestId:n.requestId,data:{error:`Cron task not found`}};break;case`tray_status`:{let t=dh();e={type:`response`,requestId:n.requestId,data:{state:t.state,joinUrl:t.session?.joinUrl??null,workerBaseUrl:t.session?.workerBaseUrl??null,trayId:t.session?.trayId??null}};break}default:e={type:`response`,requestId:n.requestId,error:`Unknown request type: ${n.type}`}}}catch(t){e={type:`response`,requestId:n.requestId,error:t instanceof Error?t.message:String(t)}}t.send(JSON.stringify(e));return}if(n.type===`webhook_event`&&j.handleWebhookEvent(n.webhookId,n.headers,n.body),n.type===`navigate_event`){let e=typeof n.sliccHeader==`string`?n.sliccHeader:``,t=typeof n.url==`string`&&n.url.length>0?n.url:``;e&&t&&j.emitEvent({type:`navigate`,navigateUrl:t,targetScoop:void 0,timestamp:typeof n.timestamp==`string`?n.timestamp:new Date().toISOString(),body:{url:t,sliccHeader:e,title:typeof n.title==`string`?n.title:void 0}})}}catch(e){$.error(`Failed to process lick message`,{error:e instanceof Error?e.message:String(e)})}},t.onclose=()=>{$.warn(`Lick WebSocket disconnected, reconnecting in 3s...`),setTimeout(N,3e3)},t.onerror=e=>{$.error(`Lick WebSocket error`,{error:String(e)})}};N(),u.onModelChange=e=>{localStorage.setItem(`selected-model`,e),w.updateModel()};let P=new Set;u.onClearChat=async()=>{await w.clearAllMessages(),y.clear(),P.clear()},u.onClearFilesystem=async()=>{await w.resetFilesystem()};let ie=async e=>{$.info(`Scoop selected`,{jid:e.jid,name:e.name}),g=e,w.createScoopTab(e.jid),u.panels.memory.setSelectedScoop(e.jid),u.panels.scoops.setSelectedJid(e.jid);let t=e.isCone?`session-cone`:`session-${e.folder}`,n=y.get(e.jid),r=!P.has(e.jid),i=e.isCone?void 0:e.name;if(!r&&n&&n.length>0)await u.panels.chat.switchToContext(t,!e.isCone,i),u.panels.chat.loadMessages(n);else{if(await u.panels.chat.switchToContext(t,!e.isCone,i),u.panels.chat.getMessages().length===0){let t=await w.getMessagesForScoop(e.jid);for(let e of t){let t=e.channel===`delegation`;yC(e.channel)?u.panels.chat.addLickMessage(e.id,e.content,e.channel,new Date(e.timestamp).getTime()):t?u.panels.chat.addUserMessage(`**[Instructions from sliccy]**\n\n${e.content}`):e.fromAssistant?(h({type:`message_start`,messageId:e.id}),h({type:`content_delta`,messageId:e.id,text:e.content}),h({type:`content_done`,messageId:e.id})):u.panels.chat.addUserMessage(e.content)}}let n=u.panels.chat.getMessages(),r=new Set(n.map(e=>e.id)),a=S(e.jid),o=a.filter(e=>!r.has(e.id));a.length=0,a.push(...n,...o),o.length>0&&u.panels.chat.loadMessages(a)}e.isCone&&w.isProcessing(e.jid)&&u.panels.chat.setProcessing(!0),P.add(e.jid)};if(u.onScoopSelect=ie,g&&(w.createScoopTab(g.jid),await ie(g)),bC()&&await xC(u.panels.chat),s===`standalone`||s===`electron-overlay`){let e=await a(),t=XS(s,e!==null)?c:null,n=await _({locationHref:window.location.href,storage:window.localStorage,envBaseUrl:null,defaultWorkerBaseUrl:t,runtimeConfigFetcher:async()=>e}),r=null,i=null,o=null;v_(()=>k?(e,t)=>k.sendFsRequest(e,t):r?(e,t)=>r.sendFsRequest(e,t):null),im(()=>k?()=>k.getBestFollowerForTeleport():null),am(()=>k?()=>k.getConnectedFollowers():null);let l=e=>{o&&=(clearInterval(o),null),r?.close();let t=`follower-${e.bootstrapId}`,n=new JS(e.channel,{browserTransport:p.getTransport(),browserAPI:p,onSnapshot:e=>{u.panels.chat.loadMessages(e)},onUserMessage:e=>{u.panels.chat.addUserMessage(e)},onStatus:e=>{u.panels.chat.setProcessing(e===`processing`)},onTargetsChanged:()=>void i()});r=n,p.setTrayTargetProvider(n),u.panels.chat.setAgent(n),n.requestSnapshot();let i=async()=>{try{let e=await p.listPages();n.advertiseTargets(e.map(e=>({targetId:e.targetId,title:e.title,url:e.url})),t)}catch{}};o=setInterval(i,5e3),i(),$.info(`Follower sync wired to chat panel`,{trayId:e.trayId})},d=e=>{i?.cancel(),o&&=(clearInterval(o),null),r?.close(),r=null,i=SS({joinUrl:e,runtime:`slicc-standalone`,fetchImpl:yh()},{onConnected:e=>l(e),onReconnecting:e=>{$.info(`Follower reconnecting`,{attempt:e})},onGaveUp:e=>{$.warn(`Follower reconnect gave up`,{lastError:e})}})};if(window.addEventListener(`slicc:tray-join`,(e=>{d(e.detail.joinUrl)})),window.addEventListener(`beforeunload`,()=>{o&&clearInterval(o),r?.close(),i?.cancel()},{once:!0}),n?.joinUrl)d(n.joinUrl);else if(n?.workerBaseUrl){let e,t,r,i,a=()=>{t=new KS({browserTransport:p.getTransport(),browserAPI:p,getMessages:()=>u.panels.chat.getMessages(),getScoopJid:()=>g?.jid??`cone`,onFollowerMessage:(e,t)=>{u.panels.chat.addUserMessage(e),A.sendMessage(e,t)},onFollowerAbort:()=>{A.stop()}}),k=t,xh(()=>t.getConnectedFollowers()),p.setTrayTargetProvider(t),i&&clearInterval(i);let n=async()=>{try{let e=await p.listPages();t.setLocalTargets(e.map(e=>({targetId:e.targetId,title:e.title,url:e.url})))}catch{}};i=setInterval(n,5e3),n(),r=new bS({sendControlMessage:t=>e.sendControlMessage(t),onPeerConnected:(e,n)=>{$.info(`Tray follower data channel opened`,{controllerId:e.controllerId,bootstrapId:e.bootstrapId,attempt:e.attempt,runtime:e.runtime}),t.addFollower(e.bootstrapId,n,{runtime:e.runtime,connectedAt:e.connectedAt??void 0})}})};a(),m.add(e=>{t.broadcastEvent(e)}),e=new hh({workerBaseUrl:n.workerBaseUrl,runtime:`slicc-standalone`,fetchImpl:yh(),onControlMessage:e=>{if(e.type===`webhook.event`){j.handleWebhookEvent(e.webhookId,e.headers,e.body);return}r.handleControlMessage(e).catch(e=>{$.warn(`Tray leader bootstrap handling failed`,{error:e instanceof Error?e.message:String(e)})})}}),wh(async()=>{t.stop(),r.stop(),e.stop(),await e.clearSession();let n=await e.start(),i=f(window.location.href,n.workerBaseUrl,n.trayId);return i!==window.location.href&&window.history.replaceState(window.history.state,``,i),a(),dh()}),e.start().then(e=>{let t=f(window.location.href,e.workerBaseUrl,e.trayId);t!==window.location.href&&window.history.replaceState(window.history.state,``,t)}).catch(e=>{$.warn(`Leader tray join failed`,{error:e instanceof Error?e.message:String(e)})}),window.addEventListener(`beforeunload`,()=>{clearInterval(i),t.stop(),r.stop(),e.stop()},{once:!0})}}$.info(`Orchestrator initialized — cone+scoops ready`,{scoopCount:w.getScoops().length}),fb().catch(()=>{})}kC().catch(e=>{$.error(`Fatal error`,e);let t=document.getElementById(`app`);if(t){let n=document.createElement(`div`);n.style.cssText=`padding: 2rem; text-align: center;`;let r=document.createElement(`h1`);r.style.color=`var(--s2-negative, #e34850)`,r.textContent=`Failed to start`;let i=document.createElement(`p`);i.style.color=`var(--s2-content-tertiary, #717171)`,i.textContent=e.message,n.appendChild(r),n.appendChild(i);let a=document.createElement(`button`);for(a.textContent=`Reset all data & reload`,a.style.cssText=`margin-top: 1rem; padding: 0.5rem 1.5rem; background: var(--s2-negative, #e34850); color: #fff; border: none; border-radius: 6px; cursor: pointer; font-size: 14px;`,a.addEventListener(`click`,async()=>{a.disabled=!0,a.textContent=`Resetting…`;let e=await indexedDB.databases();await Promise.all(e.map(e=>e.name?new Promise(t=>{let n=indexedDB.deleteDatabase(e.name);n.onsuccess=()=>t(),n.onerror=()=>t(),n.onblocked=()=>t()}):Promise.resolve())),location.reload()}),n.appendChild(a);t.firstChild;)t.removeChild(t.firstChild);t.appendChild(n)}});export{Qs as t};