@fugood/buttress-server 2.26.0-beta.23 → 2.26.0-beta.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{a as e,c as t,d as n,i as r,l as i,n as a,o,r as s,s as c,t as l,u}from"./net-tWFM4EP8.mjs";import{a as d,c as f,d as p,f as m,i as h,l as g,n as _,o as v,p as y,r as b,s as x,t as S,u as C}from"./config-DiYweJ2m.mjs";import{builtinModules as ee,createRequire as w}from"node:module";import{node as T}from"@elysiajs/node";import{Elysia as te,file as ne,sse as E,t as D}from"elysia";import{ReadableStream as re}from"node:stream/web";import O,{mkdir as ie,rm as k,unlink as A,writeFile as ae}from"node:fs/promises";import oe,{randomBytes as se,randomUUID as j,timingSafeEqual as ce}from"node:crypto";import M from"node:path";import N from"node:os";import le from"bytes";import P,{createWriteStream as ue}from"node:fs";import{fileURLToPath as de,pathToFileURL as fe}from"node:url";import{execSync as pe,spawn as me,spawnSync as he}from"node:child_process";import{ZodError as ge,z as F}from"zod";import{importSPKI as _e,jwtVerify as ve}from"jose";import ye from"ms";import be from"node:vm";import{moduleRunnerTransformSync as xe,transformSync as Se}from"oxc-transform";import Ce from"lodash";import we from"moment";import*as Te from"mathjs";import Ee from"voca";import De from"chroma-js";import Oe from"json5";import ke from"qs";import{nanoid as Ae}from"nanoid";import je from"md5";import{Server as Me}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as Ne,ListToolsRequestSchema as Pe}from"@modelcontextprotocol/sdk/types.js";import{Readable as Fe}from"node:stream";import{pipeline as Ie}from"node:stream/promises";import Le from"@iarna/toml";import{Buffer as Re}from"node:buffer";import ze from"node:dgram";import{Agent as Be}from"@earendil-works/pi-agent-core";import{createProvider as Ve,uuidv7 as He}from"@earendil-works/pi-ai";import{builtinModels as Ue}from"@earendil-works/pi-ai/providers/all";import{stream as We,streamSimple as Ge}from"@earendil-works/pi-ai/api/openai-completions";import Ke from"node:readline/promises";const qe=!(`Bun`in globalThis),I=e=>new te({adapter:qe?T():void 0,...e}),Je=(e,t,n)=>Buffer.from(JSON.stringify({t:e,d:t,ts:n}),`utf8`),Ye=(e,t,n)=>{if(!e)return null;let r=Math.floor(Date.now()/1e3),i=oe.sign(null,Je(t,n,r),e.privateKey).toString(`base64`);return{t,v:`2.0`,d:n,ts:r,kid:e.kid,sig:i}},Xe=e=>{let{workspace:t,serverKeyPair:n}=e;return!t||!n?null:{kid:n.kid,privateKey:oe.createPrivateKey({key:Buffer.from(n.privateKeyPkcs8,`base64`),format:`der`,type:`pkcs8`})}},Ze=D.Object({id:D.String(),name:D.String(),version:D.String(),address:D.String(),addresses:D.Array(D.String()),port:D.Number(),url:D.String(),generators:D.Array(D.Object({type:D.String(),score:D.Optional(D.Number()),hasGpu:D.Optional(D.Boolean()),usableBytes:D.Optional(D.Number())})),authentication:D.Object({required:D.Boolean(),type:D.String(),kid:D.Optional(D.String()),bound:D.Optional(D.Boolean())}),workspace:D.Optional(D.Object({id:D.String(),name:D.Optional(D.String())})),functions:D.Optional(D.Object({enabled:D.Boolean(),count:D.Number()})),envelope:D.Optional(D.Any())}),Qe=e=>[...new Set([e.address,...e.addresses||[]].filter(e=>typeof e==`string`&&e.length>0))],$e=e=>({id:e.id,name:e.name,version:e.version,address:e.address,addresses:Qe(e),port:e.port,url:e.url,generators:e.generators,authentication:e.authentication,workspace:e.workspace,functions:e.functions});var et=(e,t=null)=>{let n=I(),r=e.autodiscover?.http?.path??`/buttress/info`;return n.get(r,({store:{serverInfo:e}})=>{let n=$e(e),r=Ye(t,`ANNOUNCE`,{info:n});return r?{...n,envelope:r}:n},{response:Ze}),n};const tt=e=>`Bun`in globalThis?globalThis.Bun.file(e):ne(e);let nt=null;const rt=async e=>{if(nt&&nt.kid===e.kid)return nt.key;let t=await _e(e.issuerPublicKey,`EdDSA`);return nt={kid:e.kid,key:t},t},it=/^Bearer\s+(.+)$/i,at=(e,t)=>{if(e){let t=e.authorization||e.Authorization;if(t){let e=t.match(it);return e?e[1].trim():t.trim()}}if(t){let e=t.access_token??t.token;if(typeof e==`string`&&e)return e}return null},ot=async(e,t)=>{if(!e||!t)return null;try{let{payload:n}=await ve(e,await rt(t),{algorithms:[`EdDSA`]}),r=n;return r.k!==`ba`||r.w_id!==t.id||r.st!==`ws`&&r.st!==`dev`||!r.sid||!r.exp?null:{workspaceId:r.w_id,subjectType:r.st,subjectId:r.sid,jti:r.jti,exp:r.exp}}catch{return null}},st=(async({headers:e,query:t,set:n,store:r})=>{let i=r.workspaceState?.workspace;if(!i)return;let a=at(e,t);if(!r.agentsService?.verifyInternalToken?.(a)&&!await ot(a,i))return n.status=401,n.headers&&(n.headers[`WWW-Authenticate`]=`Bearer`),{error:{code:`UNAUTHORIZED`,message:`Invalid or missing workspace access token`}}}),ct=e=>{if(!e)return null;let t=e[`x-buttress-sess-id`]??e[`X-BUTTRESS-SESS-ID`];return t?t.trim():null},lt=(async({headers:e,query:t,set:n,store:r})=>{let i=r.sessions,a=ct(e);if(!a||!i)return n.status=401,{error:{code:`SESSION_REQUIRED`,message:`Missing buttress session id`}};let o=i.get(a);if(!o)return n.status=401,{error:{code:`SESSION_INVALID`,message:`Unknown or expired buttress session`}};let s=r.workspaceState?.workspace;if(s&&o.identity){let r=await ot(at(e,t),s);if(!r||r.subjectId!==o.identity.subjectId||r.subjectType!==o.identity.subjectType)return n.status=403,{error:{code:`SESSION_FORBIDDEN`,message:`Token identity mismatch for this session`}}}}),ut=(e,t)=>{let n=e.sessions,r=ct(t);if(!r||!n)return null;let i=n.get(r);return i?{sessionId:r,session:i}:null},dt=typeof process<`u`&&process.versions!=null&&process.versions.node!=null;var ft=I().onBeforeHandle(st).onBeforeHandle(lt).post(`/buttress/upload`,async({body:{file:e},headers:t,store:n})=>{let r=ut(n,t);if(!r)return{ok:!1,error:`Session guard mis-wired`};let{session:i}=r;try{let t=dt?e.stream():await e.arrayBuffer();return{ok:!0,filename:await i.fileManager.storeUpload(e.name,t)}}catch(e){return{ok:!1,error:String(e)}}},{body:D.Object({file:D.File()}),response:D.Object({ok:D.Boolean(),filename:D.Optional(D.String()),error:D.Optional(D.String())})}).get(`/buttress/download/:filename`,async({params:{filename:e},headers:t,store:n,set:r})=>{let i=ut(n,t);if(!i)return r.status=500,`Session guard mis-wired`;let{session:a}=i,o=a.fileManager.resolve(e);return o?tt(o):(r.status=404,`File not found`)},{params:D.Object({filename:D.String()})});const pt=(()=>{let e=new Set,t=[],n=(n,r)=>{if(!e.delete(n)||!r)return;let i=Date.now();t.unshift({type:n.type,repoId:n.repoId,filename:n.filename,totalBytes:null,durationMs:i-n.startedAt,finishedAt:new Date(i).toISOString(),...r}),t.length=Math.min(t.length,20)};return{begin(t){let r={type:t.type,repoId:t.repoId,filename:t.filename??null,startedAt:Date.now(),progress:null};return e.add(r),{progress(t){e.has(r)&&Number.isFinite(t)&&(r.progress=Math.round(Math.min(1,Math.max(0,t))*1e3)/1e3)},setRepoId(e){r.repoId=e},complete:()=>n(r,{success:!0}),fail:e=>n(r,{success:!1,error:e instanceof Error?e.message:String(e)}),discard:()=>n(r,null)}},snapshot(){return{active:[...e].map(e=>({type:e.type,repoId:e.repoId,filename:e.filename,receivedBytes:0,totalBytes:null,bytesPerSecond:null,startedAt:new Date(e.startedAt).toISOString(),progress:e.progress})),recent:[...t]}}}})(),mt=(e,t=200)=>e.length>t?`${e.slice(0,t)}…`:e,L=((e=50)=>{let t={calls:{total:0,failed:0},uploads:{total:0,failed:0,bytes:0},downloads:{total:0,missed:0,bytes:0},auth:{total:0,denied:0},daemons:{invocations:0,failed:0}},n={calls:[],uploads:[],downloads:[],auth:[],daemons:[]},r=null,i=(t,n)=>{t.unshift(n),t.length>e&&(t.length=e)};return{recordCall(e){t.calls.total+=1,e.success||(t.calls.failed+=1),i(n.calls,{...e,error:e.error&&mt(e.error),timestamp:new Date().toISOString()})},recordUpload(e){t.uploads.total+=1,e.success?t.uploads.bytes+=e.size:t.uploads.failed+=1,i(n.uploads,{...e,error:e.error&&mt(e.error),timestamp:new Date().toISOString()})},recordDownload(e){t.downloads.total+=1,e.success?t.downloads.bytes+=e.size??0:t.downloads.missed+=1,i(n.downloads,{...e,path:mt(e.path),timestamp:new Date().toISOString()})},recordDaemonActivity(e){t.daemons.invocations+=1,e.success||(t.daemons.failed+=1),i(n.daemons,{...e,error:e.error&&mt(e.error),timestamp:new Date().toISOString()})},setDaemonsProvider(e){r=e},recordAuth(e){t.auth.total+=1,e.outcome!==`allowed`&&(t.auth.denied+=1),i(n.auth,{...e,path:mt(e.path),timestamp:new Date().toISOString()})},snapshot(){let e=[];try{e=r?.()??[]}catch{}return{counters:{calls:{...t.calls},uploads:{...t.uploads},downloads:{...t.downloads},auth:{...t.auth},daemons:{...t.daemons}},daemons:e,history:{calls:[...n.calls],uploads:[...n.uploads],downloads:[...n.downloads],auth:[...n.auth],daemons:[...n.daemons]}}}}})(),ht=M.dirname(de(import.meta.url)),gt=()=>{try{let e=w(import.meta.url).resolve(`@fugood/buttress-ui/package.json`);return M.join(M.dirname(e),`lib`,`status.html`)}catch{return null}},_t=async()=>{let e=gt(),t=[...e?[e]:[],M.join(ht,`..`,`public`,`status.html`),M.join(ht,`..`,`..`,`public`,`status.html`),M.join(M.dirname(process.execPath),`public`,`status.html`)];return(await Promise.all(t.map(e=>O.access(e).then(()=>e,()=>null)))).find(e=>e!==null)??null},vt=e=>{let{status:t}=e;return t?.getFullStatus?t.getFullStatus():{timestamp:new Date().toISOString(),ggmlLlm:{generators:[],history:{}},ggmlStt:{generators:[],history:{}},onnxStt:{generators:[],history:{}},onnxTts:{generators:[],history:{}},ggmlTts:{generators:[],history:{}},ggmlDecision:{generators:[],history:{}}}},yt=async()=>{let e=await _t();if(!e)return console.error(`[Status] Failed to find status.html in candidate paths`),new Response(`Status page not found`,{status:404,headers:{"Content-Type":`text/plain`}});try{let t=await O.readFile(e,`utf-8`);return new Response(t,{headers:{"Content-Type":`text/html; charset=utf-8`}})}catch(e){return console.error(`[Status] Failed to serve status page:`,e),new Response(`Status page not found`,{status:404,headers:{"Content-Type":`text/plain`}})}},bt=e=>e?.functions?{enabled:!0,count:e.functions.count,daemonCount:e.functions.daemons??0,...L.snapshot()}:{enabled:!1},xt=(e,t)=>{if(!e)return null;let{udp:n,http:r}=e,i=!!(n?.announcements?.enabled||n?.requests?.enabled);return{udpPort:i?n.port??null:null,udpAnnouncing:i&&!!(t.workspace&&t.serverKeyPair),httpPath:r?.enabled?r.path??`/buttress/info`:null}},St=({config:e,endpoints:t,functionsService:n,agentsService:r,workspaceState:i})=>{let a=r?.list()??[];return{openaiCompat:t.openaiCompat,anthropicMessages:t.anthropicMessages,typesafeCompat:t.typesafeCompat,autodiscover:xt(e.autodiscover,i),functions:{enabled:n!==null,count:n?.stats.count??0,daemons:n?.stats.daemons??0,hotReload:n?.config.hotReload??!1},agents:r?{enabled:!0,count:a.length,names:a}:null}},Ct=e=>typeof e==`string`&&e.trim()!==``?e:null,wt=e=>e.map(({type:e,model:t})=>({type:e,repoId:Ct(t?.repo_id)??Ct(t?.repository),quantization:Ct(t?.quantization)})),Tt=e=>{let{serverInfo:t,startedAt:n,sessions:r,config:i,host:a}=e;return{id:t.id,name:t.name,version:t.version,port:t.port,startedAt:new Date(n).toISOString(),uptimeMs:Date.now()-n,sessions:{open:r.size},generatorTypes:[...new Set(i.generators.map(e=>e.type))],generators:wt(i.generators),features:St(e),host:a,caps:t.generators.map(({type:e,score:t,hasGpu:n,usableBytes:r})=>({type:e,score:t??0,hasGpu:n??!1,usableBytes:r??0}))}};var Et=I().get(`/status`,yt).get(`/status/`,yt).get(`/buttress/status`,({store:e})=>({...vt(e.backend),functions:bt(e.serverInfo),server:Tt(e),downloads:pt.snapshot()}));const Dt=[`repo_id`,`revision`,`filename`,`quantization`,`url`,`local_path`],Ot=[`mmproj_repo_id`,`mmproj_revision`,`mmproj_filename`,`mmproj_url`,`mmproj_local_path`],kt=(e,t)=>{let n=e?.[t];return n==null||n===``?t===`revision`?`main`:null:n},At=(e,t,n)=>n.every(n=>kt(e,n)===kt(t,n)),jt=(e,t)=>e?.rank_pooling?`rank pooling needs an embedding context`:t?.embedding||t?.vocab_only?`the LLM is embedding or vocab-only`:Ot.some(t=>kt(e,t)!=null)&&!At(e,t,Ot)?`the projectors differ`:null,Mt=(e,t)=>{if(t?.backend?.share_llm_context!==!0)return null;let n=t.model,r=(e?.generators||[]).find(e=>e?.type===`ggml-llm`&&At(e.model,n,Dt));return r?jt(n,r.model)?null:r:null},Nt=(e,t)=>(e?.generators||[]).find(e=>e?.type===`ggml-decision`&&e.backend?.share_llm_context===!0&&At(e.model,t,Dt))?Mt(e,{backend:{share_llm_context:!0},model:t}):null,Pt=e=>{let t=e?.generators||[],n=[];for(let r of t.filter(e=>e?.type===`ggml-decision`)){let i=r.model?.repo_id,a=t.find(e=>e?.type===`ggml-llm`&&At(e.model,r.model,Dt));if(!a)continue;if(r.backend?.share_llm_context!==!0){n.push(`${i}: decisions load their own context (set [generators.backend] share_llm_context = true to share the ggml-llm one)`);continue}let o=jt(r.model,a.model);if(o){n.push(`${i}: decisions load their own context (${o})`);continue}n.push(`${i}: decisions share the ggml-llm context`);let s={...e.global?.runtime,...a.runtime,...a.model},c=Number(s.n_parallel)||4,l=Math.floor((Number(s.n_ctx)||0)/c),u=Number(r.runtime?.n_ctx??r.model?.n_ctx)||0;s.kv_unified!==!0&&l>0&&u>l&&n.push(` warning: a decision gets ${l} tokens per slot (n_ctx / n_parallel), less than its n_ctx ${u}; raise the LLM n_ctx or set kv_unified = true`)}return n},Ft=[`ggml-llm`,`mlx-llm`],It=m({family:`LLM`,types:Ft}),Lt={jinja:!0,add_generation_prompt:!0,reasoning_format:`auto`,enable_thinking:!1};function Rt(e,t){return t===`mlx-llm`?e.mlxLlm:e.ggmlLlm}const zt=y({max:4,resolve:It,prepare:async(e,t)=>{await Rt(e,t.type).initContext(t.id,{})}});async function Bt(e,t,n=`[LLM]`){return zt.release(e,t,n)}async function Vt(e,t,n,r=`[LLM]`){return zt.getOrCreate(e,t,n,r)}function Ht(e){let t=e.timings||{},n=t.prompt_n??t.promptN??0,r=t.cache_n??t.cacheN??0,i=t.predicted_n??t.predictedN??0;return{promptTokens:n||e.prompt_tokens||e.promptTokens||0,cachedTokens:r,completionTokens:i||e.tokens_evaluated||e.tokensEvaluated||e.tokens_predicted||e.tokensPredicted||0}}function Ut(e){return!!(e.stopped_limit||e.stopped_limited||e.context_full)}function Wt(e){let{promptTokens:t,cachedTokens:n,completionTokens:r}=Ht(e),i=t+n;return{prompt_tokens:i,completion_tokens:r,total_tokens:i+r}}const Gt=e=>e?.type===`ggml-decision`,Kt=e=>{let t=new Set,n=new Set;for(let r of(e.generators||[]).filter(Gt)){let e=p(r);t.has(e)&&n.add(e),t.add(e)}return[...n]},qt=(e,t)=>t===`ggml-llm`?e.ggmlLlm:e.ggmlDecision,Jt=m({family:`decision`,types:[`ggml-decision`]}),Yt=y({max:2,resolve:(e,t)=>{let n=Jt(e,t),r=Mt(e,n.mergedConfig);return r?It(e,p(r)):n},prepare:async(e,t)=>{await qt(e,t.type).initContext(t.id,{})},dispose:async(e,t)=>{t.type===`ggml-llm`&&await e.ggmlLlm.releaseContext(t.id,{})}});async function Xt(e,t,{model:n,...r},i=`[Decision]`){let a=await Yt.getOrCreate(e,t,n,i);try{return await qt(e,a.type).decide(a.id,{request:r})}finally{await Yt.release(e,a,i)}}var R=class extends Error{param;constructor(e,t){super(t),this.param=e}};const Zt=e=>typeof e==`object`&&!!e&&!Array.isArray(e),Qt=e=>typeof e==`string`&&e.trim()!==``,$t=e=>/^(0|[1-9]\d{0,9})$/.test(e),en=(e,t)=>Qt(t)?`${e}: ${t}`:e,tn=e=>{if(typeof e==`string`){if(e.trim()===``)throw new R(`input`,"`input` must not be empty");return{state:e}}if(!Array.isArray(e)||e.length===0)throw new R(`input`,"`input` must be a string or a non-empty message array");let t=[],n=[];if(e.forEach((e,r)=>{let i=`input[${r}]`;if(!Zt(e)||e.role!==`user`)throw new R(`${i}.role`,"Only `user` messages are supported");if(e.type!=null&&e.type!==`message`)throw new R(`${i}.type`,"Message `type` must be `message`");let{content:a}=e;if(typeof a==`string`){t.push(a);return}if(!Array.isArray(a))throw new R(`${i}.content`,"`content` must be a string or an array of parts");a.forEach((e,r)=>{let a=`${i}.content[${r}]`;if(e?.type===`input_text`&&typeof e.text==`string`)t.push(e.text);else if(e?.type===`input_image`){if(typeof e.image_url!=`string`||!e.image_url.startsWith(`data:`))throw new R(`${a}.image_url`,`Images must be inline base64 data URLs`);n.push(e.image_url)}else throw new R(`${a}.type`,"Content parts must be `input_text` or `input_image`")})}),n.length>128)throw new R(`input`,`At most 128 images are allowed`);let r=t.filter(e=>e.trim()!==``).join(`
2
+ import{a as e,c as t,d as n,i as r,l as i,n as a,o,r as s,s as c,t as l,u}from"./net-DHnXAu8o.mjs";import{a as d,c as f,d as p,f as m,i as h,l as g,n as _,o as v,p as y,r as b,s as x,t as S,u as C}from"./config-DiYweJ2m.mjs";import{builtinModules as ee,createRequire as w}from"node:module";import{node as T}from"@elysiajs/node";import{Elysia as te,file as ne,sse as E,t as D}from"elysia";import{ReadableStream as re}from"node:stream/web";import O,{mkdir as ie,rm as k,unlink as A,writeFile as ae}from"node:fs/promises";import oe,{randomBytes as se,randomUUID as j,timingSafeEqual as ce}from"node:crypto";import M from"node:path";import N from"node:os";import le from"bytes";import P,{createWriteStream as ue}from"node:fs";import{fileURLToPath as de,pathToFileURL as fe}from"node:url";import{execSync as pe,spawn as me,spawnSync as he}from"node:child_process";import{ZodError as ge,z as F}from"zod";import{importSPKI as _e,jwtVerify as ve}from"jose";import ye from"ms";import be from"node:vm";import{moduleRunnerTransformSync as xe,transformSync as Se}from"oxc-transform";import Ce from"lodash";import we from"moment";import*as Te from"mathjs";import Ee from"voca";import De from"chroma-js";import Oe from"json5";import ke from"qs";import{nanoid as Ae}from"nanoid";import je from"md5";import{Server as Me}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as Ne,ListToolsRequestSchema as Pe}from"@modelcontextprotocol/sdk/types.js";import{Readable as Fe}from"node:stream";import{pipeline as Ie}from"node:stream/promises";import Le from"@iarna/toml";import{Buffer as Re}from"node:buffer";import ze from"node:dgram";import{Agent as Be}from"@earendil-works/pi-agent-core";import{createProvider as Ve,uuidv7 as He}from"@earendil-works/pi-ai";import{builtinModels as Ue}from"@earendil-works/pi-ai/providers/all";import{stream as We,streamSimple as Ge}from"@earendil-works/pi-ai/api/openai-completions";import Ke from"node:readline/promises";const qe=!(`Bun`in globalThis),I=e=>new te({adapter:qe?T():void 0,...e}),Je=(e,t,n)=>Buffer.from(JSON.stringify({t:e,d:t,ts:n}),`utf8`),Ye=(e,t,n)=>{if(!e)return null;let r=Math.floor(Date.now()/1e3),i=oe.sign(null,Je(t,n,r),e.privateKey).toString(`base64`);return{t,v:`2.0`,d:n,ts:r,kid:e.kid,sig:i}},Xe=e=>{let{workspace:t,serverKeyPair:n}=e;return!t||!n?null:{kid:n.kid,privateKey:oe.createPrivateKey({key:Buffer.from(n.privateKeyPkcs8,`base64`),format:`der`,type:`pkcs8`})}},Ze=D.Object({id:D.String(),name:D.String(),version:D.String(),address:D.String(),addresses:D.Array(D.String()),port:D.Number(),url:D.String(),generators:D.Array(D.Object({type:D.String(),score:D.Optional(D.Number()),hasGpu:D.Optional(D.Boolean()),usableBytes:D.Optional(D.Number())})),authentication:D.Object({required:D.Boolean(),type:D.String(),kid:D.Optional(D.String()),bound:D.Optional(D.Boolean())}),workspace:D.Optional(D.Object({id:D.String(),name:D.Optional(D.String())})),functions:D.Optional(D.Object({enabled:D.Boolean(),count:D.Number()})),envelope:D.Optional(D.Any())}),Qe=e=>[...new Set([e.address,...e.addresses||[]].filter(e=>typeof e==`string`&&e.length>0))],$e=e=>({id:e.id,name:e.name,version:e.version,address:e.address,addresses:Qe(e),port:e.port,url:e.url,generators:e.generators,authentication:e.authentication,workspace:e.workspace,functions:e.functions});var et=(e,t=null)=>{let n=I(),r=e.autodiscover?.http?.path??`/buttress/info`;return n.get(r,({store:{serverInfo:e}})=>{let n=$e(e),r=Ye(t,`ANNOUNCE`,{info:n});return r?{...n,envelope:r}:n},{response:Ze}),n};const tt=e=>`Bun`in globalThis?globalThis.Bun.file(e):ne(e);let nt=null;const rt=async e=>{if(nt&&nt.kid===e.kid)return nt.key;let t=await _e(e.issuerPublicKey,`EdDSA`);return nt={kid:e.kid,key:t},t},it=/^Bearer\s+(.+)$/i,at=(e,t)=>{if(e){let t=e.authorization||e.Authorization;if(t){let e=t.match(it);return e?e[1].trim():t.trim()}}if(t){let e=t.access_token??t.token;if(typeof e==`string`&&e)return e}return null},ot=async(e,t)=>{if(!e||!t)return null;try{let{payload:n}=await ve(e,await rt(t),{algorithms:[`EdDSA`]}),r=n;return r.k!==`ba`||r.w_id!==t.id||r.st!==`ws`&&r.st!==`dev`||!r.sid||!r.exp?null:{workspaceId:r.w_id,subjectType:r.st,subjectId:r.sid,jti:r.jti,exp:r.exp}}catch{return null}},st=(async({headers:e,query:t,set:n,store:r})=>{let i=r.workspaceState?.workspace;if(!i)return;let a=at(e,t);if(!r.agentsService?.verifyInternalToken?.(a)&&!await ot(a,i))return n.status=401,n.headers&&(n.headers[`WWW-Authenticate`]=`Bearer`),{error:{code:`UNAUTHORIZED`,message:`Invalid or missing workspace access token`}}}),ct=e=>{if(!e)return null;let t=e[`x-buttress-sess-id`]??e[`X-BUTTRESS-SESS-ID`];return t?t.trim():null},lt=(async({headers:e,query:t,set:n,store:r})=>{let i=r.sessions,a=ct(e);if(!a||!i)return n.status=401,{error:{code:`SESSION_REQUIRED`,message:`Missing buttress session id`}};let o=i.get(a);if(!o)return n.status=401,{error:{code:`SESSION_INVALID`,message:`Unknown or expired buttress session`}};let s=r.workspaceState?.workspace;if(s&&o.identity){let r=await ot(at(e,t),s);if(!r||r.subjectId!==o.identity.subjectId||r.subjectType!==o.identity.subjectType)return n.status=403,{error:{code:`SESSION_FORBIDDEN`,message:`Token identity mismatch for this session`}}}}),ut=(e,t)=>{let n=e.sessions,r=ct(t);if(!r||!n)return null;let i=n.get(r);return i?{sessionId:r,session:i}:null},dt=typeof process<`u`&&process.versions!=null&&process.versions.node!=null;var ft=I().onBeforeHandle(st).onBeforeHandle(lt).post(`/buttress/upload`,async({body:{file:e},headers:t,store:n})=>{let r=ut(n,t);if(!r)return{ok:!1,error:`Session guard mis-wired`};let{session:i}=r;try{let t=dt?e.stream():await e.arrayBuffer();return{ok:!0,filename:await i.fileManager.storeUpload(e.name,t)}}catch(e){return{ok:!1,error:String(e)}}},{body:D.Object({file:D.File()}),response:D.Object({ok:D.Boolean(),filename:D.Optional(D.String()),error:D.Optional(D.String())})}).get(`/buttress/download/:filename`,async({params:{filename:e},headers:t,store:n,set:r})=>{let i=ut(n,t);if(!i)return r.status=500,`Session guard mis-wired`;let{session:a}=i,o=a.fileManager.resolve(e);return o?tt(o):(r.status=404,`File not found`)},{params:D.Object({filename:D.String()})});const pt=(()=>{let e=new Set,t=[],n=(n,r)=>{if(!e.delete(n)||!r)return;let i=Date.now();t.unshift({type:n.type,repoId:n.repoId,filename:n.filename,totalBytes:null,durationMs:i-n.startedAt,finishedAt:new Date(i).toISOString(),...r}),t.length=Math.min(t.length,20)};return{begin(t){let r={type:t.type,repoId:t.repoId,filename:t.filename??null,startedAt:Date.now(),progress:null};return e.add(r),{progress(t){e.has(r)&&Number.isFinite(t)&&(r.progress=Math.round(Math.min(1,Math.max(0,t))*1e3)/1e3)},setRepoId(e){r.repoId=e},complete:()=>n(r,{success:!0}),fail:e=>n(r,{success:!1,error:e instanceof Error?e.message:String(e)}),discard:()=>n(r,null)}},snapshot(){return{active:[...e].map(e=>({type:e.type,repoId:e.repoId,filename:e.filename,receivedBytes:0,totalBytes:null,bytesPerSecond:null,startedAt:new Date(e.startedAt).toISOString(),progress:e.progress})),recent:[...t]}}}})(),mt=(e,t=200)=>e.length>t?`${e.slice(0,t)}…`:e,L=((e=50)=>{let t={calls:{total:0,failed:0},uploads:{total:0,failed:0,bytes:0},downloads:{total:0,missed:0,bytes:0},auth:{total:0,denied:0},daemons:{invocations:0,failed:0}},n={calls:[],uploads:[],downloads:[],auth:[],daemons:[]},r=null,i=(t,n)=>{t.unshift(n),t.length>e&&(t.length=e)};return{recordCall(e){t.calls.total+=1,e.success||(t.calls.failed+=1),i(n.calls,{...e,error:e.error&&mt(e.error),timestamp:new Date().toISOString()})},recordUpload(e){t.uploads.total+=1,e.success?t.uploads.bytes+=e.size:t.uploads.failed+=1,i(n.uploads,{...e,error:e.error&&mt(e.error),timestamp:new Date().toISOString()})},recordDownload(e){t.downloads.total+=1,e.success?t.downloads.bytes+=e.size??0:t.downloads.missed+=1,i(n.downloads,{...e,path:mt(e.path),timestamp:new Date().toISOString()})},recordDaemonActivity(e){t.daemons.invocations+=1,e.success||(t.daemons.failed+=1),i(n.daemons,{...e,error:e.error&&mt(e.error),timestamp:new Date().toISOString()})},setDaemonsProvider(e){r=e},recordAuth(e){t.auth.total+=1,e.outcome!==`allowed`&&(t.auth.denied+=1),i(n.auth,{...e,path:mt(e.path),timestamp:new Date().toISOString()})},snapshot(){let e=[];try{e=r?.()??[]}catch{}return{counters:{calls:{...t.calls},uploads:{...t.uploads},downloads:{...t.downloads},auth:{...t.auth},daemons:{...t.daemons}},daemons:e,history:{calls:[...n.calls],uploads:[...n.uploads],downloads:[...n.downloads],auth:[...n.auth],daemons:[...n.daemons]}}}}})(),ht=M.dirname(de(import.meta.url)),gt=()=>{try{let e=w(import.meta.url).resolve(`@fugood/buttress-ui/package.json`);return M.join(M.dirname(e),`lib`,`status.html`)}catch{return null}},_t=async()=>{let e=gt(),t=[...e?[e]:[],M.join(ht,`..`,`public`,`status.html`),M.join(ht,`..`,`..`,`public`,`status.html`),M.join(M.dirname(process.execPath),`public`,`status.html`)];return(await Promise.all(t.map(e=>O.access(e).then(()=>e,()=>null)))).find(e=>e!==null)??null},vt=e=>{let{status:t}=e;return t?.getFullStatus?t.getFullStatus():{timestamp:new Date().toISOString(),ggmlLlm:{generators:[],history:{}},ggmlStt:{generators:[],history:{}},onnxStt:{generators:[],history:{}},onnxTts:{generators:[],history:{}},ggmlTts:{generators:[],history:{}},ggmlDecision:{generators:[],history:{}}}},yt=async()=>{let e=await _t();if(!e)return console.error(`[Status] Failed to find status.html in candidate paths`),new Response(`Status page not found`,{status:404,headers:{"Content-Type":`text/plain`}});try{let t=await O.readFile(e,`utf-8`);return new Response(t,{headers:{"Content-Type":`text/html; charset=utf-8`}})}catch(e){return console.error(`[Status] Failed to serve status page:`,e),new Response(`Status page not found`,{status:404,headers:{"Content-Type":`text/plain`}})}},bt=e=>e?.functions?{enabled:!0,count:e.functions.count,daemonCount:e.functions.daemons??0,...L.snapshot()}:{enabled:!1},xt=(e,t)=>{if(!e)return null;let{udp:n,http:r}=e,i=!!(n?.announcements?.enabled||n?.requests?.enabled);return{udpPort:i?n.port??null:null,udpAnnouncing:i&&!!(t.workspace&&t.serverKeyPair),httpPath:r?.enabled?r.path??`/buttress/info`:null}},St=({config:e,endpoints:t,functionsService:n,agentsService:r,workspaceState:i})=>{let a=r?.list()??[];return{openaiCompat:t.openaiCompat,anthropicMessages:t.anthropicMessages,typesafeCompat:t.typesafeCompat,autodiscover:xt(e.autodiscover,i),functions:{enabled:n!==null,count:n?.stats.count??0,daemons:n?.stats.daemons??0,hotReload:n?.config.hotReload??!1},agents:r?{enabled:!0,count:a.length,names:a}:null}},Ct=e=>typeof e==`string`&&e.trim()!==``?e:null,wt=e=>e.map(({type:e,model:t})=>({type:e,repoId:Ct(t?.repo_id)??Ct(t?.repository),quantization:Ct(t?.quantization)})),Tt=e=>{let{serverInfo:t,startedAt:n,sessions:r,config:i,host:a}=e;return{id:t.id,name:t.name,version:t.version,port:t.port,startedAt:new Date(n).toISOString(),uptimeMs:Date.now()-n,sessions:{open:r.size},generatorTypes:[...new Set(i.generators.map(e=>e.type))],generators:wt(i.generators),features:St(e),host:a,caps:t.generators.map(({type:e,score:t,hasGpu:n,usableBytes:r})=>({type:e,score:t??0,hasGpu:n??!1,usableBytes:r??0}))}};var Et=I().get(`/status`,yt).get(`/status/`,yt).get(`/buttress/status`,({store:e})=>({...vt(e.backend),functions:bt(e.serverInfo),server:Tt(e),downloads:pt.snapshot()}));const Dt=[`repo_id`,`revision`,`filename`,`quantization`,`url`,`local_path`],Ot=[`mmproj_repo_id`,`mmproj_revision`,`mmproj_filename`,`mmproj_url`,`mmproj_local_path`],kt=(e,t)=>{let n=e?.[t];return n==null||n===``?t===`revision`?`main`:null:n},At=(e,t,n)=>n.every(n=>kt(e,n)===kt(t,n)),jt=(e,t)=>e?.rank_pooling?`rank pooling needs an embedding context`:t?.embedding||t?.vocab_only?`the LLM is embedding or vocab-only`:Ot.some(t=>kt(e,t)!=null)&&!At(e,t,Ot)?`the projectors differ`:null,Mt=(e,t)=>{if(t?.backend?.share_llm_context!==!0)return null;let n=t.model,r=(e?.generators||[]).find(e=>e?.type===`ggml-llm`&&At(e.model,n,Dt));return r?jt(n,r.model)?null:r:null},Nt=(e,t)=>(e?.generators||[]).find(e=>e?.type===`ggml-decision`&&e.backend?.share_llm_context===!0&&At(e.model,t,Dt))?Mt(e,{backend:{share_llm_context:!0},model:t}):null,Pt=e=>{let t=e?.generators||[],n=[];for(let r of t.filter(e=>e?.type===`ggml-decision`)){let i=r.model?.repo_id,a=t.find(e=>e?.type===`ggml-llm`&&At(e.model,r.model,Dt));if(!a)continue;if(r.backend?.share_llm_context!==!0){n.push(`${i}: decisions load their own context (set [generators.backend] share_llm_context = true to share the ggml-llm one)`);continue}let o=jt(r.model,a.model);if(o){n.push(`${i}: decisions load their own context (${o})`);continue}n.push(`${i}: decisions share the ggml-llm context`);let s={...e.global?.runtime,...a.runtime,...a.model},c=Number(s.n_parallel)||4,l=Math.floor((Number(s.n_ctx)||0)/c),u=Number(r.runtime?.n_ctx??r.model?.n_ctx)||0;s.kv_unified!==!0&&l>0&&u>l&&n.push(` warning: a decision gets ${l} tokens per slot (n_ctx / n_parallel), less than its n_ctx ${u}; raise the LLM n_ctx or set kv_unified = true`)}return n},Ft=[`ggml-llm`,`mlx-llm`],It=m({family:`LLM`,types:Ft}),Lt={jinja:!0,add_generation_prompt:!0,reasoning_format:`auto`,enable_thinking:!1};function Rt(e,t){return t===`mlx-llm`?e.mlxLlm:e.ggmlLlm}const zt=y({max:4,resolve:It,prepare:async(e,t)=>{await Rt(e,t.type).initContext(t.id,{})}});async function Bt(e,t,n=`[LLM]`){return zt.release(e,t,n)}async function Vt(e,t,n,r=`[LLM]`){return zt.getOrCreate(e,t,n,r)}function Ht(e){let t=e.timings||{},n=t.prompt_n??t.promptN??0,r=t.cache_n??t.cacheN??0,i=t.predicted_n??t.predictedN??0;return{promptTokens:n||e.prompt_tokens||e.promptTokens||0,cachedTokens:r,completionTokens:i||e.tokens_evaluated||e.tokensEvaluated||e.tokens_predicted||e.tokensPredicted||0}}function Ut(e){return!!(e.stopped_limit||e.stopped_limited||e.context_full)}function Wt(e){let{promptTokens:t,cachedTokens:n,completionTokens:r}=Ht(e),i=t+n;return{prompt_tokens:i,completion_tokens:r,total_tokens:i+r}}const Gt=e=>e?.type===`ggml-decision`,Kt=e=>{let t=new Set,n=new Set;for(let r of(e.generators||[]).filter(Gt)){let e=p(r);t.has(e)&&n.add(e),t.add(e)}return[...n]},qt=(e,t)=>t===`ggml-llm`?e.ggmlLlm:e.ggmlDecision,Jt=m({family:`decision`,types:[`ggml-decision`]}),Yt=y({max:2,resolve:(e,t)=>{let n=Jt(e,t),r=Mt(e,n.mergedConfig);return r?It(e,p(r)):n},prepare:async(e,t)=>{await qt(e,t.type).initContext(t.id,{})},dispose:async(e,t)=>{t.type===`ggml-llm`&&await e.ggmlLlm.releaseContext(t.id,{})}});async function Xt(e,t,{model:n,...r},i=`[Decision]`){let a=await Yt.getOrCreate(e,t,n,i);try{return await qt(e,a.type).decide(a.id,{request:r})}finally{await Yt.release(e,a,i)}}var R=class extends Error{param;constructor(e,t){super(t),this.param=e}};const Zt=e=>typeof e==`object`&&!!e&&!Array.isArray(e),Qt=e=>typeof e==`string`&&e.trim()!==``,$t=e=>/^(0|[1-9]\d{0,9})$/.test(e),en=(e,t)=>Qt(t)?`${e}: ${t}`:e,tn=e=>{if(typeof e==`string`){if(e.trim()===``)throw new R(`input`,"`input` must not be empty");return{state:e}}if(!Array.isArray(e)||e.length===0)throw new R(`input`,"`input` must be a string or a non-empty message array");let t=[],n=[];if(e.forEach((e,r)=>{let i=`input[${r}]`;if(!Zt(e)||e.role!==`user`)throw new R(`${i}.role`,"Only `user` messages are supported");if(e.type!=null&&e.type!==`message`)throw new R(`${i}.type`,"Message `type` must be `message`");let{content:a}=e;if(typeof a==`string`){t.push(a);return}if(!Array.isArray(a))throw new R(`${i}.content`,"`content` must be a string or an array of parts");a.forEach((e,r)=>{let a=`${i}.content[${r}]`;if(e?.type===`input_text`&&typeof e.text==`string`)t.push(e.text);else if(e?.type===`input_image`){if(typeof e.image_url!=`string`||!e.image_url.startsWith(`data:`))throw new R(`${a}.image_url`,`Images must be inline base64 data URLs`);n.push(e.image_url)}else throw new R(`${a}.type`,"Content parts must be `input_text` or `input_image`")})}),n.length>128)throw new R(`input`,`At most 128 images are allowed`);let r=t.filter(e=>e.trim()!==``).join(`
3
3
 
4
4
  `);if(r===``&&n.length===0)throw new R(`input`,"`input` has no text or images");return{state:r||(n.length>1?`The attached images.`:`The attached image.`),...n.length>0?{images:n}:{}}},nn=(e,t)=>{let n=new Set;e.forEach((e,r)=>{let{value:i}=e||{};if(typeof i!=`string`&&typeof i!=`boolean`)throw new R(`${t}[${r}].value`,"A choice `value` must be a string or a boolean");let a=`${typeof i}:${i}`;if(n.has(a))throw new R(`${t}[${r}].value`,`Choice values must be unique`);n.add(a)});let r=e.map(({value:e})=>String(e)),i=new Set(r).size===r.length&&!r.some(e=>$t(e)),a=e.map(({value:e},t)=>({key:i?r[t]:`option_${t+1}`,value:e}));return{options:a,criteria:Object.fromEntries(e.map(({description:e},t)=>[a[t].key,i?Qt(e)?e:null:en(r[t],e)]))}},rn=e=>{if(!Zt(e))throw new R(null,`Request body must be an object`);let{model:t,input:n,questions:r}=e;if(!Qt(t))throw new R(`model`,"`model` is required");let{state:i,images:a}=tn(n);if(!Array.isArray(r)||r.length===0)throw new R(`questions`,"`questions` must be a non-empty array");let o=new Set,s=[],c={};return r.forEach((e,t)=>{let n=`questions[${t}]`;if(!Zt(e))throw new R(n,`A question must be an object`);let{type:r,instructions:i}=e;if(!Qt(i))throw new R(`${n}.instructions`,"`instructions` is required");let a=null;if(e.name!=null){if(typeof e.name!=`string`)throw new R(`${n}.name`,"`name` must be a string");if(o.has(e.name))throw new R(`${n}.name`,`Duplicate question name "${e.name}"`);o.add(e.name),{name:a}=e}let l=`q${t}`;if(r===`predicate`)s.push({id:l,name:a,type:r}),c[l]={type:`noul`,instructions:i};else if(r===`choice`){let{choices:t}=e;if(!Array.isArray(t)||t.length<2||t.length>255)throw new R(`${n}.choices`,`Provide between 2 and 255 choices`);let{options:o,criteria:u}=nn(t,`${n}.choices`);s.push({id:l,name:a,type:r,options:o}),c[l]={type:`choice`,instructions:i,criteria:u}}else if(r===`score`){let{levels:t}=e;if(!Array.isArray(t)||t.length<2||t.length>10)throw new R(`${n}.levels`,`Provide between 2 and 10 levels`);t.forEach((e,t)=>{if(!Qt(e?.label))throw new R(`${n}.levels[${t}].label`,"A level needs a `label`")}),s.push({id:l,name:a,type:r,labels:t.map(e=>e.label)}),c[l]={type:`score`,instructions:i,criteria:t.map(e=>en(e.label,e.description))}}else throw new R(`${n}.type`,"Question `type` must be `predicate`, `choice` or `score`")}),{model:t,request:{state:i,questions:c,...a?{images:a}:{}},plan:{questions:s}}},z=e=>Number.isFinite(e)?e:0,an=(e,t,n)=>{let r=t.questions.map(t=>{let n=e.answers?.[t.id]||{},{name:r}=t;if(t.type===`predicate`)return{type:`predicate`,name:r,probability:z(n.noul)};let i=n.probabilities||{};if(t.type===`choice`){let e=t.options.find(e=>e.key===n.choice);return{type:`choice`,name:r,choice:e?e.value:n.choice,probabilities:t.options.map(({key:e,value:t})=>({value:t,probability:z(i[e])})),confidence:z(n.confidence)}}return{type:`score`,name:r,score:z(n.score),probabilities:t.labels.map((e,t)=>({value:t,label:e,probability:z(i[String(t)])})),confidence:z(n.confidence)}}),i=z(e.usage?.input_tokens),a=z(e.usage?.output_tokens);return{model:n,answers:r,usage:{input_tokens:i,input_tokens_details:{cached_tokens:0,cache_write_tokens:0},output_tokens:a,output_tokens_details:{reasoning_tokens:0},total_tokens:i+a}}},on=()=>`chatcmpl-${Date.now()}-${Math.random().toString(36).slice(2,9)}`;async function sn(e,t,n,r){let i=e.getReader(),a=``,o=null,s=null,c=`stop`,l={prompt_tokens:0,completion_tokens:0,total_tokens:0};try{let e=!1;for(;!e;){let n=await i.read();if({done:e}=n,e)break;let r=n.value;if(!r)break;let{event:u,data:d}=r;if(u===`token`)d.content!=null&&(a=d.content),d.reasoning_content!=null&&(o=d.reasoning_content);else if(u===`result`)d.content==null?d.text&&(a=d.text):a=d.content,d.reasoning_content!=null&&(o=d.reasoning_content),d.tool_calls?.length>0?(s=d.tool_calls.map((e,n)=>({id:e.id||`call_${t}_${n}`,type:`function`,function:{name:e.function?.name||``,arguments:e.function?.arguments||``}})),c=`tool_calls`):c=d.interrupted||Ut(d)?`length`:`stop`,l=Wt(d);else if(u===`error`)throw Error(d.message)}}finally{C(i)}let u={role:`assistant`,content:a||null};return o&&(u.reasoning_content=o),s&&(u.tool_calls=s),{id:t,object:`chat.completion`,created:n,model:r,choices:[{index:0,message:u,finish_reason:c}],usage:l}}function cn(e,t,n,r){let i=[];return e.forEach((e,a)=>{let o={index:a};n.has(a)||(n.set(a,e.id||`call_${t}_${a}`),o.id=n.get(a),o.type=`function`);let s=e.function?.arguments||``,c=r.get(a)||``,l={};!r.has(a)&&e.function?.name&&(l.name=e.function.name),s.length>c.length&&(l.arguments=s.slice(c.length),r.set(a,s)),Object.keys(l).length>0?(o.function=l,i.push(o)):o.id&&(o.function={name:e.function?.name||``,arguments:``},i.push(o))}),i}async function*ln(e,t,n,r,i){let a=e.getReader(),o=``,s=``,c=new Map,l=new Map;try{let e=!1;for(;!e;){let u=await a.read();if({done:e}=u,e)break;let d=u.value;if(!d)break;let{event:f,data:p}=d;if(f===`token`){let e={};if(p.content!=null){let t=p.content;t.length>o.length&&(e.content=t.slice(o.length),o=t)}if(p.reasoning_content!=null){let t=p.reasoning_content;t.length>s.length&&(e.reasoning_content=t.slice(s.length),s=t)}if(p.tool_calls?.length>0){let n=cn(p.tool_calls,t,l,c);n.length>0&&(e.tool_calls=n)}Object.keys(e).length>0&&(yield E({data:JSON.stringify({id:t,object:`chat.completion.chunk`,created:n,model:r,choices:[{index:0,delta:e,finish_reason:null}]})}))}else if(f===`result`){if(p.tool_calls?.length>0){let e=cn(p.tool_calls,t,l,c);e.length>0&&(yield E({data:JSON.stringify({id:t,object:`chat.completion.chunk`,created:n,model:r,choices:[{index:0,delta:{tool_calls:e},finish_reason:null}]})}))}let e=`stop`;p.tool_calls?.length>0||l.size>0?e=`tool_calls`:(p.interrupted||Ut(p))&&(e=`length`);let a={id:t,object:`chat.completion.chunk`,created:n,model:r,choices:[{index:0,delta:{},finish_reason:e}]};i&&(a.usage=Wt(p)),yield E({data:JSON.stringify(a)})}else f===`error`&&(yield E({data:JSON.stringify({error:{message:p.message,type:`server_error`}})}))}yield E({data:`[DONE]`})}finally{C(a)}}const un=e=>{let t=e?.model||{};return e.type===`ggml-llm`?!!t.enable_mtmd:Gt(e)?!!(t.mmproj_repo_id||t.mmproj_filename||t.mmproj_url||t.mmproj_local_path):!1},dn=(e,t)=>{if(un(t))return!0;let n=Mt(e,t);return n!=null&&un(n)},fn=e=>{let t=new Map;for(let n of e){let e=Ft.includes(n?.type);if(!e&&!Gt(n))continue;let r=p(n),i=t.get(r)||{image:!1,text:!1,decisions:!1};i.image||=un(n),e?i.text=!0:i.decisions=!0,t.set(r,i)}let n=Array.from(t).sort(([,e],[,t])=>Number(t.text)-Number(e.text));return new Map(n.map(([e,{image:t,text:n,decisions:r}])=>[e,{input_modalities:t?[`text`,`image`]:[`text`],output_modalities:[...n?[`text`]:[],...r?[`decisions`]:[]]}]))};function pn(){let e=I({prefix:`/oai-compat`});return e.onBeforeHandle(st),e.get(`/v1/models`,({store:e})=>{let{config:t}=e,n=Array.from(fn(t.generators||[]),([e,t])=>({id:e,object:`model`,created:Math.floor(Date.now()/1e3),owned_by:`local`,architecture:t}));return n.length===0&&n.push({id:`ggml-llm`,object:`model`,created:Math.floor(Date.now()/1e3),owned_by:`local`,architecture:{input_modalities:[`text`],output_modalities:[`text`]}}),{object:`list`,data:n}}),e.post(`/v1/chat/completions`,async function*({body:e,set:t,store:n}){let{config:r,backend:i}=n,{messages:a=[],stream:o=!1,model:s,tools:c,temperature:l,stop:u,top_p:d,max_tokens:f,presence_penalty:p,frequency_penalty:m,tool_choice:h,stream_options:g,enable_thinking:_}=e;if(!a||a.length===0)return t.status=400,{error:{message:`messages is required and must not be empty`,type:`invalid_request_error`}};let v=null;try{v=await Vt(i,r,s,`[OpenAI]`);let e=on(),t=Math.floor(Date.now()/1e3),n=v.repoId||`ggml-llm`,y={...Lt,messages:a};l!=null&&(y.temperature=l),d!=null&&(y.top_p=d),f!=null&&(y.n_predict=f),u!=null&&(y.stop=Array.isArray(u)?u:[u]),p!=null&&(y.presence_penalty=p),m!=null&&(y.frequency_penalty=m),c!=null&&(y.tools=c),h!=null&&(y.tool_choice=h),y.enable_thinking=_??!1;let b=await Rt(i,v.type).completion(v.id,{options:y});if(!o)return await sn(b,e,t,n);yield*ln(b,e,t,n,g?.include_usage===!0)}catch(e){return console.error(`[OpenAI] Chat completion error:`,e),t.status=500,{error:{message:e.message||`Internal server error`,type:`server_error`}}}finally{await Bt(i,v,`[OpenAI]`)}},{body:D.Object({model:D.Optional(D.String()),messages:D.Array(D.Any()),stream:D.Optional(D.Boolean()),temperature:D.Optional(D.Number()),top_p:D.Optional(D.Number()),max_tokens:D.Optional(D.Number()),stop:D.Optional(D.Union([D.String(),D.Array(D.String())])),presence_penalty:D.Optional(D.Number()),frequency_penalty:D.Optional(D.Number()),tools:D.Optional(D.Array(D.Any())),tool_choice:D.Optional(D.Any()),stream_options:D.Optional(D.Object({include_usage:D.Optional(D.Boolean())})),enable_thinking:D.Optional(D.Boolean())})}),e.post(`/v1/decisions`,async({body:e,set:t,store:n})=>{let{config:r,backend:i}=n,a=(e,n,r,i=null)=>(t.status=e,{error:{message:r,type:`invalid_request_error`,param:n,code:i}}),o;try{o=rn(e)}catch(e){if(e instanceof R)return a(400,e.param,e.message);throw e}let s=(r.generators||[]).filter(Gt),c=s.map(p),{model:l}=o;if(!c.includes(l))return a(404,`model`,`The decision model "${l}" does not exist. Available: ${c.join(`, `)||`(none)`}`,`model_not_found`);let u=s[c.indexOf(l)];if(o.request.images&&!dn(r,u))return a(400,`input`,`The decision model "${l}" takes no images: it has no projector (mmproj) configured`);try{return an(await Xt(i,r,{model:l,...o.request},`[OpenAI]`),o.plan,l)}catch(e){return console.error(`[OpenAI] Decision failed:`,e?.message||e),t.status=500,{error:{message:e?.message||`Decision failed`,type:`server_error`}}}}),e}const mn=()=>`msg_${Date.now()}${Math.random().toString(36).slice(2,11)}`;function hn(e){let t={},n=[];if(e.system!=null){let t=``;if(typeof e.system==`string`)t=e.system;else if(Array.isArray(e.system))for(let n of e.system)n?.type===`text`&&typeof n.text==`string`&&(t+=n.text);t&&n.push({role:`system`,content:t})}if(!Array.isArray(e.messages))throw Error(`'messages' is required and must be an array`);for(let t of e.messages){let e=t?.role||`user`;if(t?.content==null){if(e===`assistant`)continue;n.push(t);continue}if(typeof t.content==`string`){n.push({role:e,content:t.content});continue}if(!Array.isArray(t.content)){n.push(t);continue}let r=[],i=[],a=[],o=``,s=!1;for(let e of t.content){let t=e?.type||``;if(t===`text`)i.push({type:`text`,text:e.text||``});else if(t===`thinking`)o+=e.thinking||``;else if(t===`image`){let t=e.source||{};if(t.type===`base64`){let e=t.media_type||`image/jpeg`,n=t.data||``;i.push({type:`image_url`,image_url:{url:`data:${e};base64,${n}`}})}else t.type===`url`&&i.push({type:`image_url`,image_url:{url:t.url||``}})}else if(t===`tool_use`)r.push({id:e.id||``,type:`function`,function:{name:e.name||``,arguments:JSON.stringify(e.input??{})}}),s=!0;else if(t===`tool_result`){let t=e.tool_use_id||``,n=``,r=e.content;if(typeof r==`string`)n=r;else if(Array.isArray(r))for(let e of r)e?.type===`text`&&(n+=e.text||``);a.push({role:`tool`,tool_call_id:t,content:n})}}if(i.length>0||s||o){let t={role:e};i.length>0?t.content=i:(s||o)&&(t.content=``),r.length>0&&(t.tool_calls=r),o&&(t.reasoning_content=o),n.push(t)}for(let e of a)n.push(e)}if(t.messages=n,Array.isArray(e.tools)&&(t.tools=e.tools.map(e=>({type:`function`,function:{name:e.name||``,description:e.description||``,parameters:e.input_schema||{}}}))),e.tool_choice&&typeof e.tool_choice==`object`){let n=e.tool_choice.type;n===`auto`?t.tool_choice=`auto`:n===`any`||n===`tool`?t.tool_choice=`required`:n===`none`&&(t.tool_choice=`none`)}else Array.isArray(t.tools)&&t.tools.length>0&&(t.tool_choice=`auto`);e.stop_sequences!=null&&(t.stop=Array.isArray(e.stop_sequences)?e.stop_sequences:[e.stop_sequences]),t.max_tokens=e.max_tokens??4096;for(let n of[`temperature`,`top_p`,`top_k`,`stream`])e[n]!=null&&(t[n]=e[n]);return e.thinking&&typeof e.thinking==`object`&&e.thinking.type===`enabled`&&(t.enable_thinking=!0,e.thinking.budget_tokens!=null&&(t.thinking_budget_tokens=e.thinking.budget_tokens)),t}function gn(e,t){return t?`tool_use`:e.stopping_word||e.stoppingWord?`stop_sequence`:e.interrupted||e.truncated||Ut(e)?`max_tokens`:`end_turn`}function _n(e){let{promptTokens:t,cachedTokens:n,completionTokens:r}=Ht(e);return{cache_read_input_tokens:n,input_tokens:t,output_tokens:r}}async function vn(e,t,n){let r=e.getReader(),i=``,a=``,o=[],s={cache_read_input_tokens:0,input_tokens:0,output_tokens:0},c=`end_turn`,l=null;try{let e=!1;for(;!e;){let t=await r.read();if({done:e}=t,e)break;let n=t.value;if(!n)break;let{event:u,data:d}=n;if(u===`token`)d.content!=null&&(i=d.content),d.reasoning_content!=null&&(a=d.reasoning_content);else if(u===`result`)d.content==null?d.text&&d.reasoning_content==null&&(i=d.text):i=d.content,d.reasoning_content!=null&&(a=d.reasoning_content),Array.isArray(d.tool_calls)&&(o=d.tool_calls),s=_n(d),l=d.stopping_word||d.stoppingWord||null,c=gn(d,o.length>0);else if(u===`error`)throw Error(d.message||`completion error`)}}finally{C(r)}let u=[];a&&u.push({type:`thinking`,thinking:a,signature:``}),i&&u.push({type:`text`,text:i});for(let e of o){let t={};try{t=JSON.parse(e.function?.arguments||`{}`)}catch{t={}}u.push({type:`tool_use`,id:e.id||`toolu_${Math.random().toString(36).slice(2,11)}`,name:e.function?.name||``,input:t})}return{id:t,type:`message`,role:`assistant`,content:u,model:n,stop_reason:c,stop_sequence:l,usage:s}}async function*yn(e,t,n){let r=e.getReader(),i=``,a=``,o=new Map,s=new Map,c=new Map,l=new Set,u=!1,d=!1,f=0,p=-1,m=-1,h=new Map,g={cache_read_input_tokens:0,input_tokens:0,output_tokens:0},_=`end_turn`,v=null,y=!1;function*b(e){for(let n=0;n<e.length;n+=1){let r=e[n],i=r?.function?.arguments||``,a=o.get(n)||``;if(!l.has(n)){let e=r?.id||`toolu_${t}_${n}`,i=r?.function?.name||c.get(n)||``;s.set(n,e),c.set(n,i),h.set(n,f),l.add(n),yield E({event:`content_block_start`,data:JSON.stringify({type:`content_block_start`,index:f,content_block:{type:`tool_use`,id:e,name:i,input:{}}})}),f+=1}let u=h.get(n);i.length>a.length&&(yield E({event:`content_block_delta`,data:JSON.stringify({type:`content_block_delta`,index:u,delta:{type:`input_json_delta`,partial_json:i.slice(a.length)}})}),o.set(n,i))}}try{let e=!1;for(;!e;){let o=await r.read();if({done:e}=o,e)break;let s=o.value;if(!s)break;let{event:c,data:h}=s;if(c===`token`){if(!y){let e=_n(h);yield E({event:`message_start`,data:JSON.stringify({type:`message_start`,message:{id:t,type:`message`,role:`assistant`,content:[],model:n,stop_reason:null,stop_sequence:null,usage:e}})}),y=!0}if(h.reasoning_content!=null){let e=h.reasoning_content;e.length>a.length&&(u||(p=f,f+=1,u=!0,yield E({event:`content_block_start`,data:JSON.stringify({type:`content_block_start`,index:p,content_block:{type:`thinking`,thinking:``}})})),yield E({event:`content_block_delta`,data:JSON.stringify({type:`content_block_delta`,index:p,delta:{type:`thinking_delta`,thinking:e.slice(a.length)}})}),a=e)}if(h.content!=null){let e=h.content;e.length>i.length&&(d||(m=f,f+=1,d=!0,yield E({event:`content_block_start`,data:JSON.stringify({type:`content_block_start`,index:m,content_block:{type:`text`,text:``}})})),yield E({event:`content_block_delta`,data:JSON.stringify({type:`content_block_delta`,index:m,delta:{type:`text_delta`,text:e.slice(i.length)}})}),i=e)}Array.isArray(h.tool_calls)&&h.tool_calls.length>0&&(yield*b(h.tool_calls))}else if(c===`result`){if(!y){let e=_n(h);yield E({event:`message_start`,data:JSON.stringify({type:`message_start`,message:{id:t,type:`message`,role:`assistant`,content:[],model:n,stop_reason:null,stop_sequence:null,usage:e}})}),y=!0}Array.isArray(h.tool_calls)&&h.tool_calls.length>0&&(yield*b(h.tool_calls)),g=_n(h),v=h.stopping_word||h.stoppingWord||null,_=gn(h,l.size>0)}else if(c===`error`){yield E({event:`error`,data:JSON.stringify({type:`error`,error:{type:`api_error`,message:h.message||`completion error`}})});return}}u&&(yield E({event:`content_block_delta`,data:JSON.stringify({type:`content_block_delta`,index:p,delta:{type:`signature_delta`,signature:``}})}),yield E({event:`content_block_stop`,data:JSON.stringify({type:`content_block_stop`,index:p})})),d&&(yield E({event:`content_block_stop`,data:JSON.stringify({type:`content_block_stop`,index:m})}));for(let e of[...l].sort((e,t)=>e-t))yield E({event:`content_block_stop`,data:JSON.stringify({type:`content_block_stop`,index:h.get(e)})});yield E({event:`message_delta`,data:JSON.stringify({type:`message_delta`,delta:{stop_reason:_,stop_sequence:v},usage:{input_tokens:g.input_tokens,cache_read_input_tokens:g.cache_read_input_tokens,output_tokens:g.output_tokens}})}),yield E({event:`message_stop`,data:JSON.stringify({type:`message_stop`})})}finally{C(r)}}function bn(){let e=I({prefix:`/anthropic-messages`});return e.onBeforeHandle(st),e.post(`/v1/messages`,async function*({body:e,set:t,store:n}){let{config:r,backend:i}=n,a=e,o=null;try{if(!Array.isArray(a.messages)||a.messages.length===0)return t.status=400,{type:`error`,error:{type:`invalid_request_error`,message:`messages is required and must not be empty`}};let e=hn(a);o=await Vt(i,r,a.model,`[Anthropic]`);let n=mn(),s=o.repoId||`ggml-llm`,c={...Lt,messages:e.messages};e.temperature!=null&&(c.temperature=e.temperature),e.top_p!=null&&(c.top_p=e.top_p),e.top_k!=null&&(c.top_k=e.top_k),e.max_tokens!=null&&(c.n_predict=e.max_tokens),e.stop!=null&&(c.stop=e.stop),e.tools!=null&&(c.tools=e.tools),e.tool_choice!=null&&(c.tool_choice=e.tool_choice),c.enable_thinking=e.enable_thinking??!1,e.thinking_budget_tokens!=null&&(c.thinking_budget_tokens=e.thinking_budget_tokens);let l=await Rt(i,o.type).completion(o.id,{options:c});if(!a.stream)return await vn(l,n,s);yield*yn(l,n,s)}catch(e){return console.error(`[Anthropic] Messages error:`,e),t.status=500,{type:`error`,error:{type:`api_error`,message:e?.message||`Internal server error`}}}finally{await Bt(i,o,`[Anthropic]`)}},{body:D.Object({model:D.Optional(D.String()),messages:D.Array(D.Any()),system:D.Optional(D.Any()),max_tokens:D.Optional(D.Number()),stream:D.Optional(D.Boolean()),temperature:D.Optional(D.Number()),top_p:D.Optional(D.Number()),top_k:D.Optional(D.Number()),stop_sequences:D.Optional(D.Union([D.String(),D.Array(D.String())])),tools:D.Optional(D.Array(D.Any())),tool_choice:D.Optional(D.Any()),thinking:D.Optional(D.Any()),metadata:D.Optional(D.Any())})}),e.post(`/v1/messages/count_tokens`,async({body:e,set:t,store:n})=>{let{config:r,backend:i}=n,a=e,o=null;try{let e=hn(a);o=await Vt(i,r,a.model,`[Anthropic]`);let t=Rt(i,o.type),n={messages:e.messages,add_generation_prompt:!0,jinja:!0};e.tools!=null&&(n.tools=e.tools);let s=await t.applyChatTemplate(o.id,n),c=typeof s==`string`?s:s?.prompt||``,l=await t.tokenize(o.id,{text:c,add_special:!0,parse_special:!0});return{input_tokens:(Array.isArray(l)?l:l?.tokens||[]).length}}catch(e){return console.error(`[Anthropic] count_tokens error:`,e),t.status=500,{type:`error`,error:{type:`api_error`,message:e?.message||`Internal server error`}}}finally{await Bt(i,o,`[Anthropic]`)}},{body:D.Object({model:D.Optional(D.String()),messages:D.Array(D.Any()),system:D.Optional(D.Any()),tools:D.Optional(D.Array(D.Any())),tool_choice:D.Optional(D.Any())})}),e.get(`/v1/models`,({store:e})=>{let{config:t}=e,n=(t.generators||[]).filter(e=>Ft.includes(e.type)).map(e=>{let t=p(e);return{id:t,type:`model`,display_name:t,created_at:new Date().toISOString()}});return n.length===0&&n.push({id:`ggml-llm`,type:`model`,display_name:`ggml-llm`,created_at:new Date().toISOString()}),{data:n,has_more:!1,first_id:n[0]?.id,last_id:n.at(-1)?.id}}),e}const xn=[`choice`,`score`,`noul`],B=(e,t)=>({loc:[`body`,...e],msg:t,type:`value_error`}),Sn=e=>typeof e==`object`&&!!e&&!Array.isArray(e),Cn=e=>{if(!Sn(e))return[B([],`Request body must be a JSON object`)];let t=[],{state:n,questions:r,images:i}=e;if((n==null||n===``||![`string`,`object`].includes(typeof n))&&t.push(B([`state`],"`state` must be a non-empty string, object or array")),!Sn(r)||Object.keys(r).length===0)t.push(B([`questions`],"`questions` must be a non-empty object"));else for(let[e,n]of Object.entries(r)){let r=[`questions`,e];if(!Sn(n)||!xn.includes(n.type)){t.push(B([...r,`type`],`Question type must be one of ${xn}`));continue}let{type:i,criteria:a}=n;if(i===`choice`){let e=Sn(a)?Object.keys(a).length:0;(e===0||e>255)&&t.push(B([...r,`criteria`],`A choice needs 1 to 255 options in an object`))}else i===`score`?(!Array.isArray(a)||a.length<2||a.length>10)&&t.push(B([...r,`criteria`],`A score needs an ordered array of 2 to 10 levels`)):a!=null&&!Sn(a)&&t.push(B([...r,`criteria`],`Noul criteria must be { true?, false? }`))}return i!==void 0&&(!Array.isArray(i)||i.some(e=>typeof e!=`string`||!e.startsWith(`data:`)))&&t.push(B([`images`],"`images` must be an array of data URLs")),t},wn=e=>[...new Set((e.generators||[]).filter(Gt).map(p))];function Tn(){let e=I({prefix:`/typesafe-compat`});return e.onBeforeHandle(({set:e})=>{e.headers[`x-typesafe-request-id`]=j()}),e.onBeforeHandle(st),e.get(`/v1/models`,({store:e})=>({models:wn(e.config).map(e=>({name:e,description:`Buttress decision generator`,release_date:``}))})),e.post(`/v1/systemone`,async({body:e,set:t,store:n})=>{let{config:r,backend:i}=n,a=Cn(e),o=wn(r),s=e,c=s?.model,l=o.includes(c)?c:void 0;if(a.length===0&&!l){let e=o.join(`, `)||`(none)`;a.push(B([`model`],typeof c==`string`?`Unknown decision model "${c}". Available: ${e}`:`\`model\` is required. Available: ${e}`))}if(a.length>0)return t.status=422,{detail:a};let{state:u,questions:d,images:f}=s;try{return{...await Xt(i,r,{model:l,state:u,questions:d,...f?.length?{images:f}:{}},`[TypeSafe]`),model:l}}catch(e){return console.error(`[TypeSafe] Decision failed:`,e?.message||e),t.status=500,{error:{message:e?.message||`Decision failed`}}}}),e}const En=[`.ts`,`.mts`,`.js`,`.mjs`],Dn=/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/,On=new Set([`mcp`,`files`,`upload`]),kn=new Set([`cross-site`,`same-site`]),An=e=>kn.has(String(e[`sec-fetch-site`]||``).toLowerCase()),jn=(e,t)=>t?t===`*`?!0:e?(Array.isArray(t)?t:[t]).includes(e):!1:!1,Mn=e=>{let t=/^\/functions\/([^/]+)\/?$/.exec(e);if(!t)return;let n;try{n=decodeURIComponent(t[1])}catch{return}return On.has(n)?void 0:n},Nn=(e,t)=>({error:{code:e,message:t}}),Pn=({allowUnauthenticated:e,allowedOrigins:t,getCustomAuth:n})=>(async({headers:r,query:i,set:a,store:o,request:s,path:c})=>{let l=(c||(s?new URL(s.url).pathname:``)).split(`?`)[0],u=s?.method||`GET`,d=(e,t,n)=>{L.recordAuth({method:u,path:l,outcome:e,mode:t,subject:n})},f=r.origin||r.Origin;if((f||An(r))&&!jn(f,t))return d(`FUNCTIONS_ORIGIN_BLOCKED`),a.status=403,Nn(`FUNCTIONS_ORIGIN_BLOCKED`,`Cross-site browser requests${f?` from origin "${f}"`:``} are not allowed. Add the origin to [functions] cors_allowed_origins to permit browser access.`);let p=null;if(n)try{p=await n()}catch{return d(`FUNCTIONS_AUTH_UNAVAILABLE`),a.status=500,Nn(`FUNCTIONS_AUTH_UNAVAILABLE`,`The custom auth function (_auth) failed to load; calls are rejected until it is fixed.`)}let m=o.workspaceState?.workspace??null,h=at(r,i),g=null;if(!p||p.mode===`both`){let t=p?`both`:`workspace`;if(!m){if(!e)return d(`FUNCTIONS_UNAUTHENTICATED_DISABLED`,t),a.status=403,Nn(`FUNCTIONS_UNAUTHENTICATED_DISABLED`,"Local functions require a workspace binding. Run `bricks buttress bind`, or set [functions] allow_unauthenticated = true to run them unauthenticated.")}else if(g=await ot(h,m),!g)return d(`UNAUTHORIZED`,t),a.status=401,a.headers&&(a.headers[`WWW-Authenticate`]=`Bearer`),Nn(`UNAUTHORIZED`,`Invalid or missing workspace access token`);if(!p){d(`allowed`,`workspace`,g?.subjectId);return}}else g=m?await ot(h,m):null;let _={method:u,path:l,name:Mn(l),headers:r,query:i,token:h,workspaceAuth:{bound:!!m,authenticated:!!g,identity:g}},v;try{v=await p.run(_)}catch(e){return console.warn(`[Functions] custom auth function threw:`,e?.message||e),d(`FUNCTIONS_AUTH_ERROR`,p.mode,g?.subjectId),a.status=500,Nn(`FUNCTIONS_AUTH_ERROR`,`The custom auth function failed`)}let y=typeof v==`object`&&v?v:null;if(v===!0||y?.ok===!0){d(`allowed`,p.mode,g?.subjectId);return}d(`FUNCTIONS_AUTH_REJECTED`,p.mode,g?.subjectId);let b=typeof y?.status==`number`&&y.status>=400&&y.status<=499?y.status:403;return a.status=b,b===401&&a.headers&&(a.headers[`WWW-Authenticate`]=`Bearer`),Nn(`FUNCTIONS_AUTH_REJECTED`,typeof y?.error==`string`&&y.error||`Rejected by the custom auth function`)}),Fn=new Set([`.ts`,`.mts`,`.cts`]),In=(e,t)=>{let n=t.map(e=>e.codeframe||e.message||String(e)).join(`
5
5
  `);return`Failed to parse ${M.basename(e)}:\n${n}`},Ln=(e,t)=>{let n=t;if(Fn.has(M.extname(e))){let r=Se(e,t,{sourceType:`module`});if(r.errors?.length)throw SyntaxError(In(e,r.errors));n=r.code}let r=xe(e,n);if(r.errors?.length)throw SyntaxError(In(e,r.errors));return{code:r.code,deps:r.deps||[],dynamicDeps:r.dynamicDeps||[]}},Rn=Function(`specifier`,`return import(specifier)`),zn=new Set(ee),Bn={sqlite3:()=>import(`sqlite3`),"sqlite-vec":()=>import(`sqlite-vec`)};var Vn=class extends Error{constructor(e){super(e),this.name=`FunctionImportError`}};const Hn=(e={})=>({console,setTimeout,clearTimeout,setInterval,clearInterval,setImmediate,clearImmediate,queueMicrotask,URL,URLSearchParams,TextEncoder,TextDecoder,AbortController,AbortSignal,Buffer,structuredClone,performance,crypto:globalThis.crypto,fetch:globalThis.fetch,atob:globalThis.atob,btoa:globalThis.btoa,Event:globalThis.Event,EventTarget:globalThis.EventTarget,...e}),Un=async e=>{try{return(await O.stat(e)).isFile()}catch{return!1}},Wn=e=>{let t=M.extname(e);if(!t)return[...En.map(t=>`${e}${t}`),...En.map(t=>M.join(e,`index${t}`))];let n=[e];return t===`.js`&&n.push(`${e.slice(0,-3)}.ts`),t===`.mjs`&&n.push(`${e.slice(0,-4)}.mts`),n},Gn=async(e,t,n)=>{if(e.startsWith(`node:`)){let n=e.slice(5);if(!zn.has(n))throw new Vn(`Cannot import "${e}" from ${M.basename(t)}: unknown Node builtin.`);return{kind:`builtin`,id:e}}if(zn.has(e))return{kind:`builtin`,id:`node:${e}`};if(Object.prototype.hasOwnProperty.call(Bn,e))return{kind:`package`,id:e};if(!(e.startsWith(`./`)||e.startsWith(`../`))&&!M.isAbsolute(e))throw new Vn(`Cannot import "${e}" from ${M.basename(t)}: local functions may only import Node builtins (e.g. "node:fs/promises"), "sqlite3", "sqlite-vec", and sibling files in the functions directory. Other package imports are not supported.`);let r=M.resolve(M.dirname(t),e),i=M.relative(n,r);if(i.startsWith(`..`)||M.isAbsolute(i))throw new Vn(`Cannot import "${e}" from ${M.basename(t)}: path escapes the functions directory.`);for(let e of Wn(r))if(await Un(e))return{kind:`file`,path:e};throw new Vn(`Cannot import "${e}" from ${M.basename(t)}: file not found.`)},Kn=async(e,{rootDir:t,globals:n={}})=>{let r=be.createContext(Hn(n)),i=new Map,a=new Map,o=new Map,s=e=>{let t=i.get(e);if(t)return Promise.resolve(t);let n=a.get(e);if(n)return n;let r=c(e).finally(()=>{a.delete(e)});return a.set(e,r),r},c=async e=>{let[n,a]=await Promise.all([O.readFile(e,`utf8`),O.stat(e)]);o.set(e,a.mtimeMs);let{code:c}=Ln(e,n),l={};i.set(e,l);let u=be.runInContext(`(async function (__vite_ssr_exports__, __vite_ssr_import__, __vite_ssr_dynamic_import__, __vite_ssr_exportAll__, __vite_ssr_import_meta__) {
@@ -613,7 +613,7 @@ export default async function (context: ButtressDaemonContext) {
613
613
  `).slice(1)){if(!e.trim())continue;let t;try{t=JSON.parse(e)}catch{continue}n.push(...Array.isArray(t)?t:[t])}return n},Po=e=>{let t=new Map,n=null;for(let r of e)r?.kind===`entry`&&typeof r.id==`string`?t.set(r.id,r):r?.kind===`value`&&r.namespace===`pi.branch.tip`&&r.key===`main`&&(!n||r.seq>n.seq)&&(n={seq:r.seq,id:r.value??null});let r=[],i=new Set;for(let e=n?.id??null;e!=null&&!i.has(e);){i.add(e);let n=t.get(e);if(!n)break;n.type===`message`&&r.push(n.message),e=n.parentId}return r.reverse()},Fo=async e=>{let t=await No(e.path);return e.legacy?Po(t):t.filter(e=>e?.kind===`message`).map(e=>e.message)},Io=e=>`${JSON.stringify({kind:`message`,message:e})}\n`,Lo=async(e,t)=>{let n={kind:`header`,format:ko,v:1,id:e.id,createdAt:e.createdAt,...e.parentSessionId?{parentSessionId:e.parentSessionId}:{}},r=`${e.path}.${He()}.tmp`;try{await O.writeFile(r,JSON.stringify(n)+`
614
614
  `+t.map(Io).join(``)),await O.rename(r,e.path)}catch(e){throw await O.rm(r,{force:!0}),e}},Ro=e=>({sessionId:e.id,createdAt:new Date(e.createdAt).toISOString(),updatedAt:new Date(e.modifiedAt).toISOString(),parentSession:e.parentSessionId??null,preview:jo(e.path)}),zo=e=>{P.mkdirSync(e.sessionsDir,{recursive:!0});let t=t=>{let n=M.resolve(e.sessionsDir,`/agents/${t}`);return M.join(e.sessionsDir,`--${n.replace(/^[/\\]/,``).replace(/[/\\:]/g,`-`)}--`)},n=async e=>{let n=t(e);try{return(await O.readdir(n)).filter(e=>e.endsWith(`.jsonl`)).map(e=>M.join(n,e))}catch(e){if(e?.code===`ENOENT`)return[];throw e}},r=async e=>(await n(e)).map(Mo).filter(e=>e!==null),i=async(e,t)=>{let r=`_${encodeURIComponent(t)}.jsonl`,i=(await n(e)).find(e=>e.endsWith(r)),a=i?Mo(i):null;if(!a||a.id!==t)throw Error(`[Agents] unknown session "${t}" for agent "${e}"`);return a},a=async(e,n,r)=>{let i=He(),a=Date.now(),o=t(e);await O.mkdir(o,{recursive:!0});let s=new Date(a).toISOString().replace(/[:.]/g,`-`),c={id:i,createdAt:a,...r?{parentSessionId:r}:{},path:M.join(o,`${s}_${encodeURIComponent(i)}.jsonl`)};return await Lo(c,n),{metadata:{...c,modifiedAt:a,legacy:!1},appendable:!0}},o=async e=>{if(e.appendable)return;let{metadata:t}=e;if(t.legacy)await Lo(t,await Fo(t)),t.legacy=!1;else{let e=await O.readFile(t.path,`utf8`);e.endsWith(`
615
615
  `)||await O.truncate(t.path,Buffer.byteLength(e.slice(0,e.lastIndexOf(`
616
- `)+1)))}e.appendable=!0};return{create:e=>a(e,[]),open:async(e,t)=>({metadata:await i(e,t),appendable:!1}),fork:async(e,t)=>{let n=await i(e,t);return a(e,await Fo(n),n.id)},append:async(e,t)=>{await o(e),await O.appendFile(e.metadata.path,Io(t))},list:async(e,t=50)=>(await r(e)).sort((e,t)=>t.modifiedAt-e.modifiedAt).slice(0,t).map(Ro),messages:async e=>(await Fo(e.metadata)).filter(e=>!(e.role===`assistant`&&[`error`,`aborted`,`deferred`].includes(e.stopReason))),sweep:async t=>{let n=0,i=Date.now();for(let a of t){let t;try{t=await r(a)}catch{continue}t.sort((e,t)=>t.modifiedAt-e.modifiedAt);for(let[r,a]of t.entries()){let t=e.sessionMaxCount!=null&&r>=e.sessionMaxCount,o=e.sessionMaxAgeMs!=null&&i-a.modifiedAt>e.sessionMaxAgeMs;if(!(!t&&!o))try{await O.rm(a.path),n+=1}catch(e){console.warn(`[Agents] retention: failed to delete session ${a.id}:`,e?.message||e)}}}return n}}},Bo=256*1024,Vo=e=>e.length<=Bo?e:`${e.slice(0,Bo)}\n… [truncated ${e.length-Bo} characters]`,Ho=()=>import(`./mcp-DzknURyz.mjs`),Uo=e=>({...e.url?{url:e.url,headers:e.headers}:{},...e.command?{command:e.command,args:e.args,env:e.env}:{},...e.timeout==null?{}:{timeout:e.timeout},...e.exposure?{exposure:e.exposure}:{},...e.toolExposure?{toolExposure:e.toolExposure}:{}}),Wo=({configDir:e})=>{let t=new Map,n=async(t,n)=>{let r=await Ho(),i=r.validateMcpServerConfig(t,Uo(n));if(typeof i==`string`)throw Error(i);return r.connectMcpServer({name:t,config:i,cwd:e,clientName:`buttress-agent`})};return{toolsFor:async(e,r)=>{let i=[];for(let[a,o]of Object.entries(r)){let r=`${e} ${a}`,s=t.get(r);s||(s=n(a,o),t.set(r,s),s.catch(()=>t.delete(r)));try{i.push(await s)}catch(t){let n=`MCP server "${a}" failed to connect: ${t?.message||t}`;if(o.optional){console.warn(`[Agents] ${e}: ${n} (optional — continuing without it)`);continue}throw Error(`[Agents] ${e}: ${n}`)}}let{createMcpAgentTools:a}=await Ho();return a(i,{defaultExposure:`direct`,limitText:Vo})},dispose:async()=>{let e=[...t.values()];t.clear(),await Promise.all(e.map(async e=>{try{await(await e).close()}catch{}}))}}},Go=()=>import(`./codemode-Cva7OeQX.mjs`);function Ko(){let e=process.env.BUTTRESS_CODEMODE_WORKER;if(e)return{workerUrl:e,wasmPath:process.env.BUTTRESS_CODEMODE_WASM};let t=new URL(`./codemode-worker.mjs`,import.meta.url),n=new URL(`./quickjs.wasm`,import.meta.url);return t.protocol!==`file:`||!P.existsSync(de(t))?{}:{workerUrl:t,wasmPath:de(n)}}async function qo({tools:e,declaredNames:t,getState:n,models:r}){let i=await Go();return i.createCodemodeTool({getTools:()=>e,declaredNames:t,executeTool:(e,t,r)=>i.runNestedToolCall(e,t,{...r,state:n()}),getStore:()=>i.collectCodemodeStore(n()?.messages),models:i.createCodemodeModels({classifiers:async()=>r}),sandbox:{...Ko(),defaultTimeoutMs:i.DEFAULT_CODEMODE_TIMEOUT_MS,maxTimeoutMs:i.MAX_CODEMODE_TIMEOUT_MS}})}const Jo=async(e,{functions:t,runtime:n,depth:r,onToolEmit:i})=>{if(e.tools.length===0)return[];if(!t)throw Error(`[Agents] ${e.name}: tools are configured but local functions are disabled (set [functions] enabled = true)`);let a=await t.list(),o=new Map(a.map(e=>[e.name,e])),s=e.tools.filter(e=>!o.has(e));if(s.length>0)throw Error(`[Agents] ${e.name}: configured tool${s.length===1?``:`s`} not found in the functions directory: ${s.join(`, `)}`);return e.tools.map(e=>{let a=o.get(e);return{name:e,label:e,description:a.description||`Local function: ${e}`,parameters:a.parameters||{type:`object`,properties:{}},execute:async(a,o,s)=>{try{return{content:[{type:`text`,text:ni(await t.call(e,o??{},{runtime:n,signal:s,surface:`agent`,agentDepth:r,emit:(t,n)=>i?.(e,t,n,a)}))}],details:{}}}catch(e){return{content:[{type:`text`,text:`Tool error: ${e?.message||String(e)}`}],details:{}}}}}})};let Yo=w(import.meta.url);var Xo,Zo,Qo,$o,es,ts,ns,rs={84361(e){e.exports=import(`./wrapper-3PX6qE3t.mjs`).then(function(e){return e})},41314(e){e.exports=Yo(`node:dgram`)},51455(e){e.exports=Yo(`node:fs/promises`)},48161(e){e.exports=Yo(`node:os`)},76760(e){e.exports=Yo(`node:path`)},66442(e){e.exports=function(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},e.exports.__esModule=!0,e.exports.default=e.exports},3634(e){e.exports=function(e){if(Array.isArray(e))return e},e.exports.__esModule=!0,e.exports.default=e.exports},99436(e){function t(e,t,n,r,i,a,o){try{var s=e[a](o),c=s.value}catch(e){n(e);return}s.done?t(c):Promise.resolve(c).then(r,i)}e.exports=function(e){return function(){var n=this,r=arguments;return new Promise(function(i,a){var o=e.apply(n,r);function s(e){t(o,i,a,s,c,`next`,e)}function c(e){t(o,i,a,s,c,`throw`,e)}s(void 0)})}},e.exports.__esModule=!0,e.exports.default=e.exports},96525(e){e.exports=function(e,t){var n=e==null?null:`u`>typeof Symbol&&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){if(Object(n)!==n)return;c=!1}else 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}},e.exports.__esModule=!0,e.exports.default=e.exports},5523(e){e.exports=function(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
616
+ `)+1)))}e.appendable=!0};return{create:e=>a(e,[]),open:async(e,t)=>({metadata:await i(e,t),appendable:!1}),fork:async(e,t)=>{let n=await i(e,t);return a(e,await Fo(n),n.id)},append:async(e,t)=>{await o(e),await O.appendFile(e.metadata.path,Io(t))},list:async(e,t=50)=>(await r(e)).sort((e,t)=>t.modifiedAt-e.modifiedAt).slice(0,t).map(Ro),messages:async e=>(await Fo(e.metadata)).filter(e=>!(e.role===`assistant`&&[`error`,`aborted`,`deferred`].includes(e.stopReason))),sweep:async t=>{let n=0,i=Date.now();for(let a of t){let t;try{t=await r(a)}catch{continue}t.sort((e,t)=>t.modifiedAt-e.modifiedAt);for(let[r,a]of t.entries()){let t=e.sessionMaxCount!=null&&r>=e.sessionMaxCount,o=e.sessionMaxAgeMs!=null&&i-a.modifiedAt>e.sessionMaxAgeMs;if(!(!t&&!o))try{await O.rm(a.path),n+=1}catch(e){console.warn(`[Agents] retention: failed to delete session ${a.id}:`,e?.message||e)}}}return n}}},Bo=256*1024,Vo=e=>e.length<=Bo?e:`${e.slice(0,Bo)}\n… [truncated ${e.length-Bo} characters]`,Ho=()=>import(`./mcp-DzknURyz.mjs`),Uo=e=>({...e.url?{url:e.url,headers:e.headers}:{},...e.command?{command:e.command,args:e.args,env:e.env}:{},...e.timeout==null?{}:{timeout:e.timeout},...e.exposure?{exposure:e.exposure}:{},...e.toolExposure?{toolExposure:e.toolExposure}:{}}),Wo=({configDir:e})=>{let t=new Map,n=async(t,n)=>{let r=await Ho(),i=r.validateMcpServerConfig(t,Uo(n));if(typeof i==`string`)throw Error(i);return r.connectMcpServer({name:t,config:i,cwd:e,clientName:`buttress-agent`})};return{toolsFor:async(e,r)=>{let i=[];for(let[a,o]of Object.entries(r)){let r=`${e} ${a}`,s=t.get(r);s||(s=n(a,o),t.set(r,s),s.catch(()=>t.delete(r)));try{i.push(await s)}catch(t){let n=`MCP server "${a}" failed to connect: ${t?.message||t}`;if(o.optional){console.warn(`[Agents] ${e}: ${n} (optional — continuing without it)`);continue}throw Error(`[Agents] ${e}: ${n}`)}}let{createMcpAgentTools:a}=await Ho();return a(i,{defaultExposure:`direct`,limitText:Vo})},dispose:async()=>{let e=[...t.values()];t.clear(),await Promise.all(e.map(async e=>{try{await(await e).close()}catch{}}))}}},Go=()=>import(`./codemode-CRowB9aL.mjs`);function Ko(){let e=process.env.BUTTRESS_CODEMODE_WORKER;if(e)return{workerUrl:e,wasmPath:process.env.BUTTRESS_CODEMODE_WASM};let t=new URL(`./codemode-worker.mjs`,import.meta.url),n=new URL(`./quickjs.wasm`,import.meta.url);return t.protocol!==`file:`||!P.existsSync(de(t))?{}:{workerUrl:t,wasmPath:de(n)}}async function qo({tools:e,declaredNames:t,getState:n,models:r}){let i=await Go();return i.createCodemodeTool({getTools:()=>e,declaredNames:t,executeTool:(e,t,r)=>i.runNestedToolCall(e,t,{...r,state:n()}),getStore:()=>i.collectCodemodeStore(n()?.messages),models:i.createCodemodeModels({classifiers:async()=>r}),sandbox:{...Ko(),defaultTimeoutMs:i.DEFAULT_CODEMODE_TIMEOUT_MS,maxTimeoutMs:i.MAX_CODEMODE_TIMEOUT_MS}})}const Jo=async(e,{functions:t,runtime:n,depth:r,onToolEmit:i})=>{if(e.tools.length===0)return[];if(!t)throw Error(`[Agents] ${e.name}: tools are configured but local functions are disabled (set [functions] enabled = true)`);let a=await t.list(),o=new Map(a.map(e=>[e.name,e])),s=e.tools.filter(e=>!o.has(e));if(s.length>0)throw Error(`[Agents] ${e.name}: configured tool${s.length===1?``:`s`} not found in the functions directory: ${s.join(`, `)}`);return e.tools.map(e=>{let a=o.get(e);return{name:e,label:e,description:a.description||`Local function: ${e}`,parameters:a.parameters||{type:`object`,properties:{}},execute:async(a,o,s)=>{try{return{content:[{type:`text`,text:ni(await t.call(e,o??{},{runtime:n,signal:s,surface:`agent`,agentDepth:r,emit:(t,n)=>i?.(e,t,n,a)}))}],details:{}}}catch(e){return{content:[{type:`text`,text:`Tool error: ${e?.message||String(e)}`}],details:{}}}}}})};let Yo=w(import.meta.url);var Xo,Zo,Qo,$o,es,ts,ns,rs={84361(e){e.exports=import(`./wrapper-3PX6qE3t.mjs`).then(function(e){return e})},41314(e){e.exports=Yo(`node:dgram`)},51455(e){e.exports=Yo(`node:fs/promises`)},48161(e){e.exports=Yo(`node:os`)},76760(e){e.exports=Yo(`node:path`)},66442(e){e.exports=function(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},e.exports.__esModule=!0,e.exports.default=e.exports},3634(e){e.exports=function(e){if(Array.isArray(e))return e},e.exports.__esModule=!0,e.exports.default=e.exports},99436(e){function t(e,t,n,r,i,a,o){try{var s=e[a](o),c=s.value}catch(e){n(e);return}s.done?t(c):Promise.resolve(c).then(r,i)}e.exports=function(e){return function(){var n=this,r=arguments;return new Promise(function(i,a){var o=e.apply(n,r);function s(e){t(o,i,a,s,c,`next`,e)}function c(e){t(o,i,a,s,c,`throw`,e)}s(void 0)})}},e.exports.__esModule=!0,e.exports.default=e.exports},96525(e){e.exports=function(e,t){var n=e==null?null:`u`>typeof Symbol&&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){if(Object(n)!==n)return;c=!1}else 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}},e.exports.__esModule=!0,e.exports.default=e.exports},5523(e){e.exports=function(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
617
617
  In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)},e.exports.__esModule=!0,e.exports.default=e.exports},68832(e,t,n){var r=n(3634),i=n(96525),a=n(78243),o=n(5523);e.exports=function(e,t){return r(e)||i(e,t)||a(e,t)||o()},e.exports.__esModule=!0,e.exports.default=e.exports},78243(e,t,n){var r=n(66442);e.exports=function(e,t){if(e){if(typeof e==`string`)return r(e,t);var n={}.toString.call(e).slice(8,-1);return n===`Object`&&e.constructor&&(n=e.constructor.name),n===`Map`||n===`Set`?Array.from(e):n===`Arguments`||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?r(e,t):void 0}},e.exports.__esModule=!0,e.exports.default=e.exports},13346(e,t,n){n.a(e,async function(e,r){try{n.d(t,{TB:()=>o.verifyDevToolsServer,fl:()=>a.createCdpClient,le:()=>i.le});var i=n(38372),a=n(28193),o=n(75646),s=e([a]);a=(s.then?(await s)():s)[0],r()}catch(e){r(e)}})},28193(e,t,n){n.a(e,async function(e,r){try{n.d(t,{createCdpClient:()=>h});var i,a=n(99436),o=n(73610),s=n(72197),c=n(84361),l=n(19557),u=e([c]);c=(u.then?(await u)():u)[0];var d=15e3,f={[o.AB.takenOver]:`Another DevTools client took this device.`,[o.AB.targetGone]:`The device stopped its DevTools server (the app restarted or went to the background). Retry the command.`},p=({address:e,port:t,method:n,phase:r=`request`,closeCode:i,closeReason:a,local:o=!1})=>{var s=a?Buffer.isBuffer(a)?a.toString(`utf8`):String(a):``,c=r===`connect`?`before the CDP session opened`:n?`while waiting for ${n}`:`during the CDP session`,l=`${e}:${t}`,u=[];i!=null&&u.push(`code ${i}`),s&&u.push(`reason: ${s}`);var d=[o?`CDP client closed the connection to ${l} ${c}.`:`CDP connection to ${l} closed ${c}.`,u.length>0?`WebSocket close ${u.join(`, `)}.`:null,o?null:f[i]??`The DevTools server currently accepts one CDP client at a time. Another DevTools window or CLI command may have replaced this session. Retry the command, close the other inspector, or avoid running DevTools commands in parallel.`].filter(Boolean).join(`
618
618
  `),p=Error(d);return p.code=`CDP_CONNECTION_CLOSED`,p.method=n,p.phase=r,p.closeCode=i,p.closeReason=s,p},m=(i=a(function*(e,t,n){var r=n?typeof n==`string`?{passcode:n}:n:{},i=r.passcode,a=r.accessToken;if(a)return`ws://${e}:${t}/ws?access_token=${encodeURIComponent(a)}`;if(!i)try{var o=(yield(0,l.uE)(`http://${e}:${t}/json/list`))?.[0]?.webSocketDebuggerUrl;if(o){var s=o.match(/\/ws(?:\/.*)?$/);if(s)return`ws://${e}:${t}${s[0]}`}}catch{}return i?`ws://${e}:${t}/ws/${encodeURIComponent(i)}`:`ws://${e}:${t}/ws`}),function(e,t,n){return i.apply(this,arguments)}),h=(e,t,n)=>{var r,i,o=0,l=new Map,u=new Map,f=null,h=0,g=e=>{for(var t of l.values()){var n=t.reject,r=t.timer,i=t.method;clearTimeout(r),n(e(i))}l.clear()};return{connect:(r=a(function*(){var r=++h,a=yield m(e,t,n);if(r!==h)throw p({address:e,port:t,phase:`connect`,local:!0});return new Promise((n,r)=>{i=new c.WebSocket(a,{handshakeTimeout:d});var o=!1;i.once(`open`,()=>{o=!0,f=null,n()}),i.once(`error`,n=>{o||r(Error(n.message||`Cannot connect to ${e}:${t}`))}),i.on(`message`,e=>{try{var t=JSON.parse(e.toString());if(t.id!=null&&l.has(t.id)){var n=l.get(t.id),r=n.resolve,i=n.reject,a=n.timer,o=n.method;clearTimeout(a),l.delete(t.id),t.error?i((0,s.e)(t.error,o)):r(t.result);return}if(t.method){var c=u.get(t.method);if(c)for(var d of c)d(t.params)}}catch{}}),i.on(`close`,(n,i)=>{f={closeCode:n,closeReason:i},o||r(p({address:e,port:t,phase:`connect`,closeCode:n,closeReason:i})),g(r=>p({address:e,port:t,method:r,closeCode:n,closeReason:i}))})})}),function(){return r.apply(this,arguments)}),send:(n,r={},a=d)=>new Promise((s,c)=>{if(!i||i.readyState!==i.OPEN)return f?void c(p({address:e,port:t,method:n,closeCode:f.closeCode,closeReason:f.closeReason})):void c(Error(`Not connected to CDP at ${e}:${t} while sending ${n}`));var u=++o,d=setTimeout(()=>{l.delete(u),c(Error(`Timeout: ${n}`))},a);l.set(u,{resolve:s,reject:c,timer:d,method:n}),i.send(JSON.stringify({id:u,method:n,params:r}))}),on:(e,t)=>{u.has(e)||u.set(e,[]),u.get(e).push(t)},off:(e,t)=>{var n=u.get(e);if(n){var r=n.indexOf(t);r>=0&&n.splice(r,1)}},close:()=>{h++,g(n=>p({address:e,port:t,method:n,local:!0})),i&&=(i.terminate(),null)}}};r()}catch(e){r(e)}})},38372(e,t,n){n.d(t,{le:()=>m});var r,i,a,o=n(68832),s=n(99436),c=n(51455),l=n(76760),u=n(75646),d=n(19557),f=(r=s(function*(e,t,n=3e3){return(0,d.uE)(`http://${e}:${t}/json/list`,n)}),function(e,t){return r.apply(this,arguments)}),p=(i=s(function*(e,t=1e3){for(var n=[],r=e,i=0;i<10;i++){var a=l.join(r,`.bricks`,`devtools.json`);try{var o=yield c.readFile(a,`utf8`),s=JSON.parse(o),d=yield(0,u.verifyDevToolsServer)(s.address||`localhost`,s.port,t);d&&n.push({name:s.name||`BRICKS Simulator`,address:s.address||`localhost`,port:s.port,protocols:[`cdp`],hasPasscode:!1,source:`project`,projectPath:r,...d})}catch{}var f=l.dirname(r);if(f===r)break;r=f}return n}),function(e){return i.apply(this,arguments)}),m=(a=s(function*({timeout:e=3e3,verify:t=!1,udpOnly:n=!1,project:r=!0,port:i=19851,cwd:a=process.cwd(),onStatus:c}={}){var l,d=(0,u.discoverDevToolsServers)({timeout:e,idleTimeout:800}),m=n?Promise.resolve([]):(c?.(`Scanning via UDP + HTTP probe...`),(0,u.httpProbeSubnet)({port:i,timeout:e})),h=r?p(a,1e3):Promise.resolve([]),g=o(yield Promise.all([d,m,h]),3),_=(e=>{var t=new Map;for(var n of e){var r=n.deviceId||`${n.address}:${n.port}`,i=t.get(r);if(!i){t.set(r,{...n,addresses:[n.address],protocols:[...n.protocols||[]]});continue}for(var a of(i.addresses.includes(n.address)||i.addresses.push(n.address),i.address===`127.0.0.1`&&n.address!==`127.0.0.1`&&(i.address=n.address),n.protocols||[]))i.protocols.includes(a)||i.protocols.push(a);for(var s of Object.entries(n)){var c=o(s,2),l=c[0],u=c[1];u!=null&&l!==`address`&&l!==`addresses`&&l!==`protocols`&&(i[l]===void 0||i[l]===null)&&(i[l]=u)}}return[...t.values()]})([...g[0],...g[1],...g[2]]);if(_.length===0)return[];if(t){c?.(`Verifying ${_.length} server(s)...`);var v,y=yield Promise.all(_.map((v=s(function*(e){var t=yield(0,u.verifyDevToolsServer)(e.address,e.port);return{...e,...t||{},address:e.address,port:e.port,verified:!!t,version:t?.version||e.version}}),function(e){return v.apply(this,arguments)})));_.splice(0,_.length,...y)}return c?.(`Checking chrome://inspect support...`),yield Promise.all(_.map((l=s(function*(e){var t=yield f(e.address,e.port);if(t){e.chromeInspect=!0;var n=(e=>{if(!e)return null;var t=e.match(/\/ws\/(.+)$/);return t?decodeURIComponent(t[1]):null})(t[0]?.webSocketDebuggerUrl);n&&(e.passcode=n)}}),function(e){return l.apply(this,arguments)}))),_}),function(){return a.apply(this,arguments)})},75646(e,t,n){n.d(t,{discoverDevToolsServers:()=>c,httpProbeSubnet:()=>l,verifyDevToolsServer:()=>u});var r,i,a=n(99436),o=n(19557),s=`bricks-devtools`,c=({timeout:e=3e3,idleTimeout:t=0}={})=>(0,o.YH)({port:19900,timeout:e,idleTimeout:t,buildQuery:()=>Buffer.from(JSON.stringify({t:`QUERY`,v:`1.0`,s,d:{id:`cli-${(0,o.BW)()}`}})),parseMessage:(e,t)=>{var n=(0,o.nl)(e,e=>e?.s===s);if(!n)return null;var r=t.address;return{key:`${r}:${n.port}`,value:{...n,address:r}}}}),l=(r=a(function*({port:e=19851,connectTimeout:t=500,concurrency:n=50,timeout:r=0}={}){var i=(0,o.r9)();if(i.length===0)return[];var s=[],c=r>0?Date.now()+r:0,l=[],d=new Set;for(var f of i){var p=f.address.split(`.`).slice(0,3).join(`.`);if(!d.has(p)){d.add(p);for(var m=1;m<255;m++)l.push(`${p}.${m}`)}}for(var h=0;h<l.length&&!(c&&Date.now()>=c);h+=n){var g=l.slice(h,h+n);yield Promise.allSettled(g.map(function(){var n=a(function*(n){var r=yield u(n,e,t);r&&s.push({...r,address:n,port:e})});return function(e){return n.apply(this,arguments)}}()))}return s}),function(){return r.apply(this,arguments)}),u=(i=a(function*(e,t,n=3e3){return(0,o.uE)(`http://${e}:${t}/devtools/info`,n)}),function(e,t){return i.apply(this,arguments)})},19557(e,t,n){n.d(t,{BW:()=>s,YH:()=>d,nl:()=>l,r9:()=>u,uE:()=>f});var r,i=n(99436),a=n(41314),o=n(48161),s=()=>Math.random().toString(36).slice(2,9),c=new Set([`ANNOUNCE`,`RESPONSE`]),l=(e,t)=>{var n=JSON.parse(e.toString());return t(n)&&c.has(n.t)&&n.d?.info||null},u=()=>{var e=[];for(var t of Object.values(o.networkInterfaces()))for(var n of t)if(function(){if(n.family!==`IPv4`||n.internal)return 1;var t=n.address.split(`.`).map(Number),r=n.netmask.split(`.`).map(Number),i=t.map((e,t)=>(e|255&~r[t]).toString()).join(`.`);e.push({address:n.address,broadcast:i})}())continue;return e},d=({port:e,timeout:t=3e3,idleTimeout:n=0,buildQuery:r,parseMessage:i})=>new Promise((o,s)=>{var c=new Map,l=a.createSocket(`udp4`),d=null,f=null,p=!1,m=e=>{if(!p){p=!0,clearTimeout(d),clearTimeout(f);try{l.close()}catch{}e?s(e):o([...c.values()])}};l.on(`error`,m),l.on(`message`,(e,t)=>{if(!p)try{var r=i(e,t);if(!r||c.has(r.key))return;c.set(r.key,r.value),n&&!p&&(clearTimeout(f),f=setTimeout(m,n))}catch{}});try{l.bind(()=>{if(!p)try{l.setBroadcast(!0);var n=r();for(var i of(()=>{var e=new Set([`255.255.255.255`,`127.0.0.1`]);for(var t of u())e.add(t.broadcast);return[...e]})())l.send(n,0,n.length,e,i);d=setTimeout(m,t)}catch(e){m(e)}})}catch(e){m(e)}}),f=(r=i(function*(e,t=3e3){var n,r=new AbortController;try{n=setTimeout(()=>r.abort(),t);var i=yield fetch(e,{signal:r.signal});return i.ok?yield i.json():null}catch{return null}finally{n!==void 0&&clearTimeout(n),r.abort()}}),function(e){return r.apply(this,arguments)})},72197(e,t,n){n.d(t,{e:()=>r});let r=(e,t)=>{let n=Error(typeof e==`string`?e:e?.message||`CDP request failed${t?`: ${t}`:``}`);return e&&typeof e==`object`&&(e.code!==void 0&&(n.code=e.code),e.data!==void 0&&(n.data=e.data)),t&&(n.method=t),n}},73610(e,t,n){n.d(t,{AB:()=>r}),Object.freeze({ready:`bricks-devtools:ready`,init:`bricks-devtools:init`,hello:`bricks-devtools:hello`,connect:`bricks-devtools:connect`,disconnect:`bricks-devtools:disconnect`,close:`bricks-devtools:close`,openUrl:`bricks-devtools:open-url`,save:`bricks-devtools:save`,copy:`bricks-devtools:copy`,shortcut:`bricks-devtools:shortcut`,open:`bricks-devtools:open`,closed:`bricks-devtools:closed`,config:`bricks-devtools:config`,target:`bricks-devtools:target`});let r=Object.freeze({takenOver:4e3,targetGone:4001,signedOut:4003,noTarget:1006})}},is={};function q(e){var t=is[e];if(t!==void 0)return t.exports;var n=is[e]={exports:{}};return rs[e](n,n.exports,q),n.exports}Zo=(Xo=typeof Symbol==`function`)?Symbol(`rspack queues`):`__rspack_queues`,Qo=q.aE=Xo?Symbol(`rspack exports`):`__webpack_exports__`,$o=Xo?Symbol(`rspack error`):`__rspack_error`,es=Xo?Symbol(`rspack done`):`__rspack_done`,ts=q.zS=Xo?Symbol(`rspack defer`):`__rspack_defer`,q.zT=e=>{if(e.some(e=>{var t=is[e];return!t||!1===t[es]}))return{then:(t,n)=>Promise.all(e.map(q)).then(t,n)}},ns=e=>{e&&e.d<1&&(e.d=1,e.forEach(e=>e.r--),e.forEach(e=>e.r--?e.r++:e()))},q.a=(e,t,n)=>{n&&((r=[]).d=-1);var r,i,a,o,s=new Set,c=e.exports,l=new Promise((e,t)=>{o=t,a=e});l[Qo]=c,l[Zo]=e=>{r&&e(r),s.forEach(e),l.catch(()=>{})},e.exports=l,t(e=>{i=e.map(e=>{if(typeof e==`object`&&e){if(!e[Zo]&&e[ts]){var t=q.zT(e[ts]);if(!t)return e;var n=e;e={then(e,r){t.then(()=>e(n),r)}}}if(e[Zo])return e;if(e.then){var r=[];r.d=0,e.then(e=>{i[Qo]=e,ns(r)},e=>{i[$o]=e,ns(r)});var i={};return i[ts]=!1,i[Zo]=e=>e(r),i}}var a={};return a[Zo]=()=>{},a[Qo]=e,a});var t,n=()=>i.map(e=>{if(e[ts])return e;if(e[$o])throw e[$o];return e[Qo]}),a=new Promise(e=>{(t=()=>e(n)).r=0;var a=e=>e!==r&&!s.has(e)&&(s.add(e),e&&!e.d&&(t.r++,e.push(t)));i.map(e=>e[ts]||e[Zo](a))});return t.r?a:n()},e=>(e?o(l[$o]=e):a(c),ns(r),l[es]=!0)),r&&r.d<0&&(r.d=0)},q.d=(e,t)=>{for(var n in t)q.o(t,n)&&!q.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},q.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var as=q(13346),os=(as=await as).fl,ss=as.le,cs=as.TB;const ls=e=>{if(!e)return{};let t={};for(let n=0;n<e.length;n+=2)t[e[n]]=e[n+1];return t},us=e=>{if(typeof e!=`object`||!e)return{value:e};if(`value`in e)return{value:e.value};if(`unserializableValue`in e)return{value:e.unserializableValue};if(e.objectId){let t=e.preview?.properties;return Array.isArray(t)&&t.length>0?{value:t.reduce((e,t)=>(e[t.name]=t.value,e),{}),byRef:!0}:{value:e.description||`[${e.type}]`,byRef:!0}}return{value:e.type===`undefined`?void 0:e.description}},ds=e=>{if(e)return`value`in e?e.value:e.unserializableValue||e.description},fs=({text:e,exception:t}={})=>(e&&!/^Uncaught\b/.test(e)?e:t?.description||t?.value||e)||`Runtime evaluation failed`,ps=e=>{if(e.exceptionDetails)throw Error(fs(e.exceptionDetails))},ms=async(e,t,{awaitPromise:n=!1}={})=>e.send(`Runtime.evaluate`,{expression:t,objectGroup:`console`,returnByValue:!0,awaitPromise:!!n,generatePreview:!0}),hs=new WeakMap,gs=async(e,t)=>(await e.send(`Runtime.callFunctionOn`,{functionDeclaration:`function () { return typeof usage }`,objectGroup:`console`,returnByValue:!0},t))?.result?.value===`function`?`Runtime.callFunctionOn`:`Runtime.evaluate`,_s=async(e,t,{timeout:n,awaitPromise:r=!0}={})=>{if(!hs.has(e)){let t=gs(e,n);hs.set(e,t),t.catch(()=>hs.delete(e))}let i={objectGroup:`console`,returnByValue:!0,awaitPromise:!!r};return await hs.get(e)===`Runtime.evaluate`?e.send(`Runtime.evaluate`,{expression:t,...i},n):e.send(`Runtime.callFunctionOn`,{functionDeclaration:`function () { return (\n${t}\n) }`,...i},n)},vs=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/,ys=e=>{if(!vs.test(e))throw Error(`Not a dotted path of identifiers: ${e}`);let t=e.split(`.`).map((e,t,n)=>n.slice(0,t+1).join(`.`)),n=t.pop();return`!!(${[...t.length?[`typeof ${t[0]}!='undefined'`,...t]:[],`typeof ${n}=='function'`].join(`&&`)})`},bs=({subspaceId:e,handler:t,action:n,parameters:r,property:i,waitAsync:a,sync:o})=>{let s={handler:t,action:n};return r!==void 0&&(s.parameters=r),i!==void 0&&(s.property=i),a!==void 0&&(s.waitAsync=a),o!==void 0&&(s.sync=o),`(() => {
619
619
  const systemRef = globalThis.system
@@ -621,39 +621,39 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
621
621
  const subspaceId = ${e?JSON.stringify(e):`(Object.keys(globalThis.system?.subspaces?.() || {})[0] || '')`}
622
622
  if (!subspaceId) throw new Error('No BRICKS subspace is available')
623
623
  return systemRef.executeAction(subspaceId, ${JSON.stringify(s)})
624
- })()`},xs=({subspaceId:e,brickId:t,text:n})=>bs({subspaceId:e,handler:t,action:`BRICK_TEXT_INPUT_SET_TEXT`,parameters:{BRICK_TEXT_INPUT_TEXT:n}}),Ss=/^\d+$/,Cs=e=>typeof e==`string`&&Ss.test(e),ws=async(e,t,n)=>{let{result:r=[],exceptionDetails:i}=await e.send(`Runtime.getProperties`,{objectId:t,ownProperties:!0});if(i)throw Error(i.text||`Cannot read ${n}`);return r},Ts=async(e,t,n)=>{if(!t?.objectId||`value`in t||n<=0)return ds(t);let r=await ws(e,t.objectId,`object ${t.objectId}`),i=await Promise.all(r.map(async({name:t,value:r})=>[t,await Ts(e,r,n-1)]));return t.subtype===`array`?i.filter(([e])=>/^\d+$/.test(e)).map(([,e])=>e):Object.fromEntries(i)},Es=async(e,t,{expand:n=[]}={})=>{let r=(await e.send(`DOM.resolveNode`,{nodeId:Number(t)}))?.object;if(!r)throw Error(`Node ${t} not found`);if(`value`in r)return r.value;if(!r.objectId)throw Error(`Node ${t} did not resolve to metadata`);let i=await ws(e,r.objectId,`node ${t}`),a=await Promise.all(i.map(async({name:t,value:r})=>[t,n.includes(t)?await Ts(e,r,3):ds(r)]));return Object.fromEntries(a)},Ds=async(e,{subspaceId:t,brickId:n})=>{let r=t,i=n,a=null,o={};if(Cs(t)){let n=await Es(e,t);if(r=n.subspaceId||(String(n.shortId||``).startsWith(`S_`)?n.shortId:null),o.subspaceNodeId=Number(t),!r)throw Error(`Node ${t} is not inside a BRICKS subspace`)}if(Cs(n)&&(a=await Es(e,n),i=a.brickId||(String(a.shortId||``).startsWith(`B_`)?a.shortId:null),!Cs(t)&&a.subspaceId&&(r=a.subspaceId),o.brickNodeId=Number(n),!i))throw Error(`Node ${n} is not a BRICKS brick`);return{target:{subspaceId:r,brickId:i,...o},brickNode:a}},Os=async(e,t)=>(await Ds(e,t)).target,ks=[`itemsBrickId`,`itemsIndex`,`itemsDataId`],As=e=>{let t=Object.fromEntries(ks.filter(t=>e[t]!=null).map(t=>[t,e[t]]));return Object.keys(t).length>0?t:null},js=({itemsBrickId:e,itemsIndex:t,itemsDataId:n})=>{if(e==null)throw TypeError(`itemsIndex and itemsDataId need itemsBrickId, the template brick of the row`);if(!n&&t==null)throw TypeError(`itemsBrickId needs itemsIndex or itemsDataId to find the row`)},Ms=async(e,{subspaceId:t,brickId:n,...r})=>{let i=As(r);i&&js(i);let{target:a,brickNode:o}=await Ds(e,{subspaceId:t,brickId:n});if(i)return{target:{...a,...i},nodeId:null};let s=a.brickNodeId??null,{itemsParentId:c,itemsBrickId:l,itemsIndex:u}=o||{};return!c||!l||!Number.isInteger(u)?{target:a,nodeId:s}:{target:{...a,brickId:c,itemsBrickId:l,itemsIndex:u},nodeId:s}},Ns=async(e,t)=>{let n=await _s(e,t);return ps(n),n},J=Object.freeze({delivered:`delivered`,ignored:`ignored`,unsupported:`unsupported`,notReady:`not-ready`,missingTarget:`missing-target`,notInteractive:`not-interactive`,blocked:`blocked`,failed:`failed`,unconfirmed:`unconfirmed`}),Ps=e=>e===J.delivered||e===J.ignored?`ok`:e===J.unconfirmed?`warning`:`error`,Fs={ok:0,warning:1,error:2},Is=(e,t)=>Fs[Ps(e)]>Fs[Ps(t)],Ls={tap:`this runtime does not report what the tap did`,key:`this runtime does not report keys; runtimes before key simulation drop non-text keys, so drive keys through Automation keydown/keyup steps instead`,other:`this runtime does not report the outcome`},Rs={key:`the runtime sent the key to its key path; it does not report whether anything received it`,other:`the runtime took the input; it does not report whether it was delivered`},zs=e=>/unsupported/i.test(e)?J.unsupported:/unavailable|not ready/i.test(e)?J.notReady:J.failed,Bs=({dispatched:e,hitElement:t,tappedElement:n})=>{if(e)return{outcome:J.unconfirmed,reason:`the runtime started the press; it does not report whether it ran`};if(n)return{outcome:J.failed,reason:`the runtime did not start the press (the app was not ready or the row was gone)`};if(t){let e=`the brick at the point does not take a press (no pressable handler)`;return{outcome:J.notInteractive,reason:t.editable?`${e}; it is a text input: set its text with brick input / brick_input`:e}}return{outcome:J.missingTarget,reason:`no brick at the point`}},Y=(e,t)=>{let n=e&&typeof e==`object`?e:{};if(typeof n.outcome==`string`)return{outcome:n.outcome,reason:typeof n.reason==`string`?n.reason:null,blockedBy:n.blockedBy??null};let r;if(t===`tap`&&typeof n.dispatched==`boolean`)r=Bs(n);else if(n.handled===!1){let e=typeof n.reason==`string`?n.reason:null;r={outcome:e?zs(e):J.failed,reason:e}}else r=n.handled===!0?{outcome:J.unconfirmed,reason:Rs[t]??Rs.other}:{outcome:J.unconfirmed,reason:Ls[t]??Ls.other};return{...r,blockedBy:null}},Vs=async(e,{depth:t=3}={})=>{await e.send(`DOM.enable`);let{root:n}=await e.send(`DOM.getDocument`,{depth:t});return n},Hs=async(e,t)=>{let n=await e.send(`DOM.describeNode`,{nodeId:t}),{attributes:r}=await e.send(`DOM.getAttributes`,{nodeId:t});return{nodeId:t,...n.node,attributes:ls(r)}},Us=async(e,t)=>{await e.send(`DOM.enable`);let{root:n}=await e.send(`DOM.getDocument`,{depth:0}),{nodeIds:r}=await e.send(`DOM.querySelectorAll`,{nodeId:n.nodeId,selector:t}),i=[];for(let t of r)i.push(await Hs(e,t));return{nodeIds:r,nodes:i}},Ws=async(e,{subspaceId:t,brickId:n,text:r})=>{let i=await Os(e,{subspaceId:t,brickId:n}),a=Y((await Ns(e,xs({...i,text:r})))?.result?.value);return a.outcome===J.unconfirmed&&(a.reason=`BRICK_TEXT_INPUT_SET_TEXT does not report what it did; a fill through system.textInput reports the value (app version >= 2.26)`),{...i,action:`BRICK_TEXT_INPUT_SET_TEXT`,text:r,...a}},Gs=1e4,Ks=(...e)=>e.map(e=>JSON.stringify(e)).join(`, `),qs=()=>`${ys(`system.modals.list`)} ? system.modals.list() : false`,Js=({id:e,token:t,op:n,args:r={},refuseApproval:i=!1})=>{let a=`system.modals.perform(${Ks(e,t,n,r)})`,o=ys(`system.modals.perform`);if(!i)return`${o} ? ${a} : false`;let s=`(system.modals.list().modals || []).filter(${`(m) => m.id === ${JSON.stringify(e)} && m.token != null && String(m.token) === ${JSON.stringify(String(t))}`}).some((m) => !!(m.owner && m.owner.type === 'generator' && m.owner.confirm === true))`;return`${o} && ${ys(`system.modals.list`)} ? (${s} ? 'approval' : ${a}) : false`},Ys=e=>{if(!Number.isInteger(e)||e<0||e>1e4)throw TypeError(`wait must be a whole number of milliseconds, 0 to ${Gs}`)},Xs=e=>new Promise(t=>setTimeout(t,e)),Zs=async(e,t,{wait:n=0,isNotReady:r=e=>e?.outcome===J.notReady}={})=>{Ys(n);let i=performance.now();for(let a=1;;a+=1){let o=await _s(e,t);ps(o);let s=o?.result?.value,c=Math.round(performance.now()-i);if(!r(s)||c+100>n)return{answer:s,waitedMs:a>1?c:0};await Xs(100)}},Qs=e=>({handled:null,outcome:J.unsupported,reason:`this runtime has no system.modals (app version >= 2.26)`,blockedBy:null,...e}),$s=async(e,{wait:t=0}={})=>{let{answer:n,waitedMs:r}=await Zs(e,qs(),{wait:t});if(n===!1)return Qs({modals:[],waitedMs:r});let i=Array.isArray(n?.modals)?n.modals:[];return{...n,...Y(n),modals:i,waitedMs:r}},ec=e=>e?.code===`not-ready`||e?.code==null&&e?.outcome===J.notReady,tc=e=>`Modal ${e} is the confirm dialog of a generator, the approval of a person (the Assistant asks it before a tool call): this tool only dismisses it (the confirm answers false); a person approves it in the app`,nc=async(e,{id:t,token:n,op:r,args:i,wait:a=0,allowApproval:o=!0})=>{if(typeof t!=`string`||!t)throw TypeError(`id is required (from the modal list)`);if(!(typeof n==`number`||typeof n==`string`&&n))throw TypeError(`token is required (the token of the modal in the modal list)`);if(typeof r!=`string`||!r)throw TypeError(`op is required`);if(i!=null&&(typeof i!=`object`||Array.isArray(i)))throw TypeError(`args must be an object`);Ys(a);let{answer:s,waitedMs:c}=await Zs(e,Js({id:t,token:n,op:r,args:i??{},refuseApproval:!o&&r!==`dismiss`}),{wait:a,isNotReady:ec});return s===!1?Qs({code:null,id:t,op:r,token:null,waitedMs:c}):s===`approval`?{handled:null,outcome:J.unsupported,reason:tc(t),blockedBy:null,code:null,id:t,op:r,token:n,approval:!0,waitedMs:c}:{...s,...Y(s),waitedMs:c}},rc=async(e,{x:t,y:n})=>{let r=Number(t),i=Number(n),a=await e.send(`Input.dispatchMouseEvent`,{type:`mousePressed`,x:r,y:i,button:`left`,clickCount:1});return await e.send(`Input.dispatchMouseEvent`,{type:`mouseReleased`,x:r,y:i,button:`left`,clickCount:1}),{x:r,y:i,tapResult:a||null,...Y(a,`tap`)}},ic=e=>e&&typeof e.handled==`boolean`?e:null,ac=async(e,t)=>{let n=await e.send(`Input.dispatchKeyEvent`,{type:`keyDown`,key:t}),r=await e.send(`Input.dispatchKeyEvent`,{type:`keyUp`,key:t}),i=Y(n,`key`),a=Y(r,`key`),o=Is(a.outcome,i.outcome),{outcome:s,reason:c,blockedBy:l}=o?a:i,u=ic(n)||ic(r),d=o&&ic(r)||u;return{key:t,handled:d?d.handled:null,reason:c,keyCode:u?.keyCode??null,outcome:s,blockedBy:l}},oc=ys(`system.simulatePress`),sc=6e4,cc=({subspaceId:e,brickId:t,options:n={}})=>{let r=[e,t,n].map(e=>JSON.stringify(e)).join(`, `);return`${oc} ? system.simulatePress(${r}) : false`},lc=({itemsBrickId:e})=>{let t=`this runtime does not report what the press did (app version >= 2.26 does)`;return/^B_/.test(e||``)?`${t}; it takes only the full id as itemsBrickId, so a short id finds no row`:t},uc=(e,t)=>({handled:null,outcome:e,reason:t,blockedBy:null,events:null,longPressed:null}),dc=async(e,{itemsMode:t,longPress:n=!1,holdMs:r=0,...i})=>{if(!Number.isInteger(r)||r<0||r>6e4)throw TypeError(`holdMs must be a whole number of milliseconds, 0 to ${sc}`);let{target:a}=await Ms(e,i),o=As(a),s=o&&t?{itemsMode:t}:null,c={...o,...s,...n&&{longPress:!0},...r>0&&{simulateInOutTimeout:r}},{subspaceId:l,brickId:u}=a,d=await _s(e,cc({subspaceId:l,brickId:u,options:c}),r>0?{timeout:r+15e3}:void 0);ps(d);let f=d?.result?.value,p={...a,...s,longPress:!!n,holdMs:r};return f===!1?{...p,...uc(J.unsupported,`this runtime has no system.simulatePress`)}:typeof f?.outcome==`string`?{...p,...f,...Y(f)}:{...p,...uc(J.unconfirmed,lc(a))}};Object.freeze([`alert`,`generator`,`all`]);const fc=e=>{if(e.subtype===`null`)return null;if(e.type!==`undefined`){if(e.type===`boolean`)return e.value===`true`;if(e.type===`number`){let t=Number(e.value);return Number.isNaN(t)?e.value:t}return e.value}},pc=e=>{let{value:t}=us(e),n=e?.objectId?e.preview?.properties:null;if(!Array.isArray(n)||n.length===0)return t;if(e.subtype===`array`){let e=[];for(let t of n)/^\d+$/.test(t.name)&&(e[Number(t.name)]=fc(t));return e}return n.reduce((e,t)=>(e[t.name]=fc(t),e),{})},mc=e=>{let t=pc(e);if(t===void 0)return`undefined`;if(typeof t==`string`)return t;if(typeof t==`bigint`)return`${t}n`;if(typeof t==`object`&&t)try{return JSON.stringify(t)}catch{}return String(t??e?.description??t)},hc=e=>e===`error`||e===`assert`||e===`exception`?`error`:e===`warning`||e===`warn`?`warning`:e===`debug`||e===`trace`?`debug`:`info`,gc=e=>{let t=e?.callFrames;return!Array.isArray(t)||t.length===0?null:t.map(e=>{let t=e.functionName||`<anonymous>`,n=e.url?`${e.url}:${Number(e.lineNumber)+1}:${Number(e.columnNumber)+1}`:null;return n?`at ${t} (${n})`:`at ${t}`}).join(`
625
- `)},_c=(e={})=>{let t=e.type||`log`,n=(e.args||[]).map(pc),r=gc(e.stackTrace);return{level:hc(t),type:t,text:(e.args||[]).map(mc).join(` `),timestamp:e.timestamp??Date.now(),args:n,...r?{stack:r}:{}}},vc=(e={})=>{let t=e.exceptionDetails||{},n=t.exception?.description||``,r=n.split(/\r?\n/,1)[0]||t.exception?.value||t.text||`Uncaught exception`,i=t.text&&t.text!==r?`${t.text}: ${r}`:String(r),a=t.stackTrace?.callFrames,o=Array.isArray(a)?a[0]:null,s=gc(t.stackTrace)||(n.includes(`
626
- `)?n:null),c=t.url||o?.url,l=t.lineNumber??o?.lineNumber,u=t.columnNumber??o?.columnNumber;return{level:`error`,type:`exception`,text:i,timestamp:e.timestamp??Date.now(),exceptionText:String(r),...s?{stack:s}:{},...c?{url:c}:{},...l===void 0?{}:{lineNumber:l},...u===void 0?{}:{columnNumber:u}}},yc=/^Connected to BRICKS .*DevTools!/,bc=(e,{enabledAt:t,startedAt:n})=>{let r=e.find(e=>typeof e.timestamp==`number`&&yc.test(e.text||``)),i=n??r?.timestamp??t;return e.map(e=>{let t=typeof e.timestamp==`number`&&e.timestamp<i;return t?{...e,retained:t,ageMs:i-e.timestamp}:{...e,retained:t}})},xc=async e=>{try{let{result:t}=await e.send(`Runtime.evaluate`,{expression:`Date.now()`,returnByValue:!0});return typeof t?.value==`number`?t.value:null}catch{return null}},Sc=async(e,t)=>{let n=[],r=e=>n.push(_c(e)),i=e=>n.push(vc(e)),a=!1;e.on(`Runtime.consoleAPICalled`,r),e.on(`Runtime.exceptionThrown`,i);let o=Date.now(),s=await xc(e);try{await e.send(`Runtime.enable`),a=!0,await new Promise(e=>setTimeout(e,t))}finally{try{a&&await e.send(`Runtime.disable`)}finally{e.off(`Runtime.consoleAPICalled`,r),e.off(`Runtime.exceptionThrown`,i)}}return bc(n.sort((e,t)=>e.timestamp-t.timestamp),{enabledAt:o,startedAt:s})},Cc=[[/^iVBORw0KGgo/,`image/png`],[/^\/9j\//,`image/jpeg`],[/^UklGR.{6}XRUJQ/,`image/webp`]],wc=async(e,{format:t=`jpeg`,quality:n=70,clip:r}={})=>{let i={format:t};t===`jpeg`&&(i.quality=n),r&&(i.clip=r);let{data:a}=await e.send(`Page.captureScreenshot`,i),o=Cc.find(([e])=>e.test(a??``));return{data:a,mimeType:o?o[1]:`image/${t}`}},Tc=`bricks://app`,Ec=`DATA-`,Dc=e=>{let t=e.startsWith(`DATA-`)?e.slice(5):e,n=t.indexOf(`:`);return n<0?{shortId:t,title:null}:{shortId:t.slice(0,n),title:t.slice(n+1)}},Oc=async(e,t,n)=>{try{return(await e.send(`IndexedDB.getMetadata`,{securityOrigin:Tc,databaseName:t,objectStoreName:n})).entriesCount}catch{return null}},kc=async(e,t)=>{let{entries:n}=await e.send(`DOMStorage.getDOMStorageItems`,{storageId:{securityOrigin:Tc,isLocalStorage:t}});return n},Ac=async e=>{await e.send(`DOMStorage.enable`),await e.send(`IndexedDB.enable`);let t=(await kc(e,!0)).length,n=(await kc(e,!1)).length,{databaseNames:r}=await e.send(`IndexedDB.requestDatabaseNames`,{securityOrigin:Tc}),i=[];for(let t of r){let n=t.startsWith(`DATA-`)?`properties`:`entries`;i.push({name:t,objectStoreName:n,entriesCount:await Oc(e,t,n)})}return{system:{persist:t,memory:n},dataBanks:i.filter(e=>e.name.startsWith(Ec)).map(e=>({...e,...Dc(e.name)})),caches:i.filter(e=>!e.name.startsWith(Ec))}},jc=`Run bricks buttress bind again and restart Buttress to provision a fresh DevTools token.`,Mc=async(e,t,n,r)=>{let i=n?.workspace;if(!i)return;r?.throwIfAborted();let a=await cs(e,t);if(r?.throwIfAborted(),!a)throw Error(`Cannot reach device DevTools info; no workspace credential was sent.`);if(!a.auth?.workspaceJwt?.enabled)return;if(a.workspaceId!==i.id||a.auth.workspaceJwt.kid!==i.kid)throw Error(`Device workspace/issuer does not match Buttress; no workspace credential was sent.`);let o=n?.devtools;if(!o||o.workspaceId!==i.id)throw Error(`No DevTools credential is provisioned for the bound workspace. ${jc}`);try{let e=await _e(i.issuerPublicKey,`EdDSA`),{payload:t,protectedHeader:n}=await ve(o.token,e,{algorithms:[`EdDSA`],requiredClaims:[`exp`]});if(n.kid!==i.kid||t.k!==`da`||t.w_id!==i.id||t.st!==`ws`||typeof t.sid!=`string`||!t.sid)throw Error(`Invalid DevTools claims`)}catch{throw Error(`The provisioned DevTools token is expired or invalid. ${jc}`)}return r?.throwIfAborted(),o.token},Nc=(e,t)=>{let n=typeof e==`string`?e:JSON.stringify(e,null,2)??``;for(let e of t)n=n.split(e).join(`[REDACTED]`),n=n.split(encodeURIComponent(e)).join(`[REDACTED]`);return{content:[{type:`text`,text:ni(n)}],details:{}}},X=(e,t)=>{if(typeof e[t]!=`string`||!e[t].length)throw Error(`${t} must be a non-empty string`);return e[t]},Z=(e,t,n,r=-1/0,i=1/0)=>{let a=e[t]??n;if(typeof a!=`number`||!Number.isFinite(a)||a<r||a>i)throw Error(`${t} must be a number between ${r} and ${i}`);return a},Pc=(e,t)=>e[t]===void 0?void 0:X(e,t),Fc=(e,t)=>{if(e[t]===void 0)return;let n=Z(e,t,void 0,0);if(!Number.isInteger(n))throw Error(`${t} must be an integer`);return n},Ic=e=>{let t=Z(e,`port`,19851,1,65535);if(!Number.isInteger(t))throw Error(`port must be an integer`);return t},Lc=async(e,t,n)=>{switch(t.action){case`screenshot`:{let{data:t,mimeType:n}=await wc(e);if(!t)throw Error(`No screenshot data received`);return{content:[{type:`image`,data:t,mimeType:n}],details:{}}}case`tree`:return n(await Vs(e,{depth:Z(t,`depth`,3,-1)}));case`query`:return n(await Us(e,X(t,`selector`)));case`tap`:return n(await rc(e,{x:Z(t,`x`),y:Z(t,`y`)}));case`key`:return n(await ac(e,X(t,`key`)));case`press`:return n(await dc(e,{subspaceId:X(t,`subspaceId`),brickId:X(t,`brickId`),itemsBrickId:Pc(t,`itemsBrickId`),itemsIndex:Fc(t,`itemsIndex`),itemsDataId:Pc(t,`itemsDataId`),longPress:t.longPress===!0,holdMs:t.holdMs??0}));case`modal`:{let r=t.waitMs??0;return t.modalOp===void 0?n(await $s(e,{wait:r})):n(await nc(e,{id:X(t,`modalId`),token:Z(t,`modalToken`,void 0,0),op:X(t,`modalOp`),args:t.modalArgs,wait:r,allowApproval:!1}))}case`input`:if(typeof t.text!=`string`)throw Error(`text must be a string`);return n(await Ws(e,{subspaceId:X(t,`subspaceId`),brickId:X(t,`brickId`),text:t.text}));case`console`:return n(await Sc(e,Z(t,`duration`,2e3,0,1e4)));case`evaluate`:return n(await ms(e,X(t,`expression`),{awaitPromise:t.awaitPromise??!1}));case`storage`:return n(await Ac(e));case`cdp`:return n(await e.send(X(t,`method`),t.params??{}));default:throw Error(`Unknown DevTools action: ${t.action}`)}},Rc=async(e,t,n,r)=>{t?.throwIfAborted();let i=X(e,`address`);if(!/^(\[[\da-fA-F:]+\]|[\w.-]+)$/.test(i))throw Error(`address must be a hostname or IP (bracket IPv6); supply port separately`);let a=Ic(e),o=e.accessToken||(e.passcode?void 0:await Mc(i,a,r,t));t?.throwIfAborted();let s=os(i,a,{passcode:e.passcode,accessToken:o}),c,l=new Promise((e,n)=>{c=()=>{s.close(),n(t?.reason||Error(`Device tool aborted`))},t?.addEventListener(`abort`,c,{once:!0})});try{return await Promise.race([(async()=>(await s.connect(),t?.throwIfAborted(),Lc(s,e,n)))(),l])}finally{c&&t?.removeEventListener(`abort`,c),s.close()}},zc=(e,t)=>async(n,r,i)=>{let a=[t,r?.accessToken,r?.passcode].filter(e=>typeof e==`string`&&e.length>0),o=e=>Nc(e,a);try{return i?.throwIfAborted(),await e(r??{},i,o)}catch(e){return o(`Tool error: ${e?.message||String(e)}`)}},Bc={type:`integer`,minimum:1,maximum:65535,default:19851},Vc=(e,t,n)=>e.localDevices?[{name:`devices_scan`,label:`Scan local devices`,description:`Find BRICKS devices on the Buttress host LAN using the same UDP + HTTP discovery as bricks devtools scan. Returns addresses, ports and authentication hints. Also checks local project previews relative to the Buttress config directory. No cloud login needed.`,parameters:{type:`object`,properties:{timeout:{type:`integer`,minimum:100,maximum:1e4,default:3e3},udpOnly:{type:`boolean`,description:`Skip HTTP subnet probing (default false).`},verify:{type:`boolean`,description:`Verify discovered servers via HTTP.`},project:{type:`boolean`,description:`Include local project previews (default true).`},port:Bc},additionalProperties:!1},execute:zc(async(e,n,r)=>{let i=await ss({timeout:Z(e,`timeout`,3e3,100,1e4),port:Ic(e),udpOnly:e.udpOnly??!1,verify:e.verify??!1,project:e.project??!0,cwd:t});return n?.throwIfAborted(),r(i)},n?.devtools?.token)},{name:`devtools`,label:`Device DevTools`,description:`Inspect or control a BRICKS device from devices_scan. Each call opens and closes CDP; run calls sequentially (devices accept one inspector). Uses CLI DevTools operations. Actions: screenshot (inline image), tree (depth), query (selector), tap (x,y in BRICKS layout units of the root canvas, NOT pixels; a frame in a nested subspace or an Items brick is local to that parent, so get its box with cdp DOM.getBoxModel), key (key), press (subspaceId,brickId: press a brick by id as a person, the Automation brick_press path; a node id of a brick in an Items row (app version >= 2.25.12), or the Items brick with itemsBrickId and itemsIndex or itemsDataId, presses that row; longPress, holdMs; the result has the outcome and the fired events, unconfirmed before app version 2.26), modal (app version >= 2.26: with no modalOp, list the open app modals with their ids, tokens and operations; with modalId, modalToken (from the list) and modalOp, run one operation on the topmost modal: alert select (modalArgs { index } or { label }) | dismiss, information confirm | close, question input (modalArgs { value }) | next | back | skip | close; a stale token answers missing-target; a generator confirm dialog is the approval of a person: only dismiss it; waitMs waits while not-ready), input (subspaceId,brickId,text), console (duration ms; retained + new entries), evaluate (expression,awaitPromise), storage (overview), cdp (method,params for other supported CDP operations, e.g. DOM.getAttributes). Workspace authentication is automatic for matching-workspace devices after bricks buttress bind. The credential stays server-side; do not request it from the user. An optional passcode or accessToken overrides automatic auth. Local previews can use advertised inspect credentials. Input, evaluation and raw CDP can change device state.`,parameters:{type:`object`,properties:{action:{type:`string`,enum:[`screenshot`,`tree`,`query`,`tap`,`key`,`press`,`modal`,`input`,`console`,`evaluate`,`storage`,`cdp`]},address:{type:`string`,description:`Device hostname/IP from scan, without port.`},port:Bc,passcode:{type:`string`},accessToken:{type:`string`,description:`Optional explicit DevTools JWT override; normally omit.`},depth:{type:`integer`,minimum:-1,default:3},selector:{type:`string`},x:{type:`number`},y:{type:`number`},key:{type:`string`},subspaceId:{type:`string`},brickId:{type:`string`},itemsBrickId:{type:`string`,description:`press: the template brick of the row.`},itemsIndex:{type:`integer`,minimum:0},itemsDataId:{type:`string`},longPress:{type:`boolean`},holdMs:{type:`integer`,minimum:0,maximum:sc,default:0},modalId:{type:`string`,description:`modal: the id of the modal from the list.`},modalToken:{type:`integer`,minimum:0,description:`modal: its token.`},modalOp:{type:`string`,description:`modal: the operation to run.`},modalArgs:{type:`object`,additionalProperties:!0},waitMs:{type:`integer`,minimum:0,maximum:Gs,default:0},text:{type:`string`},duration:{type:`integer`,minimum:0,maximum:1e4,default:2e3},expression:{type:`string`},awaitPromise:{type:`boolean`},method:{type:`string`},params:{type:`object`,additionalProperties:!0}},required:[`action`,`address`],additionalProperties:!1},execute:zc((e,t,r)=>Rc(e,t,r,n),n?.devtools?.token)}]:[],Q=`[Agents]`,Hc=e=>e.filter(e=>e.role!==`system`),Uc=e=>{for(let t=e.length-1;t>=0;--t){let n=e[t];if(n?.role!==`assistant`||!Array.isArray(n.content))continue;let r=n.content.filter(e=>e?.type===`text`&&typeof e.text==`string`).map(e=>e.text).join(``),i=n.content.filter(e=>e?.type===`thinking`&&typeof e.thinking==`string`).map(e=>e.thinking).join(`
627
- `);if(r||i)return{content:r,reasoning:i}}return{content:``,reasoning:``}},Wc=(e,t)=>{let n={input:0,output:0,cacheRead:0,totalTurns:0};for(let r of e.slice(t))r?.role===`assistant`&&(n.totalTurns+=1,r.usage&&(n.input+=r.usage.input||0,n.output+=r.usage.output||0,n.cacheRead+=r.usage.cacheRead||0));return n},Gc=({config:e,agentsConfig:t,runtimeBase:n,getHandle:r,getFunctions:i})=>{let a=new Map(t.agents.map(e=>[e.name,e])),o=To(),s=Eo(o);try{Do(t.runtimeTokenFile,o)}catch(e){console.warn(`${Q} could not write runtime token file ${t.runtimeTokenFile}: ${e?.message||e}`)}let c=Co(e,Oo(r,o),t=>Xt(n.backend,e,t,Q)),l=zo(t),u=Wo({configDir:t.configDir}),d=new Map,f=new Map,p=async(e,t)=>{let n=(d.get(e)??Promise.resolve()).then(t,t),r=n.catch(()=>{});d.set(e,r);try{return await n}finally{d.get(e)===r&&d.delete(e)}},m=e=>e.systemPrompt==null?e.systemPromptFile?P.readFileSync(e.systemPromptFile,`utf8`):`You are a helpful automation agent running on a BRICKS Buttress server.`:e.systemPrompt,h=async(e,r,a,o)=>{let s=e.metadata.id,d=`${r.name} ${s}`;try{a.onSession?.(s)}catch{}let p=o===`new`?[]:await l.messages(e),h=a.depth??0,g=i(),v={...n,agents:_},y=r.tools.length>0?await Jo(r,{functions:g,runtime:v,depth:h+1,onToolEmit:(e,t,n,r)=>a.onEvent?.({type:`tool_emit`,toolCallId:r,toolName:e,event:t,data:n})}):[],b=await u.toolsFor(r.name,r.mcpServers),x=[...y,...Vc(r,t.configDir,n.workspaceState),...b],S=x.filter(e=>!e._mcpExposure||e._mcpExposure===`direct`),C;try{C=lo(c,r)}catch(e){throw new G(e?.message||String(e),s)}C&&S.push(fo(c,C)),r.codemode&&S.push(await qo({tools:x,declaredNames:new Set(S.map(e=>e.name)),getState:()=>E.state,models:c}));let ee=new Set;for(let e of S){if(ee.has(e.name))throw new G(`${Q} ${r.name}: duplicate tool name "${e.name}" between local functions, built-in tools or MCP servers`,s);ee.add(e.name)}let w=S;if(C&&r.decisionAssistance){let e=Date.now(),t=await vo({models:c,model:C,prompt:a.prompt,history:p,toolNames:S.map(e=>e.name),timeoutMs:r.decisionTimeoutMs,signal:a.signal});t.prune&&(w=[]);let n=JSON.stringify(S.map(({name:e,description:t,parameters:n})=>({name:e,description:t,parameters:n}))).length;console.log(`${Q} ${r.name}: tool prefilter ${t.prune?`pruned`:`kept`} ${S.length} tools (${t.reason}${t.detail?`: ${t.detail}`:``}, ${Date.now()-e}ms${t.prune?`, -${n} chars`:``})`)}let T=`end_turn`,te=0,ne=0,E=new Be({initialState:{model:wo(c,r),systemPrompt:m(r),...r.thinking?{thinkingLevel:r.thinking}:{},tools:w,messages:p},sessionId:s,streamFn:(e,t,n)=>c.streamSimple(e,t,{...n,...r.generation}),finishTurn:e=>{te+=1;let t=e.message?.usage;if(t&&(ne+=(t.input||0)+(t.output||0)),te>=r.maxTurns)return T=`max_turns`,{action:`end`};if(r.maxTokensPerRun!=null&&ne>=r.maxTokensPerRun)return T=`token_budget`,{action:`end`}}}),D=p.length,re=async()=>{let t=Hc(E.state.messages);for(;D<t.length;){let n=t[D];D+=1;try{await l.append(e,JSON.parse(JSON.stringify(n)))}catch(e){console.warn(`${Q} failed to persist message:`,e?.message||e)}}};E.subscribe(async e=>{`message`in e&&e.message.role===`system`||(a.onEvent?.(e),(e.type===`message_end`||e.type===`agent_end`)&&await re())});let O=!1,ie=()=>{O=!0,T=`aborted`,E.abort()},k=()=>ie();if(a.signal?.aborted)throw new G(`aborted before start`,s,`aborted`);a.signal?.addEventListener(`abort`,k,{once:!0}),f.set(d,{abort:ie});let A=p.length;try{await E.prompt(a.prompt),await E.waitForIdle()}catch(e){throw await re(),new G(e?.message||String(e),s,O||a.signal?.aborted?`aborted`:`error`)}finally{f.delete(d),a.signal?.removeEventListener(`abort`,k)}await re();let ae=E.state;if(ae.errorMessage)throw new G(ae.errorMessage,s,T);a.signal?.aborted&&(T=`aborted`);let oe=Hc(ae.messages),{content:se,reasoning:j}=Uc(oe);return{sessionId:s,content:se,...j?{reasoningContent:j}:{},usage:Wc(oe,A),stopReason:T}},g=async(e,t,n)=>{let r=n===`continue`?await l.open(e.name,t.sessionId):n===`fork`?await l.fork(e.name,t.sessionId):await l.create(e.name);return h(r,e,t,n)},_={config:t,list:()=>[...a.keys()],run:async(e,n)=>{let r=a.get(e);if(!r)throw new G(`unknown agent "${e}" (configured: ${[...a.keys()].join(`, `)||`none`})`,null);if((n.depth??0)>=t.maxDepth)throw new G(`agent-invocation depth limit reached (${t.maxDepth}); a function called an agent that called a function that called an agent… raise agents_options.max_depth if this chain is intended`,null);if(typeof n.prompt!=`string`||!n.prompt.trim())throw new G(`prompt is required`,null);if(n.fork&&!n.sessionId)throw new G(`fork requires sessionId`,null);let i=n.sessionId?n.fork?`fork`:`continue`:`new`;return i===`continue`?p(`${e} ${n.sessionId}`,()=>g(r,n,i)):g(r,n,i)},sessions:(e,t)=>{if(!a.has(e))throw Error(`${Q} unknown agent "${e}"`);return l.list(e,t?.limit)},transcript:async(e,t)=>{if(!a.has(e))throw Error(`${Q} unknown agent "${e}"`);return await l.messages(await l.open(e,t))},abort:(e,t)=>{let n=f.get(`${e} ${t}`);return n?(n.abort(),!0):!1},verifyInternalToken:s,dispose:async()=>{clearInterval(y);for(let e of f.values())e.abort();await u.dispose()}},v=()=>{l.sweep([...a.keys()]).then(e=>{e>0&&console.log(`${Q} retention: removed ${e} session(s)`)}).catch(e=>{console.warn(`${Q} retention sweep failed:`,e?.message||e)})},y=setInterval(v,216e5);return y.unref?.(),v(),console.log(`${Q} ${a.size} agent${a.size===1?``:`s`} configured: `+[...a.keys()].join(`, `)),_},$=e(),Kc=(e,t)=>i(e,t),qc=(e,t)=>{e.push(`
624
+ })()`},xs=({subspaceId:e,brickId:t,text:n})=>bs({subspaceId:e,handler:t,action:`BRICK_TEXT_INPUT_SET_TEXT`,parameters:{BRICK_TEXT_INPUT_TEXT:n}}),Ss=/^\d+$/,Cs=e=>typeof e==`string`&&Ss.test(e),ws=async(e,t,n)=>{let{result:r=[],exceptionDetails:i}=await e.send(`Runtime.getProperties`,{objectId:t,ownProperties:!0});if(i)throw Error(i.text||`Cannot read ${n}`);return r},Ts=async(e,t,n)=>{if(!t?.objectId||`value`in t||n<=0)return ds(t);let r=await ws(e,t.objectId,`object ${t.objectId}`),i=await Promise.all(r.map(async({name:t,value:r})=>[t,await Ts(e,r,n-1)]));return t.subtype===`array`?i.filter(([e])=>/^\d+$/.test(e)).map(([,e])=>e):Object.fromEntries(i)},Es=async(e,t,{expand:n=[]}={})=>{let r=(await e.send(`DOM.resolveNode`,{nodeId:Number(t)}))?.object;if(!r)throw Error(`Node ${t} not found`);if(`value`in r)return r.value;if(!r.objectId)throw Error(`Node ${t} did not resolve to metadata`);let i=await ws(e,r.objectId,`node ${t}`),a=await Promise.all(i.map(async({name:t,value:r})=>[t,n.includes(t)?await Ts(e,r,3):ds(r)]));return Object.fromEntries(a)},Ds=async(e,{subspaceId:t,brickId:n})=>{let r=t,i=n,a=null,o={};if(Cs(t)){let n=await Es(e,t);if(r=n.subspaceId||(String(n.shortId||``).startsWith(`S_`)?n.shortId:null),o.subspaceNodeId=Number(t),!r)throw Error(`Node ${t} is not inside a BRICKS subspace`)}if(Cs(n)&&(a=await Es(e,n),i=a.brickId||(String(a.shortId||``).startsWith(`B_`)?a.shortId:null),!Cs(t)&&a.subspaceId&&(r=a.subspaceId),o.brickNodeId=Number(n),!i))throw Error(`Node ${n} is not a BRICKS brick`);return{target:{subspaceId:r,brickId:i,...o},brickNode:a}},Os=async(e,t)=>(await Ds(e,t)).target,ks=[`itemsBrickId`,`itemsIndex`,`itemsDataId`],As=e=>{let t=Object.fromEntries(ks.filter(t=>e[t]!=null).map(t=>[t,e[t]]));return Object.keys(t).length>0?t:null},js=({itemsBrickId:e,itemsIndex:t,itemsDataId:n})=>{if(e==null)throw TypeError(`itemsIndex and itemsDataId need itemsBrickId, the template brick of the row`);if(!n&&t==null)throw TypeError(`itemsBrickId needs itemsIndex or itemsDataId to find the row`)},Ms=async(e,{subspaceId:t,brickId:n,...r})=>{let i=As(r);i&&js(i);let{target:a,brickNode:o}=await Ds(e,{subspaceId:t,brickId:n});if(i)return{target:{...a,...i},nodeId:null};let s=a.brickNodeId??null,{itemsParentId:c,itemsBrickId:l,itemsIndex:u}=o||{};return!c||!l||!Number.isInteger(u)?{target:a,nodeId:s}:{target:{...a,brickId:c,itemsBrickId:l,itemsIndex:u},nodeId:s}},Ns=async(e,t)=>{let n=await _s(e,t);return ps(n),n},J=Object.freeze({delivered:`delivered`,ignored:`ignored`,unsupported:`unsupported`,notReady:`not-ready`,missingTarget:`missing-target`,notInteractive:`not-interactive`,blocked:`blocked`,failed:`failed`,unconfirmed:`unconfirmed`}),Ps=e=>e===J.delivered||e===J.ignored?`ok`:e===J.unconfirmed?`warning`:`error`,Fs={ok:0,warning:1,error:2},Is=(e,t)=>Fs[Ps(e)]>Fs[Ps(t)],Ls={tap:`this runtime does not report what the tap did`,key:`this runtime does not report keys; runtimes before key simulation drop non-text keys, so drive keys through Automation keydown/keyup steps instead`,other:`this runtime does not report the outcome`},Rs={key:`the runtime sent the key to its key path; it does not report whether anything received it`,other:`the runtime took the input; it does not report whether it was delivered`},zs=e=>/unsupported/i.test(e)?J.unsupported:/unavailable|not ready/i.test(e)?J.notReady:J.failed,Bs=({dispatched:e,hitElement:t,tappedElement:n})=>{if(e)return{outcome:J.unconfirmed,reason:`the runtime started the press; it does not report whether it ran`};if(n)return{outcome:J.failed,reason:`the runtime did not start the press (the app was not ready or the row was gone)`};if(t){let e=`the brick at the point does not take a press (no pressable handler)`;return{outcome:J.notInteractive,reason:t.editable?`${e}; it is a text input: set its text with brick input / brick_input`:e}}return{outcome:J.missingTarget,reason:`no brick at the point`}},Y=(e,t)=>{let n=e&&typeof e==`object`?e:{};if(typeof n.outcome==`string`)return{outcome:n.outcome,reason:typeof n.reason==`string`?n.reason:null,blockedBy:n.blockedBy??null};let r;if(t===`tap`&&typeof n.dispatched==`boolean`)r=Bs(n);else if(n.handled===!1){let e=typeof n.reason==`string`?n.reason:null;r={outcome:e?zs(e):J.failed,reason:e}}else r=n.handled===!0?{outcome:J.unconfirmed,reason:Rs[t]??Rs.other}:{outcome:J.unconfirmed,reason:Ls[t]??Ls.other};return{...r,blockedBy:null}},Vs=async(e,{depth:t=3}={})=>{await e.send(`DOM.enable`);let{root:n}=await e.send(`DOM.getDocument`,{depth:t});return n},Hs=async(e,t)=>{let n=await e.send(`DOM.describeNode`,{nodeId:t}),{attributes:r}=await e.send(`DOM.getAttributes`,{nodeId:t});return{nodeId:t,...n.node,attributes:ls(r)}},Us=async(e,t)=>{await e.send(`DOM.enable`);let{root:n}=await e.send(`DOM.getDocument`,{depth:0}),{nodeIds:r}=await e.send(`DOM.querySelectorAll`,{nodeId:n.nodeId,selector:t}),i=[];for(let t of r)i.push(await Hs(e,t));return{nodeIds:r,nodes:i}},Ws=async(e,{subspaceId:t,brickId:n,text:r})=>{let i=await Os(e,{subspaceId:t,brickId:n}),a=Y((await Ns(e,xs({...i,text:r})))?.result?.value);return a.outcome===J.unconfirmed&&(a.reason=`BRICK_TEXT_INPUT_SET_TEXT does not report what it did; a fill through system.textInput reports the value (app version >= 2.26)`),{...i,action:`BRICK_TEXT_INPUT_SET_TEXT`,text:r,...a}},Gs=1e4,Ks=(...e)=>e.map(e=>JSON.stringify(e)).join(`, `),qs=()=>`${ys(`system.modals.list`)} ? system.modals.list() : false`,Js=({id:e,token:t,op:n,args:r={},refuseApproval:i=!1})=>{let a=`system.modals.perform(${Ks(e,t,n,r)})`,o=ys(`system.modals.perform`);if(!i)return`${o} ? ${a} : false`;let s=`(system.modals.list().modals || []).filter(${`(m) => m.id === ${JSON.stringify(e)} && m.token != null && String(m.token) === ${JSON.stringify(String(t))}`}).some((m) => !!(m.owner && m.owner.type === 'generator' && m.owner.confirm === true))`;return`${o} && ${ys(`system.modals.list`)} ? (${s} ? 'approval' : ${a}) : false`},Ys=(e,t=Gs)=>{if(!Number.isInteger(e)||e<0||e>t)throw TypeError(`wait must be a whole number of milliseconds, 0 to ${t}`)},Xs=e=>new Promise(t=>setTimeout(t,e)),Zs=async(e,t,{wait:n=0,maxWait:r=Gs,pollMs:i=100,isNotReady:a=e=>e?.outcome===J.notReady}={})=>{Ys(n,r);let o=performance.now();for(let r=1;;r+=1){let s=await _s(e,t);ps(s);let c=s?.result?.value,l=Math.round(performance.now()-o);if(!a(c)||l>=n)return{answer:c,waitedMs:r>1?l:0};await Xs(Math.min(i,n-l))}},Qs=e=>({handled:null,outcome:J.unsupported,reason:`this runtime has no system.modals (app version >= 2.26)`,blockedBy:null,...e}),$s=async(e,{wait:t=0}={})=>{let{answer:n,waitedMs:r}=await Zs(e,qs(),{wait:t});if(n===!1)return Qs({modals:[],waitedMs:r});let i=Array.isArray(n?.modals)?n.modals:[];return{...n,...Y(n),modals:i,waitedMs:r}},ec=e=>e?.code===`not-ready`||e?.code==null&&e?.outcome===J.notReady,tc=e=>`Modal ${e} is the confirm dialog of a generator, the approval of a person (the Assistant asks it before a tool call): this tool only dismisses it (the confirm answers false); a person approves it in the app`,nc=async(e,{id:t,token:n,op:r,args:i,wait:a=0,allowApproval:o=!0})=>{if(typeof t!=`string`||!t)throw TypeError(`id is required (from the modal list)`);if(!(typeof n==`number`||typeof n==`string`&&n))throw TypeError(`token is required (the token of the modal in the modal list)`);if(typeof r!=`string`||!r)throw TypeError(`op is required`);if(i!=null&&(typeof i!=`object`||Array.isArray(i)))throw TypeError(`args must be an object`);Ys(a);let{answer:s,waitedMs:c}=await Zs(e,Js({id:t,token:n,op:r,args:i??{},refuseApproval:!o&&r!==`dismiss`}),{wait:a,isNotReady:ec});return s===!1?Qs({code:null,id:t,op:r,token:null,waitedMs:c}):s===`approval`?{handled:null,outcome:J.unsupported,reason:tc(t),blockedBy:null,code:null,id:t,op:r,token:n,approval:!0,waitedMs:c}:{...s,...Y(s),waitedMs:c}},rc=async(e,{x:t,y:n})=>{let r=Number(t),i=Number(n),a=await e.send(`Input.dispatchMouseEvent`,{type:`mousePressed`,x:r,y:i,button:`left`,clickCount:1});return await e.send(`Input.dispatchMouseEvent`,{type:`mouseReleased`,x:r,y:i,button:`left`,clickCount:1}),{x:r,y:i,tapResult:a||null,...Y(a,`tap`)}},ic=e=>e&&typeof e.handled==`boolean`?e:null,ac=e=>{if(e?.mode!==`text`)return null;let{target:t=null,op:n,value:r,previousValue:i,focused:a,selection:o,change:s,submit:c}=e;return{target:t,op:n,value:r,previousValue:i,focused:a,selection:o,change:s,submit:c}},oc=async(e,t,{global:n=!1}={})=>{let r=n?{global:!0}:{},i=await e.send(`Input.dispatchKeyEvent`,{type:`keyDown`,key:t,...r}),a=await e.send(`Input.dispatchKeyEvent`,{type:`keyUp`,key:t,...r}),o=Y(i,`key`),s=Y(a,`key`),c=Is(s.outcome,o.outcome),{outcome:l,reason:u,blockedBy:d}=c?s:o,f=ic(i)||ic(a),p=c&&ic(a)||f,m=ac(i);return{key:t,handled:p?p.handled:null,reason:u,keyCode:f?.keyCode??null,outcome:l,blockedBy:d,...m&&{input:m}}},sc=ys(`system.simulatePress`),cc=6e4,lc=({subspaceId:e,brickId:t,options:n={}})=>{let r=[e,t,n].map(e=>JSON.stringify(e)).join(`, `);return`${sc} ? system.simulatePress(${r}) : false`},uc=({itemsBrickId:e})=>{let t=`this runtime does not report what the press did (app version >= 2.26 does)`;return/^B_/.test(e||``)?`${t}; it takes only the full id as itemsBrickId, so a short id finds no row`:t},dc=(e,t)=>({handled:null,outcome:e,reason:t,blockedBy:null,events:null,longPressed:null}),fc=async(e,{itemsMode:t,longPress:n=!1,holdMs:r=0,...i})=>{if(!Number.isInteger(r)||r<0||r>6e4)throw TypeError(`holdMs must be a whole number of milliseconds, 0 to ${cc}`);let{target:a}=await Ms(e,i),o=As(a),s=o&&t?{itemsMode:t}:null,c={...o,...s,...n&&{longPress:!0},...r>0&&{simulateInOutTimeout:r}},{subspaceId:l,brickId:u}=a,d=await _s(e,lc({subspaceId:l,brickId:u,options:c}),r>0?{timeout:r+15e3}:void 0);ps(d);let f=d?.result?.value,p={...a,...s,longPress:!!n,holdMs:r};return f===!1?{...p,...dc(J.unsupported,`this runtime has no system.simulatePress`)}:typeof f?.outcome==`string`?{...p,...f,...Y(f)}:{...p,...dc(J.unconfirmed,uc(a))}};Object.freeze([`alert`,`generator`,`all`]);const pc=e=>{if(e.subtype===`null`)return null;if(e.type!==`undefined`){if(e.type===`boolean`)return e.value===`true`;if(e.type===`number`){let t=Number(e.value);return Number.isNaN(t)?e.value:t}return e.value}},mc=e=>{let{value:t}=us(e),n=e?.objectId?e.preview?.properties:null;if(!Array.isArray(n)||n.length===0)return t;if(e.subtype===`array`){let e=[];for(let t of n)/^\d+$/.test(t.name)&&(e[Number(t.name)]=pc(t));return e}return n.reduce((e,t)=>(e[t.name]=pc(t),e),{})},hc=e=>{let t=mc(e);if(t===void 0)return`undefined`;if(typeof t==`string`)return t;if(typeof t==`bigint`)return`${t}n`;if(typeof t==`object`&&t)try{return JSON.stringify(t)}catch{}return String(t??e?.description??t)},gc=e=>e===`error`||e===`assert`||e===`exception`?`error`:e===`warning`||e===`warn`?`warning`:e===`debug`||e===`trace`?`debug`:`info`,_c=e=>{let t=e?.callFrames;return!Array.isArray(t)||t.length===0?null:t.map(e=>{let t=e.functionName||`<anonymous>`,n=e.url?`${e.url}:${Number(e.lineNumber)+1}:${Number(e.columnNumber)+1}`:null;return n?`at ${t} (${n})`:`at ${t}`}).join(`
625
+ `)},vc=(e={})=>{let t=e.type||`log`,n=(e.args||[]).map(mc),r=_c(e.stackTrace);return{level:gc(t),type:t,text:(e.args||[]).map(hc).join(` `),timestamp:e.timestamp??Date.now(),args:n,...r?{stack:r}:{}}},yc=(e={})=>{let t=e.exceptionDetails||{},n=t.exception?.description||``,r=n.split(/\r?\n/,1)[0]||t.exception?.value||t.text||`Uncaught exception`,i=t.text&&t.text!==r?`${t.text}: ${r}`:String(r),a=t.stackTrace?.callFrames,o=Array.isArray(a)?a[0]:null,s=_c(t.stackTrace)||(n.includes(`
626
+ `)?n:null),c=t.url||o?.url,l=t.lineNumber??o?.lineNumber,u=t.columnNumber??o?.columnNumber;return{level:`error`,type:`exception`,text:i,timestamp:e.timestamp??Date.now(),exceptionText:String(r),...s?{stack:s}:{},...c?{url:c}:{},...l===void 0?{}:{lineNumber:l},...u===void 0?{}:{columnNumber:u}}},bc=/^Connected to BRICKS .*DevTools!/,xc=(e,{enabledAt:t,startedAt:n})=>{let r=e.find(e=>typeof e.timestamp==`number`&&bc.test(e.text||``)),i=n??r?.timestamp??t;return e.map(e=>{let t=typeof e.timestamp==`number`&&e.timestamp<i;return t?{...e,retained:t,ageMs:i-e.timestamp}:{...e,retained:t}})},Sc=async e=>{try{let{result:t}=await e.send(`Runtime.evaluate`,{expression:`Date.now()`,returnByValue:!0});return typeof t?.value==`number`?t.value:null}catch{return null}},Cc=async(e,t)=>{let n=[],r=e=>n.push(vc(e)),i=e=>n.push(yc(e)),a=!1;e.on(`Runtime.consoleAPICalled`,r),e.on(`Runtime.exceptionThrown`,i);let o=Date.now(),s=await Sc(e);try{await e.send(`Runtime.enable`),a=!0,await new Promise(e=>setTimeout(e,t))}finally{try{a&&await e.send(`Runtime.disable`)}finally{e.off(`Runtime.consoleAPICalled`,r),e.off(`Runtime.exceptionThrown`,i)}}return xc(n.sort((e,t)=>e.timestamp-t.timestamp),{enabledAt:o,startedAt:s})},wc=[[/^iVBORw0KGgo/,`image/png`],[/^\/9j\//,`image/jpeg`],[/^UklGR.{6}XRUJQ/,`image/webp`]],Tc=async(e,{format:t=`jpeg`,quality:n=70,clip:r}={})=>{let i={format:t};t===`jpeg`&&(i.quality=n),r&&(i.clip=r);let{data:a}=await e.send(`Page.captureScreenshot`,i),o=wc.find(([e])=>e.test(a??``));return{data:a,mimeType:o?o[1]:`image/${t}`}},Ec=`bricks://app`,Dc=`DATA-`,Oc=e=>{let t=e.startsWith(`DATA-`)?e.slice(5):e,n=t.indexOf(`:`);return n<0?{shortId:t,title:null}:{shortId:t.slice(0,n),title:t.slice(n+1)}},kc=async(e,t,n)=>{try{return(await e.send(`IndexedDB.getMetadata`,{securityOrigin:Ec,databaseName:t,objectStoreName:n})).entriesCount}catch{return null}},Ac=async(e,t)=>{let{entries:n}=await e.send(`DOMStorage.getDOMStorageItems`,{storageId:{securityOrigin:Ec,isLocalStorage:t}});return n},jc=async e=>{await e.send(`DOMStorage.enable`),await e.send(`IndexedDB.enable`);let t=(await Ac(e,!0)).length,n=(await Ac(e,!1)).length,{databaseNames:r}=await e.send(`IndexedDB.requestDatabaseNames`,{securityOrigin:Ec}),i=[];for(let t of r){let n=t.startsWith(`DATA-`)?`properties`:`entries`;i.push({name:t,objectStoreName:n,entriesCount:await kc(e,t,n)})}return{system:{persist:t,memory:n},dataBanks:i.filter(e=>e.name.startsWith(Dc)).map(e=>({...e,...Oc(e.name)})),caches:i.filter(e=>!e.name.startsWith(Dc))}},Mc=`Run bricks buttress bind again and restart Buttress to provision a fresh DevTools token.`,Nc=async(e,t,n,r)=>{let i=n?.workspace;if(!i)return;r?.throwIfAborted();let a=await cs(e,t);if(r?.throwIfAborted(),!a)throw Error(`Cannot reach device DevTools info; no workspace credential was sent.`);if(!a.auth?.workspaceJwt?.enabled)return;if(a.workspaceId!==i.id||a.auth.workspaceJwt.kid!==i.kid)throw Error(`Device workspace/issuer does not match Buttress; no workspace credential was sent.`);let o=n?.devtools;if(!o||o.workspaceId!==i.id)throw Error(`No DevTools credential is provisioned for the bound workspace. ${Mc}`);try{let e=await _e(i.issuerPublicKey,`EdDSA`),{payload:t,protectedHeader:n}=await ve(o.token,e,{algorithms:[`EdDSA`],requiredClaims:[`exp`]});if(n.kid!==i.kid||t.k!==`da`||t.w_id!==i.id||t.st!==`ws`||typeof t.sid!=`string`||!t.sid)throw Error(`Invalid DevTools claims`)}catch{throw Error(`The provisioned DevTools token is expired or invalid. ${Mc}`)}return r?.throwIfAborted(),o.token},Pc=(e,t)=>{let n=typeof e==`string`?e:JSON.stringify(e,null,2)??``;for(let e of t)n=n.split(e).join(`[REDACTED]`),n=n.split(encodeURIComponent(e)).join(`[REDACTED]`);return{content:[{type:`text`,text:ni(n)}],details:{}}},X=(e,t)=>{if(typeof e[t]!=`string`||!e[t].length)throw Error(`${t} must be a non-empty string`);return e[t]},Z=(e,t,n,r=-1/0,i=1/0)=>{let a=e[t]??n;if(typeof a!=`number`||!Number.isFinite(a)||a<r||a>i)throw Error(`${t} must be a number between ${r} and ${i}`);return a},Fc=(e,t)=>e[t]===void 0?void 0:X(e,t),Ic=(e,t)=>{if(e[t]===void 0)return;let n=Z(e,t,void 0,0);if(!Number.isInteger(n))throw Error(`${t} must be an integer`);return n},Lc=e=>{let t=Z(e,`port`,19851,1,65535);if(!Number.isInteger(t))throw Error(`port must be an integer`);return t},Rc=async(e,t,n)=>{switch(t.action){case`screenshot`:{let{data:t,mimeType:n}=await Tc(e);if(!t)throw Error(`No screenshot data received`);return{content:[{type:`image`,data:t,mimeType:n}],details:{}}}case`tree`:return n(await Vs(e,{depth:Z(t,`depth`,3,-1)}));case`query`:return n(await Us(e,X(t,`selector`)));case`tap`:return n(await rc(e,{x:Z(t,`x`),y:Z(t,`y`)}));case`key`:return n(await oc(e,X(t,`key`)));case`press`:return n(await fc(e,{subspaceId:X(t,`subspaceId`),brickId:X(t,`brickId`),itemsBrickId:Fc(t,`itemsBrickId`),itemsIndex:Ic(t,`itemsIndex`),itemsDataId:Fc(t,`itemsDataId`),longPress:t.longPress===!0,holdMs:t.holdMs??0}));case`modal`:{let r=t.waitMs??0;return t.modalOp===void 0?n(await $s(e,{wait:r})):n(await nc(e,{id:X(t,`modalId`),token:Z(t,`modalToken`,void 0,0),op:X(t,`modalOp`),args:t.modalArgs,wait:r,allowApproval:!1}))}case`input`:if(typeof t.text!=`string`)throw Error(`text must be a string`);return n(await Ws(e,{subspaceId:X(t,`subspaceId`),brickId:X(t,`brickId`),text:t.text}));case`console`:return n(await Cc(e,Z(t,`duration`,2e3,0,1e4)));case`evaluate`:return n(await ms(e,X(t,`expression`),{awaitPromise:t.awaitPromise??!1}));case`storage`:return n(await jc(e));case`cdp`:return n(await e.send(X(t,`method`),t.params??{}));default:throw Error(`Unknown DevTools action: ${t.action}`)}},zc=async(e,t,n,r)=>{t?.throwIfAborted();let i=X(e,`address`);if(!/^(\[[\da-fA-F:]+\]|[\w.-]+)$/.test(i))throw Error(`address must be a hostname or IP (bracket IPv6); supply port separately`);let a=Lc(e),o=e.accessToken||(e.passcode?void 0:await Nc(i,a,r,t));t?.throwIfAborted();let s=os(i,a,{passcode:e.passcode,accessToken:o}),c,l=new Promise((e,n)=>{c=()=>{s.close(),n(t?.reason||Error(`Device tool aborted`))},t?.addEventListener(`abort`,c,{once:!0})});try{return await Promise.race([(async()=>(await s.connect(),t?.throwIfAborted(),Rc(s,e,n)))(),l])}finally{c&&t?.removeEventListener(`abort`,c),s.close()}},Bc=(e,t)=>async(n,r,i)=>{let a=[t,r?.accessToken,r?.passcode].filter(e=>typeof e==`string`&&e.length>0),o=e=>Pc(e,a);try{return i?.throwIfAborted(),await e(r??{},i,o)}catch(e){return o(`Tool error: ${e?.message||String(e)}`)}},Vc={type:`integer`,minimum:1,maximum:65535,default:19851},Hc=(e,t,n)=>e.localDevices?[{name:`devices_scan`,label:`Scan local devices`,description:`Find BRICKS devices on the Buttress host LAN using the same UDP + HTTP discovery as bricks devtools scan. Returns addresses, ports and authentication hints. Also checks local project previews relative to the Buttress config directory. No cloud login needed.`,parameters:{type:`object`,properties:{timeout:{type:`integer`,minimum:100,maximum:1e4,default:3e3},udpOnly:{type:`boolean`,description:`Skip HTTP subnet probing (default false).`},verify:{type:`boolean`,description:`Verify discovered servers via HTTP.`},project:{type:`boolean`,description:`Include local project previews (default true).`},port:Vc},additionalProperties:!1},execute:Bc(async(e,n,r)=>{let i=await ss({timeout:Z(e,`timeout`,3e3,100,1e4),port:Lc(e),udpOnly:e.udpOnly??!1,verify:e.verify??!1,project:e.project??!0,cwd:t});return n?.throwIfAborted(),r(i)},n?.devtools?.token)},{name:`devtools`,label:`Device DevTools`,description:`Inspect or control a BRICKS device from devices_scan. Each call opens and closes CDP; run calls sequentially (devices accept one inspector). Uses CLI DevTools operations. Actions: screenshot (inline image), tree (depth), query (selector), tap (x,y in BRICKS layout units of the root canvas, NOT pixels; a frame in a nested subspace or an Items brick is local to that parent, so get its box with cdp DOM.getBoxModel), key (key), press (subspaceId,brickId: press a brick by id as a person, the Automation brick_press path; a node id of a brick in an Items row (app version >= 2.25.12), or the Items brick with itemsBrickId and itemsIndex or itemsDataId, presses that row; longPress, holdMs; the result has the outcome and the fired events, unconfirmed before app version 2.26), modal (app version >= 2.26: with no modalOp, list the open app modals with their ids, tokens and operations; with modalId, modalToken (from the list) and modalOp, run one operation on the topmost modal: alert select (modalArgs { index } or { label }) | dismiss, information confirm | close, question input (modalArgs { value }) | next | back | skip | close; a stale token answers missing-target; a generator confirm dialog is the approval of a person: only dismiss it; waitMs waits while not-ready), input (subspaceId,brickId,text), console (duration ms; retained + new entries), evaluate (expression,awaitPromise), storage (overview), cdp (method,params for other supported CDP operations, e.g. DOM.getAttributes). Workspace authentication is automatic for matching-workspace devices after bricks buttress bind. The credential stays server-side; do not request it from the user. An optional passcode or accessToken overrides automatic auth. Local previews can use advertised inspect credentials. Input, evaluation and raw CDP can change device state.`,parameters:{type:`object`,properties:{action:{type:`string`,enum:[`screenshot`,`tree`,`query`,`tap`,`key`,`press`,`modal`,`input`,`console`,`evaluate`,`storage`,`cdp`]},address:{type:`string`,description:`Device hostname/IP from scan, without port.`},port:Vc,passcode:{type:`string`},accessToken:{type:`string`,description:`Optional explicit DevTools JWT override; normally omit.`},depth:{type:`integer`,minimum:-1,default:3},selector:{type:`string`},x:{type:`number`},y:{type:`number`},key:{type:`string`},subspaceId:{type:`string`},brickId:{type:`string`},itemsBrickId:{type:`string`,description:`press: the template brick of the row.`},itemsIndex:{type:`integer`,minimum:0},itemsDataId:{type:`string`},longPress:{type:`boolean`},holdMs:{type:`integer`,minimum:0,maximum:cc,default:0},modalId:{type:`string`,description:`modal: the id of the modal from the list.`},modalToken:{type:`integer`,minimum:0,description:`modal: its token.`},modalOp:{type:`string`,description:`modal: the operation to run.`},modalArgs:{type:`object`,additionalProperties:!0},waitMs:{type:`integer`,minimum:0,maximum:Gs,default:0},text:{type:`string`},duration:{type:`integer`,minimum:0,maximum:1e4,default:2e3},expression:{type:`string`},awaitPromise:{type:`boolean`},method:{type:`string`},params:{type:`object`,additionalProperties:!0}},required:[`action`,`address`],additionalProperties:!1},execute:Bc((e,t,r)=>zc(e,t,r,n),n?.devtools?.token)}]:[],Q=`[Agents]`,Uc=e=>e.filter(e=>e.role!==`system`),Wc=e=>{for(let t=e.length-1;t>=0;--t){let n=e[t];if(n?.role!==`assistant`||!Array.isArray(n.content))continue;let r=n.content.filter(e=>e?.type===`text`&&typeof e.text==`string`).map(e=>e.text).join(``),i=n.content.filter(e=>e?.type===`thinking`&&typeof e.thinking==`string`).map(e=>e.thinking).join(`
627
+ `);if(r||i)return{content:r,reasoning:i}}return{content:``,reasoning:``}},Gc=(e,t)=>{let n={input:0,output:0,cacheRead:0,totalTurns:0};for(let r of e.slice(t))r?.role===`assistant`&&(n.totalTurns+=1,r.usage&&(n.input+=r.usage.input||0,n.output+=r.usage.output||0,n.cacheRead+=r.usage.cacheRead||0));return n},Kc=({config:e,agentsConfig:t,runtimeBase:n,getHandle:r,getFunctions:i})=>{let a=new Map(t.agents.map(e=>[e.name,e])),o=To(),s=Eo(o);try{Do(t.runtimeTokenFile,o)}catch(e){console.warn(`${Q} could not write runtime token file ${t.runtimeTokenFile}: ${e?.message||e}`)}let c=Co(e,Oo(r,o),t=>Xt(n.backend,e,t,Q)),l=zo(t),u=Wo({configDir:t.configDir}),d=new Map,f=new Map,p=async(e,t)=>{let n=(d.get(e)??Promise.resolve()).then(t,t),r=n.catch(()=>{});d.set(e,r);try{return await n}finally{d.get(e)===r&&d.delete(e)}},m=e=>e.systemPrompt==null?e.systemPromptFile?P.readFileSync(e.systemPromptFile,`utf8`):`You are a helpful automation agent running on a BRICKS Buttress server.`:e.systemPrompt,h=async(e,r,a,o)=>{let s=e.metadata.id,d=`${r.name} ${s}`;try{a.onSession?.(s)}catch{}let p=o===`new`?[]:await l.messages(e),h=a.depth??0,g=i(),v={...n,agents:_},y=r.tools.length>0?await Jo(r,{functions:g,runtime:v,depth:h+1,onToolEmit:(e,t,n,r)=>a.onEvent?.({type:`tool_emit`,toolCallId:r,toolName:e,event:t,data:n})}):[],b=await u.toolsFor(r.name,r.mcpServers),x=[...y,...Hc(r,t.configDir,n.workspaceState),...b],S=x.filter(e=>!e._mcpExposure||e._mcpExposure===`direct`),C;try{C=lo(c,r)}catch(e){throw new G(e?.message||String(e),s)}C&&S.push(fo(c,C)),r.codemode&&S.push(await qo({tools:x,declaredNames:new Set(S.map(e=>e.name)),getState:()=>E.state,models:c}));let ee=new Set;for(let e of S){if(ee.has(e.name))throw new G(`${Q} ${r.name}: duplicate tool name "${e.name}" between local functions, built-in tools or MCP servers`,s);ee.add(e.name)}let w=S;if(C&&r.decisionAssistance){let e=Date.now(),t=await vo({models:c,model:C,prompt:a.prompt,history:p,toolNames:S.map(e=>e.name),timeoutMs:r.decisionTimeoutMs,signal:a.signal});t.prune&&(w=[]);let n=JSON.stringify(S.map(({name:e,description:t,parameters:n})=>({name:e,description:t,parameters:n}))).length;console.log(`${Q} ${r.name}: tool prefilter ${t.prune?`pruned`:`kept`} ${S.length} tools (${t.reason}${t.detail?`: ${t.detail}`:``}, ${Date.now()-e}ms${t.prune?`, -${n} chars`:``})`)}let T=`end_turn`,te=0,ne=0,E=new Be({initialState:{model:wo(c,r),systemPrompt:m(r),...r.thinking?{thinkingLevel:r.thinking}:{},tools:w,messages:p},sessionId:s,streamFn:(e,t,n)=>c.streamSimple(e,t,{...n,...r.generation}),finishTurn:e=>{te+=1;let t=e.message?.usage;if(t&&(ne+=(t.input||0)+(t.output||0)),te>=r.maxTurns)return T=`max_turns`,{action:`end`};if(r.maxTokensPerRun!=null&&ne>=r.maxTokensPerRun)return T=`token_budget`,{action:`end`}}}),D=p.length,re=async()=>{let t=Uc(E.state.messages);for(;D<t.length;){let n=t[D];D+=1;try{await l.append(e,JSON.parse(JSON.stringify(n)))}catch(e){console.warn(`${Q} failed to persist message:`,e?.message||e)}}};E.subscribe(async e=>{`message`in e&&e.message.role===`system`||(a.onEvent?.(e),(e.type===`message_end`||e.type===`agent_end`)&&await re())});let O=!1,ie=()=>{O=!0,T=`aborted`,E.abort()},k=()=>ie();if(a.signal?.aborted)throw new G(`aborted before start`,s,`aborted`);a.signal?.addEventListener(`abort`,k,{once:!0}),f.set(d,{abort:ie});let A=p.length;try{await E.prompt(a.prompt),await E.waitForIdle()}catch(e){throw await re(),new G(e?.message||String(e),s,O||a.signal?.aborted?`aborted`:`error`)}finally{f.delete(d),a.signal?.removeEventListener(`abort`,k)}await re();let ae=E.state;if(ae.errorMessage)throw new G(ae.errorMessage,s,T);a.signal?.aborted&&(T=`aborted`);let oe=Uc(ae.messages),{content:se,reasoning:j}=Wc(oe);return{sessionId:s,content:se,...j?{reasoningContent:j}:{},usage:Gc(oe,A),stopReason:T}},g=async(e,t,n)=>{let r=n===`continue`?await l.open(e.name,t.sessionId):n===`fork`?await l.fork(e.name,t.sessionId):await l.create(e.name);return h(r,e,t,n)},_={config:t,list:()=>[...a.keys()],run:async(e,n)=>{let r=a.get(e);if(!r)throw new G(`unknown agent "${e}" (configured: ${[...a.keys()].join(`, `)||`none`})`,null);if((n.depth??0)>=t.maxDepth)throw new G(`agent-invocation depth limit reached (${t.maxDepth}); a function called an agent that called a function that called an agent… raise agents_options.max_depth if this chain is intended`,null);if(typeof n.prompt!=`string`||!n.prompt.trim())throw new G(`prompt is required`,null);if(n.fork&&!n.sessionId)throw new G(`fork requires sessionId`,null);let i=n.sessionId?n.fork?`fork`:`continue`:`new`;return i===`continue`?p(`${e} ${n.sessionId}`,()=>g(r,n,i)):g(r,n,i)},sessions:(e,t)=>{if(!a.has(e))throw Error(`${Q} unknown agent "${e}"`);return l.list(e,t?.limit)},transcript:async(e,t)=>{if(!a.has(e))throw Error(`${Q} unknown agent "${e}"`);return await l.messages(await l.open(e,t))},abort:(e,t)=>{let n=f.get(`${e} ${t}`);return n?(n.abort(),!0):!1},verifyInternalToken:s,dispose:async()=>{clearInterval(y);for(let e of f.values())e.abort();await u.dispose()}},v=()=>{l.sweep([...a.keys()]).then(e=>{e>0&&console.log(`${Q} retention: removed ${e} session(s)`)}).catch(e=>{console.warn(`${Q} retention sweep failed:`,e?.message||e)})},y=setInterval(v,216e5);return y.unref?.(),v(),console.log(`${Q} ${a.size} agent${a.size===1?``:`s`} configured: `+[...a.keys()].join(`, `)),_},$=e(),qc=(e,t)=>i(e,t),Jc=(e,t)=>{e.push(`
628
628
  ### Command Used`);let n=process.argv.slice(2).join(` `);if(e.push(`\`\`\`bash\n${process.argv[0]} ${process.argv[1]} ${n}\n\`\`\``),e.push(`
