sliccy 2.12.2 → 2.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ui/assets/{anthropic-CwdpDvCM.js → anthropic-DydNCgDy.js} +1 -1
- package/dist/ui/assets/{azure-openai-responses-BwS3n12X.js → azure-openai-responses-DxH2Px6b.js} +1 -1
- package/dist/ui/assets/{es-CpnfS6n9.js → es-B5iJSqsW.js} +1 -1
- package/dist/ui/assets/{google-Y57SSJyD.js → google-qCN1qFF4.js} +1 -1
- package/dist/ui/assets/{index-DsbGVhyf.js → index-BT6DRWNw.js} +159 -159
- package/dist/ui/assets/{mistral-CbewUoYp.js → mistral-CTRpeltl.js} +1 -1
- package/dist/ui/assets/{openai-codex-responses-DiWYu0ab.js → openai-codex-responses-CkgVZfGw.js} +1 -1
- package/dist/ui/assets/{openai-completions-C0eWZR0C.js → openai-completions-D3-Ee_nG.js} +1 -1
- package/dist/ui/assets/{openai-responses-DRmTEaZS.js → openai-responses-B-HSv08E.js} +1 -1
- package/dist/ui/assets/{openai-responses-shared-Ib7XQMhx.js → openai-responses-shared-DNKeM9as.js} +1 -1
- package/dist/ui/assets/{provider-settings-sVrbo4MH.js → provider-settings-B-aJlxa2.js} +3 -3
- package/dist/ui/index.html +3 -3
- package/dist/ui/packages/webapp/index.html +3 -3
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/slicc-editor-DRq182-r.js","assets/preload-helper-D4M6sveU.js","assets/dist-CEBWSFtw.js","assets/magick-wasm-BuraEslY.js","assets/chunk-jRWAZmH_.js","assets/sql-wasm-CNZ88Vcf.js","assets/__vite-browser-external-MxCBxUMe.js","assets/pyodide-ZBgukovK.js","assets/es-
|
|
2
|
-
import{i as e,o as t,r as n,t as r}from"./chunk-jRWAZmH_.js";import{t as i}from"./logger-B-No_qN_.js";import{t as a}from"./preload-helper-D4M6sveU.js";import{_ as o,a as s,b as c,c as l,d as u,f as d,g as f,i as p,m,n as h,o as g,p as _,r as v,s as y,t as b,u as x,v as S,x as C,y as w}from"./provider-settings-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/slicc-editor-DRq182-r.js","assets/preload-helper-D4M6sveU.js","assets/dist-CEBWSFtw.js","assets/magick-wasm-BuraEslY.js","assets/chunk-jRWAZmH_.js","assets/sql-wasm-CNZ88Vcf.js","assets/__vite-browser-external-MxCBxUMe.js","assets/pyodide-ZBgukovK.js","assets/es-B5iJSqsW.js","assets/dist-VQCt339k2.js","assets/provider-settings-B-aJlxa2.js","assets/simple-options-CP_5aL7H.js","assets/openai-CuiHR4mv.js","assets/logger-B-No_qN_.js","assets/skills-B1zKlleu.js","assets/fs-CuJwg7sR.js","assets/path-utils-DFPXxD-4.js","assets/constants-BnzYaC4L.js","assets/xterm-BmfB5bmM.css","assets/offscreen-client-Dom7iV01.js","assets/bsh-watchdog-BofJVeV-.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{i as e,o as t,r as n,t as r}from"./chunk-jRWAZmH_.js";import{t as i}from"./logger-B-No_qN_.js";import{t as a}from"./preload-helper-D4M6sveU.js";import{_ as o,a as s,b as c,c as l,d as u,f as d,g as f,i as p,m,n as h,o as g,p as _,r as v,s as y,t as b,u as x,v as S,x as C,y as w}from"./provider-settings-B-aJlxa2.js";import{f as T,l as E,p as D,s as O,u as ee}from"./constants-BnzYaC4L.js";import{a as te,i as ne,n as k,o as re,r as ie}from"./fs-CuJwg7sR.js";import{n as ae,t as oe}from"./path-utils-DFPXxD-4.js";import{n as se,r as ce}from"./skills-B1zKlleu.js";import{_ as le,a as ue,b as de,c as fe,d as A,f as pe,g as me,h as he,i as ge,l as _e,m as ve,n as ye,o as be,p as xe,r as j,s as Se,t as Ce,u as we,v as Te,x as Ee,y as M}from"./db-CJnk7hWr.js";import{t as De}from"./magick-wasm-BuraEslY.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 N(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var P=N();function Oe(e){P=e}var ke={exec:()=>null};function Ae(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(F.caret,`$1`),n=n.replace(e,i),r},getRegex:()=>new RegExp(n,t)};return r}var je=(()=>{try{return!0}catch{return!1}})(),F={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)}}>`)},Me=/^(?:[ \t]*(?:\n|$))+/,Ne=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,Pe=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,Fe=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,Ie=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,Le=/ {0,3}(?:[*+-]|\d{1,9}[.)])/,Re=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,ze=Ae(Re).replace(/bull/g,Le).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(),Be=Ae(Re).replace(/bull/g,Le).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(),Ve=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,He=/^[^\n]+/,Ue=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,We=Ae(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace(`label`,Ue).replace(`title`,/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),Ge=Ae(/^(bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,Le).getRegex(),Ke=`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`,qe=/<!--(?:-?>|[\s\S]*?(?:-->|$))/,Je=Ae(`^ {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`,qe).replace(`tag`,Ke).replace(`attribute`,/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),Ye=Ae(Ve).replace(`hr`,Fe).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`,Ke).getRegex(),Xe={blockquote:Ae(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace(`paragraph`,Ye).getRegex(),code:Ne,def:We,fences:Pe,heading:Ie,hr:Fe,html:Je,lheading:ze,list:Ge,newline:Me,paragraph:Ye,table:ke,text:He},Ze=Ae(`^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)`).replace(`hr`,Fe).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`,Ke).getRegex(),Qe={...Xe,lheading:Be,table:Ze,paragraph:Ae(Ve).replace(`hr`,Fe).replace(`heading`,` {0,3}#{1,6}(?:\\s|$)`).replace(`|lheading`,``).replace(`table`,Ze).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`,Ke).getRegex()},$e={...Xe,html:Ae(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace(`comment`,qe).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:ke,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:Ae(Ve).replace(`hr`,Fe).replace(`heading`,` *#{1,6} *[^
|
|
3
3
|
]`).replace(`lheading`,ze).replace(`|table`,``).replace(`blockquote`,` {0,3}>`).replace(`|fences`,``).replace(`|list`,``).replace(`|html`,``).replace(`|tag`,``).getRegex()},et=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,tt=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,nt=/^( {2,}|\\)\n(?!\s*$)/,rt=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,it=/[\p{P}\p{S}]/u,at=/[\s\p{P}\p{S}]/u,ot=/[^\s\p{P}\p{S}]/u,st=Ae(/^((?![*_])punctSpace)/,`u`).replace(/punctSpace/g,at).getRegex(),ct=/(?!~)[\p{P}\p{S}]/u,lt=/(?!~)[\s\p{P}\p{S}]/u,ut=/(?:[^\s\p{P}\p{S}]|~)/u,dt=Ae(/link|precode-code|html/,`g`).replace(`link`,/\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace(`precode-`,je?"(?<!`)()":"(^^|[^`])").replace(`code`,/(?<b>`+)[^`]+\k<b>(?!`)/).replace(`html`,/<(?! )[^<>]*?>/).getRegex(),ft=/^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/,pt=Ae(ft,`u`).replace(/punct/g,it).getRegex(),mt=Ae(ft,`u`).replace(/punct/g,ct).getRegex(),ht=`^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)`,gt=Ae(ht,`gu`).replace(/notPunctSpace/g,ot).replace(/punctSpace/g,at).replace(/punct/g,it).getRegex(),_t=Ae(ht,`gu`).replace(/notPunctSpace/g,ut).replace(/punctSpace/g,lt).replace(/punct/g,ct).getRegex(),vt=Ae(`^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)`,`gu`).replace(/notPunctSpace/g,ot).replace(/punctSpace/g,at).replace(/punct/g,it).getRegex(),yt=Ae(/^~~?(?:((?!~)punct)|[^\s~])/,`u`).replace(/punct/g,it).getRegex(),bt=Ae(`^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)`,`gu`).replace(/notPunctSpace/g,ot).replace(/punctSpace/g,at).replace(/punct/g,it).getRegex(),xt=Ae(/\\(punct)/,`gu`).replace(/punct/g,it).getRegex(),St=Ae(/^<(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(),Ct=Ae(qe).replace(`(?:-->|$)`,`-->`).getRegex(),wt=Ae(`^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`,Ct).replace(`attribute`,/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),Tt=/(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/,Et=Ae(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace(`label`,Tt).replace(`href`,/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace(`title`,/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),Dt=Ae(/^!?\[(label)\]\[(ref)\]/).replace(`label`,Tt).replace(`ref`,Ue).getRegex(),Ot=Ae(/^!?\[(ref)\](?:\[\])?/).replace(`ref`,Ue).getRegex(),kt=Ae(`reflink|nolink(?!\\()`,`g`).replace(`reflink`,Dt).replace(`nolink`,Ot).getRegex(),At=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,jt={_backpedal:ke,anyPunctuation:xt,autolink:St,blockSkip:dt,br:nt,code:tt,del:ke,delLDelim:ke,delRDelim:ke,emStrongLDelim:pt,emStrongRDelimAst:gt,emStrongRDelimUnd:vt,escape:et,link:Et,nolink:Ot,punctuation:st,reflink:Dt,reflinkSearch:kt,tag:wt,text:rt,url:ke},Mt={...jt,link:Ae(/^!?\[(label)\]\((.*?)\)/).replace(`label`,Tt).getRegex(),reflink:Ae(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace(`label`,Tt).getRegex()},Nt={...jt,emStrongRDelimAst:_t,emStrongLDelim:mt,delLDelim:yt,delRDelim:bt,url:Ae(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace(`protocol`,At).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:Ae(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace(`protocol`,At).getRegex()},Pt={...Nt,br:Ae(nt).replace(`{2,}`,`*`).getRegex(),text:Ae(Nt.text).replace(`\\b_`,`\\b_| {2,}\\n`).replace(/\{2,\}/g,`*`).getRegex()},Ft={normal:Xe,gfm:Qe,pedantic:$e},It={normal:jt,gfm:Nt,breaks:Pt,pedantic:Mt},Lt={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`},Rt=e=>Lt[e];function zt(e,t){if(t){if(F.escapeTest.test(e))return e.replace(F.escapeReplace,Rt)}else if(F.escapeTestNoEncode.test(e))return e.replace(F.escapeReplaceNoEncode,Rt);return e}function Bt(e){try{e=encodeURI(e).replace(F.percentDecode,`%`)}catch{return null}return e}function Vt(e,t){let n=e.replace(F.findPipe,(e,t,n)=>{let r=!1,i=t;for(;--i>=0&&n[i]===`\\`;)r=!r;return r?`|`:` |`}).split(F.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(F.slashPipe,`|`);return n}function Ht(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 Ut(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 Wt(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 Gt(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 Kt(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 qt(e,t,n){let r=e.match(n.other.indentCodeCompensation);if(r===null)return t;let i=r[1];return t.split(`
|
|
@@ -3735,7 +3735,7 @@ Options:
|
|
|
3735
3735
|
-h, --help Show this help message
|
|
3736
3736
|
`,stderr:``,exitCode:0}}function h1(e={}){return RR(`imgcat`,async(t,n)=>{if(t.length===0||t.includes(`--help`)||t.includes(`-h`))return m1();if(typeof window>`u`||typeof document>`u`)return{stdout:``,stderr:`imgcat: browser APIs are unavailable in this environment
|
|
3737
3737
|
`,exitCode:1};if(!e.onMediaPreview)return{stdout:``,stderr:`imgcat: terminal preview is unavailable
|
|
3738
|
-
`,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=Wa(t);if(!qa(i))return{stdout:``,stderr:`imgcat: unsupported media type: ${e}\n`,exitCode:1};let a=await n.fs.readFileBuffer(t),o=new Uint8Array(a.byteLength);o.set(a),r.push({path:t,mimeType:i,bytes:o})}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}}})}
|
|
3738
|
+
`,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=Wa(t);if(!qa(i))return{stdout:``,stderr:`imgcat: unsupported media type: ${e}\n`,exitCode:1};let a=await n.fs.readFileBuffer(t),o=new Uint8Array(a.byteLength);o.set(a),r.push({path:t,mimeType:i,bytes:o})}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}}})}function g1(e){return async function(t,n){let r=t instanceof Request?t:null,i=_1(t),a=(n?.method??r?.method??`GET`).toUpperCase(),o=y1(r?.headers,n?.headers),s,c;if(n&&`body`in n&&n.body!==void 0)s=x1(n.body,a),c=n.body;else if(r&&a!==`GET`&&a!==`HEAD`){let e=await r.arrayBuffer();s=e.byteLength===0?void 0:new TextDecoder(`utf-8`).decode(new Uint8Array(e)),c=void 0}else s=void 0,c=void 0;c instanceof URLSearchParams&&o&&!b1(o,`content-type`)&&(o[`Content-Type`]=`application/x-www-form-urlencoded;charset=UTF-8`);let l=await e(i,{method:a,headers:o,body:s}),u=new Headers;for(let[e,t]of Object.entries(l.headers))try{u.set(e,t)}catch{}let d=l.status===204||l.status===205||l.status===304||!l.body||l.body.byteLength===0?null:l.body,f=new Response(d,{status:l.status,statusText:l.statusText,headers:u});try{Object.defineProperty(f,`url`,{value:l.url||i,writable:!1,configurable:!0,enumerable:!1})}catch{}return f}}function _1(e){return typeof e==`string`?e:e instanceof URL?e.toString():e.url}function v1(e){if(e){if(e instanceof Headers){let t={};return e.forEach((e,n)=>{t[n]=e}),t}if(Array.isArray(e)){let t={};for(let[n,r]of e)t[n]=r;return t}return{...e}}}function y1(e,t){let n={};e&&e.forEach((e,t)=>{n[t]=e});let r=v1(t);if(r)for(let[e,t]of Object.entries(r))n[e]=t;return n}function b1(e,t){let n=t.toLowerCase();for(let t of Object.keys(e))if(t.toLowerCase()===n)return!0;return!1}function x1(e,t){if(e!=null&&!(t===`GET`||t===`HEAD`)){if(typeof e==`string`)return e;if(e instanceof URLSearchParams)return e.toString();if(e instanceof Uint8Array)return new TextDecoder(`utf-8`).decode(e);if(e instanceof ArrayBuffer)return new TextDecoder(`utf-8`).decode(new Uint8Array(e));if(ArrayBuffer.isView(e)){let t=e;return new TextDecoder(`utf-8`).decode(new Uint8Array(t.buffer,t.byteOffset,t.byteLength))}throw typeof Blob<`u`&&e instanceof Blob?Error(`node fetch shim: Blob request bodies are not supported (use a string, Uint8Array, or URLSearchParams)`):typeof FormData<`u`&&e instanceof FormData?Error(`node fetch shim: FormData request bodies are not supported (post raw application/x-www-form-urlencoded with URLSearchParams instead)`):typeof ReadableStream<`u`&&e instanceof ReadableStream?Error(`node fetch shim: ReadableStream request bodies are not supported (collect into a Uint8Array or string before calling fetch)`):Error(`node fetch shim: unsupported request body type (${Object.prototype.toString.call(e)}); use a string, Uint8Array, ArrayBuffer, or URLSearchParams`)}}var S1=`0.29.3`,C1=`https://sql.js.org/dist/`;function w1(e,t){if(typeof t!=`string`||!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(t))throw Error(`${e} must use an exact semver version in package.json`);return t}var T1=`https://cdn.jsdelivr.net/pyodide/v${w1(`pyodide`,S1)}/full/`,E1=`v20.0.0-js-shim`,D1=`
|
|
3739
3739
|
import sys
|
|
3740
3740
|
import traceback
|
|
3741
3741
|
|
|
@@ -3755,10 +3755,10 @@ except SystemExit as exc:
|
|
|
3755
3755
|
except BaseException:
|
|
3756
3756
|
traceback.print_exc()
|
|
3757
3757
|
__slicc_exit_code = 1
|
|
3758
|
-
`,
|
|
3759
|
-
`,stderr:``,exitCode:0}}function
|
|
3758
|
+
`,O1=null,k1=null,A1=Object.create(null),j1=class extends Error{constructor(e){super(`Process exited with code ${e}`),this.code=e,this.name=`NodeExitError`}};function M1(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 N1(e){let t=e.lastIndexOf(`/`);return t<=0?`/`:e.slice(0,t)}function P1(e,t){return e===`/`?`/${t}`:`${e}/${t}`}function F1(e){if(/^(https?:\/\/|about:|file:|chrome:)/i.test(e))return!0;try{return new URL(e).protocol.length>0}catch{return!1}}function I1(e,t){return e===`/`?t.startsWith(`/`):t===e||t.startsWith(`${e}/`)}function L1(e){return Array.from(e).map(e=>e.toString(16).padStart(2,`0`)).join(``)}function R1(e){return e==null?``:e instanceof Uint8Array?`x'${L1(e)}'`:String(e)}function z1(e){return Wa(e)}function B1(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 V1(e){return e.length===0||e.startsWith(`/`)?!1:!e.split(`/`).some(e=>e===`..`)}function H1(e,t){return ae(`${e}/${t}`)}function U1(e){if(typeof e==`string`)return e;if(e==null)return String(e);try{return JSON.stringify(e)}catch{return String(e)}}function W1(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 G1(){return O1||=(async()=>{let e=(await a(()=>import(`./sql-wasm-CNZ88Vcf.js`).then(e=>t(e.default,1)),__vite__mapDeps([5,4,6]))).default,n=typeof window>`u`?W1(`sql.js/dist/sql-wasm.js`,`../../../../../node_modules/sql.js/dist/`).toString():C1;return e({locateFile:e=>`${n}${e}`})})(),O1}var K1=typeof chrome<`u`&&!!chrome?.runtime?.id;async function q1(){return k1||=(async()=>{let{loadPyodide:e}=await a(async()=>{let{loadPyodide:e}=await import(`./pyodide-ZBgukovK.js`);return{loadPyodide:e}},__vite__mapDeps([7,4,1])),t;return t=typeof window>`u`?decodeURIComponent(W1(`pyodide/pyodide.mjs`,`../../../../../node_modules/pyodide/`).pathname):K1?chrome.runtime.getURL(`pyodide/`):T1,e({indexURL:t,fullStdLib:!1})})(),k1}var J1=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 Y1(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 X1(){return{stdout:`usage: node -e <code> [args...]
|
|
3759
|
+
`,stderr:``,exitCode:0}}function Z1(){return{stdout:`${E1}\n`,stderr:``,exitCode:0}}function Q1(){return RR(`node`,async(e,t)=>{if(e.includes(`--help`)||e.includes(`-h`))return X1();if(e.includes(`--version`)||e.includes(`-v`))return Z1();let n=``,r=`<stdin>`,i=[`node`];if(e.length>0&&(e[0]===`-e`||e[0]===`--eval`)){if(!e[1])return{stdout:``,stderr:`node: option requires an argument -- eval
|
|
3760
3760
|
`,exitCode:9};n=e[1],r=`[eval]`,i=[`node`,...e.slice(2)]}else if(e.length>0&&!e[0].startsWith(`-`)){let a=e[0],o=t.fs.resolvePath(t.cwd,a);if(!await t.fs.exists(o))return{stdout:``,stderr:`node: cannot find module '${a}'\n`,exitCode:1};n=await t.fs.readFile(o),r=a,i=[`node`,a,...e.slice(1)]}else if(t.stdin.trim().length>0)n=t.stdin,r=`<stdin>`,i=[`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"
|
|
3761
|
-
`,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(
|
|
3761
|
+
`,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(U1).join(` `)}\n`),info:(...e)=>c(`${e.map(U1).join(` `)}\n`),warn:(...e)=>l(`${e.map(U1).join(` `)}\n`),error:(...e)=>l(`${e.map(U1).join(` `)}\n`)},d={argv:i,env:Object.fromEntries(t.env.entries()),cwd:()=>t.cwd,exit:e=>{throw new j1(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=t.fetch?g1(t.fetch):globalThis.fetch.bind(globalThis),h=typeof chrome<`u`&&!!chrome?.runtime?.id;if(!h){let e=Y1(n),t=new Set([`fs`,`process`,`buffer`]),r=e.map(e=>e.startsWith(`node:`)?e.slice(5):e).filter(e=>!t.has(e)&&!J1.has(e)),i=A1.__requireCache??=Object.create(null),o=r.filter(e=>!(e in i));if(o.length>0){let e=await Promise.allSettled(o.map(async e=>{let t=await a(()=>import(`https://esm.sh/`+e),[]);i[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 g=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=A1.__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(J1.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=A1.__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.`)},_={exports:{},filename:r};try{if(h){let e=`
|
|
3762
3762
|
const __stdout = [];
|
|
3763
3763
|
const __stderr = [];
|
|
3764
3764
|
const __origConsole = { log: console.log, error: console.error, warn: console.warn, info: console.info };
|
|
@@ -3859,17 +3859,17 @@ except BaseException:
|
|
|
3859
3859
|
console.info = __origConsole.info;
|
|
3860
3860
|
return { stdout: __stdout.join(''), stderr: __stderr.join('') };
|
|
3861
3861
|
`,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 a=`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 i,o=e=>{if(e.data?.type===`exec_result`&&e.data.id===a)if(window.removeEventListener(`message`,o),clearTimeout(i),e.data.error)t({stdout:``,stderr:e.data.error+`
|
|
3862
|
-
`});else try{let n=JSON.parse(e.data.result);t({stdout:n.stdout||``,stderr:n.stderr||``})}catch{t({stdout:e.data.result||``,stderr:``})}};i=setTimeout(()=>{window.removeEventListener(`message`,o),n(Error(`node eval timed out (30s)`))},3e4),window.addEventListener(`message`,o),r.contentWindow.postMessage({type:`exec`,id:a,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,
|
|
3862
|
+
`});else try{let n=JSON.parse(e.data.result);t({stdout:n.stdout||``,stderr:n.stderr||``})}catch{t({stdout:e.data.result||``,stderr:``})}};i=setTimeout(()=>{window.removeEventListener(`message`,o),n(Error(`node eval timed out (30s)`))},3e4),window.addEventListener(`message`,o),r.contentWindow.postMessage({type:`exec`,id:a,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`,`fetch`,`"use strict";\nconst globalThis = __state;\nconst global = __state;\n${n}`)(f,d,u,g,_,_.exports,A1,p,m),{stdout:o.join(``),stderr:s.join(``),exitCode:0}}catch(e){if(e instanceof j1)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 $1=[`--download`,`-d`,`--view`,`-v`];function e0(){return{stdout:`usage: open [--download|-d] [--view|-v] <url|path> [url|path...]
|
|
3863
3863
|
|
|
3864
3864
|
VFS paths are served in a new browser tab via the preview service worker.
|
|
3865
3865
|
URLs (http/https/etc.) are opened directly in a new tab.
|
|
3866
3866
|
For app directories with a default entry file, prefer serve <dir>.
|
|
3867
3867
|
--download, -d Force download instead of opening in a tab.
|
|
3868
3868
|
--view, -v Return image inline so the agent can see it.
|
|
3869
|
-
`,stderr:``,exitCode:0}}function
|
|
3870
|
-
`,exitCode:1};let n=e.includes(`--download`)||e.includes(`-d`),r=e.includes(`--view`)||e.includes(`-v`),i=e.filter(e
|
|
3869
|
+
`,stderr:``,exitCode:0}}function t0(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 n0(){return RR(`open`,async(e,t)=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return e0();if(typeof window>`u`||typeof document>`u`)return{stdout:``,stderr:`open: browser APIs are unavailable in this environment
|
|
3870
|
+
`,exitCode:1};let n=e.includes(`--download`)||e.includes(`-d`),r=e.includes(`--view`)||e.includes(`-v`),i=e.filter(e=>!$1.includes(e));if(i.length===0)return e0();let a=[];for(let e of i){if(F1(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=B1(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=z1(i),s=t0(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:z1(i)}),c=URL.createObjectURL(s),l=document.createElement(`a`);l.href=c,l.download=M1(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=B1(i);window.open(e,`_blank`,`noopener,noreferrer`),a.push(`opened ${i} → ${e}`)}}return{stdout:a.join(`
|
|
3871
3871
|
`)+`
|
|
3872
|
-
`,stderr:``,exitCode:0}})}var
|
|
3872
|
+
`,stderr:``,exitCode:0}})}var r0=null,i0=null;async function a0(){return r0||=a(()=>import(`./es-B5iJSqsW.js`),__vite__mapDeps([8,4,6])),r0}async function o0(){return i0||=a(()=>import(`./dist-VQCt339k2.js`),__vite__mapDeps([9,1])),i0}function s0(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 c0(e){let{range:t,rotation:n}=s0(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 l0(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 u0(){return{stdout:`usage: pdftk <input.pdf> <operation> [args...]
|
|
3873
3873
|
|
|
3874
3874
|
Operations:
|
|
3875
3875
|
dump_data Print metadata (page count, title, author, etc.)
|
|
@@ -3893,14 +3893,14 @@ Page ranges:
|
|
|
3893
3893
|
1-endright Pages 1 to end, rotated 90° clockwise
|
|
3894
3894
|
3left Page 3 rotated 270° (counterclockwise)
|
|
3895
3895
|
1-5down Pages 1-5 rotated 180°
|
|
3896
|
-
`,stderr:``,exitCode:0}}function
|
|
3896
|
+
`,stderr:``,exitCode:0}}function d0(e=`pdftk`){return RR(e,async(t,n)=>{if(t.length===0||t.includes(`--help`)||t.includes(`-h`))return u0();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 a0(),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(`
|
|
3897
3897
|
`)+`
|
|
3898
|
-
`,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
|
|
3899
|
-
`,stderr:``,exitCode:0}}if(a===`cat`){let a=await
|
|
3900
|
-
`,stderr:``,exitCode:0}}function
|
|
3901
|
-
`,stderr:``,exitCode:0}}function
|
|
3898
|
+
`,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 o0(),i=await n.fs.readFileBuffer(r[0].path);return{stdout:(await t.extractText(i)).text+`
|
|
3899
|
+
`,stderr:``,exitCode:0}}if(a===`cat`){let a=await a0(),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=c0(t),c=l0(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 a0(),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=c0(t);if(!n.rotation)return{stdout:``,stderr:`${e}: rotation suffix required (right/left/down) for range '${t}'\n`,exitCode:1};let r=l0(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 f0(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 p0(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 m0(){return{stdout:`usage: python3 [-c code | script.py] [args...]
|
|
3900
|
+
`,stderr:``,exitCode:0}}function h0(){return{stdout:`Python 3.12 (Pyodide)
|
|
3901
|
+
`,stderr:``,exitCode:0}}function g0(e){return RR(e,async(t,n)=>{if(t.includes(`--help`)||t.includes(`-h`))return m0();if(t.includes(`--version`)||t.includes(`-V`))return h0();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 q1(),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 f0(n.fs,e,s);try{e.FS.chdir(n.cwd)}catch{}e.setStdout({batched:e=>t.push(e+`
|
|
3902
3902
|
`)}),e.setStderr({batched:e=>o.push(e+`
|
|
3903
|
-
`)});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(
|
|
3903
|
+
`)});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(D1);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 p0(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 _0(){return{stdout:`usage: serve [--entry <relative-path>] [--project] <directory>
|
|
3904
3904
|
|
|
3905
3905
|
Serve a VFS directory in a new browser tab via the preview service worker.
|
|
3906
3906
|
Defaults to index.html inside the target directory.
|
|
@@ -3909,23 +3909,23 @@ Page ranges:
|
|
|
3909
3909
|
--project Enable project serve mode. Root-relative paths (/scripts/,
|
|
3910
3910
|
/styles/, etc.) resolve against the served directory.
|
|
3911
3911
|
Use this for frameworks like EDS that expect a local dev server.
|
|
3912
|
-
`,stderr:``,exitCode:0}}function
|
|
3912
|
+
`,stderr:``,exitCode:0}}function v0(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
|
|
3913
3913
|
`};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
|
|
3914
|
-
`};n=a}return{directory:n,entry:t,project:r}}function
|
|
3915
|
-
`,exitCode:1};let a=
|
|
3916
|
-
`,stderr:``,exitCode:0}}function
|
|
3917
|
-
`)}\n`:``,stderr:``,exitCode:0}}catch(t){return{stdout:``,stderr:`${e}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}})}function
|
|
3918
|
-
`,stderr:``,exitCode:0}}function
|
|
3914
|
+
`};n=a}return{directory:n,entry:t,project:r}}function y0(e,t){return RR(`serve`,async(n,r)=>{if(n.length===0||n.includes(`--help`)||n.includes(`-h`))return _0();let i=typeof window<`u`&&typeof window.open==`function`;if(!e&&!i)return{stdout:``,stderr:`serve: browser APIs are unavailable in this environment
|
|
3915
|
+
`,exitCode:1};let a=v0(n);if(a.error)return{stdout:``,stderr:a.error,exitCode:1};if(!a.directory)return _0();if(!V1(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=H1(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=B1(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 b0(){return{stdout:`usage: sqlite3 [database] [sql]
|
|
3916
|
+
`,stderr:``,exitCode:0}}function x0(e=`sqlite3`){return RR(e,async(t,n)=>{if(t.includes(`--help`)||t.includes(`-h`))return b0();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 G1(),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(R1).join(`|`));return{stdout:l.length>0?`${l.join(`
|
|
3917
|
+
`)}\n`:``,stderr:``,exitCode:0}}catch(t){return{stdout:``,stderr:`${e}: ${t instanceof Error?t.message:String(t)}\n`,exitCode:1}}})}function S0(){return{stdout:`usage: uname
|
|
3918
|
+
`,stderr:``,exitCode:0}}function C0(){return RR(`uname`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return S0();if(e.length>0)return{stdout:``,stderr:`uname: unsupported arguments
|
|
3919
3919
|
`,exitCode:1};let t=globalThis.navigator?.userAgent;return typeof t!=`string`||t.length===0?{stdout:``,stderr:`uname: navigator.userAgent is unavailable
|
|
3920
|
-
`,exitCode:1}:{stdout:`${t}\n`,stderr:``,exitCode:0}})}function
|
|
3920
|
+
`,exitCode:1}:{stdout:`${t}\n`,stderr:``,exitCode:0}})}function w0(){return{stdout:`usage: man <topic>
|
|
3921
3921
|
|
|
3922
3922
|
Fetches documentation for a given topic from sliccy.com.
|
|
3923
|
-
`,stderr:``,exitCode:0}}function
|
|
3923
|
+
`,stderr:``,exitCode:0}}function T0(e){return e.replace(/<[^>]*>/g,``).replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`).replace(/'/g,`'`).replace(/ /g,` `).trimEnd()}function E0(){return RR(`man`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return w0();if(e.length===0)return{stdout:``,stderr:`What manual page do you want?
|
|
3924
3924
|
For example, try 'man commands'.
|
|
3925
|
-
`,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:
|
|
3926
|
-
`,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
|
|
3927
|
-
`,stderr:``,exitCode:0}}function
|
|
3928
|
-
`,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=T(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(!
|
|
3925
|
+
`,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:T0(await e.text())+`
|
|
3926
|
+
`,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 D0(){return{stdout:`usage: unzip <archive.zip> [-d <destination>]
|
|
3927
|
+
`,stderr:``,exitCode:0}}function O0(){return RR(`unzip`,async(e,t)=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return D0();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
|
|
3928
|
+
`,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=T(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(!I1(a,i))return{stdout:``,stderr:`unzip: blocked suspicious path ${e}\n`,exitCode:1};let o=N1(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 k0(){return{stdout:`usage: webhook <command> [options]
|
|
3929
3929
|
|
|
3930
3930
|
Commands:
|
|
3931
3931
|
create --scoop <name> [--name <name>] [--filter <code>] Create a new webhook endpoint
|
|
@@ -3943,12 +3943,12 @@ Examples:
|
|
|
3943
3943
|
webhook create --scoop slack-relay --name slack --filter "(e) => ({ text: e.body.text, user: e.body.user })"
|
|
3944
3944
|
webhook list
|
|
3945
3945
|
webhook delete abc123
|
|
3946
|
-
`,stderr:``,exitCode:0}}async function
|
|
3947
|
-
`,exitCode:1};let{ok:s,data:c}=await
|
|
3946
|
+
`,stderr:``,exitCode:0}}async function A0(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 j0(){return RR(`webhook`,async e=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return k0();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)
|
|
3947
|
+
`,exitCode:1};let{ok:s,data:c}=await A0(`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 A0(`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
|
|
3948
3948
|
`,stderr:``,exitCode:0};let r=`Active webhooks:
|
|
3949
3949
|
`;for(let e of n)r+=` ${e.id} ${e.name.padEnd(20)} ${e.url}`,e.scoop&&(r+=` -> ${e.scoop}`),e.filter&&(r+=` [filtered]`),r+=`
|
|
3950
3950
|
`;return{stdout:r,stderr:``,exitCode:0}}case`delete`:{let t=e[1];if(!t)return{stdout:``,stderr:`webhook: delete requires an ID
|
|
3951
|
-
`,exitCode:1};let{ok:n,status:r,data:i}=await
|
|
3951
|
+
`,exitCode:1};let{ok:n,status:r,data:i}=await A0(`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 M0(){return{stdout:`usage: crontask <command> [options]
|
|
3952
3952
|
|
|
3953
3953
|
Commands:
|
|
3954
3954
|
create [options] Create a new cron task
|
|
@@ -3980,16 +3980,16 @@ Examples:
|
|
|
3980
3980
|
crontask create --name every-5min --scoop poller --cron "*/5 * * * *" --filter "() => ({ time: Date.now() })"
|
|
3981
3981
|
crontask list
|
|
3982
3982
|
crontask delete abc123
|
|
3983
|
-
`,stderr:``,exitCode:0}}var
|
|
3983
|
+
`,stderr:``,exitCode:0}}var N0=typeof chrome<`u`&&!!chrome?.runtime?.id;function P0(){return globalThis.__slicc_lickManager??null}var F0=null;async function I0(){if(F0)return F0;let{createLickManagerProxy:e}=await a(async()=>{let{createLickManagerProxy:e}=await import(`./lick-manager-proxy-Dw3D3AzG.js`);return{createLickManagerProxy:e}},[]);return F0=e(),F0}async function L0(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 R0(){return RR(`crontask`,async e=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return M0();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
|
|
3984
3984
|
`,exitCode:1};if(!n)return{stdout:``,stderr:`crontask: --cron is required
|
|
3985
|
-
`,exitCode:1};if(
|
|
3986
|
-
`,exitCode:1};let e=
|
|
3985
|
+
`,exitCode:1};if(N0){if(r)return{stdout:``,stderr:`crontask: --filter is not supported in extension mode (CSP restriction)
|
|
3986
|
+
`,exitCode:1};let e=P0(),a=e?await e.createCronTask(t,n,i):await(await I0()).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 L0(`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(N0){let e=P0(),t=e?e.listCronTasks():await(async()=>{let{listCronTasksAsync:e}=await a(async()=>{let{listCronTasksAsync:e}=await import(`./lick-manager-proxy-Dw3D3AzG.js`);return{listCronTasksAsync:e}},[]);return e()})();if(t.length===0)return{stdout:`No active cron tasks
|
|
3987
3987
|
`,stderr:``,exitCode:0};let n=`Active cron tasks:
|
|
3988
3988
|
`;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+=`
|
|
3989
|
-
`;return{stdout:n,stderr:``,exitCode:0}}let{ok:e,data:t}=await
|
|
3989
|
+
`;return{stdout:n,stderr:``,exitCode:0}}let{ok:e,data:t}=await L0(`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
|
|
3990
3990
|
`,stderr:``,exitCode:0};let r=`Active cron tasks:
|
|
3991
3991
|
`;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+=`
|
|
3992
|
-
`;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(
|
|
3992
|
+
`;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(N0){let e=P0();return(e?await e.deleteCronTask(n):await(await I0()).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 L0(`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 z0=new Map,B0=0;function V0(){return RR(`fswatch`,async e=>{let t=e[0];if(!t||t===`--help`)return{stdout:`usage: fswatch <command> [options]
|
|
3993
3993
|
|
|
3994
3994
|
Commands:
|
|
3995
3995
|
create --path <path> --pattern <glob> [--scoop <name>] [--name <name>] Watch for file changes
|
|
@@ -4001,11 +4001,11 @@ Options:
|
|
|
4001
4001
|
--pattern <glob> File pattern to match, e.g. "*.md", "*.bsh" (required)
|
|
4002
4002
|
--scoop <name> Route change events to this scoop as lick events
|
|
4003
4003
|
--name <name> Human-readable name for the watcher
|
|
4004
|
-
`,stderr:``,exitCode:0};if(t===`list`){if(
|
|
4005
|
-
`,stderr:``,exitCode:0};let e=``;for(let[,t]of
|
|
4006
|
-
`,exitCode:1};let n=
|
|
4004
|
+
`,stderr:``,exitCode:0};if(t===`list`){if(z0.size===0)return{stdout:`No active file watchers.
|
|
4005
|
+
`,stderr:``,exitCode:0};let e=``;for(let[,t]of z0)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
|
|
4006
|
+
`,exitCode:1};let n=z0.get(t);return n?(n.unsubscribe(),z0.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
|
|
4007
4007
|
`,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
|
|
4008
|
-
`,exitCode:1};let c=`fsw-${++
|
|
4008
|
+
`,exitCode:1};let c=`fsw-${++B0}`;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}))}})});z0.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 H0=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:K0(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:B1(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)}},U0=`slicc-sprinkle-routes`;function W0(){try{let e=localStorage.getItem(U0);return e?JSON.parse(e):{}}catch{return{}}}function G0(e){try{localStorage.setItem(U0,JSON.stringify(e))}catch{}}function K0(e){return W0()[e]}function q0(e,t){let n=W0();n[e]=t,G0(n)}function J0(e){let t=W0();delete t[e],G0(t)}function Y0(){return W0()}function X0(){return{stdout:`usage: sprinkle <subcommand> [args]
|
|
4009
4009
|
|
|
4010
4010
|
list List available .shtml sprinkles
|
|
4011
4011
|
open <name> Open a sprinkle by name
|
|
@@ -4018,23 +4018,23 @@ Options:
|
|
|
4018
4018
|
chat <html> Show inline HTML in chat (Tool UI)
|
|
4019
4019
|
Use data-action="name" on buttons for callbacks
|
|
4020
4020
|
Pipe HTML: echo "<div>...</div>" | sprinkle chat
|
|
4021
|
-
`,stderr:``,exitCode:0}}function
|
|
4021
|
+
`,stderr:``,exitCode:0}}function Z0(){return typeof window>`u`?null:window.__slicc_sprinkleManager??null}function Q0(){return RR(`sprinkle`,async(e,t)=>{if(e.length===0||e[0]===`--help`||e[0]===`-h`)return X0();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
|
|
4022
4022
|
`,exitCode:1};let r=await mi({html:n,onAction:async(e,t)=>({action:e,data:t})});return r===null?{stdout:``,stderr:`sprinkle chat: not in tool execution context
|
|
4023
4023
|
`,exitCode:1}:{stdout:JSON.stringify(r)+`
|
|
4024
|
-
`,stderr:``,exitCode:0}}let r=
|
|
4024
|
+
`,stderr:``,exitCode:0}}let r=Z0();if(!r)return{stdout:``,stderr:`sprinkle: sprinkle manager not initialized
|
|
4025
4025
|
`,exitCode:1};switch(n){case`list`:{await r.refresh();let e=r.available();if(e.length===0)return{stdout:`No .shtml sprinkles found.
|
|
4026
4026
|
`,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(`
|
|
4027
4027
|
`)+`
|
|
4028
4028
|
`,stderr:``,exitCode:0}}case`open`:{let t=e[1];if(!t)return{stdout:``,stderr:`sprinkle open: name required
|
|
4029
4029
|
`,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
|
|
4030
|
-
`,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=
|
|
4030
|
+
`,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=Y0(),t=Object.entries(e);return t.length===0?{stdout:`No sprinkle routes configured (all licks go to cone).
|
|
4031
4031
|
`,stderr:``,exitCode:0}:{stdout:`Sprinkle routes:
|
|
4032
4032
|
`+t.map(([e,t])=>` ${e} -> ${t}`).join(`
|
|
4033
4033
|
`)+`
|
|
4034
|
-
`,stderr:``,exitCode:0}}if(e.includes(`--clear`))return
|
|
4034
|
+
`,stderr:``,exitCode:0}}if(e.includes(`--clear`))return J0(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=K0(t);return e?{stdout:`${t} -> ${e}\n`,stderr:``,exitCode:0}:{stdout:`${t} -> cone (default)\n`,stderr:``,exitCode:0}}return q0(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
|
|
4035
4035
|
`,exitCode:1};let n=e.slice(2).join(` `);if(!n)return{stdout:``,stderr:`sprinkle send: JSON data required
|
|
4036
4036
|
`,exitCode:1};let i;try{i=JSON.parse(n)}catch{return{stdout:``,stderr:`sprinkle send: invalid JSON
|
|
4037
|
-
`,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
|
|
4037
|
+
`,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 $0(){return`oauth-token — get an OAuth access token for a provider
|
|
4038
4038
|
|
|
4039
4039
|
Usage:
|
|
4040
4040
|
oauth-token <providerId> Get token for a specific provider
|
|
@@ -4056,14 +4056,14 @@ Examples:
|
|
|
4056
4056
|
oauth-token adobe
|
|
4057
4057
|
oauth-token github --scope "repo,models:read"
|
|
4058
4058
|
curl -H "Authorization: Bearer $(oauth-token github)" https://api.github.com/user
|
|
4059
|
-
`}function
|
|
4059
|
+
`}function e2(){return RR(`oauth-token`,async e=>{let{getOAuthAccountInfo:t,getSelectedProvider:n,getAccounts:r}=await a(async()=>{let{getOAuthAccountInfo:e,getSelectedProvider:t,getAccounts:n}=await import(`./provider-settings-B-aJlxa2.js`).then(e=>e.l);return{getOAuthAccountInfo:e,getSelectedProvider:t,getAccounts:n}},__vite__mapDeps([10,4,1,11,12,13])),{getRegisteredProviderConfig:i,getRegisteredProviderIds:o}=await a(async()=>{let{getRegisteredProviderConfig:e,getRegisteredProviderIds:t}=await import(`./provider-settings-B-aJlxa2.js`).then(e=>e.h);return{getRegisteredProviderConfig:e,getRegisteredProviderIds:t}},__vite__mapDeps([10,4,1,11,12,13]));if(e.includes(`--help`)||e.includes(`-h`))return{stdout:$0(),stderr:``,exitCode:0};if(e.includes(`--list`))return t2(r,o,i,t);let s,c=e.indexOf(`--scope`);if(c>=0){if(s=e[c+1]?.trim(),!s||s.startsWith(`-`))return{stdout:``,stderr:`oauth-token: --scope requires a value
|
|
4060
4060
|
`,exitCode:1};e.splice(c,2)}let l,u=e.indexOf(`--provider`);if(u>=0){if(l=e[u+1],!l)return{stdout:``,stderr:`oauth-token: --provider requires a value
|
|
4061
4061
|
`,exitCode:1}}else if(e.length>0)l=e[0];else{let e=n(),t=i(e);if(t?.isOAuth&&t.onOAuthLogin)l=e;else if(l=o().find(e=>{let t=i(e);return t?.isOAuth&&t.onOAuthLogin}),!l)return{stdout:``,stderr:`oauth-token: no OAuth providers configured
|
|
4062
4062
|
`,exitCode:1}}let d=i(l);if(!d)return{stdout:``,stderr:`oauth-token: unknown provider "${l}"\n`,exitCode:1};if(!d.isOAuth||!d.onOAuthLogin)return{stdout:``,stderr:`oauth-token: provider "${l}" is not an OAuth provider\n`,exitCode:1};if(!s){let e=t(l);if(e&&!e.expired)return{stdout:`${e.token}\n`,stderr:``,exitCode:0}}try{let{createOAuthLauncher:e}=await a(async()=>{let{createOAuthLauncher:e}=await import(`./oauth-service-DUXASG7L.js`);return{createOAuthLauncher:e}},[]),n=e();await d.onOAuthLogin(n,()=>{},s?{scopes:s}:void 0);let r=t(l);return r&&r.token?{stdout:`${r.token}\n`,stderr:``,exitCode:0}:(console.error(`[oauth-token] Provider ${l}: login completed but no token was saved`),{stdout:``,stderr:`oauth-token: login completed but no token was saved
|
|
4063
|
-
`,exitCode:1})}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(`[oauth-token] Provider ${l}: login failed:`,t),{stdout:``,stderr:`oauth-token: login failed: ${t}\n`,exitCode:1}}})}function
|
|
4063
|
+
`,exitCode:1})}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(`[oauth-token] Provider ${l}: login failed:`,t),{stdout:``,stderr:`oauth-token: login failed: ${t}\n`,exitCode:1}}})}function t2(e,t,n,r){let i=t().filter(e=>n(e)?.isOAuth);if(i.length===0)return{stdout:`No OAuth providers configured.
|
|
4064
4064
|
`,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(`
|
|
4065
4065
|
`)+`
|
|
4066
|
-
`,stderr:``,exitCode:0}}function
|
|
4066
|
+
`,stderr:``,exitCode:0}}function n2(){return`secret — manage secrets for the fetch proxy
|
|
4067
4067
|
|
|
4068
4068
|
Usage:
|
|
4069
4069
|
secret set <name> --domain <patterns> Show instructions for adding a secret
|
|
@@ -4080,19 +4080,19 @@ Examples:
|
|
|
4080
4080
|
secret list
|
|
4081
4081
|
secret delete GITHUB_TOKEN
|
|
4082
4082
|
secret test GITHUB_TOKEN https://api.github.com/repos
|
|
4083
|
-
`}async function
|
|
4084
|
-
`,exitCode:1};let n=
|
|
4083
|
+
`}async function r2(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 i2(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 a2(){return RR(`secret`,async e=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return{stdout:n2(),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>
|
|
4084
|
+
`,exitCode:1};let n=i2(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):
|
|
4085
4085
|
`,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):
|
|
4086
4086
|
`,i+=` Add to ~/.slicc/secrets.env:
|
|
4087
4087
|
`,i+=` ${t}=<value>\n`,i+=` ${t}_DOMAINS=${r}\n\n`,i+=`Then restart the server to pick up changes.
|
|
4088
|
-
`,{stdout:i,stderr:``,exitCode:0}}case`list`:{let{ok:e,data:t}=await
|
|
4088
|
+
`,{stdout:i,stderr:``,exitCode:0}}case`list`:{let{ok:e,data:t}=await r2(`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
|
|
4089
4089
|
`,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>
|
|
4090
4090
|
`,exitCode:1};let n=`To delete the secret "${t}", use one of the following methods:\n\n`;return n+=` macOS Keychain (swift-server):
|
|
4091
4091
|
`,n+=` security delete-generic-password -s ai.sliccy.slicc -a ${t}\n\n`,n+=` Environment file (node-server):
|
|
4092
4092
|
`,n+=` Remove the ${t}= and ${t}_DOMAINS= lines from ~/.slicc/secrets.env\n\n`,n+=`Then restart the server to pick up changes.
|
|
4093
4093
|
`,{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>
|
|
4094
|
-
`,exitCode:1};let r;try{r=new URL(n).hostname}catch{return{stdout:``,stderr:`secret: invalid URL "${n}"\n`,exitCode:1}}let{ok:i,data:o}=await
|
|
4095
|
-
`,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 a(async()=>{let{isAllowedDomain:e}=await import(`./secret-masking-ZNVanUmG.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
|
|
4094
|
+
`,exitCode:1};let r;try{r=new URL(n).hostname}catch{return{stdout:``,stderr:`secret: invalid URL "${n}"\n`,exitCode:1}}let{ok:i,data:o}=await r2(`GET`,``);if(!i)return{stdout:``,stderr:`secret: failed to fetch secrets
|
|
4095
|
+
`,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 a(async()=>{let{isAllowedDomain:e}=await import(`./secret-masking-ZNVanUmG.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 o2(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 s2=null;function c2(e){s2=e}function l2(){return s2?.()??null}function u2(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=d2(r),o=d2(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 d2(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 f2(){return{stdout:`rsync — sync files between local VFS and a remote tray runtime
|
|
4096
4096
|
|
|
4097
4097
|
Usage:
|
|
4098
4098
|
rsync [flags] <local-path> <runtime-id>:<remote-path> # push
|
|
@@ -4108,21 +4108,21 @@ Examples:
|
|
|
4108
4108
|
rsync /workspace follower-abc123:/workspace
|
|
4109
4109
|
rsync --delete /shared leader:/shared
|
|
4110
4110
|
rsync follower-abc123:/workspace/project /workspace/project
|
|
4111
|
-
`,stderr:``,exitCode:0}}async function
|
|
4111
|
+
`,stderr:``,exitCode:0}}async function p2(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 m2(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 h2(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 g2(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 _2(e){let t=e.lastIndexOf(`/`);return t<=0?`/`:e.slice(0,t)}async function v2(e,t,n){let r=[],{localPath:i,remotePath:a,runtimeId:o,verbose:s,dryRun:c}=n,l=o2(await p2(e,i),await m2(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(`
|
|
4112
4112
|
`)+`
|
|
4113
|
-
`,stderr:``,exitCode:0};for(let n of[...l.toAdd,...l.toUpdate]){let s=i+`/`+n,c=a+`/`+n;await
|
|
4113
|
+
`,stderr:``,exitCode:0};for(let n of[...l.toAdd,...l.toUpdate]){let s=i+`/`+n,c=a+`/`+n;await g2(t,o,_2(c));let l=await t(o,{op:`writeFile`,path:c,content:b2(await e.readFile(s,{encoding:`binary`})),encoding:`base64`});if(!l[0].ok)return{stdout:r.join(`
|
|
4114
4114
|
`)+`
|
|
4115
4115
|
`,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(`
|
|
4116
4116
|
`)+`
|
|
4117
4117
|
`,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(`
|
|
4118
4118
|
`)+`
|
|
4119
|
-
`,stderr:``,exitCode:0}}async function
|
|
4119
|
+
`,stderr:``,exitCode:0}}async function y2(e,t,n){let r=[],{localPath:i,remotePath:a,runtimeId:o,verbose:s,dryRun:c}=n,l=o2(await m2(t,o,a),await p2(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(`
|
|
4120
4120
|
`)+`
|
|
4121
|
-
`,stderr:``,exitCode:0};for(let n of[...l.toAdd,...l.toUpdate]){let r=a+`/`+n,s=i+`/`+n,c=
|
|
4121
|
+
`,stderr:``,exitCode:0};for(let n of[...l.toAdd,...l.toUpdate]){let r=a+`/`+n,s=i+`/`+n,c=_2(s);await e.exists(c)||await e.mkdir(c,{recursive:!0});let l=x2(await h2(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(`
|
|
4122
4122
|
`)+`
|
|
4123
|
-
`,stderr:``,exitCode:0}}function
|
|
4123
|
+
`,stderr:``,exitCode:0}}function b2(e){let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function x2(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 S2(e={}){let t=e.fs,n=e.getSendFsRequest??l2;return RR(`rsync`,async e=>{if(e.includes(`--help`)||e.includes(`-h`)||e.length===0)return f2();if(!t)return{stdout:``,stderr:`rsync: no filesystem available
|
|
4124
4124
|
`,exitCode:1};let r=n();if(!r)return{stdout:``,stderr:`rsync: not connected to a tray — rsync requires a tray connection
|
|
4125
|
-
`,exitCode:1};let i=
|
|
4125
|
+
`,exitCode:1};let i=u2(e);if(`error`in i)return i.error===`__help__`?f2():{stdout:``,stderr:`rsync: ${i.error}\n`,exitCode:1};try{return i.direction===`push`?await v2(t,r,i):await y2(t,r,i)}catch(e){return{stdout:``,stderr:`rsync: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}})}var C2=[`/workspace/skills`];async function w2(e){let t=new Map;for(let n of C2)await e.exists(n)&&await T2(e,n,t);return await T2(e,`/`,t),t}async function T2(e,t,n){for await(let r of e.walk(t)){if(!r.endsWith(`.jsh`))continue;let e=E2(r);n.has(e)||n.set(e,r)}}function E2(e){let t=e.split(`/`).pop()??e;return t.endsWith(`.jsh`)?t.slice(0,-4):t}function D2(e={}){let t=e.scriptCatalog!==void 0||e.fs!==void 0?e:typeof e.walk==`function`&&typeof e.exists==`function`?{fs:e}:{};return RR(`which`,async(e,n)=>{if(e.includes(`--help`)||e.includes(`-h`))return{stdout:`which - locate a command
|
|
4126
4126
|
|
|
4127
4127
|
Usage: which <command> [command...]
|
|
4128
4128
|
|
|
@@ -4132,12 +4132,12 @@ Prints the path of the given command(s).
|
|
|
4132
4132
|
|
|
4133
4133
|
Exit code 0 if all commands found, 1 if any not found.
|
|
4134
4134
|
`,stderr:``,exitCode:0};if(e.length===0)return{stdout:``,stderr:`which: missing argument
|
|
4135
|
-
`,exitCode:1};let r=n.getRegisteredCommands?.()??[],i=new Set(r),a=t.scriptCatalog?await t.scriptCatalog.getJshCommands():t.fs?await
|
|
4135
|
+
`,exitCode:1};let r=n.getRegisteredCommands?.()??[],i=new Set(r),a=t.scriptCatalog?await t.scriptCatalog.getJshCommands():t.fs?await w2(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(`
|
|
4136
4136
|
`)+`
|
|
4137
|
-
`:``,stderr:``,exitCode:+!s}})}async function
|
|
4138
|
-
`,stderr:``,exitCode:0}}function
|
|
4139
|
-
`,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(/^\.\//,``))||
|
|
4140
|
-
`,exitCode:1};let c=D(o);return await t.fs.writeFile(i,c),{stdout:`created ${i} (${s} file(s))\n`,stderr:``,exitCode:0}})}function
|
|
4137
|
+
`:``,stderr:``,exitCode:+!s}})}async function O2(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=P1(t,o),s=n?`${n}/${o}`:o;a+=await O2(e,i,s,r)}return a}function k2(){return{stdout:`usage: zip [-r] <archive.zip> <path> [path...]
|
|
4138
|
+
`,stderr:``,exitCode:0}}function A2(){return RR(`zip`,async(e,t)=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return k2();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
|
|
4139
|
+
`,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(/^\.\//,``))||M1(r);if(i.isDirectory&&!n)return{stdout:``,stderr:`zip: ${e} is a directory (use -r)\n`,exitCode:1};s+=await O2(t,r,a,o)}if(s===0)return{stdout:``,stderr:`zip: nothing to do
|
|
4140
|
+
`,exitCode:1};let c=D(o);return await t.fs.writeFile(i,c),{stdout:`created ${i} (${s} file(s))\n`,stderr:``,exitCode:0}})}function j2(){return{stdout:`screencapture - capture screen, window, or tab using browser screen sharing
|
|
4141
4141
|
|
|
4142
4142
|
Usage: screencapture [options] <output-file>
|
|
4143
4143
|
|
|
@@ -4153,57 +4153,57 @@ Examples:
|
|
|
4153
4153
|
screencapture screenshot.png # Capture to file
|
|
4154
4154
|
screencapture -c # Capture to clipboard
|
|
4155
4155
|
screencapture -v capture.png # Capture and return for agent vision
|
|
4156
|
-
`,stderr:``,exitCode:0}}function
|
|
4156
|
+
`,stderr:``,exitCode:0}}function M2(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 N2(e){switch(e.split(`.`).pop()?.toLowerCase()){case`jpg`:case`jpeg`:return`image/jpeg`;case`webp`:return`image/webp`;default:return`image/png`}}async function P2(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 F2(){return RR(`screencapture`,async(e,t)=>{if(e.includes(`--help`)||e.includes(`-h`))return j2();if(typeof window>`u`||typeof navigator>`u`||typeof document>`u`)return{stdout:``,stderr:`screencapture: browser APIs are unavailable in this environment
|
|
4157
4157
|
`,exitCode:1};if(!navigator.mediaDevices?.getDisplayMedia)return{stdout:``,stderr:`screencapture: screen capture is not supported in this browser
|
|
4158
4158
|
`,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)
|
|
4159
|
-
`,exitCode:1};let s=o||`screenshot.png`,c=
|
|
4160
|
-
`,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,${
|
|
4159
|
+
`,exitCode:1};let s=o||`screenshot.png`,c=N2(s),l=c===`image/png`?1:.92,u;try{u=await P2(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
|
|
4160
|
+
`,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,${M2(f)}>`,stderr:``,exitCode:0}:{stdout:`captured ${m} KB to ${M1(p)}\n`,stderr:``,exitCode:0}})}function I2(e){return e instanceof Error?e.message:String(e)}function L2(){return{stdout:`usage: pbcopy
|
|
4161
4161
|
|
|
4162
4162
|
Copy stdin to the clipboard.
|
|
4163
4163
|
Example: echo hello | pbcopy
|
|
4164
|
-
`,stderr:``,exitCode:0}}function
|
|
4164
|
+
`,stderr:``,exitCode:0}}function R2(){return{stdout:`usage: pbpaste
|
|
4165
4165
|
|
|
4166
4166
|
Paste clipboard contents to stdout.
|
|
4167
|
-
`,stderr:``,exitCode:0}}function
|
|
4167
|
+
`,stderr:``,exitCode:0}}function z2(e){return{stdout:`usage: ${e} [-i|-o]\n\n -i Force copy mode (read from stdin)
|
|
4168
4168
|
-o Force paste mode (write to stdout)
|
|
4169
4169
|
(default) Auto-detect: stdin present = copy, no stdin = paste
|
|
4170
|
-
Example: echo hello | ${e}\n Example: ${e} -o > file.txt\n`,stderr:``,exitCode:0}}async function
|
|
4170
|
+
Example: echo hello | ${e}\n Example: ${e} -o > file.txt\n`,stderr:``,exitCode:0}}async function B2(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: ${I2(e)}\n`,exitCode:1}}}async function V2(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: ${I2(t)}\n`,exitCode:1}}}function H2(){return RR(`pbcopy`,async(e,t)=>e.includes(`--help`)||e.includes(`-h`)?L2():B2(t.stdin,`pbcopy`))}function U2(){return RR(`pbpaste`,async e=>e.includes(`--help`)||e.includes(`-h`)?R2():V2(`pbpaste`))}function W2(e){return RR(e,async(t,n)=>{if(t.includes(`--help`)||t.includes(`-h`))return z2(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?V2(e):r||n.stdin.length>0?B2(n.stdin,e):V2(e)})}function G2(){return{stdout:`usage: say [-v voice] [-r rate] [-l lang] [--list] <text>
|
|
4171
4171
|
|
|
4172
4172
|
Speaks the given text using the Web Speech API.
|
|
4173
4173
|
-v voice Voice name (partial match supported)
|
|
4174
4174
|
-r rate Speech rate (0.1 to 10, default 1)
|
|
4175
4175
|
-l lang Language tag (required, BCP 47, e.g. en-US, de-DE, fr-FR)
|
|
4176
4176
|
--list List available voices
|
|
4177
|
-
`,stderr:``,exitCode:0}}var
|
|
4178
|
-
`,exitCode:1};if(e.includes(`--list`))return{stdout:(await
|
|
4177
|
+
`,stderr:``,exitCode:0}}var K2=!1,q2=null;function J2(){return K2?Promise.resolve(speechSynthesis.getVoices()):(q2||=new Promise(e=>{let t=speechSynthesis.getVoices();if(t.length>0){K2=!0,e(t);return}let n=()=>{K2=!0,speechSynthesis.removeEventListener(`voiceschanged`,n),e(speechSynthesis.getVoices())};speechSynthesis.addEventListener(`voiceschanged`,n),setTimeout(()=>{speechSynthesis.removeEventListener(`voiceschanged`,n),K2=!0,e(speechSynthesis.getVoices())},1e3)}),q2)}function Y2(){return RR(`say`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return G2();if(typeof window>`u`||typeof speechSynthesis>`u`)return{stdout:``,stderr:`say: Web Speech API unavailable in this environment
|
|
4178
|
+
`,exitCode:1};if(e.includes(`--list`))return{stdout:(await J2()).map(e=>`${e.name} (${e.lang})${e.default?` [default]`:``}`).join(`
|
|
4179
4179
|
`)+`
|
|
4180
4180
|
`,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
|
|
4181
4181
|
`,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
|
|
4182
4182
|
`,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
|
|
4183
4183
|
`,exitCode:1}}else if(o===`-l`){if(a+1>=e.length||e[a+1].startsWith(`-`))return{stdout:``,stderr:`say: -l requires a language tag
|
|
4184
|
-
`,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
|
|
4185
|
-
`,exitCode:1};let o=new SpeechSynthesisUtterance(a);if(o.rate=n,o.lang=r,t){let e=(await
|
|
4184
|
+
`,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 G2();if(!r)return{stdout:``,stderr:`say: -l language tag is required
|
|
4185
|
+
`,exitCode:1};let o=new SpeechSynthesisUtterance(a);if(o.rate=n,o.lang=r,t){let e=(await J2()).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 X2(){return{stdout:`usage: afplay [-v volume] [-r rate] <file>
|
|
4186
4186
|
|
|
4187
4187
|
Plays an audio file using the Web Audio API.
|
|
4188
4188
|
-v volume Volume level (0 to 1, default 1)
|
|
4189
4189
|
-r rate Playback rate (0.25 to 4, default 1)
|
|
4190
|
-
`,stderr:``,exitCode:0}}var
|
|
4191
|
-
`,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(!
|
|
4190
|
+
`,stderr:``,exitCode:0}}var Z2=null;function Q2(){return(!Z2||Z2.state===`closed`)&&(Z2=new AudioContext),Z2}async function $2(e,t,n,r){if(typeof window>`u`||typeof AudioContext>`u`)return{stdout:``,stderr:`afplay: Web Audio API unavailable in this environment
|
|
4191
|
+
`,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(!z1(i).startsWith(`audio/`))return{stdout:``,stderr:`afplay: ${e} is not an audio file\n`,exitCode:1};try{let e=Q2();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 e4(){return RR(`afplay`,async(e,t)=>{if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return X2();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
|
|
4192
4192
|
`,exitCode:1};if(n=parseFloat(e[++t]),isNaN(n)||n<0||n>1)return{stdout:``,stderr:`afplay: volume must be between 0 and 1
|
|
4193
4193
|
`,exitCode:1}}else if(a===`-r`){if(t+1>=e.length||e[t+1].startsWith(`-`))return{stdout:``,stderr:`afplay: -r requires a rate value
|
|
4194
4194
|
`,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
|
|
4195
4195
|
`,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
|
|
4196
|
-
`,exitCode:1};i=a}}return i
|
|
4196
|
+
`,exitCode:1};i=a}}return i?$2(i,n,r,t):X2()})}function t4(){return RR(`chime`,async(e,t)=>e.includes(`--help`)||e.includes(`-h`)?{stdout:`usage: chime
|
|
4197
4197
|
|
|
4198
4198
|
Plays a notification chime sound.
|
|
4199
4199
|
Alias for: afplay /shared/sounds/chime.mp3
|
|
4200
|
-
`,stderr:``,exitCode:0}
|
|
4200
|
+
`,stderr:``,exitCode:0}:$2(`/shared/sounds/chime.mp3`,1,1,t))}function n4(){return RR(`debug`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return{stdout:`usage: debug [on|off]
|
|
4201
4201
|
|
|
4202
4202
|
Toggle debug tabs (Terminal, Memory) in extension mode.
|
|
4203
4203
|
Without arguments, shows current state.
|
|
4204
4204
|
`,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
|
|
4205
4205
|
`,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
|
|
4206
|
-
`,exitCode:1}}})}var
|
|
4206
|
+
`,exitCode:1}}})}var r4=`/.cache/artificial-analysis.json`,i4=1440*60*1e3,a4=`https://artificialanalysis.ai/api/v2/data/llms/models`;async function o4(e,t=!1){if(e&&!t)try{let t=await e.readFile(r4),n=JSON.parse(t);if(Date.now()-n.fetchedAt<i4)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(a4,{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(r4,JSON.stringify(t))}catch{}}return o}function s4(e){return e.toLowerCase().replace(/\./g,`-`).replace(/-\d{8}$/,``).replace(/-\d{4}$/,``)}function c4(e,t){let n=e.toLowerCase(),r=t.find(e=>e.slug===n);if(r)return r;let i=s4(e),a=t.find(e=>s4(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 l4(){return`models - list available LLM models
|
|
4207
4207
|
|
|
4208
4208
|
Usage: models [options]
|
|
4209
4209
|
|
|
@@ -4215,26 +4215,26 @@ Options:
|
|
|
4215
4215
|
--refresh Force re-fetch benchmark data from Artificial Analysis
|
|
4216
4216
|
--no-benchmarks Skip benchmark data enrichment (faster, works offline)
|
|
4217
4217
|
-h, --help Show this help message
|
|
4218
|
-
`}function
|
|
4218
|
+
`}function u4(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`.replace(`.0M`,`M`):e>=1e3?`${(e/1e3).toFixed(0)}K`:`${e}`}function d4(e){return`$${e.toFixed(2)}`}var f4=/\b(embedding|embed|tts|whisper|dall-e|image-gen|audio|vision-preview)\b/i;function p4(e){let t=`${e.id} ${e.name??``}`;return!f4.test(t)}function m4(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 h4(e){let t=new Map;for(let n of e){let e=m4(n.id);t.has(e)||t.set(e,n)}return[...t.values()]}function g4(e,t,n,r,i){let a=i?c4(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 _4(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=`${d4(e.cost.input)} / ${d4(e.cost.output)}`,a=`${u4(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(`
|
|
4219
4219
|
`)+`
|
|
4220
|
-
`}function
|
|
4221
|
-
`,exitCode:1};let y;p||(y=await
|
|
4220
|
+
`}function v4(e){return RR(`models`,async t=>{let{getAccounts:n,getAvailableProviders:r,getProviderConfig:i,getProviderModels:o,getSelectedProvider:s,getSelectedModelId:c}=await a(async()=>{let{getAccounts:e,getAvailableProviders:t,getProviderConfig:n,getProviderModels:r,getSelectedProvider:i,getSelectedModelId:a}=await import(`./provider-settings-B-aJlxa2.js`).then(e=>e.l);return{getAccounts:e,getAvailableProviders:t,getProviderConfig:n,getProviderModels:r,getSelectedProvider:i,getSelectedModelId:a}},__vite__mapDeps([10,4,1,11,12,13]));if(t.includes(`--help`)||t.includes(`-h`))return{stdout:l4(),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.
|
|
4221
|
+
`,exitCode:1};let y;p||(y=await o4(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(p4);if(t.length===0){if(!u)return{stdout:``,stderr:`No models available for provider ${e}.\n`,exitCode:1};continue}let n=t.map(t=>g4(t,e,_,g,y)).sort((e,t)=>t.cost.input-e.cost.input);if(d||(n=h4(n)),x.push(...n),!l){let t=i(e);S.push(_4(t.name,e,n,!!y))}}return l?{stdout:JSON.stringify(x,null,2)+`
|
|
4222
4222
|
`,stderr:``,exitCode:0}:(!d&&!l&&S.push(`Showing latest versions only. Use --all-versions to see all.
|
|
4223
4223
|
`),{stdout:S.join(`
|
|
4224
|
-
`),stderr:``,exitCode:0})})}var
|
|
4224
|
+
`),stderr:``,exitCode:0})})}var y4=n({createCostCommand:()=>O4,registerSessionCostsProvider:()=>x4}),b4=null;function x4(e){b4=e}function S4(){return`cost - show session cost breakdown
|
|
4225
4225
|
|
|
4226
4226
|
Usage: cost [options]
|
|
4227
4227
|
|
|
4228
4228
|
Options:
|
|
4229
4229
|
--json Output as JSON (for programmatic use)
|
|
4230
4230
|
-h, --help Show this help message
|
|
4231
|
-
`}function
|
|
4232
|
-
`);let n=` `+`Agent`.padEnd(16)+`Model`.padEnd(18)+`MTok (in/out)`.padEnd(15)+`Cache (r/w)`.padEnd(15)+`Cost`.padStart(10)+`$/hour`.padStart(10),r=` `+`─`.repeat(84);t.push(n),t.push(r);let i=0,a=0,o=0,s=0,c=0;for(let n of e){let e=n.name.padEnd(16),r=
|
|
4231
|
+
`}function C4(e){let t=e/1e6;return t<.01?`<0.01`:t.toFixed(2)}function w4(e){return`$${e.toFixed(2)}`}function T4(e,t){if(!t||t===0)return`-`;let n=t/(1e3*60*60);return n===0?`-`:`$${(e/n).toFixed(2)}`}function E4(e,t){return e.length<=t?e:e.slice(0,t-3)+`...`}function D4(e){let t=[];t.push(`Session Cost Breakdown:
|
|
4232
|
+
`);let n=` `+`Agent`.padEnd(16)+`Model`.padEnd(18)+`MTok (in/out)`.padEnd(15)+`Cache (r/w)`.padEnd(15)+`Cost`.padStart(10)+`$/hour`.padStart(10),r=` `+`─`.repeat(84);t.push(n),t.push(r);let i=0,a=0,o=0,s=0,c=0;for(let n of e){let e=n.name.padEnd(16),r=E4(n.model,18).padEnd(18),l=`${C4(n.usage.input).padStart(5)} / ${C4(n.usage.output).padStart(5)}`.padEnd(15),u=`${C4(n.usage.cacheRead).padStart(5)} / ${C4(n.usage.cacheWrite).padStart(5)}`.padEnd(15),d=w4(n.usage.cost.total).padStart(10),f=T4(n.usage.cost.total,n.activeTimeMs).padStart(10);t.push(` ${e}${r}${l}${u}${d}${f}`),i+=n.usage.input,a+=n.usage.output,o+=n.usage.cacheRead,s+=n.usage.cacheWrite,c+=n.usage.cost.total}t.push(r);let l=`Total`.padEnd(16),u=``.padEnd(18),d=`${C4(i).padStart(5)} / ${C4(a).padStart(5)}`.padEnd(15),f=`${C4(o).padStart(5)} / ${C4(s).padStart(5)}`.padEnd(15),p=w4(c).padStart(10),m=``.padStart(10);return t.push(` ${l}${u}${d}${f}${p}${m}`),t.join(`
|
|
4233
4233
|
`)+`
|
|
4234
|
-
`}function
|
|
4235
|
-
`,exitCode:1};let t=await
|
|
4234
|
+
`}function O4(){return RR(`cost`,async e=>{if(e.includes(`--help`)||e.includes(`-h`))return{stdout:S4(),stderr:``,exitCode:0};if(!b4)return{stdout:``,stderr:`Cost data not available.
|
|
4235
|
+
`,exitCode:1};let t=await b4();return t.length===0?{stdout:`No session cost data yet.
|
|
4236
4236
|
`,stderr:``,exitCode:0}:e.includes(`--json`)?{stdout:JSON.stringify(t,null,2)+`
|
|
4237
|
-
`,stderr:``,exitCode:0}:{stdout:
|
|
4237
|
+
`,stderr:``,exitCode:0}:{stdout:D4(t),stderr:``,exitCode:0}})}function k4(){return RR(`nuke`,async e=>e.includes(`--help`)||e.includes(`-h`)?{stdout:`Usage: nuke <launch-code>
|
|
4238
4238
|
|
|
4239
4239
|
Completely reset the environment by deleting all local data and reloading.
|
|
4240
4240
|
Destroys the file system, chat history, and scoops database.
|
|
@@ -4242,7 +4242,7 @@ Requires the secret launch code to proceed.
|
|
|
4242
4242
|
`,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…
|
|
4243
4243
|
`,stderr:``,exitCode:0}):{stdout:``,stderr:`⚠️ WARNING: this will reset the entire environment, file system, chats, and scoops.
|
|
4244
4244
|
Run nuke again with the secret launch code to proceed.
|
|
4245
|
-
`,exitCode:1})}var
|
|
4245
|
+
`,exitCode:1})}var A4=i(`agent-command`),j4=`usage: agent <cwd> <allowed-commands> <prompt>
|
|
4246
4246
|
|
|
4247
4247
|
Spawns a sub-scoop, feeds it a task, blocks until the agent loop completes,
|
|
4248
4248
|
then prints the scoop's final message on stdout.
|
|
@@ -4279,17 +4279,17 @@ Examples:
|
|
|
4279
4279
|
agent /home ls,wc,find "how many files do I have in my home directory"
|
|
4280
4280
|
agent --model claude-haiku-4-5 . "*" "summarize files in this directory"
|
|
4281
4281
|
agent --read-only /workspace/,/shared/assets/ . "*" "review the docs"
|
|
4282
|
-
`;function
|
|
4282
|
+
`;function M4(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=N4(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 N4(e){return e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}function P4(e,t){return e.startsWith(`/`)?ae(e):ae(`${t.length>0?t:`/`}/${e}`)}function F4(e){return e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}function I4(e){return e==null?`
|
|
4283
4283
|
`:e.replace(/\n+$/,``)+`
|
|
4284
|
-
`}function
|
|
4285
|
-
`}function
|
|
4286
|
-
`,exitCode:1};let a=
|
|
4287
|
-
`,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:
|
|
4288
|
-
`}function
|
|
4289
|
-
`}function
|
|
4284
|
+
`}function L4(e){return e==null||e===``?``:e.replace(/\n+$/,``)+`
|
|
4285
|
+
`}function R4(){let e=globalThis.__slicc_agent;if(!(!e||typeof e.spawn!=`function`))return e}function z4(e={}){let{getParentJid:t}=e;return RR(`agent`,async(e,n)=>{let r=M4(e);if(r.help)return{stdout:j4,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
|
|
4286
|
+
`,exitCode:1};let a=P4(i,n.cwd),o=F4(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=R4();if(!l)return{stdout:``,stderr:`agent: orchestrator bridge not available
|
|
4287
|
+
`,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:I4(n),stderr:``,exitCode:0}:{stdout:``,stderr:L4(n),exitCode:t}}catch(e){let t=e instanceof Error?e.message:String(e);return A4.error(`agent bridge threw`,e),{stdout:``,stderr:`${t}\n`,exitCode:1}}})}function B4(e={}){let t=[P$({getJshCommands:e.getJshCommands}),f1(),y0(e.browserAPI,e.fs),n0(),h1(e),A2(),O0(),x0(`sqlite3`),x0(`sqllite`),Q1(),g0(`python3`),g0(`python`),j0(),R0(),V0(),Q0(),d0(`pdftk`),d0(`pdf`),L$(`convert`),L$(`magick`),D2({fs:e.fs,scriptCatalog:e.scriptCatalog}),C0(),E0(),e2(),a2(),S2({fs:e.fs}),F2(),H2(),U2(),W2(`xclip`),W2(`xsel`),Y2(),e4(),t4(),v4(e.fs),O4(),k4(),z4({getParentJid:e.getParentJid})];return typeof chrome<`u`&&chrome?.runtime?.id&&t.push(n4()),e.fs&&t.push(...zQ.map(t=>j$(t,e.browserAPI,e.fs))),t}var V4=`https://wry-manatee-359.convex.site/api/v1`,H4=`https://api.tessl.io`,U4=`/workspace/skills`,W4=`slicc-fs-global`,G4=`/workspace/.git/github-token`,K4=`application/vnd.github.v3+json`,q4=`https://www.sliccy.com/skills/catalog.json`;function J4(e){if(!(!e||!e.trim()))return e.split(`,`).map(e=>e.trim()).filter(Boolean)}function Y4(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:J4(e.apps),tasks:J4(e.tasks),role:J4(e.role),purpose:J4(e.purpose)},priority:n}})}var X4={apps:3,tasks:2,role:1,purpose:1};function Z4(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*X4.apps,r.push(`apps(${i.join(`, `)})`));let a=(e.affinity.tasks??[]).filter(e=>t.tasks.includes(e));return a.length&&(n+=a.length*X4.tasks,r.push(`tasks(${a.join(`, `)})`)),(e.affinity.role??[]).includes(t.role)&&(n+=X4.role,r.push(`role(${t.role})`)),(e.affinity.purpose??[]).includes(t.purpose)&&(n+=X4.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 Q4(e){let t=`upskill ${e.repo}`;return e.path&&(t+=` --path ${e.path}`),e.skill&&(t+=` --skill ${e.skill}`),t}async function $4(e){let t=new Set;try{let n=await e.readDir(U4);for(let e of n)e.type===`directory`&&t.add(e.name)}catch{}try{let n=await e.readTextFile(`/${E}/${ee}`),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 e3;function t3(){return e3||=ne.create({dbName:W4}),e3}async function n3(){try{return(await(await t3()).readTextFile(G4)).trim()||void 0}catch{return}}function r3(e,t=K4){let n={Accept:t,"User-Agent":`slicc-upskill`};return e&&(n.Authorization=`Bearer ${e}`),n}async function i3(e){let t=await n3();return{hasToken:!!t,request:(n,r=K4)=>e(n,{headers:r3(t,r)})}}function a3(e,t){if(!e)return;let n=t.toLowerCase();for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}function o3(e){let t=eG(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 s3(e,t,n){let r=o3(e.body),i=r?` GitHub said: ${r}`:``,a=a3(e.headers,`retry-after`),o=a3(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 c3(){return`Discovery roots: /workspace/skills plus accessible **/.agents/skills/* and **/.claude/skills/* anywhere in the VFS.
|
|
4288
|
+
`}function l3(){return`Only native /workspace/skills entries are install-managed; compatibility-discovered .agents/.claude skills remain read-only.
|
|
4289
|
+
`}function u3(e){switch(e){case`native`:return`native`;case`agents`:return`.agents`;case`claude`:return`.claude`}}function d3(e){return e.source===`native`}function f3(e){return d3(e)?e.installed&&e.installedVersion?`installed (v${e.installedVersion})`:`available`:e.installed&&e.installedVersion?`compatibility (state v${e.installedVersion})`:`compatibility (read-only)`}function p3(e){return d3(e)?`install-managed (/workspace/skills)`:`compatibility-only (read-only)`}function m3(e,t){let n=`${t}:\n\n`;n+=` NAME VERSION SOURCE STATUS
|
|
4290
4290
|
`,n+=` ─────────────────────────────────────────────────────────────
|
|
4291
|
-
`;for(let t of e)n+=` ${t.name.padEnd(20)} ${t.manifest.version.padEnd(10)} ${
|
|
4292
|
-
`;for(let n of e.shadowedPaths)t+=` - ${n}\n`}return t}function
|
|
4291
|
+
`;for(let t of e)n+=` ${t.name.padEnd(20)} ${t.manifest.version.padEnd(10)} ${u3(t.source).padEnd(9)} ${f3(t)}\n`;return n+=`\n${c3()}`,n+=l3(),n}function h3(e){let t=`Skill: ${e.manifest.skill}\n`;if(t+=`Version: ${e.manifest.version}\n`,t+=`Description: ${e.manifest.description||`(none)`}\n`,t+=`Source: ${u3(e.source)}\n`,t+=`Source root: ${e.sourceRoot}\n`,t+=`Management: ${p3(e)}\n`,t+=`Status: ${f3(e)}\n`,e.skillFilePath&&(t+=`Instructions: ${e.skillFilePath}\n`),e.shadowedPaths?.length){t+=`Shadowed paths:
|
|
4292
|
+
`;for(let n of e.shadowedPaths)t+=` - ${n}\n`}return t}function g3(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 _3(){return{stdout:`usage: upskill <command> [options]
|
|
4293
4293
|
|
|
4294
4294
|
Install skills from GitHub repositories, ClawHub, or Tessl registry.
|
|
4295
4295
|
|
|
@@ -4302,7 +4302,7 @@ Commands:
|
|
|
4302
4302
|
<clawhub-url> Install skill from ClawHub URL
|
|
4303
4303
|
tessl:<name> Install skill from Tessl registry
|
|
4304
4304
|
|
|
4305
|
-
${
|
|
4305
|
+
${c3()}${l3()}
|
|
4306
4306
|
|
|
4307
4307
|
GitHub Installation:
|
|
4308
4308
|
upskill owner/repo List available skills in repo
|
|
@@ -4343,20 +4343,20 @@ Examples:
|
|
|
4343
4343
|
upskill aemcoder/skills@fix/stateless-tab-targeting --all
|
|
4344
4344
|
upskill https://clawhub.ai/arun-8687/tavily-search
|
|
4345
4345
|
upskill tessl:postgres-pro
|
|
4346
|
-
`,stderr:``,exitCode:0}}async function
|
|
4347
|
-
`),{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/
|
|
4346
|
+
`,stderr:``,exitCode:0}}async function v3(e,t){let n=await t(`${V4}/search?q=${encodeURIComponent(e)}`,{headers:{Accept:`application/json`}});if(n.status!==200)throw Error(`ClawHub returned HTTP ${n.status}`);let r=tG(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 y3(e){let t=e.match(/github\.com\/([^\/?#]+)\/([^\/?#]+)/);return t?{owner:t[1],repo:t[2].replace(/\.git$/,``)}:null}async function b3(e,t){let n=await t(`${H4}/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=tG(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=y3(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 x3=10;async function S3(e,t,n=1){let[r,i]=await Promise.allSettled([v3(e,t),b3(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
|
|
4347
|
+
`),{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/x3),f=Math.max(1,Math.min(n,d)),p=(f-1)*x3,m=s.slice(p,p+x3),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+=`
|
|
4348
4348
|
`}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:
|
|
4349
4349
|
`,a.length>0&&(h+=` From ClawHub: upskill clawhub:<slug>
|
|
4350
4350
|
`),o.length>0&&(h+=` From Tessl: upskill <owner/repo> --skill <name>
|
|
4351
|
-
`),{stdout:h,stderr:``,exitCode:0}}async function
|
|
4352
|
-
`,exitCode:1};let i,a;try{let[n,r]=await Promise.all([(async()=>{let e=await t(
|
|
4353
|
-
`,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
|
|
4351
|
+
`),{stdout:h,stderr:``,exitCode:0}}async function C3(e,t,n,r=!1,i){try{let a=`${U4}/${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=`${V4}/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=XW(o);l||=nG(s.body);let u;try{u=T(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=w3(u,i);return await M3(),{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 w3(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=T3(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 T3(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 E3(e,t){let n=await t(`${H4}/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=tG(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=y3(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 D3(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`?D3(e,t,n,`master`):{status:`not_found`};if(a.status!==200)return{status:`error`,message:`codeload returned HTTP ${a.status}`};let o=XW(i);o||=nG(a.body);try{return{status:`ok`,files:T(o)}}catch(e){return{status:`error`,message:`failed to unzip: ${e instanceof Error?e.message:String(e)}`}}}function O3(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 k3(e,t,n,r,i,a){if(i){let n=await D3(e,t,i,a);if(n.status===`ok`){let e=O3(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(s3(l,`${e}/${t}${r?`/${r}`:``}`,n.hasToken));let u=tG(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 A3(e,t,n,r,i,a,o=!1,s,c){try{let l=`${U4}/${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 D3(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=O3(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 I3(),await P3(),{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: ${s3(f,`${e}/${t}/${n}`,a.hasToken)}\n`,exitCode:1};let p=tG(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(s3(n,`${e}/${t}/${o.path}`,a.hasToken));let s=XW(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(s3(l,`${e}/${t}/${o.path}`,a.hasToken));let u=tG(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 M3(),{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 j3(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 M3(){await I3(),await P3()}async function N3(e,t,n,r,i=!1){let a=`${U4}/${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 P3(){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 F3(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 I3(){try{if(typeof window>`u`)return;let e=window.__slicc_sprinkleManager;e&&typeof e.openNewAutoOpenSprinkles==`function`&&await e.openNewAutoOpenSprinkles()}catch{}}async function L3(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.
|
|
4352
|
+
`,exitCode:1};let i,a;try{let[n,r]=await Promise.all([(async()=>{let e=await t(q4,{headers:{Accept:`application/json`}});if(e.status!==200)throw Error(`HTTP ${e.status}`);return Y4(tG(e.body).data)})(),$4(e)]);i=n,a=r}catch(e){return{stdout:``,stderr:`upskill: failed to fetch skill catalog from ${q4}: ${e instanceof Error?e.message:String(e)}\n`,exitCode:1}}let o=Z4(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.
|
|
4353
|
+
`,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 D3(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=O3(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 N3(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 M3()),{stdout:s,stderr:c,exitCode:+!!c}}let s=`Recommended skills for you:
|
|
4354
4354
|
|
|
4355
|
-
`,c=0;for(let e of o){c++;let t=
|
|
4356
|
-
`,{stdout:s,stderr:``,exitCode:0}}function
|
|
4355
|
+
`,c=0;for(let e of o){c++;let t=Q4(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
|
|
4356
|
+
`,{stdout:s,stderr:``,exitCode:0}}function R3(e,t){return RR(`upskill`,async(n,r)=>{if(n.length===0||n.includes(`--help`)||n.includes(`-h`))return _3();let i=[],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 L3(e,t,n.includes(`--install`));else if(r===`list`){let t=await(await a(()=>import(`./skills-B1zKlleu.js`).then(e=>e.t),__vite__mapDeps([14,4,15,13,16,17]))).discoverSkills(e);return t.length===0?{stdout:`No discoverable local skills found.\n\n${c3()}${l3()}`,stderr:``,exitCode:0}:{stdout:m3(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 i=await a(()=>import(`./skills-B1zKlleu.js`).then(e=>e.t),__vite__mapDeps([14,4,15,13,16,17]));if(r===`info`){let n=await i.getSkillInfo(e,t);return n?{stdout:h3(n),stderr:``,exitCode:0}:{stdout:``,stderr:`upskill: skill "${t}" not found\n`,exitCode:1}}else{let n=await i.readSkillInstructions(e,t);return n===null?{stdout:``,stderr:`upskill: no SKILL.md found for "${t}"\n`,exitCode:1}:{stdout:n+`
|
|
4357
4357
|
`,stderr:``,exitCode:0}}}else if(r===`--skill`)i.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
|
|
4358
|
-
`,exitCode:1};d=n[++m]}else r.startsWith(`-`)||(u=r);m++}if(f)return
|
|
4359
|
-
`,exitCode:1};let r=await
|
|
4358
|
+
`,exitCode:1};d=n[++m]}else r.startsWith(`-`)||(u=r);m++}if(f)return S3(f,t,p);if(!u)return _3();let h=j3(u);if(h){let n=r.getRegisteredCommands?.()??[];return C3(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
|
|
4359
|
+
`,exitCode:1};let r=await E3(n,t);if(`error`in r)return{stdout:``,stderr:`upskill: ${r.error}\n`,exitCode:1};let i=await i3(t);return A3(r.owner,r.repo,r.skillPath,r.skillName,e,i,l,t)}let g=F3(u);if(g){let{owner:n,repo:r}=g,a=d??g.branch,f=await i3(t),p=await k3(n,r,f,o,t,a);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(i.length>0){m=p.skills.filter(e=>i.includes(e.name));for(let e of i)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 i=await D3(n,r,t,a);if(i.status===`not_found`)return{stdout:``,stderr:`upskill: ${a?`branch "${a}" in ${n}/${r}`:`repository ${n}/${r}`} not found\n`,exitCode:1};if(i.status===`error`)return{stdout:``,stderr:`upskill: failed to fetch ${n}/${r}: ${i.message}\n`,exitCode:1};let o=O3(i.files);for(let t=0;t<m.length;t++){let i=m[t],a=await N3(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 i of m){let o=await A3(n,r,i.path,i.name,e,f,l,t,a);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 M3()),{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 z3(e){return RR(`skill`,async(t,n)=>{if(t.length===0||t.includes(`--help`)||t.includes(`-h`))return{stdout:`usage: skill <command> [options]
|
|
4360
4360
|
|
|
4361
4361
|
Commands:
|
|
4362
4362
|
list List discoverable skills and management status
|
|
@@ -4365,7 +4365,7 @@ Commands:
|
|
|
4365
4365
|
install <name> Install a native /workspace/skills skill (apply manifest)
|
|
4366
4366
|
uninstall <name> Uninstall a native /workspace/skills skill
|
|
4367
4367
|
|
|
4368
|
-
${
|
|
4368
|
+
${c3()}${l3()}
|
|
4369
4369
|
|
|
4370
4370
|
For installing skills from registries or GitHub, use 'upskill':
|
|
4371
4371
|
upskill search "query" Search ClawHub + Tessl
|
|
@@ -4377,27 +4377,27 @@ Examples:
|
|
|
4377
4377
|
skill list
|
|
4378
4378
|
skill info bluebubbles
|
|
4379
4379
|
skill read bluebubbles
|
|
4380
|
-
`,stderr:``,exitCode:0};let r=t[0],i=await a(()=>import(`./skills-B1zKlleu.js`).then(e=>e.t),__vite__mapDeps([14,4,15,13,16,17]));try{switch(r){case`list`:{let t=await i.discoverSkills(e);return t.length===0?{stdout:`No discoverable skills found.\n\n${
|
|
4381
|
-
`,exitCode:1};let r=await i.getSkillInfo(e,n);return r?{stdout:
|
|
4380
|
+
`,stderr:``,exitCode:0};let r=t[0],i=await a(()=>import(`./skills-B1zKlleu.js`).then(e=>e.t),__vite__mapDeps([14,4,15,13,16,17]));try{switch(r){case`list`:{let t=await i.discoverSkills(e);return t.length===0?{stdout:`No discoverable skills found.\n\n${c3()}${l3()}\nInstall install-managed skills with: upskill owner/repo --all\n`,stderr:``,exitCode:0}:{stdout:m3(t,`Discoverable skills`),stderr:``,exitCode:0}}case`info`:{let n=t[1];if(!n)return{stdout:``,stderr:`skill: info requires a skill name
|
|
4381
|
+
`,exitCode:1};let r=await i.getSkillInfo(e,n);return r?{stdout:h3(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
|
|
4382
4382
|
`,exitCode:1};let r=await i.readSkillInstructions(e,n);return r===null?{stdout:``,stderr:`skill: no SKILL.md found for "${n}"\n`,exitCode:1}:{stdout:r+`
|
|
4383
4383
|
`,stderr:``,exitCode:0}}case`install`:{let n=t[1];if(!n)return{stdout:``,stderr:`skill: install requires a skill name
|
|
4384
|
-
`,exitCode:1};let r=await i.getSkillInfo(e,n);if(r&&!
|
|
4385
|
-
`,exitCode:1};let r=await i.getSkillInfo(e,n);if(r&&!
|
|
4384
|
+
`,exitCode:1};let r=await i.getSkillInfo(e,n);if(r&&!d3(r))return{stdout:``,stderr:g3(`skill`,r),exitCode:1};let a=await i.applySkill(e,n);return a.success?(await I3(),await P3(),{stdout:`Installed skill "${a.skill}" v${a.version}\n`,stderr:``,exitCode:0}):{stdout:``,stderr:`skill: ${a.error}\n`,exitCode:1}}case`uninstall`:{let n=t[1];if(!n)return{stdout:``,stderr:`skill: uninstall requires a skill name
|
|
4385
|
+
`,exitCode:1};let r=await i.getSkillInfo(e,n);if(r&&!d3(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 a=await i.uninstallSkill(e,n);return a.success?{stdout:`Uninstalled skill "${a.skill}"\n`,stderr:``,exitCode:0}:{stdout:``,stderr:`skill: ${a.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 B3(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`).replace(/'/g,`'`)}var V3=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
|
|
4386
4386
|
`,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(`
|
|
4387
4387
|
`)+`
|
|
4388
4388
|
`,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
|
|
4389
4389
|
Usage: mount <target-path>
|
|
4390
4390
|
`,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=pi(),a;if(i){let e=await mi({html:`
|
|
4391
4391
|
<div class="sprinkle-action-card">
|
|
4392
|
-
<div class="sprinkle-action-card__header">Mount at <code>${
|
|
4392
|
+
<div class="sprinkle-action-card__header">Mount at <code>${B3(r)}</code> <span class="sprinkle-badge sprinkle-badge--notice">approval</span></div>
|
|
4393
4393
|
<div class="sprinkle-action-card__actions">
|
|
4394
4394
|
<button class="sprinkle-btn sprinkle-btn--secondary" data-action="deny">Deny</button>
|
|
4395
4395
|
<button class="sprinkle-btn sprinkle-btn--primary" data-action="approve" data-picker="directory">Select directory</button>
|
|
4396
4396
|
</div>
|
|
4397
4397
|
</div>
|
|
4398
|
-
`,onAction:async(e,t)=>{if(e===`approve`){let e=t;if(e?.handleInIdb&&typeof e.idbKey==`string`)try{let t=await
|
|
4398
|
+
`,onAction:async(e,t)=>{if(e===`approve`){let e=t;if(e?.handleInIdb&&typeof e.idbKey==`string`)try{let t=await W3(e.idbKey);return t?(await H3(t),{approved:!0,handle:t}):{error:`No directory handle found in storage`}}catch(e){return{error:e instanceof Error?e.message:String(e)}}if(e?.cancelled)return{cancelled:!0};if(e?.error)return{error:String(e.error)};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 if(typeof chrome<`u`&&chrome?.runtime?.id)try{let e=await U3();if(e.cancelled)return{stdout:``,stderr:`mount: cancelled`,exitCode:1};if(e.error)return{stdout:``,stderr:`mount: ${e.error}`,exitCode:1};if(e.handleInIdb&&typeof e.idbKey==`string`){let t=await W3(e.idbKey);if(!t)return{stdout:``,stderr:`mount: no directory handle found in storage`,exitCode:1};await H3(t),a=t}else return{stdout:``,stderr:`mount: unexpected popup result`,exitCode:1}}catch(e){return{stdout:``,stderr:`mount: ${e instanceof Error?e.message:String(e)}`,exitCode:1}}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(`
|
|
4399
4399
|
`)+`
|
|
4400
|
-
`,stderr:``,exitCode:0}}};async function
|
|
4400
|
+
`,stderr:``,exitCode:0}}};async function H3(e){let t=e;if(t.requestPermission){let n=await t.requestPermission({mode:`readwrite`});if(n!==`granted`)throw Error(`Permission denied for "${e.name}" (${n})`)}}function U3(){let e=`mount-${Date.now().toString(36)}`;return new Promise(t=>{let n=chrome.runtime.getURL(`mount-popup.html?requestId=${encodeURIComponent(e)}`),r=()=>{clearTimeout(i),chrome.runtime.onMessage.removeListener(a)},i=setTimeout(()=>{r(),t({cancelled:!0})},6e4),a=n=>{let i=n;!i||i.source!==`mount-popup`||i.requestId!==e||(r(),t(i))};chrome.runtime.onMessage.addListener(a),chrome.windows.create({url:n,type:`popup`,width:300,height:80,focused:!0}).catch(()=>{r(),t({error:`Failed to open directory picker window`})})})}async function W3(e){let t=await new Promise((e,t)=>{let n=indexedDB.open(`slicc-pending-mount`,1);n.onupgradeneeded=()=>{n.result.objectStoreNames.contains(`handles`)||n.result.createObjectStore(`handles`)},n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)}),n=t.transaction(`handles`,`readwrite`),r=n.objectStore(`handles`),i=r.get(e),a=r.delete(e);a.onerror=()=>{console.warn(`[mount] Failed to delete pending handle from IDB`,e,a.error)};let o=await new Promise((e,t)=>{n.oncomplete=()=>e(i.result??null),i.onerror=()=>t(i.error??Error(`IDB get failed`)),n.onerror=()=>t(n.error??Error(`IDB transaction failed`)),n.onabort=()=>t(n.error??Error(`IDB transaction aborted`))});return t.close(),o}var G3=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 K3(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 q3(e,t,n){return await n.fs.exists(e)?J3(await n.fs.readFile(e),[`node`,e,...t],n):{stdout:``,stderr:`jsh: cannot find script '${e}'\n`,exitCode:127}}async function J3(e,t,n){let r=[],i=[],o=e=>{r.push(typeof e==`string`?e:String(e))},s=e=>{i.push(typeof e==`string`?e:String(e))},c={log:(...e)=>o(`${e.map(U1).join(` `)}\n`),info:(...e)=>o(`${e.map(U1).join(` `)}\n`),warn:(...e)=>s(`${e.map(U1).join(` `)}\n`),error:(...e)=>s(`${e.map(U1).join(` `)}\n`)},l={argv:t,env:Object.fromEntries(n.env.entries()),cwd:()=>n.cwd,exit:e=>{throw new j1(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=K3(e),n=new Set([`fs`,`process`,`buffer`]),r=t.map(e=>e.startsWith(`node:`)?e.slice(5):e).filter(e=>!n.has(e)&&!G3.has(e)),i=A1.__requireCache??=Object.create(null),o=r.filter(e=>!(e in i));if(o.length>0){let e=await Promise.allSettled(o.map(async e=>{let t=await a(()=>import(`https://esm.sh/`+e),[]);return{id:e,value:t.default===void 0?t:t.default}}));for(let t of e)t.status===`fulfilled`&&(i[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=A1.__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(G3.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=A1.__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=`
|
|
4401
4401
|
const __stdout = [];
|
|
4402
4402
|
const __stderr = [];
|
|
4403
4403
|
const __origConsole = { log: console.log, error: console.error, warn: console.warn, info: console.info };
|
|
@@ -4493,9 +4493,9 @@ Usage: mount <target-path>
|
|
|
4493
4493
|
console.info = __origConsole.info;
|
|
4494
4494
|
return { stdout: __stdout.join(''), stderr: __stderr.join('') };
|
|
4495
4495
|
`,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+`
|
|
4496
|
-
`});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 a=Object.getPrototypeOf(async function(){}).constructor;return await new a(`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,
|
|
4497
|
-
`).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 Y3(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 X3(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||!Y3(n.hostname,a)?!1:o?Z3(n.pathname+n.search,o):!0}catch{return!1}}function Z3(e,t){let n=`^`+t.replace(/[.+^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`.*`)+`$`;return new RegExp(n).test(e)}function Q3(e,t){try{let n=new URL(t);return e.filter(e=>Y3(n.hostname,e.hostnamePattern)?e.matchPatterns.length>0?e.matchPatterns.some(e=>X3(t,e)):!0:!1)}catch{return[]}}var $3=[`/workspace`,`/shared`];function e6(e){return new Map(e)}function t6(e){return e.map(e=>({...e,matchPatterns:[...e.matchPatterns]}))}function n6(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 r6(e){return(n6(e)?.listMounts?.().length??0)>0}function i6(e){return e?(n6(e)?.listMounts?.()??[]).some(e=>$3.some(t=>e===t||e.startsWith(t+`/`))):!1}var a6=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 $3)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 e6(await this.loadJshCommands())}async getJshCommandNames(){return[...(await this.getJshCommands()).keys()]}async getBshEntries(){return this.bshFs?t6(await this.loadBshEntries()):[]}async findMatchingBshScripts(e){return this.bshFs?t6(Q3(await this.loadBshEntries(),e)):[]}shouldCacheJsh(){return!!this.watcher&&!r6(this.jshFs)}shouldCacheBsh(){return!!this.watcher&&!!this.bshFs&&!i6(this.bshFs)}async loadJshCommands(){let e=this.shouldCacheJsh();if(e&&this.jshCache)return this.jshCache;if(!this.jshInflight){let t=this.jshGeneration,n=v2(this.jshFs).then(n=>{let r=e6(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=G3(this.bshFs).then(n=>{let r=t6(n);return e&&this.bshGeneration===t&&(this.bshCache=r),r}).finally(()=>{this.bshInflight===n&&(this.bshInflight=null)});this.bshInflight=n}return this.bshInflight}},o6=null,s6=!1;function c6(){return typeof chrome<`u`&&chrome?.runtime?.id?`extension`:typeof document<`u`&&document.documentElement?.dataset?.electronOverlay?`electron`:`cli`}async function l6(){if(!s6&&!(typeof localStorage<`u`&&localStorage.getItem(`telemetry-disabled`)===`true`))try{typeof window<`u`&&(window.SAMPLE_PAGEVIEWS_AT_RATE=`high`),o6=(await a(()=>import(`./src-BqF-C6jp.js`),[])).sampleRUM,s6=!0,o6&&o6(`navigate`,{source:typeof document<`u`?document.referrer:``,target:c6()})}catch{}}function u6(e,t){o6?.(`formsubmit`,{source:e,target:t})}function d6(e){o6?.(`fill`,{source:e})}function f6(e){o6?.(`viewblock`,{source:e})}function p6(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 m6(e){return e&&typeof e.getWatcher==`function`?e.getWatcher?.()??null:e&&typeof e.getUnderlyingFS==`function`?m6(e.getUnderlyingFS?.()):null}function h6(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 g6(e,t){let n=e.headers.get(`content-type`)??``,r=await e.arrayBuffer(),i=new Uint8Array(r);if(!h6(n)){let e=``;for(let t=0;t<i.length;t+=32768)e+=String.fromCharCode(...i.subarray(t,t+32768));JW(e,i),t&&YW(t,i)}return i}function _6(e){if(e){if(e instanceof Headers){let t={};return e.forEach((e,n)=>{t[n]=e}),t}return e}}function v6(e,t){if(e){if((t?.[`Content-Type`]??t?.[`content-type`]??``).includes(`multipart/form-data`)){let t=nG(e);return new Blob([t])}return e}}function y6(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 b6(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 x6(){return typeof chrome<`u`&&chrome?.runtime?.id?async(e,t)=>{let n=_6(t?.headers),r=await fetch(e,{method:t?.method??`GET`,headers:n,body:v6(t?.body,n)}),i=await g6(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={...y6(_6(t?.headers)),"X-Target-URL":e},i={method:n,headers:r,cache:`no-store`};t?.body&&![`GET`,`HEAD`].includes(n)&&(i.body=v6(t.body,r));let a=await fetch(`/api/fetch-proxy`,i);if(gQ(a))throw Error(await _Q(a));let o=await g6(a,e),s={};a.headers.forEach((e,t)=>{s[t]=e});let c=b6(s);return{status:a.status,statusText:a.statusText,headers:c,body:o,url:e}}}var S6=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 QW(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 MQ({fs:e.fs,authorName:n.GIT_AUTHOR_NAME??`User`,authorEmail:n.GIT_AUTHOR_EMAIL??`user@example.com`}),this.mountCommands=new F3({fs:e.fs});let r=e.jshDiscoveryFs??e.fs,i=e.bshDiscoveryFs??e.fs,a=m6(r)??m6(i);this.scriptCatalog=e.scriptCatalog??new a6({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=P4({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=x6(),u=[o,c,N3(e.fs),M3(e.fs,l),...s].filter(e=>this.isCommandAllowed(e.name)),d=[...jR(),...MR()],f=this.allowedCommands?d.filter(e=>this.isCommandAllowed(e)):void 0;if(this.bash=new VW({fs:this.vfsAdapter,cwd:t,env:n,fetch:l,commands:f,customCommands:u}),this.allowedCommands!==null){let e=this.bash;for(let t of MR())this.isCommandAllowed(t)||e.commands.delete(t)}let p=u.map(e=>e.name),m=f??[...jR(),...MR()];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 H3(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 RR(`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 RR(`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?U3(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 H3(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){d6(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 a(async()=>{let{Terminal:e}=await import(`./xterm-BaLOnk9X.js`);return{Terminal:e}},[]),{FitAddon:r}=await a(async()=>{let{FitAddon:e}=await import(`./addon-fit-CniRnSyE.js`);return{FitAddon:e}},[]);await a(()=>Promise.resolve({}),__vite__mapDeps([18]));let i=!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:i?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
|
|
4498
|
-
`),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
|
|
4496
|
+
`});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 a=Object.getPrototypeOf(async function(){}).constructor;return await new a(`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,A1,d),{stdout:r.join(``),stderr:i.join(``),exitCode:0}}catch(e){if(e instanceof j1)return{stdout:r.join(``),stderr:i.join(``),exitCode:e.code};let t=e instanceof Error?e.stack??e.message:String(e);return{stdout:r.join(``),stderr:`${i.join(``)}${t}\n`,exitCode:1}}}function Y3(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 X3=[`/workspace`,`/shared`];async function Z3(e){let t=[],n=new Set;for(let r of X3)await e.exists(r)&&await Q3(e,r,t,n);return t}async function Q3(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=$3(i);if(!t)continue;let a=await e.readFile(i,{encoding:`utf-8`}),o=e6(typeof a==`string`?a:new TextDecoder().decode(a));n.push({path:i,hostnamePattern:t,matchPatterns:o})}}function $3(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 e6(e){let t=e.split(`
|
|
4497
|
+
`).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 t6(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 n6(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||!t6(n.hostname,a)?!1:o?r6(n.pathname+n.search,o):!0}catch{return!1}}function r6(e,t){let n=`^`+t.replace(/[.+^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`.*`)+`$`;return new RegExp(n).test(e)}function i6(e,t){try{let n=new URL(t);return e.filter(e=>t6(n.hostname,e.hostnamePattern)?e.matchPatterns.length>0?e.matchPatterns.some(e=>n6(t,e)):!0:!1)}catch{return[]}}var a6=[`/workspace`,`/shared`];function o6(e){return new Map(e)}function s6(e){return e.map(e=>({...e,matchPatterns:[...e.matchPatterns]}))}function c6(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 l6(e){return(c6(e)?.listMounts?.().length??0)>0}function u6(e){return e?(c6(e)?.listMounts?.()??[]).some(e=>a6.some(t=>e===t||e.startsWith(t+`/`))):!1}var d6=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 a6)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 o6(await this.loadJshCommands())}async getJshCommandNames(){return[...(await this.getJshCommands()).keys()]}async getBshEntries(){return this.bshFs?s6(await this.loadBshEntries()):[]}async findMatchingBshScripts(e){return this.bshFs?s6(i6(await this.loadBshEntries(),e)):[]}shouldCacheJsh(){return!!this.watcher&&!l6(this.jshFs)}shouldCacheBsh(){return!!this.watcher&&!!this.bshFs&&!u6(this.bshFs)}async loadJshCommands(){let e=this.shouldCacheJsh();if(e&&this.jshCache)return this.jshCache;if(!this.jshInflight){let t=this.jshGeneration,n=w2(this.jshFs).then(n=>{let r=o6(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=Z3(this.bshFs).then(n=>{let r=s6(n);return e&&this.bshGeneration===t&&(this.bshCache=r),r}).finally(()=>{this.bshInflight===n&&(this.bshInflight=null)});this.bshInflight=n}return this.bshInflight}},f6=null,p6=!1;function m6(){return typeof chrome<`u`&&chrome?.runtime?.id?`extension`:typeof document<`u`&&document.documentElement?.dataset?.electronOverlay?`electron`:`cli`}async function h6(){if(!p6&&!(typeof localStorage<`u`&&localStorage.getItem(`telemetry-disabled`)===`true`))try{typeof window<`u`&&(window.SAMPLE_PAGEVIEWS_AT_RATE=`high`),f6=(await a(()=>import(`./src-BqF-C6jp.js`),[])).sampleRUM,p6=!0,f6&&f6(`navigate`,{source:typeof document<`u`?document.referrer:``,target:m6()})}catch{}}function g6(e,t){f6?.(`formsubmit`,{source:e,target:t})}function _6(e){f6?.(`fill`,{source:e})}function v6(e){f6?.(`viewblock`,{source:e})}function y6(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 b6(e){return e&&typeof e.getWatcher==`function`?e.getWatcher?.()??null:e&&typeof e.getUnderlyingFS==`function`?b6(e.getUnderlyingFS?.()):null}function x6(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 S6(e,t){let n=e.headers.get(`content-type`)??``,r=await e.arrayBuffer(),i=new Uint8Array(r);if(!x6(n)){let e=``;for(let t=0;t<i.length;t+=32768)e+=String.fromCharCode(...i.subarray(t,t+32768));JW(e,i),t&&YW(t,i)}return i}function C6(e){if(e){if(e instanceof Headers){let t={};return e.forEach((e,n)=>{t[n]=e}),t}return e}}function w6(e,t){if(e){if((t?.[`Content-Type`]??t?.[`content-type`]??``).includes(`multipart/form-data`)){let t=nG(e);return new Blob([t])}return e}}function T6(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 E6(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 D6(){return typeof chrome<`u`&&chrome?.runtime?.id?async(e,t)=>{let n=C6(t?.headers),r=await fetch(e,{method:t?.method??`GET`,headers:n,body:w6(t?.body,n)}),i=await S6(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={...T6(C6(t?.headers)),"X-Target-URL":e},i={method:n,headers:r,cache:`no-store`};t?.body&&![`GET`,`HEAD`].includes(n)&&(i.body=w6(t.body,r));let a=await fetch(`/api/fetch-proxy`,i);if(gQ(a))throw Error(await _Q(a));let o=await S6(a,e),s={};a.headers.forEach((e,t)=>{s[t]=e});let c=E6(s);return{status:a.status,statusText:a.statusText,headers:c,body:o,url:e}}}var O6=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 QW(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 MQ({fs:e.fs,authorName:n.GIT_AUTHOR_NAME??`User`,authorEmail:n.GIT_AUTHOR_EMAIL??`user@example.com`}),this.mountCommands=new V3({fs:e.fs});let r=e.jshDiscoveryFs??e.fs,i=e.bshDiscoveryFs??e.fs,a=b6(r)??b6(i);this.scriptCatalog=e.scriptCatalog??new d6({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=B4({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=D6(),u=[o,c,z3(e.fs),R3(e.fs,l),...s].filter(e=>this.isCommandAllowed(e.name)),d=[...jR(),...MR()],f=this.allowedCommands?d.filter(e=>this.isCommandAllowed(e)):void 0;if(this.bash=new VW({fs:this.vfsAdapter,cwd:t,env:n,fetch:l,commands:f,customCommands:u}),this.allowedCommands!==null){let e=this.bash;for(let t of MR())this.isCommandAllowed(t)||e.commands.delete(t)}let p=u.map(e=>e.name),m=f??[...jR(),...MR()];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 J3(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 RR(`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 RR(`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?Y3(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 J3(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){_6(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 a(async()=>{let{Terminal:e}=await import(`./xterm-BaLOnk9X.js`);return{Terminal:e}},[]),{FitAddon:r}=await a(async()=>{let{FitAddon:e}=await import(`./addon-fit-CniRnSyE.js`);return{FitAddon:e}},[]);await a(()=>Promise.resolve({}),__vite__mapDeps([18]));let i=!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:i?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
|
|
4498
|
+
`),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 q3(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
|
|
4499
4499
|
`,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(`
|
|
4500
4500
|
`).entries()){if(e+n.length>=this.cursorPos)return t;e+=n.length+1}return 0}positionTerminalCursor(){let e=this.currentLine.split(`
|
|
4501
4501
|
`),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(`
|
|
@@ -4509,9 +4509,9 @@ Usage: mount <target-path>
|
|
|
4509
4509
|
`,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(`
|
|
4510
4510
|
`).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(`
|
|
4511
4511
|
`);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+`
|
|
4512
|
-
`+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=`${
|
|
4512
|
+
`+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=`${y6(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=y6(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())}},k6=n({WasmShell:()=>O6}),A6=i(`tool:fs`);function j6(e){return[M6(e),N6(e),P6(e)]}function M6(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;A6.debug(`Read`,{path:n,offset:r,limit:i});try{let t=(await e.readTextFile(n)).split(`
|
|
4513
4513
|
`),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(`
|
|
4514
|
-
`)}}catch(e){let t=e instanceof Error?e.message:String(e);return
|
|
4514
|
+
`)}}catch(e){let t=e instanceof Error?e.message:String(e);return A6.error(`Read failed`,{path:n,error:t}),{content:t,isError:!0}}}}}function N6(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;A6.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 A6.error(`Write failed`,{path:n,error:t}),{content:t,isError:!0}}}}}function P6(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;A6.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 A6.error(`Edit failed`,{path:n,error:t}),{content:t,isError:!0}}}}}var F6=i(`tool:bash`),I6=/^(?:[A-Za-z_][A-Za-z0-9_]*=[^\s]+\s+)*(?:command\s+)?(?:grep|egrep|fgrep|rg)\b/;function L6(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 R6(e,t,n){return t!==1||n.trim()?!1:I6.test(L6(e))}function z6(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;F6.debug(`Execute`,{command:r});try{let t=await e.executeCommand(r,n);F6.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&&!R6(r,t.exitCode,t.stderr)}}catch(e){let t=e instanceof Error?e.message:String(e);return F6.error(`Error`,{command:r,error:t}),{content:`Shell error: ${t}`,isError:!0}}}}}i(`tool:search`);var B6="# 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",V6="# 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",H6=`<!DOCTYPE html>
|
|
4515
4515
|
<html lang="en">
|
|
4516
4516
|
<head>
|
|
4517
4517
|
<meta charset="UTF-8">
|
|
@@ -5535,7 +5535,7 @@ if (hasState && violations && violations.length > 0) {
|
|
|
5535
5535
|
<\/script>
|
|
5536
5536
|
</body>
|
|
5537
5537
|
</html>
|
|
5538
|
-
`,
|
|
5538
|
+
`,U6=`<!DOCTYPE html>
|
|
5539
5539
|
<html lang="en">
|
|
5540
5540
|
<head>
|
|
5541
5541
|
<meta charset="UTF-8">
|
|
@@ -6180,7 +6180,7 @@ init();
|
|
|
6180
6180
|
<\/script>
|
|
6181
6181
|
</body>
|
|
6182
6182
|
</html>
|
|
6183
|
-
`,
|
|
6183
|
+
`,W6=`<!DOCTYPE html>
|
|
6184
6184
|
<html lang="en">
|
|
6185
6185
|
<head>
|
|
6186
6186
|
<meta charset="UTF-8">
|
|
@@ -6962,7 +6962,7 @@ function lickExportData() {
|
|
|
6962
6962
|
<\/script>
|
|
6963
6963
|
</body>
|
|
6964
6964
|
</html>
|
|
6965
|
-
`,
|
|
6965
|
+
`,G6=`<!DOCTYPE html>
|
|
6966
6966
|
<html lang="en">
|
|
6967
6967
|
<head>
|
|
6968
6968
|
<meta charset="UTF-8">
|
|
@@ -7800,7 +7800,7 @@ body { font-family: var(--s2-font-family); font-size: 14px; line-height: 1.5; co
|
|
|
7800
7800
|
<\/script>
|
|
7801
7801
|
</body>
|
|
7802
7802
|
</html>
|
|
7803
|
-
`,
|
|
7803
|
+
`,K6=`<!DOCTYPE html>
|
|
7804
7804
|
<html lang="en">
|
|
7805
7805
|
<head>
|
|
7806
7806
|
<meta charset="UTF-8">
|
|
@@ -8367,7 +8367,7 @@ if (hasData()) {
|
|
|
8367
8367
|
<\/script>
|
|
8368
8368
|
</body>
|
|
8369
8369
|
</html>
|
|
8370
|
-
`,
|
|
8370
|
+
`,q6=`<!DOCTYPE html>
|
|
8371
8371
|
<html lang="en">
|
|
8372
8372
|
<head>
|
|
8373
8373
|
<meta charset="UTF-8">
|
|
@@ -9034,7 +9034,7 @@ function saveState() {
|
|
|
9034
9034
|
<\/script>
|
|
9035
9035
|
</body>
|
|
9036
9036
|
</html>
|
|
9037
|
-
`,
|
|
9037
|
+
`,J6=`<!DOCTYPE html>
|
|
9038
9038
|
<html lang="en">
|
|
9039
9039
|
<head>
|
|
9040
9040
|
<meta charset="UTF-8">
|
|
@@ -9820,7 +9820,7 @@ if (document.getElementById('mainView').classList.contains('active')) {
|
|
|
9820
9820
|
<\/script>
|
|
9821
9821
|
</body>
|
|
9822
9822
|
</html>
|
|
9823
|
-
`,
|
|
9823
|
+
`,Y6=`<!DOCTYPE html>
|
|
9824
9824
|
<html lang="en">
|
|
9825
9825
|
<head>
|
|
9826
9826
|
<meta charset="UTF-8">
|
|
@@ -10578,7 +10578,7 @@ textarea.field-input { height: auto; min-height: 80px; padding: 10px 12px; resiz
|
|
|
10578
10578
|
<\/script>
|
|
10579
10579
|
</body>
|
|
10580
10580
|
</html>
|
|
10581
|
-
`,
|
|
10581
|
+
`,X6=`<!DOCTYPE html>
|
|
10582
10582
|
<html lang="en">
|
|
10583
10583
|
<head>
|
|
10584
10584
|
<meta charset="UTF-8">
|
|
@@ -11388,7 +11388,7 @@ init();
|
|
|
11388
11388
|
<\/script>
|
|
11389
11389
|
</body>
|
|
11390
11390
|
</html>
|
|
11391
|
-
`,
|
|
11391
|
+
`,Z6=`<!DOCTYPE html>
|
|
11392
11392
|
<html lang="en">
|
|
11393
11393
|
<head>
|
|
11394
11394
|
<meta charset="UTF-8">
|
|
@@ -13036,7 +13036,7 @@ body { font-family: var(--s2-font-family); font-size: 14px; line-height: 1.5; co
|
|
|
13036
13036
|
<\/script>
|
|
13037
13037
|
</body>
|
|
13038
13038
|
</html>
|
|
13039
|
-
`,
|
|
13039
|
+
`,Q6=`<!DOCTYPE html>
|
|
13040
13040
|
<html lang="en">
|
|
13041
13041
|
<head>
|
|
13042
13042
|
<title>Welcome</title>
|
|
@@ -13970,7 +13970,7 @@ body { font-family: var(--s2-font-family); font-size: 14px; line-height: 1.5; co
|
|
|
13970
13970
|
<\/script>
|
|
13971
13971
|
</body>
|
|
13972
13972
|
</html>
|
|
13973
|
-
|
|
13973
|
+
`,$6='---\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',e8=`---
|
|
13974
13974
|
name: handoff
|
|
13975
13975
|
description: React to navigate lick events (x-slicc response headers) with a yes/no approval card
|
|
13976
13976
|
allowed-tools: bash
|
|
@@ -14041,7 +14041,7 @@ Use this shtml block verbatim, substituting the origin URL and header value. Kee
|
|
|
14041
14041
|
- 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.
|
|
14042
14042
|
- Do not execute the header value as a shell command. It is instruction text or a pointer, not code.
|
|
14043
14043
|
- Do not render more than one approval card for a single navigate event. If you already showed the card, wait for the user.
|
|
14044
|
-
`,
|
|
14044
|
+
`,t8=`---
|
|
14045
14045
|
name: inline-widgets
|
|
14046
14046
|
description: Interactive widget patterns for inline shtml cards in chat messages
|
|
14047
14047
|
allowed-tools: bash
|
|
@@ -14311,7 +14311,7 @@ slicc.lick({ action: 'sort-complete', algorithm: algo, comparisons: n });
|
|
|
14311
14311
|
\`\`\`
|
|
14312
14312
|
|
|
14313
14313
|
The agent receives the lick as a structured message and can respond with prose, another inline widget, or spawn a scoop.
|
|
14314
|
-
`,
|
|
14314
|
+
`,n8=`---
|
|
14315
14315
|
name: playwright-cli
|
|
14316
14316
|
description: Browse the web, interact with pages, take screenshots, extract data via the playwright-cli shell command.
|
|
14317
14317
|
allowed-tools: bash
|
|
@@ -14500,7 +14500,7 @@ playwright-cli stop-recording <recordingId> # Stop and save HAR
|
|
|
14500
14500
|
- The SLICC app tab and Chrome internal UI tabs are automatically excluded from \`tab-list\`.
|
|
14501
14501
|
- \`fill\` clears and types into regular inputs, textareas, and \`contenteditable\` elements.
|
|
14502
14502
|
- Screenshots default to \`/tmp/screenshot-<timestamp>.png\`. Use \`--filename=path\` to save elsewhere.
|
|
14503
|
-
`,
|
|
14503
|
+
`,r8=`---
|
|
14504
14504
|
name: Scoop Management
|
|
14505
14505
|
description: Detailed scoop lifecycle, delegation rules, browser tab handling
|
|
14506
14506
|
---
|
|
@@ -14686,7 +14686,7 @@ scoop_scoop({ name: "architect", model: "claude-opus-4-6", prompt: "Design the n
|
|
|
14686
14686
|
\`\`\`
|
|
14687
14687
|
|
|
14688
14688
|
**Error handling**: If a scoop fails due to an invalid model or API error, it will retry up to 3 times with exponential backoff for transient errors (rate limits, server errors). Non-retryable errors (invalid model, auth failures) fail immediately and notify the cone, bypassing any \`scoop_mute\` settings.
|
|
14689
|
-
`,
|
|
14689
|
+
`,i8="---\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",a8=`---
|
|
14690
14690
|
name: Sprinkle Guide
|
|
14691
14691
|
description: Inline cards, sprinkle chat, cone orchestration rules for UI panels
|
|
14692
14692
|
---
|
|
@@ -14749,7 +14749,7 @@ The cone MUST NOT: write/edit \`.shtml\` files, run \`sprinkle open/close/send\`
|
|
|
14749
14749
|
See the sprinkles skill (\`read_file /workspace/skills/sprinkles/SKILL.md\`) for creating, modifying, and handling lick events.
|
|
14750
14750
|
|
|
14751
14751
|
**NEVER handle a lick in the cone. Always \`feed_scoop\`.**
|
|
14752
|
-
`,
|
|
14752
|
+
`,o8='---\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',s8=`# Lucide Icons Example
|
|
14753
14753
|
|
|
14754
14754
|
This shows how to use Lucide icons in inline sprinkles instead of emojis.
|
|
14755
14755
|
|
|
@@ -14859,7 +14859,7 @@ This shows how to use Lucide icons in inline sprinkles instead of emojis.
|
|
|
14859
14859
|
**UI**: \`settings\`, \`menu\`, \`more-vertical\`, \`more-horizontal\`, \`eye\`, \`eye-off\`, \`lock\`, \`unlock\`
|
|
14860
14860
|
|
|
14861
14861
|
Browse all icons at [lucide.dev/icons](https://lucide.dev/icons)
|
|
14862
|
-
`,
|
|
14862
|
+
`,c8=`# Sprinkle Component Reference
|
|
14863
14863
|
|
|
14864
14864
|
Use these CSS classes in \`.shtml\` sprinkles. Do NOT write custom CSS — these components cover all common UI patterns.
|
|
14865
14865
|
|
|
@@ -15639,7 +15639,7 @@ background: color-mix(in srgb, var(--s2-accent) 6%, transparent); /* blue tint *
|
|
|
15639
15639
|
| \`--s2-spacing-400\` | 24px |
|
|
15640
15640
|
| \`--s2-spacing-500\` | 32px |
|
|
15641
15641
|
| \`--s2-spacing-600\` | 40px |
|
|
15642
|
-
`,
|
|
15642
|
+
`,l8=`---
|
|
15643
15643
|
name: welcome
|
|
15644
15644
|
description: Handle onboarding lick from the welcome sprinkle
|
|
15645
15645
|
allowed-tools: bash
|
|
@@ -15733,8 +15733,8 @@ Do NOT save a profile, update \`/shared/CLAUDE.md\`, or write a greeting.
|
|
|
15733
15733
|
|
|
15734
15734
|
- **\`start-task\` lick** — treat as the user's first request, begin the task immediately.
|
|
15735
15735
|
- **Sparse profiles** (user skipped most steps) — keep greeting brief, ask what they need.
|
|
15736
|
-
`,
|
|
15737
|
-
`)){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
|
|
15736
|
+
`,u8=`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=`,d8=i(`skills`),f8=Object.assign({"/packages/vfs-root/AGENTS.md":B6,"/packages/vfs-root/CLAUDE.md":B6,"/packages/vfs-root/shared/CLAUDE.md":V6,"/packages/vfs-root/shared/sprinkles/brand-compliance/brand-compliance.shtml":H6,"/packages/vfs-root/shared/sprinkles/content-tree/content-tree.shtml":U6,"/packages/vfs-root/shared/sprinkles/funnels/funnels.shtml":W6,"/packages/vfs-root/shared/sprinkles/page-editor/page-editor.shtml":G6,"/packages/vfs-root/shared/sprinkles/performance/performance.shtml":K6,"/packages/vfs-root/shared/sprinkles/readability/readability.shtml":q6,"/packages/vfs-root/shared/sprinkles/review-workflow/review-workflow.shtml":J6,"/packages/vfs-root/shared/sprinkles/schema-editor/schema-editor.shtml":Y6,"/packages/vfs-root/shared/sprinkles/seo-dashboard/seo-dashboard.shtml":X6,"/packages/vfs-root/shared/sprinkles/tone-voice/tone-voice.shtml":Z6,"/packages/vfs-root/shared/sprinkles/welcome/welcome.shtml":Q6,"/packages/vfs-root/workspace/skills/automation/SKILL.md":$6,"/packages/vfs-root/workspace/skills/handoff/SKILL.md":e8,"/packages/vfs-root/workspace/skills/inline-widgets/SKILL.md":t8,"/packages/vfs-root/workspace/skills/playwright-cli/SKILL.md":n8,"/packages/vfs-root/workspace/skills/scoop-management/SKILL.md":r8,"/packages/vfs-root/workspace/skills/skill-authoring/SKILL.md":i8,"/packages/vfs-root/workspace/skills/sprinkle-guide/SKILL.md":a8,"/packages/vfs-root/workspace/skills/sprinkles/SKILL.md":o8,"/packages/vfs-root/workspace/skills/sprinkles/icon-example.md":s8,"/packages/vfs-root/workspace/skills/sprinkles/style-guide.md":c8,"/packages/vfs-root/workspace/skills/welcome/SKILL.md":l8}),p8=Object.assign({"/packages/vfs-root/shared/sounds/chime.mp3":u8});function m8(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 h8(){let e={};for(let[t,n]of Object.entries(f8))e[t]=n;for(let[t,n]of Object.entries(p8))e[t]=m8(n);return e}function g8(e){let t=new Map;for(let n of e){if(t.has(n.metadata.name)){d8.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 _8(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(`
|
|
15737
|
+
`)){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 v8(e,t){let n=await y8(e,t),r=await b8(e,t),i=n.filter(e=>e.source===`native`),a=n.filter(e=>e.source!==`native`),o=g8([...i,...r,...a]);return d8.info(`Skills loaded`,{count:o.length,dir:t}),o}async function y8(e,t){let n=await se(e,t),r=[];for(let t of n)if(t.skillFilePath)try{let{metadata:n,body:i}=_8(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}),d8.debug(`Loaded discovered skill`,{name:a,path:t.skillFilePath,source:t.source})}catch{d8.debug(`Failed to load discovered skill`,{name:t.name,path:t.skillFilePath})}return r}async function b8(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}=_8(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}),d8.debug(`Loaded standalone skill`,{name:s,path:r})}catch{}}}catch{d8.debug(`Standalone skills directory not found`,{dir:t})}return n}function x8(e){return e.length===0?``:`
|
|
15738
15738
|
---
|
|
15739
15739
|
AVAILABLE SKILLS
|
|
15740
15740
|
|
|
@@ -15743,11 +15743,11 @@ The following skills are available. To use a skill, first read its full instruct
|
|
|
15743
15743
|
|
|
15744
15744
|
${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(`
|
|
15745
15745
|
`)}
|
|
15746
|
-
---`}async function
|
|
15747
|
-
`)}`}}}),o&&p.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(
|
|
15748
|
-
`)}}}),f&&p.push({name:`scoop_wait`,description:`Block until the given scoops complete or an optional timeout expires. Use this to coordinate parallel work: you feed several scoops, then call scoop_wait to receive all their results in one go without the cone being pinged for each individual completion. Already-completed scoops (including those whose completion arrived while you were processing your previous turn) are returned immediately.`,inputSchema:{type:`object`,properties:{scoop_names:{type:`array`,items:{type:`string`},description:`Folder or display names of scoops to wait for (e.g., ["writer-scoop", "reviewer-scoop"]).`},timeout_ms:{type:`number`,description:`Optional timeout in milliseconds. If any listed scoop has not completed by the deadline, it is reported as timed-out in the result and the wait returns. Omit for no timeout.`}},required:[`scoop_names`]},execute:async e=>{let{scoop_names:t,timeout_ms:n}=e;if(!Array.isArray(t)||t.length===0)return{content:`scoop_names must be a non-empty array.`,isError:!0};if(n!==void 0&&(typeof n!=`number`||!Number.isFinite(n)||n<0))return{content:`timeout_ms must be a non-negative finite number (or omitted).`,isError:!0};let{resolved:r,unknown:a}=
|
|
15749
|
-
`)}}}),c&&l&&p.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),v8.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}}}})),p}var x8=`slicc:adobe-daily-uuid:`,S8=new Map;function C8(){return new Date().toISOString().slice(0,10)}function w8(){try{return globalThis.localStorage??null}catch{return null}}function T8(e){let t=C8(),n=w8(),r=x8+e;if(n){let e=n.getItem(r);if(e)try{let n=JSON.parse(e);if(n.date===t&&typeof n.uuid==`string`)return n.uuid}catch{}let i=crypto.randomUUID();try{n.setItem(r,JSON.stringify({uuid:i,date:t}))}catch{}return i}let i=S8.get(e);if(i&&i.date===t)return i.uuid;let a=crypto.randomUUID();return S8.set(e,{uuid:a,date:t}),a}async function E8(e,t){let n=new TextEncoder().encode(`${t}:${e}`),r=await crypto.subtle.digest(`SHA-256`,n);return Array.from(new Uint8Array(r).slice(0,8)).map(e=>e.toString(16).padStart(2,`0`)).join(``)}async function D8(e,t){let n=T8(t??e.jid);return e.isCone?n:`${n}/${await E8(e.folder,n)}`}var O8=n({fetchSecretEnvVars:()=>A8}),k8=i(`secret-env`);async function A8(){if(typeof chrome<`u`&&chrome?.runtime?.id)return{};try{let e=await fetch(`/api/secrets/masked`);if(!e.ok)return k8.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&&k8.info(`Loaded masked secrets into shell env`,{count:Object.keys(n).length}),n}catch(e){return k8.debug(`Could not fetch masked secrets (server may be unavailable)`,{error:e instanceof Error?e.message:String(e)}),{}}}var j8=i(`scoop-context`);function M8(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)}function N8(e){return/\b(401|403|404|405|410|422)\b/.test(e)||/unauthorized|forbidden|authentication.*failed|invalid.*api.?key/i.test(e)||/model.*not.*found|invalid.*model|unknown.*model|does.*not.*exist/i.test(e)||/insufficient.*quota|billing|payment.*required|account.*suspended/i.test(e)||/invalid.*request|malformed|bad.*request/i.test(e)}function P8(e){return/\b429\b|rate.*limit|too.*many.*requests|quota.*exceeded/i.test(e)||/\b(500|502|503|504)\b|internal.*server|bad.*gateway|service.*unavailable|gateway.*timeout/i.test(e)||/network.*error|connection.*refused|timeout|econnreset|socket.*hang.*up/i.test(e)||/overloaded|temporarily.*unavailable|try.*again/i.test(e)}function F8(e,t){return t?.aborted?Promise.resolve(!0):new Promise(n=>{let r=()=>{clearTimeout(i),n(!0)},i=setTimeout(()=>{t?.removeEventListener(`abort`,r),n(!1)},e);t?.addEventListener(`abort`,r,{once:!0})})}var I8=class{scoop;callbacks;fs=null;shell=null;agent=null;status=`initializing`;isProcessing=!1;disposed=!1;didStreamDeltas=!1;unsubscribe=null;promptAbortController=null;sessionStore=null;sessionId;sessionCreatedAt=0;isRecovering=!1;coneJid;skillsFs=null;skillsDir=`/workspace/skills`;constructor(e,t,n,r,i,a){this.scoop=e,this.callbacks=t,this.fs=n,this.sessionStore=r??null,this.skillsFs=i??null,this.coneJid=a,this.sessionId=e.jid}async init(){this.setStatus(`initializing`);try{if(!this.fs)throw Error(`Filesystem not provided`);j8.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 g8(this.fs,this.skillsDir);let n=this.skillsFs??this.fs,r=await A8();this.shell=new S6({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}),j8.info(`WasmShell initialized`,{folder:this.scoop.folder});let i=await f8(n,this.skillsDir),a=b8({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,onMuteScoops:this.callbacks.onMuteScoops,onUnmuteScoops:this.callbacks.onUnmuteScoops,onWaitForScoops:this.callbacks.onWaitForScoops,onSetGlobalMemory:this.callbacks.setGlobalMemory,getGlobalMemory:this.callbacks.getGlobalMemory}),c=o([...T6(this.fs),N6(this.shell),...a]),p=this.scoop.isCone?`/workspace/CLAUDE.md`:`/scoops/${this.scoop.folder}/CLAUDE.md`,m=``;try{let e=await this.fs.readFile(p,{encoding:`utf-8`});m=typeof e==`string`?e:new TextDecoder().decode(e)}catch{}let h=await this.callbacks.getGlobalMemory();if(h)try{this.scoop.isCone&&await(`getUnderlyingFS`in this.fs?this.fs.getUnderlyingFS():this.fs).writeFile(`/shared/CLAUDE.md`,h)}catch{}if(!s()){let e=l();throw Error(`No API key configured for provider "${e}"`)}let g=this.scoop.config?.modelId?d(this.scoop.config.modelId):u(),_=this.scoop.isCone?`Cone`:`Scoop "${this.scoop.name}"`;console.log(`[model] ${_} using model: ${g.id} (provider: ${g.provider})`);let v=this.buildSystemPrompt(h,m,i),y=[];if(this.sessionStore)try{let e=await this.sessionStore.load(this.sessionId);e&&(y=e.messages,this.sessionCreatedAt=e.createdAt,j8.info(`Restored agent session`,{folder:this.scoop.folder,messageCount:y.length}))}catch(e){j8.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 b=f({model:g,getApiKey:()=>s()??void 0}),x=await D8(this.scoop,this.coneJid),S=(e,t,n)=>e.provider===`adobe`?C(e,t,{...n,headers:{...n?.headers,"X-Session-Id":x}}):C(e,t,n);if(this.disposed)return;this.agent=new w({initialState:{model:g,tools:c,systemPrompt:v,messages:y},getApiKey:()=>s()??void 0,transformContext:b,streamFn:S}),this.unsubscribe=this.agent.subscribe(e=>this.handleAgentEvent(e)),this.setStatus(`ready`),j8.info(`ScoopContext initialized`,{folder:this.scoop.folder,toolCount:c.length})}catch(e){if(this.disposed)return;let t=e instanceof Error?e.message:String(e);j8.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){j8.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}let n=this.agent;this.promptAbortController?.abort();let r=new AbortController;this.promptAbortController=r;let i=r.signal;this.isProcessing=!0,this.setStatus(`processing`);let a=1e3,o=null;try{for(let t=1;t<=3;t++){if(this.disposed||i.aborted)return;this.didStreamDeltas=!1;try{await n.prompt(e),o=null;break}catch(e){if(this.disposed||i.aborted)return;o=e instanceof Error?e:Error(String(e));let n=o.message;if(N8(n)){j8.error(`Non-retryable agent error`,{folder:this.scoop.folder,error:n,attempt:t}),this.setStatus(`error`),this.callbacks.onFatalError?this.callbacks.onFatalError(`Scoop "${this.scoop.name}" failed with unrecoverable error: ${n}`):this.callbacks.onError(n);return}if(P8(n)&&t<3){let e=a*2**(t-1);if(j8.warn(`Retryable agent error, will retry`,{folder:this.scoop.folder,error:n,attempt:t,maxRetries:3,delayMs:e}),await F8(e,i)||this.disposed)return;continue}if(j8.error(`Agent error`,{folder:this.scoop.folder,error:n,attempt:t,isRetryable:P8(n)}),t===3)break;if(await F8(a*2**(t-1),i)||this.disposed)return}}if(o&&!this.disposed&&!i.aborted){let e=o.message;j8.error(`Agent error after retries exhausted`,{folder:this.scoop.folder,error:e,maxRetries:3}),this.setStatus(`error`),this.callbacks.onFatalError?this.callbacks.onFatalError(`Scoop "${this.scoop.name}" failed after 3 attempts: ${e}`):this.callbacks.onError(e);return}!this.disposed&&!i.aborted&&this.setStatus(`ready`)}finally{this.isProcessing=!1,this.promptAbortController===r&&(this.promptAbortController=null)}}stop(){this.promptAbortController?.abort(),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=u();this.agent.state.model=e,j8.info(`Model updated on running agent`,{folder:this.scoop.folder,model:e.id})}async reloadSkills(){if(!this.agent)return;let e=await f8(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,j8.info(`Skills reloaded`,{folder:this.scoop.folder,skillCount:e.length})}dispose(){this.disposed=!0,this.promptAbortController?.abort(),this.promptAbortController=null,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(`
|
|
15750
|
-
`),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&&
|
|
15746
|
+
---`}async function S8(e,t=`/workspace/skills`){let n=h8();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),d8.info(`Created default file`,{path:s})}}}async function C8(e){let t=h8();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),d8.info(`Created default shared file`,{path:t})}}}var w8=i(`scoop-management-tools`);function T8(e,t){let n=t(),r=[],i=[];for(let t of e){let e=n.find(e=>!e.isCone&&(e.folder===t||e.name===t));e?r.push(e):i.push(t)}return{resolved:r,unknown:i}}function E8(e){let{scoop:t,onSendMessage:n,onFeedScoop:r,getScoops:i,getScoopTabState:a,onScoopScoop:o,onDropScoop:s,onSetGlobalMemory:c,getGlobalMemory:l,onMuteScoops:u,onUnmuteScoops:d,onWaitForScoops:f}=e,p=[];return p.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),w8.info(`Message sent`,{scoopFolder:t.folder,textLength:r.length}),{content:`Message sent.`}}}),t.isCone&&r&&p.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),w8.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&&(p.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(`
|
|
15747
|
+
`)}`}}}),o&&p.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(w8.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 w8.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&&p.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),w8.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}}}}),u&&p.push({name:`scoop_mute`,description:`Suspend scoop→cone notifications for the given scoops. While muted, a scoop's completion is stashed and will be delivered to the cone when you call scoop_unmute (or scoop_wait which consumes it). Use this when coordinating parallel work so each scoop's completion does not trigger its own cone turn.`,inputSchema:{type:`object`,properties:{scoop_names:{type:`array`,items:{type:`string`},description:`Folder or display names of scoops to mute (e.g., ["writer-scoop", "reviewer-scoop"]).`}},required:[`scoop_names`]},execute:async e=>{let{scoop_names:t}=e;if(!Array.isArray(t)||t.length===0)return{content:`scoop_names must be a non-empty array.`,isError:!0};let{resolved:n,unknown:r}=T8(t,i);return n.length===0?{content:`No matching scoops found. Unknown: ${r.join(`, `)}`,isError:!0}:(u(n.map(e=>e.jid)),w8.info(`Scoops muted`,{names:n.map(e=>e.folder)}),{content:`Muted: ${n.map(e=>e.folder).join(`, `)}${r.length>0?` (unknown: ${r.join(`, `)})`:``}`})}}),d&&p.push({name:`scoop_unmute`,description:`Resume scoop→cone notifications for the given scoops. Any completion that landed while a scoop was muted is returned in this tool result (NOT dispatched as a new cone turn), so you can read all stashed summaries in the current turn. Scoops with no stashed completion are simply unmuted.`,inputSchema:{type:`object`,properties:{scoop_names:{type:`array`,items:{type:`string`},description:`Folder or display names of scoops to unmute (e.g., ["writer-scoop"]).`}},required:[`scoop_names`]},execute:async e=>{let{scoop_names:t}=e;if(!Array.isArray(t)||t.length===0)return{content:`scoop_names must be a non-empty array.`,isError:!0};let{resolved:n,unknown:r}=T8(t,i);if(n.length===0)return{content:`No matching scoops found. Unknown: ${r.join(`, `)}`,isError:!0};let a=n.map(e=>e.jid),o=new Map(n.map(e=>[e.jid,e.folder])),s=await d(a);w8.info(`Scoops unmuted`,{names:n.map(e=>e.folder),stashedCount:s.length});let c=[`Unmuted: ${n.map(e=>e.folder).join(`, `)}${r.length>0?` (unknown: ${r.join(`, `)})`:``}`];if(s.length===0)c.push(`No stashed completions.`);else{c.push(``,`Stashed completions:`);for(let e of s){let t=o.get(e.jid)??e.jid;c.push(`--- ${t} ---`),e.notificationPath&&c.push(`VFS path: ${e.notificationPath}`),c.push(e.summary)}}return{content:c.join(`
|
|
15748
|
+
`)}}}),f&&p.push({name:`scoop_wait`,description:`Block until the given scoops complete or an optional timeout expires. Use this to coordinate parallel work: you feed several scoops, then call scoop_wait to receive all their results in one go without the cone being pinged for each individual completion. Already-completed scoops (including those whose completion arrived while you were processing your previous turn) are returned immediately.`,inputSchema:{type:`object`,properties:{scoop_names:{type:`array`,items:{type:`string`},description:`Folder or display names of scoops to wait for (e.g., ["writer-scoop", "reviewer-scoop"]).`},timeout_ms:{type:`number`,description:`Optional timeout in milliseconds. If any listed scoop has not completed by the deadline, it is reported as timed-out in the result and the wait returns. Omit for no timeout.`}},required:[`scoop_names`]},execute:async e=>{let{scoop_names:t,timeout_ms:n}=e;if(!Array.isArray(t)||t.length===0)return{content:`scoop_names must be a non-empty array.`,isError:!0};if(n!==void 0&&(typeof n!=`number`||!Number.isFinite(n)||n<0))return{content:`timeout_ms must be a non-negative finite number (or omitted).`,isError:!0};let{resolved:r,unknown:a}=T8(t,i);if(r.length===0)return{content:`No matching scoops found. Unknown: ${a.join(`, `)}`,isError:!0};let o=r.map(e=>e.jid),s=new Map(r.map(e=>[e.jid,e.folder])),c=await f(o,n);w8.info(`Wait completed`,{names:r.map(e=>e.folder),timeout_ms:n,timedOut:c.filter(e=>e.timedOut).length});let l=[];a.length>0&&l.push(`Unknown scoops (skipped): ${a.join(`, `)}`);for(let e of c){let t=s.get(e.jid)??e.jid;e.timedOut?l.push(`--- ${t} (timed out) ---`):(l.push(`--- ${t} ---`),l.push(e.summary??`(no output)`))}return{content:l.join(`
|
|
15749
|
+
`)}}}),c&&l&&p.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),w8.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}}}})),p}var D8=`slicc:adobe-daily-uuid:`,O8=new Map;function k8(){return new Date().toISOString().slice(0,10)}function A8(){try{return globalThis.localStorage??null}catch{return null}}function j8(e){let t=k8(),n=A8(),r=D8+e;if(n){let e=n.getItem(r);if(e)try{let n=JSON.parse(e);if(n.date===t&&typeof n.uuid==`string`)return n.uuid}catch{}let i=crypto.randomUUID();try{n.setItem(r,JSON.stringify({uuid:i,date:t}))}catch{}return i}let i=O8.get(e);if(i&&i.date===t)return i.uuid;let a=crypto.randomUUID();return O8.set(e,{uuid:a,date:t}),a}async function M8(e,t){let n=new TextEncoder().encode(`${t}:${e}`),r=await crypto.subtle.digest(`SHA-256`,n);return Array.from(new Uint8Array(r).slice(0,8)).map(e=>e.toString(16).padStart(2,`0`)).join(``)}async function N8(e,t){let n=j8(t??e.jid);return e.isCone?n:`${n}/${await M8(e.folder,n)}`}var P8=n({fetchSecretEnvVars:()=>I8}),F8=i(`secret-env`);async function I8(){if(typeof chrome<`u`&&chrome?.runtime?.id)return{};try{let e=await fetch(`/api/secrets/masked`);if(!e.ok)return F8.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&&F8.info(`Loaded masked secrets into shell env`,{count:Object.keys(n).length}),n}catch(e){return F8.debug(`Could not fetch masked secrets (server may be unavailable)`,{error:e instanceof Error?e.message:String(e)}),{}}}var L8=i(`scoop-context`);function R8(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)}function z8(e){return/\b(401|403|404|405|410|422)\b/.test(e)||/unauthorized|forbidden|authentication.*failed|invalid.*api.?key/i.test(e)||/model.*not.*found|invalid.*model|unknown.*model|does.*not.*exist/i.test(e)||/insufficient.*quota|billing|payment.*required|account.*suspended/i.test(e)||/invalid.*request|malformed|bad.*request/i.test(e)}function B8(e){return/\b429\b|rate.*limit|too.*many.*requests|quota.*exceeded/i.test(e)||/\b(500|502|503|504)\b|internal.*server|bad.*gateway|service.*unavailable|gateway.*timeout/i.test(e)||/network.*error|connection.*refused|timeout|econnreset|socket.*hang.*up/i.test(e)||/overloaded|temporarily.*unavailable|try.*again/i.test(e)}function V8(e,t){return t?.aborted?Promise.resolve(!0):new Promise(n=>{let r=()=>{clearTimeout(i),n(!0)},i=setTimeout(()=>{t?.removeEventListener(`abort`,r),n(!1)},e);t?.addEventListener(`abort`,r,{once:!0})})}var H8=class{scoop;callbacks;fs=null;shell=null;agent=null;status=`initializing`;isProcessing=!1;disposed=!1;didStreamDeltas=!1;unsubscribe=null;promptAbortController=null;sessionStore=null;sessionId;sessionCreatedAt=0;isRecovering=!1;coneJid;skillsFs=null;skillsDir=`/workspace/skills`;constructor(e,t,n,r,i,a){this.scoop=e,this.callbacks=t,this.fs=n,this.sessionStore=r??null,this.skillsFs=i??null,this.coneJid=a,this.sessionId=e.jid}async init(){this.setStatus(`initializing`);try{if(!this.fs)throw Error(`Filesystem not provided`);L8.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 S8(this.fs,this.skillsDir);let n=this.skillsFs??this.fs,r=await I8();this.shell=new O6({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}),L8.info(`WasmShell initialized`,{folder:this.scoop.folder});let i=await v8(n,this.skillsDir),a=E8({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,onMuteScoops:this.callbacks.onMuteScoops,onUnmuteScoops:this.callbacks.onUnmuteScoops,onWaitForScoops:this.callbacks.onWaitForScoops,onSetGlobalMemory:this.callbacks.setGlobalMemory,getGlobalMemory:this.callbacks.getGlobalMemory}),c=o([...j6(this.fs),z6(this.shell),...a]),p=this.scoop.isCone?`/workspace/CLAUDE.md`:`/scoops/${this.scoop.folder}/CLAUDE.md`,m=``;try{let e=await this.fs.readFile(p,{encoding:`utf-8`});m=typeof e==`string`?e:new TextDecoder().decode(e)}catch{}let h=await this.callbacks.getGlobalMemory();if(h)try{this.scoop.isCone&&await(`getUnderlyingFS`in this.fs?this.fs.getUnderlyingFS():this.fs).writeFile(`/shared/CLAUDE.md`,h)}catch{}if(!s()){let e=l();throw Error(`No API key configured for provider "${e}"`)}let g=this.scoop.config?.modelId?d(this.scoop.config.modelId):u(),_=this.scoop.isCone?`Cone`:`Scoop "${this.scoop.name}"`;console.log(`[model] ${_} using model: ${g.id} (provider: ${g.provider})`);let v=this.buildSystemPrompt(h,m,i),y=[];if(this.sessionStore)try{let e=await this.sessionStore.load(this.sessionId);e&&(y=e.messages,this.sessionCreatedAt=e.createdAt,L8.info(`Restored agent session`,{folder:this.scoop.folder,messageCount:y.length}))}catch(e){L8.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 b=f({model:g,getApiKey:()=>s()??void 0}),x=await N8(this.scoop,this.coneJid),S=(e,t,n)=>e.provider===`adobe`?C(e,t,{...n,headers:{...n?.headers,"X-Session-Id":x}}):C(e,t,n);if(this.disposed)return;this.agent=new w({initialState:{model:g,tools:c,systemPrompt:v,messages:y},getApiKey:()=>s()??void 0,transformContext:b,streamFn:S}),this.unsubscribe=this.agent.subscribe(e=>this.handleAgentEvent(e)),this.setStatus(`ready`),L8.info(`ScoopContext initialized`,{folder:this.scoop.folder,toolCount:c.length})}catch(e){if(this.disposed)return;let t=e instanceof Error?e.message:String(e);L8.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){L8.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}let n=this.agent;this.promptAbortController?.abort();let r=new AbortController;this.promptAbortController=r;let i=r.signal;this.isProcessing=!0,this.setStatus(`processing`);let a=1e3,o=null;try{for(let t=1;t<=3;t++){if(this.disposed||i.aborted)return;this.didStreamDeltas=!1;try{await n.prompt(e),o=null;break}catch(e){if(this.disposed||i.aborted)return;o=e instanceof Error?e:Error(String(e));let n=o.message;if(z8(n)){L8.error(`Non-retryable agent error`,{folder:this.scoop.folder,error:n,attempt:t}),this.setStatus(`error`),this.callbacks.onFatalError?this.callbacks.onFatalError(`Scoop "${this.scoop.name}" failed with unrecoverable error: ${n}`):this.callbacks.onError(n);return}if(B8(n)&&t<3){let e=a*2**(t-1);if(L8.warn(`Retryable agent error, will retry`,{folder:this.scoop.folder,error:n,attempt:t,maxRetries:3,delayMs:e}),await V8(e,i)||this.disposed)return;continue}if(L8.error(`Agent error`,{folder:this.scoop.folder,error:n,attempt:t,isRetryable:B8(n)}),t===3)break;if(await V8(a*2**(t-1),i)||this.disposed)return}}if(o&&!this.disposed&&!i.aborted){let e=o.message;L8.error(`Agent error after retries exhausted`,{folder:this.scoop.folder,error:e,maxRetries:3}),this.setStatus(`error`),this.callbacks.onFatalError?this.callbacks.onFatalError(`Scoop "${this.scoop.name}" failed after 3 attempts: ${e}`):this.callbacks.onError(e);return}!this.disposed&&!i.aborted&&this.setStatus(`ready`)}finally{this.isProcessing=!1,this.promptAbortController===r&&(this.promptAbortController=null)}}stop(){this.promptAbortController?.abort(),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=u();this.agent.state.model=e,L8.info(`Model updated on running agent`,{folder:this.scoop.folder,model:e.id})}async reloadSkills(){if(!this.agent)return;let e=await v8(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,L8.info(`Skills reloaded`,{folder:this.scoop.folder,skillCount:e.length})}dispose(){this.disposed=!0,this.promptAbortController?.abort(),this.promptAbortController=null,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(`
|
|
15750
|
+
`),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&&R8(n)){this.recoverFromImageError(t);break}if(!this.isRecovering&&c(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=>{L8.error(`Failed to save agent session`,{folder:this.scoop.folder,error:e instanceof Error?e.message:String(e)})});break}}}recoverFromOverflow(e){if(this.agent){L8.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++,L8.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=>{L8.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){L8.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){L8.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=>{L8.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){L8.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
|
|
15751
15751
|
|
|
15752
15752
|
${this.scoop.isCone?`Role: Cone (main orchestrator)`:`Scoop: ${this.scoop.name}`}
|
|
15753
15753
|
Folder: ${this.scoop.folder}
|
|
@@ -15758,7 +15758,7 @@ Created: ${new Date().toISOString()}
|
|
|
15758
15758
|
|
|
15759
15759
|
## Context
|
|
15760
15760
|
(Add important context here)
|
|
15761
|
-
`;try{await this.fs.writeFile(t,e)}catch(e){if(e?.code===`EACCES`)
|
|
15761
|
+
`;try{await this.fs.writeFile(t,e)}catch(e){if(e?.code===`EACCES`)L8.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}
|
|
15762
15762
|
|
|
15763
15763
|
You are ${r}, ${this.scoop.isCone?`the main assistant (cone)`:`a scoop assistant`} in SLICC (Self-Licking Ice Cream Cone).
|
|
15764
15764
|
|
|
@@ -15826,18 +15826,18 @@ ${e}
|
|
|
15826
15826
|
---
|
|
15827
15827
|
${this.scoop.isCone?`CONE`:`SCOOP`} MEMORY (${this.scoop.name}):
|
|
15828
15828
|
${t}
|
|
15829
|
-
---`);let a=
|
|
15830
|
-
`);return Error(`Cannot remove scoop '${e}': it has ${r.join(` and `)}. Unregister them first:\n${i}`)}var
|
|
15829
|
+
---`);let a=x8(n);return a&&(i+=a),i}},U8=i(`scheduler`),W8=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(),U8.info(`Scheduler started`))}stop(){this.pollInterval&&=(clearInterval(this.pollInterval),null),this.running=!1,U8.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 M(i),U8.info(`Task created`,{id:i.id,groupFolder:e,scheduleType:n}),i}async updateTask(e,t){let n=await ve(e);if(!n)return null;let r={...n,...t};return(t.scheduleType||t.scheduleValue)&&(r.nextRun=this.calculateNextRun(r.scheduleType,r.scheduleValue)),await M(r),U8.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 ve(e)?(await this.updateTask(e,{status:`active`}),!0):!1}async deleteTask(e){return await ve(e)?(await ue(e),U8.info(`Task deleted`,{id:e}),!0):!1}async getTasksByScoop(e){return(await _e()).filter(t=>t.groupFolder===e)}async getAllTasks(){return _e()}async checkTasks(){let e=await _e(),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){U8.warn(`Task scoop not found`,{taskId:e.id,groupFolder:e.groupFolder});return}U8.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 M({...e,lastRun:n,nextRun:r,status:i}),await this.callbacks.onTaskRun(e,t),U8.info(`Task completed`,{id:e.id})}catch(t){U8.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}},G8=n({LickManager:()=>q8,buildActiveLicksError:()=>J8,getLickManager:()=>X8}),K8=i(`lick-manager`),q8=class{webhooks=new Map;crontasks=new Map;cronInterval=null;eventHandler=null;async init(){await he();let e=await we();for(let t of e)this.webhooks.set(t.id,t);K8.info(`Loaded webhooks`,{count:this.webhooks.size});let t=await Se();for(let e of t)this.crontasks.set(e.id,e);K8.info(`Loaded crontasks`,{count:this.crontasks.size}),this.cronInterval=setInterval(()=>this.runCronScheduler(),6e4),K8.info(`Cron scheduler started`)}dispose(){this.cronInterval&&=(clearInterval(this.cronInterval),null)}setEventHandler(e){this.eventHandler=e}emitEvent(e){K8.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 de(i),K8.info(`Webhook created`,{id:r,name:e,scoop:t}),i}async deleteWebhook(e){return this.webhooks.has(e)?(this.webhooks.delete(e),await be(e),K8.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){K8.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){K8.debug(`Webhook event dropped by filter`,{webhookId:e,name:r.name});return}typeof t==`object`&&t&&(i=t)}catch(t){K8.error(`Webhook filter error`,{webhookId:e,error:t instanceof Error?t.message:String(t)})}K8.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 me(o),K8.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 ye(e),K8.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){K8.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 me(t);continue}typeof r==`object`&&r&&(n=r)}catch(e){K8.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};K8.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 me(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 J8(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(`
|
|
15830
|
+
`);return Error(`Cannot remove scoop '${e}': it has ${r.join(` and `)}. Unregister them first:\n${i}`)}var Y8=null;function X8(){return Y8||=new q8,Y8}var Z8=i(`orchestrator`),Q8=120*1e3,$8=`/shared/scoop-notifications`,e5=200,t5=1e3;function n5(e){let t=e.replace(/\r\n?/g,`
|
|
15831
15831
|
`);if(t.length===0)return 0;let n=1;for(let e=0;e<t.length;e++)t[e]===`
|
|
15832
15832
|
`&&n++;return t.endsWith(`
|
|
15833
|
-
`)?n-1:n}var
|
|
15834
|
-
... (truncated)`:n;for(let n of r)try{n(t)}catch(t){
|
|
15835
|
-
`)}formatScoopCompletionFallbackNotification(e,t,n,r){return[`[@${e} completed]`,`VFS path: unavailable`,`Artifact persistence error: ${r}`,`Total lines: ${t}`,`Preview (up to ${
|
|
15836
|
-
`)}muteScoops(e){for(let t of e)this.mutedScoops.add(t);
|
|
15837
|
-
... (truncated)`:e.responseText,timestamp:e.timestamp,notificationPath:null};t.push(a),n.push(this.writeScoopCompletionArtifact(i,e.responseText).then(e=>{a.notificationPath=e}).catch(e=>{
|
|
15838
|
-
... (truncated)`:t.responseText;r.set(e,{summary:n,timedOut:!1})}}let a=n.filter(e=>!r.has(e)),o=a.filter(e=>this.scoops.has(e)),s=a.filter(e=>!this.scoops.has(e));for(let e of s)r.set(e,{summary:null,timedOut:!0});let c=[],l=o.map(e=>new Promise(t=>{let n=n=>{r.has(e)||(r.set(e,{summary:n,timedOut:n===null}),t())};c.push({jid:e,waiter:n});let i=this.completionWaiters.get(e);i||(i=[],this.completionWaiters.set(e,i)),i.push(n)})),u=null;try{l.length>0&&(t!=null&&t>=0?await Promise.race([Promise.all(l),new Promise(e=>{u=setTimeout(()=>e(),t)})]):await Promise.all(l))}finally{u&&clearTimeout(u);for(let{jid:e,waiter:t}of c){let n=this.completionWaiters.get(e);if(!n)continue;let r=n.indexOf(t);r!==-1&&n.splice(r,1),n.length===0&&this.completionWaiters.delete(e)}for(let e of i)this.mutedScoops.delete(e)}for(let e of o)r.has(e)||r.set(e,{summary:null,timedOut:!0});return e.map(e=>{let t=r.get(e)??{summary:null,timedOut:!0};return{jid:e,summary:t.summary,timedOut:t.timedOut}})}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){G8.warn(`scoop observer threw`,{jid:e,event:t,error:n instanceof Error?n.message:String(n)})}}}async registerScoop(e){await Te(e),this.scoops.set(e.jid,e),this.messageQueues.set(e.jid,[]),G8.info(`Scoop registered`,{jid:e.jid,name:e.name});try{await this.createScoopTab(e.jid)}catch(t){throw G8.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 ge(e.jid).catch(t=>{G8.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=H8(t.folder,e,n);if(r)throw r}this.snapshotScoopCost(e),this.clearIdleTimer(e),await this.destroyScoopTab(e),this.sessionStore?.delete(e).catch(t=>{G8.warn(`Failed to delete agent session`,{jid:e,error:t instanceof Error?t.message:String(t)})}),await ge(e),this.scoops.delete(e),this.messageQueues.delete(e),this.lastAgentTimestamp.delete(e),this.scoopResponseBuffer.delete(e),this.scoopObservers.delete(e);let n=this.completionWaiters.get(e);if(n){this.completionWaiters.delete(e);for(let t of n)try{t(null)}catch(t){G8.warn(`completion waiter threw on unregister`,{jid:e,error:t instanceof Error?t.message:String(t)})}}this.mutedScoops.delete(e),this.pendingCompletions.delete(e),G8.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 ne.create({dbName:`slicc-fs`,wipe:!0}),this.fsWatcher&&this.sharedFs.setWatcher(this.fsWatcher),await this.ensureRootStructure(),await this.ensureGlobalMemory(),await g8(this.sharedFs).catch(e=>{G8.warn(`Failed to re-seed default skills`,{error:e instanceof Error?e.message:String(e)})}),this.droppedScoopCosts=[],G8.info(`Filesystem reset and defaults re-seeded`)}async clearAllMessages(){await Ce(),this.sessionStore&&await this.sessionStore.clearAll().catch(e=>{G8.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=[],G8.info(`All messages cleared`)}async handleMessage(e){G8.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);u6(t?.isCone?`cone`:t?.name??`unknown`,localStorage.getItem(`selected-model`)??`unknown`),await le(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 le(i),this.callbacks.onIncomingMessage?.(e,i),G8.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);G8.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){G8.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)){G8.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(G8.debug(`routeToScoop: queued`,{chatJid:e.chatJid,scoopName:t.name,tabStatus:i?.status??`no-tab`,queueLength:r.length}),i?.status===`error`){G8.info(`routeToScoop: tab in error state, retrying init`,{chatJid:e.chatJid});try{await this.createScoopTab(e.chatJid),i=this.tabs.get(e.chatJid)}catch{G8.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`)G8.info(`Re-creating context after error`,{jid:e}),this.contexts.get(e)?.dispose(),this.contexts.delete(e),this.tabs.delete(e);else{G8.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 ie(this.sharedFs,t.config?.writablePaths?[...t.config.writablePaths]:[],t.config?.visiblePaths?[...t.config.visiblePaths]:[]),i={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`)},onFatalError:t=>{if(!this.scoops.has(e))return;let n=this.scoops.get(e);G8.error(`Fatal scoop error`,{jid:e,folder:n.folder,error:t});let r=this.tabs.get(e);if(r&&(r.status=`error`,r.error=t,this.tabs.set(e,r)),this.callbacks.onError(e,t),this.callbacks.onStatusChange(e,`error`),this.dispatchScoopEvent(e,`onError`,t),this.dispatchScoopEvent(e,`onStatusChange`,`error`),n.isCone)return;this.mutedScoops.delete(e),this.pendingCompletions.delete(e),this.scoopResponseBuffer.delete(e);let i=this.completionWaiters.get(e);if(i&&i.length>0){this.completionWaiters.delete(e);for(let t of i)try{t(null)}catch(t){G8.warn(`completion waiter threw on fatal error`,{jid:e,error:t instanceof Error?t.message:String(t)})}}let a=Array.from(this.scoops.values()).find(e=>e.isCone);if(!a)return;let o={id:`scoop-error-${e}-${Date.now()}`,chatJid:a.jid,senderId:n.folder,senderName:n.assistantLabel,content:`[@${n.assistantLabel} FAILED]: ${t}`,timestamp:new Date().toISOString(),fromAssistant:!1,channel:`scoop-error`};try{this.callbacks.onIncomingMessage?.(a.jid,o)}catch(e){G8.warn(`onIncomingMessage for scoop-error threw`,{scoop:n.folder,error:e instanceof Error?e.message:String(e)})}this.handleMessage(o).catch(e=>{G8.error(`Failed to route fatal error to cone`,{scoop:n.folder,error:e instanceof Error?e.message:String(e)})})},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,onMuteScoops:t.isCone?e=>this.muteScoops(e):void 0,onUnmuteScoops:t.isCone?e=>this.unmuteScoops(e):void 0,onWaitForScoops:t.isCone?(e,t)=>this.waitForScoops(e,t):void 0,getGlobalMemory:()=>this.getGlobalMemory(),setGlobalMemory:t.isCone?e=>this.setGlobalMemory(e):void 0,getBrowserAPI:()=>this.callbacks.getBrowserAPI()},a=Array.from(this.scoops.values()).find(e=>e.isCone)?.jid,o=new I8(t,i,r,this.sessionStore??void 0,this.sharedFs??void 0,a);this.contexts.set(e,o),this.tabs.set(e,{jid:e,contextId:n,status:`initializing`,lastActivity:new Date().toISOString()}),await o.init();let s=this.tabs.get(e);s&&s.status===`initializing`&&(s.status=`ready`,this.tabs.set(e,s),this.callbacks.onStatusChange(e,`ready`),this.dispatchScoopEvent(e,`onStatusChange`,`ready`));let c=this.scoops.get(e);c&&!c.isCone&&this.startIdleTimer(e),G8.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),G8.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 j(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 j(t)}async getMessagesForScoop(e){return A(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 G8.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(G8.debug(`Context initializing, waiting to send message`,{jid:e}),!await this.waitForTabReady(e)){G8.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){G8.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`)),G8.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){G8.debug(`processScoopQueue: empty queue`,{jid:e});return}let n=this.tabs.get(e);if(n?.status!==`ready`){G8.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 pe(e,a,i);if(G8.debug(`processScoopQueue: DB query`,{jid:e,scoopName:r?.name,excludeName:i,since:a,dbMessageCount:o.length,queueLength:t.length}),o.length===0){G8.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(`
|
|
15839
|
-
`);this.messageQueues.set(e,[]);let c=o[o.length-1];this.lastAgentTimestamp.set(e,c.timestamp),await Ee(`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);G8.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();G8.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=>{G8.warn(`Failed to reload skills for scoop`,{jid:t,error:e instanceof Error?e.message:String(e)})}))}await Promise.all(e),G8.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`};G8.info(`Scoop idle timeout`,{jid:e,scoop:t.folder});try{this.callbacks.onIncomingMessage?.(n.jid,r)}catch(t){G8.warn(`onIncomingMessage for scoop-idle threw`,{jid:e,error:t instanceof Error?t.message:String(t)})}this.handleMessage(r).catch(t=>{let n=t instanceof Error?t.message:String(t);G8.error(`Failed to send idle notification`,{jid:e,error:n})})},K8);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.completionWaiters.values())for(let t of e)try{t(null)}catch(e){G8.warn(`completion waiter threw during shutdown`,{error:e instanceof Error?e.message:String(e)})}this.completionWaiters.clear(),this.mutedScoops.clear(),this.pendingCompletions.clear();for(let e of this.contexts.keys())await this.destroyScoopTab(e);G8.info(`Orchestrator shutdown`)}};i(`heartbeat`);var Q8=i(`tray-follower`);function $8(e){let t=new URL(e);return t.searchParams.set(`json`,`true`),t.toString()}async function e5(e){let t=$8(e.joinUrl),n=await s5(await(e.fetchImpl??fetch)(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({controllerId:e.controllerId,runtime:e.runtime})}));return Q8.info(`Follower tray attach response`,{trayId:n.trayId,action:n.result.action,code:n.result.code,participantCount:n.participantCount}),t5(n)}function t5(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 n5(e){return o5(await c5(e,{action:`poll`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,cursor:e.cursor}))}async function r5(e){return o5(await c5(e,{action:`answer`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,answer:e.answer}))}async function i5(e){return o5(await c5(e,{action:`ice-candidate`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,candidate:e.candidate}))}async function a5(e){return o5(await c5(e,{action:`retry`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,runtime:e.runtime}))}function o5(e){return{trayId:e.trayId,controllerId:e.controllerId,participantCount:e.participantCount,leader:e.leader,bootstrap:e.bootstrap,events:e.events}}async function s5(e){let t=null,n=null;try{t=await e.text(),n=JSON.parse(t)}catch{}if(!l5(n)){let n=t?t.slice(0,200):`(empty)`;throw Q8.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 c5(e,t){let n=$8(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(!u5(i))throw Error(`Tray follower bootstrap returned an invalid response (${r.status})`);return i}function l5(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`&&d5(r.bootstrap):r.action===`fail`?(r.code===`INVALID_JOIN_CAPABILITY`||r.code===`TRAY_EXPIRED`)&&typeof r.error==`string`:!1}function u5(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`&&d5(t.bootstrap)&&Array.isArray(t.events)}function d5(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 f5=n({AGENT_BRIDGE_GLOBAL_KEY:()=>m5,AGENT_SPAWN_REQUEST_TYPE:()=>h5,createAgentBridge:()=>g5,publishAgentBridge:()=>_5,publishAgentBridgeProxy:()=>v5}),p5=i(`agent-bridge`),m5=`__slicc_agent`,h5=`agent-spawn-request`;function g5(e,t,n=null,r={}){let i=r.generateName??S5,a=r.generateUid??y5,o=r.resolveModel??w5;function s(){for(let t=0;t<8;t++){let t=i(),n=`agent_${C5(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_${C5(l)}`,f=`/scoops/${u}`,p=T5(r.cwd),m={visiblePaths:E5(r),writablePaths:D5([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??O5(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??O5(e),exitCode:1}}finally{y();try{await e.unregisterScoop(d)}catch(e){p5.warn(`unregisterScoop failed`,{jid:d,error:O5(e)})}try{await t.rm(f,{recursive:!0})}catch(e){k5(e,`ENOENT`)||p5.warn(`scratch folder cleanup failed`,{folder:u,error:O5(e)})}if(n)try{await n.delete(d)}catch(e){p5.warn(`sessionStore.delete failed`,{jid:d,error:O5(e)})}}}return{spawn:l}}function _5(e,t,n=null,r={}){let i=g5(e,t,n,r);return globalThis[m5]=i,p5.info(`agent bridge published on globalThis.__slicc_agent`),i}function v5(){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:h5,options:e}},i)}catch(e){n(e instanceof Error?e:Error(String(e)))}})}};return globalThis[m5]=e,p5.info(`agent bridge proxy published on globalThis.__slicc_agent`),e}function y5(){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 b5=`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(`.`),x5=`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 S5(){return`${b5[Math.floor(Math.random()*b5.length)]}-${x5[Math.floor(Math.random()*x5.length)]}`}function C5(e){return e.replace(/-/g,`_`)}function w5(e){try{let t=p();for(let n of t)if(n.models.some(t=>t.id===e))return e;return null}catch{return null}}function T5(e){let t=ae(e);return t.endsWith(`/`)?t:`${t}/`}function E5(e){if(e.visiblePaths!==void 0)return e.visiblePaths.map(T5);let t=[`/workspace/`];return e.invokingCwd&&e.invokingCwd.length>0&&t.push(T5(e.invokingCwd)),D5(t)}function D5(e){let t=new Set,n=[];for(let r of e)t.has(r)||(t.add(r),n.push(r));return n}function O5(e){return e instanceof Error?e.message:String(e)}function k5(e,t){if(typeof e!=`object`||!e)return!1;let n=e.code;return typeof n==`string`&&n===t}var A5=i(`tray-webrtc`),j5=`tray-control`,M5=250,N5=class{peerConnectionFactory;dataChannelLabel;peers=new Map;iceServers;constructor(e){this.options=e,this.iceServers=e.iceServers,this.peerConnectionFactory=e.peerConnectionFactory??(()=>I5(this.iceServers)),this.dataChannelLabel=e.dataChannelLabel??j5}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=R5(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`)&&(A5.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`?(A5.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`?(A5.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:L5(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){A5.warn(`Failed to report tray bootstrap failure`,{error:e instanceof Error?e.message:String(e)})}}}},P5=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??(()=>I5(this.iceServers)),this.controllerIdFactory=e.controllerIdFactory??(()=>crypto.randomUUID()),this.sleep=e.sleep??(e=>new Promise(t=>setTimeout(t,e))),this.pollIntervalMs=e.pollIntervalMs??M5}async start(){this.stopped=!1;let e=this.controllerIdFactory(),t=Date.now();vo({state:`connecting`,joinUrl:this.options.joinUrl,trayId:null,error:null,lastPingTime:null,reconnectAttempts:0,attachAttempts:0,lastAttachCode:null,connectingSince:t,lastError:null}),A5.info(`Follower tray join starting`,{joinUrl:this.options.joinUrl});let n=0;for(;;){z5(this.stopped),n++;let t;try{t=await e5({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 vo({..._o(),attachAttempts:n,lastError:t}),e}if(vo({..._o(),attachAttempts:n,lastAttachCode:t.code}),t.action===`wait`){let e=t.retryAfterMs??1e3;A5.info(`Follower tray attach waiting`,{attempt:n,code:t.code,retryAfterMs:e}),n%10==0&&A5.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 vo({state:`error`,joinUrl:this.options.joinUrl,trayId:null,error:e,lastPingTime:null,reconnectAttempts:0,attachAttempts:n,lastAttachCode:t.code,connectingSince:null,lastError:e}),A5.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 vo({state:`connected`,joinUrl:this.options.joinUrl,trayId:r.trayId,error:null,lastPingTime:null,reconnectAttempts:0,attachAttempts:n,lastAttachCode:t.code,connectingSince:null,lastError:null}),A5.info(`Follower tray connected`,{trayId:r.trayId,controllerId:e}),r}catch(e){let r=e instanceof Error?e.message:String(e);throw vo({state:`error`,joinUrl:this.options.joinUrl,trayId:t.trayId,error:r,lastPingTime:null,reconnectAttempts:0,attachAttempts:n,lastAttachCode:t.code,connectingSince:null,lastError:r}),A5.warn(`Follower tray bootstrap failed`,{error:r}),e}}}stop(){this.stopped=!0,this.activePeer?.peer.close(),this.activePeer?.channel?.close(),this.activePeer=null,vo({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(z5(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 n5({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 r5({joinUrl:this.options.joinUrl,controllerId:t,bootstrapId:r.bootstrapId,answer:L5(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 a5({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`)&&(A5.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?(A5.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?(A5.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=R5(n);r&&i5({joinUrl:this.options.joinUrl,controllerId:e,bootstrapId:t,candidate:r,fetchImpl:this.fetchImpl}).catch(e=>{A5.warn(`Failed to send follower ICE candidate`,{error:e instanceof Error?e.message:String(e)})})}),r}};function F5(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 P5({...e,sleep:o,onDisconnected:e=>{s||(A5.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,m=u??`Unknown disconnect`;for(;!s&&f<a&&(f++,t.onReconnecting?.(f),vo({..._o(),state:`reconnecting`,error:null,reconnectAttempts:f}),A5.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,vo({..._o(),state:`connected`,joinUrl:e.joinUrl,trayId:i.trayId,error:null,lastPingTime:null,reconnectAttempts:0,connectingSince:null,lastError:null}),A5.info(`Reconnect successful`,{attempt:f,trayId:i.trayId}),t.onConnected(i);return}catch(e){m=e instanceof Error?e.message:String(e),A5.warn(`Reconnect attempt failed`,{attempt:f,error:m}),n?.stop(),l=null}p=Math.min(p*r,i)}s||(c=!1,vo({..._o(),state:`error`,error:`Reconnect failed after ${f} attempts: ${m}`,reconnectAttempts:f}),A5.warn(`Reconnect gave up`,{attempts:f,lastError:m}),t.onGaveUp?.(m))},{connectionPromise:p}=d();return p.then(e=>{s||t.onConnected(e)}).catch(e=>{s||A5.warn(`Initial follower connection failed`,{error:e instanceof Error?e.message:String(e)})}),u}function I5(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 L5(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 R5(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 z5(e){if(e)throw Error(`Tray follower stopped before WebRTC bootstrap completed`)}var B5=64*1024;async function V5(e,t){try{switch(t.op){case`readFile`:return await H5(e,t.path,t.encoding);case`writeFile`:return[await U5(e,t.path,t.content,t.encoding)];case`stat`:return[await W5(e,t.path)];case`readDir`:return[await G5(e,t.path)];case`mkdir`:return[await K5(e,t.path,t.recursive)];case`rm`:return[await q5(e,t.path,t.recursive)];case`exists`:return[await J5(e,t.path)];case`walk`:return[await Y5(e,t.path)];default:return[{ok:!1,error:`Unknown fs operation: ${t.op}`}]}}catch(e){return[Z5(e)]}}async function H5(e,t,n){return(n??`utf-8`)===`utf-8`?X5(await e.readFile(t,{encoding:`utf-8`}),`utf-8`):X5(Q5(await e.readFile(t,{encoding:`binary`})),`base64`)}async function U5(e,t,n,r){if(r===`base64`){let r=$5(n);await e.writeFile(t,r)}else await e.writeFile(t,n);return{ok:!0,data:{type:`void`}}}async function W5(e,t){return{ok:!0,data:{type:`stat`,stat:await e.stat(t)}}}async function G5(e,t){return{ok:!0,data:{type:`dirEntries`,entries:await e.readDir(t)}}}async function K5(e,t,n){return await e.mkdir(t,{recursive:n}),{ok:!0,data:{type:`void`}}}async function q5(e,t,n){return await e.rm(t,{recursive:n}),{ok:!0,data:{type:`void`}}}async function J5(e,t){return{ok:!0,data:{type:`exists`,exists:await e.exists(t)}}}async function Y5(e,t){let n=[];for await(let r of e.walk(t))n.push(r);return{ok:!0,data:{type:`paths`,paths:n}}}function X5(e,t){if(e.length<=B5)return[{ok:!0,data:{type:`file`,content:e,encoding:t}}];let n=Math.ceil(e.length/B5),r=[];for(let i=0;i<n;i++){let a=i*B5,o=e.slice(a,a+B5);r.push({ok:!0,data:{type:`file`,content:o,encoding:t},chunkIndex:i,totalChunks:n})}return r}function Z5(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 Q5(e){let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function $5(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 e7=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()]}},t7=i(`data-channel-keepalive`),n7=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++,t7.debug(`Missed pong`,{missedPongs:this.missedPongs,maxMissed:this.maxMissed}),this.missedPongs>=this.maxMissed)){t7.warn(`Channel declared dead`,{missedPongs:this.missedPongs}),this.stop(),this.onDead();return}this.awaitingPong=!0,this.sendPing()}}},r7=i(`tray-leader-sync`);function i7(e){return e?e.includes(`standalone`)?`standalone`:e.includes(`extension`)?`extension`:e.includes(`electron`)?`electron`:`unknown`:`unknown`}var a7=class{followers=new Map;registry=new e7;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=Ps(t),i=r.onMessage(t=>{this.handleFollowerMessage(e,t)}),a=new n7({sendPing:()=>r.send({type:`ping`}),onDead:()=>{r7.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:i7(n?.runtime)}),r7.info(`Follower added to sync`,{bootstrapId:e,followerCount:this.followers.size}),this.options.onFollowerCountChanged?.(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(),r7.info(`Follower removed from sync`,{bootstrapId:e,followerCount:this.followers.size}),this.options.onFollowerCountChanged?.(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();js(t.sync,n,r),r7.debug(`Snapshot sent to follower`,{bootstrapId:e,messageCount:n.length})}handleFollowerMessage(e,t){switch(t.type){case`user_message`:r7.info(`Follower user message received`,{bootstrapId:e,messageId:t.messageId}),this.options.onFollowerMessage(t.text,t.messageId);break;case`abort`:r7.info(`Follower abort received`,{bootstrapId:e}),this.options.onFollowerAbort();break;case`request_snapshot`:r7.info(`Follower snapshot request received`,{bootstrapId:e}),this.sendSnapshotToFollower(e);break;case`targets.advertise`:r7.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),r7.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 Is({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),r7.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);Os(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=ks(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&&Os(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 V5(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?V5(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})})}},o7=i(`tray-follower-sync`),s7=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=Fs(e),this.unsubscribe=this.sync.onMessage(e=>{this.handleLeaderMessage(e)}),this.keepalive=new n7({sendPing:()=>this.sync.send({type:`ping`}),onDead:()=>{o7.warn(`Leader keepalive dead, cleaning up`),this.handleDisconnect(`Keepalive timeout — leader not responding`),this.options.onDead?.()}}),this.keepalive.start(),e.addEventListener(`close`,()=>{o7.warn(`Data channel closed`),this.handleDisconnect(`Data channel closed`)}),e.addEventListener(`error`,()=>{o7.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}),o7.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`}),o7.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(),o7.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,vo({..._o(),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`:o7.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=Ms(this.snapshotChunkBuffer,e);this.snapshotChunkBuffer=t.buffer,t.result&&(o7.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),o7.debug(`Skipping own message echo`,{messageId:e.messageId});break}o7.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`:o7.warn(`Error from leader`,{error:e.error}),this.emitEvent({type:`error`,error:e.error});break;case`targets.registry`:o7.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(),yo(Date.now());break}}emitEvent(e){for(let t of this.eventListeners)try{t(e)}catch(t){o7.error(`Listener error`,{eventType:e.type,error:t instanceof Error?t.message:String(t)})}}createRemoteTransport(e,t){let n=new Is({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),o7.debug(`Tracking remote CDP session`,{remoteSessionId:e})}n===`Target.detachFromTarget`&&i&&this.remoteCDPSessions.has(i)&&(this.remoteCDPSessions.delete(i),o7.debug(`Removed remote CDP session on detach`,{sessionId:i})),Os(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=ks(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 V5(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})})}},c7=i(`tab-persistence-guard`),l7=`slicc-tray-leader-active`,u7=class{active=!1;audioCtx=null;oscillator=null;lockController=null;beforeUnloadHandler=null;constructor(e={}){this.options=e}activate(){this.active||(this.active=!0,this.startSilentAudio(),this.acquireWebLock(),this.installBeforeUnload(),c7.info(`Tab persistence guard activated`))}deactivate(){this.active&&(this.active=!1,this.stopSilentAudio(),this.releaseWebLock(),this.removeBeforeUnload(),c7.info(`Tab persistence guard deactivated`))}isActive(){return this.active}startSilentAudio(){try{let e=(this.options.audioContextFactory??(()=>{let e=typeof globalThis<`u`?globalThis.AudioContext??globalThis.webkitAudioContext:void 0;return e?new e:null}))();if(!e){c7.warn(`AudioContext unavailable — discard prevention via silent audio disabled`);return}e.resume?.().catch(()=>{});let t=e.createOscillator(),n=e.createGain();n.gain.value=0,t.connect(n),n.connect(e.destination),t.start(),this.audioCtx=e,this.oscillator=t}catch(e){c7.warn(`Failed to start silent audio guard`,{error:e instanceof Error?e.message:String(e)})}}stopSilentAudio(){try{this.oscillator?.stop()}catch{}this.oscillator=null,this.audioCtx&&=(this.audioCtx.close?.().catch(()=>{}),null)}acquireWebLock(){try{let e=this.options.lockManager??(typeof navigator<`u`&&`locks`in navigator?navigator.locks:null);if(!e){c7.warn(`navigator.locks unavailable — discard prevention via Web Lock disabled`);return}let t=new AbortController;this.lockController=t,e.request(l7,{mode:`exclusive`,signal:t.signal},()=>new Promise(e=>{if(t.signal.aborted){e();return}let n=()=>{t.signal.removeEventListener(`abort`,n),e()};t.signal.addEventListener(`abort`,n,{once:!0})})).catch(e=>{e?.name!==`AbortError`&&c7.warn(`Web Lock request rejected`,{error:e instanceof Error?e.message:String(e)})})}catch(e){c7.warn(`Failed to acquire Web Lock`,{error:e instanceof Error?e.message:String(e)})}}releaseWebLock(){try{this.lockController?.abort()}catch{}this.lockController=null}installBeforeUnload(){try{let e=this.options.windowRef??(typeof window<`u`?window:null);if(!e)return;let t=()=>{};e.addEventListener(`beforeunload`,t),this.beforeUnloadHandler=t}catch{}}removeBeforeUnload(){try{let e=this.options.windowRef??(typeof window<`u`?window:null);e&&this.beforeUnloadHandler&&e.removeEventListener(`beforeunload`,this.beforeUnloadHandler)}catch{}this.beforeUnloadHandler=null}};function d7(e,t){if(t)return`extension`;try{return m7(new URL(e))?`electron-overlay`:`standalone`}catch{return`standalone`}}function f7(e,t){return e===`electron-overlay`||e===`standalone`&&t}function p7(e){try{let t=new URL(e).searchParams.get(`tab`);return t&&Go(t)?t:Uo}catch{return Uo}}function m7(e){return e.pathname===`/electron`||e.pathname===`/electron/`||e.searchParams.get(`runtime`)===`electron-overlay`}function h7(e){let t=new URL(e);return`${t.protocol===`https:`?`wss:`:`ws:`}//${t.host}/licks-ws`}function g7(e,t){return`${new URL(e).origin}/webhooks/${t}`}function _7(e,t){return`${e.replace(/\/+$/,``)}/${t.replace(/^\/+/,``)}`}function v7(e){return typeof e==`object`&&!!e&&`type`in e&&e.type===`slicc-electron-overlay:set-tab`}var y7=[`/shared/sprinkles`];async function b7(e){let t=new Map;for(let n of y7)await e.exists(n)&&await x7(e,n,t);return await x7(e,`/`,t),t}async function x7(e,t,n){for await(let r of e.walk(t)){if(!r.endsWith(`.shtml`))continue;let t=S7(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:C7(i,t),autoOpen:w7(i)})}}}function S7(e){let t=e.split(`/`).pop()??e;return t.endsWith(`.shtml`)?t.slice(0,-6):t}function C7(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 w7(e){return/data-sprinkle-autoopen\b/.test(e)}var T7=i(`sprinkle-manager`),E7=`slicc-open-sprinkles`,D7=class{fs;bridge;callbacks;availableSprinkles=new Map;watcherUnsub;openSprinkles=new Map;constructor(e,t,n,r){this.fs=e,this.bridge=new I0(e,t,e=>this.close(e),r),this.callbacks=n}async restoreOpenSprinkles(){try{let e=localStorage.getItem(E7);if(!e){for(let e of this.availableSprinkles.values())if(e.autoOpen)try{await this.open(e.name)}catch{T7.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{T7.warn(`Failed to restore sprinkle`,{name:e})}}catch{}}persistOpenSprinkles(){try{localStorage.setItem(E7,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),T7.info(`Auto-opened new sprinkle after install`,{name:e.name})}catch{T7.warn(`Failed to auto-open new sprinkle`,{name:e.name})}}async refresh(){this.availableSprinkles=await b7(this.fs),T7.info(`Discovered sprinkles`,{count:this.availableSprinkles.size})}async open(e,t){if(this.openSprinkles.has(e)){T7.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 Zr(a,this.bridge.createAPI(e));await o.render(i,e),this.openSprinkles.get(e).renderer=o,this.persistOpenSprinkles(),f6(e),T7.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(),T7.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){T7.warn(`Cannot send to closed sprinkle`,{name:e});return}this.bridge.pushUpdate(e,t),n.renderer.pushUpdate(t)}};async function O7(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 k7(e){return`'${e.replace(/'/g,`'\\''`)}'`}function A7(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 j7(e){if(!Array.isArray(e)||e.length===0)return null;let t=e.map(({path:e,dirName:t})=>{let n=t?` (previously mounted from ${A7(t)})`:``;return`- ${A7(e)}${n}`}),n=e.map(({path:e})=>` mount ${k7(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(`
|
|
15840
|
-
`)}var $=i(`main`),M7=`slicc-pending-mount`,N7=`pendingMount`;function P7(){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 F7(e){let[{createChatFixture:t,FIXTURE_SESSION_ID:n,FIXTURE_SCOOP_NAME:r}]=await Promise.all([a(()=>import(`./chat-fixture-CIjL7BDw.js`),[])]);await e.switchToContext(n,!0,r),e.loadMessages(t()),$.info(`Loaded UI fixture session for design iteration`)}async function I7(e){let t=await new Promise((e,t)=>{let n=indexedDB.open(M7,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,N7),await new Promise(e=>n.oncomplete=()=>e()),t.close()}async function L7(e){let t;try{t=await new Promise((e,t)=>{let n=indexedDB.open(M7,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(N7);t.onsuccess=()=>e(t.result),t.onerror=()=>e(void 0)});if(r){n.objectStore(`handles`).delete(N7),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 R7(){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 z7(){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 B7(e,t,n){let r=R7(),i=0,a=!1,o=()=>{i=0,a||r.hide()};window.addEventListener(`dragenter`,e=>{ss(e.dataTransfer)&&(e.preventDefault(),i+=1,a||r.show(`Drop .skill to install`,`Unpack into /workspace/skills/{name}.`))}),window.addEventListener(`dragover`,e=>{ss(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=cs(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 ce(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 V7(e){let{OffscreenClient:t}=await a(async()=>{let{OffscreenClient:e}=await import(`./offscreen-client-Dom7iV01.js`);return{OffscreenClient:e}},__vite__mapDeps([19,13])),{VirtualFS:n}=await a(async()=>{let{VirtualFS:e}=await import(`./fs-CuJwg7sR.js`).then(e=>e.t);return{VirtualFS:e}},__vite__mapDeps([15,4,13,16])),{publishAgentBridgeProxy:r}=await a(async()=>{let{publishAgentBridgeProxy:e}=await Promise.resolve().then(()=>f5);return{publishAgentBridgeProxy:e}},void 0),i=new Xo(e,!0);window.__slicc_debug_tabs=e=>i.setDebugTabs(e),await i.panels.chat.initSession(`session-cone`),r();let o=null,s=await n.create({dbName:`slicc-fs`});i.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})}})()},B7(s,z7(),async()=>{await i.panels.fileBrowser.refresh()});try{let{WasmShell:e}=await a(async()=>{let{WasmShell:e}=await Promise.resolve().then(()=>C6);return{WasmShell:e}},void 0),{PanelCdpProxy:t,BrowserAPI:n}=await a(async()=>{let{PanelCdpProxy:e,BrowserAPI:t}=await Promise.resolve().then(()=>Ls);return{PanelCdpProxy:e,BrowserAPI:t}},void 0),{fetchSecretEnvVars:r}=await a(async()=>{let{fetchSecretEnvVars:e}=await Promise.resolve().then(()=>O8);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 i.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 a(async()=>{let{registerSessionCostsProvider:e}=await Promise.resolve().then(()=>p4);return{registerSessionCostsProvider:e}},void 0);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 l,u=new Set,d=async e=>{o=e,l.selectedScoopJid=e.jid,i.panels.memory.setSelectedScoop(e.jid),i.setScoopSwitcherSelected?.(e.jid),i.panels.scoops.setSelectedJid(e.jid);let t=e.isCone?`session-cone`:`session-${e.folder}`,n=e.isCone?void 0:e.name;await i.panels.chat.switchToContext(t,!e.isCone,n),l.isProcessing(e.jid)&&i.panels.chat.setProcessing(!0)};l=new t({onStatusChange:(e,t)=>{i.panels.scoops.updateScoopStatus(e,t),i.updateScoopSwitcherStatus?.(e,t),o?.jid===e&&(i.setAgentProcessing(t===`processing`),t===`processing`?i.panels.chat.setProcessing(!0):t===`ready`&&i.panels.chat.setProcessing(!1))},onScoopCreated:e=>{i.panels.scoops.refreshScoops(),i.refreshScoopSwitcher?.(),o||(o=e,l.selectedScoopJid=e.jid,i.panels.memory.setSelectedScoop(e.jid))},onScoopListUpdate:()=>{let e=new Set(l.getScoops().map(e=>e.folder));for(let t of u)e.has(t)||i.panels.chat.deleteSessionById(`session-${t}`);if(u=e,i.panels.scoops.refreshScoops(),i.refreshScoopSwitcher?.(),!o){let e=l.getScoops().find(e=>e.isCone);e&&(o=e,l.selectedScoopJid=e.jid,i.panels.memory.setSelectedScoop(e.jid))}},onIncomingMessage:(e,t)=>{if(Ta(t.channel)){let n=new Date(t.timestamp).getTime(),r=t.channel;if(o?.jid===e)i.panels.chat.addLickMessage(t.id,t.content,r,n);else{let a=l.getScoops().find(t=>t.jid===e),o=a?.isCone?`session-cone`:a?`session-${a.folder}`:`session-${e}`;i.panels.chat.persistLickToSession(o,{id:t.id,content:t.content,channel:r,timestamp:n})}return}if(o?.jid===e){let e=t.channel===`delegation`?`**[Instructions from sliccy]**\n\n${t.content}`:t.content;i.panels.chat.addUserMessage(e)}},onReady:async()=>{try{$.info(`Offscreen engine ready, scoop count:`,l.getScoops().length),window.localStorage.getItem(`slicc.trayJoinUrl`)&&chrome.runtime.sendMessage({source:`panel`,payload:{type:`refresh-tray-runtime`}}).catch(()=>{});let e=o??l.getScoops().find(e=>e.isCone)??l.getScoops()[0];e&&(o=e,l.selectedScoopJid=e.jid,await d(e))}catch(e){$.error(`Failed to initialize on ready`,{error:e instanceof Error?e.message:String(e)})}}}),l.setLocalFS(s);let f=l.createAgentHandle();i.panels.chat.setAgent(f),i.panels.scoops.setOrchestrator(l),i.panels.memory.setOrchestrator(l),i.setScoopSwitcherOrchestrator?.(l),i.onScoopSelect=d,i.onModelChange=e=>{localStorage.setItem(`selected-model`,e),l.updateModel()},i.onClearChat=async()=>{let e=l.getScoops();for(let t of e){let e=t.isCone?`session-cone`:`session-${t.folder}`;await i.panels.chat.deleteSessionById(e)}l.clearAllMessages()},i.onClearFilesystem=async()=>{l.clearFilesystem()},i.panels.chat.onInlineSprinkleLick=(e,t)=>{l.sendSprinkleLick(`inline`,{action:e,data:t})};let p=new D7(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`&&p.close(`welcome`),n===`onboarding-complete`&&t?.data?.mountWorkspace&&L7(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 I7(t),p.sendToSprinkle(`welcome`,{action:`mount-complete`,dirName:t.name})}catch(e){e.name!==`AbortError`&&$.warn(`Mount picker failed`,e),p.sendToSprinkle(`welcome`,{action:`mount-cancelled`})}return}l.sendSprinkleLick(e.sprinkleName,e.body,e.targetScoop)}},{addSprinkle:(e,t,n,r)=>i.addSprinkle(e,t,n,r),removeSprinkle:e=>i.removeSprinkle(e)},()=>{let e=l.getScoops().find(e=>e.isCone);e&&l.stopScoop(e.jid)});if(window.__slicc_sprinkleManager=p,window.__slicc_reloadSkills=()=>(chrome.runtime.sendMessage({source:`panel`,payload:{type:`reload-skills`}}),Promise.resolve()),l.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 p.refresh(),e=p.available();break;case`opened`:e=p.opened();break;case`refresh`:await p.refresh(),e=p.available().length;break;case`open`:await p.open(r),e=!0;break;case`close`:p.close(r),e=!0;break;case`send`:p.sendToSprinkle(r,i),e=!0;break;case`openNewAutoOpen`:await p.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 p.refresh(),i.onSprinkleClose=e=>p.close(e),i.getAvailableSprinkles=()=>{let e=new Set(p.opened());return p.available().filter(t=>!e.has(t.name)).map(e=>({name:e.name,title:e.title}))},i.onOpenSprinkle=(e,t)=>p.open(e,t),i.updateAddButtons(),await p.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`)&&!co(window.localStorage)&&p.available().some(e=>e.name===`welcome`))try{await p.open(`welcome`)}catch(e){$.warn(`Failed to open welcome sprinkle`,e)}$.info(`SprinkleManager initialized (extension mode)`),l.requestState(),$.info(`Extension UI connected to offscreen agent engine`),P7()&&await F7(i.panels.chat),l6().catch(()=>{})}function H7(){if(typeof chrome<`u`&&chrome?.runtime?.id)return;let e=new Blob([`
|
|
15833
|
+
`)?n-1:n}var r5=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;mutedScoops=new Set;pendingCompletions=new Map;completionWaiters=new Map;constructor(e,t,n={name:`sliccy`,triggerPattern:/^@sliccy\b/i}){this.container=e,this.callbacks=t,this.config=n}async init(){await he(),this.sharedFs=await ne.create({dbName:`slicc-fs`}),this.sessionStore=new S,this.fsWatcher=new k,this.sharedFs.setWatcher(this.fsWatcher),globalThis.__slicc_fs_watcher=this.fsWatcher,await this.ensureRootStructure();let e=await fe();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 xe(`lastAgentTs_${t.jid}`);e&&this.lastAgentTimestamp.set(t.jid,e)}await this.ensureGlobalMemory(),this.scheduler=new W8({onTaskRun:async(e,t)=>{Z8.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(),Z8.info(`Orchestrator initialized`,{scoopCount:this.scoops.size});for(let e of this.scoops.values())await this.createScoopTab(e.jid);x4(()=>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 C8(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{Z8.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,Z8.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))}}async 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=this.completionWaiters.get(e);if(r&&r.length>0){this.completionWaiters.delete(e);let t=n.length>2e4?n.slice(0,2e4)+`
|
|
15834
|
+
... (truncated)`:n;for(let n of r)try{n(t)}catch(t){Z8.warn(`completion waiter threw`,{jid:e,error:t instanceof Error?t.message:String(t)})}return}if(this.mutedScoops.has(e)){this.pendingCompletions.set(e,{responseText:n,timestamp:new Date().toISOString()}),Z8.info(`Scoop completion stashed (muted)`,{scoop:t.folder,responseLength:n.length});return}await this.deliverCompletionToCone(t,n)}async deliverCompletionToCone(e,t){let n=Array.from(this.scoops.values()).find(e=>e.isCone);if(!n)return;let r=n5(t),i=t.slice(0,t5),a,o=null,s=null;try{s=await this.writeScoopCompletionArtifact(e,t),Z8.info(`Routing scoop completion to cone`,{scoop:e.folder,responseLength:t.length,lineCount:r,notificationPath:s})}catch(t){o=t instanceof Error?t.message:String(t),Z8.warn(`Failed to persist scoop completion artifact, falling back to inline preview`,{scoop:e.folder,error:o})}a=o===null?this.formatScoopCompletionNotification(e.assistantLabel,s??`unavailable`,r,i):this.formatScoopCompletionFallbackNotification(e.assistantLabel,r,i,o);let c={id:`scoop-done-${e.jid}-${Date.now()}`,chatJid:n.jid,senderId:e.folder,senderName:e.assistantLabel,content:a,timestamp:new Date().toISOString(),fromAssistant:!1,channel:`scoop-notify`};try{this.callbacks.onIncomingMessage?.(n.jid,c)}catch(t){Z8.warn(`onIncomingMessage for scoop-notify threw`,{scoop:e.folder,error:t instanceof Error?t.message:String(t)})}try{await this.handleMessage(c)}catch(t){let r=t instanceof Error?t.message:String(t);Z8.error(`Failed to route scoop completion to cone`,{scoop:e.folder,error:r}),this.callbacks.onError(n.jid,`Scoop ${e.folder} completed but notification failed: ${r}`)}}async writeScoopCompletionArtifact(e,t){if(!this.sharedFs)throw Error(`Shared filesystem not initialized`);await this.sharedFs.mkdir($8,{recursive:!0}),await this.pruneScoopCompletionArtifacts(e5-1);let n=new Date().toISOString().replace(/[:.]/g,`-`),r=Math.random().toString(36).slice(2,8),i=`${$8}/${n}-${e.folder}-${r}.md`;return await this.sharedFs.writeFile(i,t),await this.pruneScoopCompletionArtifacts(),i}async pruneScoopCompletionArtifacts(e=e5){if(!this.sharedFs)return;let t;try{t=await this.sharedFs.readDir($8)}catch{return}let n=t.filter(e=>e.type===`file`).map(e=>e.name).sort(),r=n.length-e;if(!(r<=0))for(let e of n.slice(0,r)){let t=`${$8}/${e}`;try{await this.sharedFs.rm(t)}catch(e){Z8.warn(`Failed to prune scoop completion artifact`,{path:t,error:e instanceof Error?e.message:String(e)})}}}formatScoopCompletionNotification(e,t,n,r){return[`[@${e} completed]`,`VFS path: ${t}`,`Total lines: ${n}`,`Preview (up to ${t5} chars):`,r].join(`
|
|
15835
|
+
`)}formatScoopCompletionFallbackNotification(e,t,n,r){return[`[@${e} completed]`,`VFS path: unavailable`,`Artifact persistence error: ${r}`,`Total lines: ${t}`,`Preview (up to ${t5} chars):`,n].join(`
|
|
15836
|
+
`)}muteScoops(e){for(let t of e)this.mutedScoops.add(t);Z8.info(`Scoops muted`,{count:e.length})}async unmuteScoops(e){let t=[],n=[];for(let r of e){this.mutedScoops.delete(r);let e=this.pendingCompletions.get(r);if(!e)continue;this.pendingCompletions.delete(r);let i=this.scoops.get(r);if(!i||i.isCone)continue;let a={jid:r,summary:e.responseText.length>2e4?e.responseText.slice(0,2e4)+`
|
|
15837
|
+
... (truncated)`:e.responseText,timestamp:e.timestamp,notificationPath:null};t.push(a),n.push(this.writeScoopCompletionArtifact(i,e.responseText).then(e=>{a.notificationPath=e}).catch(e=>{Z8.warn(`unmute artifact persist failed`,{jid:r,error:e instanceof Error?e.message:String(e)})}))}return await Promise.all(n),Z8.info(`Scoops unmuted`,{count:e.length,consumed:t.length}),t}isScoopMuted(e){return this.mutedScoops.has(e)}async waitForScoops(e,t){if(e.length===0)return[];let n=Array.from(new Set(e)),r=new Map,i=[];for(let e of n)this.mutedScoops.has(e)||(this.mutedScoops.add(e),i.push(e));for(let e of n){let t=this.pendingCompletions.get(e);if(t){this.pendingCompletions.delete(e);let n=t.responseText.length>2e4?t.responseText.slice(0,2e4)+`
|
|
15838
|
+
... (truncated)`:t.responseText;r.set(e,{summary:n,timedOut:!1})}}let a=n.filter(e=>!r.has(e)),o=a.filter(e=>this.scoops.has(e)),s=a.filter(e=>!this.scoops.has(e));for(let e of s)r.set(e,{summary:null,timedOut:!0});let c=[],l=o.map(e=>new Promise(t=>{let n=n=>{r.has(e)||(r.set(e,{summary:n,timedOut:n===null}),t())};c.push({jid:e,waiter:n});let i=this.completionWaiters.get(e);i||(i=[],this.completionWaiters.set(e,i)),i.push(n)})),u=null;try{l.length>0&&(t!=null&&t>=0?await Promise.race([Promise.all(l),new Promise(e=>{u=setTimeout(()=>e(),t)})]):await Promise.all(l))}finally{u&&clearTimeout(u);for(let{jid:e,waiter:t}of c){let n=this.completionWaiters.get(e);if(!n)continue;let r=n.indexOf(t);r!==-1&&n.splice(r,1),n.length===0&&this.completionWaiters.delete(e)}for(let e of i)this.mutedScoops.delete(e)}for(let e of o)r.has(e)||r.set(e,{summary:null,timedOut:!0});return e.map(e=>{let t=r.get(e)??{summary:null,timedOut:!0};return{jid:e,summary:t.summary,timedOut:t.timedOut}})}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){Z8.warn(`scoop observer threw`,{jid:e,event:t,error:n instanceof Error?n.message:String(n)})}}}async registerScoop(e){await Te(e),this.scoops.set(e.jid,e),this.messageQueues.set(e.jid,[]),Z8.info(`Scoop registered`,{jid:e.jid,name:e.name});try{await this.createScoopTab(e.jid)}catch(t){throw Z8.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 ge(e.jid).catch(t=>{Z8.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=J8(t.folder,e,n);if(r)throw r}this.snapshotScoopCost(e),this.clearIdleTimer(e),await this.destroyScoopTab(e),this.sessionStore?.delete(e).catch(t=>{Z8.warn(`Failed to delete agent session`,{jid:e,error:t instanceof Error?t.message:String(t)})}),await ge(e),this.scoops.delete(e),this.messageQueues.delete(e),this.lastAgentTimestamp.delete(e),this.scoopResponseBuffer.delete(e),this.scoopObservers.delete(e);let n=this.completionWaiters.get(e);if(n){this.completionWaiters.delete(e);for(let t of n)try{t(null)}catch(t){Z8.warn(`completion waiter threw on unregister`,{jid:e,error:t instanceof Error?t.message:String(t)})}}this.mutedScoops.delete(e),this.pendingCompletions.delete(e),Z8.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 ne.create({dbName:`slicc-fs`,wipe:!0}),this.fsWatcher&&this.sharedFs.setWatcher(this.fsWatcher),await this.ensureRootStructure(),await this.ensureGlobalMemory(),await S8(this.sharedFs).catch(e=>{Z8.warn(`Failed to re-seed default skills`,{error:e instanceof Error?e.message:String(e)})}),this.droppedScoopCosts=[],Z8.info(`Filesystem reset and defaults re-seeded`)}async clearAllMessages(){await Ce(),this.sessionStore&&await this.sessionStore.clearAll().catch(e=>{Z8.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=[],Z8.info(`All messages cleared`)}async handleMessage(e){Z8.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);g6(t?.isCone?`cone`:t?.name??`unknown`,localStorage.getItem(`selected-model`)??`unknown`),await le(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 le(i),this.callbacks.onIncomingMessage?.(e,i),Z8.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);Z8.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){Z8.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)){Z8.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(Z8.debug(`routeToScoop: queued`,{chatJid:e.chatJid,scoopName:t.name,tabStatus:i?.status??`no-tab`,queueLength:r.length}),i?.status===`error`){Z8.info(`routeToScoop: tab in error state, retrying init`,{chatJid:e.chatJid});try{await this.createScoopTab(e.chatJid),i=this.tabs.get(e.chatJid)}catch{Z8.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`)Z8.info(`Re-creating context after error`,{jid:e}),this.contexts.get(e)?.dispose(),this.contexts.delete(e),this.tabs.delete(e);else{Z8.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 ie(this.sharedFs,t.config?.writablePaths?[...t.config.writablePaths]:[],t.config?.visiblePaths?[...t.config.visiblePaths]:[]),i={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`)},onFatalError:t=>{if(!this.scoops.has(e))return;let n=this.scoops.get(e);Z8.error(`Fatal scoop error`,{jid:e,folder:n.folder,error:t});let r=this.tabs.get(e);if(r&&(r.status=`error`,r.error=t,this.tabs.set(e,r)),this.callbacks.onError(e,t),this.callbacks.onStatusChange(e,`error`),this.dispatchScoopEvent(e,`onError`,t),this.dispatchScoopEvent(e,`onStatusChange`,`error`),n.isCone)return;this.mutedScoops.delete(e),this.pendingCompletions.delete(e),this.scoopResponseBuffer.delete(e);let i=this.completionWaiters.get(e);if(i&&i.length>0){this.completionWaiters.delete(e);for(let t of i)try{t(null)}catch(t){Z8.warn(`completion waiter threw on fatal error`,{jid:e,error:t instanceof Error?t.message:String(t)})}}let a=Array.from(this.scoops.values()).find(e=>e.isCone);if(!a)return;let o={id:`scoop-error-${e}-${Date.now()}`,chatJid:a.jid,senderId:n.folder,senderName:n.assistantLabel,content:`[@${n.assistantLabel} FAILED]: ${t}`,timestamp:new Date().toISOString(),fromAssistant:!1,channel:`scoop-error`};try{this.callbacks.onIncomingMessage?.(a.jid,o)}catch(e){Z8.warn(`onIncomingMessage for scoop-error threw`,{scoop:n.folder,error:e instanceof Error?e.message:String(e)})}this.handleMessage(o).catch(e=>{Z8.error(`Failed to route fatal error to cone`,{scoop:n.folder,error:e instanceof Error?e.message:String(e)})})},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,onMuteScoops:t.isCone?e=>this.muteScoops(e):void 0,onUnmuteScoops:t.isCone?e=>this.unmuteScoops(e):void 0,onWaitForScoops:t.isCone?(e,t)=>this.waitForScoops(e,t):void 0,getGlobalMemory:()=>this.getGlobalMemory(),setGlobalMemory:t.isCone?e=>this.setGlobalMemory(e):void 0,getBrowserAPI:()=>this.callbacks.getBrowserAPI()},a=Array.from(this.scoops.values()).find(e=>e.isCone)?.jid,o=new H8(t,i,r,this.sessionStore??void 0,this.sharedFs??void 0,a);this.contexts.set(e,o),this.tabs.set(e,{jid:e,contextId:n,status:`initializing`,lastActivity:new Date().toISOString()}),await o.init();let s=this.tabs.get(e);s&&s.status===`initializing`&&(s.status=`ready`,this.tabs.set(e,s),this.callbacks.onStatusChange(e,`ready`),this.dispatchScoopEvent(e,`onStatusChange`,`ready`));let c=this.scoops.get(e);c&&!c.isCone&&this.startIdleTimer(e),Z8.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),Z8.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 j(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 j(t)}async getMessagesForScoop(e){return A(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 Z8.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(Z8.debug(`Context initializing, waiting to send message`,{jid:e}),!await this.waitForTabReady(e)){Z8.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){Z8.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`)),Z8.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){Z8.debug(`processScoopQueue: empty queue`,{jid:e});return}let n=this.tabs.get(e);if(n?.status!==`ready`){Z8.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 pe(e,a,i);if(Z8.debug(`processScoopQueue: DB query`,{jid:e,scoopName:r?.name,excludeName:i,since:a,dbMessageCount:o.length,queueLength:t.length}),o.length===0){Z8.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(`
|
|
15839
|
+
`);this.messageQueues.set(e,[]);let c=o[o.length-1];this.lastAgentTimestamp.set(e,c.timestamp),await Ee(`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);Z8.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();Z8.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=>{Z8.warn(`Failed to reload skills for scoop`,{jid:t,error:e instanceof Error?e.message:String(e)})}))}await Promise.all(e),Z8.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`};Z8.info(`Scoop idle timeout`,{jid:e,scoop:t.folder});try{this.callbacks.onIncomingMessage?.(n.jid,r)}catch(t){Z8.warn(`onIncomingMessage for scoop-idle threw`,{jid:e,error:t instanceof Error?t.message:String(t)})}this.handleMessage(r).catch(t=>{let n=t instanceof Error?t.message:String(t);Z8.error(`Failed to send idle notification`,{jid:e,error:n})})},Q8);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.completionWaiters.values())for(let t of e)try{t(null)}catch(e){Z8.warn(`completion waiter threw during shutdown`,{error:e instanceof Error?e.message:String(e)})}this.completionWaiters.clear(),this.mutedScoops.clear(),this.pendingCompletions.clear();for(let e of this.contexts.keys())await this.destroyScoopTab(e);Z8.info(`Orchestrator shutdown`)}};i(`heartbeat`);var i5=i(`tray-follower`);function a5(e){let t=new URL(e);return t.searchParams.set(`json`,`true`),t.toString()}async function o5(e){let t=a5(e.joinUrl),n=await p5(await(e.fetchImpl??fetch)(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({controllerId:e.controllerId,runtime:e.runtime})}));return i5.info(`Follower tray attach response`,{trayId:n.trayId,action:n.result.action,code:n.result.code,participantCount:n.participantCount}),s5(n)}function s5(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 c5(e){return f5(await m5(e,{action:`poll`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,cursor:e.cursor}))}async function l5(e){return f5(await m5(e,{action:`answer`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,answer:e.answer}))}async function u5(e){return f5(await m5(e,{action:`ice-candidate`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,candidate:e.candidate}))}async function d5(e){return f5(await m5(e,{action:`retry`,controllerId:e.controllerId,bootstrapId:e.bootstrapId,runtime:e.runtime}))}function f5(e){return{trayId:e.trayId,controllerId:e.controllerId,participantCount:e.participantCount,leader:e.leader,bootstrap:e.bootstrap,events:e.events}}async function p5(e){let t=null,n=null;try{t=await e.text(),n=JSON.parse(t)}catch{}if(!h5(n)){let n=t?t.slice(0,200):`(empty)`;throw i5.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 m5(e,t){let n=a5(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(!g5(i))throw Error(`Tray follower bootstrap returned an invalid response (${r.status})`);return i}function h5(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`&&_5(r.bootstrap):r.action===`fail`?(r.code===`INVALID_JOIN_CAPABILITY`||r.code===`TRAY_EXPIRED`)&&typeof r.error==`string`:!1}function g5(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`&&_5(t.bootstrap)&&Array.isArray(t.events)}function _5(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 v5=n({AGENT_BRIDGE_GLOBAL_KEY:()=>b5,AGENT_SPAWN_REQUEST_TYPE:()=>x5,createAgentBridge:()=>S5,publishAgentBridge:()=>C5,publishAgentBridgeProxy:()=>w5}),y5=i(`agent-bridge`),b5=`__slicc_agent`,x5=`agent-spawn-request`;function S5(e,t,n=null,r={}){let i=r.generateName??O5,a=r.generateUid??T5,o=r.resolveModel??A5;function s(){for(let t=0;t<8;t++){let t=i(),n=`agent_${k5(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_${k5(l)}`,f=`/scoops/${u}`,p=j5(r.cwd),m={visiblePaths:M5(r),writablePaths:N5([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??P5(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??P5(e),exitCode:1}}finally{y();try{await e.unregisterScoop(d)}catch(e){y5.warn(`unregisterScoop failed`,{jid:d,error:P5(e)})}try{await t.rm(f,{recursive:!0})}catch(e){F5(e,`ENOENT`)||y5.warn(`scratch folder cleanup failed`,{folder:u,error:P5(e)})}if(n)try{await n.delete(d)}catch(e){y5.warn(`sessionStore.delete failed`,{jid:d,error:P5(e)})}}}return{spawn:l}}function C5(e,t,n=null,r={}){let i=S5(e,t,n,r);return globalThis[b5]=i,y5.info(`agent bridge published on globalThis.__slicc_agent`),i}function w5(){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:x5,options:e}},i)}catch(e){n(e instanceof Error?e:Error(String(e)))}})}};return globalThis[b5]=e,y5.info(`agent bridge proxy published on globalThis.__slicc_agent`),e}function T5(){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 E5=`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(`.`),D5=`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 O5(){return`${E5[Math.floor(Math.random()*E5.length)]}-${D5[Math.floor(Math.random()*D5.length)]}`}function k5(e){return e.replace(/-/g,`_`)}function A5(e){try{let t=p();for(let n of t)if(n.models.some(t=>t.id===e))return e;return null}catch{return null}}function j5(e){let t=ae(e);return t.endsWith(`/`)?t:`${t}/`}function M5(e){if(e.visiblePaths!==void 0)return e.visiblePaths.map(j5);let t=[`/workspace/`];return e.invokingCwd&&e.invokingCwd.length>0&&t.push(j5(e.invokingCwd)),N5(t)}function N5(e){let t=new Set,n=[];for(let r of e)t.has(r)||(t.add(r),n.push(r));return n}function P5(e){return e instanceof Error?e.message:String(e)}function F5(e,t){if(typeof e!=`object`||!e)return!1;let n=e.code;return typeof n==`string`&&n===t}var I5=i(`tray-webrtc`),L5=`tray-control`,R5=250,z5=class{peerConnectionFactory;dataChannelLabel;peers=new Map;iceServers;constructor(e){this.options=e,this.iceServers=e.iceServers,this.peerConnectionFactory=e.peerConnectionFactory??(()=>H5(this.iceServers)),this.dataChannelLabel=e.dataChannelLabel??L5}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=W5(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`)&&(I5.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`?(I5.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`?(I5.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:U5(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){I5.warn(`Failed to report tray bootstrap failure`,{error:e instanceof Error?e.message:String(e)})}}}},B5=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??(()=>H5(this.iceServers)),this.controllerIdFactory=e.controllerIdFactory??(()=>crypto.randomUUID()),this.sleep=e.sleep??(e=>new Promise(t=>setTimeout(t,e))),this.pollIntervalMs=e.pollIntervalMs??R5}async start(){this.stopped=!1;let e=this.controllerIdFactory(),t=Date.now();vo({state:`connecting`,joinUrl:this.options.joinUrl,trayId:null,error:null,lastPingTime:null,reconnectAttempts:0,attachAttempts:0,lastAttachCode:null,connectingSince:t,lastError:null}),I5.info(`Follower tray join starting`,{joinUrl:this.options.joinUrl});let n=0;for(;;){G5(this.stopped),n++;let t;try{t=await o5({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 vo({..._o(),attachAttempts:n,lastError:t}),e}if(vo({..._o(),attachAttempts:n,lastAttachCode:t.code}),t.action===`wait`){let e=t.retryAfterMs??1e3;I5.info(`Follower tray attach waiting`,{attempt:n,code:t.code,retryAfterMs:e}),n%10==0&&I5.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 vo({state:`error`,joinUrl:this.options.joinUrl,trayId:null,error:e,lastPingTime:null,reconnectAttempts:0,attachAttempts:n,lastAttachCode:t.code,connectingSince:null,lastError:e}),I5.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 vo({state:`connected`,joinUrl:this.options.joinUrl,trayId:r.trayId,error:null,lastPingTime:null,reconnectAttempts:0,attachAttempts:n,lastAttachCode:t.code,connectingSince:null,lastError:null}),I5.info(`Follower tray connected`,{trayId:r.trayId,controllerId:e}),r}catch(e){let r=e instanceof Error?e.message:String(e);throw vo({state:`error`,joinUrl:this.options.joinUrl,trayId:t.trayId,error:r,lastPingTime:null,reconnectAttempts:0,attachAttempts:n,lastAttachCode:t.code,connectingSince:null,lastError:r}),I5.warn(`Follower tray bootstrap failed`,{error:r}),e}}}stop(){this.stopped=!0,this.activePeer?.peer.close(),this.activePeer?.channel?.close(),this.activePeer=null,vo({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(G5(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 c5({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 l5({joinUrl:this.options.joinUrl,controllerId:t,bootstrapId:r.bootstrapId,answer:U5(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 d5({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`)&&(I5.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?(I5.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?(I5.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=W5(n);r&&u5({joinUrl:this.options.joinUrl,controllerId:e,bootstrapId:t,candidate:r,fetchImpl:this.fetchImpl}).catch(e=>{I5.warn(`Failed to send follower ICE candidate`,{error:e instanceof Error?e.message:String(e)})})}),r}};function V5(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 B5({...e,sleep:o,onDisconnected:e=>{s||(I5.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,m=u??`Unknown disconnect`;for(;!s&&f<a&&(f++,t.onReconnecting?.(f),vo({..._o(),state:`reconnecting`,error:null,reconnectAttempts:f}),I5.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,vo({..._o(),state:`connected`,joinUrl:e.joinUrl,trayId:i.trayId,error:null,lastPingTime:null,reconnectAttempts:0,connectingSince:null,lastError:null}),I5.info(`Reconnect successful`,{attempt:f,trayId:i.trayId}),t.onConnected(i);return}catch(e){m=e instanceof Error?e.message:String(e),I5.warn(`Reconnect attempt failed`,{attempt:f,error:m}),n?.stop(),l=null}p=Math.min(p*r,i)}s||(c=!1,vo({..._o(),state:`error`,error:`Reconnect failed after ${f} attempts: ${m}`,reconnectAttempts:f}),I5.warn(`Reconnect gave up`,{attempts:f,lastError:m}),t.onGaveUp?.(m))},{connectionPromise:p}=d();return p.then(e=>{s||t.onConnected(e)}).catch(e=>{s||I5.warn(`Initial follower connection failed`,{error:e instanceof Error?e.message:String(e)})}),u}function H5(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 U5(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 W5(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 G5(e){if(e)throw Error(`Tray follower stopped before WebRTC bootstrap completed`)}var K5=64*1024;async function q5(e,t){try{switch(t.op){case`readFile`:return await J5(e,t.path,t.encoding);case`writeFile`:return[await Y5(e,t.path,t.content,t.encoding)];case`stat`:return[await X5(e,t.path)];case`readDir`:return[await Z5(e,t.path)];case`mkdir`:return[await Q5(e,t.path,t.recursive)];case`rm`:return[await $5(e,t.path,t.recursive)];case`exists`:return[await e7(e,t.path)];case`walk`:return[await t7(e,t.path)];default:return[{ok:!1,error:`Unknown fs operation: ${t.op}`}]}}catch(e){return[r7(e)]}}async function J5(e,t,n){return(n??`utf-8`)===`utf-8`?n7(await e.readFile(t,{encoding:`utf-8`}),`utf-8`):n7(i7(await e.readFile(t,{encoding:`binary`})),`base64`)}async function Y5(e,t,n,r){if(r===`base64`){let r=a7(n);await e.writeFile(t,r)}else await e.writeFile(t,n);return{ok:!0,data:{type:`void`}}}async function X5(e,t){return{ok:!0,data:{type:`stat`,stat:await e.stat(t)}}}async function Z5(e,t){return{ok:!0,data:{type:`dirEntries`,entries:await e.readDir(t)}}}async function Q5(e,t,n){return await e.mkdir(t,{recursive:n}),{ok:!0,data:{type:`void`}}}async function $5(e,t,n){return await e.rm(t,{recursive:n}),{ok:!0,data:{type:`void`}}}async function e7(e,t){return{ok:!0,data:{type:`exists`,exists:await e.exists(t)}}}async function t7(e,t){let n=[];for await(let r of e.walk(t))n.push(r);return{ok:!0,data:{type:`paths`,paths:n}}}function n7(e,t){if(e.length<=K5)return[{ok:!0,data:{type:`file`,content:e,encoding:t}}];let n=Math.ceil(e.length/K5),r=[];for(let i=0;i<n;i++){let a=i*K5,o=e.slice(a,a+K5);r.push({ok:!0,data:{type:`file`,content:o,encoding:t},chunkIndex:i,totalChunks:n})}return r}function r7(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 i7(e){let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function a7(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 o7=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()]}},s7=i(`data-channel-keepalive`),c7=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++,s7.debug(`Missed pong`,{missedPongs:this.missedPongs,maxMissed:this.maxMissed}),this.missedPongs>=this.maxMissed)){s7.warn(`Channel declared dead`,{missedPongs:this.missedPongs}),this.stop(),this.onDead();return}this.awaitingPong=!0,this.sendPing()}}},l7=i(`tray-leader-sync`);function u7(e){return e?e.includes(`standalone`)?`standalone`:e.includes(`extension`)?`extension`:e.includes(`electron`)?`electron`:`unknown`:`unknown`}var d7=class{followers=new Map;registry=new o7;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=Ps(t),i=r.onMessage(t=>{this.handleFollowerMessage(e,t)}),a=new c7({sendPing:()=>r.send({type:`ping`}),onDead:()=>{l7.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:u7(n?.runtime)}),l7.info(`Follower added to sync`,{bootstrapId:e,followerCount:this.followers.size}),this.options.onFollowerCountChanged?.(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(),l7.info(`Follower removed from sync`,{bootstrapId:e,followerCount:this.followers.size}),this.options.onFollowerCountChanged?.(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();js(t.sync,n,r),l7.debug(`Snapshot sent to follower`,{bootstrapId:e,messageCount:n.length})}handleFollowerMessage(e,t){switch(t.type){case`user_message`:l7.info(`Follower user message received`,{bootstrapId:e,messageId:t.messageId}),this.options.onFollowerMessage(t.text,t.messageId);break;case`abort`:l7.info(`Follower abort received`,{bootstrapId:e}),this.options.onFollowerAbort();break;case`request_snapshot`:l7.info(`Follower snapshot request received`,{bootstrapId:e}),this.sendSnapshotToFollower(e);break;case`targets.advertise`:l7.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),l7.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 Is({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),l7.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);Os(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=ks(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&&Os(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 q5(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?q5(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})})}},f7=i(`tray-follower-sync`),p7=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=Fs(e),this.unsubscribe=this.sync.onMessage(e=>{this.handleLeaderMessage(e)}),this.keepalive=new c7({sendPing:()=>this.sync.send({type:`ping`}),onDead:()=>{f7.warn(`Leader keepalive dead, cleaning up`),this.handleDisconnect(`Keepalive timeout — leader not responding`),this.options.onDead?.()}}),this.keepalive.start(),e.addEventListener(`close`,()=>{f7.warn(`Data channel closed`),this.handleDisconnect(`Data channel closed`)}),e.addEventListener(`error`,()=>{f7.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}),f7.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`}),f7.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(),f7.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,vo({..._o(),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`:f7.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=Ms(this.snapshotChunkBuffer,e);this.snapshotChunkBuffer=t.buffer,t.result&&(f7.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),f7.debug(`Skipping own message echo`,{messageId:e.messageId});break}f7.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`:f7.warn(`Error from leader`,{error:e.error}),this.emitEvent({type:`error`,error:e.error});break;case`targets.registry`:f7.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(),yo(Date.now());break}}emitEvent(e){for(let t of this.eventListeners)try{t(e)}catch(t){f7.error(`Listener error`,{eventType:e.type,error:t instanceof Error?t.message:String(t)})}}createRemoteTransport(e,t){let n=new Is({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),f7.debug(`Tracking remote CDP session`,{remoteSessionId:e})}n===`Target.detachFromTarget`&&i&&this.remoteCDPSessions.has(i)&&(this.remoteCDPSessions.delete(i),f7.debug(`Removed remote CDP session on detach`,{sessionId:i})),Os(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=ks(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 q5(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})})}},m7=i(`tab-persistence-guard`),h7=`slicc-tray-leader-active`,g7=class{active=!1;audioCtx=null;oscillator=null;lockController=null;beforeUnloadHandler=null;constructor(e={}){this.options=e}activate(){this.active||(this.active=!0,this.startSilentAudio(),this.acquireWebLock(),this.installBeforeUnload(),m7.info(`Tab persistence guard activated`))}deactivate(){this.active&&(this.active=!1,this.stopSilentAudio(),this.releaseWebLock(),this.removeBeforeUnload(),m7.info(`Tab persistence guard deactivated`))}isActive(){return this.active}startSilentAudio(){try{let e=(this.options.audioContextFactory??(()=>{let e=typeof globalThis<`u`?globalThis.AudioContext??globalThis.webkitAudioContext:void 0;return e?new e:null}))();if(!e){m7.warn(`AudioContext unavailable — discard prevention via silent audio disabled`);return}e.resume?.().catch(()=>{});let t=e.createOscillator(),n=e.createGain();n.gain.value=0,t.connect(n),n.connect(e.destination),t.start(),this.audioCtx=e,this.oscillator=t}catch(e){m7.warn(`Failed to start silent audio guard`,{error:e instanceof Error?e.message:String(e)})}}stopSilentAudio(){try{this.oscillator?.stop()}catch{}this.oscillator=null,this.audioCtx&&=(this.audioCtx.close?.().catch(()=>{}),null)}acquireWebLock(){try{let e=this.options.lockManager??(typeof navigator<`u`&&`locks`in navigator?navigator.locks:null);if(!e){m7.warn(`navigator.locks unavailable — discard prevention via Web Lock disabled`);return}let t=new AbortController;this.lockController=t,e.request(h7,{mode:`exclusive`,signal:t.signal},()=>new Promise(e=>{if(t.signal.aborted){e();return}let n=()=>{t.signal.removeEventListener(`abort`,n),e()};t.signal.addEventListener(`abort`,n,{once:!0})})).catch(e=>{e?.name!==`AbortError`&&m7.warn(`Web Lock request rejected`,{error:e instanceof Error?e.message:String(e)})})}catch(e){m7.warn(`Failed to acquire Web Lock`,{error:e instanceof Error?e.message:String(e)})}}releaseWebLock(){try{this.lockController?.abort()}catch{}this.lockController=null}installBeforeUnload(){try{let e=this.options.windowRef??(typeof window<`u`?window:null);if(!e)return;let t=()=>{};e.addEventListener(`beforeunload`,t),this.beforeUnloadHandler=t}catch{}}removeBeforeUnload(){try{let e=this.options.windowRef??(typeof window<`u`?window:null);e&&this.beforeUnloadHandler&&e.removeEventListener(`beforeunload`,this.beforeUnloadHandler)}catch{}this.beforeUnloadHandler=null}};function _7(e,t){if(t)return`extension`;try{return b7(new URL(e))?`electron-overlay`:`standalone`}catch{return`standalone`}}function v7(e,t){return e===`electron-overlay`||e===`standalone`&&t}function y7(e){try{let t=new URL(e).searchParams.get(`tab`);return t&&Go(t)?t:Uo}catch{return Uo}}function b7(e){return e.pathname===`/electron`||e.pathname===`/electron/`||e.searchParams.get(`runtime`)===`electron-overlay`}function x7(e){let t=new URL(e);return`${t.protocol===`https:`?`wss:`:`ws:`}//${t.host}/licks-ws`}function S7(e,t){return`${new URL(e).origin}/webhooks/${t}`}function C7(e,t){return`${e.replace(/\/+$/,``)}/${t.replace(/^\/+/,``)}`}function w7(e){return typeof e==`object`&&!!e&&`type`in e&&e.type===`slicc-electron-overlay:set-tab`}var T7=[`/shared/sprinkles`];async function E7(e){let t=new Map;for(let n of T7)await e.exists(n)&&await D7(e,n,t);return await D7(e,`/`,t),t}async function D7(e,t,n){for await(let r of e.walk(t)){if(!r.endsWith(`.shtml`))continue;let t=O7(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:k7(i,t),autoOpen:A7(i)})}}}function O7(e){let t=e.split(`/`).pop()??e;return t.endsWith(`.shtml`)?t.slice(0,-6):t}function k7(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 A7(e){return/data-sprinkle-autoopen\b/.test(e)}var j7=i(`sprinkle-manager`),M7=`slicc-open-sprinkles`,N7=class{fs;bridge;callbacks;availableSprinkles=new Map;watcherUnsub;openSprinkles=new Map;constructor(e,t,n,r){this.fs=e,this.bridge=new H0(e,t,e=>this.close(e),r),this.callbacks=n}async restoreOpenSprinkles(){try{let e=localStorage.getItem(M7);if(!e){for(let e of this.availableSprinkles.values())if(e.autoOpen)try{await this.open(e.name)}catch{j7.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{j7.warn(`Failed to restore sprinkle`,{name:e})}}catch{}}persistOpenSprinkles(){try{localStorage.setItem(M7,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),j7.info(`Auto-opened new sprinkle after install`,{name:e.name})}catch{j7.warn(`Failed to auto-open new sprinkle`,{name:e.name})}}async refresh(){this.availableSprinkles=await E7(this.fs),j7.info(`Discovered sprinkles`,{count:this.availableSprinkles.size})}async open(e,t){if(this.openSprinkles.has(e)){j7.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 Zr(a,this.bridge.createAPI(e));await o.render(i,e),this.openSprinkles.get(e).renderer=o,this.persistOpenSprinkles(),v6(e),j7.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(),j7.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){j7.warn(`Cannot send to closed sprinkle`,{name:e});return}this.bridge.pushUpdate(e,t),n.renderer.pushUpdate(t)}};async function P7(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 F7(e){return`'${e.replace(/'/g,`'\\''`)}'`}function I7(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 L7(e){if(!Array.isArray(e)||e.length===0)return null;let t=e.map(({path:e,dirName:t})=>{let n=t?` (previously mounted from ${I7(t)})`:``;return`- ${I7(e)}${n}`}),n=e.map(({path:e})=>` mount ${F7(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(`
|
|
15840
|
+
`)}var $=i(`main`),R7=`slicc-pending-mount`,z7=`pendingMount`;function B7(){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 V7(e){let[{createChatFixture:t,FIXTURE_SESSION_ID:n,FIXTURE_SCOOP_NAME:r}]=await Promise.all([a(()=>import(`./chat-fixture-CIjL7BDw.js`),[])]);await e.switchToContext(n,!0,r),e.loadMessages(t()),$.info(`Loaded UI fixture session for design iteration`)}async function H7(e){let t=await new Promise((e,t)=>{let n=indexedDB.open(R7,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,z7),await new Promise(e=>n.oncomplete=()=>e()),t.close()}async function U7(e){let t;try{t=await new Promise((e,t)=>{let n=indexedDB.open(R7,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(z7);t.onsuccess=()=>e(t.result),t.onerror=()=>e(void 0)});if(r){n.objectStore(`handles`).delete(z7),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 W7(){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 G7(){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 K7(e,t,n){let r=W7(),i=0,a=!1,o=()=>{i=0,a||r.hide()};window.addEventListener(`dragenter`,e=>{ss(e.dataTransfer)&&(e.preventDefault(),i+=1,a||r.show(`Drop .skill to install`,`Unpack into /workspace/skills/{name}.`))}),window.addEventListener(`dragover`,e=>{ss(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=cs(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 ce(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 q7(e){let{OffscreenClient:t}=await a(async()=>{let{OffscreenClient:e}=await import(`./offscreen-client-Dom7iV01.js`);return{OffscreenClient:e}},__vite__mapDeps([19,13])),{VirtualFS:n}=await a(async()=>{let{VirtualFS:e}=await import(`./fs-CuJwg7sR.js`).then(e=>e.t);return{VirtualFS:e}},__vite__mapDeps([15,4,13,16])),{publishAgentBridgeProxy:r}=await a(async()=>{let{publishAgentBridgeProxy:e}=await Promise.resolve().then(()=>v5);return{publishAgentBridgeProxy:e}},void 0),i=new Xo(e,!0);window.__slicc_debug_tabs=e=>i.setDebugTabs(e),await i.panels.chat.initSession(`session-cone`),r();let o=null,s=await n.create({dbName:`slicc-fs`});i.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})}})()},K7(s,G7(),async()=>{await i.panels.fileBrowser.refresh()});try{let{WasmShell:e}=await a(async()=>{let{WasmShell:e}=await Promise.resolve().then(()=>k6);return{WasmShell:e}},void 0),{PanelCdpProxy:t,BrowserAPI:n}=await a(async()=>{let{PanelCdpProxy:e,BrowserAPI:t}=await Promise.resolve().then(()=>Ls);return{PanelCdpProxy:e,BrowserAPI:t}},void 0),{fetchSecretEnvVars:r}=await a(async()=>{let{fetchSecretEnvVars:e}=await Promise.resolve().then(()=>P8);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 i.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 a(async()=>{let{registerSessionCostsProvider:e}=await Promise.resolve().then(()=>y4);return{registerSessionCostsProvider:e}},void 0);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 l,u=new Set,d=async e=>{o=e,l.selectedScoopJid=e.jid,i.panels.memory.setSelectedScoop(e.jid),i.setScoopSwitcherSelected?.(e.jid),i.panels.scoops.setSelectedJid(e.jid);let t=e.isCone?`session-cone`:`session-${e.folder}`,n=e.isCone?void 0:e.name;await i.panels.chat.switchToContext(t,!e.isCone,n),l.isProcessing(e.jid)&&i.panels.chat.setProcessing(!0)};l=new t({onStatusChange:(e,t)=>{i.panels.scoops.updateScoopStatus(e,t),i.updateScoopSwitcherStatus?.(e,t),o?.jid===e&&(i.setAgentProcessing(t===`processing`),t===`processing`?i.panels.chat.setProcessing(!0):t===`ready`&&i.panels.chat.setProcessing(!1))},onScoopCreated:e=>{i.panels.scoops.refreshScoops(),i.refreshScoopSwitcher?.(),o||(o=e,l.selectedScoopJid=e.jid,i.panels.memory.setSelectedScoop(e.jid))},onScoopListUpdate:()=>{let e=new Set(l.getScoops().map(e=>e.folder));for(let t of u)e.has(t)||i.panels.chat.deleteSessionById(`session-${t}`);if(u=e,i.panels.scoops.refreshScoops(),i.refreshScoopSwitcher?.(),!o){let e=l.getScoops().find(e=>e.isCone);e&&(o=e,l.selectedScoopJid=e.jid,i.panels.memory.setSelectedScoop(e.jid))}},onIncomingMessage:(e,t)=>{if(Ta(t.channel)){let n=new Date(t.timestamp).getTime(),r=t.channel;if(o?.jid===e)i.panels.chat.addLickMessage(t.id,t.content,r,n);else{let a=l.getScoops().find(t=>t.jid===e),o=a?.isCone?`session-cone`:a?`session-${a.folder}`:`session-${e}`;i.panels.chat.persistLickToSession(o,{id:t.id,content:t.content,channel:r,timestamp:n})}return}if(o?.jid===e){let e=t.channel===`delegation`?`**[Instructions from sliccy]**\n\n${t.content}`:t.content;i.panels.chat.addUserMessage(e)}},onReady:async()=>{try{$.info(`Offscreen engine ready, scoop count:`,l.getScoops().length),window.localStorage.getItem(`slicc.trayJoinUrl`)&&chrome.runtime.sendMessage({source:`panel`,payload:{type:`refresh-tray-runtime`}}).catch(()=>{});let e=o??l.getScoops().find(e=>e.isCone)??l.getScoops()[0];e&&(o=e,l.selectedScoopJid=e.jid,await d(e))}catch(e){$.error(`Failed to initialize on ready`,{error:e instanceof Error?e.message:String(e)})}}}),l.setLocalFS(s);let f=l.createAgentHandle();i.panels.chat.setAgent(f),i.panels.scoops.setOrchestrator(l),i.panels.memory.setOrchestrator(l),i.setScoopSwitcherOrchestrator?.(l),i.onScoopSelect=d,i.onModelChange=e=>{localStorage.setItem(`selected-model`,e),l.updateModel()},i.onClearChat=async()=>{let e=l.getScoops();for(let t of e){let e=t.isCone?`session-cone`:`session-${t.folder}`;await i.panels.chat.deleteSessionById(e)}l.clearAllMessages()},i.onClearFilesystem=async()=>{l.clearFilesystem()},i.panels.chat.onInlineSprinkleLick=(e,t)=>{l.sendSprinkleLick(`inline`,{action:e,data:t})};let p=new N7(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`&&p.close(`welcome`),n===`onboarding-complete`&&t?.data?.mountWorkspace&&U7(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 H7(t),p.sendToSprinkle(`welcome`,{action:`mount-complete`,dirName:t.name})}catch(e){e.name!==`AbortError`&&$.warn(`Mount picker failed`,e),p.sendToSprinkle(`welcome`,{action:`mount-cancelled`})}return}l.sendSprinkleLick(e.sprinkleName,e.body,e.targetScoop)}},{addSprinkle:(e,t,n,r)=>i.addSprinkle(e,t,n,r),removeSprinkle:e=>i.removeSprinkle(e)},()=>{let e=l.getScoops().find(e=>e.isCone);e&&l.stopScoop(e.jid)});if(window.__slicc_sprinkleManager=p,window.__slicc_reloadSkills=()=>(chrome.runtime.sendMessage({source:`panel`,payload:{type:`reload-skills`}}),Promise.resolve()),l.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 p.refresh(),e=p.available();break;case`opened`:e=p.opened();break;case`refresh`:await p.refresh(),e=p.available().length;break;case`open`:await p.open(r),e=!0;break;case`close`:p.close(r),e=!0;break;case`send`:p.sendToSprinkle(r,i),e=!0;break;case`openNewAutoOpen`:await p.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 p.refresh(),i.onSprinkleClose=e=>p.close(e),i.getAvailableSprinkles=()=>{let e=new Set(p.opened());return p.available().filter(t=>!e.has(t.name)).map(e=>({name:e.name,title:e.title}))},i.onOpenSprinkle=(e,t)=>p.open(e,t),i.updateAddButtons(),await p.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`)&&!co(window.localStorage)&&p.available().some(e=>e.name===`welcome`))try{await p.open(`welcome`)}catch(e){$.warn(`Failed to open welcome sprinkle`,e)}$.info(`SprinkleManager initialized (extension mode)`),l.requestState(),$.info(`Extension UI connected to offscreen agent engine`),B7()&&await V7(i.panels.chat),h6().catch(()=>{})}function J7(){if(typeof chrome<`u`&&chrome?.runtime?.id)return;let e=new Blob([`
|
|
15841
15841
|
let lastPong = Date.now();
|
|
15842
15842
|
let frozen = false;
|
|
15843
15843
|
setInterval(() => {
|
|
@@ -15857,7 +15857,7 @@ ${t}
|
|
|
15857
15857
|
}
|
|
15858
15858
|
}
|
|
15859
15859
|
};
|
|
15860
|
-
`],{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
|
|
15860
|
+
`],{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 Y7(){J7(),Kr(),is();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)),b();let t=s(),n=co(window.localStorage);if(!t&&!n){let e=window.location.port===`5710`||window.location.port===`3000`;window.location.port===``&&window.location.pathname.includes(`/join/`)?await m({autoJoinUrl:window.location.origin+window.location.pathname}):!e&&window.location.port!==``?await m({preferTrayJoin:!0}):await m(),t=s()}let r=!t&&co(window.localStorage),i=typeof chrome<`u`&&!!chrome?.runtime?.id,o=_7(window.location.href,i);if(o===`extension`)return q7(e);let c=new Xo(e,o===`electron-overlay`);if(o===`electron-overlay`){let e=y7(window.location.href);c.setActiveTab(e);let t=document.createElement(`style`);t.id=`slicc-electron-overlay-runtime-style`,t.textContent=`
|
|
15861
15861
|
#app > .tab-bar { display: none !important; }
|
|
15862
15862
|
#app > .tab-content {
|
|
15863
15863
|
height: calc(100vh - var(--s2-header-height));
|
|
@@ -15865,4 +15865,4 @@ ${t}
|
|
|
15865
15865
|
#app > .tab-content > .tab-content__panel {
|
|
15866
15866
|
height: 100%;
|
|
15867
15867
|
}
|
|
15868
|
-
`,document.head.appendChild(t),window.addEventListener(`message`,e=>{e.source===window.parent&&v7(e.data)&&c.setActiveTab(p7(`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 l=z7();await c.panels.chat.initSession(`session-cone`),$.info(`Session initialized`);let u=new gs,d=new Set,f=e=>{$.debug(`Emit to UI`,{type:e.type,listenerCount:d.size});for(let t of d)try{t(e)}catch(t){$.error(`Listener error`,{eventType:e.type,error:t instanceof Error?t.message:String(t)})}},p=null,h=new Map,g=new Map;function _(){return Date.now().toString(36)+Math.random().toString(36).slice(2,8)}function v(e){let t=g.get(e);return t||(t=[],g.set(e,t)),t}function y(e,t){let n=v(e),r=h.get(e);if(r){let e=n.find(e=>e.id===r);if(e)return e}r=`scoop-${e}-${_()}`,h.set(e,r);let i=x.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),p?.jid===e&&f({type:`message_start`,messageId:r}),o}let x=new Z8(c.getIframeContainer(),{onResponse:(e,t,n)=>{let r=y(e);n?r.content+=t:(r.content=t,r.isStreaming=!1),p?.jid===e&&(f({type:`content_delta`,messageId:r.id,text:t}),n||f({type:`content_done`,messageId:r.id}))},onResponseDone:e=>{let t=v(e),n=h.get(e);if(n){let r=t.find(e=>e.id===n);r&&(r.isStreaming=!1),p?.jid===e&&f({type:`content_done`,messageId:n}),h.delete(e)}},onSendMessage:(e,t)=>{$.debug(`Send message requested`,{targetJid:e,textLength:t.length});let n=`msg-${_()}`,r={id:n,chatJid:e,senderId:`assistant`,senderName:`sliccy`,content:t,timestamp:new Date().toISOString(),fromAssistant:!0,channel:`web`};x.handleMessage(r),v(e).push({id:n,role:`assistant`,content:t,timestamp:Date.now()}),p?.jid===e&&(f({type:`message_start`,messageId:n}),f({type:`content_delta`,messageId:n,text:t}),f({type:`content_done`,messageId:n}))},onStatusChange:(e,t)=>{if(c.panels.scoops.updateScoopStatus(e,t),c.updateScoopSwitcherStatus?.(e,t),p?.jid===e){if(c.setAgentProcessing(t===`processing`),t===`processing`)c.panels.chat.setProcessing(!0);else if(t===`ready`){c.panels.chat.setProcessing(!1);let t=h.get(e)??`done-${e}-${_()}`;h.delete(e),f({type:`turn_end`,messageId:t})}}},onError:(e,t)=>{$.error(`Scoop error`,{scoopJid:e,error:t}),p?.jid===e&&f({type:`error`,error:t})},getBrowserAPI:()=>u,onToolStart:(e,t,n)=>{if(new Set([`send_message`,`list_scoops`,`list_tasks`]).has(t))return;let r=y(e);r.toolCalls||=[],r.toolCalls.push({id:_(),name:t,input:n}),p?.jid===e&&f({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=v(e),a=h.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)}}p?.jid===e&&a&&f({type:`tool_result`,messageId:a,toolName:t,result:n,isError:r})},onToolUI:(e,t,n,r)=>{let i=h.get(e);i?f({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=h.get(e);n&&f({type:`tool_ui_done`,messageId:n,requestId:t})},onIncomingMessage:(e,t)=>{if(Ta(t.channel)){let n=new Date(t.timestamp).getTime(),r=t.channel;if(v(e).push({id:t.id,role:`user`,content:t.content,timestamp:n,source:`lick`,channel:r}),p?.jid===e)c.panels.chat.addLickMessage(t.id,t.content,r,n);else{let i=x.getScoops().find(t=>t.jid===e),a=i?.isCone?`session-cone`:i?`session-${i.folder}`:`session-${e}`;c.panels.chat.persistLickToSession(a,{id:t.id,content:t.content,channel:r,timestamp:n})}return}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};v(e).push(n),p?.jid===e&&(f({type:`message_start`,messageId:t.id}),f({type:`content_delta`,messageId:t.id,text:n.content}),f({type:`content_done`,messageId:t.id}))}});await x.init(),c.panels.scoops.setOrchestrator(x),c.panels.memory.setOrchestrator(x),c.setScoopSwitcherOrchestrator?.(x);{let e=x.getSharedFS();e?_5(x,e,x.getSessionStore()):$.warn(`AgentBridge not published — orchestrator.getSharedFS() returned null`)}let S=x.getSharedFS();if(S){c.panels.fileBrowser.setFs(S),$.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 S.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})}})()},B7(S,(e,t)=>{t===`error`?$.warn(`Dropped skill install failed`,{message:e}):$.info(`Dropped skill installed`,{message:e}),l(e,t)},async()=>{await c.panels.fileBrowser.refresh()});try{let{WasmShell:e}=await a(async()=>{let{WasmShell:e}=await Promise.resolve().then(()=>C6);return{WasmShell:e}},void 0),{fetchSecretEnvVars:t}=await a(async()=>{let{fetchSecretEnvVars:e}=await Promise.resolve().then(()=>O8);return{fetchSecretEnvVars:e}},void 0),n=await t(),r=new e({fs:S,browserAPI:u,env:Object.keys(n).length>0?n:void 0});await c.panels.terminal.mountShell(r),$.info(`Terminal mounted with shared VFS`);try{let{BshWatchdog:e}=await a(async()=>{let{BshWatchdog:e}=await import(`./bsh-watchdog-BofJVeV-.js`);return{BshWatchdog:e}},__vite__mapDeps([20,13])),t=new e({browserAPI:u,scriptCatalog:r.getScriptCatalog(),fs:S});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 C=x.getScoops(),w=C.some(e=>e.isCone);if(r)$.info(`Skipping local cone bootstrap while joining a tray without a configured provider`);else if(!w)p=await c.panels.scoops.createCone(),$.info(`Created cone`);else{let e=new URLSearchParams(window.location.search).get(`scoop`);if(e){let t=C.find(t=>t.folder===e);t?(p=t,$.info(`Restored scoop from URL`,{folder:e})):p=C.find(e=>e.isCone)??C[0]}else p=C.find(e=>e.isCone)??C[0]}p&&c.panels.memory.setSelectedScoop(p.jid);let T=null,E={sendMessage(e,t){if(!p){f({type:`error`,error:`No scoop selected`});return}let n={id:t??`msg-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,chatJid:p.jid,senderId:`user`,senderName:`User`,content:e,timestamp:new Date().toISOString(),fromAssistant:!1,channel:`web`};v(p.jid).push({id:n.id,role:`user`,content:e,timestamp:Date.now()}),T?.broadcastUserMessage(e,n.id),x.handleMessage(n),x.createScoopTab(p.jid)},onEvent(e){return d.add(e),()=>d.delete(e)},stop(){p&&(x.stopScoop(p.jid),x.clearQueuedMessages(p.jid).catch(e=>{$.error(`Failed to clear queued messages on stop`,{error:e instanceof Error?e.message:String(e)})}))}};c.panels.chat.setAgent(E),c.panels.chat.setDeleteQueuedMessageCallback(e=>{if(p){x.deleteQueuedMessage(p.jid,e).catch(t=>{$.error(`Failed to delete queued message`,{messageId:e,error:t instanceof Error?t.message:String(t)})});let t=g.get(p.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:D}=await a(async()=>{let{getLickManager:e}=await Promise.resolve().then(()=>z8);return{getLickManager:e}},void 0),O=D();await O.init(),x.setLickManager(O);let ee=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,l=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`)&&S?.writeFile(`/shared/.welcomed`,`1`).catch(e=>$.warn(`Failed to persist welcome marker`,e)),n===`shortcut-migrate`&&k?.close(`welcome`),n===`onboarding-complete`&&t?.data?.mountWorkspace&&S&&L7(S).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 I7(t),k?.sendToSprinkle(`welcome`,{action:`mount-complete`,dirName:t.name})}catch(e){e.name!==`AbortError`&&$.warn(`Mount picker failed`,e),k?.sendToSprinkle(`welcome`,{action:`mount-cancelled`})}})();return}let u=x.getScoops(),d;if(d=e.targetScoop?u.find(t=>t.name===e.targetScoop||t.folder===e.targetScoop||t.folder===`${e.targetScoop}-scoop`):u.find(e=>e.isCone),d){let u=`${l}-${s}-${Date.now()}`,f=t?`Webhook Event`:n?`Sprinkle Event`:r?`File Watch Event`:i?`Session Reload`:a?`Navigate Event`:`Cron Event`,m=null;if(i){let t=e.body;if(t?.reason===`mount-recovery`&&(m=j7(t.mounts??[]),m===null)){$.debug(`Dropping session-reload lick with empty mount-recovery list`);return}}m===null&&(m=`[${f}: ${o}]\n\`\`\`json\n${JSON.stringify(e.body,null,2)}\n\`\`\``);let h={id:u,chatJid:d.jid,senderId:l,senderName:`${l}:${o}`,content:m,timestamp:e.timestamp,fromAssistant:!1,channel:l},g=Date.now();if(v(d.jid).push({id:u,role:`user`,content:m,timestamp:g,source:`lick`,channel:l}),p?.jid===d.jid)c.panels.chat.addLickMessage(u,m,l,g);else{let e=d.isCone?`session-cone`:`session-${d.folder}`;c.panels.chat.persistLickToSession(e,{id:u,content:m,channel:l,timestamp:g})}$.info(`Routing lick to scoop`,{type:l,name:o,scoopJid:d.jid}),x.handleMessage(h)}else $.warn(`Lick target scoop not found`,{targetScoop:e.targetScoop})};O.setEventHandler(ee);let ne=new Ts(u.getTransport(),e=>{O.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 u.connect(),await ne.start(),$.info(`Navigation watcher started`)}catch(e){$.warn(`Failed to start navigation watcher`,{error:e instanceof Error?e.message:String(e)})}})(),S&&te().then(async e=>{if(e.length===0)return;let{needsRecovery:t}=await O7(e,S,$);t.length!==0&&ee({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)),c.panels.chat.onInlineSprinkleLick=(e,t)=>{ee({type:`sprinkle`,sprinkleName:`inline`,targetScoop:void 0,timestamp:new Date().toISOString(),body:{action:e,data:t}})};let k=null;if(S){if(k=new D7(S,ee,{addSprinkle:(e,t,n,r)=>c.addSprinkle(e,t,n,r),removeSprinkle:e=>c.removeSprinkle(e)},()=>{let e=x.getScoops().find(e=>e.isCone);e&&(x.stopScoop(e.jid),x.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=k,window.__slicc_reloadSkills=()=>x.reloadAllSkills(),await k.refresh(),c.onSprinkleClose=e=>k.close(e),c.getAvailableSprinkles=()=>{let e=new Set(k.opened());return k.available().filter(t=>!e.has(t.name)).map(e=>({name:e.name,title:e.title}))},c.onOpenSprinkle=(e,t)=>k.open(e,t),c.updateAddButtons(),!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`)&&!r&&k.available().some(e=>e.name===`welcome`))try{await k.open(`welcome`)}catch(e){$.warn(`Failed to open welcome sprinkle`,e)}await k.restoreOpenSprinkles(),$.info(`SprinkleManager initialized`)}let re=()=>{let e=h7(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:O.listWebhooks()};break;case`create_webhook`:{let t=await O.createWebhook(n.name||`default`,n.scoop,n.filter),r=q$().session,i=r?.webhookUrl?_7(r.webhookUrl,t.id):g7(window.location.href,t.id);e={type:`response`,requestId:n.requestId,data:{...t,url:i}};break}case`delete_webhook`:e=await O.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:O.listCronTasks()};break;case`create_crontask`:{if(!n.name)throw Error(`name is required`);if(!n.cron)throw Error(`cron is required`);let t=await O.createCronTask(n.name,n.cron,n.scoop,n.filter);e={type:`response`,requestId:n.requestId,data:t};break}case`delete_crontask`:e=await O.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=q$();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`&&O.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&&O.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(re,3e3)},t.onerror=e=>{$.error(`Lick WebSocket error`,{error:String(e)})}};re(),c.onModelChange=e=>{localStorage.setItem(`selected-model`,e),x.updateModel()};let ie=new Set;c.onClearChat=async()=>{await x.clearAllMessages(),g.clear(),ie.clear()},c.onClearFilesystem=async()=>{await x.resetFilesystem()};let ae=async e=>{$.info(`Scoop selected`,{jid:e.jid,name:e.name}),p=e,x.createScoopTab(e.jid),c.panels.memory.setSelectedScoop(e.jid),c.panels.scoops.setSelectedJid(e.jid);let t=e.isCone?`session-cone`:`session-${e.folder}`,n=g.get(e.jid),r=!ie.has(e.jid),i=e.isCone?void 0:e.name;if(!r&&n&&n.length>0)await c.panels.chat.switchToContext(t,!e.isCone,i),c.panels.chat.loadMessages(n);else{if(await c.panels.chat.switchToContext(t,!e.isCone,i),c.panels.chat.getMessages().length===0){let t=await x.getMessagesForScoop(e.jid);for(let e of t){let t=e.channel===`delegation`;Ta(e.channel)?c.panels.chat.addLickMessage(e.id,e.content,e.channel,new Date(e.timestamp).getTime()):t?c.panels.chat.addUserMessage(`**[Instructions from sliccy]**\n\n${e.content}`):e.fromAssistant?(f({type:`message_start`,messageId:e.id}),f({type:`content_delta`,messageId:e.id,text:e.content}),f({type:`content_done`,messageId:e.id})):c.panels.chat.addUserMessage(e.content)}}let n=c.panels.chat.getMessages(),r=new Set(n.map(e=>e.id)),a=v(e.jid),o=a.filter(e=>!r.has(e.id));a.length=0,a.push(...n,...o),o.length>0&&c.panels.chat.loadMessages(a)}e.isCone&&x.isProcessing(e.jid)&&c.panels.chat.setProcessing(!0),ie.add(e.jid)};if(c.onScoopSelect=ae,p&&(x.createScoopTab(p.jid),await ae(p)),P7()&&await F7(c.panels.chat),o===`standalone`||o===`electron-overlay`){let e=await po(),t=f7(o,e!==null)?ro:null,n=await fo({locationHref:window.location.href,storage:window.localStorage,envBaseUrl:null,defaultWorkerBaseUrl:t,runtimeConfigFetcher:async()=>e}),r=null,i=null,a=null;n2(()=>T?(e,t)=>T.sendFsRequest(e,t):r?(e,t)=>r.sendFsRequest(e,t):null),FQ(()=>T?()=>T.getBestFollowerForTeleport():null),IQ(()=>T?()=>T.getConnectedFollowers():null);let s=e=>{a&&=(clearInterval(a),null),r?.close();let t=`follower-${e.bootstrapId}`,n=new s7(e.channel,{browserTransport:u.getTransport(),browserAPI:u,onSnapshot:e=>{c.panels.chat.loadMessages(e)},onUserMessage:e=>{c.panels.chat.addUserMessage(e)},onStatus:e=>{c.panels.chat.setProcessing(e===`processing`)},onTargetsChanged:()=>void i()});r=n,u.setTrayTargetProvider(n),c.panels.chat.setAgent(n),n.requestSnapshot();let i=async()=>{try{let e=await u.listPages();n.advertiseTargets(e.map(e=>({targetId:e.targetId,title:e.title,url:e.url})),t)}catch{}};a=setInterval(i,5e3),i(),$.info(`Follower sync wired to chat panel`,{trayId:e.trayId})},l=e=>{i?.cancel(),a&&=(clearInterval(a),null),r?.close(),r=null,i=F5({joinUrl:e,runtime:`slicc-standalone`,fetchImpl:t1()},{onConnected:e=>s(e),onReconnecting:e=>{$.info(`Follower reconnecting`,{attempt:e})},onGaveUp:e=>{$.warn(`Follower reconnect gave up`,{lastError:e})}})};if(window.addEventListener(`slicc:tray-join`,(e=>{l(e.detail.joinUrl)})),window.addEventListener(`beforeunload`,()=>{a&&clearInterval(a),r?.close(),i?.cancel()},{once:!0}),n?.joinUrl)l(n.joinUrl);else if(n?.workerBaseUrl){let e,t,r,i,a=new u7,o=()=>{t=new a7({browserTransport:u.getTransport(),browserAPI:u,getMessages:()=>c.panels.chat.getMessages(),getScoopJid:()=>p?.jid??`cone`,onFollowerMessage:(e,t)=>{c.panels.chat.addUserMessage(e),E.sendMessage(e,t)},onFollowerAbort:()=>{E.stop()},onFollowerCountChanged:e=>{e>0?a.activate():a.deactivate()}}),T=t,r1(()=>t.getConnectedFollowers()),u.setTrayTargetProvider(t),i&&clearInterval(i);let n=async()=>{try{let e=await u.listPages();t.setLocalTargets(e.map(e=>({targetId:e.targetId,title:e.title,url:e.url})))}catch{}};i=setInterval(n,5e3),n(),r=new N5({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})}})};o(),d.add(e=>{t.broadcastEvent(e)}),e=new Z$({workerBaseUrl:n.workerBaseUrl,runtime:`slicc-standalone`,fetchImpl:t1(),onControlMessage:e=>{if(e.type===`webhook.event`){O.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)})})},onReconnecting:(e,t)=>{$.info(`Leader tray reconnecting`,{attempt:e,lastError:t})},onReconnected:e=>{$.info(`Leader tray reconnected`,{trayId:e.trayId});let t=uo(window.location.href,e.workerBaseUrl,e.trayId);t!==window.location.href&&window.history.replaceState(window.history.state,``,t)},onReconnectGaveUp:(e,t)=>{$.warn(`Leader tray reconnect gave up`,{lastError:e,attempts:t})}}),o1(async()=>{t.stop(),r.stop(),e.stop(),await e.clearSession();let n=await e.start(),i=uo(window.location.href,n.workerBaseUrl,n.trayId);return i!==window.location.href&&window.history.replaceState(window.history.state,``,i),o(),q$()}),e.start().then(e=>{let t=uo(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(),a.deactivate()},{once:!0})}}$.info(`Orchestrator initialized — cone+scoops ready`,{scoopCount:x.getScoops().length}),l6().catch(()=>{})}U7().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{co as a,Ha as c,di as d,to as i,Pa as l,_o as n,so as o,ro as r,Va as s,TK as t,fi as u};
|
|
15868
|
+
`,document.head.appendChild(t),window.addEventListener(`message`,e=>{e.source===window.parent&&w7(e.data)&&c.setActiveTab(y7(`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 l=G7();await c.panels.chat.initSession(`session-cone`),$.info(`Session initialized`);let u=new gs,d=new Set,f=e=>{$.debug(`Emit to UI`,{type:e.type,listenerCount:d.size});for(let t of d)try{t(e)}catch(t){$.error(`Listener error`,{eventType:e.type,error:t instanceof Error?t.message:String(t)})}},p=null,h=new Map,g=new Map;function _(){return Date.now().toString(36)+Math.random().toString(36).slice(2,8)}function v(e){let t=g.get(e);return t||(t=[],g.set(e,t)),t}function y(e,t){let n=v(e),r=h.get(e);if(r){let e=n.find(e=>e.id===r);if(e)return e}r=`scoop-${e}-${_()}`,h.set(e,r);let i=x.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),p?.jid===e&&f({type:`message_start`,messageId:r}),o}let x=new r5(c.getIframeContainer(),{onResponse:(e,t,n)=>{let r=y(e);n?r.content+=t:(r.content=t,r.isStreaming=!1),p?.jid===e&&(f({type:`content_delta`,messageId:r.id,text:t}),n||f({type:`content_done`,messageId:r.id}))},onResponseDone:e=>{let t=v(e),n=h.get(e);if(n){let r=t.find(e=>e.id===n);r&&(r.isStreaming=!1),p?.jid===e&&f({type:`content_done`,messageId:n}),h.delete(e)}},onSendMessage:(e,t)=>{$.debug(`Send message requested`,{targetJid:e,textLength:t.length});let n=`msg-${_()}`,r={id:n,chatJid:e,senderId:`assistant`,senderName:`sliccy`,content:t,timestamp:new Date().toISOString(),fromAssistant:!0,channel:`web`};x.handleMessage(r),v(e).push({id:n,role:`assistant`,content:t,timestamp:Date.now()}),p?.jid===e&&(f({type:`message_start`,messageId:n}),f({type:`content_delta`,messageId:n,text:t}),f({type:`content_done`,messageId:n}))},onStatusChange:(e,t)=>{if(c.panels.scoops.updateScoopStatus(e,t),c.updateScoopSwitcherStatus?.(e,t),p?.jid===e){if(c.setAgentProcessing(t===`processing`),t===`processing`)c.panels.chat.setProcessing(!0);else if(t===`ready`){c.panels.chat.setProcessing(!1);let t=h.get(e)??`done-${e}-${_()}`;h.delete(e),f({type:`turn_end`,messageId:t})}}},onError:(e,t)=>{$.error(`Scoop error`,{scoopJid:e,error:t}),p?.jid===e&&f({type:`error`,error:t})},getBrowserAPI:()=>u,onToolStart:(e,t,n)=>{if(new Set([`send_message`,`list_scoops`,`list_tasks`]).has(t))return;let r=y(e);r.toolCalls||=[],r.toolCalls.push({id:_(),name:t,input:n}),p?.jid===e&&f({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=v(e),a=h.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)}}p?.jid===e&&a&&f({type:`tool_result`,messageId:a,toolName:t,result:n,isError:r})},onToolUI:(e,t,n,r)=>{let i=h.get(e);i?f({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=h.get(e);n&&f({type:`tool_ui_done`,messageId:n,requestId:t})},onIncomingMessage:(e,t)=>{if(Ta(t.channel)){let n=new Date(t.timestamp).getTime(),r=t.channel;if(v(e).push({id:t.id,role:`user`,content:t.content,timestamp:n,source:`lick`,channel:r}),p?.jid===e)c.panels.chat.addLickMessage(t.id,t.content,r,n);else{let i=x.getScoops().find(t=>t.jid===e),a=i?.isCone?`session-cone`:i?`session-${i.folder}`:`session-${e}`;c.panels.chat.persistLickToSession(a,{id:t.id,content:t.content,channel:r,timestamp:n})}return}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};v(e).push(n),p?.jid===e&&(f({type:`message_start`,messageId:t.id}),f({type:`content_delta`,messageId:t.id,text:n.content}),f({type:`content_done`,messageId:t.id}))}});await x.init(),c.panels.scoops.setOrchestrator(x),c.panels.memory.setOrchestrator(x),c.setScoopSwitcherOrchestrator?.(x);{let e=x.getSharedFS();e?C5(x,e,x.getSessionStore()):$.warn(`AgentBridge not published — orchestrator.getSharedFS() returned null`)}let S=x.getSharedFS();if(S){c.panels.fileBrowser.setFs(S),$.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 S.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})}})()},K7(S,(e,t)=>{t===`error`?$.warn(`Dropped skill install failed`,{message:e}):$.info(`Dropped skill installed`,{message:e}),l(e,t)},async()=>{await c.panels.fileBrowser.refresh()});try{let{WasmShell:e}=await a(async()=>{let{WasmShell:e}=await Promise.resolve().then(()=>k6);return{WasmShell:e}},void 0),{fetchSecretEnvVars:t}=await a(async()=>{let{fetchSecretEnvVars:e}=await Promise.resolve().then(()=>P8);return{fetchSecretEnvVars:e}},void 0),n=await t(),r=new e({fs:S,browserAPI:u,env:Object.keys(n).length>0?n:void 0});await c.panels.terminal.mountShell(r),$.info(`Terminal mounted with shared VFS`);try{let{BshWatchdog:e}=await a(async()=>{let{BshWatchdog:e}=await import(`./bsh-watchdog-BofJVeV-.js`);return{BshWatchdog:e}},__vite__mapDeps([20,13])),t=new e({browserAPI:u,scriptCatalog:r.getScriptCatalog(),fs:S});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 C=x.getScoops(),w=C.some(e=>e.isCone);if(r)$.info(`Skipping local cone bootstrap while joining a tray without a configured provider`);else if(!w)p=await c.panels.scoops.createCone(),$.info(`Created cone`);else{let e=new URLSearchParams(window.location.search).get(`scoop`);if(e){let t=C.find(t=>t.folder===e);t?(p=t,$.info(`Restored scoop from URL`,{folder:e})):p=C.find(e=>e.isCone)??C[0]}else p=C.find(e=>e.isCone)??C[0]}p&&c.panels.memory.setSelectedScoop(p.jid);let T=null,E={sendMessage(e,t){if(!p){f({type:`error`,error:`No scoop selected`});return}let n={id:t??`msg-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,chatJid:p.jid,senderId:`user`,senderName:`User`,content:e,timestamp:new Date().toISOString(),fromAssistant:!1,channel:`web`};v(p.jid).push({id:n.id,role:`user`,content:e,timestamp:Date.now()}),T?.broadcastUserMessage(e,n.id),x.handleMessage(n),x.createScoopTab(p.jid)},onEvent(e){return d.add(e),()=>d.delete(e)},stop(){p&&(x.stopScoop(p.jid),x.clearQueuedMessages(p.jid).catch(e=>{$.error(`Failed to clear queued messages on stop`,{error:e instanceof Error?e.message:String(e)})}))}};c.panels.chat.setAgent(E),c.panels.chat.setDeleteQueuedMessageCallback(e=>{if(p){x.deleteQueuedMessage(p.jid,e).catch(t=>{$.error(`Failed to delete queued message`,{messageId:e,error:t instanceof Error?t.message:String(t)})});let t=g.get(p.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:D}=await a(async()=>{let{getLickManager:e}=await Promise.resolve().then(()=>G8);return{getLickManager:e}},void 0),O=D();await O.init(),x.setLickManager(O);let ee=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,l=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`)&&S?.writeFile(`/shared/.welcomed`,`1`).catch(e=>$.warn(`Failed to persist welcome marker`,e)),n===`shortcut-migrate`&&k?.close(`welcome`),n===`onboarding-complete`&&t?.data?.mountWorkspace&&S&&U7(S).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 H7(t),k?.sendToSprinkle(`welcome`,{action:`mount-complete`,dirName:t.name})}catch(e){e.name!==`AbortError`&&$.warn(`Mount picker failed`,e),k?.sendToSprinkle(`welcome`,{action:`mount-cancelled`})}})();return}let u=x.getScoops(),d;if(d=e.targetScoop?u.find(t=>t.name===e.targetScoop||t.folder===e.targetScoop||t.folder===`${e.targetScoop}-scoop`):u.find(e=>e.isCone),d){let u=`${l}-${s}-${Date.now()}`,f=t?`Webhook Event`:n?`Sprinkle Event`:r?`File Watch Event`:i?`Session Reload`:a?`Navigate Event`:`Cron Event`,m=null;if(i){let t=e.body;if(t?.reason===`mount-recovery`&&(m=L7(t.mounts??[]),m===null)){$.debug(`Dropping session-reload lick with empty mount-recovery list`);return}}m===null&&(m=`[${f}: ${o}]\n\`\`\`json\n${JSON.stringify(e.body,null,2)}\n\`\`\``);let h={id:u,chatJid:d.jid,senderId:l,senderName:`${l}:${o}`,content:m,timestamp:e.timestamp,fromAssistant:!1,channel:l},g=Date.now();if(v(d.jid).push({id:u,role:`user`,content:m,timestamp:g,source:`lick`,channel:l}),p?.jid===d.jid)c.panels.chat.addLickMessage(u,m,l,g);else{let e=d.isCone?`session-cone`:`session-${d.folder}`;c.panels.chat.persistLickToSession(e,{id:u,content:m,channel:l,timestamp:g})}$.info(`Routing lick to scoop`,{type:l,name:o,scoopJid:d.jid}),x.handleMessage(h)}else $.warn(`Lick target scoop not found`,{targetScoop:e.targetScoop})};O.setEventHandler(ee);let ne=new Ts(u.getTransport(),e=>{O.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 u.connect(),await ne.start(),$.info(`Navigation watcher started`)}catch(e){$.warn(`Failed to start navigation watcher`,{error:e instanceof Error?e.message:String(e)})}})(),S&&te().then(async e=>{if(e.length===0)return;let{needsRecovery:t}=await P7(e,S,$);t.length!==0&&ee({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)),c.panels.chat.onInlineSprinkleLick=(e,t)=>{ee({type:`sprinkle`,sprinkleName:`inline`,targetScoop:void 0,timestamp:new Date().toISOString(),body:{action:e,data:t}})};let k=null;if(S){if(k=new N7(S,ee,{addSprinkle:(e,t,n,r)=>c.addSprinkle(e,t,n,r),removeSprinkle:e=>c.removeSprinkle(e)},()=>{let e=x.getScoops().find(e=>e.isCone);e&&(x.stopScoop(e.jid),x.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=k,window.__slicc_reloadSkills=()=>x.reloadAllSkills(),await k.refresh(),c.onSprinkleClose=e=>k.close(e),c.getAvailableSprinkles=()=>{let e=new Set(k.opened());return k.available().filter(t=>!e.has(t.name)).map(e=>({name:e.name,title:e.title}))},c.onOpenSprinkle=(e,t)=>k.open(e,t),c.updateAddButtons(),!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`)&&!r&&k.available().some(e=>e.name===`welcome`))try{await k.open(`welcome`)}catch(e){$.warn(`Failed to open welcome sprinkle`,e)}await k.restoreOpenSprinkles(),$.info(`SprinkleManager initialized`)}let re=()=>{let e=x7(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:O.listWebhooks()};break;case`create_webhook`:{let t=await O.createWebhook(n.name||`default`,n.scoop,n.filter),r=q$().session,i=r?.webhookUrl?C7(r.webhookUrl,t.id):S7(window.location.href,t.id);e={type:`response`,requestId:n.requestId,data:{...t,url:i}};break}case`delete_webhook`:e=await O.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:O.listCronTasks()};break;case`create_crontask`:{if(!n.name)throw Error(`name is required`);if(!n.cron)throw Error(`cron is required`);let t=await O.createCronTask(n.name,n.cron,n.scoop,n.filter);e={type:`response`,requestId:n.requestId,data:t};break}case`delete_crontask`:e=await O.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=q$();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`&&O.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&&O.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(re,3e3)},t.onerror=e=>{$.error(`Lick WebSocket error`,{error:String(e)})}};re(),c.onModelChange=e=>{localStorage.setItem(`selected-model`,e),x.updateModel()};let ie=new Set;c.onClearChat=async()=>{await x.clearAllMessages(),g.clear(),ie.clear()},c.onClearFilesystem=async()=>{await x.resetFilesystem()};let ae=async e=>{$.info(`Scoop selected`,{jid:e.jid,name:e.name}),p=e,x.createScoopTab(e.jid),c.panels.memory.setSelectedScoop(e.jid),c.panels.scoops.setSelectedJid(e.jid);let t=e.isCone?`session-cone`:`session-${e.folder}`,n=g.get(e.jid),r=!ie.has(e.jid),i=e.isCone?void 0:e.name;if(!r&&n&&n.length>0)await c.panels.chat.switchToContext(t,!e.isCone,i),c.panels.chat.loadMessages(n);else{if(await c.panels.chat.switchToContext(t,!e.isCone,i),c.panels.chat.getMessages().length===0){let t=await x.getMessagesForScoop(e.jid);for(let e of t){let t=e.channel===`delegation`;Ta(e.channel)?c.panels.chat.addLickMessage(e.id,e.content,e.channel,new Date(e.timestamp).getTime()):t?c.panels.chat.addUserMessage(`**[Instructions from sliccy]**\n\n${e.content}`):e.fromAssistant?(f({type:`message_start`,messageId:e.id}),f({type:`content_delta`,messageId:e.id,text:e.content}),f({type:`content_done`,messageId:e.id})):c.panels.chat.addUserMessage(e.content)}}let n=c.panels.chat.getMessages(),r=new Set(n.map(e=>e.id)),a=v(e.jid),o=a.filter(e=>!r.has(e.id));a.length=0,a.push(...n,...o),o.length>0&&c.panels.chat.loadMessages(a)}e.isCone&&x.isProcessing(e.jid)&&c.panels.chat.setProcessing(!0),ie.add(e.jid)};if(c.onScoopSelect=ae,p&&(x.createScoopTab(p.jid),await ae(p)),B7()&&await V7(c.panels.chat),o===`standalone`||o===`electron-overlay`){let e=await po(),t=v7(o,e!==null)?ro:null,n=await fo({locationHref:window.location.href,storage:window.localStorage,envBaseUrl:null,defaultWorkerBaseUrl:t,runtimeConfigFetcher:async()=>e}),r=null,i=null,a=null;c2(()=>T?(e,t)=>T.sendFsRequest(e,t):r?(e,t)=>r.sendFsRequest(e,t):null),FQ(()=>T?()=>T.getBestFollowerForTeleport():null),IQ(()=>T?()=>T.getConnectedFollowers():null);let s=e=>{a&&=(clearInterval(a),null),r?.close();let t=`follower-${e.bootstrapId}`,n=new p7(e.channel,{browserTransport:u.getTransport(),browserAPI:u,onSnapshot:e=>{c.panels.chat.loadMessages(e)},onUserMessage:e=>{c.panels.chat.addUserMessage(e)},onStatus:e=>{c.panels.chat.setProcessing(e===`processing`)},onTargetsChanged:()=>void i()});r=n,u.setTrayTargetProvider(n),c.panels.chat.setAgent(n),n.requestSnapshot();let i=async()=>{try{let e=await u.listPages();n.advertiseTargets(e.map(e=>({targetId:e.targetId,title:e.title,url:e.url})),t)}catch{}};a=setInterval(i,5e3),i(),$.info(`Follower sync wired to chat panel`,{trayId:e.trayId})},l=e=>{i?.cancel(),a&&=(clearInterval(a),null),r?.close(),r=null,i=V5({joinUrl:e,runtime:`slicc-standalone`,fetchImpl:t1()},{onConnected:e=>s(e),onReconnecting:e=>{$.info(`Follower reconnecting`,{attempt:e})},onGaveUp:e=>{$.warn(`Follower reconnect gave up`,{lastError:e})}})};if(window.addEventListener(`slicc:tray-join`,(e=>{l(e.detail.joinUrl)})),window.addEventListener(`beforeunload`,()=>{a&&clearInterval(a),r?.close(),i?.cancel()},{once:!0}),n?.joinUrl)l(n.joinUrl);else if(n?.workerBaseUrl){let e,t,r,i,a=new g7,o=()=>{t=new d7({browserTransport:u.getTransport(),browserAPI:u,getMessages:()=>c.panels.chat.getMessages(),getScoopJid:()=>p?.jid??`cone`,onFollowerMessage:(e,t)=>{c.panels.chat.addUserMessage(e),E.sendMessage(e,t)},onFollowerAbort:()=>{E.stop()},onFollowerCountChanged:e=>{e>0?a.activate():a.deactivate()}}),T=t,r1(()=>t.getConnectedFollowers()),u.setTrayTargetProvider(t),i&&clearInterval(i);let n=async()=>{try{let e=await u.listPages();t.setLocalTargets(e.map(e=>({targetId:e.targetId,title:e.title,url:e.url})))}catch{}};i=setInterval(n,5e3),n(),r=new z5({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})}})};o(),d.add(e=>{t.broadcastEvent(e)}),e=new Z$({workerBaseUrl:n.workerBaseUrl,runtime:`slicc-standalone`,fetchImpl:t1(),onControlMessage:e=>{if(e.type===`webhook.event`){O.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)})})},onReconnecting:(e,t)=>{$.info(`Leader tray reconnecting`,{attempt:e,lastError:t})},onReconnected:e=>{$.info(`Leader tray reconnected`,{trayId:e.trayId});let t=uo(window.location.href,e.workerBaseUrl,e.trayId);t!==window.location.href&&window.history.replaceState(window.history.state,``,t)},onReconnectGaveUp:(e,t)=>{$.warn(`Leader tray reconnect gave up`,{lastError:e,attempts:t})}}),o1(async()=>{t.stop(),r.stop(),e.stop(),await e.clearSession();let n=await e.start(),i=uo(window.location.href,n.workerBaseUrl,n.trayId);return i!==window.location.href&&window.history.replaceState(window.history.state,``,i),o(),q$()}),e.start().then(e=>{let t=uo(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(),a.deactivate()},{once:!0})}}$.info(`Orchestrator initialized — cone+scoops ready`,{scoopCount:x.getScoops().length}),h6().catch(()=>{})}Y7().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{co as a,Ha as c,di as d,to as i,Pa as l,_o as n,so as o,ro as r,Va as s,TK as t,fi as u};
|