shadow-claw 1.35.0 → 1.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ import{n as e}from"./chunk-rJtMBaNB.js";export{e as generateSkillsIndex};
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./chunk-uAI_Zi6n.js";import t from"node:path";import n from"node:process";import{cp as r,mkdir as i,readFile as a,readdir as o,stat as s,writeFile as c}from"node:fs/promises";import l from"gray-matter";import u from"node:crypto";function d(e){return`sha256:${u.createHash(`sha256`).update(e).digest(`hex`).toLowerCase()}`}async function f(e){try{return await s(e),!0}catch{return!1}}async function p(e,n){let r=[];if(!await f(e))return r;async function i(e){let a=await o(e,{withFileTypes:!0});for(let o of a){let a=t.join(e,o.name);o.isDirectory()?await i(a):o.isFile()&&(!n||n(o.name,a))&&r.push(a)}}return await i(e),r.sort()}async function m(o=n.cwd(),s={}){let u=t.resolve(o),m=s.outDir||`.well-known/agent-skills`,h=s.metadataRoot?t.resolve(s.metadataRoot):u,g=s.siteName,_=s.siteDescription,v=t.dirname(h),y=t.dirname(v),b=[s.configPath,t.join(h,`shadow-claw.config.json`),t.join(h,`shadow-claw-config.json`),t.join(h,`site-config.json`),t.join(v,`shadow-claw.config.json`),t.join(v,`shadow-claw-config.json`),t.join(v,`site-config.json`),t.join(y,`shadow-claw.config.json`),t.join(y,`shadow-claw-config.json`),t.join(y,`site-config.json`)].filter(e=>!!e),x=null;for(let e of b)if(await f(e))try{let t=await a(e,`utf8`);x=JSON.parse(t);break}catch{}if(x&&(!g&&x.site?.title&&(g=x.site.title),!_&&x.site?.description&&(_=x.site.description)),!g||!_){let e=[t.join(h,`package.json`),t.join(v,`package.json`),t.join(y,`package.json`)];for(let t of e)if(await f(t))try{let e=JSON.parse(await a(t,`utf8`));!g&&e.name&&(g=e.name),!_&&e.description&&(_=e.description);break}catch{}}g||(g=t.basename(h),(g===`public`||g===`dist`)&&(g=t.basename(v),(g===`public`||g===`dist`)&&t.basename(y)&&(g=t.basename(y)))),_||=`Agent skills and tools collection, powered by ShadowClaw.`;let S=await p(t.join(u,`.agents`,`tools`),e=>e.endsWith(`.json`)),C=[];for(let e of S){let n=t.relative(u,e),r=t.posix.normalize(t.posix.relative(m,n.split(t.sep).join(t.posix.sep))),i=await a(e),o=d(i),s=t.basename(e,`.json`),c=``;try{let e=JSON.parse(i.toString(`utf8`));e.name&&(s=e.name),e.description&&(c=e.description)}catch{}C.push({name:s,description:c,url:r,digest:o,relFromRoot:n})}let w=await p(t.join(u,`.agents`,`scripts`),e=>e.endsWith(`.js`)||e.endsWith(`.mjs`)),T=[];for(let e of w){let n=t.relative(u,e),r=t.posix.normalize(t.posix.relative(m,n.split(t.sep).join(t.posix.sep))),i=d(await a(e)),o=t.basename(e,t.extname(e));T.push({name:o,description:`Portable ESM engine logic and tool execution handler for ${o}.`,url:r,digest:i,relFromRoot:n})}let E=t.join(u,`.agents`,`skills`),D=await p(E,e=>e===`SKILL.md`),O=[];for(let e of D){let n=t.relative(u,e),r=t.posix.normalize(t.posix.relative(m,n.split(t.sep).join(t.posix.sep))),i=await a(e),o=d(i),s={};try{s=l(i.toString(`utf8`)).data||{}}catch{}let c=t.basename(t.dirname(e)),f=s.name||c,p=s.description||``,h=new Set,g=!1;if(Array.isArray(s.metadata?.execution?.tools))for(let e of s.metadata.execution.tools)e?.name&&(h.add(e.name),g=!0);let _=s.metadata?.[`allowed-tools`]||s.metadata?.allowedTools||s[`allowed-tools`];if(typeof _==`string`&&_.split(/[,\s]+/).filter(Boolean).forEach(e=>{h.add(e),g=!0}),!g)for(let e of C)e.name.replace(/[-_]/g,``)===f.replace(/[-_]/g,``)&&h.add(e.name);let v=C.filter(e=>h.has(e.name)).map(({name:e,url:t,digest:n})=>({name:e,url:t,digest:n})),y=T.filter(e=>{let t=e.name.toLowerCase().replace(/[-_]/g,``),n=f.toLowerCase().replace(/[-_]/g,``);return n.startsWith(t)||t.startsWith(n)||h.has(e.name)}).map(({name:e,url:t,digest:n})=>({name:e,url:t,digest:n}));O.push({name:f,type:`skill-md`,description:p,url:r,digest:o,...v.length?{tools:v}:{},...y.length?{scripts:y}:{}})}let k=e(import.meta.url),A=s.bundledSkillsDir?t.resolve(s.bundledSkillsDir):s.toolchainRoot?t.join(t.resolve(s.toolchainRoot),`.agents`,`skills`):s.includeBundled?t.join(k,`.agents`,`skills`):null;if(A&&await f(A)&&A!==E){let e=await p(A,e=>e===`SKILL.md`);for(let n of e){let e=t.relative(A,n),o=t.join(`.agents`,`skills`,e),c=t.posix.normalize(t.posix.relative(m,o.split(t.sep).join(t.posix.sep))),p=await a(n),h=d(p),g={};try{g=l(p.toString(`utf8`)).data||{}}catch{}let _=t.basename(t.dirname(n)),v=g.name||_,y=g.description||``;if(!O.some(e=>e.name===v)){if(s.write!==!1){let e=t.join(u,o);if(!await f(e)){let a=t.dirname(n),o=t.dirname(e);await i(o,{recursive:!0}),await r(a,o,{recursive:!0})}}O.push({name:v,type:`skill-md`,description:y,url:c,digest:h})}}}let j={$schema:`https://schemas.agentskills.io/discovery/0.2.0/schema.json`,name:g,description:_,skills:O,...C.length?{tools:C.map(({name:e,description:t,url:n,digest:r})=>({name:e,...t?{description:t}:{},url:n,digest:r}))}:{},...T.length?{scripts:T.map(({name:e,description:t,url:n,digest:r})=>({name:e,...t?{description:t}:{},url:n,digest:r}))}:{},...C.length||T.length?{dependencies:{...C.length?{tools:C.map(e=>e.url)}:{},...T.length?{scripts:T.map(e=>e.url)}:{}}}:{}};if(s.stdout&&console.log(JSON.stringify(j,null,2)),s.write!==!1){let e=s.outFile?t.resolve(s.outFile):t.join(u,m,`index.json`);await i(t.dirname(e),{recursive:!0}),await c(e,JSON.stringify(j,null,2)+`
2
+ `,`utf8`)}return j}async function h(e,r={}){let i=e?t.resolve(e):n.cwd();console.log(`Generating Agent Skills Discovery index for ${i}...`);let a=await m(i,{includeBundled:!!r.bundled,...r,configPath:r.config||r.configPath}),o=a.skills?a.skills.length:0;return console.log(`Indexed ${o} skill(s) into .well-known/agent-skills/index.json`),a}export{m as n,h as r,d as t};
@@ -0,0 +1,2 @@
1
+ import{a as e}from"./chunk-8V8biNmG.js";import{t}from"./chunk-uAI_Zi6n.js";import{t as n}from"./chunk-B4TVZApP.js";import r from"node:path";import i from"node:process";import{cp as a,mkdir as o,readFile as s,readdir as c,stat as l,writeFile as u}from"node:fs/promises";import d from"node:crypto";var f=e(n(),1);function p(e){return`sha256:${d.createHash(`sha256`).update(e).digest(`hex`).toLowerCase()}`}async function m(e){try{return await l(e),!0}catch{return!1}}async function h(e,t){let n=[];if(!await m(e))return n;async function i(e){let a=await c(e,{withFileTypes:!0});for(let o of a){let a=r.join(e,o.name);o.isDirectory()?await i(a):o.isFile()&&(!t||t(o.name,a))&&n.push(a)}}return await i(e),n.sort()}async function g(e=i.cwd(),n={}){let c=r.resolve(e),l=n.outDir||`.well-known/agent-skills`,d=n.metadataRoot?r.resolve(n.metadataRoot):c,g=n.siteName,_=n.siteDescription,v=r.dirname(d),y=r.dirname(v),b=[n.configPath,r.join(d,`shadow-claw.config.json`),r.join(d,`shadow-claw-config.json`),r.join(d,`site-config.json`),r.join(v,`shadow-claw.config.json`),r.join(v,`shadow-claw-config.json`),r.join(v,`site-config.json`),r.join(y,`shadow-claw.config.json`),r.join(y,`shadow-claw-config.json`),r.join(y,`site-config.json`)].filter(e=>!!e),x=null;for(let e of b)if(await m(e))try{let t=await s(e,`utf8`);x=JSON.parse(t);break}catch{}if(x&&(!g&&x.site?.title&&(g=x.site.title),!_&&x.site?.description&&(_=x.site.description)),!g||!_){let e=[r.join(d,`package.json`),r.join(v,`package.json`),r.join(y,`package.json`)];for(let t of e)if(await m(t))try{let e=JSON.parse(await s(t,`utf8`));!g&&e.name&&(g=e.name),!_&&e.description&&(_=e.description);break}catch{}}g||(g=r.basename(d),(g===`public`||g===`dist`)&&(g=r.basename(v),(g===`public`||g===`dist`)&&r.basename(y)&&(g=r.basename(y)))),_||=`Agent skills and tools collection, powered by ShadowClaw.`;let S=await h(r.join(c,`.agents`,`tools`),e=>e.endsWith(`.json`)),C=[];for(let e of S){let t=r.relative(c,e),n=r.posix.normalize(r.posix.relative(l,t.split(r.sep).join(r.posix.sep))),i=await s(e),a=p(i),o=r.basename(e,`.json`),u=``;try{let e=JSON.parse(i.toString(`utf8`));e.name&&(o=e.name),e.description&&(u=e.description)}catch{}C.push({name:o,description:u,url:n,digest:a,relFromRoot:t})}let w=await h(r.join(c,`.agents`,`scripts`),e=>e.endsWith(`.js`)||e.endsWith(`.mjs`)),T=[];for(let e of w){let t=r.relative(c,e),n=r.posix.normalize(r.posix.relative(l,t.split(r.sep).join(r.posix.sep))),i=p(await s(e)),a=r.basename(e,r.extname(e));T.push({name:a,description:`Portable ESM engine logic and tool execution handler for ${a}.`,url:n,digest:i,relFromRoot:t})}let E=r.join(c,`.agents`,`skills`),D=await h(E,e=>e===`SKILL.md`),O=[];for(let e of D){let t=r.relative(c,e),n=r.posix.normalize(r.posix.relative(l,t.split(r.sep).join(r.posix.sep))),i=await s(e),a=p(i),o={};try{o=(0,f.default)(i.toString(`utf8`)).data||{}}catch{}let u=r.basename(r.dirname(e)),d=o.name||u,m=o.description||``,h=new Set,g=!1;if(Array.isArray(o.metadata?.execution?.tools))for(let e of o.metadata.execution.tools)e?.name&&(h.add(e.name),g=!0);let _=o.metadata?.[`allowed-tools`]||o.metadata?.allowedTools||o[`allowed-tools`];if(typeof _==`string`&&_.split(/[,\s]+/).filter(Boolean).forEach(e=>{h.add(e),g=!0}),!g)for(let e of C)e.name.replace(/[-_]/g,``)===d.replace(/[-_]/g,``)&&h.add(e.name);let v=C.filter(e=>h.has(e.name)).map(({name:e,url:t,digest:n})=>({name:e,url:t,digest:n})),y=T.filter(e=>{let t=e.name.toLowerCase().replace(/[-_]/g,``),n=d.toLowerCase().replace(/[-_]/g,``);return n.startsWith(t)||t.startsWith(n)||h.has(e.name)}).map(({name:e,url:t,digest:n})=>({name:e,url:t,digest:n}));O.push({name:d,type:`skill-md`,description:m,url:n,digest:a,...v.length?{tools:v}:{},...y.length?{scripts:y}:{}})}let k=t(import.meta.url),A=n.bundledSkillsDir?r.resolve(n.bundledSkillsDir):n.toolchainRoot?r.join(r.resolve(n.toolchainRoot),`.agents`,`skills`):n.includeBundled?r.join(k,`.agents`,`skills`):null;if(A&&await m(A)&&A!==E){let e=await h(A,e=>e===`SKILL.md`);for(let t of e){let e=r.relative(A,t),i=r.join(`.agents`,`skills`,e),u=r.posix.normalize(r.posix.relative(l,i.split(r.sep).join(r.posix.sep))),d=await s(t),h=p(d),g={};try{g=(0,f.default)(d.toString(`utf8`)).data||{}}catch{}let _=r.basename(r.dirname(t)),v=g.name||_,y=g.description||``;if(!O.some(e=>e.name===v)){if(n.write!==!1){let e=r.join(c,i);if(!await m(e)){let n=r.dirname(t),i=r.dirname(e);await o(i,{recursive:!0}),await a(n,i,{recursive:!0})}}O.push({name:v,type:`skill-md`,description:y,url:u,digest:h})}}}let j={$schema:`https://schemas.agentskills.io/discovery/0.2.0/schema.json`,name:g,description:_,skills:O,...C.length?{tools:C.map(({name:e,description:t,url:n,digest:r})=>({name:e,...t?{description:t}:{},url:n,digest:r}))}:{},...T.length?{scripts:T.map(({name:e,description:t,url:n,digest:r})=>({name:e,...t?{description:t}:{},url:n,digest:r}))}:{},...C.length||T.length?{dependencies:{...C.length?{tools:C.map(e=>e.url)}:{},...T.length?{scripts:T.map(e=>e.url)}:{}}}:{}};if(n.stdout&&console.log(JSON.stringify(j,null,2)),n.write!==!1){let e=n.outFile?r.resolve(n.outFile):r.join(c,l,`index.json`);await o(r.dirname(e),{recursive:!0}),await u(e,JSON.stringify(j,null,2)+`
2
+ `,`utf8`)}return j}async function _(e,t={}){let n=e?r.resolve(e):i.cwd();console.log(`Generating Agent Skills Discovery index for ${n}...`);let a=await g(n,{includeBundled:!!t.bundled,...t,configPath:t.config||t.configPath}),o=a.skills?a.skills.length:0;return console.log(`Indexed ${o} skill(s) into .well-known/agent-skills/index.json`),a}export{g as n,_ as r,p as t};
package/dist/cli/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- import{a as e}from"./chunk-8V8biNmG.js";import{t}from"./chunk-uAI_Zi6n.js";import{t as n}from"./chunk-DoHbMaWn.js";import{t as r}from"./chunk-DxIsgrAF.js";import{r as i}from"./chunk-JBAAPRpe.js";import{a}from"./chunk-CS2NqF-O.js";import{t as o}from"./chunk-CAqvQuGr.js";import s,{constants as c}from"node:fs";import l from"node:path";import{fileURLToPath as u}from"node:url";import d from"node:process";import{exec as f}from"node:child_process";import{access as p,mkdir as m,readFile as h,stat as g,writeFile as _}from"node:fs/promises";import{Command as v}from"commander";import y from"process";import{Buffer as b}from"buffer";import x from"node:http";import S from"node:https";import{tmpdir as C}from"node:os";import w from"node:readline";function T(){let e=d.emitWarning;if(!e||e.__suppressed)return;let t=function(t,...n){if(!(typeof t==`string`&&(n[0]===`ExperimentalWarning`||t.includes(`ExperimentalWarning`)||t.includes(`SQLite`)))&&!(t&&typeof t==`object`&&(t.name===`ExperimentalWarning`||typeof t.message==`string`&&t.message.includes(`SQLite`))))return e.call(d,t,...n)};t.__suppressed=!0,d.emitWarning=t}T();function E(e){let t=e||(y.env.SHADOWCLAW_CACHE_DIR||``).trim()||l.join(y.cwd(),`.cache`);return l.join(t,`webrtc-ipc.sock`)}function D(e){try{s.unlinkSync(E(e))}catch{}}async function O(e){let t=E(e);try{return s.existsSync(t)?(await new Promise((e,n)=>{let r=x.request({socketPath:t,path:`/ping`,method:`GET`},t=>{t.resume(),t.statusCode===200?e():n(Error(`status ${t.statusCode}`))});r.setTimeout(1e3,()=>{r.destroy(),n(Error(`timeout`))}),r.on(`error`,n),r.end()}),{socketPath:t}):null}catch{return null}}function k(e,t,n,r,i){let a=e.socketPath||e.port;return new Promise((e,o)=>{let s=JSON.stringify({targetPeerId:t,action:n,args:r,timeoutMs:i}),c=x.request({socketPath:a,path:`/command`,method:`POST`,headers:{"Content-Type":`application/json`,"Content-Length":b.byteLength(s)}},t=>{let n=``;t.on(`data`,e=>n+=e),t.on(`end`,()=>{try{let r=JSON.parse(n);t.statusCode&&t.statusCode>=200&&t.statusCode<300?e(r):o(Error(r?.error||`IPC error ${t.statusCode}`))}catch{o(Error(`Bad IPC response: ${n}`))}})});c.setTimeout(i+2e3,()=>{c.destroy(),o(Error(`IPC request timed out`))}),c.on(`error`,e=>o(Error(`IPC connection failed: ${e.message}`))),c.write(s),c.end()})}function A(e){let t=e||(y.env.SHADOWCLAW_CACHE_DIR||``).trim()||l.join(y.cwd(),`.cache`);return l.join(t,`cli-peer-id`)}function j(e){if(y.env.SHADOWCLAW_CLI_PEER_ID)return y.env.SHADOWCLAW_CLI_PEER_ID.trim();let t=A(e);try{if(s.existsSync(t)){let e=s.readFileSync(t,`utf8`).trim();if(e)return e}}catch{}return``}function M(e,t){let n=A(t),i=l.dirname(n),a=e&&typeof e==`string`&&e.trim()?e.trim():`cli-${r().toLowerCase()}`;try{s.existsSync(i)||s.mkdirSync(i,{recursive:!0}),s.writeFileSync(n,a+`
1
+ import{a as e}from"./chunk-8V8biNmG.js";import{t}from"./chunk-uAI_Zi6n.js";import{t as n}from"./chunk-BwtEsB9s.js";import{t as r}from"./chunk-DxIsgrAF.js";import{r as i}from"./chunk-rJtMBaNB.js";import{a}from"./chunk-CS2NqF-O.js";import{t as o}from"./chunk-CAqvQuGr.js";import s,{constants as c}from"node:fs";import l from"node:path";import{fileURLToPath as u}from"node:url";import d from"node:process";import{exec as f}from"node:child_process";import{access as p,mkdir as m,readFile as h,stat as g,writeFile as _}from"node:fs/promises";import{Command as v}from"commander";import y from"process";import{Buffer as b}from"buffer";import x from"node:http";import S from"node:https";import{tmpdir as C}from"node:os";import w from"node:readline";function T(){let e=d.emitWarning;if(!e||e.__suppressed)return;let t=function(t,...n){if(!(typeof t==`string`&&(n[0]===`ExperimentalWarning`||t.includes(`ExperimentalWarning`)||t.includes(`SQLite`)))&&!(t&&typeof t==`object`&&(t.name===`ExperimentalWarning`||typeof t.message==`string`&&t.message.includes(`SQLite`))))return e.call(d,t,...n)};t.__suppressed=!0,d.emitWarning=t}T();function E(e){let t=e||(y.env.SHADOWCLAW_CACHE_DIR||``).trim()||l.join(y.cwd(),`.cache`);return l.join(t,`webrtc-ipc.sock`)}function D(e){try{s.unlinkSync(E(e))}catch{}}async function O(e){let t=E(e);try{return s.existsSync(t)?(await new Promise((e,n)=>{let r=x.request({socketPath:t,path:`/ping`,method:`GET`},t=>{t.resume(),t.statusCode===200?e():n(Error(`status ${t.statusCode}`))});r.setTimeout(1e3,()=>{r.destroy(),n(Error(`timeout`))}),r.on(`error`,n),r.end()}),{socketPath:t}):null}catch{return null}}function k(e,t,n,r,i){let a=e.socketPath||e.port;return new Promise((e,o)=>{let s=JSON.stringify({targetPeerId:t,action:n,args:r,timeoutMs:i}),c=x.request({socketPath:a,path:`/command`,method:`POST`,headers:{"Content-Type":`application/json`,"Content-Length":b.byteLength(s)}},t=>{let n=``;t.on(`data`,e=>n+=e),t.on(`end`,()=>{try{let r=JSON.parse(n);t.statusCode&&t.statusCode>=200&&t.statusCode<300?e(r):o(Error(r?.error||`IPC error ${t.statusCode}`))}catch{o(Error(`Bad IPC response: ${n}`))}})});c.setTimeout(i+2e3,()=>{c.destroy(),o(Error(`IPC request timed out`))}),c.on(`error`,e=>o(Error(`IPC connection failed: ${e.message}`))),c.write(s),c.end()})}function A(e){let t=e||(y.env.SHADOWCLAW_CACHE_DIR||``).trim()||l.join(y.cwd(),`.cache`);return l.join(t,`cli-peer-id`)}function j(e){if(y.env.SHADOWCLAW_CLI_PEER_ID)return y.env.SHADOWCLAW_CLI_PEER_ID.trim();let t=A(e);try{if(s.existsSync(t)){let e=s.readFileSync(t,`utf8`).trim();if(e)return e}}catch{}return``}function M(e,t){let n=A(t),i=l.dirname(n),a=e&&typeof e==`string`&&e.trim()?e.trim():`cli-${r().toLowerCase()}`;try{s.existsSync(i)||s.mkdirSync(i,{recursive:!0}),s.writeFileSync(n,a+`
2
2
  `,`utf8`)}catch{}return a}function N(e,t){return e&&typeof e==`string`&&e.trim()?e.trim():y.env.SHADOWCLAW_CLI_PEER_ID?y.env.SHADOWCLAW_CLI_PEER_ID.trim():j(t)||M(void 0,t)}async function P(){if(typeof globalThis<`u`&&globalThis.RTCPeerConnection!==void 0)return!0;try{let e=await import(`./chunk-DUYVjLFv.js`);if(e&&e.RTCPeerConnection)return Object.assign(globalThis,{RTCPeerConnection:e.RTCPeerConnection,RTCSessionDescription:e.RTCSessionDescription,RTCIceCandidate:e.RTCIceCandidate}),!0}catch(e){console.warn(`[webrtc-cli] Failed to load node-datachannel polyfill:`,e?.message||String(e))}return!1}var F=class{host;port;path;secure;rejectUnauthorized;peer;cacheDir;cliPeerId;constructor(e={}){this.host=e.host||y.env.SHADOWCLAW_HOST||`127.0.0.1`,this.port=e.port||parseInt(y.env.SHADOWCLAW_PORT||`8888`,10),this.path=e.path||`/`,this.secure=e.secure??!1,this.rejectUnauthorized=e.rejectUnauthorized??!1,this.peer=null,this.cacheDir=e.cacheDir,this.cliPeerId=e.peerId&&e.peerId.trim()?e.peerId.trim():N(void 0,e.cacheDir)}async _getPeer(){if(this.peer&&!this.peer.destroyed)return this.peer;await P();let t=await import(`./chunk-C43fWl2a.js`).then(t=>e(t.default,1)),n=t.default?.Peer||t.default||t.Peer;return new Promise((e,t)=>{let r={host:this.host,port:this.port,path:this.path,secure:this.secure};this.secure&&(r.config={iceServers:[]},r.wsOptions={rejectUnauthorized:this.rejectUnauthorized});let i=new n(this.cliPeerId,r);this.peer=i,i.on(`open`,()=>{e(i)}),i.on(`error`,e=>{t(Error(`PeerJS error: ${e.type||e.message||e}`))})})}async sendCommand(e,t,n={},i=3e4){let a=await O(this.cacheDir);if(a)return k(a,e,t,n,i);let o=await this._getPeer();return new Promise((a,s)=>{let c=null,l=null,u=()=>{if(c&&clearTimeout(c),l)try{l.close()}catch{}if(this.peer){try{this.peer.destroy()}catch{}this.peer=null}};c=setTimeout(()=>{u(),s(Error(`WebRTC command '${t}' to peer '${e}' timed out after ${i}ms`))},i);try{l=o.connect(e,{reliable:!0,serialization:`binary`}),l.on(`open`,()=>{let e=r(),i={id:r(),type:`command:execute`,payload:{commandId:e,action:t,args:n}};l.send(i)}),l.on(`data`,e=>{let t=e;if(typeof e==`string`)try{t=JSON.parse(e)}catch{}if(t&&t.method===`GetAgentCard`&&t.id){try{l.send({jsonrpc:`2.0`,id:t.id,result:{name:`ShadowClaw CLI`,description:`ShadowClaw Command Line Interface`,version:`1.0.0`}})}catch{}return}t&&t.type===`command:result`&&(u(),t.payload?.error?s(Error(t.payload.error)):a(t.payload))}),l.on(`error`,t=>{u(),s(Error(`WebRTC connection error to peer '${e}': ${t.message||String(t)}`))})}catch(e){u(),s(e)}})}async listClients(){let e=await O(this.cacheDir);if(!e)return[];let t=e.socketPath;return new Promise(e=>{let n=x.request({socketPath:t,path:`/clients`,method:`GET`},t=>{let n=``;t.on(`data`,e=>n+=e),t.on(`end`,()=>{try{e(JSON.parse(n).clients||[])}catch{e([])}})});n.setTimeout(2e3,()=>{n.destroy(),e([])}),n.on(`error`,()=>e([])),n.end()})}close(){if(this.peer){try{this.peer.destroy()}catch{}this.peer=null}}},I=class t{static _RECONNECT_BASE_MS=1e3;static _RECONNECT_MAX_MS=3e4;host;port;path;secure;rejectUnauthorized;cacheDir;verbose;handlers;trustedPeerIds;cliPeerId;_peer;_connections;_peerCards;_running;_reconnectAttempts;_reconnectTimer;constructor(e={}){this.host=e.host||y.env.SHADOWCLAW_HOST||`127.0.0.1`,this.port=e.port||parseInt(y.env.SHADOWCLAW_PORT||`8888`,10),this.path=e.path||`/`,this.secure=e.secure??!1,this.rejectUnauthorized=e.rejectUnauthorized??!1,this.cacheDir=e.cacheDir,this.verbose=e.verbose??!1,this.handlers=e.handlers||{},this.trustedPeerIds=new Set((e.trustedPeerIds||[]).map(e=>e.trim()).filter(Boolean)),this.cliPeerId=e.renewPeerId?M(e.peerId,e.cacheDir):N(e.peerId,e.cacheDir),this._peer=null,this._connections=new Map,this._peerCards=new Map,this._running=!1,this._reconnectAttempts=0,this._reconnectTimer=null}_log(e){this.verbose&&console.log(`[webrtc-listen] ${e}`)}_isTrusted(e){if(this.trustedPeerIds.size===0||this.trustedPeerIds.has(e))return!0;for(let t of this.trustedPeerIds)if(t.endsWith(`*`)&&e.startsWith(t.slice(0,-1)))return!0;return!1}_scheduleReconnect(){if(!this._running||this._reconnectTimer!==null)return;let e=Math.min(t._RECONNECT_BASE_MS*2**this._reconnectAttempts,t._RECONNECT_MAX_MS);this._reconnectAttempts++,console.log(`[webrtc-listen] Disconnected from signaling server — reconnecting in ${(e/1e3).toFixed(1)}s (attempt ${this._reconnectAttempts})…`),this._reconnectTimer=setTimeout(()=>{if(this._reconnectTimer=null,!(!this._running||!this._peer||this._peer.destroyed))try{this._peer.reconnect()}catch{this._scheduleReconnect()}},e)}async _handleCommand(e,t,n){let{commandId:i,action:a,args:o}=n.payload||{},s=this.handlers[a];if(!s){e.send({id:r(),type:`command:result`,payload:{commandId:i,success:!1,error:`Unknown action: ${a}`}});return}try{let t=await s(o||{});e.send({id:r(),type:`command:result`,payload:{commandId:i,success:!0,data:t}})}catch(t){e.send({id:r(),type:`command:result`,payload:{commandId:i,success:!1,error:t?.message||String(t)}})}}_setupConnection(e,t){e.on(`open`,()=>{this._connections.set(t,e),console.log(`[webrtc-listen] Connection opened from peer: ${t}`);try{e.send({jsonrpc:`2.0`,id:r(),method:`GetAgentCard`,params:{}})}catch{}}),e.on(`data`,async n=>{let r=n;if(typeof n==`string`)try{r=JSON.parse(n)}catch{return}if(!(!r||typeof r!=`object`)){if(r.result&&typeof r.result==`object`&&r.result.name){this._peerCards.set(t,r.result);return}if(r.method===`GetAgentCard`&&r.id){try{e.send({jsonrpc:`2.0`,id:r.id,result:{name:`ShadowClaw CLI`,description:`ShadowClaw Command Line Interface`,version:`1.0.0`,capabilities:[`cli`,`webrtc`,`control`]}})}catch{}return}r.type===`command:execute`&&await this._handleCommand(e,t,r)}}),e.on(`close`,()=>{this._connections.delete(t),this._peerCards.delete(t),console.log(`[webrtc-listen] Connection closed from peer: ${t}`)}),e.on(`error`,e=>{this._connections.delete(t),this._peerCards.delete(t),console.error(`[webrtc-listen] Connection error from ${t}: ${e?.message||e}`)})}async start(){await P();let t=await import(`./chunk-C43fWl2a.js`).then(t=>e(t.default,1)),n=t.default?.Peer||t.default||t.Peer;return new Promise((e,t)=>{let r=!1,i={host:this.host,port:this.port,path:this.path,secure:this.secure};this.secure&&(i.config={iceServers:[]},i.wsOptions={rejectUnauthorized:this.rejectUnauthorized});let a=new n(this.cliPeerId,i);this._peer=a,this._running=!0,a.on(`open`,t=>{r=!0,this._reconnectAttempts=0,this._reconnectTimer!==null&&(clearTimeout(this._reconnectTimer),this._reconnectTimer=null),console.log(`[webrtc-listen] Registered on signaling server as peer: ${t}`),console.log(`[webrtc-listen] Waiting for connections from browser peers…`),e(t)}),a.on(`connection`,e=>{let t=e.peer;if(!this._isTrusted(t)){console.warn(`[webrtc-listen] Rejecting untrusted peer: ${t}`);try{e.close()}catch{}return}this._setupConnection(e,t)}),a.on(`error`,e=>{if(!this._running)return;let n=e?.type||e?.message||String(e);console.error(`[webrtc-listen] PeerJS error: ${n}`),r?a.open||this._scheduleReconnect():t(Error(`PeerJS error: ${n}`))}),a.on(`disconnected`,()=>{this._running&&this._scheduleReconnect()}),a.on(`close`,()=>{this._running=!1,this._reconnectTimer!==null&&(clearTimeout(this._reconnectTimer),this._reconnectTimer=null),console.log(`[webrtc-listen] Peer closed.`)})})}close(){this._running=!1,this._reconnectTimer!==null&&(clearTimeout(this._reconnectTimer),this._reconnectTimer=null),this._reconnectAttempts=0;for(let e of this._connections.values())try{e.close()}catch{}if(this._connections.clear(),this._peerCards.clear(),this._peer){try{this._peer.destroy()}catch{}this._peer=null}}};function L(e,t,n){if(e&&typeof e==`string`&&e.trim())return[e.trim()];if(y.env.SHADOWCLAW_CONTROL_TOKEN)return[y.env.SHADOWCLAW_CONTROL_TOKEN.trim()];let r=t||(y.env.SHADOWCLAW_CACHE_DIR||``).trim(),i=l.join(C(),`shadow-claw`),a=typeof y.env.HOME==`string`?y.env.HOME:``,o=[],c=e=>{try{if(e&&s.existsSync(e)){let t=s.statSync(e),n=s.readFileSync(e,`utf8`),r=JSON.parse(n);if(r&&typeof r.token==`string`&&r.token.trim()){let n=Number(r.createdAt)||t.mtimeMs||0;o.push({token:r.token.trim(),timestamp:n,filePath:e})}}}catch{}},u=e=>{try{let t;if(typeof y.getBuiltinModule==`function`&&(t=y.getBuiltinModule(`node:sqlite`)),t&&t.DatabaseSync&&s.existsSync(e)){let n=s.statSync(e),r=new t.DatabaseSync(e),i=r.prepare(`SELECT value FROM metadata WHERE key = 'control_token'`).get();r.close(),i&&i.value&&o.push({token:`${i.value}`.trim(),timestamp:n.mtimeMs||0,filePath:e})}}catch{}};if(r)c(l.join(r,`control-token.json`)),u(l.join(r,`database`,`clients.db`)),u(l.join(r,`clients.db`));else{n&&c(l.join(i,`control-token-${n}.json`)),c(l.join(i,`control-token.json`)),u(l.join(i,`database`,`clients.db`)),c(l.join(y.cwd(),`.cache`,`control-token.json`)),c(l.join(y.cwd(),`control-token.json`)),u(l.join(y.cwd(),`.cache`,`database`,`clients.db`)),u(l.join(y.cwd(),`database`,`clients.db`));try{let e=s.readdirSync(y.cwd(),{withFileTypes:!0});for(let t of e)if(t.isDirectory()&&!t.name.startsWith(`node_modules`)&&!t.name.startsWith(`.`)){let e=l.join(y.cwd(),t.name);c(l.join(e,`.cache`,`control-token.json`)),c(l.join(e,`control-token.json`)),u(l.join(e,`.cache`,`database`,`clients.db`))}}catch{}try{let e=y.cwd();for(let t=0;t<4;t++){let t=l.dirname(e);if(!t||t===e)break;c(l.join(t,`.cache`,`control-token.json`)),c(l.join(t,`control-token.json`)),u(l.join(t,`.cache`,`database`,`clients.db`));try{let e=s.readdirSync(t,{withFileTypes:!0});for(let n of e)if(n.isDirectory()&&!n.name.startsWith(`node_modules`)&&!n.name.startsWith(`.`)){let e=l.join(t,n.name);c(l.join(e,`.cache`,`control-token.json`)),c(l.join(e,`control-token.json`)),u(l.join(e,`.cache`,`database`,`clients.db`))}}catch{}e=t}}catch{}a&&(c(l.join(a,`.config`,`shadow-claw`,`control-token.json`)),c(l.join(a,`.cache`,`shadow-claw`,`control-token.json`)))}o.sort((e,t)=>t.timestamp-e.timestamp);let d=new Set,f=[];for(let e of o)e.token&&!d.has(e.token)&&(d.add(e.token),f.push(e.token));return f}var R=class{host;port;candidateTokens;token;protocol;rejectUnauthorized;transport;cacheDir;_webrtcClient;constructor(e={}){this.host=e.host||y.env.SHADOWCLAW_HOST||`127.0.0.1`,this.port=e.port||parseInt(y.env.SHADOWCLAW_PORT||`8888`,10),this.candidateTokens=L(e.token,e.cacheDir,this.port),this.token=e.token||this.candidateTokens[0]||``,this.cacheDir=e.cacheDir;let t=!!(e.https||[`1`,`true`,`yes`].includes((y.env.SHADOWCLAW_HTTPS||``).toLowerCase().trim()));this.protocol=e.protocol||(t?`https`:`http`),this.rejectUnauthorized=e.rejectUnauthorized===void 0?e.insecure===!1:!!e.rejectUnauthorized,this.transport=e.transport||`http`,this._webrtcClient=this.transport===`webrtc`?new F({host:this.host,port:this.port,path:e.peerPath||`/`,secure:this.protocol===`https`,rejectUnauthorized:this.rejectUnauthorized,peerId:e.peerId,cacheDir:e.cacheDir,renewPeerId:!!e.renewPeerId}):null}async _request({method:e=`GET`,path:t,body:n=null,timeout:r=3e4}){let i=i=>new Promise((a,o)=>{let s=this.protocol===`https`?S:x,c={"Content-Type":`application/json`};i&&(c[`x-control-token`]=i);let l={hostname:this.host,port:this.port,path:t,method:e,headers:c,timeout:r};this.protocol===`https`&&(l.rejectUnauthorized=this.rejectUnauthorized);let u=s.request(l,e=>{let t=``;e.on(`data`,e=>t+=e),e.on(`end`,()=>{let n=t;try{n=JSON.parse(t)}catch{}if(e.statusCode&&e.statusCode>=200&&e.statusCode<300)a({ok:!0,statusCode:e.statusCode,data:n});else{let r=n?.error||`HTTP request failed with status ${e.statusCode}: ${t}`;a({ok:!1,statusCode:e.statusCode,error:r,data:n})}})});u.on(`error`,e=>{o(Error(`Failed to connect to ShadowClaw server at ${this.host}:${this.port}: ${e.message}`))}),u.on(`timeout`,()=>{u.destroy(),o(Error(`Request timed out after ${r}ms`))}),n&&u.write(typeof n==`string`?n:JSON.stringify(n)),u.end()}),a=await i(this.token);if(a.ok)return a.data;if(a.statusCode===401&&Array.isArray(this.candidateTokens)&&this.candidateTokens.length>1)for(let e of this.candidateTokens){if(e===this.token)continue;let t=await i(e);if(t.ok)return this.token=e,t.data}throw Error(a.error||`HTTP request failed with status ${a.statusCode}`)}async listClients(){if(this._webrtcClient){try{let e=await this._webrtcClient.listClients();if(e&&e.length>0)return e}catch{}try{return(await this._request({path:`/api/control/clients`,method:`GET`})).clients||[]}catch{return[]}}return(await this._request({path:`/api/control/clients`,method:`GET`})).clients||[]}async sendCommand(e,t,n={},r=3e4){if(this._webrtcClient){let i=e;if(e&&e.startsWith(`client-`))try{let t=(await this.listClients()).find(t=>t.clientId===e);t&&t.peerId?i=t.peerId:t&&!t.peerId&&console.warn(`Warning: client "${e}" has no PeerJS peer ID registered.\nEnsure the browser has PeerJS enabled in Settings → WebRTC/PeerJS and has connected to the signaling server at least once.\nAlternatively, pass the browser's PeerJS peer ID directly with --client <peerId>.`)}catch{}return this._webrtcClient.sendCommand(i,t,n,r)}return await this._request({path:`/api/control/command`,method:`POST`,body:{clientId:e,action:t,args:n,timeoutMs:r},timeout:r+5e3})}async listBackups(e){let t=e?`?clientId=${encodeURIComponent(e)}`:``;return(await this._request({path:`/api/backup/list${t}`,method:`GET`})).backups||[]}async deleteBackup(e,t){let n=t?`?clientId=${encodeURIComponent(t)}`:``;return await this._request({path:`/api/backup/${encodeURIComponent(e)}${n}`,method:`DELETE`})}async broadcastNotification({title:e=`ShadowClaw`,body:t,clientId:n}={}){return await this._request({path:`/push/broadcast`,method:`POST`,body:{title:e,body:t,...n?{clientId:n}:{}}})}async sendNotification(e){return this.broadcastNotification(e)}async listPushSubscriptions(){try{let e=await this._request({path:`/push/subscriptions`,method:`GET`});return Array.isArray(e)?e:[]}catch{return[]}}async listPushClients(){try{let e=await this._request({path:`/push/clients`,method:`GET`});if(e&&Array.isArray(e.clients))return e.clients}catch{}try{let e=await this.listPushSubscriptions();if(Array.isArray(e)&&e.length>0){let t=new Map;for(let n of e){let e=(n.client_id||``).trim()||(n.id?String(n.id):``);if(!e)continue;let r=t.get(e);r?!r.deviceLabel&&n.device_label&&(r.deviceLabel=n.device_label):t.set(e,{clientId:e,deviceLabel:n.device_label||void 0})}return Array.from(t.values())}}catch{}try{let e;if(typeof y.getBuiltinModule==`function`&&(e=y.getBuiltinModule(`node:sqlite`)),e&&e.DatabaseSync){let t=[l.join(y.cwd(),`.cache`,`database`,`push-subscriptions.db`),l.join(y.cwd(),`database`,`push-subscriptions.db`),l.join(C(),`shadow-claw`,`database`,`push-subscriptions.db`),l.join(C(),`shadow-claw`,`push-subscriptions.db`)];this.cacheDir&&t.unshift(l.join(this.cacheDir,`database`,`push-subscriptions.db`),l.join(this.cacheDir,`push-subscriptions.db`));for(let n of t)if(s.existsSync(n)){let t=new e.DatabaseSync(n),r=t.prepare(`SELECT client_id, device_label, id FROM subscriptions ORDER BY created_at DESC, id DESC`).all();if(t.close(),r&&r.length>0){let e=new Map;for(let t of r){let n=(t.client_id?`${t.client_id}`.trim():``)||(t.id?String(t.id):``);n&&(e.has(n)||e.set(n,{clientId:n,deviceLabel:t.device_label?`${t.device_label}`.trim():void 0}))}return Array.from(e.values())}}}}catch{}return[]}};async function ee(e={}){let t=new R(e);try{let e=await t.listClients();if(!e||e.length===0){console.log(`No clients currently registered or connected.`);return}console.log(`Connected / registered clients (${e.length}):\n`),e.forEach((e,t)=>{let n=Math.max(0,Math.floor((Date.now()-e.lastSeen)/1e3)),r=n<60?`${n}s ago`:`${Math.floor(n/60)}m ago`;console.log(` ${t+1}. ${e.deviceLabel} (id: ${e.clientId})`),e.peerId&&console.log(` Peer ID: ${e.peerId}`),console.log(` Capabilities: ${e.capabilities.join(`, `)||`none`}`),console.log(` Version: ${e.version}`),console.log(` Last seen: ${r}\n`)})}catch(e){console.error(`Error fetching clients: ${e.message}`),y.exitCode=1}}async function te(e,t={}){if(!e||typeof e!=`string`||!e.trim()){console.error(`Error: Message cannot be empty.`),y.exitCode=1;return}let n=new R(t);try{let r=t.client;if(!r){let e=await n.listClients();if(!e||e.length===0){console.error(`Error: No clients are connected.`),y.exitCode=1;return}r=e[0].clientId,console.log(`Targeting client: ${e[0].deviceLabel} (${r})`)}let i=r||``;console.log(`Sending message to ${i}...`);let a=await n.sendCommand(i,`send-message`,{text:e.trim(),groupId:t.group});a.success?(console.log(`Message successfully dispatched.`),a.data&&console.log(JSON.stringify(a.data,null,2))):(console.error(`Error from client: ${a.error}`),y.exitCode=1)}catch(e){console.error(`Error sending message: ${e.message}`),y.exitCode=1}}async function ne(e=`trigger`,t={}){let n=new R(t);try{if(e===`list`){let e=await n.listBackups(t.client);if(!e||e.length===0){console.log(`No backups found.`);return}console.log(`Available backups (${e.length}):\n`),e.forEach((e,t)=>{let n=new Date(e.timestamp).toISOString(),r=(e.totalBytes/(1024*1024)).toFixed(2);console.log(` ${t+1}. [${e.id}] Client: ${e.clientId}`),console.log(` Date: ${n}`),console.log(` Files: ${e.fileCount} (${r} MB)\n`)});return}if(e===`delete`){if(!t.backupId){console.error(`Error: --backup-id is required for delete action.`),y.exitCode=1;return}await n.deleteBackup(t.backupId,t.client),console.log(`Backup ${t.backupId} deleted.`);return}let r=t.client;if(!r){let e=await n.listClients();if(!e||e.length===0){console.error(`Error: No clients are connected to back up.`),y.exitCode=1;return}r=e[0].clientId}let i=r||``;console.log(`Requesting backup from client ${i}...`);let a=await n.sendCommand(i,`trigger-backup`,{groupId:t.group,token:n.token});a.success?(console.log(`Backup completed successfully.`),console.log(JSON.stringify(a.data,null,2))):(console.error(`Backup failed: ${a.error}`),y.exitCode=1)}catch(e){console.error(`Error executing backup command: ${e.message}`),y.exitCode=1}}async function re(e={}){let t=new R(e);try{let n=e.client;if(!n){let e=await t.listClients();if(!e||e.length===0){console.error(`Error: No clients connected.`),y.exitCode=1;return}n=e[0].clientId}let r=n||``;console.log(`Fetching tasks from client ${r}${e.group?` (group: ${e.group})`:``}...`);let i=await t.sendCommand(r,`list-tasks`,{groupId:e.group});if(i.success){let t=i.data?.tasks||[];if(t.length===0){console.log(e.group?`No tasks configured on client for group "${e.group}".`:`No tasks configured on client.`);return}console.log(`Tasks on ${n}${e.group?` (group: ${e.group})`:``} (${t.length}):\n`),t.forEach((e,t)=>{let n=e.enabled?`[enabled]`:`[disabled]`,r=e.name||e.prompt?.slice(0,30)||`Untitled task`;console.log(` ${t+1}. ${n} ${r} (${e.schedule||`manual`})`)})}else console.error(`Failed to list tasks: ${i.error}`),y.exitCode=1}catch(e){console.error(`Error executing tasks command: ${e.message}`),y.exitCode=1}}async function z(e=`get`,t={}){let n=t.cacheDir,r=A(n),i=!!(t.renew||e===`renew`||e===`generate`||e===`new`),a=t.set||(e===`set`&&t.id?t.id:null),o=``,s=!1;if(a)o=M(a,n),s=!0;else if(i)o=M(void 0,n),s=!0;else{let e=j(n);e?(o=e,s=!1):(o=N(void 0,n),s=!0)}return t.quiet?(console.log(o),{peerId:o,filePath:r,isRenewed:s}):t.json?(console.log(JSON.stringify({peerId:o,filePath:r,renewed:s},null,2)),{peerId:o,filePath:r,isRenewed:s}):(console.log(a?`WebRTC CLI Peer ID set to: ${o}`:s?`WebRTC CLI Peer ID created/renewed: ${o}`:`WebRTC CLI Peer ID: ${o}`),console.log(`Stored in: ${r}`),{peerId:o,filePath:r,isRenewed:s})}function ie(e,t){return new Promise((n,r)=>{let i=E(t);try{s.unlinkSync(i)}catch{}try{s.mkdirSync(l.dirname(i),{recursive:!0})}catch{}let a=x.createServer(async(t,n)=>{if(t.method===`GET`&&t.url===`/ping`){n.writeHead(200,{"Content-Type":`application/json`}),n.end(JSON.stringify({ok:!0,peerId:e.cliPeerId}));return}if(t.method===`GET`&&t.url===`/clients`){let t=Array.from(e._connections.keys()).map(t=>{let n=e._peerCards?.get(t);return{clientId:t,peerId:t,deviceLabel:n?.name||`Browser Peer (${t})`,capabilities:n?.capabilities||[`webrtc`,`peerjs`],version:n?.version||`1.0.0`,transport:`webrtc`,connectedAt:Date.now(),lastSeen:Date.now()}});n.writeHead(200,{"Content-Type":`application/json`}),n.end(JSON.stringify({ok:!0,clients:t}));return}if(t.method===`POST`&&t.url===`/command`){let r=``;t.on(`data`,e=>r+=e),t.on(`end`,async()=>{try{let{targetPeerId:t,action:i,args:a,timeoutMs:o}=JSON.parse(r);if(!t){n.writeHead(400,{"Content-Type":`application/json`}),n.end(JSON.stringify({error:`targetPeerId is required`}));return}let s=e._connections.get(t);if(!s){let r=Array.from(e._connections.keys());n.writeHead(503,{"Content-Type":`application/json`}),n.end(JSON.stringify({error:`No DataChannel open to peer "${t}". Make sure the browser has connected to this listener first.`+(r.length?` Connected peers: ${r.join(`, `)}`:` No peers are currently connected.`)}));return}let c=`${Date.now()}-${Math.random().toString(36).slice(2)}`,l={id:c,type:`command:execute`,payload:{commandId:c,action:i,args:a||{}}},u=await new Promise((t,n)=>{let r=setTimeout(()=>{e._pendingIpc.delete(c),n(Error(`Command "${i}" timed out after ${o||3e4}ms`))},o||3e4);e._pendingIpc.set(c,e=>{clearTimeout(r),t(e)});try{s.send(l)}catch(t){clearTimeout(r),e._pendingIpc.delete(c),n(t)}});n.writeHead(200,{"Content-Type":`application/json`}),n.end(JSON.stringify(u))}catch(e){n.writeHead(500,{"Content-Type":`application/json`}),n.end(JSON.stringify({error:e.message}))}});return}n.writeHead(404),n.end()});a.listen(i,()=>{console.log(`[webrtc-listen] IPC socket: ${i}`),n(a)}),a.on(`error`,r)})}async function ae(e={}){let t=e.host||y.env.SHADOWCLAW_HOST||`127.0.0.1`,n=e.port?parseInt(String(e.port),10):parseInt(y.env.SHADOWCLAW_PORT||`8888`,10),r=e.path||`/`,i=!!(e.secure||e.https||[`1`,`true`,`yes`].includes((y.env.SHADOWCLAW_HTTPS||``).toLowerCase().trim())),a=!!(e.insecure===!1||[`0`,`false`,`no`].includes((y.env.SHADOWCLAW_TLS_REJECT_UNAUTHORIZED||``).toLowerCase().trim())),o=e.trustedPeer?Array.isArray(e.trustedPeer)?e.trustedPeer:[e.trustedPeer]:[],s=N(e.peerId,e.cacheDir);console.log(`WebRTC CLI Peer ID : ${s}`),console.log(`Signaling server : ${i?`wss`:`ws`}://${t}:${n}${r}`),i&&!a&&console.log(`TLS verification : disabled (self-signed cert allowed)`),o.length>0?console.log(`Trusted peers : ${o.join(`, `)}`):console.log(`Trusted peers : (any — add --trusted-peer <id> to restrict)`),console.log(``),console.log(`Add this CLI Peer ID as a trusted peer in the browser:`),console.log(` Settings → WebRTC/PeerJS → Trusted Peer IDs → "${s}"`),console.log(``);let c=new I({host:t,port:n,path:r,secure:i,rejectUnauthorized:a,trustedPeerIds:o,peerId:e.peerId,cacheDir:e.cacheDir,renewPeerId:!!e.renewPeerId,verbose:!!e.verbose}),l=new Map;c._pendingIpc=l;let u=c._setupConnection.bind(c);c._setupConnection=function(e,t){u(e,t),e.on(`data`,e=>{let t=e;if(typeof e==`string`)try{t=JSON.parse(e)}catch{return}if(!(!t||typeof t!=`object`)&&t.type===`command:result`){let e=t.payload||{},n=l.get(e.commandId);n&&(l.delete(e.commandId),n(e))}})};let d=t=>{if(console.log(`
3
3
  [webrtc-listen] Shutting down…`),D(e.cacheDir),t)try{t.close()}catch{}c.close(),y.exit(0)};try{await c.start();let t=await ie(c,e.cacheDir);y.on(`SIGINT`,()=>d(t)),y.on(`SIGTERM`,()=>d(t)),console.log(`[webrtc-listen] Ready. Run commands with:
4
4
  node bin/cli.mjs send --transport webrtc --client <browser-peer-id> "message"`),await new Promise(()=>{})}catch(t){D(e.cacheDir),console.error(`Error starting WebRTC listener: ${t.message}`),y.exitCode=1}}const oe=l.dirname(u(import.meta.url));function se(){try{let e=l.resolve(oe,`../../../package.json`);if(s.existsSync(e)){let t=JSON.parse(s.readFileSync(e,`utf8`));if(t.version)return t.version}}catch{}return`1.27.1`}function B(e){return typeof e==`string`&&e.startsWith(`shadowclaw_client_`)?e.slice(18):e}function ce(e){return typeof e==`string`&&!e.startsWith(`shadowclaw_client_`)?`shadowclaw_client_${e}`:e}const le=[{name:`shadowclaw_server_list_clients`,description:`List connected browser and Electron clients, including device type, ID, and active capabilities.`,inputSchema:{type:`object`,properties:{}}},{name:`shadowclaw_server_send_message`,description:`Send a message or prompt to a connected ShadowClaw client's active AI orchestrator queue.`,inputSchema:{type:`object`,properties:{text:{type:`string`,description:`The prompt or message text to dispatch.`},clientId:{type:`string`,description:`Target client ID. If omitted, targets the first available connected client.`},groupId:{type:`string`,description:`Target conversation group ID (e.g. 'br:main'). If omitted, targets the active group.`}},required:[`text`]}},{name:`shadowclaw_server_read_state`,description:`Read the current orchestrator state, active group ID, and capabilities from a connected client.`,inputSchema:{type:`object`,properties:{clientId:{type:`string`,description:`Target client ID.`}}}},{name:`shadowclaw_server_list_tasks`,description:`List scheduled background tasks configured on a connected client.`,inputSchema:{type:`object`,properties:{clientId:{type:`string`},groupId:{type:`string`}}}},{name:`shadowclaw_server_set_active_client`,description:`Set the active default connected client used when no clientId is explicitly provided in tool calls.`,inputSchema:{type:`object`,properties:{clientId:{type:`string`,description:`Target client ID (or index '0', '1', prefix, or device label) to make active.`}},required:[`clientId`]}},{name:`shadowclaw_server_manage_backup`,description:`Trigger or manage OPFS workspace backups for a connected client (trigger, list, or delete).`,inputSchema:{type:`object`,properties:{action:{type:`string`,enum:[`trigger`,`list`,`delete`],default:`trigger`},clientId:{type:`string`},backupId:{type:`string`},groupId:{type:`string`}}}},{name:`shadowclaw_server_status`,description:`Query ShadowClaw Node server status, version, and active client count.`,inputSchema:{type:`object`,properties:{}}},{name:`shadowclaw_server_send_notification`,description:`Broadcast an OS-level push notification to subscribed devices via Web Push (VAPID), or send to a specific registered client. Works even when the client browser tab is closed, asleep, or running in the background.`,inputSchema:{type:`object`,properties:{title:{type:`string`,description:`Notification title (default: 'ShadowClaw').`},body:{type:`string`,description:`The notification body message text.`},clientId:{type:`string`,description:`Target client ID, prefix, or device label of a specific client that has registered in the past. If omitted, broadcasts to all subscribed devices.`}},required:[`body`]}}];function V(e={}){let t=e.client||new R(e),n=e.relayClientTools!==!1,r=e.targetClientId||e.clientTarget,i=r||``,a={name:`shadow-claw`,version:e.version||se()},o={tools:{listChanged:!0},extensions:{"io.modelcontextprotocol/tasks":{}}};async function s(e){let n=e||i||r;try{let e=await t.listClients();if(Array.isArray(e)&&e.length>0){if(n&&typeof n==`string`&&n.trim()){let t=n.trim(),r=e.find(e=>(e.clientId||e.id)===t);if(r)return r.clientId||r.id;let i=parseInt(t,10);if(!isNaN(i)&&i>=0&&i<e.length)return e[i].clientId||e[i].id;let a=e.find(e=>(e.clientId||e.id||``).startsWith(t)||(e.clientId||``).replace(/^client-/,``).startsWith(t));if(a)return a.clientId||a.id;let o=e.find(e=>e.deviceLabel?.toLowerCase().includes(t.toLowerCase()));return o?o.clientId||o.id:t}return e[0].clientId||e[0].id||``}}catch{}return typeof n==`string`?n.trim():``}let c=new Map,l=new Map;async function u(){if(!n)return[];let e=[];try{e=await t.listClients()}catch{}if(!Array.isArray(e)||e.length===0)return c.clear(),l.clear(),[];c.clear(),l.clear();for(let n of e){let e=n.clientId||n.id;if(e)try{let r=await t.sendCommand(e,`list-tools`,{});if(r&&r.success&&r.data?.tools&&Array.isArray(r.data.tools))for(let e of r.data.tools){let t=B(e.name);t===`send_notification`||t.startsWith(`shadowclaw_`)&&!t.startsWith(`shadowclaw_client_`)||(l.has(t)||(l.set(t,e),c.set(t,[])),c.get(t).push(n))}}catch{}}let r=await s(),i=[];for(let[t,n]of l.entries()){let a=c.get(t)||[],o=a.map(e=>e.clientId||e.id).filter(Boolean),s=a.find(e=>(e.clientId||e.id)===r)||a[0],l=s?.clientId||s?.id||``,u=s?.deviceLabel||`Client`,d=n.inputSchema&&typeof n.inputSchema==`object`?n.inputSchema:{type:`object`,properties:{}},f={...d.properties||{},clientId:{type:`string`,description:`Target ShadowClaw client ID (optional; defaults to ${l} [${u}]). Available on: ${a.map(e=>`${e.clientId||e.id} (${e.deviceLabel||`Client`})`).join(`, `)}`,enum:o}},p=e.length>1?a.length>1?` [Default: ${u} (${l.slice(0,14)}...)]`:` [Client: ${u} (${l.slice(0,14)}...)]`:``,m=ce(t);i.push({name:m,description:(n.description||`Relayed tool '${t}' from connected client.`)+p,inputSchema:{...d,type:`object`,properties:f},annotations:n.annotations})}return i}async function d(e,n={}){let r=e.id===void 0||e.id===null,d=e.id??null;if(n[`mcp-method`]&&n[`mcp-method`]!==e.method)return{jsonrpc:`2.0`,id:d,error:{code:-32020,message:`Mcp-Method header '${n[`mcp-method`]}' does not match '${e.method}'`}};switch(e.method){case`server/discover`:return{jsonrpc:`2.0`,id:d,result:{protocolVersion:`2026-07-28`,supportedProtocolVersions:[`2026-07-28`,`2025-11-25`,`2024-11-05`],capabilities:o,serverInfo:a,_meta:{"io.modelcontextprotocol/serverInfo":a}}};case`initialize`:return{jsonrpc:`2.0`,id:d,result:{protocolVersion:e.params?.protocolVersion||`2024-11-05`,capabilities:o,serverInfo:a}};case`notifications/initialized`:return null;case`tools/list`:{let e=[];try{if(typeof t.listPushClients==`function`)e=await t.listPushClients();else if(typeof t.listPushSubscriptions==`function`){let n=await t.listPushSubscriptions();if(Array.isArray(n)){let t=new Map;for(let e of n){let n=(e.client_id||``).trim()||(e.id?String(e.id):``);n&&!t.has(n)&&t.set(n,{clientId:n,deviceLabel:e.device_label||void 0})}e=Array.from(t.values())}}}catch{}let n=Array.isArray(e)?[...e].sort((e,t)=>(e.clientId||``).localeCompare(t.clientId||``)):[],r=n.map(e=>e.clientId).filter(Boolean),i=await u(),o=new Map;for(let e of le)o.set(e.name,e);for(let e of i)o.has(e.name)||o.set(e.name,e);if(r.length>0)for(let e of[`shadowclaw_server_send_notification`,`shadowclaw_send_notification`]){let t=o.get(e);t&&o.set(e,{...t,inputSchema:{...t.inputSchema,type:`object`,properties:{...t.inputSchema?.properties||{},clientId:{type:`string`,description:`Target client ID, prefix, or device label of a specific client registered for push notifications (optional; if omitted, broadcasts to all subscribed devices). Available on: ${n.map(e=>`${e.clientId} (${e.deviceLabel||`Client`})`).join(`, `)}`,enum:r}}}})}return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,ttlMs:5e3,cacheScope:`private`,tools:Array.from(o.values()).sort((e,t)=>e.name.localeCompare(t.name)),_meta:{"io.modelcontextprotocol/serverInfo":a}}}}case`tools/call`:{let n=e.params?.name,r=e.params?.arguments||{},o=e.params?.inputResponses;if(!n)return{jsonrpc:`2.0`,id:d,error:{code:-32602,message:`Missing required parameter 'name'`}};if(n===`shadowclaw_server_list_clients`||n===`shadowclaw_list_clients`)try{let e=await t.listClients();return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,content:[{type:`text`,text:JSON.stringify({clients:e},null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error listing clients: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}if(n===`shadowclaw_server_set_active_client`||n===`shadowclaw_set_active_client`){let e=await s(r.clientId);return e?(i=e,console.error(`[ShadowClaw MCP] Active default client set to: ${i}`),{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,content:[{type:`text`,text:`Active default client set to: ${i}`}],_meta:{activeClientId:i,"io.modelcontextprotocol/serverInfo":a}}}):{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error: Client '${r.clientId}' not found among connected clients.`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}if(n===`shadowclaw_server_send_message`||n===`shadowclaw_send_message`){let e=await s(r.clientId);if(!e)return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error: No connected client available.`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}};try{let n=await t.sendCommand(e,`send-message`,{text:r.text,groupId:r.groupId});return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!n.success,content:[{type:`text`,text:JSON.stringify(n.data||n,null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error sending message: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}}if(n===`shadowclaw_server_read_state`||n===`shadowclaw_read_state`){let e=await s(r.clientId);try{let n=await t.sendCommand(e,`read-state`,{});return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!n.success,content:[{type:`text`,text:JSON.stringify(n.data||n,null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error reading state: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}}if(n===`shadowclaw_server_list_tasks`||n===`shadowclaw_list_tasks`){let e=await s(r.clientId);try{let n=await t.sendCommand(e,`list-tasks`,{groupId:r.groupId});return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!n.success,content:[{type:`text`,text:JSON.stringify(n.data||n,null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error listing tasks: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}}if(n===`shadowclaw_server_manage_backup`||n===`shadowclaw_manage_backup`){let e=r.action||`trigger`,n=await s(r.clientId);try{if(e===`list`){let e=await t.listBackups(n);return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,content:[{type:`text`,text:JSON.stringify({backups:e},null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}if(e===`delete`){let e=await t.deleteBackup(r.backupId,n);return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,content:[{type:`text`,text:JSON.stringify(e,null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}let i=await t.sendCommand(n,`trigger-backup`,{groupId:r.groupId});return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!i.success,content:[{type:`text`,text:JSON.stringify(i.data||i,null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error managing backup: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}}if(n===`shadowclaw_server_status`||n===`shadowclaw_status`)try{let e=await t.listClients();return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,content:[{type:`text`,text:JSON.stringify({server:`ShadowClaw`,version:a.version,connectedClients:e.length,status:`healthy`},null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error querying server status: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}if(n===`shadowclaw_server_send_notification`||n===`shadowclaw_send_notification`||n===`send_notification`){let e=String(r.body||``).trim();if(!e)return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error: Notification 'body' parameter cannot be empty.`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}};let n=String(r.title||`ShadowClaw`).trim(),i=typeof r.clientId==`string`&&r.clientId.trim()?r.clientId.trim():void 0;try{let r=await t.broadcastNotification({title:n,body:e,...i?{clientId:i}:{}}),o=r?.sent??0,s=r?.failed??0,c;return c=r?.notFound?`Warning: No push subscriptions found for client '${i}'. Ensure push notifications were registered by this client in ShadowClaw Settings.`:r?.noSubscribers?`Warning: Push notification broadcast completed, but no devices are currently subscribed to push notifications. Ensure push notifications are enabled in ShadowClaw Settings on the client first.`:i?`Push notification sent to client '${i}': ${o} recipient(s) delivered, ${s} failed.`:`Push notification broadcast sent: ${o} recipient(s) delivered, ${s} failed.`,{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!1,content:[{type:`text`,text:c}],_meta:{...r,...i?{targetClientId:i}:{},"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Failed to send push notification: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}}let f=B(n);if((f===`ask_user`||n===`ask_user`)&&o&&o.response)return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,content:[{type:`text`,text:String(o.response)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}};l.size===0&&await u();let p=(c.get(f)||c.get(n)||[]).map(e=>e.clientId||e.id).filter(Boolean),m=``;if(r.clientId)m=await s(r.clientId);else{let e=await s();m=p.includes(e)?e:p.length>0?p[0]:e}if(!m)return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error: No connected client available.`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}};if(p.length>0&&!p.includes(m))return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error: Tool '${n}' is not enabled or available on client '${m}'. (Available on: ${p.join(`, `)})`}],_meta:{clientId:m,"io.modelcontextprotocol/serverInfo":a}}};try{console.error(`[ShadowClaw MCP] Executing '${f}' on client: ${m}`);let e={...r};delete e.clientId;let n=f===`ask_user`?await t.sendCommand(m,`invoke-tool`,{toolName:f,input:e},3e5):await t.sendCommand(m,`invoke-tool`,{toolName:f,input:e}),i=n.data?.result===void 0?n.data:n.data.result,o=typeof i==`string`?i:JSON.stringify(i,null,2),s=n.error||n.data&&n.data.error||`Unknown tool execution error`;return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!n.success,content:[{type:`text`,text:n.success?o||``:o&&o!==`null`&&o!==`{}`?`${o}\n${s}`:`Tool execution error: ${s}`}],_meta:{clientId:m,"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Tool error: ${e.message}`}],_meta:{clientId:m,"io.modelcontextprotocol/serverInfo":a}}}}}case`tasks/get`:return{jsonrpc:`2.0`,id:d,result:{resultType:`complete`,task:{taskId:e.params?.taskId||`task-1`,status:`completed`},_meta:{"io.modelcontextprotocol/serverInfo":a}}};default:return r?null:{jsonrpc:`2.0`,id:d,error:{code:-32601,message:`Method not found: '${e.method}'`}}}}return{handleMessage:d,getActiveClientId:()=>i,setActiveClientId:e=>{i=e}}}async function ue(e={}){if((e.mcpTransport||(e.http?`http`:`stdio`))===`http`){let t=parseInt(String(e.port||y.env.MCP_PORT||`8888`),10),n=e.host||`127.0.0.1`,r=V(e);x.createServer(async(e,t)=>{if(e.method!==`POST`||e.url?.split(`?`)[0]!==`/mcp`){t.writeHead(404,{"Content-Type":`application/json`}),t.end(JSON.stringify({error:`Not found`}));return}let n=``;e.on(`data`,e=>n+=e),e.on(`end`,async()=>{let i;try{i=JSON.parse(n)}catch{t.writeHead(400,{"Content-Type":`application/json`}),t.end(JSON.stringify({jsonrpc:`2.0`,id:null,error:{code:-32700,message:`Parse error`}}));return}try{let n={"mcp-protocol-version":e.headers[`mcp-protocol-version`],"mcp-method":e.headers[`mcp-method`],"mcp-name":e.headers[`mcp-name`]},a=await r.handleMessage(i,n);if(a===null){t.writeHead(202),t.end();return}t.writeHead(200,{"Content-Type":`application/json`,"MCP-Protocol-Version":`2026-07-28`}),t.end(JSON.stringify(a))}catch(e){t.writeHead(500,{"Content-Type":`application/json`}),t.end(JSON.stringify({jsonrpc:`2.0`,id:i?.id??null,error:{code:-32603,message:e?.message||`Internal error`}}))}})}).listen(t,n,()=>{console.error(`[ShadowClaw MCP] HTTP MCP server listening at http://${n}:${t}/mcp (2026-07-28)`)});return}console.log=(...e)=>console.error(...e),console.info=(...e)=>console.error(...e);let t=V(e);w.createInterface({input:y.stdin,output:y.stdout,terminal:!1}).on(`line`,async e=>{let n=e.trim();if(!n)return;let r;try{r=JSON.parse(n)}catch{y.stdout.write(JSON.stringify({jsonrpc:`2.0`,id:null,error:{code:-32700,message:`Parse error`}})+`
@@ -51,4 +51,4 @@ slug: "home"
51
51
  .cache/
52
52
  node_modules/
53
53
  `,`utf8`),console.log(`Created ${o}`)),console.log(`\nShadowClaw template successfully initialized in ${t}`),console.log(`To start developing, run:`),console.log(` npx shadow-claw dev
54
- `)}catch(e){console.error(`Init failed:`,e),d.exit(1)}}),$.command(`skills:index [dir]`).alias(`agent-skills`).description(`Generate or update .well-known/agent-skills/index.json per the Agent Skills Discovery RFC`).optionsGroup(`Output & Path Options:`).option(`--out-dir <dir>`,`Output directory relative to content root (default: .well-known/agent-skills)`).option(`--out-file <file>`,`Explicit destination path for index.json`).option(`--metadata-root <dir>`,`Directory to read site metadata from (default: content root)`).option(`--config <file>`,`Explicit path to shadow-claw.config.json or site-config.json`).optionsGroup(`Generation Options:`).option(`--no-bundled`,`Exclude bundled ShadowClaw skills from index`).option(`--stdout`,`Print generated index.json to stdout`,!1).option(`--no-write`,`Skip writing file to disk`).action(async(e,t)=>{try{await i(e,t)}catch(e){console.error(`Failed to generate skills index:`,e),d.exit(1)}}),$.commandsGroup(`Headless Agent:`),$.command(`agent [action] [args...]`).description(`Run the headless CLI agent (init | model | skills | tools | tool | skill | import | run)`).optionsGroup(`Agent Options:`).option(`--workspace <dir>`,`Workspace directory (default: .cache)`).option(`--database-dir <dir>`,`Directory where SQLite databases are stored`).option(`--cache-dir <dir>`,`Custom cache directory for databases and logs`).option(`--tmp, --temp`,`Store cache, token, and databases in OS temporary directory`).option(`-y, --yes`,`Skip interactive cache directory prompt and accept defaults`).option(`--group <groupId>`,`Conversation group ID`,`server:main`).option(`--provider <provider>`,`LLM provider ID`).option(`--model <model>`,`Model name`).option(`--download`,`Prewarm and download the model during agent init or execution`,!1).option(`--api-key <key>`,`API key`).option(`-v, --verbose`,`Enable verbose execution logging`,!1).option(`-o, --output <file>`,`Write command output to a file instead of stdout`).option(`--stream`,`Stream response tokens to stdout as they arrive (default: true)`,!0).option(`--no-stream`,`Disable streaming response tokens to stdout`).option(`--progress`,`Show progress bar during model downloads (default: true)`,!0).option(`--no-progress`,`Disable download progress bar`).option(`--system-prompt <text>`,`Override system prompt with inline text`).option(`--system-prompt-file <file>`,`Load system prompt from a text or markdown file`).option(`--tools <tools>`,`Comma-separated list of tools to enable or import (e.g. bash,read_file)`).option(`--skills <skills>`,`Comma-separated list of skills to filter or import`).option(`--scripts <scripts>`,`Comma-separated list of scripts to import`).option(`--all`,`Import all tools, skills, and scripts from discovery manifest`,!1).option(`--overwrite`,`Overwrite existing skills, tools, or scripts during import`,!1).option(`--auto-enable`,`Automatically enable imported declarative tools (default: true)`,!0).option(`--no-auto-enable`,`Do not automatically enable imported declarative tools`).option(`--tools-profile <name>`,`Tools profile to activate (e.g. __builtin_default)`).option(`-r, --remote`,`List or search available models from Hugging Face onnx-community repository`,!1).option(`--huggingface, --hf`,`Alias for --remote to query Hugging Face`,!1).option(`--query <query>`,`Filter models by search query`).option(`-q, --quiet`,`Suppress all non-error output`,!1).action(async(e,t,n)=>{await Ce(e,t,n)}),$.commandsGroup(`Help & Utility:`),$.helpCommand(`help [command]`,`display help for command`);async function Ae(e=d.argv){await $.parseAsync(e)}export{Ae as main,$ as program,we as registerTerminationCleanup};
54
+ `)}catch(e){console.error(`Init failed:`,e),d.exit(1)}}),$.command(`skills:index [dir]`).alias(`agent-skills`).description(`Generate or update .well-known/agent-skills/index.json per the Agent Skills Discovery RFC`).optionsGroup(`Output & Path Options:`).option(`--out-dir <dir>`,`Output directory relative to content root (default: .well-known/agent-skills)`).option(`--out-file <file>`,`Explicit destination path for index.json`).option(`--metadata-root <dir>`,`Directory to read site metadata from (default: content root)`).option(`--config <file>`,`Explicit path to shadow-claw.config.json or site-config.json`).optionsGroup(`Generation Options:`).option(`--bundled`,`Include and materialize bundled ShadowClaw skills in index and .agents/skills`,!1).option(`--no-bundled`,`Exclude bundled ShadowClaw skills from index`).option(`--stdout`,`Print generated index.json to stdout`,!1).option(`--no-write`,`Skip writing file to disk`).action(async(e,t)=>{try{await i(e,t)}catch(e){console.error(`Failed to generate skills index:`,e),d.exit(1)}}),$.commandsGroup(`Headless Agent:`),$.command(`agent [action] [args...]`).description(`Run the headless CLI agent (init | model | skills | tools | tool | skill | import | run)`).optionsGroup(`Agent Options:`).option(`--workspace <dir>`,`Workspace directory (default: .cache)`).option(`--database-dir <dir>`,`Directory where SQLite databases are stored`).option(`--cache-dir <dir>`,`Custom cache directory for databases and logs`).option(`--tmp, --temp`,`Store cache, token, and databases in OS temporary directory`).option(`-y, --yes`,`Skip interactive cache directory prompt and accept defaults`).option(`--group <groupId>`,`Conversation group ID`,`server:main`).option(`--provider <provider>`,`LLM provider ID`).option(`--model <model>`,`Model name`).option(`--download`,`Prewarm and download the model during agent init or execution`,!1).option(`--api-key <key>`,`API key`).option(`-v, --verbose`,`Enable verbose execution logging`,!1).option(`-o, --output <file>`,`Write command output to a file instead of stdout`).option(`--stream`,`Stream response tokens to stdout as they arrive (default: true)`,!0).option(`--no-stream`,`Disable streaming response tokens to stdout`).option(`--progress`,`Show progress bar during model downloads (default: true)`,!0).option(`--no-progress`,`Disable download progress bar`).option(`--system-prompt <text>`,`Override system prompt with inline text`).option(`--system-prompt-file <file>`,`Load system prompt from a text or markdown file`).option(`--tools <tools>`,`Comma-separated list of tools to enable or import (e.g. bash,read_file)`).option(`--skills <skills>`,`Comma-separated list of skills to filter or import`).option(`--scripts <scripts>`,`Comma-separated list of scripts to import`).option(`--all`,`Import all tools, skills, and scripts from discovery manifest`,!1).option(`--overwrite`,`Overwrite existing skills, tools, or scripts during import`,!1).option(`--auto-enable`,`Automatically enable imported declarative tools (default: true)`,!0).option(`--no-auto-enable`,`Do not automatically enable imported declarative tools`).option(`--tools-profile <name>`,`Tools profile to activate (e.g. __builtin_default)`).option(`-r, --remote`,`List or search available models from Hugging Face onnx-community repository`,!1).option(`--huggingface, --hf`,`Alias for --remote to query Hugging Face`,!1).option(`--query <query>`,`Filter models by search query`).option(`-q, --quiet`,`Suppress all non-error output`,!1).action(async(e,t,n)=>{await Ce(e,t,n)}),$.commandsGroup(`Help & Utility:`),$.helpCommand(`help [command]`,`display help for command`);async function Ae(e=d.argv){await $.parseAsync(e)}export{Ae as main,$ as program,we as registerTerminationCleanup};
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://modelcontextprotocol.io/schemas/server-card/v1.json",
3
3
  "name": "shadow-claw",
4
- "version": "1.35.0",
4
+ "version": "1.36.0",
5
5
  "description": "Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.",
6
6
  "title": "ShadowClaw MCP Server",
7
7
  "websiteUrl": "https://xt-ml.github.io/shadow-claw/",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://modelcontextprotocol.io/schemas/server-card/v1.json",
3
3
  "name": "shadow-claw",
4
- "version": "1.35.0",
4
+ "version": "1.36.0",
5
5
  "description": "Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.",
6
6
  "title": "ShadowClaw MCP Server",
7
7
  "websiteUrl": "https://xt-ml.github.io/shadow-claw/",
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="72143ec88485970231da8c06ecf74089dd580224" /><meta name="version" content="1.35.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - Browser-native AI agent." /><link rel="canonical" href="https://xt-ml.github.io/shadow-claw/"><meta property="og:title" content="ShadowClaw"><meta property="og:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta property="og:type" content="website"><meta property="og:url" content="https://xt-ml.github.io/shadow-claw/"><meta property="og:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="ShadowClaw"><meta name="twitter:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta name="twitter:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"SoftwareApplication","@id":"https://xt-ml.github.io/shadow-claw/#software","name":"ShadowClaw","description":"Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.","url":"https://xt-ml.github.io/shadow-claw/","applicationCategory":"DeveloperApplication","operatingSystem":"Web, Browser, Desktop","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"author":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"},"codeRepository":"https://github.com/xt-ml/shadow-claw","license":"https://github.com/xt-ml/shadow-claw/blob/main/LICENSE"},{"@type":"WebSite","@id":"https://xt-ml.github.io/shadow-claw/#website","url":"https://xt-ml.github.io/shadow-claw/","name":"ShadowClaw","description":"Official website and live deployment of ShadowClaw browser-native AI assistant.","publisher":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"}},{"@type":"Organization","@id":"https://xt-ml.github.io/shadow-claw/#organization","name":"xt-ml","url":"https://github.com/xt-ml","sameAs":["https://github.com/xt-ml"]}]}</script><meta name="theme-color" content="#fff" /><meta http-equiv="origin-trial" content="A88uTgESYWcVgREKVReKB6jom41uP8TzW6ei3jNdidf+Xl6ONqKRjKNBphsxhrZmdkakLK3oXDgkGq53rtZYSAMAAAB2eyJvcmlnaW4iOiJodHRwczovL3h0LW1sLmdpdGh1Yi5pbzo0NDMiLCJmZWF0dXJlIjoiV2ViTUNQIiwiZXhwaXJ5IjoxNzk0ODczNjAwLCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ=="><base href="/shadow-claw/" /><script id="shadow-claw-site-config" type="application/json">{"$schema":"https:\u002f\u002fjson-schema.org\u002fdraft\u002f2020-12\u002fschema","site":{"title":"ShadowClaw","description":"ShadowClaw - Browser-native AI agent.","themeColor":"#fff"},"branding":{"faviconPath":"assets\u002ficons\u002ffavicon.ico","appleTouchIconPath":"assets\u002ficons\u002f180.png","notFoundPath":"404.html"},"pwa":{"manifestPath":"manifest.json","themeColor":"#000000"},"sitemapPath":"sitemap.xml","assets":["assets"],"sidebar":{"pagesHidden":false,"chatHidden":false,"tasksHidden":false,"filesHidden":false,"defaultPage":"pages"},"settings":{"defaultToolsProfile":"__builtin_default"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"],"scripts":[{"src":"https:\u002f\u002fkherrick.github.io\u002fblock-garden-knowledge-hub\u002f.agents\u002fscripts\u002fmain\u002fblock-garden-adapter.js","hasInit":true},"https:\u002f\u002fkherrick.github.io\u002fblock-garden\u002fblock-garden-bundle-min.mjs"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
1
+ <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="c9c194eb19a561ec3f67a803f0e078e361735425" /><meta name="version" content="1.36.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - Browser-native AI agent." /><link rel="canonical" href="https://xt-ml.github.io/shadow-claw/"><meta property="og:title" content="ShadowClaw"><meta property="og:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta property="og:type" content="website"><meta property="og:url" content="https://xt-ml.github.io/shadow-claw/"><meta property="og:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="ShadowClaw"><meta name="twitter:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta name="twitter:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"SoftwareApplication","@id":"https://xt-ml.github.io/shadow-claw/#software","name":"ShadowClaw","description":"Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.","url":"https://xt-ml.github.io/shadow-claw/","applicationCategory":"DeveloperApplication","operatingSystem":"Web, Browser, Desktop","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"author":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"},"codeRepository":"https://github.com/xt-ml/shadow-claw","license":"https://github.com/xt-ml/shadow-claw/blob/main/LICENSE"},{"@type":"WebSite","@id":"https://xt-ml.github.io/shadow-claw/#website","url":"https://xt-ml.github.io/shadow-claw/","name":"ShadowClaw","description":"Official website and live deployment of ShadowClaw browser-native AI assistant.","publisher":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"}},{"@type":"Organization","@id":"https://xt-ml.github.io/shadow-claw/#organization","name":"xt-ml","url":"https://github.com/xt-ml","sameAs":["https://github.com/xt-ml"]}]}</script><meta name="theme-color" content="#fff" /><meta http-equiv="origin-trial" content="A88uTgESYWcVgREKVReKB6jom41uP8TzW6ei3jNdidf+Xl6ONqKRjKNBphsxhrZmdkakLK3oXDgkGq53rtZYSAMAAAB2eyJvcmlnaW4iOiJodHRwczovL3h0LW1sLmdpdGh1Yi5pbzo0NDMiLCJmZWF0dXJlIjoiV2ViTUNQIiwiZXhwaXJ5IjoxNzk0ODczNjAwLCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ=="><base href="/shadow-claw/" /><script id="shadow-claw-site-config" type="application/json">{"$schema":"https:\u002f\u002fjson-schema.org\u002fdraft\u002f2020-12\u002fschema","site":{"title":"ShadowClaw","description":"ShadowClaw - Browser-native AI agent.","themeColor":"#fff"},"branding":{"faviconPath":"assets\u002ficons\u002ffavicon.ico","appleTouchIconPath":"assets\u002ficons\u002f180.png","notFoundPath":"404.html"},"pwa":{"manifestPath":"manifest.json","themeColor":"#000000"},"sitemapPath":"sitemap.xml","assets":["assets"],"sidebar":{"pagesHidden":false,"chatHidden":false,"tasksHidden":false,"filesHidden":false,"defaultPage":"pages"},"settings":{"defaultToolsProfile":"__builtin_default"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"],"scripts":[{"src":"https:\u002f\u002fkherrick.github.io\u002fblock-garden-knowledge-hub\u002f.agents\u002fscripts\u002fmain\u002fblock-garden-adapter.js","hasInit":true},"https:\u002f\u002fkherrick.github.io\u002fblock-garden\u002fblock-garden-bundle-min.mjs"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
2
2
  <script>var ShadowClawThemeInit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);function n(){if(globalThis.trustedTypes)return;let e=new Map;globalThis.trustedTypes={createPolicy:(t,n)=>{if(e.has(t))throw TypeError(`Policy with name "${t}" already exists.`);let r={createHTML:n.createHTML?e=>n.createHTML(e):void 0,createScriptURL:n.createScriptURL?e=>n.createScriptURL(e):void 0,createScript:n.createScript?e=>n.createScript(e):void 0};return e.set(t,r),r},getPolicy:t=>e.get(t)??null,isHTML:e=>typeof e==`string`||e instanceof Object&&`toString`in e,isScriptURL:e=>typeof e==`string`||e instanceof Object&&`toString`in e,isScript:e=>typeof e==`string`||e instanceof Object&&`toString`in e}}let r=`__shadowClawDefaultTrustedTypesPolicyState`,i=`default`,a=`shadowclaw-sandbox`;function o(){let e=globalThis;return e[r]||(e[r]={initialized:!1,policy:null}),e[r]}function s(){let e=o();if(e.initialized)return;let t=Reflect.get(globalThis,`trustedTypes`);if(!(!t||typeof t.createPolicy!=`function`)){e.initialized=!0;try{if(typeof t.getPolicy==`function`){let n=t.getPolicy(i);if(n){e.policy=n;return}}let n=!1;if(typeof t.getPolicyNames==`function`){let e=t.getPolicyNames();Array.isArray(e)&&e.includes(i)&&(n=!0)}if(n){if(typeof t.getPolicy==`function`){let n=t.getPolicy(a);if(n){e.policy=n;return}}e.policy=t.createPolicy(a,{createHTML:e=>e,createScriptURL:e=>e});return}e.policy=t.createPolicy(i,{createHTML:e=>e,createScriptURL:e=>e})}catch{typeof t.getPolicy==`function`&&(e.policy=t.getPolicy(i)??t.getPolicy(a)??null)}}}new class{loading=!1;models=new Map;getModelInfo(e){if(!e||typeof e!=`string`)return null;let t=e.toLowerCase().trim(),n=this.models.get(t);if(n)return n;if(t.includes(`/`)){let e=t.split(`/`).pop();if(e&&this.models.has(e))return this.models.get(e)}else for(let[e,n]of this.models.entries())if(e.endsWith(`/${t}`))return n;if(t.includes(`:`)){let e=t.split(`:`)[0],n=this.getModelInfo(e);if(n)return n}return null}registerModelInfo(e,t){this.models.set(e.toLowerCase(),t)}clear(){this.models.clear()}async fetchModelInfo(e,t,n){if(e.modelsUrl){this.loading=!0;try{let r=new Headers;if(r.set(`Content-Type`,`application/json`),e.headers)for(let[t,n]of Object.entries(e.headers))r.set(t,n);if(n)for(let[e,t]of Object.entries(n))r.set(e,t);if(t&&e.apiKeyHeader){let n=e.apiKeyHeaderFormat;r.set(e.apiKeyHeader,n?n.replace(`{key}`,t):t)}let i=await fetch(e.modelsUrl,{headers:r});if(!i.ok)throw Error(`HTTP ${i.status} ${i.statusText}`);let a=await i.json(),o=Array.isArray(a.data)?a.data:Array.isArray(a.models)?a.models:[];for(let e of o){if(!e.id)continue;let t=e.context_length??e.context_window??0,n=e.max_completion_tokens||e.per_request_limits?.completion_tokens||e.top_provider?.max_completion_tokens||null,r=typeof e.supports_tools==`boolean`?e.supports_tools:typeof e.supportsTools==`boolean`?e.supportsTools:void 0,i=this.extractModalities(e,`input`),a=this.extractModalities(e,`output`),o=this.modalitiesInclude(i,`image`,`vision`),s=this.modalitiesInclude(i,`audio`,`voice`,`hearing`),c=this.modalitiesInclude(i,`video`),l=e.id===`openrouter/free`||this.supportedParametersInclude(e,`image`,`vision`,`audio`,`tool`,`structured`),u=this.extractReasoning(e),d=typeof e.supports_prompt_caching==`boolean`?e.supports_prompt_caching:typeof e.supportsPromptCaching==`boolean`?e.supportsPromptCaching:this.supportedParametersInclude(e,`cache_control`,`prompt_caching`)?!0:void 0;!t&&Array.isArray(e.providers)&&e.providers.length>0&&(t=e.providers[0]?.context_length||0),this.registerModelInfo(e.id,{contextWindow:t,maxOutput:n,...r!==void 0&&{supportsTools:r},...i.length>0&&{inputModalities:i},...a.length>0&&{outputModalities:a},...o!==void 0&&{supportsImageInput:o},...s!==void 0&&{supportsAudioInput:s},...c!==void 0&&{supportsVideoInput:c},...u&&{reasoning:u},...l&&{routesByRequestFeatures:l},...d!==void 0&&{supportsPromptCaching:d}})}o.length>0&&console.log(`[ModelRegistry] Registered ${o.length} models for provider "${e.id}"`)}catch(t){console.error(`[ModelRegistry] Error fetching models for ${e.id}:`,t)}finally{this.loading=!1}}}extractModalities(e,t){let n=t===`input`?e.input_modalities||e.inputModalities:e.output_modalities||e.outputModalities,r=e.architecture||{},i=t===`input`?r.input_modalities||r.inputModalities:r.output_modalities||r.outputModalities,a=typeof r.modality==`string`?r.modality:``,o=this.parseArchitectureModality(a,t),s=[...this.normalizeStringArray(n),...this.normalizeStringArray(i),...o];return Array.from(new Set(s))}extractReasoning(e){let t=e?.reasoning;if(!t||typeof t!=`object`)return;let n=this.normalizeStringArray(t.supported_efforts),r=typeof t.default_effort==`string`?t.default_effort.toLowerCase():void 0,i=typeof t.default_enabled==`boolean`?t.default_enabled:void 0,a=typeof t.supports_max_tokens==`boolean`?t.supports_max_tokens:void 0,o=typeof t.mandatory==`boolean`?t.mandatory:void 0;if(!(n.length===0&&r===void 0&&i===void 0&&a===void 0&&o===void 0))return{...n.length>0&&{supportedEfforts:n},...r!==void 0&&{defaultEffort:r},...i!==void 0&&{defaultEnabled:i},...a!==void 0&&{supportsMaxTokens:a},...o!==void 0&&{mandatory:o}}}modalitiesInclude(e,...t){if(e.length!==0)return t.some(t=>e.some(e=>e.includes(t)))}normalizeStringArray(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`).map(e=>e.toLowerCase()):[]}parseArchitectureModality(e,t){if(!e)return[];let[n=``,r=``]=e.toLowerCase().split(`->`).map(e=>e.trim());return(t===`input`?n:r).split(/[+,/\s]+/).map(e=>e.trim()).filter(Boolean)}supportedParametersInclude(e,...t){let n=this.normalizeStringArray(e.supported_parameters||e.supportedParameters);return t.some(e=>n.some(t=>t.includes(e)))}};function c(e){return e.replace(/^\/+|\/+$/g,``)}function l(e){let t=c(e);return t.endsWith(`/index.html`)?t=t.slice(0,-11):t.endsWith(`index.html`)&&(t=t.slice(0,-10)),c(t)}function u(e){let t=c(e),n=t.split(`/`).filter(Boolean);if(n.length===0)return null;let r=n[0].toLowerCase();if(r===`pages`){if(n.length>=3){let e=n[1];return{page:`pages`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e,path:n.slice(2).join(`/`)}}return{page:`pages`,groupId:`br:main`,path:n.slice(1).join(`/`)}}if(r===`files`){let e=n[1]||`main`;return{page:`files`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e,path:n.slice(2).join(`/`)||void 0}}if(r===`chat`){let e=n[1]||`main`;return{page:`chat`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e}}if(r===`tasks`){let e=n[1]||`main`;return{page:`tasks`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e}}return r===`main`?{page:`pages`,groupId:`br:main`,path:n.slice(1).join(`/`)}:{page:`pages`,groupId:`br:main`,path:t}}function d(){if(typeof document<`u`){let e=document.getElementById(`shadow-claw-static-routing`);if(e&&e.textContent)try{let t=JSON.parse(e.textContent);if(t&&typeof t==`object`&&t.routes)return t}catch(e){console.warn(`Failed to parse embedded static routing manifest:`,e)}}return null}function f(e,t){let n=t||d();if(!n||!n.routes)return null;let r=l(e);if(!r)return null;for(let[e,t]of Object.entries(n.routes))if(!(!t||!t.prettyPath)&&l(t.prettyPath)===r)return u(e);return null}let p=null,ee=new Set([`chat`,`files`,`tasks`,`pages`,`settings`,`tools`,`channels`]);function m(){p=null}typeof globalThis<`u`&&(globalThis.__applyBasePathCacheReset=m);function h(){let e=typeof window<`u`?window:typeof self<`u`?self:globalThis;if(e&&e.__SHADOWCLAW_DEPLOY_ID__){let t=String(e.__SHADOWCLAW_DEPLOY_ID__).trim();if(t)return t.replace(/[^a-zA-Z0-9_-]/g,`-`)}let t=globalThis.process;if(t&&t.env&&t.env.SHADOWCLAW_DEPLOY_ID){let e=String(t.env.SHADOWCLAW_DEPLOY_ID).trim();if(e)return e.replace(/[^a-zA-Z0-9_-]/g,`-`)}let n=te();return!n||n===`/`?``:n.replace(/^\/+|\/+$/g,``).replace(/[^a-zA-Z0-9_-]/g,`-`)}function te(){if(p!==null)return p;if((typeof window>`u`||globalThis.WorkerGlobalScope!==void 0&&typeof self<`u`&&self instanceof globalThis.WorkerGlobalScope)&&typeof self<`u`&&self.location){let e=(self.location.pathname||`/`).split(`/`).filter(Boolean);if(e.length<=1)return p=`/`,p;let t=e[0].toLowerCase(),n=t===`service-worker.js`||t===`sw.js`||t===`manifest.json`||t===`sitemap.xml`||t===`favicon.ico`||t===`index.html`||t===`service-worker`||t===`assets`||t===`dist`||t===`public`;if(n&&e.length===2)return p=`/`,p;if(!n)return p=`/`+e[0]+`/`,p}let e=typeof window<`u`&&window.location?window.location:typeof self<`u`&&self.location?self.location:null;if(!e)return`/`;if(typeof document<`u`&&typeof document.querySelector==`function`){let t=document.querySelector(`base[href]`);if(t){let n=t.getAttribute(`href`);if(n)try{let t=new URL(n,e.origin).pathname;return t.endsWith(`/`)||(t+=`/`),p=t,p}catch{}}}let t=e.pathname||`/`;if(t===`/`)return p=`/`,p;let n=t.split(`/`).filter(Boolean),r=n.findIndex(e=>ee.has(e.toLowerCase()));return r>=0?r===0?(p=`/`,p):(p=`/`+n.slice(0,r).join(`/`)+`/`,p):f(t)?(p=`/`,p):n.length===1&&!t.includes(`.`)?(p=`/`+n[0]+`/`,p):(p=`/`,p)}function ne(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`(^|\\s)@${t}\\b`,`i`)}ne(`ShadowClaw`);function g(){let e=h();return e?`shadowclaw-${e}`:`shadowclaw`}g();let _={github:{providerId:`github`,name:`GitHub`,aliases:[`github`,`api.github.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`token `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://github.com/login/oauth/authorize`,tokenUrl:`https://github.com/login/oauth/access_token`,defaultScopes:[`repo`,`read:user`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},gitlab:{providerId:`gitlab`,name:`GitLab`,aliases:[`gitlab`,`gitlab.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`PRIVATE-TOKEN`,headerPrefix:``},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},tokenAuthByServiceType:{git_remote:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}}},oauth:{authorizeUrl:`https://gitlab.com/oauth/authorize`,tokenUrl:`https://gitlab.com/oauth/token`,defaultScopes:[`read_api`,`read_user`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},figma:{providerId:`figma`,name:`Figma`,aliases:[`figma`,`api.figma.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`X-Figma-Token`,headerPrefix:``},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://www.figma.com/oauth`,tokenUrl:`https://api.figma.com/v1/oauth/token`,refreshUrl:`https://api.figma.com/v1/oauth/refresh`,defaultScopes:[],usePkce:!0,clientAuthMethod:`basic_header`,scopeSeparator:`space`}},notion:{providerId:`notion`,name:`Notion`,aliases:[`notion`,`api.notion.com`,`notion.so`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://api.notion.com/v1/oauth/authorize`,tokenUrl:`https://api.notion.com/v1/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`basic_header`,scopeSeparator:`space`}},microsoft_graph:{providerId:`microsoft_graph`,name:`Microsoft Graph`,aliases:[`microsoft`,`graph.microsoft.com`,`microsoft_graph`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://login.microsoftonline.com/common/oauth2/v2.0/authorize`,tokenUrl:`https://login.microsoftonline.com/common/oauth2/v2.0/token`,defaultScopes:[`openid`,`profile`,`offline_access`,`User.Read`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},yahoo_mail:{providerId:`yahoo_mail`,name:`Yahoo Mail`,aliases:[`yahoo`,`yahoo_mail`,`mail.yahoo.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://api.login.yahoo.com/oauth2/request_auth`,tokenUrl:`https://api.login.yahoo.com/oauth2/get_token`,defaultScopes:[`mail-r`,`mail-w`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},google:{providerId:`google`,name:`Google`,aliases:[`google`,`googleapis.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://accounts.google.com/o/oauth2/v2/auth`,tokenUrl:`https://oauth2.googleapis.com/token`,defaultScopes:[`openid`,`profile`,`email`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},atlassian:{providerId:`atlassian`,name:`Atlassian`,aliases:[`atlassian`,`api.atlassian.com`],modes:[`oauth`,`token`,`basic`],defaultMode:`basic`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`,`basic_userpass`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `},basic:{headerName:`Authorization`,headerPrefix:`Basic `}},oauth:{authorizeUrl:`https://auth.atlassian.com/authorize`,tokenUrl:`https://auth.atlassian.com/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},slack:{providerId:`slack`,name:`Slack`,aliases:[`slack`,`slack.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://slack.com/oauth/v2/authorize`,tokenUrl:`https://slack.com/api/oauth.v2.access`,defaultScopes:[],usePkce:!1,clientAuthMethod:`request_body`,scopeSeparator:`comma`}},linear:{providerId:`linear`,name:`Linear`,aliases:[`linear`,`api.linear.app`,`linear.app`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://linear.app/oauth/authorize`,tokenUrl:`https://api.linear.app/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},azure_devops:{providerId:`azure_devops`,name:`Azure DevOps`,aliases:[`azure_devops`,`dev.azure.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`,`basic_userpass`,`ssh_key`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},tokenAuthByServiceType:{git_remote:{token:{headerName:`Authorization`,headerPrefix:`Basic `},oauth:{headerName:`Authorization`,headerPrefix:`Basic `}}},oauth:{authorizeUrl:`https://app.vssps.visualstudio.com/oauth2/authorize`,tokenUrl:`https://app.vssps.visualstudio.com/oauth2/token`,defaultScopes:[`vso.code`,`vso.profile`,`offline_access`],usePkce:!1,clientAuthMethod:`request_body`,scopeSeparator:`space`}},custom_mcp:{providerId:`custom_mcp`,name:`Custom MCP`,aliases:[`custom_mcp`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`mcp_remote`,`webmcp_local`],authTypes:[`none`,`token`,`oauth`,`custom_header`,`ssh_key`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://example.com/oauth/authorize`,tokenUrl:`https://example.com/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}}};Object.fromEntries(Object.values(_).filter(e=>!!e.oauth).map(e=>{let t=e.oauth;return[e.providerId,{id:e.providerId,name:e.name,authorizeUrl:t.authorizeUrl,tokenUrl:t.tokenUrl,redirectUri:t.redirectUri,defaultScopes:t.defaultScopes,usePkce:t.usePkce,clientAuthMethod:t.clientAuthMethod,scopeSeparator:t.scopeSeparator}]})),Object.fromEntries(Object.values(_).map(e=>[e.providerId,{providerId:e.providerId,modes:e.modes,defaultMode:e.defaultMode}])),new Promise(e=>{});
3
3
  /*! @license DOMPurify 3.4.13 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.13/LICENSE */
4
4
  function v(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function y(e){if(Array.isArray(e))return e}function b(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t!==0)for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function re(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="72143ec88485970231da8c06ecf74089dd580224" /><meta name="version" content="1.35.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - Browser-native AI agent." /><link rel="canonical" href="https://xt-ml.github.io/shadow-claw/"><meta property="og:title" content="ShadowClaw"><meta property="og:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta property="og:type" content="website"><meta property="og:url" content="https://xt-ml.github.io/shadow-claw/"><meta property="og:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="ShadowClaw"><meta name="twitter:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta name="twitter:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"SoftwareApplication","@id":"https://xt-ml.github.io/shadow-claw/#software","name":"ShadowClaw","description":"Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.","url":"https://xt-ml.github.io/shadow-claw/","applicationCategory":"DeveloperApplication","operatingSystem":"Web, Browser, Desktop","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"author":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"},"codeRepository":"https://github.com/xt-ml/shadow-claw","license":"https://github.com/xt-ml/shadow-claw/blob/main/LICENSE"},{"@type":"WebSite","@id":"https://xt-ml.github.io/shadow-claw/#website","url":"https://xt-ml.github.io/shadow-claw/","name":"ShadowClaw","description":"Official website and live deployment of ShadowClaw browser-native AI assistant.","publisher":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"}},{"@type":"Organization","@id":"https://xt-ml.github.io/shadow-claw/#organization","name":"xt-ml","url":"https://github.com/xt-ml","sameAs":["https://github.com/xt-ml"]}]}</script><meta name="theme-color" content="#fff" /><meta http-equiv="origin-trial" content="A88uTgESYWcVgREKVReKB6jom41uP8TzW6ei3jNdidf+Xl6ONqKRjKNBphsxhrZmdkakLK3oXDgkGq53rtZYSAMAAAB2eyJvcmlnaW4iOiJodHRwczovL3h0LW1sLmdpdGh1Yi5pbzo0NDMiLCJmZWF0dXJlIjoiV2ViTUNQIiwiZXhwaXJ5IjoxNzk0ODczNjAwLCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ=="><base href="/shadow-claw/" /><script id="shadow-claw-site-config" type="application/json">{"$schema":"https:\u002f\u002fjson-schema.org\u002fdraft\u002f2020-12\u002fschema","site":{"title":"ShadowClaw","description":"ShadowClaw - Browser-native AI agent.","themeColor":"#fff"},"branding":{"faviconPath":"assets\u002ficons\u002ffavicon.ico","appleTouchIconPath":"assets\u002ficons\u002f180.png","notFoundPath":"404.html"},"pwa":{"manifestPath":"manifest.json","themeColor":"#000000"},"sitemapPath":"sitemap.xml","assets":["assets"],"sidebar":{"pagesHidden":false,"chatHidden":false,"tasksHidden":false,"filesHidden":false,"defaultPage":"pages"},"settings":{"defaultToolsProfile":"__builtin_default"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"],"scripts":[{"src":"https:\u002f\u002fkherrick.github.io\u002fblock-garden-knowledge-hub\u002f.agents\u002fscripts\u002fmain\u002fblock-garden-adapter.js","hasInit":true},"https:\u002f\u002fkherrick.github.io\u002fblock-garden\u002fblock-garden-bundle-min.mjs"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
1
+ <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="c9c194eb19a561ec3f67a803f0e078e361735425" /><meta name="version" content="1.36.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - Browser-native AI agent." /><link rel="canonical" href="https://xt-ml.github.io/shadow-claw/"><meta property="og:title" content="ShadowClaw"><meta property="og:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta property="og:type" content="website"><meta property="og:url" content="https://xt-ml.github.io/shadow-claw/"><meta property="og:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="ShadowClaw"><meta name="twitter:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta name="twitter:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"SoftwareApplication","@id":"https://xt-ml.github.io/shadow-claw/#software","name":"ShadowClaw","description":"Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.","url":"https://xt-ml.github.io/shadow-claw/","applicationCategory":"DeveloperApplication","operatingSystem":"Web, Browser, Desktop","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"author":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"},"codeRepository":"https://github.com/xt-ml/shadow-claw","license":"https://github.com/xt-ml/shadow-claw/blob/main/LICENSE"},{"@type":"WebSite","@id":"https://xt-ml.github.io/shadow-claw/#website","url":"https://xt-ml.github.io/shadow-claw/","name":"ShadowClaw","description":"Official website and live deployment of ShadowClaw browser-native AI assistant.","publisher":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"}},{"@type":"Organization","@id":"https://xt-ml.github.io/shadow-claw/#organization","name":"xt-ml","url":"https://github.com/xt-ml","sameAs":["https://github.com/xt-ml"]}]}</script><meta name="theme-color" content="#fff" /><meta http-equiv="origin-trial" content="A88uTgESYWcVgREKVReKB6jom41uP8TzW6ei3jNdidf+Xl6ONqKRjKNBphsxhrZmdkakLK3oXDgkGq53rtZYSAMAAAB2eyJvcmlnaW4iOiJodHRwczovL3h0LW1sLmdpdGh1Yi5pbzo0NDMiLCJmZWF0dXJlIjoiV2ViTUNQIiwiZXhwaXJ5IjoxNzk0ODczNjAwLCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ=="><base href="/shadow-claw/" /><script id="shadow-claw-site-config" type="application/json">{"$schema":"https:\u002f\u002fjson-schema.org\u002fdraft\u002f2020-12\u002fschema","site":{"title":"ShadowClaw","description":"ShadowClaw - Browser-native AI agent.","themeColor":"#fff"},"branding":{"faviconPath":"assets\u002ficons\u002ffavicon.ico","appleTouchIconPath":"assets\u002ficons\u002f180.png","notFoundPath":"404.html"},"pwa":{"manifestPath":"manifest.json","themeColor":"#000000"},"sitemapPath":"sitemap.xml","assets":["assets"],"sidebar":{"pagesHidden":false,"chatHidden":false,"tasksHidden":false,"filesHidden":false,"defaultPage":"pages"},"settings":{"defaultToolsProfile":"__builtin_default"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"],"scripts":[{"src":"https:\u002f\u002fkherrick.github.io\u002fblock-garden-knowledge-hub\u002f.agents\u002fscripts\u002fmain\u002fblock-garden-adapter.js","hasInit":true},"https:\u002f\u002fkherrick.github.io\u002fblock-garden\u002fblock-garden-bundle-min.mjs"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
2
2
  <script>var ShadowClawThemeInit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);function n(){if(globalThis.trustedTypes)return;let e=new Map;globalThis.trustedTypes={createPolicy:(t,n)=>{if(e.has(t))throw TypeError(`Policy with name "${t}" already exists.`);let r={createHTML:n.createHTML?e=>n.createHTML(e):void 0,createScriptURL:n.createScriptURL?e=>n.createScriptURL(e):void 0,createScript:n.createScript?e=>n.createScript(e):void 0};return e.set(t,r),r},getPolicy:t=>e.get(t)??null,isHTML:e=>typeof e==`string`||e instanceof Object&&`toString`in e,isScriptURL:e=>typeof e==`string`||e instanceof Object&&`toString`in e,isScript:e=>typeof e==`string`||e instanceof Object&&`toString`in e}}let r=`__shadowClawDefaultTrustedTypesPolicyState`,i=`default`,a=`shadowclaw-sandbox`;function o(){let e=globalThis;return e[r]||(e[r]={initialized:!1,policy:null}),e[r]}function s(){let e=o();if(e.initialized)return;let t=Reflect.get(globalThis,`trustedTypes`);if(!(!t||typeof t.createPolicy!=`function`)){e.initialized=!0;try{if(typeof t.getPolicy==`function`){let n=t.getPolicy(i);if(n){e.policy=n;return}}let n=!1;if(typeof t.getPolicyNames==`function`){let e=t.getPolicyNames();Array.isArray(e)&&e.includes(i)&&(n=!0)}if(n){if(typeof t.getPolicy==`function`){let n=t.getPolicy(a);if(n){e.policy=n;return}}e.policy=t.createPolicy(a,{createHTML:e=>e,createScriptURL:e=>e});return}e.policy=t.createPolicy(i,{createHTML:e=>e,createScriptURL:e=>e})}catch{typeof t.getPolicy==`function`&&(e.policy=t.getPolicy(i)??t.getPolicy(a)??null)}}}new class{loading=!1;models=new Map;getModelInfo(e){if(!e||typeof e!=`string`)return null;let t=e.toLowerCase().trim(),n=this.models.get(t);if(n)return n;if(t.includes(`/`)){let e=t.split(`/`).pop();if(e&&this.models.has(e))return this.models.get(e)}else for(let[e,n]of this.models.entries())if(e.endsWith(`/${t}`))return n;if(t.includes(`:`)){let e=t.split(`:`)[0],n=this.getModelInfo(e);if(n)return n}return null}registerModelInfo(e,t){this.models.set(e.toLowerCase(),t)}clear(){this.models.clear()}async fetchModelInfo(e,t,n){if(e.modelsUrl){this.loading=!0;try{let r=new Headers;if(r.set(`Content-Type`,`application/json`),e.headers)for(let[t,n]of Object.entries(e.headers))r.set(t,n);if(n)for(let[e,t]of Object.entries(n))r.set(e,t);if(t&&e.apiKeyHeader){let n=e.apiKeyHeaderFormat;r.set(e.apiKeyHeader,n?n.replace(`{key}`,t):t)}let i=await fetch(e.modelsUrl,{headers:r});if(!i.ok)throw Error(`HTTP ${i.status} ${i.statusText}`);let a=await i.json(),o=Array.isArray(a.data)?a.data:Array.isArray(a.models)?a.models:[];for(let e of o){if(!e.id)continue;let t=e.context_length??e.context_window??0,n=e.max_completion_tokens||e.per_request_limits?.completion_tokens||e.top_provider?.max_completion_tokens||null,r=typeof e.supports_tools==`boolean`?e.supports_tools:typeof e.supportsTools==`boolean`?e.supportsTools:void 0,i=this.extractModalities(e,`input`),a=this.extractModalities(e,`output`),o=this.modalitiesInclude(i,`image`,`vision`),s=this.modalitiesInclude(i,`audio`,`voice`,`hearing`),c=this.modalitiesInclude(i,`video`),l=e.id===`openrouter/free`||this.supportedParametersInclude(e,`image`,`vision`,`audio`,`tool`,`structured`),u=this.extractReasoning(e),d=typeof e.supports_prompt_caching==`boolean`?e.supports_prompt_caching:typeof e.supportsPromptCaching==`boolean`?e.supportsPromptCaching:this.supportedParametersInclude(e,`cache_control`,`prompt_caching`)?!0:void 0;!t&&Array.isArray(e.providers)&&e.providers.length>0&&(t=e.providers[0]?.context_length||0),this.registerModelInfo(e.id,{contextWindow:t,maxOutput:n,...r!==void 0&&{supportsTools:r},...i.length>0&&{inputModalities:i},...a.length>0&&{outputModalities:a},...o!==void 0&&{supportsImageInput:o},...s!==void 0&&{supportsAudioInput:s},...c!==void 0&&{supportsVideoInput:c},...u&&{reasoning:u},...l&&{routesByRequestFeatures:l},...d!==void 0&&{supportsPromptCaching:d}})}o.length>0&&console.log(`[ModelRegistry] Registered ${o.length} models for provider "${e.id}"`)}catch(t){console.error(`[ModelRegistry] Error fetching models for ${e.id}:`,t)}finally{this.loading=!1}}}extractModalities(e,t){let n=t===`input`?e.input_modalities||e.inputModalities:e.output_modalities||e.outputModalities,r=e.architecture||{},i=t===`input`?r.input_modalities||r.inputModalities:r.output_modalities||r.outputModalities,a=typeof r.modality==`string`?r.modality:``,o=this.parseArchitectureModality(a,t),s=[...this.normalizeStringArray(n),...this.normalizeStringArray(i),...o];return Array.from(new Set(s))}extractReasoning(e){let t=e?.reasoning;if(!t||typeof t!=`object`)return;let n=this.normalizeStringArray(t.supported_efforts),r=typeof t.default_effort==`string`?t.default_effort.toLowerCase():void 0,i=typeof t.default_enabled==`boolean`?t.default_enabled:void 0,a=typeof t.supports_max_tokens==`boolean`?t.supports_max_tokens:void 0,o=typeof t.mandatory==`boolean`?t.mandatory:void 0;if(!(n.length===0&&r===void 0&&i===void 0&&a===void 0&&o===void 0))return{...n.length>0&&{supportedEfforts:n},...r!==void 0&&{defaultEffort:r},...i!==void 0&&{defaultEnabled:i},...a!==void 0&&{supportsMaxTokens:a},...o!==void 0&&{mandatory:o}}}modalitiesInclude(e,...t){if(e.length!==0)return t.some(t=>e.some(e=>e.includes(t)))}normalizeStringArray(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`).map(e=>e.toLowerCase()):[]}parseArchitectureModality(e,t){if(!e)return[];let[n=``,r=``]=e.toLowerCase().split(`->`).map(e=>e.trim());return(t===`input`?n:r).split(/[+,/\s]+/).map(e=>e.trim()).filter(Boolean)}supportedParametersInclude(e,...t){let n=this.normalizeStringArray(e.supported_parameters||e.supportedParameters);return t.some(e=>n.some(t=>t.includes(e)))}};function c(e){return e.replace(/^\/+|\/+$/g,``)}function l(e){let t=c(e);return t.endsWith(`/index.html`)?t=t.slice(0,-11):t.endsWith(`index.html`)&&(t=t.slice(0,-10)),c(t)}function u(e){let t=c(e),n=t.split(`/`).filter(Boolean);if(n.length===0)return null;let r=n[0].toLowerCase();if(r===`pages`){if(n.length>=3){let e=n[1];return{page:`pages`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e,path:n.slice(2).join(`/`)}}return{page:`pages`,groupId:`br:main`,path:n.slice(1).join(`/`)}}if(r===`files`){let e=n[1]||`main`;return{page:`files`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e,path:n.slice(2).join(`/`)||void 0}}if(r===`chat`){let e=n[1]||`main`;return{page:`chat`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e}}if(r===`tasks`){let e=n[1]||`main`;return{page:`tasks`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e}}return r===`main`?{page:`pages`,groupId:`br:main`,path:n.slice(1).join(`/`)}:{page:`pages`,groupId:`br:main`,path:t}}function d(){if(typeof document<`u`){let e=document.getElementById(`shadow-claw-static-routing`);if(e&&e.textContent)try{let t=JSON.parse(e.textContent);if(t&&typeof t==`object`&&t.routes)return t}catch(e){console.warn(`Failed to parse embedded static routing manifest:`,e)}}return null}function f(e,t){let n=t||d();if(!n||!n.routes)return null;let r=l(e);if(!r)return null;for(let[e,t]of Object.entries(n.routes))if(!(!t||!t.prettyPath)&&l(t.prettyPath)===r)return u(e);return null}let p=null,ee=new Set([`chat`,`files`,`tasks`,`pages`,`settings`,`tools`,`channels`]);function m(){p=null}typeof globalThis<`u`&&(globalThis.__applyBasePathCacheReset=m);function h(){let e=typeof window<`u`?window:typeof self<`u`?self:globalThis;if(e&&e.__SHADOWCLAW_DEPLOY_ID__){let t=String(e.__SHADOWCLAW_DEPLOY_ID__).trim();if(t)return t.replace(/[^a-zA-Z0-9_-]/g,`-`)}let t=globalThis.process;if(t&&t.env&&t.env.SHADOWCLAW_DEPLOY_ID){let e=String(t.env.SHADOWCLAW_DEPLOY_ID).trim();if(e)return e.replace(/[^a-zA-Z0-9_-]/g,`-`)}let n=te();return!n||n===`/`?``:n.replace(/^\/+|\/+$/g,``).replace(/[^a-zA-Z0-9_-]/g,`-`)}function te(){if(p!==null)return p;if((typeof window>`u`||globalThis.WorkerGlobalScope!==void 0&&typeof self<`u`&&self instanceof globalThis.WorkerGlobalScope)&&typeof self<`u`&&self.location){let e=(self.location.pathname||`/`).split(`/`).filter(Boolean);if(e.length<=1)return p=`/`,p;let t=e[0].toLowerCase(),n=t===`service-worker.js`||t===`sw.js`||t===`manifest.json`||t===`sitemap.xml`||t===`favicon.ico`||t===`index.html`||t===`service-worker`||t===`assets`||t===`dist`||t===`public`;if(n&&e.length===2)return p=`/`,p;if(!n)return p=`/`+e[0]+`/`,p}let e=typeof window<`u`&&window.location?window.location:typeof self<`u`&&self.location?self.location:null;if(!e)return`/`;if(typeof document<`u`&&typeof document.querySelector==`function`){let t=document.querySelector(`base[href]`);if(t){let n=t.getAttribute(`href`);if(n)try{let t=new URL(n,e.origin).pathname;return t.endsWith(`/`)||(t+=`/`),p=t,p}catch{}}}let t=e.pathname||`/`;if(t===`/`)return p=`/`,p;let n=t.split(`/`).filter(Boolean),r=n.findIndex(e=>ee.has(e.toLowerCase()));return r>=0?r===0?(p=`/`,p):(p=`/`+n.slice(0,r).join(`/`)+`/`,p):f(t)?(p=`/`,p):n.length===1&&!t.includes(`.`)?(p=`/`+n[0]+`/`,p):(p=`/`,p)}function ne(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`(^|\\s)@${t}\\b`,`i`)}ne(`ShadowClaw`);function g(){let e=h();return e?`shadowclaw-${e}`:`shadowclaw`}g();let _={github:{providerId:`github`,name:`GitHub`,aliases:[`github`,`api.github.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`token `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://github.com/login/oauth/authorize`,tokenUrl:`https://github.com/login/oauth/access_token`,defaultScopes:[`repo`,`read:user`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},gitlab:{providerId:`gitlab`,name:`GitLab`,aliases:[`gitlab`,`gitlab.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`PRIVATE-TOKEN`,headerPrefix:``},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},tokenAuthByServiceType:{git_remote:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}}},oauth:{authorizeUrl:`https://gitlab.com/oauth/authorize`,tokenUrl:`https://gitlab.com/oauth/token`,defaultScopes:[`read_api`,`read_user`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},figma:{providerId:`figma`,name:`Figma`,aliases:[`figma`,`api.figma.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`X-Figma-Token`,headerPrefix:``},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://www.figma.com/oauth`,tokenUrl:`https://api.figma.com/v1/oauth/token`,refreshUrl:`https://api.figma.com/v1/oauth/refresh`,defaultScopes:[],usePkce:!0,clientAuthMethod:`basic_header`,scopeSeparator:`space`}},notion:{providerId:`notion`,name:`Notion`,aliases:[`notion`,`api.notion.com`,`notion.so`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://api.notion.com/v1/oauth/authorize`,tokenUrl:`https://api.notion.com/v1/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`basic_header`,scopeSeparator:`space`}},microsoft_graph:{providerId:`microsoft_graph`,name:`Microsoft Graph`,aliases:[`microsoft`,`graph.microsoft.com`,`microsoft_graph`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://login.microsoftonline.com/common/oauth2/v2.0/authorize`,tokenUrl:`https://login.microsoftonline.com/common/oauth2/v2.0/token`,defaultScopes:[`openid`,`profile`,`offline_access`,`User.Read`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},yahoo_mail:{providerId:`yahoo_mail`,name:`Yahoo Mail`,aliases:[`yahoo`,`yahoo_mail`,`mail.yahoo.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://api.login.yahoo.com/oauth2/request_auth`,tokenUrl:`https://api.login.yahoo.com/oauth2/get_token`,defaultScopes:[`mail-r`,`mail-w`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},google:{providerId:`google`,name:`Google`,aliases:[`google`,`googleapis.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://accounts.google.com/o/oauth2/v2/auth`,tokenUrl:`https://oauth2.googleapis.com/token`,defaultScopes:[`openid`,`profile`,`email`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},atlassian:{providerId:`atlassian`,name:`Atlassian`,aliases:[`atlassian`,`api.atlassian.com`],modes:[`oauth`,`token`,`basic`],defaultMode:`basic`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`,`basic_userpass`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `},basic:{headerName:`Authorization`,headerPrefix:`Basic `}},oauth:{authorizeUrl:`https://auth.atlassian.com/authorize`,tokenUrl:`https://auth.atlassian.com/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},slack:{providerId:`slack`,name:`Slack`,aliases:[`slack`,`slack.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://slack.com/oauth/v2/authorize`,tokenUrl:`https://slack.com/api/oauth.v2.access`,defaultScopes:[],usePkce:!1,clientAuthMethod:`request_body`,scopeSeparator:`comma`}},linear:{providerId:`linear`,name:`Linear`,aliases:[`linear`,`api.linear.app`,`linear.app`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://linear.app/oauth/authorize`,tokenUrl:`https://api.linear.app/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},azure_devops:{providerId:`azure_devops`,name:`Azure DevOps`,aliases:[`azure_devops`,`dev.azure.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`,`basic_userpass`,`ssh_key`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},tokenAuthByServiceType:{git_remote:{token:{headerName:`Authorization`,headerPrefix:`Basic `},oauth:{headerName:`Authorization`,headerPrefix:`Basic `}}},oauth:{authorizeUrl:`https://app.vssps.visualstudio.com/oauth2/authorize`,tokenUrl:`https://app.vssps.visualstudio.com/oauth2/token`,defaultScopes:[`vso.code`,`vso.profile`,`offline_access`],usePkce:!1,clientAuthMethod:`request_body`,scopeSeparator:`space`}},custom_mcp:{providerId:`custom_mcp`,name:`Custom MCP`,aliases:[`custom_mcp`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`mcp_remote`,`webmcp_local`],authTypes:[`none`,`token`,`oauth`,`custom_header`,`ssh_key`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://example.com/oauth/authorize`,tokenUrl:`https://example.com/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}}};Object.fromEntries(Object.values(_).filter(e=>!!e.oauth).map(e=>{let t=e.oauth;return[e.providerId,{id:e.providerId,name:e.name,authorizeUrl:t.authorizeUrl,tokenUrl:t.tokenUrl,redirectUri:t.redirectUri,defaultScopes:t.defaultScopes,usePkce:t.usePkce,clientAuthMethod:t.clientAuthMethod,scopeSeparator:t.scopeSeparator}]})),Object.fromEntries(Object.values(_).map(e=>[e.providerId,{providerId:e.providerId,modes:e.modes,defaultMode:e.defaultMode}])),new Promise(e=>{});
3
3
  /*! @license DOMPurify 3.4.13 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.13/LICENSE */
4
4
  function v(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function y(e){if(Array.isArray(e))return e}function b(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t!==0)for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function re(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="72143ec88485970231da8c06ecf74089dd580224" /><meta name="version" content="1.35.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - Browser-native AI agent." /><link rel="canonical" href="https://xt-ml.github.io/shadow-claw/"><meta property="og:title" content="ShadowClaw"><meta property="og:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta property="og:type" content="website"><meta property="og:url" content="https://xt-ml.github.io/shadow-claw/"><meta property="og:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="ShadowClaw"><meta name="twitter:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta name="twitter:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"SoftwareApplication","@id":"https://xt-ml.github.io/shadow-claw/#software","name":"ShadowClaw","description":"Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.","url":"https://xt-ml.github.io/shadow-claw/","applicationCategory":"DeveloperApplication","operatingSystem":"Web, Browser, Desktop","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"author":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"},"codeRepository":"https://github.com/xt-ml/shadow-claw","license":"https://github.com/xt-ml/shadow-claw/blob/main/LICENSE"},{"@type":"WebSite","@id":"https://xt-ml.github.io/shadow-claw/#website","url":"https://xt-ml.github.io/shadow-claw/","name":"ShadowClaw","description":"Official website and live deployment of ShadowClaw browser-native AI assistant.","publisher":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"}},{"@type":"Organization","@id":"https://xt-ml.github.io/shadow-claw/#organization","name":"xt-ml","url":"https://github.com/xt-ml","sameAs":["https://github.com/xt-ml"]}]}</script><meta name="theme-color" content="#fff" /><meta http-equiv="origin-trial" content="A88uTgESYWcVgREKVReKB6jom41uP8TzW6ei3jNdidf+Xl6ONqKRjKNBphsxhrZmdkakLK3oXDgkGq53rtZYSAMAAAB2eyJvcmlnaW4iOiJodHRwczovL3h0LW1sLmdpdGh1Yi5pbzo0NDMiLCJmZWF0dXJlIjoiV2ViTUNQIiwiZXhwaXJ5IjoxNzk0ODczNjAwLCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ=="><base href="/shadow-claw/" /><script id="shadow-claw-site-config" type="application/json">{"$schema":"https:\u002f\u002fjson-schema.org\u002fdraft\u002f2020-12\u002fschema","site":{"title":"ShadowClaw","description":"ShadowClaw - Browser-native AI agent.","themeColor":"#fff"},"branding":{"faviconPath":"assets\u002ficons\u002ffavicon.ico","appleTouchIconPath":"assets\u002ficons\u002f180.png","notFoundPath":"404.html"},"pwa":{"manifestPath":"manifest.json","themeColor":"#000000"},"sitemapPath":"sitemap.xml","assets":["assets"],"sidebar":{"pagesHidden":false,"chatHidden":false,"tasksHidden":false,"filesHidden":false,"defaultPage":"pages"},"settings":{"defaultToolsProfile":"__builtin_default"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"],"scripts":[{"src":"https:\u002f\u002fkherrick.github.io\u002fblock-garden-knowledge-hub\u002f.agents\u002fscripts\u002fmain\u002fblock-garden-adapter.js","hasInit":true},"https:\u002f\u002fkherrick.github.io\u002fblock-garden\u002fblock-garden-bundle-min.mjs"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
1
+ <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="c9c194eb19a561ec3f67a803f0e078e361735425" /><meta name="version" content="1.36.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - Browser-native AI agent." /><link rel="canonical" href="https://xt-ml.github.io/shadow-claw/"><meta property="og:title" content="ShadowClaw"><meta property="og:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta property="og:type" content="website"><meta property="og:url" content="https://xt-ml.github.io/shadow-claw/"><meta property="og:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="ShadowClaw"><meta name="twitter:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta name="twitter:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"SoftwareApplication","@id":"https://xt-ml.github.io/shadow-claw/#software","name":"ShadowClaw","description":"Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.","url":"https://xt-ml.github.io/shadow-claw/","applicationCategory":"DeveloperApplication","operatingSystem":"Web, Browser, Desktop","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"author":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"},"codeRepository":"https://github.com/xt-ml/shadow-claw","license":"https://github.com/xt-ml/shadow-claw/blob/main/LICENSE"},{"@type":"WebSite","@id":"https://xt-ml.github.io/shadow-claw/#website","url":"https://xt-ml.github.io/shadow-claw/","name":"ShadowClaw","description":"Official website and live deployment of ShadowClaw browser-native AI assistant.","publisher":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"}},{"@type":"Organization","@id":"https://xt-ml.github.io/shadow-claw/#organization","name":"xt-ml","url":"https://github.com/xt-ml","sameAs":["https://github.com/xt-ml"]}]}</script><meta name="theme-color" content="#fff" /><meta http-equiv="origin-trial" content="A88uTgESYWcVgREKVReKB6jom41uP8TzW6ei3jNdidf+Xl6ONqKRjKNBphsxhrZmdkakLK3oXDgkGq53rtZYSAMAAAB2eyJvcmlnaW4iOiJodHRwczovL3h0LW1sLmdpdGh1Yi5pbzo0NDMiLCJmZWF0dXJlIjoiV2ViTUNQIiwiZXhwaXJ5IjoxNzk0ODczNjAwLCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ=="><base href="/shadow-claw/" /><script id="shadow-claw-site-config" type="application/json">{"$schema":"https:\u002f\u002fjson-schema.org\u002fdraft\u002f2020-12\u002fschema","site":{"title":"ShadowClaw","description":"ShadowClaw - Browser-native AI agent.","themeColor":"#fff"},"branding":{"faviconPath":"assets\u002ficons\u002ffavicon.ico","appleTouchIconPath":"assets\u002ficons\u002f180.png","notFoundPath":"404.html"},"pwa":{"manifestPath":"manifest.json","themeColor":"#000000"},"sitemapPath":"sitemap.xml","assets":["assets"],"sidebar":{"pagesHidden":false,"chatHidden":false,"tasksHidden":false,"filesHidden":false,"defaultPage":"pages"},"settings":{"defaultToolsProfile":"__builtin_default"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"],"scripts":[{"src":"https:\u002f\u002fkherrick.github.io\u002fblock-garden-knowledge-hub\u002f.agents\u002fscripts\u002fmain\u002fblock-garden-adapter.js","hasInit":true},"https:\u002f\u002fkherrick.github.io\u002fblock-garden\u002fblock-garden-bundle-min.mjs"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
2
2
  <script>var ShadowClawThemeInit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);function n(){if(globalThis.trustedTypes)return;let e=new Map;globalThis.trustedTypes={createPolicy:(t,n)=>{if(e.has(t))throw TypeError(`Policy with name "${t}" already exists.`);let r={createHTML:n.createHTML?e=>n.createHTML(e):void 0,createScriptURL:n.createScriptURL?e=>n.createScriptURL(e):void 0,createScript:n.createScript?e=>n.createScript(e):void 0};return e.set(t,r),r},getPolicy:t=>e.get(t)??null,isHTML:e=>typeof e==`string`||e instanceof Object&&`toString`in e,isScriptURL:e=>typeof e==`string`||e instanceof Object&&`toString`in e,isScript:e=>typeof e==`string`||e instanceof Object&&`toString`in e}}let r=`__shadowClawDefaultTrustedTypesPolicyState`,i=`default`,a=`shadowclaw-sandbox`;function o(){let e=globalThis;return e[r]||(e[r]={initialized:!1,policy:null}),e[r]}function s(){let e=o();if(e.initialized)return;let t=Reflect.get(globalThis,`trustedTypes`);if(!(!t||typeof t.createPolicy!=`function`)){e.initialized=!0;try{if(typeof t.getPolicy==`function`){let n=t.getPolicy(i);if(n){e.policy=n;return}}let n=!1;if(typeof t.getPolicyNames==`function`){let e=t.getPolicyNames();Array.isArray(e)&&e.includes(i)&&(n=!0)}if(n){if(typeof t.getPolicy==`function`){let n=t.getPolicy(a);if(n){e.policy=n;return}}e.policy=t.createPolicy(a,{createHTML:e=>e,createScriptURL:e=>e});return}e.policy=t.createPolicy(i,{createHTML:e=>e,createScriptURL:e=>e})}catch{typeof t.getPolicy==`function`&&(e.policy=t.getPolicy(i)??t.getPolicy(a)??null)}}}new class{loading=!1;models=new Map;getModelInfo(e){if(!e||typeof e!=`string`)return null;let t=e.toLowerCase().trim(),n=this.models.get(t);if(n)return n;if(t.includes(`/`)){let e=t.split(`/`).pop();if(e&&this.models.has(e))return this.models.get(e)}else for(let[e,n]of this.models.entries())if(e.endsWith(`/${t}`))return n;if(t.includes(`:`)){let e=t.split(`:`)[0],n=this.getModelInfo(e);if(n)return n}return null}registerModelInfo(e,t){this.models.set(e.toLowerCase(),t)}clear(){this.models.clear()}async fetchModelInfo(e,t,n){if(e.modelsUrl){this.loading=!0;try{let r=new Headers;if(r.set(`Content-Type`,`application/json`),e.headers)for(let[t,n]of Object.entries(e.headers))r.set(t,n);if(n)for(let[e,t]of Object.entries(n))r.set(e,t);if(t&&e.apiKeyHeader){let n=e.apiKeyHeaderFormat;r.set(e.apiKeyHeader,n?n.replace(`{key}`,t):t)}let i=await fetch(e.modelsUrl,{headers:r});if(!i.ok)throw Error(`HTTP ${i.status} ${i.statusText}`);let a=await i.json(),o=Array.isArray(a.data)?a.data:Array.isArray(a.models)?a.models:[];for(let e of o){if(!e.id)continue;let t=e.context_length??e.context_window??0,n=e.max_completion_tokens||e.per_request_limits?.completion_tokens||e.top_provider?.max_completion_tokens||null,r=typeof e.supports_tools==`boolean`?e.supports_tools:typeof e.supportsTools==`boolean`?e.supportsTools:void 0,i=this.extractModalities(e,`input`),a=this.extractModalities(e,`output`),o=this.modalitiesInclude(i,`image`,`vision`),s=this.modalitiesInclude(i,`audio`,`voice`,`hearing`),c=this.modalitiesInclude(i,`video`),l=e.id===`openrouter/free`||this.supportedParametersInclude(e,`image`,`vision`,`audio`,`tool`,`structured`),u=this.extractReasoning(e),d=typeof e.supports_prompt_caching==`boolean`?e.supports_prompt_caching:typeof e.supportsPromptCaching==`boolean`?e.supportsPromptCaching:this.supportedParametersInclude(e,`cache_control`,`prompt_caching`)?!0:void 0;!t&&Array.isArray(e.providers)&&e.providers.length>0&&(t=e.providers[0]?.context_length||0),this.registerModelInfo(e.id,{contextWindow:t,maxOutput:n,...r!==void 0&&{supportsTools:r},...i.length>0&&{inputModalities:i},...a.length>0&&{outputModalities:a},...o!==void 0&&{supportsImageInput:o},...s!==void 0&&{supportsAudioInput:s},...c!==void 0&&{supportsVideoInput:c},...u&&{reasoning:u},...l&&{routesByRequestFeatures:l},...d!==void 0&&{supportsPromptCaching:d}})}o.length>0&&console.log(`[ModelRegistry] Registered ${o.length} models for provider "${e.id}"`)}catch(t){console.error(`[ModelRegistry] Error fetching models for ${e.id}:`,t)}finally{this.loading=!1}}}extractModalities(e,t){let n=t===`input`?e.input_modalities||e.inputModalities:e.output_modalities||e.outputModalities,r=e.architecture||{},i=t===`input`?r.input_modalities||r.inputModalities:r.output_modalities||r.outputModalities,a=typeof r.modality==`string`?r.modality:``,o=this.parseArchitectureModality(a,t),s=[...this.normalizeStringArray(n),...this.normalizeStringArray(i),...o];return Array.from(new Set(s))}extractReasoning(e){let t=e?.reasoning;if(!t||typeof t!=`object`)return;let n=this.normalizeStringArray(t.supported_efforts),r=typeof t.default_effort==`string`?t.default_effort.toLowerCase():void 0,i=typeof t.default_enabled==`boolean`?t.default_enabled:void 0,a=typeof t.supports_max_tokens==`boolean`?t.supports_max_tokens:void 0,o=typeof t.mandatory==`boolean`?t.mandatory:void 0;if(!(n.length===0&&r===void 0&&i===void 0&&a===void 0&&o===void 0))return{...n.length>0&&{supportedEfforts:n},...r!==void 0&&{defaultEffort:r},...i!==void 0&&{defaultEnabled:i},...a!==void 0&&{supportsMaxTokens:a},...o!==void 0&&{mandatory:o}}}modalitiesInclude(e,...t){if(e.length!==0)return t.some(t=>e.some(e=>e.includes(t)))}normalizeStringArray(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`).map(e=>e.toLowerCase()):[]}parseArchitectureModality(e,t){if(!e)return[];let[n=``,r=``]=e.toLowerCase().split(`->`).map(e=>e.trim());return(t===`input`?n:r).split(/[+,/\s]+/).map(e=>e.trim()).filter(Boolean)}supportedParametersInclude(e,...t){let n=this.normalizeStringArray(e.supported_parameters||e.supportedParameters);return t.some(e=>n.some(t=>t.includes(e)))}};function c(e){return e.replace(/^\/+|\/+$/g,``)}function l(e){let t=c(e);return t.endsWith(`/index.html`)?t=t.slice(0,-11):t.endsWith(`index.html`)&&(t=t.slice(0,-10)),c(t)}function u(e){let t=c(e),n=t.split(`/`).filter(Boolean);if(n.length===0)return null;let r=n[0].toLowerCase();if(r===`pages`){if(n.length>=3){let e=n[1];return{page:`pages`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e,path:n.slice(2).join(`/`)}}return{page:`pages`,groupId:`br:main`,path:n.slice(1).join(`/`)}}if(r===`files`){let e=n[1]||`main`;return{page:`files`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e,path:n.slice(2).join(`/`)||void 0}}if(r===`chat`){let e=n[1]||`main`;return{page:`chat`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e}}if(r===`tasks`){let e=n[1]||`main`;return{page:`tasks`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e}}return r===`main`?{page:`pages`,groupId:`br:main`,path:n.slice(1).join(`/`)}:{page:`pages`,groupId:`br:main`,path:t}}function d(){if(typeof document<`u`){let e=document.getElementById(`shadow-claw-static-routing`);if(e&&e.textContent)try{let t=JSON.parse(e.textContent);if(t&&typeof t==`object`&&t.routes)return t}catch(e){console.warn(`Failed to parse embedded static routing manifest:`,e)}}return null}function f(e,t){let n=t||d();if(!n||!n.routes)return null;let r=l(e);if(!r)return null;for(let[e,t]of Object.entries(n.routes))if(!(!t||!t.prettyPath)&&l(t.prettyPath)===r)return u(e);return null}let p=null,ee=new Set([`chat`,`files`,`tasks`,`pages`,`settings`,`tools`,`channels`]);function m(){p=null}typeof globalThis<`u`&&(globalThis.__applyBasePathCacheReset=m);function h(){let e=typeof window<`u`?window:typeof self<`u`?self:globalThis;if(e&&e.__SHADOWCLAW_DEPLOY_ID__){let t=String(e.__SHADOWCLAW_DEPLOY_ID__).trim();if(t)return t.replace(/[^a-zA-Z0-9_-]/g,`-`)}let t=globalThis.process;if(t&&t.env&&t.env.SHADOWCLAW_DEPLOY_ID){let e=String(t.env.SHADOWCLAW_DEPLOY_ID).trim();if(e)return e.replace(/[^a-zA-Z0-9_-]/g,`-`)}let n=te();return!n||n===`/`?``:n.replace(/^\/+|\/+$/g,``).replace(/[^a-zA-Z0-9_-]/g,`-`)}function te(){if(p!==null)return p;if((typeof window>`u`||globalThis.WorkerGlobalScope!==void 0&&typeof self<`u`&&self instanceof globalThis.WorkerGlobalScope)&&typeof self<`u`&&self.location){let e=(self.location.pathname||`/`).split(`/`).filter(Boolean);if(e.length<=1)return p=`/`,p;let t=e[0].toLowerCase(),n=t===`service-worker.js`||t===`sw.js`||t===`manifest.json`||t===`sitemap.xml`||t===`favicon.ico`||t===`index.html`||t===`service-worker`||t===`assets`||t===`dist`||t===`public`;if(n&&e.length===2)return p=`/`,p;if(!n)return p=`/`+e[0]+`/`,p}let e=typeof window<`u`&&window.location?window.location:typeof self<`u`&&self.location?self.location:null;if(!e)return`/`;if(typeof document<`u`&&typeof document.querySelector==`function`){let t=document.querySelector(`base[href]`);if(t){let n=t.getAttribute(`href`);if(n)try{let t=new URL(n,e.origin).pathname;return t.endsWith(`/`)||(t+=`/`),p=t,p}catch{}}}let t=e.pathname||`/`;if(t===`/`)return p=`/`,p;let n=t.split(`/`).filter(Boolean),r=n.findIndex(e=>ee.has(e.toLowerCase()));return r>=0?r===0?(p=`/`,p):(p=`/`+n.slice(0,r).join(`/`)+`/`,p):f(t)?(p=`/`,p):n.length===1&&!t.includes(`.`)?(p=`/`+n[0]+`/`,p):(p=`/`,p)}function ne(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`(^|\\s)@${t}\\b`,`i`)}ne(`ShadowClaw`);function g(){let e=h();return e?`shadowclaw-${e}`:`shadowclaw`}g();let _={github:{providerId:`github`,name:`GitHub`,aliases:[`github`,`api.github.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`token `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://github.com/login/oauth/authorize`,tokenUrl:`https://github.com/login/oauth/access_token`,defaultScopes:[`repo`,`read:user`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},gitlab:{providerId:`gitlab`,name:`GitLab`,aliases:[`gitlab`,`gitlab.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`PRIVATE-TOKEN`,headerPrefix:``},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},tokenAuthByServiceType:{git_remote:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}}},oauth:{authorizeUrl:`https://gitlab.com/oauth/authorize`,tokenUrl:`https://gitlab.com/oauth/token`,defaultScopes:[`read_api`,`read_user`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},figma:{providerId:`figma`,name:`Figma`,aliases:[`figma`,`api.figma.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`X-Figma-Token`,headerPrefix:``},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://www.figma.com/oauth`,tokenUrl:`https://api.figma.com/v1/oauth/token`,refreshUrl:`https://api.figma.com/v1/oauth/refresh`,defaultScopes:[],usePkce:!0,clientAuthMethod:`basic_header`,scopeSeparator:`space`}},notion:{providerId:`notion`,name:`Notion`,aliases:[`notion`,`api.notion.com`,`notion.so`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://api.notion.com/v1/oauth/authorize`,tokenUrl:`https://api.notion.com/v1/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`basic_header`,scopeSeparator:`space`}},microsoft_graph:{providerId:`microsoft_graph`,name:`Microsoft Graph`,aliases:[`microsoft`,`graph.microsoft.com`,`microsoft_graph`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://login.microsoftonline.com/common/oauth2/v2.0/authorize`,tokenUrl:`https://login.microsoftonline.com/common/oauth2/v2.0/token`,defaultScopes:[`openid`,`profile`,`offline_access`,`User.Read`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},yahoo_mail:{providerId:`yahoo_mail`,name:`Yahoo Mail`,aliases:[`yahoo`,`yahoo_mail`,`mail.yahoo.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://api.login.yahoo.com/oauth2/request_auth`,tokenUrl:`https://api.login.yahoo.com/oauth2/get_token`,defaultScopes:[`mail-r`,`mail-w`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},google:{providerId:`google`,name:`Google`,aliases:[`google`,`googleapis.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://accounts.google.com/o/oauth2/v2/auth`,tokenUrl:`https://oauth2.googleapis.com/token`,defaultScopes:[`openid`,`profile`,`email`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},atlassian:{providerId:`atlassian`,name:`Atlassian`,aliases:[`atlassian`,`api.atlassian.com`],modes:[`oauth`,`token`,`basic`],defaultMode:`basic`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`,`basic_userpass`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `},basic:{headerName:`Authorization`,headerPrefix:`Basic `}},oauth:{authorizeUrl:`https://auth.atlassian.com/authorize`,tokenUrl:`https://auth.atlassian.com/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},slack:{providerId:`slack`,name:`Slack`,aliases:[`slack`,`slack.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://slack.com/oauth/v2/authorize`,tokenUrl:`https://slack.com/api/oauth.v2.access`,defaultScopes:[],usePkce:!1,clientAuthMethod:`request_body`,scopeSeparator:`comma`}},linear:{providerId:`linear`,name:`Linear`,aliases:[`linear`,`api.linear.app`,`linear.app`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://linear.app/oauth/authorize`,tokenUrl:`https://api.linear.app/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},azure_devops:{providerId:`azure_devops`,name:`Azure DevOps`,aliases:[`azure_devops`,`dev.azure.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`,`basic_userpass`,`ssh_key`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},tokenAuthByServiceType:{git_remote:{token:{headerName:`Authorization`,headerPrefix:`Basic `},oauth:{headerName:`Authorization`,headerPrefix:`Basic `}}},oauth:{authorizeUrl:`https://app.vssps.visualstudio.com/oauth2/authorize`,tokenUrl:`https://app.vssps.visualstudio.com/oauth2/token`,defaultScopes:[`vso.code`,`vso.profile`,`offline_access`],usePkce:!1,clientAuthMethod:`request_body`,scopeSeparator:`space`}},custom_mcp:{providerId:`custom_mcp`,name:`Custom MCP`,aliases:[`custom_mcp`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`mcp_remote`,`webmcp_local`],authTypes:[`none`,`token`,`oauth`,`custom_header`,`ssh_key`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://example.com/oauth/authorize`,tokenUrl:`https://example.com/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}}};Object.fromEntries(Object.values(_).filter(e=>!!e.oauth).map(e=>{let t=e.oauth;return[e.providerId,{id:e.providerId,name:e.name,authorizeUrl:t.authorizeUrl,tokenUrl:t.tokenUrl,redirectUri:t.redirectUri,defaultScopes:t.defaultScopes,usePkce:t.usePkce,clientAuthMethod:t.clientAuthMethod,scopeSeparator:t.scopeSeparator}]})),Object.fromEntries(Object.values(_).map(e=>[e.providerId,{providerId:e.providerId,modes:e.modes,defaultMode:e.defaultMode}])),new Promise(e=>{});
3
3
  /*! @license DOMPurify 3.4.13 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.13/LICENSE */
4
4
  function v(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function y(e){if(Array.isArray(e))return e}function b(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t!==0)for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function re(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
@@ -493,15 +493,16 @@ npx shadow-claw skills:index --stdout --no-write
493
493
  npx shadow-claw skills:index --out-file custom/discovery/index.json
494
494
  ```
495
495
 
496
- | Option | Type | Description | Default |
497
- | :---------------------- | :------ | :----------------------------------------------- | :--------------------------- |
498
- | `--out-dir <dir>` | string | Output directory relative to content root | `".well-known/agent-skills"` |
499
- | `--out-file <file>` | string | Explicit destination file path for `index.json` | `undefined` |
500
- | `--metadata-root <dir>` | string | Directory to read site metadata from | content root |
501
- | `--config <file>` | string | Path to `shadow-claw.config.json` | auto-discovered |
502
- | `--no-bundled` | boolean | Exclude bundled ShadowClaw skills from discovery | `false` |
503
- | `--stdout` | boolean | Print generated JSON directly to stdout | `false` |
504
- | `--no-write` | boolean | Skip writing the generated index file to disk | `false` |
496
+ | Option | Type | Description | Default |
497
+ | :---------------------- | :------ | :-------------------------------------------------------------- | :--------------------------- |
498
+ | `--out-dir <dir>` | string | Output directory relative to content root | `".well-known/agent-skills"` |
499
+ | `--out-file <file>` | string | Explicit destination file path for `index.json` | `undefined` |
500
+ | `--metadata-root <dir>` | string | Directory to read site metadata from | content root |
501
+ | `--config <file>` | string | Path to `shadow-claw.config.json` | auto-discovered |
502
+ | `--bundled` | boolean | Include and materialize bundled ShadowClaw skills on disk/index | `false` |
503
+ | `--no-bundled` | boolean | Exclude bundled ShadowClaw skills from discovery | `true` (default behavior) |
504
+ | `--stdout` | boolean | Print generated JSON directly to stdout | `false` |
505
+ | `--no-write` | boolean | Skip writing the generated index file to disk | `false` |
505
506
 
506
507
  > **Build Pipeline Integration:** `src/cli/build/build.ts` (invoked via `bin/build.mjs`) automatically generates `.well-known/agent-skills/index.json` during builds into `dist/public`, indexing both content skills and bundled skills (such as `skill-creator`) using the content root's site metadata, and keeps `.agents/scripts` and repository `.well-known` synchronized.
507
508
 
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="72143ec88485970231da8c06ecf74089dd580224" /><meta name="version" content="1.35.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - Browser-native AI agent." /><link rel="canonical" href="https://xt-ml.github.io/shadow-claw/"><meta property="og:title" content="ShadowClaw"><meta property="og:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta property="og:type" content="website"><meta property="og:url" content="https://xt-ml.github.io/shadow-claw/"><meta property="og:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="ShadowClaw"><meta name="twitter:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta name="twitter:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"SoftwareApplication","@id":"https://xt-ml.github.io/shadow-claw/#software","name":"ShadowClaw","description":"Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.","url":"https://xt-ml.github.io/shadow-claw/","applicationCategory":"DeveloperApplication","operatingSystem":"Web, Browser, Desktop","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"author":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"},"codeRepository":"https://github.com/xt-ml/shadow-claw","license":"https://github.com/xt-ml/shadow-claw/blob/main/LICENSE"},{"@type":"WebSite","@id":"https://xt-ml.github.io/shadow-claw/#website","url":"https://xt-ml.github.io/shadow-claw/","name":"ShadowClaw","description":"Official website and live deployment of ShadowClaw browser-native AI assistant.","publisher":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"}},{"@type":"Organization","@id":"https://xt-ml.github.io/shadow-claw/#organization","name":"xt-ml","url":"https://github.com/xt-ml","sameAs":["https://github.com/xt-ml"]}]}</script><meta name="theme-color" content="#fff" /><meta http-equiv="origin-trial" content="A88uTgESYWcVgREKVReKB6jom41uP8TzW6ei3jNdidf+Xl6ONqKRjKNBphsxhrZmdkakLK3oXDgkGq53rtZYSAMAAAB2eyJvcmlnaW4iOiJodHRwczovL3h0LW1sLmdpdGh1Yi5pbzo0NDMiLCJmZWF0dXJlIjoiV2ViTUNQIiwiZXhwaXJ5IjoxNzk0ODczNjAwLCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ=="><base href="/shadow-claw/" /><script id="shadow-claw-site-config" type="application/json">{"$schema":"https:\u002f\u002fjson-schema.org\u002fdraft\u002f2020-12\u002fschema","site":{"title":"ShadowClaw","description":"ShadowClaw - Browser-native AI agent.","themeColor":"#fff"},"branding":{"faviconPath":"assets\u002ficons\u002ffavicon.ico","appleTouchIconPath":"assets\u002ficons\u002f180.png","notFoundPath":"404.html"},"pwa":{"manifestPath":"manifest.json","themeColor":"#000000"},"sitemapPath":"sitemap.xml","assets":["assets"],"sidebar":{"pagesHidden":false,"chatHidden":false,"tasksHidden":false,"filesHidden":false,"defaultPage":"pages"},"settings":{"defaultToolsProfile":"__builtin_default"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"],"scripts":[{"src":"https:\u002f\u002fkherrick.github.io\u002fblock-garden-knowledge-hub\u002f.agents\u002fscripts\u002fmain\u002fblock-garden-adapter.js","hasInit":true},"https:\u002f\u002fkherrick.github.io\u002fblock-garden\u002fblock-garden-bundle-min.mjs"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
1
+ <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="c9c194eb19a561ec3f67a803f0e078e361735425" /><meta name="version" content="1.36.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - Browser-native AI agent." /><link rel="canonical" href="https://xt-ml.github.io/shadow-claw/"><meta property="og:title" content="ShadowClaw"><meta property="og:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta property="og:type" content="website"><meta property="og:url" content="https://xt-ml.github.io/shadow-claw/"><meta property="og:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="ShadowClaw"><meta name="twitter:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta name="twitter:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"SoftwareApplication","@id":"https://xt-ml.github.io/shadow-claw/#software","name":"ShadowClaw","description":"Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.","url":"https://xt-ml.github.io/shadow-claw/","applicationCategory":"DeveloperApplication","operatingSystem":"Web, Browser, Desktop","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"author":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"},"codeRepository":"https://github.com/xt-ml/shadow-claw","license":"https://github.com/xt-ml/shadow-claw/blob/main/LICENSE"},{"@type":"WebSite","@id":"https://xt-ml.github.io/shadow-claw/#website","url":"https://xt-ml.github.io/shadow-claw/","name":"ShadowClaw","description":"Official website and live deployment of ShadowClaw browser-native AI assistant.","publisher":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"}},{"@type":"Organization","@id":"https://xt-ml.github.io/shadow-claw/#organization","name":"xt-ml","url":"https://github.com/xt-ml","sameAs":["https://github.com/xt-ml"]}]}</script><meta name="theme-color" content="#fff" /><meta http-equiv="origin-trial" content="A88uTgESYWcVgREKVReKB6jom41uP8TzW6ei3jNdidf+Xl6ONqKRjKNBphsxhrZmdkakLK3oXDgkGq53rtZYSAMAAAB2eyJvcmlnaW4iOiJodHRwczovL3h0LW1sLmdpdGh1Yi5pbzo0NDMiLCJmZWF0dXJlIjoiV2ViTUNQIiwiZXhwaXJ5IjoxNzk0ODczNjAwLCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ=="><base href="/shadow-claw/" /><script id="shadow-claw-site-config" type="application/json">{"$schema":"https:\u002f\u002fjson-schema.org\u002fdraft\u002f2020-12\u002fschema","site":{"title":"ShadowClaw","description":"ShadowClaw - Browser-native AI agent.","themeColor":"#fff"},"branding":{"faviconPath":"assets\u002ficons\u002ffavicon.ico","appleTouchIconPath":"assets\u002ficons\u002f180.png","notFoundPath":"404.html"},"pwa":{"manifestPath":"manifest.json","themeColor":"#000000"},"sitemapPath":"sitemap.xml","assets":["assets"],"sidebar":{"pagesHidden":false,"chatHidden":false,"tasksHidden":false,"filesHidden":false,"defaultPage":"pages"},"settings":{"defaultToolsProfile":"__builtin_default"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"],"scripts":[{"src":"https:\u002f\u002fkherrick.github.io\u002fblock-garden-knowledge-hub\u002f.agents\u002fscripts\u002fmain\u002fblock-garden-adapter.js","hasInit":true},"https:\u002f\u002fkherrick.github.io\u002fblock-garden\u002fblock-garden-bundle-min.mjs"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
2
2
  <script>var ShadowClawThemeInit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);function n(){if(globalThis.trustedTypes)return;let e=new Map;globalThis.trustedTypes={createPolicy:(t,n)=>{if(e.has(t))throw TypeError(`Policy with name "${t}" already exists.`);let r={createHTML:n.createHTML?e=>n.createHTML(e):void 0,createScriptURL:n.createScriptURL?e=>n.createScriptURL(e):void 0,createScript:n.createScript?e=>n.createScript(e):void 0};return e.set(t,r),r},getPolicy:t=>e.get(t)??null,isHTML:e=>typeof e==`string`||e instanceof Object&&`toString`in e,isScriptURL:e=>typeof e==`string`||e instanceof Object&&`toString`in e,isScript:e=>typeof e==`string`||e instanceof Object&&`toString`in e}}let r=`__shadowClawDefaultTrustedTypesPolicyState`,i=`default`,a=`shadowclaw-sandbox`;function o(){let e=globalThis;return e[r]||(e[r]={initialized:!1,policy:null}),e[r]}function s(){let e=o();if(e.initialized)return;let t=Reflect.get(globalThis,`trustedTypes`);if(!(!t||typeof t.createPolicy!=`function`)){e.initialized=!0;try{if(typeof t.getPolicy==`function`){let n=t.getPolicy(i);if(n){e.policy=n;return}}let n=!1;if(typeof t.getPolicyNames==`function`){let e=t.getPolicyNames();Array.isArray(e)&&e.includes(i)&&(n=!0)}if(n){if(typeof t.getPolicy==`function`){let n=t.getPolicy(a);if(n){e.policy=n;return}}e.policy=t.createPolicy(a,{createHTML:e=>e,createScriptURL:e=>e});return}e.policy=t.createPolicy(i,{createHTML:e=>e,createScriptURL:e=>e})}catch{typeof t.getPolicy==`function`&&(e.policy=t.getPolicy(i)??t.getPolicy(a)??null)}}}new class{loading=!1;models=new Map;getModelInfo(e){if(!e||typeof e!=`string`)return null;let t=e.toLowerCase().trim(),n=this.models.get(t);if(n)return n;if(t.includes(`/`)){let e=t.split(`/`).pop();if(e&&this.models.has(e))return this.models.get(e)}else for(let[e,n]of this.models.entries())if(e.endsWith(`/${t}`))return n;if(t.includes(`:`)){let e=t.split(`:`)[0],n=this.getModelInfo(e);if(n)return n}return null}registerModelInfo(e,t){this.models.set(e.toLowerCase(),t)}clear(){this.models.clear()}async fetchModelInfo(e,t,n){if(e.modelsUrl){this.loading=!0;try{let r=new Headers;if(r.set(`Content-Type`,`application/json`),e.headers)for(let[t,n]of Object.entries(e.headers))r.set(t,n);if(n)for(let[e,t]of Object.entries(n))r.set(e,t);if(t&&e.apiKeyHeader){let n=e.apiKeyHeaderFormat;r.set(e.apiKeyHeader,n?n.replace(`{key}`,t):t)}let i=await fetch(e.modelsUrl,{headers:r});if(!i.ok)throw Error(`HTTP ${i.status} ${i.statusText}`);let a=await i.json(),o=Array.isArray(a.data)?a.data:Array.isArray(a.models)?a.models:[];for(let e of o){if(!e.id)continue;let t=e.context_length??e.context_window??0,n=e.max_completion_tokens||e.per_request_limits?.completion_tokens||e.top_provider?.max_completion_tokens||null,r=typeof e.supports_tools==`boolean`?e.supports_tools:typeof e.supportsTools==`boolean`?e.supportsTools:void 0,i=this.extractModalities(e,`input`),a=this.extractModalities(e,`output`),o=this.modalitiesInclude(i,`image`,`vision`),s=this.modalitiesInclude(i,`audio`,`voice`,`hearing`),c=this.modalitiesInclude(i,`video`),l=e.id===`openrouter/free`||this.supportedParametersInclude(e,`image`,`vision`,`audio`,`tool`,`structured`),u=this.extractReasoning(e),d=typeof e.supports_prompt_caching==`boolean`?e.supports_prompt_caching:typeof e.supportsPromptCaching==`boolean`?e.supportsPromptCaching:this.supportedParametersInclude(e,`cache_control`,`prompt_caching`)?!0:void 0;!t&&Array.isArray(e.providers)&&e.providers.length>0&&(t=e.providers[0]?.context_length||0),this.registerModelInfo(e.id,{contextWindow:t,maxOutput:n,...r!==void 0&&{supportsTools:r},...i.length>0&&{inputModalities:i},...a.length>0&&{outputModalities:a},...o!==void 0&&{supportsImageInput:o},...s!==void 0&&{supportsAudioInput:s},...c!==void 0&&{supportsVideoInput:c},...u&&{reasoning:u},...l&&{routesByRequestFeatures:l},...d!==void 0&&{supportsPromptCaching:d}})}o.length>0&&console.log(`[ModelRegistry] Registered ${o.length} models for provider "${e.id}"`)}catch(t){console.error(`[ModelRegistry] Error fetching models for ${e.id}:`,t)}finally{this.loading=!1}}}extractModalities(e,t){let n=t===`input`?e.input_modalities||e.inputModalities:e.output_modalities||e.outputModalities,r=e.architecture||{},i=t===`input`?r.input_modalities||r.inputModalities:r.output_modalities||r.outputModalities,a=typeof r.modality==`string`?r.modality:``,o=this.parseArchitectureModality(a,t),s=[...this.normalizeStringArray(n),...this.normalizeStringArray(i),...o];return Array.from(new Set(s))}extractReasoning(e){let t=e?.reasoning;if(!t||typeof t!=`object`)return;let n=this.normalizeStringArray(t.supported_efforts),r=typeof t.default_effort==`string`?t.default_effort.toLowerCase():void 0,i=typeof t.default_enabled==`boolean`?t.default_enabled:void 0,a=typeof t.supports_max_tokens==`boolean`?t.supports_max_tokens:void 0,o=typeof t.mandatory==`boolean`?t.mandatory:void 0;if(!(n.length===0&&r===void 0&&i===void 0&&a===void 0&&o===void 0))return{...n.length>0&&{supportedEfforts:n},...r!==void 0&&{defaultEffort:r},...i!==void 0&&{defaultEnabled:i},...a!==void 0&&{supportsMaxTokens:a},...o!==void 0&&{mandatory:o}}}modalitiesInclude(e,...t){if(e.length!==0)return t.some(t=>e.some(e=>e.includes(t)))}normalizeStringArray(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`).map(e=>e.toLowerCase()):[]}parseArchitectureModality(e,t){if(!e)return[];let[n=``,r=``]=e.toLowerCase().split(`->`).map(e=>e.trim());return(t===`input`?n:r).split(/[+,/\s]+/).map(e=>e.trim()).filter(Boolean)}supportedParametersInclude(e,...t){let n=this.normalizeStringArray(e.supported_parameters||e.supportedParameters);return t.some(e=>n.some(t=>t.includes(e)))}};function c(e){return e.replace(/^\/+|\/+$/g,``)}function l(e){let t=c(e);return t.endsWith(`/index.html`)?t=t.slice(0,-11):t.endsWith(`index.html`)&&(t=t.slice(0,-10)),c(t)}function u(e){let t=c(e),n=t.split(`/`).filter(Boolean);if(n.length===0)return null;let r=n[0].toLowerCase();if(r===`pages`){if(n.length>=3){let e=n[1];return{page:`pages`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e,path:n.slice(2).join(`/`)}}return{page:`pages`,groupId:`br:main`,path:n.slice(1).join(`/`)}}if(r===`files`){let e=n[1]||`main`;return{page:`files`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e,path:n.slice(2).join(`/`)||void 0}}if(r===`chat`){let e=n[1]||`main`;return{page:`chat`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e}}if(r===`tasks`){let e=n[1]||`main`;return{page:`tasks`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e}}return r===`main`?{page:`pages`,groupId:`br:main`,path:n.slice(1).join(`/`)}:{page:`pages`,groupId:`br:main`,path:t}}function d(){if(typeof document<`u`){let e=document.getElementById(`shadow-claw-static-routing`);if(e&&e.textContent)try{let t=JSON.parse(e.textContent);if(t&&typeof t==`object`&&t.routes)return t}catch(e){console.warn(`Failed to parse embedded static routing manifest:`,e)}}return null}function f(e,t){let n=t||d();if(!n||!n.routes)return null;let r=l(e);if(!r)return null;for(let[e,t]of Object.entries(n.routes))if(!(!t||!t.prettyPath)&&l(t.prettyPath)===r)return u(e);return null}let p=null,ee=new Set([`chat`,`files`,`tasks`,`pages`,`settings`,`tools`,`channels`]);function m(){p=null}typeof globalThis<`u`&&(globalThis.__applyBasePathCacheReset=m);function h(){let e=typeof window<`u`?window:typeof self<`u`?self:globalThis;if(e&&e.__SHADOWCLAW_DEPLOY_ID__){let t=String(e.__SHADOWCLAW_DEPLOY_ID__).trim();if(t)return t.replace(/[^a-zA-Z0-9_-]/g,`-`)}let t=globalThis.process;if(t&&t.env&&t.env.SHADOWCLAW_DEPLOY_ID){let e=String(t.env.SHADOWCLAW_DEPLOY_ID).trim();if(e)return e.replace(/[^a-zA-Z0-9_-]/g,`-`)}let n=te();return!n||n===`/`?``:n.replace(/^\/+|\/+$/g,``).replace(/[^a-zA-Z0-9_-]/g,`-`)}function te(){if(p!==null)return p;if((typeof window>`u`||globalThis.WorkerGlobalScope!==void 0&&typeof self<`u`&&self instanceof globalThis.WorkerGlobalScope)&&typeof self<`u`&&self.location){let e=(self.location.pathname||`/`).split(`/`).filter(Boolean);if(e.length<=1)return p=`/`,p;let t=e[0].toLowerCase(),n=t===`service-worker.js`||t===`sw.js`||t===`manifest.json`||t===`sitemap.xml`||t===`favicon.ico`||t===`index.html`||t===`service-worker`||t===`assets`||t===`dist`||t===`public`;if(n&&e.length===2)return p=`/`,p;if(!n)return p=`/`+e[0]+`/`,p}let e=typeof window<`u`&&window.location?window.location:typeof self<`u`&&self.location?self.location:null;if(!e)return`/`;if(typeof document<`u`&&typeof document.querySelector==`function`){let t=document.querySelector(`base[href]`);if(t){let n=t.getAttribute(`href`);if(n)try{let t=new URL(n,e.origin).pathname;return t.endsWith(`/`)||(t+=`/`),p=t,p}catch{}}}let t=e.pathname||`/`;if(t===`/`)return p=`/`,p;let n=t.split(`/`).filter(Boolean),r=n.findIndex(e=>ee.has(e.toLowerCase()));return r>=0?r===0?(p=`/`,p):(p=`/`+n.slice(0,r).join(`/`)+`/`,p):f(t)?(p=`/`,p):n.length===1&&!t.includes(`.`)?(p=`/`+n[0]+`/`,p):(p=`/`,p)}function ne(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`(^|\\s)@${t}\\b`,`i`)}ne(`ShadowClaw`);function g(){let e=h();return e?`shadowclaw-${e}`:`shadowclaw`}g();let _={github:{providerId:`github`,name:`GitHub`,aliases:[`github`,`api.github.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`token `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://github.com/login/oauth/authorize`,tokenUrl:`https://github.com/login/oauth/access_token`,defaultScopes:[`repo`,`read:user`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},gitlab:{providerId:`gitlab`,name:`GitLab`,aliases:[`gitlab`,`gitlab.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`PRIVATE-TOKEN`,headerPrefix:``},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},tokenAuthByServiceType:{git_remote:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}}},oauth:{authorizeUrl:`https://gitlab.com/oauth/authorize`,tokenUrl:`https://gitlab.com/oauth/token`,defaultScopes:[`read_api`,`read_user`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},figma:{providerId:`figma`,name:`Figma`,aliases:[`figma`,`api.figma.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`X-Figma-Token`,headerPrefix:``},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://www.figma.com/oauth`,tokenUrl:`https://api.figma.com/v1/oauth/token`,refreshUrl:`https://api.figma.com/v1/oauth/refresh`,defaultScopes:[],usePkce:!0,clientAuthMethod:`basic_header`,scopeSeparator:`space`}},notion:{providerId:`notion`,name:`Notion`,aliases:[`notion`,`api.notion.com`,`notion.so`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://api.notion.com/v1/oauth/authorize`,tokenUrl:`https://api.notion.com/v1/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`basic_header`,scopeSeparator:`space`}},microsoft_graph:{providerId:`microsoft_graph`,name:`Microsoft Graph`,aliases:[`microsoft`,`graph.microsoft.com`,`microsoft_graph`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://login.microsoftonline.com/common/oauth2/v2.0/authorize`,tokenUrl:`https://login.microsoftonline.com/common/oauth2/v2.0/token`,defaultScopes:[`openid`,`profile`,`offline_access`,`User.Read`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},yahoo_mail:{providerId:`yahoo_mail`,name:`Yahoo Mail`,aliases:[`yahoo`,`yahoo_mail`,`mail.yahoo.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://api.login.yahoo.com/oauth2/request_auth`,tokenUrl:`https://api.login.yahoo.com/oauth2/get_token`,defaultScopes:[`mail-r`,`mail-w`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},google:{providerId:`google`,name:`Google`,aliases:[`google`,`googleapis.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://accounts.google.com/o/oauth2/v2/auth`,tokenUrl:`https://oauth2.googleapis.com/token`,defaultScopes:[`openid`,`profile`,`email`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},atlassian:{providerId:`atlassian`,name:`Atlassian`,aliases:[`atlassian`,`api.atlassian.com`],modes:[`oauth`,`token`,`basic`],defaultMode:`basic`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`,`basic_userpass`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `},basic:{headerName:`Authorization`,headerPrefix:`Basic `}},oauth:{authorizeUrl:`https://auth.atlassian.com/authorize`,tokenUrl:`https://auth.atlassian.com/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},slack:{providerId:`slack`,name:`Slack`,aliases:[`slack`,`slack.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://slack.com/oauth/v2/authorize`,tokenUrl:`https://slack.com/api/oauth.v2.access`,defaultScopes:[],usePkce:!1,clientAuthMethod:`request_body`,scopeSeparator:`comma`}},linear:{providerId:`linear`,name:`Linear`,aliases:[`linear`,`api.linear.app`,`linear.app`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://linear.app/oauth/authorize`,tokenUrl:`https://api.linear.app/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},azure_devops:{providerId:`azure_devops`,name:`Azure DevOps`,aliases:[`azure_devops`,`dev.azure.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`,`basic_userpass`,`ssh_key`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},tokenAuthByServiceType:{git_remote:{token:{headerName:`Authorization`,headerPrefix:`Basic `},oauth:{headerName:`Authorization`,headerPrefix:`Basic `}}},oauth:{authorizeUrl:`https://app.vssps.visualstudio.com/oauth2/authorize`,tokenUrl:`https://app.vssps.visualstudio.com/oauth2/token`,defaultScopes:[`vso.code`,`vso.profile`,`offline_access`],usePkce:!1,clientAuthMethod:`request_body`,scopeSeparator:`space`}},custom_mcp:{providerId:`custom_mcp`,name:`Custom MCP`,aliases:[`custom_mcp`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`mcp_remote`,`webmcp_local`],authTypes:[`none`,`token`,`oauth`,`custom_header`,`ssh_key`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://example.com/oauth/authorize`,tokenUrl:`https://example.com/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}}};Object.fromEntries(Object.values(_).filter(e=>!!e.oauth).map(e=>{let t=e.oauth;return[e.providerId,{id:e.providerId,name:e.name,authorizeUrl:t.authorizeUrl,tokenUrl:t.tokenUrl,redirectUri:t.redirectUri,defaultScopes:t.defaultScopes,usePkce:t.usePkce,clientAuthMethod:t.clientAuthMethod,scopeSeparator:t.scopeSeparator}]})),Object.fromEntries(Object.values(_).map(e=>[e.providerId,{providerId:e.providerId,modes:e.modes,defaultMode:e.defaultMode}])),new Promise(e=>{});
3
3
  /*! @license DOMPurify 3.4.13 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.13/LICENSE */
4
4
  function v(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function y(e){if(Array.isArray(e))return e}function b(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t!==0)for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function re(){throw TypeError(`Invalid attempt to destructure non-iterable instance.