629
629
  ### Package Information`),e.push(`- **Name:** ${$.name}`),e.push(`- **Version:** ${$.version}`),$.description&&e.push(`- **Description:** ${$.description}`),t&&Object.keys(t).length>0){e.push(`
630
- ### Configuration`),e.push(`<details>`),e.push(`<summary>Click to expand TOML configuration</summary>`),e.push("\n```toml");try{let n=Le.stringify(t);e.push(n)}catch{e.push(`# Error serializing config`),e.push(JSON.stringify(t,null,2))}e.push("```"),e.push(`</details>`)}},Jc=(e,{includeArchitecture:t=!1}={})=>{e.push(`
630
+ ### Configuration`),e.push(`<details>`),e.push(`<summary>Click to expand TOML configuration</summary>`),e.push("\n```toml");try{let n=Le.stringify(t);e.push(n)}catch{e.push(`# Error serializing config`),e.push(JSON.stringify(t,null,2))}e.push("```"),e.push(`</details>`)}},Yc=(e,{includeArchitecture:t=!1}={})=>{e.push(`
631
631
  ---`),e.push(`
632
- ### System Information`);let n=null;if(process.platform!==`win32`)try{n=pe(`uname -a`,{encoding:`utf8`}).trim()}catch{}n?e.push(`- **System:** ${n}`):(e.push(`- **Hostname:** ${N.hostname()}`),e.push(`- **OS:** ${N.type()} ${N.release()}`)),e.push(`- **Platform:** ${process.platform}`),t&&e.push(`- **Architecture:** ${N.arch()}`),e.push(`- **CPU Cores:** ${N.cpus().length}`),e.push(`- **Total System Memory:** ${(N.totalmem()/1024/1024/1024).toFixed(2)} GB`)},Yc=(e,t)=>{let n=t?.buttress?.selected;if(!n)return;let r=n.cpuTotalBytes>0?(n.cpuUsableBytes/n.cpuTotalBytes*100).toFixed(0):0;if(e.push(`- **Usable CPU Memory:** ${(n.cpuUsableBytes/1024/1024/1024).toFixed(2)} GB (${r}% of ${(n.cpuTotalBytes/1024/1024/1024).toFixed(2)} GB)`),n.hasGpu){let t=n.devices.filter(e=>e.type===`gpu`);if(t.length>0){let r=t[0];e.push(`- **GPU Backend:** ${r.backend}`),e.push(`- **GPU Name:** ${r.deviceName}`),e.push(`- **GPU Total Memory:** ${(r.maxMemorySize/1024/1024/1024).toFixed(2)} GB`);let i=n.gpuTotalBytes>0?(n.gpuUsableBytes/n.gpuTotalBytes*100).toFixed(0):0;e.push(`- **GPU Usable Memory:** ${(n.gpuUsableBytes/1024/1024/1024).toFixed(2)} GB (${i}% of ${(n.gpuTotalBytes/1024/1024/1024).toFixed(2)} GB)`)}}else e.push(`- **GPU:** Not available`)},Xc=(e,{includeLimitedFit:t=!1}={})=>{console.log(`
632
+ ### System Information`);let n=null;if(process.platform!==`win32`)try{n=pe(`uname -a`,{encoding:`utf8`}).trim()}catch{}n?e.push(`- **System:** ${n}`):(e.push(`- **Hostname:** ${N.hostname()}`),e.push(`- **OS:** ${N.type()} ${N.release()}`)),e.push(`- **Platform:** ${process.platform}`),t&&e.push(`- **Architecture:** ${N.arch()}`),e.push(`- **CPU Cores:** ${N.cpus().length}`),e.push(`- **Total System Memory:** ${(N.totalmem()/1024/1024/1024).toFixed(2)} GB`)},Xc=(e,t)=>{let n=t?.buttress?.selected;if(!n)return;let r=n.cpuTotalBytes>0?(n.cpuUsableBytes/n.cpuTotalBytes*100).toFixed(0):0;if(e.push(`- **Usable CPU Memory:** ${(n.cpuUsableBytes/1024/1024/1024).toFixed(2)} GB (${r}% of ${(n.cpuTotalBytes/1024/1024/1024).toFixed(2)} GB)`),n.hasGpu){let t=n.devices.filter(e=>e.type===`gpu`);if(t.length>0){let r=t[0];e.push(`- **GPU Backend:** ${r.backend}`),e.push(`- **GPU Name:** ${r.deviceName}`),e.push(`- **GPU Total Memory:** ${(r.maxMemorySize/1024/1024/1024).toFixed(2)} GB`);let i=n.gpuTotalBytes>0?(n.gpuUsableBytes/n.gpuTotalBytes*100).toFixed(0):0;e.push(`- **GPU Usable Memory:** ${(n.gpuUsableBytes/1024/1024/1024).toFixed(2)} GB (${i}% of ${(n.gpuTotalBytes/1024/1024/1024).toFixed(2)} GB)`)}}else e.push(`- **GPU:** Not available`)},Zc=(e,{includeLimitedFit:t=!1}={})=>{console.log(`
633
633
  === Hardware Information ===`);let n=null;if(process.platform!==`win32`)try{n=pe(`uname -a`,{encoding:`utf8`}).trim()}catch{}n?console.log(`System: ${n}`):(console.log(`Hostname: ${N.hostname()}`),console.log(`OS: ${N.type()} ${N.release()}`)),console.log(`Platform: ${e.platform}`),console.log(`CPU Cores: ${N.cpus().length}`),console.log(`Total System Memory: ${(N.totalmem()/1024/1024/1024).toFixed(2)} GB`);let r=e.cpuTotalBytes>0?(e.cpuUsableBytes/e.cpuTotalBytes*100).toFixed(0):0;console.log(`Usable CPU Memory: ${(e.cpuUsableBytes/1024/1024/1024).toFixed(2)} GB (${r}% of ${(e.cpuTotalBytes/1024/1024/1024).toFixed(2)} GB)`),e.hasGpu?(console.log(`
634
634
  --- GPU Details ---`),e.devices.filter(e=>e.type===`gpu`).forEach(t=>{console.log(`GPU Backend: ${t.backend}`),console.log(`GPU Name: ${t.deviceName}`),console.log(`GPU Total Memory: ${(t.maxMemorySize/1024/1024/1024).toFixed(2)} GB`);let n=e.gpuTotalBytes>0?(e.gpuUsableBytes/e.gpuTotalBytes*100).toFixed(0):0;console.log(`GPU Usable Memory: ${(e.gpuUsableBytes/1024/1024/1024).toFixed(2)} GB (${n}% of ${(e.gpuTotalBytes/1024/1024/1024).toFixed(2)} GB)`),t.metadata&&(t.metadata.hasBFloat16&&console.log(`Supports BFloat16: Yes`),t.metadata.hasUnifiedMemory&&console.log(`Unified Memory: Yes`))})):console.log(`GPU: Not available`),console.log(`\nBackend Variant: ${e.variant}`),console.log(`Performance Score: ${e.score}`),e.fit&&(console.log(`
635
635
  --- Model Fit Analysis ---`),console.log(`Fits in GPU: ${e.fit.fitsInGpu?`Yes`:`No`}`),console.log(`Fits in CPU: ${e.fit.fitsInCpu?`Yes`:`No`}`),console.log(`Limiting Factor: ${e.fit.limiting}`),t&&e.limitedFit&&(console.log(`
636
- --- Memory-Limited Fit Analysis ---`),console.log(`Limited Total Required: ${(e.limitedFit.totalRequiredBytes/1024/1024/1024).toFixed(2)} GB`),console.log(`Fits in GPU (Limited): ${e.limitedFit.fitsInGpu?`Yes`:`No`}`),console.log(`Fits in CPU (Limited): ${e.limitedFit.fitsInCpu?`Yes`:`No`}`),console.log(`Limiting Factor (Limited): ${e.limitedFit.limiting}`)))},Zc=e=>{if(!e)return{repoId:null,filename:null};let[t,n]=e.split(`:`);return{repoId:t,filename:n||null}};async function Qc({modelIds:e=[],defaultConfig:t=null}={}){let r=[];console.log(`${$.name} v${$.version}`),console.log(`Generating model capabilities comparison...
636
+ --- Memory-Limited Fit Analysis ---`),console.log(`Limited Total Required: ${(e.limitedFit.totalRequiredBytes/1024/1024/1024).toFixed(2)} GB`),console.log(`Fits in GPU (Limited): ${e.limitedFit.fitsInGpu?`Yes`:`No`}`),console.log(`Fits in CPU (Limited): ${e.limitedFit.fitsInCpu?`Yes`:`No`}`),console.log(`Limiting Factor (Limited): ${e.limitedFit.limiting}`)))},Qc=e=>{if(!e)return{repoId:null,filename:null};let[t,n]=e.split(`:`);return{repoId:t,filename:n||null}};async function $c({modelIds:e=[],defaultConfig:t=null}={}){let r=[];console.log(`${$.name} v${$.version}`),console.log(`Generating model capabilities comparison...
637
637
  `),r.push(`${$.name} v${$.version}`),r.push(`## Model Capabilities Comparison
638
- `),(!e||e.length===0)&&(console.error(`Error: No model IDs provided`),process.exit(1));try{let{globalDefaults:i,resolveDefaultConfig:a}=Kc(t,`ggml-llm`),o=[];for(let t=0;t<e.length;t+=1){let n=e[t];console.log(`[${t+1}/${e.length}] Analyzing ${n}...`);let r=a(n);r={...r||{},model:{...i.runtime||{},...r?.model||{},repo_id:n}};let s=await u(`ggml-llm`,null,{config:r,includeBreakdown:!0});o.push({modelId:n,capabilities:s,modelInfo:s.buttress?.selected||null,modelConfig:s.modelConfig||null})}let s=e=>e?(e/1024/1024/1024).toFixed(2):`N/A`,c=e=>e?`✅`:`🚫`;r.push(`| Model ID | Size (GB) | Context Size | KV Cache Size (GB) | Recurrent Mem (GB) | Total Required Memory (GB) | Fits GPU (Full) | Fits CPU (Full) |`),r.push(`|----------|-----------|--------------|--------------------|--------------------|----------------------------|-----------------|-----------------|`),o.forEach(({modelId:e,modelInfo:t,modelConfig:i})=>{let a=s(t?.modelBytes),o=i?.nCtx||t?.kvInfo?.nCtxTrain||`N/A`,l=t?n(t):null,u=Number(o),d=t?.kvCacheBytes||(l&&Number.isFinite(u)&&u>0?l(u):l&&l(t?.kvInfo?.nCtxTrain||0))||null,f=s(d),p=t?.recurrentMemoryBytes||0,m=p>0?s(p):`-`,h=s(t?.modelBytes&&(d!=null||p>0)?t.modelBytes+(d||0)+p:t?.fit?.totalRequiredBytes),g=c(t?.fit?.fitsInGpu),_=c(t?.fit?.fitsInCpu);r.push(`| ${e} | ${a} | ${o} | ${f} | ${m} | ${h} | ${g} | ${_} |`);let v=t?.memoryLimitedCtx!=null||t?.limitedFit!=null,y=!t?.fit?.fitsInGpu||!t?.fit?.fitsInCpu;if(v&&y){let e=t?.memoryLimitedCtx||o,n=Number(e),i=t?.limitedKvCacheBytes||l&&Number.isFinite(n)&&n>0&&l(n)||null,u=s(i),d=s(t?.modelBytes&&(i!=null||p>0)?t.modelBytes+(i||0)+p:t?.limitedFit?.totalRequiredBytes),g=c(t?.limitedFit?.fitsInGpu),_=c(t?.limitedFit?.fitsInCpu);(e!==o||u!==f||d!==h)&&r.push(`| ↳ Limited | ${a} | ${e} | ${u} | ${m} | ${d} | ${g} | ${_} |`)}}),Jc(r),Yc(r,o[0]?.capabilities),qc(r,t);let l=`ggml-llm-model-capabilities-${new Date().toISOString().replace(/[.:]/g,`-`).split(`T`)[0]}.md`,d=M.join(process.cwd(),l);P.writeFileSync(d,r.join(`
639
- `),`utf8`),console.log(`\nModel capabilities table saved to: ${d}`),process.exit(0)}catch(e){console.error(`Failed to generate model table:`,e.message),process.exit(1)}}async function $c({modelId:e=null,defaultConfig:t=null}={}){console.log(`${$.name} v${$.version}`),console.log(`Testing capabilities for backend: ggml-llm`),e&&console.log(`Model: ${e}`),console.log(`--------------------------------`);try{let{resolveDefaultConfig:n}=i(t,`ggml-llm`),r=n(e);e&&(r={...r||{},model:{...r?.model||{},repo_id:e}});let a=await u(`ggml-llm`,null,{config:r,includeBreakdown:!0}),o=a.buttress?.selected||null,s=a.modelConfig||null;if(e||s?.repoId){console.log(`
640
- === Model Information ===`);let t=e||s?.repoId;if(console.log(`Repository ID: ${t}`),s?.quantization&&console.log(`Quantization: ${s.quantization}`),s?.nCtx&&console.log(`Context Length: ${s.nCtx}`),o?.quantization){let{fileType:e}=o.quantization;e!=null&&console.log(`Model File Type (GGUF): ${e}`)}let n=s?.cache_type_k||`f16`,r=s?.cache_type_v||`f16`;if(console.log(`KV Cache Type: K=${n}, V=${r}`),o?.modelBytes&&o?.kvCacheBytes!=null){console.log(`Model Size: ${(o.modelBytes/1024/1024/1024).toFixed(2)} GB`),o.kvInfo?console.log(`KV Cache Size: ${(o.kvCacheBytes/1024/1024/1024).toFixed(2)} GB (KV info: ${JSON.stringify(o.kvInfo)})`):console.log(`KV Cache Size: ${(o.kvCacheBytes/1024/1024/1024).toFixed(2)} GB`);let e=o.recurrentMemoryBytes||0;e>0&&console.log(`Recurrent Memory: ${(e/1024/1024/1024).toFixed(2)} GB`);let t=o.modelBytes+o.kvCacheBytes+e;if(console.log(`Total Required Memory: ${(t/1024/1024/1024).toFixed(2)} GB`),o.memoryLimitedCtx!=null){let e=o.memoryLimitedCtx,t=o.kvInfo?.nCtxTrain;console.log(t?`\nMemory-Limited Context: ${e} (Train: ${t})`:`\nMemory-Limited Context: ${e}`),o.limitedKvCacheBytes!=null&&console.log(`Limited KV Cache Size: ${(o.limitedKvCacheBytes/1024/1024/1024).toFixed(2)} GB`)}}else if(a.buttress?.selected?.fit){let{totalRequiredBytes:e}=a.buttress.selected.fit;console.log(`Total Required Memory: ${(e/1024/1024/1024).toFixed(2)} GB`)}}a.buttress?.selected&&Xc(a.buttress.selected,{includeLimitedFit:!0}),console.log(`
641
- === Full Capabilities JSON ===`),console.log(JSON.stringify(a,null,2)),process.exit(0)}catch(e){console.error(`Failed to get capabilities:`,e.message),process.exit(1)}}async function el({modelIds:e=[],defaultConfig:t=null}={}){let n=[];console.log(`${$.name} v${$.version}`),console.log(`Generating STT model capabilities comparison...
638
+ `),(!e||e.length===0)&&(console.error(`Error: No model IDs provided`),process.exit(1));try{let{globalDefaults:i,resolveDefaultConfig:a}=qc(t,`ggml-llm`),o=[];for(let t=0;t<e.length;t+=1){let n=e[t];console.log(`[${t+1}/${e.length}] Analyzing ${n}...`);let r=a(n);r={...r||{},model:{...i.runtime||{},...r?.model||{},repo_id:n}};let s=await u(`ggml-llm`,null,{config:r,includeBreakdown:!0});o.push({modelId:n,capabilities:s,modelInfo:s.buttress?.selected||null,modelConfig:s.modelConfig||null})}let s=e=>e?(e/1024/1024/1024).toFixed(2):`N/A`,c=e=>e?`✅`:`🚫`;r.push(`| Model ID | Size (GB) | Context Size | KV Cache Size (GB) | Recurrent Mem (GB) | Total Required Memory (GB) | Fits GPU (Full) | Fits CPU (Full) |`),r.push(`|----------|-----------|--------------|--------------------|--------------------|----------------------------|-----------------|-----------------|`),o.forEach(({modelId:e,modelInfo:t,modelConfig:i})=>{let a=s(t?.modelBytes),o=i?.nCtx||t?.kvInfo?.nCtxTrain||`N/A`,l=t?n(t):null,u=Number(o),d=t?.kvCacheBytes||(l&&Number.isFinite(u)&&u>0?l(u):l&&l(t?.kvInfo?.nCtxTrain||0))||null,f=s(d),p=t?.recurrentMemoryBytes||0,m=p>0?s(p):`-`,h=s(t?.modelBytes&&(d!=null||p>0)?t.modelBytes+(d||0)+p:t?.fit?.totalRequiredBytes),g=c(t?.fit?.fitsInGpu),_=c(t?.fit?.fitsInCpu);r.push(`| ${e} | ${a} | ${o} | ${f} | ${m} | ${h} | ${g} | ${_} |`);let v=t?.memoryLimitedCtx!=null||t?.limitedFit!=null,y=!t?.fit?.fitsInGpu||!t?.fit?.fitsInCpu;if(v&&y){let e=t?.memoryLimitedCtx||o,n=Number(e),i=t?.limitedKvCacheBytes||l&&Number.isFinite(n)&&n>0&&l(n)||null,u=s(i),d=s(t?.modelBytes&&(i!=null||p>0)?t.modelBytes+(i||0)+p:t?.limitedFit?.totalRequiredBytes),g=c(t?.limitedFit?.fitsInGpu),_=c(t?.limitedFit?.fitsInCpu);(e!==o||u!==f||d!==h)&&r.push(`| ↳ Limited | ${a} | ${e} | ${u} | ${m} | ${d} | ${g} | ${_} |`)}}),Yc(r),Xc(r,o[0]?.capabilities),Jc(r,t);let l=`ggml-llm-model-capabilities-${new Date().toISOString().replace(/[.:]/g,`-`).split(`T`)[0]}.md`,d=M.join(process.cwd(),l);P.writeFileSync(d,r.join(`
639
+ `),`utf8`),console.log(`\nModel capabilities table saved to: ${d}`),process.exit(0)}catch(e){console.error(`Failed to generate model table:`,e.message),process.exit(1)}}async function el({modelId:e=null,defaultConfig:t=null}={}){console.log(`${$.name} v${$.version}`),console.log(`Testing capabilities for backend: ggml-llm`),e&&console.log(`Model: ${e}`),console.log(`--------------------------------`);try{let{resolveDefaultConfig:n}=i(t,`ggml-llm`),r=n(e);e&&(r={...r||{},model:{...r?.model||{},repo_id:e}});let a=await u(`ggml-llm`,null,{config:r,includeBreakdown:!0}),o=a.buttress?.selected||null,s=a.modelConfig||null;if(e||s?.repoId){console.log(`
640
+ === Model Information ===`);let t=e||s?.repoId;if(console.log(`Repository ID: ${t}`),s?.quantization&&console.log(`Quantization: ${s.quantization}`),s?.nCtx&&console.log(`Context Length: ${s.nCtx}`),o?.quantization){let{fileType:e}=o.quantization;e!=null&&console.log(`Model File Type (GGUF): ${e}`)}let n=s?.cache_type_k||`f16`,r=s?.cache_type_v||`f16`;if(console.log(`KV Cache Type: K=${n}, V=${r}`),o?.modelBytes&&o?.kvCacheBytes!=null){console.log(`Model Size: ${(o.modelBytes/1024/1024/1024).toFixed(2)} GB`),o.kvInfo?console.log(`KV Cache Size: ${(o.kvCacheBytes/1024/1024/1024).toFixed(2)} GB (KV info: ${JSON.stringify(o.kvInfo)})`):console.log(`KV Cache Size: ${(o.kvCacheBytes/1024/1024/1024).toFixed(2)} GB`);let e=o.recurrentMemoryBytes||0;e>0&&console.log(`Recurrent Memory: ${(e/1024/1024/1024).toFixed(2)} GB`);let t=o.modelBytes+o.kvCacheBytes+e;if(console.log(`Total Required Memory: ${(t/1024/1024/1024).toFixed(2)} GB`),o.memoryLimitedCtx!=null){let e=o.memoryLimitedCtx,t=o.kvInfo?.nCtxTrain;console.log(t?`\nMemory-Limited Context: ${e} (Train: ${t})`:`\nMemory-Limited Context: ${e}`),o.limitedKvCacheBytes!=null&&console.log(`Limited KV Cache Size: ${(o.limitedKvCacheBytes/1024/1024/1024).toFixed(2)} GB`)}}else if(a.buttress?.selected?.fit){let{totalRequiredBytes:e}=a.buttress.selected.fit;console.log(`Total Required Memory: ${(e/1024/1024/1024).toFixed(2)} GB`)}}a.buttress?.selected&&Zc(a.buttress.selected,{includeLimitedFit:!0}),console.log(`
641
+ === Full Capabilities JSON ===`),console.log(JSON.stringify(a,null,2)),process.exit(0)}catch(e){console.error(`Failed to get capabilities:`,e.message),process.exit(1)}}async function tl({modelIds:e=[],defaultConfig:t=null}={}){let n=[];console.log(`${$.name} v${$.version}`),console.log(`Generating STT model capabilities comparison...
642
642
  `),n.push(`${$.name} v${$.version}`),n.push(`## STT Model Capabilities Comparison
643
- `),(!e||e.length===0)&&(console.error(`Error: No model IDs provided`),process.exit(1));try{let{resolveDefaultConfig:r}=i(t,`ggml-stt`),a=[];for(let t=0;t<e.length;t+=1){let n=e[t],{repoId:i,filename:o}=Zc(n);console.log(`[${t+1}/${e.length}] Analyzing ${n}...`);let s=r(i);s={...s||{},model:{...s?.model||{},repo_id:i,...o&&{filename:o}}};let c=await u(`ggml-stt`,null,{config:s,includeBreakdown:!0});a.push({modelId:n,repoId:i,filename:o,capabilities:c,modelInfo:c.buttress?.selected||null,modelConfig:c.modelConfig||null})}let o=e=>e?(e/1024/1024).toFixed(1):`N/A`,s=e=>e?`✅`:`🚫`;n.push(`| Model | Size (MB) | Processing Buffer (MB) | Total Required (MB) | Fits GPU | Fits CPU |`),n.push(`|-------|-----------|------------------------|---------------------|----------|----------|`),a.forEach(({modelId:e,modelInfo:t})=>{let r=o(t?.modelBytes),i=o(t?.processingBytes||t?.kvCacheBytes),a=o(t?.fit?.totalRequiredBytes),c=s(t?.fit?.fitsInGpu),l=s(t?.fit?.fitsInCpu);n.push(`| ${e} | ${r} | ${i} | ${a} | ${c} | ${l} |`)}),Jc(n),Yc(n,a[0]?.capabilities),qc(n,t);let c=`ggml-stt-model-capabilities-${new Date().toISOString().replace(/[.:]/g,`-`).split(`T`)[0]}.md`,l=M.join(process.cwd(),c);P.writeFileSync(l,n.join(`
644
- `),`utf8`),console.log(`\nSTT model capabilities table saved to: ${l}`),process.exit(0)}catch(e){console.error(`Failed to generate STT model table:`,e.message),process.exit(1)}}async function tl({modelIds:e=[],defaultConfig:t=null}={}){let n=[];console.log(`${$.name} v${$.version}`),console.log(`Generating MLX model capabilities comparison...
643
+ `),(!e||e.length===0)&&(console.error(`Error: No model IDs provided`),process.exit(1));try{let{resolveDefaultConfig:r}=i(t,`ggml-stt`),a=[];for(let t=0;t<e.length;t+=1){let n=e[t],{repoId:i,filename:o}=Qc(n);console.log(`[${t+1}/${e.length}] Analyzing ${n}...`);let s=r(i);s={...s||{},model:{...s?.model||{},repo_id:i,...o&&{filename:o}}};let c=await u(`ggml-stt`,null,{config:s,includeBreakdown:!0});a.push({modelId:n,repoId:i,filename:o,capabilities:c,modelInfo:c.buttress?.selected||null,modelConfig:c.modelConfig||null})}let o=e=>e?(e/1024/1024).toFixed(1):`N/A`,s=e=>e?`✅`:`🚫`;n.push(`| Model | Size (MB) | Processing Buffer (MB) | Total Required (MB) | Fits GPU | Fits CPU |`),n.push(`|-------|-----------|------------------------|---------------------|----------|----------|`),a.forEach(({modelId:e,modelInfo:t})=>{let r=o(t?.modelBytes),i=o(t?.processingBytes||t?.kvCacheBytes),a=o(t?.fit?.totalRequiredBytes),c=s(t?.fit?.fitsInGpu),l=s(t?.fit?.fitsInCpu);n.push(`| ${e} | ${r} | ${i} | ${a} | ${c} | ${l} |`)}),Yc(n),Xc(n,a[0]?.capabilities),Jc(n,t);let c=`ggml-stt-model-capabilities-${new Date().toISOString().replace(/[.:]/g,`-`).split(`T`)[0]}.md`,l=M.join(process.cwd(),c);P.writeFileSync(l,n.join(`
644
+ `),`utf8`),console.log(`\nSTT model capabilities table saved to: ${l}`),process.exit(0)}catch(e){console.error(`Failed to generate STT model table:`,e.message),process.exit(1)}}async function nl({modelIds:e=[],defaultConfig:t=null}={}){let n=[];console.log(`${$.name} v${$.version}`),console.log(`Generating MLX model capabilities comparison...
645
645
  `),n.push(`${$.name} v${$.version}`),n.push(`## MLX Model Capabilities Comparison
646
- `),(!e||e.length===0)&&(console.error(`Error: No model IDs provided`),process.exit(1));try{let{resolveDefaultConfig:r}=i(t,`mlx-llm`),a=[];for(let t=0;t<e.length;t+=1){let n=e[t];console.log(`[${t+1}/${e.length}] Analyzing ${n}...`);let i=r(n);i={...i||{},model:{...i?.model||{},repo_id:n}};let o=await u(`mlx-llm`,null,{config:i,includeBreakdown:!0});a.push({modelId:n,capabilities:o,modelInfo:o.buttress?.selected||null,modelConfig:o.modelConfig||null})}let o=e=>e?(e/1024/1024/1024).toFixed(2):`N/A`,s=e=>e?`✅`:`🚫`;if(n.push(`| Model ID | Quant | Size (GB) | Context | KV Cache (GB) | Total Required (GB) | Fits Unified Memory |`),n.push(`|----------|-------|-----------|---------|---------------|---------------------|---------------------|`),a.forEach(({modelId:e,modelInfo:t,modelConfig:r})=>{let i=t?.quantization?.bits||r?.quantBits||`N/A`,a=typeof i==`number`?`${i}bit`:i,c=o(t?.modelBytes),l=r?.nCtx||t?.kvInfo?.nCtxTrain||`N/A`,u=o(t?.kvCacheBytes),d=o(t?.fit?.totalRequiredBytes),f=s(t?.fit?.fitsInGpu);n.push(`| ${e} | ${a} | ${c} | ${l} | ${u} | ${d} | ${f} |`);let p=t?.limitedFit!=null&&t?.memoryLimitedCtx!=null,m=!t?.fit?.fitsInGpu;if(p&&m){let e=t.memoryLimitedCtx,r=o(t.limitedKvCacheBytes),i=o(t.limitedFit.totalRequiredBytes),l=s(t.limitedFit.fitsInGpu);n.push(`| ↳ Limited | ${a} | ${c} | ${e} | ${r} | ${i} | ${l} |`)}}),Jc(n,{includeArchitecture:!0}),a.length>0){let e=a[0].capabilities.buttress?.selected;e&&(n.push(`- **Unified Memory (Usable):** ${(e.gpuUsableBytes/1024/1024/1024).toFixed(2)} GB (${(e.gpuUsableBytes/e.gpuTotalBytes*100).toFixed(0)}% of ${(e.gpuTotalBytes/1024/1024/1024).toFixed(2)} GB)`),e.devices?.length>0&&n.push(`- **Metal Device:** ${e.devices[0].deviceName}`),n.push(`- **Performance Score:** ${e.score}`))}if(a.length>0){let e=a[0].capabilities;n.push(`- **Python3:** ${e.python?.available?`Available`:`Not found`}`),n.push(`- **MLX (system):** ${e.mlx?.systemAvailable?`Available`:`Not installed (will use venv)`}`)}qc(n,t);let c=`mlx-llm-model-capabilities-${new Date().toISOString().replace(/[.:]/g,`-`).split(`T`)[0]}.md`,l=M.join(process.cwd(),c);P.writeFileSync(l,n.join(`
647
- `),`utf8`),console.log(`\nMLX model capabilities table saved to: ${l}`),process.exit(0)}catch(e){console.error(`Failed to generate MLX model table:`,e.message),process.exit(1)}}async function nl({modelId:e=null,defaultConfig:t=null}={}){console.log(`${$.name} v${$.version}`),console.log(`Testing capabilities for backend: mlx-llm`),e&&console.log(`Model: ${e}`),console.log(`--------------------------------`);try{let{server:n,generators:r=[],...i}=t||{},a=Object.keys(i).length>0?{...i}:null;e&&(a={...a||{},model:{...a?.model||{},repo_id:e}});let o=await u(`mlx-llm`,null,{config:a,includeBreakdown:!0});console.log(`
646
+ `),(!e||e.length===0)&&(console.error(`Error: No model IDs provided`),process.exit(1));try{let{resolveDefaultConfig:r}=i(t,`mlx-llm`),a=[];for(let t=0;t<e.length;t+=1){let n=e[t];console.log(`[${t+1}/${e.length}] Analyzing ${n}...`);let i=r(n);i={...i||{},model:{...i?.model||{},repo_id:n}};let o=await u(`mlx-llm`,null,{config:i,includeBreakdown:!0});a.push({modelId:n,capabilities:o,modelInfo:o.buttress?.selected||null,modelConfig:o.modelConfig||null})}let o=e=>e?(e/1024/1024/1024).toFixed(2):`N/A`,s=e=>e?`✅`:`🚫`;if(n.push(`| Model ID | Quant | Size (GB) | Context | KV Cache (GB) | Total Required (GB) | Fits Unified Memory |`),n.push(`|----------|-------|-----------|---------|---------------|---------------------|---------------------|`),a.forEach(({modelId:e,modelInfo:t,modelConfig:r})=>{let i=t?.quantization?.bits||r?.quantBits||`N/A`,a=typeof i==`number`?`${i}bit`:i,c=o(t?.modelBytes),l=r?.nCtx||t?.kvInfo?.nCtxTrain||`N/A`,u=o(t?.kvCacheBytes),d=o(t?.fit?.totalRequiredBytes),f=s(t?.fit?.fitsInGpu);n.push(`| ${e} | ${a} | ${c} | ${l} | ${u} | ${d} | ${f} |`);let p=t?.limitedFit!=null&&t?.memoryLimitedCtx!=null,m=!t?.fit?.fitsInGpu;if(p&&m){let e=t.memoryLimitedCtx,r=o(t.limitedKvCacheBytes),i=o(t.limitedFit.totalRequiredBytes),l=s(t.limitedFit.fitsInGpu);n.push(`| ↳ Limited | ${a} | ${c} | ${e} | ${r} | ${i} | ${l} |`)}}),Yc(n,{includeArchitecture:!0}),a.length>0){let e=a[0].capabilities.buttress?.selected;e&&(n.push(`- **Unified Memory (Usable):** ${(e.gpuUsableBytes/1024/1024/1024).toFixed(2)} GB (${(e.gpuUsableBytes/e.gpuTotalBytes*100).toFixed(0)}% of ${(e.gpuTotalBytes/1024/1024/1024).toFixed(2)} GB)`),e.devices?.length>0&&n.push(`- **Metal Device:** ${e.devices[0].deviceName}`),n.push(`- **Performance Score:** ${e.score}`))}if(a.length>0){let e=a[0].capabilities;n.push(`- **Python3:** ${e.python?.available?`Available`:`Not found`}`),n.push(`- **MLX (system):** ${e.mlx?.systemAvailable?`Available`:`Not installed (will use venv)`}`)}Jc(n,t);let c=`mlx-llm-model-capabilities-${new Date().toISOString().replace(/[.:]/g,`-`).split(`T`)[0]}.md`,l=M.join(process.cwd(),c);P.writeFileSync(l,n.join(`
647
+ `),`utf8`),console.log(`\nMLX model capabilities table saved to: ${l}`),process.exit(0)}catch(e){console.error(`Failed to generate MLX model table:`,e.message),process.exit(1)}}async function rl({modelId:e=null,defaultConfig:t=null}={}){console.log(`${$.name} v${$.version}`),console.log(`Testing capabilities for backend: mlx-llm`),e&&console.log(`Model: ${e}`),console.log(`--------------------------------`);try{let{server:n,generators:r=[],...i}=t||{},a=Object.keys(i).length>0?{...i}:null;e&&(a={...a||{},model:{...a?.model||{},repo_id:e}});let o=await u(`mlx-llm`,null,{config:a,includeBreakdown:!0});console.log(`
648
648
  === Platform Information ===`),console.log(`Available: ${o.available?`Yes`:`No`}`),console.log(`OS: ${o.platform.os} (${o.platform.arch})`),o.platform.errors?.length>0&&console.log(`Errors: ${o.platform.errors.join(`; `)}`),console.log(`Python3: ${o.python.available?`Available`:`Not found`}`),console.log(`MLX (system): ${o.mlx.systemAvailable?`Available`:`Not installed (will use venv)`}`);let s=o.buttress?.selected,c=o.modelConfig;if(e||c?.repoId){console.log(`
649
649
  === Model Information ===`);let t=e||c?.repoId;if(console.log(`Repository ID: ${t}`),c?.architecture&&console.log(`Architecture: ${c.architecture}`),c?.quantBits&&console.log(`Quantization: ${c.quantBits}bit (group_size=${c.quantGroupSize||`N/A`})`),c?.nCtx&&console.log(`Max Context Length: ${c.nCtx}`),s?.modelBytes&&console.log(`Model Size: ${(s.modelBytes/1024/1024/1024).toFixed(2)} GB`),s?.kvCacheBytes!=null&&console.log(`KV Cache Size (full context): ${(s.kvCacheBytes/1024/1024/1024).toFixed(2)} GB`),s?.kvInfo&&console.log(`KV Info: ${s.kvInfo.nLayer} layers, ${s.kvInfo.nHeadKv} KV heads, ${s.kvInfo.headDim} head dim`),s?.modelBytes&&s?.kvCacheBytes!=null){let e=s.modelBytes+s.kvCacheBytes;console.log(`Total Required Memory: ${(e/1024/1024/1024).toFixed(2)} GB`)}s?.memoryLimitedCtx!=null&&(console.log(`\nMemory-Limited Context: ${s.memoryLimitedCtx}`),s.limitedKvCacheBytes!=null&&console.log(`Limited KV Cache Size: ${(s.limitedKvCacheBytes/1024/1024/1024).toFixed(2)} GB`))}if(o.buttress?.selected){let{selected:e}=o.buttress;console.log(`
650
650
  === Hardware Information ===`);let t=null;if(process.platform!==`win32`)try{t=pe(`uname -a`,{encoding:`utf8`}).trim()}catch{}t?console.log(`System: ${t}`):(console.log(`Hostname: ${N.hostname()}`),console.log(`OS: ${N.type()} ${N.release()}`)),console.log(`Platform: ${e.platform}`),console.log(`CPU Cores: ${N.cpus().length}`),console.log(`Total System Memory: ${(N.totalmem()/1024/1024/1024).toFixed(2)} GB`),console.log(`
651
651
  --- Unified Memory (Metal) ---`),e.devices?.length>0&&console.log(`Device: ${e.devices[0].deviceName}`),console.log(`Total Memory: ${(e.gpuTotalBytes/1024/1024/1024).toFixed(2)} GB`);let n=e.gpuTotalBytes>0?(e.gpuUsableBytes/e.gpuTotalBytes*100).toFixed(0):0;console.log(`Usable Memory: ${(e.gpuUsableBytes/1024/1024/1024).toFixed(2)} GB (${n}%)`),console.log(`Performance Score: ${e.score}`),e.fit&&(console.log(`
652
652
  --- Model Fit Analysis ---`),console.log(`Fits in Unified Memory: ${e.fit.fitsInGpu?`Yes`:`No`}`),console.log(`Limiting Factor: ${e.fit.limiting}`),console.log(`Total Required: ${(e.fit.totalRequiredBytes/1024/1024/1024).toFixed(2)} GB`),e.limitedFit&&(console.log(`
653
653
  --- Memory-Limited Fit Analysis ---`),console.log(`Limited Total Required: ${(e.limitedFit.totalRequiredBytes/1024/1024/1024).toFixed(2)} GB`),console.log(`Fits (Limited): ${e.limitedFit.fitsInGpu?`Yes`:`No`}`),console.log(`Limiting Factor (Limited): ${e.limitedFit.limiting}`)))}console.log(`
654
- === Full Capabilities JSON ===`),console.log(JSON.stringify(o,null,2)),process.exit(0)}catch(e){console.error(`Failed to get capabilities:`,e.message),process.exit(1)}}async function rl({modelId:e=null,defaultConfig:t=null}={}){console.log(`${$.name} v${$.version}`),console.log(`Testing capabilities for backend: ggml-stt`),e&&console.log(`Model: ${e}`),console.log(`--------------------------------`);try{let{repoId:n,filename:r}=Zc(e),{globalDefaults:i,resolveDefaultConfig:a}=Kc(t,`ggml-stt`),o=a(n);n&&(o={...o||{},model:{...i.runtime||{},...o?.model||{},repo_id:n,...r&&{filename:r}}});let s=await u(`ggml-stt`,null,{config:o,includeBreakdown:!0}),c=s.buttress?.selected||null,l=s.modelConfig||null;if(n||l?.repoId){console.log(`
655
- === Model Information ===`);let e=n||l?.repoId;console.log(`Repository ID: ${e}`),r&&console.log(`Filename: ${r}`),c?.modelBytes&&console.log(`Model Size: ${(c.modelBytes/1024/1024).toFixed(1)} MB`);let t=c?.processingBytes||c?.kvCacheBytes;if(t&&console.log(`Processing Buffer: ${(t/1024/1024).toFixed(1)} MB`),c?.modelBytes&&t)console.log(`Total Required Memory: ${((c.modelBytes+t)/1024/1024).toFixed(1)} MB`);else if(s.buttress?.selected?.fit){let{totalRequiredBytes:e}=s.buttress.selected.fit;console.log(`Total Required Memory: ${(e/1024/1024).toFixed(1)} MB`)}}s.buttress?.selected&&Xc(s.buttress.selected),console.log(`
656
- === Full Capabilities JSON ===`),console.log(JSON.stringify(s,null,2)),process.exit(0)}catch(e){console.error(`Failed to get capabilities:`,e.message),process.exit(1)}}const il=async({message:e,defaultValue:t,autoYes:n})=>{if(n)return!0;(!process.stdin.isTTY||!process.stdout.isTTY)&&(console.error(`Refusing to prompt in a non-interactive shell. Pass -y/--yes to confirm.`),process.exit(1));let r=Ke.createInterface({input:process.stdin,output:process.stdout});try{let n=t?`[Y/n]`:`[y/N]`,i=(await r.question(`${e} ${n} `)).trim().toLowerCase();return i?i===`y`||i===`yes`:t}catch{return!1}finally{r.close()}},al=async t=>{(t.includes(`--help`)||t.includes(`-h`))&&(console.log(`
654
+ === Full Capabilities JSON ===`),console.log(JSON.stringify(o,null,2)),process.exit(0)}catch(e){console.error(`Failed to get capabilities:`,e.message),process.exit(1)}}async function il({modelId:e=null,defaultConfig:t=null}={}){console.log(`${$.name} v${$.version}`),console.log(`Testing capabilities for backend: ggml-stt`),e&&console.log(`Model: ${e}`),console.log(`--------------------------------`);try{let{repoId:n,filename:r}=Qc(e),{globalDefaults:i,resolveDefaultConfig:a}=qc(t,`ggml-stt`),o=a(n);n&&(o={...o||{},model:{...i.runtime||{},...o?.model||{},repo_id:n,...r&&{filename:r}}});let s=await u(`ggml-stt`,null,{config:o,includeBreakdown:!0}),c=s.buttress?.selected||null,l=s.modelConfig||null;if(n||l?.repoId){console.log(`
655
+ === Model Information ===`);let e=n||l?.repoId;console.log(`Repository ID: ${e}`),r&&console.log(`Filename: ${r}`),c?.modelBytes&&console.log(`Model Size: ${(c.modelBytes/1024/1024).toFixed(1)} MB`);let t=c?.processingBytes||c?.kvCacheBytes;if(t&&console.log(`Processing Buffer: ${(t/1024/1024).toFixed(1)} MB`),c?.modelBytes&&t)console.log(`Total Required Memory: ${((c.modelBytes+t)/1024/1024).toFixed(1)} MB`);else if(s.buttress?.selected?.fit){let{totalRequiredBytes:e}=s.buttress.selected.fit;console.log(`Total Required Memory: ${(e/1024/1024).toFixed(1)} MB`)}}s.buttress?.selected&&Zc(s.buttress.selected),console.log(`
656
+ === Full Capabilities JSON ===`),console.log(JSON.stringify(s,null,2)),process.exit(0)}catch(e){console.error(`Failed to get capabilities:`,e.message),process.exit(1)}}const al=async({message:e,defaultValue:t,autoYes:n})=>{if(n)return!0;(!process.stdin.isTTY||!process.stdout.isTTY)&&(console.error(`Refusing to prompt in a non-interactive shell. Pass -y/--yes to confirm.`),process.exit(1));let r=Ke.createInterface({input:process.stdin,output:process.stdout});try{let n=t?`[Y/n]`:`[y/N]`,i=(await r.question(`${e} ${n} `)).trim().toLowerCase();return i?i===`y`||i===`yes`:t}catch{return!1}finally{r.close()}},ol=async t=>{(t.includes(`--help`)||t.includes(`-h`))&&(console.log(`
657
657
  bricks-buttress update
658
658
 
659
659
  Update bricks-buttress to the latest version. Standalone binary installs
@@ -673,10 +673,10 @@ Options:
673
673
  (default|cuda|vulkan|snapdragon|all; default: auto-detect)
674
674
  `),process.exit(0));let n=t.includes(`--yes`)||t.includes(`-y`),r=t.includes(`--check`),i=t.findIndex(e=>e===`--channel`),a=i>=0?t[i+1]:null;a&&a!==`release`&&a!==`beta`&&(console.error(`Invalid --channel: ${a} (expected release or beta)`),process.exit(1));let o=t.findIndex(e=>e===`--ggml-variant`),s=o>=0?t[o+1]:void 0,c=e().version,l=qa(),u=a||Ka({version:c});console.log(r?`bricks-buttress update check`:`bricks-buttress update`),console.log(`-`.repeat(60)),console.log(`Current version : ${c}`),console.log(`Channel : ${u}`),console.log(`Detected method : ${l.method}`),l.execPath&&l.method===`binary`&&console.log(`Binary path : ${l.execPath}`),l.installRoot&&console.log(`Install root : ${l.installRoot}`);let d=l.method===`npm`||l.method===`bun`?`npm`:`cdn`,f=null,p=null;try{f=(await Za(u,l.method)).version,console.log(`Latest ${u} (${d}): ${f}`)}catch(e){p=e,console.error(`Could not fetch version info: ${p.message}`)}let m=f!=null&&!Ga(c,f);r&&(p&&process.exit(2),m&&(console.log(`
675
675
  Up to date.`),process.exit(0)),console.log(`\nUpdate available: ${c} -> ${f}. Run 'bricks-buttress update' to install.`),process.exit(1)),m&&(console.log(`
676
- Already running the latest version.`),await il({message:`Reinstall anyway?`,defaultValue:!1,autoYes:n})||(console.log(`Skipped.`),process.exit(0)));let h=[`npm`,`bun`,`binary`].includes(l.method);h||console.log(`Cannot auto-detect installer (method: ${l.method}); falling back to binary install.`);let g=h?l.method:`binary`;await il({message:`Update using "${g}" method?`,defaultValue:!0,autoYes:n})||(console.log(`Cancelled.`),process.exit(0));let _=async e=>{console.log(`\n-> Running ${e} update...`);try{return await ro(e,u,l,{ggmlVariant:s}),!0}catch(t){return console.error(`\n${e} update failed: ${t.message}`),!1}},v=await _(g),y=g;!v&&g!==`binary`&&await il({message:`Try the binary installer as a fallback?`,defaultValue:!0,autoYes:n})&&(y=`binary`,v=await _(`binary`)),v||(console.error(`
676
+ Already running the latest version.`),await al({message:`Reinstall anyway?`,defaultValue:!1,autoYes:n})||(console.log(`Skipped.`),process.exit(0)));let h=[`npm`,`bun`,`binary`].includes(l.method);h||console.log(`Cannot auto-detect installer (method: ${l.method}); falling back to binary install.`);let g=h?l.method:`binary`;await al({message:`Update using "${g}" method?`,defaultValue:!0,autoYes:n})||(console.log(`Cancelled.`),process.exit(0));let _=async e=>{console.log(`\n-> Running ${e} update...`);try{return await ro(e,u,l,{ggmlVariant:s}),!0}catch(t){return console.error(`\n${e} update failed: ${t.message}`),!1}},v=await _(g),y=g;!v&&g!==`binary`&&await al({message:`Try the binary installer as a fallback?`,defaultValue:!0,autoYes:n})&&(y=`binary`,v=await _(`binary`)),v||(console.error(`
677
677
  Update failed. See messages above.`),y===`binary`&&console.error(`The previously installed version is still in place.`),process.exit(1)),console.log(`
678
- Update complete.`),process.exit(0)},ol=e();var sl=async()=>{if(process.argv[2]===`update`){await al(process.argv.slice(3));return}if(process.argv[2]===`agent`){let{runAgentCommand:e}=await import(`./cli-KbjOekMI.mjs`);await e(process.argv.slice(3)),process.exit(0)}if(process.argv[2]===`ui`){let{runUiCommand:e}=await import(`./command-EH7igDhV.mjs`);await e(process.argv.slice(3));return}(process.argv.includes(`--version`)||process.argv.includes(`-v`))&&(console.log(ol.version),process.exit(0)),(process.argv.includes(`--help`)||process.argv.includes(`-h`))&&(console.log(`
679
- bricks-buttress v${ol.version}
678
+ Update complete.`),process.exit(0)},sl=e();var cl=async()=>{if(process.argv[2]===`update`){await ol(process.argv.slice(3));return}if(process.argv[2]===`agent`){let{runAgentCommand:e}=await import(`./cli-KbjOekMI.mjs`);await e(process.argv.slice(3)),process.exit(0)}if(process.argv[2]===`ui`){let{runUiCommand:e}=await import(`./command-PAmVAGdx.mjs`);await e(process.argv.slice(3));return}(process.argv.includes(`--version`)||process.argv.includes(`-v`))&&(console.log(sl.version),process.exit(0)),(process.argv.includes(`--help`)||process.argv.includes(`-h`))&&(console.log(`
679
+ bricks-buttress v${sl.version}
680
680
 
681
681
  Buttress server for remote inference with GGML backends.
682
682
 
@@ -719,4 +719,4 @@ Examples:
719
719
  bricks-buttress --test-caps ggml-stt --test-caps-model-id BricksDisplay/whisper-ggml:ggml-small.bin
720
720
  bricks-buttress --test-caps mlx-llm --test-models-default
721
721
  `),process.exit(0));let e=process.argv.findIndex(e=>e===`--port`||e===`-p`),n=e>=0?Number(process.argv[e+1]):void 0,r=process.argv.findIndex(e=>e===`--config`||e===`-c`),i=r>=0?process.argv[r+1]:null,s=null,c=process.cwd();if(i){let e;if(i.includes(`
722
- `))e=i;else{let t=M.resolve(i);c=M.dirname(t);try{e=P.readFileSync(t,`utf8`)}catch(e){console.error(`Failed to read Buttress config at ${t}:`,e),process.exit(1)}}try{let t=Le.parse(e);t.env&&typeof t.env==`object`&&(Object.entries(t.env).forEach(([e,t])=>{process.env[e]===void 0&&(process.env[e]=String(t))}),delete t.env),Array.isArray(t.generators)&&(t.generators=t.generators.filter(e=>{if(g(e))return!0;let t=[e.type,e.model?.repo_id].filter(Boolean).join(` `);return console.log(`[Config] Skipping disabled generator: ${t}`),!1})),s=t}catch(e){console.error(`Failed to parse TOML config:`,e),process.exit(1)}}async function l(e){if(!e?.generators||!Array.isArray(e.generators))return;let n=e.generators.filter(e=>{if(!e.model?.download)return!1;let{type:t}=e;return!t||![`ggml-llm`,`ggml-stt`,`ggml-tts`,`ggml-decision`,`mlx-llm`,`onnx-stt`,`onnx-tts`].includes(t)?(console.warn(`[Download] Skipping unknown generator type: ${t}`),!1):!0});if(n.length===0)return;let{server:r,generators:i,...a}=e,s=n.map(e=>{let{type:n}=e,r=e.model?.repo_id||o(n).model.repo_id||``;console.log(`[Download] Starting pre-download for ${n}: ${r}`);let i={...a,backend:e.backend||{},model:e.model||{},runtime:{...a.runtime,...e.runtime||{}}},s=pt.begin({type:n,repoId:r,filename:e.model?.filename});return t(n,i,{onProgress:e=>s.progress(e),onComplete:({repoId:e,alreadyExists:t})=>{t?(console.log(`[Download] Pre-download complete (already exists): ${e}`),s.discard()):(console.log(`[Download] Pre-download complete: ${e}`),s.complete())},onError:e=>{console.error(`[Download] Pre-download failed for ${r}:`,e.message),s.fail(e)}}).then(e=>(e.repoId&&s.setRepoId(e.repoId),e.error?s.fail(e.error):e.started||s.discard(),e))}),c=await Promise.all(s),l=c.filter(e=>e.started).length,u=c.filter(e=>e.alreadyExists).length,d=c.filter(e=>e.alreadyDownloading).length;console.log(`[Download] Pre-download summary: ${l} started, ${u} already exist, ${d} already downloading`)}let u=[`ggml-org/gpt-oss-20b-GGUF`,`ggml-org/gpt-oss-120b-GGUF`,`unsloth/Nemotron-3-Nano-30B-A3B-GGUF`,`unsloth/Qwen3-30B-A3B-Instruct-2507-GGUF`,`unsloth/Qwen3.5-27B-GGUF`,`unsloth/gemma-4-26B-A4B-it-GGUF`,`unsloth/gemma-4-31B-it-GGUF`,`unsloth/GLM-4.7-Flash-GGUF`,`DevQuasar/MiniMaxAI.MiniMax-M2.5-GGUF`,`bartowski/Mistral-Nemo-Instruct-2407-GGUF`,`mistralai/Magistral-Small-2509-GGUF`,`mistralai/Ministral-3-14B-Reasoning-2512-GGUF`,`bartowski/mistralai_Devstral-Small-2-24B-Instruct-2512-GGUF`,`bartowski/mistralai_Devstral-2-123B-Instruct-2512-GGUF`,`ggml-org/gemma-3-12b-it-qat-GGUF`,`ggml-org/gemma-3-27b-it-qat-GGUF`,`unsloth/phi-4-GGUF`],p=[`BricksDisplay/whisper-ggml:ggml-small.bin`,`BricksDisplay/whisper-ggml:ggml-small-q8_0.bin`,`BricksDisplay/whisper-ggml:ggml-medium.bin`,`BricksDisplay/whisper-ggml:ggml-medium-q8_0.bin`,`BricksDisplay/whisper-ggml:ggml-large-v3-turbo.bin`,`BricksDisplay/whisper-ggml:ggml-large-v3-turbo-q8_0.bin`,`BricksDisplay/whisper-ggml:ggml-large-v3.bin`],m=[`mlx-community/Qwen3.5-27B-8bit`,`mlx-community/Qwen3.5-27B-4bit`,`mlx-community/Qwen3.5-35B-A3B-8bit`,`mlx-community/Qwen3.5-35B-A3B-4bit`,`mlx-community/Qwen3-235B-A22B-8bit`,`mlx-community/Qwen3-235B-A22B-4bit`,`mlx-community/GLM-4.7-Flash-8bit`,`mlx-community/GLM-4.7-Flash-4bit`,`mlx-community/MiniMax-M2.5-4bit`,`mlx-community/gpt-oss-120b-4bit`,`mlx-community/gemma-4-26b-a4b-it-8bit`,`mlx-community/gemma-4-26b-a4b-it-4bit`,`mlx-community/gemma-4-31b-it-8bit`,`mlx-community/gemma-4-31b-it-4bit`],h=process.argv.findIndex(e=>e===`--test-caps`);if(h>=0){let e=process.argv[h+1]||`ggml-llm`;e!==`ggml-llm`&&e!==`ggml-stt`&&e!==`mlx-llm`&&(console.error(`Only ggml-llm, ggml-stt, and mlx-llm backends are supported for testing capabilities`),process.exit(1));let t=process.argv.findIndex(e=>e===`--test-models`),n=process.argv.includes(`--test-models-default`);if(e===`mlx-llm`)if(t>=0){let e=process.argv[t+1];e||(console.error(`Error: --test-models requires a comma-separated list of model IDs`),process.exit(1)),await tl({modelIds:e.split(`,`).map(e=>e.trim()),defaultConfig:s})}else if(n)await tl({modelIds:m,defaultConfig:s});else{let e=process.argv.findIndex(e=>e===`--test-caps-model-id`);await nl({modelId:e>=0?process.argv[e+1]:null,defaultConfig:s})}else if(e===`ggml-stt`)if(t>=0){let e=process.argv[t+1];e||(console.error(`Error: --test-models requires a comma-separated list of model IDs`),process.exit(1)),await el({modelIds:e.split(`,`).map(e=>e.trim()),defaultConfig:s})}else if(n)await el({modelIds:p,defaultConfig:s});else{let e=process.argv.findIndex(e=>e===`--test-caps-model-id`);await rl({modelId:e>=0?process.argv[e+1]:null,defaultConfig:s})}else if(t>=0){let e=process.argv[t+1];e||(console.error(`Error: --test-models requires a comma-separated list of model IDs`),process.exit(1)),await Qc({modelIds:e.split(`,`).map(e=>e.trim()),defaultConfig:s})}else if(n)await Qc({modelIds:u,defaultConfig:s});else{let e=process.argv.findIndex(e=>e===`--test-caps-model-id`);await $c({modelId:e>=0?process.argv[e+1]:null,defaultConfig:s})}}let v=d(s);n&&(v.server.port=n),v.server.port||(v.server.port=f);let y=process.env.ENABLE_OPENAI_COMPAT_ENDPOINT===`1`||v.global.openai_compat?.enabled===!0,b=process.env.ENABLE_ANTHROPIC_MESSAGES_ENDPOINT===`1`||v.global.anthropic_messages?.enabled===!0,x=process.env.ENABLE_TYPESAFE_COMPAT_ENDPOINT===`1`||v.global.typesafe_compat?.enabled===!0,S=$r(v.global,{configDir:c}),C;try{C=_(v,{configDir:c})}catch(e){console.error(e?.message||e),process.exit(1)}hl({config:v,enableOpenAICompat:y,enableAnthropicMessages:b,enableTypeSafeCompat:x,functions:S,agents:C}).then(async({app:e,port:t,openaiEnabled:n,anthropicMessagesEnabled:r,typesafeCompatEnabled:i,functions:o,agents:c,autoDiscover:u})=>{let d=a();console.log(`Buttress server listening on port ${t}`),console.log(`--------------------------------`),await fl(),console.log();let f=e.store.workspaceState.workspace;if(f){let t=f.name?`${f.name} (${f.id})`:f.id;console.log(`Workspace: ${t}`),console.log(`- Server ID: ${f.serverId}`),console.log(`- Issuer kid: ${f.kid}`),console.log(`- Bound at: ${f.boundAt}`);let n=e.store.workspaceState.bank;n&&console.log(`- Data Bank: ${n.spacename} @ ${n.endpoint}`)}else console.log(`Workspace: not bound`),console.log(`- State file: ${Oa()}`),console.log("- Run `bricks buttress bind` from a workspace-authed CLI to pair.");console.log();let p={"ggml-llm":`LLM (GGML)`,"ggml-stt":`STT (GGML)`,"ggml-tts":`TTS (GGML)`,"ggml-decision":`Typed Decision (GGML)`,"mlx-llm":`LLM (MLX)`,"onnx-stt":`STT (ONNX)`,"onnx-tts":`TTS (ONNX)`};console.log(`Current supported Generators:`);let m=new Set((v?.generators||[]).map(e=>e.type).filter(Boolean));if(m.size===0)console.log(`- LLM (GGML)`),console.log(`- STT (GGML)`);else for(let e of m)console.log(`- ${p[e]||e}`);if(console.log(),console.log("Please configure `Buttress (Remote Inference)` in the Generator to connect to this server."),console.log(),console.log(`- Use http://${d}:${t} to connect to this server via LAN.`),console.log(`- Visit http://${d}:${t}/status to see status via LAN.`),console.log(),n?(console.log(`OpenAI-compatible API [EXPERIMENTAL]:`),console.log(`- Base URL: http://${d}:${t}/oai-compat/v1`),console.log(`- Chat completions: POST http://${d}:${t}/oai-compat/v1/chat/completions`),console.log(`- Decisions: POST http://${d}:${t}/oai-compat/v1/decisions`),console.log(`- Models: GET http://${d}:${t}/oai-compat/v1/models`),console.log()):(console.log(`OpenAI-compatible API [EXPERIMENTAL]: disabled`),console.log(` Set [openai_compat] enabled = true in config to enable`),console.log()),r?(console.log(`Anthropic Messages API [EXPERIMENTAL]:`),console.log(`- Base URL: http://${d}:${t}/anthropic-messages`),console.log(`- Messages: POST http://${d}:${t}/anthropic-messages/v1/messages`),console.log(`- Count tokens: POST http://${d}:${t}/anthropic-messages/v1/messages/count_tokens`),console.log()):(console.log(`Anthropic Messages API [EXPERIMENTAL]: disabled`),console.log(` Set [anthropic_messages] enabled = true in config to enable`),console.log()),i?(console.log(`TypeSafe-compatible System One API [EXPERIMENTAL]:`),console.log(`- Base URL: http://${d}:${t}/typesafe-compat (TYPESAFE_BASE_URL)`),console.log(`- Decisions: POST http://${d}:${t}/typesafe-compat/v1/systemone`),console.log(`- Models: GET http://${d}:${t}/typesafe-compat/v1/models`),console.log()):(console.log(`TypeSafe-compatible System One API [EXPERIMENTAL]: disabled`),console.log(` Set [typesafe_compat] enabled = true in config to enable`),console.log()),o){let n=await o.list();console.log(`Local Functions [EXPERIMENTAL]:`),console.log(`- Experimental: endpoints and the function contract may change between releases.`),console.log(`- Directory: ${o.dir}`),console.log(`- List: GET http://${d}:${t}/functions`),console.log(`- Call: POST http://${d}:${t}/functions/<name>`),console.log(`- MCP: POST http://${d}:${t}/functions/mcp`),console.log(`- Loaded: ${n.length?n.map(e=>e.name).join(`, `):`(none yet)`}`),o.config.hotReload&&console.log(`- Hot reload: watching the functions directory for changes`);let r=null,i=!1;try{r=await o.getCustomAuth()}catch{i=!0}if(i)console.warn(`- WARNING: the custom auth file (_auth) failed to load. Every call is rejected until it is fixed.`);else if(r){let e=r.mode===`override`?`replaces workspace auth`:`extra gate after workspace auth`;console.log(`- Custom auth: ${M.basename(r.file)} (${r.mode} — ${e})`)}let a=!i&&r?.mode!==`override`;!e.store.workspaceState.workspace&&a&&(o.config.allowUnauthenticated?console.warn(r?`- Unauthenticated access is ON and this server is not bound; the custom auth function is the only gate on these functions.`:`- WARNING: unauthenticated access is ON and this server is not bound to a workspace. Anyone who can reach this port can run these functions.`):console.log("- Calls are rejected until this server is bound (`bricks buttress bind`), or [functions] allow_unauthenticated = true is set.")),console.log()}else console.log(`Local Functions [EXPERIMENTAL]: disabled`),console.log(` Set [functions] enabled = true and dir = "./functions" in config to enable`),console.log();c&&(console.log(`Agents [EXPERIMENTAL]:`),console.log(`- Experimental: config shape and endpoints may change between releases.`),console.log(`- Configured: ${c.list().join(`, `)}`),console.log(`- Run: POST http://${d}:${t}/agents/<name>/run`),console.log(`- Chat: bricks-buttress agent <name> -c <this config>`),console.log(`- Sessions dir: ${c.config.sessionsDir}`),!e.store.workspaceState.workspace&&!c.config.allowUnauthenticated&&console.log(`- Remote calls are rejected until this server is bound; the same-host CLI uses the local runtime token.`),console.log()),u&&(console.log(`Auto-discover enabled`),console.log()),s&&await l(s)}).catch(e=>{console.error(`Failed to start Buttress server:`,e),process.exitCode=1})};const{version:cl,name:ll}=e(),ul=async()=>{let e=`https://registry.npmjs.org/${ll}/latest`;try{let t=new AbortController,n=setTimeout(()=>t.abort(),3e3),r=await fetch(e,{headers:{Accept:`application/json`},signal:t.signal});return clearTimeout(n),r.ok&&(await r.json()).version||null}catch{return null}},dl=e=>{console.log(``),console.log(`\x1B[33m╭─────────────────────────────────────────────────╮\x1B[0m`),console.log(`\x1B[33m│\x1B[0m Update available! \x1B[2m%s\x1B[0m → \x1B[32m%s\x1B[0m`,cl.padEnd(12),e.padEnd(12),`\x1B[33m│\x1B[0m`),console.log(`\x1B[33m│\x1B[0m \x1B[33m│\x1B[0m`),console.log(`\x1B[33m│\x1B[0m Run to upgrade: \x1B[33m│\x1B[0m`),console.log(`\x1B[33m│\x1B[0m \x1B[36m%s\x1B[0m\x1B[33m│\x1B[0m`,`bricks-buttress update`.padEnd(47)),console.log(`\x1B[33m╰─────────────────────────────────────────────────╯\x1B[0m`),console.log(``)},fl=async()=>{try{let e=await ul();e&&Ga(cl,e)&&dl(e)}catch{}},pl=!(`Bun`in globalThis),ml=async({backend:e,router:t,config:n,enableOpenAICompat:i,enableAnthropicMessages:o,enableTypeSafeCompat:u,functions:d,agents:f})=>{let p=Date.now();for(let e of Kt(n))console.warn(`[Decision] ${e} is configured more than once; local functions and the TypeSafe endpoint use the first entry`);for(let e of Pt(n))console.log(`[Decision] ${e}`);try{await O.mkdir(n.server.temp_file_dir,{recursive:!0})}catch{}let m=a()||`0.0.0.0`,h=[...new Set([m,...l().map(e=>e.address)].filter(Boolean))],g=Na(),_=g.workspace!=null,v=e||c,y=await r(x(n,n.generators.map(e=>e.type))),b=null,S=null,C=null;if(f)try{C=Gc({config:n,agentsConfig:f,runtimeBase:{backend:v,config:n,workspaceState:g},getHandle:()=>S,getFunctions:()=>b})}catch(e){console.error(`[Agents] disabled: failed to initialize:`,e?.message||e)}if(d)try{b=await ei(d,{tempFileDir:n.server.temp_file_dir,runtime:{backend:v,config:n,workspaceState:g,...C?{agents:C}:{}}})}catch(e){console.error(`[Functions] disabled: failed to initialize ${d.dir}:`,e?.message||e)}let ee={id:n.server.id,name:n.server.name,version:cl,address:m,addresses:h,port:n.server.port,url:`http://${m}:${n.server.port}`,generators:y,authentication:_?{required:!0,type:`workspace-jwt`,kid:g.workspace.kid,bound:!0}:{required:!1,type:`workspace-jwt`,bound:!1},..._?{workspace:{id:g.workspace.id,name:g.workspace.name}}:{},...b?{functions:b.stats}:{},...C?{agents:{enabled:!0,count:C.list().length}}:{}},w=new te({serve:{maxRequestBodySize:n.server.max_body_size},websocket:{idleTimeout:Math.ceil(n.server.session_timeout/1e3)},adapter:pl?T():void 0}).state({sessions:new Map,backend:v,config:n,serverInfo:ee,workspaceState:g,agentsService:C,functionsService:b,startedAt:p,endpoints:{openaiCompat:!!i,anthropicMessages:!!o,typesafeCompat:!!u},host:s()});S=e=>w.handle(e),t&&w.use(t),Sa(w,xa(n,{openaiCompat:i,anthropicMessages:o,typesafeCompat:u,functions:!!b})),n.autodiscover?.http?.enabled&&w.use(et(n,Xe(g))),w.use(ft),w.use(Et),i&&w.use(pn()),o&&w.use(bn()),u&&w.use(Tn()),b&&w.use(Ci(n,b)),C&&w.use(Mi(C));let ne=(e,t)=>ot(at(e,t),g.workspace),E={INVALID_REQUEST:-32600,INVALID_PARAMS:-32602,METHOD_NOT_FOUND:-32601,INTERNAL_ERROR:-32603},ie=e=>e.id??e.raw?.id??e.remoteAddress??`unknown-peer`,k=new Map,A=new Map;return w.ws(`/buttress/rpc`,{parse:(e,t)=>{if(typeof t==`string`)try{return JSON.parse(t)}catch{return e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_REQUEST,message:`Invalid request`},id:null})),null}return t},body:D.Object({jsonrpc:D.String(),method:D.String(),params:D.String(),id:D.String()}),async open(e){let t=ie(e),n=e.data?.headers,r=e.data?.query,i,a=new Promise(e=>{i=e});if(A.set(t,{identity:null,ready:a}),!_){console.log(`[Request] New connection: ${t} (unbound, no auth)`),i(!0);return}let o=await ne(n||{},r);if(!o){console.warn(`[Auth] Rejecting WS ${t}: invalid or missing workspace-access token`),A.delete(t),i(!1),e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_REQUEST,message:`Unauthorized`},id:null})),e.close(1008,`UNAUTHORIZED`);return}console.log(`[Request] New connection: ${t} (subject=${o.subjectType}:${o.subjectId})`);let s=A.get(t);s&&(s.identity=o),i(!0)},async message(e,{id:t,method:r,params:i}){let{sessions:a}=e.data.store,o=ie(e),s=A.get(o);if(s?.ready&&!await s.ready){e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_REQUEST,message:`Unauthorized`},id:t}));return}let c=A.get(o)?.identity??null;if(_&&!c){e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_REQUEST,message:`Unauthorized`},id:t}));return}if(r===`init`){let[r]=ga(i)??[],s,l=!1,u=r&&a.has(r)?a.get(r):null,d=!u?.identity||!!c&&c.subjectId===u.identity.subjectId&&c.subjectType===u.identity.subjectType;if(u&&d)u.timeout&&=(clearTimeout(u.timeout),null),u.identity=c,u.currentPeerId=o,s=r,l=!0,console.log(`[Request] Session restored: ${s}`);else{u&&console.warn(`[Request] Refused to restore session ${r}: identity mismatch (session=${u.identity?.subjectType}:${u.identity?.subjectId} peer=${c?.subjectType}:${c?.subjectId})`),s=j();let e={streams:new Map,streamReaders:new Map,generators:new Map,initializedContexts:new Set,fileManager:new Ea(s,n.server.temp_file_dir),timeout:null,identity:c,currentPeerId:o};a.set(s,e),console.log(`[Request] New session: ${s}`)}k.set(o,s),e.send(JSON.stringify({jsonrpc:`2.0`,result:_a({sessionId:s,restored:l}),id:t}));return}let l=k.get(o);if(!l){e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_REQUEST,message:`Session not initialized`},id:t}));return}let u=a.get(l);if(!u){k.delete(o),e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_REQUEST,message:`Session not initialized`},id:t}));return}console.log(`[Request] Received request from ${l}: ${r}`);let[d,f]=r.split(`.`),p=pa[d]?.[f];if(!p&&r!==`cancel`&&r!==`ping`){e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.METHOD_NOT_FOUND,message:`Method not found`},id:t}));return}try{if(r===`cancel`){let e=u.streamReaders.get(t);e&&(e.reader.cancel(),u.streamReaders.delete(t));return}if(r===`ping`){e.send(JSON.stringify({jsonrpc:`2.0`,result:`pong`,id:t}));return}let n=ga(i),a=ma[d]?.[f],s=a?a.parse(n):n,c=await p({...e.data.store,peerId:l,session:u},...s);if(c instanceof re){let n=c.getReader();u.streamReaders.set(t,{reader:n,peerId:o}),e.send(JSON.stringify({jsonrpc:`2.0`,result:{type:`stream`},id:t}));try{for(;;){let{value:r,done:i}=await n.read();if(i)break;let{event:a,data:o}=r;e.send(JSON.stringify({jsonrpc:`2.0`,method:`notification/${a}`,params:_a(o),id:t}))}e.send(JSON.stringify({jsonrpc:`2.0`,method:`notification/_end`,id:t}))}catch(n){console.error(`[RPC] Stream error for ${r}:`,n),e.send(JSON.stringify({jsonrpc:`2.0`,method:`notification/_error`,params:_a(n),id:t}))}u.streamReaders.delete(t)}else e.send(JSON.stringify({jsonrpc:`2.0`,result:_a(c),id:t}))}catch(n){if(n instanceof ge){e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_PARAMS,message:`Invalid params`,data:n.issues},id:t}));return}console.error(`[RPC] Handler error for ${r}:`,n),e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INTERNAL_ERROR,message:String(n)},id:t}))}},async close(e){let t=ie(e),r=k.get(t);if(k.delete(t),A.delete(t),!r){console.log(`[Request] Connection closed (no session)`);return}console.log(`[Request] Connection closed: ${r}`);let{backend:i,sessions:a}=e.data.store,o=a.get(r);if(o){for(let[e,n]of o.streamReaders)n.peerId===t&&(n.reader.cancel().catch(()=>{}),o.streamReaders.delete(e));if(o.currentPeerId!==t){console.log(`[Request] Session ${r} already adopted by another peer; skip arm`);return}o.timeout=setTimeout(()=>{if(o.currentPeerId!==t)return;a.delete(r),console.log(`[Request] Session timed out: ${r}`);let{generators:e}=o;e.forEach((e,t)=>{for(let n=0;n<e;n++)i.finalizeGenerator(t)}),o.fileManager.destroy().catch(()=>{})},n.server.session_timeout)}}}),{app:w,config:n,functions:b,agents:C}},hl=async({backend:e,router:t,config:n,enableOpenAICompat:r=!1,enableAnthropicMessages:i=!1,enableTypeSafeCompat:a=!1,functions:o=null,agents:s=null})=>{let{app:c,config:l,functions:u,agents:d}=await ml({backend:e,router:t,config:n,enableOpenAICompat:r,enableAnthropicMessages:i,enableTypeSafeCompat:a,functions:o,agents:s}),{server:{port:f}}=l,p=[new Promise(e=>c.listen(f,e))],m=null;if(l.autodiscover){let{workspace:e,serverKeyPair:t}=c.store.workspaceState;if(e&&t){let e=Xe(c.store.workspaceState);m=new Ta(l.autodiscover,()=>c.store.serverInfo,e),p.push(m.start())}else console.warn(e?"[Autodiscover] disabled: bound to a workspace but state.json is missing serverKeyPair. Re-run `bricks buttress bind` to register a per-server announce key (required for v2.0 signed UDP discovery).":"[Autodiscover] disabled: buttress-server is not bound to a workspace. Run `bricks buttress bind` from a workspace-authed CLI to pair.")}return await Promise.all(p),{app:c,port:f,openaiEnabled:r,anthropicMessagesEnabled:i,typesafeCompatEnabled:a,functions:u,agents:d,autoDiscover:m}},gl=[new URL(`index.mjs`,import.meta.url).pathname,new URL(`index.ts`,import.meta.url).pathname];(process.argv[1]?.endsWith(`/bricks-buttress`)||gl.includes(process.argv[1]))&&await sl();export{fl as checkAndNotifyUpdates,ul as checkForUpdates,Ga as compareVersions,ml as createServer,dl as logUpdateMessage,d as processConfig,_ as resolveAgentsConfig,$r as resolveFunctionsConfig,t as startModelDownload,hl as startServer};
722
+ `))e=i;else{let t=M.resolve(i);c=M.dirname(t);try{e=P.readFileSync(t,`utf8`)}catch(e){console.error(`Failed to read Buttress config at ${t}:`,e),process.exit(1)}}try{let t=Le.parse(e);t.env&&typeof t.env==`object`&&(Object.entries(t.env).forEach(([e,t])=>{process.env[e]===void 0&&(process.env[e]=String(t))}),delete t.env),Array.isArray(t.generators)&&(t.generators=t.generators.filter(e=>{if(g(e))return!0;let t=[e.type,e.model?.repo_id].filter(Boolean).join(` `);return console.log(`[Config] Skipping disabled generator: ${t}`),!1})),s=t}catch(e){console.error(`Failed to parse TOML config:`,e),process.exit(1)}}async function l(e){if(!e?.generators||!Array.isArray(e.generators))return;let n=e.generators.filter(e=>{if(!e.model?.download)return!1;let{type:t}=e;return!t||![`ggml-llm`,`ggml-stt`,`ggml-tts`,`ggml-decision`,`mlx-llm`,`onnx-stt`,`onnx-tts`].includes(t)?(console.warn(`[Download] Skipping unknown generator type: ${t}`),!1):!0});if(n.length===0)return;let{server:r,generators:i,...a}=e,s=n.map(e=>{let{type:n}=e,r=e.model?.repo_id||o(n).model.repo_id||``;console.log(`[Download] Starting pre-download for ${n}: ${r}`);let i={...a,backend:e.backend||{},model:e.model||{},runtime:{...a.runtime,...e.runtime||{}}},s=pt.begin({type:n,repoId:r,filename:e.model?.filename});return t(n,i,{onProgress:e=>s.progress(e),onComplete:({repoId:e,alreadyExists:t})=>{t?(console.log(`[Download] Pre-download complete (already exists): ${e}`),s.discard()):(console.log(`[Download] Pre-download complete: ${e}`),s.complete())},onError:e=>{console.error(`[Download] Pre-download failed for ${r}:`,e.message),s.fail(e)}}).then(e=>(e.repoId&&s.setRepoId(e.repoId),e.error?s.fail(e.error):e.started||s.discard(),e))}),c=await Promise.all(s),l=c.filter(e=>e.started).length,u=c.filter(e=>e.alreadyExists).length,d=c.filter(e=>e.alreadyDownloading).length;console.log(`[Download] Pre-download summary: ${l} started, ${u} already exist, ${d} already downloading`)}let u=[`ggml-org/gpt-oss-20b-GGUF`,`ggml-org/gpt-oss-120b-GGUF`,`unsloth/Nemotron-3-Nano-30B-A3B-GGUF`,`unsloth/Qwen3-30B-A3B-Instruct-2507-GGUF`,`unsloth/Qwen3.5-27B-GGUF`,`unsloth/gemma-4-26B-A4B-it-GGUF`,`unsloth/gemma-4-31B-it-GGUF`,`unsloth/GLM-4.7-Flash-GGUF`,`DevQuasar/MiniMaxAI.MiniMax-M2.5-GGUF`,`bartowski/Mistral-Nemo-Instruct-2407-GGUF`,`mistralai/Magistral-Small-2509-GGUF`,`mistralai/Ministral-3-14B-Reasoning-2512-GGUF`,`bartowski/mistralai_Devstral-Small-2-24B-Instruct-2512-GGUF`,`bartowski/mistralai_Devstral-2-123B-Instruct-2512-GGUF`,`ggml-org/gemma-3-12b-it-qat-GGUF`,`ggml-org/gemma-3-27b-it-qat-GGUF`,`unsloth/phi-4-GGUF`],p=[`BricksDisplay/whisper-ggml:ggml-small.bin`,`BricksDisplay/whisper-ggml:ggml-small-q8_0.bin`,`BricksDisplay/whisper-ggml:ggml-medium.bin`,`BricksDisplay/whisper-ggml:ggml-medium-q8_0.bin`,`BricksDisplay/whisper-ggml:ggml-large-v3-turbo.bin`,`BricksDisplay/whisper-ggml:ggml-large-v3-turbo-q8_0.bin`,`BricksDisplay/whisper-ggml:ggml-large-v3.bin`],m=[`mlx-community/Qwen3.5-27B-8bit`,`mlx-community/Qwen3.5-27B-4bit`,`mlx-community/Qwen3.5-35B-A3B-8bit`,`mlx-community/Qwen3.5-35B-A3B-4bit`,`mlx-community/Qwen3-235B-A22B-8bit`,`mlx-community/Qwen3-235B-A22B-4bit`,`mlx-community/GLM-4.7-Flash-8bit`,`mlx-community/GLM-4.7-Flash-4bit`,`mlx-community/MiniMax-M2.5-4bit`,`mlx-community/gpt-oss-120b-4bit`,`mlx-community/gemma-4-26b-a4b-it-8bit`,`mlx-community/gemma-4-26b-a4b-it-4bit`,`mlx-community/gemma-4-31b-it-8bit`,`mlx-community/gemma-4-31b-it-4bit`],h=process.argv.findIndex(e=>e===`--test-caps`);if(h>=0){let e=process.argv[h+1]||`ggml-llm`;e!==`ggml-llm`&&e!==`ggml-stt`&&e!==`mlx-llm`&&(console.error(`Only ggml-llm, ggml-stt, and mlx-llm backends are supported for testing capabilities`),process.exit(1));let t=process.argv.findIndex(e=>e===`--test-models`),n=process.argv.includes(`--test-models-default`);if(e===`mlx-llm`)if(t>=0){let e=process.argv[t+1];e||(console.error(`Error: --test-models requires a comma-separated list of model IDs`),process.exit(1)),await nl({modelIds:e.split(`,`).map(e=>e.trim()),defaultConfig:s})}else if(n)await nl({modelIds:m,defaultConfig:s});else{let e=process.argv.findIndex(e=>e===`--test-caps-model-id`);await rl({modelId:e>=0?process.argv[e+1]:null,defaultConfig:s})}else if(e===`ggml-stt`)if(t>=0){let e=process.argv[t+1];e||(console.error(`Error: --test-models requires a comma-separated list of model IDs`),process.exit(1)),await tl({modelIds:e.split(`,`).map(e=>e.trim()),defaultConfig:s})}else if(n)await tl({modelIds:p,defaultConfig:s});else{let e=process.argv.findIndex(e=>e===`--test-caps-model-id`);await il({modelId:e>=0?process.argv[e+1]:null,defaultConfig:s})}else if(t>=0){let e=process.argv[t+1];e||(console.error(`Error: --test-models requires a comma-separated list of model IDs`),process.exit(1)),await $c({modelIds:e.split(`,`).map(e=>e.trim()),defaultConfig:s})}else if(n)await $c({modelIds:u,defaultConfig:s});else{let e=process.argv.findIndex(e=>e===`--test-caps-model-id`);await el({modelId:e>=0?process.argv[e+1]:null,defaultConfig:s})}}let v=d(s);n&&(v.server.port=n),v.server.port||(v.server.port=f);let y=process.env.ENABLE_OPENAI_COMPAT_ENDPOINT===`1`||v.global.openai_compat?.enabled===!0,b=process.env.ENABLE_ANTHROPIC_MESSAGES_ENDPOINT===`1`||v.global.anthropic_messages?.enabled===!0,x=process.env.ENABLE_TYPESAFE_COMPAT_ENDPOINT===`1`||v.global.typesafe_compat?.enabled===!0,S=$r(v.global,{configDir:c}),C;try{C=_(v,{configDir:c})}catch(e){console.error(e?.message||e),process.exit(1)}gl({config:v,enableOpenAICompat:y,enableAnthropicMessages:b,enableTypeSafeCompat:x,functions:S,agents:C}).then(async({app:e,port:t,openaiEnabled:n,anthropicMessagesEnabled:r,typesafeCompatEnabled:i,functions:o,agents:c,autoDiscover:u})=>{let d=a();console.log(`Buttress server listening on port ${t}`),console.log(`--------------------------------`),await pl(),console.log();let f=e.store.workspaceState.workspace;if(f){let t=f.name?`${f.name} (${f.id})`:f.id;console.log(`Workspace: ${t}`),console.log(`- Server ID: ${f.serverId}`),console.log(`- Issuer kid: ${f.kid}`),console.log(`- Bound at: ${f.boundAt}`);let n=e.store.workspaceState.bank;n&&console.log(`- Data Bank: ${n.spacename} @ ${n.endpoint}`)}else console.log(`Workspace: not bound`),console.log(`- State file: ${Oa()}`),console.log("- Run `bricks buttress bind` from a workspace-authed CLI to pair.");console.log();let p={"ggml-llm":`LLM (GGML)`,"ggml-stt":`STT (GGML)`,"ggml-tts":`TTS (GGML)`,"ggml-decision":`Typed Decision (GGML)`,"mlx-llm":`LLM (MLX)`,"onnx-stt":`STT (ONNX)`,"onnx-tts":`TTS (ONNX)`};console.log(`Current supported Generators:`);let m=new Set((v?.generators||[]).map(e=>e.type).filter(Boolean));if(m.size===0)console.log(`- LLM (GGML)`),console.log(`- STT (GGML)`);else for(let e of m)console.log(`- ${p[e]||e}`);if(console.log(),console.log("Please configure `Buttress (Remote Inference)` in the Generator to connect to this server."),console.log(),console.log(`- Use http://${d}:${t} to connect to this server via LAN.`),console.log(`- Visit http://${d}:${t}/status to see status via LAN.`),console.log(),n?(console.log(`OpenAI-compatible API [EXPERIMENTAL]:`),console.log(`- Base URL: http://${d}:${t}/oai-compat/v1`),console.log(`- Chat completions: POST http://${d}:${t}/oai-compat/v1/chat/completions`),console.log(`- Decisions: POST http://${d}:${t}/oai-compat/v1/decisions`),console.log(`- Models: GET http://${d}:${t}/oai-compat/v1/models`),console.log()):(console.log(`OpenAI-compatible API [EXPERIMENTAL]: disabled`),console.log(` Set [openai_compat] enabled = true in config to enable`),console.log()),r?(console.log(`Anthropic Messages API [EXPERIMENTAL]:`),console.log(`- Base URL: http://${d}:${t}/anthropic-messages`),console.log(`- Messages: POST http://${d}:${t}/anthropic-messages/v1/messages`),console.log(`- Count tokens: POST http://${d}:${t}/anthropic-messages/v1/messages/count_tokens`),console.log()):(console.log(`Anthropic Messages API [EXPERIMENTAL]: disabled`),console.log(` Set [anthropic_messages] enabled = true in config to enable`),console.log()),i?(console.log(`TypeSafe-compatible System One API [EXPERIMENTAL]:`),console.log(`- Base URL: http://${d}:${t}/typesafe-compat (TYPESAFE_BASE_URL)`),console.log(`- Decisions: POST http://${d}:${t}/typesafe-compat/v1/systemone`),console.log(`- Models: GET http://${d}:${t}/typesafe-compat/v1/models`),console.log()):(console.log(`TypeSafe-compatible System One API [EXPERIMENTAL]: disabled`),console.log(` Set [typesafe_compat] enabled = true in config to enable`),console.log()),o){let n=await o.list();console.log(`Local Functions [EXPERIMENTAL]:`),console.log(`- Experimental: endpoints and the function contract may change between releases.`),console.log(`- Directory: ${o.dir}`),console.log(`- List: GET http://${d}:${t}/functions`),console.log(`- Call: POST http://${d}:${t}/functions/<name>`),console.log(`- MCP: POST http://${d}:${t}/functions/mcp`),console.log(`- Loaded: ${n.length?n.map(e=>e.name).join(`, `):`(none yet)`}`),o.config.hotReload&&console.log(`- Hot reload: watching the functions directory for changes`);let r=null,i=!1;try{r=await o.getCustomAuth()}catch{i=!0}if(i)console.warn(`- WARNING: the custom auth file (_auth) failed to load. Every call is rejected until it is fixed.`);else if(r){let e=r.mode===`override`?`replaces workspace auth`:`extra gate after workspace auth`;console.log(`- Custom auth: ${M.basename(r.file)} (${r.mode} — ${e})`)}let a=!i&&r?.mode!==`override`;!e.store.workspaceState.workspace&&a&&(o.config.allowUnauthenticated?console.warn(r?`- Unauthenticated access is ON and this server is not bound; the custom auth function is the only gate on these functions.`:`- WARNING: unauthenticated access is ON and this server is not bound to a workspace. Anyone who can reach this port can run these functions.`):console.log("- Calls are rejected until this server is bound (`bricks buttress bind`), or [functions] allow_unauthenticated = true is set.")),console.log()}else console.log(`Local Functions [EXPERIMENTAL]: disabled`),console.log(` Set [functions] enabled = true and dir = "./functions" in config to enable`),console.log();c&&(console.log(`Agents [EXPERIMENTAL]:`),console.log(`- Experimental: config shape and endpoints may change between releases.`),console.log(`- Configured: ${c.list().join(`, `)}`),console.log(`- Run: POST http://${d}:${t}/agents/<name>/run`),console.log(`- Chat: bricks-buttress agent <name> -c <this config>`),console.log(`- Sessions dir: ${c.config.sessionsDir}`),!e.store.workspaceState.workspace&&!c.config.allowUnauthenticated&&console.log(`- Remote calls are rejected until this server is bound; the same-host CLI uses the local runtime token.`),console.log()),u&&(console.log(`Auto-discover enabled`),console.log()),s&&await l(s)}).catch(e=>{console.error(`Failed to start Buttress server:`,e),process.exitCode=1})};const{version:ll,name:ul}=e(),dl=async()=>{let e=`https://registry.npmjs.org/${ul}/latest`;try{let t=new AbortController,n=setTimeout(()=>t.abort(),3e3),r=await fetch(e,{headers:{Accept:`application/json`},signal:t.signal});return clearTimeout(n),r.ok&&(await r.json()).version||null}catch{return null}},fl=e=>{console.log(``),console.log(`\x1B[33m╭─────────────────────────────────────────────────╮\x1B[0m`),console.log(`\x1B[33m│\x1B[0m Update available! \x1B[2m%s\x1B[0m → \x1B[32m%s\x1B[0m`,ll.padEnd(12),e.padEnd(12),`\x1B[33m│\x1B[0m`),console.log(`\x1B[33m│\x1B[0m \x1B[33m│\x1B[0m`),console.log(`\x1B[33m│\x1B[0m Run to upgrade: \x1B[33m│\x1B[0m`),console.log(`\x1B[33m│\x1B[0m \x1B[36m%s\x1B[0m\x1B[33m│\x1B[0m`,`bricks-buttress update`.padEnd(47)),console.log(`\x1B[33m╰─────────────────────────────────────────────────╯\x1B[0m`),console.log(``)},pl=async()=>{try{let e=await dl();e&&Ga(ll,e)&&fl(e)}catch{}},ml=!(`Bun`in globalThis),hl=async({backend:e,router:t,config:n,enableOpenAICompat:i,enableAnthropicMessages:o,enableTypeSafeCompat:u,functions:d,agents:f})=>{let p=Date.now();for(let e of Kt(n))console.warn(`[Decision] ${e} is configured more than once; local functions and the TypeSafe endpoint use the first entry`);for(let e of Pt(n))console.log(`[Decision] ${e}`);try{await O.mkdir(n.server.temp_file_dir,{recursive:!0})}catch{}let m=a()||`0.0.0.0`,h=[...new Set([m,...l().map(e=>e.address)].filter(Boolean))],g=Na(),_=g.workspace!=null,v=e||c,y=await r(x(n,n.generators.map(e=>e.type))),b=null,S=null,C=null;if(f)try{C=Kc({config:n,agentsConfig:f,runtimeBase:{backend:v,config:n,workspaceState:g},getHandle:()=>S,getFunctions:()=>b})}catch(e){console.error(`[Agents] disabled: failed to initialize:`,e?.message||e)}if(d)try{b=await ei(d,{tempFileDir:n.server.temp_file_dir,runtime:{backend:v,config:n,workspaceState:g,...C?{agents:C}:{}}})}catch(e){console.error(`[Functions] disabled: failed to initialize ${d.dir}:`,e?.message||e)}let ee={id:n.server.id,name:n.server.name,version:ll,address:m,addresses:h,port:n.server.port,url:`http://${m}:${n.server.port}`,generators:y,authentication:_?{required:!0,type:`workspace-jwt`,kid:g.workspace.kid,bound:!0}:{required:!1,type:`workspace-jwt`,bound:!1},..._?{workspace:{id:g.workspace.id,name:g.workspace.name}}:{},...b?{functions:b.stats}:{},...C?{agents:{enabled:!0,count:C.list().length}}:{}},w=new te({serve:{maxRequestBodySize:n.server.max_body_size},websocket:{idleTimeout:Math.ceil(n.server.session_timeout/1e3)},adapter:ml?T():void 0}).state({sessions:new Map,backend:v,config:n,serverInfo:ee,workspaceState:g,agentsService:C,functionsService:b,startedAt:p,endpoints:{openaiCompat:!!i,anthropicMessages:!!o,typesafeCompat:!!u},host:s()});S=e=>w.handle(e),t&&w.use(t),Sa(w,xa(n,{openaiCompat:i,anthropicMessages:o,typesafeCompat:u,functions:!!b})),n.autodiscover?.http?.enabled&&w.use(et(n,Xe(g))),w.use(ft),w.use(Et),i&&w.use(pn()),o&&w.use(bn()),u&&w.use(Tn()),b&&w.use(Ci(n,b)),C&&w.use(Mi(C));let ne=(e,t)=>ot(at(e,t),g.workspace),E={INVALID_REQUEST:-32600,INVALID_PARAMS:-32602,METHOD_NOT_FOUND:-32601,INTERNAL_ERROR:-32603},ie=e=>e.id??e.raw?.id??e.remoteAddress??`unknown-peer`,k=new Map,A=new Map;return w.ws(`/buttress/rpc`,{parse:(e,t)=>{if(typeof t==`string`)try{return JSON.parse(t)}catch{return e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_REQUEST,message:`Invalid request`},id:null})),null}return t},body:D.Object({jsonrpc:D.String(),method:D.String(),params:D.String(),id:D.String()}),async open(e){let t=ie(e),n=e.data?.headers,r=e.data?.query,i,a=new Promise(e=>{i=e});if(A.set(t,{identity:null,ready:a}),!_){console.log(`[Request] New connection: ${t} (unbound, no auth)`),i(!0);return}let o=await ne(n||{},r);if(!o){console.warn(`[Auth] Rejecting WS ${t}: invalid or missing workspace-access token`),A.delete(t),i(!1),e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_REQUEST,message:`Unauthorized`},id:null})),e.close(1008,`UNAUTHORIZED`);return}console.log(`[Request] New connection: ${t} (subject=${o.subjectType}:${o.subjectId})`);let s=A.get(t);s&&(s.identity=o),i(!0)},async message(e,{id:t,method:r,params:i}){let{sessions:a}=e.data.store,o=ie(e),s=A.get(o);if(s?.ready&&!await s.ready){e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_REQUEST,message:`Unauthorized`},id:t}));return}let c=A.get(o)?.identity??null;if(_&&!c){e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_REQUEST,message:`Unauthorized`},id:t}));return}if(r===`init`){let[r]=ga(i)??[],s,l=!1,u=r&&a.has(r)?a.get(r):null,d=!u?.identity||!!c&&c.subjectId===u.identity.subjectId&&c.subjectType===u.identity.subjectType;if(u&&d)u.timeout&&=(clearTimeout(u.timeout),null),u.identity=c,u.currentPeerId=o,s=r,l=!0,console.log(`[Request] Session restored: ${s}`);else{u&&console.warn(`[Request] Refused to restore session ${r}: identity mismatch (session=${u.identity?.subjectType}:${u.identity?.subjectId} peer=${c?.subjectType}:${c?.subjectId})`),s=j();let e={streams:new Map,streamReaders:new Map,generators:new Map,initializedContexts:new Set,fileManager:new Ea(s,n.server.temp_file_dir),timeout:null,identity:c,currentPeerId:o};a.set(s,e),console.log(`[Request] New session: ${s}`)}k.set(o,s),e.send(JSON.stringify({jsonrpc:`2.0`,result:_a({sessionId:s,restored:l}),id:t}));return}let l=k.get(o);if(!l){e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_REQUEST,message:`Session not initialized`},id:t}));return}let u=a.get(l);if(!u){k.delete(o),e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_REQUEST,message:`Session not initialized`},id:t}));return}console.log(`[Request] Received request from ${l}: ${r}`);let[d,f]=r.split(`.`),p=pa[d]?.[f];if(!p&&r!==`cancel`&&r!==`ping`){e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.METHOD_NOT_FOUND,message:`Method not found`},id:t}));return}try{if(r===`cancel`){let e=u.streamReaders.get(t);e&&(e.reader.cancel(),u.streamReaders.delete(t));return}if(r===`ping`){e.send(JSON.stringify({jsonrpc:`2.0`,result:`pong`,id:t}));return}let n=ga(i),a=ma[d]?.[f],s=a?a.parse(n):n,c=await p({...e.data.store,peerId:l,session:u},...s);if(c instanceof re){let n=c.getReader();u.streamReaders.set(t,{reader:n,peerId:o}),e.send(JSON.stringify({jsonrpc:`2.0`,result:{type:`stream`},id:t}));try{for(;;){let{value:r,done:i}=await n.read();if(i)break;let{event:a,data:o}=r;e.send(JSON.stringify({jsonrpc:`2.0`,method:`notification/${a}`,params:_a(o),id:t}))}e.send(JSON.stringify({jsonrpc:`2.0`,method:`notification/_end`,id:t}))}catch(n){console.error(`[RPC] Stream error for ${r}:`,n),e.send(JSON.stringify({jsonrpc:`2.0`,method:`notification/_error`,params:_a(n),id:t}))}u.streamReaders.delete(t)}else e.send(JSON.stringify({jsonrpc:`2.0`,result:_a(c),id:t}))}catch(n){if(n instanceof ge){e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INVALID_PARAMS,message:`Invalid params`,data:n.issues},id:t}));return}console.error(`[RPC] Handler error for ${r}:`,n),e.send(JSON.stringify({jsonrpc:`2.0`,error:{code:E.INTERNAL_ERROR,message:String(n)},id:t}))}},async close(e){let t=ie(e),r=k.get(t);if(k.delete(t),A.delete(t),!r){console.log(`[Request] Connection closed (no session)`);return}console.log(`[Request] Connection closed: ${r}`);let{backend:i,sessions:a}=e.data.store,o=a.get(r);if(o){for(let[e,n]of o.streamReaders)n.peerId===t&&(n.reader.cancel().catch(()=>{}),o.streamReaders.delete(e));if(o.currentPeerId!==t){console.log(`[Request] Session ${r} already adopted by another peer; skip arm`);return}o.timeout=setTimeout(()=>{if(o.currentPeerId!==t)return;a.delete(r),console.log(`[Request] Session timed out: ${r}`);let{generators:e}=o;e.forEach((e,t)=>{for(let n=0;n<e;n++)i.finalizeGenerator(t)}),o.fileManager.destroy().catch(()=>{})},n.server.session_timeout)}}}),{app:w,config:n,functions:b,agents:C}},gl=async({backend:e,router:t,config:n,enableOpenAICompat:r=!1,enableAnthropicMessages:i=!1,enableTypeSafeCompat:a=!1,functions:o=null,agents:s=null})=>{let{app:c,config:l,functions:u,agents:d}=await hl({backend:e,router:t,config:n,enableOpenAICompat:r,enableAnthropicMessages:i,enableTypeSafeCompat:a,functions:o,agents:s}),{server:{port:f}}=l,p=[new Promise(e=>c.listen(f,e))],m=null;if(l.autodiscover){let{workspace:e,serverKeyPair:t}=c.store.workspaceState;if(e&&t){let e=Xe(c.store.workspaceState);m=new Ta(l.autodiscover,()=>c.store.serverInfo,e),p.push(m.start())}else console.warn(e?"[Autodiscover] disabled: bound to a workspace but state.json is missing serverKeyPair. Re-run `bricks buttress bind` to register a per-server announce key (required for v2.0 signed UDP discovery).":"[Autodiscover] disabled: buttress-server is not bound to a workspace. Run `bricks buttress bind` from a workspace-authed CLI to pair.")}return await Promise.all(p),{app:c,port:f,openaiEnabled:r,anthropicMessagesEnabled:i,typesafeCompatEnabled:a,functions:u,agents:d,autoDiscover:m}},_l=[new URL(`index.mjs`,import.meta.url).pathname,new URL(`index.ts`,import.meta.url).pathname];(process.argv[1]?.endsWith(`/bricks-buttress`)||_l.includes(process.argv[1]))&&await cl();export{pl as checkAndNotifyUpdates,dl as checkForUpdates,Ga as compareVersions,hl as createServer,fl as logUpdateMessage,d as processConfig,_ as resolveAgentsConfig,$r as resolveFunctionsConfig,t as startModelDownload,gl as startServer};