@rizom/brain 0.2.0-alpha.142 → 0.2.0-alpha.143

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/brain.js CHANGED
@@ -422,7 +422,7 @@ ${f}`:"")}function x_0(A,Q,w,B){return async($,f)=>{if(B){let Y={toolName:A,args
422
422
  `);let w=A.content.split(`
423
423
  `),B=(Q.content??"").split(`
424
424
  `),$=[];for(let f=0;f<Math.max(w.length,B.length);f++)if((w[f]??"")!==(B[f]??"")){if(w[f])$.push(`- ${w[f]}`);if(B[f])$.push(`+ ${B[f]}`)}return $.join(`
425
- `)}function zLA(A){let{entityService:Q,logger:w,entityRegistry:B}=A;return EW("update","Update an entity's fields or content. Requires confirmation; call this tool without confirmed to request that confirmation instead of asking for plain-text approval. For direct requests that provide exact IDs to set an existing image as an entity cover, call this tool on the target entity with fields.coverImageId set to the image ID; do not stop after lookup.",TFA,async($,f)=>{let Y=w$(f.userPermissionLevel),X=await G4(Q,$.entityType,$.id,w,void 0,Y);if(!X.ok)return{success:!1,error:X.error};let{entity:W}=X,H=iFA({...$.fields!==void 0?{fields:$.fields}:{},...$.content!==void 0?{content:$.content}:{}}),K=H.content?.trim().length===0&&H.fields===void 0,U=W.metadata.status;if($.confirmed&&W.entityType==="agent"&&(U==="discovered"||U==="approved")&&(!H.content&&!H.fields||K))H={fields:{status:"approved"}};if(H.content&&H.fields)return{success:!1,error:"Provide either 'content' or 'fields', not both"};if(!H.content&&!H.fields)return{success:!1,error:"Provide 'content' (full replacement) or 'fields' (partial update)"};let D=Lg2(W.entityType,H);if(D)return D;let q=kg2(W.entityType,H,B);if(q)return q;let b=_g2(W.entityType,H,B);if(b)return b;let I=W.metadata.status,V=Ng2(W,H,B),N=GLA(W.entityType,I,V,B)==="non-publish"?"update":"publish",k=yW(A,$.entityType,N,f);if(k)return k;if($.confirmed){if($.contentHash&&W.contentHash!==$.contentHash)return{success:!1,error:"Entity was modified since you reviewed the changes. Please try again."};let h=H.content!==void 0?{...W,content:H.content,visibility:Dk(H.content)}:Fg2(W,H.fields??{});if(h.visibility!==W.visibility&&!CO(f.userPermissionLevel,h.visibility))return{success:!1,error:`Cannot set entity visibility to "${h.visibility}" \u2014 caller permission "${f.userPermissionLevel??"public"}" is not allowed to write at that level.`};try{let P=BR(f);await Q.updateEntity({entity:h,...P?{options:{eventContext:P}}:{}})}catch(P){return{success:!1,error:P instanceof Error?P.message:"Failed to update entity"}}return{success:!0,data:{updated:W.id}}}let x=K20(W),R=jg2(W,H);return{needsConfirmation:!0,toolName:"system_update",summary:`Update "${x}"?`,completionSummary:`Updated ${dFA(W.entityType)}.`,preview:R,args:{...$,...H,id:W.id,confirmed:!0,contentHash:W.contentHash}}},{visibility:"trusted",sideEffects:"writes"})}var qLA=i(()=>{CB();J4();xz();wR();oV()});function bLA(A){return[oFA(A),aFA(A),eFA(A),zLA(A),QLA(A)]}var VLA=i(()=>{sFA();tFA();ALA();wLA();qLA()});function ILA(A){let{entityService:Q,logger:w}=A;return[P6("system","search","Search entities using semantic search. For broad search, make one system_search call with scope.kind all. Use scope.kind type only when the user asks for a specific entity type. Applies a default minScore of 0.5 to reduce weak matches; lower minScore only for exploratory or loose recall. Search results are candidates; do not present weak or unrelated candidates as exact matches.",hFA,async(B,$)=>{let f=w$($.userPermissionLevel);return{success:!0,data:{results:(await Q.search({query:B.query,options:{limit:B.limit??A.searchLimit,...B.scope.kind==="type"&&{types:[B.scope.entityType]},minScore:B.minScore??Pg2,...B.includeUngenerated!==void 0&&{includeUngenerated:B.includeUngenerated},visibilityScope:f}})).map((Y)=>({...Y,entity:t_0(Y.entity)}))}}},{visibility:"public",sideEffects:"none",cli:{name:"search"}}),P6("system","get","Retrieve a specific entity by type and identifier (ID, slug, or title). If retrieval fails, report the entity as not found rather than describing related generation work as pending.",CFA,async(B,$)=>{if(!Q.getEntityTypes().includes(B.entityType))return{success:!1,error:`Unknown entity type: ${B.entityType}. Available: ${Q.getEntityTypes().join(", ")}`};let f=w$($.userPermissionLevel),Y=await G4(Q,B.entityType,B.id,w,void 0,f);if(!Y.ok)return{success:!1,error:Y.error};return{success:!0,data:{entity:t_0(Y.entity)}}},{visibility:"public",sideEffects:"none",cli:{name:"get"}}),P6("system","list","List entities by a known entity type. Returns metadata only \u2014 use system_get for full content. Use system_search, not system_list, for broad or vague lookup requests. Use system_list to inspect metadata dates such as publishedAt when the user asks for the latest item of a known type, such as latest blog post.",gFA,async(B,$)=>{if(!Q.getEntityTypes().includes(B.entityType))return{success:!1,error:`Unknown entity type: ${B.entityType}. Available: ${Q.getEntityTypes().join(", ")}`};let Y={visibilityScope:w$($.userPermissionLevel)};if(B.status&&B.status!=="any")Y.metadata={status:B.status};let W=(await Q.listEntities({entityType:B.entityType,options:{limit:B.limit??20,filter:Y}})).map(({content:H,contentHash:K,...U})=>U);if(B.entityType==="post"&&B.status==="published")W.sort((H,K)=>{let U=H.metadata.publishedAt,D=K.metadata.publishedAt,q=typeof U==="string"?Date.parse(U):0;return(typeof D==="string"?Date.parse(D):0)-q});return{success:!0,data:{entities:W,count:W.length}}},{visibility:"public",sideEffects:"none",cli:{name:"list"}})]}var Pg2=0.5;var JLA=i(()=>{Q9();CB();xz();oV()});function FLA(A){let{entityService:Q}=A;return[P6("system","insights",`Get aggregate content insights and analytics only. For a general overview of actual content, use system_list instead. Available types: ${A.insights.getTypes().join(", ")}.`,cFA,async(w,B)=>{let $=w$(B.userPermissionLevel);return{success:!0,data:await A.insights.get(w.type,Q,$)}},{visibility:"public",sideEffects:"none"})]}var LLA=i(()=>{Q9();CB();xz()});function kLA(A){let{jobs:Q}=A;return[EW("job_status","Get status for background operations. Use this for ready checks, follow-up questions about queued/background work, and status disputes where the operator says logs or runtime state disagree with the conversation. Inspect runtime job status before answering. Do not argue from the transcript alone when job status is available.",uFA,async(w)=>{if(w.batchId){let f=await Q.getBatchStatus(w.batchId);if(!f)return{success:!1,error:`No batch found with ID: ${w.batchId}`};let Y=f.totalOperations>0?Math.round(f.completedOperations/f.totalOperations*100):0;return{success:!0,data:{batchId:w.batchId,status:f.status,progress:{total:f.totalOperations,completed:f.completedOperations,failed:f.failedOperations,percentComplete:Y},currentOperation:f.currentOperation,errors:f.errors}}}let B=await Q.getActiveJobs(w.jobTypes),$=await Q.getActiveBatches();return{success:!0,data:{summary:{activeJobs:B.length,activeBatches:$.length},jobs:B.map((f)=>({id:f.id,type:f.type,status:f.status,priority:f.priority,retryCount:f.retryCount,createdAt:new Date(f.createdAt).toISOString(),startedAt:f.startedAt?new Date(f.startedAt).toISOString():null})),batches:$.map((f)=>({batchId:f.batchId,status:f.status.status,totalOperations:f.status.totalOperations,completedOperations:f.status.completedOperations,failedOperations:f.status.failedOperations,currentOperation:f.status.currentOperation,pluginId:f.metadata.metadata.pluginId,errors:f.status.errors}))}}},{visibility:"public",sideEffects:"none"})]}var _LA=i(()=>{xz();oV()});function Mg2(A){let{entityCounts:Q,daemons:w,endpoints:B,interactions:$,...f}=A;return f}function NLA(A){return[P6("system","status","Get system status including model, version, interfaces, and tools",Z.object({}),async()=>({success:!0,data:Mg2(await A.getAppInfo())}),{visibility:"public",sideEffects:"none",cli:{name:"status"}})]}var jLA=i(()=>{Q9();N0()});function PLA(A){return[...ILA(A),...kLA(A),...NLA(A),...bLA(A),...FLA(A)]}var MLA=i(()=>{VLA();JLA();LLA();_LA();jLA()});function OLA(A){return[{uri:"entity://types",name:"Entity Types",description:"List of registered entity types",mimeType:"text/plain",handler:async()=>({contents:[{uri:"entity://types",mimeType:"text/plain",text:A.entityService.getEntityTypes().join(`
425
+ `)}function zLA(A){let{entityService:Q,logger:w,entityRegistry:B}=A;return EW("update","Update an entity's fields or content. Requires confirmation; call this tool without confirmed to request that confirmation instead of asking for plain-text approval. For direct requests that provide exact IDs to set an existing image as an entity cover, call this tool on the target entity with fields.coverImageId set to the image ID; do not stop after lookup.",TFA,async($,f)=>{let Y=w$(f.userPermissionLevel),X=await G4(Q,$.entityType,$.id,w,void 0,Y);if(!X.ok)return{success:!1,error:X.error};let{entity:W}=X,H=iFA({...$.fields!==void 0?{fields:$.fields}:{},...$.content!==void 0?{content:$.content}:{}}),K=H.content?.trim().length===0&&H.fields===void 0,U=W.metadata.status;if($.confirmed&&W.entityType==="agent"&&(U==="discovered"||U==="approved")&&(!H.content&&!H.fields||K))H={fields:{status:"approved"}};if(H.content&&H.fields)return{success:!1,error:"Provide either 'content' or 'fields', not both"};if(!H.content&&!H.fields)return{success:!1,error:"Provide 'content' (full replacement) or 'fields' (partial update)"};let D=Lg2(W.entityType,H);if(D)return D;let q=kg2(W.entityType,H,B);if(q)return q;let b=_g2(W.entityType,H,B);if(b)return b;let I=W.metadata.status,V=Ng2(W,H,B),N=GLA(W.entityType,I,V,B)==="non-publish"?"update":"publish",k=yW(A,$.entityType,N,f);if(k)return k;if($.confirmed){if($.contentHash&&W.contentHash!==$.contentHash)return{success:!1,error:"Entity was modified since you reviewed the changes. Please try again."};let h=H.content!==void 0?{...W,content:H.content,visibility:Dk(H.content)}:Fg2(W,H.fields??{});if(h.visibility!==W.visibility&&!CO(f.userPermissionLevel,h.visibility))return{success:!1,error:`Cannot set entity visibility to "${h.visibility}" \u2014 caller permission "${f.userPermissionLevel??"public"}" is not allowed to write at that level.`};try{let P=BR(f);await Q.updateEntity({entity:h,...P?{options:{eventContext:P}}:{}})}catch(P){return{success:!1,error:P instanceof Error?P.message:"Failed to update entity"}}return{success:!0,data:{updated:W.id}}}let x=K20(W),R=jg2(W,H);return{needsConfirmation:!0,toolName:"system_update",summary:`Update "${x}"?`,completionSummary:`Updated ${dFA(W.entityType)}.`,preview:R,args:{...$,...H,id:W.id,confirmed:!0,contentHash:W.contentHash}}},{visibility:"trusted",sideEffects:"writes"})}var qLA=i(()=>{CB();J4();xz();wR();oV()});function bLA(A){return[oFA(A),aFA(A),eFA(A),zLA(A),QLA(A)]}var VLA=i(()=>{sFA();tFA();ALA();wLA();qLA()});function ILA(A){let{entityService:Q,logger:w}=A;return[P6("system","search","Search entities using semantic search. For broad search, make one system_search call with scope.kind all. Use scope.kind type only when the user asks for a specific entity type. Applies a default minScore of 0.5 to reduce weak matches; lower minScore only for exploratory or loose recall. Search results are candidates; do not present weak or unrelated candidates as exact matches.",hFA,async(B,$)=>{let f=w$($.userPermissionLevel);return{success:!0,data:{results:(await Q.search({query:B.query,options:{limit:B.limit??A.searchLimit,...B.scope.kind==="type"&&{types:[B.scope.entityType]},minScore:B.minScore??Pg2,...B.includeUngenerated!==void 0&&{includeUngenerated:B.includeUngenerated},visibilityScope:f}})).map((Y)=>({...Y,entity:t_0(Y.entity)}))}}},{visibility:"public",sideEffects:"none",cli:{name:"search"}}),P6("system","get","Retrieve a specific entity by type and identifier (ID, slug, or title). If retrieval fails, report the entity as not found rather than describing related generation work as pending.",CFA,async(B,$)=>{if(!Q.getEntityTypes().includes(B.entityType))return{success:!1,error:`Unknown entity type: ${B.entityType}. Available: ${Q.getEntityTypes().join(", ")}`};let f=w$($.userPermissionLevel),Y=await G4(Q,B.entityType,B.id,w,void 0,f);if(!Y.ok)return{success:!1,error:Y.error};return{success:!0,data:{entity:t_0(Y.entity)}}},{visibility:"public",sideEffects:"none",cli:{name:"get"}}),P6("system","list","List entities by a known entity type. Returns metadata only \u2014 use system_get for full content. Use system_search, not system_list, for broad or vague lookup requests. Use system_list to inspect metadata dates such as publishedAt when the user asks for the latest item of a known type, such as latest blog post.",gFA,async(B,$)=>{if(!Q.getEntityTypes().includes(B.entityType))return{success:!1,error:`Unknown entity type: ${B.entityType}. Available: ${Q.getEntityTypes().join(", ")}`};let Y={visibilityScope:w$($.userPermissionLevel)};if(B.status&&B.status!=="any")Y.metadata={status:B.status};let W=(await Q.listEntities({entityType:B.entityType,options:{limit:B.limit??20,filter:Y}})).map(({content:H,contentHash:K,...U})=>U);if(B.entityType==="post")W.sort((H,K)=>{let U=H.metadata.publishedAt,D=K.metadata.publishedAt,q=typeof U==="string"?Date.parse(U):0;return(typeof D==="string"?Date.parse(D):0)-q});return{success:!0,data:{entities:W,count:W.length}}},{visibility:"public",sideEffects:"none",cli:{name:"list"}})]}var Pg2=0.5;var JLA=i(()=>{Q9();CB();xz();oV()});function FLA(A){let{entityService:Q}=A;return[P6("system","insights",`Get aggregate content insights and analytics only. For a general overview of actual content, use system_list instead. Available types: ${A.insights.getTypes().join(", ")}.`,cFA,async(w,B)=>{let $=w$(B.userPermissionLevel);return{success:!0,data:await A.insights.get(w.type,Q,$)}},{visibility:"public",sideEffects:"none"})]}var LLA=i(()=>{Q9();CB();xz()});function kLA(A){let{jobs:Q}=A;return[EW("job_status","Get status for background operations. Use this for ready checks, follow-up questions about queued/background work, and status disputes where the operator says logs or runtime state disagree with the conversation. Inspect runtime job status before answering. Do not argue from the transcript alone when job status is available.",uFA,async(w)=>{if(w.batchId){let f=await Q.getBatchStatus(w.batchId);if(!f)return{success:!1,error:`No batch found with ID: ${w.batchId}`};let Y=f.totalOperations>0?Math.round(f.completedOperations/f.totalOperations*100):0;return{success:!0,data:{batchId:w.batchId,status:f.status,progress:{total:f.totalOperations,completed:f.completedOperations,failed:f.failedOperations,percentComplete:Y},currentOperation:f.currentOperation,errors:f.errors}}}let B=await Q.getActiveJobs(w.jobTypes),$=await Q.getActiveBatches();return{success:!0,data:{summary:{activeJobs:B.length,activeBatches:$.length},jobs:B.map((f)=>({id:f.id,type:f.type,status:f.status,priority:f.priority,retryCount:f.retryCount,createdAt:new Date(f.createdAt).toISOString(),startedAt:f.startedAt?new Date(f.startedAt).toISOString():null})),batches:$.map((f)=>({batchId:f.batchId,status:f.status.status,totalOperations:f.status.totalOperations,completedOperations:f.status.completedOperations,failedOperations:f.status.failedOperations,currentOperation:f.status.currentOperation,pluginId:f.metadata.metadata.pluginId,errors:f.status.errors}))}}},{visibility:"public",sideEffects:"none"})]}var _LA=i(()=>{xz();oV()});function Mg2(A){let{entityCounts:Q,daemons:w,endpoints:B,interactions:$,...f}=A;return f}function NLA(A){return[P6("system","status","Get system status including model, version, interfaces, and tools",Z.object({}),async()=>({success:!0,data:Mg2(await A.getAppInfo())}),{visibility:"public",sideEffects:"none",cli:{name:"status"}})]}var jLA=i(()=>{Q9();N0()});function PLA(A){return[...ILA(A),...kLA(A),...NLA(A),...bLA(A),...FLA(A)]}var MLA=i(()=>{VLA();JLA();LLA();_LA();jLA()});function OLA(A){return[{uri:"entity://types",name:"Entity Types",description:"List of registered entity types",mimeType:"text/plain",handler:async()=>({contents:[{uri:"entity://types",mimeType:"text/plain",text:A.entityService.getEntityTypes().join(`
426
426
  `)}]})},{uri:"brain://identity",name:"Brain Identity",description:"Brain character \u2014 name, role, purpose, values",mimeType:"application/json",handler:async()=>({contents:[{uri:"brain://identity",mimeType:"application/json",text:JSON.stringify(A.getIdentity(),null,2)}]})},{uri:"brain://profile",name:"Anchor Profile",description:"Brain owner profile \u2014 name, bio, expertise",mimeType:"application/json",handler:async()=>({contents:[{uri:"brain://profile",mimeType:"application/json",text:JSON.stringify(A.getProfile(),null,2)}]})},{uri:"brain://status",name:"Brain Status",description:"System status \u2014 version, model, interfaces, tools",mimeType:"application/json",handler:async()=>({contents:[{uri:"brain://status",mimeType:"application/json",text:JSON.stringify(await A.getAppInfo(),null,2)}]})}]}function xLA(A){let{entityService:Q}=A;return[{name:"entity-list",uriTemplate:"entity://{type}",description:"List entities of a given type",mimeType:"application/json",list:async()=>{return Q.getEntityTypes().map((B)=>({uri:`entity://${B}`,name:`${B} entities`}))},complete:{type:async()=>Q.getEntityTypes()},handler:async({type:w})=>{let B=Q.getEntityTypes();if(!B.includes(w))throw Error(`Unknown entity type: ${w}. Available: ${B.join(", ")}`);let f=(await Q.listEntities({entityType:w})).map((Y)=>({id:Y.id,entityType:Y.entityType,...Y.metadata,updated:Y.updated}));return{contents:[{uri:`entity://${w}`,mimeType:"application/json",text:JSON.stringify(f,null,2)}]}}},{name:"entity-detail",uriTemplate:"entity://{type}/{id}",description:"Read a single entity by type and ID",mimeType:"text/markdown",complete:{type:async(w)=>{let B=Q.getEntityTypes();return w?B.filter(($)=>$.startsWith(w)):B},id:async()=>[]},handler:async({type:w,id:B})=>{let $=await Q.getEntity({entityType:w,id:B});if(!$)throw Error(`Entity not found: ${w}/${B}`);return{contents:[{uri:`entity://${w}/${B}`,mimeType:"text/markdown",text:$.content}]}}}]}function RLA(A){return[{name:"create",description:"Create new content of any type",args:{type:{description:"Entity type (e.g. post, deck, note)",required:!0},topic:{description:"Topic or title for the content"}},handler:async({topic:w,type:B})=>({messages:[{role:"user",content:{type:"text",text:w?`Create a new ${B} about: ${w}`:`Create a new ${B}. Ask me what it should be about.`}}]})},{name:"generate",description:"AI-generate content with a prompt",args:{type:{description:`Entity type (${(()=>A.entityService.getEntityTypes().join(", "))()})`,required:!0},topic:{description:"What to generate",required:!0}},handler:async({type:w,topic:B})=>({messages:[{role:"user",content:{type:"text",text:`Generate a ${w} about: ${B}`}}]})},{name:"review",description:"Review and improve existing content",args:{type:{description:"Entity type",required:!0},id:{description:"Entity ID or slug",required:!0}},handler:async({type:w,id:B})=>({messages:[{role:"user",content:{type:"text",text:`Review my ${w} "${B}". Read it first, then give me specific feedback on structure, clarity, and impact. Suggest concrete improvements.`}}]})},{name:"publish",description:"Publish content \u2014 preview, confirm, and publish",args:{type:{description:"Entity type",required:!0},id:{description:"Entity ID or slug",required:!0}},handler:async({type:w,id:B})=>({messages:[{role:"user",content:{type:"text",text:`I want to publish my ${w} "${B}". Show me a preview first, then publish it.`}}]})},{name:"brainstorm",description:"Brainstorm ideas using brain context and expertise",args:{topic:{description:"Topic to brainstorm about",required:!0}},handler:async({topic:w})=>({messages:[{role:"user",content:{type:"text",text:`Let's brainstorm about: ${w}. Use my existing content and expertise as context. Give me fresh angles and concrete ideas.`}}]})}]}function vLA(A){let Q=A.entityService.getEntityTypes(),w=Q.map((B)=>`- ${B}: ${A.entityRegistry.getAdapter(B).purpose}`);return["## Entity CRUD","","Use these system tools for ALL entity operations:","","Treat explicit verbs such as save, create, capture, remember, import, add/connect an agent, approve/archive an agent, update, delete, generate, publish, or sync as mutation requests. Ordinary status questions like 'what is the status', 'is it ready', 'did that finish', or 'what happened' are not capture requests; answer them by using the relevant status/read tool for the prior operation. Never call system_create for a status follow-up.","",`- **system_create**: Create an entity from existing/concrete material. Requires confirmation before persisting; call system_create without \`confirmed\` to request that confirmation, and never pass \`confirmed: true\` on the initial user request. Required \`source\` union: \`{ kind: "text", content }\` stores exact/direct content; \`{ kind: "url", url }\` creates URL/domain-backed records such as links (preserve bare domains as bare domains); \`{ kind: "upload", upload, transform: "extract-markdown" }\` imports extractable upload bytes as a markdown note; \`{ kind: "upload", upload, transform: "preserve" }\` preserves raw uploaded bytes as their durable file entity; \`{ kind: "prior-response", messageId? }\` saves a previous assistant answer/summary by reference without copying or paraphrasing it. If a direct save request includes the content in the same message, that content is sufficient, even if it is a short sentence or fragment after a colon or embedded in the request phrase (for example, "Save this memo about the launch timeline"); call system_create instead of asking the user to paste it again. If the immediate context is an assistant summary/answer about an upload and the user asks to save it/that/this/summary, create a note with \`source.kind: "prior-response"\`; do this even when the prior answer says there was limited readable content. Do not ask whether they meant the summary or the file after you just summarized/answered about the upload: save the visible prior response as a note. Do not treat a bare upload receipt like "I got filename. What would you like me to do?" as a summary/answer; if the user then says "save it", preserve the latest uploaded file itself with upload \`preserve\` (image uploads as entityType image, PDFs/documents as their file entity type). Only use \`source.kind: "upload"\` when the runtime supplies an actual upload reference/attachment; if the message contains a pasted uploaded-file transcript with readable content (for example, \`User uploaded a file "name.md": ...\`), save the visible transcript content as \`source.kind: "text"\`. Only use upload \`preserve\` otherwise when they explicitly want to save the uploaded file/document itself. Use system_generate, not system_create, for AI generation, generated images, cover images, and source-derived artifacts. Available entity types: ${Q.join(", ")}.`,'- **system_generate**: Generate a new durable entity or deterministic artifact. Requires confirmation before queueing generation; call system_generate without `confirmed` to request that confirmation, and never pass `confirmed: true` on the initial user request. When the user asks you to create, write, draft, or generate new durable content and has not supplied final exact content to store, call system_generate instead of drafting the content in chat or asking for separate prose approval first. If generation depends on an existing source entity (for example, a newsletter from a blog post), resolve the source with read/search/list tools first unless the user gives an exact entity id in quotes, then call system_generate with `operation.kind: "prompt-from-source"` in the same turn when a clear source is found. If you identify the latest source entity, do not stop after saying you found it or can generate from it; call system_generate immediately. If no existing durable source entity is resolved, use `operation.kind: "prompt"`, which has no source field; never invent source IDs, use upload IDs/filenames as entity refs, use profile/brain-character as a generic source, or create placeholder source refs. For broad topical prompts like \'about AI\' or \'about continuous learning\', use `operation.kind: "prompt"`. If the user asks for the latest published/blog source, use system_list for that entity type (for blog posts, entityType post) to inspect publishedAt dates; do not rely on semantic search result order. Choose the newest matching candidate by publishedAt (not updated/created order) and proceed with system_generate rather than asking for separate prose approval; do not say \'if that is the one you mean\' when a newest dated candidate is visible. Do not say \'I can generate it if you want\' or \'I need to queue it first\'; calling system_generate without `confirmed` is the confirmation request. Required `operation` union: `{ kind: "prompt", entityType, prompt }` generates a new non-image durable entity from a broad prompt with no source; `{ kind: "prompt-from-source", entityType, source: { entityType, entityId }, prompt }` generates from an existing resolved entity, such as a newsletter from a blog post. `{ kind: "standalone-image", prompt }` generates an unattached image; `{ kind: "cover-image", target: { entityType, entityId }, prompt }` generates an image and attaches it to an existing canonical entity as `coverImageId`; `{ kind: "attachment", source: { entityType, entityId }, attachmentType }` renders a deterministic artifact from an existing entity attachment provider. For save/render/regenerate/replace requests for source-derived artifacts, call `system_generate` with `operation.kind: "attachment"` immediately; do not say you can queue it later. Use `replace: true` when the user says regenerate, replace, refresh, or update an existing artifact. For OG/social preview renders, use `attachmentType: "og-image"`; the provider derives the output image and updates `ogImageId`. For deck carousel PDFs use `attachmentType: "carousel"`; for printable post/project/product PDFs use `attachmentType: "printable"`. If the user asks to attach a generated artifact to another entity, generate the artifact first in the same turn; do not ask whether they mean an existing artifact when the source entity is explicit or given as a quoted id such as deck `distributed-systems-primer`. Update the target only after the real artifact ID exists. To create an entity and a cover image, first create/generate only the entity, then after confirmation and after the real canonical entity ID is known call system_generate with operation.kind cover-image. When the user asks to create/regenerate a cover for an existing entity and search/get resolves a clear target, call system_generate with operation.kind cover-image in the same turn; do not stop after saying you found it. In a single initial request for \'a post with a cover image\', do not also call standalone-image; never guess a future target ID, and do not generate a standalone image as a substitute for a requested cover image.','- **system_update**: Modify an entity\'s fields or content. Use `fields` for title, status, coverImageId, ogImageId, and other frontmatter/metadata changes. To remove or clear a cover image, set `fields.coverImageId` to null, not an empty string. Use system_update for coverImageId when an existing image entity id is known; if the user says to set an existing image as a cover, update `coverImageId` even when `ogImageId` already points at that image. To generate a new cover image for an existing entity, use system_generate with operation.kind cover-image. Agent approval/archive is a status field update on `entityType: "agent"`. Cover images use `coverImageId`; OG/social previews use `ogImageId`; do not treat them as interchangeable. Requires confirmation before applying changes; call system_update without `confirmed` to request that confirmation, rather than asking for prose approval. For explicit publish requests, use the publishing tool if available instead of changing status with system_update; follow-up pronouns like \'publish it\' should target the entity just read or updated in the conversation.',"- **system_delete**: Owner/anchor-only entity removal. Requires confirmation before deleting. Never pass `confirmed: true` on the initial user request; call without `confirmed` so the confirmation flow can ask the owner first. If system_delete is not available in the current tool surface, say deletion requires owner access; do not imply a confirmation flow is available. Protected identity/profile records such as brain-character and anchor-profile cannot be deleted; update them instead.","- **system_get**: Retrieve a specific entity by type and ID/slug/title.","- **system_list**: List entities by type with optional filters. For simple list/show-all/summary requests that name or browse a known type or synonym (for example essays/articles/blog posts => post), use system_list with that entity type instead of semantic search. For 'summarize my blog posts' or similar whole-type summaries, first call system_list for entityType post, then summarize those returned entities. For 'latest' requests, use system_list metadata dates such as publishedAt to choose the newest candidate.","- **system_search**: Semantic search across all entities. For each new user question about what they have written, mentioned, discussed, or saved, run a fresh search for that turn instead of answering from prior-turn search results or memory; this includes analysis phrasing such as 'How do I discuss X in my writing?' even if prior turns searched related topics.","","Do not ask for prose confirmation instead of calling the applicable mutating tool; for create, update, delete, generate, publish, sync, and similar state-changing requests, the initial tool call without `confirmed` is how you create the pending confirmation. Never claim a durable create/update/delete change was saved, created, done, or completed unless the relevant tool call succeeded or returned a pending confirmation. If a create/update/delete tool is unavailable, unauthorized, or intentionally not called, say you can't make that durable change from the current context; never say saved/created/done. For an explicit write request from an unauthorized/currently unwritable context, refuse directly; do not call system_status or system_search to check permission or look up related content.","","Entity types \u2014 select `entityType` by what the type is for:",...w].join(`
427
427
  `)}function G20(A,Q,w,B,$){for(let f of A)try{Q(f)}catch{$.debug(`System ${B} ${w(f)} already registered, skipping`)}}function hLA(A,Q,w,B){let $=PLA(A);G20($,(K)=>Q.registerTool($R,K),(K)=>K.name,"tool",B);let f=w.subscribe(`plugin:${$R}:tool:execute`,async(K)=>{let U=Og2.safeParse(K.payload);if(!U.success)return{success:!1,error:"Invalid system tool execute payload"};let{toolName:D,args:q,interfaceType:b,userId:I,conversationId:V,channelId:L,userPermissionLevel:N}=U.data,k=$.find((h)=>h.name===D);if(!k)return{success:!1,error:`System tool not found: ${D}`};let x={interfaceType:b??"system",userId:I??"system"};if(V)x.conversationId=V;if(L)x.channelId=L;if(N)x.userPermissionLevel=N;return{success:!0,data:await k.handler(q,x)}});B.debug(`Registered ${$.length} system tools`);let Y=OLA(A);G20(Y,(K)=>Q.registerResource($R,K),(K)=>K.uri,"resource",B),B.debug(`Registered ${Y.length} system resources`);let X=xLA(A);G20(X,(K)=>Q.registerResourceTemplate($R,K),(K)=>K.uriTemplate,"resource template",B),B.debug(`Registered ${X.length} system resource templates`);let W=RLA(A);G20(W,(K)=>Q.registerPrompt($R,K),(K)=>K.name,"prompt",B),B.debug(`Registered ${W.length} system prompts`);let H=vLA(A);try{Q.registerInstructions($R,H)}catch{B.debug("System instructions already registered, skipping")}return B.debug("Registered system instructions"),f}var $R="system",Og2;var CLA=i(()=>{Q9();N0();MLA();Og2=Z.object({toolName:Z.string(),args:Z.unknown(),...oS.partial().shape})});function gLA(A){let{services:Q,jobs:w,insights:B,query:$,getAppInfo:f}=A,Y=Q.jobQueueService,X=Q.logger.child("system"),W=hLA({entityService:Q.entityService,entityRegistry:Q.entityRegistry,jobs:{...w,enqueue:jS(Y,"system",!1),enqueueBatch:PS(w,"system"),registerHandler:MS(Y,"system")},conversationService:Q.conversationService,runtimeUploads:Q.runtimeUploadRegistry,attachments:nS(Q.attachmentRegistry),logger:X,query:$,getIdentity:()=>Q.identityService.getCharacter(),getProfile:()=>Q.profileService.getProfile(),getAppInfo:f,searchLimit:10,insights:B,permissionService:Q.permissionService},Q.mcpService,Q.messageBus,X);Q.disposables.push(W)}var yLA=i(()=>{Bz();wA();CLA()});class bY{config;static instance=null;services;bootloader;initialized=!1;insightsRegistry;bootTime=Date.now();endpointRegistry=new s_0;interactionRegistry=new a_0;jobs;static getInstance(A){return bY.instance??=new bY(Dx(A??{})),bY.instance}static async resetInstance(){if(bY.instance)await bY.instance.shutdown(),bY.instance=null}static createFresh(A,Q){QR();let w=Dx(A);return new bY(w,Q)}constructor(A,Q){this.config=A;let w=LK.getInstance(Q?.logger??JQ.getInstance(),this.config);this.services=w.initializeServices(Q),this.jobs=OFA(this.services.batchJobManager,this.services.jobQueueService),this.insightsRegistry=NFA(),this.bootloader=new r_0(this.config,this.services,{registerCoreDataSources:()=>yWA(this.services,this.config),registerSystemCapabilities:()=>gLA({services:this.services,jobs:this.jobs,insights:this.insightsRegistry,query:(B,$)=>this.query(B,$),getAppInfo:()=>this.getAppInfo()})}),w.wireShell(this.services,this)}getInsightsRegistry(){return this.insightsRegistry}async initialize(A){if(this.services.logger.debug("Shell.initialize() called"),this.initialized){this.services.logger.warn("Shell already initialized");return}try{await this.bootloader.boot(A),this.initialized=!0}catch(Q){throw this.services.logger.error("Failed to initialize Shell",Q),Q}}registerTemplates(A,Q){this.services.logger.debug("Registering templates",{pluginId:Q,count:Object.keys(A).length});for(let[w,B]of Object.entries(A))this.registerTemplate(w,B,Q)}async shutdown(){this.services.logger.debug("Shutting down Shell"),await vFA(this.services),this.initialized=!1,this.services.logger.debug("Shell shutdown complete")}async generateContent(A){return this.requireInitialized("Shell content generation"),TWA(this.services,A)}async query(A,Q){this.requireInitialized("Shell query");let w=await this.getAppInfo(),B={...Q,appInfo:w,timestamp:new Date().toISOString()},{conversationHistory:$,...f}=B;return this.generateContent({prompt:A,templateName:Gx.KNOWLEDGE_QUERY,...$&&{conversationHistory:$},data:f,interfacePermissionGrant:"public"})}registerPlugin(A){this.requireInitialized("Plugin registration"),this.services.pluginManager.registerPlugin(A)}isInitialized(){return this.initialized}requireInitialized(A){if(!this.initialized)throw Error(`${A} attempted before initialization`)}getEntityService(){return this.services.entityService}getConversationService(){return this.services.conversationService}getEntityRegistry(){return this.services.entityRegistry}async generateObject(A,Q){this.requireInitialized("Shell generateObject");let{object:w}=await this.services.aiService.generateObject("You are a helpful assistant. Respond with the requested structured data.",A,Q);return{object:w}}async judge(A){return this.requireInitialized("Shell judge"),this.services.aiService.judge(A)}getAIService(){return this.services.aiService}generateImage(A,Q){return this.services.aiService.generateImage(A,Q)}canGenerateImages(){return this.services.aiService.canGenerateImages()}getPluginManager(){return this.services.pluginManager}getContentService(){return this.services.contentService}getRenderService(){return this.services.renderService}getAttachmentRegistry(){return nS(this.services.attachmentRegistry)}getRuntimeUploadRegistry(){return DJ0(this.services.runtimeUploadRegistry)}getRuntimeState(){return this.services.runtimeStateService}getMessageBus(){return this.services.messageBus}getLogger(){return this.services.logger}getJobQueueService(){return this.services.jobQueueService}getMCPService(){return this.services.mcpService}listToolsForPermissionLevel(A){return this.services.mcpService.listToolsForPermissionLevel(A).map(({pluginId:Q,tool:w})=>({name:w.name,description:w.description,pluginId:Q}))}getPermissionService(){return this.services.permissionService}getAgentService(){return this.services.agentService}registerTools(A,Q){for(let w of Q)try{this.services.mcpService.registerTool(A,w)}catch(B){this.services.logger.error(`Failed to register tool ${w.name} from ${A}:`,B)}}registerResources(A,Q){for(let w of Q)try{this.services.mcpService.registerResource(A,w)}catch(B){this.services.logger.error(`Failed to register resource ${w.name} from ${A}:`,B)}}registerResourceTemplate(A,Q){this.services.mcpService.registerResourceTemplate(A,Q)}registerPrompt(A,Q){this.services.mcpService.registerPrompt(A,Q)}registerInstructions(A,Q){if(this.services.mcpService.registerInstructions(A,Q),this.initialized)this.services.agentService.invalidateAgent()}getPluginPackageName(A){return this.services.pluginManager.getPluginPackageName(A)}hasPlugin(A){return this.services.pluginManager.hasPlugin(A)}getPluginApiRoutes(){return xFA(this.services.pluginManager)}getPluginWebRoutes(){return RFA(this.services.pluginManager)}registerDaemon(A,Q,w){this.services.daemonRegistry.register(A,Q,w)}registerEndpoint(A){this.endpointRegistry.register(A)}listEndpoints(){return this.endpointRegistry.list()}registerInteraction(A){this.interactionRegistry.register(A)}listInteractions(){return this.interactionRegistry.list()}getPublicContext(){return{entityService:this.services.entityService,generateContent:(A)=>this.generateContent(A),getBatchStatus:(A)=>this.services.batchJobManager.getBatchStatus(A)}}registerTemplate(A,Q,w){let B=w?`${w}:${A}`:`shell:${A}`;this.services.templateRegistry.register(B,Q),this.services.logger.debug(`Registered template: ${B}`)}getTemplate(A){return this.services.templateRegistry.get(A)}getDataSourceRegistry(){return this.services.dataSourceRegistry}getIdentity(){return this.services.identityService.getCharacter()}getProfile(){return this.services.profileService.getProfile()}getDomain(){return this.config.siteBaseUrl}getLocalSiteUrl(){return this.config.localSiteUrl}shouldPreferLocalUrls(){return this.config.preferLocalUrls}getThemeCSS(){return this.config.themeCSS}getSpaces(){return this.config.spaces}getDataDir(){return this.config.dataDir}registerEvalHandler(A,Q,w){this.config.evalHandlerRegistry?.register(A,Q,w)}async getAppInfo(){return OWA({config:this.config,services:this.services,bootTime:this.bootTime,endpoints:()=>this.listEndpoints(),interactions:()=>this.listInteractions()})}}var fN0=i(()=>{wA();C9();xWA();XF0();Nk();EWA();Lu();kFA();PFA();MFA();yLA()});function ELA(){return[...g_0]}var TLA=i(()=>{y_0()});async function SLA(){await bY.resetInstance(),QR()}var mLA=i(()=>{fN0();Lu()});var uLA={};D6(uLA,{shellEnvVars:()=>ELA,shellConfigSchema:()=>iA0,resetServiceSingletons:()=>QR,resetAllSingletons:()=>SLA,getStandardConfig:()=>pA0,createStandardConfig:()=>mV,createShellConfig:()=>Dx,Shell:()=>bY,STANDARD_PATHS:()=>lA0,SHELL_TEMPLATE_NAMES:()=>Gx,SHELL_ENTITY_TYPES:()=>Jf,SHELL_DATASOURCE_IDS:()=>dA0});var z20=i(()=>{fN0();XF0();TLA();Nk();mLA();Lu()});var xg2,Rg2,fR,YN0,q20;var Pu=i(()=>{N0();xg2=Z.object({id:Z.string(),version:Z.string(),type:Z.enum(["core","entity","service","interface"]),description:Z.string().optional(),dependencies:Z.array(Z.string()).optional(),packageName:Z.string()}),Rg2=Z.object({name:Z.string(),role:Z.string(),purpose:Z.string(),values:Z.array(Z.string())}),fR=Z.enum(["debug","info","warn","error"]),YN0=Z.object({provider:Z.enum(["hetzner","docker"]).default("hetzner"),serverSize:Z.string().default("cx33"),location:Z.string().default("fsn1"),domain:Z.string().optional(),docker:Z.object({enabled:Z.boolean().default(!0),image:Z.string().optional()}).prefault({}),ports:Z.object({default:Z.number().default(3333),preview:Z.number().default(4321),production:Z.number().default(8080)}).prefault({}),cdn:Z.object({enabled:Z.boolean().default(!1),provider:Z.enum(["bunny","none"]).default("none")}).prefault({}),dns:Z.object({enabled:Z.boolean().default(!1),provider:Z.enum(["bunny","none"]).default("none")}).prefault({}),paths:Z.object({install:Z.string().optional(),data:Z.string().optional()}).prefault({})}),q20=Z.object({name:Z.string().default("brain-app"),version:Z.string().default("1.0.0"),database:Z.string().optional(),aiApiKey:Z.string().optional(),aiImageKey:Z.string().optional(),aiModel:Z.string().optional(),logLevel:fR.optional(),logFile:Z.string().optional(),plugins:Z.array(xg2).default([]),spaces:Z.array(Z.string()).default([]),identity:Rg2.optional(),agentInstructions:Z.array(Z.string()).optional(),deployment:YN0.prefault({})})});import vg2 from"crypto";import XN0 from"fs";function cLA(A){let Q=A.migrationsFolder,w=[],B=`${Q}/meta/_journal.json`;if(!XN0.existsSync(B))throw Error("Can't find meta/_journal.json file");let $=XN0.readFileSync(`${Q}/meta/_journal.json`).toString(),f=JSON.parse($);for(let Y of f.entries){let X=`${Q}/${Y.tag}.sql`;try{let W=XN0.readFileSync(`${Q}/${Y.tag}.sql`).toString(),H=W.split("--> statement-breakpoint").map((K)=>{return K});w.push({sql:H,bps:Y.breakpoints,folderMillis:Y.when,hash:vg2.createHash("sha256").update(W).digest("hex")})}catch{throw Error(`No file ${X} found in ${Q} folder`)}}return w}var lLA=()=>{};async function eV(A,Q){let w=cLA(Q),B=Q.migrationsTable??"__drizzle_migrations",$=r0`
428
428
  CREATE TABLE IF NOT EXISTS ${r0.identifier(B)} (
@@ -430,7 +430,7 @@ ${f}`:"")}function x_0(A,Q,w,B){return async($,f)=>{if(B){let Y={toolName:A,args
430
430
  hash text NOT NULL,
431
431
  created_at numeric
432
432
  )
433
- `;await A.session.run($);let Y=(await A.values(r0`SELECT id, hash, created_at FROM ${r0.identifier(B)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,X=[];for(let W of w)if(!Y||Number(Y[2])<W.folderMillis){for(let H of W.sql)X.push(A.run(r0.raw(H)));X.push(A.run(r0`INSERT INTO ${r0.identifier(B)} ("hash", "created_at") VALUES(${W.hash}, ${W.folderMillis})`))}await A.session.migrate(X)}var Mu=i(()=>{lLA();t5()});async function pLA(A,Q){let w=Q?.child("entity-migrate")??JQ.getInstance().child("entity-migrate"),{db:B,client:$,url:f}=m00(A);w.debug("Running entity database migrations...");try{await u00($,f);let X=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await eV(B,{migrationsFolder:X}),await c00($),w.debug("Entity database migrations completed successfully")}catch(Y){throw w.error("Entity database migration failed:",Y),Y}finally{$.close()}}var iLA=i(()=>{Mu();YI0();C9()});async function dLA(A,Q){let w=Q?.child("job-queue-migrate")??JQ.getInstance().child("job-queue-migrate"),{db:B,client:$,url:f}=C00(A);w.debug("Running job queue migrations...");try{await g00($,f);let X=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await eV(B,{migrationsFolder:X}),w.debug("Job queue migrations completed successfully")}catch(Y){throw w.error("Job queue migration failed:",Y),Y}finally{$.close()}}var nLA=i(()=>{Mu();pV0();C9()});async function rLA(A,Q){let w=Q?.child("conversation-migrate")??JQ.getInstance().child("conversation-migrate"),{db:B,client:$,url:f}=y00(A);w.debug("Running conversation database migrations...");try{if(f.startsWith("file:"))await $.execute("PRAGMA journal_mode = WAL");let X=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await eV(B,{migrationsFolder:X}),w.debug("Conversation database migrations completed successfully")}catch(Y){throw w.error("Conversation database migration failed:",Y),Y}finally{$.close()}}var oLA=i(()=>{Mu();sV0();C9()});async function sLA(A,Q){let w=Q?.child("runtime-state-migrate")??JQ.getInstance().child("runtime-state-migrate"),{db:B,client:$,url:f}=Z20(A);w.debug("Running runtime state migrations...");try{await W20($,f);let X=import.meta.url.includes("/dist/")?new URL("./migrations/runtime-state",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await eV(B,{migrationsFolder:X}),w.debug("Runtime state migrations completed successfully")}catch(Y){throw w.error("Runtime state migration failed:",Y),Y}finally{$.close()}}var aLA=i(()=>{Mu();C9();l_0()});import{mkdir as ZN0}from"fs/promises";function b20(A=process.env){return{dataDir:A.XDG_DATA_HOME??"./data",cacheDir:A.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function V20(A=process.env){return mV(b20(A))}async function I20(A=process.env){let Q=b20(A);try{await ZN0(Q.dataDir,{recursive:!0}),await ZN0(Q.cacheDir,{recursive:!0}),await ZN0(Q.distDir,{recursive:!0})}catch(w){let B=w instanceof Error&&w.message.includes("EACCES")?`Cannot create data directories \u2014 permission denied. Run from a writable directory or check permissions on ${Q.dataDir}`:`Cannot create data directories: ${w instanceof Error?w.message:String(w)}`;throw Error(B,{cause:w})}return mV(Q)}var J20=i(()=>{z20()});class Ou{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:()=>I20(),migrateEntities:pLA,migrateJobQueue:dLA,migrateConversations:rLA,migrateRuntimeState:sLA}}async runAllMigrations(A){this.logger.debug("Running database migrations...");let Q=await this.migrations.getStandardConfigWithDirectories();if(A?.database)Q.database.url=A.database;if(A?.jobQueueDatabase)Q.jobQueueDatabase.url=A.jobQueueDatabase;if(A?.conversationDatabase)Q.conversationDatabase.url=A.conversationDatabase;if(A?.runtimeStateDatabase)Q.runtimeStateDatabase.url=A.runtimeStateDatabase;await this.migrateEntityDatabase(Q),await this.migrateJobQueueDatabase(Q),await this.migrateConversationDatabase(Q),await this.migrateRuntimeStateDatabase(Q),this.logger.debug("All database migrations completed successfully")}async migrateEntityDatabase(A){this.logger.debug("Running entity database migrations..."),await this.migrations.migrateEntities({url:A.database.url,...A.database.authToken&&{authToken:A.database.authToken}},this.logger)}async migrateJobQueueDatabase(A){this.logger.debug("Running job queue database migrations..."),await this.migrations.migrateJobQueue({url:A.jobQueueDatabase.url,...A.jobQueueDatabase.authToken&&{authToken:A.jobQueueDatabase.authToken}},this.logger)}async migrateConversationDatabase(A){this.logger.debug("Running conversation database migrations..."),await this.migrations.migrateConversations({url:A.conversationDatabase.url,...A.conversationDatabase.authToken&&{authToken:A.conversationDatabase.authToken}},this.logger)}async migrateRuntimeStateDatabase(A){this.logger.debug("Running runtime state database migrations..."),await this.migrations.migrateRuntimeState({url:A.runtimeStateDatabase.url,...A.runtimeStateDatabase.authToken&&{authToken:A.runtimeStateDatabase.authToken}},this.logger)}}var WN0=i(()=>{iLA();nLA();oLA();aLA();J20()});function Cg2(){return process.env[hg2]}function tLA(){return Cg2()!=="production"}var hg2="NODE_ENV";var F20;var HN0=i(()=>{N0();F20=Z.object({theme:Z.object({primaryColor:Z.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:Z.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var AkA;var eLA=i(()=>{AkA={name:"@brains/chat-repl",version:"0.2.0-alpha.142",dependencies:{"@brains/plugins":"workspace:*",chalk:"^5.4.1",ink:"^7.0.6","ink-spinner":"^5.0.0","ink-text-input":"^6.0.0",marked:"^18.0.5",react:"^19.2.7"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17",typescript:"^6.0.3"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{dev:"tsc --watch",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"}});var tQ=O((yg2,L20)=>{(function(){function A($0,L0){Object.defineProperty(B.prototype,$0,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",L0[0],L0[1])}})}function Q($0){if($0===null||typeof $0!=="object")return null;return $0=k0&&$0[k0]||$0["@@iterator"],typeof $0==="function"?$0:null}function w($0,L0){$0=($0=$0.constructor)&&($0.displayName||$0.name)||"ReactClass";var v0=$0+"."+L0;_0[v0]||(console.error("Can't call %s on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the %s component.",L0,$0),_0[v0]=!0)}function B($0,L0,v0){this.props=$0,this.context=L0,this.refs=T0,this.updater=v0||P0}function $(){}function f($0,L0,v0){this.props=$0,this.context=L0,this.refs=T0,this.updater=v0||P0}function Y(){}function X($0){return""+$0}function W($0){try{X($0);var L0=!1}catch(x0){L0=!0}if(L0){L0=console;var v0=L0.error,m0=typeof Symbol==="function"&&Symbol.toStringTag&&$0[Symbol.toStringTag]||$0.constructor.name||"Object";return v0.call(L0,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",m0),X($0)}}function H($0){if($0==null)return null;if(typeof $0==="function")return $0.$$typeof===XA?null:$0.displayName||$0.name||null;if(typeof $0==="string")return $0;switch($0){case K0:return"Fragment";case X0:return"Profiler";case c:return"StrictMode";case S0:return"Suspense";case V0:return"SuspenseList";case C0:return"Activity"}if(typeof $0==="object")switch(typeof $0.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),$0.$$typeof){case o:return"Portal";case w0:return $0.displayName||"Context";case b0:return($0._context.displayName||"Context")+".Consumer";case h0:var L0=$0.render;return $0=$0.displayName,$0||($0=L0.displayName||L0.name||"",$0=$0!==""?"ForwardRef("+$0+")":"ForwardRef"),$0;case I0:return L0=$0.displayName||null,L0!==null?L0:H($0.type)||"Memo";case j0:L0=$0._payload,$0=$0._init;try{return H($0(L0))}catch(v0){}}return null}function K($0){if($0===K0)return"<>";if(typeof $0==="object"&&$0!==null&&$0.$$typeof===j0)return"<...>";try{var L0=H($0);return L0?"<"+L0+">":"<...>"}catch(v0){return"<...>"}}function U(){var $0=YA.A;return $0===null?null:$0.getOwner()}function D(){return Error("react-stack-top-frame")}function q($0){if(u0.call($0,"key")){var L0=Object.getOwnPropertyDescriptor($0,"key").get;if(L0&&L0.isReactWarning)return!1}return $0.key!==void 0}function b($0,L0){function v0(){UA||(UA=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",L0))}v0.isReactWarning=!0,Object.defineProperty($0,"key",{get:v0,configurable:!0})}function I(){var $0=H(this.type);return RA[$0]||(RA[$0]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),$0=this.props.ref,$0!==void 0?$0:null}function V($0,L0,v0,m0,x0,e0){var d0=v0.ref;return $0={$$typeof:n,type:$0,key:L0,props:v0,_owner:m0},(d0!==void 0?d0:null)!==null?Object.defineProperty($0,"ref",{enumerable:!1,get:I}):Object.defineProperty($0,"ref",{enumerable:!1,value:null}),$0._store={},Object.defineProperty($0._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty($0,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty($0,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:x0}),Object.defineProperty($0,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:e0}),Object.freeze&&(Object.freeze($0.props),Object.freeze($0)),$0}function L($0,L0){return L0=V($0.type,L0,$0.props,$0._owner,$0._debugStack,$0._debugTask),$0._store&&(L0._store.validated=$0._store.validated),L0}function N($0){k($0)?$0._store&&($0._store.validated=1):typeof $0==="object"&&$0!==null&&$0.$$typeof===j0&&($0._payload.status==="fulfilled"?k($0._payload.value)&&$0._payload.value._store&&($0._payload.value._store.validated=1):$0._store&&($0._store.validated=1))}function k($0){return typeof $0==="object"&&$0!==null&&$0.$$typeof===n}function x($0){var L0={"=":"=0",":":"=2"};return"$"+$0.replace(/[=:]/g,function(v0){return L0[v0]})}function R($0,L0){return typeof $0==="object"&&$0!==null&&$0.key!=null?(W($0.key),x(""+$0.key)):L0.toString(36)}function h($0){switch($0.status){case"fulfilled":return $0.value;case"rejected":throw $0.reason;default:switch(typeof $0.status==="string"?$0.then(Y,Y):($0.status="pending",$0.then(function(L0){$0.status==="pending"&&($0.status="fulfilled",$0.value=L0)},function(L0){$0.status==="pending"&&($0.status="rejected",$0.reason=L0)})),$0.status){case"fulfilled":return $0.value;case"rejected":throw $0.reason}}throw $0}function P($0,L0,v0,m0,x0){var e0=typeof $0;if(e0==="undefined"||e0==="boolean")$0=null;var d0=!1;if($0===null)d0=!0;else switch(e0){case"bigint":case"string":case"number":d0=!0;break;case"object":switch($0.$$typeof){case n:case o:d0=!0;break;case j0:return d0=$0._init,P(d0($0._payload),L0,v0,m0,x0)}}if(d0){d0=$0,x0=x0(d0);var FA=m0===""?"."+R(d0,0):m0;return zA(x0)?(v0="",FA!=null&&(v0=FA.replace(o0,"$&/")+"/"),P(x0,L0,v0,"",function(oA){return oA})):x0!=null&&(k(x0)&&(x0.key!=null&&(d0&&d0.key===x0.key||W(x0.key)),v0=L(x0,v0+(x0.key==null||d0&&d0.key===x0.key?"":(""+x0.key).replace(o0,"$&/")+"/")+FA),m0!==""&&d0!=null&&k(d0)&&d0.key==null&&d0._store&&!d0._store.validated&&(v0._store.validated=2),x0=v0),L0.push(x0)),1}if(d0=0,FA=m0===""?".":m0+":",zA($0))for(var LA=0;LA<$0.length;LA++)m0=$0[LA],e0=FA+R(m0,LA),d0+=P(m0,L0,v0,e0,x0);else if(LA=Q($0),typeof LA==="function")for(LA===$0.entries&&(QA||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),QA=!0),$0=LA.call($0),LA=0;!(m0=$0.next()).done;)m0=m0.value,e0=FA+R(m0,LA++),d0+=P(m0,L0,v0,e0,x0);else if(e0==="object"){if(typeof $0.then==="function")return P(h($0),L0,v0,m0,x0);throw L0=String($0),Error("Objects are not valid as a React child (found: "+(L0==="[object Object]"?"object with keys {"+Object.keys($0).join(", ")+"}":L0)+"). If you meant to render a collection of children, use an array instead.")}return d0}function E($0,L0,v0){if($0==null)return $0;var m0=[],x0=0;return P($0,m0,"","",function(e0){return L0.call(v0,e0,x0++)}),m0}function S($0){if($0._status===-1){var L0=$0._ioInfo;L0!=null&&(L0.start=L0.end=performance.now()),L0=$0._result;var v0=L0();if(v0.then(function(x0){if($0._status===0||$0._status===-1){$0._status=1,$0._result=x0;var e0=$0._ioInfo;e0!=null&&(e0.end=performance.now()),v0.status===void 0&&(v0.status="fulfilled",v0.value=x0)}},function(x0){if($0._status===0||$0._status===-1){$0._status=2,$0._result=x0;var e0=$0._ioInfo;e0!=null&&(e0.end=performance.now()),v0.status===void 0&&(v0.status="rejected",v0.reason=x0)}}),L0=$0._ioInfo,L0!=null){L0.value=v0;var m0=v0.displayName;typeof m0==="string"&&(L0.name=m0)}$0._status===-1&&($0._status=0,$0._result=v0)}if($0._status===1)return L0=$0._result,L0===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
433
+ `;await A.session.run($);let Y=(await A.values(r0`SELECT id, hash, created_at FROM ${r0.identifier(B)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,X=[];for(let W of w)if(!Y||Number(Y[2])<W.folderMillis){for(let H of W.sql)X.push(A.run(r0.raw(H)));X.push(A.run(r0`INSERT INTO ${r0.identifier(B)} ("hash", "created_at") VALUES(${W.hash}, ${W.folderMillis})`))}await A.session.migrate(X)}var Mu=i(()=>{lLA();t5()});async function pLA(A,Q){let w=Q?.child("entity-migrate")??JQ.getInstance().child("entity-migrate"),{db:B,client:$,url:f}=m00(A);w.debug("Running entity database migrations...");try{await u00($,f);let X=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await eV(B,{migrationsFolder:X}),await c00($),w.debug("Entity database migrations completed successfully")}catch(Y){throw w.error("Entity database migration failed:",Y),Y}finally{$.close()}}var iLA=i(()=>{Mu();YI0();C9()});async function dLA(A,Q){let w=Q?.child("job-queue-migrate")??JQ.getInstance().child("job-queue-migrate"),{db:B,client:$,url:f}=C00(A);w.debug("Running job queue migrations...");try{await g00($,f);let X=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await eV(B,{migrationsFolder:X}),w.debug("Job queue migrations completed successfully")}catch(Y){throw w.error("Job queue migration failed:",Y),Y}finally{$.close()}}var nLA=i(()=>{Mu();pV0();C9()});async function rLA(A,Q){let w=Q?.child("conversation-migrate")??JQ.getInstance().child("conversation-migrate"),{db:B,client:$,url:f}=y00(A);w.debug("Running conversation database migrations...");try{if(f.startsWith("file:"))await $.execute("PRAGMA journal_mode = WAL");let X=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await eV(B,{migrationsFolder:X}),w.debug("Conversation database migrations completed successfully")}catch(Y){throw w.error("Conversation database migration failed:",Y),Y}finally{$.close()}}var oLA=i(()=>{Mu();sV0();C9()});async function sLA(A,Q){let w=Q?.child("runtime-state-migrate")??JQ.getInstance().child("runtime-state-migrate"),{db:B,client:$,url:f}=Z20(A);w.debug("Running runtime state migrations...");try{await W20($,f);let X=import.meta.url.includes("/dist/")?new URL("./migrations/runtime-state",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await eV(B,{migrationsFolder:X}),w.debug("Runtime state migrations completed successfully")}catch(Y){throw w.error("Runtime state migration failed:",Y),Y}finally{$.close()}}var aLA=i(()=>{Mu();C9();l_0()});import{mkdir as ZN0}from"fs/promises";function b20(A=process.env){return{dataDir:A.XDG_DATA_HOME??"./data",cacheDir:A.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function V20(A=process.env){return mV(b20(A))}async function I20(A=process.env){let Q=b20(A);try{await ZN0(Q.dataDir,{recursive:!0}),await ZN0(Q.cacheDir,{recursive:!0}),await ZN0(Q.distDir,{recursive:!0})}catch(w){let B=w instanceof Error&&w.message.includes("EACCES")?`Cannot create data directories \u2014 permission denied. Run from a writable directory or check permissions on ${Q.dataDir}`:`Cannot create data directories: ${w instanceof Error?w.message:String(w)}`;throw Error(B,{cause:w})}return mV(Q)}var J20=i(()=>{z20()});class Ou{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:()=>I20(),migrateEntities:pLA,migrateJobQueue:dLA,migrateConversations:rLA,migrateRuntimeState:sLA}}async runAllMigrations(A){this.logger.debug("Running database migrations...");let Q=await this.migrations.getStandardConfigWithDirectories();if(A?.database)Q.database.url=A.database;if(A?.jobQueueDatabase)Q.jobQueueDatabase.url=A.jobQueueDatabase;if(A?.conversationDatabase)Q.conversationDatabase.url=A.conversationDatabase;if(A?.runtimeStateDatabase)Q.runtimeStateDatabase.url=A.runtimeStateDatabase;await this.migrateEntityDatabase(Q),await this.migrateJobQueueDatabase(Q),await this.migrateConversationDatabase(Q),await this.migrateRuntimeStateDatabase(Q),this.logger.debug("All database migrations completed successfully")}async migrateEntityDatabase(A){this.logger.debug("Running entity database migrations..."),await this.migrations.migrateEntities({url:A.database.url,...A.database.authToken&&{authToken:A.database.authToken}},this.logger)}async migrateJobQueueDatabase(A){this.logger.debug("Running job queue database migrations..."),await this.migrations.migrateJobQueue({url:A.jobQueueDatabase.url,...A.jobQueueDatabase.authToken&&{authToken:A.jobQueueDatabase.authToken}},this.logger)}async migrateConversationDatabase(A){this.logger.debug("Running conversation database migrations..."),await this.migrations.migrateConversations({url:A.conversationDatabase.url,...A.conversationDatabase.authToken&&{authToken:A.conversationDatabase.authToken}},this.logger)}async migrateRuntimeStateDatabase(A){this.logger.debug("Running runtime state database migrations..."),await this.migrations.migrateRuntimeState({url:A.runtimeStateDatabase.url,...A.runtimeStateDatabase.authToken&&{authToken:A.runtimeStateDatabase.authToken}},this.logger)}}var WN0=i(()=>{iLA();nLA();oLA();aLA();J20()});function Cg2(){return process.env[hg2]}function tLA(){return Cg2()!=="production"}var hg2="NODE_ENV";var F20;var HN0=i(()=>{N0();F20=Z.object({theme:Z.object({primaryColor:Z.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:Z.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var AkA;var eLA=i(()=>{AkA={name:"@brains/chat-repl",version:"0.2.0-alpha.143",dependencies:{"@brains/plugins":"workspace:*",chalk:"^5.4.1",ink:"^7.0.6","ink-spinner":"^5.0.0","ink-text-input":"^6.0.0",marked:"^18.0.5",react:"^19.2.7"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17",typescript:"^6.0.3"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{dev:"tsc --watch",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"}});var tQ=O((yg2,L20)=>{(function(){function A($0,L0){Object.defineProperty(B.prototype,$0,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",L0[0],L0[1])}})}function Q($0){if($0===null||typeof $0!=="object")return null;return $0=k0&&$0[k0]||$0["@@iterator"],typeof $0==="function"?$0:null}function w($0,L0){$0=($0=$0.constructor)&&($0.displayName||$0.name)||"ReactClass";var v0=$0+"."+L0;_0[v0]||(console.error("Can't call %s on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the %s component.",L0,$0),_0[v0]=!0)}function B($0,L0,v0){this.props=$0,this.context=L0,this.refs=T0,this.updater=v0||P0}function $(){}function f($0,L0,v0){this.props=$0,this.context=L0,this.refs=T0,this.updater=v0||P0}function Y(){}function X($0){return""+$0}function W($0){try{X($0);var L0=!1}catch(x0){L0=!0}if(L0){L0=console;var v0=L0.error,m0=typeof Symbol==="function"&&Symbol.toStringTag&&$0[Symbol.toStringTag]||$0.constructor.name||"Object";return v0.call(L0,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",m0),X($0)}}function H($0){if($0==null)return null;if(typeof $0==="function")return $0.$$typeof===XA?null:$0.displayName||$0.name||null;if(typeof $0==="string")return $0;switch($0){case K0:return"Fragment";case X0:return"Profiler";case c:return"StrictMode";case S0:return"Suspense";case V0:return"SuspenseList";case C0:return"Activity"}if(typeof $0==="object")switch(typeof $0.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),$0.$$typeof){case o:return"Portal";case w0:return $0.displayName||"Context";case b0:return($0._context.displayName||"Context")+".Consumer";case h0:var L0=$0.render;return $0=$0.displayName,$0||($0=L0.displayName||L0.name||"",$0=$0!==""?"ForwardRef("+$0+")":"ForwardRef"),$0;case I0:return L0=$0.displayName||null,L0!==null?L0:H($0.type)||"Memo";case j0:L0=$0._payload,$0=$0._init;try{return H($0(L0))}catch(v0){}}return null}function K($0){if($0===K0)return"<>";if(typeof $0==="object"&&$0!==null&&$0.$$typeof===j0)return"<...>";try{var L0=H($0);return L0?"<"+L0+">":"<...>"}catch(v0){return"<...>"}}function U(){var $0=YA.A;return $0===null?null:$0.getOwner()}function D(){return Error("react-stack-top-frame")}function q($0){if(u0.call($0,"key")){var L0=Object.getOwnPropertyDescriptor($0,"key").get;if(L0&&L0.isReactWarning)return!1}return $0.key!==void 0}function b($0,L0){function v0(){UA||(UA=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",L0))}v0.isReactWarning=!0,Object.defineProperty($0,"key",{get:v0,configurable:!0})}function I(){var $0=H(this.type);return RA[$0]||(RA[$0]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),$0=this.props.ref,$0!==void 0?$0:null}function V($0,L0,v0,m0,x0,e0){var d0=v0.ref;return $0={$$typeof:n,type:$0,key:L0,props:v0,_owner:m0},(d0!==void 0?d0:null)!==null?Object.defineProperty($0,"ref",{enumerable:!1,get:I}):Object.defineProperty($0,"ref",{enumerable:!1,value:null}),$0._store={},Object.defineProperty($0._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty($0,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty($0,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:x0}),Object.defineProperty($0,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:e0}),Object.freeze&&(Object.freeze($0.props),Object.freeze($0)),$0}function L($0,L0){return L0=V($0.type,L0,$0.props,$0._owner,$0._debugStack,$0._debugTask),$0._store&&(L0._store.validated=$0._store.validated),L0}function N($0){k($0)?$0._store&&($0._store.validated=1):typeof $0==="object"&&$0!==null&&$0.$$typeof===j0&&($0._payload.status==="fulfilled"?k($0._payload.value)&&$0._payload.value._store&&($0._payload.value._store.validated=1):$0._store&&($0._store.validated=1))}function k($0){return typeof $0==="object"&&$0!==null&&$0.$$typeof===n}function x($0){var L0={"=":"=0",":":"=2"};return"$"+$0.replace(/[=:]/g,function(v0){return L0[v0]})}function R($0,L0){return typeof $0==="object"&&$0!==null&&$0.key!=null?(W($0.key),x(""+$0.key)):L0.toString(36)}function h($0){switch($0.status){case"fulfilled":return $0.value;case"rejected":throw $0.reason;default:switch(typeof $0.status==="string"?$0.then(Y,Y):($0.status="pending",$0.then(function(L0){$0.status==="pending"&&($0.status="fulfilled",$0.value=L0)},function(L0){$0.status==="pending"&&($0.status="rejected",$0.reason=L0)})),$0.status){case"fulfilled":return $0.value;case"rejected":throw $0.reason}}throw $0}function P($0,L0,v0,m0,x0){var e0=typeof $0;if(e0==="undefined"||e0==="boolean")$0=null;var d0=!1;if($0===null)d0=!0;else switch(e0){case"bigint":case"string":case"number":d0=!0;break;case"object":switch($0.$$typeof){case n:case o:d0=!0;break;case j0:return d0=$0._init,P(d0($0._payload),L0,v0,m0,x0)}}if(d0){d0=$0,x0=x0(d0);var FA=m0===""?"."+R(d0,0):m0;return zA(x0)?(v0="",FA!=null&&(v0=FA.replace(o0,"$&/")+"/"),P(x0,L0,v0,"",function(oA){return oA})):x0!=null&&(k(x0)&&(x0.key!=null&&(d0&&d0.key===x0.key||W(x0.key)),v0=L(x0,v0+(x0.key==null||d0&&d0.key===x0.key?"":(""+x0.key).replace(o0,"$&/")+"/")+FA),m0!==""&&d0!=null&&k(d0)&&d0.key==null&&d0._store&&!d0._store.validated&&(v0._store.validated=2),x0=v0),L0.push(x0)),1}if(d0=0,FA=m0===""?".":m0+":",zA($0))for(var LA=0;LA<$0.length;LA++)m0=$0[LA],e0=FA+R(m0,LA),d0+=P(m0,L0,v0,e0,x0);else if(LA=Q($0),typeof LA==="function")for(LA===$0.entries&&(QA||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),QA=!0),$0=LA.call($0),LA=0;!(m0=$0.next()).done;)m0=m0.value,e0=FA+R(m0,LA++),d0+=P(m0,L0,v0,e0,x0);else if(e0==="object"){if(typeof $0.then==="function")return P(h($0),L0,v0,m0,x0);throw L0=String($0),Error("Objects are not valid as a React child (found: "+(L0==="[object Object]"?"object with keys {"+Object.keys($0).join(", ")+"}":L0)+"). If you meant to render a collection of children, use an array instead.")}return d0}function E($0,L0,v0){if($0==null)return $0;var m0=[],x0=0;return P($0,m0,"","",function(e0){return L0.call(v0,e0,x0++)}),m0}function S($0){if($0._status===-1){var L0=$0._ioInfo;L0!=null&&(L0.start=L0.end=performance.now()),L0=$0._result;var v0=L0();if(v0.then(function(x0){if($0._status===0||$0._status===-1){$0._status=1,$0._result=x0;var e0=$0._ioInfo;e0!=null&&(e0.end=performance.now()),v0.status===void 0&&(v0.status="fulfilled",v0.value=x0)}},function(x0){if($0._status===0||$0._status===-1){$0._status=2,$0._result=x0;var e0=$0._ioInfo;e0!=null&&(e0.end=performance.now()),v0.status===void 0&&(v0.status="rejected",v0.reason=x0)}}),L0=$0._ioInfo,L0!=null){L0.value=v0;var m0=v0.displayName;typeof m0==="string"&&(L0.name=m0)}$0._status===-1&&($0._status=0,$0._result=v0)}if($0._status===1)return L0=$0._result,L0===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
434
434
 
435
435
  Your code should look like:
436
436
  const MyComponent = lazy(() => import('./MyComponent'))
@@ -1717,7 +1717,7 @@ Example bad output: "A dreamlike crystal formation glowing with ethereal light i
1717
1717
  Title: "${A.entityTitle??X}"
1718
1718
 
1719
1719
  Content:
1720
- ${K}`,sc2);H=`${B.trim()} ${L.imagePrompt}`}catch(L){this.logger.warn("AI prompt distillation failed, using fallback",{error:mA(L)})}}await this.reportProgress(w,{progress:dQ.PROCESS,message:"Generating image"});let U=this.context.identity.get(),D=this.context.identity.getProfile(),b=OOA(U,D)+H,I;try{I=await this.context.ai.generateImage(b,{...$&&{aspectRatio:$}})}catch(L){return this.logger.error("Image generation failed",{jobId:Q,error:mA(L)}),Q$.failure(L)}await this.reportProgress(w,{progress:dQ.GENERATE,message:"Creating image entity"});let V=mX.createImageEntity({dataUrl:I.dataUrl,title:X,status:"draft",attachmentType:"generated",...f&&{sourceEntityType:f},...Y&&{sourceEntityId:Y}});if(await Vf({entityService:this.context.entityService,entity:{...V,id:W}}),this.logger.debug("Created image entity",{imageId:W}),f&&Y){await this.reportProgress(w,{progress:dQ.SAVE,message:`Updating ${f} with cover image`});let L=await zk(this.context.entityService,f,Y,this.logger);if(!L)return Q$.failure(Error(`Target entity not found: ${f}/${Y}`));let N=nk(L,W);await this.context.entities.update(N),this.logger.debug("Updated target entity with cover image",{targetEntityType:f,targetEntityId:Y,imageId:W})}return await this.reportProgress(w,{progress:dQ.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:W,targetEntityType:f,targetEntityId:Y}),{success:!0,imageId:W}}catch(H){let K=mA(H);return this.logger.error("Image generation job failed",{jobId:Q,error:K}),await _D({entityService:this.context.entityService,entityType:"image",id:W,error:K}),Q$.failure(H)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}wA();N0();g6();J4();var tc2=Z.object({sourceEntityType:Z.string().min(1),sourceEntityId:Z.string().min(1),attachmentType:Z.string().min(1),imageId:Z.string().min(1),dedupKey:Z.string().min(1).optional(),replace:Z.boolean().optional(),targetEntityType:Z.string().min(1).optional(),targetEntityId:Z.string().min(1).optional(),targetImageField:Z.enum(["coverImageId","ogImageId"]).optional()});class hP0 extends aw{context;constructor(A,Q){super(Q,{schema:tc2,jobTypeName:"image-render-source"});this.context=A}async process(A,Q,w){this.logger.debug("Starting source image render job",{jobId:Q,sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,imageId:A.imageId});try{if(A.replace!==!0&&A.dedupKey){let Y=await this.findImageByDedupKey(A.dedupKey);if(Y)return await this.updateTarget(A,Y.id),await this.reportProgress(w,{progress:dQ.COMPLETE,message:"Reusing existing generated image"}),{success:!0,imageId:Y.id,reused:!0}}await this.reportProgress(w,{progress:dQ.PROCESS,message:"Rendering source image"});let B=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!B)return Q$.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if(B.type!=="image")return Q$.failure(Error(`Attachment provider returned ${B.type}; expected image`));await this.reportProgress(w,{progress:dQ.GENERATE,message:"Creating image entity"});let $=B.mimeType.split("/")[1]??"png",f=mX.createImageEntity({dataUrl:AN0(B.data.toString("base64"),$),title:A.imageId,status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,...A.dedupKey&&{dedupKey:A.dedupKey}});return await Vf({entityService:this.context.entityService,entity:{...f,id:A.imageId}}),await this.updateTarget(A,A.imageId),await this.reportProgress(w,{progress:dQ.COMPLETE,message:"Image render complete"}),{success:!0,imageId:A.imageId,reused:!1}}catch(B){let $=mA(B);return this.logger.error("Source image render job failed",{jobId:Q,error:$}),await _D({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:$}),Q$.failure(B)}}async findImageByDedupKey(A){return(await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{dedupKey:A}}}})).find((w)=>w.metadata.status!=="pending"&&w.metadata.status!=="failed")}async updateTarget(A,Q){if(!A.targetEntityType||!A.targetEntityId)return;let w=await zk(this.context.entityService,A.targetEntityType,A.targetEntityId,this.logger);if(!w)throw Error(`Target entity not found: ${A.targetEntityType}/${A.targetEntityId}`);let $=(A.targetImageField??"coverImageId")==="ogImageId"?ju(w,Q):nk(w,Q);await this.context.entities.update($)}}wA();N0();g6();J4();K2();var TR={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function dQ0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function nQ0(A){let Q=ec2(A.title,A.filename),w=Z1(Q);if(!w)throw Error("Could not derive an image id from the uploaded filename. Provide a title.");return{id:w,title:Q}}function xOA(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function ec2(A,Q){let w=A?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}var Al2=Z.object({uploadId:Z.string().min(1),imageId:Z.string().min(1).optional(),title:Z.string().optional()});class CP0 extends aw{context;constructor(A,Q){super(A,{schema:Al2,jobTypeName:"upload-promote"});this.context=Q}async process(A,Q,w){try{await this.reportProgress(w,{progress:10,message:"Reading uploaded image"});let B=await this.context.uploads.scoped(TR).read(A.uploadId);if(!dQ0(B.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let $=nQ0({filename:B.record.filename,...A.title!==void 0?{title:A.title}:{}}),f=A.imageId??$.id;await this.reportProgress(w,{progress:60,message:"Saving uploaded image"});let Y=new Date().toISOString(),X=mX.createImageEntity({dataUrl:xOA(B.record.mediaType,B.content),title:$.title,status:"draft",sourceUploadId:A.uploadId,sourceFilename:B.record.filename,sourceMediaType:B.record.mediaType,attachmentType:"uploaded"}),W=await Vf({entityService:this.context.entityService,entity:{id:f,...X,created:Y,updated:Y}});return await this.reportProgress(w,{progress:100,message:"Uploaded image promoted"}),{entityId:W.entityId,status:"created"}}catch(B){if(A.imageId)await _D({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:mA(B)});return Q$.failure(B)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var ROA={name:"@brains/image-plugin",version:"0.2.0-alpha.142",description:"Plugin for AI-powered image generation and management",dependencies:{"@brains/contracts":"workspace:*","@brains/entity-service":"workspace:*","@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},main:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var wl2="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",Bl2=Z.object({defaultAspectRatio:Z.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});function RK(A){let Q=A?.trim();if(!Q)return;return Q}function $l2(A){let Q=RK(A.prompt);if(Q)return Q;let w=RK(A.content);if(w&&!vP0(w))return w;return}function fl2(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return Z1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function vOA(A){let Q=RK(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return Z1(Q)}async function Yl2(A,Q){let w=`${Q.attachmentType}:${Q.sourceEntityType}:${Q.sourceEntityId}:resolved-attachment`,B=await A.entityService.getEntity({entityType:Q.sourceEntityType,id:Q.sourceEntityId});return B?`${w}:${B.contentHash}`:w}function gP0(A,Q="generated"){let w=encodeURIComponent(A);return{mediaType:"image/png",url:`/api/chat/attachments/image?id=${w}`,downloadUrl:`/api/chat/attachments/image?id=${w}&download=1`,filename:`${A}.png`,source:{entityType:"image",entityId:A,attachmentType:Q}}}function Xl2(A){let Q=encodeURIComponent(A.entityId);return{mediaType:A.mediaType,url:`/api/chat/attachments/image?id=${Q}`,downloadUrl:`/api/chat/attachments/image?id=${Q}&download=1`,filename:A.filename,source:{entityType:"image",entityId:A.entityId,attachmentType:"uploaded"}}}class yP0 extends nQ{entityType=mX.entityType;schema=_u;adapter=mX;constructor(A={}){super("image",ROA,A,Bl2)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,w){if(A.from?.kind===TR.refKind)return this.promoteUpload(A,w);let B=$l2(A),$=RK(A.targetEntityType),f=RK(A.targetEntityId),Y=$===this.entityType?f:void 0,X=A.from;if(X?.kind==="entity-attachment")return this.enqueueSourceImageRender({...A,from:X},w);if(!$||!f||Y){if(!B)return{kind:"continue",input:A};let D=RK(A.title)??Y,q=vOA({prompt:B,...D&&{title:D}});await this.createPendingImage(w,{id:q,title:D??B.slice(0,60).trim(),alt:D??B.slice(0,60).trim(),attachmentType:"generated"});let b=await w.jobs.enqueue({type:"image-generate",data:{prompt:B,...D&&{title:D}}});return{kind:"handled",result:{success:!0,data:{entityId:q,status:"generating",jobId:b,attachment:gP0(q)}}}}let W=await G4(w.entityService,$,f,this.logger,"Target entity");if(!W.ok)return{kind:"handled",result:{success:!1,error:W.error}};if(!B)return{kind:"continue",input:{...A,targetEntityId:W.entity.id}};let H=pQ0(W.entity.content),K=vOA({prompt:B,...A.title&&{title:A.title},targetEntityId:W.entity.id});await this.createPendingImage(w,{id:K,title:A.title??`cover-${W.entity.id}`,alt:A.title??`cover-${W.entity.id}`,attachmentType:"generated",sourceEntityType:$,sourceEntityId:W.entity.id});let U=await w.jobs.enqueue({type:"image-generate",data:{prompt:B,...A.title&&{title:A.title},targetEntityType:$,targetEntityId:W.entity.id,entityTitle:typeof W.entity.metadata.title==="string"?W.entity.metadata.title:W.entity.id,...H&&{entityContent:H}}});return{kind:"handled",result:{success:!0,data:{entityId:K,status:"generating",jobId:U,attachment:gP0(K)}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==TR.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let B=w.id,$;try{$=await Q.uploads.scoped(TR).readRecord(B)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!dQ0($.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let f;try{f=nQ0({filename:$.filename,...A.title!==void 0?{title:A.title}:{}})}catch(X){return{kind:"handled",result:{success:!1,error:X instanceof Error?X.message:String(X)}}}await this.createPendingImage(Q,{id:f.id,title:f.title,alt:f.title,sourceUploadId:B,sourceFilename:$.filename,sourceMediaType:$.mediaType,attachmentType:"uploaded"});let Y=await Q.jobs.enqueue({type:"upload-promote",data:{uploadId:B,imageId:f.id,title:f.title}});return{kind:"handled",result:{success:!0,data:{entityId:f.id,status:"generating",jobId:Y,attachment:Xl2({mediaType:$.mediaType,entityId:f.id,filename:$.filename})}}}}async enqueueSourceImageRender(A,Q){let w=RK(A.from.sourceEntityType),B=RK(A.from.sourceEntityId),$=RK(A.from.attachmentType);if(!w||!B||!$)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let f=await G4(Q.entityService,w,B,this.logger,"Source entity");if(!f.ok)return{kind:"handled",result:{success:!1,error:f.error}};let Y=RK(A.targetEntityType),X=RK(A.targetEntityId),W;if(Y&&X){let q=await G4(Q.entityService,Y,X,this.logger,"Target entity");if(!q.ok)return{kind:"handled",result:{success:!1,error:q.error}};W=q.entity.id}let H={sourceEntityType:w,sourceEntityId:f.entity.id,attachmentType:$},K=await Yl2(Q,H),U=fl2(H);await this.createPendingImage(Q,{id:U,title:U,alt:U,sourceEntityType:H.sourceEntityType,sourceEntityId:H.sourceEntityId,attachmentType:$,dedupKey:K});let D=await Q.jobs.enqueue({type:"image-render-source",data:{...H,imageId:U,dedupKey:K,...A.replace===!0&&{replace:!0},...Y&&{targetEntityType:Y},...W&&{targetEntityId:W},...$==="og-image"&&{targetImageField:"ogImageId"}}});return{kind:"handled",result:{success:!0,data:{entityId:U,status:"generating",jobId:D,attachment:gP0(U,$)}}}}async createPendingImage(A,Q){let w=new Date().toISOString(),B=mX.createImageEntity({dataUrl:wl2,title:Q.title,alt:Q.alt,status:"pending",attachmentType:Q.attachmentType,...Q.sourceEntityType&&{sourceEntityType:Q.sourceEntityType},...Q.sourceEntityId&&{sourceEntityId:Q.sourceEntityId},...Q.sourceUploadId&&{sourceUploadId:Q.sourceUploadId},...Q.sourceFilename&&{sourceFilename:Q.sourceFilename},...Q.sourceMediaType&&{sourceMediaType:Q.sourceMediaType},...Q.dedupKey&&{dedupKey:Q.dedupKey}});await bk({entityService:A.entityService,entity:{id:Q.id,...B,created:w,updated:w}})}async getInstructions(){return"Image entities store durable images. Standalone generated images are valid system_generate image calls with a prompt source and no target fields. A prompt source creates a new image; never use it to describe, analyze, or discuss an existing uploaded image. For uploaded-image discussion, answer directly from the attachment/context; if the user later asks to save that discussion as a note, create entityType note from prior-response or exact text. targetEntityType and targetEntityId are only for attaching the result to an existing entity as coverImageId. Cover images and OG/social preview images are distinct domain concepts: cover-image fields use coverImageId, while OG/Open Graph/social preview fields use ogImageId. Rendered OG/social preview images are deterministic attachment-source images with attachmentType og-image."}createGenerationHandler(A){return new iQ0(A,this.logger)}async onRegister(A){A.entities.registerUploadSaveHandler({entityType:this.entityType,mediaTypes:["image/*"],handler:async(w)=>{let B=await this.promoteUpload({entityType:this.entityType,...w.title!==void 0?{title:w.title}:{},from:w.upload},A);return B.kind==="handled"?B.result:{success:!1,error:"Image upload save was not handled"}}});let Q=new iQ0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new hP0(A,this.logger)),A.jobs.registerHandler("upload-promote",new CP0(this.logger.child("UploadPromotionJobHandler"),A))}}function Mc(A={}){return new yP0(A)}wA();import{StdioServerTransport as Wl2}from"@modelcontextprotocol/sdk/server/stdio.js";N0();var Zl2=Z.custom((A)=>typeof A==="object"&&A!==null&&("info"in A)&&typeof A.info==="function"&&("debug"in A)&&typeof A.debug==="function"&&("error"in A)&&typeof A.error==="function"&&("warn"in A)&&typeof A.warn==="function");function hOA(){return{info:(A,...Q)=>console.error(`[STDIO MCP] ${A}`,...Q),debug:(A,...Q)=>console.error(`[STDIO MCP DEBUG] ${A}`,...Q),error:(A,...Q)=>console.error(`[STDIO MCP ERROR] ${A}`,...Q),warn:(A,...Q)=>console.error(`[STDIO MCP WARN] ${A}`,...Q)}}function EP0(){return{info:(A,...Q)=>console.log(`[HTTP MCP] ${A}`,...Q),debug:(A,...Q)=>console.debug(`[HTTP MCP DEBUG] ${A}`,...Q),error:(A,...Q)=>console.error(`[HTTP MCP ERROR] ${A}`,...Q),warn:(A,...Q)=>console.warn(`[HTTP MCP WARN] ${A}`,...Q)}}function rQ0(A){let Q=Zl2.safeParse(A);if(Q.success)return{info:(w,...B)=>Q.data.info(w,...B),debug:(w,...B)=>Q.data.debug(w,...B),error:(w,...B)=>Q.data.error(w,...B),warn:(w,...B)=>Q.data.warn(w,...B)};return EP0()}class vK{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return vK.instance??=new vK(A),vK.instance}static resetInstance(){if(vK.instance)vK.instance.stop(),vK.instance=null}static createFresh(A){return new vK(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?rQ0(this.config.logger):hOA()}connectMCPServer(A){this.mcpServer=A,this.logger.debug("MCP server connected to stdio transport")}async start(){if(!this.mcpServer)throw Error("MCP server not connected. Call connectMCPServer() first.");if(this.transport)throw Error("Server is already running");this.logger.info("Starting stdio transport"),this.transport=new Wl2,await this.mcpServer.connect(this.transport),this.logger.info("Stdio transport started successfully")}stop(){if(this.logger.info("Stopping stdio transport"),this.transport)this.transport=null;this.logger.info("Stdio transport stopped")}isRunning(){return this.transport!==null}}import{randomUUID as Hl2,timingSafeEqual as Kl2}from"crypto";import{WebStandardStreamableHTTPServerTransport as Ul2}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as Dl2}from"@modelcontextprotocol/sdk/types.js";N0();var Gl2=1800000,zl2=60000,ql2={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, DELETE, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization, MCP-Session-Id, MCP-Protocol-Version, Last-Event-ID","Access-Control-Allow-Private-Network":"true","X-Content-Type-Options":"nosniff"},bl2=Z.looseObject({code:Z.string().optional()});function Vl2(A){let Q=new URL(A.url),B=A.headers.get("x-forwarded-proto")?.split(",")[0]?.trim(),$=A.headers.get("x-forwarded-host")??A.headers.get("host");if(!$)return Q.origin;return`${B??Q.protocol.replace(":","")}://${$}`}class Ez{static instance=null;transports={};sessionLastActivity=new Map;mcpServer=null;mcpTransport=null;server=null;boundPort=null;evictionTimer=null;config;logger;authConfig;sessionIdleTtlMs;constructor(A={}){if(this.config=A,this.logger=this.config.logger?rQ0(this.config.logger):EP0(),this.authConfig=A.auth??{},this.sessionIdleTtlMs=A.sessionIdleTtlMs??Gl2,this.evictionTimer=setInterval(()=>this.evictIdleSessions(),Math.min(this.sessionIdleTtlMs,zl2)),this.evictionTimer.unref(),!this.authConfig.disabled&&!this.authConfig.token&&!this.authConfig.verifyBearerToken)throw Error("MCP HTTP transport requires an auth token or bearer token verifier. Set MCP_AUTH_TOKEN, configure OAuth verification, or pass auth: { disabled: true } for local dev.")}static getInstance(A){return Ez.instance??=new Ez(A),Ez.instance}static resetInstance(){Ez.instance=null}static createFresh(A){return new Ez(A)}withCors(A){let Q=new Headers(A.headers);for(let[w,B]of Object.entries(ql2))Q.set(w,B);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}createJsonResponse(A,Q=200){return this.withCors(new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json"}}))}createTextResponse(A,Q=200){return this.withCors(new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8"}}))}getAuthErrorResponse(A,Q=401,w){let B=this.createJsonResponse({jsonrpc:"2.0",error:{code:-32001,message:A},id:null},Q);if(!w)return B;let $=new Headers(B.headers);return $.set("WWW-Authenticate",w),new Response(B.body,{status:B.status,statusText:B.statusText,headers:$})}getBearerChallenge(A,Q={}){let w={...this.authConfig.token?{}:{resource_metadata:`${Vl2(A)}/.well-known/oauth-protected-resource`},...Q};return`Bearer ${Object.entries(w).map(([$,f])=>`${$}="${Il2(f)}"`).join(", ")}`}async authenticate(A){let Q=new URL(A.url).pathname;if(Q==="/health"||Q==="/status"||Q==="/mcp"&&A.method==="OPTIONS")return null;if(this.authConfig.disabled)return null;let w=A.headers.get("authorization");if(!w?.startsWith("Bearer "))return this.logger.warn("Authentication failed: Missing Bearer token"),this.getAuthErrorResponse("Unauthorized: Bearer token required",401,this.getBearerChallenge(A,{realm:"mcp"}));if(this.authConfig.token){let B=w.substring(7);if(!Jl2(B,this.authConfig.token))return this.logger.warn("Authentication failed: Invalid token"),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}));return this.logger.debug("Authentication successful"),null}try{let B=await this.authConfig.verifyBearerToken?.(A);if(!B)return this.logger.warn("Authentication failed: Invalid token"),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}));let $=this.authConfig.requiredScopes??[],f=$.filter((Y)=>!B.scope?.includes(Y));if(f.length>0)return this.logger.warn(`Authentication failed: Missing required scope(s): ${f.join(", ")}`),this.getAuthErrorResponse("Forbidden: Missing required scope",403,this.getBearerChallenge(A,{error:"insufficient_scope",scope:$.join(" ")}));return this.logger.debug("Authentication successful"),null}catch(B){return this.logger.warn("Authentication failed: Invalid token",B),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}))}}touchSession(A){this.sessionLastActivity.set(A,Date.now())}evictIdleSessions(){let A=Date.now();for(let[Q,w]of this.sessionLastActivity){if(A-w<this.sessionIdleTtlMs)continue;this.logger.info(`Evicting idle session ${Q}`),this.sessionLastActivity.delete(Q);let B=this.transports[Q];if(B)delete this.transports[Q],B.close().catch(($)=>{this.logger.error(`Error closing idle transport for session ${Q}:`,$)})}}async handleMcpRequest(A){let Q=A.headers.get("mcp-session-id")??void 0;if(A.method==="GET"){if(!Q||!this.transports[Q])return this.createTextResponse("Invalid or missing session ID",400);return this.touchSession(Q),this.logger.debug(`GET /mcp - SSE stream for session ${Q}`),this.withCors(await this.transports[Q].handleRequest(A))}if(A.method==="DELETE"){if(!Q||!this.transports[Q])return this.createTextResponse("Invalid or missing session ID",400);return this.logger.info(`DELETE /mcp - Terminating session ${Q}`),this.withCors(await this.transports[Q].handleRequest(A))}if(A.method==="OPTIONS")return this.withCors(new Response(null,{status:204}));if(A.method!=="POST")return this.createTextResponse("Method Not Allowed",405);if(!this.mcpServer)return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32603,message:"Service Unavailable: MCP server not connected"},id:null},503);let w;try{w=await A.json()}catch{return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32700,message:"Parse error: Invalid JSON body"},id:null},400)}this.logger.debug(`POST /mcp - Session: ${Q??"new"}`);try{let B;if(Q&&this.transports[Q])B=this.transports[Q],this.touchSession(Q);else if(!Q&&Dl2(w))B=new Ul2({sessionIdGenerator:()=>Hl2(),onsessioninitialized:(f)=>{this.logger.info(`Session initialized: ${f}`),this.transports[f]=B,this.touchSession(f)},onsessionclosed:(f)=>{this.logger.info(`Session closed: ${f}`),delete this.transports[f],this.sessionLastActivity.delete(f)}}),await(this.mcpTransport?this.mcpTransport.createMcpServer():this.mcpServer).connect(B);else return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32000,message:"Bad Request: Server not initialized"},id:null},400);return this.withCors(await B.handleRequest(A,{parsedBody:w}))}catch(B){return this.logger.error("MCP transport error:",B),this.createJsonResponse({jsonrpc:"2.0",error:{code:-32603,message:"Internal error"}},500)}}async handleRequest(A){let Q=new URL(A.url);this.logger.debug(`${A.method} ${Q.pathname}`);let w=await this.authenticate(A);if(w)return w;if(Q.pathname==="/health")return this.createJsonResponse({status:"ok",transport:"streamable-http",timestamp:new Date().toISOString()});if(Q.pathname==="/status")return this.createJsonResponse({status:"ok",sessions:Object.keys(this.transports).length});if(Q.pathname==="/mcp")return this.handleMcpRequest(A);return this.createTextResponse("Not Found",404)}connectMCPServer(A,Q){this.mcpServer=A,this.mcpTransport=Q??null,this.logger.debug("MCP server connected to StreamableHTTP transport")}async start(){if(this.server)throw Error("Server is already running");let A=Number(this.config.port??3333),Q=this.config.host??"0.0.0.0";try{this.server=Bun.serve({port:A,hostname:Q,fetch:(w)=>this.handleRequest(w)}),this.boundPort=this.server.port??A,this.logger.info(`StreamableHTTP server listening on http://${Q}:${this.boundPort}/mcp`)}catch(w){let B=bl2.safeParse(w);if(B.success&&B.data.code==="EADDRINUSE")this.logger.error(`Port ${A} is already in use`);throw w}}async stop(){if(this.evictionTimer)clearInterval(this.evictionTimer),this.evictionTimer=null;this.sessionLastActivity.clear();for(let A in this.transports)try{let Q=this.transports[A];if(Q)this.logger.debug(`Closing transport for session ${A}`),await Q.close(),delete this.transports[A]}catch(Q){this.logger.error(`Error closing transport for session ${A}:`,Q)}if(this.server)await this.server.stop(),this.logger.info("StreamableHTTP server stopped"),this.server=null,this.boundPort=null}getPort(){if(this.boundPort===null)throw Error("Server is not running");return this.boundPort}getApp(){return{fetch:(A)=>this.handleRequest(A)}}isRunning(){return this.server!==null}getSessionCount(){return Object.keys(this.transports).length}}function Il2(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}function Jl2(A,Q){let w=Buffer.from(A),B=Buffer.from(Q);if(w.length!==B.length)return!1;return Kl2(w,B)}import{randomUUID as Pl2}from"crypto";import{chmod as Fl2,mkdir as Ll2,readFile as kl2,rename as COA,writeFile as _l2}from"fs/promises";import{dirname as Nl2}from"path";class jf{filePath;parse;empty;logError;onCorrupt;writeQueue=Promise.resolve();constructor(A){this.filePath=A.filePath,this.parse=A.parse,this.empty=A.empty,this.onCorrupt=A.onCorrupt??"quarantine",this.logError=A.logError??((Q,w)=>{console.error(Q,w)})}async enqueueWrite(A){return this.writeQueue=this.writeQueue.then(A,A),this.writeQueue}async read(){let A;try{A=await kl2(this.filePath,"utf8")}catch(Q){if(Q.code==="ENOENT")return this.empty();throw Q}try{return this.parse(JSON.parse(A))}catch(Q){if(this.onCorrupt==="throw")throw Error(`Corrupt JSON store at ${this.filePath}; refusing to start empty. Inspect or remove the file to proceed.`,{cause:Q});return await this.quarantineCorruptFile(Q),this.empty()}}async write(A){await Ll2(Nl2(this.filePath),{recursive:!0,mode:448});let Q=`${this.filePath}.tmp`;await _l2(Q,`${JSON.stringify(A,null,2)}
1720
+ ${K}`,sc2);H=`${B.trim()} ${L.imagePrompt}`}catch(L){this.logger.warn("AI prompt distillation failed, using fallback",{error:mA(L)})}}await this.reportProgress(w,{progress:dQ.PROCESS,message:"Generating image"});let U=this.context.identity.get(),D=this.context.identity.getProfile(),b=OOA(U,D)+H,I;try{I=await this.context.ai.generateImage(b,{...$&&{aspectRatio:$}})}catch(L){return this.logger.error("Image generation failed",{jobId:Q,error:mA(L)}),Q$.failure(L)}await this.reportProgress(w,{progress:dQ.GENERATE,message:"Creating image entity"});let V=mX.createImageEntity({dataUrl:I.dataUrl,title:X,status:"draft",attachmentType:"generated",...f&&{sourceEntityType:f},...Y&&{sourceEntityId:Y}});if(await Vf({entityService:this.context.entityService,entity:{...V,id:W}}),this.logger.debug("Created image entity",{imageId:W}),f&&Y){await this.reportProgress(w,{progress:dQ.SAVE,message:`Updating ${f} with cover image`});let L=await zk(this.context.entityService,f,Y,this.logger);if(!L)return Q$.failure(Error(`Target entity not found: ${f}/${Y}`));let N=nk(L,W);await this.context.entities.update(N),this.logger.debug("Updated target entity with cover image",{targetEntityType:f,targetEntityId:Y,imageId:W})}return await this.reportProgress(w,{progress:dQ.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:W,targetEntityType:f,targetEntityId:Y}),{success:!0,imageId:W}}catch(H){let K=mA(H);return this.logger.error("Image generation job failed",{jobId:Q,error:K}),await _D({entityService:this.context.entityService,entityType:"image",id:W,error:K}),Q$.failure(H)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}wA();N0();g6();J4();var tc2=Z.object({sourceEntityType:Z.string().min(1),sourceEntityId:Z.string().min(1),attachmentType:Z.string().min(1),imageId:Z.string().min(1),dedupKey:Z.string().min(1).optional(),replace:Z.boolean().optional(),targetEntityType:Z.string().min(1).optional(),targetEntityId:Z.string().min(1).optional(),targetImageField:Z.enum(["coverImageId","ogImageId"]).optional()});class hP0 extends aw{context;constructor(A,Q){super(Q,{schema:tc2,jobTypeName:"image-render-source"});this.context=A}async process(A,Q,w){this.logger.debug("Starting source image render job",{jobId:Q,sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,imageId:A.imageId});try{if(A.replace!==!0&&A.dedupKey){let Y=await this.findImageByDedupKey(A.dedupKey);if(Y)return await this.updateTarget(A,Y.id),await this.reportProgress(w,{progress:dQ.COMPLETE,message:"Reusing existing generated image"}),{success:!0,imageId:Y.id,reused:!0}}await this.reportProgress(w,{progress:dQ.PROCESS,message:"Rendering source image"});let B=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!B)return Q$.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if(B.type!=="image")return Q$.failure(Error(`Attachment provider returned ${B.type}; expected image`));await this.reportProgress(w,{progress:dQ.GENERATE,message:"Creating image entity"});let $=B.mimeType.split("/")[1]??"png",f=mX.createImageEntity({dataUrl:AN0(B.data.toString("base64"),$),title:A.imageId,status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,...A.dedupKey&&{dedupKey:A.dedupKey}});return await Vf({entityService:this.context.entityService,entity:{...f,id:A.imageId}}),await this.updateTarget(A,A.imageId),await this.reportProgress(w,{progress:dQ.COMPLETE,message:"Image render complete"}),{success:!0,imageId:A.imageId,reused:!1}}catch(B){let $=mA(B);return this.logger.error("Source image render job failed",{jobId:Q,error:$}),await _D({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:$}),Q$.failure(B)}}async findImageByDedupKey(A){return(await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{dedupKey:A}}}})).find((w)=>w.metadata.status!=="pending"&&w.metadata.status!=="failed")}async updateTarget(A,Q){if(!A.targetEntityType||!A.targetEntityId)return;let w=await zk(this.context.entityService,A.targetEntityType,A.targetEntityId,this.logger);if(!w)throw Error(`Target entity not found: ${A.targetEntityType}/${A.targetEntityId}`);let $=(A.targetImageField??"coverImageId")==="ogImageId"?ju(w,Q):nk(w,Q);await this.context.entities.update($)}}wA();N0();g6();J4();K2();var TR={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function dQ0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function nQ0(A){let Q=ec2(A.title,A.filename),w=Z1(Q);if(!w)throw Error("Could not derive an image id from the uploaded filename. Provide a title.");return{id:w,title:Q}}function xOA(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function ec2(A,Q){let w=A?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}var Al2=Z.object({uploadId:Z.string().min(1),imageId:Z.string().min(1).optional(),title:Z.string().optional()});class CP0 extends aw{context;constructor(A,Q){super(A,{schema:Al2,jobTypeName:"upload-promote"});this.context=Q}async process(A,Q,w){try{await this.reportProgress(w,{progress:10,message:"Reading uploaded image"});let B=await this.context.uploads.scoped(TR).read(A.uploadId);if(!dQ0(B.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let $=nQ0({filename:B.record.filename,...A.title!==void 0?{title:A.title}:{}}),f=A.imageId??$.id;await this.reportProgress(w,{progress:60,message:"Saving uploaded image"});let Y=new Date().toISOString(),X=mX.createImageEntity({dataUrl:xOA(B.record.mediaType,B.content),title:$.title,status:"draft",sourceUploadId:A.uploadId,sourceFilename:B.record.filename,sourceMediaType:B.record.mediaType,attachmentType:"uploaded"}),W=await Vf({entityService:this.context.entityService,entity:{id:f,...X,created:Y,updated:Y}});return await this.reportProgress(w,{progress:100,message:"Uploaded image promoted"}),{entityId:W.entityId,status:"created"}}catch(B){if(A.imageId)await _D({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:mA(B)});return Q$.failure(B)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var ROA={name:"@brains/image-plugin",version:"0.2.0-alpha.143",description:"Plugin for AI-powered image generation and management",dependencies:{"@brains/contracts":"workspace:*","@brains/entity-service":"workspace:*","@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},main:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var wl2="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",Bl2=Z.object({defaultAspectRatio:Z.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});function RK(A){let Q=A?.trim();if(!Q)return;return Q}function $l2(A){let Q=RK(A.prompt);if(Q)return Q;let w=RK(A.content);if(w&&!vP0(w))return w;return}function fl2(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return Z1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function vOA(A){let Q=RK(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return Z1(Q)}async function Yl2(A,Q){let w=`${Q.attachmentType}:${Q.sourceEntityType}:${Q.sourceEntityId}:resolved-attachment`,B=await A.entityService.getEntity({entityType:Q.sourceEntityType,id:Q.sourceEntityId});return B?`${w}:${B.contentHash}`:w}function gP0(A,Q="generated"){let w=encodeURIComponent(A);return{mediaType:"image/png",url:`/api/chat/attachments/image?id=${w}`,downloadUrl:`/api/chat/attachments/image?id=${w}&download=1`,filename:`${A}.png`,source:{entityType:"image",entityId:A,attachmentType:Q}}}function Xl2(A){let Q=encodeURIComponent(A.entityId);return{mediaType:A.mediaType,url:`/api/chat/attachments/image?id=${Q}`,downloadUrl:`/api/chat/attachments/image?id=${Q}&download=1`,filename:A.filename,source:{entityType:"image",entityId:A.entityId,attachmentType:"uploaded"}}}class yP0 extends nQ{entityType=mX.entityType;schema=_u;adapter=mX;constructor(A={}){super("image",ROA,A,Bl2)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,w){if(A.from?.kind===TR.refKind)return this.promoteUpload(A,w);let B=$l2(A),$=RK(A.targetEntityType),f=RK(A.targetEntityId),Y=$===this.entityType?f:void 0,X=A.from;if(X?.kind==="entity-attachment")return this.enqueueSourceImageRender({...A,from:X},w);if(!$||!f||Y){if(!B)return{kind:"continue",input:A};let D=RK(A.title)??Y,q=vOA({prompt:B,...D&&{title:D}});await this.createPendingImage(w,{id:q,title:D??B.slice(0,60).trim(),alt:D??B.slice(0,60).trim(),attachmentType:"generated"});let b=await w.jobs.enqueue({type:"image-generate",data:{prompt:B,...D&&{title:D}}});return{kind:"handled",result:{success:!0,data:{entityId:q,status:"generating",jobId:b,attachment:gP0(q)}}}}let W=await G4(w.entityService,$,f,this.logger,"Target entity");if(!W.ok)return{kind:"handled",result:{success:!1,error:W.error}};if(!B)return{kind:"continue",input:{...A,targetEntityId:W.entity.id}};let H=pQ0(W.entity.content),K=vOA({prompt:B,...A.title&&{title:A.title},targetEntityId:W.entity.id});await this.createPendingImage(w,{id:K,title:A.title??`cover-${W.entity.id}`,alt:A.title??`cover-${W.entity.id}`,attachmentType:"generated",sourceEntityType:$,sourceEntityId:W.entity.id});let U=await w.jobs.enqueue({type:"image-generate",data:{prompt:B,...A.title&&{title:A.title},targetEntityType:$,targetEntityId:W.entity.id,entityTitle:typeof W.entity.metadata.title==="string"?W.entity.metadata.title:W.entity.id,...H&&{entityContent:H}}});return{kind:"handled",result:{success:!0,data:{entityId:K,status:"generating",jobId:U,attachment:gP0(K)}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==TR.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let B=w.id,$;try{$=await Q.uploads.scoped(TR).readRecord(B)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!dQ0($.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let f;try{f=nQ0({filename:$.filename,...A.title!==void 0?{title:A.title}:{}})}catch(X){return{kind:"handled",result:{success:!1,error:X instanceof Error?X.message:String(X)}}}await this.createPendingImage(Q,{id:f.id,title:f.title,alt:f.title,sourceUploadId:B,sourceFilename:$.filename,sourceMediaType:$.mediaType,attachmentType:"uploaded"});let Y=await Q.jobs.enqueue({type:"upload-promote",data:{uploadId:B,imageId:f.id,title:f.title}});return{kind:"handled",result:{success:!0,data:{entityId:f.id,status:"generating",jobId:Y,attachment:Xl2({mediaType:$.mediaType,entityId:f.id,filename:$.filename})}}}}async enqueueSourceImageRender(A,Q){let w=RK(A.from.sourceEntityType),B=RK(A.from.sourceEntityId),$=RK(A.from.attachmentType);if(!w||!B||!$)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let f=await G4(Q.entityService,w,B,this.logger,"Source entity");if(!f.ok)return{kind:"handled",result:{success:!1,error:f.error}};let Y=RK(A.targetEntityType),X=RK(A.targetEntityId),W;if(Y&&X){let q=await G4(Q.entityService,Y,X,this.logger,"Target entity");if(!q.ok)return{kind:"handled",result:{success:!1,error:q.error}};W=q.entity.id}let H={sourceEntityType:w,sourceEntityId:f.entity.id,attachmentType:$},K=await Yl2(Q,H),U=fl2(H);await this.createPendingImage(Q,{id:U,title:U,alt:U,sourceEntityType:H.sourceEntityType,sourceEntityId:H.sourceEntityId,attachmentType:$,dedupKey:K});let D=await Q.jobs.enqueue({type:"image-render-source",data:{...H,imageId:U,dedupKey:K,...A.replace===!0&&{replace:!0},...Y&&{targetEntityType:Y},...W&&{targetEntityId:W},...$==="og-image"&&{targetImageField:"ogImageId"}}});return{kind:"handled",result:{success:!0,data:{entityId:U,status:"generating",jobId:D,attachment:gP0(U,$)}}}}async createPendingImage(A,Q){let w=new Date().toISOString(),B=mX.createImageEntity({dataUrl:wl2,title:Q.title,alt:Q.alt,status:"pending",attachmentType:Q.attachmentType,...Q.sourceEntityType&&{sourceEntityType:Q.sourceEntityType},...Q.sourceEntityId&&{sourceEntityId:Q.sourceEntityId},...Q.sourceUploadId&&{sourceUploadId:Q.sourceUploadId},...Q.sourceFilename&&{sourceFilename:Q.sourceFilename},...Q.sourceMediaType&&{sourceMediaType:Q.sourceMediaType},...Q.dedupKey&&{dedupKey:Q.dedupKey}});await bk({entityService:A.entityService,entity:{id:Q.id,...B,created:w,updated:w}})}async getInstructions(){return"Image entities store durable images. Standalone generated images are valid system_generate image calls with a prompt source and no target fields. A prompt source creates a new image; never use it to describe, analyze, or discuss an existing uploaded image. For uploaded-image discussion, answer directly from the attachment/context; if the user later asks to save that discussion as a note, create entityType note from prior-response or exact text. targetEntityType and targetEntityId are only for attaching the result to an existing entity as coverImageId. Cover images and OG/social preview images are distinct domain concepts: cover-image fields use coverImageId, while OG/Open Graph/social preview fields use ogImageId. Rendered OG/social preview images are deterministic attachment-source images with attachmentType og-image."}createGenerationHandler(A){return new iQ0(A,this.logger)}async onRegister(A){A.entities.registerUploadSaveHandler({entityType:this.entityType,mediaTypes:["image/*"],handler:async(w)=>{let B=await this.promoteUpload({entityType:this.entityType,...w.title!==void 0?{title:w.title}:{},from:w.upload},A);return B.kind==="handled"?B.result:{success:!1,error:"Image upload save was not handled"}}});let Q=new iQ0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new hP0(A,this.logger)),A.jobs.registerHandler("upload-promote",new CP0(this.logger.child("UploadPromotionJobHandler"),A))}}function Mc(A={}){return new yP0(A)}wA();import{StdioServerTransport as Wl2}from"@modelcontextprotocol/sdk/server/stdio.js";N0();var Zl2=Z.custom((A)=>typeof A==="object"&&A!==null&&("info"in A)&&typeof A.info==="function"&&("debug"in A)&&typeof A.debug==="function"&&("error"in A)&&typeof A.error==="function"&&("warn"in A)&&typeof A.warn==="function");function hOA(){return{info:(A,...Q)=>console.error(`[STDIO MCP] ${A}`,...Q),debug:(A,...Q)=>console.error(`[STDIO MCP DEBUG] ${A}`,...Q),error:(A,...Q)=>console.error(`[STDIO MCP ERROR] ${A}`,...Q),warn:(A,...Q)=>console.error(`[STDIO MCP WARN] ${A}`,...Q)}}function EP0(){return{info:(A,...Q)=>console.log(`[HTTP MCP] ${A}`,...Q),debug:(A,...Q)=>console.debug(`[HTTP MCP DEBUG] ${A}`,...Q),error:(A,...Q)=>console.error(`[HTTP MCP ERROR] ${A}`,...Q),warn:(A,...Q)=>console.warn(`[HTTP MCP WARN] ${A}`,...Q)}}function rQ0(A){let Q=Zl2.safeParse(A);if(Q.success)return{info:(w,...B)=>Q.data.info(w,...B),debug:(w,...B)=>Q.data.debug(w,...B),error:(w,...B)=>Q.data.error(w,...B),warn:(w,...B)=>Q.data.warn(w,...B)};return EP0()}class vK{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return vK.instance??=new vK(A),vK.instance}static resetInstance(){if(vK.instance)vK.instance.stop(),vK.instance=null}static createFresh(A){return new vK(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?rQ0(this.config.logger):hOA()}connectMCPServer(A){this.mcpServer=A,this.logger.debug("MCP server connected to stdio transport")}async start(){if(!this.mcpServer)throw Error("MCP server not connected. Call connectMCPServer() first.");if(this.transport)throw Error("Server is already running");this.logger.info("Starting stdio transport"),this.transport=new Wl2,await this.mcpServer.connect(this.transport),this.logger.info("Stdio transport started successfully")}stop(){if(this.logger.info("Stopping stdio transport"),this.transport)this.transport=null;this.logger.info("Stdio transport stopped")}isRunning(){return this.transport!==null}}import{randomUUID as Hl2,timingSafeEqual as Kl2}from"crypto";import{WebStandardStreamableHTTPServerTransport as Ul2}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as Dl2}from"@modelcontextprotocol/sdk/types.js";N0();var Gl2=1800000,zl2=60000,ql2={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, DELETE, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization, MCP-Session-Id, MCP-Protocol-Version, Last-Event-ID","Access-Control-Allow-Private-Network":"true","X-Content-Type-Options":"nosniff"},bl2=Z.looseObject({code:Z.string().optional()});function Vl2(A){let Q=new URL(A.url),B=A.headers.get("x-forwarded-proto")?.split(",")[0]?.trim(),$=A.headers.get("x-forwarded-host")??A.headers.get("host");if(!$)return Q.origin;return`${B??Q.protocol.replace(":","")}://${$}`}class Ez{static instance=null;transports={};sessionLastActivity=new Map;mcpServer=null;mcpTransport=null;server=null;boundPort=null;evictionTimer=null;config;logger;authConfig;sessionIdleTtlMs;constructor(A={}){if(this.config=A,this.logger=this.config.logger?rQ0(this.config.logger):EP0(),this.authConfig=A.auth??{},this.sessionIdleTtlMs=A.sessionIdleTtlMs??Gl2,this.evictionTimer=setInterval(()=>this.evictIdleSessions(),Math.min(this.sessionIdleTtlMs,zl2)),this.evictionTimer.unref(),!this.authConfig.disabled&&!this.authConfig.token&&!this.authConfig.verifyBearerToken)throw Error("MCP HTTP transport requires an auth token or bearer token verifier. Set MCP_AUTH_TOKEN, configure OAuth verification, or pass auth: { disabled: true } for local dev.")}static getInstance(A){return Ez.instance??=new Ez(A),Ez.instance}static resetInstance(){Ez.instance=null}static createFresh(A){return new Ez(A)}withCors(A){let Q=new Headers(A.headers);for(let[w,B]of Object.entries(ql2))Q.set(w,B);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}createJsonResponse(A,Q=200){return this.withCors(new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json"}}))}createTextResponse(A,Q=200){return this.withCors(new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8"}}))}getAuthErrorResponse(A,Q=401,w){let B=this.createJsonResponse({jsonrpc:"2.0",error:{code:-32001,message:A},id:null},Q);if(!w)return B;let $=new Headers(B.headers);return $.set("WWW-Authenticate",w),new Response(B.body,{status:B.status,statusText:B.statusText,headers:$})}getBearerChallenge(A,Q={}){let w={...this.authConfig.token?{}:{resource_metadata:`${Vl2(A)}/.well-known/oauth-protected-resource`},...Q};return`Bearer ${Object.entries(w).map(([$,f])=>`${$}="${Il2(f)}"`).join(", ")}`}async authenticate(A){let Q=new URL(A.url).pathname;if(Q==="/health"||Q==="/status"||Q==="/mcp"&&A.method==="OPTIONS")return null;if(this.authConfig.disabled)return null;let w=A.headers.get("authorization");if(!w?.startsWith("Bearer "))return this.logger.warn("Authentication failed: Missing Bearer token"),this.getAuthErrorResponse("Unauthorized: Bearer token required",401,this.getBearerChallenge(A,{realm:"mcp"}));if(this.authConfig.token){let B=w.substring(7);if(!Jl2(B,this.authConfig.token))return this.logger.warn("Authentication failed: Invalid token"),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}));return this.logger.debug("Authentication successful"),null}try{let B=await this.authConfig.verifyBearerToken?.(A);if(!B)return this.logger.warn("Authentication failed: Invalid token"),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}));let $=this.authConfig.requiredScopes??[],f=$.filter((Y)=>!B.scope?.includes(Y));if(f.length>0)return this.logger.warn(`Authentication failed: Missing required scope(s): ${f.join(", ")}`),this.getAuthErrorResponse("Forbidden: Missing required scope",403,this.getBearerChallenge(A,{error:"insufficient_scope",scope:$.join(" ")}));return this.logger.debug("Authentication successful"),null}catch(B){return this.logger.warn("Authentication failed: Invalid token",B),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}))}}touchSession(A){this.sessionLastActivity.set(A,Date.now())}evictIdleSessions(){let A=Date.now();for(let[Q,w]of this.sessionLastActivity){if(A-w<this.sessionIdleTtlMs)continue;this.logger.info(`Evicting idle session ${Q}`),this.sessionLastActivity.delete(Q);let B=this.transports[Q];if(B)delete this.transports[Q],B.close().catch(($)=>{this.logger.error(`Error closing idle transport for session ${Q}:`,$)})}}async handleMcpRequest(A){let Q=A.headers.get("mcp-session-id")??void 0;if(A.method==="GET"){if(!Q||!this.transports[Q])return this.createTextResponse("Invalid or missing session ID",400);return this.touchSession(Q),this.logger.debug(`GET /mcp - SSE stream for session ${Q}`),this.withCors(await this.transports[Q].handleRequest(A))}if(A.method==="DELETE"){if(!Q||!this.transports[Q])return this.createTextResponse("Invalid or missing session ID",400);return this.logger.info(`DELETE /mcp - Terminating session ${Q}`),this.withCors(await this.transports[Q].handleRequest(A))}if(A.method==="OPTIONS")return this.withCors(new Response(null,{status:204}));if(A.method!=="POST")return this.createTextResponse("Method Not Allowed",405);if(!this.mcpServer)return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32603,message:"Service Unavailable: MCP server not connected"},id:null},503);let w;try{w=await A.json()}catch{return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32700,message:"Parse error: Invalid JSON body"},id:null},400)}this.logger.debug(`POST /mcp - Session: ${Q??"new"}`);try{let B;if(Q&&this.transports[Q])B=this.transports[Q],this.touchSession(Q);else if(!Q&&Dl2(w))B=new Ul2({sessionIdGenerator:()=>Hl2(),onsessioninitialized:(f)=>{this.logger.info(`Session initialized: ${f}`),this.transports[f]=B,this.touchSession(f)},onsessionclosed:(f)=>{this.logger.info(`Session closed: ${f}`),delete this.transports[f],this.sessionLastActivity.delete(f)}}),await(this.mcpTransport?this.mcpTransport.createMcpServer():this.mcpServer).connect(B);else return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32000,message:"Bad Request: Server not initialized"},id:null},400);return this.withCors(await B.handleRequest(A,{parsedBody:w}))}catch(B){return this.logger.error("MCP transport error:",B),this.createJsonResponse({jsonrpc:"2.0",error:{code:-32603,message:"Internal error"}},500)}}async handleRequest(A){let Q=new URL(A.url);this.logger.debug(`${A.method} ${Q.pathname}`);let w=await this.authenticate(A);if(w)return w;if(Q.pathname==="/health")return this.createJsonResponse({status:"ok",transport:"streamable-http",timestamp:new Date().toISOString()});if(Q.pathname==="/status")return this.createJsonResponse({status:"ok",sessions:Object.keys(this.transports).length});if(Q.pathname==="/mcp")return this.handleMcpRequest(A);return this.createTextResponse("Not Found",404)}connectMCPServer(A,Q){this.mcpServer=A,this.mcpTransport=Q??null,this.logger.debug("MCP server connected to StreamableHTTP transport")}async start(){if(this.server)throw Error("Server is already running");let A=Number(this.config.port??3333),Q=this.config.host??"0.0.0.0";try{this.server=Bun.serve({port:A,hostname:Q,fetch:(w)=>this.handleRequest(w)}),this.boundPort=this.server.port??A,this.logger.info(`StreamableHTTP server listening on http://${Q}:${this.boundPort}/mcp`)}catch(w){let B=bl2.safeParse(w);if(B.success&&B.data.code==="EADDRINUSE")this.logger.error(`Port ${A} is already in use`);throw w}}async stop(){if(this.evictionTimer)clearInterval(this.evictionTimer),this.evictionTimer=null;this.sessionLastActivity.clear();for(let A in this.transports)try{let Q=this.transports[A];if(Q)this.logger.debug(`Closing transport for session ${A}`),await Q.close(),delete this.transports[A]}catch(Q){this.logger.error(`Error closing transport for session ${A}:`,Q)}if(this.server)await this.server.stop(),this.logger.info("StreamableHTTP server stopped"),this.server=null,this.boundPort=null}getPort(){if(this.boundPort===null)throw Error("Server is not running");return this.boundPort}getApp(){return{fetch:(A)=>this.handleRequest(A)}}isRunning(){return this.server!==null}getSessionCount(){return Object.keys(this.transports).length}}function Il2(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}function Jl2(A,Q){let w=Buffer.from(A),B=Buffer.from(Q);if(w.length!==B.length)return!1;return Kl2(w,B)}import{randomUUID as Pl2}from"crypto";import{chmod as Fl2,mkdir as Ll2,readFile as kl2,rename as COA,writeFile as _l2}from"fs/promises";import{dirname as Nl2}from"path";class jf{filePath;parse;empty;logError;onCorrupt;writeQueue=Promise.resolve();constructor(A){this.filePath=A.filePath,this.parse=A.parse,this.empty=A.empty,this.onCorrupt=A.onCorrupt??"quarantine",this.logError=A.logError??((Q,w)=>{console.error(Q,w)})}async enqueueWrite(A){return this.writeQueue=this.writeQueue.then(A,A),this.writeQueue}async read(){let A;try{A=await kl2(this.filePath,"utf8")}catch(Q){if(Q.code==="ENOENT")return this.empty();throw Q}try{return this.parse(JSON.parse(A))}catch(Q){if(this.onCorrupt==="throw")throw Error(`Corrupt JSON store at ${this.filePath}; refusing to start empty. Inspect or remove the file to proceed.`,{cause:Q});return await this.quarantineCorruptFile(Q),this.empty()}}async write(A){await Ll2(Nl2(this.filePath),{recursive:!0,mode:448});let Q=`${this.filePath}.tmp`;await _l2(Q,`${JSON.stringify(A,null,2)}
1721
1721
  `,{mode:384}),await Fl2(Q,384),await COA(Q,this.filePath)}async quarantineCorruptFile(A){let Q=`${this.filePath}.corrupt-${process.pid}`;this.logError(`Corrupt JSON store at ${this.filePath}; moving it to ${Q} and starting from an empty store`,A);try{await COA(this.filePath,Q)}catch(w){this.logError(`Failed to quarantine corrupt JSON store at ${this.filePath}`,w)}}}function SR(A){let Q=A.toISOString();return Q.substring(0,Q.indexOf("T"))}function oQ0(){let A=new Date;return A.setDate(A.getDate()-1),A}function gOA(A){let Q=new Date;return Q.setDate(Q.getDate()-A),Q}function f9(){return Math.floor(Date.now()/1000)}N0();import{join as Ml2}from"path";function yOA(A){let Q=A.toLowerCase();return Q==="localhost"||Q==="[::1]"||Q==="::1"||Q.startsWith("127.")}function EOA(A){try{return new URL(A)}catch{return}}function TP0(A,Q){if(A===Q)return!0;let w=EOA(A),B=EOA(Q);if(!w||!B)return!1;if(!yOA(w.hostname)||!yOA(B.hostname))return!1;return w.protocol===B.protocol&&w.port===B.port&&jl2(w.pathname,B.pathname)&&w.search===B.search&&w.hash===B.hash}function jl2(A,Q){return A===Q||A===`${Q}/debug`||Q===`${A}/debug`}function SP0(A,Q){return A.some((w)=>TP0(w,Q))}var Ol2="oauth-auth-codes.json",xl2=600,Rl2=Z.looseObject({code:Z.string(),client_id:Z.string(),redirect_uri:Z.string(),code_challenge:Z.string(),code_challenge_method:Z.literal("S256"),scope:Z.string().optional(),subject:Z.string(),created_at:Z.number(),expires_at:Z.number(),consumed_at:Z.number().optional()}).transform((A)=>({code:A.code,client_id:A.client_id,redirect_uri:A.redirect_uri,code_challenge:A.code_challenge,code_challenge_method:A.code_challenge_method,...A.scope!==void 0?{scope:A.scope}:{},subject:A.subject,created_at:A.created_at,expires_at:A.expires_at,...A.consumed_at!==void 0?{consumed_at:A.consumed_at}:{}})),vl2=Z.looseObject({codes:Z.array(Z.unknown()).optional()});function hl2(A){let Q=vl2.safeParse(A);if(!Q.success)return{codes:[]};return{codes:Q.data.codes?.flatMap(Cl2)??[]}}function Cl2(A){let Q=Rl2.safeParse(A);return Q.success?[Q.data]:[]}async function gl2(A){let Q=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(A));return Buffer.from(Q).toString("base64url")}class sQ0{store;constructor(A){this.store=new jf({filePath:Ml2(A.storageDir,A.storeFile??Ol2),parse:hl2,empty:()=>({codes:[]})})}async createCode(A){let Q=f9(),w={code:`ocd_${Pl2()}`,client_id:A.clientId,redirect_uri:A.redirectUri,code_challenge:A.codeChallenge,code_challenge_method:"S256",...A.scope?{scope:A.scope}:{},subject:A.subject,created_at:Q,expires_at:Q+xl2};return await this.store.enqueueWrite(async()=>{let B=await this.store.read();B.codes=B.codes.filter(($)=>$.expires_at>Q),B.codes.push(w),await this.store.write(B)}),w}async consumeCode(A){let Q=f9(),w;if(await this.store.enqueueWrite(async()=>{let B=await this.store.read(),$=B.codes.findIndex((X)=>X.code===A.code),f=$>=0?B.codes[$]:void 0;if(!f)throw new hK("Authorization code not found");if(f.consumed_at!==void 0)throw new hK("Authorization code already consumed");if(f.expires_at<=Q)throw new hK("Authorization code expired");if(f.client_id!==A.clientId)throw new hK("Authorization code client mismatch");if(!TP0(f.redirect_uri,A.redirectUri))throw new hK("Authorization code redirect URI mismatch");let Y=await gl2(A.codeVerifier);if(f.code_challenge!==Y)throw new hK("PKCE verification failed");w={...f,consumed_at:Q},B.codes[$]=w,await this.store.write(B)}),!w)throw new hK("Authorization code not consumed");return w}}class hK extends Error{constructor(A){super(A);this.name="InvalidGrantError"}}import{randomUUID as TOA}from"crypto";N0();import{join as yl2}from"path";var El2="oauth-clients.json",Tl2=Z.enum(["none","client_secret_basic","client_secret_post"]),Sl2=Z.object({redirect_uris:Z.array(Z.url()).min(1),token_endpoint_auth_method:Tl2.default("none"),grant_types:Z.array(Z.enum(["authorization_code","refresh_token"])).default(["authorization_code","refresh_token"]),response_types:Z.array(Z.literal("code")).default(["code"]),scope:Z.string().optional(),client_name:Z.string().optional(),client_uri:Z.url().optional(),logo_uri:Z.url().optional(),contacts:Z.array(Z.string()).optional()}),ml2=Z.looseObject({client_id:Z.string(),client_id_issued_at:Z.number(),redirect_uris:Z.array(Z.string()),token_endpoint_auth_method:Z.string().optional(),grant_types:Z.array(Z.string()).optional(),response_types:Z.array(Z.string()).optional(),scope:Z.string().optional(),client_name:Z.string().optional(),client_uri:Z.string().optional(),logo_uri:Z.string().optional(),contacts:Z.array(Z.string()).optional(),client_secret:Z.string().optional(),client_secret_expires_at:Z.number().optional()}).transform((A)=>({client_id:A.client_id,client_id_issued_at:A.client_id_issued_at,redirect_uris:A.redirect_uris,token_endpoint_auth_method:A.token_endpoint_auth_method??"none",grant_types:A.grant_types??["authorization_code","refresh_token"],response_types:A.response_types??["code"],...A.scope!==void 0?{scope:A.scope}:{},...A.client_name!==void 0?{client_name:A.client_name}:{},...A.client_uri!==void 0?{client_uri:A.client_uri}:{},...A.logo_uri!==void 0?{logo_uri:A.logo_uri}:{},...A.contacts!==void 0?{contacts:A.contacts}:{},...A.client_secret!==void 0?{client_secret:A.client_secret}:{},...A.client_secret_expires_at!==void 0?{client_secret_expires_at:A.client_secret_expires_at}:{}})),ul2=Z.looseObject({clients:Z.array(Z.unknown()).optional()});function cl2(){return`ocs_${TOA().replaceAll("-","")}`}function ll2(A){let Q=ul2.safeParse(A);if(!Q.success)return{clients:[]};return{clients:Q.data.clients?.flatMap(pl2)??[]}}function pl2(A){let Q=ml2.safeParse(A);return Q.success?[Q.data]:[]}class aQ0{store;constructor(A){this.store=new jf({filePath:yl2(A.storageDir,A.storeFile??El2),parse:ll2,empty:()=>({clients:[]})})}async registerClient(A){let Q=Sl2.safeParse(A);if(!Q.success)throw new Oc(Q.error.message);let w=Q.data,B=f9(),$=`oc_${TOA()}`,f=w.token_endpoint_auth_method==="none",Y={client_id:$,client_id_issued_at:B,redirect_uris:w.redirect_uris,token_endpoint_auth_method:w.token_endpoint_auth_method,grant_types:w.grant_types,response_types:w.response_types,...w.scope?{scope:w.scope}:{},...w.client_name?{client_name:w.client_name}:{},...w.client_uri?{client_uri:w.client_uri}:{},...w.logo_uri?{logo_uri:w.logo_uri}:{},...w.contacts?{contacts:w.contacts}:{},...!f?{client_secret:cl2(),client_secret_expires_at:0}:{}};return await this.store.enqueueWrite(async()=>{let X=await this.store.read();X.clients.push(Y),await this.store.write(X)}),Y}async getClient(A){return(await this.store.read()).clients.find((w)=>w.client_id===A)}}class Oc extends Error{constructor(A){super(A);this.name="InvalidClientMetadataError"}}N0();import{createHash as SOA,generateKeyPairSync as il2}from"crypto";import{mkdir as dl2,readFile as mOA,writeFile as nl2,chmod as rl2}from"fs/promises";import{dirname as ol2,join as uOA}from"path";var sl2="oauth-signing-key.jwk",al2="a2a-signing-key.jwk",cOA=Z.object({kty:Z.literal("EC"),crv:Z.literal("P-256"),x:Z.string(),y:Z.string(),d:Z.string(),kid:Z.string().optional()}),lOA=Z.object({kty:Z.literal("OKP"),crv:Z.literal("Ed25519"),x:Z.string(),d:Z.string(),kid:Z.string().optional()});function tl2(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x,y:A.y});return SOA("sha256").update(Q).digest("base64url")}function el2(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x});return SOA("sha256").update(Q).digest("base64url")}function Ap2(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,kid:A.kid,use:"sig",alg:"ES256"}}function Qp2(A){return{kty:"OKP",crv:"Ed25519",x:A.x,kid:A.kid,use:"sig",alg:"EdDSA"}}async function wp2(){let A=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!0,["sign","verify"]),Q=cOA.safeParse(await crypto.subtle.exportKey("jwk",A.privateKey));if(!Q.success)throw Error("Generated OAuth signing key is not a P-256 private JWK");return pOA(Q.data)}function Bp2(){let{privateKey:A}=il2("ed25519"),Q=lOA.safeParse(A.export({format:"jwk"}));if(!Q.success)throw Error("Generated A2A signing key is not an Ed25519 private JWK");return iOA(Q.data)}function pOA(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,d:A.d,kid:A.kid??tl2(A),use:"sig",alg:"ES256"}}function iOA(A){return{kty:"OKP",crv:"Ed25519",x:A.x,d:A.d,kid:A.kid??el2(A),use:"sig",alg:"EdDSA"}}class tQ0{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=uOA(A.storageDir,A.keyFile??sl2)}async getPrivateJwk(){if(this.cachedKey)return this.cachedKey;this.loadPromise??=this.loadOrCreateKey();try{return this.cachedKey=await this.loadPromise,this.cachedKey}catch(A){throw this.loadPromise=void 0,A}}async loadOrCreateKey(){let A=await this.readExistingKey();if(A)return A;let Q=await wp2();return await dOA(this.keyFile,Q),Q}async getPublicJwk(){return Ap2(await this.getPrivateJwk())}async readExistingKey(){try{let A=cOA.safeParse(JSON.parse(await mOA(this.keyFile,"utf8")));if(!A.success)throw Error(`OAuth signing key at ${this.keyFile} is not a private P-256 JWK`);return pOA(A.data)}catch(A){if(nOA(A))return;throw A}}}class mP0{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=uOA(A.storageDir,A.keyFile??al2)}async getPrivateJwk(){if(this.cachedKey)return this.cachedKey;this.loadPromise??=this.loadOrCreateKey();try{return this.cachedKey=await this.loadPromise,this.cachedKey}catch(A){throw this.loadPromise=void 0,A}}async loadOrCreateKey(){let A=await this.readExistingKey();if(A)return A;let Q=Bp2();return await dOA(this.keyFile,Q),Q}async getPublicJwk(){return Qp2(await this.getPrivateJwk())}async readExistingKey(){try{let A=lOA.safeParse(JSON.parse(await mOA(this.keyFile,"utf8")));if(!A.success)throw Error(`A2A signing key at ${this.keyFile} is not a private Ed25519 JWK`);return iOA(A.data)}catch(A){if(nOA(A))return;throw A}}}async function dOA(A,Q){await dl2(ol2(A),{recursive:!0,mode:448}),await nl2(A,`${JSON.stringify(Q,null,2)}
1722
1722
  `,{mode:384}),await rl2(A,384)}function nOA(A){return A instanceof Error&&"code"in A&&A.code==="ENOENT"}var NQ={};D6(NQ,{trimPadding:()=>oOA,toUTF8String:()=>Up2,toBuffer:()=>Zp2,toBase64:()=>Hp2,isBase64URL:()=>Gp2,isBase64:()=>Dp2,fromUTF8String:()=>Kp2,fromBuffer:()=>Wp2});var rOA=(A)=>{let Q=typeof Uint8Array>"u"?[]:new Uint8Array(256),w=64;for(let B=0;B<64;B++)Q[A.charCodeAt(B)]=B;return Q},$p2=rOA("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),fp2=rOA("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"),Yp2=/^[-A-Za-z0-9\-_]*$/,Xp2=/^[-A-Za-z0-9+/]*={0,3}$/,uD={};uD.toArrayBuffer=(A,Q)=>{let w=A.length,B=A.length*0.75,$,f=0,Y,X,W,H;if(A[A.length-1]==="="){if(B--,A[A.length-2]==="=")B--}let K=new ArrayBuffer(B),U=new Uint8Array(K),D=Q?fp2:$p2;for($=0;$<w;$+=4)Y=D[A.charCodeAt($)],X=D[A.charCodeAt($+1)],W=D[A.charCodeAt($+2)],H=D[A.charCodeAt($+3)],U[f++]=Y<<2|X>>4,U[f++]=(X&15)<<4|W>>2,U[f++]=(W&3)<<6|H&63;return K};uD.fromArrayBuffer=(A,Q)=>{let w=new Uint8Array(A),B,$="",f=w.length,Y=Q?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(B=0;B<f;B+=3)$+=Y[w[B]>>2],$+=Y[(w[B]&3)<<4|w[B+1]>>4],$+=Y[(w[B+1]&15)<<2|w[B+2]>>6],$+=Y[w[B+2]&63];let X=f%3;if(X===2)$=$.substring(0,$.length-1)+(Q?"":"=");else if(X===1)$=$.substring(0,$.length-2)+(Q?"":"==");return $};uD.toString=(A,Q)=>{return new TextDecoder().decode(uD.toArrayBuffer(A,Q))};uD.fromString=(A,Q)=>{return uD.fromArrayBuffer(new TextEncoder().encode(A),Q)};uD.validate=(A,Q)=>{if(!(typeof A==="string"||A instanceof String))return!1;try{return Q?Yp2.test(A):Xp2.test(A)}catch(w){return!1}};uD.base64=uD;var Tz=uD;function Zp2(A,Q="base64url"){let w=Tz.toArrayBuffer(A,Q==="base64url");return new Uint8Array(w)}function Wp2(A,Q="base64url"){let w=new Uint8Array(A);return Tz.fromArrayBuffer(w.buffer,Q==="base64url")}function Hp2(A){let Q=Tz.toArrayBuffer(A,!0);return Tz.fromArrayBuffer(Q)}function Kp2(A){return Tz.fromString(A,!0)}function Up2(A){return Tz.toString(A,!0)}function Dp2(A){return Tz.validate(A,!1)}function Gp2(A){return A=oOA(A),Tz.validate(A,!0)}function oOA(A){return A.replace(/=/g,"")}var Pf={};D6(Pf,{encode:()=>gp2,decodeFirst:()=>Cp2});function mR(A,Q,w){if(Q<24)return[Q,1];let B=A.byteLength-w-1,$=new DataView(A.buffer,w+1),f,Y=0;switch(Q){case 24:{if(B>0)f=$.getUint8(0),Y=2;break}case 25:{if(B>1)f=$.getUint16(0,!1),Y=3;break}case 26:{if(B>3)f=$.getUint32(0,!1),Y=5;break}case 27:{if(B>7){let X=$.getBigUint64(0,!1);if(X>=24n&&X<=Number.MAX_SAFE_INTEGER)return[Number(X),9]}break}}if(f&&f>=24)return[f,Y];throw Error("Length not supported or not well formed")}var eQ0=0,xc=1,uP0=2,cP0=3,lP0=4,pP0=5,iP0=6,sOA=7;function cD(A,Q){let w=A<<5;if(Q<0)throw Error("CBOR Data Item argument must not be negative");let B;if(typeof Q=="number"){if(!Number.isInteger(Q))throw Error("CBOR Data Item argument must be an integer");B=BigInt(Q)}else B=Q;if(A==xc){if(B==0n)throw Error("CBOR Data Item argument cannot be zero when negative");B=B-1n}if(B>18446744073709551615n)throw Error("CBOR number out of range");let $=new Uint8Array(8);if(new DataView($.buffer).setBigUint64(0,B,!1),B<=23)return[w|$[7]];else if(B<=255)return[w|24,$[7]];else if(B<=65535)return[w|25,...$.slice(6)];else if(B<=4294967295)return[w|26,...$.slice(4)];else return[w|27,...$]}class Qw0{constructor(A,Q){Object.defineProperty(this,"tagId",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"tagValue",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.tagId=A,this.tagValue=Q}get tag(){return this.tagId}get value(){return this.tagValue}}function aOA(A,Q,w){return mR(A,Q,w)}function zp2(A,Q,w){let[B,$]=aOA(A,Q,w);return[-B-1,$]}function tOA(A,Q,w){let[B,$]=mR(A,Q,w),f=w+$;return[new Uint8Array(A.buffer.slice(f,f+B)),$+B]}var qp2=new TextDecoder;function bp2(A,Q,w){let[B,$]=tOA(A,Q,w);return[qp2.decode(B),$]}function Vp2(A,Q,w){if(Q===0)return[[],1];let[B,$]=mR(A,Q,w),f=$,Y=[];for(let X=0;X<B;X++){if(A.byteLength-w-f<=0)throw Error("array is not supported or well formed");let[H,K]=D_(A,w+f);Y.push(H),f+=K}return[Y,f]}var Aw0="Map is not supported or well formed";function Ip2(A,Q,w){if(Q===0)return[new Map,1];let[B,$]=mR(A,Q,w),f=$,Y=new Map;for(let X=0;X<B;X++){let W=A.byteLength-w-f;if(W<=0)throw Error(Aw0);let[H,K]=D_(A,w+f);if(f+=K,W-=K,W<=0)throw Error(Aw0);if(typeof H!=="string"&&typeof H!=="number")throw Error(Aw0);if(Y.has(H))throw Error(Aw0);let[U,D]=D_(A,w+f);f+=D,Y.set(H,U)}return[Y,f]}function Jp2(A,Q){if(Q+3>A.byteLength)throw Error("CBOR stream ended before end of Float 16");let w=A.getUint16(Q+1,!1);if(w==31744)return[1/0,3];else if(w==32256)return[NaN,3];else if(w==64512)return[-1/0,3];throw Error("Float16 data is unsupported")}function Fp2(A,Q){if(Q+5>A.byteLength)throw Error("CBOR stream ended before end of Float 32");return[A.getFloat32(Q+1,!1),5]}function Lp2(A,Q){if(Q+9>A.byteLength)throw Error("CBOR stream ended before end of Float 64");return[A.getFloat64(Q+1,!1),9]}function kp2(A,Q,w){let[B,$]=mR(A,Q,w),[f,Y]=D_(A,w+$);return[new Qw0(B,f),$+Y]}function D_(A,Q){if(Q>=A.byteLength)throw Error("CBOR stream ended before tag value");let w=A.getUint8(Q),B=w>>5,$=w&31;switch(B){case eQ0:return aOA(A,$,Q);case xc:return zp2(A,$,Q);case uP0:return tOA(A,$,Q);case cP0:return bp2(A,$,Q);case lP0:return Vp2(A,$,Q);case pP0:return Ip2(A,$,Q);case iP0:return kp2(A,$,Q);case sOA:switch($){case 20:return[!1,1];case 21:return[!0,1];case 22:return[null,1];case 23:return[void 0,1];case 25:return Jp2(A,Q);case 26:return Fp2(A,Q);case 27:return Lp2(A,Q)}}throw Error(`Unsupported or not well formed at ${Q}`)}function _p2(A){if(A===!0)return 245;else if(A===!1)return 244;else if(A===null)return 246;return 247}function Np2(A){if(Math.fround(A)==A||!Number.isFinite(A)||Number.isNaN(A)){let Q=new Uint8Array(5);return Q[0]=250,new DataView(Q.buffer).setFloat32(1,A,!1),Q}else{let Q=new Uint8Array(9);return Q[0]=251,new DataView(Q.buffer).setFloat64(1,A,!1),Q}}function jp2(A){if(typeof A=="number"){if(Number.isSafeInteger(A))if(A<0)return cD(xc,Math.abs(A));else return cD(eQ0,A);return[Np2(A)]}else if(A<0n)return cD(xc,A*-1n);else return cD(eQ0,A)}var Pp2=new TextEncoder;function Mp2(A,Q){Q.push(...cD(cP0,A.length)),Q.push(Pp2.encode(A))}function Op2(A,Q){Q.push(...cD(uP0,A.length)),Q.push(A)}function xp2(A,Q){Q.push(...cD(lP0,A.length));for(let w of A)Rc(w,Q)}function Rp2(A,Q){Q.push(new Uint8Array(cD(pP0,A.size)));for(let[w,B]of A.entries())Rc(w,Q),Rc(B,Q)}function vp2(A,Q){Q.push(...cD(iP0,A.tag)),Rc(A.value,Q)}function Rc(A,Q){if(typeof A=="boolean"||A===null||A==null){Q.push(_p2(A));return}if(typeof A=="number"||typeof A=="bigint"){Q.push(...jp2(A));return}if(typeof A=="string"){Mp2(A,Q);return}if(A instanceof Uint8Array){Op2(A,Q);return}if(Array.isArray(A)){xp2(A,Q);return}if(A instanceof Map){Rp2(A,Q);return}if(A instanceof Qw0){vp2(A,Q);return}throw Error("Not implemented")}function dP0(A,Q){if(A.byteLength===0||A.byteLength<=Q||Q<0)throw Error("No data");if(A instanceof Uint8Array)return D_(new DataView(A.buffer),Q);else if(A instanceof ArrayBuffer)return D_(new DataView(A),Q);return D_(A,Q)}function nP0(A){let Q=[];Rc(A,Q);let w=0;for(let f of Q)if(typeof f=="number")w+=1;else w+=f.length;let B=new Uint8Array(w),$=0;for(let f of Q)if(typeof f=="number")B[$]=f,$+=1;else B.set(f,$),$+=f.length;return B}function Cp2(A){let Q=new Uint8Array(A),w=dP0(Q,0),[B]=w;return B}function gp2(A){return nP0(A)}var pD={};D6(pD,{verify:()=>CCA,getRandomValues:()=>BxA,digest:()=>wxA});function eOA(A){let Q=A.get(VQ.kty);return rP0(Q)&&Q===uX.OKP}function bI(A){let Q=A.get(VQ.kty);return rP0(Q)&&Q===uX.EC2}function uR(A){let Q=A.get(VQ.kty);return rP0(Q)&&Q===uX.RSA}var VQ;(function(A){A[A.kty=1]="kty",A[A.alg=3]="alg",A[A.crv=-1]="crv",A[A.x=-2]="x",A[A.y=-3]="y",A[A.n=-1]="n",A[A.e=-2]="e"})(VQ||(VQ={}));var uX;(function(A){A[A.OKP=1]="OKP",A[A.EC2=2]="EC2",A[A.RSA=3]="RSA"})(uX||(uX={}));function rP0(A){return Object.values(uX).indexOf(A)>=0}var k4;(function(A){A[A.P256=1]="P256",A[A.P384=2]="P384",A[A.P521=3]="P521",A[A.ED25519=6]="ED25519",A[A.SECP256K1=8]="SECP256K1"})(k4||(k4={}));function AxA(A){return Object.values(k4).indexOf(A)>=0}var eQ;(function(A){A[A.ES256=-7]="ES256",A[A.EdDSA=-8]="EdDSA",A[A.ES384=-35]="ES384",A[A.ES512=-36]="ES512",A[A.PS256=-37]="PS256",A[A.PS384=-38]="PS384",A[A.PS512=-39]="PS512",A[A.ES256K=-47]="ES256K",A[A.RS256=-257]="RS256",A[A.RS384=-258]="RS384",A[A.RS512=-259]="RS512",A[A.RS1=-65535]="RS1"})(eQ||(eQ={}));function lD(A){return Object.values(eQ).indexOf(A)>=0}function VI(A){if([eQ.RS1].indexOf(A)>=0)return"SHA-1";else if([eQ.ES256,eQ.PS256,eQ.RS256].indexOf(A)>=0)return"SHA-256";else if([eQ.ES384,eQ.PS384,eQ.RS384].indexOf(A)>=0)return"SHA-384";else if([eQ.ES512,eQ.PS512,eQ.RS512,eQ.EdDSA].indexOf(A)>=0)return"SHA-512";throw Error(`Could not map COSE alg value of ${A} to a WebCrypto alg`)}var vc=void 0;function cW(){return new Promise((Q,w)=>{if(vc)return Q(vc);let B=Ep2.stubThisGlobalThisCrypto();if(B)return vc=B,Q(vc);return w(new QxA)})}class QxA extends Error{constructor(){super("An instance of the Crypto API could not be located");this.name="MissingWebCrypto"}}var Ep2={stubThisGlobalThisCrypto:()=>globalThis.crypto,setCachedCrypto:(A)=>{vc=A}};async function wxA(A,Q){let w=await cW(),B=VI(Q),$=await w.subtle.digest(B,A);return new Uint8Array($)}async function BxA(A){return(await cW()).getRandomValues(A),A}async function cR(A){let Q=await cW(),{keyData:w,algorithm:B}=A;return Q.subtle.importKey("jwk",w,B,!1,["verify"])}async function ww0(A){let{cosePublicKey:Q,signature:w,data:B,shaHashOverride:$}=A,f=await cW(),Y=Q.get(VQ.alg),X=Q.get(VQ.crv),W=Q.get(VQ.x),H=Q.get(VQ.y);if(!Y)throw Error("Public key was missing alg (EC2)");if(!X)throw Error("Public key was missing crv (EC2)");if(!W)throw Error("Public key was missing x (EC2)");if(!H)throw Error("Public key was missing y (EC2)");let K;if(X===k4.P256)K="P-256";else if(X===k4.P384)K="P-384";else if(X===k4.P521)K="P-521";else throw Error(`Unexpected COSE crv value of ${X} (EC2)`);let U={kty:"EC",crv:K,x:NQ.fromBuffer(W),y:NQ.fromBuffer(H),ext:!1},q=await cR({keyData:U,algorithm:{name:"ECDSA",namedCurve:K}}),b=VI(Y);if($)b=VI($);let I={name:"ECDSA",hash:{name:b}};return f.subtle.verify(I,q,w,B)}function oP0(A){if([eQ.EdDSA].indexOf(A)>=0)return"Ed25519";else if([eQ.ES256,eQ.ES384,eQ.ES512,eQ.ES256K].indexOf(A)>=0)return"ECDSA";else if([eQ.RS256,eQ.RS384,eQ.RS512,eQ.RS1].indexOf(A)>=0)return"RSASSA-PKCS1-v1_5";else if([eQ.PS256,eQ.PS384,eQ.PS512].indexOf(A)>=0)return"RSA-PSS";throw Error(`Could not map COSE alg value of ${A} to a WebCrypto key alg name`)}async function Bw0(A){let{cosePublicKey:Q,signature:w,data:B,shaHashOverride:$}=A,f=await cW(),Y=Q.get(VQ.alg),X=Q.get(VQ.n),W=Q.get(VQ.e);if(!Y)throw Error("Public key was missing alg (RSA)");if(!lD(Y))throw Error(`Public key had invalid alg ${Y} (RSA)`);if(!X)throw Error("Public key was missing n (RSA)");if(!W)throw Error("Public key was missing e (RSA)");let H={kty:"RSA",alg:"",n:NQ.fromBuffer(X),e:NQ.fromBuffer(W),ext:!1},K={name:oP0(Y),hash:{name:VI(Y)}},U={name:oP0(Y)};if($)K.hash.name=VI($);if(K.name==="RSASSA-PKCS1-v1_5"){if(K.hash.name==="SHA-256")H.alg="RS256";else if(K.hash.name==="SHA-384")H.alg="RS384";else if(K.hash.name==="SHA-512")H.alg="RS512";else if(K.hash.name==="SHA-1")H.alg="RS1"}else if(K.name==="RSA-PSS"){let q=0;if(K.hash.name==="SHA-256")H.alg="PS256",q=32;else if(K.hash.name==="SHA-384")H.alg="PS384",q=48;else if(K.hash.name==="SHA-512")H.alg="PS512",q=64;U.saltLength=q}else throw Error(`Unexpected RSA key algorithm ${Y} (${K.name})`);let D=await cR({keyData:H,algorithm:K});return f.subtle.verify(U,D,w,B)}function $w0(A){let Q=R2.toHex(A);return[Q.slice(0,8),Q.slice(8,12),Q.slice(12,16),Q.slice(16,20),Q.slice(20,32)].join("-")}function J5(A){let Q;if(typeof A==="string")if(NQ.isBase64URL(A))Q=NQ.toBase64(A);else if(NQ.isBase64(A))Q=A;else throw Error("Certificate is not a valid base64 or base64url string");else Q=NQ.fromBuffer(A,"base64");let w="";for(let B=0;B<Math.ceil(Q.length/64);B+=1){let $=64*B;w+=`${Q.substr($,64)}
1723
1723
  `}return w=`-----BEGIN CERTIFICATE-----
@@ -2292,14 +2292,14 @@ ${L}`)}if(B!==void 0&&f?.algorithms!==void 0){let V=f.algorithms.map((L)=>L.alg)
2292
2292
  </form>
2293
2293
  </main>
2294
2294
  </body>
2295
- </html>`}function qp(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(HR0(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function fG(A){return A.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;")}import{randomUUID as Hr2}from"crypto";function ngA(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function Wr2(A){let Q=new Uint8Array(A);if(Q.length===64)return Q;if(Q[0]!==48)return Q;let w=2;if(Q[1]&&Q[1]>128)w+=Q[1]-128;if(Q[w]!==2)throw Error("Invalid DER ECDSA signature");let B=Q[w+1];if(B===void 0)throw Error("Invalid DER ECDSA signature");let $=w+2,f=Q.slice($,$+B);if(w=$+B,Q[w]!==2)throw Error("Invalid DER ECDSA signature");let Y=Q[w+1];if(Y===void 0)throw Error("Invalid DER ECDSA signature");let X=w+2,W=Q.slice(X,X+Y);return new Uint8Array([...rgA(f),...rgA(W)])}function rgA(A){let Q=A;while(Q.length>32&&Q[0]===0)Q=Q.slice(1);if(Q.length>32)throw Error("Invalid P-256 signature component length");if(Q.length===32)return Q;let w=new Uint8Array(32);return w.set(Q,32-Q.length),w}async function UR0(A,Q){let w={typ:"JWT",alg:"ES256",kid:A.kid},B=`${ngA(w)}.${ngA(Q)}`,$=await crypto.subtle.importKey("jwk",A,{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),f=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},$,new TextEncoder().encode(B));return`${B}.${Buffer.from(Wr2(f)).toString("base64url")}`}var Kr2=600;class DR0{clientStore;authCodeStore;refreshTokenStore;sessionStore;keyStore;authorizationApprovalTokens=new Map;constructor(A){this.clientStore=A.clientStore,this.authCodeStore=A.authCodeStore,this.refreshTokenStore=A.refreshTokenStore,this.sessionStore=A.sessionStore,this.keyStore=A.keyStore}async handleAuthorizePage(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return qp(A);let w=await this.validateAuthorizationRequest(new URL(A.url).searchParams);if(!w.success)return new Response(w.error,{status:400});let B=this.createAuthorizationApprovalToken(Q,w.params);return Xh(dgA(w.params,B))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return qp(A);let w=await A.formData(),B=await this.validateAuthorizationRequest(new URLSearchParams(YR0(w)));if(!B.success)return new Response(B.error,{status:400});let $=w.get("approval_token"),f=typeof $==="string"?$:void 0;if(!f||!this.consumeAuthorizationApprovalToken(f,Q,B.params))return new Response("Invalid authorization approval token",{status:400});let Y=await this.authCodeStore.createCode({clientId:B.params.clientId,redirectUri:B.params.redirectUri,codeChallenge:B.params.codeChallenge,...B.params.scope?{scope:B.params.scope}:{},subject:Q.subject}),X=new URL(B.params.redirectUri);if(X.searchParams.set("code",Y.code),B.params.state)X.searchParams.set("state",B.params.state);return Response.redirect(X.toString(),302)}createAuthorizationApprovalToken(A,Q){this.pruneExpiredAuthorizationApprovalTokens();let w=`oat_${Hr2()}`;return this.authorizationApprovalTokens.set(w,{token:w,sessionId:A.id,clientId:Q.clientId,redirectUri:Q.redirectUri,codeChallenge:Q.codeChallenge,...Q.scope?{scope:Q.scope}:{},...Q.state?{state:Q.state}:{},expiresAt:Math.floor(Date.now()/1000)+Kr2}),w}consumeAuthorizationApprovalToken(A,Q,w){this.pruneExpiredAuthorizationApprovalTokens();let B=this.authorizationApprovalTokens.get(A);if(!B)return!1;return this.authorizationApprovalTokens.delete(A),B.sessionId===Q.id&&B.clientId===w.clientId&&B.redirectUri===w.redirectUri&&B.codeChallenge===w.codeChallenge&&B.scope===w.scope&&B.state===w.state}pruneExpiredAuthorizationApprovalTokens(){let A=Math.floor(Date.now()/1000);for(let[Q,w]of this.authorizationApprovalTokens.entries())if(w.expiresAt<=A)this.authorizationApprovalTokens.delete(Q)}async validateAuthorizationRequest(A){let Q=A.get("response_type"),w=A.get("client_id"),B=A.get("redirect_uri"),$=A.get("code_challenge"),f=A.get("code_challenge_method"),Y=A.get("scope")??void 0,X=A.get("state")??void 0;if(Q!=="code")return{success:!1,error:"Unsupported response_type"};if(!w)return{success:!1,error:"Missing client_id"};if(!B)return{success:!1,error:"Missing redirect_uri"};if(!$)return{success:!1,error:"Missing code_challenge"};if(f!=="S256")return{success:!1,error:"Unsupported code_challenge_method"};let W=await this.clientStore.getClient(w);if(!W)return{success:!1,error:"Unknown client_id"};if(!SP0(W.redirect_uris,B))return{success:!1,error:"Unregistered redirect_uri"};let H=Y??W.scope;return{success:!0,params:{clientId:w,redirectUri:B,codeChallenge:$,...H?{scope:H}:{},...X?{state:X}:{},clientName:W.client_name??W.client_id}}}async handleClientRegistration(A){let Q;try{Q=await A.json()}catch{return r$("invalid_client_metadata","Request body must be JSON")}try{let w=await this.clientStore.registerClient(Q);return sX(w,201)}catch(w){if(w instanceof Oc)return r$("invalid_client_metadata",w.message);throw w}}async handleTokenRequest(A,Q){let w=await fR0(A),B=w.get("grant_type"),$=ZR0(A,w),f=$.clientId??w.get("client_id");if($.error)return r$("invalid_client",$.error);if(!f)return r$("invalid_request","client_id is required");let Y=await this.clientStore.getClient(f),X=XR0(Y,$);if(X)return r$("invalid_client",X);if(B==="authorization_code")return this.handleAuthorizationCodeGrant(w,f,Q);if(B==="refresh_token")return this.handleRefreshTokenGrant(w,f,Q);return r$("unsupported_grant_type","Only authorization_code and refresh_token are supported")}async handleAuthorizationCodeGrant(A,Q,w){let B=A.get("code"),$=A.get("redirect_uri"),f=A.get("code_verifier");if(!B||!$||!f)return r$("invalid_request","code, redirect_uri, and code_verifier are required");let Y=await this.clientStore.getClient(Q);if(!Y||!SP0(Y.redirect_uris,$))return r$("invalid_grant","Unregistered redirect_uri");try{let X=await this.authCodeStore.consumeCode({code:B,clientId:Q,redirectUri:$,codeVerifier:f});return await this.createTokenResponse({issuer:w,clientId:Q,subject:X.subject,...X.scope?{scope:X.scope}:{}})}catch(X){if(X instanceof hK)return r$("invalid_grant",X.message);throw X}}async handleRefreshTokenGrant(A,Q,w){let B=A.get("refresh_token");if(!B)return r$("invalid_request","refresh_token is required");try{let $=await this.refreshTokenStore.rotateToken(B,Q);return await this.createTokenResponse({issuer:w,clientId:Q,subject:$.consumed.subject,...$.consumed.scope?{scope:$.consumed.scope}:{},refreshToken:$.replacement.token})}catch($){if($ instanceof Xq)return r$("invalid_grant",$.message);throw $}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),w=900,B=await UR0(await this.keyStore.getPrivateJwk(),{iss:A.issuer,sub:A.subject,aud:A.clientId,iat:Q,exp:Q+900,...A.scope?{scope:A.scope}:{}}),$=A.refreshToken??(await this.refreshTokenStore.issueToken({clientId:A.clientId,subject:A.subject,...A.scope?{scope:A.scope}:{}})).token;return sX({access_token:B,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:$})}async handleRevokeRequest(A){let Q=await fR0(A),w=ZR0(A,Q),B=w.clientId??Q.get("client_id")??void 0,$=Q.get("token");if(w.error)return r$("invalid_client",w.error);if(!$)return r$("invalid_request","token is required");if(B){let f=await this.clientStore.getClient(B),Y=XR0(f,w);if(Y)return r$("invalid_client",Y)}return await this.refreshTokenStore.revokeToken($,B),new Response(null,{status:200})}}class GR0{passkeyService;sessionStore;setupFlow;constructor(A){this.passkeyService=A.passkeyService,this.sessionStore=A.sessionStore,this.setupFlow=A.setupFlow}async handleRegistrationOptions(A){if(await this.passkeyService.hasCredentials())return r$("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return r$("access_denied","Invalid setup token");let Q=await this.passkeyService.generateRegistrationOptions(E60(A));return sX(Q)}async handleRegistrationVerify(A){if(await this.passkeyService.hasCredentials())return r$("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return r$("access_denied","Invalid setup token");let Q=await this.passkeyService.verifyRegistrationResponse(await A.json(),E60(A));if(!Q.verified)return r$("access_denied","Passkey registration failed");await this.setupFlow.clearSetupState();let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:Up(A)});return sX({verified:!0},200,{"Set-Cookie":w.cookie})}async handleAuthenticationOptions(A){if(!await this.passkeyService.hasCredentials())return r$("access_denied","No passkey registered");let Q=await this.passkeyService.generateAuthenticationOptions(E60(A));return sX(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),E60(A));if(!Q.verified)return r$("access_denied","Passkey authentication failed");let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:Up(A)});return sX({verified:!0},200,{"Set-Cookie":w.cookie})}}function E60(A){let Q=Ah(A),w=new URL(Q);return{origin:w.origin,rpID:w.hostname}}import{randomUUID as Ur2}from"crypto";var bp=86400;class zR0{setupStateStore;passkeyService;setupTokenTtlSeconds;setupToken;constructor(A){this.setupStateStore=A.setupStateStore,this.passkeyService=A.passkeyService,this.setupTokenTtlSeconds=A.setupTokenTtlSeconds??bp}async ensureSetupToken(){let A=this.getValidSetupToken();if(A)return A;let Q=await this.setupStateStore.getValidSetupToken(Math.floor(Date.now()/1000));if(Q)return this.setupToken=Q,Q;return this.createSetupToken()}async createSetupToken(){return this.setupToken={token:`setup_${Ur2()}`,expiresAt:Math.floor(Date.now()/1000)+this.setupTokenTtlSeconds},await this.setupStateStore.saveSetupToken(this.setupToken),this.setupToken}getValidSetupToken(){if(!this.setupToken)return;if(this.setupToken.expiresAt<=Math.floor(Date.now()/1000)){this.setupToken=void 0;return}return this.setupToken}hasValidSetupToken(A){let Q=this.getValidSetupToken();if(!Q)return!1;let w=new URL(A.url);return(w.searchParams.get("setup_token")??w.searchParams.get("token"))===Q.token}async clearSetupState(){this.setupToken=void 0,await this.setupStateStore.clearSetupState()}getSetupUrl(A){let Q=this.getValidSetupToken();if(!Q)return;return pK(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:pK(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:Sx0(Q.token)}}async handleSetupPage(A){if(await this.passkeyService.hasCredentials())return new Response("Setup already completed",{status:404});if(!this.hasValidSetupToken(A))return new Response("Not Found",{status:404});let Q=new URL(A.url).searchParams.get("token")??"";return Xh(pgA(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupStateStore.recordDelivery(A,Q,w)}}class T60{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;a2aKeyStore;clientStore;authCodeStore;sessionStore;peerTrustStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=lK(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>lK(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??ev(this.issuer),this.keyStore=new tQ0({storageDir:A.storageDir}),this.a2aKeyStore=new mP0({storageDir:A.storageDir}),this.clientStore=new aQ0({storageDir:A.storageDir}),this.authCodeStore=new sQ0({storageDir:A.storageDir}),this.sessionStore=new v60({storageDir:A.storageDir}),this.peerTrustStore=new M60({storageDir:A.storageDir}),this.passkeyService=new P60({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new zR0({setupStateStore:new mx0({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??bp}),this.oauthEndpoints=new DR0({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new O60({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new GR0({passkeyService:this.passkeyService,sessionStore:this.sessionStore,setupFlow:this.setupFlow}),this.logger=A.logger}getIssuer(){return this.issuer}async initialize(){if(await Promise.all([this.keyStore.getPrivateJwk(),this.a2aKeyStore.getPrivateJwk()]),this.logger?.debug("Auth service signing keys loaded"),!await this.hasPasskeyCredentials()){await this.setupFlow.ensureSetupToken();let A=this.getSetupUrl();if(A)if(ev(this.issuer))this.logger?.warn(`Passkey setup required: ${A}`);else this.logger?.warn("Passkey setup required. Ask through an anchor-visible interface for the setup URL.")}}async hasPasskeyCredentials(){return this.passkeyService.hasCredentials()}async getJwks(){let[A,Q]=await Promise.all([this.keyStore.getPublicJwk(),this.a2aKeyStore.getPublicJwk()]);return{keys:[A,Q]}}async getA2ASigningKey(){let A=await this.a2aKeyStore.getPrivateJwk();return{privateJwk:A,keyId:pK(this.issuer,`/.well-known/jwks.json#${A.kid}`)}}grantA2APeerTrust(A){return this.peerTrustStore.grant(A)}getA2APeerTrust(A){return this.peerTrustStore.get(A)}revokeA2APeerTrust(A){return this.peerTrustStore.revoke(A)}getAuthorizationServerMetadata(A=this.issuer){let Q=lK(A);return{issuer:Q,authorization_endpoint:pK(Q,"/authorize"),token_endpoint:pK(Q,"/token"),registration_endpoint:pK(Q,"/register"),revocation_endpoint:pK(Q,"/revoke"),jwks_uri:pK(Q,"/.well-known/jwks.json"),response_types_supported:["code"],grant_types_supported:["authorization_code","refresh_token"],code_challenge_methods_supported:["S256"],token_endpoint_auth_methods_supported:["none","client_secret_basic","client_secret_post"],scopes_supported:["openid","profile","email","offline_access","mcp"],subject_types_supported:["public"],id_token_signing_alg_values_supported:["ES256"]}}getProtectedResourceMetadata(A,Q=this.issuer){return{resource:A,authorization_servers:[lK(Q)],bearer_methods_supported:["header"],resource_signing_alg_values_supported:["ES256"],scopes_supported:["mcp"]}}async registerClient(A){return this.clientStore.registerClient(A)}async getRegisteredClient(A){return this.clientStore.getClient(A)}async createOperatorSession(A="single-operator",Q={}){return this.sessionStore.createSession(A,Q)}async getOperatorSession(A){return this.sessionStore.getSessionFromRequest(A)}createOperatorLoginResponse(A){return qp(A)}async verifyBearerToken(A,Q={}){let w=$R0(A);if(!w)return;let B=Q.issuer?lK(Q.issuer):this.resolveRequestIssuer(A);return BR0(w,await this.getJwks(),{issuer:B,...Q.audience?{audience:Q.audience}:{}})}getSetupUrl(A=this.issuer){return this.setupFlow.getSetupUrl(A)}async getOperatorSetupRequired(A=this.issuer){return this.setupFlow.getOperatorSetupRequired(A)}async hasSetupEmailDelivery(A,Q){return this.setupFlow.hasSetupEmailDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupFlow.recordSetupEmailDelivery(A,Q,w)}async handleRequest(A){let Q;try{Q=this.resolveRequestIssuer(A)}catch(B){return this.logger?.warn("Rejected OAuth request from untrusted issuer",{error:B instanceof Error?B.message:String(B)}),new Response("Untrusted OAuth issuer",{status:400})}let w=new URL(A.url).pathname;if(A.method==="OPTIONS"&&ugA(w))return cgA();if(A.method==="GET"){if(w==="/.well-known/oauth-authorization-server")return rI(sX(this.getAuthorizationServerMetadata(Q)));if(w==="/.well-known/jwks.json")return rI(sX(await this.getJwks()));if(w==="/.well-known/oauth-protected-resource")return rI(sX(this.getProtectedResourceMetadata(Q,Q)))}if(A.method==="GET"&&w==="/setup")return this.setupFlow.handleSetupPage(A);if(A.method==="GET"&&w==="/login")return this.handleLoginPage(A);if((A.method==="GET"||A.method==="POST")&&w==="/logout")return this.handleLogout(A);if(A.method==="POST"&&w==="/webauthn/register/options")return this.webauthnEndpoints.handleRegistrationOptions(A);if(A.method==="POST"&&w==="/webauthn/register/verify")return this.webauthnEndpoints.handleRegistrationVerify(A);if(A.method==="POST"&&w==="/webauthn/auth/options")return this.webauthnEndpoints.handleAuthenticationOptions(A);if(A.method==="POST"&&w==="/webauthn/auth/verify")return this.webauthnEndpoints.handleAuthenticationVerify(A);if(A.method==="GET"&&w==="/authorize")return this.oauthEndpoints.handleAuthorizePage(A);if(A.method==="POST"&&w==="/authorize")return this.oauthEndpoints.handleAuthorizeApproval(A);if(A.method==="POST"&&w==="/register")return rI(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&w==="/token")return rI(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&w==="/revoke")return rI(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=Ah(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&ev(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=WR0(new URL(A.url).searchParams.get("return_to"));return Xh(HR0(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=WR0(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":cx0(Up(A)),"Cache-Control":"no-store"}})}}N0();var S60="email:send",ogA=Z.strictObject({to:Z.string().email(),subject:Z.string().min(1),text:Z.string().min(1),html:Z.string().min(1).optional(),sensitivity:Z.enum(["normal","secret"]).default("normal")});wA();N0();var sgA={name:"@brains/notifications",version:"0.2.0-alpha.142",description:"Generic notification routing for transactional and administrative messages",dependencies:{"@brains/email-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var qR0="notifications:send",Gr2=Z.looseObject({}),zr2=Z.discriminatedUnion("type",[Z.strictObject({type:Z.literal("email"),address:Z.email()})]),qr2=Z.strictObject({recipient:zr2,title:Z.string().min(1),body:Z.string().min(1),html:Z.string().min(1).optional(),sensitivity:Z.enum(["normal","secret"]).default("normal")}),agA=Z.discriminatedUnion("status",[Z.strictObject({status:Z.literal("sent"),deliveryId:Z.string().optional()}),Z.strictObject({status:Z.literal("failed")})]);class tgA extends aQ{constructor(A={}){super("notifications",sgA,A,Gr2)}async onRegister(A){A.messaging.subscribe(qR0,async(Q)=>{let w=qr2.parse(Q.payload),B={to:w.recipient.address,subject:w.title,text:w.body,...w.html?{html:w.html}:{},sensitivity:w.sensitivity},$=await A.messaging.send({type:S60,payload:B});if(!("success"in $)||!$.success||!$.data)return{success:!1,error:"Notification delivery failed"};let f=$.data;if(f.status!=="sent")return{success:!1,error:"Notification delivery failed"};return{success:!0,data:f.id?{status:"sent",deliveryId:f.id}:{status:"sent"}}})}}function m60(A={}){return new tgA(A)}wA();N0();var egA={name:"@brains/auth-service",version:"0.2.0-alpha.142",description:"Embedded OAuth/OIDC auth service for brain operator authentication",dependencies:{"@brains/notifications":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@simplewebauthn/server":"^13.3.1",jose:"^6.2.3"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},files:["src"],main:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var Vr2=Z.union([Z.string().email(),Z.object({to:Z.string().email(),subject:Z.string().min(1),body:Z.string().min(1)}).strict()]),Ir2=Z.object({issuer:Z.string().optional(),trustedIssuers:Z.array(Z.string()).default([]),allowLocalhostIssuers:Z.boolean().optional(),storageDir:Z.string().default("./data/auth"),setupTokenTtlSeconds:Z.number().int().positive().default(bp),setupEmail:Vr2.optional()}),u60;function P7(){return u60}class bR0 extends aQ{service;constructor(A={}){super("auth-service",egA,A,Ir2)}async onRegister(A){await super.onRegister(A);let Q=this.config.issuer??(A.preferLocalUrls?A.localSiteUrl??A.siteUrl:A.siteUrl??A.localSiteUrl);this.service=new T60({storageDir:this.config.storageDir,...Q?{issuer:Q}:{},trustedIssuers:this.config.trustedIssuers,...this.config.allowLocalhostIssuers!==void 0?{allowLocalhostIssuers:this.config.allowLocalhostIssuers}:{},setupTokenTtlSeconds:this.config.setupTokenTtlSeconds,logger:A.logger}),await this.service.initialize(),u60=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(u60===this.service)u60=void 0;this.service=void 0}async getTools(){return[{name:`${this.id}_get_passkey_setup_url`,description:"Get the first-passkey setup URL when operator setup is required. Anchor-only.",inputSchema:{},visibility:"anchor",handler:async()=>{let A=this.getService();if(await A.hasPasskeyCredentials())return{success:!0,data:{status:"complete"}};let Q=await A.getOperatorSetupRequired();if(Q)return{success:!0,data:{status:"setup_required",setupUrl:Q.setupUrl,expiresAt:Q.expiresAt}};return{success:!0,data:{status:"unavailable",reason:"Passkey setup URL is not available."}}},sideEffects:"none"}]}getWebRoutes(){let A=(Q)=>this.getService().handleRequest(Q);return[{path:"/.well-known/oauth-authorization-server",method:"GET",public:!0,handler:A},{path:"/.well-known/oauth-authorization-server",method:"OPTIONS",public:!0,handler:A},{path:"/.well-known/jwks.json",method:"GET",public:!0,handler:A},{path:"/.well-known/jwks.json",method:"OPTIONS",public:!0,handler:A},{path:"/.well-known/oauth-protected-resource",method:"GET",public:!0,handler:A},{path:"/.well-known/oauth-protected-resource",method:"OPTIONS",public:!0,handler:A},{path:"/setup",method:"GET",public:!0,handler:A},{path:"/login",method:"GET",public:!0,handler:A},{path:"/logout",method:"GET",public:!0,handler:A},{path:"/logout",method:"POST",public:!0,handler:A},{path:"/authorize",method:"GET",public:!0,handler:A},{path:"/authorize",method:"POST",public:!0,handler:A},{path:"/register",method:"POST",public:!0,handler:A},{path:"/register",method:"OPTIONS",public:!0,handler:A},{path:"/token",method:"POST",public:!0,handler:A},{path:"/token",method:"OPTIONS",public:!0,handler:A},{path:"/revoke",method:"POST",public:!0,handler:A},{path:"/revoke",method:"OPTIONS",public:!0,handler:A},{path:"/webauthn/register/options",method:"POST",public:!0,handler:A},{path:"/webauthn/register/verify",method:"POST",public:!0,handler:A},{path:"/webauthn/auth/options",method:"POST",public:!0,handler:A},{path:"/webauthn/auth/verify",method:"POST",public:!0,handler:A}]}getService(){if(!this.service)throw Error("AuthServicePlugin has not been registered");return this.service}async requestSetupEmailIfNeeded(A){if(!this.config.setupEmail)return;let Q=this.getService();if(await Q.hasPasskeyCredentials())return;let w=await Q.getOperatorSetupRequired();if(!w)return;let B=Jr2(this.config.setupEmail,w);if(await Q.hasSetupEmailDelivery(w.setupTokenId,B.to))return;let $=await A.messaging.send({type:qR0,payload:{recipient:{type:"email",address:B.to},title:B.subject,body:B.body,sensitivity:"secret"}});if(!("success"in $)||!$.success||!$.data){A.logger.warn("Passkey setup email delivery was not confirmed");return}let f=agA.safeParse($.data);if(!f.success||f.data.status!=="sent"){A.logger.warn("Passkey setup email delivery was not confirmed");return}await Q.recordSetupEmailDelivery(w.setupTokenId,B.to,f.data.deliveryId?{deliveryId:f.data.deliveryId}:{})}}function Jr2(A,Q){if(typeof A==="string"){let w=new Date(Q.expiresAt*1000).toISOString(),B=new URL(Q.setupUrl).origin;return{to:A,subject:"Set up your brain passkey",body:["Set up your brain passkey using this single-use link:","",Q.setupUrl,"",`This link expires at ${w}.`,`Dashboard: ${B}/`,`MCP endpoint: ${B}/mcp`,"The first successful passkey registration completes setup and closes this link."].join(`
2296
- `)}}return{to:A.to,subject:AyA(A.subject,Q),body:AyA(A.body,Q)}}function AyA(A,Q){let w=new Date(Q.expiresAt*1000).toISOString(),B=new URL(Q.setupUrl).origin;return A.replaceAll("{{setupUrl}}",Q.setupUrl).replaceAll("{{expiresAt}}",w).replaceAll("{{origin}}",B)}function Vp(A={}){return new bR0(A)}N0();var VR0=Z.object({transport:Z.enum(["stdio","http"]).default("http"),mode:Z.enum(["basic","debug"]).default("basic"),httpPort:Z.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:Z.string().describe("Bearer token for HTTP transport authentication").optional(),sessionIdleTtlMs:Z.number().describe("Idle time in ms after which an HTTP session is closed and evicted").default(1800000)});N0();function Fr2(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function Ip(A,Q){let w=A?.[Q];return typeof w==="string"&&w.length>0?w:void 0}function Lr2(A){let Q=Fr2(A.data)?A.data:void 0,w=A.args,B=Ip(Q,"entityId")??Ip(Q,"id"),$=A.jobId??Ip(Q,"jobId"),f=Ip(w,"entityType")??Ip(w,"type");if(!B&&!$)return;return{toolName:A.toolName,...f?{entityType:f}:{},...B?{entityId:B}:{},...$?{jobId:$}:{}}}function kr2(A){return A?.map(Lr2).filter((Q)=>Q!==void 0)??[]}function IR0(A,Q={}){let w=A.pendingConfirmations?.[0];if(w)return{needsConfirmation:!0,toolName:w.toolName,summary:w.summary,...w.completionSummary?{completionSummary:w.completionSummary}:{},...w.preview?{preview:w.preview}:{},args:{approvalId:w.id,...Q.conversationId?{conversationId:Q.conversationId}:{},...w.toolCallId?{toolCallId:w.toolCallId}:{},originalArgs:w.args}};let B=kr2(A.toolResults);return{success:!0,data:{text:A.text,...A.toolResults?{toolResults:A.toolResults}:{},...B.length>0?{readYourWrites:B}:{}}}}var QyA=Z.object({message:Z.string().min(1),conversationId:Z.string().min(1).optional()}),wyA=Z.object({approvalId:Z.string().min(1),confirmed:Z.boolean(),conversationId:Z.string().min(1).optional()});function ByA(A,Q,w,B){return A.conversationId??w??B??`mcp:${Q}`}function $yA(A){return{userPermissionLevel:A.userPermissionLevel??"public",interfaceType:"mcp",...A.channelId?{channelId:A.channelId}:{},...A.channelName?{channelName:A.channelName}:{},actor:{actorId:A.userId,interfaceType:"mcp",role:"user"}}}function fyA(A,Q){return[{name:"chat",description:"Talk to the brain to make changes or get reasoned answers. Use this for any create/update/delete request or questions requiring reasoning across content. For simple lookups, use search/get/list directly.",inputSchema:QyA.shape,visibility:"public",sideEffects:"writes",handler:async(w,B)=>{let $=QyA.parse(w),f=Q();if(!f)return{success:!1,error:"MCP chat tool is not initialized."};let Y=ByA($,B.userId,B.conversationId,B.channelId),X=await f.agent.chat($.message,Y,{...$yA(B)});return IR0(X,{conversationId:Y})}},{name:"confirm",description:"Resolve a pending confirmation returned by chat. Use this only after chat returns needsConfirmation with an approvalId.",inputSchema:wyA.shape,visibility:"public",sideEffects:"writes",handler:async(w,B)=>{let $=wyA.parse(w),f=Q();if(!f)return{success:!1,error:"MCP confirm tool is not initialized."};let Y=ByA($,B.userId,B.conversationId,B.channelId),X=await f.agent.confirmPendingAction(Y,$.confirmed,$.approvalId,$yA(B));return IR0(X,{conversationId:Y})}}]}wA();function JR0(A,Q){A.messaging.subscribe("job-progress",async(w)=>{let B=IO.safeParse(w.payload);if(!B.success)return Q.warn("Received invalid job-progress message",{error:B.error.message}),{success:!1};let $=B.data,f=$.type,Y=$.status,X=$.id;if(Q.debug(`${f} ${X} - ${Y}:`,{id:$.id,message:$.message,progress:$.progress,metadata:$.metadata}),$.batchDetails)Q.debug(`Batch details for ${X}:`,{totalOperations:$.batchDetails.totalOperations,completedOperations:$.batchDetails.completedOperations,failedOperations:$.batchDetails.failedOperations,currentOperation:$.batchDetails.currentOperation,errors:$.batchDetails.errors});if($.jobDetails)Q.debug(`Job details for ${X}:`,{jobType:$.jobDetails.jobType,priority:$.jobDetails.priority,retryCount:$.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var YyA={name:"@brains/mcp",version:"0.2.0-alpha.142",dependencies:{"@brains/auth-service":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@modelcontextprotocol/sdk":"^1.29.0",cors:"^2.8.5",express:"^4.18.0","express-async-handler":"^1.2.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/cors":"^2.8.17",typescript:"^6.0.3"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};class oI extends ND{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",YyA,Q,VR0)}async getTools(){return fyA(this.id,()=>this.context)}async getResources(){return[]}async onRegister(A){if(this.domain=A.domain,this.config.transport==="http"&&!A.plugins.has("webserver"))throw Error("MCP HTTP transport requires the webserver interface. Standalone HTTP listeners have been removed.");if(this.logger.debug(`MCP interface initialized with ${this.config.transport} transport`),this.config.transport==="http")A.endpoints.register({label:"MCP",url:"/mcp",priority:30,visibility:"trusted"}),A.interactions.register({id:"mcp",label:"MCP",description:"Connect a trusted client through the Model Context Protocol.",href:"/mcp",kind:"protocol",priority:30,visibility:"trusted"});JR0(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;let A=P7();return this.httpServer=Ez.createFresh({port:this.config.httpPort,logger:this.logger,sessionIdleTtlMs:this.config.sessionIdleTtlMs,auth:this.config.authToken?{token:this.config.authToken}:A?{requiredScopes:["mcp"],verifyBearerToken:async(Q)=>A.verifyBearerToken(Q)}:{disabled:!0}}),this.httpServer}getWebRoutes(){if(this.config.transport!=="http")return[];let A=(Q)=>this.getOrCreateHttpServer().handleRequest(Q);return[{path:"/status",method:"GET",public:!0,handler:A},{path:"/mcp",method:"GET",public:!0,handler:A},{path:"/mcp",method:"POST",public:!0,handler:A},{path:"/mcp",method:"DELETE",public:!0,handler:A},{path:"/mcp",method:"OPTIONS",public:!0,handler:A}]}createDaemon(){return{start:async()=>{await this.startServer()},stop:async()=>{await this.stopServer()},healthCheck:async()=>{let A=this.isServerRunning(),Q="MCP server not running";if(A)if(this.config.transport==="http")Q=`MCP HTTP: ${this.domain?`https://${this.domain}/mcp`:"http://localhost:8080/mcp"}`;else Q="MCP stdio server running";return{status:A?"healthy":"error",message:Q,lastCheck:new Date,details:{transport:this.config.transport,mode:this.config.mode,url:this.config.transport==="http"?this.domain?`https://${this.domain}/mcp`:"http://localhost:8080/mcp":void 0,running:A}}}}}isServerRunning(){if(this.config.transport==="stdio")return this.stdioServer!==void 0&&this.mcpTransport!==void 0;else return this.httpServer!==void 0&&this.mcpTransport!==void 0}async startServer(){if(!this.context)throw Error("Context not initialized");let A=this.context;this.mcpTransport=A.mcpTransport;let Q=this.config.transport==="stdio"?"stdio":"http",w=this.context.permissions.getUserLevel("mcp",Q),B=P7(),$=this.config.transport==="http"&&(this.config.authToken?!0:B!==void 0);if($)w="anchor",this.logger.debug("HTTP authentication configured - authenticated users will have anchor permissions");if(this.config.mode==="debug"){if(this.config.transport==="http"&&!$)throw Error("MCP debug mode requires authenticated HTTP transport; configure authToken or OAuth auth service.");if(w!=="anchor")throw Error("MCP debug mode requires anchor permissions.")}if(this.mcpTransport.setProtocolMode(this.config.mode),this.mcpTransport.setPermissionLevel(w),this.logger.debug(`Starting MCP ${this.config.transport} transport in ${this.config.mode} mode with ${w} permissions`),this.config.transport==="stdio"){this.stdioServer=vK.createFresh();let f=this.mcpTransport.getMcpServer();this.stdioServer.connectMCPServer(f),await this.stdioServer.start(),this.logger.debug("MCP STDIO transport started")}else{this.httpServer=this.getOrCreateHttpServer();let f=this.mcpTransport.getMcpServer();this.httpServer.connectMCPServer(f,this.mcpTransport),this.logger.debug("MCP HTTP transport mounted on shared webserver host")}}async stopServer(){if(this.logger.debug(`Stopping MCP ${this.config.transport} transport`),this.stdioServer)this.stdioServer.stop(),this.stdioServer=void 0;if(this.httpServer)await this.httpServer.stop(),this.httpServer=void 0;this.mcpTransport=void 0}async handleProgressEvent(A,Q){}async onShutdown(){vK.resetInstance(),Ez.resetInstance()}}wA();function Jp(A,Q=2000){if(A.length<=Q)return[A];let w=Pr2(A),B=[],$="";for(let f of w){let Y=$?`
2295
+ </html>`}function qp(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(HR0(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function fG(A){return A.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;")}import{randomUUID as Hr2}from"crypto";function ngA(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function Wr2(A){let Q=new Uint8Array(A);if(Q.length===64)return Q;if(Q[0]!==48)return Q;let w=2;if(Q[1]&&Q[1]>128)w+=Q[1]-128;if(Q[w]!==2)throw Error("Invalid DER ECDSA signature");let B=Q[w+1];if(B===void 0)throw Error("Invalid DER ECDSA signature");let $=w+2,f=Q.slice($,$+B);if(w=$+B,Q[w]!==2)throw Error("Invalid DER ECDSA signature");let Y=Q[w+1];if(Y===void 0)throw Error("Invalid DER ECDSA signature");let X=w+2,W=Q.slice(X,X+Y);return new Uint8Array([...rgA(f),...rgA(W)])}function rgA(A){let Q=A;while(Q.length>32&&Q[0]===0)Q=Q.slice(1);if(Q.length>32)throw Error("Invalid P-256 signature component length");if(Q.length===32)return Q;let w=new Uint8Array(32);return w.set(Q,32-Q.length),w}async function UR0(A,Q){let w={typ:"JWT",alg:"ES256",kid:A.kid},B=`${ngA(w)}.${ngA(Q)}`,$=await crypto.subtle.importKey("jwk",A,{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),f=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},$,new TextEncoder().encode(B));return`${B}.${Buffer.from(Wr2(f)).toString("base64url")}`}var Kr2=600;class DR0{clientStore;authCodeStore;refreshTokenStore;sessionStore;keyStore;authorizationApprovalTokens=new Map;constructor(A){this.clientStore=A.clientStore,this.authCodeStore=A.authCodeStore,this.refreshTokenStore=A.refreshTokenStore,this.sessionStore=A.sessionStore,this.keyStore=A.keyStore}async handleAuthorizePage(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return qp(A);let w=await this.validateAuthorizationRequest(new URL(A.url).searchParams);if(!w.success)return new Response(w.error,{status:400});let B=this.createAuthorizationApprovalToken(Q,w.params);return Xh(dgA(w.params,B))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return qp(A);let w=await A.formData(),B=await this.validateAuthorizationRequest(new URLSearchParams(YR0(w)));if(!B.success)return new Response(B.error,{status:400});let $=w.get("approval_token"),f=typeof $==="string"?$:void 0;if(!f||!this.consumeAuthorizationApprovalToken(f,Q,B.params))return new Response("Invalid authorization approval token",{status:400});let Y=await this.authCodeStore.createCode({clientId:B.params.clientId,redirectUri:B.params.redirectUri,codeChallenge:B.params.codeChallenge,...B.params.scope?{scope:B.params.scope}:{},subject:Q.subject}),X=new URL(B.params.redirectUri);if(X.searchParams.set("code",Y.code),B.params.state)X.searchParams.set("state",B.params.state);return Response.redirect(X.toString(),302)}createAuthorizationApprovalToken(A,Q){this.pruneExpiredAuthorizationApprovalTokens();let w=`oat_${Hr2()}`;return this.authorizationApprovalTokens.set(w,{token:w,sessionId:A.id,clientId:Q.clientId,redirectUri:Q.redirectUri,codeChallenge:Q.codeChallenge,...Q.scope?{scope:Q.scope}:{},...Q.state?{state:Q.state}:{},expiresAt:Math.floor(Date.now()/1000)+Kr2}),w}consumeAuthorizationApprovalToken(A,Q,w){this.pruneExpiredAuthorizationApprovalTokens();let B=this.authorizationApprovalTokens.get(A);if(!B)return!1;return this.authorizationApprovalTokens.delete(A),B.sessionId===Q.id&&B.clientId===w.clientId&&B.redirectUri===w.redirectUri&&B.codeChallenge===w.codeChallenge&&B.scope===w.scope&&B.state===w.state}pruneExpiredAuthorizationApprovalTokens(){let A=Math.floor(Date.now()/1000);for(let[Q,w]of this.authorizationApprovalTokens.entries())if(w.expiresAt<=A)this.authorizationApprovalTokens.delete(Q)}async validateAuthorizationRequest(A){let Q=A.get("response_type"),w=A.get("client_id"),B=A.get("redirect_uri"),$=A.get("code_challenge"),f=A.get("code_challenge_method"),Y=A.get("scope")??void 0,X=A.get("state")??void 0;if(Q!=="code")return{success:!1,error:"Unsupported response_type"};if(!w)return{success:!1,error:"Missing client_id"};if(!B)return{success:!1,error:"Missing redirect_uri"};if(!$)return{success:!1,error:"Missing code_challenge"};if(f!=="S256")return{success:!1,error:"Unsupported code_challenge_method"};let W=await this.clientStore.getClient(w);if(!W)return{success:!1,error:"Unknown client_id"};if(!SP0(W.redirect_uris,B))return{success:!1,error:"Unregistered redirect_uri"};let H=Y??W.scope;return{success:!0,params:{clientId:w,redirectUri:B,codeChallenge:$,...H?{scope:H}:{},...X?{state:X}:{},clientName:W.client_name??W.client_id}}}async handleClientRegistration(A){let Q;try{Q=await A.json()}catch{return r$("invalid_client_metadata","Request body must be JSON")}try{let w=await this.clientStore.registerClient(Q);return sX(w,201)}catch(w){if(w instanceof Oc)return r$("invalid_client_metadata",w.message);throw w}}async handleTokenRequest(A,Q){let w=await fR0(A),B=w.get("grant_type"),$=ZR0(A,w),f=$.clientId??w.get("client_id");if($.error)return r$("invalid_client",$.error);if(!f)return r$("invalid_request","client_id is required");let Y=await this.clientStore.getClient(f),X=XR0(Y,$);if(X)return r$("invalid_client",X);if(B==="authorization_code")return this.handleAuthorizationCodeGrant(w,f,Q);if(B==="refresh_token")return this.handleRefreshTokenGrant(w,f,Q);return r$("unsupported_grant_type","Only authorization_code and refresh_token are supported")}async handleAuthorizationCodeGrant(A,Q,w){let B=A.get("code"),$=A.get("redirect_uri"),f=A.get("code_verifier");if(!B||!$||!f)return r$("invalid_request","code, redirect_uri, and code_verifier are required");let Y=await this.clientStore.getClient(Q);if(!Y||!SP0(Y.redirect_uris,$))return r$("invalid_grant","Unregistered redirect_uri");try{let X=await this.authCodeStore.consumeCode({code:B,clientId:Q,redirectUri:$,codeVerifier:f});return await this.createTokenResponse({issuer:w,clientId:Q,subject:X.subject,...X.scope?{scope:X.scope}:{}})}catch(X){if(X instanceof hK)return r$("invalid_grant",X.message);throw X}}async handleRefreshTokenGrant(A,Q,w){let B=A.get("refresh_token");if(!B)return r$("invalid_request","refresh_token is required");try{let $=await this.refreshTokenStore.rotateToken(B,Q);return await this.createTokenResponse({issuer:w,clientId:Q,subject:$.consumed.subject,...$.consumed.scope?{scope:$.consumed.scope}:{},refreshToken:$.replacement.token})}catch($){if($ instanceof Xq)return r$("invalid_grant",$.message);throw $}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),w=900,B=await UR0(await this.keyStore.getPrivateJwk(),{iss:A.issuer,sub:A.subject,aud:A.clientId,iat:Q,exp:Q+900,...A.scope?{scope:A.scope}:{}}),$=A.refreshToken??(await this.refreshTokenStore.issueToken({clientId:A.clientId,subject:A.subject,...A.scope?{scope:A.scope}:{}})).token;return sX({access_token:B,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:$})}async handleRevokeRequest(A){let Q=await fR0(A),w=ZR0(A,Q),B=w.clientId??Q.get("client_id")??void 0,$=Q.get("token");if(w.error)return r$("invalid_client",w.error);if(!$)return r$("invalid_request","token is required");if(B){let f=await this.clientStore.getClient(B),Y=XR0(f,w);if(Y)return r$("invalid_client",Y)}return await this.refreshTokenStore.revokeToken($,B),new Response(null,{status:200})}}class GR0{passkeyService;sessionStore;setupFlow;constructor(A){this.passkeyService=A.passkeyService,this.sessionStore=A.sessionStore,this.setupFlow=A.setupFlow}async handleRegistrationOptions(A){if(await this.passkeyService.hasCredentials())return r$("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return r$("access_denied","Invalid setup token");let Q=await this.passkeyService.generateRegistrationOptions(E60(A));return sX(Q)}async handleRegistrationVerify(A){if(await this.passkeyService.hasCredentials())return r$("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return r$("access_denied","Invalid setup token");let Q=await this.passkeyService.verifyRegistrationResponse(await A.json(),E60(A));if(!Q.verified)return r$("access_denied","Passkey registration failed");await this.setupFlow.clearSetupState();let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:Up(A)});return sX({verified:!0},200,{"Set-Cookie":w.cookie})}async handleAuthenticationOptions(A){if(!await this.passkeyService.hasCredentials())return r$("access_denied","No passkey registered");let Q=await this.passkeyService.generateAuthenticationOptions(E60(A));return sX(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),E60(A));if(!Q.verified)return r$("access_denied","Passkey authentication failed");let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:Up(A)});return sX({verified:!0},200,{"Set-Cookie":w.cookie})}}function E60(A){let Q=Ah(A),w=new URL(Q);return{origin:w.origin,rpID:w.hostname}}import{randomUUID as Ur2}from"crypto";var bp=86400;class zR0{setupStateStore;passkeyService;setupTokenTtlSeconds;setupToken;constructor(A){this.setupStateStore=A.setupStateStore,this.passkeyService=A.passkeyService,this.setupTokenTtlSeconds=A.setupTokenTtlSeconds??bp}async ensureSetupToken(){let A=this.getValidSetupToken();if(A)return A;let Q=await this.setupStateStore.getValidSetupToken(Math.floor(Date.now()/1000));if(Q)return this.setupToken=Q,Q;return this.createSetupToken()}async createSetupToken(){return this.setupToken={token:`setup_${Ur2()}`,expiresAt:Math.floor(Date.now()/1000)+this.setupTokenTtlSeconds},await this.setupStateStore.saveSetupToken(this.setupToken),this.setupToken}getValidSetupToken(){if(!this.setupToken)return;if(this.setupToken.expiresAt<=Math.floor(Date.now()/1000)){this.setupToken=void 0;return}return this.setupToken}hasValidSetupToken(A){let Q=this.getValidSetupToken();if(!Q)return!1;let w=new URL(A.url);return(w.searchParams.get("setup_token")??w.searchParams.get("token"))===Q.token}async clearSetupState(){this.setupToken=void 0,await this.setupStateStore.clearSetupState()}getSetupUrl(A){let Q=this.getValidSetupToken();if(!Q)return;return pK(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:pK(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:Sx0(Q.token)}}async handleSetupPage(A){if(await this.passkeyService.hasCredentials())return new Response("Setup already completed",{status:404});if(!this.hasValidSetupToken(A))return new Response("Not Found",{status:404});let Q=new URL(A.url).searchParams.get("token")??"";return Xh(pgA(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupStateStore.recordDelivery(A,Q,w)}}class T60{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;a2aKeyStore;clientStore;authCodeStore;sessionStore;peerTrustStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=lK(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>lK(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??ev(this.issuer),this.keyStore=new tQ0({storageDir:A.storageDir}),this.a2aKeyStore=new mP0({storageDir:A.storageDir}),this.clientStore=new aQ0({storageDir:A.storageDir}),this.authCodeStore=new sQ0({storageDir:A.storageDir}),this.sessionStore=new v60({storageDir:A.storageDir}),this.peerTrustStore=new M60({storageDir:A.storageDir}),this.passkeyService=new P60({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new zR0({setupStateStore:new mx0({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??bp}),this.oauthEndpoints=new DR0({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new O60({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new GR0({passkeyService:this.passkeyService,sessionStore:this.sessionStore,setupFlow:this.setupFlow}),this.logger=A.logger}getIssuer(){return this.issuer}async initialize(){if(await Promise.all([this.keyStore.getPrivateJwk(),this.a2aKeyStore.getPrivateJwk()]),this.logger?.debug("Auth service signing keys loaded"),!await this.hasPasskeyCredentials()){await this.setupFlow.ensureSetupToken();let A=this.getSetupUrl();if(A)if(ev(this.issuer))this.logger?.warn(`Passkey setup required: ${A}`);else this.logger?.warn("Passkey setup required. Ask through an anchor-visible interface for the setup URL.")}}async hasPasskeyCredentials(){return this.passkeyService.hasCredentials()}async getJwks(){let[A,Q]=await Promise.all([this.keyStore.getPublicJwk(),this.a2aKeyStore.getPublicJwk()]);return{keys:[A,Q]}}async getA2ASigningKey(){let A=await this.a2aKeyStore.getPrivateJwk();return{privateJwk:A,keyId:pK(this.issuer,`/.well-known/jwks.json#${A.kid}`)}}grantA2APeerTrust(A){return this.peerTrustStore.grant(A)}getA2APeerTrust(A){return this.peerTrustStore.get(A)}revokeA2APeerTrust(A){return this.peerTrustStore.revoke(A)}getAuthorizationServerMetadata(A=this.issuer){let Q=lK(A);return{issuer:Q,authorization_endpoint:pK(Q,"/authorize"),token_endpoint:pK(Q,"/token"),registration_endpoint:pK(Q,"/register"),revocation_endpoint:pK(Q,"/revoke"),jwks_uri:pK(Q,"/.well-known/jwks.json"),response_types_supported:["code"],grant_types_supported:["authorization_code","refresh_token"],code_challenge_methods_supported:["S256"],token_endpoint_auth_methods_supported:["none","client_secret_basic","client_secret_post"],scopes_supported:["openid","profile","email","offline_access","mcp"],subject_types_supported:["public"],id_token_signing_alg_values_supported:["ES256"]}}getProtectedResourceMetadata(A,Q=this.issuer){return{resource:A,authorization_servers:[lK(Q)],bearer_methods_supported:["header"],resource_signing_alg_values_supported:["ES256"],scopes_supported:["mcp"]}}async registerClient(A){return this.clientStore.registerClient(A)}async getRegisteredClient(A){return this.clientStore.getClient(A)}async createOperatorSession(A="single-operator",Q={}){return this.sessionStore.createSession(A,Q)}async getOperatorSession(A){return this.sessionStore.getSessionFromRequest(A)}createOperatorLoginResponse(A){return qp(A)}async verifyBearerToken(A,Q={}){let w=$R0(A);if(!w)return;let B=Q.issuer?lK(Q.issuer):this.resolveRequestIssuer(A);return BR0(w,await this.getJwks(),{issuer:B,...Q.audience?{audience:Q.audience}:{}})}getSetupUrl(A=this.issuer){return this.setupFlow.getSetupUrl(A)}async getOperatorSetupRequired(A=this.issuer){return this.setupFlow.getOperatorSetupRequired(A)}async hasSetupEmailDelivery(A,Q){return this.setupFlow.hasSetupEmailDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupFlow.recordSetupEmailDelivery(A,Q,w)}async handleRequest(A){let Q;try{Q=this.resolveRequestIssuer(A)}catch(B){return this.logger?.warn("Rejected OAuth request from untrusted issuer",{error:B instanceof Error?B.message:String(B)}),new Response("Untrusted OAuth issuer",{status:400})}let w=new URL(A.url).pathname;if(A.method==="OPTIONS"&&ugA(w))return cgA();if(A.method==="GET"){if(w==="/.well-known/oauth-authorization-server")return rI(sX(this.getAuthorizationServerMetadata(Q)));if(w==="/.well-known/jwks.json")return rI(sX(await this.getJwks()));if(w==="/.well-known/oauth-protected-resource")return rI(sX(this.getProtectedResourceMetadata(Q,Q)))}if(A.method==="GET"&&w==="/setup")return this.setupFlow.handleSetupPage(A);if(A.method==="GET"&&w==="/login")return this.handleLoginPage(A);if((A.method==="GET"||A.method==="POST")&&w==="/logout")return this.handleLogout(A);if(A.method==="POST"&&w==="/webauthn/register/options")return this.webauthnEndpoints.handleRegistrationOptions(A);if(A.method==="POST"&&w==="/webauthn/register/verify")return this.webauthnEndpoints.handleRegistrationVerify(A);if(A.method==="POST"&&w==="/webauthn/auth/options")return this.webauthnEndpoints.handleAuthenticationOptions(A);if(A.method==="POST"&&w==="/webauthn/auth/verify")return this.webauthnEndpoints.handleAuthenticationVerify(A);if(A.method==="GET"&&w==="/authorize")return this.oauthEndpoints.handleAuthorizePage(A);if(A.method==="POST"&&w==="/authorize")return this.oauthEndpoints.handleAuthorizeApproval(A);if(A.method==="POST"&&w==="/register")return rI(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&w==="/token")return rI(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&w==="/revoke")return rI(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=Ah(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&ev(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=WR0(new URL(A.url).searchParams.get("return_to"));return Xh(HR0(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=WR0(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":cx0(Up(A)),"Cache-Control":"no-store"}})}}N0();var S60="email:send",ogA=Z.strictObject({to:Z.string().email(),subject:Z.string().min(1),text:Z.string().min(1),html:Z.string().min(1).optional(),sensitivity:Z.enum(["normal","secret"]).default("normal")});wA();N0();var sgA={name:"@brains/notifications",version:"0.2.0-alpha.143",description:"Generic notification routing for transactional and administrative messages",dependencies:{"@brains/email-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var qR0="notifications:send",Gr2=Z.looseObject({}),zr2=Z.discriminatedUnion("type",[Z.strictObject({type:Z.literal("email"),address:Z.email()})]),qr2=Z.strictObject({recipient:zr2,title:Z.string().min(1),body:Z.string().min(1),html:Z.string().min(1).optional(),sensitivity:Z.enum(["normal","secret"]).default("normal")}),agA=Z.discriminatedUnion("status",[Z.strictObject({status:Z.literal("sent"),deliveryId:Z.string().optional()}),Z.strictObject({status:Z.literal("failed")})]);class tgA extends aQ{constructor(A={}){super("notifications",sgA,A,Gr2)}async onRegister(A){A.messaging.subscribe(qR0,async(Q)=>{let w=qr2.parse(Q.payload),B={to:w.recipient.address,subject:w.title,text:w.body,...w.html?{html:w.html}:{},sensitivity:w.sensitivity},$=await A.messaging.send({type:S60,payload:B});if(!("success"in $)||!$.success||!$.data)return{success:!1,error:"Notification delivery failed"};let f=$.data;if(f.status!=="sent")return{success:!1,error:"Notification delivery failed"};return{success:!0,data:f.id?{status:"sent",deliveryId:f.id}:{status:"sent"}}})}}function m60(A={}){return new tgA(A)}wA();N0();var egA={name:"@brains/auth-service",version:"0.2.0-alpha.143",description:"Embedded OAuth/OIDC auth service for brain operator authentication",dependencies:{"@brains/notifications":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@simplewebauthn/server":"^13.3.1",jose:"^6.2.3"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},files:["src"],main:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var Vr2=Z.union([Z.string().email(),Z.object({to:Z.string().email(),subject:Z.string().min(1),body:Z.string().min(1)}).strict()]),Ir2=Z.object({issuer:Z.string().optional(),trustedIssuers:Z.array(Z.string()).default([]),allowLocalhostIssuers:Z.boolean().optional(),storageDir:Z.string().default("./data/auth"),setupTokenTtlSeconds:Z.number().int().positive().default(bp),setupEmail:Vr2.optional()}),u60;function P7(){return u60}class bR0 extends aQ{service;constructor(A={}){super("auth-service",egA,A,Ir2)}async onRegister(A){await super.onRegister(A);let Q=this.config.issuer??(A.preferLocalUrls?A.localSiteUrl??A.siteUrl:A.siteUrl??A.localSiteUrl);this.service=new T60({storageDir:this.config.storageDir,...Q?{issuer:Q}:{},trustedIssuers:this.config.trustedIssuers,...this.config.allowLocalhostIssuers!==void 0?{allowLocalhostIssuers:this.config.allowLocalhostIssuers}:{},setupTokenTtlSeconds:this.config.setupTokenTtlSeconds,logger:A.logger}),await this.service.initialize(),u60=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(u60===this.service)u60=void 0;this.service=void 0}async getTools(){return[{name:`${this.id}_get_passkey_setup_url`,description:"Get the first-passkey setup URL when operator setup is required. Anchor-only.",inputSchema:{},visibility:"anchor",handler:async()=>{let A=this.getService();if(await A.hasPasskeyCredentials())return{success:!0,data:{status:"complete"}};let Q=await A.getOperatorSetupRequired();if(Q)return{success:!0,data:{status:"setup_required",setupUrl:Q.setupUrl,expiresAt:Q.expiresAt}};return{success:!0,data:{status:"unavailable",reason:"Passkey setup URL is not available."}}},sideEffects:"none"}]}getWebRoutes(){let A=(Q)=>this.getService().handleRequest(Q);return[{path:"/.well-known/oauth-authorization-server",method:"GET",public:!0,handler:A},{path:"/.well-known/oauth-authorization-server",method:"OPTIONS",public:!0,handler:A},{path:"/.well-known/jwks.json",method:"GET",public:!0,handler:A},{path:"/.well-known/jwks.json",method:"OPTIONS",public:!0,handler:A},{path:"/.well-known/oauth-protected-resource",method:"GET",public:!0,handler:A},{path:"/.well-known/oauth-protected-resource",method:"OPTIONS",public:!0,handler:A},{path:"/setup",method:"GET",public:!0,handler:A},{path:"/login",method:"GET",public:!0,handler:A},{path:"/logout",method:"GET",public:!0,handler:A},{path:"/logout",method:"POST",public:!0,handler:A},{path:"/authorize",method:"GET",public:!0,handler:A},{path:"/authorize",method:"POST",public:!0,handler:A},{path:"/register",method:"POST",public:!0,handler:A},{path:"/register",method:"OPTIONS",public:!0,handler:A},{path:"/token",method:"POST",public:!0,handler:A},{path:"/token",method:"OPTIONS",public:!0,handler:A},{path:"/revoke",method:"POST",public:!0,handler:A},{path:"/revoke",method:"OPTIONS",public:!0,handler:A},{path:"/webauthn/register/options",method:"POST",public:!0,handler:A},{path:"/webauthn/register/verify",method:"POST",public:!0,handler:A},{path:"/webauthn/auth/options",method:"POST",public:!0,handler:A},{path:"/webauthn/auth/verify",method:"POST",public:!0,handler:A}]}getService(){if(!this.service)throw Error("AuthServicePlugin has not been registered");return this.service}async requestSetupEmailIfNeeded(A){if(!this.config.setupEmail)return;let Q=this.getService();if(await Q.hasPasskeyCredentials())return;let w=await Q.getOperatorSetupRequired();if(!w)return;let B=Jr2(this.config.setupEmail,w);if(await Q.hasSetupEmailDelivery(w.setupTokenId,B.to))return;let $=await A.messaging.send({type:qR0,payload:{recipient:{type:"email",address:B.to},title:B.subject,body:B.body,sensitivity:"secret"}});if(!("success"in $)||!$.success||!$.data){A.logger.warn("Passkey setup email delivery was not confirmed");return}let f=agA.safeParse($.data);if(!f.success||f.data.status!=="sent"){A.logger.warn("Passkey setup email delivery was not confirmed");return}await Q.recordSetupEmailDelivery(w.setupTokenId,B.to,f.data.deliveryId?{deliveryId:f.data.deliveryId}:{})}}function Jr2(A,Q){if(typeof A==="string"){let w=new Date(Q.expiresAt*1000).toISOString(),B=new URL(Q.setupUrl).origin;return{to:A,subject:"Set up your brain passkey",body:["Set up your brain passkey using this single-use link:","",Q.setupUrl,"",`This link expires at ${w}.`,`Dashboard: ${B}/`,`MCP endpoint: ${B}/mcp`,"The first successful passkey registration completes setup and closes this link."].join(`
2296
+ `)}}return{to:A.to,subject:AyA(A.subject,Q),body:AyA(A.body,Q)}}function AyA(A,Q){let w=new Date(Q.expiresAt*1000).toISOString(),B=new URL(Q.setupUrl).origin;return A.replaceAll("{{setupUrl}}",Q.setupUrl).replaceAll("{{expiresAt}}",w).replaceAll("{{origin}}",B)}function Vp(A={}){return new bR0(A)}N0();var VR0=Z.object({transport:Z.enum(["stdio","http"]).default("http"),mode:Z.enum(["basic","debug"]).default("basic"),httpPort:Z.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:Z.string().describe("Bearer token for HTTP transport authentication").optional(),sessionIdleTtlMs:Z.number().describe("Idle time in ms after which an HTTP session is closed and evicted").default(1800000)});N0();function Fr2(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function Ip(A,Q){let w=A?.[Q];return typeof w==="string"&&w.length>0?w:void 0}function Lr2(A){let Q=Fr2(A.data)?A.data:void 0,w=A.args,B=Ip(Q,"entityId")??Ip(Q,"id"),$=A.jobId??Ip(Q,"jobId"),f=Ip(w,"entityType")??Ip(w,"type");if(!B&&!$)return;return{toolName:A.toolName,...f?{entityType:f}:{},...B?{entityId:B}:{},...$?{jobId:$}:{}}}function kr2(A){return A?.map(Lr2).filter((Q)=>Q!==void 0)??[]}function IR0(A,Q={}){let w=A.pendingConfirmations?.[0];if(w)return{needsConfirmation:!0,toolName:w.toolName,summary:w.summary,...w.completionSummary?{completionSummary:w.completionSummary}:{},...w.preview?{preview:w.preview}:{},args:{approvalId:w.id,...Q.conversationId?{conversationId:Q.conversationId}:{},...w.toolCallId?{toolCallId:w.toolCallId}:{},originalArgs:w.args}};let B=kr2(A.toolResults);return{success:!0,data:{text:A.text,...A.toolResults?{toolResults:A.toolResults}:{},...B.length>0?{readYourWrites:B}:{}}}}var QyA=Z.object({message:Z.string().min(1),conversationId:Z.string().min(1).optional()}),wyA=Z.object({approvalId:Z.string().min(1),confirmed:Z.boolean(),conversationId:Z.string().min(1).optional()});function ByA(A,Q,w,B){return A.conversationId??w??B??`mcp:${Q}`}function $yA(A){return{userPermissionLevel:A.userPermissionLevel??"public",interfaceType:"mcp",...A.channelId?{channelId:A.channelId}:{},...A.channelName?{channelName:A.channelName}:{},actor:{actorId:A.userId,interfaceType:"mcp",role:"user"}}}function fyA(A,Q){return[{name:"chat",description:"Talk to the brain to make changes or get reasoned answers. Use this for any create/update/delete request or questions requiring reasoning across content. For simple lookups, use search/get/list directly.",inputSchema:QyA.shape,visibility:"public",sideEffects:"writes",handler:async(w,B)=>{let $=QyA.parse(w),f=Q();if(!f)return{success:!1,error:"MCP chat tool is not initialized."};let Y=ByA($,B.userId,B.conversationId,B.channelId),X=await f.agent.chat($.message,Y,{...$yA(B)});return IR0(X,{conversationId:Y})}},{name:"confirm",description:"Resolve a pending confirmation returned by chat. Use this only after chat returns needsConfirmation with an approvalId.",inputSchema:wyA.shape,visibility:"public",sideEffects:"writes",handler:async(w,B)=>{let $=wyA.parse(w),f=Q();if(!f)return{success:!1,error:"MCP confirm tool is not initialized."};let Y=ByA($,B.userId,B.conversationId,B.channelId),X=await f.agent.confirmPendingAction(Y,$.confirmed,$.approvalId,$yA(B));return IR0(X,{conversationId:Y})}}]}wA();function JR0(A,Q){A.messaging.subscribe("job-progress",async(w)=>{let B=IO.safeParse(w.payload);if(!B.success)return Q.warn("Received invalid job-progress message",{error:B.error.message}),{success:!1};let $=B.data,f=$.type,Y=$.status,X=$.id;if(Q.debug(`${f} ${X} - ${Y}:`,{id:$.id,message:$.message,progress:$.progress,metadata:$.metadata}),$.batchDetails)Q.debug(`Batch details for ${X}:`,{totalOperations:$.batchDetails.totalOperations,completedOperations:$.batchDetails.completedOperations,failedOperations:$.batchDetails.failedOperations,currentOperation:$.batchDetails.currentOperation,errors:$.batchDetails.errors});if($.jobDetails)Q.debug(`Job details for ${X}:`,{jobType:$.jobDetails.jobType,priority:$.jobDetails.priority,retryCount:$.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var YyA={name:"@brains/mcp",version:"0.2.0-alpha.143",dependencies:{"@brains/auth-service":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@modelcontextprotocol/sdk":"^1.29.0",cors:"^2.8.5",express:"^4.18.0","express-async-handler":"^1.2.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/cors":"^2.8.17",typescript:"^6.0.3"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};class oI extends ND{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",YyA,Q,VR0)}async getTools(){return fyA(this.id,()=>this.context)}async getResources(){return[]}async onRegister(A){if(this.domain=A.domain,this.config.transport==="http"&&!A.plugins.has("webserver"))throw Error("MCP HTTP transport requires the webserver interface. Standalone HTTP listeners have been removed.");if(this.logger.debug(`MCP interface initialized with ${this.config.transport} transport`),this.config.transport==="http")A.endpoints.register({label:"MCP",url:"/mcp",priority:30,visibility:"trusted"}),A.interactions.register({id:"mcp",label:"MCP",description:"Connect a trusted client through the Model Context Protocol.",href:"/mcp",kind:"protocol",priority:30,visibility:"trusted"});JR0(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;let A=P7();return this.httpServer=Ez.createFresh({port:this.config.httpPort,logger:this.logger,sessionIdleTtlMs:this.config.sessionIdleTtlMs,auth:this.config.authToken?{token:this.config.authToken}:A?{requiredScopes:["mcp"],verifyBearerToken:async(Q)=>A.verifyBearerToken(Q)}:{disabled:!0}}),this.httpServer}getWebRoutes(){if(this.config.transport!=="http")return[];let A=(Q)=>this.getOrCreateHttpServer().handleRequest(Q);return[{path:"/status",method:"GET",public:!0,handler:A},{path:"/mcp",method:"GET",public:!0,handler:A},{path:"/mcp",method:"POST",public:!0,handler:A},{path:"/mcp",method:"DELETE",public:!0,handler:A},{path:"/mcp",method:"OPTIONS",public:!0,handler:A}]}createDaemon(){return{start:async()=>{await this.startServer()},stop:async()=>{await this.stopServer()},healthCheck:async()=>{let A=this.isServerRunning(),Q="MCP server not running";if(A)if(this.config.transport==="http")Q=`MCP HTTP: ${this.domain?`https://${this.domain}/mcp`:"http://localhost:8080/mcp"}`;else Q="MCP stdio server running";return{status:A?"healthy":"error",message:Q,lastCheck:new Date,details:{transport:this.config.transport,mode:this.config.mode,url:this.config.transport==="http"?this.domain?`https://${this.domain}/mcp`:"http://localhost:8080/mcp":void 0,running:A}}}}}isServerRunning(){if(this.config.transport==="stdio")return this.stdioServer!==void 0&&this.mcpTransport!==void 0;else return this.httpServer!==void 0&&this.mcpTransport!==void 0}async startServer(){if(!this.context)throw Error("Context not initialized");let A=this.context;this.mcpTransport=A.mcpTransport;let Q=this.config.transport==="stdio"?"stdio":"http",w=this.context.permissions.getUserLevel("mcp",Q),B=P7(),$=this.config.transport==="http"&&(this.config.authToken?!0:B!==void 0);if($)w="anchor",this.logger.debug("HTTP authentication configured - authenticated users will have anchor permissions");if(this.config.mode==="debug"){if(this.config.transport==="http"&&!$)throw Error("MCP debug mode requires authenticated HTTP transport; configure authToken or OAuth auth service.");if(w!=="anchor")throw Error("MCP debug mode requires anchor permissions.")}if(this.mcpTransport.setProtocolMode(this.config.mode),this.mcpTransport.setPermissionLevel(w),this.logger.debug(`Starting MCP ${this.config.transport} transport in ${this.config.mode} mode with ${w} permissions`),this.config.transport==="stdio"){this.stdioServer=vK.createFresh();let f=this.mcpTransport.getMcpServer();this.stdioServer.connectMCPServer(f),await this.stdioServer.start(),this.logger.debug("MCP STDIO transport started")}else{this.httpServer=this.getOrCreateHttpServer();let f=this.mcpTransport.getMcpServer();this.httpServer.connectMCPServer(f,this.mcpTransport),this.logger.debug("MCP HTTP transport mounted on shared webserver host")}}async stopServer(){if(this.logger.debug(`Stopping MCP ${this.config.transport} transport`),this.stdioServer)this.stdioServer.stop(),this.stdioServer=void 0;if(this.httpServer)await this.httpServer.stop(),this.httpServer=void 0;this.mcpTransport=void 0}async handleProgressEvent(A,Q){}async onShutdown(){vK.resetInstance(),Ez.resetInstance()}}wA();function Jp(A,Q=2000){if(A.length<=Q)return[A];let w=Pr2(A),B=[],$="";for(let f of w){let Y=$?`
2297
2297
 
2298
2298
  `:"";if($.length+Y.length+f.length<=Q){$+=Y+f;continue}if($)B.push($),$="";if(f.length<=Q){$=f;continue}Nr2(f,Q,B,(X)=>{$=X})}if($)B.push($);return B}function Nr2(A,Q,w,B){let $="",f=A.split(`
2299
2299
  `);for(let Y of f){let X=$?`
2300
2300
  `:"";if($.length+X.length+Y.length<=Q){$+=X+Y;continue}if($)w.push($),$="";if(Y.length<=Q){$=Y;continue}jr2(Y,Q,w,(W)=>{$=W})}B($)}function jr2(A,Q,w,B){let $="",f=A.split(" ");for(let Y of f){let X=$?" ":"";if($.length+X.length+Y.length<=Q){$+=X+Y;continue}if($)w.push($);if(Y.length>Q)for(let W=0;W<Y.length;W+=Q){let H=Y.slice(W,W+Q);if(W+Q>=Y.length)$=H;else w.push(H)}else $=Y}B($)}function Pr2(A){let Q=[],w=A.split(`
2301
2301
  `),B="",$=!1;for(let f of w){if(f.startsWith("```"))$=!$;if(!$&&f===""&&B){Q.push(B),B="";continue}B+=(B?`
2302
- `:"")+f}if(B)Q.push(B);return Q}K2();var fZ=X1(yT0(),1);wA();N0();var ET0=Z.object({botToken:Z.string().min(1).describe("Discord bot token"),allowedChannels:Z.array(Z.string()).default([]),requireMention:Z.boolean().default(!0),allowDMs:Z.boolean().default(!0),showTypingIndicator:Z.boolean().default(!0),statusMessage:Z.string().default("Mention me to chat"),useThreads:Z.boolean().default(!0),threadAutoArchive:Z.union([Z.literal(60),Z.literal(1440),Z.literal(4320),Z.literal(10080)]).default(1440),...wm.shape,captureUrlEmoji:Z.string().default("\uD83D\uDD16")});var Vz1={name:"@brains/discord",version:"0.2.0-alpha.142",description:"Discord interface for Brains",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","discord.js":"^14.26.4"},devDependencies:{"@brains/core":"workspace:*","@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var fd=2000,wMQ={completed:"Action completed",declined:"Action declined",failed:"Action failed"},BMQ={completed:2278750,declined:9741240,failed:15680580},$MQ=8388608,fMQ=8000,YMQ=100;function X50(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class CJ extends HK{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;constructor(A,Q={}){super("discord",Vz1,A,ET0);this.fetchText=Q.fetchText??XLA}async onRegister(A){await super.onRegister(A),this.client=new fZ.Client({intents:[fZ.GatewayIntentBits.Guilds,fZ.GatewayIntentBits.GuildMessages,fZ.GatewayIntentBits.MessageContent,fZ.GatewayIntentBits.DirectMessages],partials:[fZ.Partials.Channel]}),this.client.on(fZ.Events.MessageCreate,(Q)=>{this.handleMessage(Q)}),this.client.on(fZ.Events.InteractionCreate,(Q)=>{this.handleInteraction(Q)}),this.client.once(fZ.Events.ClientReady,()=>{this.logger.info("Discord bot connected",{tag:this.client?.user?.tag})})}createDaemon(){return{start:async()=>{if(!this.client)throw Error("Discord client not initialized");await this.client.login(this.config.botToken)},stop:async()=>{for(let A of this.typingIntervals.values())clearInterval(A);if(this.typingIntervals.clear(),this.client)await this.client.destroy(),this.client=null},healthCheck:async()=>({status:this.client?.user?"healthy":"error",message:this.client?.user?`Connected as ${this.client.user.tag}`:"Not connected",lastCheck:new Date})}}sendMessageToChannel({channelId:A,message:Q}){if(!A||!this.client)return;let w=this.client.channels.cache.get(A);if(!X50(w))return;let B=Jp(Q,fd);for(let $ of B)w.send($).catch((f)=>this.logger.error("Failed to send message",{error:f}))}async sendMessageWithId({channelId:A,message:Q,approvalCard:w,approvalCards:B}){let $=B??(w?[w]:[]),f=$.length>0?this.buildApprovalMessagePayload(Q,$):Q;return this.sendPayloadWithId(A,f)}async sendPayloadWithId(A,Q){if(!A||!this.client)return;let w=this.client.channels.cache.get(A);if(!X50(w))return;if(typeof Q!=="string")return(await w.send(Q)).id;let B=Jp(Q,fd),$;for(let f of B)$=(await w.send(f)).id;return $}async editMessage({channelId:A,messageId:Q,newMessage:w}){if(!A||!this.client)return!1;let B=this.client.channels.cache.get(A);if(!X50(B))return!1;try{return await(await B.messages.fetch(Q)).edit(w.slice(0,fd)),!0}catch{return!1}}supportsMessageEditing(){return!0}async handleMessage(A){if(A.author.id===this.client?.user?.id)return;if(!this.context)return;let Q=!A.guild,w=A.channel.isThread();if(Q&&!this.config.allowDMs)return;let B=!!this.client?.user&&A.mentions.has(this.client.user,{ignoreEveryone:!0});if(A.author.bot&&!B)return;let $=w&&"ownerId"in A.channel&&A.channel.ownerId===this.client?.user?.id,f=this.getSpaceChannelId(A),Y=!Q&&this.isConfiguredSpace(f),X={channelId:f,isBot:A.author.bot};if(this.config.allowedChannels.length>0&&!Q&&!this.isAllowedChannel(A.channel.id,f))return;let W=Q||$||!this.config.requireMention||B;if(Y&&(!W||this.willRouteUseNonSpaceConversation(A)))await this.capturePassiveSpaceMessage(A,f).catch((U)=>this.logger.error("Passive Discord space capture failed",{error:U,channelId:f}));if(!W){if(this.config.captureUrls){let U=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(U.length>0){await A.react(this.config.captureUrlEmoji).catch((D)=>this.logger.debug("React failed",{error:D}));for(let D of U)await this.captureUrlViaAgent(D,A.channel.id,A.author.id,"discord",X).catch((q)=>this.logger.error("URL capture failed",{error:q,url:D}))}}return}let H=this.stripMention(A.content);if(A.attachments.size>0){let U=this.context.permissions.getUserLevel("discord",A.author.id,X);if(U==="anchor"||U==="trusted")for(let q of A.attachments.values()){let b=q.name,I=q.contentType??void 0,V=q.size;if(!this.isUploadableTextFile(b,I))continue;if(!this.isFileSizeAllowed(V))continue;try{let L=await this.fetchText(q.url);H+=`
2302
+ `:"")+f}if(B)Q.push(B);return Q}K2();var fZ=X1(yT0(),1);wA();N0();var ET0=Z.object({botToken:Z.string().min(1).describe("Discord bot token"),allowedChannels:Z.array(Z.string()).default([]),requireMention:Z.boolean().default(!0),allowDMs:Z.boolean().default(!0),showTypingIndicator:Z.boolean().default(!0),statusMessage:Z.string().default("Mention me to chat"),useThreads:Z.boolean().default(!0),threadAutoArchive:Z.union([Z.literal(60),Z.literal(1440),Z.literal(4320),Z.literal(10080)]).default(1440),...wm.shape,captureUrlEmoji:Z.string().default("\uD83D\uDD16")});var Vz1={name:"@brains/discord",version:"0.2.0-alpha.143",description:"Discord interface for Brains",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","discord.js":"^14.26.4"},devDependencies:{"@brains/core":"workspace:*","@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var fd=2000,wMQ={completed:"Action completed",declined:"Action declined",failed:"Action failed"},BMQ={completed:2278750,declined:9741240,failed:15680580},$MQ=8388608,fMQ=8000,YMQ=100;function X50(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class CJ extends HK{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;constructor(A,Q={}){super("discord",Vz1,A,ET0);this.fetchText=Q.fetchText??XLA}async onRegister(A){await super.onRegister(A),this.client=new fZ.Client({intents:[fZ.GatewayIntentBits.Guilds,fZ.GatewayIntentBits.GuildMessages,fZ.GatewayIntentBits.MessageContent,fZ.GatewayIntentBits.DirectMessages],partials:[fZ.Partials.Channel]}),this.client.on(fZ.Events.MessageCreate,(Q)=>{this.handleMessage(Q)}),this.client.on(fZ.Events.InteractionCreate,(Q)=>{this.handleInteraction(Q)}),this.client.once(fZ.Events.ClientReady,()=>{this.logger.info("Discord bot connected",{tag:this.client?.user?.tag})})}createDaemon(){return{start:async()=>{if(!this.client)throw Error("Discord client not initialized");await this.client.login(this.config.botToken)},stop:async()=>{for(let A of this.typingIntervals.values())clearInterval(A);if(this.typingIntervals.clear(),this.client)await this.client.destroy(),this.client=null},healthCheck:async()=>({status:this.client?.user?"healthy":"error",message:this.client?.user?`Connected as ${this.client.user.tag}`:"Not connected",lastCheck:new Date})}}sendMessageToChannel({channelId:A,message:Q}){if(!A||!this.client)return;let w=this.client.channels.cache.get(A);if(!X50(w))return;let B=Jp(Q,fd);for(let $ of B)w.send($).catch((f)=>this.logger.error("Failed to send message",{error:f}))}async sendMessageWithId({channelId:A,message:Q,approvalCard:w,approvalCards:B}){let $=B??(w?[w]:[]),f=$.length>0?this.buildApprovalMessagePayload(Q,$):Q;return this.sendPayloadWithId(A,f)}async sendPayloadWithId(A,Q){if(!A||!this.client)return;let w=this.client.channels.cache.get(A);if(!X50(w))return;if(typeof Q!=="string")return(await w.send(Q)).id;let B=Jp(Q,fd),$;for(let f of B)$=(await w.send(f)).id;return $}async editMessage({channelId:A,messageId:Q,newMessage:w}){if(!A||!this.client)return!1;let B=this.client.channels.cache.get(A);if(!X50(B))return!1;try{return await(await B.messages.fetch(Q)).edit(w.slice(0,fd)),!0}catch{return!1}}supportsMessageEditing(){return!0}async handleMessage(A){if(A.author.id===this.client?.user?.id)return;if(!this.context)return;let Q=!A.guild,w=A.channel.isThread();if(Q&&!this.config.allowDMs)return;let B=!!this.client?.user&&A.mentions.has(this.client.user,{ignoreEveryone:!0});if(A.author.bot&&!B)return;let $=w&&"ownerId"in A.channel&&A.channel.ownerId===this.client?.user?.id,f=this.getSpaceChannelId(A),Y=!Q&&this.isConfiguredSpace(f),X={channelId:f,isBot:A.author.bot};if(this.config.allowedChannels.length>0&&!Q&&!this.isAllowedChannel(A.channel.id,f))return;let W=Q||$||!this.config.requireMention||B;if(Y&&(!W||this.willRouteUseNonSpaceConversation(A)))await this.capturePassiveSpaceMessage(A,f).catch((U)=>this.logger.error("Passive Discord space capture failed",{error:U,channelId:f}));if(!W){if(this.config.captureUrls){let U=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(U.length>0){await A.react(this.config.captureUrlEmoji).catch((D)=>this.logger.debug("React failed",{error:D}));for(let D of U)await this.captureUrlViaAgent(D,A.channel.id,A.author.id,"discord",X).catch((q)=>this.logger.error("URL capture failed",{error:q,url:D}))}}return}let H=this.stripMention(A.content);if(A.attachments.size>0){let U=this.context.permissions.getUserLevel("discord",A.author.id,X);if(U==="anchor"||U==="trusted")for(let q of A.attachments.values()){let b=q.name,I=q.contentType??void 0,V=q.size;if(!this.isUploadableTextFile(b,I))continue;if(!this.isFileSizeAllowed(V))continue;try{let L=await this.fetchText(q.url);H+=`
2303
2303
 
2304
2304
  `+this.formatFileUploadMessage(b,L)}catch(L){this.logger.error("Failed to download attachment",{error:L,filename:b})}}}if(H=H.trim(),!H)return;let K=A.channel.id;await this.routeToAgent(H,K,A,X)}async handleInteraction(A){if(!this.context||!A.isButton())return;let Q=this.parseApprovalButtonCustomId(A.customId);if(!Q)return;let w=`discord-${A.channelId}`;if(!this.pendingConfirmations.get(w)?.has(Q.approvalId)){await A.reply({content:"This approval is no longer pending or has changed.",ephemeral:!0}).catch((Y)=>this.logger.debug("Failed to reply to stale approval button",{error:Y}));return}await A.deferUpdate().catch((Y)=>this.logger.debug("Failed to defer approval button",{error:Y})),await this.clearApprovalInteractionComponents(A);let $=this.buildInteractionConfirmationContext(A),f=await this.context.agent.confirmPendingAction(w,Q.confirmed,Q.approvalId,$);await this.handleAgentResponseToolStatuses(f,w),this.syncPendingApprovalsAfterResolution(w,Q.approvalId,f),await this.sendApprovalResultMessage({channelId:A.channelId,response:f,userPermissionLevel:$.userPermissionLevel??"public"})}async clearApprovalInteractionComponents(A){await A.message.edit({components:[]}).catch((Q)=>this.logger.debug("Failed to clear approval buttons",{error:Q}))}buildInteractionConfirmationContext(A){if(!this.context)throw Error("Discord context is not registered");return{userPermissionLevel:this.context.permissions.getUserLevel("discord",A.user.id,{channelId:A.channelId}),interfaceType:"discord",channelId:A.channelId,actor:{actorId:`discord:${A.user.id}`,interfaceType:"discord",role:"user",displayName:A.user.displayName,username:A.user.username,isBot:Boolean(A.user.bot)}}}async capturePassiveSpaceMessage(A,Q){if(!this.context)return;let w=this.stripMention(A.content).trim();if(!w)return;let B=`discord-${Q}`,$=this.getChannelName(A);await this.context.conversations.start({sessionId:B,interfaceType:"discord",channelId:Q,metadata:{channelName:$,interfaceType:"discord",channelId:Q}}),await this.context.conversations.addMessage({conversationId:B,role:"user",content:w,metadata:this.buildUserMessageMetadata(A,Q,$,{threadId:A.channel.isThread()?A.channel.id:void 0})})}async routeToAgent(A,Q,w,B){if(!this.context)return;let $=this.context.agent,f=Q;if(this.config.useThreads&&w.guild&&!w.channel.isThread())try{f=(await w.startThread({name:Gf(A,YMQ),autoArchiveDuration:this.config.threadAutoArchive})).id}catch(H){this.logger.error("Failed to create thread",{error:H})}let Y=`discord-${f}`,X=this.context.permissions.getUserLevel("discord",w.author.id,B),W=this.getChannelName(w);this.startProcessingInput(f);try{let H=this.client?.channels.cache.get(f);if(X50(H))this.startTypingIndicator(H);if(this.pendingConfirmations.has(Y)){if(await this.handleConfirmationResponse(A,Y,f,w,B))return}let K=await $.chat(A,Y,{userPermissionLevel:X,interfaceType:"discord",channelId:f,channelName:W,...this.buildUserMessageMetadata(w,Q,W,{threadId:f!==Q||w.channel.isThread()?f:void 0})});await this.handleAgentResponseToolStatuses(K,Y);let U=Fk(K.cards);if(U.length>0)this.pendingConfirmations.set(Y,new Set(U.map((q)=>q.id)));else if(K.pendingConfirmations)this.pendingConfirmations.set(Y,new Set(K.pendingConfirmations.map((q)=>q.id)));else this.pendingConfirmations.delete(Y);let D=await this.sendMessageWithId({channelId:f,message:wx(K.text,U),approvalCards:U});if(D&&K.toolResults){for(let q of K.toolResults)if(q.jobId)this.trackAgentResponseForJob(q.jobId,D,f)}}catch(H){this.logger.error("Error handling message",{error:H,channelId:f}),this.sendMessageToChannel({channelId:f,message:`**Error:** ${H instanceof Error?H.message:"Unknown error"}`})}finally{this.endProcessingInput(),this.stopTypingIndicator(f)}}buildApprovalMessagePayload(A,Q){let w=Q.length>1;return{content:Gf(A.trim().length>0?`${A}
2305
2305
 
@@ -2369,7 +2369,7 @@ ${A.value}
2369
2369
  `);if(K50(A))return this.renderList(A,0,(Q)=>this.nodeToDiscordMarkdown(Q));if(A.type==="break")return`
2370
2370
  `;if(A.type==="thematicBreak")return"---";if(rS0(A))return`\`\`\`
2371
2371
  ${oS0(A)}
2372
- \`\`\``;return this.defaultNodeToText(A,(Q)=>this.nodeToDiscordMarkdown(Q))}};var Tj1={DeferredChannelMessageWithSource:5,DeferredUpdateMessage:6},L50="https://discord.com/api/v10",Sj1=2000,mgQ=/^[0-9a-f]{64}$/,ugQ=/^[0-9a-f]+$/,cgQ=class A{name="discord";userName;botUserId;apiBaseUrl;botToken;publicKey;applicationId;mentionRoleIds;interactionFlags;chat=null;logger;formatConverter=new SgQ;requestContext=new OgQ;threadParentCache=new Map;static THREAD_PARENT_CACHE_TTL=300000;constructor(Q={}){let w=Q.botToken??process.env.DISCORD_BOT_TOKEN;if(!w)throw new HH("discord","botToken is required. Set DISCORD_BOT_TOKEN or provide it in config.");let B=Q.publicKey??process.env.DISCORD_PUBLIC_KEY;if(!B)throw new HH("discord","publicKey is required. Set DISCORD_PUBLIC_KEY or provide it in config.");let $=Q.applicationId??process.env.DISCORD_APPLICATION_ID;if(!$)throw new HH("discord","applicationId is required. Set DISCORD_APPLICATION_ID or provide it in config.");if(this.apiBaseUrl=Q.apiUrl??process.env.DISCORD_API_URL??L50,this.botToken=w,this.publicKey=B.trim().toLowerCase(),this.applicationId=$,this.mentionRoleIds=Q.mentionRoleIds??(process.env.DISCORD_MENTION_ROLE_IDS?process.env.DISCORD_MENTION_ROLE_IDS.split(",").map((f)=>f.trim()):[]),this.botUserId=$,this.interactionFlags=Q.interactionFlags,this.logger=Q.logger??new V50("info").child("discord"),this.userName=Q.userName??"bot",!mgQ.test(this.publicKey))this.logger.error("Invalid Discord public key format",{length:this.publicKey.length,isHex:ugQ.test(this.publicKey)})}async initialize(Q){this.chat=Q,this.logger.info("Discord adapter initialized")}async getUser(Q){try{let B=await(await this.discordFetch(`/users/${Q}`,"GET")).json();return{avatarUrl:B.avatar?`https://cdn.discordapp.com/avatars/${B.id}/${B.avatar}.png`:void 0,email:void 0,fullName:B.global_name||B.username,isBot:B.bot??!1,userId:B.id,userName:B.username}}catch{return null}}async handleWebhook(Q,w){let B=await Q.arrayBuffer(),$=new Uint8Array(B),f=new TextDecoder().decode($),Y=Q.headers.get("x-discord-gateway-token");if(Y){if(Y!==this.botToken)return this.logger.warn("Invalid gateway token"),new Response("Invalid gateway token",{status:401});this.logger.info("Discord forwarded Gateway event received");try{let U=JSON.parse(f);return this.handleForwardedGatewayEvent(U,w)}catch{return new Response("Invalid JSON",{status:400})}}this.logger.info("Discord webhook received",{bodyLength:f.length,bodyBytesLength:$.length,hasSignature:!!Q.headers.get("x-signature-ed25519"),hasTimestamp:!!Q.headers.get("x-signature-timestamp")});let X=Q.headers.get("x-signature-ed25519"),W=Q.headers.get("x-signature-timestamp");if(!await this.verifySignature($,X,W))return this.logger.warn("Discord signature verification failed, returning 401"),new Response("Invalid signature",{status:401});this.logger.info("Discord signature verification passed");let K;try{K=JSON.parse(f)}catch{return new Response("Invalid JSON",{status:400})}if(this.logger.info("Discord interaction parsed",{type:K.type,typeIsPing:K.type===LC.Ping,expectedPingType:LC.Ping,id:K.id}),K.type===LC.Ping){let U=JSON.stringify({type:bd.InteractionResponseType.PONG});return this.logger.info("Discord PING received, responding with PONG",{responseBody:U,responseType:bd.InteractionResponseType.PONG}),new Response(U,{status:200,headers:{"Content-Type":"application/json"}})}if(K.type===LC.MessageComponent)return this.handleComponentInteraction(K,w),this.respondToInteraction({type:Tj1.DeferredUpdateMessage});if(K.type===LC.ApplicationCommand){let U=this.getApplicationCommandContext(K),D=this.getInteractionFlags(U);return this.handleApplicationCommandInteraction(U,w),this.respondToInteraction({...D===void 0?{}:{data:{flags:D}},type:Tj1.DeferredChannelMessageWithSource})}return new Response("Unknown interaction type",{status:400})}async verifySignature(Q,w,B){if(!(w&&B))return this.logger.warn("Discord signature verification failed: missing headers",{hasSignature:!!w,hasTimestamp:!!B}),!1;try{this.logger.info("Discord signature verification attempt",{bodyBytesLength:Q.length,signatureLength:w.length,timestampLength:B.length,publicKeyLength:this.publicKey.length,timestamp:B,signaturePrefix:w.slice(0,16),publicKey:this.publicKey});let $=await bd.verifyKey(Q,w,B,this.publicKey);if(!$){let f=new TextDecoder().decode(Q);this.logger.warn("Discord signature verification failed: invalid signature",{publicKeyLength:this.publicKey.length,signatureLength:w.length,publicKeyPrefix:this.publicKey.slice(0,8),publicKeySuffix:this.publicKey.slice(-8),timestamp:B,bodyLength:Q.length,bodyPrefix:f.slice(0,50)})}return $}catch($){return this.logger.warn("Discord signature verification failed: exception",{error:$}),!1}}respondToInteraction(Q){return Response.json(Q)}handleComponentInteraction(Q,w){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring interaction");return}let B=Q.data?.custom_id;if(!B){this.logger.warn("No custom_id in component interaction");return}let $=Q.member?.user||Q.user;if(!$){this.logger.warn("No user in component interaction");return}let f=Q.channel_id,Y=Q.guild_id||"@me",X=Q.message?.id;if(!(f&&X)){this.logger.warn("Missing channel_id or message_id in interaction");return}let W=Q.channel,H=W?.type===11||W?.type===12,K=H&&W?.parent_id?W.parent_id:f,U=H?this.encodeThreadId({guildId:Y,channelId:K,threadId:f}):this.encodeThreadId({guildId:Y,channelId:f}),D=RgQ(B),q={actionId:D.actionId,value:D.value??D.actionId,user:{userId:$.id,userName:$.username,fullName:$.global_name||$.username,isBot:$.bot??!1,isMe:!1},messageId:X,threadId:U,adapter:this,raw:Q};this.logger.debug("Processing Discord button action",{actionId:B,messageId:X,threadId:U}),this.chat.processAction(q,w)}getApplicationCommandContext(Q){let w=Q.data?.name;if(!w)return this.logger.warn("No command name in application command interaction"),null;let B=Q.member?.user||Q.user;if(!B)return this.logger.warn("No user in application command interaction"),null;let $=Q.channel_id;if(!$)return this.logger.warn("Missing channel_id in application command interaction"),null;let f=Q.guild_id||"@me",Y=Q.channel,X=Y?.type===11||Y?.type===12,W=X&&Y?.parent_id?Y.parent_id:$,H=X?this.encodeThreadId({guildId:f,channelId:W,threadId:$}):this.encodeThreadId({guildId:f,channelId:$}),{command:K,text:U}=this.parseSlashCommand(w,Q.data?.options);return{channelId:H,command:K,interaction:Q,text:U,user:B}}getInteractionFlags(Q){if(!(Q&&this.interactionFlags))return;return this.interactionFlags(Q)}handleApplicationCommandInteraction(Q,w){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring interaction");return}if(!Q)return;let{channelId:B,command:$,interaction:f,text:Y,user:X}=Q;this.logger.debug("Processing Discord slash command",{command:$,text:Y,userId:X.id,channelId:B}),this.requestContext.run({slashCommand:{channelId:B,interactionToken:f.token,initialResponseSent:!1}},()=>{this.chat?.processSlashCommand({command:$,text:Y,user:{userId:X.id,userName:X.username,fullName:X.global_name||X.username,isBot:X.bot??!1,isMe:X.id===this.applicationId},adapter:this,raw:f,channelId:B},w)})}parseSlashCommand(Q,w){let B=[Q.startsWith("/")?Q:`/${Q}`],$=[],f=(Y)=>{for(let X of Y){if(X.value!==void 0){$.push(String(X.value));continue}if(X.options&&X.options.length>0)B.push(X.name),f(X.options)}};if(w&&w.length>0)f(w);return{command:B.join(" "),text:$.join(" ").trim()}}async handleGatewayInteraction(Q){if(Q.isChatInputCommand()){let w=this.getApplicationCommandContext(this.normalizeGatewaySlashCommandInteraction(Q)),B=this.getInteractionFlags(w);await Q.deferReply(B===void 0?void 0:{flags:B}),this.handleApplicationCommandInteraction(w);return}if(Q.isMessageComponent())await Q.deferUpdate(),this.handleComponentInteraction(this.normalizeGatewayComponentInteraction(Q))}normalizeGatewaySlashCommandInteraction(Q){return{application_id:Q.applicationId,channel:this.normalizeGatewayChannel(Q),channel_id:Q.channelId??void 0,data:{name:Q.commandName,options:this.normalizeGatewayCommandOptions(Q.options.data),type:Q.commandType},guild_id:Q.guildId??void 0,id:Q.id,token:Q.token,type:Q.type,user:this.normalizeGatewayUser(Q.user),version:Q.version}}normalizeGatewayComponentInteraction(Q){let w="values"in Q&&Array.isArray(Q.values)?Q.values:void 0;return{application_id:Q.applicationId,channel:this.normalizeGatewayChannel(Q),channel_id:Q.channelId??void 0,data:{component_type:Q.componentType,custom_id:Q.customId,values:w},guild_id:Q.guildId??void 0,id:Q.id,message:{id:Q.message.id},token:Q.token,type:Q.type,user:this.normalizeGatewayUser(Q.user),version:Q.version}}normalizeGatewayChannel(Q){if(!Q.channel)return;let w="parentId"in Q.channel&&typeof Q.channel.parentId==="string"?Q.channel.parentId:void 0;return{id:Q.channel.id,parent_id:w,type:Q.channel.type}}normalizeGatewayCommandOptions(Q){return Q.map((w)=>({name:w.name,options:w.options?this.normalizeGatewayCommandOptions(w.options):void 0,type:w.type,value:w.value}))}normalizeGatewayUser(Q){return{avatar:Q.avatar??void 0,bot:Q.bot,discriminator:Q.discriminator,global_name:Q.globalName??void 0,id:Q.id,username:Q.username}}async handleForwardedGatewayEvent(Q,w){switch(this.logger.info("Processing forwarded Gateway event",{type:Q.type,timestamp:Q.timestamp}),Q.type){case"GATEWAY_MESSAGE_CREATE":await this.handleForwardedMessage(Q.data,w);break;case"GATEWAY_MESSAGE_REACTION_ADD":await this.handleForwardedReaction(Q.data,!0,w);break;case"GATEWAY_MESSAGE_REACTION_REMOVE":await this.handleForwardedReaction(Q.data,!1,w);break;default:this.logger.debug("Forwarded Gateway event (no handler)",{type:Q.type})}return new Response(JSON.stringify({ok:!0}),{status:200,headers:{"Content-Type":"application/json"}})}async handleForwardedMessage(Q,w){if(!this.chat)return;let B=Q.guild_id||"@me",$=Q.channel_id,f,Y=$;if(Q.thread)f=Q.thread.id,Y=Q.thread.parent_id;else if(Q.channel_type===11||Q.channel_type===12)try{let q=await(await this.discordFetch(`/channels/${$}`,"GET")).json();if(q.parent_id)f=$,Y=q.parent_id,this.logger.debug("Fetched thread parent for forwarded message",{threadId:$,parentId:q.parent_id})}catch(D){this.logger.error("Failed to fetch thread parent",{error:String(D),channelId:$})}let X=Q.is_mention||Q.mentions.some((D)=>D.id===this.applicationId),W=this.mentionRoleIds.length>0&&Q.mention_roles?.some((D)=>this.mentionRoleIds.includes(D)),H=X||W;if(!f&&H)try{let D=await this.createDiscordThread($,Q.id);f=D.id,this.logger.debug("Created Discord thread for forwarded mention",{channelId:$,messageId:Q.id,threadId:D.id})}catch(D){this.logger.error("Failed to create Discord thread for mention",{error:String(D),messageId:Q.id})}let K=this.encodeThreadId({guildId:B,channelId:Y,threadId:f}),U=new c8({id:Q.id,threadId:K,text:Q.content,formatted:this.formatConverter.toAst(Q.content),author:{userId:Q.author.id,userName:Q.author.username,fullName:Q.author.global_name||Q.author.username,isBot:Q.author.bot===!0,isMe:Q.author.id===this.applicationId},metadata:{dateSent:new Date(Q.timestamp),edited:!1},attachments:Q.attachments.map((D)=>({type:this.getAttachmentType(D.content_type),url:D.url,name:D.filename,mimeType:D.content_type,size:D.size})),raw:Q,isMention:H});try{await this.chat.handleIncomingMessage(this,K,U)}catch(D){this.logger.error("Error handling forwarded message",{error:String(D),messageId:Q.id})}}async handleForwardedReaction(Q,w,B){if(!this.chat)return;let $=Q.guild_id||"@me",f=Q.channel_id,Y,X=f;if(Q.channel_type===oN.GuildPublicThread||Q.channel_type===oN.GuildPrivateThread){let q=this.threadParentCache.get(f);if(q&&q.expiresAt>Date.now())Y=f,X=q.parentId;else try{let I=await(await this.discordFetch(`/channels/${f}`,"GET")).json();if(I.parent_id)Y=f,X=I.parent_id,this.threadParentCache.set(f,{parentId:I.parent_id,expiresAt:Date.now()+A.THREAD_PARENT_CACHE_TTL})}catch(b){this.logger.error("Failed to fetch thread parent for reaction",{error:String(b),channelId:f})}}let W=this.encodeThreadId({guildId:$,channelId:X,threadId:Y}),H=Q.emoji.name||"unknown",K=this.normalizeDiscordEmoji(H),U=Q.user??Q.member?.user;if(!U){this.logger.warn("Reaction event missing user info",{data:Q});return}let D={adapter:this,threadId:W,messageId:Q.message_id,emoji:K,rawEmoji:Q.emoji.id?`<:${H}:${Q.emoji.id}>`:H,added:w,user:{userId:U.id,userName:U.username,fullName:U.username,isBot:U.bot===!0,isMe:U.id===this.applicationId},raw:Q};this.chat.processReaction(D)}async postMessage(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=Q;if($)B=$;let Y={},X=[],W=[],H=F50(w);if(H){let b=Cm0(H);X.push(...b.embeds),W.push(...b.components)}else Y.content=this.truncateContent(iN(this.formatConverter.renderPostable(w),"discord"));if(X.length>0)Y.embeds=X;if(W.length>0)Y.components=W;let K=Um0(w),U=this.tryPostSlashResponse(f,Y,K);if(U)return U;if(K.length>0)return this.postMessageWithFiles(B,f,Y,K);this.logger.debug("Discord API: POST message",{channelId:B,contentLength:Y.content?.length||0,embedCount:X.length,componentCount:W.length});let q=await(await this.discordFetch(`/channels/${B}/messages`,"POST",Y)).json();return this.logger.debug("Discord API: POST message response",{messageId:q.id}),{id:q.id,threadId:f,raw:q}}tryPostSlashResponse(Q,w,B){let $=this.requestContext.getStore()?.slashCommand;if(!$||$.channelId!==Q)return;return this.postSlashCommandResponse($,Q,w,B)}async postSlashCommandResponse(Q,w,B,$){let f=!Q.initialResponseSent;Q.initialResponseSent=!0;let Y=f?`/webhooks/${this.applicationId}/${Q.interactionToken}/messages/@original`:`/webhooks/${this.applicationId}/${Q.interactionToken}?wait=true`,X=f?"PATCH":"POST";this.logger.debug("Discord interaction webhook: responding to slash command",{threadId:w,isInitialResponse:f,hasFiles:$.length>0});let H=await($.length>0?await this.discordInteractionFetchWithFiles(Y,X,B,$):await this.discordInteractionFetch(Y,X,B)).json();return{id:H.id,threadId:w,raw:H}}async createDiscordThread(Q,w){let B=`Thread ${new Date().toLocaleString()}`;this.logger.debug("Discord API: POST thread",{channelId:Q,messageId:w,threadName:B});try{let f=await(await this.discordFetch(`/channels/${Q}/messages/${w}/threads`,"POST",{name:B,auto_archive_duration:1440})).json();return this.logger.debug("Discord API: POST thread response",{threadId:f.id,threadName:f.name}),f}catch($){if($ instanceof TJ&&typeof $.message==="string"&&$.message.includes('"code"')&&$.message.includes("160004"))return this.logger.debug("Thread already exists for message, reusing existing thread",{channelId:Q,messageId:w}),{id:w,name:B};throw $}}truncateContent(Q){if(Q.length<=Sj1)return Q;return`${Q.slice(0,Sj1-3)}...`}async postMessageWithFiles(Q,w,B,$){let f=new FormData;f.append("payload_json",JSON.stringify(B));for(let W=0;W<$.length;W++){let H=$[W];if(!H)continue;let K=await Dm0(H.data,{platform:"discord"});if(!K)continue;let U=new Blob([new Uint8Array(K)],{type:H.mimeType||"application/octet-stream"});f.append(`files[${W}]`,U,H.filename)}let Y=await fetch(`${L50}/channels/${Q}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.botToken}`},body:f});if(!Y.ok){let W=await Y.text();throw new TJ("discord",`Failed to post message: ${Y.status} ${W}`)}let X=await Y.json();return{id:X.id,threadId:w,raw:X}}async discordInteractionFetch(Q,w,B){let $=await fetch(`${L50}${Q}`,{method:w,headers:B?{"Content-Type":"application/json"}:void 0,body:B?JSON.stringify(B):void 0});if(!$.ok){let f=await $.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:$.status,error:f}),new TJ("discord",`Discord interaction API error: ${$.status} ${f}`)}return $}async discordInteractionFetchWithFiles(Q,w,B,$){let f=new FormData;f.append("payload_json",JSON.stringify(B));for(let X=0;X<$.length;X++){let W=$[X];if(!W)continue;let H=await Dm0(W.data,{platform:"discord"});if(!H)continue;let K=new Blob([new Uint8Array(H)],{type:W.mimeType||"application/octet-stream"});f.append(`files[${X}]`,K,W.filename)}let Y=await fetch(`${L50}${Q}`,{method:w,body:f});if(!Y.ok){let X=await Y.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:Y.status,error:X}),new TJ("discord",`Discord interaction API error: ${Y.status} ${X}`)}return Y}async editMessage(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),Y=f||$,X={},W=[],H=[],K=F50(B);if(K){let q=Cm0(K);W.push(...q.embeds),H.push(...q.components),X.content=""}else X.content=this.truncateContent(iN(this.formatConverter.renderPostable(B),"discord"));if(W.length>0)X.embeds=W;if(H.length>0)X.components=H;this.logger.debug("Discord API: PATCH message",{channelId:Y,messageId:w,contentLength:X.content?.length||0});let D=await(await this.discordFetch(`/channels/${Y}/messages/${w}`,"PATCH",X)).json();return this.logger.debug("Discord API: PATCH message response",{messageId:D.id}),{id:D.id,threadId:Q,raw:D}}async deleteMessage(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=$||B;this.logger.debug("Discord API: DELETE message",{channelId:f,messageId:w}),await this.discordFetch(`/channels/${f}/messages/${w}`,"DELETE"),this.logger.debug("Discord API: DELETE message response",{ok:!0})}async addReaction(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),Y=f||$,X=this.encodeEmoji(B);this.logger.debug("Discord API: PUT reaction",{channelId:Y,messageId:w,emoji:X}),await this.discordFetch(`/channels/${Y}/messages/${w}/reactions/${X}/@me`,"PUT"),this.logger.debug("Discord API: PUT reaction response",{ok:!0})}async removeReaction(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),Y=f||$,X=this.encodeEmoji(B);this.logger.debug("Discord API: DELETE reaction",{channelId:Y,messageId:w,emoji:X}),await this.discordFetch(`/channels/${Y}/messages/${w}/reactions/${X}/@me`,"DELETE"),this.logger.debug("Discord API: DELETE reaction response",{ok:!0})}encodeEmoji(Q){let w=Ud.toDiscord?Ud.toDiscord(Q):String(Q);return encodeURIComponent(w)}async startTyping(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=$||B;this.logger.debug("Discord API: POST typing",{channelId:f}),await this.discordFetch(`/channels/${f}/typing`,"POST")}async fetchMessages(Q,w={}){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=$||B,Y=w.limit||50,X=w.direction??"backward",W=new URLSearchParams;if(W.set("limit",String(Y)),w.cursor)if(X==="backward")W.set("before",w.cursor);else W.set("after",w.cursor);this.logger.debug("Discord API: GET messages",{channelId:f,limit:Y,direction:X,cursor:w.cursor});let K=await(await this.discordFetch(`/channels/${f}/messages?${W.toString()}`,"GET")).json();this.logger.debug("Discord API: GET messages response",{messageCount:K.length});let D=[...K].reverse().map((b)=>this.parseDiscordMessage(b,Q)),q;if(K.length===Y)if(X==="backward")q=K.at(-1)?.id;else q=K[0]?.id;return{messages:D,nextCursor:q}}async fetchThread(Q){let{channelId:w,guildId:B}=this.decodeThreadId(Q);this.logger.debug("Discord API: GET channel",{channelId:w});let f=await(await this.discordFetch(`/channels/${w}`,"GET")).json();return{id:Q,channelId:w,channelName:f.name,isDM:f.type===oN.DM||f.type===oN.GroupDM,metadata:{guildId:B,channelType:f.type,raw:f}}}async openDM(Q){this.logger.debug("Discord API: POST DM channel",{userId:Q});let B=await(await this.discordFetch("/users/@me/channels","POST",{recipient_id:Q})).json();return this.logger.debug("Discord API: POST DM channel response",{channelId:B.id}),this.encodeThreadId({guildId:"@me",channelId:B.id})}isDM(Q){let{guildId:w}=this.decodeThreadId(Q);return w==="@me"}encodeThreadId(Q){let w=Q.threadId?`:${Q.threadId}`:"";return`discord:${Q.guildId}:${Q.channelId}${w}`}decodeThreadId(Q){let w=Q.split(":");if(w.length<3||w[0]!=="discord")throw new HH("discord",`Invalid Discord thread ID: ${Q}`);return{guildId:w[1],channelId:w[2],threadId:w[3]}}parseMessage(Q){let w=Q,B=w.guild_id||"@me",$=this.encodeThreadId({guildId:B,channelId:w.channel_id});return this.parseDiscordMessage(w,$)}parseDiscordMessage(Q,w){let B=Q.type===yF1.ThreadStarterMessage&&Q.referenced_message?Q.referenced_message:Q,$=B.author,f=$.bot??!1,Y=$.id===this.botUserId;return new c8({id:B.id,threadId:w,text:this.formatConverter.extractPlainText(B.content),formatted:this.formatConverter.toAst(B.content),raw:Q,author:{userId:$.id,userName:$.username,fullName:$.global_name||$.username,isBot:f,isMe:Y},metadata:{dateSent:new Date(B.timestamp),edited:B.edited_timestamp!==null,editedAt:B.edited_timestamp?new Date(B.edited_timestamp):void 0},attachments:(B.attachments||[]).map((X)=>({type:this.getAttachmentType(X.content_type),url:X.url,name:X.filename,mimeType:X.content_type,size:X.size,width:X.width??void 0,height:X.height??void 0}))})}getAttachmentType(Q){if(!Q)return"file";if(Q.startsWith("image/"))return"image";if(Q.startsWith("video/"))return"video";if(Q.startsWith("audio/"))return"audio";return"file"}rehydrateAttachment(Q){let w=Q.fetchMetadata?.url??Q.url;if(!w)return Q;return{...Q,fetchData:()=>this.downloadAttachment(w)}}async downloadAttachment(Q){let w;try{w=await fetch(Q)}catch(B){throw new TJ("discord","Failed to download Discord attachment",B instanceof Error?B:void 0)}if(!w.ok)throw new TJ("discord",`Failed to download Discord attachment: ${w.status}`);return Buffer.from(await w.arrayBuffer())}renderFormatted(Q){return this.formatConverter.fromAst(Q)}async discordFetch(Q,w,B){let $=`${this.apiBaseUrl}${Q}`,f={Authorization:`Bot ${this.botToken}`};if(B)f["Content-Type"]="application/json";let Y=await fetch($,{method:w,headers:f,body:B?JSON.stringify(B):void 0});if(!Y.ok){let X=await Y.text();throw this.logger.error("Discord API error",{path:Q,method:w,status:Y.status,error:X}),new TJ("discord",`Discord API error: ${Y.status} ${X}`)}return Y}async startGatewayListener(Q,w=180000,B,$){if(!this.chat)return new Response("Chat instance not initialized",{status:500});if(!Q.waitUntil)return new Response("waitUntil not provided",{status:500});this.logger.info("Starting Discord Gateway listener",{durationMs:w,webhookUrl:$?"configured":"not configured"});let f=this.runGatewayListener(w,B,$);return Q.waitUntil(f),new Response(JSON.stringify({status:"listening",durationMs:w,message:`Gateway listener started, will run for ${w/1000} seconds`}),{status:200,headers:{"Content-Type":"application/json"}})}async runGatewayListener(Q,w,B){let $=new A7.Client({intents:[A7.GatewayIntentBits.Guilds,A7.GatewayIntentBits.GuildMessages,A7.GatewayIntentBits.MessageContent,A7.GatewayIntentBits.DirectMessages,A7.GatewayIntentBits.GuildMessageReactions,A7.GatewayIntentBits.DirectMessageReactions],partials:[A7.Partials.Channel]}),f=!1;if(B)$.on("raw",async(Y)=>{if(f)return;if(!Y.t)return;this.logger.info("Discord Gateway forwarding event",{type:Y.t}),await this.forwardGatewayEvent(B,{type:`GATEWAY_${Y.t}`,timestamp:Date.now(),data:Y.d})});else this.setupLegacyGatewayHandlers($,()=>f);$.on(A7.Events.ClientReady,()=>{this.logger.info("Discord Gateway connected",{username:$.user?.username,id:$.user?.id})}),$.on(A7.Events.Error,(Y)=>{this.logger.error("Discord Gateway error",{error:String(Y)})});try{await $.login(this.botToken),await new Promise((Y)=>{let X=setTimeout(Y,Q);if(w){if(w.aborted){clearTimeout(X),Y();return}w.addEventListener("abort",()=>{this.logger.info("Discord Gateway listener received abort signal (new listener started)"),clearTimeout(X),Y()},{once:!0})}}),this.logger.info("Discord Gateway listener duration elapsed, disconnecting")}catch(Y){this.logger.error("Discord Gateway listener error",{error:String(Y)})}finally{f=!0,$.destroy(),this.logger.info("Discord Gateway listener stopped")}}setupLegacyGatewayHandlers(Q,w){Q.on(A7.Events.MessageCreate,async(B)=>{if(w()){this.logger.debug("Ignoring message - Gateway is shutting down");return}if(B.author.bot){this.logger.debug("Ignoring message from bot",{authorId:B.author.id,authorName:B.author.username,isMe:B.author.id===Q.user?.id});return}let $=B.mentions.has(Q.user?.id??""),f=this.mentionRoleIds.length>0&&B.mentions.roles.some((X)=>this.mentionRoleIds.includes(X.id)),Y=$||f;this.logger.info("Discord Gateway message received",{channelId:B.channelId,guildId:B.guildId,authorId:B.author.id,isMentioned:Y,isUserMentioned:$,isRoleMentioned:f,content:B.content.slice(0,100)}),await this.handleGatewayMessage(B,Y)}),Q.on(A7.Events.InteractionCreate,async(B)=>{if(w()){this.logger.debug("Ignoring interaction - Gateway is shutting down");return}this.logger.info("Discord Gateway interaction received",{id:B.id,type:B.type});try{await this.handleGatewayInteraction(B)}catch($){this.logger.error("Error handling Gateway interaction",{error:String($),interactionId:B.id})}}),Q.on(A7.Events.MessageReactionAdd,async(B,$)=>{if(w()){this.logger.debug("Ignoring reaction - Gateway is shutting down");return}if($.bot){this.logger.debug("Ignoring reaction from bot",{userId:$.id,isMe:$.id===Q.user?.id});return}if(this.logger.info("Discord Gateway reaction added",{emoji:B.emoji.name,messageId:B.message.id,channelId:B.message.channelId,userId:$.id}),$.username)await this.handleGatewayReaction(B,$,!0)}),Q.on(A7.Events.MessageReactionRemove,async(B,$)=>{if(w()){this.logger.debug("Ignoring reaction removal - Gateway is shutting down");return}if($.bot){this.logger.debug("Ignoring reaction removal from bot",{userId:$.id,isMe:$.id===Q.user?.id});return}if(this.logger.info("Discord Gateway reaction removed",{emoji:B.emoji.name,messageId:B.message.id,channelId:B.message.channelId,userId:$.id}),$.username)await this.handleGatewayReaction(B,$,!1)})}async forwardGatewayEvent(Q,w){try{this.logger.debug("Forwarding Gateway event to webhook",{type:w.type,webhookUrl:Q});let B=await fetch(Q,{method:"POST",headers:{"Content-Type":"application/json","x-discord-gateway-token":this.botToken},body:JSON.stringify(w)});if(B.ok)this.logger.debug("Gateway event forwarded successfully",{type:w.type});else{let $=await B.text();this.logger.error("Failed to forward Gateway event",{type:w.type,status:B.status,error:$})}}catch(B){this.logger.error("Error forwarding Gateway event",{type:w.type,error:String(B)})}}async handleGatewayMessage(Q,w){if(!this.chat)return;let B=Q.guildId||"@me",$=Q.channelId,f=Q.channel.isThread(),Y,X=$;if(f&&"parentId"in Q.channel&&Q.channel.parentId)Y=$,X=Q.channel.parentId;if(!Y&&w)try{let K=await this.createDiscordThread($,Q.id);Y=K.id,this.logger.debug("Created Discord thread for incoming mention",{channelId:$,messageId:Q.id,threadId:K.id})}catch(K){this.logger.error("Failed to create Discord thread for mention",{error:String(K),messageId:Q.id})}let W=this.encodeThreadId({guildId:B,channelId:X,threadId:Y}),H=new c8({id:Q.id,threadId:W,text:Q.content,formatted:this.formatConverter.toAst(Q.content),author:{userId:Q.author.id,userName:Q.author.username,fullName:Q.author.displayName||Q.author.username,isBot:Q.author.bot,isMe:!1},metadata:{dateSent:Q.createdAt,edited:Q.editedAt!==null,editedAt:Q.editedAt??void 0},attachments:Q.attachments.map((K)=>({type:this.getAttachmentType(K.contentType),url:K.url,name:K.name,mimeType:K.contentType??void 0,size:K.size})),raw:{id:Q.id,channel_id:$,guild_id:B,content:Q.content,author:{id:Q.author.id,username:Q.author.username},timestamp:Q.createdAt.toISOString()},isMention:w});try{await this.chat.handleIncomingMessage(this,W,H)}catch(K){this.logger.error("Error handling Gateway message",{error:String(K),messageId:Q.id})}}async handleGatewayReaction(Q,w,B){if(!this.chat)return;let $=Q.message.guildId||"@me",f=Q.message.channelId,Y=Q.message.channel?.isThread?.(),X=f,W;if(Y&&Q.message.channel?.parentId)W=f,X=Q.message.channel.parentId;let H=this.encodeThreadId({guildId:$,channelId:X,threadId:W}),K=Q.emoji.name||"unknown",U=this.normalizeDiscordEmoji(K),D={adapter:this,threadId:H,messageId:Q.message.id,emoji:U,rawEmoji:Q.emoji.id?`<:${K}:${Q.emoji.id}>`:K,added:B,user:{userId:w.id,userName:w.username,fullName:w.username,isBot:w.bot===!0,isMe:w.id===this.applicationId},raw:{emoji:Q.emoji,message_id:Q.message.id,channel_id:Q.message.channelId,guild_id:Q.message.guildId,user_id:w.id}};this.chat.processReaction(D)}channelIdFromThreadId(Q){return Q.split(":").slice(0,3).join(":")}async fetchChannelMessages(Q,w={}){let $=Q.split(":")[2];if(!$)throw new HH("discord",`Invalid Discord channel ID: ${Q}`);let f=w.limit||50,Y=w.direction??"backward",X=new URLSearchParams;if(X.set("limit",String(f)),w.cursor)if(Y==="backward")X.set("before",w.cursor);else X.set("after",w.cursor);this.logger.debug("Discord API: GET channel messages",{channelId:$,limit:f,direction:Y,cursor:w.cursor});let H=await(await this.discordFetch(`/channels/${$}/messages?${X.toString()}`,"GET")).json();this.logger.debug("Discord API: GET channel messages response",{messageCount:H.length});let U=[...H].reverse().map((q)=>this.parseDiscordMessage(q,Q)),D;if(H.length===f)if(Y==="backward")D=H.at(-1)?.id;else D=H[0]?.id;return{messages:U,nextCursor:D}}async listThreads(Q,w={}){let B=Q.split(":"),$=B[1],f=B[2];if(!($&&f))throw new HH("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET threads",{guildId:$,channelId:f});let W=((await(await this.discordFetch(`/guilds/${$}/threads/active`,"GET")).json()).threads||[]).filter((V)=>V.parent_id===f),H=[];try{H=(await(await this.discordFetch(`/channels/${f}/threads/archived/public?limit=${w.limit||50}`,"GET")).json()).threads||[]}catch{this.logger.debug("Could not fetch archived threads (may lack permissions)")}let K=[...W,...H],U=new Set,D=K.filter((V)=>{if(U.has(V.id))return!1;return U.add(V.id),!0}),q=w.limit||50,b=D.slice(0,q),I=[];for(let V of b){let L=this.encodeThreadId({guildId:$,channelId:f,threadId:V.id});try{let x=(await(await this.discordFetch(`/channels/${V.id}/messages?limit=1&after=0`,"GET")).json())[0];if(x)I.push({id:L,rootMessage:this.parseDiscordMessage(x,L),replyCount:V.total_message_sent??V.message_count,lastReplyAt:V.thread_metadata?.archive_timestamp?new Date(V.thread_metadata.archive_timestamp):void 0})}catch{I.push({id:L,rootMessage:new c8({id:V.id,threadId:L,text:V.name,formatted:this.formatConverter.toAst(V.name),raw:V,author:{userId:"unknown",userName:"unknown",fullName:"unknown",isBot:!1,isMe:!1},metadata:{dateSent:new Date,edited:!1},attachments:[]}),replyCount:V.total_message_sent??V.message_count})}}return this.logger.debug("Discord API: listThreads result",{threadCount:I.length}),{threads:I,nextCursor:D.length>q?String(q):void 0}}async fetchChannelInfo(Q){let B=Q.split(":")[2];if(!B)throw new HH("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET channel info",{channelId:B});let f=await(await this.discordFetch(`/channels/${B}`,"GET")).json();return{id:Q,name:f.name,isDM:f.type===oN.DM||f.type===oN.GroupDM,memberCount:f.member_count,metadata:{channelType:f.type,raw:f}}}async postChannelMessage(Q,w){let $=Q.split(":")[2];if(!$)throw new HH("discord",`Invalid Discord channel ID: ${Q}`);let f={},Y=[],X=[],W=F50(w);if(W){let q=Cm0(W);Y.push(...q.embeds),X.push(...q.components)}else f.content=this.truncateContent(iN(this.formatConverter.renderPostable(w),"discord"));if(Y.length>0)f.embeds=Y;if(X.length>0)f.components=X;let H=Um0(w),K=this.tryPostSlashResponse(Q,f,H);if(K)return K;if(H.length>0)return this.postMessageWithFiles($,Q,f,H);this.logger.debug("Discord API: POST channel message",{channelId:$,contentLength:f.content?.length||0});let D=await(await this.discordFetch(`/channels/${$}/messages`,"POST",f)).json();return{id:D.id,threadId:Q,raw:D}}normalizeDiscordEmoji(Q){let B={"\uD83D\uDC4D":"thumbs_up","\uD83D\uDC4E":"thumbs_down","\u2764\uFE0F":"heart","\u2764":"heart","\uD83D\uDD25":"fire","\uD83D\uDE80":"rocket","\uD83D\uDE4C":"raised_hands","\u2705":"check","\u274C":"x","\uD83D\uDC4B":"wave","\uD83E\uDD14":"thinking","\uD83D\uDE0A":"smile","\uD83D\uDE02":"laugh","\uD83C\uDF89":"party","\u2B50":"star","\u2728":"sparkles","\uD83D\uDC40":"eyes","\uD83D\uDCAF":"100"}[Q]||Q;return EJ(B)}};function cj1(A){return new cgQ(A??{})}var lgQ=class{subscriptions=new Set;locks=new Map;cache=new Map;queues=new Map;connected=!1;connectPromise=null;async connect(){if(this.connected)return;if(!this.connectPromise)this.connectPromise=Promise.resolve().then(()=>{this.connected=!0});await this.connectPromise}async disconnect(){this.connected=!1,this.connectPromise=null,this.subscriptions.clear(),this.locks.clear(),this.queues.clear()}async subscribe(A){this.ensureConnected(),this.subscriptions.add(A)}async unsubscribe(A){this.ensureConnected(),this.subscriptions.delete(A)}async isSubscribed(A){return this.ensureConnected(),this.subscriptions.has(A)}async acquireLock(A,Q){this.ensureConnected(),this.cleanExpiredLocks();let w=this.locks.get(A);if(w&&w.expiresAt>Date.now())return null;let B={threadId:A,token:pgQ(),expiresAt:Date.now()+Q};return this.locks.set(A,B),B}async forceReleaseLock(A){this.ensureConnected(),this.locks.delete(A)}async releaseLock(A){this.ensureConnected();let Q=this.locks.get(A.threadId);if(Q&&Q.token===A.token)this.locks.delete(A.threadId)}async extendLock(A,Q){this.ensureConnected();let w=this.locks.get(A.threadId);if(!w||w.token!==A.token)return!1;if(w.expiresAt<Date.now())return this.locks.delete(A.threadId),!1;return w.expiresAt=Date.now()+Q,!0}async get(A){this.ensureConnected();let Q=this.cache.get(A);if(!Q)return null;if(Q.expiresAt!==null&&Q.expiresAt<=Date.now())return this.cache.delete(A),null;return Q.value}async set(A,Q,w){this.ensureConnected(),this.cache.set(A,{value:Q,expiresAt:w?Date.now()+w:null})}async setIfNotExists(A,Q,w){this.ensureConnected();let B=this.cache.get(A);if(B)if(B.expiresAt!==null&&B.expiresAt<=Date.now())this.cache.delete(A);else return!1;return this.cache.set(A,{value:Q,expiresAt:w?Date.now()+w:null}),!0}async delete(A){this.ensureConnected(),this.cache.delete(A)}async appendToList(A,Q,w){this.ensureConnected();let B=this.cache.get(A),$;if(B&&B.expiresAt!==null&&B.expiresAt<=Date.now())$=[];else if(B&&Array.isArray(B.value))$=B.value;else $=[];if($.push(Q),w?.maxLength&&$.length>w.maxLength)$=$.slice($.length-w.maxLength);this.cache.set(A,{value:$,expiresAt:w?.ttlMs?Date.now()+w.ttlMs:null})}async enqueue(A,Q,w){this.ensureConnected();let B=this.queues.get(A);if(!B)B=[],this.queues.set(A,B);if(B.push(Q),B.length>w)B.splice(0,B.length-w);return B.length}async dequeue(A){this.ensureConnected();let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let w=Q.shift();if(Q.length===0)this.queues.delete(A);return w??null}async queueDepth(A){return this.ensureConnected(),this.queues.get(A)?.length??0}async getList(A){this.ensureConnected();let Q=this.cache.get(A);if(!Q)return[];if(Q.expiresAt!==null&&Q.expiresAt<=Date.now())return this.cache.delete(A),[];if(Array.isArray(Q.value))return Q.value;return[]}ensureConnected(){if(!this.connected)throw Error("MemoryStateAdapter is not connected. Call connect() first.")}cleanExpiredLocks(){let A=Date.now();for(let[Q,w]of this.locks)if(w.expiresAt<=A)this.locks.delete(Q)}_getSubscriptionCount(){return this.subscriptions.size}_getLockCount(){return this.cleanExpiredLocks(),this.locks.size}};function pgQ(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function k50(A){return new lgQ}N0();var igQ=Z.object({subscribedAt:Z.string().datetime(),routingMode:Z.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:Z.boolean().optional()}),dgQ="chat.discord.subscriptions";function gm0(A){return A.scoped({namespace:dgQ,schema:igQ})}function lj1(A,Q=k50()){let w=gm0(A);return new pj1(Q,w)}class pj1{memoryState;subscriptions;constructor(A,Q){this.memoryState=A,this.subscriptions=Q}connect(){return this.memoryState.connect()}disconnect(){return this.memoryState.disconnect()}async subscribe(A){await this.subscriptions.set(A,{subscribedAt:new Date().toISOString()})}async unsubscribe(A){await this.subscriptions.delete(A)}isSubscribed(A){return this.subscriptions.has(A)}acquireLock(A,Q){return this.memoryState.acquireLock(A,Q)}appendToList(A,Q,w){return this.memoryState.appendToList(A,Q,w)}delete(A){return this.memoryState.delete(A)}dequeue(A){return this.memoryState.dequeue(A)}enqueue(A,Q,w){return this.memoryState.enqueue(A,Q,w)}extendLock(A,Q){return this.memoryState.extendLock(A,Q)}forceReleaseLock(A){return this.memoryState.forceReleaseLock(A)}get(A){return this.memoryState.get(A)}getList(A){return this.memoryState.getList(A)}queueDepth(A){return this.memoryState.queueDepth(A)}releaseLock(A){return this.memoryState.releaseLock(A)}set(A,Q,w){return this.memoryState.set(A,Q,w)}setIfNotExists(A,Q,w){return this.memoryState.setIfNotExists(A,Q,w)}}function ij1(A){let{discord:Q}=A;if(!Q)return new Wm0({userName:A.userName,adapters:{},state:k50()});let w=cj1({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds});return A.gatewayLoop.setAdapter(w),new Wm0({userName:A.userName,adapters:{discord:w},concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"},state:lj1(A.runtimeState)})}class ym0{deps;constructor(A){this.deps=A}async subscribeOwnedThread(A,Q){if(!this.deps.isBotCreatedThread(A,Q))return;try{await A.subscribe(),await this.deps.getSubscriptions()?.set(A.id,{subscribedAt:new Date().toISOString()})}catch(w){this.deps.logger.debug("Discord thread subscription failed",{error:w,threadId:A.id})}}async shouldRouteSubscribedMessage(A,Q){if(this.deps.getPlatform(A)!=="discord")return!1;if(A.isDM)return!0;let w=await this.deps.getSubscriptions()?.get(A.id);if(!w)return!1;if(w.routingMode==="mention-required"){if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,w);return Boolean(Q.isMention)}if(!await this.shouldRequireMentionInSubscribedThread(A))return!0;let $={...w,routingMode:"mention-required"};if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,$);else await this.deps.getSubscriptions()?.set(A.id,$);return Boolean(Q.isMention)}async postMentionRequiredNotice(A,Q){await A.post("I\u2019ll stop auto-replying now that more people joined. Mention me if you need me."),await this.deps.getSubscriptions()?.set(A.id,{...Q,routingMode:"mention-required",mentionRequiredNoticeSent:!0})}async shouldRequireMentionInSubscribedThread(A){try{return(await A.getParticipants()).filter((B)=>!B.isBot&&!B.isMe).length>1}catch(Q){return this.deps.logger.debug("Failed to inspect Discord thread participants",{error:Q,threadId:A.id}),!1}}}wA();class Em0{deps;constructor(A){this.deps=A}async build(A,Q,w,B){let $={message:w.text.trim(),attachments:[],notices:[]};if(w.attachments.length===0)return $;if(!(B==="anchor"||B==="trusted"))return $;let Y=this.deps.getUploadStore();if(!Y)return $;for(let X of w.attachments){let W=X.name;if(!W)continue;let H=zz(W,"upload"),K=EV(H,X.mimeType),U=X.size??0,D=vA0(H,K);if(!D){$.notices.push(`Unsupported file upload type: ${H}`);continue}if(!hA0(D,U)){$.notices.push(`File upload too large: ${H}`);continue}try{let q=await this.readAttachmentData(X);if(!q)continue;let b=qz({filename:H,mediaType:K,content:q,fallbackFilename:"upload"});if(!b.ok){$.notices.push(b.message);continue}let I=await Y.save({filename:b.filename,mediaType:b.mediaType,content:q,metadata:this.buildMetadata(A,Q,w)});$.attachments.push(nj1(I.filename,I.mediaType,q,I.ref,b.kind==="text"))}catch(q){this.deps.logger.error("Failed to read chat attachment",{error:q,filename:H}),$.notices.push(`Could not read file upload: ${H}`)}}return $}async readAttachmentData(A){if(A.fetchData)return A.fetchData();if(!A.url)return;let Q=await fetch(A.url);if(!Q.ok)throw Error(`Attachment download failed with status ${Q.status}`);let w=await Q.arrayBuffer();return Buffer.from(new Uint8Array(w))}buildMetadata(A,Q,w){let B=this.deps.getThreadIdParts(Q.id);return{interfaceType:A,channelId:Q.id,parentChannelId:Q.channelId,messageId:w.id,uploaderId:w.author.userId,uploaderUsername:w.author.userName,...B.guildId?{guildId:B.guildId}:{},...B.threadId?{threadId:B.threadId}:{}}}}function dj1(A,Q,w,B){return nj1(A,Q,w,B,TV(A,Q))}function nj1(A,Q,w,B,$){if($)return{kind:"text",filename:A,mediaType:Q,content:w.toString("utf8").replace(/^\uFEFF/,""),sizeBytes:w.byteLength,source:B};return{kind:"file",filename:A,mediaType:Q,data:w,sizeBytes:w.byteLength,source:B}}function Vd(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}function LG(A){let Q=A.split(":");if(Q[0]!=="discord")return{};return{...Q[1]?{guildId:Q[1]}:{},...Q[2]?{channelId:Q[2]}:{},...Q[3]?{threadId:Q[3]}:{}}}function ngQ(A){let Q=A.raw;if(typeof Q!=="object"||Q===null)return;let w=Q.channel_id;return typeof w==="string"?w:void 0}function rj1(A,Q){if(A.isDM)return!1;let w=LG(A.id);if(!w.threadId)return!1;let B=ngQ(Q);return B!==void 0&&B!==w.threadId}function _50(A,Q){if(Q.allowedChannels.length===0||A.isDM)return!0;let w=LG(A.id);return[A.id,A.channelId,w.channelId,w.threadId].some((B)=>typeof B==="string"&&Q.allowedChannels.includes(B))}function Tm0(A,Q,w){if(A.isDM&&!w.allowDMs)return!1;if(Q.author.isMe)return!1;if(Q.author.isBot&&!Q.isMention)return!1;return _50(A,w)}function Sm0(A,Q,w){if(Q!=="discord")return!0;if(!w)return!1;if(A.isDM&&!w.allowDMs)return!1;return _50(A,w)}function mm0(A,Q){return{channelId:LG(A.id).channelId??A.channelId,isBot:Boolean(Q.author.isBot)}}function _C(A){return A.isDM?"DM":A.channelId}var rgQ="https://discord.com/api/v10";async function oj1(A){let Q=LG(A.threadId),w=Q.threadId??Q.channelId;if(!w)return;let B=A.fetchFn??fetch;try{let $=await B(`${rgQ}/channels/${w}/messages/${A.messageId}`,{method:"PATCH",headers:{Authorization:`Bot ${A.botToken}`,"Content-Type":"application/json"},body:JSON.stringify({components:[]})});if(!$.ok)A.logger.debug("Failed to clear Discord message components",{messageId:A.messageId,channelId:w,status:$.status})}catch($){A.logger.debug("Failed to clear Discord message components",{error:$,messageId:A.messageId,channelId:w})}}var sj1={name:"@brains/chat",version:"0.2.0-alpha.142",description:"Discord Chat SDK interface for Brains",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@chat-adapter/discord":"^4.29.0","@chat-adapter/state-memory":"^4.29.0",chat:"^4.29.0"},devDependencies:{"@brains/core":"workspace:*","@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var sgQ=/https?:\/\/\S+/i,agQ=/[\s\S]+/,tgQ=1000,egQ=Z.looseObject({type:Z.literal("card"),children:Z.array(Z.looseObject({type:Z.string()})),imageUrl:Z.string().optional(),subtitle:Z.string().optional(),title:Z.string().optional()}),AyQ=Z.object({card:Z.custom((A)=>egQ.safeParse(A).success),fallbackText:Z.string().optional()});class N50 extends HK{threadRegistry=new Z50;pendingApprovals;uploadContinuity;promptActions=new ST0(tgQ);toolStatusMessenger=new mT0(this.threadRegistry);cardBuilder=new pT0({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new dT0({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new nT0({cardBuilder:this.cardBuilder,clearMessageComponents:async(A,Q)=>{let w=this.config.adapters.discord?.botToken;if(!w)return;await oj1({threadId:A,messageId:Q,botToken:w,logger:this.logger})}});subscriptionRouter=new ym0({getSubscriptions:()=>this.discordSubscriptions,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:rj1,logger:this.logger});chatInputBuilder=new Em0({getUploadStore:()=>this.context?.uploads.scoped(Vd()),getThreadIdParts:LG,logger:this.logger});gatewayLoop;discordApp;discordSubscriptions;constructor(A={}){super("chat",sj1,A,TT0);this.gatewayLoop=new rT0({getApp:()=>this.discordApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.discordApp=new oT0({discord:this.config.adapters.discord,getUploadStore:()=>this.context?.uploads.scoped(Vd()),buildApp:(Q)=>ij1({userName:this.config.userName,discord:this.config.adapters.discord,gatewayLoop:this.gatewayLoop,runtimeState:Q})}),this.pendingApprovals=new Xm({loadMessages:async(Q)=>{return await this.context?.conversations.getMessages(Q,{limit:50})??[]},onRestoreError:(Q,w)=>{this.logger.debug("Failed to load pending chat approvals",{error:Q,conversationId:w})}}),this.uploadContinuity=new Dm({sourceKind:"discord-chat-upload",loadMessages:async(Q)=>{return await this.context?.conversations.getMessages(Q,{limit:50})??[]},restoreAttachment:async(Q)=>{let w=this.context?.uploads.scoped(Vd());if(!w)throw Error("Chat upload store unavailable");let B=await w.read(Q);return dj1(B.record.filename,B.record.mediaType,B.content,B.record.ref)},onLoadError:(Q,w)=>{this.logger.debug("Failed to load prior chat uploads",{error:Q,conversationId:w})},onRestoreError:(Q,w)=>{this.logger.debug("Failed to restore prior chat upload",{error:Q,uploadId:w})}})}async onRegister(A){await super.onRegister(A),this.discordSubscriptions=gm0(A.runtimeState),this.registerChatHandlers(this.discordApp.build(A.runtimeState))}getWebRoutes(){return this.discordApp.getWebRoutes()}createDaemon(){if(!this.config.adapters.discord)return;return{start:async()=>{await this.discordApp.initialize(),this.gatewayLoop.start()},stop:async()=>{await this.gatewayLoop.stop(),this.threadRegistry.clear(),this.uploadContinuity.clear(),this.toolStatusMessenger.clear(),await this.discordApp.shutdown()},healthCheck:async()=>({status:this.gatewayLoop.isRunning()?"healthy":"error",message:this.gatewayLoop.isRunning()?"Chat gateway loop running":"Chat gateway loop stopped",lastCheck:new Date})}}sendMessageToChannel({channelId:A,message:Q}){let w=this.threadRegistry.get(A);if(!w)return;let B=this.toDiscordCardOutput(Q);if(B){w.post(B).catch(($)=>this.logger.error("Failed to send chat message",{error:$,channelId:A}));return}if(typeof Q!=="string")return;for(let $ of Yd(A,Q))w.post($).catch((f)=>this.logger.error("Failed to send chat message",{error:f,channelId:A}))}async sendMessageWithId({channelId:A,message:Q}){let w=this.threadRegistry.get(A);if(!w)return;let B=this.toDiscordCardOutput(Q);if(B){let f=await w.post(B);return this.threadRegistry.trackMessage(w.id,f),f.id}if(typeof Q!=="string")return;let $;for(let f of Yd(A,Q))$=await w.post(f),this.threadRegistry.trackMessage(w.id,$);return $?.id}async editMessage({channelId:A,messageId:Q,newMessage:w}){let B=this.threadRegistry.getMessage(A,Q);if(!B)return!1;try{let $=await B.edit(this.toDiscordCardOutput(w)??(typeof w==="string"?w:""));if(A)this.threadRegistry.trackMessage(A,$);return!0}catch{return!1}}supportsMessageEditing(){return!0}toDiscordCardOutput(A){let Q=AyQ.safeParse(A);if(!Q.success)return;let{card:w,fallbackText:B}=Q.data;if(B===void 0)return{card:w};return{card:w,fallbackText:B}}formatProgressOutput(A){return lT0(A)}formatCompletionOutput(A){return lT0(A)}async handleProgressEvent(A,Q){let w=A.metadata.interfaceType;if(w&&w!==this.id){if(!this.isEnabledPlatform(w))return;let B={...A,metadata:{...A.metadata,interfaceType:this.id}};await super.handleProgressEvent(B,B.metadata);return}await super.handleProgressEvent(A,Q)}async handleToolActivityEvent(A){if(A.interfaceType===this.id){await super.handleToolActivityEvent(A);return}if(!this.isEnabledPlatform(A.interfaceType))return;await super.handleToolActivityEvent({...A,interfaceType:this.id})}async handleToolStatusUpdate(A){if(A.interfaceType!==this.id||!A.channelId)return;await this.toolStatusMessenger.handle(A)}isEnabledPlatform(A){return Lz1(A,Boolean(this.config.adapters.discord))}registerChatHandlers(A){if(A.onDirectMessage(async(Q,w,B,$)=>{await this.handleRoutedMessage(Q,w,$)}),A.onNewMention(async(Q,w,B)=>{let $=this.getPlatformConfig(Q);if($&&Tm0(Q,w,$)&&!Q.isDM&&$.useThreads)await this.subscriptionRouter.subscribeOwnedThread(Q,w);await this.handleRoutedMessage(Q,w,B)}),A.onSubscribedMessage(async(Q,w,B)=>{if(!await this.subscriptionRouter.shouldRouteSubscribedMessage(Q,w))return;await this.handleRoutedMessage(Q,w,B)}),this.config.adapters.discord&&!this.config.adapters.discord.requireMention)A.onNewMessage(agQ,async(Q,w,B)=>{await this.handleRoutedMessage(Q,w,B)});A.onNewMessage(sgQ,async(Q,w)=>{await this.handlePassiveUrlCapture(Q,w)}),A.onAction([W50,uT0],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction(cT0,async(Q)=>{await this.handlePromptAction(Q)})}async handlePromptAction(A){if(!this.context||!A.thread||!A.value)return;let Q=A.adapter.name;if(!this.isEnabledPlatform(Q))return;let w=A.thread;if(!Sm0(w,Q,this.config.adapters.discord))return;let B=this.promptActions.get(A.value);if(B?.threadId!==w.id){await w.post(this.formatNoticePayload("That suggested action is no longer available.","Action unavailable"));return}this.promptActions.consume(A.value);let $=LG(w.id),f=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:$.channelId??w.channelId,isBot:Boolean(A.user.isBot)}),Y=this.getConversationId(Q,w.id),X=w.id;await this.runAgentTurn({thread:w,channelId:X,logLabel:"Error handling chat prompt action",body:async()=>{if(!this.context)return;let W=await this.context.agent.chat(B.prompt,Y,{userPermissionLevel:f,interfaceType:Q,channelId:X,channelName:_C(w),...this.buildActionEventMetadata(Q,w,A)});await this.renderAgentResponse({thread:w,channelId:X,conversationId:Y,response:W,userPermissionLevel:f})}})}async handleApprovalAction(A){if(!this.context||!A.thread||!A.value)return;let Q=A.adapter.name;if(!this.isEnabledPlatform(Q))return;let w=this.getConversationId(Q,A.thread.id);if(!(await this.getPendingApprovalIds(w)).has(A.value)){await A.thread.post(this.formatNoticePayload("That approval is no longer pending."));return}let $=A.thread;if(!Sm0($,Q,this.config.adapters.discord))return;let f=LG($.id),Y=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:f.channelId??$.channelId,isBot:Boolean(A.user.isBot)});await this.confirmApproval({thread:$,conversationId:w,approvalId:A.value,confirmed:A.actionId===W50,userPermissionLevel:Y,metadata:this.buildActionEventMetadata(Q,$,A)})}async handleRoutedMessage(A,Q,w){if(!this.context)return;let B=this.getPlatform(A);if(B!=="discord")return;let $=this.getPlatformConfig(A);if(!$)return;if(!Tm0(A,Q,$))return;await this.routeToAgent(B,A,Q,w)}async runAgentTurn(A){this.startProcessingInput(A.channelId);try{if(this.getPlatformConfig(A.thread)?.showTypingIndicator)await A.thread.startTyping().catch((Q)=>this.logger.debug("Typing indicator failed",{error:Q,channelId:A.channelId}));await A.body()}catch(Q){this.logger.error(A.logLabel,{error:Q,channelId:A.channelId}),await this.postTurnError(A.thread,A.channelId,Q)}finally{this.endProcessingInput()}}async postTurnError(A,Q,w){let B=this.formatErrorPayload(w),$=this.toDiscordCardOutput(B);if($){await A.post($);return}let f=typeof B==="string"?B:"Message failed.";for(let Y of Yd(Q,f))await A.post(Y)}async routeToAgent(A,Q,w,B){if(!this.context)return;this.threadRegistry.set(Q);let $=this.getConversationId(A,Q.id),f=Q.id,Y=mm0(Q,w),X=this.context.permissions.getUserLevel(A,w.author.userId,Y),W=await this.chatInputBuilder.build(A,Q,w,X),H=[...W.attachments];if(await this.attachPriorUploads($,W,X),await this.postUploadNotices(Q,W.notices),!W.message&&W.attachments.length===0)return;this.rememberUploadAttachments($,H),await this.runAgentTurn({thread:Q,channelId:f,logLabel:"Error handling chat message",body:async()=>{if(!this.context)return;let K=await this.getPendingApprovalIds($);if(K.size>0){if(await this.handleConfirmationResponse(W.message,$,Q,K,X,this.buildUserMessageMetadata(A,Q,w)))return}let U=this.buildCoalescedAgentInput(W.message,B),D=await this.context.agent.chat(U.message,$,{userPermissionLevel:X,interfaceType:A,channelId:f,channelName:_C(Q),...this.buildUserMessageMetadata(A,Q,w,U.metadata),...W.attachments.length>0?{attachments:W.attachments}:{}});await this.renderAgentResponse({thread:Q,channelId:f,conversationId:$,response:D,userPermissionLevel:X})}})}async renderAgentResponse(A){if(A.confirmation)this.syncPendingConfirmationsFromResponse(A.conversationId,A.response,A.confirmation.approvalId);else this.rememberPendingConfirmationsFromResponse(A.conversationId,A.response);await this.handleAgentResponseToolStatuses(A.response,A.conversationId);let Q=await this.artifactDelivery.resolve(A.response.cards,A.userPermissionLevel),w=Lk(A.response,{deniedCardIds:Q.deniedCardIds});if(A.confirmation)await this.approvalCards.resolve(A.conversationId,A.confirmation.approvalId,A.confirmation.confirmed);let B=A.confirmation?this.formatConfirmationResponsePayload(A.response,A.confirmation.confirmed,this.getRemainingApprovalHelp(A.conversationId,A.response),Q.deniedCardIds):this.formatAgentResponseText(w,Q.deniedCardIds),$=await this.sendAgentResponseWithFiles({thread:A.thread,channelId:A.channelId,message:B,files:Q.files}),f=await this.sendArtifactCards(A.thread,w);await this.sendSupplementalCards(A.thread,w);let Y=w.directives.find((W)=>W.kind==="approvals");await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,Y?.confirmations);let X=f??$;if(X)for(let W of w.jobIds)this.trackAgentResponseForJob(W,X,A.channelId)}rememberPendingConfirmationsFromResponse(A,Q){this.pendingApprovals.rememberFromResponse(A,Q)}async getPendingApprovalIds(A){return this.pendingApprovals.getApprovalIds(A)}async handleConfirmationResponse(A,Q,w,B,$,f){if(!Bm(A,B))return!1;let Y=IA0({message:A,approvalIds:B});if(Y.kind==="not-confirmation")return this.pendingApprovals.deleteConversation(Q),await w.post(this.formatNoticePayload("No pending approval to resolve.")),!0;if(Y.kind==="notice")return await w.post(this.formatNoticePayload(Y.message)),!0;return await this.confirmApproval({thread:w,conversationId:Q,approvalId:Y.approvalId,confirmed:Y.confirmed,userPermissionLevel:$,...f?{metadata:f}:{}}),!0}async confirmApproval(A){let Q=await this.context?.agent.confirmPendingAction(A.conversationId,A.confirmed,A.approvalId,{userPermissionLevel:A.userPermissionLevel,interfaceType:"discord",channelId:A.thread.id,channelName:_C(A.thread),...A.metadata});if(this.removePendingApproval(A.conversationId,A.approvalId),!Q)return;await this.renderAgentResponse({thread:A.thread,channelId:A.thread.id,conversationId:A.conversationId,response:Q,userPermissionLevel:A.userPermissionLevel,confirmation:{approvalId:A.approvalId,confirmed:A.confirmed}})}formatNoticePayload(A,Q="Approval notice"){return{card:{type:"card",title:Q,children:[{type:"text",content:A}]},fallbackText:A}}formatErrorPayload(A){let Q=A instanceof Error?A.message:"Unknown error";return{card:{type:"card",title:"Message failed",children:[{type:"text",content:Q}]},fallbackText:`Message failed: ${Q}`}}formatAgentResponseText(A,Q){return A.directives.flatMap((w)=>{if(w.kind==="text")return[w.text];if(w.kind==="denied-artifact")return[this.cardBuilder.formatStructuredCard(w.card,Q)];return[]}).filter((w)=>w.trim().length>0).join(`
2372
+ \`\`\``;return this.defaultNodeToText(A,(Q)=>this.nodeToDiscordMarkdown(Q))}};var Tj1={DeferredChannelMessageWithSource:5,DeferredUpdateMessage:6},L50="https://discord.com/api/v10",Sj1=2000,mgQ=/^[0-9a-f]{64}$/,ugQ=/^[0-9a-f]+$/,cgQ=class A{name="discord";userName;botUserId;apiBaseUrl;botToken;publicKey;applicationId;mentionRoleIds;interactionFlags;chat=null;logger;formatConverter=new SgQ;requestContext=new OgQ;threadParentCache=new Map;static THREAD_PARENT_CACHE_TTL=300000;constructor(Q={}){let w=Q.botToken??process.env.DISCORD_BOT_TOKEN;if(!w)throw new HH("discord","botToken is required. Set DISCORD_BOT_TOKEN or provide it in config.");let B=Q.publicKey??process.env.DISCORD_PUBLIC_KEY;if(!B)throw new HH("discord","publicKey is required. Set DISCORD_PUBLIC_KEY or provide it in config.");let $=Q.applicationId??process.env.DISCORD_APPLICATION_ID;if(!$)throw new HH("discord","applicationId is required. Set DISCORD_APPLICATION_ID or provide it in config.");if(this.apiBaseUrl=Q.apiUrl??process.env.DISCORD_API_URL??L50,this.botToken=w,this.publicKey=B.trim().toLowerCase(),this.applicationId=$,this.mentionRoleIds=Q.mentionRoleIds??(process.env.DISCORD_MENTION_ROLE_IDS?process.env.DISCORD_MENTION_ROLE_IDS.split(",").map((f)=>f.trim()):[]),this.botUserId=$,this.interactionFlags=Q.interactionFlags,this.logger=Q.logger??new V50("info").child("discord"),this.userName=Q.userName??"bot",!mgQ.test(this.publicKey))this.logger.error("Invalid Discord public key format",{length:this.publicKey.length,isHex:ugQ.test(this.publicKey)})}async initialize(Q){this.chat=Q,this.logger.info("Discord adapter initialized")}async getUser(Q){try{let B=await(await this.discordFetch(`/users/${Q}`,"GET")).json();return{avatarUrl:B.avatar?`https://cdn.discordapp.com/avatars/${B.id}/${B.avatar}.png`:void 0,email:void 0,fullName:B.global_name||B.username,isBot:B.bot??!1,userId:B.id,userName:B.username}}catch{return null}}async handleWebhook(Q,w){let B=await Q.arrayBuffer(),$=new Uint8Array(B),f=new TextDecoder().decode($),Y=Q.headers.get("x-discord-gateway-token");if(Y){if(Y!==this.botToken)return this.logger.warn("Invalid gateway token"),new Response("Invalid gateway token",{status:401});this.logger.info("Discord forwarded Gateway event received");try{let U=JSON.parse(f);return this.handleForwardedGatewayEvent(U,w)}catch{return new Response("Invalid JSON",{status:400})}}this.logger.info("Discord webhook received",{bodyLength:f.length,bodyBytesLength:$.length,hasSignature:!!Q.headers.get("x-signature-ed25519"),hasTimestamp:!!Q.headers.get("x-signature-timestamp")});let X=Q.headers.get("x-signature-ed25519"),W=Q.headers.get("x-signature-timestamp");if(!await this.verifySignature($,X,W))return this.logger.warn("Discord signature verification failed, returning 401"),new Response("Invalid signature",{status:401});this.logger.info("Discord signature verification passed");let K;try{K=JSON.parse(f)}catch{return new Response("Invalid JSON",{status:400})}if(this.logger.info("Discord interaction parsed",{type:K.type,typeIsPing:K.type===LC.Ping,expectedPingType:LC.Ping,id:K.id}),K.type===LC.Ping){let U=JSON.stringify({type:bd.InteractionResponseType.PONG});return this.logger.info("Discord PING received, responding with PONG",{responseBody:U,responseType:bd.InteractionResponseType.PONG}),new Response(U,{status:200,headers:{"Content-Type":"application/json"}})}if(K.type===LC.MessageComponent)return this.handleComponentInteraction(K,w),this.respondToInteraction({type:Tj1.DeferredUpdateMessage});if(K.type===LC.ApplicationCommand){let U=this.getApplicationCommandContext(K),D=this.getInteractionFlags(U);return this.handleApplicationCommandInteraction(U,w),this.respondToInteraction({...D===void 0?{}:{data:{flags:D}},type:Tj1.DeferredChannelMessageWithSource})}return new Response("Unknown interaction type",{status:400})}async verifySignature(Q,w,B){if(!(w&&B))return this.logger.warn("Discord signature verification failed: missing headers",{hasSignature:!!w,hasTimestamp:!!B}),!1;try{this.logger.info("Discord signature verification attempt",{bodyBytesLength:Q.length,signatureLength:w.length,timestampLength:B.length,publicKeyLength:this.publicKey.length,timestamp:B,signaturePrefix:w.slice(0,16),publicKey:this.publicKey});let $=await bd.verifyKey(Q,w,B,this.publicKey);if(!$){let f=new TextDecoder().decode(Q);this.logger.warn("Discord signature verification failed: invalid signature",{publicKeyLength:this.publicKey.length,signatureLength:w.length,publicKeyPrefix:this.publicKey.slice(0,8),publicKeySuffix:this.publicKey.slice(-8),timestamp:B,bodyLength:Q.length,bodyPrefix:f.slice(0,50)})}return $}catch($){return this.logger.warn("Discord signature verification failed: exception",{error:$}),!1}}respondToInteraction(Q){return Response.json(Q)}handleComponentInteraction(Q,w){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring interaction");return}let B=Q.data?.custom_id;if(!B){this.logger.warn("No custom_id in component interaction");return}let $=Q.member?.user||Q.user;if(!$){this.logger.warn("No user in component interaction");return}let f=Q.channel_id,Y=Q.guild_id||"@me",X=Q.message?.id;if(!(f&&X)){this.logger.warn("Missing channel_id or message_id in interaction");return}let W=Q.channel,H=W?.type===11||W?.type===12,K=H&&W?.parent_id?W.parent_id:f,U=H?this.encodeThreadId({guildId:Y,channelId:K,threadId:f}):this.encodeThreadId({guildId:Y,channelId:f}),D=RgQ(B),q={actionId:D.actionId,value:D.value??D.actionId,user:{userId:$.id,userName:$.username,fullName:$.global_name||$.username,isBot:$.bot??!1,isMe:!1},messageId:X,threadId:U,adapter:this,raw:Q};this.logger.debug("Processing Discord button action",{actionId:B,messageId:X,threadId:U}),this.chat.processAction(q,w)}getApplicationCommandContext(Q){let w=Q.data?.name;if(!w)return this.logger.warn("No command name in application command interaction"),null;let B=Q.member?.user||Q.user;if(!B)return this.logger.warn("No user in application command interaction"),null;let $=Q.channel_id;if(!$)return this.logger.warn("Missing channel_id in application command interaction"),null;let f=Q.guild_id||"@me",Y=Q.channel,X=Y?.type===11||Y?.type===12,W=X&&Y?.parent_id?Y.parent_id:$,H=X?this.encodeThreadId({guildId:f,channelId:W,threadId:$}):this.encodeThreadId({guildId:f,channelId:$}),{command:K,text:U}=this.parseSlashCommand(w,Q.data?.options);return{channelId:H,command:K,interaction:Q,text:U,user:B}}getInteractionFlags(Q){if(!(Q&&this.interactionFlags))return;return this.interactionFlags(Q)}handleApplicationCommandInteraction(Q,w){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring interaction");return}if(!Q)return;let{channelId:B,command:$,interaction:f,text:Y,user:X}=Q;this.logger.debug("Processing Discord slash command",{command:$,text:Y,userId:X.id,channelId:B}),this.requestContext.run({slashCommand:{channelId:B,interactionToken:f.token,initialResponseSent:!1}},()=>{this.chat?.processSlashCommand({command:$,text:Y,user:{userId:X.id,userName:X.username,fullName:X.global_name||X.username,isBot:X.bot??!1,isMe:X.id===this.applicationId},adapter:this,raw:f,channelId:B},w)})}parseSlashCommand(Q,w){let B=[Q.startsWith("/")?Q:`/${Q}`],$=[],f=(Y)=>{for(let X of Y){if(X.value!==void 0){$.push(String(X.value));continue}if(X.options&&X.options.length>0)B.push(X.name),f(X.options)}};if(w&&w.length>0)f(w);return{command:B.join(" "),text:$.join(" ").trim()}}async handleGatewayInteraction(Q){if(Q.isChatInputCommand()){let w=this.getApplicationCommandContext(this.normalizeGatewaySlashCommandInteraction(Q)),B=this.getInteractionFlags(w);await Q.deferReply(B===void 0?void 0:{flags:B}),this.handleApplicationCommandInteraction(w);return}if(Q.isMessageComponent())await Q.deferUpdate(),this.handleComponentInteraction(this.normalizeGatewayComponentInteraction(Q))}normalizeGatewaySlashCommandInteraction(Q){return{application_id:Q.applicationId,channel:this.normalizeGatewayChannel(Q),channel_id:Q.channelId??void 0,data:{name:Q.commandName,options:this.normalizeGatewayCommandOptions(Q.options.data),type:Q.commandType},guild_id:Q.guildId??void 0,id:Q.id,token:Q.token,type:Q.type,user:this.normalizeGatewayUser(Q.user),version:Q.version}}normalizeGatewayComponentInteraction(Q){let w="values"in Q&&Array.isArray(Q.values)?Q.values:void 0;return{application_id:Q.applicationId,channel:this.normalizeGatewayChannel(Q),channel_id:Q.channelId??void 0,data:{component_type:Q.componentType,custom_id:Q.customId,values:w},guild_id:Q.guildId??void 0,id:Q.id,message:{id:Q.message.id},token:Q.token,type:Q.type,user:this.normalizeGatewayUser(Q.user),version:Q.version}}normalizeGatewayChannel(Q){if(!Q.channel)return;let w="parentId"in Q.channel&&typeof Q.channel.parentId==="string"?Q.channel.parentId:void 0;return{id:Q.channel.id,parent_id:w,type:Q.channel.type}}normalizeGatewayCommandOptions(Q){return Q.map((w)=>({name:w.name,options:w.options?this.normalizeGatewayCommandOptions(w.options):void 0,type:w.type,value:w.value}))}normalizeGatewayUser(Q){return{avatar:Q.avatar??void 0,bot:Q.bot,discriminator:Q.discriminator,global_name:Q.globalName??void 0,id:Q.id,username:Q.username}}async handleForwardedGatewayEvent(Q,w){switch(this.logger.info("Processing forwarded Gateway event",{type:Q.type,timestamp:Q.timestamp}),Q.type){case"GATEWAY_MESSAGE_CREATE":await this.handleForwardedMessage(Q.data,w);break;case"GATEWAY_MESSAGE_REACTION_ADD":await this.handleForwardedReaction(Q.data,!0,w);break;case"GATEWAY_MESSAGE_REACTION_REMOVE":await this.handleForwardedReaction(Q.data,!1,w);break;default:this.logger.debug("Forwarded Gateway event (no handler)",{type:Q.type})}return new Response(JSON.stringify({ok:!0}),{status:200,headers:{"Content-Type":"application/json"}})}async handleForwardedMessage(Q,w){if(!this.chat)return;let B=Q.guild_id||"@me",$=Q.channel_id,f,Y=$;if(Q.thread)f=Q.thread.id,Y=Q.thread.parent_id;else if(Q.channel_type===11||Q.channel_type===12)try{let q=await(await this.discordFetch(`/channels/${$}`,"GET")).json();if(q.parent_id)f=$,Y=q.parent_id,this.logger.debug("Fetched thread parent for forwarded message",{threadId:$,parentId:q.parent_id})}catch(D){this.logger.error("Failed to fetch thread parent",{error:String(D),channelId:$})}let X=Q.is_mention||Q.mentions.some((D)=>D.id===this.applicationId),W=this.mentionRoleIds.length>0&&Q.mention_roles?.some((D)=>this.mentionRoleIds.includes(D)),H=X||W;if(!f&&H)try{let D=await this.createDiscordThread($,Q.id);f=D.id,this.logger.debug("Created Discord thread for forwarded mention",{channelId:$,messageId:Q.id,threadId:D.id})}catch(D){this.logger.error("Failed to create Discord thread for mention",{error:String(D),messageId:Q.id})}let K=this.encodeThreadId({guildId:B,channelId:Y,threadId:f}),U=new c8({id:Q.id,threadId:K,text:Q.content,formatted:this.formatConverter.toAst(Q.content),author:{userId:Q.author.id,userName:Q.author.username,fullName:Q.author.global_name||Q.author.username,isBot:Q.author.bot===!0,isMe:Q.author.id===this.applicationId},metadata:{dateSent:new Date(Q.timestamp),edited:!1},attachments:Q.attachments.map((D)=>({type:this.getAttachmentType(D.content_type),url:D.url,name:D.filename,mimeType:D.content_type,size:D.size})),raw:Q,isMention:H});try{await this.chat.handleIncomingMessage(this,K,U)}catch(D){this.logger.error("Error handling forwarded message",{error:String(D),messageId:Q.id})}}async handleForwardedReaction(Q,w,B){if(!this.chat)return;let $=Q.guild_id||"@me",f=Q.channel_id,Y,X=f;if(Q.channel_type===oN.GuildPublicThread||Q.channel_type===oN.GuildPrivateThread){let q=this.threadParentCache.get(f);if(q&&q.expiresAt>Date.now())Y=f,X=q.parentId;else try{let I=await(await this.discordFetch(`/channels/${f}`,"GET")).json();if(I.parent_id)Y=f,X=I.parent_id,this.threadParentCache.set(f,{parentId:I.parent_id,expiresAt:Date.now()+A.THREAD_PARENT_CACHE_TTL})}catch(b){this.logger.error("Failed to fetch thread parent for reaction",{error:String(b),channelId:f})}}let W=this.encodeThreadId({guildId:$,channelId:X,threadId:Y}),H=Q.emoji.name||"unknown",K=this.normalizeDiscordEmoji(H),U=Q.user??Q.member?.user;if(!U){this.logger.warn("Reaction event missing user info",{data:Q});return}let D={adapter:this,threadId:W,messageId:Q.message_id,emoji:K,rawEmoji:Q.emoji.id?`<:${H}:${Q.emoji.id}>`:H,added:w,user:{userId:U.id,userName:U.username,fullName:U.username,isBot:U.bot===!0,isMe:U.id===this.applicationId},raw:Q};this.chat.processReaction(D)}async postMessage(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=Q;if($)B=$;let Y={},X=[],W=[],H=F50(w);if(H){let b=Cm0(H);X.push(...b.embeds),W.push(...b.components)}else Y.content=this.truncateContent(iN(this.formatConverter.renderPostable(w),"discord"));if(X.length>0)Y.embeds=X;if(W.length>0)Y.components=W;let K=Um0(w),U=this.tryPostSlashResponse(f,Y,K);if(U)return U;if(K.length>0)return this.postMessageWithFiles(B,f,Y,K);this.logger.debug("Discord API: POST message",{channelId:B,contentLength:Y.content?.length||0,embedCount:X.length,componentCount:W.length});let q=await(await this.discordFetch(`/channels/${B}/messages`,"POST",Y)).json();return this.logger.debug("Discord API: POST message response",{messageId:q.id}),{id:q.id,threadId:f,raw:q}}tryPostSlashResponse(Q,w,B){let $=this.requestContext.getStore()?.slashCommand;if(!$||$.channelId!==Q)return;return this.postSlashCommandResponse($,Q,w,B)}async postSlashCommandResponse(Q,w,B,$){let f=!Q.initialResponseSent;Q.initialResponseSent=!0;let Y=f?`/webhooks/${this.applicationId}/${Q.interactionToken}/messages/@original`:`/webhooks/${this.applicationId}/${Q.interactionToken}?wait=true`,X=f?"PATCH":"POST";this.logger.debug("Discord interaction webhook: responding to slash command",{threadId:w,isInitialResponse:f,hasFiles:$.length>0});let H=await($.length>0?await this.discordInteractionFetchWithFiles(Y,X,B,$):await this.discordInteractionFetch(Y,X,B)).json();return{id:H.id,threadId:w,raw:H}}async createDiscordThread(Q,w){let B=`Thread ${new Date().toLocaleString()}`;this.logger.debug("Discord API: POST thread",{channelId:Q,messageId:w,threadName:B});try{let f=await(await this.discordFetch(`/channels/${Q}/messages/${w}/threads`,"POST",{name:B,auto_archive_duration:1440})).json();return this.logger.debug("Discord API: POST thread response",{threadId:f.id,threadName:f.name}),f}catch($){if($ instanceof TJ&&typeof $.message==="string"&&$.message.includes('"code"')&&$.message.includes("160004"))return this.logger.debug("Thread already exists for message, reusing existing thread",{channelId:Q,messageId:w}),{id:w,name:B};throw $}}truncateContent(Q){if(Q.length<=Sj1)return Q;return`${Q.slice(0,Sj1-3)}...`}async postMessageWithFiles(Q,w,B,$){let f=new FormData;f.append("payload_json",JSON.stringify(B));for(let W=0;W<$.length;W++){let H=$[W];if(!H)continue;let K=await Dm0(H.data,{platform:"discord"});if(!K)continue;let U=new Blob([new Uint8Array(K)],{type:H.mimeType||"application/octet-stream"});f.append(`files[${W}]`,U,H.filename)}let Y=await fetch(`${L50}/channels/${Q}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.botToken}`},body:f});if(!Y.ok){let W=await Y.text();throw new TJ("discord",`Failed to post message: ${Y.status} ${W}`)}let X=await Y.json();return{id:X.id,threadId:w,raw:X}}async discordInteractionFetch(Q,w,B){let $=await fetch(`${L50}${Q}`,{method:w,headers:B?{"Content-Type":"application/json"}:void 0,body:B?JSON.stringify(B):void 0});if(!$.ok){let f=await $.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:$.status,error:f}),new TJ("discord",`Discord interaction API error: ${$.status} ${f}`)}return $}async discordInteractionFetchWithFiles(Q,w,B,$){let f=new FormData;f.append("payload_json",JSON.stringify(B));for(let X=0;X<$.length;X++){let W=$[X];if(!W)continue;let H=await Dm0(W.data,{platform:"discord"});if(!H)continue;let K=new Blob([new Uint8Array(H)],{type:W.mimeType||"application/octet-stream"});f.append(`files[${X}]`,K,W.filename)}let Y=await fetch(`${L50}${Q}`,{method:w,body:f});if(!Y.ok){let X=await Y.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:Y.status,error:X}),new TJ("discord",`Discord interaction API error: ${Y.status} ${X}`)}return Y}async editMessage(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),Y=f||$,X={},W=[],H=[],K=F50(B);if(K){let q=Cm0(K);W.push(...q.embeds),H.push(...q.components),X.content=""}else X.content=this.truncateContent(iN(this.formatConverter.renderPostable(B),"discord"));if(W.length>0)X.embeds=W;if(H.length>0)X.components=H;this.logger.debug("Discord API: PATCH message",{channelId:Y,messageId:w,contentLength:X.content?.length||0});let D=await(await this.discordFetch(`/channels/${Y}/messages/${w}`,"PATCH",X)).json();return this.logger.debug("Discord API: PATCH message response",{messageId:D.id}),{id:D.id,threadId:Q,raw:D}}async deleteMessage(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=$||B;this.logger.debug("Discord API: DELETE message",{channelId:f,messageId:w}),await this.discordFetch(`/channels/${f}/messages/${w}`,"DELETE"),this.logger.debug("Discord API: DELETE message response",{ok:!0})}async addReaction(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),Y=f||$,X=this.encodeEmoji(B);this.logger.debug("Discord API: PUT reaction",{channelId:Y,messageId:w,emoji:X}),await this.discordFetch(`/channels/${Y}/messages/${w}/reactions/${X}/@me`,"PUT"),this.logger.debug("Discord API: PUT reaction response",{ok:!0})}async removeReaction(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),Y=f||$,X=this.encodeEmoji(B);this.logger.debug("Discord API: DELETE reaction",{channelId:Y,messageId:w,emoji:X}),await this.discordFetch(`/channels/${Y}/messages/${w}/reactions/${X}/@me`,"DELETE"),this.logger.debug("Discord API: DELETE reaction response",{ok:!0})}encodeEmoji(Q){let w=Ud.toDiscord?Ud.toDiscord(Q):String(Q);return encodeURIComponent(w)}async startTyping(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=$||B;this.logger.debug("Discord API: POST typing",{channelId:f}),await this.discordFetch(`/channels/${f}/typing`,"POST")}async fetchMessages(Q,w={}){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=$||B,Y=w.limit||50,X=w.direction??"backward",W=new URLSearchParams;if(W.set("limit",String(Y)),w.cursor)if(X==="backward")W.set("before",w.cursor);else W.set("after",w.cursor);this.logger.debug("Discord API: GET messages",{channelId:f,limit:Y,direction:X,cursor:w.cursor});let K=await(await this.discordFetch(`/channels/${f}/messages?${W.toString()}`,"GET")).json();this.logger.debug("Discord API: GET messages response",{messageCount:K.length});let D=[...K].reverse().map((b)=>this.parseDiscordMessage(b,Q)),q;if(K.length===Y)if(X==="backward")q=K.at(-1)?.id;else q=K[0]?.id;return{messages:D,nextCursor:q}}async fetchThread(Q){let{channelId:w,guildId:B}=this.decodeThreadId(Q);this.logger.debug("Discord API: GET channel",{channelId:w});let f=await(await this.discordFetch(`/channels/${w}`,"GET")).json();return{id:Q,channelId:w,channelName:f.name,isDM:f.type===oN.DM||f.type===oN.GroupDM,metadata:{guildId:B,channelType:f.type,raw:f}}}async openDM(Q){this.logger.debug("Discord API: POST DM channel",{userId:Q});let B=await(await this.discordFetch("/users/@me/channels","POST",{recipient_id:Q})).json();return this.logger.debug("Discord API: POST DM channel response",{channelId:B.id}),this.encodeThreadId({guildId:"@me",channelId:B.id})}isDM(Q){let{guildId:w}=this.decodeThreadId(Q);return w==="@me"}encodeThreadId(Q){let w=Q.threadId?`:${Q.threadId}`:"";return`discord:${Q.guildId}:${Q.channelId}${w}`}decodeThreadId(Q){let w=Q.split(":");if(w.length<3||w[0]!=="discord")throw new HH("discord",`Invalid Discord thread ID: ${Q}`);return{guildId:w[1],channelId:w[2],threadId:w[3]}}parseMessage(Q){let w=Q,B=w.guild_id||"@me",$=this.encodeThreadId({guildId:B,channelId:w.channel_id});return this.parseDiscordMessage(w,$)}parseDiscordMessage(Q,w){let B=Q.type===yF1.ThreadStarterMessage&&Q.referenced_message?Q.referenced_message:Q,$=B.author,f=$.bot??!1,Y=$.id===this.botUserId;return new c8({id:B.id,threadId:w,text:this.formatConverter.extractPlainText(B.content),formatted:this.formatConverter.toAst(B.content),raw:Q,author:{userId:$.id,userName:$.username,fullName:$.global_name||$.username,isBot:f,isMe:Y},metadata:{dateSent:new Date(B.timestamp),edited:B.edited_timestamp!==null,editedAt:B.edited_timestamp?new Date(B.edited_timestamp):void 0},attachments:(B.attachments||[]).map((X)=>({type:this.getAttachmentType(X.content_type),url:X.url,name:X.filename,mimeType:X.content_type,size:X.size,width:X.width??void 0,height:X.height??void 0}))})}getAttachmentType(Q){if(!Q)return"file";if(Q.startsWith("image/"))return"image";if(Q.startsWith("video/"))return"video";if(Q.startsWith("audio/"))return"audio";return"file"}rehydrateAttachment(Q){let w=Q.fetchMetadata?.url??Q.url;if(!w)return Q;return{...Q,fetchData:()=>this.downloadAttachment(w)}}async downloadAttachment(Q){let w;try{w=await fetch(Q)}catch(B){throw new TJ("discord","Failed to download Discord attachment",B instanceof Error?B:void 0)}if(!w.ok)throw new TJ("discord",`Failed to download Discord attachment: ${w.status}`);return Buffer.from(await w.arrayBuffer())}renderFormatted(Q){return this.formatConverter.fromAst(Q)}async discordFetch(Q,w,B){let $=`${this.apiBaseUrl}${Q}`,f={Authorization:`Bot ${this.botToken}`};if(B)f["Content-Type"]="application/json";let Y=await fetch($,{method:w,headers:f,body:B?JSON.stringify(B):void 0});if(!Y.ok){let X=await Y.text();throw this.logger.error("Discord API error",{path:Q,method:w,status:Y.status,error:X}),new TJ("discord",`Discord API error: ${Y.status} ${X}`)}return Y}async startGatewayListener(Q,w=180000,B,$){if(!this.chat)return new Response("Chat instance not initialized",{status:500});if(!Q.waitUntil)return new Response("waitUntil not provided",{status:500});this.logger.info("Starting Discord Gateway listener",{durationMs:w,webhookUrl:$?"configured":"not configured"});let f=this.runGatewayListener(w,B,$);return Q.waitUntil(f),new Response(JSON.stringify({status:"listening",durationMs:w,message:`Gateway listener started, will run for ${w/1000} seconds`}),{status:200,headers:{"Content-Type":"application/json"}})}async runGatewayListener(Q,w,B){let $=new A7.Client({intents:[A7.GatewayIntentBits.Guilds,A7.GatewayIntentBits.GuildMessages,A7.GatewayIntentBits.MessageContent,A7.GatewayIntentBits.DirectMessages,A7.GatewayIntentBits.GuildMessageReactions,A7.GatewayIntentBits.DirectMessageReactions],partials:[A7.Partials.Channel]}),f=!1;if(B)$.on("raw",async(Y)=>{if(f)return;if(!Y.t)return;this.logger.info("Discord Gateway forwarding event",{type:Y.t}),await this.forwardGatewayEvent(B,{type:`GATEWAY_${Y.t}`,timestamp:Date.now(),data:Y.d})});else this.setupLegacyGatewayHandlers($,()=>f);$.on(A7.Events.ClientReady,()=>{this.logger.info("Discord Gateway connected",{username:$.user?.username,id:$.user?.id})}),$.on(A7.Events.Error,(Y)=>{this.logger.error("Discord Gateway error",{error:String(Y)})});try{await $.login(this.botToken),await new Promise((Y)=>{let X=setTimeout(Y,Q);if(w){if(w.aborted){clearTimeout(X),Y();return}w.addEventListener("abort",()=>{this.logger.info("Discord Gateway listener received abort signal (new listener started)"),clearTimeout(X),Y()},{once:!0})}}),this.logger.info("Discord Gateway listener duration elapsed, disconnecting")}catch(Y){this.logger.error("Discord Gateway listener error",{error:String(Y)})}finally{f=!0,$.destroy(),this.logger.info("Discord Gateway listener stopped")}}setupLegacyGatewayHandlers(Q,w){Q.on(A7.Events.MessageCreate,async(B)=>{if(w()){this.logger.debug("Ignoring message - Gateway is shutting down");return}if(B.author.bot){this.logger.debug("Ignoring message from bot",{authorId:B.author.id,authorName:B.author.username,isMe:B.author.id===Q.user?.id});return}let $=B.mentions.has(Q.user?.id??""),f=this.mentionRoleIds.length>0&&B.mentions.roles.some((X)=>this.mentionRoleIds.includes(X.id)),Y=$||f;this.logger.info("Discord Gateway message received",{channelId:B.channelId,guildId:B.guildId,authorId:B.author.id,isMentioned:Y,isUserMentioned:$,isRoleMentioned:f,content:B.content.slice(0,100)}),await this.handleGatewayMessage(B,Y)}),Q.on(A7.Events.InteractionCreate,async(B)=>{if(w()){this.logger.debug("Ignoring interaction - Gateway is shutting down");return}this.logger.info("Discord Gateway interaction received",{id:B.id,type:B.type});try{await this.handleGatewayInteraction(B)}catch($){this.logger.error("Error handling Gateway interaction",{error:String($),interactionId:B.id})}}),Q.on(A7.Events.MessageReactionAdd,async(B,$)=>{if(w()){this.logger.debug("Ignoring reaction - Gateway is shutting down");return}if($.bot){this.logger.debug("Ignoring reaction from bot",{userId:$.id,isMe:$.id===Q.user?.id});return}if(this.logger.info("Discord Gateway reaction added",{emoji:B.emoji.name,messageId:B.message.id,channelId:B.message.channelId,userId:$.id}),$.username)await this.handleGatewayReaction(B,$,!0)}),Q.on(A7.Events.MessageReactionRemove,async(B,$)=>{if(w()){this.logger.debug("Ignoring reaction removal - Gateway is shutting down");return}if($.bot){this.logger.debug("Ignoring reaction removal from bot",{userId:$.id,isMe:$.id===Q.user?.id});return}if(this.logger.info("Discord Gateway reaction removed",{emoji:B.emoji.name,messageId:B.message.id,channelId:B.message.channelId,userId:$.id}),$.username)await this.handleGatewayReaction(B,$,!1)})}async forwardGatewayEvent(Q,w){try{this.logger.debug("Forwarding Gateway event to webhook",{type:w.type,webhookUrl:Q});let B=await fetch(Q,{method:"POST",headers:{"Content-Type":"application/json","x-discord-gateway-token":this.botToken},body:JSON.stringify(w)});if(B.ok)this.logger.debug("Gateway event forwarded successfully",{type:w.type});else{let $=await B.text();this.logger.error("Failed to forward Gateway event",{type:w.type,status:B.status,error:$})}}catch(B){this.logger.error("Error forwarding Gateway event",{type:w.type,error:String(B)})}}async handleGatewayMessage(Q,w){if(!this.chat)return;let B=Q.guildId||"@me",$=Q.channelId,f=Q.channel.isThread(),Y,X=$;if(f&&"parentId"in Q.channel&&Q.channel.parentId)Y=$,X=Q.channel.parentId;if(!Y&&w)try{let K=await this.createDiscordThread($,Q.id);Y=K.id,this.logger.debug("Created Discord thread for incoming mention",{channelId:$,messageId:Q.id,threadId:K.id})}catch(K){this.logger.error("Failed to create Discord thread for mention",{error:String(K),messageId:Q.id})}let W=this.encodeThreadId({guildId:B,channelId:X,threadId:Y}),H=new c8({id:Q.id,threadId:W,text:Q.content,formatted:this.formatConverter.toAst(Q.content),author:{userId:Q.author.id,userName:Q.author.username,fullName:Q.author.displayName||Q.author.username,isBot:Q.author.bot,isMe:!1},metadata:{dateSent:Q.createdAt,edited:Q.editedAt!==null,editedAt:Q.editedAt??void 0},attachments:Q.attachments.map((K)=>({type:this.getAttachmentType(K.contentType),url:K.url,name:K.name,mimeType:K.contentType??void 0,size:K.size})),raw:{id:Q.id,channel_id:$,guild_id:B,content:Q.content,author:{id:Q.author.id,username:Q.author.username},timestamp:Q.createdAt.toISOString()},isMention:w});try{await this.chat.handleIncomingMessage(this,W,H)}catch(K){this.logger.error("Error handling Gateway message",{error:String(K),messageId:Q.id})}}async handleGatewayReaction(Q,w,B){if(!this.chat)return;let $=Q.message.guildId||"@me",f=Q.message.channelId,Y=Q.message.channel?.isThread?.(),X=f,W;if(Y&&Q.message.channel?.parentId)W=f,X=Q.message.channel.parentId;let H=this.encodeThreadId({guildId:$,channelId:X,threadId:W}),K=Q.emoji.name||"unknown",U=this.normalizeDiscordEmoji(K),D={adapter:this,threadId:H,messageId:Q.message.id,emoji:U,rawEmoji:Q.emoji.id?`<:${K}:${Q.emoji.id}>`:K,added:B,user:{userId:w.id,userName:w.username,fullName:w.username,isBot:w.bot===!0,isMe:w.id===this.applicationId},raw:{emoji:Q.emoji,message_id:Q.message.id,channel_id:Q.message.channelId,guild_id:Q.message.guildId,user_id:w.id}};this.chat.processReaction(D)}channelIdFromThreadId(Q){return Q.split(":").slice(0,3).join(":")}async fetchChannelMessages(Q,w={}){let $=Q.split(":")[2];if(!$)throw new HH("discord",`Invalid Discord channel ID: ${Q}`);let f=w.limit||50,Y=w.direction??"backward",X=new URLSearchParams;if(X.set("limit",String(f)),w.cursor)if(Y==="backward")X.set("before",w.cursor);else X.set("after",w.cursor);this.logger.debug("Discord API: GET channel messages",{channelId:$,limit:f,direction:Y,cursor:w.cursor});let H=await(await this.discordFetch(`/channels/${$}/messages?${X.toString()}`,"GET")).json();this.logger.debug("Discord API: GET channel messages response",{messageCount:H.length});let U=[...H].reverse().map((q)=>this.parseDiscordMessage(q,Q)),D;if(H.length===f)if(Y==="backward")D=H.at(-1)?.id;else D=H[0]?.id;return{messages:U,nextCursor:D}}async listThreads(Q,w={}){let B=Q.split(":"),$=B[1],f=B[2];if(!($&&f))throw new HH("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET threads",{guildId:$,channelId:f});let W=((await(await this.discordFetch(`/guilds/${$}/threads/active`,"GET")).json()).threads||[]).filter((V)=>V.parent_id===f),H=[];try{H=(await(await this.discordFetch(`/channels/${f}/threads/archived/public?limit=${w.limit||50}`,"GET")).json()).threads||[]}catch{this.logger.debug("Could not fetch archived threads (may lack permissions)")}let K=[...W,...H],U=new Set,D=K.filter((V)=>{if(U.has(V.id))return!1;return U.add(V.id),!0}),q=w.limit||50,b=D.slice(0,q),I=[];for(let V of b){let L=this.encodeThreadId({guildId:$,channelId:f,threadId:V.id});try{let x=(await(await this.discordFetch(`/channels/${V.id}/messages?limit=1&after=0`,"GET")).json())[0];if(x)I.push({id:L,rootMessage:this.parseDiscordMessage(x,L),replyCount:V.total_message_sent??V.message_count,lastReplyAt:V.thread_metadata?.archive_timestamp?new Date(V.thread_metadata.archive_timestamp):void 0})}catch{I.push({id:L,rootMessage:new c8({id:V.id,threadId:L,text:V.name,formatted:this.formatConverter.toAst(V.name),raw:V,author:{userId:"unknown",userName:"unknown",fullName:"unknown",isBot:!1,isMe:!1},metadata:{dateSent:new Date,edited:!1},attachments:[]}),replyCount:V.total_message_sent??V.message_count})}}return this.logger.debug("Discord API: listThreads result",{threadCount:I.length}),{threads:I,nextCursor:D.length>q?String(q):void 0}}async fetchChannelInfo(Q){let B=Q.split(":")[2];if(!B)throw new HH("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET channel info",{channelId:B});let f=await(await this.discordFetch(`/channels/${B}`,"GET")).json();return{id:Q,name:f.name,isDM:f.type===oN.DM||f.type===oN.GroupDM,memberCount:f.member_count,metadata:{channelType:f.type,raw:f}}}async postChannelMessage(Q,w){let $=Q.split(":")[2];if(!$)throw new HH("discord",`Invalid Discord channel ID: ${Q}`);let f={},Y=[],X=[],W=F50(w);if(W){let q=Cm0(W);Y.push(...q.embeds),X.push(...q.components)}else f.content=this.truncateContent(iN(this.formatConverter.renderPostable(w),"discord"));if(Y.length>0)f.embeds=Y;if(X.length>0)f.components=X;let H=Um0(w),K=this.tryPostSlashResponse(Q,f,H);if(K)return K;if(H.length>0)return this.postMessageWithFiles($,Q,f,H);this.logger.debug("Discord API: POST channel message",{channelId:$,contentLength:f.content?.length||0});let D=await(await this.discordFetch(`/channels/${$}/messages`,"POST",f)).json();return{id:D.id,threadId:Q,raw:D}}normalizeDiscordEmoji(Q){let B={"\uD83D\uDC4D":"thumbs_up","\uD83D\uDC4E":"thumbs_down","\u2764\uFE0F":"heart","\u2764":"heart","\uD83D\uDD25":"fire","\uD83D\uDE80":"rocket","\uD83D\uDE4C":"raised_hands","\u2705":"check","\u274C":"x","\uD83D\uDC4B":"wave","\uD83E\uDD14":"thinking","\uD83D\uDE0A":"smile","\uD83D\uDE02":"laugh","\uD83C\uDF89":"party","\u2B50":"star","\u2728":"sparkles","\uD83D\uDC40":"eyes","\uD83D\uDCAF":"100"}[Q]||Q;return EJ(B)}};function cj1(A){return new cgQ(A??{})}var lgQ=class{subscriptions=new Set;locks=new Map;cache=new Map;queues=new Map;connected=!1;connectPromise=null;async connect(){if(this.connected)return;if(!this.connectPromise)this.connectPromise=Promise.resolve().then(()=>{this.connected=!0});await this.connectPromise}async disconnect(){this.connected=!1,this.connectPromise=null,this.subscriptions.clear(),this.locks.clear(),this.queues.clear()}async subscribe(A){this.ensureConnected(),this.subscriptions.add(A)}async unsubscribe(A){this.ensureConnected(),this.subscriptions.delete(A)}async isSubscribed(A){return this.ensureConnected(),this.subscriptions.has(A)}async acquireLock(A,Q){this.ensureConnected(),this.cleanExpiredLocks();let w=this.locks.get(A);if(w&&w.expiresAt>Date.now())return null;let B={threadId:A,token:pgQ(),expiresAt:Date.now()+Q};return this.locks.set(A,B),B}async forceReleaseLock(A){this.ensureConnected(),this.locks.delete(A)}async releaseLock(A){this.ensureConnected();let Q=this.locks.get(A.threadId);if(Q&&Q.token===A.token)this.locks.delete(A.threadId)}async extendLock(A,Q){this.ensureConnected();let w=this.locks.get(A.threadId);if(!w||w.token!==A.token)return!1;if(w.expiresAt<Date.now())return this.locks.delete(A.threadId),!1;return w.expiresAt=Date.now()+Q,!0}async get(A){this.ensureConnected();let Q=this.cache.get(A);if(!Q)return null;if(Q.expiresAt!==null&&Q.expiresAt<=Date.now())return this.cache.delete(A),null;return Q.value}async set(A,Q,w){this.ensureConnected(),this.cache.set(A,{value:Q,expiresAt:w?Date.now()+w:null})}async setIfNotExists(A,Q,w){this.ensureConnected();let B=this.cache.get(A);if(B)if(B.expiresAt!==null&&B.expiresAt<=Date.now())this.cache.delete(A);else return!1;return this.cache.set(A,{value:Q,expiresAt:w?Date.now()+w:null}),!0}async delete(A){this.ensureConnected(),this.cache.delete(A)}async appendToList(A,Q,w){this.ensureConnected();let B=this.cache.get(A),$;if(B&&B.expiresAt!==null&&B.expiresAt<=Date.now())$=[];else if(B&&Array.isArray(B.value))$=B.value;else $=[];if($.push(Q),w?.maxLength&&$.length>w.maxLength)$=$.slice($.length-w.maxLength);this.cache.set(A,{value:$,expiresAt:w?.ttlMs?Date.now()+w.ttlMs:null})}async enqueue(A,Q,w){this.ensureConnected();let B=this.queues.get(A);if(!B)B=[],this.queues.set(A,B);if(B.push(Q),B.length>w)B.splice(0,B.length-w);return B.length}async dequeue(A){this.ensureConnected();let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let w=Q.shift();if(Q.length===0)this.queues.delete(A);return w??null}async queueDepth(A){return this.ensureConnected(),this.queues.get(A)?.length??0}async getList(A){this.ensureConnected();let Q=this.cache.get(A);if(!Q)return[];if(Q.expiresAt!==null&&Q.expiresAt<=Date.now())return this.cache.delete(A),[];if(Array.isArray(Q.value))return Q.value;return[]}ensureConnected(){if(!this.connected)throw Error("MemoryStateAdapter is not connected. Call connect() first.")}cleanExpiredLocks(){let A=Date.now();for(let[Q,w]of this.locks)if(w.expiresAt<=A)this.locks.delete(Q)}_getSubscriptionCount(){return this.subscriptions.size}_getLockCount(){return this.cleanExpiredLocks(),this.locks.size}};function pgQ(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function k50(A){return new lgQ}N0();var igQ=Z.object({subscribedAt:Z.string().datetime(),routingMode:Z.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:Z.boolean().optional()}),dgQ="chat.discord.subscriptions";function gm0(A){return A.scoped({namespace:dgQ,schema:igQ})}function lj1(A,Q=k50()){let w=gm0(A);return new pj1(Q,w)}class pj1{memoryState;subscriptions;constructor(A,Q){this.memoryState=A,this.subscriptions=Q}connect(){return this.memoryState.connect()}disconnect(){return this.memoryState.disconnect()}async subscribe(A){await this.subscriptions.set(A,{subscribedAt:new Date().toISOString()})}async unsubscribe(A){await this.subscriptions.delete(A)}isSubscribed(A){return this.subscriptions.has(A)}acquireLock(A,Q){return this.memoryState.acquireLock(A,Q)}appendToList(A,Q,w){return this.memoryState.appendToList(A,Q,w)}delete(A){return this.memoryState.delete(A)}dequeue(A){return this.memoryState.dequeue(A)}enqueue(A,Q,w){return this.memoryState.enqueue(A,Q,w)}extendLock(A,Q){return this.memoryState.extendLock(A,Q)}forceReleaseLock(A){return this.memoryState.forceReleaseLock(A)}get(A){return this.memoryState.get(A)}getList(A){return this.memoryState.getList(A)}queueDepth(A){return this.memoryState.queueDepth(A)}releaseLock(A){return this.memoryState.releaseLock(A)}set(A,Q,w){return this.memoryState.set(A,Q,w)}setIfNotExists(A,Q,w){return this.memoryState.setIfNotExists(A,Q,w)}}function ij1(A){let{discord:Q}=A;if(!Q)return new Wm0({userName:A.userName,adapters:{},state:k50()});let w=cj1({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds});return A.gatewayLoop.setAdapter(w),new Wm0({userName:A.userName,adapters:{discord:w},concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"},state:lj1(A.runtimeState)})}class ym0{deps;constructor(A){this.deps=A}async subscribeOwnedThread(A,Q){if(!this.deps.isBotCreatedThread(A,Q))return;try{await A.subscribe(),await this.deps.getSubscriptions()?.set(A.id,{subscribedAt:new Date().toISOString()})}catch(w){this.deps.logger.debug("Discord thread subscription failed",{error:w,threadId:A.id})}}async shouldRouteSubscribedMessage(A,Q){if(this.deps.getPlatform(A)!=="discord")return!1;if(A.isDM)return!0;let w=await this.deps.getSubscriptions()?.get(A.id);if(!w)return!1;if(w.routingMode==="mention-required"){if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,w);return Boolean(Q.isMention)}if(!await this.shouldRequireMentionInSubscribedThread(A))return!0;let $={...w,routingMode:"mention-required"};if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,$);else await this.deps.getSubscriptions()?.set(A.id,$);return Boolean(Q.isMention)}async postMentionRequiredNotice(A,Q){await A.post("I\u2019ll stop auto-replying now that more people joined. Mention me if you need me."),await this.deps.getSubscriptions()?.set(A.id,{...Q,routingMode:"mention-required",mentionRequiredNoticeSent:!0})}async shouldRequireMentionInSubscribedThread(A){try{return(await A.getParticipants()).filter((B)=>!B.isBot&&!B.isMe).length>1}catch(Q){return this.deps.logger.debug("Failed to inspect Discord thread participants",{error:Q,threadId:A.id}),!1}}}wA();class Em0{deps;constructor(A){this.deps=A}async build(A,Q,w,B){let $={message:w.text.trim(),attachments:[],notices:[]};if(w.attachments.length===0)return $;if(!(B==="anchor"||B==="trusted"))return $;let Y=this.deps.getUploadStore();if(!Y)return $;for(let X of w.attachments){let W=X.name;if(!W)continue;let H=zz(W,"upload"),K=EV(H,X.mimeType),U=X.size??0,D=vA0(H,K);if(!D){$.notices.push(`Unsupported file upload type: ${H}`);continue}if(!hA0(D,U)){$.notices.push(`File upload too large: ${H}`);continue}try{let q=await this.readAttachmentData(X);if(!q)continue;let b=qz({filename:H,mediaType:K,content:q,fallbackFilename:"upload"});if(!b.ok){$.notices.push(b.message);continue}let I=await Y.save({filename:b.filename,mediaType:b.mediaType,content:q,metadata:this.buildMetadata(A,Q,w)});$.attachments.push(nj1(I.filename,I.mediaType,q,I.ref,b.kind==="text"))}catch(q){this.deps.logger.error("Failed to read chat attachment",{error:q,filename:H}),$.notices.push(`Could not read file upload: ${H}`)}}return $}async readAttachmentData(A){if(A.fetchData)return A.fetchData();if(!A.url)return;let Q=await fetch(A.url);if(!Q.ok)throw Error(`Attachment download failed with status ${Q.status}`);let w=await Q.arrayBuffer();return Buffer.from(new Uint8Array(w))}buildMetadata(A,Q,w){let B=this.deps.getThreadIdParts(Q.id);return{interfaceType:A,channelId:Q.id,parentChannelId:Q.channelId,messageId:w.id,uploaderId:w.author.userId,uploaderUsername:w.author.userName,...B.guildId?{guildId:B.guildId}:{},...B.threadId?{threadId:B.threadId}:{}}}}function dj1(A,Q,w,B){return nj1(A,Q,w,B,TV(A,Q))}function nj1(A,Q,w,B,$){if($)return{kind:"text",filename:A,mediaType:Q,content:w.toString("utf8").replace(/^\uFEFF/,""),sizeBytes:w.byteLength,source:B};return{kind:"file",filename:A,mediaType:Q,data:w,sizeBytes:w.byteLength,source:B}}function Vd(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}function LG(A){let Q=A.split(":");if(Q[0]!=="discord")return{};return{...Q[1]?{guildId:Q[1]}:{},...Q[2]?{channelId:Q[2]}:{},...Q[3]?{threadId:Q[3]}:{}}}function ngQ(A){let Q=A.raw;if(typeof Q!=="object"||Q===null)return;let w=Q.channel_id;return typeof w==="string"?w:void 0}function rj1(A,Q){if(A.isDM)return!1;let w=LG(A.id);if(!w.threadId)return!1;let B=ngQ(Q);return B!==void 0&&B!==w.threadId}function _50(A,Q){if(Q.allowedChannels.length===0||A.isDM)return!0;let w=LG(A.id);return[A.id,A.channelId,w.channelId,w.threadId].some((B)=>typeof B==="string"&&Q.allowedChannels.includes(B))}function Tm0(A,Q,w){if(A.isDM&&!w.allowDMs)return!1;if(Q.author.isMe)return!1;if(Q.author.isBot&&!Q.isMention)return!1;return _50(A,w)}function Sm0(A,Q,w){if(Q!=="discord")return!0;if(!w)return!1;if(A.isDM&&!w.allowDMs)return!1;return _50(A,w)}function mm0(A,Q){return{channelId:LG(A.id).channelId??A.channelId,isBot:Boolean(Q.author.isBot)}}function _C(A){return A.isDM?"DM":A.channelId}var rgQ="https://discord.com/api/v10";async function oj1(A){let Q=LG(A.threadId),w=Q.threadId??Q.channelId;if(!w)return;let B=A.fetchFn??fetch;try{let $=await B(`${rgQ}/channels/${w}/messages/${A.messageId}`,{method:"PATCH",headers:{Authorization:`Bot ${A.botToken}`,"Content-Type":"application/json"},body:JSON.stringify({components:[]})});if(!$.ok)A.logger.debug("Failed to clear Discord message components",{messageId:A.messageId,channelId:w,status:$.status})}catch($){A.logger.debug("Failed to clear Discord message components",{error:$,messageId:A.messageId,channelId:w})}}var sj1={name:"@brains/chat",version:"0.2.0-alpha.143",description:"Discord Chat SDK interface for Brains",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@chat-adapter/discord":"^4.29.0","@chat-adapter/state-memory":"^4.29.0",chat:"^4.29.0"},devDependencies:{"@brains/core":"workspace:*","@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var sgQ=/https?:\/\/\S+/i,agQ=/[\s\S]+/,tgQ=1000,egQ=Z.looseObject({type:Z.literal("card"),children:Z.array(Z.looseObject({type:Z.string()})),imageUrl:Z.string().optional(),subtitle:Z.string().optional(),title:Z.string().optional()}),AyQ=Z.object({card:Z.custom((A)=>egQ.safeParse(A).success),fallbackText:Z.string().optional()});class N50 extends HK{threadRegistry=new Z50;pendingApprovals;uploadContinuity;promptActions=new ST0(tgQ);toolStatusMessenger=new mT0(this.threadRegistry);cardBuilder=new pT0({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new dT0({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new nT0({cardBuilder:this.cardBuilder,clearMessageComponents:async(A,Q)=>{let w=this.config.adapters.discord?.botToken;if(!w)return;await oj1({threadId:A,messageId:Q,botToken:w,logger:this.logger})}});subscriptionRouter=new ym0({getSubscriptions:()=>this.discordSubscriptions,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:rj1,logger:this.logger});chatInputBuilder=new Em0({getUploadStore:()=>this.context?.uploads.scoped(Vd()),getThreadIdParts:LG,logger:this.logger});gatewayLoop;discordApp;discordSubscriptions;constructor(A={}){super("chat",sj1,A,TT0);this.gatewayLoop=new rT0({getApp:()=>this.discordApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.discordApp=new oT0({discord:this.config.adapters.discord,getUploadStore:()=>this.context?.uploads.scoped(Vd()),buildApp:(Q)=>ij1({userName:this.config.userName,discord:this.config.adapters.discord,gatewayLoop:this.gatewayLoop,runtimeState:Q})}),this.pendingApprovals=new Xm({loadMessages:async(Q)=>{return await this.context?.conversations.getMessages(Q,{limit:50})??[]},onRestoreError:(Q,w)=>{this.logger.debug("Failed to load pending chat approvals",{error:Q,conversationId:w})}}),this.uploadContinuity=new Dm({sourceKind:"discord-chat-upload",loadMessages:async(Q)=>{return await this.context?.conversations.getMessages(Q,{limit:50})??[]},restoreAttachment:async(Q)=>{let w=this.context?.uploads.scoped(Vd());if(!w)throw Error("Chat upload store unavailable");let B=await w.read(Q);return dj1(B.record.filename,B.record.mediaType,B.content,B.record.ref)},onLoadError:(Q,w)=>{this.logger.debug("Failed to load prior chat uploads",{error:Q,conversationId:w})},onRestoreError:(Q,w)=>{this.logger.debug("Failed to restore prior chat upload",{error:Q,uploadId:w})}})}async onRegister(A){await super.onRegister(A),this.discordSubscriptions=gm0(A.runtimeState),this.registerChatHandlers(this.discordApp.build(A.runtimeState))}getWebRoutes(){return this.discordApp.getWebRoutes()}createDaemon(){if(!this.config.adapters.discord)return;return{start:async()=>{await this.discordApp.initialize(),this.gatewayLoop.start()},stop:async()=>{await this.gatewayLoop.stop(),this.threadRegistry.clear(),this.uploadContinuity.clear(),this.toolStatusMessenger.clear(),await this.discordApp.shutdown()},healthCheck:async()=>({status:this.gatewayLoop.isRunning()?"healthy":"error",message:this.gatewayLoop.isRunning()?"Chat gateway loop running":"Chat gateway loop stopped",lastCheck:new Date})}}sendMessageToChannel({channelId:A,message:Q}){let w=this.threadRegistry.get(A);if(!w)return;let B=this.toDiscordCardOutput(Q);if(B){w.post(B).catch(($)=>this.logger.error("Failed to send chat message",{error:$,channelId:A}));return}if(typeof Q!=="string")return;for(let $ of Yd(A,Q))w.post($).catch((f)=>this.logger.error("Failed to send chat message",{error:f,channelId:A}))}async sendMessageWithId({channelId:A,message:Q}){let w=this.threadRegistry.get(A);if(!w)return;let B=this.toDiscordCardOutput(Q);if(B){let f=await w.post(B);return this.threadRegistry.trackMessage(w.id,f),f.id}if(typeof Q!=="string")return;let $;for(let f of Yd(A,Q))$=await w.post(f),this.threadRegistry.trackMessage(w.id,$);return $?.id}async editMessage({channelId:A,messageId:Q,newMessage:w}){let B=this.threadRegistry.getMessage(A,Q);if(!B)return!1;try{let $=await B.edit(this.toDiscordCardOutput(w)??(typeof w==="string"?w:""));if(A)this.threadRegistry.trackMessage(A,$);return!0}catch{return!1}}supportsMessageEditing(){return!0}toDiscordCardOutput(A){let Q=AyQ.safeParse(A);if(!Q.success)return;let{card:w,fallbackText:B}=Q.data;if(B===void 0)return{card:w};return{card:w,fallbackText:B}}formatProgressOutput(A){return lT0(A)}formatCompletionOutput(A){return lT0(A)}async handleProgressEvent(A,Q){let w=A.metadata.interfaceType;if(w&&w!==this.id){if(!this.isEnabledPlatform(w))return;let B={...A,metadata:{...A.metadata,interfaceType:this.id}};await super.handleProgressEvent(B,B.metadata);return}await super.handleProgressEvent(A,Q)}async handleToolActivityEvent(A){if(A.interfaceType===this.id){await super.handleToolActivityEvent(A);return}if(!this.isEnabledPlatform(A.interfaceType))return;await super.handleToolActivityEvent({...A,interfaceType:this.id})}async handleToolStatusUpdate(A){if(A.interfaceType!==this.id||!A.channelId)return;await this.toolStatusMessenger.handle(A)}isEnabledPlatform(A){return Lz1(A,Boolean(this.config.adapters.discord))}registerChatHandlers(A){if(A.onDirectMessage(async(Q,w,B,$)=>{await this.handleRoutedMessage(Q,w,$)}),A.onNewMention(async(Q,w,B)=>{let $=this.getPlatformConfig(Q);if($&&Tm0(Q,w,$)&&!Q.isDM&&$.useThreads)await this.subscriptionRouter.subscribeOwnedThread(Q,w);await this.handleRoutedMessage(Q,w,B)}),A.onSubscribedMessage(async(Q,w,B)=>{if(!await this.subscriptionRouter.shouldRouteSubscribedMessage(Q,w))return;await this.handleRoutedMessage(Q,w,B)}),this.config.adapters.discord&&!this.config.adapters.discord.requireMention)A.onNewMessage(agQ,async(Q,w,B)=>{await this.handleRoutedMessage(Q,w,B)});A.onNewMessage(sgQ,async(Q,w)=>{await this.handlePassiveUrlCapture(Q,w)}),A.onAction([W50,uT0],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction(cT0,async(Q)=>{await this.handlePromptAction(Q)})}async handlePromptAction(A){if(!this.context||!A.thread||!A.value)return;let Q=A.adapter.name;if(!this.isEnabledPlatform(Q))return;let w=A.thread;if(!Sm0(w,Q,this.config.adapters.discord))return;let B=this.promptActions.get(A.value);if(B?.threadId!==w.id){await w.post(this.formatNoticePayload("That suggested action is no longer available.","Action unavailable"));return}this.promptActions.consume(A.value);let $=LG(w.id),f=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:$.channelId??w.channelId,isBot:Boolean(A.user.isBot)}),Y=this.getConversationId(Q,w.id),X=w.id;await this.runAgentTurn({thread:w,channelId:X,logLabel:"Error handling chat prompt action",body:async()=>{if(!this.context)return;let W=await this.context.agent.chat(B.prompt,Y,{userPermissionLevel:f,interfaceType:Q,channelId:X,channelName:_C(w),...this.buildActionEventMetadata(Q,w,A)});await this.renderAgentResponse({thread:w,channelId:X,conversationId:Y,response:W,userPermissionLevel:f})}})}async handleApprovalAction(A){if(!this.context||!A.thread||!A.value)return;let Q=A.adapter.name;if(!this.isEnabledPlatform(Q))return;let w=this.getConversationId(Q,A.thread.id);if(!(await this.getPendingApprovalIds(w)).has(A.value)){await A.thread.post(this.formatNoticePayload("That approval is no longer pending."));return}let $=A.thread;if(!Sm0($,Q,this.config.adapters.discord))return;let f=LG($.id),Y=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:f.channelId??$.channelId,isBot:Boolean(A.user.isBot)});await this.confirmApproval({thread:$,conversationId:w,approvalId:A.value,confirmed:A.actionId===W50,userPermissionLevel:Y,metadata:this.buildActionEventMetadata(Q,$,A)})}async handleRoutedMessage(A,Q,w){if(!this.context)return;let B=this.getPlatform(A);if(B!=="discord")return;let $=this.getPlatformConfig(A);if(!$)return;if(!Tm0(A,Q,$))return;await this.routeToAgent(B,A,Q,w)}async runAgentTurn(A){this.startProcessingInput(A.channelId);try{if(this.getPlatformConfig(A.thread)?.showTypingIndicator)await A.thread.startTyping().catch((Q)=>this.logger.debug("Typing indicator failed",{error:Q,channelId:A.channelId}));await A.body()}catch(Q){this.logger.error(A.logLabel,{error:Q,channelId:A.channelId}),await this.postTurnError(A.thread,A.channelId,Q)}finally{this.endProcessingInput()}}async postTurnError(A,Q,w){let B=this.formatErrorPayload(w),$=this.toDiscordCardOutput(B);if($){await A.post($);return}let f=typeof B==="string"?B:"Message failed.";for(let Y of Yd(Q,f))await A.post(Y)}async routeToAgent(A,Q,w,B){if(!this.context)return;this.threadRegistry.set(Q);let $=this.getConversationId(A,Q.id),f=Q.id,Y=mm0(Q,w),X=this.context.permissions.getUserLevel(A,w.author.userId,Y),W=await this.chatInputBuilder.build(A,Q,w,X),H=[...W.attachments];if(await this.attachPriorUploads($,W,X),await this.postUploadNotices(Q,W.notices),!W.message&&W.attachments.length===0)return;this.rememberUploadAttachments($,H),await this.runAgentTurn({thread:Q,channelId:f,logLabel:"Error handling chat message",body:async()=>{if(!this.context)return;let K=await this.getPendingApprovalIds($);if(K.size>0){if(await this.handleConfirmationResponse(W.message,$,Q,K,X,this.buildUserMessageMetadata(A,Q,w)))return}let U=this.buildCoalescedAgentInput(W.message,B),D=await this.context.agent.chat(U.message,$,{userPermissionLevel:X,interfaceType:A,channelId:f,channelName:_C(Q),...this.buildUserMessageMetadata(A,Q,w,U.metadata),...W.attachments.length>0?{attachments:W.attachments}:{}});await this.renderAgentResponse({thread:Q,channelId:f,conversationId:$,response:D,userPermissionLevel:X})}})}async renderAgentResponse(A){if(A.confirmation)this.syncPendingConfirmationsFromResponse(A.conversationId,A.response,A.confirmation.approvalId);else this.rememberPendingConfirmationsFromResponse(A.conversationId,A.response);await this.handleAgentResponseToolStatuses(A.response,A.conversationId);let Q=await this.artifactDelivery.resolve(A.response.cards,A.userPermissionLevel),w=Lk(A.response,{deniedCardIds:Q.deniedCardIds});if(A.confirmation)await this.approvalCards.resolve(A.conversationId,A.confirmation.approvalId,A.confirmation.confirmed);let B=A.confirmation?this.formatConfirmationResponsePayload(A.response,A.confirmation.confirmed,this.getRemainingApprovalHelp(A.conversationId,A.response),Q.deniedCardIds):this.formatAgentResponseText(w,Q.deniedCardIds),$=await this.sendAgentResponseWithFiles({thread:A.thread,channelId:A.channelId,message:B,files:Q.files}),f=await this.sendArtifactCards(A.thread,w);await this.sendSupplementalCards(A.thread,w);let Y=w.directives.find((W)=>W.kind==="approvals");await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,Y?.confirmations);let X=f??$;if(X)for(let W of w.jobIds)this.trackAgentResponseForJob(W,X,A.channelId)}rememberPendingConfirmationsFromResponse(A,Q){this.pendingApprovals.rememberFromResponse(A,Q)}async getPendingApprovalIds(A){return this.pendingApprovals.getApprovalIds(A)}async handleConfirmationResponse(A,Q,w,B,$,f){if(!Bm(A,B))return!1;let Y=IA0({message:A,approvalIds:B});if(Y.kind==="not-confirmation")return this.pendingApprovals.deleteConversation(Q),await w.post(this.formatNoticePayload("No pending approval to resolve.")),!0;if(Y.kind==="notice")return await w.post(this.formatNoticePayload(Y.message)),!0;return await this.confirmApproval({thread:w,conversationId:Q,approvalId:Y.approvalId,confirmed:Y.confirmed,userPermissionLevel:$,...f?{metadata:f}:{}}),!0}async confirmApproval(A){let Q=await this.context?.agent.confirmPendingAction(A.conversationId,A.confirmed,A.approvalId,{userPermissionLevel:A.userPermissionLevel,interfaceType:"discord",channelId:A.thread.id,channelName:_C(A.thread),...A.metadata});if(this.removePendingApproval(A.conversationId,A.approvalId),!Q)return;await this.renderAgentResponse({thread:A.thread,channelId:A.thread.id,conversationId:A.conversationId,response:Q,userPermissionLevel:A.userPermissionLevel,confirmation:{approvalId:A.approvalId,confirmed:A.confirmed}})}formatNoticePayload(A,Q="Approval notice"){return{card:{type:"card",title:Q,children:[{type:"text",content:A}]},fallbackText:A}}formatErrorPayload(A){let Q=A instanceof Error?A.message:"Unknown error";return{card:{type:"card",title:"Message failed",children:[{type:"text",content:Q}]},fallbackText:`Message failed: ${Q}`}}formatAgentResponseText(A,Q){return A.directives.flatMap((w)=>{if(w.kind==="text")return[w.text];if(w.kind==="denied-artifact")return[this.cardBuilder.formatStructuredCard(w.card,Q)];return[]}).filter((w)=>w.trim().length>0).join(`
2373
2373
 
2374
2374
  `)}formatConfirmationResponsePayload(A,Q,w,B){let $=MA0({response:A,confirmed:Q,remainingApprovalHelp:w,deniedCardIds:B,formatCard:(f)=>this.cardBuilder.formatStructuredCard(f,B),formatPendingConfirmationHelp:fx});return{card:{type:"card",title:jA0($.variant),children:$.parts.map((f)=>({type:"text",content:f}))},fallbackText:$.parts.join(`
2375
2375
 
@@ -2441,7 +2441,7 @@ ${oS0(A)}
2441
2441
  <p>Once built, this page will be replaced with your actual website.</p>
2442
2442
  </div>
2443
2443
  </body>
2444
- </html>`;var hP1={name:"@brains/webserver",version:"0.2.0-alpha.142",dependencies:{"@brains/plugins":"workspace:*","@hono/bun-compress":"^0.1.1",hono:"^4.12.25"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/messaging-service":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class mJ extends ND{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",hP1,A,$u0)}async onRegister(A){if(this.siteUrl=A.siteUrl,this.previewUrl=A.previewUrl,this.siteUrl)A.endpoints.register({label:"Site",url:this.siteUrl,priority:10}),A.interactions.register({id:"site",label:"Public site",description:"Visit the published public site for this brain.",href:this.siteUrl,kind:"human",priority:10});if(this.config.enablePreview&&this.previewUrl)A.endpoints.register({label:"Preview",url:this.previewUrl,priority:20,visibility:"anchor"}),A.interactions.register({id:"preview",label:"Preview site",description:"Open the private preview build.",href:this.previewUrl,kind:"admin",priority:20,visibility:"anchor"});this.serverManager=new E50({logger:A.logger,productionDistDir:this.config.productionDistDir,sharedImagesDir:this.config.sharedImagesDir,productionPort:this.config.productionPort,...this.config.enablePreview&&this.config.previewDistDir&&{previewDistDir:this.config.previewDistDir},...this.config.enablePreview&&this.config.previewPort&&{previewPort:this.config.previewPort},getHealthData:()=>A.appInfo(),getWebRoutes:()=>A.webRoutes.getRoutes(),getApiRoutes:()=>A.apiRoutes.getRoutes(),messageBus:A.apiRoutes.getMessageBus()})}getServerManager(){if(!this.serverManager)throw Error("ServerManager not initialized \u2014 onRegister not called");return this.serverManager}requiresDaemonStartup(){return!0}createDaemon(){return{start:async()=>{await this.ensureDistDirectories(),await this.getServerManager().start()},stop:async()=>{await this.serverManager?.stop()},healthCheck:async()=>{let A=this.serverManager?.getStatus(),Q=A?.running??!1,w=this.siteUrl??A?.productionUrl??`http://localhost:${this.config.productionPort}`,B=this.previewUrl??A?.previewUrl??`http://localhost:${this.config.previewPort}`,$=[];if(Q){if($.push(`Production: ${w}`),A?.previewUrl)$.push(`Preview: ${B}`)}return{status:Q?"healthy":"error",message:Q?$.join(", "):"Webserver not running",lastCheck:new Date,details:{preview:!!A?.previewUrl,production:Q,previewUrl:A?.previewUrl?B:void 0,productionUrl:Q?w:void 0}}}}}async handleProgressEvent(A,Q){}async ensureDistDirectories(){let{mkdir:A,writeFile:Q}=await import("fs/promises");if(this.config.enablePreview&&this.config.previewDistDir&&!CP1(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(gP1(this.config.previewDistDir,"index.html"),fu0),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!CP1(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(gP1(this.config.productionDistDir,"index.html"),fu0),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}g6();wA();N0();Tk();var yP1={name:"@brains/web-chat",version:"0.2.0-alpha.142",description:"Web chat interface for Brains",dependencies:{"@ai-sdk/react":"^3.0.208","@brains/auth-service":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@streamdown/cjk":"^1.0.3","@streamdown/code":"^1.1.1","@streamdown/math":"^1.0.2","@streamdown/mermaid":"^1.0.2",ai:"^6.0.206","class-variance-authority":"^0.7.0",cmdk:"^1.1.1","lucide-react":"^1.20.0",nanoid:"^5.0.4","radix-ui":"^1.6.0",react:"^19.2.7","react-dom":"^19.2.7",shiki:"^4.2.0",streamdown:"^2.5.0","tailwind-merge":"^3.6.0","use-stick-to-bottom":"^1.1.6"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3",typescript:"^6.0.3",vite:"^8.0.16"},exports:{".":"./src/index.ts"},files:["src","dist","package.json"],private:!0,scripts:{build:"bun scripts/build-ui.ts","build:ui":"bun scripts/build-ui.ts",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit && tsc --noEmit -p ui-react/tsconfig.json"},type:"module"};wA();async function EP1(A,Q){let w=await Q.resolvePermissionLevel(A);if(w==="public")return Q.createOperatorLoginRequiredResponse(A);let B=new URL(A.url),$=B.searchParams.get("id")?.trim();if(!$)return new Response("Missing document id",{status:400});let f=await SP1({entityType:"document",id:$,permissionLevel:w,entityService:Q.entityService});if(!f)return new Response("Document not found",{status:404});if(typeof f.content!=="string")return new Response("Document content is not a PDF",{status:415});let Y=Kz("document",f.content);if(!Y)return new Response("Document content is not a PDF",{status:415});let X=Uz(f.metadata,$,"document",Y.mimeType);return mP1({requestUrl:B,data:Y.data,mediaType:Y.mimeType,filename:X})}async function TP1(A,Q){let w=await Q.resolvePermissionLevel(A);if(w==="public")return Q.createOperatorLoginRequiredResponse(A);let B=new URL(A.url),$=B.searchParams.get("id")?.trim();if(!$)return new Response("Missing image id",{status:400});let f=await SP1({entityType:"image",id:$,permissionLevel:w,entityService:Q.entityService});if(!f)return new Response("Image not found",{status:404});if(typeof f.content!=="string")return new Response("Image content is not an image",{status:415});let Y=Kz("image",f.content);if(!Y)return new Response("Image content is not an image",{status:415});let X=Uz(f.metadata,$,"image",Y.mimeType);return mP1({requestUrl:B,data:Y.data,mediaType:Y.mimeType,filename:X})}async function SP1(A){let Q={entityType:A.entityType,id:A.id},w=await Dz({entityRef:Q,userLevel:A.permissionLevel,getEntity:(B)=>A.entityService.getEntity(B),getVisibleEntity:(B,$)=>A.entityService.getEntity({...B,visibilityScope:$})});return w.status==="visible"?w.entity:void 0}function mP1(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":gV({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}N0();wA();var Nd="upload",uP1=oO;var oyQ={namespace:"upload",refKind:Nd,routePath:"/api/chat/uploads"};function T50(){return oyQ}wA();sJ0();var cP1=xA0;var lP1=RA0;var syQ="file",ayQ=16384;async function pP1(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let w=Number(A.headers.get("content-length"));if(Number.isFinite(w)&&w>lP1+ayQ)return new Response("File upload too large",{status:400});let B;try{B=await A.formData()}catch{return new Response("Invalid multipart upload",{status:400})}let $=B.get(syQ);if(!($ instanceof File))return new Response("Missing upload file",{status:400});let f=Buffer.from(await $.arrayBuffer()),Y=qz({filename:$.name,mediaType:$.type,content:f});if(!Y.ok)return new Response(Y.message,{status:400});let X=Q.getUploadStore(),W=await X.save({filename:Y.filename,mediaType:Y.mediaType,content:f});return Response.json(X.toResponseBody(W),{status:201})}async function iP1(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let w=new URL(A.url).searchParams.get("id")?.trim();if(!w)return new Response("Missing upload id",{status:400});let B=await rP1(w,Q.getUploadStore());if(B instanceof Response)return B;let{record:$,content:f}=B,Y=oP1($,f);if(Y instanceof Response)return Y;let X=new URL(A.url).searchParams.has("download")?"attachment":"inline",W=new Uint8Array(f).buffer;return new Response(W,{headers:{"Content-Type":$.mediaType,"Content-Length":String(f.byteLength),"Content-Disposition":gV({disposition:X,filename:$.filename})}})}function dP1(A){let Q=zz(A.filename??cP1),w=eyQ(A.url);if(!w)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let B=qz({filename:Q,mediaType:A.mediaType,content:w.buffer});if(!B.ok)return new Response(B.message,{status:400});return sP1(B,w.buffer)}async function nP1(A,Q){let w=await rP1(A,Q);if(w instanceof Response)return w;let{record:B,content:$}=w,f=oP1(B,$);if(f instanceof Response)return f;return sP1(f,$,{kind:Nd,id:A})}async function rP1(A,Q){try{return await Q.read(A)}catch(w){if(w instanceof jD)return tyQ(w);throw w}}function oP1(A,Q){let w=qz({filename:A.filename,mediaType:A.mediaType,content:Q});if(!w.ok)return new Response(w.message,{status:400});return w}function sP1(A,Q,w){if(A.kind==="text")return{kind:"text",filename:A.filename,mediaType:A.mediaType,content:A.text,sizeBytes:A.sizeBytes,...w!==void 0?{source:w}:{}};return{kind:"file",filename:A.filename,mediaType:A.mediaType,data:new Uint8Array(Q),sizeBytes:A.sizeBytes,...w!==void 0?{source:w}:{}}}function tyQ(A){switch(A.code){case"invalid_ref":return new Response("Invalid upload ref",{status:400});case"invalid_metadata":return new Response("Invalid upload metadata",{status:500});case"not_found":return new Response("Upload not found",{status:404})}}function eyQ(A){let Q=/^data:[^,]*,(.*)$/s.exec(A);if(!Q)return null;let B=A.slice(5,A.indexOf(",")).split(";").some(($)=>$.toLowerCase()==="base64");try{let $=B?Buffer.from(Q[1]??"","base64"):Buffer.from(decodeURIComponent(Q[1]??""),"utf8");return{buffer:$,byteLength:$.byteLength}}catch{return null}}var AEQ=Z.object({type:Z.literal("text"),text:Z.string()}),QEQ=Z.object({type:Z.literal("file"),mediaType:Z.string().optional(),filename:Z.string().optional(),url:Z.string()}),wEQ=Z.looseObject({state:Z.literal("approval-responded"),approval:Z.object({id:Z.string(),approved:Z.boolean()})}),BEQ=Z.object({id:Z.string().optional(),role:Z.string(),parts:Z.array(Z.unknown()).optional(),content:Z.string().optional()}),aP1=Z.object({id:Z.string().optional(),messages:Z.array(BEQ).min(1),trigger:Z.string().optional()}),$EQ=Z.object({kind:Z.literal(Nd),id:Z.string().regex(uP1)}),fEQ=Z.object({type:Z.literal("data-upload"),data:Z.object({ref:$EQ})});async function tP1(A,Q){let w=YEQ(A);if(!w)return{message:"",attachments:[]};let B=[],$=[];for(let Y of w.parts??[]){let X=AEQ.safeParse(Y);if(X.success){if(X.data.text.length>0)B.push(X.data.text);continue}let W=QEQ.safeParse(Y);if(W.success){let K=dP1(W.data);if(K instanceof Response)return K;$.push(K);continue}let H=fEQ.safeParse(Y);if(H.success){let K=await nP1(H.data.data.ref.id,Q.uploadStore);if(K instanceof Response)return K;$.push(K);continue}if(XEQ(Y)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:B.length>0?B.join(`
2444
+ </html>`;var hP1={name:"@brains/webserver",version:"0.2.0-alpha.143",dependencies:{"@brains/plugins":"workspace:*","@hono/bun-compress":"^0.1.1",hono:"^4.12.25"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/messaging-service":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class mJ extends ND{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",hP1,A,$u0)}async onRegister(A){if(this.siteUrl=A.siteUrl,this.previewUrl=A.previewUrl,this.siteUrl)A.endpoints.register({label:"Site",url:this.siteUrl,priority:10}),A.interactions.register({id:"site",label:"Public site",description:"Visit the published public site for this brain.",href:this.siteUrl,kind:"human",priority:10});if(this.config.enablePreview&&this.previewUrl)A.endpoints.register({label:"Preview",url:this.previewUrl,priority:20,visibility:"anchor"}),A.interactions.register({id:"preview",label:"Preview site",description:"Open the private preview build.",href:this.previewUrl,kind:"admin",priority:20,visibility:"anchor"});this.serverManager=new E50({logger:A.logger,productionDistDir:this.config.productionDistDir,sharedImagesDir:this.config.sharedImagesDir,productionPort:this.config.productionPort,...this.config.enablePreview&&this.config.previewDistDir&&{previewDistDir:this.config.previewDistDir},...this.config.enablePreview&&this.config.previewPort&&{previewPort:this.config.previewPort},getHealthData:()=>A.appInfo(),getWebRoutes:()=>A.webRoutes.getRoutes(),getApiRoutes:()=>A.apiRoutes.getRoutes(),messageBus:A.apiRoutes.getMessageBus()})}getServerManager(){if(!this.serverManager)throw Error("ServerManager not initialized \u2014 onRegister not called");return this.serverManager}requiresDaemonStartup(){return!0}createDaemon(){return{start:async()=>{await this.ensureDistDirectories(),await this.getServerManager().start()},stop:async()=>{await this.serverManager?.stop()},healthCheck:async()=>{let A=this.serverManager?.getStatus(),Q=A?.running??!1,w=this.siteUrl??A?.productionUrl??`http://localhost:${this.config.productionPort}`,B=this.previewUrl??A?.previewUrl??`http://localhost:${this.config.previewPort}`,$=[];if(Q){if($.push(`Production: ${w}`),A?.previewUrl)$.push(`Preview: ${B}`)}return{status:Q?"healthy":"error",message:Q?$.join(", "):"Webserver not running",lastCheck:new Date,details:{preview:!!A?.previewUrl,production:Q,previewUrl:A?.previewUrl?B:void 0,productionUrl:Q?w:void 0}}}}}async handleProgressEvent(A,Q){}async ensureDistDirectories(){let{mkdir:A,writeFile:Q}=await import("fs/promises");if(this.config.enablePreview&&this.config.previewDistDir&&!CP1(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(gP1(this.config.previewDistDir,"index.html"),fu0),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!CP1(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(gP1(this.config.productionDistDir,"index.html"),fu0),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}g6();wA();N0();Tk();var yP1={name:"@brains/web-chat",version:"0.2.0-alpha.143",description:"Web chat interface for Brains",dependencies:{"@ai-sdk/react":"^3.0.208","@brains/auth-service":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@streamdown/cjk":"^1.0.3","@streamdown/code":"^1.1.1","@streamdown/math":"^1.0.2","@streamdown/mermaid":"^1.0.2",ai:"^6.0.206","class-variance-authority":"^0.7.0",cmdk:"^1.1.1","lucide-react":"^1.20.0",nanoid:"^5.0.4","radix-ui":"^1.6.0",react:"^19.2.7","react-dom":"^19.2.7",shiki:"^4.2.0",streamdown:"^2.5.0","tailwind-merge":"^3.6.0","use-stick-to-bottom":"^1.1.6"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3",typescript:"^6.0.3",vite:"^8.0.16"},exports:{".":"./src/index.ts"},files:["src","dist","package.json"],private:!0,scripts:{build:"bun scripts/build-ui.ts","build:ui":"bun scripts/build-ui.ts",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit && tsc --noEmit -p ui-react/tsconfig.json"},type:"module"};wA();async function EP1(A,Q){let w=await Q.resolvePermissionLevel(A);if(w==="public")return Q.createOperatorLoginRequiredResponse(A);let B=new URL(A.url),$=B.searchParams.get("id")?.trim();if(!$)return new Response("Missing document id",{status:400});let f=await SP1({entityType:"document",id:$,permissionLevel:w,entityService:Q.entityService});if(!f)return new Response("Document not found",{status:404});if(typeof f.content!=="string")return new Response("Document content is not a PDF",{status:415});let Y=Kz("document",f.content);if(!Y)return new Response("Document content is not a PDF",{status:415});let X=Uz(f.metadata,$,"document",Y.mimeType);return mP1({requestUrl:B,data:Y.data,mediaType:Y.mimeType,filename:X})}async function TP1(A,Q){let w=await Q.resolvePermissionLevel(A);if(w==="public")return Q.createOperatorLoginRequiredResponse(A);let B=new URL(A.url),$=B.searchParams.get("id")?.trim();if(!$)return new Response("Missing image id",{status:400});let f=await SP1({entityType:"image",id:$,permissionLevel:w,entityService:Q.entityService});if(!f)return new Response("Image not found",{status:404});if(typeof f.content!=="string")return new Response("Image content is not an image",{status:415});let Y=Kz("image",f.content);if(!Y)return new Response("Image content is not an image",{status:415});let X=Uz(f.metadata,$,"image",Y.mimeType);return mP1({requestUrl:B,data:Y.data,mediaType:Y.mimeType,filename:X})}async function SP1(A){let Q={entityType:A.entityType,id:A.id},w=await Dz({entityRef:Q,userLevel:A.permissionLevel,getEntity:(B)=>A.entityService.getEntity(B),getVisibleEntity:(B,$)=>A.entityService.getEntity({...B,visibilityScope:$})});return w.status==="visible"?w.entity:void 0}function mP1(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":gV({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}N0();wA();var Nd="upload",uP1=oO;var oyQ={namespace:"upload",refKind:Nd,routePath:"/api/chat/uploads"};function T50(){return oyQ}wA();sJ0();var cP1=xA0;var lP1=RA0;var syQ="file",ayQ=16384;async function pP1(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let w=Number(A.headers.get("content-length"));if(Number.isFinite(w)&&w>lP1+ayQ)return new Response("File upload too large",{status:400});let B;try{B=await A.formData()}catch{return new Response("Invalid multipart upload",{status:400})}let $=B.get(syQ);if(!($ instanceof File))return new Response("Missing upload file",{status:400});let f=Buffer.from(await $.arrayBuffer()),Y=qz({filename:$.name,mediaType:$.type,content:f});if(!Y.ok)return new Response(Y.message,{status:400});let X=Q.getUploadStore(),W=await X.save({filename:Y.filename,mediaType:Y.mediaType,content:f});return Response.json(X.toResponseBody(W),{status:201})}async function iP1(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let w=new URL(A.url).searchParams.get("id")?.trim();if(!w)return new Response("Missing upload id",{status:400});let B=await rP1(w,Q.getUploadStore());if(B instanceof Response)return B;let{record:$,content:f}=B,Y=oP1($,f);if(Y instanceof Response)return Y;let X=new URL(A.url).searchParams.has("download")?"attachment":"inline",W=new Uint8Array(f).buffer;return new Response(W,{headers:{"Content-Type":$.mediaType,"Content-Length":String(f.byteLength),"Content-Disposition":gV({disposition:X,filename:$.filename})}})}function dP1(A){let Q=zz(A.filename??cP1),w=eyQ(A.url);if(!w)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let B=qz({filename:Q,mediaType:A.mediaType,content:w.buffer});if(!B.ok)return new Response(B.message,{status:400});return sP1(B,w.buffer)}async function nP1(A,Q){let w=await rP1(A,Q);if(w instanceof Response)return w;let{record:B,content:$}=w,f=oP1(B,$);if(f instanceof Response)return f;return sP1(f,$,{kind:Nd,id:A})}async function rP1(A,Q){try{return await Q.read(A)}catch(w){if(w instanceof jD)return tyQ(w);throw w}}function oP1(A,Q){let w=qz({filename:A.filename,mediaType:A.mediaType,content:Q});if(!w.ok)return new Response(w.message,{status:400});return w}function sP1(A,Q,w){if(A.kind==="text")return{kind:"text",filename:A.filename,mediaType:A.mediaType,content:A.text,sizeBytes:A.sizeBytes,...w!==void 0?{source:w}:{}};return{kind:"file",filename:A.filename,mediaType:A.mediaType,data:new Uint8Array(Q),sizeBytes:A.sizeBytes,...w!==void 0?{source:w}:{}}}function tyQ(A){switch(A.code){case"invalid_ref":return new Response("Invalid upload ref",{status:400});case"invalid_metadata":return new Response("Invalid upload metadata",{status:500});case"not_found":return new Response("Upload not found",{status:404})}}function eyQ(A){let Q=/^data:[^,]*,(.*)$/s.exec(A);if(!Q)return null;let B=A.slice(5,A.indexOf(",")).split(";").some(($)=>$.toLowerCase()==="base64");try{let $=B?Buffer.from(Q[1]??"","base64"):Buffer.from(decodeURIComponent(Q[1]??""),"utf8");return{buffer:$,byteLength:$.byteLength}}catch{return null}}var AEQ=Z.object({type:Z.literal("text"),text:Z.string()}),QEQ=Z.object({type:Z.literal("file"),mediaType:Z.string().optional(),filename:Z.string().optional(),url:Z.string()}),wEQ=Z.looseObject({state:Z.literal("approval-responded"),approval:Z.object({id:Z.string(),approved:Z.boolean()})}),BEQ=Z.object({id:Z.string().optional(),role:Z.string(),parts:Z.array(Z.unknown()).optional(),content:Z.string().optional()}),aP1=Z.object({id:Z.string().optional(),messages:Z.array(BEQ).min(1),trigger:Z.string().optional()}),$EQ=Z.object({kind:Z.literal(Nd),id:Z.string().regex(uP1)}),fEQ=Z.object({type:Z.literal("data-upload"),data:Z.object({ref:$EQ})});async function tP1(A,Q){let w=YEQ(A);if(!w)return{message:"",attachments:[]};let B=[],$=[];for(let Y of w.parts??[]){let X=AEQ.safeParse(Y);if(X.success){if(X.data.text.length>0)B.push(X.data.text);continue}let W=QEQ.safeParse(Y);if(W.success){let K=dP1(W.data);if(K instanceof Response)return K;$.push(K);continue}let H=fEQ.safeParse(Y);if(H.success){let K=await nP1(H.data.data.ref.id,Q.uploadStore);if(K instanceof Response)return K;$.push(K);continue}if(XEQ(Y)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:B.length>0?B.join(`
2445
2445
 
2446
2446
  `):w.content??"",attachments:$,...w.id?{messageId:w.id}:{}}}function eP1(A){let Q=A.messages.at(-1);if(!Q||Q.role==="user")return[];return(Q.parts??[]).map((w)=>wEQ.safeParse(w)).filter((w)=>w.success).map((w)=>w.data.approval)}function YEQ(A){for(let Q=A.messages.length-1;Q>=0;Q-=1){let w=A.messages[Q];if(w?.role==="user")return w}return}function XEQ(A){if(typeof A!=="object"||A===null||!("type"in A))return;let Q=A.type;return typeof Q==="string"?Q:void 0}wA();var ZEQ=/\n{0,2}\[Entities affected this turn: [\s\S]*? Reference these IDs directly in follow-ups instead of searching for them\.\]\s*$/;function S50(A){return A.replace(ZEQ,"").trimEnd()}wA();function AM1(A,Q,w){A.write({type:"text-start",id:Q}),A.write({type:"text-delta",id:Q,delta:w}),A.write({type:"text-end",id:Q})}function Yu0(A,Q){let w=Q.directives.flatMap((B)=>{switch(B.kind){case"artifact":case"supplemental":return[B.card];case"approvals":return B.cards;default:return[]}});for(let B of w){let $=EA0(B);if($.kind==="attachment"){A.write({type:"data-attachment",id:$.id,data:$});continue}if($.kind==="sources"){A.write({type:"data-sources",id:$.id,data:$});continue}if($.kind==="actions"){A.write({type:"data-actions",id:$.id,data:$});continue}let f=$.toolCallId??$.id,Y=$.input??{};switch(A.write({type:"tool-input-available",toolCallId:f,toolName:$.toolName,input:Y,dynamic:!0,title:$.preview?`${$.summary}
2447
2447
 
@@ -4745,7 +4745,7 @@ details.web-chat-data-part[open] > summary > .web-chat-data-part-chevron {
4745
4745
 
4746
4746
  `);$=Y.pop()??"";for(let X of Y){let W=X.split(`
4747
4747
  `).find((I)=>I.startsWith("data: "));if(!W)continue;let H;try{let I=sEQ.safeParse(JSON.parse(W.slice(6)));if(!I.success)continue;H=I.data}catch{return w.cancel().catch(()=>{}),{success:!1,error:"Malformed SSE event from remote agent"}}let K=H.result;if(!K?.final)continue;w.cancel().catch(()=>{});let U=K.status,D=U?.state??"unknown",b=(U?.message?.parts??[]).filter((I)=>I.kind==="text"&&typeof I.text==="string").map((I)=>I.text).join(`
4748
- `)||"No response text";return{success:!0,data:{state:D,response:b}}}f=await EM1(w,Q)}return{success:!1,error:"Stream ended without a terminal event"}}class jd extends Error{timeoutMs;constructor(A){super(`request timed out after ${A}ms`);this.timeoutMs=A,this.name="A2ARequestTimeoutError"}}class Pd extends Error{timeoutMs;constructor(A){super(`A2A stream stalled waiting for final event after ${A}ms`);this.timeoutMs=A,this.name="A2AStreamIdleTimeoutError"}}async function fTQ(A,Q,w,B){let $=new AbortController,f;try{return await Promise.race([A(Q,{...w,signal:$.signal}),new Promise((Y,X)=>{f=setTimeout(()=>{$.abort(),X(new jd(B))},B)})])}catch(Y){if(Y instanceof jd)throw Y;if($.signal.aborted)throw new jd(B);throw Y}finally{if(f)clearTimeout(f)}}async function EM1(A,Q){let w;try{return await Promise.race([A.read(),new Promise((B,$)=>{w=setTimeout(()=>$(new Pd(Q)),Q)})])}catch(B){if(B instanceof Pd)A.cancel().catch(()=>{});throw B}finally{if(w)clearTimeout(w)}}function YTQ(A){if(A instanceof jd||A instanceof Pd)return!1;return A instanceof Error}function bu0(A,Q){let w=Q>1?` after ${Q} attempts`:"";if(A instanceof Pd)return`${A.message}${w}`;let B=A instanceof Error?A.message:"Unknown network error";return`Failed to reach remote agent${w}: ${B}`}function SM1(A={}){let Q=A.fetch??globalThis.fetch,w={requestTimeoutMs:A.requestTimeoutMs??aEQ,streamIdleTimeoutMs:A.streamIdleTimeoutMs??tEQ,maxNetworkAttempts:A.maxNetworkAttempts??eEQ};return{name:"agent_call",description:"Call a remote A2A agent by exact domain-like target or saved local agent id. Use this when the user asks what an exact domain-like agent id has to say, asks to talk/message/contact that id, or asks that agent for its skills/capabilities. For saved agents, the tool enforces approved/not-archived status before network contact. For unsaved exact domains, the tool verifies the A2A Agent Card over HTTPS and may perform a one-shot call without saving; it returns a typed save/connect candidate after success. Use bare ids such as yeehaa.io, docs.rizom.ai, or save-it-regression.example; .example test domains are exact domain-like ids. If the user provides an HTTPS URL such as https://docs.rizom.ai/a2a, pass only the hostname docs.rizom.ai. For follow-ups to a prior exact-id call, call again with the same id so the tool revalidates current state. Never pass a full URL, a display name like Brain, or a non-HTTPS URL. If the user gives an ambiguous name, ask them to connect/save or clarify the agent first.",inputSchema:ATQ,visibility:"trusted",sideEffects:"external",handler:async(B)=>{let $=QTQ.safeParse(B);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};let{agent:f,message:Y}=$.data,X=wTQ(f);if(!X.ok)return{success:!1,error:X.error};let{agentId:W}=X;if(!A.entityService)return{success:!1,error:"Agent directory is unavailable. Add the agent first, then try again."};let H=await A.entityService.getEntity({entityType:"agent",id:W,visibilityScope:T9("agent_call tool is anchor-only and resolves saved remote agents at any visibility")});if(!H){if(!BTQ(W))return{success:!1,error:`Agent ${f} is not an exact domain-like id and is not saved. Connect or clarify the agent first.`,code:"agent_not_saved"};let b=`https://${W}`,I=await gM1(b,Q);if(!I)return{success:!1,error:`Could not verify an A2A Agent Card for ${W}. Connect/save it first if you want to add it to the directory.`,code:"agent_card_unavailable"};let V=CM1(I.url,W);if(!V.ok)return{success:!1,error:V.error};let L=await yM1(I.url,Y,Q,A.requestSigner,w);if("success"in L&&L.success===!0){let N=typeof L.data==="object"&&L.data!==null?L.data:{};return{...L,data:{...N,agentCall:{mode:"one-shot",agent:W},agentContactCandidate:{source:{kind:"url",url:X.sourceUrl??W}}}}}return L}if(H.metadata.status==="archived")return{success:!1,error:`Agent ${W} is archived and cannot be contacted until it is restored and approved.`,code:"agent_archived"};if(H.metadata.status!=="approved")return{success:!1,error:`Agent ${W} is discovered but not approved yet. Approve it first.`,code:"agent_not_approved"};let K=`https://${W}`,U=await gM1(K,Q);if(!U)return{success:!1,error:`Could not fetch Agent Card from ${K}`};let D=CM1(U.url,W);if(!D.ok)return{success:!1,error:D.error};let q=U.url;return yM1(q,Y,Q,A.requestSigner,w)}}}var Vu0={name:"@brains/a2a",version:"0.2.0-alpha.142",dependencies:{"@a2a-js/sdk":"^0.3.13","@brains/auth-service":"workspace:*","@brains/http-signatures":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",hono:"^4.12.25"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^6.0.3"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var ZTQ={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Signature, Signature-Input, Content-Digest, Date","X-Content-Type-Options":"nosniff"};class xC extends ND{agentCard;taskManager=new qu0;agentService;jwksResolver=new Gu0;app;hasWebserver=!1;constructor(A={}){if(Object.prototype.hasOwnProperty.call(A,"trustedTokens"))throw Error("trustedTokens legacy config is no longer supported");if(Object.prototype.hasOwnProperty.call(A,"outboundTokens"))throw Error("outboundTokens legacy config is no longer supported");super("a2a",Vu0,A,NM1)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,this.hasWebserver)A.endpoints.register({label:"A2A",url:"/a2a",priority:25}),A.interactions.register({id:"a2a",label:"A2A",description:"Let other agents discover and talk to this brain.",href:"/a2a",kind:"agent",priority:25}),this.logger.info("A2A interface registered",{domain:A.domain});else this.logger.info("A2A interface registered in tool-only mode",{domain:A.domain})}async onReady(A){await this.rebuildAgentCard(A)}async rebuildAgentCard(A){let Q=A.identity.get(),w=A.identity.getProfile(),B=A.tools.listForPermissionLevel("public"),$;if(A.entityService.hasEntityType("skill"))try{let f=await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}});if(f.length>0)$=f.map((Y)=>zm.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=jM1({character:Q,profile:w,version:Vu0.version,domain:A.domain,organization:this.config.organization,tools:B,skills:$,authEnabled:!1}),this.logger.debug("Agent Card rebuilt",{skills:this.agentCard.skills.length})}getAgentCard(){return this.agentCard}async resolveCaller(A,Q){let w=await LM1({method:A.method,url:A.url,headers:A.headers,body:Q},this.jwksResolver);if(w){let B=await P7()?.getA2APeerTrust(w.domain);return{permissionLevel:B?.keyFingerprint===w.keyFingerprint?B.grantedLevel:"public",callerDomain:w.domain}}return{permissionLevel:"public",callerDomain:null}}withCors(A){let Q=new Headers(A.headers);for(let[w,B]of Object.entries(ZTQ))Q.set(w,B);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}getOrCreateApp(){if(this.app)return this.app;let A=new jC;return A.get("/.well-known/agent-card.json",(Q)=>{if(!this.agentCard)return this.withCors(Q.json({error:"Agent Card not ready"},503));return this.withCors(Q.json(this.agentCard))}),A.get("/a2a",(Q)=>{return this.withCors(Q.json({error:"Use POST with JSON-RPC 2.0 requests.",agentCard:"/.well-known/agent-card.json"},405))}),A.options("/a2a",()=>this.withCors(new Response(null,{status:204}))),A.post("/a2a",async(Q)=>{if(!this.agentService)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32603,message:"Agent service not ready"},id:null},503));let w=await Q.req.text(),B;try{B=await this.resolveCaller(Q.req.raw,w)}catch{return this.withCors(Q.json({error:"Invalid HTTP signature"},401))}let $;try{$=JSON.parse(w)}catch{return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32700,message:"Parse error"},id:null}))}let f=OM1.safeParse($);if(!f.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32600,message:"Invalid request"},id:null}));if(f.data.method==="message/stream"){let X=RM1.safeParse(f.data.params??{});if(!X.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${X.error.message}`},id:f.data.id}));let W=vM1(f.data.id,X.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:B.permissionLevel,callerDomain:B.callerDomain});if("error"in W)return this.withCors(Q.json(W));let{stream:H}=W;return this.withCors(new Response(H,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let Y=await xM1(f.data,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:B.permissionLevel,callerDomain:B.callerDomain});return this.withCors(Q.json(Y))}),this.app=A,A}getWebRoutes(){if(!this.hasWebserver)return[];let A=(Q)=>Promise.resolve(this.getOrCreateApp().fetch(Q));return[{path:"/.well-known/agent-card.json",method:"GET",public:!0,handler:A},{path:"/a2a",method:"GET",public:!0,handler:A},{path:"/a2a",method:"POST",public:!0,handler:A},{path:"/a2a",method:"OPTIONS",public:!0,handler:A}]}createRequestSigner(){let A=P7();if(!A)return;return async(Q)=>{let w=await A.getA2ASigningKey();await FM1(Q,w.privateJwk,w.keyId)}}async getTools(){return[SM1({requestSigner:this.createRequestSigner(),requestTimeoutMs:this.config.requestTimeoutMs,streamIdleTimeoutMs:this.config.streamIdleTimeoutMs,maxNetworkAttempts:this.config.maxNetworkAttempts,entityService:this.getContext().entityService})]}async getInstructions(){return"## Agent-to-agent calls\n- Use `agent_call` for exact domain-like agent ids (for example `yeehaa.io`, `docs.rizom.ai`, or `save-it-regression.example`). A domain-like id is bare text with a dot and no slash/protocol; `.example` test domains are still exact domain-like ids. For saved agents, the tool validates approval before network contact. For unsaved exact domains, it verifies the Agent Card over HTTPS and may perform a one-shot call without saving.\n- Pass only an exact domain-like agent id to `agent_call`. If the user provides an HTTPS URL, pass only its hostname as the agent id (for `https://docs.rizom.ai/a2a`, pass `docs.rizom.ai`). Never pass a full URL, a non-HTTPS URL, or a display name like `Brain`.\n- If the user names an exact domain-like agent id such as `yeehaa.io`, `docs.rizom.ai`, or `refusal-followup.example`, call `agent_call` directly with that id. Do not preflight with `system_list` or `system_get`; the tool reports structured errors such as invalid Agent Card, not approved, or archived.\n- If the user asks you to ask, message, contact, hear what an exact domain-like agent id has to say, or ask that agent for its own skills/capabilities, treat that as an agent call request first and call `agent_call` in the same turn. Do not stop after listing the agent, drafting the question, searching general content locally, or reading saved agent entity metadata.\n- After `agent_call` returns within a turn, answer that turn from its response. Do **not** supplement with `system_get` (or any other read tool) on the agent entity, unless the user explicitly asks for directory/profile details about the agent itself.\n- Do not create, capture, or generate a note containing the user's question in the same turn as an agent contact request. The user asked to ask the agent, not to persist the question.\n- If `agent_call` succeeds for an unsaved one-shot domain, you may offer to save/connect that agent for future calls, but do not auto-save it.\n- If `agent_call` fails because auth, re-authentication, network, invalid Agent Card, or the remote agent is unavailable, report that failure directly. Do not say the agent was saved, connected, or may need to be saved/connected first. If useful, offer to add the agent contact using the word \"add\". Do not answer from memory, local docs, onboarding docs, or general knowledge; the requested agent was the source.\n- Each new turn that asks the same exact domain-like agent id something \u2014 including short follow-ups like \"what skills does it have\", \"and what about X\", \"tell me more\" \u2014 is a **new** contact request and needs its **own** fresh `agent_call`. Do not assume the previous turn's agent response already covers a new question, and do not substitute `system_list`/`system_get` or a no-tool answer for the fresh call. If the previous turn targeted an exact domain-like id such as `yeehaa.io`, use that same id again for the follow-up even if the previous response was a refusal or error; let `agent_call` validate the current directory state again.\n- When the user provides an HTTPS URL for an agent, use its hostname as the exact domain-like id for `agent_call`; the runtime verifies/contact over HTTPS. If the user provides a non-HTTPS URL, ask for the HTTPS agent URL or exact domain-like id instead.\n- If the user refers to an agent by name, first make sure that name resolves to exactly one saved agent id. If multiple saved agents could match, ask a concise clarification question naming the matching saved agent ids and do not call any agent yet. Never choose the first match.\n- After asking that clarification question, end the turn. Do not call `agent_call` later in the same turn.\n- If `agent_call` reports that an exact domain-like agent id cannot be verified, tell the user the agent could not be verified/contacted. Do not create a wish, reminder, todo, note, fallback task, or any new entity.\n- For non-HTTPS URLs and ambiguous display names, do not call `agent_call`; ask the user for the HTTPS agent URL, exact domain-like id, or a clarification first.\n- Use `agent_connect`, not generic entity creation, when the user explicitly asks you to add, save, or connect an agent contact.\n- If the target agent is discovered but not approved yet, do not call it and do not create a wish. Tell the user it must be approved first."}createDaemon(){return{start:async()=>{if(this.hasWebserver)this.logger.info("A2A mounted on shared webserver host");else this.logger.info("A2A running without webserver routes")},stop:async()=>{this.logger.info("A2A server stopped")}}}}wA();N0();var mM1={lexicon:1,id:"ai.rizom.brain.card",defs:{main:{type:"record",description:"Public discovery card for a Rizom brain. The operational A2A Agent Card is conventionally served at /.well-known/agent-card.json under siteUrl.",key:"literal:self",record:{type:"object",required:["siteUrl","brain","anchor","skills","model","version","createdAt"],properties:{siteUrl:{type:"string",format:"uri",description:"Public site URL. Consumers derive the A2A Agent Card URL from this base."},brain:{type:"object",description:"Brain identity described by this discovery card.",required:["did","name","role","purpose","values"],properties:{did:{type:"string",description:"Public DID for the brain identity."},name:{type:"string",maxLength:200,description:"Human-readable brain name."},role:{type:"string",maxLength:500,description:"Brain role or persona."},purpose:{type:"string",maxLength:2000,description:"Short public description of what this brain is for."},values:{type:"array",description:"Public values or principles for this brain.",items:{type:"string",maxLength:200},maxLength:50}}},anchor:{type:"object",description:"Minimal owner/operator snapshot for discovery grouping and display.",required:["did","name","kind"],properties:{did:{type:"string",description:"Public DID for the owner/operator anchor identity."},name:{type:"string",maxLength:200,description:"Human-readable anchor name."},kind:{type:"string",knownValues:["professional","team","collective"],description:"Anchor type."}}},skills:{type:"array",description:"User-facing skills this brain advertises for discovery.",items:{type:"object",required:["id","name","description"],properties:{id:{type:"string",maxLength:200},name:{type:"string",maxLength:200},description:{type:"string",maxLength:2000},tags:{type:"array",items:{type:"string"},maxLength:50},examples:{type:"array",items:{type:"string"},maxLength:20}}},maxLength:100},model:{type:"string",description:"Rizom brain model identifier."},version:{type:"string",description:"Brain runtime/model implementation version."},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var uM1={lexicon:1,id:"ai.rizom.brain.deck",defs:{main:{type:"record",description:"Public presentation deck from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},slug:{type:"string"},description:{type:"string",maxLength:2000},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},author:{type:"string"},event:{type:"string"},publishedAt:{type:"string",format:"datetime"},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var cM1={lexicon:1,id:"ai.rizom.brain.link",defs:{main:{type:"record",description:"Public curated link from a Rizom brain.",key:"any",record:{type:"object",required:["title","url","createdAt"],properties:{title:{type:"string",maxLength:500},url:{type:"string",format:"uri"},description:{type:"string",maxLength:2000},summary:{type:"string",maxLength:1e5},domain:{type:"string"},capturedAt:{type:"string",format:"datetime"},source:{type:"object",required:["ref","label"],properties:{ref:{type:"string"},label:{type:"string"}}},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var lM1={lexicon:1,id:"ai.rizom.brain.note",defs:{main:{type:"record",description:"Public knowledge note from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var pM1={lexicon:1,id:"ai.rizom.brain.post",defs:{main:{type:"record",description:"Markdown blog post distributed by a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},summary:{type:"string",maxLength:2000},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},brainDid:{type:"string"},anchorDid:{type:"string"},canonicalUrl:{type:"string",format:"uri"},topics:{type:"array",items:{type:"string"},maxLength:50},coverImage:{type:"object",required:["blob"],properties:{blob:{type:"blob"},alt:{type:"string",maxLength:1000},width:{type:"integer"},height:{type:"integer"}}},series:{type:"string",maxLength:200},seriesIndex:{type:"integer"},sourceEntityType:{type:"string",knownValues:["post"]},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},publishedAt:{type:"string",format:"datetime"}}}}}};var iM1={lexicon:1,id:"ai.rizom.brain.project",defs:{main:{type:"record",description:"Public project or case study from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","year","createdAt"],properties:{title:{type:"string",maxLength:300},slug:{type:"string"},description:{type:"string",maxLength:2000},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},year:{type:"integer"},url:{type:"string",format:"uri"},publishedAt:{type:"string",format:"datetime"},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var dM1={lexicon:1,id:"ai.rizom.brain.series",defs:{main:{type:"record",description:"Public content series from a Rizom brain.",key:"any",record:{type:"object",required:["title","createdAt"],properties:{title:{type:"string",maxLength:300},slug:{type:"string"},description:{type:"string",maxLength:1e4},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var nM1={lexicon:1,id:"ai.rizom.brain.socialPost",defs:{main:{type:"record",description:"Semantic local social-post entity from a Rizom brain; not a Bluesky feed post.",key:"any",record:{type:"object",required:["title","platform","body","createdAt"],properties:{title:{type:"string",maxLength:300},platform:{type:"string"},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},status:{type:"string"},publishedAt:{type:"string",format:"datetime"},platformPostId:{type:"string"},sourceLocalEntityType:{type:"string"},sourceLocalEntityId:{type:"string"},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var rM1={lexicon:1,id:"ai.rizom.brain.topic",defs:{main:{type:"record",description:"Public topic page from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var VTQ=Z.object({type:Z.string()}).catchall(Z.unknown()),ITQ=Z.object({lexicon:Z.literal(1),id:Z.string(),defs:Z.object({main:Z.object({type:Z.literal("record"),key:Z.string().min(1),record:Z.object({type:Z.literal("object"),required:Z.array(Z.string()).optional(),properties:Z.record(Z.string(),VTQ)})})})});function BU(A){return ITQ.parse(A)}var L6={"ai.rizom.brain.card":BU(mM1),"ai.rizom.brain.deck":BU(uM1),"ai.rizom.brain.link":BU(cM1),"ai.rizom.brain.note":BU(lM1),"ai.rizom.brain.post":BU(pM1),"ai.rizom.brain.project":BU(iM1),"ai.rizom.brain.series":BU(dM1),"ai.rizom.brain.socialPost":BU(nM1),"ai.rizom.brain.topic":BU(rM1)},JTQ="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function xq(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:JTQ}}var oM1={"ai.rizom.brain.card":xq("@brains/atproto"),"ai.rizom.brain.deck":xq("@brains/decks"),"ai.rizom.brain.link":xq("@brains/link"),"ai.rizom.brain.note":xq("@brains/note"),"ai.rizom.brain.post":xq("@brains/blog"),"ai.rizom.brain.project":xq("@brains/portfolio"),"ai.rizom.brain.series":xq("@brains/series"),"ai.rizom.brain.socialPost":xq("@brains/social-media"),"ai.rizom.brain.topic":xq("@brains/topics")};function uJ(){return Object.values(L6)}function i50(A){if(!(A in L6))return;return L6[A]}function d50(){return Object.entries(oM1).map(([A,Q])=>({id:A,...Q}))}N0();function n50(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var FTQ=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function LTQ(A){let Q=Z.string(),w=A.maxLength!==void 0?Q.max(A.maxLength):Q;if(A.knownValues)w=w.refine((B)=>A.knownValues?.includes(B),{message:`expected one of ${A.knownValues.join(", ")}`});if(A.format==="datetime")w=w.refine((B)=>FTQ.test(B)&&!Number.isNaN(Date.parse(B)),{message:"expected datetime"});if(A.format==="uri")w=w.refine((B)=>{try{return new URL(B),!0}catch{return!1}},{message:"expected uri"});return w}function sM1(A){switch(A.type){case"string":return LTQ(A);case"integer":return Z.number().int();case"boolean":return Z.boolean();case"array":{let Q=A.items?sM1(A.items):Z.unknown(),w=Z.array(Q);if(A.maxLength!==void 0)w=w.max(A.maxLength);return w}case"object":return kTQ(A);case"blob":return Z.custom(n50,{message:"expected blob"});default:return Z.unknown()}}function aM1(A){let Q=new Set(A.required??[]),w={};for(let[B,$]of Object.entries(A.properties??{})){let f=sM1($);w[B]=Q.has(B)?f:f.optional()}return w}function kTQ(A){return Z.object(aM1(A)).passthrough()}function Iu0(A,Q,w,B=[]){let $=Object.keys(A).filter((f)=>!Q.has(f));if($.length===0)return;w.addIssue({code:Z.ZodIssueCode.custom,path:B,message:`unrecognized field(s): ${$.join(", ")}`})}function _TQ(A,Q){if(Iu0(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),n50(A.brain))Iu0(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(n50(A.anchor))Iu0(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function $U(A){let Q=Z.object({...aM1(A.defs.main.record),$type:Z.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(_TQ):Q}var Ju0={"ai.rizom.brain.card":$U(L6["ai.rizom.brain.card"]),"ai.rizom.brain.deck":$U(L6["ai.rizom.brain.deck"]),"ai.rizom.brain.link":$U(L6["ai.rizom.brain.link"]),"ai.rizom.brain.note":$U(L6["ai.rizom.brain.note"]),"ai.rizom.brain.post":$U(L6["ai.rizom.brain.post"]),"ai.rizom.brain.project":$U(L6["ai.rizom.brain.project"]),"ai.rizom.brain.series":$U(L6["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":$U(L6["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":$U(L6["ai.rizom.brain.topic"])};function NTQ(A,Q){let w=A;for(let B of Q){if(typeof B==="symbol")return;if(Array.isArray(w)){w=w[Number(B)];continue}if(!n50(w))return;w=w[String(B)]}return w}function jTQ(A,Q,w){let B=w.path.join(".");if(B==="$type")return`AT Protocol record $type must match lexicon id: ${String(Q.$type)} !== ${A.id}`;if(w.code==="invalid_type"&&NTQ(Q,w.path)===void 0)return`Missing required AT Protocol record field: ${B}`;if(w.code==="invalid_type")return`Invalid AT Protocol record field ${B}: expected ${w.expected}`;if(w.code==="too_big")return`Invalid AT Protocol record field ${B}: exceeds maxLength ${w.maximum}`;if(w.code==="custom")return`Invalid AT Protocol record field ${B}: ${w.message}`;if(w.code==="unrecognized_keys")return`Unrecognized AT Protocol record field(s): ${w.keys.join(", ")}`;return`Invalid AT Protocol record field ${B}: ${w.message}`}function Rq(A,Q){let w=$U(A).safeParse(Q);if(w.success)return;let B=w.error.issues[0];if(!B)throw w.error;throw Error(jTQ(A,Q,B))}N0();var Md="atproto:brain-card-discovered",Fu0="atproto:brain-discovered",Lu0="atproto:brain-card-refreshed",PTQ=Z.custom((A)=>Ju0["ai.rizom.brain.card"].safeParse(A).success),ku0=Z.object({repoDid:Z.string().min(1),uri:Z.string().min(1),cid:Z.string().min(1),record:PTQ}).strict(),MTQ=Z.object({agentId:Z.string().min(1),name:Z.string().min(1),url:Z.string().url(),status:Z.enum(["discovered","approved"]),repoDid:Z.string().min(1).optional(),brainDid:Z.string().min(1).optional(),anchorDid:Z.string().min(1).optional(),cardUri:Z.string().min(1).optional(),cardCid:Z.string().min(1).optional()}).strict();class A8{static instance;projections=new Map;static getInstance(){return this.instance??=new A8,this.instance}static createFresh(){return new A8}static resetInstance(){this.instance=void 0}register(A){this.validateProjection(A);let Q=this.get(A.entityType);if(Q&&!this.isEquivalentProjection(Q,A))throw Error(`AT Protocol projection already registered for entity type ${A.entityType}`);let w=this.projections.get(A.entityType)??[];return w.push(A),this.projections.set(A.entityType,w),this.createUnregister(A.entityType,A)}get(A){let Q=this.projections.get(A);return Q?.[Q.length-1]}has(A){return this.get(A)!==void 0}list(){let A=[];for(let Q of this.projections.keys()){let w=this.get(Q);if(w)A.push(w)}return A}listLexicons(){return this.list().map((A)=>A.lexicon)}createUnregister(A,Q){let w=!0;return()=>{if(!w)return;w=!1;let B=this.projections.get(A);if(!B)return;let $=B.lastIndexOf(Q);if($!==-1)B.splice($,1);if(B.length===0)this.projections.delete(A)}}isEquivalentProjection(A,Q){return A.entityType===Q.entityType&&A.collection===Q.collection&&A.lexicon.id===Q.lexicon.id&&A.validate===Q.validate}validateProjection(A){if(A.collection!==A.lexicon.id)throw Error(`AT Protocol projection collection must match lexicon id: ${A.collection} !== ${A.lexicon.id}`);if(!A.lexicon.defs.main.key)throw Error(`AT Protocol projection lexicon must define a record key: ${A.collection}`)}}N0();var tM1={name:"@brains/atproto-registry",version:"0.2.0-alpha.142",description:"Canonical Rizom AT Protocol lexicon registry",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var AO1=Z.object({enabled:Z.boolean().default(!0)}),_u0="/atproto/lexicons",xTQ=Z.strictObject({nsid:Z.string(),record:Z.record(Z.string(),Z.unknown())});function eM1(A){return new Response(`${JSON.stringify(A,null,2)}
4748
+ `)||"No response text";return{success:!0,data:{state:D,response:b}}}f=await EM1(w,Q)}return{success:!1,error:"Stream ended without a terminal event"}}class jd extends Error{timeoutMs;constructor(A){super(`request timed out after ${A}ms`);this.timeoutMs=A,this.name="A2ARequestTimeoutError"}}class Pd extends Error{timeoutMs;constructor(A){super(`A2A stream stalled waiting for final event after ${A}ms`);this.timeoutMs=A,this.name="A2AStreamIdleTimeoutError"}}async function fTQ(A,Q,w,B){let $=new AbortController,f;try{return await Promise.race([A(Q,{...w,signal:$.signal}),new Promise((Y,X)=>{f=setTimeout(()=>{$.abort(),X(new jd(B))},B)})])}catch(Y){if(Y instanceof jd)throw Y;if($.signal.aborted)throw new jd(B);throw Y}finally{if(f)clearTimeout(f)}}async function EM1(A,Q){let w;try{return await Promise.race([A.read(),new Promise((B,$)=>{w=setTimeout(()=>$(new Pd(Q)),Q)})])}catch(B){if(B instanceof Pd)A.cancel().catch(()=>{});throw B}finally{if(w)clearTimeout(w)}}function YTQ(A){if(A instanceof jd||A instanceof Pd)return!1;return A instanceof Error}function bu0(A,Q){let w=Q>1?` after ${Q} attempts`:"";if(A instanceof Pd)return`${A.message}${w}`;let B=A instanceof Error?A.message:"Unknown network error";return`Failed to reach remote agent${w}: ${B}`}function SM1(A={}){let Q=A.fetch??globalThis.fetch,w={requestTimeoutMs:A.requestTimeoutMs??aEQ,streamIdleTimeoutMs:A.streamIdleTimeoutMs??tEQ,maxNetworkAttempts:A.maxNetworkAttempts??eEQ};return{name:"agent_call",description:"Call a remote A2A agent by exact domain-like target or saved local agent id. Use this when the user asks what an exact domain-like agent id has to say, asks to talk/message/contact that id, or asks that agent for its skills/capabilities. For saved agents, the tool enforces approved/not-archived status before network contact. For unsaved exact domains, the tool verifies the A2A Agent Card over HTTPS and may perform a one-shot call without saving; it returns a typed save/connect candidate after success. Use bare ids such as yeehaa.io, docs.rizom.ai, or save-it-regression.example; .example test domains are exact domain-like ids. If the user provides an HTTPS URL such as https://docs.rizom.ai/a2a, pass only the hostname docs.rizom.ai. For follow-ups to a prior exact-id call, call again with the same id so the tool revalidates current state. Never pass a full URL, a display name like Brain, or a non-HTTPS URL. If the user gives an ambiguous name, ask them to connect/save or clarify the agent first.",inputSchema:ATQ,visibility:"trusted",sideEffects:"external",handler:async(B)=>{let $=QTQ.safeParse(B);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};let{agent:f,message:Y}=$.data,X=wTQ(f);if(!X.ok)return{success:!1,error:X.error};let{agentId:W}=X;if(!A.entityService)return{success:!1,error:"Agent directory is unavailable. Add the agent first, then try again."};let H=await A.entityService.getEntity({entityType:"agent",id:W,visibilityScope:T9("agent_call tool is anchor-only and resolves saved remote agents at any visibility")});if(!H){if(!BTQ(W))return{success:!1,error:`Agent ${f} is not an exact domain-like id and is not saved. Connect or clarify the agent first.`,code:"agent_not_saved"};let b=`https://${W}`,I=await gM1(b,Q);if(!I)return{success:!1,error:`Could not verify an A2A Agent Card for ${W}. Connect/save it first if you want to add it to the directory.`,code:"agent_card_unavailable"};let V=CM1(I.url,W);if(!V.ok)return{success:!1,error:V.error};let L=await yM1(I.url,Y,Q,A.requestSigner,w);if("success"in L&&L.success===!0){let N=typeof L.data==="object"&&L.data!==null?L.data:{};return{...L,data:{...N,agentCall:{mode:"one-shot",agent:W},agentContactCandidate:{source:{kind:"url",url:X.sourceUrl??W}}}}}return L}if(H.metadata.status==="archived")return{success:!1,error:`Agent ${W} is archived and cannot be contacted until it is restored and approved.`,code:"agent_archived"};if(H.metadata.status!=="approved")return{success:!1,error:`Agent ${W} is discovered but not approved yet. Approve it first.`,code:"agent_not_approved"};let K=`https://${W}`,U=await gM1(K,Q);if(!U)return{success:!1,error:`Could not fetch Agent Card from ${K}`};let D=CM1(U.url,W);if(!D.ok)return{success:!1,error:D.error};let q=U.url;return yM1(q,Y,Q,A.requestSigner,w)}}}var Vu0={name:"@brains/a2a",version:"0.2.0-alpha.143",dependencies:{"@a2a-js/sdk":"^0.3.13","@brains/auth-service":"workspace:*","@brains/http-signatures":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",hono:"^4.12.25"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^6.0.3"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var ZTQ={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Signature, Signature-Input, Content-Digest, Date","X-Content-Type-Options":"nosniff"};class xC extends ND{agentCard;taskManager=new qu0;agentService;jwksResolver=new Gu0;app;hasWebserver=!1;constructor(A={}){if(Object.prototype.hasOwnProperty.call(A,"trustedTokens"))throw Error("trustedTokens legacy config is no longer supported");if(Object.prototype.hasOwnProperty.call(A,"outboundTokens"))throw Error("outboundTokens legacy config is no longer supported");super("a2a",Vu0,A,NM1)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,this.hasWebserver)A.endpoints.register({label:"A2A",url:"/a2a",priority:25}),A.interactions.register({id:"a2a",label:"A2A",description:"Let other agents discover and talk to this brain.",href:"/a2a",kind:"agent",priority:25}),this.logger.info("A2A interface registered",{domain:A.domain});else this.logger.info("A2A interface registered in tool-only mode",{domain:A.domain})}async onReady(A){await this.rebuildAgentCard(A)}async rebuildAgentCard(A){let Q=A.identity.get(),w=A.identity.getProfile(),B=A.tools.listForPermissionLevel("public"),$;if(A.entityService.hasEntityType("skill"))try{let f=await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}});if(f.length>0)$=f.map((Y)=>zm.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=jM1({character:Q,profile:w,version:Vu0.version,domain:A.domain,organization:this.config.organization,tools:B,skills:$,authEnabled:!1}),this.logger.debug("Agent Card rebuilt",{skills:this.agentCard.skills.length})}getAgentCard(){return this.agentCard}async resolveCaller(A,Q){let w=await LM1({method:A.method,url:A.url,headers:A.headers,body:Q},this.jwksResolver);if(w){let B=await P7()?.getA2APeerTrust(w.domain);return{permissionLevel:B?.keyFingerprint===w.keyFingerprint?B.grantedLevel:"public",callerDomain:w.domain}}return{permissionLevel:"public",callerDomain:null}}withCors(A){let Q=new Headers(A.headers);for(let[w,B]of Object.entries(ZTQ))Q.set(w,B);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}getOrCreateApp(){if(this.app)return this.app;let A=new jC;return A.get("/.well-known/agent-card.json",(Q)=>{if(!this.agentCard)return this.withCors(Q.json({error:"Agent Card not ready"},503));return this.withCors(Q.json(this.agentCard))}),A.get("/a2a",(Q)=>{return this.withCors(Q.json({error:"Use POST with JSON-RPC 2.0 requests.",agentCard:"/.well-known/agent-card.json"},405))}),A.options("/a2a",()=>this.withCors(new Response(null,{status:204}))),A.post("/a2a",async(Q)=>{if(!this.agentService)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32603,message:"Agent service not ready"},id:null},503));let w=await Q.req.text(),B;try{B=await this.resolveCaller(Q.req.raw,w)}catch{return this.withCors(Q.json({error:"Invalid HTTP signature"},401))}let $;try{$=JSON.parse(w)}catch{return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32700,message:"Parse error"},id:null}))}let f=OM1.safeParse($);if(!f.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32600,message:"Invalid request"},id:null}));if(f.data.method==="message/stream"){let X=RM1.safeParse(f.data.params??{});if(!X.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${X.error.message}`},id:f.data.id}));let W=vM1(f.data.id,X.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:B.permissionLevel,callerDomain:B.callerDomain});if("error"in W)return this.withCors(Q.json(W));let{stream:H}=W;return this.withCors(new Response(H,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let Y=await xM1(f.data,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:B.permissionLevel,callerDomain:B.callerDomain});return this.withCors(Q.json(Y))}),this.app=A,A}getWebRoutes(){if(!this.hasWebserver)return[];let A=(Q)=>Promise.resolve(this.getOrCreateApp().fetch(Q));return[{path:"/.well-known/agent-card.json",method:"GET",public:!0,handler:A},{path:"/a2a",method:"GET",public:!0,handler:A},{path:"/a2a",method:"POST",public:!0,handler:A},{path:"/a2a",method:"OPTIONS",public:!0,handler:A}]}createRequestSigner(){let A=P7();if(!A)return;return async(Q)=>{let w=await A.getA2ASigningKey();await FM1(Q,w.privateJwk,w.keyId)}}async getTools(){return[SM1({requestSigner:this.createRequestSigner(),requestTimeoutMs:this.config.requestTimeoutMs,streamIdleTimeoutMs:this.config.streamIdleTimeoutMs,maxNetworkAttempts:this.config.maxNetworkAttempts,entityService:this.getContext().entityService})]}async getInstructions(){return"## Agent-to-agent calls\n- Use `agent_call` for exact domain-like agent ids (for example `yeehaa.io`, `docs.rizom.ai`, or `save-it-regression.example`). A domain-like id is bare text with a dot and no slash/protocol; `.example` test domains are still exact domain-like ids. For saved agents, the tool validates approval before network contact. For unsaved exact domains, it verifies the Agent Card over HTTPS and may perform a one-shot call without saving.\n- Pass only an exact domain-like agent id to `agent_call`. If the user provides an HTTPS URL, pass only its hostname as the agent id (for `https://docs.rizom.ai/a2a`, pass `docs.rizom.ai`). Never pass a full URL, a non-HTTPS URL, or a display name like `Brain`.\n- If the user names an exact domain-like agent id such as `yeehaa.io`, `docs.rizom.ai`, or `refusal-followup.example`, call `agent_call` directly with that id. Do not preflight with `system_list` or `system_get`; the tool reports structured errors such as invalid Agent Card, not approved, or archived.\n- If the user asks you to ask, message, contact, hear what an exact domain-like agent id has to say, or ask that agent for its own skills/capabilities, treat that as an agent call request first and call `agent_call` in the same turn. Do not stop after listing the agent, drafting the question, searching general content locally, or reading saved agent entity metadata.\n- After `agent_call` returns within a turn, answer that turn from its response. Do **not** supplement with `system_get` (or any other read tool) on the agent entity, unless the user explicitly asks for directory/profile details about the agent itself.\n- Do not create, capture, or generate a note containing the user's question in the same turn as an agent contact request. The user asked to ask the agent, not to persist the question.\n- If `agent_call` succeeds for an unsaved one-shot domain, you may offer to save/connect that agent for future calls, but do not auto-save it.\n- If `agent_call` fails because auth, re-authentication, network, invalid Agent Card, or the remote agent is unavailable, report that failure directly. Do not say the agent was saved, connected, or may need to be saved/connected first. If useful, offer to add the agent contact using the word \"add\". Do not answer from memory, local docs, onboarding docs, or general knowledge; the requested agent was the source.\n- Each new turn that asks the same exact domain-like agent id something \u2014 including short follow-ups like \"what skills does it have\", \"and what about X\", \"tell me more\" \u2014 is a **new** contact request and needs its **own** fresh `agent_call`. Do not assume the previous turn's agent response already covers a new question, and do not substitute `system_list`/`system_get` or a no-tool answer for the fresh call. If the previous turn targeted an exact domain-like id such as `yeehaa.io`, use that same id again for the follow-up even if the previous response was a refusal or error; let `agent_call` validate the current directory state again.\n- When the user provides an HTTPS URL for an agent, use its hostname as the exact domain-like id for `agent_call`; the runtime verifies/contact over HTTPS. If the user provides a non-HTTPS URL, ask for the HTTPS agent URL or exact domain-like id instead.\n- If the user refers to an agent by name, first make sure that name resolves to exactly one saved agent id. If multiple saved agents could match, ask a concise clarification question naming the matching saved agent ids and do not call any agent yet. Never choose the first match.\n- After asking that clarification question, end the turn. Do not call `agent_call` later in the same turn.\n- If `agent_call` reports that an exact domain-like agent id cannot be verified, tell the user the agent could not be verified/contacted. Do not create a wish, reminder, todo, note, fallback task, or any new entity.\n- For non-HTTPS URLs and ambiguous display names, do not call `agent_call`; ask the user for the HTTPS agent URL, exact domain-like id, or a clarification first.\n- Use `agent_connect`, not generic entity creation, when the user explicitly asks you to add, save, or connect an agent contact.\n- If the target agent is discovered but not approved yet, do not call it and do not create a wish. Tell the user it must be approved first."}createDaemon(){return{start:async()=>{if(this.hasWebserver)this.logger.info("A2A mounted on shared webserver host");else this.logger.info("A2A running without webserver routes")},stop:async()=>{this.logger.info("A2A server stopped")}}}}wA();N0();var mM1={lexicon:1,id:"ai.rizom.brain.card",defs:{main:{type:"record",description:"Public discovery card for a Rizom brain. The operational A2A Agent Card is conventionally served at /.well-known/agent-card.json under siteUrl.",key:"literal:self",record:{type:"object",required:["siteUrl","brain","anchor","skills","model","version","createdAt"],properties:{siteUrl:{type:"string",format:"uri",description:"Public site URL. Consumers derive the A2A Agent Card URL from this base."},brain:{type:"object",description:"Brain identity described by this discovery card.",required:["did","name","role","purpose","values"],properties:{did:{type:"string",description:"Public DID for the brain identity."},name:{type:"string",maxLength:200,description:"Human-readable brain name."},role:{type:"string",maxLength:500,description:"Brain role or persona."},purpose:{type:"string",maxLength:2000,description:"Short public description of what this brain is for."},values:{type:"array",description:"Public values or principles for this brain.",items:{type:"string",maxLength:200},maxLength:50}}},anchor:{type:"object",description:"Minimal owner/operator snapshot for discovery grouping and display.",required:["did","name","kind"],properties:{did:{type:"string",description:"Public DID for the owner/operator anchor identity."},name:{type:"string",maxLength:200,description:"Human-readable anchor name."},kind:{type:"string",knownValues:["professional","team","collective"],description:"Anchor type."}}},skills:{type:"array",description:"User-facing skills this brain advertises for discovery.",items:{type:"object",required:["id","name","description"],properties:{id:{type:"string",maxLength:200},name:{type:"string",maxLength:200},description:{type:"string",maxLength:2000},tags:{type:"array",items:{type:"string"},maxLength:50},examples:{type:"array",items:{type:"string"},maxLength:20}}},maxLength:100},model:{type:"string",description:"Rizom brain model identifier."},version:{type:"string",description:"Brain runtime/model implementation version."},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var uM1={lexicon:1,id:"ai.rizom.brain.deck",defs:{main:{type:"record",description:"Public presentation deck from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},slug:{type:"string"},description:{type:"string",maxLength:2000},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},author:{type:"string"},event:{type:"string"},publishedAt:{type:"string",format:"datetime"},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var cM1={lexicon:1,id:"ai.rizom.brain.link",defs:{main:{type:"record",description:"Public curated link from a Rizom brain.",key:"any",record:{type:"object",required:["title","url","createdAt"],properties:{title:{type:"string",maxLength:500},url:{type:"string",format:"uri"},description:{type:"string",maxLength:2000},summary:{type:"string",maxLength:1e5},domain:{type:"string"},capturedAt:{type:"string",format:"datetime"},source:{type:"object",required:["ref","label"],properties:{ref:{type:"string"},label:{type:"string"}}},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var lM1={lexicon:1,id:"ai.rizom.brain.note",defs:{main:{type:"record",description:"Public knowledge note from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var pM1={lexicon:1,id:"ai.rizom.brain.post",defs:{main:{type:"record",description:"Markdown blog post distributed by a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},summary:{type:"string",maxLength:2000},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},brainDid:{type:"string"},anchorDid:{type:"string"},canonicalUrl:{type:"string",format:"uri"},topics:{type:"array",items:{type:"string"},maxLength:50},coverImage:{type:"object",required:["blob"],properties:{blob:{type:"blob"},alt:{type:"string",maxLength:1000},width:{type:"integer"},height:{type:"integer"}}},series:{type:"string",maxLength:200},seriesIndex:{type:"integer"},sourceEntityType:{type:"string",knownValues:["post"]},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},publishedAt:{type:"string",format:"datetime"}}}}}};var iM1={lexicon:1,id:"ai.rizom.brain.project",defs:{main:{type:"record",description:"Public project or case study from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","year","createdAt"],properties:{title:{type:"string",maxLength:300},slug:{type:"string"},description:{type:"string",maxLength:2000},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},year:{type:"integer"},url:{type:"string",format:"uri"},publishedAt:{type:"string",format:"datetime"},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var dM1={lexicon:1,id:"ai.rizom.brain.series",defs:{main:{type:"record",description:"Public content series from a Rizom brain.",key:"any",record:{type:"object",required:["title","createdAt"],properties:{title:{type:"string",maxLength:300},slug:{type:"string"},description:{type:"string",maxLength:1e4},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var nM1={lexicon:1,id:"ai.rizom.brain.socialPost",defs:{main:{type:"record",description:"Semantic local social-post entity from a Rizom brain; not a Bluesky feed post.",key:"any",record:{type:"object",required:["title","platform","body","createdAt"],properties:{title:{type:"string",maxLength:300},platform:{type:"string"},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},status:{type:"string"},publishedAt:{type:"string",format:"datetime"},platformPostId:{type:"string"},sourceLocalEntityType:{type:"string"},sourceLocalEntityId:{type:"string"},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var rM1={lexicon:1,id:"ai.rizom.brain.topic",defs:{main:{type:"record",description:"Public topic page from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var VTQ=Z.object({type:Z.string()}).catchall(Z.unknown()),ITQ=Z.object({lexicon:Z.literal(1),id:Z.string(),defs:Z.object({main:Z.object({type:Z.literal("record"),key:Z.string().min(1),record:Z.object({type:Z.literal("object"),required:Z.array(Z.string()).optional(),properties:Z.record(Z.string(),VTQ)})})})});function BU(A){return ITQ.parse(A)}var L6={"ai.rizom.brain.card":BU(mM1),"ai.rizom.brain.deck":BU(uM1),"ai.rizom.brain.link":BU(cM1),"ai.rizom.brain.note":BU(lM1),"ai.rizom.brain.post":BU(pM1),"ai.rizom.brain.project":BU(iM1),"ai.rizom.brain.series":BU(dM1),"ai.rizom.brain.socialPost":BU(nM1),"ai.rizom.brain.topic":BU(rM1)},JTQ="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function xq(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:JTQ}}var oM1={"ai.rizom.brain.card":xq("@brains/atproto"),"ai.rizom.brain.deck":xq("@brains/decks"),"ai.rizom.brain.link":xq("@brains/link"),"ai.rizom.brain.note":xq("@brains/note"),"ai.rizom.brain.post":xq("@brains/blog"),"ai.rizom.brain.project":xq("@brains/portfolio"),"ai.rizom.brain.series":xq("@brains/series"),"ai.rizom.brain.socialPost":xq("@brains/social-media"),"ai.rizom.brain.topic":xq("@brains/topics")};function uJ(){return Object.values(L6)}function i50(A){if(!(A in L6))return;return L6[A]}function d50(){return Object.entries(oM1).map(([A,Q])=>({id:A,...Q}))}N0();function n50(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var FTQ=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function LTQ(A){let Q=Z.string(),w=A.maxLength!==void 0?Q.max(A.maxLength):Q;if(A.knownValues)w=w.refine((B)=>A.knownValues?.includes(B),{message:`expected one of ${A.knownValues.join(", ")}`});if(A.format==="datetime")w=w.refine((B)=>FTQ.test(B)&&!Number.isNaN(Date.parse(B)),{message:"expected datetime"});if(A.format==="uri")w=w.refine((B)=>{try{return new URL(B),!0}catch{return!1}},{message:"expected uri"});return w}function sM1(A){switch(A.type){case"string":return LTQ(A);case"integer":return Z.number().int();case"boolean":return Z.boolean();case"array":{let Q=A.items?sM1(A.items):Z.unknown(),w=Z.array(Q);if(A.maxLength!==void 0)w=w.max(A.maxLength);return w}case"object":return kTQ(A);case"blob":return Z.custom(n50,{message:"expected blob"});default:return Z.unknown()}}function aM1(A){let Q=new Set(A.required??[]),w={};for(let[B,$]of Object.entries(A.properties??{})){let f=sM1($);w[B]=Q.has(B)?f:f.optional()}return w}function kTQ(A){return Z.object(aM1(A)).passthrough()}function Iu0(A,Q,w,B=[]){let $=Object.keys(A).filter((f)=>!Q.has(f));if($.length===0)return;w.addIssue({code:Z.ZodIssueCode.custom,path:B,message:`unrecognized field(s): ${$.join(", ")}`})}function _TQ(A,Q){if(Iu0(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),n50(A.brain))Iu0(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(n50(A.anchor))Iu0(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function $U(A){let Q=Z.object({...aM1(A.defs.main.record),$type:Z.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(_TQ):Q}var Ju0={"ai.rizom.brain.card":$U(L6["ai.rizom.brain.card"]),"ai.rizom.brain.deck":$U(L6["ai.rizom.brain.deck"]),"ai.rizom.brain.link":$U(L6["ai.rizom.brain.link"]),"ai.rizom.brain.note":$U(L6["ai.rizom.brain.note"]),"ai.rizom.brain.post":$U(L6["ai.rizom.brain.post"]),"ai.rizom.brain.project":$U(L6["ai.rizom.brain.project"]),"ai.rizom.brain.series":$U(L6["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":$U(L6["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":$U(L6["ai.rizom.brain.topic"])};function NTQ(A,Q){let w=A;for(let B of Q){if(typeof B==="symbol")return;if(Array.isArray(w)){w=w[Number(B)];continue}if(!n50(w))return;w=w[String(B)]}return w}function jTQ(A,Q,w){let B=w.path.join(".");if(B==="$type")return`AT Protocol record $type must match lexicon id: ${String(Q.$type)} !== ${A.id}`;if(w.code==="invalid_type"&&NTQ(Q,w.path)===void 0)return`Missing required AT Protocol record field: ${B}`;if(w.code==="invalid_type")return`Invalid AT Protocol record field ${B}: expected ${w.expected}`;if(w.code==="too_big")return`Invalid AT Protocol record field ${B}: exceeds maxLength ${w.maximum}`;if(w.code==="custom")return`Invalid AT Protocol record field ${B}: ${w.message}`;if(w.code==="unrecognized_keys")return`Unrecognized AT Protocol record field(s): ${w.keys.join(", ")}`;return`Invalid AT Protocol record field ${B}: ${w.message}`}function Rq(A,Q){let w=$U(A).safeParse(Q);if(w.success)return;let B=w.error.issues[0];if(!B)throw w.error;throw Error(jTQ(A,Q,B))}N0();var Md="atproto:brain-card-discovered",Fu0="atproto:brain-discovered",Lu0="atproto:brain-card-refreshed",PTQ=Z.custom((A)=>Ju0["ai.rizom.brain.card"].safeParse(A).success),ku0=Z.object({repoDid:Z.string().min(1),uri:Z.string().min(1),cid:Z.string().min(1),record:PTQ}).strict(),MTQ=Z.object({agentId:Z.string().min(1),name:Z.string().min(1),url:Z.string().url(),status:Z.enum(["discovered","approved"]),repoDid:Z.string().min(1).optional(),brainDid:Z.string().min(1).optional(),anchorDid:Z.string().min(1).optional(),cardUri:Z.string().min(1).optional(),cardCid:Z.string().min(1).optional()}).strict();class A8{static instance;projections=new Map;static getInstance(){return this.instance??=new A8,this.instance}static createFresh(){return new A8}static resetInstance(){this.instance=void 0}register(A){this.validateProjection(A);let Q=this.get(A.entityType);if(Q&&!this.isEquivalentProjection(Q,A))throw Error(`AT Protocol projection already registered for entity type ${A.entityType}`);let w=this.projections.get(A.entityType)??[];return w.push(A),this.projections.set(A.entityType,w),this.createUnregister(A.entityType,A)}get(A){let Q=this.projections.get(A);return Q?.[Q.length-1]}has(A){return this.get(A)!==void 0}list(){let A=[];for(let Q of this.projections.keys()){let w=this.get(Q);if(w)A.push(w)}return A}listLexicons(){return this.list().map((A)=>A.lexicon)}createUnregister(A,Q){let w=!0;return()=>{if(!w)return;w=!1;let B=this.projections.get(A);if(!B)return;let $=B.lastIndexOf(Q);if($!==-1)B.splice($,1);if(B.length===0)this.projections.delete(A)}}isEquivalentProjection(A,Q){return A.entityType===Q.entityType&&A.collection===Q.collection&&A.lexicon.id===Q.lexicon.id&&A.validate===Q.validate}validateProjection(A){if(A.collection!==A.lexicon.id)throw Error(`AT Protocol projection collection must match lexicon id: ${A.collection} !== ${A.lexicon.id}`);if(!A.lexicon.defs.main.key)throw Error(`AT Protocol projection lexicon must define a record key: ${A.collection}`)}}N0();var tM1={name:"@brains/atproto-registry",version:"0.2.0-alpha.143",description:"Canonical Rizom AT Protocol lexicon registry",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var AO1=Z.object({enabled:Z.boolean().default(!0)}),_u0="/atproto/lexicons",xTQ=Z.strictObject({nsid:Z.string(),record:Z.record(Z.string(),Z.unknown())});function eM1(A){return new Response(`${JSON.stringify(A,null,2)}
4749
4749
  `,{headers:{"Content-Type":"application/json"}})}class Nu0 extends aQ{constructor(A={}){super("atproto-registry",tM1,A,AO1)}getWebRoutes(){if(!this.config.enabled)return[];return[{path:`${_u0}/index.json`,method:"GET",public:!0,handler:()=>eM1(this.getIndex())},...uJ().map((A)=>({path:`${_u0}/${A.id}.json`,method:"GET",public:!0,handler:()=>eM1(A)}))]}getIndex(){return{lexicons:d50().map((A)=>({...A,path:`${_u0}/${A.id}.json`}))}}getLexicon(A){return i50(A)}async getTools(){return[this.createListLexiconsTool(),this.createValidateLexiconTool(),this.createCheckContractsTool()]}createListLexiconsTool(){return{name:`${this.id}_list_lexicons`,description:"List canonical Rizom AT Protocol lexicons.",inputSchema:{},handler:async()=>({success:!0,data:this.getIndex()})}}createValidateLexiconTool(){return{name:`${this.id}_validate_lexicon`,description:"Validate a record payload against a canonical Rizom AT Protocol lexicon.",inputSchema:{nsid:Z.string().describe("Canonical lexicon NSID"),record:Z.record(Z.string(),Z.unknown()).describe("Record payload to validate")},handler:async(A)=>{let Q=xTQ.safeParse(A);if(!Q.success)return{success:!1,error:`Invalid input: ${Q.error.message}`};let w=this.getLexicon(Q.data.nsid);if(!w)return{success:!1,error:`Unknown AT Protocol lexicon: ${Q.data.nsid}`};try{return Rq(w,Q.data.record),{success:!0,data:{valid:!0}}}catch(B){return{success:!0,data:{valid:!1,error:B instanceof Error?B.message:"Invalid record"}}}}}}createCheckContractsTool(){return{name:`${this.id}_check_contracts`,description:"Check that canonical Rizom AT Protocol lexicon contracts are available.",inputSchema:{},handler:async()=>({success:!0,data:{lexiconCount:uJ().length,nsids:uJ().map((A)=>A.id),metadata:d50()}})}}}function Od(A={}){return new Nu0(A)}wA();class ju0{logger;handleImport;handleDelete;deleteOnFileRemoval;fileOperations;constructor(A,Q,w,B,$=!0){if(this.logger=A,this.fileOperations=B,this.deleteOnFileRemoval=$,w)this.handleImport=async(f)=>{let Y=await w({type:"directory-import",data:{paths:[f]}});this.logger.debug("Queued import job for file change",{jobId:Y,path:f})},this.handleDelete=async(f)=>{if(!this.deleteOnFileRemoval){this.logger.warn("File deleted but deleteOnFileRemoval is disabled",{path:f});return}try{let{entityType:Y,id:X}=this.fileOperations.parseEntityFromPath(f),W=await w({type:"directory-delete",data:{entityId:X,entityType:Y,filePath:f}});this.logger.info("Queued delete job for removed file",{jobId:W,path:f,entityId:X,entityType:Y})}catch(Y){this.logger.warn("Could not extract entity info from deleted file",{path:f,error:Y})}};else this.handleImport=async(f)=>{await Q([f])},this.handleDelete=async(f)=>{this.logger.warn("File deleted but no job queue available",{path:f})}}async handleFileChange(A,Q){this.logger.debug("Processing file change",{event:A,path:Q});try{switch(A){case"add":case"change":await this.handleImport(Q);break;case"delete":case"unlink":await this.handleDelete(Q);break;default:this.logger.debug("Unhandled file event",{event:A,path:Q})}}catch(w){this.logger.error("Failed to handle file change",{event:A,path:Q,error:w})}}}import{EventEmitter as YSQ}from"events";import{stat as XSQ,Stats as ljB}from"fs";import{readdir as ZSQ,stat as WSQ}from"fs/promises";import*as ew from"path";import{lstat as QO1,readdir as RTQ,realpath as vTQ,stat as hTQ}from"fs/promises";import{join as CTQ,relative as gTQ,resolve as wO1,sep as yTQ}from"path";import{Readable as ETQ}from"stream";var DZ={FILE_TYPE:"files",DIR_TYPE:"directories",FILE_DIR_TYPE:"files_directories",EVERYTHING_TYPE:"all"},Pu0={root:".",fileFilter:(A)=>!0,directoryFilter:(A)=>!0,type:DZ.FILE_TYPE,lstat:!1,depth:2147483648,alwaysStat:!1,highWaterMark:4096};Object.freeze(Pu0);var YO1="READDIRP_RECURSIVE_ERROR",TTQ=new Set(["ENOENT","EPERM","EACCES","ELOOP",YO1]),BO1=[DZ.DIR_TYPE,DZ.EVERYTHING_TYPE,DZ.FILE_DIR_TYPE,DZ.FILE_TYPE],STQ=new Set([DZ.DIR_TYPE,DZ.EVERYTHING_TYPE,DZ.FILE_DIR_TYPE]),mTQ=new Set([DZ.EVERYTHING_TYPE,DZ.FILE_DIR_TYPE,DZ.FILE_TYPE]),uTQ=(A)=>TTQ.has(A.code),cTQ=process.platform==="win32",$O1=(A)=>!0,fO1=(A)=>{if(A===void 0)return $O1;if(typeof A==="function")return A;if(typeof A==="string"){let Q=A.trim();return(w)=>w.basename===Q}if(Array.isArray(A)){let Q=A.map((w)=>w.trim());return(w)=>Q.some((B)=>w.basename===B)}return $O1};class Mu0 extends ETQ{parents;reading;parent;_stat;_maxDepth;_wantsDir;_wantsFile;_wantsEverything;_root;_isDirent;_statsProp;_rdOptions;_fileFilter;_directoryFilter;constructor(A={}){super({objectMode:!0,autoDestroy:!0,highWaterMark:A.highWaterMark});let Q={...Pu0,...A},{root:w,type:B}=Q;this._fileFilter=fO1(Q.fileFilter),this._directoryFilter=fO1(Q.directoryFilter);let $=Q.lstat?QO1:hTQ;if(cTQ)this._stat=(f)=>$(f,{bigint:!0});else this._stat=$;this._maxDepth=Q.depth!=null&&Number.isSafeInteger(Q.depth)?Q.depth:Pu0.depth,this._wantsDir=B?STQ.has(B):!1,this._wantsFile=B?mTQ.has(B):!1,this._wantsEverything=B===DZ.EVERYTHING_TYPE,this._root=wO1(w),this._isDirent=!Q.alwaysStat,this._statsProp=this._isDirent?"dirent":"stats",this._rdOptions={encoding:"utf8",withFileTypes:this._isDirent},this.parents=[this._exploreDir(w,1)],this.reading=!1,this.parent=void 0}async _read(A){if(this.reading)return;this.reading=!0;try{while(!this.destroyed&&A>0){let Q=this.parent,w=Q&&Q.files;if(w&&w.length>0){let{path:B,depth:$}=Q,f=w.splice(0,A).map((X)=>this._formatEntry(X,B)),Y=await Promise.all(f);for(let X of Y){if(!X)continue;if(this.destroyed)return;let W=await this._getEntryType(X);if(W==="directory"&&this._directoryFilter(X)){if($<=this._maxDepth)this.parents.push(this._exploreDir(X.fullPath,$+1));if(this._wantsDir)this.push(X),A--}else if((W==="file"||this._includeAsFile(X))&&this._fileFilter(X)){if(this._wantsFile)this.push(X),A--}}}else{let B=this.parents.pop();if(!B){this.push(null);break}if(this.parent=await B,this.destroyed)return}}}catch(Q){this.destroy(Q)}finally{this.reading=!1}}async _exploreDir(A,Q){let w;try{w=await RTQ(A,this._rdOptions)}catch(B){this._onError(B)}return{files:w,depth:Q,path:A}}async _formatEntry(A,Q){let w,B=this._isDirent?A.name:A;try{let $=wO1(CTQ(Q,B));w={path:gTQ(this._root,$),fullPath:$,basename:B},w[this._statsProp]=this._isDirent?A:await this._stat($)}catch($){this._onError($);return}return w}_onError(A){if(uTQ(A)&&!this.destroyed)this.emit("warn",A);else this.destroy(A)}async _getEntryType(A){if(!A&&this._statsProp in A)return"";let Q=A[this._statsProp];if(Q.isFile())return"file";if(Q.isDirectory())return"directory";if(Q&&Q.isSymbolicLink()){let w=A.fullPath;try{let B=await vTQ(w),$=await QO1(B);if($.isFile())return"file";if($.isDirectory()){let f=B.length;if(w.startsWith(B)&&w.substr(f,1)===yTQ){let Y=Error(`Circular symlink detected: "${w}" points to "${B}"`);return Y.code=YO1,this._onError(Y)}return"directory"}}catch(B){return this._onError(B),""}}}_includeAsFile(A){let Q=A&&A[this._statsProp];return Q&&this._wantsEverything&&!Q.isDirectory()}}function XO1(A,Q={}){let w=Q.entryType||Q.type;if(w==="both")w=DZ.FILE_DIR_TYPE;if(w)Q.type=w;if(!A)throw Error("readdirp: root argument is required. Usage: readdirp(root, options)");else if(typeof A!=="string")throw TypeError("readdirp: root argument must be a string. Usage: readdirp(root, options)");else if(w&&!BO1.includes(w))throw Error(`readdirp: Invalid type passed. Use one of ${BO1.join(", ")}`);return Q.root=A,new Mu0(Q)}import{watch as lTQ,unwatchFile as ZO1,watchFile as pTQ}from"fs";import{realpath as Ou0,lstat as iTQ,open as dTQ,stat as HO1}from"fs/promises";import{type as nTQ}from"os";import*as x$ from"path";var rTQ="data",vu0="end",KO1="close",a50=()=>{};var t50=process.platform,hu0=t50==="win32",oTQ=t50==="darwin",sTQ=t50==="linux",aTQ=t50==="freebsd",UO1=nTQ()==="OS400",Y$={ALL:"all",READY:"ready",ADD:"add",CHANGE:"change",ADD_DIR:"addDir",UNLINK:"unlink",UNLINK_DIR:"unlinkDir",RAW:"raw",ERROR:"error"},fU=Y$,tTQ="watch",eTQ={lstat:iTQ,stat:HO1},eN="listeners",r50="errHandlers",RC="rawEmitters",ASQ=[eN,r50,RC],QSQ=new Set(["3dm","3ds","3g2","3gp","7z","a","aac","adp","afdesign","afphoto","afpub","ai","aif","aiff","alz","ape","apk","appimage","ar","arj","asf","au","avi","bak","baml","bh","bin","bk","bmp","btif","bz2","bzip2","cab","caf","cgm","class","cmx","cpio","cr2","cur","dat","dcm","deb","dex","djvu","dll","dmg","dng","doc","docm","docx","dot","dotm","dra","DS_Store","dsk","dts","dtshd","dvb","dwg","dxf","ecelp4800","ecelp7470","ecelp9600","egg","eol","eot","epub","exe","f4v","fbs","fh","fla","flac","flatpak","fli","flv","fpx","fst","fvt","g3","gh","gif","graffle","gz","gzip","h261","h263","h264","icns","ico","ief","img","ipa","iso","jar","jpeg","jpg","jpgv","jpm","jxr","key","ktx","lha","lib","lvp","lz","lzh","lzma","lzo","m3u","m4a","m4v","mar","mdi","mht","mid","midi","mj2","mka","mkv","mmr","mng","mobi","mov","movie","mp3","mp4","mp4a","mpeg","mpg","mpga","mxu","nef","npx","numbers","nupkg","o","odp","ods","odt","oga","ogg","ogv","otf","ott","pages","pbm","pcx","pdb","pdf","pea","pgm","pic","png","pnm","pot","potm","potx","ppa","ppam","ppm","pps","ppsm","ppsx","ppt","pptm","pptx","psd","pya","pyc","pyo","pyv","qt","rar","ras","raw","resources","rgb","rip","rlc","rmf","rmvb","rpm","rtf","rz","s3m","s7z","scpt","sgi","shar","snap","sil","sketch","slk","smv","snk","so","stl","suo","sub","swf","tar","tbz","tbz2","tga","tgz","thmx","tif","tiff","tlz","ttc","ttf","txz","udf","uvh","uvi","uvm","uvp","uvs","uvu","viv","vob","war","wav","wax","wbmp","wdp","weba","webm","webp","whl","wim","wm","wma","wmv","wmx","woff","woff2","wrm","wvx","xbm","xif","xla","xlam","xls","xlsb","xlsm","xlsx","xlt","xltm","xltx","xm","xmind","xpi","xpm","xwd","xz","z","zip","zipx"]),wSQ=(A)=>QSQ.has(x$.extname(A).slice(1).toLowerCase()),Ru0=(A,Q)=>{if(A instanceof Set)A.forEach(Q);else Q(A)},xd=(A,Q,w)=>{let B=A[Q];if(!(B instanceof Set))A[Q]=B=new Set([B]);B.add(w)},BSQ=(A)=>(Q)=>{let w=A[Q];if(w instanceof Set)w.clear();else delete A[Q]},Rd=(A,Q,w)=>{let B=A[Q];if(B instanceof Set)B.delete(w);else if(B===w)delete A[Q]},DO1=(A)=>A instanceof Set?A.size===0:!A,o50=new Map;function WO1(A,Q,w,B,$){let f=(Y,X)=>{if(w(A),$(Y,X,{watchedPath:A}),X&&A!==X)s50(x$.resolve(A,X),eN,x$.join(A,X))};try{return lTQ(A,{persistent:Q.persistent},f)}catch(Y){B(Y);return}}var s50=(A,Q,w,B,$)=>{let f=o50.get(A);if(!f)return;Ru0(f[Q],(Y)=>{Y(w,B,$)})},$SQ=(A,Q,w,B)=>{let{listener:$,errHandler:f,rawEmitter:Y}=B,X=o50.get(Q),W;if(!w.persistent){if(W=WO1(A,w,$,f,Y),!W)return;return W.close.bind(W)}if(X)xd(X,eN,$),xd(X,r50,f),xd(X,RC,Y);else{if(W=WO1(A,w,s50.bind(null,Q,eN),f,s50.bind(null,Q,RC)),!W)return;W.on(fU.ERROR,async(H)=>{let K=s50.bind(null,Q,r50);if(X)X.watcherUnusable=!0;if(hu0&&H.code==="EPERM")try{await(await dTQ(A,"r")).close(),K(H)}catch(U){}else K(H)}),X={listeners:$,errHandlers:f,rawEmitters:Y,watcher:W},o50.set(Q,X)}return()=>{if(Rd(X,eN,$),Rd(X,r50,f),Rd(X,RC,Y),DO1(X.listeners))X.watcher.close(),o50.delete(Q),ASQ.forEach(BSQ(X)),X.watcher=void 0,Object.freeze(X)}},xu0=new Map,fSQ=(A,Q,w,B)=>{let{listener:$,rawEmitter:f}=B,Y=xu0.get(Q),X=Y&&Y.options;if(X&&(X.persistent<w.persistent||X.interval>w.interval))ZO1(Q),Y=void 0;if(Y)xd(Y,eN,$),xd(Y,RC,f);else Y={listeners:$,rawEmitters:f,options:w,watcher:pTQ(Q,w,(W,H)=>{Ru0(Y.rawEmitters,(U)=>{U(fU.CHANGE,Q,{curr:W,prev:H})});let K=W.mtimeMs;if(W.size!==H.size||K>H.mtimeMs||K===0)Ru0(Y.listeners,(U)=>U(A,W))})},xu0.set(Q,Y);return()=>{if(Rd(Y,eN,$),Rd(Y,RC,f),DO1(Y.listeners))xu0.delete(Q),ZO1(Q),Y.options=Y.watcher=void 0,Object.freeze(Y)}};class Cu0{fsw;_boundHandleError;constructor(A){this.fsw=A,this._boundHandleError=(Q)=>A._handleError(Q)}_watchWithNodeFs(A,Q){let w=this.fsw.options,B=x$.dirname(A),$=x$.basename(A);this.fsw._getWatchedDir(B).add($);let Y=x$.resolve(A),X={persistent:w.persistent};if(!Q)Q=a50;let W;if(w.usePolling){let H=w.interval!==w.binaryInterval;X.interval=H&&wSQ($)?w.binaryInterval:w.interval,W=fSQ(A,Y,X,{listener:Q,rawEmitter:this.fsw._emitRaw})}else W=$SQ(A,Y,X,{listener:Q,errHandler:this._boundHandleError,rawEmitter:this.fsw._emitRaw});return W}_handleFile(A,Q,w){if(this.fsw.closed)return;let B=x$.dirname(A),$=x$.basename(A),f=this.fsw._getWatchedDir(B),Y=Q;if(f.has($))return;let X=async(H,K)=>{if(!this.fsw._throttle(tTQ,A,5))return;if(!K||K.mtimeMs===0)try{let U=await HO1(A);if(this.fsw.closed)return;let{atimeMs:D,mtimeMs:q}=U;if(!D||D<=q||q!==Y.mtimeMs)this.fsw._emit(fU.CHANGE,A,U);if((oTQ||sTQ||aTQ)&&Y.ino!==U.ino){this.fsw._closeFile(H),Y=U;let b=this._watchWithNodeFs(A,X);if(b)this.fsw._addPathCloser(H,b)}else Y=U}catch(U){this.fsw._remove(B,$)}else if(f.has($)){let{atimeMs:U,mtimeMs:D}=K;if(!U||U<=D||D!==Y.mtimeMs)this.fsw._emit(fU.CHANGE,A,K);Y=K}},W=this._watchWithNodeFs(A,X);if(!(w&&this.fsw.options.ignoreInitial)&&this.fsw._isntIgnored(A)){if(!this.fsw._throttle(fU.ADD,A,0))return;this.fsw._emit(fU.ADD,A,Q)}return W}async _handleSymlink(A,Q,w,B){if(this.fsw.closed)return;let $=A.fullPath,f=this.fsw._getWatchedDir(Q);if(!this.fsw.options.followSymlinks){this.fsw._incrReadyCount();let Y;try{Y=await Ou0(w)}catch(X){return this.fsw._emitReady(),!0}if(this.fsw.closed)return;if(f.has(B)){if(this.fsw._symlinkPaths.get($)!==Y)this.fsw._symlinkPaths.set($,Y),this.fsw._emit(fU.CHANGE,w,A.stats)}else f.add(B),this.fsw._symlinkPaths.set($,Y),this.fsw._emit(fU.ADD,w,A.stats);return this.fsw._emitReady(),!0}if(this.fsw._symlinkPaths.has($))return!0;this.fsw._symlinkPaths.set($,!0)}_handleRead(A,Q,w,B,$,f,Y){A=x$.join(A,"");let X=B?`${A}:${B}`:A;if(Y=this.fsw._throttle("readdir",X,1000),!Y)return;let W=this.fsw._getWatchedDir(w.path),H=new Set,K=this.fsw._readdirp(A,{fileFilter:(U)=>w.filterPath(U),directoryFilter:(U)=>w.filterDir(U)});if(!K)return;return K.on(rTQ,async(U)=>{if(this.fsw.closed){K=void 0;return}let D=U.path,q=x$.join(A,D);if(H.add(D),U.stats.isSymbolicLink()&&await this._handleSymlink(U,A,q,D))return;if(this.fsw.closed){K=void 0;return}if(D===B||!B&&!W.has(D))this.fsw._incrReadyCount(),q=x$.join($,x$.relative($,q)),this._addToNodeFs(q,Q,w,f+1)}).on(fU.ERROR,this._boundHandleError),new Promise((U,D)=>{if(!K)return D();K.once(vu0,()=>{if(this.fsw.closed){K=void 0;return}let q=Y?Y.clear():!1;if(U(void 0),W.getChildren().filter((b)=>{return b!==A&&!H.has(b)}).forEach((b)=>{this.fsw._remove(A,b)}),K=void 0,q)this._handleRead(A,!1,w,B,$,f,Y)})})}async _handleDir(A,Q,w,B,$,f,Y){let X=this.fsw._getWatchedDir(x$.dirname(A)),W=X.has(x$.basename(A));if(!(w&&this.fsw.options.ignoreInitial)&&!$&&!W)this.fsw._emit(fU.ADD_DIR,A,Q);X.add(x$.basename(A)),this.fsw._getWatchedDir(A);let H,K,U=this.fsw.options.depth;if((U==null||B<=U)&&!this.fsw._symlinkPaths.has(Y)){if(!$){if(await this._handleRead(A,w,f,$,A,B,H),this.fsw.closed)return}K=this._watchWithNodeFs(A,(D,q)=>{if(q&&q.mtimeMs===0)return;this._handleRead(D,!1,f,$,A,B,H)})}return K}async _addToNodeFs(A,Q,w,B,$){let f=this.fsw._emitReady;if(this.fsw._isIgnored(A)||this.fsw.closed)return f(),!1;let Y=this.fsw._getWatchHelpers(A);if(w)Y.filterPath=(X)=>w.filterPath(X),Y.filterDir=(X)=>w.filterDir(X);try{let X=await eTQ[Y.statMethod](Y.watchPath);if(this.fsw.closed)return;if(this.fsw._isIgnored(Y.watchPath,X))return f(),!1;let W=this.fsw.options.followSymlinks,H;if(X.isDirectory()){let K=x$.resolve(A),U=W?await Ou0(A):A;if(this.fsw.closed)return;if(H=await this._handleDir(Y.watchPath,X,Q,B,$,Y,U),this.fsw.closed)return;if(K!==U&&U!==void 0)this.fsw._symlinkPaths.set(K,U)}else if(X.isSymbolicLink()){let K=W?await Ou0(A):A;if(this.fsw.closed)return;let U=x$.dirname(Y.watchPath);if(this.fsw._getWatchedDir(U).add(Y.watchPath),this.fsw._emit(fU.ADD,Y.watchPath,X),H=await this._handleDir(U,X,Q,B,A,Y,K),this.fsw.closed)return;if(K!==void 0)this.fsw._symlinkPaths.set(x$.resolve(A),K)}else H=this._handleFile(Y.watchPath,X,Q);if(f(),H)this.fsw._addPathCloser(A,H);return!1}catch(X){if(this.fsw._handleError(X))return f(),A}}}/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */var gu0="/",HSQ="//",VO1=".",KSQ="..",USQ="string",DSQ=/\\/g,IO1=/\/\//g,GSQ=/\..*\.(sw[px])$|~$|\.subl.*\.tmp/,zSQ=/^\.[/\\]/;function e50(A){return Array.isArray(A)?A:[A]}var yu0=(A)=>typeof A==="object"&&A!==null&&!(A instanceof RegExp);function qSQ(A){if(typeof A==="function")return A;if(typeof A==="string")return(Q)=>A===Q;if(A instanceof RegExp)return(Q)=>A.test(Q);if(typeof A==="object"&&A!==null)return(Q)=>{if(A.path===Q)return!0;if(A.recursive){let w=ew.relative(A.path,Q);if(!w)return!1;return!w.startsWith("..")&&!ew.isAbsolute(w)}return!1};return()=>!1}function bSQ(A){if(typeof A!=="string")throw Error("string expected");A=ew.normalize(A),A=A.replace(/\\/g,"/");let Q=!1;if(A.startsWith("//"))Q=!0;if(A=A.replace(IO1,"/"),Q)A="/"+A;return A}function GO1(A,Q,w){let B=bSQ(Q);for(let $=0;$<A.length;$++){let f=A[$];if(f(B,w))return!0}return!1}function VSQ(A,Q){if(A==null)throw TypeError("anymatch: specify first argument");let B=e50(A).map(($)=>qSQ($));if(Q==null)return($,f)=>{return GO1(B,$,f)};return GO1(B,Q)}var zO1=(A)=>{let Q=e50(A).flat();if(!Q.every((w)=>typeof w===USQ))throw TypeError(`Non-string provided as watch path: ${Q}`);return Q.map(JO1)},qO1=(A)=>{let Q=A.replace(DSQ,gu0),w=!1;if(Q.startsWith(HSQ))w=!0;if(Q=Q.replace(IO1,gu0),w)Q=gu0+Q;return Q},JO1=(A)=>qO1(ew.normalize(qO1(A))),bO1=(A="")=>(Q)=>{if(typeof Q==="string")return JO1(ew.isAbsolute(Q)?Q:ew.join(A,Q));else return Q},ISQ=(A,Q)=>{if(ew.isAbsolute(A))return A;return ew.join(Q,A)},JSQ=Object.freeze(new Set);class FO1{path;_removeWatcher;items;constructor(A,Q){this.path=A,this._removeWatcher=Q,this.items=new Set}add(A){let{items:Q}=this;if(!Q)return;if(A!==VO1&&A!==KSQ)Q.add(A)}async remove(A){let{items:Q}=this;if(!Q)return;if(Q.delete(A),Q.size>0)return;let w=this.path;try{await ZSQ(w)}catch(B){if(this._removeWatcher)this._removeWatcher(ew.dirname(w),ew.basename(w))}}has(A){let{items:Q}=this;if(!Q)return;return Q.has(A)}getChildren(){let{items:A}=this;if(!A)return[];return[...A.values()]}dispose(){this.items.clear(),this.path="",this._removeWatcher=a50,this.items=JSQ,Object.freeze(this)}}var FSQ="stat",LSQ="lstat";class LO1{fsw;path;watchPath;fullWatchPath;dirParts;followSymlinks;statMethod;constructor(A,Q,w){this.fsw=w;let B=A;this.path=A=A.replace(zSQ,""),this.watchPath=B,this.fullWatchPath=ew.resolve(B),this.dirParts=[],this.dirParts.forEach(($)=>{if($.length>1)$.pop()}),this.followSymlinks=Q,this.statMethod=Q?FSQ:LSQ}entryPath(A){return ew.join(this.watchPath,ew.relative(this.watchPath,A.fullPath))}filterPath(A){let{stats:Q}=A;if(Q&&Q.isSymbolicLink())return this.filterDir(A);let w=this.entryPath(A);return this.fsw._isntIgnored(w,Q)&&this.fsw._hasReadPermissions(Q)}filterDir(A){return this.fsw._isntIgnored(this.entryPath(A),A.stats)}}class Eu0 extends YSQ{closed;options;_closers;_ignoredPaths;_throttled;_streams;_symlinkPaths;_watched;_pendingWrites;_pendingUnlinks;_readyCount;_emitReady;_closePromise;_userIgnored;_readyEmitted;_emitRaw;_boundRemove;_nodeFsHandler;constructor(A={}){super();this.closed=!1,this._closers=new Map,this._ignoredPaths=new Set,this._throttled=new Map,this._streams=new Set,this._symlinkPaths=new Map,this._watched=new Map,this._pendingWrites=new Map,this._pendingUnlinks=new Map,this._readyCount=0,this._readyEmitted=!1;let Q=A.awaitWriteFinish,w={stabilityThreshold:2000,pollInterval:100},B={persistent:!0,ignoreInitial:!1,ignorePermissionErrors:!1,interval:100,binaryInterval:300,followSymlinks:!0,usePolling:!1,atomic:!0,...A,ignored:A.ignored?e50(A.ignored):e50([]),awaitWriteFinish:Q===!0?w:typeof Q==="object"?{...w,...Q}:!1};if(UO1)B.usePolling=!0;if(B.atomic===void 0)B.atomic=!B.usePolling;let $=process.env.CHOKIDAR_USEPOLLING;if($!==void 0){let X=$.toLowerCase();if(X==="false"||X==="0")B.usePolling=!1;else if(X==="true"||X==="1")B.usePolling=!0;else B.usePolling=!!X}let f=process.env.CHOKIDAR_INTERVAL;if(f)B.interval=Number.parseInt(f,10);let Y=0;this._emitReady=()=>{if(Y++,Y>=this._readyCount)this._emitReady=a50,this._readyEmitted=!0,process.nextTick(()=>this.emit(Y$.READY))},this._emitRaw=(...X)=>this.emit(Y$.RAW,...X),this._boundRemove=this._remove.bind(this),this.options=B,this._nodeFsHandler=new Cu0(this),Object.freeze(B)}_addIgnoredPath(A){if(yu0(A)){for(let Q of this._ignoredPaths)if(yu0(Q)&&Q.path===A.path&&Q.recursive===A.recursive)return}this._ignoredPaths.add(A)}_removeIgnoredPath(A){if(this._ignoredPaths.delete(A),typeof A==="string"){for(let Q of this._ignoredPaths)if(yu0(Q)&&Q.path===A)this._ignoredPaths.delete(Q)}}add(A,Q,w){let{cwd:B}=this.options;this.closed=!1,this._closePromise=void 0;let $=zO1(A);if(B)$=$.map((f)=>{return ISQ(f,B)});if($.forEach((f)=>{this._removeIgnoredPath(f)}),this._userIgnored=void 0,!this._readyCount)this._readyCount=0;return this._readyCount+=$.length,Promise.all($.map(async(f)=>{let Y=await this._nodeFsHandler._addToNodeFs(f,!w,void 0,0,Q);if(Y)this._emitReady();return Y})).then((f)=>{if(this.closed)return;f.forEach((Y)=>{if(Y)this.add(ew.dirname(Y),ew.basename(Q||Y))})}),this}unwatch(A){if(this.closed)return this;let Q=zO1(A),{cwd:w}=this.options;return Q.forEach((B)=>{if(!ew.isAbsolute(B)&&!this._closers.has(B)){if(w)B=ew.join(w,B);B=ew.resolve(B)}if(this._closePath(B),this._addIgnoredPath(B),this._watched.has(B))this._addIgnoredPath({path:B,recursive:!0});this._userIgnored=void 0}),this}close(){if(this._closePromise)return this._closePromise;this.closed=!0,this.removeAllListeners();let A=[];return this._closers.forEach((Q)=>Q.forEach((w)=>{let B=w();if(B instanceof Promise)A.push(B)})),this._streams.forEach((Q)=>Q.destroy()),this._userIgnored=void 0,this._readyCount=0,this._readyEmitted=!1,this._watched.forEach((Q)=>Q.dispose()),this._closers.clear(),this._watched.clear(),this._streams.clear(),this._symlinkPaths.clear(),this._throttled.clear(),this._closePromise=A.length?Promise.all(A).then(()=>{return}):Promise.resolve(),this._closePromise}getWatched(){let A={};return this._watched.forEach((Q,w)=>{let $=(this.options.cwd?ew.relative(this.options.cwd,w):w)||VO1;A[$]=Q.getChildren().sort()}),A}emitWithAll(A,Q){if(this.emit(A,...Q),A!==Y$.ERROR)this.emit(Y$.ALL,A,...Q)}async _emit(A,Q,w){if(this.closed)return;let B=this.options;if(hu0)Q=ew.normalize(Q);if(B.cwd)Q=ew.relative(B.cwd,Q);let $=[Q];if(w!=null)$.push(w);let f=B.awaitWriteFinish,Y;if(f&&(Y=this._pendingWrites.get(Q)))return Y.lastChange=new Date,this;if(B.atomic){if(A===Y$.UNLINK)return this._pendingUnlinks.set(Q,[A,...$]),setTimeout(()=>{this._pendingUnlinks.forEach((X,W)=>{this.emit(...X),this.emit(Y$.ALL,...X),this._pendingUnlinks.delete(W)})},typeof B.atomic==="number"?B.atomic:100),this;if(A===Y$.ADD&&this._pendingUnlinks.has(Q))A=Y$.CHANGE,this._pendingUnlinks.delete(Q)}if(f&&(A===Y$.ADD||A===Y$.CHANGE)&&this._readyEmitted){let X=(W,H)=>{if(W)A=Y$.ERROR,$[0]=W,this.emitWithAll(A,$);else if(H){if($.length>1)$[1]=H;else $.push(H);this.emitWithAll(A,$)}};return this._awaitWriteFinish(Q,f.stabilityThreshold,A,X),this}if(A===Y$.CHANGE){if(!this._throttle(Y$.CHANGE,Q,50))return this}if(B.alwaysStat&&w===void 0&&(A===Y$.ADD||A===Y$.ADD_DIR||A===Y$.CHANGE)){let X=B.cwd?ew.join(B.cwd,Q):Q,W;try{W=await WSQ(X)}catch(H){}if(!W||this.closed)return;$.push(W)}return this.emitWithAll(A,$),this}_handleError(A){let Q=A&&A.code;if(A&&Q!=="ENOENT"&&Q!=="ENOTDIR"&&(!this.options.ignorePermissionErrors||Q!=="EPERM"&&Q!=="EACCES"))this.emit(Y$.ERROR,A);return A||this.closed}_throttle(A,Q,w){if(!this._throttled.has(A))this._throttled.set(A,new Map);let B=this._throttled.get(A);if(!B)throw Error("invalid throttle");let $=B.get(Q);if($)return $.count++,!1;let f,Y=()=>{let W=B.get(Q),H=W?W.count:0;if(B.delete(Q),clearTimeout(f),W)clearTimeout(W.timeoutObject);return H};f=setTimeout(Y,w);let X={timeoutObject:f,clear:Y,count:0};return B.set(Q,X),X}_incrReadyCount(){return this._readyCount++}_awaitWriteFinish(A,Q,w,B){let $=this.options.awaitWriteFinish;if(typeof $!=="object")return;let f=$.pollInterval,Y,X=A;if(this.options.cwd&&!ew.isAbsolute(A))X=ew.join(this.options.cwd,A);let W=new Date,H=this._pendingWrites;function K(U){XSQ(X,(D,q)=>{if(D||!H.has(A)){if(D&&D.code!=="ENOENT")B(D);return}let b=Number(new Date);if(U&&q.size!==U.size)H.get(A).lastChange=b;let I=H.get(A);if(b-I.lastChange>=Q)H.delete(A),B(void 0,q);else Y=setTimeout(K,f,q)})}if(!H.has(A))H.set(A,{lastChange:W,cancelWait:()=>{return H.delete(A),clearTimeout(Y),w}}),Y=setTimeout(K,f)}_isIgnored(A,Q){if(this.options.atomic&&GSQ.test(A))return!0;if(!this._userIgnored){let{cwd:w}=this.options,$=(this.options.ignored||[]).map(bO1(w)),Y=[...[...this._ignoredPaths].map(bO1(w)),...$];this._userIgnored=VSQ(Y,void 0)}return this._userIgnored(A,Q)}_isntIgnored(A,Q){return!this._isIgnored(A,Q)}_getWatchHelpers(A){return new LO1(A,this.options.followSymlinks,this)}_getWatchedDir(A){let Q=ew.resolve(A);if(!this._watched.has(Q))this._watched.set(Q,new FO1(Q,this._boundRemove));return this._watched.get(Q)}_hasReadPermissions(A){if(this.options.ignorePermissionErrors)return!0;return Boolean(Number(A.mode)&256)}_remove(A,Q,w){let B=ew.join(A,Q),$=ew.resolve(B);if(w=w!=null?w:this._watched.has(B)||this._watched.has($),!this._throttle("remove",B,100))return;if(!w&&this._watched.size===1)this.add(A,Q,!0);this._getWatchedDir(B).getChildren().forEach((U)=>this._remove(B,U));let X=this._getWatchedDir(A),W=X.has(Q);if(X.remove(Q),this._symlinkPaths.has($))this._symlinkPaths.delete($);let H=B;if(this.options.cwd)H=ew.relative(this.options.cwd,B);if(this.options.awaitWriteFinish&&this._pendingWrites.has(H)){if(this._pendingWrites.get(H).cancelWait()===Y$.ADD)return}this._watched.delete(B),this._watched.delete($);let K=w?Y$.UNLINK_DIR:Y$.UNLINK;if(W&&!this._isIgnored(B))this._emit(K,B);this._closePath(B)}_closePath(A){this._closeFile(A);let Q=ew.dirname(A);this._getWatchedDir(Q).remove(ew.basename(A))}_closeFile(A){let Q=this._closers.get(A);if(!Q)return;Q.forEach((w)=>w()),this._closers.delete(A)}_addPathCloser(A,Q){if(!Q)return;let w=this._closers.get(A);if(!w)w=[],this._closers.set(A,w);w.push(Q)}_readdirp(A,Q){if(this.closed)return;let w={type:Y$.ALL,alwaysStat:!0,lstat:!0,...Q,depth:0},B=XO1(A,w);return this._streams.add(B),B.once(KO1,()=>{B=void 0}),B.once(vu0,()=>{if(B)this._streams.delete(B),B=void 0}),B}}function kSQ(A,Q={}){let w=new Eu0(Q);return w.add(A),w}var kO1={watch:kSQ,FSWatcher:Eu0};import{extname as _SQ}from"path";var A90=[".png",".jpg",".jpeg",".webp",".gif",".svg"];function Aj(A){let Q=_SQ(A).toLowerCase();return A90.includes(Q)}function _O1(A){switch(A.toLowerCase().replace(".","")){case"jpg":case"jpeg":return"image/jpeg";case"png":return"image/png";case"gif":return"image/gif";case"webp":return"image/webp";case"svg":return"image/svg+xml";default:return"image/png"}}function Tu0(A){switch(A.toLowerCase()){case"jpeg":return".jpg";case"svg+xml":return".svg";default:return`.${A.toLowerCase()}`}}import{isAbsolute as NSQ,relative as jSQ,sep as NO1,join as PSQ}from"path";function UH(A,Q){return NSQ(Q)?Q:PSQ(A,Q)}function vC(A,Q){let w=UH(A,Q),B=jSQ(A,w);return NO1==="/"?B:B.split(NO1).join("/")}function MSQ(A,Q){if(!vC(Q,A).startsWith("image/"))return!1;return Aj(A)}function OSQ(A,Q){if(vC(Q,A).split("/")[0]?.startsWith("_"))return!1;if(A.endsWith(".md"))return!0;return MSQ(A,Q)}class Su0{watcher;watchCallback;pendingChanges=new Map;batchTimeout;syncPath;watchInterval;logger;onFileChange;constructor(A){this.syncPath=A.syncPath,this.watchInterval=A.watchInterval,this.logger=A.logger,this.onFileChange=A.onFileChange}async start(){if(this.watcher){this.logger.debug("Already watching directory");return}if(this.logger.debug("Starting directory watch",{path:this.syncPath,interval:this.watchInterval}),this.watcher=kO1.watch(this.syncPath,{ignored:/(^|[/\\])\../,persistent:!0,interval:this.watchInterval,awaitWriteFinish:{stabilityThreshold:2000,pollInterval:100}}),this.watcher.on("add",(A)=>void this.handleFileChange("add",A)).on("change",(A)=>void this.handleFileChange("change",A)).on("unlink",(A)=>void this.handleFileChange("delete",A)).on("error",(A)=>this.logger.error("Watcher error",A)),this.watchCallback)this.watcher.on("all",this.watchCallback)}stop(){if(this.watcher)this.watcher.close(),this.watcher=void 0,this.logger.info("Stopped directory watch");if(this.batchTimeout)clearTimeout(this.batchTimeout),this.batchTimeout=void 0}setCallback(A){if(this.watchCallback=A,this.watcher)this.watcher.on("all",A)}async handleFileChange(A,Q){if(!OSQ(Q,this.syncPath))return;this.logger.debug("File change detected",{event:A,path:Q});let w=vC(this.syncPath,Q);if(this.pendingChanges.set(w,A),this.batchTimeout)clearTimeout(this.batchTimeout);this.batchTimeout=setTimeout(()=>{this.processPendingChanges()},500)}async processPendingChanges(){if(this.pendingChanges.size===0)return;let A=new Map(this.pendingChanges);this.pendingChanges.clear(),this.batchTimeout=void 0,this.logger.debug("Processing batched file changes",{changeCount:A.size});for(let[Q,w]of A){let B=UH(this.syncPath,Q);try{if(this.onFileChange)await this.onFileChange(w,B)}catch($){this.logger.error("Error processing file change",{path:Q,event:w,error:$})}}}isWatching(){return!!this.watcher}getPendingChangesCount(){return this.pendingChanges.size}}async function jO1(A,Q){if(A?.isWatching())return Q.logger.debug("Already watching directory"),A;return xSQ(Q)}function PO1(A){if(A)A.stop();return}function MO1(A,Q){if(A)A.setCallback(Q)}async function xSQ(A){let{logger:Q,syncPath:w,watchInterval:B,importEntities:$,jobQueueCallback:f,fileOperations:Y,deleteOnFileRemoval:X}=A,W=new ju0(Q,$,f,Y,X),H=new Su0({syncPath:w,watchInterval:B,logger:Q,onFileChange:async(K,U)=>{await W.handleFileChange(K,U)}});return await H.start(),H}async function OO1(A){let Q=Date.now();A.logger.debug("Starting sync (import only)");let w=await A.importEntities(),B=await A.removeOrphanedEntities(),$=Date.now()-Q;return A.markSynced(new Date),A.logger.debug("Sync completed",{duration:$,imported:w.imported,orphansDeleted:B.deleted}),{export:{exported:0,failed:0,errors:[]},import:w,duration:$}}wA();class mu0{logger;syncPath;deleteOnFileRemoval;constructor(A){this.logger=A.logger,this.syncPath=A.syncPath,this.deleteOnFileRemoval=A.deleteOnFileRemoval}prepareBatchOperations(A){let Q=[],w=this.createImportOperations(A);Q.push(...w);let B=w.length;if(this.deleteOnFileRemoval)Q.push({type:"directory-cleanup",data:{}});let $=A.length;return this.logger.debug("Prepared batch operations",{exportOperationsCount:0,importOperationsCount:B,totalFiles:$}),{operations:Q,exportOperationsCount:0,importOperationsCount:B,totalFiles:$}}async queueSyncBatch(A,Q,w,B){let $=this.prepareBatchOperations(w);if($.operations.length===0)return this.logger.debug("No sync operations needed",{source:Q}),null;return{batchId:await A.jobs.enqueueBatch($.operations,{source:Q,rootJobId:B?.rootJobId??Z4(),metadata:{progressToken:B?.progressToken,operationType:"file_operations",operationTarget:this.syncPath,pluginId:B?.pluginId??"directory-sync",interfaceType:B?.interfaceType,channelId:B?.channelId}}),operationCount:$.operations.length,exportOperationsCount:$.exportOperationsCount,importOperationsCount:$.importOperationsCount,totalFiles:$.totalFiles}}createImportOperations(A){if(A.length===0)return[];let Q=50,w=[];for(let B=0;B<A.length;B+=Q){let $=A.slice(B,B+Q);w.push({type:"directory-import",data:{batchIndex:Math.floor(B/Q),paths:$,batchSize:$.length}})}return w}}class uu0{syncInProgress=!1;logger;fileOperations;batchOperationsManager;constructor(A){this.logger=A.logger,this.fileOperations=A.fileOperations,this.batchOperationsManager=new mu0({logger:A.logger,syncPath:A.syncPath,deleteOnFileRemoval:A.deleteOnFileRemoval})}async queueSyncBatch(A,Q,w){if(this.syncInProgress)return this.logger.debug("Sync already in progress, skipping",{source:Q}),null;this.syncInProgress=!0;try{let B=await this.fileOperations.getAllSyncFiles();return await this.batchOperationsManager.queueSyncBatch(A,Q,B,w)}finally{this.syncInProgress=!1}}}class cu0{options;constructor(A){this.options=A}createExportDeps(A,Q){return{entityService:this.options.entityService,logger:this.options.logger,fileOperations:this.options.fileOperations,deleteOnFileRemoval:A,entityTypes:Q}}createImportDeps(A){return{entityService:this.options.entityService,logger:this.options.logger,fileOperations:this.options.fileOperations,quarantine:this.options.quarantine,imageJobQueue:this.createImageJobQueueDeps(),entityTypes:A}}createCleanupDeps(A,Q){return{entityService:this.options.entityService,logger:this.options.logger,fileOperations:this.options.fileOperations,deleteOnFileRemoval:A,entityTypes:Q}}createImageJobQueueDeps(){return{logger:this.options.logger,syncPath:this.options.syncPath,jobQueueCallback:this.options.getJobQueueCallback(),coverImageConverter:this.options.coverImageConverter,inlineImageConverter:this.options.inlineImageConverter}}}import{basename as ySQ,dirname as ESQ,extname as TSQ}from"path";import{extname as RSQ}from"path";var Q90=[".pdf"],xO1=".meta.json";function Qj(A){let Q=RSQ(A).toLowerCase();return Q90.includes(Q)}function RO1(A){return A.toLowerCase().endsWith(xO1)}function lu0(A){return`${A}${xO1}`}function vO1(A){switch(A.toLowerCase().replace(".","")){case"pdf":default:return"application/pdf"}}import{extname as vSQ,join as w90}from"path";function B90(A,Q){let B=vC(A,Q).split("/"),$,f;if(B.length===1)$="note",f=B;else if(B.length>1&&B[0])$=B[0],f=B.slice(1);else $="note",f=B;let Y;if(f.length>1){let X=f[f.length-1];if(X)f[f.length-1]=hO1(X);Y=f.join(":")}else Y=hO1(f[0]??"");return{entityType:$,id:Y}}function CO1(A,Q,w,B=".md"){let $=Q.split(":").filter((H)=>H.length>0),f=w==="note";if($.length===1)return f?w90(A,`${$[0]}${B}`):w90(A,w,`${$[0]}${B}`);let Y=$;if($[0]===w)Y=$.slice(1);let X=Y[Y.length-1],W=Y.slice(0,-1);if(f)return w90(A,...W,`${X}${B}`);return w90(A,w,...W,`${X}${B}`)}function gO1(A){if(A.entityType==="document")return".pdf";if(A.entityType!=="image")return".md";let Q=A.metadata.format;if(Q)return Tu0(Q);let w=A.content.match(/^data:image\/([a-z+]+);base64,/i);return w?.[1]?Tu0(w[1]):".md"}function hO1(A){let Q=vSQ(A).toLowerCase();return Q===".md"||A90.includes(Q)||Q90.includes(Q)?A.slice(0,-Q.length):A}N0();xX();import{mkdir as SSQ,readFile as hC,writeFile as iu0,stat as mSQ,utimes as uSQ}from"fs/promises";import{join as $90}from"path";import{mkdir as yO1,readdir as CSQ,stat as gSQ}from"fs/promises";import{access as hSQ}from"fs/promises";async function i8(A){try{return await hSQ(A),!0}catch{return!1}}async function pu0(A,Q){return mO1(A,Q,{includeDocuments:!1,includeImages:!1})}async function EO1(A,Q){return mO1(A,Q,{includeDocuments:!0,includeImages:!0})}async function TO1(A,Q){if(!await i8(A))await yO1(A,{recursive:!0});for(let w of Q)if(w!=="note")await yO1($90(A,w),{recursive:!0})}async function SO1(A,Q){let w=[],B={totalFiles:0,byEntityType:{}};if(!await i8(A))return{files:w,stats:B};let $=await pu0(A,Q);for(let f of $)try{let Y=$90(A,f),X=await gSQ(Y),{entityType:W}=B90(A,f);w.push({path:f,entityType:W,modified:X.mtime}),B.totalFiles++,B.byEntityType[W]=(B.byEntityType[W]??0)+1}catch{continue}return{files:w,stats:B}}async function mO1(A,Q,w){let B=[];if(!await i8(A))return B;let $=async(f,Y="",X=!1,W=!1)=>{let H=await CSQ(f,{withFileTypes:!0});for(let K of H){let U=Y?$90(Y,K.name):K.name;if(K.isFile()&&!K.name.endsWith(".invalid")&&!RO1(K.name)){if(K.name.endsWith(".md"))B.push(U);else if(w.includeImages&&X&&Aj(K.name))B.push(U);else if(w.includeDocuments&&W&&Qj(K.name))B.push(U)}else if(K.isDirectory()&&!K.name.startsWith(".")){if(Y===""&&!Q.hasEntityType(K.name))continue;let D=$90(f,K.name),q=K.name==="image"&&Y==="",b=K.name==="document"&&Y==="";await $(D,U,X||q,W||b)}}};return await $(A),B}var cSQ=Z.record(Z.string(),Z.unknown());class du0{syncPath;entityService;constructor(A,Q){this.syncPath=A,this.entityService=Q}parseEntityFromPath(A){return B90(this.syncPath,A)}async readEntity(A){let Q=UH(this.syncPath,A),w=await mSQ(Q),{entityType:B,id:$}=this.parseEntityFromPath(A),f=w.birthtime.getTime()>0?w.birthtime:w.mtime,Y=w.mtime,X,W;if(Aj(A)||Qj(A)){let U=(await hC(Q)).toString("base64"),D=TSQ(A);if(X=`data:${Qj(A)?vO1(D):_O1(D)};base64,${U}`,Qj(A))W=await this.readDocumentSidecar(Q,A)}else X=await hC(Q,"utf-8");let H={entityType:B,id:$,content:X,created:f,updated:Y};if(W)H.metadata=W;return H}async readDocumentSidecar(A,Q){let w={mimeType:"application/pdf",filename:ySQ(Q)},B=lu0(A);if(!await i8(B))return w;try{let $=await hC(B,"utf-8"),f=cSQ.safeParse(JSON.parse($));return{...w,...f.success?f.data:{}}}catch{return w}}async writeEntity(A){let Q=this.getEntityFilePath(A),w=A.entityType==="image",B=A.entityType==="document";if(w||B){let f=w?/^data:image\/[a-z+]+;base64,(.+)$/i:/^data:application\/pdf;base64,(.+)$/i,Y=A.content.match(f),X=Y?.[1]?Buffer.from(Y[1],"base64"):Buffer.from(A.content,"base64"),W=!1;if(await i8(Q)){let H=await hC(Q),K=w6(H.toString("base64")),U=w6(X.toString("base64"));if(K===U)W=!0}if(!W)await this.ensureEntityDirectory(A,Q),await iu0(Q,X);if(B)await this.writeDocumentSidecar(A,Q);if(W)return}else{let f=this.entityService.serializeEntity(A);if(await i8(Q)){let Y=await hC(Q,"utf-8"),X=w6(Y),W=w6(f);if(X===W)return}await this.ensureEntityDirectory(A,Q),await iu0(Q,f,"utf-8")}let $=new Date(A.updated);await uSQ(Q,$,$)}async ensureEntityDirectory(A,Q){if(A.entityType!=="note")await SSQ(ESQ(Q),{recursive:!0})}async writeDocumentSidecar(A,Q){let w=A.metadata,B={};for(let[Y,X]of Object.entries(w)){if(Y==="mimeType")continue;if(X===void 0)continue;B[Y]=X}let $=lu0(Q),f=`${JSON.stringify(B,null,2)}
4750
4750
  `;if(await i8($)){if(await hC($,"utf-8")===f)return}await this.ensureEntityDirectory(A,$),await iu0($,f,"utf-8")}getFilePath(A,Q,w=".md"){return CO1(this.syncPath,A,Q,w)}getEntityFilePath(A){return this.getFilePath(A.id,A.entityType,gO1(A))}async getAllMarkdownFiles(){return pu0(this.syncPath,this.entityService)}async getAllSyncFiles(){return EO1(this.syncPath,this.entityService)}async ensureDirectoryStructure(A){await TO1(this.syncPath,A)}shouldUpdateEntity(A,Q){let w=w6(Q.content);return A.contentHash!==w}async gatherFileStatus(){return SO1(this.syncPath,this.entityService)}async syncDirectoryExists(){return i8(this.syncPath)}async fileExists(A){return i8(A)}}J4();N0();S9();K2();J4();async function f90(A,Q,w,B){let{sourceUrl:$}=A,f=await Q.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:$}},limit:1}});if(f[0])return B.debug("Reusing existing image entity",{sourceUrl:$,imageId:f[0].id}),f[0].id;let Y=await w($),{base64:X}=sV(Y),W=ik(X),H=aV(X);if(!W||!H)throw Error("Could not detect image format or dimensions");let K=await Q.createEntity({entity:{id:A.id,entityType:"image",content:Y,metadata:{title:A.title,alt:A.alt,format:W,width:H.width,height:H.height,sourceUrl:$}}});return B.debug("Created image entity from URL",{sourceUrl:$,imageId:K.entityId}),K.entityId}var uO1=Z.object({title:Z.string(),slug:Z.string().optional(),coverImageUrl:Z.url(),coverImageId:Z.string().optional(),coverImageAlt:Z.string().optional()});class nu0{entityService;fetcher;logger;constructor(A,Q,w=TW){this.entityService=A,this.fetcher=w,this.logger=Q.child("FrontmatterImageConverter")}detectCoverImageUrl(A){let Q;try{Q=j6(A)}catch{return null}let{frontmatter:w}=Q,B=uO1.safeParse(w);if(!B.success)return null;if(B.data.coverImageId)return null;let{title:$,slug:f,coverImageUrl:Y,coverImageAlt:X}=B.data;if(!pk(Y))return null;return{sourceUrl:Y,postTitle:$,postSlug:f??Z1($),customAlt:X}}async convert(A){let Q;try{Q=j6(A)}catch(H){return this.logger.debug("Parse failed",{error:H}),{content:A,converted:!1}}let{frontmatter:w}=Q,B=uO1.safeParse(w);if(!B.success)return{content:A,converted:!1};if(B.data.coverImageId)return{content:A,converted:!1};let{title:$,slug:f,coverImageUrl:Y,coverImageAlt:X}=B.data;if(!pk(Y))return{content:A,converted:!1};let W={postTitle:$,postSlug:f??Z1($),sourceUrl:Y,customAlt:X};try{let H=await this.createImageEntity(W),K={...w};return delete K.coverImageUrl,delete K.coverImageAlt,K.coverImageId=H,{content:Gk(K,Q.content),converted:!0,imageId:H}}catch(H){return this.logger.warn("Failed to convert coverImageUrl",{url:Y,error:mA(H)}),{content:A,converted:!1}}}async createImageEntity(A){let{postTitle:Q,postSlug:w,sourceUrl:B,customAlt:$}=A,f=`Cover image for ${Q}`;return f90({id:`${w}-cover`,title:f,alt:$??f,sourceUrl:B},this.entityService,this.fetcher,this.logger)}}J4();class vd{entityService;fetcher;logger;constructor(A,Q,w=TW){this.entityService=A,this.fetcher=w,this.logger=Q.child("MarkdownImageConverter")}detectInlineImages(A,Q){let w=[],B=$N0(A);for(let $ of B){if(!pk($.url))continue;if($.url.startsWith("entity://"))continue;let f=this.reconstructMarkdown($);w.push({sourceUrl:$.url,alt:$.alt,originalMarkdown:f,postSlug:Q})}return w}reconstructMarkdown(A){if(A.title)return`![${A.alt}](${A.url} "${A.title}")`;return`![${A.alt}](${A.url})`}async convert(A,Q){let w=this.detectInlineImages(A,Q);if(w.length===0)return{content:A,converted:!1,convertedCount:0};let B=A,$=0,f=0;for(let Y of w)try{let X=await this.createImageEntity(Y,f++),W=`![${Y.alt}](entity://image/${X})`;B=B.replace(Y.originalMarkdown,W),$++,this.logger.debug("Converted inline image",{sourceUrl:Y.sourceUrl,imageId:X})}catch(X){this.logger.warn("Failed to convert inline image",{sourceUrl:Y.sourceUrl,error:mA(X)})}return{content:B,converted:$>0,convertedCount:$}}async createImageEntity(A,Q){let{sourceUrl:w,alt:B,postSlug:$}=A;return f90({id:`${$}-inline-${Q}`,title:B||`Inline image ${Q+1} for ${$}`,alt:B||"",sourceUrl:w},this.entityService,this.fetcher,this.logger)}}class ru0{logger;entityService;fileOperations;constructor(A,Q,w){this.logger=A,this.entityService=Q,this.fileOperations=w}async importEntitiesWithProgress(A,Q,w,B){this.logger.debug("Importing entities with progress reporting");let $={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},f=A??await this.fileOperations.getAllSyncFiles(),Y=f.length;await Q.report({progress:0,message:`Starting import of ${Y} files`});for(let X=0;X<Y;X+=w){let W=f.slice(X,X+w),H=await B(W);$.imported+=H.imported,$.skipped+=H.skipped,$.failed+=H.failed,$.quarantined+=H.quarantined,$.errors.push(...H.errors),$.quarantinedFiles.push(...H.quarantinedFiles),$.jobIds.push(...H.jobIds);let K=Math.min(X+w,Y),U=Math.round(K/Y*40);await Q.report({progress:U,message:`Imported ${K}/${Y} files`})}return $}async exportEntitiesWithProgress(A,Q,w,B){this.logger.debug("Exporting entities with progress reporting");let $=A??this.entityService.getEntityTypes();await Q.report({progress:50,message:`Starting export of ${$.length} entity types`});let f=await B(A);return await Q.report({progress:100,message:`Exported ${f.exported} entities`}),this.logger.debug("Export completed",f),f}}wA();import{rename as lSQ,appendFile as pSQ,readFile as iSQ,writeFile as dSQ,access as nSQ}from"fs/promises";import{join as cO1}from"path";class ou0{logger;syncPath;constructor(A,Q){this.logger=A,this.syncPath=Q}isValidationError(A){return XA0(A)}async quarantineInvalidFile(A,Q,w,B){let $=B(A),f=`${$}.invalid`;try{await lSQ($,f),w.quarantined++,w.quarantinedFiles.push(A);let Y=cO1(this.syncPath,".import-errors.log"),X=new Date().toISOString(),W=mA(Q),H=`${X} - ${A}: ${W}
4751
4751
  \u2192 ${A}.invalid
@@ -4774,7 +4774,7 @@ details.web-chat-data-part[open] > summary > .web-chat-data-part-chevron {
4774
4774
  *...and ${A.files.length-10} more files*`)}if(A.exists&&A.stats.totalFiles===0)Q.push(`
4775
4775
  ## Getting Started
4776
4776
  `),Q.push("Your sync directory is empty. Entities will be organized as follows:"),Q.push("- Base entities: `/<entity-id>.md`"),Q.push("- Other types: `/<entity-type>/<entity-id>.md`");return Q.join(`
4777
- `)}}wA();class x90 extends aw{directorySync;constructor(A,Q,w){super(A,{schema:ac0,jobTypeName:"directory-export"});this.directorySync=w}async process(A,Q,w){this.logger.debug("Processing directory export job",{jobId:Q,data:A});let B=Date.now();try{let $=await this.directorySync.exportEntitiesWithProgress(A.entityTypes,w,A.batchSize??100);return this.logger.debug("Directory export job completed",{jobId:Q,exported:$.exported,failed:$.failed,duration:Date.now()-B}),$}catch($){throw this.logger.error("Directory export job failed",{jobId:Q,error:$}),$}}summarizeDataForLog(A){return{entityTypes:A.entityTypes??"all",batchSize:A.batchSize}}}wA();class R90 extends aw{directorySync;constructor(A,Q,w){super(A,{schema:sc0,jobTypeName:"directory-import"});this.directorySync=w}async process(A,Q,w){this.logger.debug("Processing directory import job",{jobId:Q,data:A});let B=Date.now();try{let $=await this.directorySync.importEntitiesWithProgress(A.paths,w,A.batchSize??100);return this.logger.debug("Directory import job completed",{jobId:Q,imported:$.imported,skipped:$.skipped,failed:$.failed,quarantined:$.quarantined,duration:Date.now()-B}),$}catch($){throw this.logger.error("Directory import job failed",{jobId:Q,error:$}),$}}summarizeDataForLog(A){return{pathCount:A.paths?.length??"all",batchSize:A.batchSize}}}wA();class v90 extends aw{directorySync;context;constructor(A,Q,w){super(A,{schema:rc0,jobTypeName:"directory-sync"});this.context=Q,this.directorySync=w}async process(A,Q,w){let B=Date.now(),$=A.syncDirection??"both";this.logger.info("Starting directory sync job",{jobId:Q,operation:A.operation,syncDirection:$});let f={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},Y={exported:0,failed:0,errors:[]};if($!=="export")if(await w.report({progress:10,message:"Scanning directory for changes"}),f=await this.importWithProgress(A.paths,w),$==="import")await this.waitForImportJobs(f.jobIds,w),await w.report({progress:100,message:`Import complete: ${f.imported} imported`});else await w.report({progress:50,message:`Imported ${f.imported} entities`}),await this.waitForImportJobs(f.jobIds,w),await w.report({progress:56,message:"Processing complete, starting export"});if($!=="import"){let W=$==="export"?10:60;await w.report({progress:W,message:"Exporting entities to directory"}),Y=await this.exportWithProgress(A.entityTypes,w),await w.report({progress:100,message:$==="export"?`Export complete: ${Y.exported} exported`:`Sync complete: ${f.imported} imported, ${Y.exported} exported`})}let X=Date.now()-B;return this.logger.info("Directory sync job completed",{jobId:Q,duration:X,imported:f.imported,exported:Y.exported}),{import:f,export:Y,duration:X}}async importWithProgress(A,Q){try{return await this.directorySync.importEntitiesWithProgress(A,Q,10)}catch(w){throw this.logger.error("Import phase failed",{error:w}),w}}async exportWithProgress(A,Q){try{return await this.directorySync.exportEntitiesWithProgress(A,Q,10)}catch(w){throw this.logger.error("Export phase failed",{error:w}),w}}async waitForImportJobs(A,Q){if(A.length===0)return;this.logger.debug(`Waiting for ${A.length} import jobs to complete`);let{entityService:w}=this.context,B=300000,$=500,f=Date.now(),Y=async()=>{let W=(await Promise.all(A.map((K)=>w.getAsyncJobStatus(K)))).filter((K)=>K&&(K.status==="completed"||K.status==="failed")).length;if(W===A.length){this.logger.debug("All import jobs completed");return}if(Date.now()-f>B){this.logger.warn(`Timeout waiting for import jobs (${W}/${A.length} completed)`);return}let H=Math.round(W/A.length*100);return await Q.report({progress:50+Math.round(H*0.05),message:`Processing ${W}/${A.length} entities`}),await new Promise((K)=>setTimeout(K,$)),Y()};return Y()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}wA();class h90 extends aw{context;directorySync;gitSync;constructor(A,Q,w,B){super(A,{schema:oc0,jobTypeName:"sync-request"});this.context=Q,this.directorySync=w,this.gitSync=B}async process(A,Q,w){await w.report({progress:5,message:"Pulling latest content from git"});let B=await this.gitSync.withLock(async()=>{return await this.gitSync.pull(),await w.report({progress:35,message:"Scanning pulled content for sync changes"}),this.directorySync.queueSyncBatch(this.context,A.source,{rootJobId:Q,interfaceType:A.interfaceType,channelId:A.channelId})});if(!B)return await w.report({progress:100,message:"Sync complete: no files to import"}),{gitPulled:!0,batchQueued:!1};return await w.report({progress:100,message:`Sync queued: ${B.importOperationsCount} import jobs for ${B.totalFiles} files`}),KpQ(B)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function KpQ(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}wA();class C90 extends aw{context;constructor(A,Q,w){super(A,{schema:M90,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,w){let B=M90.parse(A);this.logger.info("Processing entity deletion for removed file",{entityId:B.entityId,entityType:B.entityType,filePath:B.filePath}),await w.report({progress:0,total:1,message:`Deleting ${B.entityType}:${B.entityId}`});try{let $=await this.context.entityService.deleteEntity({entityType:B.entityType,id:B.entityId});if($)this.logger.info("Successfully deleted entity for removed file",{entityId:B.entityId,entityType:B.entityType});else this.logger.warn("Entity not found in database",{entityId:B.entityId,entityType:B.entityType});return await w.report({progress:1,total:1,message:`Deleted ${B.entityType}:${B.entityId}`}),{deleted:$,entityId:B.entityId,entityType:B.entityType,filePath:B.filePath}}catch($){throw this.logger.error("Failed to delete entity",{entityId:B.entityId,entityType:B.entityType,error:$}),$}}summarizeDataForLog(A){return{entityId:A.entityId,entityType:A.entityType,filePath:A.filePath}}}wA();N0();var UpQ=Z.object({});class g90 extends aw{directorySync;constructor(A,Q){super(A,{schema:UpQ,jobTypeName:"directory-cleanup"});this.directorySync=Q}async process(A,Q,w){await w.report({progress:0,message:"Removing orphaned entities"});let B=await this.directorySync.removeOrphanedEntities();return await w.report({progress:100,message:`Cleanup complete: ${B.deleted} orphans removed`}),B}}wA();J4();S9();g6();N0();J4();import{readFile as DpQ,writeFile as GpQ}from"fs/promises";var zpQ=tc0,qpQ=Z.record(Z.string(),Z.unknown());class y90 extends aw{context;fetcher;constructor(A,Q,w=TW){super(Q,{schema:zpQ,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=w}async process(A,Q,w){let{filePath:B,sourceUrl:$,postTitle:f,postSlug:Y,customAlt:X}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:B,sourceUrl:$,postSlug:Y});try{await this.reportProgress(w,{progress:dQ.INIT,message:`Reading file: ${B}`});let W;try{W=await DpQ(B,"utf-8")}catch(V){return this.logger.error("Failed to read file",{filePath:B,error:mA(V)}),Q$.failure(V)}let H;try{H=j6(W)}catch(V){return this.logger.warn("Failed to parse markdown",{filePath:B,error:mA(V)}),Q$.failure(V)}let K=qpQ.safeParse(H.frontmatter),U=K.success?K.data:{};if(U.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:B}),await this.reportProgress(w,{progress:dQ.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(w,{progress:dQ.FETCH,message:"Checking for existing image"});let D=await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:$}},limit:1}}),q;if(D[0])q=D[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:$,imageId:q}),await this.reportProgress(w,{progress:dQ.EXTRACT,message:`Reusing existing image: ${q}`});else{await this.reportProgress(w,{progress:dQ.PROCESS,message:`Fetching image from ${$}`});let V;try{V=await this.fetcher($)}catch(h){return this.logger.error("Failed to fetch image",{sourceUrl:$,error:mA(h)}),Q$.failure(h)}await this.reportProgress(w,{progress:dQ.GENERATE,message:"Creating image entity"});let{base64:L}=sV(V),N=ik(L),k=aV(L);if(!N||!k)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:$}),Q$.failure(Error("Could not detect image format or dimensions"));q=`${Y}-cover`;let x=`Cover image for ${f}`,R=X??x;await this.context.entityService.createEntity({entity:{id:q,entityType:"image",content:V,metadata:{title:x,alt:R,format:N,width:k.width,height:k.height,sourceUrl:$}}}),this.logger.debug("Created image entity",{imageId:q,sourceUrl:$}),await this.reportProgress(w,{progress:dQ.EXTRACT,message:`Created image: ${q}`})}await this.reportProgress(w,{progress:dQ.SAVE,message:"Updating file"});let b={...U};delete b.coverImageUrl,delete b.coverImageAlt,b.coverImageId=q;let I=Gk(b,H.content);try{await GpQ(B,I,"utf-8")}catch(V){return this.logger.error("Failed to write file",{filePath:B,error:mA(V)}),Q$.failure(V)}return await this.reportProgress(w,{progress:dQ.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:B,imageId:q,sourceUrl:$}),{success:!0,imageId:q}}catch(W){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:B,error:mA(W)}),Q$.failure(W)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}wA();J4();g6();import{readFile as bpQ,writeFile as VpQ}from"fs/promises";class E90 extends aw{converter;constructor(A,Q,w=TW){super(Q,{schema:ec0,jobTypeName:"inline-image-convert"});this.converter=new vd(A.entityService,Q,w)}async process(A,Q,w){let{filePath:B,postSlug:$}=A;this.logger.debug("Starting inline image conversion job",{jobId:Q,filePath:B,postSlug:$});try{await this.reportProgress(w,{progress:dQ.INIT,message:`Reading file: ${B}`});let f;try{f=await bpQ(B,"utf-8")}catch(W){let H=mA(W);return this.logger.error("Failed to read file",{filePath:B,error:H}),{success:!1,error:H}}await this.reportProgress(w,{progress:dQ.FETCH,message:"Detecting inline images"});let Y=this.converter.detectInlineImages(f,$);if(Y.length===0)return this.logger.debug("No inline images to convert",{filePath:B}),await this.reportProgress(w,{progress:dQ.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:B,count:Y.length}),await this.reportProgress(w,{progress:dQ.PROCESS,message:`Converting ${Y.length} images`});let X=await this.converter.convert(f,$);if(!X.converted)return this.logger.debug("No images were converted",{filePath:B}),await this.reportProgress(w,{progress:dQ.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(w,{progress:dQ.SAVE,message:"Writing updated file"});try{await VpQ(B,X.content,"utf-8")}catch(W){let H=mA(W);return this.logger.error("Failed to write file",{filePath:B,error:H}),{success:!1,error:H}}return await this.reportProgress(w,{progress:dQ.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:B,convertedCount:X.convertedCount}),{success:!0,convertedCount:X.convertedCount}}catch(f){let Y=mA(f);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:B,error:Y}),{success:!1,error:Y}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function jh1(A,Q,w){let B=($)=>w.child($);A.jobs.registerHandler("directory-sync",new v90(B("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new x90(B("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new R90(B("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new C90(B("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new g90(B("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new y90(A,B("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new E90(A,B("InlineImageConversionJobHandler"))),w.debug("Registered async job handlers")}wA();N0();import{unlink as IpQ,access as JpQ}from"fs/promises";var FpQ=Z.record(Z.string(),Z.unknown());function Ph1(A,Q,w,B){let{subscribe:$}=A.messaging,{entityService:f}=A;$("entity:created",async(Y)=>{let{entity:X}=Y.payload;try{await Q.fileOps.writeEntity(X),w.debug("Auto-exported created entity",{id:X.id,entityType:X.entityType})}catch(W){w.error("Auto-export FAILED for created entity",{id:X.id,entityType:X.entityType,error:W instanceof Error?W.message:String(W),stack:W instanceof Error?W.stack:void 0})}return{success:!0}}),$("entity:updated",async(Y)=>{let{entityType:X,entityId:W}=Y.payload;try{let H=await f.getEntity({entityType:X,id:W});if(!H)return w.debug("Entity not found in DB, skipping export",{entityType:X,entityId:W}),{success:!1};await Q.fileOps.writeEntity(H),w.debug("Auto-exported updated entity",{id:H.id,entityType:H.entityType})}catch(H){w.error("Auto-export FAILED for updated entity",{entityType:X,entityId:W,error:H instanceof Error?H.message:String(H),stack:H instanceof Error?H.stack:void 0})}return{success:!0}}),$("entity:deleted",async(Y)=>{let{entityId:X,entityType:W}=Y.payload,H=Q.fileOps.getFilePath(X,W);if(await JpQ(H).then(()=>!0,()=>!1))await IpQ(H),w.debug("Auto-deleted entity file",{id:X,entityType:W,path:H});return{success:!0}}),w.debug("Setup auto-sync for entity events",{entityTypes:B})}function Mh1(A,Q,w){Q.setJobQueueCallback(async(B)=>{let $=[{type:B.type,data:FpQ.parse(B.data)}];return A.jobs.enqueueBatch($,{priority:5,source:"directory-sync-watcher",rootJobId:Z4(),metadata:{operationType:"file_operations",operationTarget:w,pluginId:"directory-sync"}})})}wA();import{readdir as Rh1,mkdir as kpQ,copyFile as _pQ}from"fs/promises";import{join as xh1,resolve as Al0}from"path";import{join as LpQ}from"path";async function Oh1(A){if(!await i8(LpQ(A,".git")))return!1;try{return await YU(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function NpQ(A,Q){if(!await i8(A))return!0;if((await Rh1(A)).filter(($)=>!$.startsWith(".")&&!$.startsWith("_")).length>0)return!1;if(await Oh1(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function vh1(A,Q){let w=await Rh1(A,{withFileTypes:!0});for(let B of w){let $=xh1(A,B.name),f=xh1(Q,B.name);if(B.isDirectory()){if(!await i8(f))await kpQ(f,{recursive:!0});await vh1($,f)}else await _pQ($,f)}}async function hh1(A,Q,w){let B=Al0(process.cwd(),A);w=w?Al0(w):Al0(process.cwd(),"seed-content");let $=await NpQ(B,Q);if($&&await i8(w))Q.debug("Copying seed content to brain-data directory"),await vh1(w,B),Q.debug("Seed content copied successfully");else if($)Q.debug("No seed content directory found, starting with empty brain-data");else Q.debug("brain-data directory not empty, skipping seed content")}function Ch1(A,Q,w,B,$){let f=!1,Y=async()=>{if(f)return;f=!0;let X=Q();if(w.seedContent){let W=w.syncPath??A.dataDir;await hh1(W,B,w.seedContentPath)}try{if($){B.debug("Git enabled \u2014 pulling before import");let H=await $.pull();if(H.files.length>0)B.info("Pulled changes from remote",{filesChanged:H.files.length})}B.debug("Starting initial sync");let W=await X.sync();B.debug("Initial sync completed",{imported:W.import.imported,failed:W.import.failed,duration:W.duration}),await A.messaging.send({type:Vk.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(W){B.error("Initial sync failed",W),await A.messaging.send({type:Vk.initialSyncCompleted,payload:{success:!1,error:mA(W)},...{broadcast:!0}})}};A.messaging.subscribe(Vk.pluginsRegistered,async()=>{return B.debug("Plugins registered, starting initial sync"),await Y(),{success:!0}})}class nd{fn;delayMs;timeout;pending=!1;constructor(A,Q){this.fn=A,this.delayMs=Q}trigger(){if(!this.timeout){this.fn(),this.timeout=setTimeout(()=>{if(this.timeout=void 0,this.pending)this.pending=!1,this.fn()},this.delayMs);return}this.pending=!0,clearTimeout(this.timeout),this.timeout=setTimeout(()=>{if(this.timeout=void 0,this.pending)this.pending=!1,this.fn()},this.delayMs)}dispose(){if(this.timeout)clearTimeout(this.timeout),this.timeout=void 0;this.pending=!1}}function gh1(A,Q,w,B){let $=new nd(()=>{Q.withLock(async()=>{try{await Q.commit(),await Q.push()}catch(X){B.error("Git auto-commit failed",{error:X})}})},w),f=["entity:created","entity:updated","entity:deleted"],Y=[];for(let X of f){let W=A.subscribe(X,async()=>{return $.trigger(),{success:!0}});Y.push(W)}return()=>{$.dispose();for(let X of Y)X()}}function yh1(A,Q,w,B,$){if(B<=0)return()=>{};let f=B*60*1000,Y=!1,X=async()=>{if(Y)return;Y=!0;try{let{files:H,result:K}=await A.withLock(async()=>{let U=await A.pull();if(U.files.length===0)return{files:[],result:null};let D=await Q.queueSyncBatch(w,"periodic-sync");return{files:U.files,result:D}});if(H.length>0)$.info("Periodic sync: pulled changes",{filesChanged:H.length});if(K)$.debug("Periodic sync: queued imports",{importOperations:K.importOperationsCount,totalFiles:K.totalFiles})}catch(H){$.error("Periodic git sync failed",{error:H})}finally{Y=!1}},W=setInterval(()=>{X()},f);return $.info("Started periodic git sync",{intervalMinutes:B}),()=>{clearInterval(W)}}import{spawnSync as Th1}from"child_process";import{cpSync as jpQ,existsSync as Eh1,mkdirSync as PpQ,mkdtempSync as MpQ,rmSync as OpQ}from"fs";import{tmpdir as xpQ}from"os";import{fileURLToPath as RpQ}from"url";import{join as vpQ,resolve as hpQ}from"path";function pJ(A,Q){let w=Th1("git",Q,{cwd:A,stdio:"pipe"});if(w.status!==0){let B=w.stderr.toString().trim(),$=w.stdout.toString().trim();throw Error(B||$||`git ${Q.join(" ")} failed`)}}function CpQ(A){return A.startsWith("file://")}function gpQ(A){return RpQ(A)}function ypQ(A,Q){return Th1("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function Sh1(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!CpQ(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",w=gpQ(A.gitUrl),B=hpQ(A.seedContentPath);if(!Eh1(B))throw Error(`Seed content path not found: ${B}`);if(!Eh1(w))A.logger.debug("Creating local bare content remote",{remotePath:w,branch:Q}),PpQ(w,{recursive:!0}),pJ(process.cwd(),["init","--bare",`--initial-branch=${Q}`,w]);if(ypQ(w,Q)){A.logger.debug("Content remote already initialized",{remotePath:w,branch:Q});return}A.logger.debug("Seeding local content remote",{remotePath:w,seedPath:B,branch:Q});let $=MpQ(vpQ(xpQ(),"directory-sync-seed-"));try{pJ($,["init",`--initial-branch=${Q}`]),pJ($,["config","user.name",A.authorName??"Brain"]),pJ($,["config","user.email",A.authorEmail??"brain@localhost"]),jpQ(B,$,{recursive:!0}),pJ($,["add","."]),pJ($,["commit","-m","seed content remote"]),pJ($,["remote","add","origin",A.gitUrl]),pJ($,["push","-u","origin",Q])}finally{OpQ($,{recursive:!0,force:!0})}}function mh1(A,Q,w,B,$){let{subscribe:f}=A.messaging;f("entity:export:request",async(Y)=>{try{return{success:!0,data:await Q().exportEntities(Y.payload.entityTypes)}}catch(X){return{success:!1,error:X instanceof Error?X.message:"Export failed"}}}),f("entity:import:request",async(Y)=>{try{let X=Q(),W=Y.payload.paths,H=await X.importEntities(W);if(W&&W.length>0)await X.removeOrphanedEntities();return{success:!0,data:H}}catch(X){return{success:!1,error:X instanceof Error?X.message:"Import failed"}}}),f("sync:status:request",async()=>{try{let X=await Q().getStatus();return{success:!0,data:{syncPath:X.syncPath,isInitialized:X.exists,watchEnabled:X.watching}}}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:"Status check failed"}}}),f("sync:configure:request",async(Y)=>{try{return await w({syncPath:Y.payload.syncPath}),{success:!0,data:{syncPath:Y.payload.syncPath,configured:!0}}}catch(X){return{success:!1,error:X instanceof Error?X.message:"Configuration failed"}}}),f("git-sync:get-repo-info",async()=>{if(!$?.repo)return{success:!1,error:"Git not configured"};return{success:!0,data:{repo:$.repo,branch:$.branch??"main"}}}),B.debug("Registered message handlers")}wA();N0();wA();N0();function uh1(A,Q){return P6(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",Z.object({entityType:Z.string().describe("Entity type (e.g. post, note, link)"),id:Z.string().describe("Entity ID"),sha:Z.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:Z.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async(w)=>{let B=`${w.entityType}/${w.id}.md`;try{if(w.sha){let f=await Q.show(w.sha,B);return z5({sha:w.sha,entityType:w.entityType,id:w.id,content:f},`Content at ${w.sha.slice(0,7)}`)}let $=await Q.log(B,w.limit);if($.length===0)return z5({commits:[]},`No history found for ${w.entityType}/${w.id}`);return z5({commits:$,entityType:w.entityType,id:w.id},`${$.length} version${$.length===1?"":"s"} found`)}catch($){return k7($ instanceof Error?$.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function ch1(A,Q,w,B){let $=[P6(w,"sync","Sync brain entities with the filesystem. Use this for refresh, pull, sync, or backup-to-git requests. Pulls from git if configured, then imports files. Git commit and push happen automatically after imports complete.",Z.object({}),async(f,Y)=>{try{let X=Y.channelId?`${Y.interfaceType}:${Y.channelId}`:`plugin:${w}`,W={interfaceType:Y.interfaceType,channelId:Y.channelId};if(B){let K=await Q.jobs.enqueue({type:"sync-request",data:{source:X,interfaceType:W.interfaceType,channelId:W.channelId},toolContext:Y});return z5({jobId:K,status:"queued",gitPulled:!0},"Sync queued: git pull and filesystem scan will run in the background")}let H=await A.queueSyncBatch(Q,X,W);if(!H)return z5({gitPulled:!1},"No files to sync");return z5({batchId:H.batchId,importOperations:H.importOperationsCount,totalFiles:H.totalFiles,gitPulled:!1},`Sync started: ${H.importOperationsCount} import jobs queued for ${H.totalFiles} files`)}catch(X){return k7(X instanceof Error?X.message:"Sync failed")}},{visibility:"anchor",sideEffects:"external",cli:{name:"sync"}}),P6(w,"status","Get sync and git repository status \u2014 last sync time, watching state, pending git changes. Use this for status questions, not for actually syncing or backing up.",Z.object({}),async()=>{try{let f=await A.getStatus(),Y={syncPath:f.syncPath,lastSync:f.lastSync?.toISOString(),watching:f.watching};if(B){let X=await B.getStatus();Y.git={isRepo:X.isRepo,branch:X.branch,hasChanges:X.hasChanges,ahead:X.ahead,behind:X.behind,remote:X.remote}}return z5(Y)}catch(f){return k7(f instanceof Error?f.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if(B)$.push(uh1(w,B));return $}var lh1={name:"@brains/directory-sync",version:"0.2.0-alpha.142",description:"Directory-based entity synchronization plugin for Brains",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",chokidar:"^5.0.0","simple-git":"^3.36.0"},devDependencies:{"@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^6.0.3"},exports:{".":{types:"./src/index.ts",import:"./src/index.ts"},"./env-schema":"./src/env-schema.ts"},main:"./src/index.ts",peerDependencies:{},private:!0,scripts:{clean:"rm -rf .turbo",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};class Ql0 extends aQ{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",lh1,A,id)}requireDirectorySync(){if(!this.directorySync)throw Error("DirectorySync service not initialized");return this.directorySync}hasGitSync(){return this.gitSync!==void 0}async onRegister(A){let{logger:Q,entityService:w}=A;A.templates.register({status:{name:"status",description:"Directory synchronization status",schema:dd,basePrompt:"",formatter:new O90,requiredPermission:"anchor"}});let B=this.config.syncPath??A.dataDir;this.directorySync=new hd({syncPath:B,autoSync:this.config.autoSync,watchInterval:this.config.watchInterval,includeMetadata:this.config.includeMetadata,entityTypes:this.config.entityTypes,deleteOnFileRemoval:this.config.deleteOnFileRemoval,entityService:w,logger:Q});try{await this.directorySync.initializeDirectory(),this.logger.debug("Directory structure initialized",{path:B})}catch(Y){throw this.logger.error("Failed to initialize directory",Y),Y}await this.registerJobHandlers(A);let $=this.requireDirectorySync();if(Ph1(A,$,this.logger,this.config.entityTypes),this.config.autoSync)Mh1(A,$,this.config.syncPath??A.dataDir);let f=this.config.git!==void 0&&(this.config.git.repo!==void 0||this.config.git.gitUrl!==void 0);if(this.config.git&&!f)this.logger.debug("Git block present but no repo/gitUrl configured \u2014 git sync disabled");if(f&&this.config.git){await Sh1({gitUrl:this.config.git.gitUrl,branch:this.config.git.branch,seedContentPath:this.config.seedContentPath,bootstrapFromSeed:this.config.git.bootstrapFromSeed,authorName:this.config.git.authorName,authorEmail:this.config.git.authorEmail,logger:this.logger.child("ContentRemoteBootstrap")});let Y=this.config.syncPath??A.dataDir;if(this.gitSync=new nc0({logger:this.logger.child("GitSync"),dataDir:Y,repo:this.config.git.repo,gitUrl:this.config.git.gitUrl,branch:this.config.git.branch,authToken:this.config.git.authToken,authorName:this.config.git.authorName,authorEmail:this.config.git.authorEmail}),await this.gitSync.initialize(),this.logger.info("Git integration enabled",{repo:this.config.git.repo}),A.jobs.registerHandler("sync-request",new h90(this.logger.child("DirectorySyncRequestJobHandler"),A,this.requireDirectorySync(),this.gitSync)),this.gitCleanups.push(gh1(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(yh1(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)Ch1(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync);mh1(A,()=>this.requireDirectorySync(),(Y)=>this.configure(Y),this.logger,this.config.git)}async getTools(){let A=this.requireDirectorySync();return ch1(A,this.getContext(),this.id,this.gitSync)}async onShutdown(){for(let A of this.gitCleanups)A();this.gitCleanups=[],this.directorySync?.stopWatching(),this.gitSync?.cleanup()}getDirectorySync(){return this.directorySync}async configure(A){this.requireDirectorySync();let Q=this.getContext();this.directorySync=new hd({...this.config,syncPath:A.syncPath,entityService:Q.entityService,logger:Q.logger}),await this.directorySync.initialize(),this.logger.info("Directory sync reconfigured",{path:A.syncPath})}async registerJobHandlers(A){jh1(A,this.requireDirectorySync(),this.logger)}}function fj(A={}){return new Ql0(A)}wA();N0();var ph1={name:"@brains/email-resend",version:"0.2.0-alpha.142",description:"Generic email delivery adapter for Resend",dependencies:{"@brains/email-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var SpQ=Z.object({apiKey:Z.string().min(1).optional(),from:Z.string().min(1).optional()}),mpQ=Z.looseObject({id:Z.string().optional()});class ih1 extends aQ{fetchImpl;constructor(A={},Q={}){super("email-resend",ph1,A,SpQ);this.fetchImpl=Q.fetchImpl??fetch}async onRegister(A){if(!this.config.apiKey||!this.config.from){this.logger.warn("Email Resend adapter is disabled because apiKey or from is missing");return}let Q=this.logger;A.messaging.subscribe(S60,async(w)=>{let B=ogA.parse(w.payload);try{return{success:!0,data:await this.sendWithResend(B)}}catch($){if(B.sensitivity==="secret")Q.warn("Email delivery failed for a secret message");else Q.warn("Email delivery failed",{to:B.to,subject:B.subject,error:$ instanceof Error?$.message:String($)});return{success:!1,error:"Email delivery failed"}}})}async sendWithResend(A){let Q=this.config.apiKey,w=this.config.from;if(!Q||!w)return{status:"failed"};let B=await this.fetchImpl("https://api.resend.com/emails",{method:"POST",headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},body:JSON.stringify({from:w,to:A.to,subject:A.subject,text:A.text,...A.html?{html:A.html}:{}})});if(!B.ok)throw Error("Resend email request failed");let $=mpQ.parse(await B.json());return $.id?{status:"sent",id:$.id}:{status:"sent"}}}function T90(A={}){return new ih1(A)}wA();import{render as Ro1}from"preact-render-to-string";import{h as uj}from"preact";function dh1(A){var Q,w,B="";if(typeof A=="string"||typeof A=="number")B+=A;else if(typeof A=="object")if(Array.isArray(A)){var $=A.length;for(Q=0;Q<$;Q++)A[Q]&&(w=dh1(A[Q]))&&(B&&(B+=" "),B+=w)}else for(w in A)A[w]&&(B&&(B+=" "),B+=w);return B}function pC(){for(var A,Q,w=0,B="",$=arguments.length;w<$;w++)(A=arguments[w])&&(Q=dh1(A))&&(B&&(B+=" "),B+=Q);return B}var upQ=(A,Q)=>{let w=Array(A.length+Q.length);for(let B=0;B<A.length;B++)w[B]=A[B];for(let B=0;B<Q.length;B++)w[A.length+B]=Q[B];return w},cpQ=(A,Q)=>({classGroupId:A,validator:Q}),AC1=(A=new Map,Q=null,w)=>({nextPart:A,validators:Q,classGroupId:w});var nh1=[];var lpQ=(A)=>{let Q=ipQ(A),{conflictingClassGroups:w,conflictingClassGroupModifiers:B}=A;return{getClassGroupId:(Y)=>{if(Y.startsWith("[")&&Y.endsWith("]"))return ppQ(Y);let X=Y.split("-"),W=X[0]===""&&X.length>1?1:0;return QC1(X,W,Q)},getConflictingClassGroupIds:(Y,X)=>{if(X){let W=B[Y],H=w[Y];if(W){if(H)return upQ(H,W);return W}return H||nh1}return w[Y]||nh1}}},QC1=(A,Q,w)=>{if(A.length-Q===0)return w.classGroupId;let $=A[Q],f=w.nextPart.get($);if(f){let H=QC1(A,Q+1,f);if(H)return H}let Y=w.validators;if(Y===null)return;let X=Q===0?A.join("-"):A.slice(Q).join("-"),W=Y.length;for(let H=0;H<W;H++){let K=Y[H];if(K.validator(X))return K.classGroupId}return},ppQ=(A)=>A.slice(1,-1).indexOf(":")===-1?void 0:(()=>{let Q=A.slice(1,-1),w=Q.indexOf(":"),B=Q.slice(0,w);return B?"arbitrary.."+B:void 0})(),ipQ=(A)=>{let{theme:Q,classGroups:w}=A;return dpQ(w,Q)},dpQ=(A,Q)=>{let w=AC1();for(let B in A){let $=A[B];$l0($,w,B,Q)}return w},$l0=(A,Q,w,B)=>{let $=A.length;for(let f=0;f<$;f++){let Y=A[f];npQ(Y,Q,w,B)}},npQ=(A,Q,w,B)=>{if(typeof A==="string"){rpQ(A,Q,w);return}if(typeof A==="function"){opQ(A,Q,w,B);return}spQ(A,Q,w,B)},rpQ=(A,Q,w)=>{let B=A===""?Q:wC1(Q,A);B.classGroupId=w},opQ=(A,Q,w,B)=>{if(apQ(A)){$l0(A(B),Q,w,B);return}if(Q.validators===null)Q.validators=[];Q.validators.push(cpQ(w,A))},spQ=(A,Q,w,B)=>{let $=Object.entries(A),f=$.length;for(let Y=0;Y<f;Y++){let[X,W]=$[Y];$l0(W,wC1(Q,X),w,B)}},wC1=(A,Q)=>{let w=A,B=Q.split("-"),$=B.length;for(let f=0;f<$;f++){let Y=B[f],X=w.nextPart.get(Y);if(!X)X=AC1(),w.nextPart.set(Y,X);w=X}return w},apQ=(A)=>("isThemeGetter"in A)&&A.isThemeGetter===!0,tpQ=(A)=>{if(A<1)return{get:()=>{return},set:()=>{}};let Q=0,w=Object.create(null),B=Object.create(null),$=(f,Y)=>{if(w[f]=Y,Q++,Q>A)Q=0,B=w,w=Object.create(null)};return{get(f){let Y=w[f];if(Y!==void 0)return Y;if((Y=B[f])!==void 0)return $(f,Y),Y},set(f,Y){if(f in w)w[f]=Y;else $(f,Y)}}};var epQ=[],rh1=(A,Q,w,B,$)=>({modifiers:A,hasImportantModifier:Q,baseClassName:w,maybePostfixModifierPosition:B,isExternal:$}),AiQ=(A)=>{let{prefix:Q,experimentalParseClassName:w}=A,B=($)=>{let f=[],Y=0,X=0,W=0,H,K=$.length;for(let I=0;I<K;I++){let V=$[I];if(Y===0&&X===0){if(V===":"){f.push($.slice(W,I)),W=I+1;continue}if(V==="/"){H=I;continue}}if(V==="[")Y++;else if(V==="]")Y--;else if(V==="(")X++;else if(V===")")X--}let U=f.length===0?$:$.slice(W),D=U,q=!1;if(U.endsWith("!"))D=U.slice(0,-1),q=!0;else if(U.startsWith("!"))D=U.slice(1),q=!0;let b=H&&H>W?H-W:void 0;return rh1(f,q,D,b)};if(Q){let $=Q+":",f=B;B=(Y)=>Y.startsWith($)?f(Y.slice($.length)):rh1(epQ,!1,Y,void 0,!0)}if(w){let $=B;B=(f)=>w({className:f,parseClassName:$})}return B},QiQ=(A)=>{let Q=new Map;return A.orderSensitiveModifiers.forEach((w,B)=>{Q.set(w,1e6+B)}),(w)=>{let B=[],$=[];for(let f=0;f<w.length;f++){let Y=w[f],X=Y[0]==="[",W=Q.has(Y);if(X||W){if($.length>0)$.sort(),B.push(...$),$=[];B.push(Y)}else $.push(Y)}if($.length>0)$.sort(),B.push(...$);return B}},wiQ=(A)=>({cache:tpQ(A.cacheSize),parseClassName:AiQ(A),sortModifiers:QiQ(A),postfixLookupClassGroupIds:BiQ(A),...lpQ(A)}),BiQ=(A)=>{let Q=Object.create(null),w=A.postfixLookupClassGroups;if(w)for(let B=0;B<w.length;B++)Q[w[B]]=!0;return Q},$iQ=/\s+/,fiQ=(A,Q)=>{let{parseClassName:w,getClassGroupId:B,getConflictingClassGroupIds:$,sortModifiers:f,postfixLookupClassGroupIds:Y}=Q,X=[],W=A.trim().split($iQ),H="";for(let K=W.length-1;K>=0;K-=1){let U=W[K],{isExternal:D,modifiers:q,hasImportantModifier:b,baseClassName:I,maybePostfixModifierPosition:V}=w(U);if(D){H=U+(H.length>0?" "+H:H);continue}let L=!!V,N;if(L){let P=I.substring(0,V);N=B(P);let E=N&&Y[N]?B(I):void 0;if(E&&E!==N)N=E,L=!1}else N=B(I);if(!N){if(!L){H=U+(H.length>0?" "+H:H);continue}if(N=B(I),!N){H=U+(H.length>0?" "+H:H);continue}L=!1}let k=q.length===0?"":q.length===1?q[0]:f(q).join(":"),x=b?k+"!":k,R=x+N;if(X.indexOf(R)>-1)continue;X.push(R);let h=$(N,L);for(let P=0;P<h.length;++P){let E=h[P];X.push(x+E)}H=U+(H.length>0?" "+H:H)}return H},YiQ=(...A)=>{let Q=0,w,B,$="";while(Q<A.length)if(w=A[Q++]){if(B=BC1(w))$&&($+=" "),$+=B}return $},BC1=(A)=>{if(typeof A==="string")return A;let Q,w="";for(let B=0;B<A.length;B++)if(A[B]){if(Q=BC1(A[B]))w&&(w+=" "),w+=Q}return w},oh1=(A,...Q)=>{let w,B,$,f,Y=(W)=>{let H=Q.reduce((K,U)=>U(K),A());return w=wiQ(H),B=w.cache.get,$=w.cache.set,f=X,X(W)},X=(W)=>{let H=B(W);if(H)return H;let K=fiQ(W,w);return $(W,K),K};return f=Y,(...W)=>f(YiQ(...W))},XiQ=[],q9=(A)=>{let Q=(w)=>w[A]||XiQ;return Q.isThemeGetter=!0,Q},$C1=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,fC1=/^\((?:(\w[\w-]*):)?(.+)\)$/i,ZiQ=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,WiQ=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,HiQ=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,KiQ=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,UiQ=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,DiQ=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,iJ=(A)=>ZiQ.test(A),Cw=(A)=>!!A&&!Number.isNaN(Number(A)),_G=(A)=>!!A&&Number.isInteger(Number(A)),wl0=(A)=>A.endsWith("%")&&Cw(A.slice(0,-1)),hq=(A)=>WiQ.test(A),YC1=()=>!0,GiQ=(A)=>HiQ.test(A)&&!KiQ.test(A),fl0=()=>!1,ziQ=(A)=>UiQ.test(A),qiQ=(A)=>DiQ.test(A),biQ=(A)=>!I2(A)&&!k2(A),ViQ=(A)=>A.startsWith("@container")&&(A[10]==="/"&&A[11]!==void 0||A[11]==="s"&&A[16]!==void 0&&A.startsWith("-size/",10)||A[11]==="n"&&A[18]!==void 0&&A.startsWith("-normal/",10)),IiQ=(A)=>dJ(A,WC1,fl0),I2=(A)=>$C1.test(A),Yj=(A)=>dJ(A,HC1,GiQ),sh1=(A)=>dJ(A,PiQ,Cw),JiQ=(A)=>dJ(A,UC1,YC1),FiQ=(A)=>dJ(A,KC1,fl0),ah1=(A)=>dJ(A,XC1,fl0),LiQ=(A)=>dJ(A,ZC1,qiQ),S90=(A)=>dJ(A,DC1,ziQ),k2=(A)=>fC1.test(A),rd=(A)=>Xj(A,HC1),kiQ=(A)=>Xj(A,KC1),th1=(A)=>Xj(A,XC1),_iQ=(A)=>Xj(A,WC1),NiQ=(A)=>Xj(A,ZC1),m90=(A)=>Xj(A,DC1,!0),jiQ=(A)=>Xj(A,UC1,!0),dJ=(A,Q,w)=>{let B=$C1.exec(A);if(B){if(B[1])return Q(B[1]);return w(B[2])}return!1},Xj=(A,Q,w=!1)=>{let B=fC1.exec(A);if(B){if(B[1])return Q(B[1]);return w}return!1},XC1=(A)=>A==="position"||A==="percentage",ZC1=(A)=>A==="image"||A==="url",WC1=(A)=>A==="length"||A==="size"||A==="bg-size",HC1=(A)=>A==="length",PiQ=(A)=>A==="number",KC1=(A)=>A==="family-name",UC1=(A)=>A==="number"||A==="weight",DC1=(A)=>A==="shadow";var eh1=()=>{let A=q9("color"),Q=q9("font"),w=q9("text"),B=q9("font-weight"),$=q9("tracking"),f=q9("leading"),Y=q9("breakpoint"),X=q9("container"),W=q9("spacing"),H=q9("radius"),K=q9("shadow"),U=q9("inset-shadow"),D=q9("text-shadow"),q=q9("drop-shadow"),b=q9("blur"),I=q9("perspective"),V=q9("aspect"),L=q9("ease"),N=q9("animate"),k=()=>["auto","avoid","all","avoid-page","page","left","right","column"],x=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],R=()=>[...x(),k2,I2],h=()=>["auto","hidden","clip","visible","scroll"],P=()=>["auto","contain","none"],E=()=>[k2,I2,W],S=()=>[iJ,"full","auto",...E()],p=()=>[_G,"none","subgrid",k2,I2],e=()=>["auto",{span:["full",_G,k2,I2]},_G,k2,I2],Y0=()=>[_G,"auto",k2,I2],l=()=>["auto","min","max","fr",k2,I2],j=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],g=()=>["start","end","center","stretch","center-safe","end-safe"],y=()=>["auto",...E()],n=()=>[iJ,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...E()],o=()=>[iJ,"screen","full","dvw","lvw","svw","min","max","fit",...E()],K0=()=>[iJ,"screen","full","lh","dvh","lvh","svh","min","max","fit",...E()],c=()=>[A,k2,I2],X0=()=>[...x(),th1,ah1,{position:[k2,I2]}],b0=()=>["no-repeat",{repeat:["","x","y","space","round"]}],w0=()=>["auto","cover","contain",_iQ,IiQ,{size:[k2,I2]}],h0=()=>[wl0,rd,Yj],S0=()=>["","none","full",H,k2,I2],V0=()=>["",Cw,rd,Yj],I0=()=>["solid","dashed","dotted","double"],j0=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],C0=()=>[Cw,wl0,th1,ah1],k0=()=>["","none",b,k2,I2],_0=()=>["none",Cw,k2,I2],P0=()=>["none",Cw,k2,I2],M0=()=>[Cw,k2,I2],T0=()=>[iJ,"full",...E()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[hq],breakpoint:[hq],color:[YC1],container:[hq],"drop-shadow":[hq],ease:["in","out","in-out"],font:[biQ],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[hq],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[hq],shadow:[hq],spacing:["px",Cw],text:[hq],"text-shadow":[hq],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",iJ,I2,k2,V]}],container:["container"],"container-type":[{"@container":["","normal","size",k2,I2]}],"container-named":[ViQ],columns:[{columns:[Cw,I2,k2,X]}],"break-after":[{"break-after":k()}],"break-before":[{"break-before":k()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],sr:["sr-only","not-sr-only"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:R()}],overflow:[{overflow:h()}],"overflow-x":[{"overflow-x":h()}],"overflow-y":[{"overflow-y":h()}],overscroll:[{overscroll:P()}],"overscroll-x":[{"overscroll-x":P()}],"overscroll-y":[{"overscroll-y":P()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:S()}],"inset-x":[{"inset-x":S()}],"inset-y":[{"inset-y":S()}],start:[{"inset-s":S(),start:S()}],end:[{"inset-e":S(),end:S()}],"inset-bs":[{"inset-bs":S()}],"inset-be":[{"inset-be":S()}],top:[{top:S()}],right:[{right:S()}],bottom:[{bottom:S()}],left:[{left:S()}],visibility:["visible","invisible","collapse"],z:[{z:[_G,"auto",k2,I2]}],basis:[{basis:[iJ,"full","auto",X,...E()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[Cw,iJ,"auto","initial","none",I2]}],grow:[{grow:["",Cw,k2,I2]}],shrink:[{shrink:["",Cw,k2,I2]}],order:[{order:[_G,"first","last","none",k2,I2]}],"grid-cols":[{"grid-cols":p()}],"col-start-end":[{col:e()}],"col-start":[{"col-start":Y0()}],"col-end":[{"col-end":Y0()}],"grid-rows":[{"grid-rows":p()}],"row-start-end":[{row:e()}],"row-start":[{"row-start":Y0()}],"row-end":[{"row-end":Y0()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":l()}],"auto-rows":[{"auto-rows":l()}],gap:[{gap:E()}],"gap-x":[{"gap-x":E()}],"gap-y":[{"gap-y":E()}],"justify-content":[{justify:[...j(),"normal"]}],"justify-items":[{"justify-items":[...g(),"normal"]}],"justify-self":[{"justify-self":["auto",...g()]}],"align-content":[{content:["normal",...j()]}],"align-items":[{items:[...g(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...g(),{baseline:["","last"]}]}],"place-content":[{"place-content":j()}],"place-items":[{"place-items":[...g(),"baseline"]}],"place-self":[{"place-self":["auto",...g()]}],p:[{p:E()}],px:[{px:E()}],py:[{py:E()}],ps:[{ps:E()}],pe:[{pe:E()}],pbs:[{pbs:E()}],pbe:[{pbe:E()}],pt:[{pt:E()}],pr:[{pr:E()}],pb:[{pb:E()}],pl:[{pl:E()}],m:[{m:y()}],mx:[{mx:y()}],my:[{my:y()}],ms:[{ms:y()}],me:[{me:y()}],mbs:[{mbs:y()}],mbe:[{mbe:y()}],mt:[{mt:y()}],mr:[{mr:y()}],mb:[{mb:y()}],ml:[{ml:y()}],"space-x":[{"space-x":E()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":E()}],"space-y-reverse":["space-y-reverse"],size:[{size:n()}],"inline-size":[{inline:["auto",...o()]}],"min-inline-size":[{"min-inline":["auto",...o()]}],"max-inline-size":[{"max-inline":["none",...o()]}],"block-size":[{block:["auto",...K0()]}],"min-block-size":[{"min-block":["auto",...K0()]}],"max-block-size":[{"max-block":["none",...K0()]}],w:[{w:[X,"screen",...n()]}],"min-w":[{"min-w":[X,"screen","none",...n()]}],"max-w":[{"max-w":[X,"screen","none","prose",{screen:[Y]},...n()]}],h:[{h:["screen","lh",...n()]}],"min-h":[{"min-h":["screen","lh","none",...n()]}],"max-h":[{"max-h":["screen","lh",...n()]}],"font-size":[{text:["base",w,rd,Yj]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[B,jiQ,JiQ]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",wl0,I2]}],"font-family":[{font:[kiQ,FiQ,Q]}],"font-features":[{"font-features":[I2]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:[$,k2,I2]}],"line-clamp":[{"line-clamp":[Cw,"none",k2,sh1]}],leading:[{leading:[f,...E()]}],"list-image":[{"list-image":["none",k2,I2]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",k2,I2]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:c()}],"text-color":[{text:c()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...I0(),"wavy"]}],"text-decoration-thickness":[{decoration:[Cw,"from-font","auto",k2,Yj]}],"text-decoration-color":[{decoration:c()}],"underline-offset":[{"underline-offset":[Cw,"auto",k2,I2]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:E()}],"tab-size":[{tab:[_G,k2,I2]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",k2,I2]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],wrap:[{wrap:["break-word","anywhere","normal"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",k2,I2]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:X0()}],"bg-repeat":[{bg:b0()}],"bg-size":[{bg:w0()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},_G,k2,I2],radial:["",k2,I2],conic:[_G,k2,I2]},NiQ,LiQ]}],"bg-color":[{bg:c()}],"gradient-from-pos":[{from:h0()}],"gradient-via-pos":[{via:h0()}],"gradient-to-pos":[{to:h0()}],"gradient-from":[{from:c()}],"gradient-via":[{via:c()}],"gradient-to":[{to:c()}],rounded:[{rounded:S0()}],"rounded-s":[{"rounded-s":S0()}],"rounded-e":[{"rounded-e":S0()}],"rounded-t":[{"rounded-t":S0()}],"rounded-r":[{"rounded-r":S0()}],"rounded-b":[{"rounded-b":S0()}],"rounded-l":[{"rounded-l":S0()}],"rounded-ss":[{"rounded-ss":S0()}],"rounded-se":[{"rounded-se":S0()}],"rounded-ee":[{"rounded-ee":S0()}],"rounded-es":[{"rounded-es":S0()}],"rounded-tl":[{"rounded-tl":S0()}],"rounded-tr":[{"rounded-tr":S0()}],"rounded-br":[{"rounded-br":S0()}],"rounded-bl":[{"rounded-bl":S0()}],"border-w":[{border:V0()}],"border-w-x":[{"border-x":V0()}],"border-w-y":[{"border-y":V0()}],"border-w-s":[{"border-s":V0()}],"border-w-e":[{"border-e":V0()}],"border-w-bs":[{"border-bs":V0()}],"border-w-be":[{"border-be":V0()}],"border-w-t":[{"border-t":V0()}],"border-w-r":[{"border-r":V0()}],"border-w-b":[{"border-b":V0()}],"border-w-l":[{"border-l":V0()}],"divide-x":[{"divide-x":V0()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":V0()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...I0(),"hidden","none"]}],"divide-style":[{divide:[...I0(),"hidden","none"]}],"border-color":[{border:c()}],"border-color-x":[{"border-x":c()}],"border-color-y":[{"border-y":c()}],"border-color-s":[{"border-s":c()}],"border-color-e":[{"border-e":c()}],"border-color-bs":[{"border-bs":c()}],"border-color-be":[{"border-be":c()}],"border-color-t":[{"border-t":c()}],"border-color-r":[{"border-r":c()}],"border-color-b":[{"border-b":c()}],"border-color-l":[{"border-l":c()}],"divide-color":[{divide:c()}],"outline-style":[{outline:[...I0(),"none","hidden"]}],"outline-offset":[{"outline-offset":[Cw,k2,I2]}],"outline-w":[{outline:["",Cw,rd,Yj]}],"outline-color":[{outline:c()}],shadow:[{shadow:["","none",K,m90,S90]}],"shadow-color":[{shadow:c()}],"inset-shadow":[{"inset-shadow":["none",U,m90,S90]}],"inset-shadow-color":[{"inset-shadow":c()}],"ring-w":[{ring:V0()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:c()}],"ring-offset-w":[{"ring-offset":[Cw,Yj]}],"ring-offset-color":[{"ring-offset":c()}],"inset-ring-w":[{"inset-ring":V0()}],"inset-ring-color":[{"inset-ring":c()}],"text-shadow":[{"text-shadow":["none",D,m90,S90]}],"text-shadow-color":[{"text-shadow":c()}],opacity:[{opacity:[Cw,k2,I2]}],"mix-blend":[{"mix-blend":[...j0(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":j0()}],"mask-clip":[{"mask-clip":["border","padding","content","fill","stroke","view"]},"mask-no-clip"],"mask-composite":[{mask:["add","subtract","intersect","exclude"]}],"mask-image-linear-pos":[{"mask-linear":[Cw]}],"mask-image-linear-from-pos":[{"mask-linear-from":C0()}],"mask-image-linear-to-pos":[{"mask-linear-to":C0()}],"mask-image-linear-from-color":[{"mask-linear-from":c()}],"mask-image-linear-to-color":[{"mask-linear-to":c()}],"mask-image-t-from-pos":[{"mask-t-from":C0()}],"mask-image-t-to-pos":[{"mask-t-to":C0()}],"mask-image-t-from-color":[{"mask-t-from":c()}],"mask-image-t-to-color":[{"mask-t-to":c()}],"mask-image-r-from-pos":[{"mask-r-from":C0()}],"mask-image-r-to-pos":[{"mask-r-to":C0()}],"mask-image-r-from-color":[{"mask-r-from":c()}],"mask-image-r-to-color":[{"mask-r-to":c()}],"mask-image-b-from-pos":[{"mask-b-from":C0()}],"mask-image-b-to-pos":[{"mask-b-to":C0()}],"mask-image-b-from-color":[{"mask-b-from":c()}],"mask-image-b-to-color":[{"mask-b-to":c()}],"mask-image-l-from-pos":[{"mask-l-from":C0()}],"mask-image-l-to-pos":[{"mask-l-to":C0()}],"mask-image-l-from-color":[{"mask-l-from":c()}],"mask-image-l-to-color":[{"mask-l-to":c()}],"mask-image-x-from-pos":[{"mask-x-from":C0()}],"mask-image-x-to-pos":[{"mask-x-to":C0()}],"mask-image-x-from-color":[{"mask-x-from":c()}],"mask-image-x-to-color":[{"mask-x-to":c()}],"mask-image-y-from-pos":[{"mask-y-from":C0()}],"mask-image-y-to-pos":[{"mask-y-to":C0()}],"mask-image-y-from-color":[{"mask-y-from":c()}],"mask-image-y-to-color":[{"mask-y-to":c()}],"mask-image-radial":[{"mask-radial":[k2,I2]}],"mask-image-radial-from-pos":[{"mask-radial-from":C0()}],"mask-image-radial-to-pos":[{"mask-radial-to":C0()}],"mask-image-radial-from-color":[{"mask-radial-from":c()}],"mask-image-radial-to-color":[{"mask-radial-to":c()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":x()}],"mask-image-conic-pos":[{"mask-conic":[Cw]}],"mask-image-conic-from-pos":[{"mask-conic-from":C0()}],"mask-image-conic-to-pos":[{"mask-conic-to":C0()}],"mask-image-conic-from-color":[{"mask-conic-from":c()}],"mask-image-conic-to-color":[{"mask-conic-to":c()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:X0()}],"mask-repeat":[{mask:b0()}],"mask-size":[{mask:w0()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",k2,I2]}],filter:[{filter:["","none",k2,I2]}],blur:[{blur:k0()}],brightness:[{brightness:[Cw,k2,I2]}],contrast:[{contrast:[Cw,k2,I2]}],"drop-shadow":[{"drop-shadow":["","none",q,m90,S90]}],"drop-shadow-color":[{"drop-shadow":c()}],grayscale:[{grayscale:["",Cw,k2,I2]}],"hue-rotate":[{"hue-rotate":[Cw,k2,I2]}],invert:[{invert:["",Cw,k2,I2]}],saturate:[{saturate:[Cw,k2,I2]}],sepia:[{sepia:["",Cw,k2,I2]}],"backdrop-filter":[{"backdrop-filter":["","none",k2,I2]}],"backdrop-blur":[{"backdrop-blur":k0()}],"backdrop-brightness":[{"backdrop-brightness":[Cw,k2,I2]}],"backdrop-contrast":[{"backdrop-contrast":[Cw,k2,I2]}],"backdrop-grayscale":[{"backdrop-grayscale":["",Cw,k2,I2]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[Cw,k2,I2]}],"backdrop-invert":[{"backdrop-invert":["",Cw,k2,I2]}],"backdrop-opacity":[{"backdrop-opacity":[Cw,k2,I2]}],"backdrop-saturate":[{"backdrop-saturate":[Cw,k2,I2]}],"backdrop-sepia":[{"backdrop-sepia":["",Cw,k2,I2]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":E()}],"border-spacing-x":[{"border-spacing-x":E()}],"border-spacing-y":[{"border-spacing-y":E()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",k2,I2]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[Cw,"initial",k2,I2]}],ease:[{ease:["linear","initial",L,k2,I2]}],delay:[{delay:[Cw,k2,I2]}],animate:[{animate:["none",N,k2,I2]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[I,k2,I2]}],"perspective-origin":[{"perspective-origin":R()}],rotate:[{rotate:_0()}],"rotate-x":[{"rotate-x":_0()}],"rotate-y":[{"rotate-y":_0()}],"rotate-z":[{"rotate-z":_0()}],scale:[{scale:P0()}],"scale-x":[{"scale-x":P0()}],"scale-y":[{"scale-y":P0()}],"scale-z":[{"scale-z":P0()}],"scale-3d":["scale-3d"],skew:[{skew:M0()}],"skew-x":[{"skew-x":M0()}],"skew-y":[{"skew-y":M0()}],transform:[{transform:[k2,I2,"","none","gpu","cpu"]}],"transform-origin":[{origin:R()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:T0()}],"translate-x":[{"translate-x":T0()}],"translate-y":[{"translate-y":T0()}],"translate-z":[{"translate-z":T0()}],"translate-none":["translate-none"],zoom:[{zoom:[_G,k2,I2]}],accent:[{accent:c()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:c()}],"color-scheme":[{scheme:["normal","dark","light","light-dark","only-dark","only-light"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",k2,I2]}],"field-sizing":[{"field-sizing":["fixed","content"]}],"pointer-events":[{"pointer-events":["auto","none"]}],resize:[{resize:["none","","y","x"]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scrollbar-thumb-color":[{"scrollbar-thumb":c()}],"scrollbar-track-color":[{"scrollbar-track":c()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":E()}],"scroll-mx":[{"scroll-mx":E()}],"scroll-my":[{"scroll-my":E()}],"scroll-ms":[{"scroll-ms":E()}],"scroll-me":[{"scroll-me":E()}],"scroll-mbs":[{"scroll-mbs":E()}],"scroll-mbe":[{"scroll-mbe":E()}],"scroll-mt":[{"scroll-mt":E()}],"scroll-mr":[{"scroll-mr":E()}],"scroll-mb":[{"scroll-mb":E()}],"scroll-ml":[{"scroll-ml":E()}],"scroll-p":[{"scroll-p":E()}],"scroll-px":[{"scroll-px":E()}],"scroll-py":[{"scroll-py":E()}],"scroll-ps":[{"scroll-ps":E()}],"scroll-pe":[{"scroll-pe":E()}],"scroll-pbs":[{"scroll-pbs":E()}],"scroll-pbe":[{"scroll-pbe":E()}],"scroll-pt":[{"scroll-pt":E()}],"scroll-pr":[{"scroll-pr":E()}],"scroll-pb":[{"scroll-pb":E()}],"scroll-pl":[{"scroll-pl":E()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",k2,I2]}],fill:[{fill:["none",...c()]}],"stroke-w":[{stroke:[Cw,rd,Yj,sh1]}],stroke:[{stroke:["none",...c()]}],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{"container-named":["container-type"],overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","inset-bs","inset-be","start","end","top","right","bottom","left"],"inset-x":["right","left"],"inset-y":["top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pbs","pbe","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","mbs","mbe","mt","mr","mb","ml"],mx:["mr","ml"],my:["mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-x","border-w-y","border-w-s","border-w-e","border-w-bs","border-w-be","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-r","border-w-l"],"border-w-y":["border-w-t","border-w-b"],"border-color":["border-color-x","border-color-y","border-color-s","border-color-e","border-color-bs","border-color-be","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-r","border-color-l"],"border-color-y":["border-color-t","border-color-b"],translate:["translate-x","translate-y","translate-none"],"translate-none":["translate","translate-x","translate-y","translate-z"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mbs","scroll-mbe","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-mr","scroll-ml"],"scroll-my":["scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pbs","scroll-pbe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-pr","scroll-pl"],"scroll-py":["scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]},postfixLookupClassGroups:["container-type"],orderSensitiveModifiers:["*","**","after","backdrop","before","details-content","file","first-letter","first-line","marker","placeholder","selection"]}},MiQ=(A,{cacheSize:Q,prefix:w,experimentalParseClassName:B,extend:$={},override:f={}})=>{return iC(A,"cacheSize",Q),iC(A,"prefix",w),iC(A,"experimentalParseClassName",B),u90(A.theme,f.theme),u90(A.classGroups,f.classGroups),u90(A.conflictingClassGroups,f.conflictingClassGroups),u90(A.conflictingClassGroupModifiers,f.conflictingClassGroupModifiers),iC(A,"postfixLookupClassGroups",f.postfixLookupClassGroups),iC(A,"orderSensitiveModifiers",f.orderSensitiveModifiers),c90(A.theme,$.theme),c90(A.classGroups,$.classGroups),c90(A.conflictingClassGroups,$.conflictingClassGroups),c90(A.conflictingClassGroupModifiers,$.conflictingClassGroupModifiers),Bl0(A,$,"postfixLookupClassGroups"),Bl0(A,$,"orderSensitiveModifiers"),A},iC=(A,Q,w)=>{if(w!==void 0)A[Q]=w},u90=(A,Q)=>{if(Q)for(let w in Q)iC(A,w,Q[w])},c90=(A,Q)=>{if(Q)for(let w in Q)Bl0(A,Q,w)},Bl0=(A,Q,w)=>{let B=Q[w];if(B!==void 0)A[w]=A[w]?A[w].concat(B):B},l90=(A,...Q)=>typeof A==="function"?oh1(eh1,A,...Q):oh1(()=>MiQ(eh1(),A),...Q);var OiQ=l90({extend:{classGroups:{"font-size":[{text:["display-2xl","display-xl","display-lg","display-md","display-sm","heading-lg","heading-md","heading-sm","body-xl","body-lg","body-md","body-sm","body-xs","label-md","label-sm","label-xs"]}]}}});function _2(...A){return OiQ(pC(A))}var GC1=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,zC1=pC,JB=(A,Q)=>(w)=>{var B;if((Q===null||Q===void 0?void 0:Q.variants)==null)return zC1(A,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className);let{variants:$,defaultVariants:f}=Q,Y=Object.keys($).map((H)=>{let K=w===null||w===void 0?void 0:w[H],U=f===null||f===void 0?void 0:f[H];if(K===null)return null;let D=GC1(K)||GC1(U);return $[H][D]}),X=w&&Object.entries(w).reduce((H,K)=>{let[U,D]=K;if(D===void 0)return H;return H[U]=D,H},{}),W=Q===null||Q===void 0?void 0:(B=Q.compoundVariants)===null||B===void 0?void 0:B.reduce((H,K)=>{let{class:U,className:D,...q}=K;return Object.entries(q).every((b)=>{let[I,V]=b;return Array.isArray(V)?V.includes({...f,...X}[I]):{...f,...X}[I]===V})?[...H,U,D]:H},[]);return zC1(A,Y,W,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className)};import{jsxDEV as Yl0}from"preact/jsx-dev-runtime";var qC1=JB("p-4 rounded-lg border",{variants:{variant:{warning:"bg-warning border-warning text-warning",error:"bg-error border-error text-error",success:"bg-success border-success text-success",info:"bg-info border-info text-info"}},defaultVariants:{variant:"info"}});function Xl0({variant:A,title:Q,children:w,className:B}){return Yl0("div",{className:_2(qC1({variant:A}),B),role:"alert",children:[Q&&Yl0("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),Yl0("div",{className:_2(Q&&"mt-1","text-sm text-current opacity-75"),children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as xiQ}from"preact/jsx-dev-runtime";var bC1=JB("inline-flex items-center justify-center font-bold transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed",{variants:{variant:{default:"bg-brand hover:bg-brand-dark text-theme-inverse",secondary:"bg-theme-muted hover:bg-theme-subtle text-theme border border-theme",ghost:"hover:bg-theme-subtle text-theme"},size:{sm:"h-8 px-3 text-sm rounded-md",md:"h-10 px-4 py-2 text-sm rounded-lg",lg:"h-12 px-6 text-base rounded-lg"}},defaultVariants:{variant:"default",size:"md"}});function Zj({variant:A,size:Q,className:w,children:B,ssrOnClick:$,type:f="button",...Y}){return xiQ("button",{type:f,className:_2(bC1({variant:A,size:Q}),w),...Y,...$&&{onclick:$},children:B},void 0,!1,void 0,this)}import{jsxDEV as RiQ}from"preact/jsx-dev-runtime";var VC1=JB("inline-flex items-center justify-center font-semibold transition-all text-center",{variants:{variant:{primary:"bg-brand text-theme-inverse hover:bg-brand-dark focus:ring-brand/20 focus:outline-none focus:ring-4",accent:"bg-accent text-theme-inverse hover:bg-accent-dark focus:ring-accent/20 focus:outline-none focus:ring-4",secondary:"bg-theme-muted text-theme hover:bg-theme-muted-dark focus:outline-none focus:ring-4",outline:"border-2 border-brand text-brand hover:bg-brand hover:text-theme-inverse focus:ring-brand/20 focus:outline-none focus:ring-4","outline-light":"border-2 border-theme-light text-theme-inverse hover:bg-theme-inverse hover:text-brand hover:border-theme-inverse focus:outline-none focus:ring-4",unstyled:""},size:{icon:"w-10 h-10 rounded-full",sm:"px-3 py-1.5 text-sm rounded-lg",md:"px-4 py-2 text-sm rounded-lg",lg:"px-6 py-3 text-base rounded-xl",xl:"px-8 py-4 text-lg rounded-xl","2xl":"px-10 py-5 text-lg rounded-2xl"}},defaultVariants:{size:"md"}});function b9({href:A,children:Q,variant:w,size:B,external:$=!1,className:f,"aria-label":Y}){let X=$?{target:"_blank",rel:"noopener noreferrer"}:{};return RiQ("a",{href:A,className:_2(VC1({variant:w,size:B}),f),"aria-label":Y,...X,children:Q},void 0,!1,void 0,this)}import{jsxDEV as p90}from"preact/jsx-dev-runtime";var IC1=JB("transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2",{variants:{variant:{default:"rounded-[10px] bg-theme-subtle border border-theme text-theme-muted hover:text-accent hover:border-brand/40",light:"rounded-[10px] bg-theme-subtle border border-theme text-theme-muted hover:text-accent",dark:"rounded-[10px] bg-theme-dark hover:bg-theme-muted text-theme-inverse",footer:"rounded-full bg-theme-toggle hover:bg-theme-toggle-hover text-theme-toggle-icon"},size:{sm:"p-1.5",md:"p-2",lg:"p-3"}},defaultVariants:{variant:"default",size:"md"}}),viQ={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function dC({variant:A,size:Q,className:w}){let B=viQ[Q??"md"];return p90("button",{onclick:"toggleTheme()",type:"button",className:_2(IC1({variant:A,size:Q}),w),"aria-label":"Toggle dark mode",children:p90("svg",{className:_2(B,"transition-colors"),fill:"none",stroke:"currentColor",strokeWidth:1.6,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[p90("path",{className:"sun-icon",strokeLinecap:"round",strokeLinejoin:"round",d:"M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"},void 0,!1,void 0,this),p90("path",{className:"moon-icon",strokeLinecap:"round",strokeLinejoin:"round",d:"M20.354 15.354A9 9 0 018.646 3.646 9 9 0 1020.354 15.354z"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}import{jsxDEV as Zl0}from"preact/jsx-dev-runtime";var JC1=JB("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function i90({items:A,className:Q,linkClassName:w="hover:text-accent transition-colors",orientation:B,children:$}){if(A.length===0&&!$)return null;let f=[...A].sort((Y,X)=>Y.priority-X.priority);return Zl0("ul",{className:_2(JC1({orientation:B}),Q),children:[f.map((Y)=>Zl0("li",{children:Zl0("a",{href:Y.href,className:w,children:Y.label},void 0,!1,void 0,this)},Y.href,!1,void 0,this)),$]},void 0,!0,void 0,this)}import{jsxDEV as EhB}from"preact/jsx-dev-runtime";import{jsxDEV as mhB}from"preact/jsx-dev-runtime";import{createContext as hiQ,h as CiQ}from"preact";import{useContext as giQ}from"preact/hooks";var Wl0=hiQ(null);function nC({headCollector:A,children:Q}){return CiQ(Wl0.Provider,{value:A},Q)}function FC1(){return giQ(Wl0)}function lQ(A){let Q=FC1();if(Q)Q.setHeadProps(A);return null}import{createContext as UtQ,h as DtQ}from"preact";import{useContext as GtQ}from"preact/hooks";GP0();var RT1=X1(xT1(),1),HtQ=new SQ0({gfm:!0,breaks:!0}),KtQ={allowedTags:["h1","h2","h3","h4","h5","h6","p","br","hr","ul","ol","li","blockquote","cite","code","pre","em","strong","del","ins","sub","sup","a","img","span","table","thead","tbody","tr","th","td","div"],allowedAttributes:{a:["href","title","name"],img:["src","srcset","sizes","alt","title","width","height","class","loading","decoding"],code:["class"],pre:["class"],span:["class"],cite:["class"],div:["class"],th:["align","colspan","rowspan","scope"],td:["align","colspan","rowspan"]},allowedSchemes:["http","https","mailto","tel"],allowedSchemesByTag:{img:["http","https","entity"]},allowProtocolRelative:!1,disallowedTagsMode:"discard"};function Cp0(A,Q){let{imageRenderer:w}=Q??{},$=(w?new SQ0({gfm:!0,breaks:!0}).use({renderer:{image({href:f,title:Y,text:X}){return w(f,Y,X)??!1}}}):HtQ).parse(A);return $=$.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
4777
+ `)}}wA();class x90 extends aw{directorySync;constructor(A,Q,w){super(A,{schema:ac0,jobTypeName:"directory-export"});this.directorySync=w}async process(A,Q,w){this.logger.debug("Processing directory export job",{jobId:Q,data:A});let B=Date.now();try{let $=await this.directorySync.exportEntitiesWithProgress(A.entityTypes,w,A.batchSize??100);return this.logger.debug("Directory export job completed",{jobId:Q,exported:$.exported,failed:$.failed,duration:Date.now()-B}),$}catch($){throw this.logger.error("Directory export job failed",{jobId:Q,error:$}),$}}summarizeDataForLog(A){return{entityTypes:A.entityTypes??"all",batchSize:A.batchSize}}}wA();class R90 extends aw{directorySync;constructor(A,Q,w){super(A,{schema:sc0,jobTypeName:"directory-import"});this.directorySync=w}async process(A,Q,w){this.logger.debug("Processing directory import job",{jobId:Q,data:A});let B=Date.now();try{let $=await this.directorySync.importEntitiesWithProgress(A.paths,w,A.batchSize??100);return this.logger.debug("Directory import job completed",{jobId:Q,imported:$.imported,skipped:$.skipped,failed:$.failed,quarantined:$.quarantined,duration:Date.now()-B}),$}catch($){throw this.logger.error("Directory import job failed",{jobId:Q,error:$}),$}}summarizeDataForLog(A){return{pathCount:A.paths?.length??"all",batchSize:A.batchSize}}}wA();class v90 extends aw{directorySync;context;constructor(A,Q,w){super(A,{schema:rc0,jobTypeName:"directory-sync"});this.context=Q,this.directorySync=w}async process(A,Q,w){let B=Date.now(),$=A.syncDirection??"both";this.logger.info("Starting directory sync job",{jobId:Q,operation:A.operation,syncDirection:$});let f={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},Y={exported:0,failed:0,errors:[]};if($!=="export")if(await w.report({progress:10,message:"Scanning directory for changes"}),f=await this.importWithProgress(A.paths,w),$==="import")await this.waitForImportJobs(f.jobIds,w),await w.report({progress:100,message:`Import complete: ${f.imported} imported`});else await w.report({progress:50,message:`Imported ${f.imported} entities`}),await this.waitForImportJobs(f.jobIds,w),await w.report({progress:56,message:"Processing complete, starting export"});if($!=="import"){let W=$==="export"?10:60;await w.report({progress:W,message:"Exporting entities to directory"}),Y=await this.exportWithProgress(A.entityTypes,w),await w.report({progress:100,message:$==="export"?`Export complete: ${Y.exported} exported`:`Sync complete: ${f.imported} imported, ${Y.exported} exported`})}let X=Date.now()-B;return this.logger.info("Directory sync job completed",{jobId:Q,duration:X,imported:f.imported,exported:Y.exported}),{import:f,export:Y,duration:X}}async importWithProgress(A,Q){try{return await this.directorySync.importEntitiesWithProgress(A,Q,10)}catch(w){throw this.logger.error("Import phase failed",{error:w}),w}}async exportWithProgress(A,Q){try{return await this.directorySync.exportEntitiesWithProgress(A,Q,10)}catch(w){throw this.logger.error("Export phase failed",{error:w}),w}}async waitForImportJobs(A,Q){if(A.length===0)return;this.logger.debug(`Waiting for ${A.length} import jobs to complete`);let{entityService:w}=this.context,B=300000,$=500,f=Date.now(),Y=async()=>{let W=(await Promise.all(A.map((K)=>w.getAsyncJobStatus(K)))).filter((K)=>K&&(K.status==="completed"||K.status==="failed")).length;if(W===A.length){this.logger.debug("All import jobs completed");return}if(Date.now()-f>B){this.logger.warn(`Timeout waiting for import jobs (${W}/${A.length} completed)`);return}let H=Math.round(W/A.length*100);return await Q.report({progress:50+Math.round(H*0.05),message:`Processing ${W}/${A.length} entities`}),await new Promise((K)=>setTimeout(K,$)),Y()};return Y()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}wA();class h90 extends aw{context;directorySync;gitSync;constructor(A,Q,w,B){super(A,{schema:oc0,jobTypeName:"sync-request"});this.context=Q,this.directorySync=w,this.gitSync=B}async process(A,Q,w){await w.report({progress:5,message:"Pulling latest content from git"});let B=await this.gitSync.withLock(async()=>{return await this.gitSync.pull(),await w.report({progress:35,message:"Scanning pulled content for sync changes"}),this.directorySync.queueSyncBatch(this.context,A.source,{rootJobId:Q,interfaceType:A.interfaceType,channelId:A.channelId})});if(!B)return await w.report({progress:100,message:"Sync complete: no files to import"}),{gitPulled:!0,batchQueued:!1};return await w.report({progress:100,message:`Sync queued: ${B.importOperationsCount} import jobs for ${B.totalFiles} files`}),KpQ(B)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function KpQ(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}wA();class C90 extends aw{context;constructor(A,Q,w){super(A,{schema:M90,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,w){let B=M90.parse(A);this.logger.info("Processing entity deletion for removed file",{entityId:B.entityId,entityType:B.entityType,filePath:B.filePath}),await w.report({progress:0,total:1,message:`Deleting ${B.entityType}:${B.entityId}`});try{let $=await this.context.entityService.deleteEntity({entityType:B.entityType,id:B.entityId});if($)this.logger.info("Successfully deleted entity for removed file",{entityId:B.entityId,entityType:B.entityType});else this.logger.warn("Entity not found in database",{entityId:B.entityId,entityType:B.entityType});return await w.report({progress:1,total:1,message:`Deleted ${B.entityType}:${B.entityId}`}),{deleted:$,entityId:B.entityId,entityType:B.entityType,filePath:B.filePath}}catch($){throw this.logger.error("Failed to delete entity",{entityId:B.entityId,entityType:B.entityType,error:$}),$}}summarizeDataForLog(A){return{entityId:A.entityId,entityType:A.entityType,filePath:A.filePath}}}wA();N0();var UpQ=Z.object({});class g90 extends aw{directorySync;constructor(A,Q){super(A,{schema:UpQ,jobTypeName:"directory-cleanup"});this.directorySync=Q}async process(A,Q,w){await w.report({progress:0,message:"Removing orphaned entities"});let B=await this.directorySync.removeOrphanedEntities();return await w.report({progress:100,message:`Cleanup complete: ${B.deleted} orphans removed`}),B}}wA();J4();S9();g6();N0();J4();import{readFile as DpQ,writeFile as GpQ}from"fs/promises";var zpQ=tc0,qpQ=Z.record(Z.string(),Z.unknown());class y90 extends aw{context;fetcher;constructor(A,Q,w=TW){super(Q,{schema:zpQ,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=w}async process(A,Q,w){let{filePath:B,sourceUrl:$,postTitle:f,postSlug:Y,customAlt:X}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:B,sourceUrl:$,postSlug:Y});try{await this.reportProgress(w,{progress:dQ.INIT,message:`Reading file: ${B}`});let W;try{W=await DpQ(B,"utf-8")}catch(V){return this.logger.error("Failed to read file",{filePath:B,error:mA(V)}),Q$.failure(V)}let H;try{H=j6(W)}catch(V){return this.logger.warn("Failed to parse markdown",{filePath:B,error:mA(V)}),Q$.failure(V)}let K=qpQ.safeParse(H.frontmatter),U=K.success?K.data:{};if(U.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:B}),await this.reportProgress(w,{progress:dQ.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(w,{progress:dQ.FETCH,message:"Checking for existing image"});let D=await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:$}},limit:1}}),q;if(D[0])q=D[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:$,imageId:q}),await this.reportProgress(w,{progress:dQ.EXTRACT,message:`Reusing existing image: ${q}`});else{await this.reportProgress(w,{progress:dQ.PROCESS,message:`Fetching image from ${$}`});let V;try{V=await this.fetcher($)}catch(h){return this.logger.error("Failed to fetch image",{sourceUrl:$,error:mA(h)}),Q$.failure(h)}await this.reportProgress(w,{progress:dQ.GENERATE,message:"Creating image entity"});let{base64:L}=sV(V),N=ik(L),k=aV(L);if(!N||!k)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:$}),Q$.failure(Error("Could not detect image format or dimensions"));q=`${Y}-cover`;let x=`Cover image for ${f}`,R=X??x;await this.context.entityService.createEntity({entity:{id:q,entityType:"image",content:V,metadata:{title:x,alt:R,format:N,width:k.width,height:k.height,sourceUrl:$}}}),this.logger.debug("Created image entity",{imageId:q,sourceUrl:$}),await this.reportProgress(w,{progress:dQ.EXTRACT,message:`Created image: ${q}`})}await this.reportProgress(w,{progress:dQ.SAVE,message:"Updating file"});let b={...U};delete b.coverImageUrl,delete b.coverImageAlt,b.coverImageId=q;let I=Gk(b,H.content);try{await GpQ(B,I,"utf-8")}catch(V){return this.logger.error("Failed to write file",{filePath:B,error:mA(V)}),Q$.failure(V)}return await this.reportProgress(w,{progress:dQ.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:B,imageId:q,sourceUrl:$}),{success:!0,imageId:q}}catch(W){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:B,error:mA(W)}),Q$.failure(W)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}wA();J4();g6();import{readFile as bpQ,writeFile as VpQ}from"fs/promises";class E90 extends aw{converter;constructor(A,Q,w=TW){super(Q,{schema:ec0,jobTypeName:"inline-image-convert"});this.converter=new vd(A.entityService,Q,w)}async process(A,Q,w){let{filePath:B,postSlug:$}=A;this.logger.debug("Starting inline image conversion job",{jobId:Q,filePath:B,postSlug:$});try{await this.reportProgress(w,{progress:dQ.INIT,message:`Reading file: ${B}`});let f;try{f=await bpQ(B,"utf-8")}catch(W){let H=mA(W);return this.logger.error("Failed to read file",{filePath:B,error:H}),{success:!1,error:H}}await this.reportProgress(w,{progress:dQ.FETCH,message:"Detecting inline images"});let Y=this.converter.detectInlineImages(f,$);if(Y.length===0)return this.logger.debug("No inline images to convert",{filePath:B}),await this.reportProgress(w,{progress:dQ.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:B,count:Y.length}),await this.reportProgress(w,{progress:dQ.PROCESS,message:`Converting ${Y.length} images`});let X=await this.converter.convert(f,$);if(!X.converted)return this.logger.debug("No images were converted",{filePath:B}),await this.reportProgress(w,{progress:dQ.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(w,{progress:dQ.SAVE,message:"Writing updated file"});try{await VpQ(B,X.content,"utf-8")}catch(W){let H=mA(W);return this.logger.error("Failed to write file",{filePath:B,error:H}),{success:!1,error:H}}return await this.reportProgress(w,{progress:dQ.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:B,convertedCount:X.convertedCount}),{success:!0,convertedCount:X.convertedCount}}catch(f){let Y=mA(f);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:B,error:Y}),{success:!1,error:Y}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function jh1(A,Q,w){let B=($)=>w.child($);A.jobs.registerHandler("directory-sync",new v90(B("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new x90(B("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new R90(B("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new C90(B("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new g90(B("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new y90(A,B("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new E90(A,B("InlineImageConversionJobHandler"))),w.debug("Registered async job handlers")}wA();N0();import{unlink as IpQ,access as JpQ}from"fs/promises";var FpQ=Z.record(Z.string(),Z.unknown());function Ph1(A,Q,w,B){let{subscribe:$}=A.messaging,{entityService:f}=A;$("entity:created",async(Y)=>{let{entity:X}=Y.payload;try{await Q.fileOps.writeEntity(X),w.debug("Auto-exported created entity",{id:X.id,entityType:X.entityType})}catch(W){w.error("Auto-export FAILED for created entity",{id:X.id,entityType:X.entityType,error:W instanceof Error?W.message:String(W),stack:W instanceof Error?W.stack:void 0})}return{success:!0}}),$("entity:updated",async(Y)=>{let{entityType:X,entityId:W}=Y.payload;try{let H=await f.getEntity({entityType:X,id:W});if(!H)return w.debug("Entity not found in DB, skipping export",{entityType:X,entityId:W}),{success:!1};await Q.fileOps.writeEntity(H),w.debug("Auto-exported updated entity",{id:H.id,entityType:H.entityType})}catch(H){w.error("Auto-export FAILED for updated entity",{entityType:X,entityId:W,error:H instanceof Error?H.message:String(H),stack:H instanceof Error?H.stack:void 0})}return{success:!0}}),$("entity:deleted",async(Y)=>{let{entityId:X,entityType:W}=Y.payload,H=Q.fileOps.getFilePath(X,W);if(await JpQ(H).then(()=>!0,()=>!1))await IpQ(H),w.debug("Auto-deleted entity file",{id:X,entityType:W,path:H});return{success:!0}}),w.debug("Setup auto-sync for entity events",{entityTypes:B})}function Mh1(A,Q,w){Q.setJobQueueCallback(async(B)=>{let $=[{type:B.type,data:FpQ.parse(B.data)}];return A.jobs.enqueueBatch($,{priority:5,source:"directory-sync-watcher",rootJobId:Z4(),metadata:{operationType:"file_operations",operationTarget:w,pluginId:"directory-sync"}})})}wA();import{readdir as Rh1,mkdir as kpQ,copyFile as _pQ}from"fs/promises";import{join as xh1,resolve as Al0}from"path";import{join as LpQ}from"path";async function Oh1(A){if(!await i8(LpQ(A,".git")))return!1;try{return await YU(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function NpQ(A,Q){if(!await i8(A))return!0;if((await Rh1(A)).filter(($)=>!$.startsWith(".")&&!$.startsWith("_")).length>0)return!1;if(await Oh1(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function vh1(A,Q){let w=await Rh1(A,{withFileTypes:!0});for(let B of w){let $=xh1(A,B.name),f=xh1(Q,B.name);if(B.isDirectory()){if(!await i8(f))await kpQ(f,{recursive:!0});await vh1($,f)}else await _pQ($,f)}}async function hh1(A,Q,w){let B=Al0(process.cwd(),A);w=w?Al0(w):Al0(process.cwd(),"seed-content");let $=await NpQ(B,Q);if($&&await i8(w))Q.debug("Copying seed content to brain-data directory"),await vh1(w,B),Q.debug("Seed content copied successfully");else if($)Q.debug("No seed content directory found, starting with empty brain-data");else Q.debug("brain-data directory not empty, skipping seed content")}function Ch1(A,Q,w,B,$){let f=!1,Y=async()=>{if(f)return;f=!0;let X=Q();if(w.seedContent){let W=w.syncPath??A.dataDir;await hh1(W,B,w.seedContentPath)}try{if($){B.debug("Git enabled \u2014 pulling before import");let H=await $.pull();if(H.files.length>0)B.info("Pulled changes from remote",{filesChanged:H.files.length})}B.debug("Starting initial sync");let W=await X.sync();B.debug("Initial sync completed",{imported:W.import.imported,failed:W.import.failed,duration:W.duration}),await A.messaging.send({type:Vk.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(W){B.error("Initial sync failed",W),await A.messaging.send({type:Vk.initialSyncCompleted,payload:{success:!1,error:mA(W)},...{broadcast:!0}})}};A.messaging.subscribe(Vk.pluginsRegistered,async()=>{return B.debug("Plugins registered, starting initial sync"),await Y(),{success:!0}})}class nd{fn;delayMs;timeout;pending=!1;constructor(A,Q){this.fn=A,this.delayMs=Q}trigger(){if(!this.timeout){this.fn(),this.timeout=setTimeout(()=>{if(this.timeout=void 0,this.pending)this.pending=!1,this.fn()},this.delayMs);return}this.pending=!0,clearTimeout(this.timeout),this.timeout=setTimeout(()=>{if(this.timeout=void 0,this.pending)this.pending=!1,this.fn()},this.delayMs)}dispose(){if(this.timeout)clearTimeout(this.timeout),this.timeout=void 0;this.pending=!1}}function gh1(A,Q,w,B){let $=new nd(()=>{Q.withLock(async()=>{try{await Q.commit(),await Q.push()}catch(X){B.error("Git auto-commit failed",{error:X})}})},w),f=["entity:created","entity:updated","entity:deleted"],Y=[];for(let X of f){let W=A.subscribe(X,async()=>{return $.trigger(),{success:!0}});Y.push(W)}return()=>{$.dispose();for(let X of Y)X()}}function yh1(A,Q,w,B,$){if(B<=0)return()=>{};let f=B*60*1000,Y=!1,X=async()=>{if(Y)return;Y=!0;try{let{files:H,result:K}=await A.withLock(async()=>{let U=await A.pull();if(U.files.length===0)return{files:[],result:null};let D=await Q.queueSyncBatch(w,"periodic-sync");return{files:U.files,result:D}});if(H.length>0)$.info("Periodic sync: pulled changes",{filesChanged:H.length});if(K)$.debug("Periodic sync: queued imports",{importOperations:K.importOperationsCount,totalFiles:K.totalFiles})}catch(H){$.error("Periodic git sync failed",{error:H})}finally{Y=!1}},W=setInterval(()=>{X()},f);return $.info("Started periodic git sync",{intervalMinutes:B}),()=>{clearInterval(W)}}import{spawnSync as Th1}from"child_process";import{cpSync as jpQ,existsSync as Eh1,mkdirSync as PpQ,mkdtempSync as MpQ,rmSync as OpQ}from"fs";import{tmpdir as xpQ}from"os";import{fileURLToPath as RpQ}from"url";import{join as vpQ,resolve as hpQ}from"path";function pJ(A,Q){let w=Th1("git",Q,{cwd:A,stdio:"pipe"});if(w.status!==0){let B=w.stderr.toString().trim(),$=w.stdout.toString().trim();throw Error(B||$||`git ${Q.join(" ")} failed`)}}function CpQ(A){return A.startsWith("file://")}function gpQ(A){return RpQ(A)}function ypQ(A,Q){return Th1("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function Sh1(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!CpQ(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",w=gpQ(A.gitUrl),B=hpQ(A.seedContentPath);if(!Eh1(B))throw Error(`Seed content path not found: ${B}`);if(!Eh1(w))A.logger.debug("Creating local bare content remote",{remotePath:w,branch:Q}),PpQ(w,{recursive:!0}),pJ(process.cwd(),["init","--bare",`--initial-branch=${Q}`,w]);if(ypQ(w,Q)){A.logger.debug("Content remote already initialized",{remotePath:w,branch:Q});return}A.logger.debug("Seeding local content remote",{remotePath:w,seedPath:B,branch:Q});let $=MpQ(vpQ(xpQ(),"directory-sync-seed-"));try{pJ($,["init",`--initial-branch=${Q}`]),pJ($,["config","user.name",A.authorName??"Brain"]),pJ($,["config","user.email",A.authorEmail??"brain@localhost"]),jpQ(B,$,{recursive:!0}),pJ($,["add","."]),pJ($,["commit","-m","seed content remote"]),pJ($,["remote","add","origin",A.gitUrl]),pJ($,["push","-u","origin",Q])}finally{OpQ($,{recursive:!0,force:!0})}}function mh1(A,Q,w,B,$){let{subscribe:f}=A.messaging;f("entity:export:request",async(Y)=>{try{return{success:!0,data:await Q().exportEntities(Y.payload.entityTypes)}}catch(X){return{success:!1,error:X instanceof Error?X.message:"Export failed"}}}),f("entity:import:request",async(Y)=>{try{let X=Q(),W=Y.payload.paths,H=await X.importEntities(W);if(W&&W.length>0)await X.removeOrphanedEntities();return{success:!0,data:H}}catch(X){return{success:!1,error:X instanceof Error?X.message:"Import failed"}}}),f("sync:status:request",async()=>{try{let X=await Q().getStatus();return{success:!0,data:{syncPath:X.syncPath,isInitialized:X.exists,watchEnabled:X.watching}}}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:"Status check failed"}}}),f("sync:configure:request",async(Y)=>{try{return await w({syncPath:Y.payload.syncPath}),{success:!0,data:{syncPath:Y.payload.syncPath,configured:!0}}}catch(X){return{success:!1,error:X instanceof Error?X.message:"Configuration failed"}}}),f("git-sync:get-repo-info",async()=>{if(!$?.repo)return{success:!1,error:"Git not configured"};return{success:!0,data:{repo:$.repo,branch:$.branch??"main"}}}),B.debug("Registered message handlers")}wA();N0();wA();N0();function uh1(A,Q){return P6(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",Z.object({entityType:Z.string().describe("Entity type (e.g. post, note, link)"),id:Z.string().describe("Entity ID"),sha:Z.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:Z.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async(w)=>{let B=`${w.entityType}/${w.id}.md`;try{if(w.sha){let f=await Q.show(w.sha,B);return z5({sha:w.sha,entityType:w.entityType,id:w.id,content:f},`Content at ${w.sha.slice(0,7)}`)}let $=await Q.log(B,w.limit);if($.length===0)return z5({commits:[]},`No history found for ${w.entityType}/${w.id}`);return z5({commits:$,entityType:w.entityType,id:w.id},`${$.length} version${$.length===1?"":"s"} found`)}catch($){return k7($ instanceof Error?$.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function ch1(A,Q,w,B){let $=[P6(w,"sync","Sync brain entities with the filesystem. Use this for refresh, pull, sync, or backup-to-git requests. Pulls from git if configured, then imports files. Git commit and push happen automatically after imports complete.",Z.object({}),async(f,Y)=>{try{let X=Y.channelId?`${Y.interfaceType}:${Y.channelId}`:`plugin:${w}`,W={interfaceType:Y.interfaceType,channelId:Y.channelId};if(B){let K=await Q.jobs.enqueue({type:"sync-request",data:{source:X,interfaceType:W.interfaceType,channelId:W.channelId},toolContext:Y});return z5({jobId:K,status:"queued",gitPulled:!0},"Sync queued: git pull and filesystem scan will run in the background")}let H=await A.queueSyncBatch(Q,X,W);if(!H)return z5({gitPulled:!1},"No files to sync");return z5({batchId:H.batchId,importOperations:H.importOperationsCount,totalFiles:H.totalFiles,gitPulled:!1},`Sync started: ${H.importOperationsCount} import jobs queued for ${H.totalFiles} files`)}catch(X){return k7(X instanceof Error?X.message:"Sync failed")}},{visibility:"anchor",sideEffects:"external",cli:{name:"sync"}}),P6(w,"status","Get sync and git repository status \u2014 last sync time, watching state, pending git changes. Use this for status questions, not for actually syncing or backing up.",Z.object({}),async()=>{try{let f=await A.getStatus(),Y={syncPath:f.syncPath,lastSync:f.lastSync?.toISOString(),watching:f.watching};if(B){let X=await B.getStatus();Y.git={isRepo:X.isRepo,branch:X.branch,hasChanges:X.hasChanges,ahead:X.ahead,behind:X.behind,remote:X.remote}}return z5(Y)}catch(f){return k7(f instanceof Error?f.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if(B)$.push(uh1(w,B));return $}var lh1={name:"@brains/directory-sync",version:"0.2.0-alpha.143",description:"Directory-based entity synchronization plugin for Brains",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",chokidar:"^5.0.0","simple-git":"^3.36.0"},devDependencies:{"@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^6.0.3"},exports:{".":{types:"./src/index.ts",import:"./src/index.ts"},"./env-schema":"./src/env-schema.ts"},main:"./src/index.ts",peerDependencies:{},private:!0,scripts:{clean:"rm -rf .turbo",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};class Ql0 extends aQ{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",lh1,A,id)}requireDirectorySync(){if(!this.directorySync)throw Error("DirectorySync service not initialized");return this.directorySync}hasGitSync(){return this.gitSync!==void 0}async onRegister(A){let{logger:Q,entityService:w}=A;A.templates.register({status:{name:"status",description:"Directory synchronization status",schema:dd,basePrompt:"",formatter:new O90,requiredPermission:"anchor"}});let B=this.config.syncPath??A.dataDir;this.directorySync=new hd({syncPath:B,autoSync:this.config.autoSync,watchInterval:this.config.watchInterval,includeMetadata:this.config.includeMetadata,entityTypes:this.config.entityTypes,deleteOnFileRemoval:this.config.deleteOnFileRemoval,entityService:w,logger:Q});try{await this.directorySync.initializeDirectory(),this.logger.debug("Directory structure initialized",{path:B})}catch(Y){throw this.logger.error("Failed to initialize directory",Y),Y}await this.registerJobHandlers(A);let $=this.requireDirectorySync();if(Ph1(A,$,this.logger,this.config.entityTypes),this.config.autoSync)Mh1(A,$,this.config.syncPath??A.dataDir);let f=this.config.git!==void 0&&(this.config.git.repo!==void 0||this.config.git.gitUrl!==void 0);if(this.config.git&&!f)this.logger.debug("Git block present but no repo/gitUrl configured \u2014 git sync disabled");if(f&&this.config.git){await Sh1({gitUrl:this.config.git.gitUrl,branch:this.config.git.branch,seedContentPath:this.config.seedContentPath,bootstrapFromSeed:this.config.git.bootstrapFromSeed,authorName:this.config.git.authorName,authorEmail:this.config.git.authorEmail,logger:this.logger.child("ContentRemoteBootstrap")});let Y=this.config.syncPath??A.dataDir;if(this.gitSync=new nc0({logger:this.logger.child("GitSync"),dataDir:Y,repo:this.config.git.repo,gitUrl:this.config.git.gitUrl,branch:this.config.git.branch,authToken:this.config.git.authToken,authorName:this.config.git.authorName,authorEmail:this.config.git.authorEmail}),await this.gitSync.initialize(),this.logger.info("Git integration enabled",{repo:this.config.git.repo}),A.jobs.registerHandler("sync-request",new h90(this.logger.child("DirectorySyncRequestJobHandler"),A,this.requireDirectorySync(),this.gitSync)),this.gitCleanups.push(gh1(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(yh1(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)Ch1(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync);mh1(A,()=>this.requireDirectorySync(),(Y)=>this.configure(Y),this.logger,this.config.git)}async getTools(){let A=this.requireDirectorySync();return ch1(A,this.getContext(),this.id,this.gitSync)}async onShutdown(){for(let A of this.gitCleanups)A();this.gitCleanups=[],this.directorySync?.stopWatching(),this.gitSync?.cleanup()}getDirectorySync(){return this.directorySync}async configure(A){this.requireDirectorySync();let Q=this.getContext();this.directorySync=new hd({...this.config,syncPath:A.syncPath,entityService:Q.entityService,logger:Q.logger}),await this.directorySync.initialize(),this.logger.info("Directory sync reconfigured",{path:A.syncPath})}async registerJobHandlers(A){jh1(A,this.requireDirectorySync(),this.logger)}}function fj(A={}){return new Ql0(A)}wA();N0();var ph1={name:"@brains/email-resend",version:"0.2.0-alpha.143",description:"Generic email delivery adapter for Resend",dependencies:{"@brains/email-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var SpQ=Z.object({apiKey:Z.string().min(1).optional(),from:Z.string().min(1).optional()}),mpQ=Z.looseObject({id:Z.string().optional()});class ih1 extends aQ{fetchImpl;constructor(A={},Q={}){super("email-resend",ph1,A,SpQ);this.fetchImpl=Q.fetchImpl??fetch}async onRegister(A){if(!this.config.apiKey||!this.config.from){this.logger.warn("Email Resend adapter is disabled because apiKey or from is missing");return}let Q=this.logger;A.messaging.subscribe(S60,async(w)=>{let B=ogA.parse(w.payload);try{return{success:!0,data:await this.sendWithResend(B)}}catch($){if(B.sensitivity==="secret")Q.warn("Email delivery failed for a secret message");else Q.warn("Email delivery failed",{to:B.to,subject:B.subject,error:$ instanceof Error?$.message:String($)});return{success:!1,error:"Email delivery failed"}}})}async sendWithResend(A){let Q=this.config.apiKey,w=this.config.from;if(!Q||!w)return{status:"failed"};let B=await this.fetchImpl("https://api.resend.com/emails",{method:"POST",headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},body:JSON.stringify({from:w,to:A.to,subject:A.subject,text:A.text,...A.html?{html:A.html}:{}})});if(!B.ok)throw Error("Resend email request failed");let $=mpQ.parse(await B.json());return $.id?{status:"sent",id:$.id}:{status:"sent"}}}function T90(A={}){return new ih1(A)}wA();import{render as Ro1}from"preact-render-to-string";import{h as uj}from"preact";function dh1(A){var Q,w,B="";if(typeof A=="string"||typeof A=="number")B+=A;else if(typeof A=="object")if(Array.isArray(A)){var $=A.length;for(Q=0;Q<$;Q++)A[Q]&&(w=dh1(A[Q]))&&(B&&(B+=" "),B+=w)}else for(w in A)A[w]&&(B&&(B+=" "),B+=w);return B}function pC(){for(var A,Q,w=0,B="",$=arguments.length;w<$;w++)(A=arguments[w])&&(Q=dh1(A))&&(B&&(B+=" "),B+=Q);return B}var upQ=(A,Q)=>{let w=Array(A.length+Q.length);for(let B=0;B<A.length;B++)w[B]=A[B];for(let B=0;B<Q.length;B++)w[A.length+B]=Q[B];return w},cpQ=(A,Q)=>({classGroupId:A,validator:Q}),AC1=(A=new Map,Q=null,w)=>({nextPart:A,validators:Q,classGroupId:w});var nh1=[];var lpQ=(A)=>{let Q=ipQ(A),{conflictingClassGroups:w,conflictingClassGroupModifiers:B}=A;return{getClassGroupId:(Y)=>{if(Y.startsWith("[")&&Y.endsWith("]"))return ppQ(Y);let X=Y.split("-"),W=X[0]===""&&X.length>1?1:0;return QC1(X,W,Q)},getConflictingClassGroupIds:(Y,X)=>{if(X){let W=B[Y],H=w[Y];if(W){if(H)return upQ(H,W);return W}return H||nh1}return w[Y]||nh1}}},QC1=(A,Q,w)=>{if(A.length-Q===0)return w.classGroupId;let $=A[Q],f=w.nextPart.get($);if(f){let H=QC1(A,Q+1,f);if(H)return H}let Y=w.validators;if(Y===null)return;let X=Q===0?A.join("-"):A.slice(Q).join("-"),W=Y.length;for(let H=0;H<W;H++){let K=Y[H];if(K.validator(X))return K.classGroupId}return},ppQ=(A)=>A.slice(1,-1).indexOf(":")===-1?void 0:(()=>{let Q=A.slice(1,-1),w=Q.indexOf(":"),B=Q.slice(0,w);return B?"arbitrary.."+B:void 0})(),ipQ=(A)=>{let{theme:Q,classGroups:w}=A;return dpQ(w,Q)},dpQ=(A,Q)=>{let w=AC1();for(let B in A){let $=A[B];$l0($,w,B,Q)}return w},$l0=(A,Q,w,B)=>{let $=A.length;for(let f=0;f<$;f++){let Y=A[f];npQ(Y,Q,w,B)}},npQ=(A,Q,w,B)=>{if(typeof A==="string"){rpQ(A,Q,w);return}if(typeof A==="function"){opQ(A,Q,w,B);return}spQ(A,Q,w,B)},rpQ=(A,Q,w)=>{let B=A===""?Q:wC1(Q,A);B.classGroupId=w},opQ=(A,Q,w,B)=>{if(apQ(A)){$l0(A(B),Q,w,B);return}if(Q.validators===null)Q.validators=[];Q.validators.push(cpQ(w,A))},spQ=(A,Q,w,B)=>{let $=Object.entries(A),f=$.length;for(let Y=0;Y<f;Y++){let[X,W]=$[Y];$l0(W,wC1(Q,X),w,B)}},wC1=(A,Q)=>{let w=A,B=Q.split("-"),$=B.length;for(let f=0;f<$;f++){let Y=B[f],X=w.nextPart.get(Y);if(!X)X=AC1(),w.nextPart.set(Y,X);w=X}return w},apQ=(A)=>("isThemeGetter"in A)&&A.isThemeGetter===!0,tpQ=(A)=>{if(A<1)return{get:()=>{return},set:()=>{}};let Q=0,w=Object.create(null),B=Object.create(null),$=(f,Y)=>{if(w[f]=Y,Q++,Q>A)Q=0,B=w,w=Object.create(null)};return{get(f){let Y=w[f];if(Y!==void 0)return Y;if((Y=B[f])!==void 0)return $(f,Y),Y},set(f,Y){if(f in w)w[f]=Y;else $(f,Y)}}};var epQ=[],rh1=(A,Q,w,B,$)=>({modifiers:A,hasImportantModifier:Q,baseClassName:w,maybePostfixModifierPosition:B,isExternal:$}),AiQ=(A)=>{let{prefix:Q,experimentalParseClassName:w}=A,B=($)=>{let f=[],Y=0,X=0,W=0,H,K=$.length;for(let I=0;I<K;I++){let V=$[I];if(Y===0&&X===0){if(V===":"){f.push($.slice(W,I)),W=I+1;continue}if(V==="/"){H=I;continue}}if(V==="[")Y++;else if(V==="]")Y--;else if(V==="(")X++;else if(V===")")X--}let U=f.length===0?$:$.slice(W),D=U,q=!1;if(U.endsWith("!"))D=U.slice(0,-1),q=!0;else if(U.startsWith("!"))D=U.slice(1),q=!0;let b=H&&H>W?H-W:void 0;return rh1(f,q,D,b)};if(Q){let $=Q+":",f=B;B=(Y)=>Y.startsWith($)?f(Y.slice($.length)):rh1(epQ,!1,Y,void 0,!0)}if(w){let $=B;B=(f)=>w({className:f,parseClassName:$})}return B},QiQ=(A)=>{let Q=new Map;return A.orderSensitiveModifiers.forEach((w,B)=>{Q.set(w,1e6+B)}),(w)=>{let B=[],$=[];for(let f=0;f<w.length;f++){let Y=w[f],X=Y[0]==="[",W=Q.has(Y);if(X||W){if($.length>0)$.sort(),B.push(...$),$=[];B.push(Y)}else $.push(Y)}if($.length>0)$.sort(),B.push(...$);return B}},wiQ=(A)=>({cache:tpQ(A.cacheSize),parseClassName:AiQ(A),sortModifiers:QiQ(A),postfixLookupClassGroupIds:BiQ(A),...lpQ(A)}),BiQ=(A)=>{let Q=Object.create(null),w=A.postfixLookupClassGroups;if(w)for(let B=0;B<w.length;B++)Q[w[B]]=!0;return Q},$iQ=/\s+/,fiQ=(A,Q)=>{let{parseClassName:w,getClassGroupId:B,getConflictingClassGroupIds:$,sortModifiers:f,postfixLookupClassGroupIds:Y}=Q,X=[],W=A.trim().split($iQ),H="";for(let K=W.length-1;K>=0;K-=1){let U=W[K],{isExternal:D,modifiers:q,hasImportantModifier:b,baseClassName:I,maybePostfixModifierPosition:V}=w(U);if(D){H=U+(H.length>0?" "+H:H);continue}let L=!!V,N;if(L){let P=I.substring(0,V);N=B(P);let E=N&&Y[N]?B(I):void 0;if(E&&E!==N)N=E,L=!1}else N=B(I);if(!N){if(!L){H=U+(H.length>0?" "+H:H);continue}if(N=B(I),!N){H=U+(H.length>0?" "+H:H);continue}L=!1}let k=q.length===0?"":q.length===1?q[0]:f(q).join(":"),x=b?k+"!":k,R=x+N;if(X.indexOf(R)>-1)continue;X.push(R);let h=$(N,L);for(let P=0;P<h.length;++P){let E=h[P];X.push(x+E)}H=U+(H.length>0?" "+H:H)}return H},YiQ=(...A)=>{let Q=0,w,B,$="";while(Q<A.length)if(w=A[Q++]){if(B=BC1(w))$&&($+=" "),$+=B}return $},BC1=(A)=>{if(typeof A==="string")return A;let Q,w="";for(let B=0;B<A.length;B++)if(A[B]){if(Q=BC1(A[B]))w&&(w+=" "),w+=Q}return w},oh1=(A,...Q)=>{let w,B,$,f,Y=(W)=>{let H=Q.reduce((K,U)=>U(K),A());return w=wiQ(H),B=w.cache.get,$=w.cache.set,f=X,X(W)},X=(W)=>{let H=B(W);if(H)return H;let K=fiQ(W,w);return $(W,K),K};return f=Y,(...W)=>f(YiQ(...W))},XiQ=[],q9=(A)=>{let Q=(w)=>w[A]||XiQ;return Q.isThemeGetter=!0,Q},$C1=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,fC1=/^\((?:(\w[\w-]*):)?(.+)\)$/i,ZiQ=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,WiQ=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,HiQ=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,KiQ=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,UiQ=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,DiQ=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,iJ=(A)=>ZiQ.test(A),Cw=(A)=>!!A&&!Number.isNaN(Number(A)),_G=(A)=>!!A&&Number.isInteger(Number(A)),wl0=(A)=>A.endsWith("%")&&Cw(A.slice(0,-1)),hq=(A)=>WiQ.test(A),YC1=()=>!0,GiQ=(A)=>HiQ.test(A)&&!KiQ.test(A),fl0=()=>!1,ziQ=(A)=>UiQ.test(A),qiQ=(A)=>DiQ.test(A),biQ=(A)=>!I2(A)&&!k2(A),ViQ=(A)=>A.startsWith("@container")&&(A[10]==="/"&&A[11]!==void 0||A[11]==="s"&&A[16]!==void 0&&A.startsWith("-size/",10)||A[11]==="n"&&A[18]!==void 0&&A.startsWith("-normal/",10)),IiQ=(A)=>dJ(A,WC1,fl0),I2=(A)=>$C1.test(A),Yj=(A)=>dJ(A,HC1,GiQ),sh1=(A)=>dJ(A,PiQ,Cw),JiQ=(A)=>dJ(A,UC1,YC1),FiQ=(A)=>dJ(A,KC1,fl0),ah1=(A)=>dJ(A,XC1,fl0),LiQ=(A)=>dJ(A,ZC1,qiQ),S90=(A)=>dJ(A,DC1,ziQ),k2=(A)=>fC1.test(A),rd=(A)=>Xj(A,HC1),kiQ=(A)=>Xj(A,KC1),th1=(A)=>Xj(A,XC1),_iQ=(A)=>Xj(A,WC1),NiQ=(A)=>Xj(A,ZC1),m90=(A)=>Xj(A,DC1,!0),jiQ=(A)=>Xj(A,UC1,!0),dJ=(A,Q,w)=>{let B=$C1.exec(A);if(B){if(B[1])return Q(B[1]);return w(B[2])}return!1},Xj=(A,Q,w=!1)=>{let B=fC1.exec(A);if(B){if(B[1])return Q(B[1]);return w}return!1},XC1=(A)=>A==="position"||A==="percentage",ZC1=(A)=>A==="image"||A==="url",WC1=(A)=>A==="length"||A==="size"||A==="bg-size",HC1=(A)=>A==="length",PiQ=(A)=>A==="number",KC1=(A)=>A==="family-name",UC1=(A)=>A==="number"||A==="weight",DC1=(A)=>A==="shadow";var eh1=()=>{let A=q9("color"),Q=q9("font"),w=q9("text"),B=q9("font-weight"),$=q9("tracking"),f=q9("leading"),Y=q9("breakpoint"),X=q9("container"),W=q9("spacing"),H=q9("radius"),K=q9("shadow"),U=q9("inset-shadow"),D=q9("text-shadow"),q=q9("drop-shadow"),b=q9("blur"),I=q9("perspective"),V=q9("aspect"),L=q9("ease"),N=q9("animate"),k=()=>["auto","avoid","all","avoid-page","page","left","right","column"],x=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],R=()=>[...x(),k2,I2],h=()=>["auto","hidden","clip","visible","scroll"],P=()=>["auto","contain","none"],E=()=>[k2,I2,W],S=()=>[iJ,"full","auto",...E()],p=()=>[_G,"none","subgrid",k2,I2],e=()=>["auto",{span:["full",_G,k2,I2]},_G,k2,I2],Y0=()=>[_G,"auto",k2,I2],l=()=>["auto","min","max","fr",k2,I2],j=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],g=()=>["start","end","center","stretch","center-safe","end-safe"],y=()=>["auto",...E()],n=()=>[iJ,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...E()],o=()=>[iJ,"screen","full","dvw","lvw","svw","min","max","fit",...E()],K0=()=>[iJ,"screen","full","lh","dvh","lvh","svh","min","max","fit",...E()],c=()=>[A,k2,I2],X0=()=>[...x(),th1,ah1,{position:[k2,I2]}],b0=()=>["no-repeat",{repeat:["","x","y","space","round"]}],w0=()=>["auto","cover","contain",_iQ,IiQ,{size:[k2,I2]}],h0=()=>[wl0,rd,Yj],S0=()=>["","none","full",H,k2,I2],V0=()=>["",Cw,rd,Yj],I0=()=>["solid","dashed","dotted","double"],j0=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],C0=()=>[Cw,wl0,th1,ah1],k0=()=>["","none",b,k2,I2],_0=()=>["none",Cw,k2,I2],P0=()=>["none",Cw,k2,I2],M0=()=>[Cw,k2,I2],T0=()=>[iJ,"full",...E()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[hq],breakpoint:[hq],color:[YC1],container:[hq],"drop-shadow":[hq],ease:["in","out","in-out"],font:[biQ],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[hq],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[hq],shadow:[hq],spacing:["px",Cw],text:[hq],"text-shadow":[hq],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",iJ,I2,k2,V]}],container:["container"],"container-type":[{"@container":["","normal","size",k2,I2]}],"container-named":[ViQ],columns:[{columns:[Cw,I2,k2,X]}],"break-after":[{"break-after":k()}],"break-before":[{"break-before":k()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],sr:["sr-only","not-sr-only"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:R()}],overflow:[{overflow:h()}],"overflow-x":[{"overflow-x":h()}],"overflow-y":[{"overflow-y":h()}],overscroll:[{overscroll:P()}],"overscroll-x":[{"overscroll-x":P()}],"overscroll-y":[{"overscroll-y":P()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:S()}],"inset-x":[{"inset-x":S()}],"inset-y":[{"inset-y":S()}],start:[{"inset-s":S(),start:S()}],end:[{"inset-e":S(),end:S()}],"inset-bs":[{"inset-bs":S()}],"inset-be":[{"inset-be":S()}],top:[{top:S()}],right:[{right:S()}],bottom:[{bottom:S()}],left:[{left:S()}],visibility:["visible","invisible","collapse"],z:[{z:[_G,"auto",k2,I2]}],basis:[{basis:[iJ,"full","auto",X,...E()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[Cw,iJ,"auto","initial","none",I2]}],grow:[{grow:["",Cw,k2,I2]}],shrink:[{shrink:["",Cw,k2,I2]}],order:[{order:[_G,"first","last","none",k2,I2]}],"grid-cols":[{"grid-cols":p()}],"col-start-end":[{col:e()}],"col-start":[{"col-start":Y0()}],"col-end":[{"col-end":Y0()}],"grid-rows":[{"grid-rows":p()}],"row-start-end":[{row:e()}],"row-start":[{"row-start":Y0()}],"row-end":[{"row-end":Y0()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":l()}],"auto-rows":[{"auto-rows":l()}],gap:[{gap:E()}],"gap-x":[{"gap-x":E()}],"gap-y":[{"gap-y":E()}],"justify-content":[{justify:[...j(),"normal"]}],"justify-items":[{"justify-items":[...g(),"normal"]}],"justify-self":[{"justify-self":["auto",...g()]}],"align-content":[{content:["normal",...j()]}],"align-items":[{items:[...g(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...g(),{baseline:["","last"]}]}],"place-content":[{"place-content":j()}],"place-items":[{"place-items":[...g(),"baseline"]}],"place-self":[{"place-self":["auto",...g()]}],p:[{p:E()}],px:[{px:E()}],py:[{py:E()}],ps:[{ps:E()}],pe:[{pe:E()}],pbs:[{pbs:E()}],pbe:[{pbe:E()}],pt:[{pt:E()}],pr:[{pr:E()}],pb:[{pb:E()}],pl:[{pl:E()}],m:[{m:y()}],mx:[{mx:y()}],my:[{my:y()}],ms:[{ms:y()}],me:[{me:y()}],mbs:[{mbs:y()}],mbe:[{mbe:y()}],mt:[{mt:y()}],mr:[{mr:y()}],mb:[{mb:y()}],ml:[{ml:y()}],"space-x":[{"space-x":E()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":E()}],"space-y-reverse":["space-y-reverse"],size:[{size:n()}],"inline-size":[{inline:["auto",...o()]}],"min-inline-size":[{"min-inline":["auto",...o()]}],"max-inline-size":[{"max-inline":["none",...o()]}],"block-size":[{block:["auto",...K0()]}],"min-block-size":[{"min-block":["auto",...K0()]}],"max-block-size":[{"max-block":["none",...K0()]}],w:[{w:[X,"screen",...n()]}],"min-w":[{"min-w":[X,"screen","none",...n()]}],"max-w":[{"max-w":[X,"screen","none","prose",{screen:[Y]},...n()]}],h:[{h:["screen","lh",...n()]}],"min-h":[{"min-h":["screen","lh","none",...n()]}],"max-h":[{"max-h":["screen","lh",...n()]}],"font-size":[{text:["base",w,rd,Yj]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[B,jiQ,JiQ]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",wl0,I2]}],"font-family":[{font:[kiQ,FiQ,Q]}],"font-features":[{"font-features":[I2]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:[$,k2,I2]}],"line-clamp":[{"line-clamp":[Cw,"none",k2,sh1]}],leading:[{leading:[f,...E()]}],"list-image":[{"list-image":["none",k2,I2]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",k2,I2]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:c()}],"text-color":[{text:c()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...I0(),"wavy"]}],"text-decoration-thickness":[{decoration:[Cw,"from-font","auto",k2,Yj]}],"text-decoration-color":[{decoration:c()}],"underline-offset":[{"underline-offset":[Cw,"auto",k2,I2]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:E()}],"tab-size":[{tab:[_G,k2,I2]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",k2,I2]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],wrap:[{wrap:["break-word","anywhere","normal"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",k2,I2]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:X0()}],"bg-repeat":[{bg:b0()}],"bg-size":[{bg:w0()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},_G,k2,I2],radial:["",k2,I2],conic:[_G,k2,I2]},NiQ,LiQ]}],"bg-color":[{bg:c()}],"gradient-from-pos":[{from:h0()}],"gradient-via-pos":[{via:h0()}],"gradient-to-pos":[{to:h0()}],"gradient-from":[{from:c()}],"gradient-via":[{via:c()}],"gradient-to":[{to:c()}],rounded:[{rounded:S0()}],"rounded-s":[{"rounded-s":S0()}],"rounded-e":[{"rounded-e":S0()}],"rounded-t":[{"rounded-t":S0()}],"rounded-r":[{"rounded-r":S0()}],"rounded-b":[{"rounded-b":S0()}],"rounded-l":[{"rounded-l":S0()}],"rounded-ss":[{"rounded-ss":S0()}],"rounded-se":[{"rounded-se":S0()}],"rounded-ee":[{"rounded-ee":S0()}],"rounded-es":[{"rounded-es":S0()}],"rounded-tl":[{"rounded-tl":S0()}],"rounded-tr":[{"rounded-tr":S0()}],"rounded-br":[{"rounded-br":S0()}],"rounded-bl":[{"rounded-bl":S0()}],"border-w":[{border:V0()}],"border-w-x":[{"border-x":V0()}],"border-w-y":[{"border-y":V0()}],"border-w-s":[{"border-s":V0()}],"border-w-e":[{"border-e":V0()}],"border-w-bs":[{"border-bs":V0()}],"border-w-be":[{"border-be":V0()}],"border-w-t":[{"border-t":V0()}],"border-w-r":[{"border-r":V0()}],"border-w-b":[{"border-b":V0()}],"border-w-l":[{"border-l":V0()}],"divide-x":[{"divide-x":V0()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":V0()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...I0(),"hidden","none"]}],"divide-style":[{divide:[...I0(),"hidden","none"]}],"border-color":[{border:c()}],"border-color-x":[{"border-x":c()}],"border-color-y":[{"border-y":c()}],"border-color-s":[{"border-s":c()}],"border-color-e":[{"border-e":c()}],"border-color-bs":[{"border-bs":c()}],"border-color-be":[{"border-be":c()}],"border-color-t":[{"border-t":c()}],"border-color-r":[{"border-r":c()}],"border-color-b":[{"border-b":c()}],"border-color-l":[{"border-l":c()}],"divide-color":[{divide:c()}],"outline-style":[{outline:[...I0(),"none","hidden"]}],"outline-offset":[{"outline-offset":[Cw,k2,I2]}],"outline-w":[{outline:["",Cw,rd,Yj]}],"outline-color":[{outline:c()}],shadow:[{shadow:["","none",K,m90,S90]}],"shadow-color":[{shadow:c()}],"inset-shadow":[{"inset-shadow":["none",U,m90,S90]}],"inset-shadow-color":[{"inset-shadow":c()}],"ring-w":[{ring:V0()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:c()}],"ring-offset-w":[{"ring-offset":[Cw,Yj]}],"ring-offset-color":[{"ring-offset":c()}],"inset-ring-w":[{"inset-ring":V0()}],"inset-ring-color":[{"inset-ring":c()}],"text-shadow":[{"text-shadow":["none",D,m90,S90]}],"text-shadow-color":[{"text-shadow":c()}],opacity:[{opacity:[Cw,k2,I2]}],"mix-blend":[{"mix-blend":[...j0(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":j0()}],"mask-clip":[{"mask-clip":["border","padding","content","fill","stroke","view"]},"mask-no-clip"],"mask-composite":[{mask:["add","subtract","intersect","exclude"]}],"mask-image-linear-pos":[{"mask-linear":[Cw]}],"mask-image-linear-from-pos":[{"mask-linear-from":C0()}],"mask-image-linear-to-pos":[{"mask-linear-to":C0()}],"mask-image-linear-from-color":[{"mask-linear-from":c()}],"mask-image-linear-to-color":[{"mask-linear-to":c()}],"mask-image-t-from-pos":[{"mask-t-from":C0()}],"mask-image-t-to-pos":[{"mask-t-to":C0()}],"mask-image-t-from-color":[{"mask-t-from":c()}],"mask-image-t-to-color":[{"mask-t-to":c()}],"mask-image-r-from-pos":[{"mask-r-from":C0()}],"mask-image-r-to-pos":[{"mask-r-to":C0()}],"mask-image-r-from-color":[{"mask-r-from":c()}],"mask-image-r-to-color":[{"mask-r-to":c()}],"mask-image-b-from-pos":[{"mask-b-from":C0()}],"mask-image-b-to-pos":[{"mask-b-to":C0()}],"mask-image-b-from-color":[{"mask-b-from":c()}],"mask-image-b-to-color":[{"mask-b-to":c()}],"mask-image-l-from-pos":[{"mask-l-from":C0()}],"mask-image-l-to-pos":[{"mask-l-to":C0()}],"mask-image-l-from-color":[{"mask-l-from":c()}],"mask-image-l-to-color":[{"mask-l-to":c()}],"mask-image-x-from-pos":[{"mask-x-from":C0()}],"mask-image-x-to-pos":[{"mask-x-to":C0()}],"mask-image-x-from-color":[{"mask-x-from":c()}],"mask-image-x-to-color":[{"mask-x-to":c()}],"mask-image-y-from-pos":[{"mask-y-from":C0()}],"mask-image-y-to-pos":[{"mask-y-to":C0()}],"mask-image-y-from-color":[{"mask-y-from":c()}],"mask-image-y-to-color":[{"mask-y-to":c()}],"mask-image-radial":[{"mask-radial":[k2,I2]}],"mask-image-radial-from-pos":[{"mask-radial-from":C0()}],"mask-image-radial-to-pos":[{"mask-radial-to":C0()}],"mask-image-radial-from-color":[{"mask-radial-from":c()}],"mask-image-radial-to-color":[{"mask-radial-to":c()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":x()}],"mask-image-conic-pos":[{"mask-conic":[Cw]}],"mask-image-conic-from-pos":[{"mask-conic-from":C0()}],"mask-image-conic-to-pos":[{"mask-conic-to":C0()}],"mask-image-conic-from-color":[{"mask-conic-from":c()}],"mask-image-conic-to-color":[{"mask-conic-to":c()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:X0()}],"mask-repeat":[{mask:b0()}],"mask-size":[{mask:w0()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",k2,I2]}],filter:[{filter:["","none",k2,I2]}],blur:[{blur:k0()}],brightness:[{brightness:[Cw,k2,I2]}],contrast:[{contrast:[Cw,k2,I2]}],"drop-shadow":[{"drop-shadow":["","none",q,m90,S90]}],"drop-shadow-color":[{"drop-shadow":c()}],grayscale:[{grayscale:["",Cw,k2,I2]}],"hue-rotate":[{"hue-rotate":[Cw,k2,I2]}],invert:[{invert:["",Cw,k2,I2]}],saturate:[{saturate:[Cw,k2,I2]}],sepia:[{sepia:["",Cw,k2,I2]}],"backdrop-filter":[{"backdrop-filter":["","none",k2,I2]}],"backdrop-blur":[{"backdrop-blur":k0()}],"backdrop-brightness":[{"backdrop-brightness":[Cw,k2,I2]}],"backdrop-contrast":[{"backdrop-contrast":[Cw,k2,I2]}],"backdrop-grayscale":[{"backdrop-grayscale":["",Cw,k2,I2]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[Cw,k2,I2]}],"backdrop-invert":[{"backdrop-invert":["",Cw,k2,I2]}],"backdrop-opacity":[{"backdrop-opacity":[Cw,k2,I2]}],"backdrop-saturate":[{"backdrop-saturate":[Cw,k2,I2]}],"backdrop-sepia":[{"backdrop-sepia":["",Cw,k2,I2]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":E()}],"border-spacing-x":[{"border-spacing-x":E()}],"border-spacing-y":[{"border-spacing-y":E()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",k2,I2]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[Cw,"initial",k2,I2]}],ease:[{ease:["linear","initial",L,k2,I2]}],delay:[{delay:[Cw,k2,I2]}],animate:[{animate:["none",N,k2,I2]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[I,k2,I2]}],"perspective-origin":[{"perspective-origin":R()}],rotate:[{rotate:_0()}],"rotate-x":[{"rotate-x":_0()}],"rotate-y":[{"rotate-y":_0()}],"rotate-z":[{"rotate-z":_0()}],scale:[{scale:P0()}],"scale-x":[{"scale-x":P0()}],"scale-y":[{"scale-y":P0()}],"scale-z":[{"scale-z":P0()}],"scale-3d":["scale-3d"],skew:[{skew:M0()}],"skew-x":[{"skew-x":M0()}],"skew-y":[{"skew-y":M0()}],transform:[{transform:[k2,I2,"","none","gpu","cpu"]}],"transform-origin":[{origin:R()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:T0()}],"translate-x":[{"translate-x":T0()}],"translate-y":[{"translate-y":T0()}],"translate-z":[{"translate-z":T0()}],"translate-none":["translate-none"],zoom:[{zoom:[_G,k2,I2]}],accent:[{accent:c()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:c()}],"color-scheme":[{scheme:["normal","dark","light","light-dark","only-dark","only-light"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",k2,I2]}],"field-sizing":[{"field-sizing":["fixed","content"]}],"pointer-events":[{"pointer-events":["auto","none"]}],resize:[{resize:["none","","y","x"]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scrollbar-thumb-color":[{"scrollbar-thumb":c()}],"scrollbar-track-color":[{"scrollbar-track":c()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":E()}],"scroll-mx":[{"scroll-mx":E()}],"scroll-my":[{"scroll-my":E()}],"scroll-ms":[{"scroll-ms":E()}],"scroll-me":[{"scroll-me":E()}],"scroll-mbs":[{"scroll-mbs":E()}],"scroll-mbe":[{"scroll-mbe":E()}],"scroll-mt":[{"scroll-mt":E()}],"scroll-mr":[{"scroll-mr":E()}],"scroll-mb":[{"scroll-mb":E()}],"scroll-ml":[{"scroll-ml":E()}],"scroll-p":[{"scroll-p":E()}],"scroll-px":[{"scroll-px":E()}],"scroll-py":[{"scroll-py":E()}],"scroll-ps":[{"scroll-ps":E()}],"scroll-pe":[{"scroll-pe":E()}],"scroll-pbs":[{"scroll-pbs":E()}],"scroll-pbe":[{"scroll-pbe":E()}],"scroll-pt":[{"scroll-pt":E()}],"scroll-pr":[{"scroll-pr":E()}],"scroll-pb":[{"scroll-pb":E()}],"scroll-pl":[{"scroll-pl":E()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",k2,I2]}],fill:[{fill:["none",...c()]}],"stroke-w":[{stroke:[Cw,rd,Yj,sh1]}],stroke:[{stroke:["none",...c()]}],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{"container-named":["container-type"],overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","inset-bs","inset-be","start","end","top","right","bottom","left"],"inset-x":["right","left"],"inset-y":["top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pbs","pbe","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","mbs","mbe","mt","mr","mb","ml"],mx:["mr","ml"],my:["mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-x","border-w-y","border-w-s","border-w-e","border-w-bs","border-w-be","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-r","border-w-l"],"border-w-y":["border-w-t","border-w-b"],"border-color":["border-color-x","border-color-y","border-color-s","border-color-e","border-color-bs","border-color-be","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-r","border-color-l"],"border-color-y":["border-color-t","border-color-b"],translate:["translate-x","translate-y","translate-none"],"translate-none":["translate","translate-x","translate-y","translate-z"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mbs","scroll-mbe","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-mr","scroll-ml"],"scroll-my":["scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pbs","scroll-pbe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-pr","scroll-pl"],"scroll-py":["scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]},postfixLookupClassGroups:["container-type"],orderSensitiveModifiers:["*","**","after","backdrop","before","details-content","file","first-letter","first-line","marker","placeholder","selection"]}},MiQ=(A,{cacheSize:Q,prefix:w,experimentalParseClassName:B,extend:$={},override:f={}})=>{return iC(A,"cacheSize",Q),iC(A,"prefix",w),iC(A,"experimentalParseClassName",B),u90(A.theme,f.theme),u90(A.classGroups,f.classGroups),u90(A.conflictingClassGroups,f.conflictingClassGroups),u90(A.conflictingClassGroupModifiers,f.conflictingClassGroupModifiers),iC(A,"postfixLookupClassGroups",f.postfixLookupClassGroups),iC(A,"orderSensitiveModifiers",f.orderSensitiveModifiers),c90(A.theme,$.theme),c90(A.classGroups,$.classGroups),c90(A.conflictingClassGroups,$.conflictingClassGroups),c90(A.conflictingClassGroupModifiers,$.conflictingClassGroupModifiers),Bl0(A,$,"postfixLookupClassGroups"),Bl0(A,$,"orderSensitiveModifiers"),A},iC=(A,Q,w)=>{if(w!==void 0)A[Q]=w},u90=(A,Q)=>{if(Q)for(let w in Q)iC(A,w,Q[w])},c90=(A,Q)=>{if(Q)for(let w in Q)Bl0(A,Q,w)},Bl0=(A,Q,w)=>{let B=Q[w];if(B!==void 0)A[w]=A[w]?A[w].concat(B):B},l90=(A,...Q)=>typeof A==="function"?oh1(eh1,A,...Q):oh1(()=>MiQ(eh1(),A),...Q);var OiQ=l90({extend:{classGroups:{"font-size":[{text:["display-2xl","display-xl","display-lg","display-md","display-sm","heading-lg","heading-md","heading-sm","body-xl","body-lg","body-md","body-sm","body-xs","label-md","label-sm","label-xs"]}]}}});function _2(...A){return OiQ(pC(A))}var GC1=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,zC1=pC,JB=(A,Q)=>(w)=>{var B;if((Q===null||Q===void 0?void 0:Q.variants)==null)return zC1(A,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className);let{variants:$,defaultVariants:f}=Q,Y=Object.keys($).map((H)=>{let K=w===null||w===void 0?void 0:w[H],U=f===null||f===void 0?void 0:f[H];if(K===null)return null;let D=GC1(K)||GC1(U);return $[H][D]}),X=w&&Object.entries(w).reduce((H,K)=>{let[U,D]=K;if(D===void 0)return H;return H[U]=D,H},{}),W=Q===null||Q===void 0?void 0:(B=Q.compoundVariants)===null||B===void 0?void 0:B.reduce((H,K)=>{let{class:U,className:D,...q}=K;return Object.entries(q).every((b)=>{let[I,V]=b;return Array.isArray(V)?V.includes({...f,...X}[I]):{...f,...X}[I]===V})?[...H,U,D]:H},[]);return zC1(A,Y,W,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className)};import{jsxDEV as Yl0}from"preact/jsx-dev-runtime";var qC1=JB("p-4 rounded-lg border",{variants:{variant:{warning:"bg-warning border-warning text-warning",error:"bg-error border-error text-error",success:"bg-success border-success text-success",info:"bg-info border-info text-info"}},defaultVariants:{variant:"info"}});function Xl0({variant:A,title:Q,children:w,className:B}){return Yl0("div",{className:_2(qC1({variant:A}),B),role:"alert",children:[Q&&Yl0("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),Yl0("div",{className:_2(Q&&"mt-1","text-sm text-current opacity-75"),children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as xiQ}from"preact/jsx-dev-runtime";var bC1=JB("inline-flex items-center justify-center font-bold transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed",{variants:{variant:{default:"bg-brand hover:bg-brand-dark text-theme-inverse",secondary:"bg-theme-muted hover:bg-theme-subtle text-theme border border-theme",ghost:"hover:bg-theme-subtle text-theme"},size:{sm:"h-8 px-3 text-sm rounded-md",md:"h-10 px-4 py-2 text-sm rounded-lg",lg:"h-12 px-6 text-base rounded-lg"}},defaultVariants:{variant:"default",size:"md"}});function Zj({variant:A,size:Q,className:w,children:B,ssrOnClick:$,type:f="button",...Y}){return xiQ("button",{type:f,className:_2(bC1({variant:A,size:Q}),w),...Y,...$&&{onclick:$},children:B},void 0,!1,void 0,this)}import{jsxDEV as RiQ}from"preact/jsx-dev-runtime";var VC1=JB("inline-flex items-center justify-center font-semibold transition-all text-center",{variants:{variant:{primary:"bg-brand text-theme-inverse hover:bg-brand-dark focus:ring-brand/20 focus:outline-none focus:ring-4",accent:"bg-accent text-theme-inverse hover:bg-accent-dark focus:ring-accent/20 focus:outline-none focus:ring-4",secondary:"bg-theme-muted text-theme hover:bg-theme-muted-dark focus:outline-none focus:ring-4",outline:"border-2 border-brand text-brand hover:bg-brand hover:text-theme-inverse focus:ring-brand/20 focus:outline-none focus:ring-4","outline-light":"border-2 border-theme-light text-theme-inverse hover:bg-theme-inverse hover:text-brand hover:border-theme-inverse focus:outline-none focus:ring-4",unstyled:""},size:{icon:"w-10 h-10 rounded-full",sm:"px-3 py-1.5 text-sm rounded-lg",md:"px-4 py-2 text-sm rounded-lg",lg:"px-6 py-3 text-base rounded-xl",xl:"px-8 py-4 text-lg rounded-xl","2xl":"px-10 py-5 text-lg rounded-2xl"}},defaultVariants:{size:"md"}});function b9({href:A,children:Q,variant:w,size:B,external:$=!1,className:f,"aria-label":Y}){let X=$?{target:"_blank",rel:"noopener noreferrer"}:{};return RiQ("a",{href:A,className:_2(VC1({variant:w,size:B}),f),"aria-label":Y,...X,children:Q},void 0,!1,void 0,this)}import{jsxDEV as p90}from"preact/jsx-dev-runtime";var IC1=JB("transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2",{variants:{variant:{default:"rounded-[10px] bg-theme-subtle border border-theme text-theme-muted hover:text-accent hover:border-brand/40",light:"rounded-[10px] bg-theme-subtle border border-theme text-theme-muted hover:text-accent",dark:"rounded-[10px] bg-theme-dark hover:bg-theme-muted text-theme-inverse",footer:"rounded-full bg-theme-toggle hover:bg-theme-toggle-hover text-theme-toggle-icon"},size:{sm:"p-1.5",md:"p-2",lg:"p-3"}},defaultVariants:{variant:"default",size:"md"}}),viQ={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function dC({variant:A,size:Q,className:w}){let B=viQ[Q??"md"];return p90("button",{onclick:"toggleTheme()",type:"button",className:_2(IC1({variant:A,size:Q}),w),"aria-label":"Toggle dark mode",children:p90("svg",{className:_2(B,"transition-colors"),fill:"none",stroke:"currentColor",strokeWidth:1.6,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[p90("path",{className:"sun-icon",strokeLinecap:"round",strokeLinejoin:"round",d:"M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"},void 0,!1,void 0,this),p90("path",{className:"moon-icon",strokeLinecap:"round",strokeLinejoin:"round",d:"M20.354 15.354A9 9 0 018.646 3.646 9 9 0 1020.354 15.354z"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}import{jsxDEV as Zl0}from"preact/jsx-dev-runtime";var JC1=JB("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function i90({items:A,className:Q,linkClassName:w="hover:text-accent transition-colors",orientation:B,children:$}){if(A.length===0&&!$)return null;let f=[...A].sort((Y,X)=>Y.priority-X.priority);return Zl0("ul",{className:_2(JC1({orientation:B}),Q),children:[f.map((Y)=>Zl0("li",{children:Zl0("a",{href:Y.href,className:w,children:Y.label},void 0,!1,void 0,this)},Y.href,!1,void 0,this)),$]},void 0,!0,void 0,this)}import{jsxDEV as EhB}from"preact/jsx-dev-runtime";import{jsxDEV as mhB}from"preact/jsx-dev-runtime";import{createContext as hiQ,h as CiQ}from"preact";import{useContext as giQ}from"preact/hooks";var Wl0=hiQ(null);function nC({headCollector:A,children:Q}){return CiQ(Wl0.Provider,{value:A},Q)}function FC1(){return giQ(Wl0)}function lQ(A){let Q=FC1();if(Q)Q.setHeadProps(A);return null}import{createContext as UtQ,h as DtQ}from"preact";import{useContext as GtQ}from"preact/hooks";GP0();var RT1=X1(xT1(),1),HtQ=new SQ0({gfm:!0,breaks:!0}),KtQ={allowedTags:["h1","h2","h3","h4","h5","h6","p","br","hr","ul","ol","li","blockquote","cite","code","pre","em","strong","del","ins","sub","sup","a","img","span","table","thead","tbody","tr","th","td","div"],allowedAttributes:{a:["href","title","name"],img:["src","srcset","sizes","alt","title","width","height","class","loading","decoding"],code:["class"],pre:["class"],span:["class"],cite:["class"],div:["class"],th:["align","colspan","rowspan","scope"],td:["align","colspan","rowspan"]},allowedSchemes:["http","https","mailto","tel"],allowedSchemesByTag:{img:["http","https","entity"]},allowProtocolRelative:!1,disallowedTagsMode:"discard"};function Cp0(A,Q){let{imageRenderer:w}=Q??{},$=(w?new SQ0({gfm:!0,breaks:!0}).use({renderer:{image({href:f,title:Y,text:X}){return w(f,Y,X)??!1}}}):HtQ).parse(A);return $=$.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
4778
4778
  <cite class="block-attribution"><span class="emdash">$1</span>$2</cite>`),RT1.default($,KtQ)}var vT1=UtQ(null);function Hg({imageRenderer:A,children:Q}){return DtQ(vT1.Provider,{value:A??null},Q)}function hT1(){return GtQ(vT1)}function uq(){let A=hT1();return(Q)=>Cp0(Q,A?{imageRenderer:A}:void 0)}var ztQ=/<pre><code class="language-mermaid">([\s\S]*?)<\/code><\/pre>/g,qtQ={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'"},btQ=/&(?:amp|lt|gt|quot|#39);/g;function VtQ(A){return A.replace(btQ,(Q)=>qtQ[Q]??Q)}function gp0(A){return A.replace(ztQ,(Q,w)=>{return`<div class="mermaid">${VtQ(w)}</div>`})}var CT1=/<!--\s*\.slide:\s*(.*?)\s*-->/g;function gT1(A){let Q={};for(let B of A.matchAll(CT1)){let $=B[1]??"";for(let Y of $.matchAll(/([\w-]+)=["']([^"']*?)["']/g)){let X=Y[1],W=Y[2];if(X&&W!==void 0)Q[X]=W}let f=$.replace(/([\w-]+)=["']([^"']*?)["']/g,"").trim();if(f)for(let Y of f.matchAll(/(?:^|\s)([\w-]+)(?=\s|$)/g)){let X=Y[1];if(X)Q[X]="true"}}let w=A.replace(CT1,"").replace(/^\n+/,"").replace(/\n{3,}/g,`
4779
4779
 
4780
4780
  `).trim();return{attributes:Q,markdown:w}}var ItQ=/<!--\s*\.break\s*-->/;function yT1(A){let Q=A.split(ItQ);return Q.length>1?Q:null}import{jsxDEV as RG}from"preact/jsx-dev-runtime";var yp0=({markdown:A,deck:Q})=>{let w=uq(),$=A.split(/^---$/gm).map((K)=>K.trim()).map((K)=>{let{attributes:U,markdown:D}=gT1(K),q=yT1(D),b;if(q)b=`<div class="slide-columns">${q.map((V)=>`<div class="slide-column">${gp0(w(V.trim()))}</div>`).join("")}</div>`;else b=gp0(w(D));return{attributes:U,htmlContent:b}}),f=$.some((K)=>K.htmlContent.includes('class="mermaid"')),Y=Q?.frontmatter?.title??Q?.metadata?.title,X=Q?.frontmatter?.description??Q?.metadata?.description,W=Q?.ogImageUrl??Q?.coverImageUrl,H=$.map(({attributes:K,htmlContent:U},D)=>RG("section",{...K,dangerouslySetInnerHTML:{__html:U}},D,!1,void 0,this));return RG("section",{className:"presentation-section",children:[Y&&RG(lQ,{title:Y,...X?{description:X}:{},...W?{ogImage:W}:{},ogType:"article"},void 0,!1,void 0,this),RG("link",{rel:"stylesheet",href:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.css"},void 0,!1,void 0,this),RG("div",{className:"reveal",children:RG("div",{className:"slides",children:H},void 0,!1,void 0,this)},void 0,!1,void 0,this),RG("script",{src:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.js",defer:!0},void 0,!1,void 0,this),f&&RG("script",{src:"https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js",defer:!0},void 0,!1,void 0,this),RG("script",{dangerouslySetInnerHTML:{__html:`
@@ -5761,13 +5761,13 @@ ${A.map((f)=>({url:`${Q}${f.path}`,lastmod:w,changefreq:f.path==="/"?"daily":"we
5761
5761
  `+$:w,Y=lG(this.outputDir,"styles","main.css");await this.cssProcessor.process(f,Y,this.workingDir,this.outputDir,this.logger);let X=await u7.readFile(Y,"utf-8"),W=B.length>0?B:Q;if(W.length>0){let H=W.join(`
5762
5762
  `)+`
5763
5763
 
5764
- `+X;await u7.writeFile(Y,H,"utf-8")}this.logger.debug("CSS processed successfully with font imports")}async copyStaticAssets(){this.logger.debug("Copying static assets from public/ directory");let A=lG(process.cwd(),"public");try{await u7.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await u7.readdir(A,{withFileTypes:!0});for(let w of Q){let B=lG(A,w.name),$=lG(this.outputDir,w.name);if(w.isDirectory())await this.copyDirectory(B,$);else await u7.copyFile(B,$),this.logger.debug(`Copied static asset: ${w.name}`)}this.logger.debug("Static assets copied successfully")}async writeInlineStaticAssets(A){if(!A)return;let Q=Object.entries(A);if(Q.length===0)return;this.logger.debug(`Writing ${Q.length} inline static asset(s) from SitePackage`),await Promise.all(Q.map(async([w,B])=>{let $=w.startsWith("/")?w.slice(1):w,f=lG(this.outputDir,$);await u7.mkdir(eYw(f),{recursive:!0}),await u7.writeFile(f,B,"utf-8"),this.logger.debug(`Wrote inline static asset: ${$}`)}))}async copyDirectory(A,Q){await u7.mkdir(Q,{recursive:!0});let w=await u7.readdir(A,{withFileTypes:!0});for(let B of w){let $=lG(A,B.name),f=lG(Q,B.name);if(B.isDirectory())await this.copyDirectory($,f);else await u7.copyFile($,f)}}}function Cn0(A){return new ho1(A)}s5();N0();N0();var AXw=Z.object({heading:Z.string(),buttonText:Z.string(),buttonLink:Z.string()}),QXw=Z.object({blurb:Z.string().optional()}),pg=Z.object({title:Z.string(),description:Z.string(),url:Z.string().optional(),copyright:Z.string().optional(),logo:Z.boolean().optional(),themeMode:Z.enum(["light","dark"]).optional(),analyticsScript:Z.string().optional(),cta:AXw.optional(),sections:Z.record(Z.string(),QXw).optional()});var Co1=Z.object({environment:Z.enum(["preview","production"]),outputDir:Z.string(),workingDir:Z.string().optional(),sharedImagesDir:Z.string().default("./dist/images"),enableContentGeneration:Z.boolean().default(!1),cleanBeforeBuild:Z.boolean().default(!0),siteConfig:pg,layouts:Z.record(Z.string(),Z.any()),themeCSS:Z.string().optional()}),jdB=Z.object({success:Z.boolean(),outputDir:Z.string(),filesGenerated:Z.number(),routesBuilt:Z.number(),errors:Z.array(Z.string()).optional(),warnings:Z.array(Z.string()).optional()});function go1(A){let Q=A.list(),w=Q.length===0?["No routes registered for site build"]:[];return{routes:Q,warnings:w}}function yo1(A,Q,w){let B=Q.getProfile(),$=w.getNavigationItems("primary"),f=w.getNavigationItems("secondary");return{...A,...B.socialLinks!==void 0&&{socialLinks:B.socialLinks},navigation:{primary:$,secondary:f},copyright:A.copyright??"Powered by Rizom"}}s5();J4();s5();K2();N0();var wXw=Z.looseObject({id:Z.string(),entityType:Z.string(),content:Z.string(),metadata:Z.looseObject({slug:Z.string()})}),BXw=Z.looseObject({content:Z.string(),metadata:Z.looseObject({width:Z.number().optional(),height:Z.number().optional()})});async function Ff0(A,Q){let w=Q.urlGenerator??X4.getInstance();if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((x)=>Ff0(x,{...Q,urlGenerator:w})));if(typeof A!=="object")return A;let B={},$=Object.entries(A),f=await Promise.all($.map(([,x])=>Ff0(x,{...Q,urlGenerator:w})));for(let x=0;x<$.length;x++){let R=$[x];if(R)B[R[0]]=f[x]}let Y=wXw.safeParse(A);if(!Y.success)return B;let X=Y.data,W=X.entityType,H=X.metadata.slug,K=Q.pipelineContext.entityDisplay?.[W],U=K?K.label:W.charAt(0).toUpperCase()+W.slice(1),D=K?K.pluralName??K.label.toLowerCase()+"s":eH(W),q=`/${D}`,b=D.charAt(0).toUpperCase()+D.slice(1),I=Nu(X),V=await $Xw(I,Q),L=D20(X)??I,N=await fXw(L,Q);return{...B,...X,url:w.generateUrl(W,H),typeLabel:U,listUrl:q,listLabel:b,...V,...N&&{ogImageUrl:N}}}async function $Xw(A,Q){let w=A?Q.imageBuildService?.get(A):void 0;if(w)return{coverImageUrl:w.src,coverImageWidth:w.width,coverImageHeight:w.height,...w.srcset&&{coverImageSrcset:w.srcset,coverImageSizes:w.sizes}};let B=await To1(A,Q.pipelineContext.services.entityService);if(!B)return{};return{coverImageUrl:B.url,...B.width&&{coverImageWidth:B.width},...B.height&&{coverImageHeight:B.height}}}async function fXw(A,Q){if(!A)return;let w=Q.imageBuildService?.get(A);if(w)return Eo1(w.src,Q.siteUrl);let B=await To1(A,Q.pipelineContext.services.entityService);if(!B)return;if(B.url.startsWith("data:"))return;return Eo1(B.url,Q.siteUrl)}function Eo1(A,Q){if(/^https?:\/\//i.test(A)||A.startsWith("data:"))return A;if(!Q)return A;return`${Q.replace(/\/$/,"")}/${A.replace(/^\//,"")}`}async function To1(A,Q){if(!A)return;let w=await Q.getEntity({entityType:"image",id:A}),B=BXw.safeParse(w);if(!B.success)return;return{url:B.data.content,...B.data.metadata.width&&{width:B.data.metadata.width},...B.data.metadata.height&&{height:B.data.metadata.height}}}async function So1(A,Q){let w=new Set;try{let B=A.getEntityTypes();for(let $ of B){if($==="image")continue;let f=await A.listEntities({entityType:$});for(let Y of f){let X=Nu(Y);if(X)w.add(X);let W=D20(Y);if(W)w.add(W)}}}catch(B){Q.warn("Failed to collect image IDs for pre-resolution",{error:mA(B)})}return[...w]}async function mo1(A,Q,w,B,$){if(!A.template)return A.content??null;let f=A.template,Y=A.dataQuery?{dataParams:A.dataQuery,fallback:A.content,publishedOnly:w,visibilityScope:B}:{savedContent:{entityType:"site-content",entityId:`${Q.id}:${A.id}`},fallback:A.content,visibilityScope:B},X=await $.pipelineContext.services.resolveTemplateContent(f,Y);if(!X)return null;return Ff0(X,{pipelineContext:$.pipelineContext,imageBuildService:$.imageBuildService,siteUrl:$.siteUrl,urlGenerator:X4.getInstance()})}function uo1(A){return{routes:A.routes,siteConfig:{title:A.siteMetadata.title,description:A.siteMetadata.description,...A.siteMetadata.url&&{url:A.siteMetadata.url},...A.siteMetadata.copyright&&{copyright:A.siteMetadata.copyright},...A.siteMetadata.themeMode&&{themeMode:A.siteMetadata.themeMode},...A.siteMetadata.analyticsScript&&{analyticsScript:A.siteMetadata.analyticsScript}},headScripts:A.buildOptions.headScripts,...A.buildOptions.staticAssets&&{staticAssets:A.buildOptions.staticAssets},getContent:async(Q,w)=>{let B=A.parsedOptions.environment==="production";return mo1(w,Q,B,"public",{pipelineContext:A.pipelineContext,imageBuildService:A.imageBuildService,siteUrl:A.siteMetadata.url})},getViewTemplate:(Q)=>{return A.pipelineContext.services.getViewTemplate(Q)},layouts:A.parsedOptions.layouts,getSiteLayoutInfo:async()=>{return yo1(A.siteMetadata,A.pipelineContext.profileService,A.pipelineContext.routeRegistry)},...A.parsedOptions.themeCSS!==void 0&&{themeCSS:A.parsedOptions.themeCSS},...A.buildOptions.slots&&{slots:A.buildOptions.slots},imageBuildService:A.imageBuildService}}import{join as YXw}from"path";async function co1(A){let Q=A.parsedOptions.workingDir??YXw(A.parsedOptions.outputDir,".preact-work"),w=A.staticSiteBuilderFactory({logger:A.logger.child("StaticSiteBuilder"),workingDir:Q,outputDir:A.parsedOptions.outputDir});if(A.parsedOptions.cleanBeforeBuild)await w.clean();return w}async function lo1(A){await new If0({logger:A.pipelineContext.logger.child("DynamicRouteGenerator"),entityService:A.pipelineContext.services.entityService,listViewTemplateNames:()=>A.pipelineContext.services.listViewTemplateNames()},A.pipelineContext.routeRegistry,A.pipelineContext.entityDisplay,{visibilityScope:"public",...A.publishedOnly!==void 0&&{publishedOnly:A.publishedOnly}}).generateEntityRoutes()}async function po1(A){let Q=new Vf0(A.pipelineContext.services.entityService,A.pipelineContext.logger,A.sharedImagesDir),w=await So1(A.pipelineContext.services.entityService,A.pipelineContext.logger);if(w.length>0)await Q.resolveAll(w);return Q}async function io1(A){let Q=A.reporter?.createSub({scale:{start:85,end:95}});await A.staticSiteBuilder.build(A.buildContext,(w)=>{Q?.report(w).catch(()=>{})})}function do1(A){return{success:!0,outputDir:A.outputDir,filesGenerated:A.routesBuilt+1,routesBuilt:A.routesBuilt,...A.warnings.length>0&&{warnings:A.warnings}}}function no1(A){return{success:!1,outputDir:A.outputDir,filesGenerated:0,routesBuilt:0,errors:[A.errorMessage]}}async function ro1(A){let Q=Co1.parse(A.buildOptions),w=Xf.from(A.progress),B=[];try{await w?.report({message:"Starting site build",progress:0,total:100}),await w?.report({message:"Generating dynamic routes",progress:10,total:100}),await lo1({pipelineContext:A.pipelineContext,publishedOnly:Q.environment==="production"});let $=await co1({logger:A.pipelineContext.logger,parsedOptions:Q,staticSiteBuilderFactory:A.staticSiteBuilderFactory}),f=go1(A.pipelineContext.routeRegistry);B.push(...f.warnings);let{routes:Y}=f;await w?.report({message:`Building ${Y.length} routes`,progress:20,total:100}),await w?.report({message:"Resolving images",progress:25,total:100});let X=await po1({pipelineContext:A.pipelineContext,sharedImagesDir:Q.sharedImagesDir}),W=uo1({routes:Y,parsedOptions:Q,buildOptions:A.buildOptions,pipelineContext:A.pipelineContext,imageBuildService:X,siteMetadata:Q.siteConfig});return await io1({staticSiteBuilder:$,buildContext:W,reporter:w}),await w?.report({message:"Site build complete",progress:100,total:100}),do1({outputDir:Q.outputDir,routesBuilt:Y.length,warnings:B})}catch($){let f=Error("Site build process failed");return A.pipelineContext.logger.error("Site build failed",{error:f,originalError:$}),no1({outputDir:Q.outputDir,errorMessage:f.message})}}class xZ{static instance=null;static defaultStaticSiteBuilderFactory=Cn0;pipelineContext;staticSiteBuilderFactory;static setDefaultStaticSiteBuilderFactory(A){xZ.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,w,B,$=void 0){return xZ.instance??=new xZ(A,xZ.defaultStaticSiteBuilderFactory,Q,w,B,$),xZ.instance}static resetInstance(){xZ.instance=null}static createFresh(A,Q,w,B,$,f=void 0){return new xZ(A,$??xZ.defaultStaticSiteBuilderFactory,Q,w,B,f)}constructor(A,Q,w,B,$,f){this.pipelineContext={logger:A,services:w,routeRegistry:B,profileService:$,entityDisplay:f},this.staticSiteBuilderFactory=Q,X4.getInstance().configure(f)}async build(A,Q){return ro1({buildOptions:A,progress:Q,pipelineContext:this.pipelineContext,staticSiteBuilderFactory:this.staticSiteBuilderFactory})}}class gn0{config;context;pluginId;logger;debounces=new Map;unsubscribeFunctions=[];constructor(A,Q,w,B){this.config=A,this.context=Q,this.pluginId=w,this.logger=B}requestBuild(A){let Q=A??(this.config.previewOutputDir?"preview":"production"),w=this.debounces.get(Q);if(!w)w=new nd(()=>{this.enqueueBuild(Q)},this.config.rebuildDebounce),this.debounces.set(Q,w);w.trigger()}setupAutoRebuild(){let A=new Set(["note"]),Q=async(B)=>{let{entityType:$}=B.payload;if(!A.has($))this.logger.debug(`Entity type ${$} will trigger rebuild`),this.requestBuild();return{success:!0}},w=["entity:created","entity:updated","entity:deleted"];for(let B of w)this.unsubscribeFunctions.push(this.context.messaging.subscribe(B,Q));this.logger.debug(`Auto-rebuild enabled (${this.config.rebuildDebounce}ms debounce), excluding types: ${[...A].join(", ")}`)}dispose(){for(let A of this.debounces.values())A.dispose();this.debounces.clear();for(let A of this.unsubscribeFunctions)A();this.unsubscribeFunctions=[]}async enqueueBuild(A){let Q=A==="production"?this.config.productionOutputDir:this.config.previewOutputDir;this.logger.debug(`Triggering ${A} site rebuild`);try{await this.context.jobs.enqueue({type:"site-build",data:{environment:A,outputDir:Q,workingDir:this.config.workingDir,enableContentGeneration:!0,metadata:{trigger:"debounced-rebuild",timestamp:new Date().toISOString()}},options:{priority:0,source:this.pluginId,metadata:{operationType:"content_operations"},deduplication:"skip"}}),this.logger.debug("Site rebuild enqueued")}catch(w){this.logger.error("Failed to enqueue site rebuild",{error:w})}}}s5();function XXw(A,Q){return A.map((w)=>({...w,template:w.template.includes(":")?w.template:`${Q}:${w.template}`}))}function Lf0(A,Q,w){for(let B of A)w.register({...B,pluginId:Q,sections:B.sections?XXw(B.sections,Q):[]})}function oo1(A,Q,w){A.messaging.subscribe("plugin:site-builder:route:register",async(B)=>{try{let $=Be.parse(B.payload),{routes:f,pluginId:Y}=$;return Lf0(f,Y,Q),{success:!0}}catch($){return w.error("Failed to register routes",{error:$}),{success:!1,error:"Failed to register routes"}}}),A.messaging.subscribe("plugin:site-builder:route:unregister",async(B)=>{try{let $=$e.parse(B.payload),{paths:f,pluginId:Y}=$;if(f)for(let X of f)Q.unregister(X);else if(Y)Q.unregisterByPlugin(Y);return{success:!0}}catch($){return w.error("Failed to unregister routes",{error:$}),{success:!1,error:"Failed to unregister routes"}}}),A.messaging.subscribe("plugin:site-builder:route:list",async(B)=>{try{let $=fe.parse(B.payload);return{success:!0,data:{routes:Q.list($.pluginId?$:void 0)}}}catch($){return w.error("Failed to list routes",{error:$}),{success:!1,error:"Failed to list routes"}}}),A.messaging.subscribe("plugin:site-builder:route:get",async(B)=>{try{let $=Ye.parse(B.payload);return{success:!0,data:{route:Q.get($.path)}}}catch($){return w.error("Failed to get route",{error:$}),{success:!1,error:"Failed to get route"}}}),A.messaging.subscribe("site-builder:routes:list",async()=>{return{success:!0,data:Q.list()}})}import{promises as so1}from"fs";import{join as ao1}from"path";async function ZXw(A,Q,w){let B=A.siteConfig.url??"https://example.com",$=Q.list(),f=vn0(B,A.environment);await so1.writeFile(ao1(A.outputDir,"robots.txt"),f,"utf-8"),w.info(`Generated robots.txt for ${A.environment} environment`);let Y=hn0($,B);await so1.writeFile(ao1(A.outputDir,"sitemap.xml"),Y,"utf-8"),w.info(`Generated sitemap.xml with ${$.length} URLs`)}function to1(A){let{context:Q,routeRegistry:w,logger:B}=A;Q.messaging.subscribe("site:build:completed",async($)=>{try{let f=$.payload;return B.info(`Received site:build:completed event for ${f.environment} environment - generating SEO files`),await ZXw(f,w,B),{success:!0}}catch(f){return B.error("Failed to generate SEO files",f),{success:!1}}})}wA();N0();var eo1=Z.object({environment:Z.enum(["preview","production"]).optional(),outputDir:Z.string(),workingDir:Z.string().optional(),enableContentGeneration:Z.boolean().optional(),siteConfig:pg.optional()});s5();s5();N0();var WXw=Z.object({heading:Z.string(),buttonText:Z.string(),buttonLink:Z.string()}),HXw=Z.object({blurb:Z.string().optional()}),As1=Z.object({title:Z.string(),description:Z.string(),url:Z.string().optional(),copyright:Z.string().optional(),logo:Z.boolean().optional(),themeMode:Z.enum(["light","dark"]).optional(),analyticsScript:Z.string().optional(),cta:WXw.optional(),sections:Z.record(Z.string(),HXw).optional()});async function Fr(A,Q){try{let w=await A({type:cT,payload:void 0});if("success"in w&&w.success&&w.data){let B=As1.safeParse(w.data);if(B.success)return As1.parse({...Q,...B.data})}}catch{}return Q}class yn0 extends aw{sendMessage;cfg;constructor(A,Q,w){super(A,{schema:eo1,jobTypeName:"site-build"});this.sendMessage=Q,this.cfg=w}async process(A,Q,w){let B=A.environment??"preview",$=A.enableContentGeneration??!1;try{this.logger.debug("Starting site build job",{jobId:Q,environment:B,outputDir:A.outputDir}),await w.report({progress:0,total:100,message:`Starting site build for ${B} environment`});let f=w.createSub({scale:{start:10,end:90}}),Y=await Fr(this.sendMessage,A.siteConfig??this.cfg.defaultSiteConfig),X=await this.cfg.siteBuilder.build({outputDir:A.outputDir,workingDir:A.workingDir,sharedImagesDir:this.cfg.sharedImagesDir,enableContentGeneration:$,environment:B,cleanBeforeBuild:!0,siteConfig:Y,layouts:this.cfg.layouts,themeCSS:this.cfg.themeCSS,slots:this.cfg.slots,headScripts:this.cfg.getHeadScripts?.(),...this.cfg.staticAssets&&{staticAssets:this.cfg.staticAssets}},f.toCallback());if(await w.report({progress:100,total:100,message:`Site build completed: ${X.routesBuilt} routes built`}),this.logger.debug("Site build job completed",{jobId:Q,environment:B,routesBuilt:X.routesBuilt,success:X.success}),X.success){this.logger.info(`Emitting site:build:completed event for ${B} environment`);let W=B==="preview"?this.cfg.previewUrl??this.cfg.siteUrl:this.cfg.siteUrl;await this.sendMessage({type:"site:build:completed",payload:{outputDir:A.outputDir,environment:B,routesBuilt:X.routesBuilt,siteConfig:{...Y,url:W},generateEntityUrl:(H,K)=>X4.getInstance().generateUrl(H,K)},broadcast:!0})}return{success:X.success,routesBuilt:X.routesBuilt,outputDir:A.outputDir,environment:B,...X.errors&&{errors:X.errors},...X.warnings&&{warnings:X.warnings}}}catch(f){throw this.logger.error("Site build job failed",f),f}}summarizeDataForLog(A){return{environment:A.environment,outputDir:A.outputDir}}}N0();s5();var KXw=Z.object({slot:Z.enum(XV).optional().default("primary"),limit:Z.number().optional()});class En0{routeRegistry;logger;id="site:navigation";name="Site Navigation DataSource";description="Provides navigation items for site menus";constructor(A,Q){this.routeRegistry=A,this.logger=Q,this.logger.debug("NavigationDataSource initialized")}async fetch(A,Q,w){let B=KXw.parse(A??{});this.logger.debug("NavigationDataSource fetch called",{params:B});let $=this.routeRegistry.getNavigationItems(B.slot),f=B.limit?$.slice(0,B.limit):$,Y=f.map((W)=>({label:W.label,href:W.href}));this.logger.debug("NavigationDataSource returning",{slot:B.slot,itemCount:f.length,items:Y});let X={navigation:Y};return Q.parse(X)}}s5();wA();N0();var UXw=Z.object({environment:Z.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function Qs1(A,Q){return[P6(A,"build-site","Build a static site from registered routes. Call this for every user build/rebuild request, including repeated requests like 'build it again' or 'one more build'.",UXw,async(w)=>{return Q(w.environment),{success:!0,message:`Site build requested${w.environment?` for ${w.environment}`:""} (debounced)`,data:{}}},{sideEffects:"external",cli:{name:"build"}})]}N0();s5();var DXw=Z.object({id:Z.string(),template:Z.string(),content:Z.unknown().optional(),dataQuery:Z.looseObject({entityType:Z.string().optional(),template:Z.string().optional(),query:Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),offset:Z.number().optional()}).optional()}).optional(),order:Z.number().optional()}),GXw=Z.object({show:Z.boolean().default(!1),label:Z.string().optional(),slot:Z.enum(XV).default("primary"),priority:Z.number().min(0).max(100).default(50)}).optional(),zXw=Z.object({id:Z.string(),path:Z.string(),title:Z.string().default(""),pageLabel:Z.string().optional(),description:Z.string().default(""),sections:Z.array(DXw).default([]),layout:Z.string().default("default"),fullscreen:Z.boolean().optional(),pluginId:Z.string().optional(),sourceEntityType:Z.string().optional(),external:Z.boolean().optional(),navigation:GXw}),ws1=Z.object({previewOutputDir:Z.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:Z.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:Z.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:Z.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:pg.default({title:"Brain",description:"A knowledge management system"}),themeCSS:Z.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:Z.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:Z.any().optional().describe("Template definitions to register"),routes:Z.array(zXw).optional().describe("Routes to register"),layouts:Z.record(Z.string(),Z.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:Z.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:Z.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:Z.record(Z.string(),Z.object({label:Z.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:Z.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:Z.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:Z.boolean().optional().describe("Enable pagination for list pages"),pageSize:Z.number().optional().describe("Items per page (default: 10)"),navigation:Z.object({show:Z.boolean().optional().describe("Show in navigation"),slot:Z.enum(XV).optional().describe("Navigation slot (primary or secondary)"),priority:Z.number().min(0).max(100).optional().describe("Navigation priority (0-100)")}).optional().describe("Navigation settings for this entity type")})).optional().describe("Display metadata per entity type \u2014 label, plural name, layout, pagination, navigation slot. Consulted when auto-generating routes for active entity plugins."),staticAssets:Z.record(Z.string(),Z.string()).optional().describe("Static files to write to the output directory at build time. Keys are output paths (e.g. '/canvases/tree.js'), values are file contents as strings. Typically supplied by a SitePackage via text imports.")});var Bs1={name:"@brains/site-builder-plugin",version:"0.2.0-alpha.142",description:"Static site generation plugin for Brain system",dependencies:{"@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-engine":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*","@tailwindcss/typography":"^0.5.20",preact:"^10.27.2","preact-render-to-string":"^6.7.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{clean:"rm -rf dist",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class Tn0 extends aQ{siteBuilder;pluginContext;_routeRegistry;_slotRegistry;profileService;layouts;rebuildManager;headScripts=new Map;get routeRegistry(){if(!this._routeRegistry)throw Error("RouteRegistry not initialized - plugin not registered");return this._routeRegistry}constructor(A={}){let Q=A.layouts??{};super("site-builder",Bs1,{...A,layouts:Q},ws1);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new Jf0(A.logger),this._slotRegistry=new r40,A.messaging.subscribe("plugin:site-builder:slot:register",async(w)=>{let{slotName:B,pluginId:$,render:f,priority:Y}=w.payload;return this._slotRegistry?.register(B,{pluginId:$,render:f,...Y!==void 0&&{priority:Y}}),{success:!0}}),A.messaging.subscribe("plugin:site-builder:head-script:register",async(w)=>{let{pluginId:B,script:$}=w.payload;return this.headScripts.set(B,$),{success:!0}}),A.entities.registerDataSource(new En0(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService=If.getInstance(A.entityService,A.logger),oo1(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)Lf0(this.config.routes,this.id,this.routeRegistry);let Q={entityService:A.entityService,sendMessage:A.messaging.send,resolveTemplateContent:(w,B)=>A.templates.resolve(w,B),getViewTemplate:(w)=>A.views.get(w),listViewTemplateNames:()=>A.views.list().map((w)=>w.name)};if(this.siteBuilder=xZ.getInstance(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,this.config.entityDisplay),A.jobs.registerHandler("site-build",new yn0(this.logger.child("SiteBuildJobHandler"),A.messaging.send,{siteBuilder:this.siteBuilder,layouts:this.layouts,defaultSiteConfig:this.config.siteInfo,sharedImagesDir:this.config.sharedImagesDir,siteUrl:A.siteUrl,previewUrl:A.previewUrl,themeCSS:this.config.themeCSS,slots:this._slotRegistry,getHeadScripts:()=>this.getRegisteredHeadScripts(),...this.config.staticAssets&&{staticAssets:this.config.staticAssets}})),this.rebuildManager=new gn0(this.config,A,this.id,this.logger),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();A.messaging.subscribe(lT,async()=>{let w=await this.getInstructions();if(w)A.registerInstructions(w);return{success:!0}}),to1({context:A,routeRegistry:this._routeRegistry,logger:this.logger})}getRegisteredHeadScripts(){return Array.from(this.headScripts.values())}async getTools(){if(!this.pluginContext||!this.rebuildManager)throw Error("Plugin context not initialized");let A=this.rebuildManager;return Qs1(this.id,(Q)=>A.requestBuild(Q))}async getResources(){let A=this.getContext();return[{uri:"brain://site",name:"Site Metadata",description:"Site metadata \u2014 title, description, domain, URLs",mimeType:"application/json",handler:async()=>{let Q=await Fr(A.messaging.send,this.config.siteInfo);return{contents:[{uri:"brain://site",mimeType:"application/json",text:JSON.stringify({...Q,domain:A.domain,siteUrl:A.siteUrl,previewUrl:A.previewUrl},null,2)}]}}},{uri:"site://routes",name:"Site Routes",description:"All registered routes with sections and templates",mimeType:"application/json",handler:async()=>{let Q=this.routeRegistry.list();return{contents:[{uri:"site://routes",mimeType:"application/json",text:JSON.stringify(Q.map((w)=>({id:w.id,path:w.path,title:w.title,description:w.description,sections:w.sections.map((B)=>({id:B.id,template:B.template}))})),null,2)}]}}},{uri:"site://templates",name:"View Templates",description:"All registered view templates",mimeType:"application/json",handler:async()=>{let Q=A.views.list();return{contents:[{uri:"site://templates",mimeType:"application/json",text:JSON.stringify(Q.map((w)=>({name:w.name,description:w.description,hasWebRenderer:!!w.renderers.web})),null,2)}]}}}]}getSiteBuilder(){return this.siteBuilder}getSlotRegistry(){return this._slotRegistry}async getInstructions(){let A=this.getContext(),Q="## Site Builder Actions\n- When the user asks to build, rebuild, publish, or build the website/site again, call `site-builder_build-site` immediately.\n- Every repeated build request requires a fresh `site-builder_build-site` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.",w=await Fr(A.messaging.send,this.config.siteInfo);return`## Your Site
5764
+ `+X;await u7.writeFile(Y,H,"utf-8")}this.logger.debug("CSS processed successfully with font imports")}async copyStaticAssets(){this.logger.debug("Copying static assets from public/ directory");let A=lG(process.cwd(),"public");try{await u7.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await u7.readdir(A,{withFileTypes:!0});for(let w of Q){let B=lG(A,w.name),$=lG(this.outputDir,w.name);if(w.isDirectory())await this.copyDirectory(B,$);else await u7.copyFile(B,$),this.logger.debug(`Copied static asset: ${w.name}`)}this.logger.debug("Static assets copied successfully")}async writeInlineStaticAssets(A){if(!A)return;let Q=Object.entries(A);if(Q.length===0)return;this.logger.debug(`Writing ${Q.length} inline static asset(s) from SitePackage`),await Promise.all(Q.map(async([w,B])=>{let $=w.startsWith("/")?w.slice(1):w,f=lG(this.outputDir,$);await u7.mkdir(eYw(f),{recursive:!0}),await u7.writeFile(f,B,"utf-8"),this.logger.debug(`Wrote inline static asset: ${$}`)}))}async copyDirectory(A,Q){await u7.mkdir(Q,{recursive:!0});let w=await u7.readdir(A,{withFileTypes:!0});for(let B of w){let $=lG(A,B.name),f=lG(Q,B.name);if(B.isDirectory())await this.copyDirectory($,f);else await u7.copyFile($,f)}}}function Cn0(A){return new ho1(A)}s5();N0();N0();var AXw=Z.object({heading:Z.string(),buttonText:Z.string(),buttonLink:Z.string()}),QXw=Z.object({blurb:Z.string().optional()}),pg=Z.object({title:Z.string(),description:Z.string(),url:Z.string().optional(),copyright:Z.string().optional(),logo:Z.boolean().optional(),themeMode:Z.enum(["light","dark"]).optional(),analyticsScript:Z.string().optional(),cta:AXw.optional(),sections:Z.record(Z.string(),QXw).optional()});var Co1=Z.object({environment:Z.enum(["preview","production"]),outputDir:Z.string(),workingDir:Z.string().optional(),sharedImagesDir:Z.string().default("./dist/images"),enableContentGeneration:Z.boolean().default(!1),cleanBeforeBuild:Z.boolean().default(!0),siteConfig:pg,layouts:Z.record(Z.string(),Z.any()),themeCSS:Z.string().optional()}),jdB=Z.object({success:Z.boolean(),outputDir:Z.string(),filesGenerated:Z.number(),routesBuilt:Z.number(),errors:Z.array(Z.string()).optional(),warnings:Z.array(Z.string()).optional()});function go1(A){let Q=A.list(),w=Q.length===0?["No routes registered for site build"]:[];return{routes:Q,warnings:w}}function yo1(A,Q,w){let B=Q.getProfile(),$=w.getNavigationItems("primary"),f=w.getNavigationItems("secondary");return{...A,...B.socialLinks!==void 0&&{socialLinks:B.socialLinks},navigation:{primary:$,secondary:f},copyright:A.copyright??"Powered by Rizom"}}s5();J4();s5();K2();N0();var wXw=Z.looseObject({id:Z.string(),entityType:Z.string(),content:Z.string(),metadata:Z.looseObject({slug:Z.string()})}),BXw=Z.looseObject({content:Z.string(),metadata:Z.looseObject({width:Z.number().optional(),height:Z.number().optional()})});async function Ff0(A,Q){let w=Q.urlGenerator??X4.getInstance();if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((x)=>Ff0(x,{...Q,urlGenerator:w})));if(typeof A!=="object")return A;let B={},$=Object.entries(A),f=await Promise.all($.map(([,x])=>Ff0(x,{...Q,urlGenerator:w})));for(let x=0;x<$.length;x++){let R=$[x];if(R)B[R[0]]=f[x]}let Y=wXw.safeParse(A);if(!Y.success)return B;let X=Y.data,W=X.entityType,H=X.metadata.slug,K=Q.pipelineContext.entityDisplay?.[W],U=K?K.label:W.charAt(0).toUpperCase()+W.slice(1),D=K?K.pluralName??K.label.toLowerCase()+"s":eH(W),q=`/${D}`,b=D.charAt(0).toUpperCase()+D.slice(1),I=Nu(X),V=await $Xw(I,Q),L=D20(X)??I,N=await fXw(L,Q);return{...B,...X,url:w.generateUrl(W,H),typeLabel:U,listUrl:q,listLabel:b,...V,...N&&{ogImageUrl:N}}}async function $Xw(A,Q){let w=A?Q.imageBuildService?.get(A):void 0;if(w)return{coverImageUrl:w.src,coverImageWidth:w.width,coverImageHeight:w.height,...w.srcset&&{coverImageSrcset:w.srcset,coverImageSizes:w.sizes}};let B=await To1(A,Q.pipelineContext.services.entityService);if(!B)return{};return{coverImageUrl:B.url,...B.width&&{coverImageWidth:B.width},...B.height&&{coverImageHeight:B.height}}}async function fXw(A,Q){if(!A)return;let w=Q.imageBuildService?.get(A);if(w)return Eo1(w.src,Q.siteUrl);let B=await To1(A,Q.pipelineContext.services.entityService);if(!B)return;if(B.url.startsWith("data:"))return;return Eo1(B.url,Q.siteUrl)}function Eo1(A,Q){if(/^https?:\/\//i.test(A)||A.startsWith("data:"))return A;if(!Q)return A;return`${Q.replace(/\/$/,"")}/${A.replace(/^\//,"")}`}async function To1(A,Q){if(!A)return;let w=await Q.getEntity({entityType:"image",id:A}),B=BXw.safeParse(w);if(!B.success)return;return{url:B.data.content,...B.data.metadata.width&&{width:B.data.metadata.width},...B.data.metadata.height&&{height:B.data.metadata.height}}}async function So1(A,Q){let w=new Set;try{let B=A.getEntityTypes();for(let $ of B){if($==="image")continue;let f=await A.listEntities({entityType:$});for(let Y of f){let X=Nu(Y);if(X)w.add(X);let W=D20(Y);if(W)w.add(W)}}}catch(B){Q.warn("Failed to collect image IDs for pre-resolution",{error:mA(B)})}return[...w]}async function mo1(A,Q,w,B,$){if(!A.template)return A.content??null;let f=A.template,Y=A.dataQuery?{dataParams:A.dataQuery,fallback:A.content,publishedOnly:w,visibilityScope:B}:{savedContent:{entityType:"site-content",entityId:`${Q.id}:${A.id}`},fallback:A.content,visibilityScope:B},X=await $.pipelineContext.services.resolveTemplateContent(f,Y);if(!X)return null;return Ff0(X,{pipelineContext:$.pipelineContext,imageBuildService:$.imageBuildService,siteUrl:$.siteUrl,urlGenerator:X4.getInstance()})}function uo1(A){return{routes:A.routes,siteConfig:{title:A.siteMetadata.title,description:A.siteMetadata.description,...A.siteMetadata.url&&{url:A.siteMetadata.url},...A.siteMetadata.copyright&&{copyright:A.siteMetadata.copyright},...A.siteMetadata.themeMode&&{themeMode:A.siteMetadata.themeMode},...A.siteMetadata.analyticsScript&&{analyticsScript:A.siteMetadata.analyticsScript}},headScripts:A.buildOptions.headScripts,...A.buildOptions.staticAssets&&{staticAssets:A.buildOptions.staticAssets},getContent:async(Q,w)=>{let B=A.parsedOptions.environment==="production";return mo1(w,Q,B,"public",{pipelineContext:A.pipelineContext,imageBuildService:A.imageBuildService,siteUrl:A.siteMetadata.url})},getViewTemplate:(Q)=>{return A.pipelineContext.services.getViewTemplate(Q)},layouts:A.parsedOptions.layouts,getSiteLayoutInfo:async()=>{return yo1(A.siteMetadata,A.pipelineContext.profileService,A.pipelineContext.routeRegistry)},...A.parsedOptions.themeCSS!==void 0&&{themeCSS:A.parsedOptions.themeCSS},...A.buildOptions.slots&&{slots:A.buildOptions.slots},imageBuildService:A.imageBuildService}}import{join as YXw}from"path";async function co1(A){let Q=A.parsedOptions.workingDir??YXw(A.parsedOptions.outputDir,".preact-work"),w=A.staticSiteBuilderFactory({logger:A.logger.child("StaticSiteBuilder"),workingDir:Q,outputDir:A.parsedOptions.outputDir});if(A.parsedOptions.cleanBeforeBuild)await w.clean();return w}async function lo1(A){await new If0({logger:A.pipelineContext.logger.child("DynamicRouteGenerator"),entityService:A.pipelineContext.services.entityService,listViewTemplateNames:()=>A.pipelineContext.services.listViewTemplateNames()},A.pipelineContext.routeRegistry,A.pipelineContext.entityDisplay,{visibilityScope:"public",...A.publishedOnly!==void 0&&{publishedOnly:A.publishedOnly}}).generateEntityRoutes()}async function po1(A){let Q=new Vf0(A.pipelineContext.services.entityService,A.pipelineContext.logger,A.sharedImagesDir),w=await So1(A.pipelineContext.services.entityService,A.pipelineContext.logger);if(w.length>0)await Q.resolveAll(w);return Q}async function io1(A){let Q=A.reporter?.createSub({scale:{start:85,end:95}});await A.staticSiteBuilder.build(A.buildContext,(w)=>{Q?.report(w).catch(()=>{})})}function do1(A){return{success:!0,outputDir:A.outputDir,filesGenerated:A.routesBuilt+1,routesBuilt:A.routesBuilt,...A.warnings.length>0&&{warnings:A.warnings}}}function no1(A){return{success:!1,outputDir:A.outputDir,filesGenerated:0,routesBuilt:0,errors:[A.errorMessage]}}async function ro1(A){let Q=Co1.parse(A.buildOptions),w=Xf.from(A.progress),B=[];try{await w?.report({message:"Starting site build",progress:0,total:100}),await w?.report({message:"Generating dynamic routes",progress:10,total:100}),await lo1({pipelineContext:A.pipelineContext,publishedOnly:Q.environment==="production"});let $=await co1({logger:A.pipelineContext.logger,parsedOptions:Q,staticSiteBuilderFactory:A.staticSiteBuilderFactory}),f=go1(A.pipelineContext.routeRegistry);B.push(...f.warnings);let{routes:Y}=f;await w?.report({message:`Building ${Y.length} routes`,progress:20,total:100}),await w?.report({message:"Resolving images",progress:25,total:100});let X=await po1({pipelineContext:A.pipelineContext,sharedImagesDir:Q.sharedImagesDir}),W=uo1({routes:Y,parsedOptions:Q,buildOptions:A.buildOptions,pipelineContext:A.pipelineContext,imageBuildService:X,siteMetadata:Q.siteConfig});return await io1({staticSiteBuilder:$,buildContext:W,reporter:w}),await w?.report({message:"Site build complete",progress:100,total:100}),do1({outputDir:Q.outputDir,routesBuilt:Y.length,warnings:B})}catch($){let f=Error("Site build process failed");return A.pipelineContext.logger.error("Site build failed",{error:f,originalError:$}),no1({outputDir:Q.outputDir,errorMessage:f.message})}}class xZ{static instance=null;static defaultStaticSiteBuilderFactory=Cn0;pipelineContext;staticSiteBuilderFactory;static setDefaultStaticSiteBuilderFactory(A){xZ.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,w,B,$=void 0){return xZ.instance??=new xZ(A,xZ.defaultStaticSiteBuilderFactory,Q,w,B,$),xZ.instance}static resetInstance(){xZ.instance=null}static createFresh(A,Q,w,B,$,f=void 0){return new xZ(A,$??xZ.defaultStaticSiteBuilderFactory,Q,w,B,f)}constructor(A,Q,w,B,$,f){this.pipelineContext={logger:A,services:w,routeRegistry:B,profileService:$,entityDisplay:f},this.staticSiteBuilderFactory=Q,X4.getInstance().configure(f)}async build(A,Q){return ro1({buildOptions:A,progress:Q,pipelineContext:this.pipelineContext,staticSiteBuilderFactory:this.staticSiteBuilderFactory})}}class gn0{config;context;pluginId;logger;debounces=new Map;unsubscribeFunctions=[];constructor(A,Q,w,B){this.config=A,this.context=Q,this.pluginId=w,this.logger=B}requestBuild(A){let Q=A??(this.config.previewOutputDir?"preview":"production"),w=this.debounces.get(Q);if(!w)w=new nd(()=>{this.enqueueBuild(Q)},this.config.rebuildDebounce),this.debounces.set(Q,w);w.trigger()}setupAutoRebuild(){let A=new Set(["note"]),Q=async(B)=>{let{entityType:$}=B.payload;if(!A.has($))this.logger.debug(`Entity type ${$} will trigger rebuild`),this.requestBuild();return{success:!0}},w=["entity:created","entity:updated","entity:deleted"];for(let B of w)this.unsubscribeFunctions.push(this.context.messaging.subscribe(B,Q));this.logger.debug(`Auto-rebuild enabled (${this.config.rebuildDebounce}ms debounce), excluding types: ${[...A].join(", ")}`)}dispose(){for(let A of this.debounces.values())A.dispose();this.debounces.clear();for(let A of this.unsubscribeFunctions)A();this.unsubscribeFunctions=[]}async enqueueBuild(A){let Q=A==="production"?this.config.productionOutputDir:this.config.previewOutputDir;this.logger.debug(`Triggering ${A} site rebuild`);try{await this.context.jobs.enqueue({type:"site-build",data:{environment:A,outputDir:Q,workingDir:this.config.workingDir,enableContentGeneration:!0,metadata:{trigger:"debounced-rebuild",timestamp:new Date().toISOString()}},options:{priority:0,source:this.pluginId,metadata:{operationType:"content_operations"},deduplication:"skip"}}),this.logger.debug("Site rebuild enqueued")}catch(w){this.logger.error("Failed to enqueue site rebuild",{error:w})}}}s5();function XXw(A,Q){return A.map((w)=>({...w,template:w.template.includes(":")?w.template:`${Q}:${w.template}`}))}function Lf0(A,Q,w){for(let B of A)w.register({...B,pluginId:Q,sections:B.sections?XXw(B.sections,Q):[]})}function oo1(A,Q,w){A.messaging.subscribe("plugin:site-builder:route:register",async(B)=>{try{let $=Be.parse(B.payload),{routes:f,pluginId:Y}=$;return Lf0(f,Y,Q),{success:!0}}catch($){return w.error("Failed to register routes",{error:$}),{success:!1,error:"Failed to register routes"}}}),A.messaging.subscribe("plugin:site-builder:route:unregister",async(B)=>{try{let $=$e.parse(B.payload),{paths:f,pluginId:Y}=$;if(f)for(let X of f)Q.unregister(X);else if(Y)Q.unregisterByPlugin(Y);return{success:!0}}catch($){return w.error("Failed to unregister routes",{error:$}),{success:!1,error:"Failed to unregister routes"}}}),A.messaging.subscribe("plugin:site-builder:route:list",async(B)=>{try{let $=fe.parse(B.payload);return{success:!0,data:{routes:Q.list($.pluginId?$:void 0)}}}catch($){return w.error("Failed to list routes",{error:$}),{success:!1,error:"Failed to list routes"}}}),A.messaging.subscribe("plugin:site-builder:route:get",async(B)=>{try{let $=Ye.parse(B.payload);return{success:!0,data:{route:Q.get($.path)}}}catch($){return w.error("Failed to get route",{error:$}),{success:!1,error:"Failed to get route"}}}),A.messaging.subscribe("site-builder:routes:list",async()=>{return{success:!0,data:Q.list()}})}import{promises as so1}from"fs";import{join as ao1}from"path";async function ZXw(A,Q,w){let B=A.siteConfig.url??"https://example.com",$=Q.list(),f=vn0(B,A.environment);await so1.writeFile(ao1(A.outputDir,"robots.txt"),f,"utf-8"),w.info(`Generated robots.txt for ${A.environment} environment`);let Y=hn0($,B);await so1.writeFile(ao1(A.outputDir,"sitemap.xml"),Y,"utf-8"),w.info(`Generated sitemap.xml with ${$.length} URLs`)}function to1(A){let{context:Q,routeRegistry:w,logger:B}=A;Q.messaging.subscribe("site:build:completed",async($)=>{try{let f=$.payload;return B.info(`Received site:build:completed event for ${f.environment} environment - generating SEO files`),await ZXw(f,w,B),{success:!0}}catch(f){return B.error("Failed to generate SEO files",f),{success:!1}}})}wA();N0();var eo1=Z.object({environment:Z.enum(["preview","production"]).optional(),outputDir:Z.string(),workingDir:Z.string().optional(),enableContentGeneration:Z.boolean().optional(),siteConfig:pg.optional()});s5();s5();N0();var WXw=Z.object({heading:Z.string(),buttonText:Z.string(),buttonLink:Z.string()}),HXw=Z.object({blurb:Z.string().optional()}),As1=Z.object({title:Z.string(),description:Z.string(),url:Z.string().optional(),copyright:Z.string().optional(),logo:Z.boolean().optional(),themeMode:Z.enum(["light","dark"]).optional(),analyticsScript:Z.string().optional(),cta:WXw.optional(),sections:Z.record(Z.string(),HXw).optional()});async function Fr(A,Q){try{let w=await A({type:cT,payload:void 0});if("success"in w&&w.success&&w.data){let B=As1.safeParse(w.data);if(B.success)return As1.parse({...Q,...B.data})}}catch{}return Q}class yn0 extends aw{sendMessage;cfg;constructor(A,Q,w){super(A,{schema:eo1,jobTypeName:"site-build"});this.sendMessage=Q,this.cfg=w}async process(A,Q,w){let B=A.environment??"preview",$=A.enableContentGeneration??!1;try{this.logger.debug("Starting site build job",{jobId:Q,environment:B,outputDir:A.outputDir}),await w.report({progress:0,total:100,message:`Starting site build for ${B} environment`});let f=w.createSub({scale:{start:10,end:90}}),Y=await Fr(this.sendMessage,A.siteConfig??this.cfg.defaultSiteConfig),X=await this.cfg.siteBuilder.build({outputDir:A.outputDir,workingDir:A.workingDir,sharedImagesDir:this.cfg.sharedImagesDir,enableContentGeneration:$,environment:B,cleanBeforeBuild:!0,siteConfig:Y,layouts:this.cfg.layouts,themeCSS:this.cfg.themeCSS,slots:this.cfg.slots,headScripts:this.cfg.getHeadScripts?.(),...this.cfg.staticAssets&&{staticAssets:this.cfg.staticAssets}},f.toCallback());if(await w.report({progress:100,total:100,message:`Site build completed: ${X.routesBuilt} routes built`}),this.logger.debug("Site build job completed",{jobId:Q,environment:B,routesBuilt:X.routesBuilt,success:X.success}),X.success){this.logger.info(`Emitting site:build:completed event for ${B} environment`);let W=B==="preview"?this.cfg.previewUrl??this.cfg.siteUrl:this.cfg.siteUrl;await this.sendMessage({type:"site:build:completed",payload:{outputDir:A.outputDir,environment:B,routesBuilt:X.routesBuilt,siteConfig:{...Y,url:W},generateEntityUrl:(H,K)=>X4.getInstance().generateUrl(H,K)},broadcast:!0})}return{success:X.success,routesBuilt:X.routesBuilt,outputDir:A.outputDir,environment:B,...X.errors&&{errors:X.errors},...X.warnings&&{warnings:X.warnings}}}catch(f){throw this.logger.error("Site build job failed",f),f}}summarizeDataForLog(A){return{environment:A.environment,outputDir:A.outputDir}}}N0();s5();var KXw=Z.object({slot:Z.enum(XV).optional().default("primary"),limit:Z.number().optional()});class En0{routeRegistry;logger;id="site:navigation";name="Site Navigation DataSource";description="Provides navigation items for site menus";constructor(A,Q){this.routeRegistry=A,this.logger=Q,this.logger.debug("NavigationDataSource initialized")}async fetch(A,Q,w){let B=KXw.parse(A??{});this.logger.debug("NavigationDataSource fetch called",{params:B});let $=this.routeRegistry.getNavigationItems(B.slot),f=B.limit?$.slice(0,B.limit):$,Y=f.map((W)=>({label:W.label,href:W.href}));this.logger.debug("NavigationDataSource returning",{slot:B.slot,itemCount:f.length,items:Y});let X={navigation:Y};return Q.parse(X)}}s5();wA();N0();var UXw=Z.object({environment:Z.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function Qs1(A,Q){return[P6(A,"build-site","Build a static site from registered routes. Call this for every user build/rebuild request, including repeated requests like 'build it again' or 'one more build'.",UXw,async(w)=>{return Q(w.environment),{success:!0,message:`Site build requested${w.environment?` for ${w.environment}`:""} (debounced)`,data:{}}},{sideEffects:"external",cli:{name:"build"}})]}N0();s5();var DXw=Z.object({id:Z.string(),template:Z.string(),content:Z.unknown().optional(),dataQuery:Z.looseObject({entityType:Z.string().optional(),template:Z.string().optional(),query:Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),offset:Z.number().optional()}).optional()}).optional(),order:Z.number().optional()}),GXw=Z.object({show:Z.boolean().default(!1),label:Z.string().optional(),slot:Z.enum(XV).default("primary"),priority:Z.number().min(0).max(100).default(50)}).optional(),zXw=Z.object({id:Z.string(),path:Z.string(),title:Z.string().default(""),pageLabel:Z.string().optional(),description:Z.string().default(""),sections:Z.array(DXw).default([]),layout:Z.string().default("default"),fullscreen:Z.boolean().optional(),pluginId:Z.string().optional(),sourceEntityType:Z.string().optional(),external:Z.boolean().optional(),navigation:GXw}),ws1=Z.object({previewOutputDir:Z.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:Z.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:Z.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:Z.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:pg.default({title:"Brain",description:"A knowledge management system"}),themeCSS:Z.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:Z.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:Z.any().optional().describe("Template definitions to register"),routes:Z.array(zXw).optional().describe("Routes to register"),layouts:Z.record(Z.string(),Z.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:Z.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:Z.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:Z.record(Z.string(),Z.object({label:Z.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:Z.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:Z.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:Z.boolean().optional().describe("Enable pagination for list pages"),pageSize:Z.number().optional().describe("Items per page (default: 10)"),navigation:Z.object({show:Z.boolean().optional().describe("Show in navigation"),slot:Z.enum(XV).optional().describe("Navigation slot (primary or secondary)"),priority:Z.number().min(0).max(100).optional().describe("Navigation priority (0-100)")}).optional().describe("Navigation settings for this entity type")})).optional().describe("Display metadata per entity type \u2014 label, plural name, layout, pagination, navigation slot. Consulted when auto-generating routes for active entity plugins."),staticAssets:Z.record(Z.string(),Z.string()).optional().describe("Static files to write to the output directory at build time. Keys are output paths (e.g. '/canvases/tree.js'), values are file contents as strings. Typically supplied by a SitePackage via text imports.")});var Bs1={name:"@brains/site-builder-plugin",version:"0.2.0-alpha.143",description:"Static site generation plugin for Brain system",dependencies:{"@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-engine":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*","@tailwindcss/typography":"^0.5.20",preact:"^10.27.2","preact-render-to-string":"^6.7.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{clean:"rm -rf dist",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class Tn0 extends aQ{siteBuilder;pluginContext;_routeRegistry;_slotRegistry;profileService;layouts;rebuildManager;headScripts=new Map;get routeRegistry(){if(!this._routeRegistry)throw Error("RouteRegistry not initialized - plugin not registered");return this._routeRegistry}constructor(A={}){let Q=A.layouts??{};super("site-builder",Bs1,{...A,layouts:Q},ws1);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new Jf0(A.logger),this._slotRegistry=new r40,A.messaging.subscribe("plugin:site-builder:slot:register",async(w)=>{let{slotName:B,pluginId:$,render:f,priority:Y}=w.payload;return this._slotRegistry?.register(B,{pluginId:$,render:f,...Y!==void 0&&{priority:Y}}),{success:!0}}),A.messaging.subscribe("plugin:site-builder:head-script:register",async(w)=>{let{pluginId:B,script:$}=w.payload;return this.headScripts.set(B,$),{success:!0}}),A.entities.registerDataSource(new En0(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService=If.getInstance(A.entityService,A.logger),oo1(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)Lf0(this.config.routes,this.id,this.routeRegistry);let Q={entityService:A.entityService,sendMessage:A.messaging.send,resolveTemplateContent:(w,B)=>A.templates.resolve(w,B),getViewTemplate:(w)=>A.views.get(w),listViewTemplateNames:()=>A.views.list().map((w)=>w.name)};if(this.siteBuilder=xZ.getInstance(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,this.config.entityDisplay),A.jobs.registerHandler("site-build",new yn0(this.logger.child("SiteBuildJobHandler"),A.messaging.send,{siteBuilder:this.siteBuilder,layouts:this.layouts,defaultSiteConfig:this.config.siteInfo,sharedImagesDir:this.config.sharedImagesDir,siteUrl:A.siteUrl,previewUrl:A.previewUrl,themeCSS:this.config.themeCSS,slots:this._slotRegistry,getHeadScripts:()=>this.getRegisteredHeadScripts(),...this.config.staticAssets&&{staticAssets:this.config.staticAssets}})),this.rebuildManager=new gn0(this.config,A,this.id,this.logger),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();A.messaging.subscribe(lT,async()=>{let w=await this.getInstructions();if(w)A.registerInstructions(w);return{success:!0}}),to1({context:A,routeRegistry:this._routeRegistry,logger:this.logger})}getRegisteredHeadScripts(){return Array.from(this.headScripts.values())}async getTools(){if(!this.pluginContext||!this.rebuildManager)throw Error("Plugin context not initialized");let A=this.rebuildManager;return Qs1(this.id,(Q)=>A.requestBuild(Q))}async getResources(){let A=this.getContext();return[{uri:"brain://site",name:"Site Metadata",description:"Site metadata \u2014 title, description, domain, URLs",mimeType:"application/json",handler:async()=>{let Q=await Fr(A.messaging.send,this.config.siteInfo);return{contents:[{uri:"brain://site",mimeType:"application/json",text:JSON.stringify({...Q,domain:A.domain,siteUrl:A.siteUrl,previewUrl:A.previewUrl},null,2)}]}}},{uri:"site://routes",name:"Site Routes",description:"All registered routes with sections and templates",mimeType:"application/json",handler:async()=>{let Q=this.routeRegistry.list();return{contents:[{uri:"site://routes",mimeType:"application/json",text:JSON.stringify(Q.map((w)=>({id:w.id,path:w.path,title:w.title,description:w.description,sections:w.sections.map((B)=>({id:B.id,template:B.template}))})),null,2)}]}}},{uri:"site://templates",name:"View Templates",description:"All registered view templates",mimeType:"application/json",handler:async()=>{let Q=A.views.list();return{contents:[{uri:"site://templates",mimeType:"application/json",text:JSON.stringify(Q.map((w)=>({name:w.name,description:w.description,hasWebRenderer:!!w.renderers.web})),null,2)}]}}}]}getSiteBuilder(){return this.siteBuilder}getSlotRegistry(){return this._slotRegistry}async getInstructions(){let A=this.getContext(),Q="## Site Builder Actions\n- When the user asks to build, rebuild, publish, or build the website/site again, call `site-builder_build-site` immediately.\n- Every repeated build request requires a fresh `site-builder_build-site` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.",w=await Fr(A.messaging.send,this.config.siteInfo);return`## Your Site
5765
5765
  ${[`**Title:** ${w.title}`,`**Description:** ${w.description}`,A.domain&&`**Domain:** ${A.domain}`,A.siteUrl&&`**URL:** ${A.siteUrl}`].filter(Boolean).join(`
5766
5766
  `)}
5767
5767
 
5768
5768
  ## Site Builder Actions
5769
5769
  - When the user asks to build, rebuild, publish, or build the website/site again, call \`site-builder_build-site\` immediately.
5770
- - Every repeated build request requires a fresh \`site-builder_build-site\` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.`}async onShutdown(){this.logger.debug("Shutting down site-builder plugin"),this.rebuildManager?.dispose(),xZ.resetInstance(),this.logger.debug("Cleaned up all event subscriptions")}}function cj(A={}){return new Tn0(A)}wA();s5();wA();N0();s5();var bXw=Z.object({}),VXw=Z.object({}),Lr=LQ.extend({id:Z.literal("site-info"),entityType:Z.literal("site-info"),metadata:VXw});var ig=az0.omit({url:!0,analyticsScript:!0});wA();N0();var IXw=Z.record(Z.string(),Z.unknown());class pG extends C2{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:Lr,frontmatterSchema:ig,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=ig.parse(A);return this.buildMarkdown("",Q)}parseSiteInfoBody(A){return this.parseFrontmatter(A)}fromMarkdown(A){return{content:A,entityType:"site-info"}}extractMetadata(A){return{}}generateFrontMatter(A){let Q=this.parseFrontmatter(A.content);return this.buildMarkdown("",IXw.parse(Q))}}class iG{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,w){return iG.instance??=new iG(A,Q,w),iG.instance}static resetInstance(){iG.instance=null}static createFresh(A,Q,w){return new iG(A,Q,w)}constructor(A,Q,w){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new pG;let B=iG.getDefaultSiteInfo();this.defaultSiteInfo={...B,...w}}async initialize(){try{if(!await this.entityService.getEntity({entityType:"site-info",id:"site-info"})){if(await this.entityService.getEntity({entityType:"site-info",id:"site-info"}))return;this.logger.info("No site info found, creating default site info");let w=this.adapter.createSiteInfoContent(this.defaultSiteInfo);await this.entityService.createEntity({entity:{id:"site-info",entityType:"site-info",content:w,metadata:{}}}),this.logger.info("Default site info created successfully")}}catch(A){this.logger.error("Failed to initialize site info",{error:A})}}async getSiteInfo(){try{let A=await this.entityService.getEntity({entityType:"site-info",id:"site-info"});if(A)return this.adapter.parseSiteInfoBody(A.content)}catch(A){this.logger.debug("Site info not found, using defaults",{error:A})}return this.defaultSiteInfo}}N0();var JXw=new pG,FXw=Z.looseObject({platform:Z.string(),url:Z.string(),label:Z.string().optional()}).transform((A)=>({platform:A.platform,url:A.url,...A.label!==void 0?{label:A.label}:{}})),LXw=Z.looseObject({socialLinks:Z.array(FXw).optional()});class kf0{logger;id="site-info:entities";name="Site Info DataSource";description="Provides site metadata (title, description, CTA) and profile social links";constructor(A){this.logger=A}async fetch(A,Q,w){let{entityService:B}=w,$;try{let X=await B.getEntity({entityType:"site-info",id:"site-info"});$=X?JXw.parseSiteInfoBody(X.content):{title:"Brain",description:"A knowledge management system"}}catch{$={title:"Brain",description:"A knowledge management system"}}let f;try{let X=await B.getEntity({entityType:"anchor-profile",id:"anchor-profile"});if(X){let W=LXw.safeParse(X.metadata);f=W.success?W.data.socialLinks:void 0}}catch{}let Y={...$,socialLinks:f,copyright:$.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var $s1={name:"@brains/site-info",version:"0.2.0-alpha.142",description:"Site info entity \u2014 site metadata, title, description, CTA",dependencies:{"@brains/entity-service":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var _Xw=new pG,NXw="site-info";class Sn0 extends nQ{entityType=NXw;schema=Lr;adapter=_Xw;defaultSiteInfo;constructor(A){super("site-info",$s1,{},L7);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new kf0(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=iG.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(cT,async()=>{return{success:!0,data:await Q.getSiteInfo()}}),A.messaging.subscribe("entity:updated",async(w)=>{if(w.payload.entityType==="site-info"){let $=await Q.getSiteInfo();await A.messaging.send({type:lT,payload:$,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function lj(A){return new Sn0(A)}var jXw=new pG;async function kr(A){let w=(await A.listEntities({entityType:"site-info",options:{limit:1}}))[0];if(!w)throw Error("Site info not found \u2014 create a site-info entity");return jXw.parseSiteInfoBody(w.content)}function fs1(A,Q){let w=A.metadata.publishedAt??A.created,B=Q.metadata.publishedAt??Q.created;return new Date(B).getTime()-new Date(w).getTime()}async function _f0(A,Q){return(await A.listEntities({entityType:Q.entityType,options:{limit:20}})).sort(fs1).slice(0,Q.count).map(Q.parse)}function mn0(A){if(!A)throw Error("CTA not configured in site-info");return A}N0();var Ys1=Z.object({label:Z.string(),href:Z.string(),priority:Z.number()}),PXw=Z.object({primary:Z.array(Ys1),secondary:Z.array(Ys1)}),MXw=Z.object({platform:Z.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:Z.string().describe("Profile or contact URL"),label:Z.string().optional().describe("Optional display label")}),OXw=ig.extend({navigation:PXw,copyright:Z.string(),socialLinks:Z.array(MXw).optional().describe("Social media links from profile entity")});wA();kH();ng();N0();var un0=Z.object({defaultPrompt:Z.string().default("Write a blog post about my recent work and insights"),paginate:Z.boolean().default(!0),pageSize:Z.number().default(10)});wA();g6();K2();N0();var CXw=Z.object({prompt:Z.string().optional(),title:Z.string().optional(),content:Z.string().optional(),excerpt:Z.string().optional(),coverImageId:Z.string().optional(),seriesName:Z.string().optional(),seriesIndex:Z.number().optional(),skipAi:Z.boolean().optional()}),XoB=LX.extend({title:Z.string().optional(),slug:Z.string().optional()});class cn0 extends z4{constructor(A,Q){super(A,Q,{schema:CXw,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:w,coverImageId:B,seriesName:$,seriesIndex:f,skipAi:Y}=A,{title:X,content:W,excerpt:H}=A;if(Y){if(!X)this.failEarly("Title is required when skipAi is true");W=W??`## Introduction
5770
+ - Every repeated build request requires a fresh \`site-builder_build-site\` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.`}async onShutdown(){this.logger.debug("Shutting down site-builder plugin"),this.rebuildManager?.dispose(),xZ.resetInstance(),this.logger.debug("Cleaned up all event subscriptions")}}function cj(A={}){return new Tn0(A)}wA();s5();wA();N0();s5();var bXw=Z.object({}),VXw=Z.object({}),Lr=LQ.extend({id:Z.literal("site-info"),entityType:Z.literal("site-info"),metadata:VXw});var ig=az0.omit({url:!0,analyticsScript:!0});wA();N0();var IXw=Z.record(Z.string(),Z.unknown());class pG extends C2{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:Lr,frontmatterSchema:ig,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=ig.parse(A);return this.buildMarkdown("",Q)}parseSiteInfoBody(A){return this.parseFrontmatter(A)}fromMarkdown(A){return{content:A,entityType:"site-info"}}extractMetadata(A){return{}}generateFrontMatter(A){let Q=this.parseFrontmatter(A.content);return this.buildMarkdown("",IXw.parse(Q))}}class iG{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,w){return iG.instance??=new iG(A,Q,w),iG.instance}static resetInstance(){iG.instance=null}static createFresh(A,Q,w){return new iG(A,Q,w)}constructor(A,Q,w){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new pG;let B=iG.getDefaultSiteInfo();this.defaultSiteInfo={...B,...w}}async initialize(){try{if(!await this.entityService.getEntity({entityType:"site-info",id:"site-info"})){if(await this.entityService.getEntity({entityType:"site-info",id:"site-info"}))return;this.logger.info("No site info found, creating default site info");let w=this.adapter.createSiteInfoContent(this.defaultSiteInfo);await this.entityService.createEntity({entity:{id:"site-info",entityType:"site-info",content:w,metadata:{}}}),this.logger.info("Default site info created successfully")}}catch(A){this.logger.error("Failed to initialize site info",{error:A})}}async getSiteInfo(){try{let A=await this.entityService.getEntity({entityType:"site-info",id:"site-info"});if(A)return this.adapter.parseSiteInfoBody(A.content)}catch(A){this.logger.debug("Site info not found, using defaults",{error:A})}return this.defaultSiteInfo}}N0();var JXw=new pG,FXw=Z.looseObject({platform:Z.string(),url:Z.string(),label:Z.string().optional()}).transform((A)=>({platform:A.platform,url:A.url,...A.label!==void 0?{label:A.label}:{}})),LXw=Z.looseObject({socialLinks:Z.array(FXw).optional()});class kf0{logger;id="site-info:entities";name="Site Info DataSource";description="Provides site metadata (title, description, CTA) and profile social links";constructor(A){this.logger=A}async fetch(A,Q,w){let{entityService:B}=w,$;try{let X=await B.getEntity({entityType:"site-info",id:"site-info"});$=X?JXw.parseSiteInfoBody(X.content):{title:"Brain",description:"A knowledge management system"}}catch{$={title:"Brain",description:"A knowledge management system"}}let f;try{let X=await B.getEntity({entityType:"anchor-profile",id:"anchor-profile"});if(X){let W=LXw.safeParse(X.metadata);f=W.success?W.data.socialLinks:void 0}}catch{}let Y={...$,socialLinks:f,copyright:$.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var $s1={name:"@brains/site-info",version:"0.2.0-alpha.143",description:"Site info entity \u2014 site metadata, title, description, CTA",dependencies:{"@brains/entity-service":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var _Xw=new pG,NXw="site-info";class Sn0 extends nQ{entityType=NXw;schema=Lr;adapter=_Xw;defaultSiteInfo;constructor(A){super("site-info",$s1,{},L7);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new kf0(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=iG.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(cT,async()=>{return{success:!0,data:await Q.getSiteInfo()}}),A.messaging.subscribe("entity:updated",async(w)=>{if(w.payload.entityType==="site-info"){let $=await Q.getSiteInfo();await A.messaging.send({type:lT,payload:$,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function lj(A){return new Sn0(A)}var jXw=new pG;async function kr(A){let w=(await A.listEntities({entityType:"site-info",options:{limit:1}}))[0];if(!w)throw Error("Site info not found \u2014 create a site-info entity");return jXw.parseSiteInfoBody(w.content)}function fs1(A,Q){let w=A.metadata.publishedAt??A.created,B=Q.metadata.publishedAt??Q.created;return new Date(B).getTime()-new Date(w).getTime()}async function _f0(A,Q){return(await A.listEntities({entityType:Q.entityType,options:{limit:20}})).sort(fs1).slice(0,Q.count).map(Q.parse)}function mn0(A){if(!A)throw Error("CTA not configured in site-info");return A}N0();var Ys1=Z.object({label:Z.string(),href:Z.string(),priority:Z.number()}),PXw=Z.object({primary:Z.array(Ys1),secondary:Z.array(Ys1)}),MXw=Z.object({platform:Z.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:Z.string().describe("Profile or contact URL"),label:Z.string().optional().describe("Optional display label")}),OXw=ig.extend({navigation:PXw,copyright:Z.string(),socialLinks:Z.array(MXw).optional().describe("Social media links from profile entity")});wA();kH();ng();N0();var un0=Z.object({defaultPrompt:Z.string().default("Write a blog post about my recent work and insights"),paginate:Z.boolean().default(!0),pageSize:Z.number().default(10)});wA();g6();K2();N0();var CXw=Z.object({prompt:Z.string().optional(),title:Z.string().optional(),content:Z.string().optional(),excerpt:Z.string().optional(),coverImageId:Z.string().optional(),seriesName:Z.string().optional(),seriesIndex:Z.number().optional(),skipAi:Z.boolean().optional()}),XoB=LX.extend({title:Z.string().optional(),slug:Z.string().optional()});class cn0 extends z4{constructor(A,Q){super(A,Q,{schema:CXw,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:w,coverImageId:B,seriesName:$,seriesIndex:f,skipAi:Y}=A,{title:X,content:W,excerpt:H}=A;if(Y){if(!X)this.failEarly("Title is required when skipAi is true");W=W??`## Introduction
5771
5771
 
5772
5772
  Add your introduction here.
5773
5773
 
@@ -5987,7 +5987,7 @@ ${w.content}`,templateName:"blog:excerpt"})})}wA();ng();kH();function $Zw(A){let
5987
5987
  letter-spacing: 0.02em;
5988
5988
  }
5989
5989
  .printable-footer a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
5990
- `}},void 0,!1,void 0,this),c7("header",{className:"printable-hero",children:[c7("div",{className:"printable-masthead",children:Q.brandLabel&&c7("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),c7("div",{children:[c7("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&c7("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),c7("div",{className:"printable-meta",children:[Q.author&&c7("span",{children:["By ",Q.author]},void 0,!0,void 0,this),w&&c7("span",{children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Q.coverImageUrl&&c7("figure",{className:"printable-cover-wrap",children:c7("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),c7(V9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.brandLabel))&&c7("footer",{className:"printable-footer",children:[c7("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&c7("a",{href:Q.canonicalUrl,children:Q.canonicalUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var mZw=26214400,uZw=60000;class en0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??kU}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==Mf0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=cZw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await yZw(SZw(TZw(),"brain-blog-printable-"));try{let $=await vZ({outputDir:B,mediaPath:`/_media/printable/post/${Q.id}`,template:Ps1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await hZ({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:mZw,timeoutMs:uZw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${lZw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await EZw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=j6(A.content),w=H$.parse(Q);if(!w.coverImageId)return;let B=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return B?.content.startsWith("data:image/")?B.content:void 0}}function cZw(A,Q={}){let{frontmatter:w,content:B}=j6(A.content),$=H$.parse(w);return{title:$.title,body:B,...$.excerpt?{excerpt:$.excerpt}:{},...$.author?{author:$.author}:{},...$.publishedAt?{publishedAt:$.publishedAt}:{},...$.canonicalUrl?{canonicalUrl:$.canonicalUrl}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function lZw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.title)}import{mkdtemp as rZw,rm as oZw}from"fs/promises";import{tmpdir as sZw}from"os";import{join as aZw}from"path";S9();K2();kH();N0();import{jsxDEV as nZw}from"preact/jsx-dev-runtime";var Or="og-image",pZw="blog:og-image",Ms1=Z.object({title:Z.string().min(1),excerpt:Z.string().optional(),author:Z.string().optional(),publishedAt:Z.string().optional(),brandLabel:Z.string().optional(),coverImageUrl:Z.string().optional()}),Os1={name:pZw,pluginId:"blog",schema:Ms1,renderers:{image:dZw}};function iZw(A){if(!A)return;let Q=new Date(A);if(Number.isNaN(Q.getTime()))return;return Q.toLocaleDateString("en-GB",{year:"numeric",month:"short",day:"2-digit"})}function dZw(A){let Q=Ms1.parse(A);return nZw(cq,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:iZw(Q.publishedAt)},void 0,!1,void 0,this)}var tZw={width:1200,height:630},eZw=60000;class Ar0{metadata={outputEntityType:"image",targetField:"ogImageId"};context;screenshotPng;constructor(A,Q={}){this.context=A,this.screenshotPng=Q.screenshotPng??Mr}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==Or)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=AWw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await rZw(aZw(sZw(),"brain-blog-og-image-"));try{let $=await vZ({outputDir:B,mediaPath:`/_media/og/post/${Q.id}`,template:Os1,format:"image",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await hZ({rootDir:B});try{return{type:"image",data:await this.screenshotPng(f.urlFor($.urlPath),tZw,{timeoutMs:eZw,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${QWw(Q)}-og.png`}}finally{await f.close()}}finally{await oZw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=j6(A.content),w=H$.parse(Q);if(!w.coverImageId)return;let B=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return B?.content.startsWith("data:image/")?B.content:void 0}}function AWw(A,Q={}){let{frontmatter:w}=j6(A.content),B=H$.parse(w);return{title:B.title,...B.excerpt?{excerpt:B.excerpt}:{},...B.author?{author:B.author}:{},...B.publishedAt?{publishedAt:B.publishedAt}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function QWw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.title)}var xs1={name:"@brains/blog",version:"0.2.0-alpha.142",description:"AI-powered blog post generation from existing brain content",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/contracts":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class Qr0 extends nQ{entityType=$b.entityType;schema=dg;adapter=$b;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",xs1,A,un0)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new cn0(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return Us1()}getDataSources(){return[new pn0(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (hs1(),vs1));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),Ds1(A,this.logger),Gs1(A,this.logger),qs1(A,this.logger),bs1(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",Mf0,new en0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",Or,new Ar0(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=A8.getInstance().register(nn0()),this.logger.info("Blog plugin registered (routes auto-generated at /posts/)")}deferPublishAssetRegistration(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish-assets:register",payload:{entityType:"post",attachmentType:Or,mediaEntityType:"image",targetEntityField:{location:"frontmatter",field:"ogImageId"},requiredWhen:{status:"published"},autoGenerate:!0,jobType:"image:image-render-source"}}),{success:!0}})}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function wr0(A={}){return new Qr0(A)}kH();ng();wA();N0();o5();wA();N0();var _U=Z.object({title:Z.string(),slug:Z.string(),coverImageId:Z.string().optional()}),$Ww=Z.object({title:Z.string(),slug:Z.string()}),fWw=Z.object({title:Z.string(),slug:Z.string()}),bF=LQ.extend({entityType:Z.literal("series"),metadata:fWw}),Of0=bF.extend({frontmatter:_U}),YWw=Of0.extend({description:Z.string().optional(),postCount:Z.number(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),Cs1=Z.object({description:Z.string().optional()});function dj(A){return new G6(Cs1,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}wA();class Br0 extends C2{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:bF,frontmatterSchema:_U,supportsCoverImage:!0,bodyFormatter:dj("")})}toMarkdown(A){let Q,w={};try{Q=this.parseFrontMatter(A.content,_U).coverImageId,w=dj(A.metadata.title).parse(this.extractBody(A.content))}catch{}let B={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},f=dj(A.metadata.title).format(w);return this.buildMarkdown(f,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,_U);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,_U);return dj(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var VF=new Br0;wA();K2();xX();N0();var XWw=Z.object({seriesName:Z.string().optional(),seriesIndex:Z.number().optional()});function xf0(A){let Q=XWw.safeParse(A);return Q.success?Q.data:{}}function nj(A){return xf0(A.metadata).seriesName}function gs1(A){return xf0(A.metadata).seriesIndex}function ys1(A,Q){let w=gs1(A)??Number.MAX_SAFE_INTEGER,B=gs1(Q)??Number.MAX_SAFE_INTEGER;return w-B}class $r0{entityService;logger;constructor(A,Q){this.entityService=A,this.logger=Q}async syncAllSeries(){this.logger.debug("Syncing series from all entity types");let A=await this.collectSeriesNames();this.logger.debug(`Found ${A.size} unique series`);let Q=await this.entityService.listEntities({entityType:"series"}),w=new Map(Q.map(($)=>[$.id,$])),B=new Set;for(let $ of A){let f=Z1($);B.add(f);let Y=w.get(f),X=Y?.content??this.createSeriesContent($),W=w6(X);if(Y?.contentHash===W)continue;let H={id:f,entityType:"series",content:X,contentHash:W,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:$,slug:Z1($)}};await this.entityService.upsertEntity({entity:H}),this.logger.debug(`Upserted series: ${$}`)}for(let $ of Q)if(!B.has($.id))await this.entityService.deleteEntity({entityType:"series",id:$.id}),this.logger.debug(`Deleted orphaned series: ${$.id}`)}async handleEntityChange(A,Q){let w=nj(A);if(w)await this.ensureSeriesExists(w);if(Q&&Q!==w)await this.cleanupOrphanedSeries(Q)}async handleEntityDeleted(){await this.syncAllSeries()}async ensureSeriesExists(A){let Q=Z1(A);if(await this.entityService.getEntity({entityType:"series",id:Q}))return;let B=this.createSeriesContent(A),$={id:Q,entityType:"series",content:B,contentHash:w6(B),created:new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:A,slug:Z1(A)}};await this.entityService.upsertEntity({entity:$}),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=Z1(A);if(!await this.entityService.getEntity({entityType:"series",id:Q}))return;if(!await this.hasSeriesReferences(A))await this.entityService.deleteEntity({entityType:"series",id:Q}),this.logger.debug(`Deleted orphaned series: ${A}`)}async hasSeriesReferences(A){let Q=this.entityService.getEntityTypes();for(let w of Q){if(w==="series")continue;if((await this.entityService.listEntities({entityType:w,options:{filter:{metadata:{seriesName:A}},limit:1}})).length>0)return!0}return!1}async collectSeriesNames(){let A=new Set,Q=this.entityService.getEntityTypes();for(let w of Q){if(w==="series")continue;let B=await this.entityService.listEntities({entityType:w});for(let $ of B){let f=nj($);if(f)A.add(f)}}return A}createSeriesContent(A){let Q={title:A,slug:Z1(A)};return F7("",Q)}}wA();N0();var ZWw=Z.object({entityType:Z.literal("series"),query:Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional()})}),WWw=Z.object({type:Z.enum(["list","detail"]),seriesName:Z.string().optional()});function HWw(A){let Q=WWw.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let w=ZWw.safeParse(A);if(w.success){let{query:B}=w.data;if(B.id)return{type:"detail",seriesSlug:B.id};return{type:"list"}}throw Error('Invalid series query format. Expected { type: "list"|"detail" } or { entityType: "series", query: { id?: string } }')}function Es1(A){let Q=o2(A.content,_U);return Of0.parse({...A,frontmatter:Q.metadata})}class fr0{logger;id="series:entities";name="Series DataSource";description="Fetches series list and detail data";constructor(A){this.logger=A}async fetch(A,Q,w){let B=HWw(A),$=w.entityService;if(B.type==="list")return this.fetchSeriesList(Q,$);if(B.seriesName)return this.fetchSeriesDetail(B.seriesName,Q,$);if(B.seriesSlug)return this.fetchSeriesDetailBySlug(B.seriesSlug,Q,$);throw Error("Invalid series query: must specify seriesName or slug for detail")}async fetchSeriesList(A,Q){let w=await Q.listEntities({entityType:"series"}),B=await this.countEntitiesPerSeries(Q),$=w.map((f)=>{let Y=Es1(f),X=VF.parseBody(f.content);return{...Y,description:X.description,postCount:B.get(f.metadata.title)??0}});return this.logger.debug(`Found ${$.length} series entities`),A.parse({series:$})}async fetchSeriesDetail(A,Q,w,B){if(!B)B=(await w.listEntities({entityType:"series",options:{filter:{metadata:{title:A}}}}))[0];if(!B)throw Error(`Series not found: ${A}`);let $=Es1(B),f=VF.parseBody(B.content),Y=await this.getSeriesMembers(A,w);return this.logger.debug(`Found ${Y.length} entities in series "${A}"`),Q.parse({seriesName:A,posts:Y,series:{...$,description:f.description,postCount:Y.length},description:f.description})}async fetchSeriesDetailBySlug(A,Q,w){let $=(await w.listEntities({entityType:"series",options:{filter:{metadata:{slug:A}}}}))[0];if(!$)throw Error(`Series not found with slug: ${A}`);return this.fetchSeriesDetail($.metadata.title,Q,w,$)}async countEntitiesPerSeries(A){let Q=new Map,w=A.getEntityTypes();for(let B of w){if(B==="series")continue;let $=await A.listEntities({entityType:B});for(let f of $){let Y=nj(f);if(Y)Q.set(Y,(Q.get(Y)??0)+1)}}return Q}async getSeriesMembers(A,Q){let w=[],B=Q.getEntityTypes();for(let $ of B){if($==="series")continue;let f=await Q.listEntities({entityType:$,options:{filter:{metadata:{seriesName:A}}}});w.push(...f)}return w.sort(ys1),w}}wA();N0();xX();var KWw=Z.object({prompt:Z.string().optional(),title:Z.string().optional(),seriesId:Z.string().optional()}),UWw=Z.object({title:Z.string().optional(),excerpt:Z.string().optional()});class Rf0{logger;context;constructor(A,Q){this.logger=A,this.context=Q}async process(A){let Q=A.seriesId??A.title;if(!Q)return{success:!1,error:"seriesId or title required"};let w=await this.context.entityService.getEntity({entityType:"series",id:Q});if(!w)return{success:!1,error:`Series not found: ${Q}`};let B=await this.gatherMemberSummaries(w.metadata.title);if(B.length===0)return{success:!1,error:`No members found in series: ${w.metadata.title}`};let $=A.prompt??`Series name: ${w.metadata.title}
5990
+ `}},void 0,!1,void 0,this),c7("header",{className:"printable-hero",children:[c7("div",{className:"printable-masthead",children:Q.brandLabel&&c7("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),c7("div",{children:[c7("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&c7("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),c7("div",{className:"printable-meta",children:[Q.author&&c7("span",{children:["By ",Q.author]},void 0,!0,void 0,this),w&&c7("span",{children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Q.coverImageUrl&&c7("figure",{className:"printable-cover-wrap",children:c7("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),c7(V9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.brandLabel))&&c7("footer",{className:"printable-footer",children:[c7("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&c7("a",{href:Q.canonicalUrl,children:Q.canonicalUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var mZw=26214400,uZw=60000;class en0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??kU}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==Mf0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=cZw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await yZw(SZw(TZw(),"brain-blog-printable-"));try{let $=await vZ({outputDir:B,mediaPath:`/_media/printable/post/${Q.id}`,template:Ps1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await hZ({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:mZw,timeoutMs:uZw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${lZw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await EZw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=j6(A.content),w=H$.parse(Q);if(!w.coverImageId)return;let B=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return B?.content.startsWith("data:image/")?B.content:void 0}}function cZw(A,Q={}){let{frontmatter:w,content:B}=j6(A.content),$=H$.parse(w);return{title:$.title,body:B,...$.excerpt?{excerpt:$.excerpt}:{},...$.author?{author:$.author}:{},...$.publishedAt?{publishedAt:$.publishedAt}:{},...$.canonicalUrl?{canonicalUrl:$.canonicalUrl}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function lZw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.title)}import{mkdtemp as rZw,rm as oZw}from"fs/promises";import{tmpdir as sZw}from"os";import{join as aZw}from"path";S9();K2();kH();N0();import{jsxDEV as nZw}from"preact/jsx-dev-runtime";var Or="og-image",pZw="blog:og-image",Ms1=Z.object({title:Z.string().min(1),excerpt:Z.string().optional(),author:Z.string().optional(),publishedAt:Z.string().optional(),brandLabel:Z.string().optional(),coverImageUrl:Z.string().optional()}),Os1={name:pZw,pluginId:"blog",schema:Ms1,renderers:{image:dZw}};function iZw(A){if(!A)return;let Q=new Date(A);if(Number.isNaN(Q.getTime()))return;return Q.toLocaleDateString("en-GB",{year:"numeric",month:"short",day:"2-digit"})}function dZw(A){let Q=Ms1.parse(A);return nZw(cq,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:iZw(Q.publishedAt)},void 0,!1,void 0,this)}var tZw={width:1200,height:630},eZw=60000;class Ar0{metadata={outputEntityType:"image",targetField:"ogImageId"};context;screenshotPng;constructor(A,Q={}){this.context=A,this.screenshotPng=Q.screenshotPng??Mr}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==Or)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=AWw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await rZw(aZw(sZw(),"brain-blog-og-image-"));try{let $=await vZ({outputDir:B,mediaPath:`/_media/og/post/${Q.id}`,template:Os1,format:"image",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await hZ({rootDir:B});try{return{type:"image",data:await this.screenshotPng(f.urlFor($.urlPath),tZw,{timeoutMs:eZw,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${QWw(Q)}-og.png`}}finally{await f.close()}}finally{await oZw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=j6(A.content),w=H$.parse(Q);if(!w.coverImageId)return;let B=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return B?.content.startsWith("data:image/")?B.content:void 0}}function AWw(A,Q={}){let{frontmatter:w}=j6(A.content),B=H$.parse(w);return{title:B.title,...B.excerpt?{excerpt:B.excerpt}:{},...B.author?{author:B.author}:{},...B.publishedAt?{publishedAt:B.publishedAt}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function QWw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.title)}var xs1={name:"@brains/blog",version:"0.2.0-alpha.143",description:"AI-powered blog post generation from existing brain content",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/contracts":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class Qr0 extends nQ{entityType=$b.entityType;schema=dg;adapter=$b;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",xs1,A,un0)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new cn0(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return Us1()}getDataSources(){return[new pn0(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (hs1(),vs1));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),Ds1(A,this.logger),Gs1(A,this.logger),qs1(A,this.logger),bs1(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",Mf0,new en0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",Or,new Ar0(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=A8.getInstance().register(nn0()),this.logger.info("Blog plugin registered (routes auto-generated at /posts/)")}deferPublishAssetRegistration(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish-assets:register",payload:{entityType:"post",attachmentType:Or,mediaEntityType:"image",targetEntityField:{location:"frontmatter",field:"ogImageId"},requiredWhen:{status:"published"},autoGenerate:!0,jobType:"image:image-render-source"}}),{success:!0}})}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function wr0(A={}){return new Qr0(A)}kH();ng();wA();N0();o5();wA();N0();var _U=Z.object({title:Z.string(),slug:Z.string(),coverImageId:Z.string().optional()}),$Ww=Z.object({title:Z.string(),slug:Z.string()}),fWw=Z.object({title:Z.string(),slug:Z.string()}),bF=LQ.extend({entityType:Z.literal("series"),metadata:fWw}),Of0=bF.extend({frontmatter:_U}),YWw=Of0.extend({description:Z.string().optional(),postCount:Z.number(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),Cs1=Z.object({description:Z.string().optional()});function dj(A){return new G6(Cs1,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}wA();class Br0 extends C2{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:bF,frontmatterSchema:_U,supportsCoverImage:!0,bodyFormatter:dj("")})}toMarkdown(A){let Q,w={};try{Q=this.parseFrontMatter(A.content,_U).coverImageId,w=dj(A.metadata.title).parse(this.extractBody(A.content))}catch{}let B={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},f=dj(A.metadata.title).format(w);return this.buildMarkdown(f,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,_U);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,_U);return dj(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var VF=new Br0;wA();K2();xX();N0();var XWw=Z.object({seriesName:Z.string().optional(),seriesIndex:Z.number().optional()});function xf0(A){let Q=XWw.safeParse(A);return Q.success?Q.data:{}}function nj(A){return xf0(A.metadata).seriesName}function gs1(A){return xf0(A.metadata).seriesIndex}function ys1(A,Q){let w=gs1(A)??Number.MAX_SAFE_INTEGER,B=gs1(Q)??Number.MAX_SAFE_INTEGER;return w-B}class $r0{entityService;logger;constructor(A,Q){this.entityService=A,this.logger=Q}async syncAllSeries(){this.logger.debug("Syncing series from all entity types");let A=await this.collectSeriesNames();this.logger.debug(`Found ${A.size} unique series`);let Q=await this.entityService.listEntities({entityType:"series"}),w=new Map(Q.map(($)=>[$.id,$])),B=new Set;for(let $ of A){let f=Z1($);B.add(f);let Y=w.get(f),X=Y?.content??this.createSeriesContent($),W=w6(X);if(Y?.contentHash===W)continue;let H={id:f,entityType:"series",content:X,contentHash:W,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:$,slug:Z1($)}};await this.entityService.upsertEntity({entity:H}),this.logger.debug(`Upserted series: ${$}`)}for(let $ of Q)if(!B.has($.id))await this.entityService.deleteEntity({entityType:"series",id:$.id}),this.logger.debug(`Deleted orphaned series: ${$.id}`)}async handleEntityChange(A,Q){let w=nj(A);if(w)await this.ensureSeriesExists(w);if(Q&&Q!==w)await this.cleanupOrphanedSeries(Q)}async handleEntityDeleted(){await this.syncAllSeries()}async ensureSeriesExists(A){let Q=Z1(A);if(await this.entityService.getEntity({entityType:"series",id:Q}))return;let B=this.createSeriesContent(A),$={id:Q,entityType:"series",content:B,contentHash:w6(B),created:new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:A,slug:Z1(A)}};await this.entityService.upsertEntity({entity:$}),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=Z1(A);if(!await this.entityService.getEntity({entityType:"series",id:Q}))return;if(!await this.hasSeriesReferences(A))await this.entityService.deleteEntity({entityType:"series",id:Q}),this.logger.debug(`Deleted orphaned series: ${A}`)}async hasSeriesReferences(A){let Q=this.entityService.getEntityTypes();for(let w of Q){if(w==="series")continue;if((await this.entityService.listEntities({entityType:w,options:{filter:{metadata:{seriesName:A}},limit:1}})).length>0)return!0}return!1}async collectSeriesNames(){let A=new Set,Q=this.entityService.getEntityTypes();for(let w of Q){if(w==="series")continue;let B=await this.entityService.listEntities({entityType:w});for(let $ of B){let f=nj($);if(f)A.add(f)}}return A}createSeriesContent(A){let Q={title:A,slug:Z1(A)};return F7("",Q)}}wA();N0();var ZWw=Z.object({entityType:Z.literal("series"),query:Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional()})}),WWw=Z.object({type:Z.enum(["list","detail"]),seriesName:Z.string().optional()});function HWw(A){let Q=WWw.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let w=ZWw.safeParse(A);if(w.success){let{query:B}=w.data;if(B.id)return{type:"detail",seriesSlug:B.id};return{type:"list"}}throw Error('Invalid series query format. Expected { type: "list"|"detail" } or { entityType: "series", query: { id?: string } }')}function Es1(A){let Q=o2(A.content,_U);return Of0.parse({...A,frontmatter:Q.metadata})}class fr0{logger;id="series:entities";name="Series DataSource";description="Fetches series list and detail data";constructor(A){this.logger=A}async fetch(A,Q,w){let B=HWw(A),$=w.entityService;if(B.type==="list")return this.fetchSeriesList(Q,$);if(B.seriesName)return this.fetchSeriesDetail(B.seriesName,Q,$);if(B.seriesSlug)return this.fetchSeriesDetailBySlug(B.seriesSlug,Q,$);throw Error("Invalid series query: must specify seriesName or slug for detail")}async fetchSeriesList(A,Q){let w=await Q.listEntities({entityType:"series"}),B=await this.countEntitiesPerSeries(Q),$=w.map((f)=>{let Y=Es1(f),X=VF.parseBody(f.content);return{...Y,description:X.description,postCount:B.get(f.metadata.title)??0}});return this.logger.debug(`Found ${$.length} series entities`),A.parse({series:$})}async fetchSeriesDetail(A,Q,w,B){if(!B)B=(await w.listEntities({entityType:"series",options:{filter:{metadata:{title:A}}}}))[0];if(!B)throw Error(`Series not found: ${A}`);let $=Es1(B),f=VF.parseBody(B.content),Y=await this.getSeriesMembers(A,w);return this.logger.debug(`Found ${Y.length} entities in series "${A}"`),Q.parse({seriesName:A,posts:Y,series:{...$,description:f.description,postCount:Y.length},description:f.description})}async fetchSeriesDetailBySlug(A,Q,w){let $=(await w.listEntities({entityType:"series",options:{filter:{metadata:{slug:A}}}}))[0];if(!$)throw Error(`Series not found with slug: ${A}`);return this.fetchSeriesDetail($.metadata.title,Q,w,$)}async countEntitiesPerSeries(A){let Q=new Map,w=A.getEntityTypes();for(let B of w){if(B==="series")continue;let $=await A.listEntities({entityType:B});for(let f of $){let Y=nj(f);if(Y)Q.set(Y,(Q.get(Y)??0)+1)}}return Q}async getSeriesMembers(A,Q){let w=[],B=Q.getEntityTypes();for(let $ of B){if($==="series")continue;let f=await Q.listEntities({entityType:$,options:{filter:{metadata:{seriesName:A}}}});w.push(...f)}return w.sort(ys1),w}}wA();N0();xX();var KWw=Z.object({prompt:Z.string().optional(),title:Z.string().optional(),seriesId:Z.string().optional()}),UWw=Z.object({title:Z.string().optional(),excerpt:Z.string().optional()});class Rf0{logger;context;constructor(A,Q){this.logger=A,this.context=Q}async process(A){let Q=A.seriesId??A.title;if(!Q)return{success:!1,error:"seriesId or title required"};let w=await this.context.entityService.getEntity({entityType:"series",id:Q});if(!w)return{success:!1,error:`Series not found: ${Q}`};let B=await this.gatherMemberSummaries(w.metadata.title);if(B.length===0)return{success:!1,error:`No members found in series: ${w.metadata.title}`};let $=A.prompt??`Series name: ${w.metadata.title}
5991
5991
 
5992
5992
  Content in this series:
5993
5993
  ${B.join(`
@@ -5999,7 +5999,7 @@ Your task is to write a series description (2-3 sentences) that:
5999
5999
  3. Is engaging and makes readers want to explore the content
6000
6000
  4. Works well as a series overview on a website
6001
6001
 
6002
- Be concise and focus on what makes this series unique and valuable.`});async function is1({entity:A,config:Q}){let w=bF.parse(A),B=VF.parseBody(w.content);return{$type:"ai.rizom.brain.series",title:w.metadata.title,slug:w.metadata.slug,...B.description&&{description:B.description},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"series",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function Yr0(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:L6["ai.rizom.brain.series"],validate:!1,buildRecord:is1}}var ds1={name:"@brains/series",version:"0.2.0-alpha.142",description:"Cross-content series \u2014 auto-derived from entities with seriesName metadata",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/entity-service":"workspace:*","@brains/job-queue":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var ns1=Z.discriminatedUnion("mode",[Z.object({mode:Z.literal("derive"),reason:Z.string().optional()}),Z.object({mode:Z.literal("source"),entityId:Z.string(),entityType:Z.string(),seriesName:Z.string().optional(),previousSeriesName:Z.string().optional()})]);class Xr0 extends nQ{entityType="series";schema=bF;adapter=VF;manager;unregisterAtprotoProjection;constructor(){super("series",ds1,{},L7)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new Rf0(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...ls1(),description:ps1}}getDataSources(){return[new fr0(this.logger.child("SeriesDataSource"))]}getDerivedEntityProjections(A){return[{id:"series-projection",targetType:"series",job:{type:"series:project",handler:this.createSeriesProjectionHandler(A)},initialSync:{jobData:{mode:"derive",reason:"initial-sync"},jobOptions:this.getSyncProjectionJobOptions("initial-sync")},sourceChange:{sourceTypes:["*"],events:["entity:created","entity:updated","entity:deleted"],requireInitialSync:!0,jobData:(Q)=>{if(Q.entityType==="series")return null;if(!Q.entity)return null;let w=nj(Q.entity),B=xf0(Q.previousMetadata).seriesName;if(!w&&!B)return null;return{mode:"source",entityId:Q.entity.id,entityType:Q.entity.entityType,...w?{seriesName:w}:{},...B&&B!==w?{previousSeriesName:B}:{}}},jobOptions:(Q)=>{if(!Q.entity)return;return this.getSourceProjectionJobOptions(Q.entity)}}}]}async onRegister(A){this.manager=new $r0(A.entityService,this.logger.child("SeriesManager")),this.unregisterAtprotoProjection=A8.getInstance().register(Yr0())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}createSeriesProjectionHandler(A){return{process:async(Q)=>{let w=ns1.parse(Q);if(w.mode==="derive")return await this.projectAll(A),{success:!0};let B=await A.entityService.getEntity({entityType:w.entityType,id:w.entityId});if(B)await this.projectSource(B,w.previousSeriesName);else{let $=this.requireManager();for(let f of[w.seriesName,w.previousSeriesName])if(f)await $.cleanupOrphanedSeries(f)}return{success:!0}},validateAndParse:(Q)=>{let w=ns1.safeParse(Q??{});return w.success?w.data:null}}}requireManager(){if(!this.manager)throw Error("SeriesPlugin not registered");return this.manager}getSyncProjectionJobOptions(A){return{source:this.id,deduplication:"coalesce",deduplicationKey:`series-sync:${A}`,metadata:{operationType:"data_processing",operationTarget:"series"}}}getSourceProjectionJobOptions(A){return{source:this.id,deduplication:"coalesce",deduplicationKey:`series-source:${A.entityType}:${A.id}`,metadata:{operationType:"data_processing",operationTarget:`series:${A.entityType}:${A.id}`}}}async projectSource(A,Q){await this.requireManager().handleEntityChange(A,Q)}async projectAll(A){await this.requireManager().syncAllSeries();let Q=new Rf0(this.logger.child("SeriesGenerationHandler"),A),w=await A.entityService.listEntities({entityType:"series"});for(let B of w)try{if(!this.adapter.parseBody(B.content).description)this.logger.info(`Generating description for series: ${B.metadata.title}`),await Q.process({seriesId:B.id})}catch($){this.logger.error(`Failed to generate description for series: ${B.id}`,{error:$})}}}function Zr0(){return new Xr0}wA();N0();wA();K2();N0();wA();var rs1=Z.enum(["generating","draft","queued","published","failed"]),os1=Z.enum(["generating","draft","queued","published","failed"]),Wr0="publishedAt is required when deck status is published",Hr0=(A)=>A.status==="published"&&!A.publishedAt,Kr0=(A)=>{if(Hr0(A))throw Error(Wr0)},dG=Z.object({title:Z.string(),slug:Z.string().optional(),description:Z.string().optional(),author:Z.string().optional(),status:rs1,publishedAt:Z.string().datetime().optional(),event:Z.string().optional(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional()}),AeB=Z.object({title:Z.string(),description:Z.string().optional(),status:rs1,publishedAt:Z.string().datetime().optional(),coverImageId:Z.string().optional(),slug:Z.string(),error:Z.string().optional()}).superRefine((A,Q)=>{if(!Hr0(A))return;Q.addIssue({code:Z.ZodIssueCode.custom,path:["publishedAt"],message:Wr0})}),FWw=Z.object({title:Z.string(),description:Z.string().optional(),status:os1,publishedAt:Z.string().datetime().optional(),coverImageId:Z.string().optional(),slug:Z.string(),error:Z.string().optional()}).superRefine((A,Q)=>{if(!Hr0(A))return;Q.addIssue({code:"custom",path:["publishedAt"],message:Wr0})}),LWw=Z.object({title:Z.string(),slug:Z.string().optional(),description:Z.string().optional(),author:Z.string().optional(),status:os1,publishedAt:Z.string().datetime().optional(),event:Z.string().optional(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional()}),og=LQ.extend({entityType:Z.literal("deck"),metadata:FWw}),vf0=og.extend({frontmatter:LWw,body:Z.string(),ogImageUrl:Z.string().optional()}),xr=vf0.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});class Ur0 extends C2{constructor(){super({entityType:"deck",purpose:"A slide-deck presentation.",schema:og,frontmatterSchema:dG,supportsCoverImage:!0})}validateSlideStructure(A){if(!/^---$/gm.test(A))throw Error("Invalid deck: markdown must contain slide separators (---) to be a valid presentation")}toMarkdown(A){let Q=this.extractBody(A.content);this.validateSlideStructure(Q);let w=this.parseFrontMatter(A.content,dG);Kr0(w);let B={...w,slug:w.slug??A.metadata.slug};return this.buildMarkdown(Q,B)}fromMarkdown(A){let Q=this.parseFrontmatter(A),w=this.extractBody(A);Kr0(Q),this.validateSlideStructure(w);let B=Q.slug??Z1(Q.title),$=Q.status;return{entityType:"deck",content:A,metadata:{slug:B,title:Q.title,description:Q.description,status:$,publishedAt:Q.publishedAt,coverImageId:Q.coverImageId}}}generateTitle(A){return A.metadata.title}generateSummary(A){if(A.metadata.description)return A.metadata.description;return`Presentation: ${A.metadata.title}`}generateFrontMatter(A){return this.toMarkdown(A)}buildStub(A){let Q={title:A.title,slug:A.id,status:"generating"};return{content:this.buildMarkdown(`---
6002
+ Be concise and focus on what makes this series unique and valuable.`});async function is1({entity:A,config:Q}){let w=bF.parse(A),B=VF.parseBody(w.content);return{$type:"ai.rizom.brain.series",title:w.metadata.title,slug:w.metadata.slug,...B.description&&{description:B.description},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"series",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function Yr0(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:L6["ai.rizom.brain.series"],validate:!1,buildRecord:is1}}var ds1={name:"@brains/series",version:"0.2.0-alpha.143",description:"Cross-content series \u2014 auto-derived from entities with seriesName metadata",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/entity-service":"workspace:*","@brains/job-queue":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var ns1=Z.discriminatedUnion("mode",[Z.object({mode:Z.literal("derive"),reason:Z.string().optional()}),Z.object({mode:Z.literal("source"),entityId:Z.string(),entityType:Z.string(),seriesName:Z.string().optional(),previousSeriesName:Z.string().optional()})]);class Xr0 extends nQ{entityType="series";schema=bF;adapter=VF;manager;unregisterAtprotoProjection;constructor(){super("series",ds1,{},L7)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new Rf0(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...ls1(),description:ps1}}getDataSources(){return[new fr0(this.logger.child("SeriesDataSource"))]}getDerivedEntityProjections(A){return[{id:"series-projection",targetType:"series",job:{type:"series:project",handler:this.createSeriesProjectionHandler(A)},initialSync:{jobData:{mode:"derive",reason:"initial-sync"},jobOptions:this.getSyncProjectionJobOptions("initial-sync")},sourceChange:{sourceTypes:["*"],events:["entity:created","entity:updated","entity:deleted"],requireInitialSync:!0,jobData:(Q)=>{if(Q.entityType==="series")return null;if(!Q.entity)return null;let w=nj(Q.entity),B=xf0(Q.previousMetadata).seriesName;if(!w&&!B)return null;return{mode:"source",entityId:Q.entity.id,entityType:Q.entity.entityType,...w?{seriesName:w}:{},...B&&B!==w?{previousSeriesName:B}:{}}},jobOptions:(Q)=>{if(!Q.entity)return;return this.getSourceProjectionJobOptions(Q.entity)}}}]}async onRegister(A){this.manager=new $r0(A.entityService,this.logger.child("SeriesManager")),this.unregisterAtprotoProjection=A8.getInstance().register(Yr0())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}createSeriesProjectionHandler(A){return{process:async(Q)=>{let w=ns1.parse(Q);if(w.mode==="derive")return await this.projectAll(A),{success:!0};let B=await A.entityService.getEntity({entityType:w.entityType,id:w.entityId});if(B)await this.projectSource(B,w.previousSeriesName);else{let $=this.requireManager();for(let f of[w.seriesName,w.previousSeriesName])if(f)await $.cleanupOrphanedSeries(f)}return{success:!0}},validateAndParse:(Q)=>{let w=ns1.safeParse(Q??{});return w.success?w.data:null}}}requireManager(){if(!this.manager)throw Error("SeriesPlugin not registered");return this.manager}getSyncProjectionJobOptions(A){return{source:this.id,deduplication:"coalesce",deduplicationKey:`series-sync:${A}`,metadata:{operationType:"data_processing",operationTarget:"series"}}}getSourceProjectionJobOptions(A){return{source:this.id,deduplication:"coalesce",deduplicationKey:`series-source:${A.entityType}:${A.id}`,metadata:{operationType:"data_processing",operationTarget:`series:${A.entityType}:${A.id}`}}}async projectSource(A,Q){await this.requireManager().handleEntityChange(A,Q)}async projectAll(A){await this.requireManager().syncAllSeries();let Q=new Rf0(this.logger.child("SeriesGenerationHandler"),A),w=await A.entityService.listEntities({entityType:"series"});for(let B of w)try{if(!this.adapter.parseBody(B.content).description)this.logger.info(`Generating description for series: ${B.metadata.title}`),await Q.process({seriesId:B.id})}catch($){this.logger.error(`Failed to generate description for series: ${B.id}`,{error:$})}}}function Zr0(){return new Xr0}wA();N0();wA();K2();N0();wA();var rs1=Z.enum(["generating","draft","queued","published","failed"]),os1=Z.enum(["generating","draft","queued","published","failed"]),Wr0="publishedAt is required when deck status is published",Hr0=(A)=>A.status==="published"&&!A.publishedAt,Kr0=(A)=>{if(Hr0(A))throw Error(Wr0)},dG=Z.object({title:Z.string(),slug:Z.string().optional(),description:Z.string().optional(),author:Z.string().optional(),status:rs1,publishedAt:Z.string().datetime().optional(),event:Z.string().optional(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional()}),AeB=Z.object({title:Z.string(),description:Z.string().optional(),status:rs1,publishedAt:Z.string().datetime().optional(),coverImageId:Z.string().optional(),slug:Z.string(),error:Z.string().optional()}).superRefine((A,Q)=>{if(!Hr0(A))return;Q.addIssue({code:Z.ZodIssueCode.custom,path:["publishedAt"],message:Wr0})}),FWw=Z.object({title:Z.string(),description:Z.string().optional(),status:os1,publishedAt:Z.string().datetime().optional(),coverImageId:Z.string().optional(),slug:Z.string(),error:Z.string().optional()}).superRefine((A,Q)=>{if(!Hr0(A))return;Q.addIssue({code:"custom",path:["publishedAt"],message:Wr0})}),LWw=Z.object({title:Z.string(),slug:Z.string().optional(),description:Z.string().optional(),author:Z.string().optional(),status:os1,publishedAt:Z.string().datetime().optional(),event:Z.string().optional(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional()}),og=LQ.extend({entityType:Z.literal("deck"),metadata:FWw}),vf0=og.extend({frontmatter:LWw,body:Z.string(),ogImageUrl:Z.string().optional()}),xr=vf0.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});class Ur0 extends C2{constructor(){super({entityType:"deck",purpose:"A slide-deck presentation.",schema:og,frontmatterSchema:dG,supportsCoverImage:!0})}validateSlideStructure(A){if(!/^---$/gm.test(A))throw Error("Invalid deck: markdown must contain slide separators (---) to be a valid presentation")}toMarkdown(A){let Q=this.extractBody(A.content);this.validateSlideStructure(Q);let w=this.parseFrontMatter(A.content,dG);Kr0(w);let B={...w,slug:w.slug??A.metadata.slug};return this.buildMarkdown(Q,B)}fromMarkdown(A){let Q=this.parseFrontmatter(A),w=this.extractBody(A);Kr0(Q),this.validateSlideStructure(w);let B=Q.slug??Z1(Q.title),$=Q.status;return{entityType:"deck",content:A,metadata:{slug:B,title:Q.title,description:Q.description,status:$,publishedAt:Q.publishedAt,coverImageId:Q.coverImageId}}}generateTitle(A){return A.metadata.title}generateSummary(A){if(A.metadata.description)return A.metadata.description;return`Presentation: ${A.metadata.title}`}generateFrontMatter(A){return this.toMarkdown(A)}buildStub(A){let Q={title:A.title,slug:A.id,status:"generating"};return{content:this.buildMarkdown(`---
6003
6003
  `,Q),metadata:{title:A.title,slug:A.id,status:"generating"}}}}var Rr=new Ur0;N0();NB();var kWw=Z.object({markdown:Z.string().describe("Markdown content with slide separators (---)"),deck:xr.optional()}),Dr0=i1({name:"deck-detail",description:"Render a presentation deck as Reveal.js slides",schema:kWw,dataSourceId:"decks:entities",requiredPermission:"public",layout:{component:yp0,fullscreen:!0}});NB();N0();var Gr0=Z.object({decks:Z.array(vf0)}),zr0=Z.object({decks:Z.array(xr),pageTitle:Z.string().optional(),pageLabel:Z.string().optional()});import{jsxDEV as qr0}from"preact/jsx-dev-runtime";var _Ww="Presentations",br0=({decks:A,pageLabel:Q})=>{let w=A.map(($)=>({id:$.id,url:$.url,title:$.frontmatter.title,date:$.frontmatter.publishedAt??$.created,description:$.frontmatter.description}));return qr0("div",{className:"deck-list bg-theme",children:qr0("div",{className:"container mx-auto max-w-[1100px] px-6 py-16 md:px-12 md:py-24",children:qr0(Fn,{label:Q&&Q!=="Decks"?Q:_Ww,items:w},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)};o5();class hf0 extends G6{constructor(){super(Gr0,{title:"Deck List",mappings:[{key:"decks",label:"Decks",type:"array",itemType:"object"}]})}}var Vr0=i1({name:"deck-list",description:"List view of all presentation decks",schema:zr0,dataSourceId:"decks:entities",requiredPermission:"public",formatter:new hf0,layout:{component:br0}});N0();wA();var NWw=Z.object({title:Z.string().max(80).describe("A short, punchy title (2-5 words) that's memorable and evocative"),content:Z.string().describe("Full slide deck content in markdown format with slide separators (---). Each slide should have a header and focused content."),description:Z.string().describe("A concise 1-2 sentence summary that captures the essence of the talk")}),ss1=i1({name:"decks:generation",description:"Template for AI to generate complete slide decks from prompts",schema:NWw,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are creating slide decks in a distinctive voice that blends philosophy, technology, and culture.
6004
6004
 
6005
6005
  Your task is to generate a complete slide deck based on the user's prompt.
@@ -6307,7 +6307,7 @@ ${X}`,templateName:"decks:description"})).description,await this.reportProgress(
6307
6307
  color: var(--carousel-accent);
6308
6308
  font-weight: 600;
6309
6309
  }
6310
- `}},void 0,!1,void 0,this),$.map((H,K)=>l4("section",{className:`deck-carousel-slide${K===0?" is-cover":""}`,children:[l4("header",{className:"deck-carousel-header",children:l4("span",{className:"deck-carousel-wordmark","aria-label":w??Q,children:[l4("span",{className:"wm-primary",children:f.primary},void 0,!1,void 0,this),f.secondary!==void 0&&l4(RWw,{children:[l4("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),l4("span",{className:"wm-secondary",children:f.secondary},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),l4("div",{className:"deck-carousel-body",children:l4("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:W(H.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),l4("footer",{className:"deck-carousel-footer",children:[l4("span",{className:"deck-carousel-footer-meta",children:B??Q},void 0,!1,void 0,this),l4("span",{className:"deck-carousel-counter","aria-label":`Slide ${K+1} of ${Y}`,children:[l4("span",{className:"deck-carousel-counter-current",children:String(K+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",l4("span",{children:X},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},K,!0,void 0,this))]},void 0,!0,void 0,this)}import{mkdtemp as vWw,rm as hWw}from"fs/promises";import{tmpdir as CWw}from"os";import{join as gWw}from"path";S9();K2();var yWw=26214400,EWw=60000,Qa1=20;class Fr0{metadata={outputEntityType:"document"};context;renderPdf;getThemeMode;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??kU,this.getThemeMode=Q.getThemeMode??(async()=>"dark")}async resolve(A){if(A.sourceEntityType!=="deck")return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let w=TWw(Q,{brandLabel:this.resolveBrandLabel()});if(w.slides.length>Qa1)throw Error(`Refusing to render carousel with ${w.slides.length} slides; maxSlides=${Qa1}`);let B=await this.getThemeMode(),$=await vWw(gWw(CWw(),"brain-deck-carousel-"));try{let f=await vZ({outputDir:$,mediaPath:`/_media/carousel/${Q.id}`,template:Aa1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:B},themeCSS:this.context.themeCSS}),Y=await hZ({rootDir:$});try{return{type:"document",data:await this.renderPdf(Y.urlFor(f.urlPath),{maxBytes:yWw,timeoutMs:EWw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${SWw(Q)}-carousel.pdf`}}finally{await Y.close()}}finally{await hWw($,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name;return Q.length>0?Q:void 0}}function TWw(A,Q={}){let{frontmatter:w,content:B}=j6(A.content),$=typeof w.title==="string"?w.title:A.metadata.title,f=typeof w.event==="string"&&w.event.length>0?w.event:void 0,Y=B.split(/^---$/gm).map((X)=>X.trim()).filter((X)=>X.length>0).map((X)=>({markdown:X}));return{title:$,slides:Y,...Q.brandLabel?{brandLabel:Q.brandLabel}:{},...f?{eyebrow:f}:{}}}function SWw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.title)}N0();import{jsxDEV as cWw}from"preact/jsx-dev-runtime";var Cf0="og-image",mWw="decks:og-image",wa1=Z.object({title:Z.string().min(1),description:Z.string().optional(),event:Z.string().optional(),brandLabel:Z.string().optional(),slideCount:Z.number().int().positive().optional(),coverImageUrl:Z.string().optional()}),Ba1={name:mWw,pluginId:"decks",schema:wa1,renderers:{image:uWw}};function uWw(A){let Q=wa1.parse(A),w=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return cWw(cq,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Deck",title:Q.title,subtitle:Q.description,meta:[Q.event],tag:w},void 0,!1,void 0,this)}S9();K2();class Lr0{metadata={outputEntityType:"image",targetField:"ogImageId"};context;deps;constructor(A,Q={}){this.context=A,this.deps=Q}async resolve(A){if(A.sourceEntityType!=="deck"||A.attachmentType!==Cf0)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:B}=j6(Q.content),$=dG.parse(w),f=lWw(B),Y=this.resolveBrandLabel(),X=await this.resolveCoverImageUrl($.coverImageId),W={title:$.title,...$.description?{description:$.description}:{},...$.event?{event:$.event}:{},...f?{slideCount:f}:{},...X?{coverImageUrl:X}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await ij({mediaPath:`/_media/og/deck/${Q.id}`,template:Ba1,content:W,title:W.title,themeMode:"dark",themeCSS:this.context.themeCSS,tmpPrefix:"brain-deck-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${pWw(Q)}-og.png`}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){if(!A)return;let Q=await this.context.entityService.getEntity({entityType:"image",id:A});return Q?.content.startsWith("data:image/")?Q.content:void 0}}function lWw(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function pWw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.title)}wA();async function $a1({entity:A,config:Q}){let w=og.parse(A),B=o2(w.content,dG),$=B.metadata;return{$type:"ai.rizom.brain.deck",title:$.title,...$.slug&&{slug:$.slug},...$.description&&{description:$.description},body:B.content,format:"text/markdown",...$.author&&{author:$.author},...$.event&&{event:$.event},...$.publishedAt&&{publishedAt:$.publishedAt},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"deck",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function kr0(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:L6["ai.rizom.brain.deck"],validate:!1,buildRecord:$a1}}var fa1={name:"@brains/decks",version:"0.2.0-alpha.142",description:"Presentation decks plugin for creating and viewing slide presentations",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/image":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/site-info":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var dWw=Z.object({prompt:Z.string(),event:Z.string().optional()}),nWw=Z.object({title:Z.string(),content:Z.string()});class _r0 extends nQ{deps;entityType=Rr.entityType;schema=Rr.schema;adapter=Rr;unregisterCarouselAttachmentProvider;unregisterOgImageAttachmentProvider;unregisterAtprotoProjection;constructor(A={}){super("decks",fa1,{},L7);this.deps=A}createGenerationHandler(A){return new Jr0(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":Dr0,"deck-list":Vr0,generation:ss1,description:as1}}getDataSources(){return[new Ir0(this.logger)]}getEntityTypeConfig(){return{weight:1.5}}async onRegister(A){this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.registerCarouselAttachmentProvider(A),this.registerOgImageAttachmentProvider(A),this.registerEvalHandlers(A),this.unregisterAtprotoProjection=A8.getInstance().register(kr0()),this.logger.info("Decks plugin registered")}async onShutdown(){this.unregisterCarouselAttachmentProvider?.(),this.unregisterCarouselAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}deferPublishRegistration(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"deck",provider:{name:"internal",publish:async()=>({id:"internal"})},config:{executionMode:"provider"}}}),{success:!0}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:w,entityId:B}=Q.payload;if(w!=="deck")return{success:!0};try{let $=await A.entityService.getEntity({entityType:"deck",id:B});if(!$)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:`Deck not found: ${B}`}}),{success:!0};if($.metadata.status==="published")return{success:!0};let f=new Date().toISOString(),Y={...$,metadata:{...$.metadata,status:"published",publishedAt:f}};await A.entityService.updateEntity({entity:{...Y,content:this.adapter.toMarkdown(Y)}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:w,entityId:B,result:{id:B}}})}catch($){await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:mA($)}})}return{success:!0}})}registerCarouselAttachmentProvider(A){let Q={...this.deps,getThemeMode:this.deps.getThemeMode??(async()=>{try{return(await kr(A.entityService)).themeMode??"dark"}catch{return"dark"}})};this.unregisterCarouselAttachmentProvider=A.attachments.register("deck",ts1,new Fr0(A,Q))}registerOgImageAttachmentProvider(A){this.unregisterOgImageAttachmentProvider=A.attachments.register("deck",Cf0,new Lr0(A))}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let w=dWw.parse(Q);return A.ai.generate({prompt:`${w.prompt}${w.event?`
6310
+ `}},void 0,!1,void 0,this),$.map((H,K)=>l4("section",{className:`deck-carousel-slide${K===0?" is-cover":""}`,children:[l4("header",{className:"deck-carousel-header",children:l4("span",{className:"deck-carousel-wordmark","aria-label":w??Q,children:[l4("span",{className:"wm-primary",children:f.primary},void 0,!1,void 0,this),f.secondary!==void 0&&l4(RWw,{children:[l4("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),l4("span",{className:"wm-secondary",children:f.secondary},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),l4("div",{className:"deck-carousel-body",children:l4("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:W(H.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),l4("footer",{className:"deck-carousel-footer",children:[l4("span",{className:"deck-carousel-footer-meta",children:B??Q},void 0,!1,void 0,this),l4("span",{className:"deck-carousel-counter","aria-label":`Slide ${K+1} of ${Y}`,children:[l4("span",{className:"deck-carousel-counter-current",children:String(K+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",l4("span",{children:X},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},K,!0,void 0,this))]},void 0,!0,void 0,this)}import{mkdtemp as vWw,rm as hWw}from"fs/promises";import{tmpdir as CWw}from"os";import{join as gWw}from"path";S9();K2();var yWw=26214400,EWw=60000,Qa1=20;class Fr0{metadata={outputEntityType:"document"};context;renderPdf;getThemeMode;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??kU,this.getThemeMode=Q.getThemeMode??(async()=>"dark")}async resolve(A){if(A.sourceEntityType!=="deck")return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let w=TWw(Q,{brandLabel:this.resolveBrandLabel()});if(w.slides.length>Qa1)throw Error(`Refusing to render carousel with ${w.slides.length} slides; maxSlides=${Qa1}`);let B=await this.getThemeMode(),$=await vWw(gWw(CWw(),"brain-deck-carousel-"));try{let f=await vZ({outputDir:$,mediaPath:`/_media/carousel/${Q.id}`,template:Aa1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:B},themeCSS:this.context.themeCSS}),Y=await hZ({rootDir:$});try{return{type:"document",data:await this.renderPdf(Y.urlFor(f.urlPath),{maxBytes:yWw,timeoutMs:EWw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${SWw(Q)}-carousel.pdf`}}finally{await Y.close()}}finally{await hWw($,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name;return Q.length>0?Q:void 0}}function TWw(A,Q={}){let{frontmatter:w,content:B}=j6(A.content),$=typeof w.title==="string"?w.title:A.metadata.title,f=typeof w.event==="string"&&w.event.length>0?w.event:void 0,Y=B.split(/^---$/gm).map((X)=>X.trim()).filter((X)=>X.length>0).map((X)=>({markdown:X}));return{title:$,slides:Y,...Q.brandLabel?{brandLabel:Q.brandLabel}:{},...f?{eyebrow:f}:{}}}function SWw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.title)}N0();import{jsxDEV as cWw}from"preact/jsx-dev-runtime";var Cf0="og-image",mWw="decks:og-image",wa1=Z.object({title:Z.string().min(1),description:Z.string().optional(),event:Z.string().optional(),brandLabel:Z.string().optional(),slideCount:Z.number().int().positive().optional(),coverImageUrl:Z.string().optional()}),Ba1={name:mWw,pluginId:"decks",schema:wa1,renderers:{image:uWw}};function uWw(A){let Q=wa1.parse(A),w=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return cWw(cq,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Deck",title:Q.title,subtitle:Q.description,meta:[Q.event],tag:w},void 0,!1,void 0,this)}S9();K2();class Lr0{metadata={outputEntityType:"image",targetField:"ogImageId"};context;deps;constructor(A,Q={}){this.context=A,this.deps=Q}async resolve(A){if(A.sourceEntityType!=="deck"||A.attachmentType!==Cf0)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:B}=j6(Q.content),$=dG.parse(w),f=lWw(B),Y=this.resolveBrandLabel(),X=await this.resolveCoverImageUrl($.coverImageId),W={title:$.title,...$.description?{description:$.description}:{},...$.event?{event:$.event}:{},...f?{slideCount:f}:{},...X?{coverImageUrl:X}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await ij({mediaPath:`/_media/og/deck/${Q.id}`,template:Ba1,content:W,title:W.title,themeMode:"dark",themeCSS:this.context.themeCSS,tmpPrefix:"brain-deck-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${pWw(Q)}-og.png`}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){if(!A)return;let Q=await this.context.entityService.getEntity({entityType:"image",id:A});return Q?.content.startsWith("data:image/")?Q.content:void 0}}function lWw(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function pWw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.title)}wA();async function $a1({entity:A,config:Q}){let w=og.parse(A),B=o2(w.content,dG),$=B.metadata;return{$type:"ai.rizom.brain.deck",title:$.title,...$.slug&&{slug:$.slug},...$.description&&{description:$.description},body:B.content,format:"text/markdown",...$.author&&{author:$.author},...$.event&&{event:$.event},...$.publishedAt&&{publishedAt:$.publishedAt},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"deck",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function kr0(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:L6["ai.rizom.brain.deck"],validate:!1,buildRecord:$a1}}var fa1={name:"@brains/decks",version:"0.2.0-alpha.143",description:"Presentation decks plugin for creating and viewing slide presentations",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/image":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/site-info":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var dWw=Z.object({prompt:Z.string(),event:Z.string().optional()}),nWw=Z.object({title:Z.string(),content:Z.string()});class _r0 extends nQ{deps;entityType=Rr.entityType;schema=Rr.schema;adapter=Rr;unregisterCarouselAttachmentProvider;unregisterOgImageAttachmentProvider;unregisterAtprotoProjection;constructor(A={}){super("decks",fa1,{},L7);this.deps=A}createGenerationHandler(A){return new Jr0(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":Dr0,"deck-list":Vr0,generation:ss1,description:as1}}getDataSources(){return[new Ir0(this.logger)]}getEntityTypeConfig(){return{weight:1.5}}async onRegister(A){this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.registerCarouselAttachmentProvider(A),this.registerOgImageAttachmentProvider(A),this.registerEvalHandlers(A),this.unregisterAtprotoProjection=A8.getInstance().register(kr0()),this.logger.info("Decks plugin registered")}async onShutdown(){this.unregisterCarouselAttachmentProvider?.(),this.unregisterCarouselAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}deferPublishRegistration(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"deck",provider:{name:"internal",publish:async()=>({id:"internal"})},config:{executionMode:"provider"}}}),{success:!0}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:w,entityId:B}=Q.payload;if(w!=="deck")return{success:!0};try{let $=await A.entityService.getEntity({entityType:"deck",id:B});if(!$)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:`Deck not found: ${B}`}}),{success:!0};if($.metadata.status==="published")return{success:!0};let f=new Date().toISOString(),Y={...$,metadata:{...$.metadata,status:"published",publishedAt:f}};await A.entityService.updateEntity({entity:{...Y,content:this.adapter.toMarkdown(Y)}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:w,entityId:B,result:{id:B}}})}catch($){await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:mA($)}})}return{success:!0}})}registerCarouselAttachmentProvider(A){let Q={...this.deps,getThemeMode:this.deps.getThemeMode??(async()=>{try{return(await kr(A.entityService)).themeMode??"dark"}catch{return"dark"}})};this.unregisterCarouselAttachmentProvider=A.attachments.register("deck",ts1,new Fr0(A,Q))}registerOgImageAttachmentProvider(A){this.unregisterOgImageAttachmentProvider=A.attachments.register("deck",Cf0,new Lr0(A))}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let w=dWw.parse(Q);return A.ai.generate({prompt:`${w.prompt}${w.event?`
6311
6311
 
6312
6312
  Note: This presentation is for "${w.event}".`:""}`,templateName:"decks:generation"})}),A.eval.registerHandler("generateDescription",async(Q)=>{let w=nWw.parse(Q);return A.ai.generate({prompt:`Title: ${w.title}
6313
6313
 
@@ -6464,9 +6464,9 @@ ${w.content}`,templateName:"decks:description"})})}}function hr(){return new _r0
6464
6464
  background: transparent;
6465
6465
  }
6466
6466
 
6467
- `,za1=()=>T5("style",{children:eWw},void 0,!1,void 0,this);import{jsxDEV as v2,Fragment as AHw}from"preact/jsx-dev-runtime";var Sf0=({title:A,description:Q,children:w,detail:B=!1,footer:$=!1,contentClassName:f=""})=>v2(AHw,{children:[v2(lQ,{title:A,description:Q},void 0,!1,void 0,this),v2(za1,{},void 0,!1,void 0,this),v2("div",{className:`docs-handbook${B?" docs-handbook--detail":""}`,children:[v2(Da1,{},void 0,!1,void 0,this),v2("div",{className:`${nG.wrap} ${f}`.trim(),children:[w,$&&v2(Ga1,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),qa1=({docsCount:A,sectionsCount:Q,startDoc:w})=>v2("section",{className:"border-b border-[var(--docs-text)] py-14 md:py-24 md:pb-[72px]",children:[v2("p",{className:`${nG.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),v2("h1",{className:`${nG.display} m-0 max-w-[16ch] text-5xl leading-[1.05] tracking-[-0.02em] md:text-7xl`,children:["Build, run, and publish"," ",v2("em",{className:"text-[var(--docs-accent)]",children:"brains."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v2("p",{className:"mt-8 max-w-[52ch] text-lg leading-[1.65] text-[var(--docs-text-muted)]",children:"Documentation for composing brain models, managing markdown entities, wiring interfaces, and shipping generated sites."},void 0,!1,void 0,this),v2("dl",{className:"mt-10 flex flex-wrap gap-7 docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)] md:mt-14 md:gap-12",children:[v2("div",{children:[v2("strong",{className:"mb-0.5 block font-medium text-[var(--docs-text)]",children:A},void 0,!1,void 0,this),"Documents"]},void 0,!0,void 0,this),v2("div",{children:[v2("strong",{className:"mb-0.5 block font-medium text-[var(--docs-text)]",children:Q},void 0,!1,void 0,this),"Sections"]},void 0,!0,void 0,this),v2("div",{children:[v2("strong",{className:"mb-0.5 block font-medium text-[var(--docs-text)]",children:"April 2026"},void 0,!1,void 0,this),"Updated"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),v2("div",{className:"mt-9 flex flex-wrap gap-3.5",children:[w&&v2("a",{className:nG.primaryButton,href:ag(w),children:"Start reading"},void 0,!1,void 0,this),v2("a",{className:nG.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),ba1=({groups:A})=>v2("aside",{className:"docs-rail sticky top-8 hidden docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)] min-[861px]:block","aria-label":"Documentation sections",children:[v2("p",{className:"m-0 mb-3.5 font-medium text-[var(--docs-text)]",children:"Sections"},void 0,!1,void 0,this),v2("ol",{className:"m-0 list-none p-0",children:A.map((Q,w)=>v2("li",{className:"grid grid-cols-[32px_1fr] gap-2 py-1.5",children:[v2("span",{className:"docs-font-display text-[var(--docs-text-light)] italic",children:[tg(w),"."]},void 0,!0,void 0,this),v2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${Tf0(w)}`,children:Q.section},void 0,!1,void 0,this)]},Q.section,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Va1=({group:A,index:Q})=>v2("article",{className:"mb-16 last:mb-0",id:Tf0(Q),children:[v2("header",{className:"mb-2 grid grid-cols-[36px_auto_1fr] items-baseline gap-x-3 border-b border-[var(--docs-border)] pb-3.5 md:grid-cols-[48px_auto_1fr] md:gap-x-5",children:[v2("span",{className:"text-right docs-font-display text-3xl leading-[1.1] text-[var(--docs-accent)] italic md:text-4xl",children:[tg(Q),"."]},void 0,!0,void 0,this),v2("h2",{className:`${nG.display} m-0 text-3xl leading-[1.1] tracking-[-0.015em] md:text-4xl`,children:A.section},void 0,!1,void 0,this),v2("span",{className:"docs-chapter__leader"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v2("ol",{className:"m-0 list-none p-0",children:A.docs.map((w)=>v2("li",{className:"border-b border-[var(--docs-border-light)] last:border-b-0",children:v2("a",{className:"group block py-[18px] pl-12 md:pl-[68px]",href:ag(w),children:[v2("p",{className:"m-0 text-[22px] leading-[1.2] tracking-[-0.005em] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:w.metadata.title},void 0,!1,void 0,this),w.metadata.description&&v2("p",{className:"mt-1.5 mb-0 max-w-[70ch] text-sm leading-[1.55] text-[var(--docs-text-muted)]",children:w.metadata.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},w.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Ia1=({title:A})=>v2("nav",{className:"mb-8 flex flex-wrap items-baseline gap-2.5 docs-font-label text-[11px] uppercase tracking-[0.06em] text-[var(--docs-text-light)]","aria-label":"Breadcrumb",children:[v2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/",children:"Home"},void 0,!1,void 0,this),v2("span",{children:"/"},void 0,!1,void 0,this),v2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/docs",children:"Docs"},void 0,!1,void 0,this),v2("span",{children:"/"},void 0,!1,void 0,this),v2("span",{children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Ja1=({groups:A,activeGroupIndex:Q,activeSlug:w})=>v2("aside",{className:"docs-detail-rail sticky top-24 hidden max-h-[calc(100vh-120px)] overflow-auto pr-2 min-[861px]:block","aria-label":"Documentation navigation",children:v2("nav",{className:"docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)]",children:[v2("p",{className:"m-0 mb-4 border-b border-[var(--docs-text)] pb-3 text-[11px] uppercase tracking-[0.08em] text-[var(--docs-text-light)]",children:"Documentation"},void 0,!1,void 0,this),v2("ol",{className:"m-0 list-none p-0",children:A.map((B,$)=>{let f=$===Q;return v2("li",{className:f?"mb-[22px]":"mb-3.5",children:[v2("a",{className:`mb-2 flex items-baseline gap-2.5 docs-font-label text-[11px] uppercase leading-[1.4] tracking-[0.06em] transition-colors duration-150 hover:text-[var(--docs-text)] ${f?"text-[var(--docs-text)]":"text-[var(--docs-text-muted)]"}`,href:`/docs#${Tf0($)}`,children:[v2("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[tg($),"."]},void 0,!0,void 0,this)," ",B.section]},void 0,!0,void 0,this),f&&v2("ol",{className:"mt-0.5 list-none p-0",children:B.docs.map((Y)=>{let X=Y.metadata.slug===w;return v2("li",{children:v2("a",{className:`docs-rail__doc relative block py-1.5 docs-font-body text-sm leading-[1.4] tracking-normal transition-[color,padding-left] duration-150 hover:text-[var(--docs-text)] ${X?"pl-3.5 font-medium text-[var(--docs-accent)]":"text-[var(--docs-text-muted)]"}`,href:ag(Y),"aria-current":X?"page":void 0,children:Y.metadata.title},void 0,!1,void 0,this)},Y.id,!1,void 0,this)})},void 0,!1,void 0,this)]},B.section,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Fa1=({prevDoc:A,nextDoc:Q})=>{if(!A&&!Q)return null;return v2("nav",{className:"mt-12 grid grid-cols-1 gap-5 border-t border-[var(--docs-border)] pt-7 md:grid-cols-2","aria-label":"Previous and next docs",children:[A?v2("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] transition-colors duration-150 hover:border-[var(--docs-accent)]",href:ag(A),children:[v2("span",{className:"block docs-font-label text-[10.5px] uppercase tracking-[0.22em] text-[var(--docs-text-light)]",children:"Previous"},void 0,!1,void 0,this),v2("span",{className:"mt-2 block docs-font-display text-[22px] leading-[1.2] text-[var(--docs-heading)] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:["\u2190 ",A.metadata.title]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):v2("span",{},void 0,!1,void 0,this),Q&&v2("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] text-left transition-colors duration-150 hover:border-[var(--docs-accent)] md:text-right",href:ag(Q),children:[v2("span",{className:"block docs-font-label text-[10.5px] uppercase tracking-[0.22em] text-[var(--docs-text-light)]",children:"Next"},void 0,!1,void 0,this),v2("span",{className:"mt-2 block docs-font-display text-[22px] leading-[1.2] text-[var(--docs-heading)] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:[Q.metadata.title," \u2192"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as eg}from"preact/jsx-dev-runtime";var Mr0=({docs:A})=>{let Q=Cr(A),w=Ef0(Q),$=Q.filter((f)=>f.metadata.slug!=="index")[0]??Q[0];return eg(Sf0,{title:"Documentation",description:"Brains documentation",children:[eg(qa1,{docsCount:A.length,sectionsCount:w.length,startDoc:$},void 0,!1,void 0,this),eg("section",{className:"grid items-start gap-10 py-12 md:grid-cols-[200px_minmax(0,1fr)] md:gap-20 md:py-20 md:pb-[120px]",id:"sections",children:[eg(ba1,{groups:w},void 0,!1,void 0,this),eg("div",{children:w.map((f,Y)=>eg(Va1,{group:f,index:Y},f.section,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as CZ}from"preact/jsx-dev-runtime";var Or0=({doc:A,docs:Q,prevDoc:w,nextDoc:B})=>{let $=Ef0(Q.length>0?Q:[A]),f=Cr(Q.length>0?Q:[A]),Y=f.findIndex((W)=>W.metadata.slug===A.metadata.slug),X=Math.max($.findIndex((W)=>W.docs.some((H)=>H.metadata.slug===A.metadata.slug)),0);return CZ(Sf0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[CZ(Ia1,{title:A.metadata.title},void 0,!1,void 0,this),CZ("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[CZ(Ja1,{groups:$,activeGroupIndex:X,activeSlug:A.metadata.slug},void 0,!1,void 0,this),CZ("article",{className:"min-w-0",children:[CZ("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[CZ("p",{className:`${nG.label} m-0 mb-6 flex items-baseline gap-3`,children:[CZ("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[tg(X),"."]},void 0,!0,void 0,this)," ",A.metadata.section,Y>=0?` \xB7 ${Y+1}/${f.length}`:""]},void 0,!0,void 0,this),CZ("h1",{className:`${nG.display} m-0 max-w-[18ch] text-4xl leading-[1.05] tracking-[-0.02em] md:text-6xl`,children:A.metadata.title},void 0,!1,void 0,this),A.metadata.description&&CZ("p",{className:"mt-6 max-w-[56ch] docs-font-display text-[22px] font-[350] leading-[1.5] text-[var(--docs-text-muted)]",children:A.metadata.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),CZ("div",{className:"docs-article__body",children:CZ(V9,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),CZ(Fa1,{prevDoc:w,nextDoc:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};var QHw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),wHw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),BHw=Z.object({title:Z.string(),section:Z.string(),order:Z.number().int(),sourcePath:Z.string(),description:Z.string().optional(),slug:Z.string().optional()}),$Hw=Z.object({title:Z.string(),section:Z.string(),order:Z.number().int(),description:Z.string().optional(),slug:Z.string()}),gr=Z.object({id:Z.string(),entityType:Z.literal("doc"),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:wHw,metadata:$Hw,contentHash:Z.string(),frontmatter:BHw,body:Z.string()}),fHw=Z.object({docs:Z.array(gr),pagination:QHw.nullable(),baseUrl:Z.string().optional()}),YHw=Z.object({doc:gr,docs:Z.array(gr),prevDoc:gr.nullable(),nextDoc:gr.nullable()});function La1(){return{"doc-list":i1({name:"doc-list",description:"Documentation index template",schema:fHw,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:Mr0}}),"doc-detail":i1({name:"doc-detail",description:"Documentation page template",schema:YHw,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:Or0}})}}var ka1={name:"@brains/doc",version:"0.2.0-alpha.142",description:"Documentation entity type \u2014 markdown docs as first-class brain content",dependencies:{"@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","bun-types":"^1.3.14",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class xr0 extends nQ{entityType=gf0.entityType;schema=sg;adapter=gf0;constructor(){super("docs",ka1,{},L7)}getTemplates(){return La1()}getDataSources(){return[new yf0(this.logger.child("DocDataSource"))]}}function yr(){return new xr0}wA();K2();N0();CB();N0();var Rr0=Z.literal("application/pdf"),_a1=Z.enum(["pending","draft","failed"]),vr0=Z.object({title:Z.string().optional(),mimeType:Rr0,filename:Z.string().min(1),pageCount:Z.number().int().min(0).optional(),status:_a1.optional(),processingJobId:Z.string().optional(),processingError:Z.string().optional(),sourceEntityType:Z.string().min(1).optional(),sourceEntityId:Z.string().min(1).optional(),sourceUploadId:Z.string().optional(),sourceFilename:Z.string().optional(),sourceMediaType:Z.string().optional(),attachmentType:Z.string().min(1).optional(),dedupKey:Z.string().min(1).optional()}),Ay=LQ.extend({entityType:Z.literal("document"),content:Z.string().regex(/^data:application\/pdf;base64,.+$/),metadata:vr0});function Er(A){let Q=A.match(/^data:(application\/pdf);base64,(.+)$/i);if(!Q?.[1]||!Q[2])throw Error("Invalid PDF document data URL");return{mimeType:"application/pdf",base64:Q[2]}}function mf0(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function hr0(A){let Q=Buffer.from(A).toString("latin1"),w=0,B=/\/Type\s*\/Pages\b[^]*?\/Count\s+(\d+)|\/Count\s+(\d+)[^]*?\/Type\s*\/Pages\b/g;for(let f of Q.matchAll(B)){let Y=parseInt(f[1]??f[2]??"0",10);if(Y>w)w=Y}if(w>0)return w;return Q.match(/\/Type\s*\/Page(?!\w)/g)?.length??0}class uf0{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=Ay;toMarkdown(A){return A.content}fromMarkdown(A){return Er(A),{entityType:"document",content:A}}extractMetadata(A){return A.metadata}parseFrontMatter(A,Q){return Q.parse({})}generateFrontMatter(A){return""}getBodyTemplate(){return""}createDocumentEntity(A){let{dataUrl:Q,...w}=A,{mimeType:B}=Er(Q);return{entityType:"document",content:Q,metadata:{mimeType:B,...w}}}}var fb=new uf0;async function Io0(A,Q={}){let w=Q.maxBytes??5000000;if(A.byteLength>w)throw Error(`Uploaded PDF is too large for synchronous markdown extraction (${A.byteLength} bytes; max ${w} bytes)`);let $=(await Promise.resolve().then(() => (he1(),ve1))).getDocument({data:new Uint8Array(A),disableFontFace:!1,useSystemFonts:!0,useWorkerFetch:!1}),f=await $.promise;try{let Y=Q.maxPages??50;if(f.numPages>Y)throw Error(`Uploaded PDF has ${f.numPages} pages; maximum supported for synchronous markdown extraction is ${Y}`);let X=[];for(let H=1;H<=f.numPages;H+=1){let D=(await(await f.getPage(H)).getTextContent()).items.flatMap((q)=>("str"in q)?[q.str]:[]).join(" ").replace(/\s+/g," ").trim();if(D.length>0)X.push(D)}let W=X.join(`
6467
+ `,za1=()=>T5("style",{children:eWw},void 0,!1,void 0,this);import{jsxDEV as v2,Fragment as AHw}from"preact/jsx-dev-runtime";var Sf0=({title:A,description:Q,children:w,detail:B=!1,footer:$=!1,contentClassName:f=""})=>v2(AHw,{children:[v2(lQ,{title:A,description:Q},void 0,!1,void 0,this),v2(za1,{},void 0,!1,void 0,this),v2("div",{className:`docs-handbook${B?" docs-handbook--detail":""}`,children:[v2(Da1,{},void 0,!1,void 0,this),v2("div",{className:`${nG.wrap} ${f}`.trim(),children:[w,$&&v2(Ga1,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),qa1=({docsCount:A,sectionsCount:Q,startDoc:w})=>v2("section",{className:"border-b border-[var(--docs-text)] py-14 md:py-24 md:pb-[72px]",children:[v2("p",{className:`${nG.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),v2("h1",{className:`${nG.display} m-0 max-w-[16ch] text-5xl leading-[1.05] tracking-[-0.02em] md:text-7xl`,children:["Build, run, and publish"," ",v2("em",{className:"text-[var(--docs-accent)]",children:"brains."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v2("p",{className:"mt-8 max-w-[52ch] text-lg leading-[1.65] text-[var(--docs-text-muted)]",children:"Documentation for composing brain models, managing markdown entities, wiring interfaces, and shipping generated sites."},void 0,!1,void 0,this),v2("dl",{className:"mt-10 flex flex-wrap gap-7 docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)] md:mt-14 md:gap-12",children:[v2("div",{children:[v2("strong",{className:"mb-0.5 block font-medium text-[var(--docs-text)]",children:A},void 0,!1,void 0,this),"Documents"]},void 0,!0,void 0,this),v2("div",{children:[v2("strong",{className:"mb-0.5 block font-medium text-[var(--docs-text)]",children:Q},void 0,!1,void 0,this),"Sections"]},void 0,!0,void 0,this),v2("div",{children:[v2("strong",{className:"mb-0.5 block font-medium text-[var(--docs-text)]",children:"April 2026"},void 0,!1,void 0,this),"Updated"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),v2("div",{className:"mt-9 flex flex-wrap gap-3.5",children:[w&&v2("a",{className:nG.primaryButton,href:ag(w),children:"Start reading"},void 0,!1,void 0,this),v2("a",{className:nG.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),ba1=({groups:A})=>v2("aside",{className:"docs-rail sticky top-8 hidden docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)] min-[861px]:block","aria-label":"Documentation sections",children:[v2("p",{className:"m-0 mb-3.5 font-medium text-[var(--docs-text)]",children:"Sections"},void 0,!1,void 0,this),v2("ol",{className:"m-0 list-none p-0",children:A.map((Q,w)=>v2("li",{className:"grid grid-cols-[32px_1fr] gap-2 py-1.5",children:[v2("span",{className:"docs-font-display text-[var(--docs-text-light)] italic",children:[tg(w),"."]},void 0,!0,void 0,this),v2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${Tf0(w)}`,children:Q.section},void 0,!1,void 0,this)]},Q.section,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Va1=({group:A,index:Q})=>v2("article",{className:"mb-16 last:mb-0",id:Tf0(Q),children:[v2("header",{className:"mb-2 grid grid-cols-[36px_auto_1fr] items-baseline gap-x-3 border-b border-[var(--docs-border)] pb-3.5 md:grid-cols-[48px_auto_1fr] md:gap-x-5",children:[v2("span",{className:"text-right docs-font-display text-3xl leading-[1.1] text-[var(--docs-accent)] italic md:text-4xl",children:[tg(Q),"."]},void 0,!0,void 0,this),v2("h2",{className:`${nG.display} m-0 text-3xl leading-[1.1] tracking-[-0.015em] md:text-4xl`,children:A.section},void 0,!1,void 0,this),v2("span",{className:"docs-chapter__leader"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v2("ol",{className:"m-0 list-none p-0",children:A.docs.map((w)=>v2("li",{className:"border-b border-[var(--docs-border-light)] last:border-b-0",children:v2("a",{className:"group block py-[18px] pl-12 md:pl-[68px]",href:ag(w),children:[v2("p",{className:"m-0 text-[22px] leading-[1.2] tracking-[-0.005em] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:w.metadata.title},void 0,!1,void 0,this),w.metadata.description&&v2("p",{className:"mt-1.5 mb-0 max-w-[70ch] text-sm leading-[1.55] text-[var(--docs-text-muted)]",children:w.metadata.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},w.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Ia1=({title:A})=>v2("nav",{className:"mb-8 flex flex-wrap items-baseline gap-2.5 docs-font-label text-[11px] uppercase tracking-[0.06em] text-[var(--docs-text-light)]","aria-label":"Breadcrumb",children:[v2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/",children:"Home"},void 0,!1,void 0,this),v2("span",{children:"/"},void 0,!1,void 0,this),v2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/docs",children:"Docs"},void 0,!1,void 0,this),v2("span",{children:"/"},void 0,!1,void 0,this),v2("span",{children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Ja1=({groups:A,activeGroupIndex:Q,activeSlug:w})=>v2("aside",{className:"docs-detail-rail sticky top-24 hidden max-h-[calc(100vh-120px)] overflow-auto pr-2 min-[861px]:block","aria-label":"Documentation navigation",children:v2("nav",{className:"docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)]",children:[v2("p",{className:"m-0 mb-4 border-b border-[var(--docs-text)] pb-3 text-[11px] uppercase tracking-[0.08em] text-[var(--docs-text-light)]",children:"Documentation"},void 0,!1,void 0,this),v2("ol",{className:"m-0 list-none p-0",children:A.map((B,$)=>{let f=$===Q;return v2("li",{className:f?"mb-[22px]":"mb-3.5",children:[v2("a",{className:`mb-2 flex items-baseline gap-2.5 docs-font-label text-[11px] uppercase leading-[1.4] tracking-[0.06em] transition-colors duration-150 hover:text-[var(--docs-text)] ${f?"text-[var(--docs-text)]":"text-[var(--docs-text-muted)]"}`,href:`/docs#${Tf0($)}`,children:[v2("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[tg($),"."]},void 0,!0,void 0,this)," ",B.section]},void 0,!0,void 0,this),f&&v2("ol",{className:"mt-0.5 list-none p-0",children:B.docs.map((Y)=>{let X=Y.metadata.slug===w;return v2("li",{children:v2("a",{className:`docs-rail__doc relative block py-1.5 docs-font-body text-sm leading-[1.4] tracking-normal transition-[color,padding-left] duration-150 hover:text-[var(--docs-text)] ${X?"pl-3.5 font-medium text-[var(--docs-accent)]":"text-[var(--docs-text-muted)]"}`,href:ag(Y),"aria-current":X?"page":void 0,children:Y.metadata.title},void 0,!1,void 0,this)},Y.id,!1,void 0,this)})},void 0,!1,void 0,this)]},B.section,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Fa1=({prevDoc:A,nextDoc:Q})=>{if(!A&&!Q)return null;return v2("nav",{className:"mt-12 grid grid-cols-1 gap-5 border-t border-[var(--docs-border)] pt-7 md:grid-cols-2","aria-label":"Previous and next docs",children:[A?v2("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] transition-colors duration-150 hover:border-[var(--docs-accent)]",href:ag(A),children:[v2("span",{className:"block docs-font-label text-[10.5px] uppercase tracking-[0.22em] text-[var(--docs-text-light)]",children:"Previous"},void 0,!1,void 0,this),v2("span",{className:"mt-2 block docs-font-display text-[22px] leading-[1.2] text-[var(--docs-heading)] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:["\u2190 ",A.metadata.title]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):v2("span",{},void 0,!1,void 0,this),Q&&v2("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] text-left transition-colors duration-150 hover:border-[var(--docs-accent)] md:text-right",href:ag(Q),children:[v2("span",{className:"block docs-font-label text-[10.5px] uppercase tracking-[0.22em] text-[var(--docs-text-light)]",children:"Next"},void 0,!1,void 0,this),v2("span",{className:"mt-2 block docs-font-display text-[22px] leading-[1.2] text-[var(--docs-heading)] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:[Q.metadata.title," \u2192"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as eg}from"preact/jsx-dev-runtime";var Mr0=({docs:A})=>{let Q=Cr(A),w=Ef0(Q),$=Q.filter((f)=>f.metadata.slug!=="index")[0]??Q[0];return eg(Sf0,{title:"Documentation",description:"Brains documentation",children:[eg(qa1,{docsCount:A.length,sectionsCount:w.length,startDoc:$},void 0,!1,void 0,this),eg("section",{className:"grid items-start gap-10 py-12 md:grid-cols-[200px_minmax(0,1fr)] md:gap-20 md:py-20 md:pb-[120px]",id:"sections",children:[eg(ba1,{groups:w},void 0,!1,void 0,this),eg("div",{children:w.map((f,Y)=>eg(Va1,{group:f,index:Y},f.section,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as CZ}from"preact/jsx-dev-runtime";var Or0=({doc:A,docs:Q,prevDoc:w,nextDoc:B})=>{let $=Ef0(Q.length>0?Q:[A]),f=Cr(Q.length>0?Q:[A]),Y=f.findIndex((W)=>W.metadata.slug===A.metadata.slug),X=Math.max($.findIndex((W)=>W.docs.some((H)=>H.metadata.slug===A.metadata.slug)),0);return CZ(Sf0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[CZ(Ia1,{title:A.metadata.title},void 0,!1,void 0,this),CZ("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[CZ(Ja1,{groups:$,activeGroupIndex:X,activeSlug:A.metadata.slug},void 0,!1,void 0,this),CZ("article",{className:"min-w-0",children:[CZ("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[CZ("p",{className:`${nG.label} m-0 mb-6 flex items-baseline gap-3`,children:[CZ("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[tg(X),"."]},void 0,!0,void 0,this)," ",A.metadata.section,Y>=0?` \xB7 ${Y+1}/${f.length}`:""]},void 0,!0,void 0,this),CZ("h1",{className:`${nG.display} m-0 max-w-[18ch] text-4xl leading-[1.05] tracking-[-0.02em] md:text-6xl`,children:A.metadata.title},void 0,!1,void 0,this),A.metadata.description&&CZ("p",{className:"mt-6 max-w-[56ch] docs-font-display text-[22px] font-[350] leading-[1.5] text-[var(--docs-text-muted)]",children:A.metadata.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),CZ("div",{className:"docs-article__body",children:CZ(V9,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),CZ(Fa1,{prevDoc:w,nextDoc:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};var QHw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),wHw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),BHw=Z.object({title:Z.string(),section:Z.string(),order:Z.number().int(),sourcePath:Z.string(),description:Z.string().optional(),slug:Z.string().optional()}),$Hw=Z.object({title:Z.string(),section:Z.string(),order:Z.number().int(),description:Z.string().optional(),slug:Z.string()}),gr=Z.object({id:Z.string(),entityType:Z.literal("doc"),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:wHw,metadata:$Hw,contentHash:Z.string(),frontmatter:BHw,body:Z.string()}),fHw=Z.object({docs:Z.array(gr),pagination:QHw.nullable(),baseUrl:Z.string().optional()}),YHw=Z.object({doc:gr,docs:Z.array(gr),prevDoc:gr.nullable(),nextDoc:gr.nullable()});function La1(){return{"doc-list":i1({name:"doc-list",description:"Documentation index template",schema:fHw,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:Mr0}}),"doc-detail":i1({name:"doc-detail",description:"Documentation page template",schema:YHw,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:Or0}})}}var ka1={name:"@brains/doc",version:"0.2.0-alpha.143",description:"Documentation entity type \u2014 markdown docs as first-class brain content",dependencies:{"@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","bun-types":"^1.3.14",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class xr0 extends nQ{entityType=gf0.entityType;schema=sg;adapter=gf0;constructor(){super("docs",ka1,{},L7)}getTemplates(){return La1()}getDataSources(){return[new yf0(this.logger.child("DocDataSource"))]}}function yr(){return new xr0}wA();K2();N0();CB();N0();var Rr0=Z.literal("application/pdf"),_a1=Z.enum(["pending","draft","failed"]),vr0=Z.object({title:Z.string().optional(),mimeType:Rr0,filename:Z.string().min(1),pageCount:Z.number().int().min(0).optional(),status:_a1.optional(),processingJobId:Z.string().optional(),processingError:Z.string().optional(),sourceEntityType:Z.string().min(1).optional(),sourceEntityId:Z.string().min(1).optional(),sourceUploadId:Z.string().optional(),sourceFilename:Z.string().optional(),sourceMediaType:Z.string().optional(),attachmentType:Z.string().min(1).optional(),dedupKey:Z.string().min(1).optional()}),Ay=LQ.extend({entityType:Z.literal("document"),content:Z.string().regex(/^data:application\/pdf;base64,.+$/),metadata:vr0});function Er(A){let Q=A.match(/^data:(application\/pdf);base64,(.+)$/i);if(!Q?.[1]||!Q[2])throw Error("Invalid PDF document data URL");return{mimeType:"application/pdf",base64:Q[2]}}function mf0(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function hr0(A){let Q=Buffer.from(A).toString("latin1"),w=0,B=/\/Type\s*\/Pages\b[^]*?\/Count\s+(\d+)|\/Count\s+(\d+)[^]*?\/Type\s*\/Pages\b/g;for(let f of Q.matchAll(B)){let Y=parseInt(f[1]??f[2]??"0",10);if(Y>w)w=Y}if(w>0)return w;return Q.match(/\/Type\s*\/Page(?!\w)/g)?.length??0}class uf0{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=Ay;toMarkdown(A){return A.content}fromMarkdown(A){return Er(A),{entityType:"document",content:A}}extractMetadata(A){return A.metadata}parseFrontMatter(A,Q){return Q.parse({})}generateFrontMatter(A){return""}getBodyTemplate(){return""}createDocumentEntity(A){let{dataUrl:Q,...w}=A,{mimeType:B}=Er(Q);return{entityType:"document",content:Q,metadata:{mimeType:B,...w}}}}var fb=new uf0;async function Io0(A,Q={}){let w=Q.maxBytes??5000000;if(A.byteLength>w)throw Error(`Uploaded PDF is too large for synchronous markdown extraction (${A.byteLength} bytes; max ${w} bytes)`);let $=(await Promise.resolve().then(() => (he1(),ve1))).getDocument({data:new Uint8Array(A),disableFontFace:!1,useSystemFonts:!0,useWorkerFetch:!1}),f=await $.promise;try{let Y=Q.maxPages??50;if(f.numPages>Y)throw Error(`Uploaded PDF has ${f.numPages} pages; maximum supported for synchronous markdown extraction is ${Y}`);let X=[];for(let H=1;H<=f.numPages;H+=1){let D=(await(await f.getPage(H)).getTextContent()).items.flatMap((q)=>("str"in q)?[q.str]:[]).join(" ").replace(/\s+/g," ").trim();if(D.length>0)X.push(D)}let W=X.join(`
6468
6468
 
6469
- `).trim();if(!W)throw Error("Could not extract text from the uploaded PDF");return W}finally{await $.destroy()}}wA();S9();K2();N0();import{createHash as nHw}from"crypto";var rHw=26214400,oHw=20,sHw=60000,Ce1=80,aHw=10,tHw={renderUrl:Z.url().optional(),sourceEntityType:Z.string().min(1),sourceEntityId:Z.string().min(1),attachmentType:Z.string().min(1),documentId:Z.string().min(1).optional(),title:Z.string().min(1).optional(),filename:Z.string().min(1).optional(),dedupKey:Z.string().min(1).optional(),replace:Z.boolean().optional(),pageCount:Z.number().int().min(0).optional(),maxPageCount:Z.number().int().positive().optional(),maxBytes:Z.number().int().positive().optional(),timeoutMs:Z.number().int().positive().optional(),width:Z.union([Z.string(),Z.number()]).optional(),height:Z.union([Z.string(),Z.number()]).optional(),format:Z.string().optional(),targetEntityType:Z.string().min(1).optional(),targetEntityId:Z.string().min(1).optional()},ye1=Z.object(tHw),PY0=ye1.refine((A)=>A.targetEntityType===void 0&&A.targetEntityId===void 0||A.targetEntityType!==void 0&&A.targetEntityId!==void 0,{message:"targetEntityType and targetEntityId must be provided together",path:["targetEntityId"]});class MY0 extends aw{context;renderPdf;constructor(A,Q,w={}){super(A,{schema:PY0,jobTypeName:"document-generate"});this.context=Q,this.renderPdf=w.renderPdf??kU}async getDedupKey(A){if(A.dedupKey!==void 0)return A.dedupKey;if(A.renderUrl!==void 0)return`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl}`;let Q=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:resolved-attachment`,w=await this.context.entityService.getEntity({entityType:A.sourceEntityType,id:A.sourceEntityId});return w?`${Q}:${w.contentHash}`:Q}async process(A,Q,w){this.logger.debug("Starting document generation job",{jobId:Q,sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});let B=A.maxPageCount??oHw,$=A.maxBytes??rHw,f=A.timeoutMs??sHw;if(A.pageCount!==void 0&&A.pageCount>B)throw Error(`Refusing to render ${A.pageCount} page PDF; maxPageCount=${B}`);let Y=await this.getDedupKey(A),X=Jo0(A,Y),W=A.documentId!==void 0||A.filename!==void 0;if(A.replace!==!0){let H=await this.findDocumentByDedupKey(Y,W?X:void 0);if(H&&(!W||H.id===X)){if(A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,H.id,A);return await this.reportProgress(w,{progress:100,message:"Reusing existing generated document"}),{success:!0,documentId:H.id,reused:!0}}}await this.reportProgress(w,{progress:20,message:"Rendering PDF document"});try{let H=await this.resolveDocumentAttachment(A,X,{timeoutMs:f,maxBytes:$}),K=H.data;if(K.byteLength>$)throw Error(`Rendered PDF exceeds maxBytes=${$}: ${K.byteLength} bytes`);let U=hr0(K);if(U>B)throw Error(`Rendered PDF has ${U} pages, exceeding maxPageCount=${B}`);let D=U>0?U:A.pageCount;await this.reportProgress(w,{progress:70,message:"Storing PDF document"});let q=A.filename??(A.renderUrl===void 0?H.filename:`${X}.pdf`),b=fb.createDocumentEntity({dataUrl:mf0(K),filename:q,...A.title&&{title:A.title},...D!==void 0&&{pageCount:D},status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,dedupKey:Y});if(await Vf({entityService:this.context.entityService,entity:{...b,id:X}}),A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,X,A);return await this.reportProgress(w,{progress:100,message:"PDF document generation complete"}),{success:!0,documentId:X,reused:!1}}catch(H){let K=mA(H);throw this.logger.error("Document generation failed",{jobId:Q,error:K}),await _D({entityService:this.context.entityService,entityType:"document",id:X,error:K}),H}}async resolveDocumentAttachment(A,Q,w){if(A.renderUrl!==void 0)return{type:"document",data:await this.renderPdf(A.renderUrl,{timeoutMs:w.timeoutMs,maxBytes:w.maxBytes,printBackground:!0,preferCSSPageSize:!0,...A.width!==void 0&&{width:A.width},...A.height!==void 0&&{height:A.height},...A.format!==void 0&&{format:A.format}}),mimeType:"application/pdf",filename:A.filename??`${Q}.pdf`};let B=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!B)throw Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`);if(B.type!=="document")throw Error(`Attachment provider returned ${B.type}; expected document`);return B}async findDocumentByDedupKey(A,Q){let w=await this.context.entityService.listEntities({entityType:"document",options:{filter:{metadata:{dedupKey:A}}}});if(w.length>1)this.logger.warn("Multiple documents share dedupKey; using first",{dedupKey:A,count:w.length,ids:w.map(($)=>$.id),preferredDocumentId:Q});let B=w.filter(($)=>$.metadata.status!=="pending"&&$.metadata.status!=="failed");return B.find(($)=>$.id===Q)??B[0]}async attachDocumentToTarget(A,Q,w,B){let $=await this.context.entityService.getEntity({entityType:A,id:Q});if(!$)throw Error(`Target entity not found: ${A}/${Q}`);let{frontmatter:f}=j6($.content),Y=Array.isArray(f.documents)?f.documents.filter(AKw):[],X=B.replace?await this.removeReferencesForSameSourceAttachment(Y,w,B):Y,W=X.some((H)=>H.id===w)?X:[...X,{id:w}];await this.context.entityService.updateEntity({entity:{...$,content:D4($.content,"documents",W)}})}async removeReferencesForSameSourceAttachment(A,Q,w){let B=[];for(let $ of A){if($.id===Q){B.push($);continue}let f=await this.context.entityService.getEntity({entityType:"document",id:$.id});if(!f||!QKw(f,w))B.push($)}return B}}function Jo0(A,Q){let w=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl??"resolved-attachment"}`,B=A.documentId??A.filename?.replace(/\.pdf$/i,"")??Q??w,$=A.replace===!0&&A.documentId===void 0?`${B}-${Date.now()}`:B;return eHw($)}function eHw(A){let Q=Z1(A.replace(/[/:]+/g," "))||`document-${ge1(A)}`;if(Q.length<=Ce1)return Q;let w=`-${ge1(A)}`;return`${Q.slice(0,Ce1-w.length).replace(/-+$/g,"")}${w}`}function ge1(A){return nHw("sha256").update(A).digest("hex").slice(0,aHw)}function AKw(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function QKw(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var Ee1={name:"@brains/document-plugin",version:"0.2.0-alpha.142",description:"Document entity type for generated PDFs and publishable document attachments",dependencies:{"@brains/contracts":"workspace:*","@brains/document":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/typescript-config":"workspace:*","bun-types":"^1.3.14",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var BKw=`data:application/pdf;base64,${Buffer.from(`%PDF-1.4
6469
+ `).trim();if(!W)throw Error("Could not extract text from the uploaded PDF");return W}finally{await $.destroy()}}wA();S9();K2();N0();import{createHash as nHw}from"crypto";var rHw=26214400,oHw=20,sHw=60000,Ce1=80,aHw=10,tHw={renderUrl:Z.url().optional(),sourceEntityType:Z.string().min(1),sourceEntityId:Z.string().min(1),attachmentType:Z.string().min(1),documentId:Z.string().min(1).optional(),title:Z.string().min(1).optional(),filename:Z.string().min(1).optional(),dedupKey:Z.string().min(1).optional(),replace:Z.boolean().optional(),pageCount:Z.number().int().min(0).optional(),maxPageCount:Z.number().int().positive().optional(),maxBytes:Z.number().int().positive().optional(),timeoutMs:Z.number().int().positive().optional(),width:Z.union([Z.string(),Z.number()]).optional(),height:Z.union([Z.string(),Z.number()]).optional(),format:Z.string().optional(),targetEntityType:Z.string().min(1).optional(),targetEntityId:Z.string().min(1).optional()},ye1=Z.object(tHw),PY0=ye1.refine((A)=>A.targetEntityType===void 0&&A.targetEntityId===void 0||A.targetEntityType!==void 0&&A.targetEntityId!==void 0,{message:"targetEntityType and targetEntityId must be provided together",path:["targetEntityId"]});class MY0 extends aw{context;renderPdf;constructor(A,Q,w={}){super(A,{schema:PY0,jobTypeName:"document-generate"});this.context=Q,this.renderPdf=w.renderPdf??kU}async getDedupKey(A){if(A.dedupKey!==void 0)return A.dedupKey;if(A.renderUrl!==void 0)return`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl}`;let Q=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:resolved-attachment`,w=await this.context.entityService.getEntity({entityType:A.sourceEntityType,id:A.sourceEntityId});return w?`${Q}:${w.contentHash}`:Q}async process(A,Q,w){this.logger.debug("Starting document generation job",{jobId:Q,sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});let B=A.maxPageCount??oHw,$=A.maxBytes??rHw,f=A.timeoutMs??sHw;if(A.pageCount!==void 0&&A.pageCount>B)throw Error(`Refusing to render ${A.pageCount} page PDF; maxPageCount=${B}`);let Y=await this.getDedupKey(A),X=Jo0(A,Y),W=A.documentId!==void 0||A.filename!==void 0;if(A.replace!==!0){let H=await this.findDocumentByDedupKey(Y,W?X:void 0);if(H&&(!W||H.id===X)){if(A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,H.id,A);return await this.reportProgress(w,{progress:100,message:"Reusing existing generated document"}),{success:!0,documentId:H.id,reused:!0}}}await this.reportProgress(w,{progress:20,message:"Rendering PDF document"});try{let H=await this.resolveDocumentAttachment(A,X,{timeoutMs:f,maxBytes:$}),K=H.data;if(K.byteLength>$)throw Error(`Rendered PDF exceeds maxBytes=${$}: ${K.byteLength} bytes`);let U=hr0(K);if(U>B)throw Error(`Rendered PDF has ${U} pages, exceeding maxPageCount=${B}`);let D=U>0?U:A.pageCount;await this.reportProgress(w,{progress:70,message:"Storing PDF document"});let q=A.filename??(A.renderUrl===void 0?H.filename:`${X}.pdf`),b=fb.createDocumentEntity({dataUrl:mf0(K),filename:q,...A.title&&{title:A.title},...D!==void 0&&{pageCount:D},status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,dedupKey:Y});if(await Vf({entityService:this.context.entityService,entity:{...b,id:X}}),A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,X,A);return await this.reportProgress(w,{progress:100,message:"PDF document generation complete"}),{success:!0,documentId:X,reused:!1}}catch(H){let K=mA(H);throw this.logger.error("Document generation failed",{jobId:Q,error:K}),await _D({entityService:this.context.entityService,entityType:"document",id:X,error:K}),H}}async resolveDocumentAttachment(A,Q,w){if(A.renderUrl!==void 0)return{type:"document",data:await this.renderPdf(A.renderUrl,{timeoutMs:w.timeoutMs,maxBytes:w.maxBytes,printBackground:!0,preferCSSPageSize:!0,...A.width!==void 0&&{width:A.width},...A.height!==void 0&&{height:A.height},...A.format!==void 0&&{format:A.format}}),mimeType:"application/pdf",filename:A.filename??`${Q}.pdf`};let B=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!B)throw Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`);if(B.type!=="document")throw Error(`Attachment provider returned ${B.type}; expected document`);return B}async findDocumentByDedupKey(A,Q){let w=await this.context.entityService.listEntities({entityType:"document",options:{filter:{metadata:{dedupKey:A}}}});if(w.length>1)this.logger.warn("Multiple documents share dedupKey; using first",{dedupKey:A,count:w.length,ids:w.map(($)=>$.id),preferredDocumentId:Q});let B=w.filter(($)=>$.metadata.status!=="pending"&&$.metadata.status!=="failed");return B.find(($)=>$.id===Q)??B[0]}async attachDocumentToTarget(A,Q,w,B){let $=await this.context.entityService.getEntity({entityType:A,id:Q});if(!$)throw Error(`Target entity not found: ${A}/${Q}`);let{frontmatter:f}=j6($.content),Y=Array.isArray(f.documents)?f.documents.filter(AKw):[],X=B.replace?await this.removeReferencesForSameSourceAttachment(Y,w,B):Y,W=X.some((H)=>H.id===w)?X:[...X,{id:w}];await this.context.entityService.updateEntity({entity:{...$,content:D4($.content,"documents",W)}})}async removeReferencesForSameSourceAttachment(A,Q,w){let B=[];for(let $ of A){if($.id===Q){B.push($);continue}let f=await this.context.entityService.getEntity({entityType:"document",id:$.id});if(!f||!QKw(f,w))B.push($)}return B}}function Jo0(A,Q){let w=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl??"resolved-attachment"}`,B=A.documentId??A.filename?.replace(/\.pdf$/i,"")??Q??w,$=A.replace===!0&&A.documentId===void 0?`${B}-${Date.now()}`:B;return eHw($)}function eHw(A){let Q=Z1(A.replace(/[/:]+/g," "))||`document-${ge1(A)}`;if(Q.length<=Ce1)return Q;let w=`-${ge1(A)}`;return`${Q.slice(0,Ce1-w.length).replace(/-+$/g,"")}${w}`}function ge1(A){return nHw("sha256").update(A).digest("hex").slice(0,aHw)}function AKw(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function QKw(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var Ee1={name:"@brains/document-plugin",version:"0.2.0-alpha.143",description:"Document entity type for generated PDFs and publishable document attachments",dependencies:{"@brains/contracts":"workspace:*","@brains/document":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/typescript-config":"workspace:*","bun-types":"^1.3.14",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var BKw=`data:application/pdf;base64,${Buffer.from(`%PDF-1.4
6470
6470
  % Pending document placeholder
6471
6471
  %%EOF
6472
6472
  `).toString("base64")}`,$Kw=Z.object({}).catchall(Z.unknown()).transform(()=>({})),Fo0={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function fKw(A,Q){let w=A.title?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}function YKw(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function XKw(A){let Q=encodeURIComponent(A.entityId);return{mediaType:"application/pdf",url:`/api/chat/attachments/document?id=${Q}`,downloadUrl:`/api/chat/attachments/document?id=${Q}&download=1`,filename:A.filename,source:{entityType:"document",entityId:A.entityId,attachmentType:"uploaded"}}}class Lo0 extends aQ{entityType=fb.entityType;schema=Ay;adapter=fb;pluginContext;constructor(){super("document",Ee1,{},$Kw)}async onRegister(A){this.pluginContext=A,A.entities.register(this.entityType,this.schema,this.adapter,{embeddable:!1}),A.entities.registerCreateInterceptor(this.entityType,(Q)=>this.interceptCreate(Q)),A.entities.registerUploadSaveHandler({entityType:this.entityType,mediaTypes:["application/pdf"],handler:async(Q)=>{let w=await this.promoteUpload({entityType:this.entityType,...Q.title!==void 0?{title:Q.title}:{},from:Q.upload},A);return w.kind==="handled"?w.result:{success:!1,error:"Document upload save was not handled"}}}),A.jobs.registerHandler("generate",new MY0(this.logger.child("DocumentGenerationJobHandler"),A))}async interceptCreate(A){let Q=this.pluginContext;if(A.from?.kind===Fo0.refKind){if(!Q)return{kind:"handled",result:{success:!1,error:"Plugin context not initialized"}};return this.promoteUpload(A,Q)}if(A.from?.kind!=="entity-attachment")return{kind:"continue",input:A};if(!Q)return{kind:"handled",result:{success:!1,error:"Plugin context not initialized"}};let w=PY0.parse({sourceEntityType:A.from.sourceEntityType,sourceEntityId:A.from.sourceEntityId,attachmentType:A.from.attachmentType,...A.title&&{title:A.title},...A.replace===!0&&{replace:!0},...A.targetEntityType&&{targetEntityType:A.targetEntityType},...A.targetEntityId&&{targetEntityId:A.targetEntityId}}),B=await this.getDedupKey(w,Q),$=w.replace===!0?void 0:await this.findExistingDocument(B,Q),f=$?.id??Jo0(w,B);if(!$)await this.createPendingDocument(Q,{id:f,title:w.title??f,filename:`${f}.pdf`,sourceEntityType:w.sourceEntityType,sourceEntityId:w.sourceEntityId,attachmentType:w.attachmentType,dedupKey:B});let Y=await Q.jobs.enqueue({type:"generate",data:{...w,dedupKey:B,documentId:f}}),X=`${f}.pdf`;return{kind:"handled",result:{success:!0,data:{entityId:f,jobId:Y,status:"generating",attachment:{mediaType:"application/pdf",url:`/api/chat/attachments/document?id=${encodeURIComponent(f)}`,downloadUrl:`/api/chat/attachments/document?id=${encodeURIComponent(f)}&download=1`,filename:X,source:{entityType:"document",entityId:f,attachmentType:w.attachmentType}}}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==Fo0.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let B;try{B=await Q.uploads.scoped(Fo0).read(w.id)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(B.record.mediaType!=="application/pdf")return{kind:"handled",result:{success:!1,error:"Only PDF uploads can be promoted to document entities"}};let $=fKw(A,B.record.filename),f=Z1($);if(!f)return{kind:"handled",result:{success:!1,error:"Could not derive a document id from the uploaded filename. Provide a title."}};let Y=new Date().toISOString(),X=fb.createDocumentEntity({dataUrl:YKw(B.record.mediaType,B.content),filename:B.record.filename,title:$,status:"draft",sourceUploadId:w.id,sourceFilename:B.record.filename,sourceMediaType:B.record.mediaType,attachmentType:"uploaded",dedupKey:`upload:${w.kind}:${w.id}`}),W=await Q.entityService.createEntity({entity:{id:f,...X,created:Y,updated:Y},options:{deduplicateId:!0}});return{kind:"handled",result:{success:!0,data:{entityId:W.entityId,status:"created",attachment:XKw({entityId:W.entityId,filename:B.record.filename})}}}}async createPendingDocument(A,Q){let w=new Date().toISOString(),B=fb.createDocumentEntity({dataUrl:BKw,filename:Q.filename,title:Q.title,status:"pending",sourceEntityType:Q.sourceEntityType,sourceEntityId:Q.sourceEntityId,attachmentType:Q.attachmentType,dedupKey:Q.dedupKey});await bk({entityService:A.entityService,entity:{id:Q.id,...B,created:w,updated:w}})}async getDedupKey(A,Q){if(A.dedupKey!==void 0)return A.dedupKey;if(A.renderUrl!==void 0)return`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl}`;let w=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:resolved-attachment`,B=await Q.entityService.getEntity({entityType:A.sourceEntityType,id:A.sourceEntityId});return B?`${w}:${B.contentHash}`:w}async findExistingDocument(A,Q){return(await Q.entityService.listEntities({entityType:"document",options:{filter:{metadata:{dedupKey:A}}}}))[0]}async getInstructions(){return"Document entities store durable file artifacts such as PDFs. Uploaded PDFs are raw document files, not decks. Source-derived document artifacts are durable documents backed by registered attachment providers such as carousel or printable. Generate saved PDF artifacts through system_generate with source.kind attachment; preserve raw uploaded PDFs with system_create source.kind upload and transform preserve."}async getTools(){return[]}}function ko0(){return new Lo0}wA();N0();wA();N0();var Te1=Z.enum(["generating","failed"]),ZKw=Z.enum(["generating","failed"]),NF=Z.object({title:Z.string().optional(),status:Te1.optional(),error:Z.string().optional()}),WKw=Z.object({title:Z.string(),status:Te1.optional(),error:Z.string().optional()}),HKw=Z.object({title:Z.string(),status:ZKw.optional(),error:Z.string().optional()}),jF=LQ.extend({entityType:Z.literal("note"),metadata:HKw}),KKw=jF.extend({frontmatter:NF,body:Z.string()});wA();N0();var UKw=Z.record(Z.string(),Z.unknown());class _o0 extends C2{constructor(){super({entityType:"note",purpose:"A short, free-form captured thought, reference, or snippet the user wants to keep.",schema:jF,frontmatterSchema:NF})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,NF);if(Object.values(w).some((B)=>B!==void 0))return this.buildMarkdown(Q,w)}catch{}return Q}fromMarkdown(A){let Q=this.parseMarkdownFrontmatter(A),w=Q.title??this.extractH1(A)??"Untitled";return{content:A,entityType:"note",metadata:{title:w,...Q.status&&{status:Q.status},...Q.error&&{error:Q.error}}}}parseNoteFrontmatter(A){return this.parseMarkdownFrontmatter(A.content)}parseMarkdownFrontmatter(A){try{return this.parseFrontMatter(A,NF)}catch{return{}}}buildStub(A){let Q={title:A.title,status:"generating"};return{content:this.buildMarkdown("",Q),metadata:{title:A.title,status:"generating"}}}createNoteContent(A,Q){try{let w=this.parseFrontMatter(Q,UKw);if(Object.keys(w).length===0)return Q;let B={...w,title:w.title??A},$=this.extractBody(Q);return this.buildMarkdown($,B)}catch{return Q}}extractH1(A){return A.match(/^#\s+(.+)$/m)?.[1]?.trim()??null}}var Wb=new _o0;N0();var No0=Z.object({defaultPrompt:Z.string().default("Create a note summarizing key concepts from my knowledge base")});N0();wA();var Se1=Z.object({title:Z.string().max(80).describe("A clear, descriptive title for the note (3-8 words)"),body:Z.string().describe("Note content in markdown format with clear organization and structure")}),jo0=i1({name:"note:generation",description:"Template for AI to generate notes from prompts",schema:Se1,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create personal knowledge notes for research and reference.
@@ -6484,7 +6484,7 @@ title: ${JSON.stringify(A)}
6484
6484
  ---
6485
6485
 
6486
6486
  ${Q.trim()}
6487
- `}var bKw={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},VKw=Z.object({uploadId:Z.string().min(1),entityId:Z.string().min(1),title:Z.string().optional()});class Mo0 extends aw{context;constructor(A,Q){super(A,{schema:VKw,jobTypeName:"upload-import"});this.context=Q}async process(A,Q,w){try{await this.reportProgress(w,{progress:10,message:"Reading uploaded file"});let B=await this.context.uploads.scoped(bKw).read(A.uploadId);await this.reportProgress(w,{progress:35,message:"Extracting markdown from upload"});let $=await le1({upload:B,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress(w,{progress:80,message:"Saving imported note"});let f=new Date().toISOString(),Y=Wb.fromMarkdown($.content),X=await Vf({entityService:this.context.entityService,entity:{id:A.entityId,entityType:"note",content:$.content,metadata:{title:$.title,...Y.metadata},created:f,updated:f}});return await this.reportProgress(w,{progress:100,message:"Upload imported as markdown note"}),{entityId:X.entityId,status:"created"}}catch(B){return await this.markStubFailed(A.entityId,mA(B)),Q$.failure(B)}}async markStubFailed(A,Q){try{let w=await this.context.entityService.getEntity({entityType:"note",id:A});if(!w)return;await this.context.entityService.updateEntity({entity:{...w,content:D4(D4(w.content,"status","failed"),"error",Q),metadata:{...w.metadata,status:"failed",error:Q}}})}catch(w){this.logger.warn("Failed to mark import stub as failed",{error:w,entityId:A})}}summarizeDataForLog(A){return{uploadId:A.uploadId,entityId:A.entityId,hasTitle:A.title!==void 0}}}wA();async function pe1({entity:A,config:Q}){let w=jF.parse(A),B=o2(w.content,NF);return{$type:"ai.rizom.brain.note",title:w.metadata.title,body:B.content,format:"text/markdown",...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"note",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function Oo0(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:L6["ai.rizom.brain.note"],validate:!1,buildRecord:pe1}}var ie1={name:"@brains/note",version:"0.2.0-alpha.142",description:"Personal knowledge capture with markdown-first workflow",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/contracts":"workspace:*","@brains/document":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var de1={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},JKw=Z.object({prompt:Z.string()});class xo0 extends nQ{entityType=Wb.entityType;schema=jF;adapter=Wb;unregisterAtprotoProjection;constructor(A={}){super("note",ie1,A,No0)}async interceptCreate(A,Q,w){if(A.from?.kind!==de1.refKind)return{kind:"continue",input:A};if(A.transform!=="extract-markdown")return{kind:"handled",result:{success:!1,error:'Importing an upload as a note requires transform: "extract-markdown"'}};let B=A.from.id,$;try{$=await w.uploads.scoped(de1).readRecord(B)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}try{if(!ce1($.mediaType))return{kind:"handled",result:{success:!1,error:"Only text, JSON, and PDF uploads can be imported as markdown notes"}};let f=Po0({filename:$.filename,...A.title!==void 0?{title:A.title}:{}}),Y=Wb.buildStub({id:f.id,title:f.title}),X=new Date().toISOString(),W=await w.entityService.createEntity({entity:{id:f.id,entityType:"note",content:Y.content,metadata:Y.metadata,created:X,updated:X},options:{deduplicateId:!0}}),H=await w.jobs.enqueue({type:"upload-import",data:{uploadId:B,entityId:W.entityId,...A.title!==void 0?{title:A.title}:{}}});return{kind:"handled",result:{success:!0,data:{entityId:W.entityId,status:"generating",jobId:H}}}}catch(f){return{kind:"handled",result:{success:!1,error:f instanceof Error?f.message:"Failed to import upload as markdown"}}}}createGenerationHandler(A){return new OY0(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:jo0}}async onRegister(A){A.jobs.registerHandler("upload-import",new Mo0(this.logger.child("UploadMarkdownImportJobHandler"),A)),A.eval.registerHandler("generateNote",async(Q)=>{let w=JKw.parse(Q);return A.ai.generate({prompt:w.prompt,templateName:"note:generation"})}),this.unregisterAtprotoProjection=A8.getInstance().register(Oo0())}async getInstructions(){return"Note entities are editable markdown notes. Use them for durable text captures, summaries, and imported markdown; raw files remain document or image entities instead of notes."}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function QP(A={}){return new xo0(A)}wA();N0();wA();var ne1=Z.object({ref:Z.string(),label:Z.string()}),re1=Z.enum(["pending","draft","published"]),FKw=Z.enum(["pending","draft","published"]),Wo=Z.object({status:re1,title:Z.string(),url:Z.string().url(),description:Z.string().optional(),domain:Z.string(),capturedAt:Z.string().datetime(),source:ne1}),LKw=Wo.pick({title:!0,status:!0}),kKw=Z.object({title:Z.string(),status:FKw}),wP=LQ.extend({entityType:Z.literal("link"),metadata:kKw});K2();N0();N0();var Ro0=Z.object({enableSummarization:Z.boolean().default(!0).describe("Generate AI summaries for captured links"),jinaApiKey:Z.string().optional().describe("Jina Reader API key for higher rate limits (500 RPM vs 20 RPM without key)")});wA();class PF extends C2{constructor(){super({entityType:"link",purpose:"A saved external URL or web resource captured for later reference.",schema:wP,frontmatterSchema:Wo})}createLinkContent(A){let Q={status:A.status,title:A.title,url:A.url,description:A.description,domain:A.domain,capturedAt:A.capturedAt,source:A.source},w=A.summary??"";return this.buildMarkdown(w,Q)}parseLinkContent(A){return{frontmatter:this.parseFrontMatter(A,Wo),summary:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseLinkContent(A);return{content:A,entityType:"link",metadata:{title:Q.title,status:Q.status}}}}var Gy=new PF;wA();N0();var _Kw=Z.object({success:Z.boolean().describe("Set to true if you can extract meaningful content. Set to false only if the provided content is empty, just an error message, or otherwise unusable."),error:Z.string().describe("If success is false, explain why content could not be extracted. Use an empty string when success is true."),title:Z.string().max(80).describe("The page title - extract from the content or create a descriptive one. Leave empty string if success is false."),description:Z.string().describe("A one-sentence description of what the page is about. Leave empty string if success is false."),summary:Z.string().describe("A 1-2 paragraph summary of the main content. Leave empty string if success is false.")}),oe1=i1({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:_Kw,basePrompt:`You are an expert at extracting key information from webpage content.
6487
+ `}var bKw={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},VKw=Z.object({uploadId:Z.string().min(1),entityId:Z.string().min(1),title:Z.string().optional()});class Mo0 extends aw{context;constructor(A,Q){super(A,{schema:VKw,jobTypeName:"upload-import"});this.context=Q}async process(A,Q,w){try{await this.reportProgress(w,{progress:10,message:"Reading uploaded file"});let B=await this.context.uploads.scoped(bKw).read(A.uploadId);await this.reportProgress(w,{progress:35,message:"Extracting markdown from upload"});let $=await le1({upload:B,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress(w,{progress:80,message:"Saving imported note"});let f=new Date().toISOString(),Y=Wb.fromMarkdown($.content),X=await Vf({entityService:this.context.entityService,entity:{id:A.entityId,entityType:"note",content:$.content,metadata:{title:$.title,...Y.metadata},created:f,updated:f}});return await this.reportProgress(w,{progress:100,message:"Upload imported as markdown note"}),{entityId:X.entityId,status:"created"}}catch(B){return await this.markStubFailed(A.entityId,mA(B)),Q$.failure(B)}}async markStubFailed(A,Q){try{let w=await this.context.entityService.getEntity({entityType:"note",id:A});if(!w)return;await this.context.entityService.updateEntity({entity:{...w,content:D4(D4(w.content,"status","failed"),"error",Q),metadata:{...w.metadata,status:"failed",error:Q}}})}catch(w){this.logger.warn("Failed to mark import stub as failed",{error:w,entityId:A})}}summarizeDataForLog(A){return{uploadId:A.uploadId,entityId:A.entityId,hasTitle:A.title!==void 0}}}wA();async function pe1({entity:A,config:Q}){let w=jF.parse(A),B=o2(w.content,NF);return{$type:"ai.rizom.brain.note",title:w.metadata.title,body:B.content,format:"text/markdown",...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"note",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function Oo0(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:L6["ai.rizom.brain.note"],validate:!1,buildRecord:pe1}}var ie1={name:"@brains/note",version:"0.2.0-alpha.143",description:"Personal knowledge capture with markdown-first workflow",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/contracts":"workspace:*","@brains/document":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var de1={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},JKw=Z.object({prompt:Z.string()});class xo0 extends nQ{entityType=Wb.entityType;schema=jF;adapter=Wb;unregisterAtprotoProjection;constructor(A={}){super("note",ie1,A,No0)}async interceptCreate(A,Q,w){if(A.from?.kind!==de1.refKind)return{kind:"continue",input:A};if(A.transform!=="extract-markdown")return{kind:"handled",result:{success:!1,error:'Importing an upload as a note requires transform: "extract-markdown"'}};let B=A.from.id,$;try{$=await w.uploads.scoped(de1).readRecord(B)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}try{if(!ce1($.mediaType))return{kind:"handled",result:{success:!1,error:"Only text, JSON, and PDF uploads can be imported as markdown notes"}};let f=Po0({filename:$.filename,...A.title!==void 0?{title:A.title}:{}}),Y=Wb.buildStub({id:f.id,title:f.title}),X=new Date().toISOString(),W=await w.entityService.createEntity({entity:{id:f.id,entityType:"note",content:Y.content,metadata:Y.metadata,created:X,updated:X},options:{deduplicateId:!0}}),H=await w.jobs.enqueue({type:"upload-import",data:{uploadId:B,entityId:W.entityId,...A.title!==void 0?{title:A.title}:{}}});return{kind:"handled",result:{success:!0,data:{entityId:W.entityId,status:"generating",jobId:H}}}}catch(f){return{kind:"handled",result:{success:!1,error:f instanceof Error?f.message:"Failed to import upload as markdown"}}}}createGenerationHandler(A){return new OY0(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:jo0}}async onRegister(A){A.jobs.registerHandler("upload-import",new Mo0(this.logger.child("UploadMarkdownImportJobHandler"),A)),A.eval.registerHandler("generateNote",async(Q)=>{let w=JKw.parse(Q);return A.ai.generate({prompt:w.prompt,templateName:"note:generation"})}),this.unregisterAtprotoProjection=A8.getInstance().register(Oo0())}async getInstructions(){return"Note entities are editable markdown notes. Use them for durable text captures, summaries, and imported markdown; raw files remain document or image entities instead of notes."}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function QP(A={}){return new xo0(A)}wA();N0();wA();var ne1=Z.object({ref:Z.string(),label:Z.string()}),re1=Z.enum(["pending","draft","published"]),FKw=Z.enum(["pending","draft","published"]),Wo=Z.object({status:re1,title:Z.string(),url:Z.string().url(),description:Z.string().optional(),domain:Z.string(),capturedAt:Z.string().datetime(),source:ne1}),LKw=Wo.pick({title:!0,status:!0}),kKw=Z.object({title:Z.string(),status:FKw}),wP=LQ.extend({entityType:Z.literal("link"),metadata:kKw});K2();N0();N0();var Ro0=Z.object({enableSummarization:Z.boolean().default(!0).describe("Generate AI summaries for captured links"),jinaApiKey:Z.string().optional().describe("Jina Reader API key for higher rate limits (500 RPM vs 20 RPM without key)")});wA();class PF extends C2{constructor(){super({entityType:"link",purpose:"A saved external URL or web resource captured for later reference.",schema:wP,frontmatterSchema:Wo})}createLinkContent(A){let Q={status:A.status,title:A.title,url:A.url,description:A.description,domain:A.domain,capturedAt:A.capturedAt,source:A.source},w=A.summary??"";return this.buildMarkdown(w,Q)}parseLinkContent(A){return{frontmatter:this.parseFrontMatter(A,Wo),summary:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseLinkContent(A);return{content:A,entityType:"link",metadata:{title:Q.title,status:Q.status}}}}var Gy=new PF;wA();N0();var _Kw=Z.object({success:Z.boolean().describe("Set to true if you can extract meaningful content. Set to false only if the provided content is empty, just an error message, or otherwise unusable."),error:Z.string().describe("If success is false, explain why content could not be extracted. Use an empty string when success is true."),title:Z.string().max(80).describe("The page title - extract from the content or create a descriptive one. Leave empty string if success is false."),description:Z.string().describe("A one-sentence description of what the page is about. Leave empty string if success is false."),summary:Z.string().describe("A 1-2 paragraph summary of the main content. Leave empty string if success is false.")}),oe1=i1({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:_Kw,basePrompt:`You are an expert at extracting key information from webpage content.
6488
6488
 
6489
6489
  You will receive webpage content in markdown format. Your job is to extract structured information from it.
6490
6490
 
@@ -6506,7 +6506,7 @@ Accuracy rules:
6506
6506
 
6507
6507
  `))return{success:!1,error:Y.trim(),errorType:"fetch_failed"};return{success:!0,content:Y}}catch(w){return this.handleFetchError(w,A)}}handleHttpError(A,Q){if(A===400)return{success:!1,error:`Invalid or non-existent URL: ${Q}`,errorType:"url_not_found"};if(A===404)return{success:!1,error:`Page not found: ${Q}`,errorType:"url_not_found"};if(A>=500)return{success:!1,error:`Server error while fetching ${Q}`,errorType:"url_unreachable"};return{success:!1,error:`HTTP ${A} error while fetching ${Q}`,errorType:"fetch_failed"}}handleFetchError(A,Q){if(A instanceof Error){if(A.name==="AbortError")return{success:!1,error:`Request timeout while fetching ${Q}`,errorType:"url_unreachable"};if(A.message.includes("ENOTFOUND")||A.message.includes("getaddrinfo"))return{success:!1,error:`Domain not found: ${new URL(Q).hostname}`,errorType:"url_not_found"};if(A.message.includes("ECONNREFUSED")||A.message.includes("ETIMEDOUT"))return{success:!1,error:`Could not connect to ${Q}`,errorType:"url_unreachable"};return{success:!1,error:`Failed to fetch ${Q}: ${A.message}`,errorType:"fetch_failed"}}return{success:!1,error:`Unknown error fetching ${Q}`,errorType:"fetch_failed"}}}import{createHash as xKw}from"crypto";class MF{static URL_PATTERN=/https?:\/\/[^\s<>"{}|\\^`[\]]+?(?=[,;:\s]|$)/gi;static extractUrls(A){let Q=A.match(MF.URL_PATTERN)??[];return[...new Set(Q)]}static normalizeUrl(A){try{let Q=new URL(A),w=Q.pathname.replace(/\/$/,"")||"/";return`${Q.protocol}//${Q.host}${w}`}catch{return A}}static generateEntityId(A){let Q=this.normalizeUrl(A),w=xKw("sha256").update(Q).digest("hex");try{return`${new URL(Q).hostname.replace(/\./g,"-")}-${w.substring(0,6)}`}catch{return w.substring(0,12)}}static isValidUrl(A){try{let Q=new URL(A);return["http:","https:"].includes(Q.protocol)}catch{return!1}}}wA();N0();g6();var RKw=Z.object({interfaceId:Z.string().optional(),userId:Z.string().optional(),channelId:Z.string().optional(),channelName:Z.string().optional(),timestamp:Z.string().optional()}),vKw=Z.object({url:Z.url(),metadata:RKw.optional()}),ww$=Z.object({success:Z.boolean(),entityId:Z.string().optional(),title:Z.string().optional(),url:Z.string().optional(),status:Z.enum(["pending","draft","published"]).optional(),error:Z.string().optional()});class RY0 extends aw{context;linkAdapter;urlFetcher;constructor(A,Q,w){super(A,{schema:vKw,jobTypeName:"link-capture"});this.context=Q,this.linkAdapter=new PF,this.urlFetcher=new zy(w?.jinaApiKey?{jinaApiKey:w.jinaApiKey}:void 0)}async process(A,Q,w){let{url:B,metadata:$}=A;try{await w.report({progress:dQ.START,total:100,message:"Starting link capture"});let f=MF.generateEntityId(B);await w.report({progress:dQ.INIT,total:100,message:"Checking for existing link"});let Y=await this.context.entityService.getEntity({entityType:"link",id:f});if(Y){let{frontmatter:q}=this.linkAdapter.parseLinkContent(Y.content),b=Y.metadata.status;if(b!=="pending")return this.logger.info("Link already captured, returning existing",{url:B,entityId:f}),{success:!0,entityId:Y.id,title:q.title,url:B,status:b};this.logger.info("Pending link exists, completing extraction",{url:B,entityId:f})}let X=this.resolveSource($),W=new Date().toISOString();await w.report({progress:dQ.FETCH,total:100,message:"Fetching webpage content"});let H=await this.urlFetcher.fetch(B);if(!H.success){if(H.errorType==="url_not_found"||H.errorType==="url_unreachable"){this.logger.warn("Link URL not accessible",{url:B,errorType:H.errorType,error:H.error});let q=new URL(B).hostname,b=`Could not capture link: ${H.error}`,I=this.linkAdapter.createLinkContent({status:"pending",title:q,url:B,description:b,summary:b,domain:q,capturedAt:W,source:X});return await Vf({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:I,metadata:{status:"pending",title:q}}}),{success:!1,entityId:f,title:q,url:B,status:"pending",error:b}}}await w.report({progress:dQ.PROCESS,total:100,message:"Extracting content with AI"});let K=await this.context.ai.generate({templateName:"link:extraction",prompt:H.success?`Extract structured information from this webpage content:
6508
6508
 
6509
- ${H.content}`:`The URL ${B} could not be fetched. Return success: false with error: "${H.error}"`,data:{url:B,hasContent:H.success},interfacePermissionGrant:"public"});if(this.logger.debug("AI extraction result",{result:K}),await w.report({progress:dQ.EXTRACT,total:100,message:"Processing extraction results"}),K.success===!1||!K.title||!K.description||!K.summary){let q=K.title||new URL(B).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:B}),await w.report({progress:dQ.SAVE,total:100,message:"Saving link as pending"});let b=this.linkAdapter.createLinkContent({status:"pending",title:q,url:B,description:K.description,summary:K.summary,domain:new URL(B).hostname,capturedAt:W,source:X}),I=await Vf({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:b,metadata:{status:"pending",title:q}}});return await w.report({progress:dQ.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:I.entityId,title:q,url:B,status:"pending"}}await w.report({progress:dQ.SAVE,total:100,message:`Saving link: "${K.title}"`});let U=this.linkAdapter.createLinkContent({status:"draft",title:K.title,url:B,description:K.description,summary:K.summary,domain:new URL(B).hostname,capturedAt:W,source:X}),D=await Vf({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:U,metadata:{status:"draft",title:K.title}}});return await w.report({progress:dQ.COMPLETE,total:100,message:`Link captured: "${K.title}"`}),{success:!0,entityId:D.entityId,title:K.title,url:B,status:"draft"}}catch(f){return this.logger.error("Link capture job failed",{error:f,jobId:Q,data:A}),Q$.failure(f)}}resolveSource(A){let Q=A?.channelId,w=A?.channelName;if(Q)return{ref:`matrix:${Q}`,label:w??Q};let B=A?.interfaceId??"cli";return{ref:`${B}:local`,label:B.toUpperCase()}}summarizeDataForLog(A){return{url:A.url,interfaceId:A.metadata?.interfaceId}}}async function te1({entity:A,config:Q}){let w=wP.parse(A),{frontmatter:B,summary:$}=Gy.parseLinkContent(w.content);return{$type:"ai.rizom.brain.link",title:B.title,url:B.url,...B.description&&{description:B.description},...$&&{summary:$},domain:B.domain,capturedAt:B.capturedAt,source:B.source,...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"link",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function Eo0(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:L6["ai.rizom.brain.link"],validate:!1,buildRecord:te1}}var ee1={name:"@brains/link",version:"0.2.0-alpha.142",description:"Web content capture plugin with AI-powered extraction and structured storage",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var CKw=Z.object({url:Z.url()});class To0 extends nQ{entityType=Gy.entityType;schema=wP;adapter=Gy;shell;unregisterAtprotoProjection;constructor(A={}){super("link",ee1,A,Ro0)}async register(A){this.shell=A;let Q=await super.register(A);if(!this.context)throw Error("LinkPlugin context was not initialized during register()");return A.getJobQueueService().registerHandler("link-capture",new RY0(this.logger.child("LinkCaptureJobHandler"),this.context,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0),this.id),Q}async interceptCreate(A,Q,w){if(A.content)try{let f=this.adapter.fromMarkdown(A.content).metadata,Y=typeof f?.title==="string"?f.title:void 0,X=typeof f?.status==="string"?f.status:void 0,W=this.extractFirstUrl(A.content);if(Y&&X&&W){let H=Z1(W)||Z1(Y)||`${A.entityType}-${Date.now()}`,K=new Date().toISOString();return{kind:"handled",result:{success:!0,data:{entityId:(await w.entityService.createEntity({entity:{id:H,entityType:A.entityType,content:A.content,metadata:{title:Y,status:X},created:K,updated:K}})).entityId,status:"created"}}}}}catch{}let B=A.url??this.extractFirstUrl(A.content,A.prompt,A.title);if(B){if(!this.shell)throw Error("LinkPlugin shell was not initialized during register()");try{let $=await this.createPendingLink(B,A.title,Q,w),f=await this.shell.getJobQueueService().enqueue({type:"link-capture",data:{url:B,metadata:{interfaceId:Q.interfaceType,userId:Q.userId,...Q.channelId?{channelId:Q.channelId}:{},...Q.channelName?{channelName:Q.channelName}:{},timestamp:new Date().toISOString()}},options:{source:this.id,metadata:{operationType:"data_processing",pluginId:this.id,interfaceType:Q.interfaceType,...Q.channelId?{channelId:Q.channelId}:{}}}});return{kind:"handled",result:{success:!0,data:{entityId:$,status:"generating",jobId:f}}}}catch($){return{kind:"handled",result:{success:!1,error:$ instanceof Error?$.message:"Failed to queue link capture job"}}}}if(A.content)return{kind:"handled",result:{success:!1,error:"Direct link creation requires full link markdown/frontmatter, or provide a URL to capture."}};if(A.prompt)return{kind:"handled",result:{success:!1,error:"Link creation requires a URL in the prompt, content, or title, or full link markdown content for direct creation."}};return{kind:"continue",input:A}}createGenerationHandler(A){return new RY0(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:oe1,"link-list":se1,"link-detail":ae1}}getDataSources(){return[new yo0(this.logger.child("LinksDataSource"))]}async onRegister(A){this.unregisterAtprotoProjection=A8.getInstance().register(Eo0()),A.eval.registerHandler("extractContent",async(Q)=>{let{url:w}=CKw.parse(Q),$=await new zy(this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0).fetch(w);if(!$.success)return{success:!1,error:$.error,errorType:$.errorType};return A.ai.generate({templateName:"link:extraction",prompt:`Extract structured information from this webpage content:
6509
+ ${H.content}`:`The URL ${B} could not be fetched. Return success: false with error: "${H.error}"`,data:{url:B,hasContent:H.success},interfacePermissionGrant:"public"});if(this.logger.debug("AI extraction result",{result:K}),await w.report({progress:dQ.EXTRACT,total:100,message:"Processing extraction results"}),K.success===!1||!K.title||!K.description||!K.summary){let q=K.title||new URL(B).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:B}),await w.report({progress:dQ.SAVE,total:100,message:"Saving link as pending"});let b=this.linkAdapter.createLinkContent({status:"pending",title:q,url:B,description:K.description,summary:K.summary,domain:new URL(B).hostname,capturedAt:W,source:X}),I=await Vf({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:b,metadata:{status:"pending",title:q}}});return await w.report({progress:dQ.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:I.entityId,title:q,url:B,status:"pending"}}await w.report({progress:dQ.SAVE,total:100,message:`Saving link: "${K.title}"`});let U=this.linkAdapter.createLinkContent({status:"draft",title:K.title,url:B,description:K.description,summary:K.summary,domain:new URL(B).hostname,capturedAt:W,source:X}),D=await Vf({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:U,metadata:{status:"draft",title:K.title}}});return await w.report({progress:dQ.COMPLETE,total:100,message:`Link captured: "${K.title}"`}),{success:!0,entityId:D.entityId,title:K.title,url:B,status:"draft"}}catch(f){return this.logger.error("Link capture job failed",{error:f,jobId:Q,data:A}),Q$.failure(f)}}resolveSource(A){let Q=A?.channelId,w=A?.channelName;if(Q)return{ref:`matrix:${Q}`,label:w??Q};let B=A?.interfaceId??"cli";return{ref:`${B}:local`,label:B.toUpperCase()}}summarizeDataForLog(A){return{url:A.url,interfaceId:A.metadata?.interfaceId}}}async function te1({entity:A,config:Q}){let w=wP.parse(A),{frontmatter:B,summary:$}=Gy.parseLinkContent(w.content);return{$type:"ai.rizom.brain.link",title:B.title,url:B.url,...B.description&&{description:B.description},...$&&{summary:$},domain:B.domain,capturedAt:B.capturedAt,source:B.source,...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"link",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function Eo0(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:L6["ai.rizom.brain.link"],validate:!1,buildRecord:te1}}var ee1={name:"@brains/link",version:"0.2.0-alpha.143",description:"Web content capture plugin with AI-powered extraction and structured storage",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var CKw=Z.object({url:Z.url()});class To0 extends nQ{entityType=Gy.entityType;schema=wP;adapter=Gy;shell;unregisterAtprotoProjection;constructor(A={}){super("link",ee1,A,Ro0)}async register(A){this.shell=A;let Q=await super.register(A);if(!this.context)throw Error("LinkPlugin context was not initialized during register()");return A.getJobQueueService().registerHandler("link-capture",new RY0(this.logger.child("LinkCaptureJobHandler"),this.context,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0),this.id),Q}async interceptCreate(A,Q,w){if(A.content)try{let f=this.adapter.fromMarkdown(A.content).metadata,Y=typeof f?.title==="string"?f.title:void 0,X=typeof f?.status==="string"?f.status:void 0,W=this.extractFirstUrl(A.content);if(Y&&X&&W){let H=Z1(W)||Z1(Y)||`${A.entityType}-${Date.now()}`,K=new Date().toISOString();return{kind:"handled",result:{success:!0,data:{entityId:(await w.entityService.createEntity({entity:{id:H,entityType:A.entityType,content:A.content,metadata:{title:Y,status:X},created:K,updated:K}})).entityId,status:"created"}}}}}catch{}let B=A.url??this.extractFirstUrl(A.content,A.prompt,A.title);if(B){if(!this.shell)throw Error("LinkPlugin shell was not initialized during register()");try{let $=await this.createPendingLink(B,A.title,Q,w),f=await this.shell.getJobQueueService().enqueue({type:"link-capture",data:{url:B,metadata:{interfaceId:Q.interfaceType,userId:Q.userId,...Q.channelId?{channelId:Q.channelId}:{},...Q.channelName?{channelName:Q.channelName}:{},timestamp:new Date().toISOString()}},options:{source:this.id,metadata:{operationType:"data_processing",pluginId:this.id,interfaceType:Q.interfaceType,...Q.channelId?{channelId:Q.channelId}:{}}}});return{kind:"handled",result:{success:!0,data:{entityId:$,status:"generating",jobId:f}}}}catch($){return{kind:"handled",result:{success:!1,error:$ instanceof Error?$.message:"Failed to queue link capture job"}}}}if(A.content)return{kind:"handled",result:{success:!1,error:"Direct link creation requires full link markdown/frontmatter, or provide a URL to capture."}};if(A.prompt)return{kind:"handled",result:{success:!1,error:"Link creation requires a URL in the prompt, content, or title, or full link markdown content for direct creation."}};return{kind:"continue",input:A}}createGenerationHandler(A){return new RY0(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:oe1,"link-list":se1,"link-detail":ae1}}getDataSources(){return[new yo0(this.logger.child("LinksDataSource"))]}async onRegister(A){this.unregisterAtprotoProjection=A8.getInstance().register(Eo0()),A.eval.registerHandler("extractContent",async(Q)=>{let{url:w}=CKw.parse(Q),$=await new zy(this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0).fetch(w);if(!$.success)return{success:!1,error:$.error,errorType:$.errorType};return A.ai.generate({templateName:"link:extraction",prompt:`Extract structured information from this webpage content:
6510
6510
 
6511
6511
  ${$.content}`,data:{url:w,hasContent:!0},interfacePermissionGrant:"public"})})}async createPendingLink(A,Q,w,B){let $=MF.generateEntityId(A),f=new URL(A),Y=new Date().toISOString(),X=Q?.trim()?Q.trim():f.hostname,W=this.adapter.createLinkContent({status:"pending",title:X,url:A,description:"Link capture is in progress.",summary:`Pending link capture for ${A}.`,domain:f.hostname,capturedAt:Y,source:this.resolveSource(w)});return(await bk({entityService:B.entityService,entity:{id:$,entityType:"link",content:W,metadata:{status:"pending",title:X},created:Y,updated:Y}})).entityId}resolveSource(A){if(A.channelId)return{ref:`matrix:${A.channelId}`,label:A.channelName??A.channelId};return{ref:`${A.interfaceType}:local`,label:A.interfaceType.toUpperCase()}}extractFirstUrl(...A){for(let Q of A){if(!Q)continue;let[w]=MF.extractUrls(Q);if(w)return w}return}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function A02(A={}){return new To0(A)}var BP=A02;N0();var gKw=Z.object({conversationId:Z.string().optional(),interfaceId:Z.string().optional(),userId:Z.string().optional(),messageId:Z.string().optional(),timestamp:Z.string().optional()}),xw$=Z.object({id:Z.string().optional(),metadata:gKw.optional()});wA();N0();NB();N0();wA();var Q02=Z.enum(["generating","draft","published","failed"]),w02=Z.enum(["generating","draft","published","failed"]),W7=Z.object({title:Z.string(),slug:Z.string().optional(),status:Q02,publishedAt:Z.string().datetime().optional(),description:Z.string(),year:Z.number(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional(),url:Z.string().url().optional()}),yKw=W7.pick({title:!0,status:!0,publishedAt:!0,year:!0}).extend({slug:Z.string(),error:Z.string().optional()}),EKw=Z.object({title:Z.string(),status:w02,publishedAt:Z.string().datetime().optional(),year:Z.number(),slug:Z.string(),error:Z.string().optional()}),TKw=Z.object({title:Z.string(),slug:Z.string().optional(),status:w02,publishedAt:Z.string().datetime().optional(),description:Z.string(),year:Z.number(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional(),url:Z.string().url().optional()}),OF=LQ.extend({entityType:Z.literal("project"),metadata:EKw}),vY0=Z.object({context:Z.string(),problem:Z.string(),solution:Z.string(),outcome:Z.string()}),Ko=OF.extend({frontmatter:TKw,body:Z.string(),structuredContent:vY0.optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional()}),SKw=Ko.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),mKw=Ko.extend({url:Z.string(),typeLabel:Z.string(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});wA();K2();o5();class So0 extends G6{constructor(){super(vY0,{title:"Project",mappings:[{key:"context",label:"Context",type:"string"},{key:"problem",label:"Problem",type:"string"},{key:"solution",label:"Solution",type:"string"},{key:"outcome",label:"Outcome",type:"string"}]})}}var mo0=new So0;class uo0 extends C2{constructor(){super({entityType:"project",purpose:"A project record in the user's portfolio.",schema:OF,frontmatterSchema:W7,supportsCoverImage:!0,bodyFormatter:mo0})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,W7),B={...w,slug:w.slug??A.metadata.slug};return this.buildMarkdown(Q,B)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,W7),w=Q.slug??Z1(Q.title);return{content:A,entityType:"project",metadata:{title:Q.title,slug:w,status:Q.status,publishedAt:Q.publishedAt,year:Q.year}}}parseProjectFrontmatter(A){return this.parseFrontMatter(A.content,W7)}parseStructuredContent(A){return mo0.parse(this.extractBody(A.content))}createProjectContent(A,Q){let w=mo0.format(Q);return this.buildMarkdown(w,A)}buildStub(A){let Q=new Date().getUTCFullYear(),w={title:A.title,slug:A.id,status:"generating",description:"",year:Q};return{content:this.buildMarkdown("",w),metadata:{title:A.title,slug:A.id,status:"generating",year:Q}}}}var $P=new uo0;N0();var co0=Z.looseObject({});import{jsxDEV as cZ,Fragment as cKw}from"preact/jsx-dev-runtime";var uKw=({project:A})=>{let{frontmatter:Q,url:w,coverImageUrl:B}=A;return cZ(U6,{href:w,children:[B&&cZ("img",{src:B,alt:Q.title,className:"w-full h-56 object-cover rounded-md mb-4"},void 0,!1,void 0,this),cZ($7,{children:Q.title},void 0,!1,void 0,this),cZ("p",{className:"text-theme leading-relaxed",children:Q.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},lo0=({projects:A,pageTitle:Q,pagination:w,baseUrl:B="/projects"})=>{let $=Q??"Projects",f=w?.totalItems??A.length,Y=`Browse all ${f} ${f===1?"project":"projects"}`;return cZ(cKw,{children:[cZ(lQ,{title:$,description:Y},void 0,!1,void 0,this),cZ("div",{className:"project-list bg-theme",children:cZ("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[cZ("h1",{className:"text-4xl font-bold text-heading mb-12",children:$},void 0,!1,void 0,this),cZ("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:A.map((X)=>cZ(uKw,{project:X},X.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&cZ("div",{className:"mt-12",children:cZ(iq,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:B},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as l6,Fragment as B02}from"preact/jsx-dev-runtime";var lKw=({prevProject:A,nextProject:Q})=>{if(!A&&!Q)return null;return l6("nav",{className:"pt-12 mt-12 border-t border-theme-muted",children:l6("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[A?l6(U6,{href:A.url,variant:"compact",children:[l6("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Previous"},void 0,!1,void 0,this),l6("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:A.metadata.title},void 0,!1,void 0,this)]},void 0,!0,void 0,this):l6("div",{},void 0,!1,void 0,this),Q&&l6(U6,{href:Q.url,variant:"compact",className:"md:text-right",children:[l6("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Next"},void 0,!1,void 0,this),l6("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:Q.metadata.title},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},hY0=({title:A,content:Q})=>{if(!Q)return null;return l6("section",{className:"mb-12",children:[l6("h2",{className:"text-2xl font-bold text-heading mb-4",children:A},void 0,!1,void 0,this),l6(V9,{markdown:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},po0=({project:A,prevProject:Q,nextProject:w})=>{let{frontmatter:B,structuredContent:$,metadata:f,coverImageUrl:Y}=A,X=A.ogImageUrl??Y;return l6(B02,{children:[l6(lQ,{title:B.title,description:B.description,...X?{ogImage:X}:{},ogType:"article"},void 0,!1,void 0,this),l6("article",{className:"project-detail",children:l6("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:l6("div",{className:"max-w-3xl mx-auto",children:[Y&&A.coverImageWidth&&A.coverImageHeight&&l6(lq,{src:Y,alt:B.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8 shadow-lg"},void 0,!1,void 0,this),l6("h1",{className:"text-4xl md:text-5xl font-bold text-heading leading-tight tracking-tight mb-4",children:B.title},void 0,!1,void 0,this),l6("div",{className:"flex flex-wrap items-center gap-4 text-theme-muted mb-8",children:[l6("span",{className:"text-sm",children:f.year},void 0,!1,void 0,this),B.url&&l6(B02,{children:[l6("span",{className:"text-theme-muted",children:"|"},void 0,!1,void 0,this),l6("a",{href:B.url,target:"_blank",rel:"noopener noreferrer",className:"text-brand hover:text-brand-dark transition-colors",children:"View Project"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),l6("p",{className:"text-lg text-theme mb-12 leading-relaxed",children:B.description},void 0,!1,void 0,this),$&&l6("div",{className:"case-study",children:[l6(hY0,{title:"Context",content:$.context},void 0,!1,void 0,this),l6(hY0,{title:"Problem",content:$.problem},void 0,!1,void 0,this),l6(hY0,{title:"Solution",content:$.solution},void 0,!1,void 0,this),l6(hY0,{title:"Outcome",content:$.outcome},void 0,!1,void 0,this)]},void 0,!0,void 0,this),l6(lKw,{prevProject:Q,nextProject:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};N0();wA();var pKw=Z.object({title:Z.string().max(80).describe("A clear, compelling project title (3-8 words). Should capture the essence of the project."),description:Z.string().describe("A 1-2 sentence summary of the project for portfolio cards. Focus on the core value delivered."),context:Z.string().describe("Background information: Who was the client/user? What was the situation? What constraints existed? (2-4 paragraphs)"),problem:Z.string().describe("The challenge: What specific problem needed solving? What were the pain points? (2-3 paragraphs)"),solution:Z.string().describe("The approach: What was built? What technologies/methods were used? How did it work? (3-5 paragraphs)"),outcome:Z.string().describe("The results: What impact did this have? What metrics improved? What was learned? (2-3 paragraphs)")}),io0=i1({name:"portfolio:generation",description:"Template for AI to generate portfolio project case studies",schema:pKw,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create a professional portfolio case study based on REAL project information.
6512
6512
 
@@ -6682,7 +6682,7 @@ Use the project request as the primary source of truth. If retrieved knowledge c
6682
6682
  font: 10px/1.45 var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
6683
6683
  }
6684
6684
  .printable-footer a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
6685
- `}},void 0,!1,void 0,this),_9("section",{className:"project-shell",children:[_9("header",{className:"project-hero",children:[_9("div",{className:"project-index",children:[Q.brandLabel&&_9("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&_9("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_9("div",{className:"project-title-panel",children:[_9("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),_9("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&_9("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),_9("div",{className:"printable-meta",children:[Q.year&&_9("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&_9("span",{children:Q.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Q.coverImageUrl&&_9("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),_9(V9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.url)||Boolean(Q.brandLabel))&&_9("footer",{className:"printable-footer",children:[_9("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?_9("a",{href:Q.canonicalUrl??Q.url,children:Q.canonicalUrl??Q.url},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var eKw=26214400,AUw=60000;class ro0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??kU}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==yY0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let w=QUw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await oKw(tKw(aKw(),"brain-project-printable-"));try{let $=await vZ({outputDir:B,mediaPath:`/_media/printable/project/${Q.id}`,template:Y02,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await hZ({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:eKw,timeoutMs:AUw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${wUw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await sKw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=j6(A.content),w=W7.parse(Q);if(!w.coverImageId)return;let B=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return B?.content.startsWith("data:image/")?B.content:void 0}}function QUw(A,Q={}){let{frontmatter:w,content:B}=j6(A.content),$=W7.parse(w);return{title:$.title,body:B,...$.description?{description:$.description}:{},year:$.year,...$.publishedAt?{publishedAt:$.publishedAt}:{},...$.url?{url:$.url,canonicalUrl:$.url}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function wUw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.title)}S9();K2();N0();import{jsxDEV as fUw}from"preact/jsx-dev-runtime";var EY0="og-image",BUw="portfolio:og-image",X02=Z.object({title:Z.string().min(1),description:Z.string().optional(),year:Z.number().optional(),brandLabel:Z.string().optional(),coverImageUrl:Z.string().optional()}),Z02={name:BUw,pluginId:"portfolio",schema:X02,renderers:{image:$Uw}};function $Uw(A){let Q=X02.parse(A);return fUw(cq,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class oo0{metadata={outputEntityType:"image",targetField:"ogImageId"};context;deps;constructor(A,Q={}){this.context=A,this.deps=Q}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==EY0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w}=j6(Q.content),B=W7.parse(w),$=this.resolveBrandLabel(),f=await this.resolveCoverImageUrl(B.coverImageId),Y={title:B.title,...B.description?{description:B.description}:{},year:B.year,...f?{coverImageUrl:f}:{},...$?{brandLabel:$}:{}};return{type:"image",data:await ij({mediaPath:`/_media/og/project/${Q.id}`,template:Z02,content:Y,title:Y.title,themeMode:"light",themeCSS:this.context.themeCSS,tmpPrefix:"brain-project-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${YUw(Q)}-og.png`}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){if(!A)return;let Q=await this.context.entityService.getEntity({entityType:"image",id:A});return Q?.content.startsWith("data:image/")?Q.content:void 0}}function YUw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.title)}var W02={name:"@brains/portfolio",version:"0.2.0-alpha.142",description:"Portfolio showcase for projects and case studies",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var ZUw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),WUw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),H02=Z.enum(["generating","draft","published","failed"]),HUw=Z.object({title:Z.string(),slug:Z.string().optional(),status:H02,publishedAt:Z.string().optional(),description:Z.string(),year:Z.number(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional(),url:Z.url().optional()}),KUw=Z.object({title:Z.string(),status:H02,publishedAt:Z.string().optional(),year:Z.number(),slug:Z.string(),error:Z.string().optional()}),UUw=Z.object({context:Z.string(),problem:Z.string(),solution:Z.string(),outcome:Z.string()}),TY0=Z.object({id:Z.string(),entityType:Z.literal("project"),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:WUw,metadata:KUw,contentHash:Z.string(),frontmatter:HUw,body:Z.string(),structuredContent:UUw.optional(),url:Z.string(),typeLabel:Z.string(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),DUw=Z.object({projects:Z.array(TY0),pageTitle:Z.string().optional(),pagination:ZUw.nullable(),baseUrl:Z.string().optional()}),GUw=Z.object({prompt:Z.string(),year:Z.number()});function zUw(A,Q){for(let w of[A,Q]){let B=w?.match(/\b(19\d{2}|20\d{2})\b/);if(B?.[1])return Number(B[1])}return null}class so0 extends nQ{entityType="project";schema=OF;adapter=$P;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",W02,A,co0)}async interceptCreate(A,Q,w){if(!A.prompt||A.content)return{kind:"continue",input:A};let B=zUw(A.title,A.prompt);if(!B)return{kind:"continue",input:A};return{kind:"handled",result:{success:!0,data:{status:"generating",jobId:await w.jobs.enqueue({type:"project:generation",data:{prompt:A.prompt,...A.title?{title:A.title}:{},year:B},toolContext:Q,options:{source:this.id,metadata:{operationType:"content_operations"}}})}}}}createGenerationHandler(A){return new CY0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":i1({name:"project-list",description:"Portfolio project list page template",schema:DUw,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:lo0}}),"project-detail":i1({name:"project-detail",description:"Individual project case study template",schema:Z.object({project:TY0,prevProject:TY0.nullable(),nextProject:TY0.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:po0}}),generation:io0}}getDataSources(){return[new gY0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",yY0,new ro0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",EY0,new oo0(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=A8.getInstance().register(no0())}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}registerEvalHandlers(A){A.eval.registerHandler("generateProject",async(Q)=>{let w=GUw.parse(Q);return A.ai.generate({prompt:do0(w),templateName:"portfolio:generation"})})}deferPublishRegistration(A){let Q={name:"internal",publish:async()=>({id:"internal"})};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"project",provider:Q,config:{executionMode:"provider"}}}),{success:!0}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:w,entityId:B}=Q.payload;if(w!=="project")return{success:!0};try{let $=await A.entityService.getEntity({entityType:"project",id:B});if(!$)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:`Project not found: ${B}`}}),{success:!0};if($.metadata.status==="published")return{success:!0};let f=o2($.content,W7),Y=new Date().toISOString(),X=F7(f.content,{...f.metadata,status:"published",publishedAt:Y});await A.entityService.updateEntity({entity:{...$,content:X,metadata:{...$.metadata,status:"published",publishedAt:Y}}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:w,entityId:B,publishedAt:Y}})}catch($){await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:mA($)}})}return{success:!0}})}}function ao0(A={}){return new so0(A)}wA();N0();N0();var qUw=Z.enum(["public","shared","restricted"]),K02=Z.object({includeEntityTypes:Z.array(Z.string()).default([]),minRelevanceScore:Z.number().min(0).max(1).default(0.5),mergeSimilarityThreshold:Z.number().min(0).max(1).default(0.85),autoMerge:Z.boolean().default(!0),extractableStatuses:Z.array(Z.string()).default(["published"]),enableAutoExtraction:Z.boolean().default(!0),extractionVisibility:qUw.default("public"),sourceChangeBatchDelayMs:Z.number().int().min(0).default(1000)});wA();N0();wA();var xB$=Z.object({}),bUw=Z.record(Z.string(),Z.unknown()).transform(()=>({})),qy=LQ.extend({entityType:Z.literal("topic"),metadata:bUw}),RB$=Z.object({content:Z.string()}),U02=Z.object({title:Z.string().describe("Topic title")});var fP="topics",p6="topic",to0="topics-projection",D02="topic:project",SY0="topics-plugin",G02="topics:batch-completed",z02="topics-source-batch";class PU extends C2{constructor(){super({entityType:p6,purpose:"A recurring theme or subject derived from the user's content.",schema:qy,frontmatterSchema:U02})}buildFrontmatter(A){return{title:A}}toMarkdown(A){let Q=this.parseTopicBody(A.content);return this.buildMarkdown(Q.content,this.buildFrontmatter(Q.title))}fromMarkdown(A){return{content:A,entityType:p6}}extractMetadata(A){return{}}generateFrontMatter(A){let Q=this.parseTopicBody(A.content),B=this.buildMarkdown("",this.buildFrontmatter(Q.title)).match(/^---\n[\s\S]*?\n---/);return B?B[0]:""}parseTopicBody(A){if(A.startsWith("---"))try{let Q=this.parseFrontmatter(A);return{content:this.extractBody(A).replace(/\n*## Sources[\s\S]*$/,"").trim(),formatted:A,title:Q.title}}catch{return{content:A,formatted:A,title:"Unknown Topic"}}return{content:A,formatted:A,title:"Unknown Topic"}}createTopicBody(A){return this.buildMarkdown(A.content,this.buildFrontmatter(A.title))}}wA();N0();N0();var VUw=Z.object({title:Z.string().max(100),content:Z.string(),relevanceScore:Z.number().min(0).max(1)}),q02=Z.array(VUw);var IUw=Z.object({topics:q02}),b02=i1({name:"topics:extraction",description:"Extract topics from conversation text",dataSourceId:"shell:ai-content",schema:IUw,basePrompt:`You are an expert at analyzing content and extracting key topics.
6685
+ `}},void 0,!1,void 0,this),_9("section",{className:"project-shell",children:[_9("header",{className:"project-hero",children:[_9("div",{className:"project-index",children:[Q.brandLabel&&_9("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&_9("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_9("div",{className:"project-title-panel",children:[_9("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),_9("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&_9("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),_9("div",{className:"printable-meta",children:[Q.year&&_9("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&_9("span",{children:Q.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Q.coverImageUrl&&_9("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),_9(V9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.url)||Boolean(Q.brandLabel))&&_9("footer",{className:"printable-footer",children:[_9("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?_9("a",{href:Q.canonicalUrl??Q.url,children:Q.canonicalUrl??Q.url},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var eKw=26214400,AUw=60000;class ro0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??kU}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==yY0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let w=QUw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await oKw(tKw(aKw(),"brain-project-printable-"));try{let $=await vZ({outputDir:B,mediaPath:`/_media/printable/project/${Q.id}`,template:Y02,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await hZ({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:eKw,timeoutMs:AUw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${wUw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await sKw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=j6(A.content),w=W7.parse(Q);if(!w.coverImageId)return;let B=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return B?.content.startsWith("data:image/")?B.content:void 0}}function QUw(A,Q={}){let{frontmatter:w,content:B}=j6(A.content),$=W7.parse(w);return{title:$.title,body:B,...$.description?{description:$.description}:{},year:$.year,...$.publishedAt?{publishedAt:$.publishedAt}:{},...$.url?{url:$.url,canonicalUrl:$.url}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function wUw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.title)}S9();K2();N0();import{jsxDEV as fUw}from"preact/jsx-dev-runtime";var EY0="og-image",BUw="portfolio:og-image",X02=Z.object({title:Z.string().min(1),description:Z.string().optional(),year:Z.number().optional(),brandLabel:Z.string().optional(),coverImageUrl:Z.string().optional()}),Z02={name:BUw,pluginId:"portfolio",schema:X02,renderers:{image:$Uw}};function $Uw(A){let Q=X02.parse(A);return fUw(cq,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class oo0{metadata={outputEntityType:"image",targetField:"ogImageId"};context;deps;constructor(A,Q={}){this.context=A,this.deps=Q}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==EY0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w}=j6(Q.content),B=W7.parse(w),$=this.resolveBrandLabel(),f=await this.resolveCoverImageUrl(B.coverImageId),Y={title:B.title,...B.description?{description:B.description}:{},year:B.year,...f?{coverImageUrl:f}:{},...$?{brandLabel:$}:{}};return{type:"image",data:await ij({mediaPath:`/_media/og/project/${Q.id}`,template:Z02,content:Y,title:Y.title,themeMode:"light",themeCSS:this.context.themeCSS,tmpPrefix:"brain-project-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${YUw(Q)}-og.png`}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){if(!A)return;let Q=await this.context.entityService.getEntity({entityType:"image",id:A});return Q?.content.startsWith("data:image/")?Q.content:void 0}}function YUw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.title)}var W02={name:"@brains/portfolio",version:"0.2.0-alpha.143",description:"Portfolio showcase for projects and case studies",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var ZUw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),WUw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),H02=Z.enum(["generating","draft","published","failed"]),HUw=Z.object({title:Z.string(),slug:Z.string().optional(),status:H02,publishedAt:Z.string().optional(),description:Z.string(),year:Z.number(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional(),url:Z.url().optional()}),KUw=Z.object({title:Z.string(),status:H02,publishedAt:Z.string().optional(),year:Z.number(),slug:Z.string(),error:Z.string().optional()}),UUw=Z.object({context:Z.string(),problem:Z.string(),solution:Z.string(),outcome:Z.string()}),TY0=Z.object({id:Z.string(),entityType:Z.literal("project"),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:WUw,metadata:KUw,contentHash:Z.string(),frontmatter:HUw,body:Z.string(),structuredContent:UUw.optional(),url:Z.string(),typeLabel:Z.string(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),DUw=Z.object({projects:Z.array(TY0),pageTitle:Z.string().optional(),pagination:ZUw.nullable(),baseUrl:Z.string().optional()}),GUw=Z.object({prompt:Z.string(),year:Z.number()});function zUw(A,Q){for(let w of[A,Q]){let B=w?.match(/\b(19\d{2}|20\d{2})\b/);if(B?.[1])return Number(B[1])}return null}class so0 extends nQ{entityType="project";schema=OF;adapter=$P;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",W02,A,co0)}async interceptCreate(A,Q,w){if(!A.prompt||A.content)return{kind:"continue",input:A};let B=zUw(A.title,A.prompt);if(!B)return{kind:"continue",input:A};return{kind:"handled",result:{success:!0,data:{status:"generating",jobId:await w.jobs.enqueue({type:"project:generation",data:{prompt:A.prompt,...A.title?{title:A.title}:{},year:B},toolContext:Q,options:{source:this.id,metadata:{operationType:"content_operations"}}})}}}}createGenerationHandler(A){return new CY0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":i1({name:"project-list",description:"Portfolio project list page template",schema:DUw,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:lo0}}),"project-detail":i1({name:"project-detail",description:"Individual project case study template",schema:Z.object({project:TY0,prevProject:TY0.nullable(),nextProject:TY0.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:po0}}),generation:io0}}getDataSources(){return[new gY0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",yY0,new ro0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",EY0,new oo0(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=A8.getInstance().register(no0())}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}registerEvalHandlers(A){A.eval.registerHandler("generateProject",async(Q)=>{let w=GUw.parse(Q);return A.ai.generate({prompt:do0(w),templateName:"portfolio:generation"})})}deferPublishRegistration(A){let Q={name:"internal",publish:async()=>({id:"internal"})};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"project",provider:Q,config:{executionMode:"provider"}}}),{success:!0}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:w,entityId:B}=Q.payload;if(w!=="project")return{success:!0};try{let $=await A.entityService.getEntity({entityType:"project",id:B});if(!$)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:`Project not found: ${B}`}}),{success:!0};if($.metadata.status==="published")return{success:!0};let f=o2($.content,W7),Y=new Date().toISOString(),X=F7(f.content,{...f.metadata,status:"published",publishedAt:Y});await A.entityService.updateEntity({entity:{...$,content:X,metadata:{...$.metadata,status:"published",publishedAt:Y}}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:w,entityId:B,publishedAt:Y}})}catch($){await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:mA($)}})}return{success:!0}})}}function ao0(A={}){return new so0(A)}wA();N0();N0();var qUw=Z.enum(["public","shared","restricted"]),K02=Z.object({includeEntityTypes:Z.array(Z.string()).default([]),minRelevanceScore:Z.number().min(0).max(1).default(0.5),mergeSimilarityThreshold:Z.number().min(0).max(1).default(0.85),autoMerge:Z.boolean().default(!0),extractableStatuses:Z.array(Z.string()).default(["published"]),enableAutoExtraction:Z.boolean().default(!0),extractionVisibility:qUw.default("public"),sourceChangeBatchDelayMs:Z.number().int().min(0).default(1000)});wA();N0();wA();var xB$=Z.object({}),bUw=Z.record(Z.string(),Z.unknown()).transform(()=>({})),qy=LQ.extend({entityType:Z.literal("topic"),metadata:bUw}),RB$=Z.object({content:Z.string()}),U02=Z.object({title:Z.string().describe("Topic title")});var fP="topics",p6="topic",to0="topics-projection",D02="topic:project",SY0="topics-plugin",G02="topics:batch-completed",z02="topics-source-batch";class PU extends C2{constructor(){super({entityType:p6,purpose:"A recurring theme or subject derived from the user's content.",schema:qy,frontmatterSchema:U02})}buildFrontmatter(A){return{title:A}}toMarkdown(A){let Q=this.parseTopicBody(A.content);return this.buildMarkdown(Q.content,this.buildFrontmatter(Q.title))}fromMarkdown(A){return{content:A,entityType:p6}}extractMetadata(A){return{}}generateFrontMatter(A){let Q=this.parseTopicBody(A.content),B=this.buildMarkdown("",this.buildFrontmatter(Q.title)).match(/^---\n[\s\S]*?\n---/);return B?B[0]:""}parseTopicBody(A){if(A.startsWith("---"))try{let Q=this.parseFrontmatter(A);return{content:this.extractBody(A).replace(/\n*## Sources[\s\S]*$/,"").trim(),formatted:A,title:Q.title}}catch{return{content:A,formatted:A,title:"Unknown Topic"}}return{content:A,formatted:A,title:"Unknown Topic"}}createTopicBody(A){return this.buildMarkdown(A.content,this.buildFrontmatter(A.title))}}wA();N0();N0();var VUw=Z.object({title:Z.string().max(100),content:Z.string(),relevanceScore:Z.number().min(0).max(1)}),q02=Z.array(VUw);var IUw=Z.object({topics:q02}),b02=i1({name:"topics:extraction",description:"Extract topics from conversation text",dataSourceId:"shell:ai-content",schema:IUw,basePrompt:`You are an expert at analyzing content and extracting key topics.
6686
6686
 
6687
6687
  Analyze the provided content and extract meaningful topics discussed.
6688
6688
 
@@ -6785,13 +6785,13 @@ ${A.incomingTopic.content}`})}}function xUw(A){if(A.length===0)return"";return A
6785
6785
 
6786
6786
  ${Q.content}`}).join(`
6787
6787
 
6788
- `)}async function YP(A,Q,w,B={}){if(A.length===0)return{created:0,merged:0,skipped:0,batches:0};let $=B.minRelevanceScore??0,f=B.autoMerge??!1,Y=B.mergeSimilarityThreshold??0.85,X=B.targetVisibility??"public",W=M02(A),H=new MU(Q.entityService,w),K=B.topicMergeSynthesizer??new $s0(Q,w),U=await pY0(Q.entityService,void 0,X),D=new Map,q=0,b=0,I=0;for(let L of W){w.info(`Processing batch of ${L.length} entities`);let N=xUw(L),k=iY0({entityTitle:`Batch of ${L.length} entities`,entityType:"batch",content:N,existingTopicTitles:U});try{let R=(await Q.ai.generate({prompt:k,templateName:"topics:extraction"})).topics.filter((h)=>h.relevanceScore>=$);for(let h of R)try{if(f){let S=await H.findMergeCandidate({incoming:h,threshold:Y,additionalCandidates:Array.from(D.values()),targetVisibility:X});if(S){let p=await K.synthesize({existingTopic:S.topic,incomingTopic:h}),e=await H.applySynthesizedMerge({existingId:S.topic.id,synthesized:{...p,title:S.title},visibility:X});if(!e)throw Error(`Failed to merge topic: ${h.title}`);D.set(e.id,e),b++;continue}}let P=H.getTopicIdForTitle(h.title,X);if(D.has(P)){I++;continue}let E=await H.createTopicOptimistic({title:h.title,content:h.content,visibility:X});if(E.topic)D.set(E.topic.id,E.topic);if(E.created)q++;else I++}catch(P){w.error("Topic batch item failed",{title:h.title,error:mA(P)})}}catch(x){w.error("Batch topic extraction failed",{batchSize:L.length,promptChars:k.length,error:mA(x)})}}let V={created:q,merged:b,skipped:I,batches:W.length};if(q>0||b>0)await Q.messaging.send({type:G02,payload:V,broadcast:!0});return V}wA();N0();var RUw=Z.discriminatedUnion("mode",[Z.object({mode:Z.literal("derive"),reason:Z.string().optional()}),Z.object({mode:Z.literal("rebuild"),reason:Z.string().optional()}),Z.object({mode:Z.literal("source-batch"),minRelevanceScore:Z.number().min(0).max(1).optional()})]);class fs0{refs=new Map;add(A){this.refs.set(`${A.entityType}:${A.entityId}`,A)}drain(){let A=Array.from(this.refs.values());return this.refs.clear(),A}}function C02(A){let{context:Q,logger:w,config:B}=A;return{process:async($)=>{if($.mode==="derive")return await A.extractAllTopics(),{success:!0};if($.mode==="rebuild")return await A.rebuildAllTopics(),{success:!0};return vUw({context:Q,logger:w,config:B,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:$.minRelevanceScore??B.minRelevanceScore})},validateAndParse:($)=>{let f=RUw.safeParse($??{});return f.success?f.data:null}}}async function vUw(A){let Q=A.sourceBatch.drain(),w=await Promise.all(Q.map(async(H)=>({ref:H,entity:await A.context.entityService.getEntity({entityType:H.entityType,id:H.entityId})}))),B=0,$=0,f=0,Y=0,X=[];for(let{ref:H,entity:K}of w){if(!K){$++;continue}if(K.contentHash!==H.contentHash){B++;continue}if(!A.isEntityPublished(K)){f++;continue}if(!OV(K.visibility,A.config.extractionVisibility)){Y++;continue}X.push(K)}if(X.length===0)return{success:!0,sources:Q.length,created:0,merged:0,skipped:0,batches:0,stale:B,missing:$,unpublished:f,hidden:Y};let W=await YP(X,A.context,A.logger,{minRelevanceScore:A.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});return{success:!0,sources:Q.length,...W,stale:B,missing:$,unpublished:f,hidden:Y}}function g02(){return{priority:5,source:SY0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:fP}}}async function y02(A){let Q=await T02(A);if(Q.length===0){A.logger.info("No entities to extract topics from");return}A.logger.info(`Batch topic extraction: ${Q.length} entities`);let w=await YP(Q,A.context,A.logger,{minRelevanceScore:A.config.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});A.logger.info("Batch topic extraction complete",w)}async function E02(A){let Q=await T02(A),w=await Ys0(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",w)}async function Ys0(A,Q,w,B){let $=new MU(Q.entityService,w),f=await $.listTopics({visibility:B.extractionVisibility});for(let X of f)await $.deleteTopic(X.id);if(A.length===0)return{deleted:f.length,created:0,merged:0,skipped:0,batches:0};let Y=await YP(A,Q,w,{minRelevanceScore:B.minRelevanceScore,autoMerge:B.autoMerge,mergeSimilarityThreshold:B.mergeSimilarityThreshold,targetVisibility:B.extractionVisibility});return{deleted:f.length,...Y}}async function T02(A){let Q=hUw(A),w=[];for(let B of Q){let $=await A.context.entityService.listEntities({entityType:B,options:{filter:{visibilityScope:A.config.extractionVisibility}}});for(let f of $){if(!A.isEntityPublished(f))continue;w.push(f)}}return w}function hUw(A){return A.context.entityService.getEntityTypes().filter((w)=>A.shouldProcessEntityType(w))}var Iy=Z.object({entityType:Z.string(),content:Z.string(),metadata:Z.record(Z.string(),Z.unknown()).optional()}),CUw=Iy.extend({minRelevanceScore:Z.number().optional()}),gUw=Z.object({contentA:Iy,contentB:Iy,minRelevanceScore:Z.number().optional(),threshold:Z.number().min(0).max(1).optional()}),zo=Z.object({title:Z.string(),content:Z.string()}),yUw=Z.object({existingTopics:Z.array(zo),incomingTopic:zo,threshold:Z.number().optional()}),EUw=Z.object({existingTopics:Z.array(zo).default([]),incomingTopic:zo.extend({relevanceScore:Z.number().min(0).max(1).optional()}),threshold:Z.number().optional()}),TUw=Z.object({entities:Z.array(Iy).min(1),minRelevanceScore:Z.number().optional()}),SUw=Z.object({existingTopics:Z.array(zo).optional(),entities:Z.array(Iy)}),mUw=Z.object({entities:Z.array(Iy)});function Vy(A,Q=""){return{id:`eval${Q}-${Date.now()}`,entityType:A.entityType,content:A.content,contentHash:w6(A.content),visibility:"public",metadata:A.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}}function S02(A){return{title:A.title,relevanceScore:A.relevanceScore}}function uUw(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function cUw(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:uUw(Q)}]}}async function XP(A){let Q=await A.entityService.listEntities({entityType:p6});await Promise.all(Q.map((w)=>A.entityService.deleteEntity({entityType:p6,id:w.id})))}async function lUw(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise((w)=>setTimeout(w,100))}}function m02(A){let{context:Q,logger:w,config:B}=A,$=new Bs0(Q,w),f=async(Y,X,W="")=>{let H=Vy(Y,W);return $.extractFromEntity(H,X)};Q.eval.registerHandler("extractFromEntity",async(Y)=>{await XP(Q);let X=CUw.parse(Y),W=X.minRelevanceScore??B.minRelevanceScore,H=Vy(X);return(await $.extractFromEntity(H,W)).map((U)=>cUw(U,H))}),Q.eval.registerHandler("checkMergeSimilarity",async(Y)=>{await XP(Q);let X=gUw.parse(Y),W=X.minRelevanceScore??B.minRelevanceScore,H=X.threshold??B.mergeSimilarityThreshold,[K,U]=await Promise.all([f(X.contentA,W,"-a"),f(X.contentB,W,"-b")]),D=new MU(Q.entityService,w),q=[];for(let V of K){let L=await D.createTopic(V);if(L)q.push(L)}let b=(await Promise.all(U.map(async(V)=>{let L=await D.findMergeCandidate({incoming:V,threshold:H,additionalCandidates:q});if(!L)return null;return{incomingTitle:V.title,candidateTitle:L.title,candidateScore:L.score}}))).filter((V)=>V!==null),I=b.map((V)=>V.candidateTitle);return{topicsA:K.map(S02),topicsB:U.map(S02),matchingTitles:I,mergeCandidates:b,wouldMerge:b.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(Y)=>{await XP(Q);let X=yUw.parse(Y),W=X.threshold??B.mergeSimilarityThreshold,H=new MU(Q.entityService,w),K=[];for(let D of X.existingTopics){let q=await H.createTopic(D);if(q)K.push(q)}let U=await H.findMergeCandidate({incoming:{title:X.incomingTopic.title},threshold:W,additionalCandidates:K});return{found:U!==null,candidateTitle:U?.title,candidateScore:U?.score}}),Q.eval.registerHandler("processTopicWithAutoMerge",async(Y)=>{await XP(Q);let X=EUw.parse(Y),W=new MU(Q.entityService,w);for(let D of X.existingTopics)await W.createTopic({title:D.title,content:D.content});await lUw(Q);let H=Vy({entityType:"post",content:X.incomingTopic.content,metadata:{title:X.incomingTopic.title}},"-source"),K=await YP([H],Q,w,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:X.threshold??B.mergeSimilarityThreshold}),U=await Q.entityService.listEntities({entityType:p6});return{...K,topicCount:U.length,topics:U.map(Qs0)}}),Q.eval.registerHandler("rebuildTopics",async(Y)=>{await XP(Q);let X=SUw.parse(Y),W=new MU(Q.entityService,w);for(let D of X.existingTopics??[])await W.createTopic(D);let H=X.entities.map((D,q)=>Vy(D,`-rebuild-${q}`)),K=await Ys0(H,Q,w,B),U=await Q.entityService.listEntities({entityType:p6});return{...K,topicCount:U.length,topics:U.map(Qs0)}}),Q.eval.registerHandler("extractSequentially",async(Y)=>{await XP(Q);let X=TUw.parse(Y),W=X.minRelevanceScore??B.minRelevanceScore,H=new MU(Q.entityService,w),K=[];for(let[D,q]of X.entities.entries()){let b=Vy(q,`-sequential-${D}`),I=await $.extractFromEntity(b,W);for(let V of I)await H.createTopic({title:V.title,content:V.content});K.push({extractedTitles:I.map((V)=>V.title)})}let U=await Q.entityService.listEntities({entityType:p6});return{totalTopics:U.length,perEntity:K,topics:U.map(by)}}),Q.eval.registerHandler("batchExtract",async(Y)=>{await XP(Q);let W=mUw.parse(Y).entities.map((U,D)=>Vy(U,`-batch-${D}`)),H=await YP(W,Q,w,{minRelevanceScore:B.minRelevanceScore}),K=await Q.entityService.listEntities({entityType:p6});return{...H,topics:K.map(by)}})}var pUw=new PU;async function u02({entity:A,config:Q}){let w=qy.parse(A),B=pUw.parseTopicBody(w.content);return{$type:"ai.rizom.brain.topic",title:B.title,body:B.content,format:"text/markdown",...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"topic",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function Xs0(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:L6["ai.rizom.brain.topic"],validate:!1,buildRecord:u02}}var c02={name:"@brains/topics",version:"0.2.0-alpha.142",description:"Extract and manage topics from conversations",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},main:"./src/index.ts",private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var dUw=new PU,nUw=Z.looseObject({status:Z.unknown().optional()});class l02 extends nQ{entityType=p6;schema=qy;adapter=dUw;unregisterAtprotoProjection;sourceBatch=new fs0;constructor(A={}){super(fP,c02,A,K02)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:b02,"merge-synthesis":V02,"topic-list":I02,"topic-detail":J02}}getDataSources(){return[new ws0(this.logger.child("TopicsDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:to0,targetType:p6,job:{type:D02,handler:C02({context:A,logger:this.logger,config:this.config,extractAllTopics:()=>this.extractAllTopics(A),rebuildAllTopics:()=>this.rebuildAllTopics(A),sourceBatch:this.sourceBatch,isEntityPublished:(Q)=>this.isEntityPublished(Q)})},initialSync:{shouldEnqueue:async()=>!await qk(A,p6,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:g02()},sourceChange:{sourceTypes:this.config.includeEntityTypes,requireInitialSync:!0,jobData:(Q)=>{let w=Q.entity;if(!w)return null;if(!this.shouldProcessEntityType(w.entityType,A.entityService))return null;if(!this.isEntityPublished(w))return null;if(!OV(w.visibility,this.config.extractionVisibility))return null;return this.sourceBatch.add({entityId:w.id,entityType:w.entityType,contentHash:w.contentHash}),{mode:"source-batch"}},jobOptions:()=>({priority:5,source:SY0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:z02,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:fP}})}}]}async onRegister(A){A.insights.register("topic-distribution",k02()),_02({context:A,pluginId:this.id}),m02({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=A8.getInstance().register(Xs0())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(to0)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===p6)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let Q=nUw.safeParse(A.metadata),w=Q.success?Q.data.status:void 0;if(w===void 0||w===null)return!0;if(typeof w!=="string")return!1;return this.config.extractableStatuses.includes(w)}async extractAllTopics(A){await y02({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await E02({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function dY0(A={}){return new l02(A)}wA();N0();wA();var Zs0=Z.enum(["linkedin"]),p02=Z.enum(["linkedin"]),Ws0=Z.enum(["generating","draft","queued","published","failed"]),i02=Z.enum(["generating","draft","queued","published","failed"]),d02=Z.enum(["post","deck"]),rUw=Z.enum(["post","deck"]),n02=Z.object({id:Z.string().min(1).describe("Document entity ID")}),oUw=Z.object({id:Z.string().min(1)}),OU=Z.object({title:Z.string().describe("Short descriptive title (3-6 words) for file naming"),platform:Zs0.describe("Target platform"),status:Ws0,coverImageId:Z.string().optional().describe("Image entity ID for post image"),documents:Z.array(n02).optional().describe("Document attachments for publishing"),publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional().describe("ID from platform after publishing"),sourceEntityId:Z.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:d02.optional().describe("Source entity type (post, deck)")}),r02=OU.extend({platform:Zs0.optional(),status:Ws0.optional()}),sUw=OU.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:Z.string().describe("URL-friendly identifier: {platform}-{title}"),error:Z.string().optional()}),aUw=Z.object({title:Z.string(),platform:p02,status:i02,publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional(),slug:Z.string(),error:Z.string().optional()}),tUw=Z.object({title:Z.string(),platform:p02,status:i02,coverImageId:Z.string().optional(),documents:Z.array(oUw).optional(),publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional(),sourceEntityId:Z.string().optional(),sourceEntityType:rUw.optional()}),xF=LQ.extend({entityType:Z.literal("social-post"),metadata:aUw}),nY0=xF.extend({frontmatter:tUw,body:Z.string()}),eUw=nY0.extend({url:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});wA();K2();class Hs0 extends C2{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:xF,frontmatterSchema:OU,supportsCoverImage:!0})}toMarkdown(A){let Q,w={};try{w=this.parseFrontMatter(A.content,OU),Q=this.extractBody(A.content)}catch{Q=A.content}let B={...w,title:A.metadata.title,platform:A.metadata.platform,status:A.metadata.status,...A.metadata.publishedAt!==void 0&&{publishedAt:A.metadata.publishedAt},...A.metadata.platformPostId!==void 0&&{platformPostId:A.metadata.platformPostId}};return this.buildMarkdown(Q,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,r02),w=Q.platform??"linkedin",B=Q.status??"draft",$=`${w}-${Z1(Q.title)}`;return{content:A,entityType:"social-post",metadata:{title:Q.title,slug:$,platform:w,status:B,publishedAt:Q.publishedAt,platformPostId:Q.platformPostId}}}parsePostFrontmatter(A){return this.parseFrontMatter(A.content,OU)}getPostContent(A){return this.extractBody(A.content)}createPostContent(A,Q){return this.buildMarkdown(Q,A)}buildStub(A){let w={title:A.title,platform:"linkedin",status:"generating"};return{content:this.buildMarkdown("",w),metadata:{title:A.title,slug:`linkedin-${Z1(A.title)}`,platform:"linkedin",status:"generating"}}}}var p7=new Hs0;wA();wA();N0();var ADw=Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional(),baseUrl:Z.string().optional(),platform:Z.enum(["linkedin"]).optional(),status:Z.enum(["generating","draft","queued","published","failed"]).optional(),sortByQueue:Z.boolean().optional(),nextInQueue:Z.boolean().optional()}),QDw=Z.looseObject({entityType:Z.string().optional(),query:ADw.optional()});function o02(A){let Q=o2(A.content,OU);return nY0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class rY0 extends q5{id="social-media:posts";name="Social Post DataSource";description="Fetches and transforms social post entities for queue management and publishing";config={entityType:"social-post",defaultSort:[{field:"publishedAt",direction:"desc",nullsFirst:!0},{field:"created",direction:"desc"}],defaultLimit:100};constructor(A){super(A);this.logger.debug("SocialPostDataSource initialized")}parseQuery(A){let Q=QDw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return o02(A)}buildDetailResult(A,Q){return{post:A}}buildListResult(A,Q,w){return{posts:A,totalCount:Q?.totalItems??A.length,pagination:Q,baseUrl:w.baseUrl}}async fetch(A,Q,w){let{query:B}=this.parseQuery(A),$=w.entityService;if(B.nextInQueue)return this.fetchNextInQueue(Q,$);if(B.id){let{item:K}=await this.fetchDetail(B.id,$);return Q.parse(this.buildDetailResult(K,null))}let f={};if(B.platform)f.platform=B.platform;if(B.status)f.status=B.status;let Y=Object.keys(f).length>0,X=B.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:W,pagination:H}=await this.fetchList(B,$,{...Y&&{filter:{metadata:f}},sortFields:X});return Q.parse(this.buildListResult(W,H,B))}async fetchNextInQueue(A,Q){let B=(await Q.listEntities({entityType:this.config.entityType,options:{filter:{metadata:{status:"queued"}},sortFields:[{field:"queueOrder",direction:"asc"}],limit:1}}))[0],$=B?o02(B):null;return A.parse({post:$})}}N0();var s02=Z.object({accessToken:Z.string().optional(),refreshToken:Z.string().optional(),organizationId:Z.string().optional(),apiVersion:Z.string().regex(/^\d{6}$/).optional()}),Ks0=Z.object({linkedin:s02.optional(),publishInterval:Z.number().default(3600000),enabled:Z.boolean().default(!0),defaultPrompt:Z.string().default("Create an engaging social media post that drives engagement"),maxRetries:Z.number().default(3),autoGenerateOnBlogPublish:Z.boolean().default(!1)});wA();K2();N0();g6();Ds0();import{jsxDEV as a8,Fragment as $Dw}from"preact/jsx-dev-runtime";function wDw(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function BDw(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var sY0=({posts:A,pageTitle:Q,pagination:w,baseUrl:B="/social-posts"})=>{let $=Q??"Social Posts",f=w?.totalItems??A.length,Y=`Browse all ${f} social ${f===1?"post":"posts"}`;return a8($Dw,{children:[a8(lQ,{title:$,description:Y},void 0,!1,void 0,this),a8("div",{className:"social-post-list bg-theme",children:a8("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[a8("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:$},void 0,!1,void 0,this),A.length===0?a8("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):a8("ul",{className:"space-y-6",children:A.map((X)=>a8("li",{children:a8(U6,{href:X.url,variant:"horizontal",children:a8("div",{className:"flex flex-col sm:flex-row gap-4",children:[X.coverImageUrl&&a8("img",{src:X.coverImageUrl,alt:X.frontmatter.title,className:"w-full sm:w-24 h-48 sm:h-24 object-cover rounded-lg shrink-0"},void 0,!1,void 0,this),a8("div",{className:"flex-1 min-w-0",children:[a8("div",{className:"flex items-start justify-between gap-4 mb-2",children:[a8("h2",{className:"text-lg font-semibold text-heading",children:X.frontmatter.title},void 0,!1,void 0,this),a8("time",{className:"text-sm text-theme-muted shrink-0",children:BDw(X.frontmatter.publishedAt??X.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a8("div",{className:"flex items-center gap-2 mb-3",children:[a8(pY,{status:X.frontmatter.status},void 0,!1,void 0,this),a8("span",{className:"text-xs text-theme-muted uppercase",children:X.frontmatter.platform},void 0,!1,void 0,this),a8("span",{className:"text-xs text-theme-muted font-mono",children:X.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a8("p",{className:"text-theme leading-relaxed",children:wDw(X.body,200)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},X.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&a8(iq,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as t8,Fragment as fDw}from"preact/jsx-dev-runtime";function a02(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var aY0=({post:A})=>{let Q=`Social Post - ${A.frontmatter.platform}`,w=A.body.slice(0,160),B=[{label:"Home",href:"/"},{label:A.listLabel??"Social Posts",href:A.listUrl??"/social-posts"},{label:A.frontmatter.platform}];return t8(fDw,{children:[t8(lQ,{title:Q,description:w},void 0,!1,void 0,this),t8("section",{className:"social-post-detail",children:t8("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:t8("div",{className:"max-w-3xl mx-auto",children:[t8(vG,{items:B},void 0,!1,void 0,this),t8("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),t8("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[t8(pY,{status:A.frontmatter.status},void 0,!1,void 0,this),t8("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),t8("span",{className:"text-sm text-theme-muted font-mono",children:A.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.coverImageUrl&&A.coverImageWidth&&A.coverImageHeight&&t8(lq,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),t8(U6,{className:"p-8 mb-8",children:t8("p",{className:"text-lg text-theme leading-relaxed whitespace-pre-wrap",children:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),t8("div",{className:"space-y-4 text-sm text-theme-muted",children:[t8("div",{children:[t8("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",a02(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&t8("div",{children:[t8("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",a02(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&t8("div",{children:t8("a",{href:`https://www.linkedin.com/feed/update/${A.frontmatter.platformPostId}`,target:"_blank",rel:"noopener noreferrer",className:"text-brand hover:underline",children:"View on LinkedIn \u2192"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};function qo(A){return`social-media:${A}`}var YDw=Z.union([Z.boolean(),Z.object({generate:Z.boolean().optional(),prompt:Z.string().optional()})]),Gs0=Z.object({prompt:Z.string().optional(),platform:Z.enum(["linkedin"]).optional(),sourceEntityType:Z.enum(["post","deck"]).optional(),sourceEntityId:Z.string().optional(),title:Z.string().optional().describe("Required when content is provided directly"),content:Z.string().optional(),addToQueue:Z.boolean().optional(),generateImage:Z.boolean().optional().describe("Auto-generate cover image for post"),coverImage:YDw.optional().describe("Generic cover image generation request")}),XDw=LX.extend({slug:Z.string().optional()});class ZP extends z4{constructor(A,Q){super(A,Q,{schema:Gs0,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let w=A.platform??"linkedin",B=A.addToQueue??!1,{prompt:$,sourceEntityType:f,sourceEntityId:Y}=A,{content:X,title:W}=A;if(X&&W)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(X&&!W){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let V=await this.context.ai.generate({prompt:X,templateName:qo(w)});W=V.title,X=V.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(Y&&f){await this.reportProgress(Q,{progress:10,message:`Fetching source ${f}`});let V=await this.context.entityService.getEntity({entityType:f,id:Y});if(!V)this.failEarly(`Source entity not found: ${f}/${Y}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let N=Z.looseObject({slug:Z.string()}).safeParse(V.metadata),k=N.success?N.data.slug:Y,x=await this.context.ai.generate({prompt:`Create an engaging ${w} post to promote this ${f}:
6788
+ `)}async function YP(A,Q,w,B={}){if(A.length===0)return{created:0,merged:0,skipped:0,batches:0};let $=B.minRelevanceScore??0,f=B.autoMerge??!1,Y=B.mergeSimilarityThreshold??0.85,X=B.targetVisibility??"public",W=M02(A),H=new MU(Q.entityService,w),K=B.topicMergeSynthesizer??new $s0(Q,w),U=await pY0(Q.entityService,void 0,X),D=new Map,q=0,b=0,I=0;for(let L of W){w.info(`Processing batch of ${L.length} entities`);let N=xUw(L),k=iY0({entityTitle:`Batch of ${L.length} entities`,entityType:"batch",content:N,existingTopicTitles:U});try{let R=(await Q.ai.generate({prompt:k,templateName:"topics:extraction"})).topics.filter((h)=>h.relevanceScore>=$);for(let h of R)try{if(f){let S=await H.findMergeCandidate({incoming:h,threshold:Y,additionalCandidates:Array.from(D.values()),targetVisibility:X});if(S){let p=await K.synthesize({existingTopic:S.topic,incomingTopic:h}),e=await H.applySynthesizedMerge({existingId:S.topic.id,synthesized:{...p,title:S.title},visibility:X});if(!e)throw Error(`Failed to merge topic: ${h.title}`);D.set(e.id,e),b++;continue}}let P=H.getTopicIdForTitle(h.title,X);if(D.has(P)){I++;continue}let E=await H.createTopicOptimistic({title:h.title,content:h.content,visibility:X});if(E.topic)D.set(E.topic.id,E.topic);if(E.created)q++;else I++}catch(P){w.error("Topic batch item failed",{title:h.title,error:mA(P)})}}catch(x){w.error("Batch topic extraction failed",{batchSize:L.length,promptChars:k.length,error:mA(x)})}}let V={created:q,merged:b,skipped:I,batches:W.length};if(q>0||b>0)await Q.messaging.send({type:G02,payload:V,broadcast:!0});return V}wA();N0();var RUw=Z.discriminatedUnion("mode",[Z.object({mode:Z.literal("derive"),reason:Z.string().optional()}),Z.object({mode:Z.literal("rebuild"),reason:Z.string().optional()}),Z.object({mode:Z.literal("source-batch"),minRelevanceScore:Z.number().min(0).max(1).optional()})]);class fs0{refs=new Map;add(A){this.refs.set(`${A.entityType}:${A.entityId}`,A)}drain(){let A=Array.from(this.refs.values());return this.refs.clear(),A}}function C02(A){let{context:Q,logger:w,config:B}=A;return{process:async($)=>{if($.mode==="derive")return await A.extractAllTopics(),{success:!0};if($.mode==="rebuild")return await A.rebuildAllTopics(),{success:!0};return vUw({context:Q,logger:w,config:B,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:$.minRelevanceScore??B.minRelevanceScore})},validateAndParse:($)=>{let f=RUw.safeParse($??{});return f.success?f.data:null}}}async function vUw(A){let Q=A.sourceBatch.drain(),w=await Promise.all(Q.map(async(H)=>({ref:H,entity:await A.context.entityService.getEntity({entityType:H.entityType,id:H.entityId})}))),B=0,$=0,f=0,Y=0,X=[];for(let{ref:H,entity:K}of w){if(!K){$++;continue}if(K.contentHash!==H.contentHash){B++;continue}if(!A.isEntityPublished(K)){f++;continue}if(!OV(K.visibility,A.config.extractionVisibility)){Y++;continue}X.push(K)}if(X.length===0)return{success:!0,sources:Q.length,created:0,merged:0,skipped:0,batches:0,stale:B,missing:$,unpublished:f,hidden:Y};let W=await YP(X,A.context,A.logger,{minRelevanceScore:A.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});return{success:!0,sources:Q.length,...W,stale:B,missing:$,unpublished:f,hidden:Y}}function g02(){return{priority:5,source:SY0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:fP}}}async function y02(A){let Q=await T02(A);if(Q.length===0){A.logger.info("No entities to extract topics from");return}A.logger.info(`Batch topic extraction: ${Q.length} entities`);let w=await YP(Q,A.context,A.logger,{minRelevanceScore:A.config.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});A.logger.info("Batch topic extraction complete",w)}async function E02(A){let Q=await T02(A),w=await Ys0(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",w)}async function Ys0(A,Q,w,B){let $=new MU(Q.entityService,w),f=await $.listTopics({visibility:B.extractionVisibility});for(let X of f)await $.deleteTopic(X.id);if(A.length===0)return{deleted:f.length,created:0,merged:0,skipped:0,batches:0};let Y=await YP(A,Q,w,{minRelevanceScore:B.minRelevanceScore,autoMerge:B.autoMerge,mergeSimilarityThreshold:B.mergeSimilarityThreshold,targetVisibility:B.extractionVisibility});return{deleted:f.length,...Y}}async function T02(A){let Q=hUw(A),w=[];for(let B of Q){let $=await A.context.entityService.listEntities({entityType:B,options:{filter:{visibilityScope:A.config.extractionVisibility}}});for(let f of $){if(!A.isEntityPublished(f))continue;w.push(f)}}return w}function hUw(A){return A.context.entityService.getEntityTypes().filter((w)=>A.shouldProcessEntityType(w))}var Iy=Z.object({entityType:Z.string(),content:Z.string(),metadata:Z.record(Z.string(),Z.unknown()).optional()}),CUw=Iy.extend({minRelevanceScore:Z.number().optional()}),gUw=Z.object({contentA:Iy,contentB:Iy,minRelevanceScore:Z.number().optional(),threshold:Z.number().min(0).max(1).optional()}),zo=Z.object({title:Z.string(),content:Z.string()}),yUw=Z.object({existingTopics:Z.array(zo),incomingTopic:zo,threshold:Z.number().optional()}),EUw=Z.object({existingTopics:Z.array(zo).default([]),incomingTopic:zo.extend({relevanceScore:Z.number().min(0).max(1).optional()}),threshold:Z.number().optional()}),TUw=Z.object({entities:Z.array(Iy).min(1),minRelevanceScore:Z.number().optional()}),SUw=Z.object({existingTopics:Z.array(zo).optional(),entities:Z.array(Iy)}),mUw=Z.object({entities:Z.array(Iy)});function Vy(A,Q=""){return{id:`eval${Q}-${Date.now()}`,entityType:A.entityType,content:A.content,contentHash:w6(A.content),visibility:"public",metadata:A.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}}function S02(A){return{title:A.title,relevanceScore:A.relevanceScore}}function uUw(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function cUw(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:uUw(Q)}]}}async function XP(A){let Q=await A.entityService.listEntities({entityType:p6});await Promise.all(Q.map((w)=>A.entityService.deleteEntity({entityType:p6,id:w.id})))}async function lUw(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise((w)=>setTimeout(w,100))}}function m02(A){let{context:Q,logger:w,config:B}=A,$=new Bs0(Q,w),f=async(Y,X,W="")=>{let H=Vy(Y,W);return $.extractFromEntity(H,X)};Q.eval.registerHandler("extractFromEntity",async(Y)=>{await XP(Q);let X=CUw.parse(Y),W=X.minRelevanceScore??B.minRelevanceScore,H=Vy(X);return(await $.extractFromEntity(H,W)).map((U)=>cUw(U,H))}),Q.eval.registerHandler("checkMergeSimilarity",async(Y)=>{await XP(Q);let X=gUw.parse(Y),W=X.minRelevanceScore??B.minRelevanceScore,H=X.threshold??B.mergeSimilarityThreshold,[K,U]=await Promise.all([f(X.contentA,W,"-a"),f(X.contentB,W,"-b")]),D=new MU(Q.entityService,w),q=[];for(let V of K){let L=await D.createTopic(V);if(L)q.push(L)}let b=(await Promise.all(U.map(async(V)=>{let L=await D.findMergeCandidate({incoming:V,threshold:H,additionalCandidates:q});if(!L)return null;return{incomingTitle:V.title,candidateTitle:L.title,candidateScore:L.score}}))).filter((V)=>V!==null),I=b.map((V)=>V.candidateTitle);return{topicsA:K.map(S02),topicsB:U.map(S02),matchingTitles:I,mergeCandidates:b,wouldMerge:b.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(Y)=>{await XP(Q);let X=yUw.parse(Y),W=X.threshold??B.mergeSimilarityThreshold,H=new MU(Q.entityService,w),K=[];for(let D of X.existingTopics){let q=await H.createTopic(D);if(q)K.push(q)}let U=await H.findMergeCandidate({incoming:{title:X.incomingTopic.title},threshold:W,additionalCandidates:K});return{found:U!==null,candidateTitle:U?.title,candidateScore:U?.score}}),Q.eval.registerHandler("processTopicWithAutoMerge",async(Y)=>{await XP(Q);let X=EUw.parse(Y),W=new MU(Q.entityService,w);for(let D of X.existingTopics)await W.createTopic({title:D.title,content:D.content});await lUw(Q);let H=Vy({entityType:"post",content:X.incomingTopic.content,metadata:{title:X.incomingTopic.title}},"-source"),K=await YP([H],Q,w,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:X.threshold??B.mergeSimilarityThreshold}),U=await Q.entityService.listEntities({entityType:p6});return{...K,topicCount:U.length,topics:U.map(Qs0)}}),Q.eval.registerHandler("rebuildTopics",async(Y)=>{await XP(Q);let X=SUw.parse(Y),W=new MU(Q.entityService,w);for(let D of X.existingTopics??[])await W.createTopic(D);let H=X.entities.map((D,q)=>Vy(D,`-rebuild-${q}`)),K=await Ys0(H,Q,w,B),U=await Q.entityService.listEntities({entityType:p6});return{...K,topicCount:U.length,topics:U.map(Qs0)}}),Q.eval.registerHandler("extractSequentially",async(Y)=>{await XP(Q);let X=TUw.parse(Y),W=X.minRelevanceScore??B.minRelevanceScore,H=new MU(Q.entityService,w),K=[];for(let[D,q]of X.entities.entries()){let b=Vy(q,`-sequential-${D}`),I=await $.extractFromEntity(b,W);for(let V of I)await H.createTopic({title:V.title,content:V.content});K.push({extractedTitles:I.map((V)=>V.title)})}let U=await Q.entityService.listEntities({entityType:p6});return{totalTopics:U.length,perEntity:K,topics:U.map(by)}}),Q.eval.registerHandler("batchExtract",async(Y)=>{await XP(Q);let W=mUw.parse(Y).entities.map((U,D)=>Vy(U,`-batch-${D}`)),H=await YP(W,Q,w,{minRelevanceScore:B.minRelevanceScore}),K=await Q.entityService.listEntities({entityType:p6});return{...H,topics:K.map(by)}})}var pUw=new PU;async function u02({entity:A,config:Q}){let w=qy.parse(A),B=pUw.parseTopicBody(w.content);return{$type:"ai.rizom.brain.topic",title:B.title,body:B.content,format:"text/markdown",...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"topic",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function Xs0(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:L6["ai.rizom.brain.topic"],validate:!1,buildRecord:u02}}var c02={name:"@brains/topics",version:"0.2.0-alpha.143",description:"Extract and manage topics from conversations",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},main:"./src/index.ts",private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var dUw=new PU,nUw=Z.looseObject({status:Z.unknown().optional()});class l02 extends nQ{entityType=p6;schema=qy;adapter=dUw;unregisterAtprotoProjection;sourceBatch=new fs0;constructor(A={}){super(fP,c02,A,K02)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:b02,"merge-synthesis":V02,"topic-list":I02,"topic-detail":J02}}getDataSources(){return[new ws0(this.logger.child("TopicsDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:to0,targetType:p6,job:{type:D02,handler:C02({context:A,logger:this.logger,config:this.config,extractAllTopics:()=>this.extractAllTopics(A),rebuildAllTopics:()=>this.rebuildAllTopics(A),sourceBatch:this.sourceBatch,isEntityPublished:(Q)=>this.isEntityPublished(Q)})},initialSync:{shouldEnqueue:async()=>!await qk(A,p6,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:g02()},sourceChange:{sourceTypes:this.config.includeEntityTypes,requireInitialSync:!0,jobData:(Q)=>{let w=Q.entity;if(!w)return null;if(!this.shouldProcessEntityType(w.entityType,A.entityService))return null;if(!this.isEntityPublished(w))return null;if(!OV(w.visibility,this.config.extractionVisibility))return null;return this.sourceBatch.add({entityId:w.id,entityType:w.entityType,contentHash:w.contentHash}),{mode:"source-batch"}},jobOptions:()=>({priority:5,source:SY0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:z02,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:fP}})}}]}async onRegister(A){A.insights.register("topic-distribution",k02()),_02({context:A,pluginId:this.id}),m02({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=A8.getInstance().register(Xs0())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(to0)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===p6)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let Q=nUw.safeParse(A.metadata),w=Q.success?Q.data.status:void 0;if(w===void 0||w===null)return!0;if(typeof w!=="string")return!1;return this.config.extractableStatuses.includes(w)}async extractAllTopics(A){await y02({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await E02({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function dY0(A={}){return new l02(A)}wA();N0();wA();var Zs0=Z.enum(["linkedin"]),p02=Z.enum(["linkedin"]),Ws0=Z.enum(["generating","draft","queued","published","failed"]),i02=Z.enum(["generating","draft","queued","published","failed"]),d02=Z.enum(["post","deck"]),rUw=Z.enum(["post","deck"]),n02=Z.object({id:Z.string().min(1).describe("Document entity ID")}),oUw=Z.object({id:Z.string().min(1)}),OU=Z.object({title:Z.string().describe("Short descriptive title (3-6 words) for file naming"),platform:Zs0.describe("Target platform"),status:Ws0,coverImageId:Z.string().optional().describe("Image entity ID for post image"),documents:Z.array(n02).optional().describe("Document attachments for publishing"),publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional().describe("ID from platform after publishing"),sourceEntityId:Z.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:d02.optional().describe("Source entity type (post, deck)")}),r02=OU.extend({platform:Zs0.optional(),status:Ws0.optional()}),sUw=OU.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:Z.string().describe("URL-friendly identifier: {platform}-{title}"),error:Z.string().optional()}),aUw=Z.object({title:Z.string(),platform:p02,status:i02,publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional(),slug:Z.string(),error:Z.string().optional()}),tUw=Z.object({title:Z.string(),platform:p02,status:i02,coverImageId:Z.string().optional(),documents:Z.array(oUw).optional(),publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional(),sourceEntityId:Z.string().optional(),sourceEntityType:rUw.optional()}),xF=LQ.extend({entityType:Z.literal("social-post"),metadata:aUw}),nY0=xF.extend({frontmatter:tUw,body:Z.string()}),eUw=nY0.extend({url:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});wA();K2();class Hs0 extends C2{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:xF,frontmatterSchema:OU,supportsCoverImage:!0})}toMarkdown(A){let Q,w={};try{w=this.parseFrontMatter(A.content,OU),Q=this.extractBody(A.content)}catch{Q=A.content}let B={...w,title:A.metadata.title,platform:A.metadata.platform,status:A.metadata.status,...A.metadata.publishedAt!==void 0&&{publishedAt:A.metadata.publishedAt},...A.metadata.platformPostId!==void 0&&{platformPostId:A.metadata.platformPostId}};return this.buildMarkdown(Q,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,r02),w=Q.platform??"linkedin",B=Q.status??"draft",$=`${w}-${Z1(Q.title)}`;return{content:A,entityType:"social-post",metadata:{title:Q.title,slug:$,platform:w,status:B,publishedAt:Q.publishedAt,platformPostId:Q.platformPostId}}}parsePostFrontmatter(A){return this.parseFrontMatter(A.content,OU)}getPostContent(A){return this.extractBody(A.content)}createPostContent(A,Q){return this.buildMarkdown(Q,A)}buildStub(A){let w={title:A.title,platform:"linkedin",status:"generating"};return{content:this.buildMarkdown("",w),metadata:{title:A.title,slug:`linkedin-${Z1(A.title)}`,platform:"linkedin",status:"generating"}}}}var p7=new Hs0;wA();wA();N0();var ADw=Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional(),baseUrl:Z.string().optional(),platform:Z.enum(["linkedin"]).optional(),status:Z.enum(["generating","draft","queued","published","failed"]).optional(),sortByQueue:Z.boolean().optional(),nextInQueue:Z.boolean().optional()}),QDw=Z.looseObject({entityType:Z.string().optional(),query:ADw.optional()});function o02(A){let Q=o2(A.content,OU);return nY0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class rY0 extends q5{id="social-media:posts";name="Social Post DataSource";description="Fetches and transforms social post entities for queue management and publishing";config={entityType:"social-post",defaultSort:[{field:"publishedAt",direction:"desc",nullsFirst:!0},{field:"created",direction:"desc"}],defaultLimit:100};constructor(A){super(A);this.logger.debug("SocialPostDataSource initialized")}parseQuery(A){let Q=QDw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return o02(A)}buildDetailResult(A,Q){return{post:A}}buildListResult(A,Q,w){return{posts:A,totalCount:Q?.totalItems??A.length,pagination:Q,baseUrl:w.baseUrl}}async fetch(A,Q,w){let{query:B}=this.parseQuery(A),$=w.entityService;if(B.nextInQueue)return this.fetchNextInQueue(Q,$);if(B.id){let{item:K}=await this.fetchDetail(B.id,$);return Q.parse(this.buildDetailResult(K,null))}let f={};if(B.platform)f.platform=B.platform;if(B.status)f.status=B.status;let Y=Object.keys(f).length>0,X=B.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:W,pagination:H}=await this.fetchList(B,$,{...Y&&{filter:{metadata:f}},sortFields:X});return Q.parse(this.buildListResult(W,H,B))}async fetchNextInQueue(A,Q){let B=(await Q.listEntities({entityType:this.config.entityType,options:{filter:{metadata:{status:"queued"}},sortFields:[{field:"queueOrder",direction:"asc"}],limit:1}}))[0],$=B?o02(B):null;return A.parse({post:$})}}N0();var s02=Z.object({accessToken:Z.string().optional(),refreshToken:Z.string().optional(),organizationId:Z.string().optional(),apiVersion:Z.string().regex(/^\d{6}$/).optional()}),Ks0=Z.object({linkedin:s02.optional(),publishInterval:Z.number().default(3600000),enabled:Z.boolean().default(!0),defaultPrompt:Z.string().default("Create an engaging social media post that drives engagement"),maxRetries:Z.number().default(3),autoGenerateOnBlogPublish:Z.boolean().default(!1)});wA();K2();N0();g6();Ds0();import{jsxDEV as a8,Fragment as $Dw}from"preact/jsx-dev-runtime";function wDw(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function BDw(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var sY0=({posts:A,pageTitle:Q,pagination:w,baseUrl:B="/social-posts"})=>{let $=Q??"Social Posts",f=w?.totalItems??A.length,Y=`Browse all ${f} social ${f===1?"post":"posts"}`;return a8($Dw,{children:[a8(lQ,{title:$,description:Y},void 0,!1,void 0,this),a8("div",{className:"social-post-list bg-theme",children:a8("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[a8("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:$},void 0,!1,void 0,this),A.length===0?a8("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):a8("ul",{className:"space-y-6",children:A.map((X)=>a8("li",{children:a8(U6,{href:X.url,variant:"horizontal",children:a8("div",{className:"flex flex-col sm:flex-row gap-4",children:[X.coverImageUrl&&a8("img",{src:X.coverImageUrl,alt:X.frontmatter.title,className:"w-full sm:w-24 h-48 sm:h-24 object-cover rounded-lg shrink-0"},void 0,!1,void 0,this),a8("div",{className:"flex-1 min-w-0",children:[a8("div",{className:"flex items-start justify-between gap-4 mb-2",children:[a8("h2",{className:"text-lg font-semibold text-heading",children:X.frontmatter.title},void 0,!1,void 0,this),a8("time",{className:"text-sm text-theme-muted shrink-0",children:BDw(X.frontmatter.publishedAt??X.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a8("div",{className:"flex items-center gap-2 mb-3",children:[a8(pY,{status:X.frontmatter.status},void 0,!1,void 0,this),a8("span",{className:"text-xs text-theme-muted uppercase",children:X.frontmatter.platform},void 0,!1,void 0,this),a8("span",{className:"text-xs text-theme-muted font-mono",children:X.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a8("p",{className:"text-theme leading-relaxed",children:wDw(X.body,200)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},X.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&a8(iq,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as t8,Fragment as fDw}from"preact/jsx-dev-runtime";function a02(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var aY0=({post:A})=>{let Q=`Social Post - ${A.frontmatter.platform}`,w=A.body.slice(0,160),B=[{label:"Home",href:"/"},{label:A.listLabel??"Social Posts",href:A.listUrl??"/social-posts"},{label:A.frontmatter.platform}];return t8(fDw,{children:[t8(lQ,{title:Q,description:w},void 0,!1,void 0,this),t8("section",{className:"social-post-detail",children:t8("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:t8("div",{className:"max-w-3xl mx-auto",children:[t8(vG,{items:B},void 0,!1,void 0,this),t8("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),t8("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[t8(pY,{status:A.frontmatter.status},void 0,!1,void 0,this),t8("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),t8("span",{className:"text-sm text-theme-muted font-mono",children:A.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.coverImageUrl&&A.coverImageWidth&&A.coverImageHeight&&t8(lq,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),t8(U6,{className:"p-8 mb-8",children:t8("p",{className:"text-lg text-theme leading-relaxed whitespace-pre-wrap",children:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),t8("div",{className:"space-y-4 text-sm text-theme-muted",children:[t8("div",{children:[t8("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",a02(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&t8("div",{children:[t8("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",a02(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&t8("div",{children:t8("a",{href:`https://www.linkedin.com/feed/update/${A.frontmatter.platformPostId}`,target:"_blank",rel:"noopener noreferrer",className:"text-brand hover:underline",children:"View on LinkedIn \u2192"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};function qo(A){return`social-media:${A}`}var YDw=Z.union([Z.boolean(),Z.object({generate:Z.boolean().optional(),prompt:Z.string().optional()})]),Gs0=Z.object({prompt:Z.string().optional(),platform:Z.enum(["linkedin"]).optional(),sourceEntityType:Z.enum(["post","deck"]).optional(),sourceEntityId:Z.string().optional(),title:Z.string().optional().describe("Required when content is provided directly"),content:Z.string().optional(),addToQueue:Z.boolean().optional(),generateImage:Z.boolean().optional().describe("Auto-generate cover image for post"),coverImage:YDw.optional().describe("Generic cover image generation request")}),XDw=LX.extend({slug:Z.string().optional()});class ZP extends z4{constructor(A,Q){super(A,Q,{schema:Gs0,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let w=A.platform??"linkedin",B=A.addToQueue??!1,{prompt:$,sourceEntityType:f,sourceEntityId:Y}=A,{content:X,title:W}=A;if(X&&W)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(X&&!W){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let V=await this.context.ai.generate({prompt:X,templateName:qo(w)});W=V.title,X=V.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(Y&&f){await this.reportProgress(Q,{progress:10,message:`Fetching source ${f}`});let V=await this.context.entityService.getEntity({entityType:f,id:Y});if(!V)this.failEarly(`Source entity not found: ${f}/${Y}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let N=Z.looseObject({slug:Z.string()}).safeParse(V.metadata),k=N.success?N.data.slug:Y,x=await this.context.ai.generate({prompt:`Create an engaging ${w} post to promote this ${f}:
6789
6789
 
6790
6790
  Source: ${f}/${k}
6791
6791
 
6792
6792
  ${V.content}`,templateName:qo(w)});W=x.title,X=x.content,await this.reportProgress(Q,{progress:50,message:"Social post generated from source"})}else if($){await this.reportProgress(Q,{progress:10,message:"Generating social post with AI"});let V=await this.context.ai.generate({prompt:$,templateName:qo(w)});W=V.title,X=V.content,await this.reportProgress(Q,{progress:50,message:"Social post generated"})}else this.failEarly("No content source provided (prompt, sourceEntityId, or content)");if(!X||!W)this.failEarly("Content or title was not generated");let K={title:W,platform:w,status:B?"queued":"draft",...Y&&{sourceEntityId:Y},...f&&{sourceEntityType:f}},U=p7.createPostContent(K,X),q=p7.fromMarkdown(U).metadata;if(!q)this.failEarly("Failed to parse social post metadata");let b=await KK({entityType:"social-post",title:W,deriveId:(V)=>`${w}-${Z1(V)}`,regeneratePrompt:"Generate a different social media post title on the same topic.",context:this.context}),I=U;if(b!==W){q.title=b,q.slug=`${w}-${Z1(b)}`;let V={...K,title:b};I=p7.createPostContent(V,X)}return{id:q.slug,content:I,metadata:q,title:b,resultExtras:{slug:q.slug},createOptions:{deduplicateId:!0}}}async onGenerationFailure(A,Q){await this.context.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:Q}})}async afterCreate(A,Q,w,B){if(A.generateImage){await this.reportProgress(w,{progress:90,message:"Queueing image generation"});let $=B.title??"Social Post";await this.context.jobs.enqueue({type:"image:image-generate",data:{prompt:`Social media graphic for: ${$}`,title:`${$} Image`,aspectRatio:"16:9",targetEntityType:"social-post",targetEntityId:Q},toolContext:{interfaceType:"job",userId:"system"}})}await this.context.messaging.send({type:"generate:report:success",payload:{entityType:"social-post",entityId:Q}})}summarizeDataForLog(A){return{platform:A.platform??"linkedin",hasPrompt:!!A.prompt,sourceEntityType:A.sourceEntityType,addToQueue:A.addToQueue??!1,generateImage:A.generateImage??!1,coverImage:!!A.coverImage}}}N0();var t02=200,e02="com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest";function bo(A){if(A.length<=t02)return A;return`${A.slice(0,t02)}\u2026 (truncated, ${A.length} bytes)`}var ZDw=Z.looseObject({sub:Z.string()}),WDw=Z.looseObject({id:Z.string()}),HDw=Z.looseObject({value:Z.looseObject({asset:Z.string(),uploadMechanism:Z.looseObject({[e02]:Z.looseObject({uploadUrl:Z.url()})})})}).transform((A)=>({uploadUrl:A.value.uploadMechanism[e02].uploadUrl,assetUrn:A.value.asset})),KDw=Z.looseObject({value:Z.looseObject({uploadUrl:Z.url(),document:Z.string()})}).transform((A)=>({uploadUrl:A.value.uploadUrl,documentUrn:A.value.document}));function UDw(A){let Q={status:"READY",media:A.urn};if(A.title)Q.title={text:A.title};return Q}function DDw(A){let Q=HDw.safeParse(A);return Q.success?Q.data:null}function GDw(A){let Q=KDw.safeParse(A);return Q.success?Q.data:null}var zDw="202604";class zs0{config;logger;name="linkedin";apiBaseUrl="https://api.linkedin.com/v2";restApiBaseUrl="https://api.linkedin.com/rest";fetch;cachedUserId=null;constructor(A,Q,w={}){this.config=A,this.logger=Q,this.fetch=w.fetch??globalThis.fetch.bind(globalThis)}async publish(A,Q,w,B){if(!this.config.accessToken)throw Error("LinkedIn access token not configured");let $=await this.getAuthor(),f=B?.[0];if(B&&B.length>1)this.logger.warn("LinkedIn document publishing supports one PDF",{count:B.length});let Y=null;if(f){let U=await this.uploadDocument($,f);return this.publishDocumentPost($,A,U,f.filename)}else if(w){let U=await this.uploadImage($,w);if(U)Y={category:"IMAGE",urn:U}}let X={shareCommentary:{text:A},shareMediaCategory:Y?.category??"NONE",...Y&&{media:[UDw(Y)]}},W=await this.fetch(`${this.apiBaseUrl}/ugcPosts`,{method:"POST",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","X-Restli-Protocol-Version":"2.0.0"},body:JSON.stringify({author:$,lifecycleState:"PUBLISHED",specificContent:{"com.linkedin.ugc.ShareContent":X},visibility:{"com.linkedin.ugc.MemberNetworkVisibility":"PUBLIC"}})});if(!W.ok){let U=bo(await W.text());throw this.logger.error("LinkedIn API error",{status:W.status,error:U}),Error(`LinkedIn API error: ${W.status} - ${U}`)}let H=W.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn post created",{postId:H,mediaCategory:Y?.category??"NONE"});let K={id:H};if(H)K.url=`https://www.linkedin.com/feed/update/${H}`;return K}getRestHeaders(){return{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","Linkedin-Version":this.config.apiVersion??zDw,"X-Restli-Protocol-Version":"2.0.0"}}async uploadImage(A,Q){try{let w=await this.fetch(`${this.apiBaseUrl}/assets?action=registerUpload`,{method:"POST",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","X-Restli-Protocol-Version":"2.0.0"},body:JSON.stringify({registerUploadRequest:{recipes:["urn:li:digitalmediaRecipe:feedshare-image"],owner:A,serviceRelationships:[{relationshipType:"OWNER",identifier:"urn:li:userGeneratedContent"}]}})});if(!w.ok){let X=bo(await w.text());return this.logger.warn("LinkedIn image upload registration failed",{status:w.status,error:X}),null}let B=DDw(await w.json());if(!B)return this.logger.warn("LinkedIn image upload registration was malformed"),null;let{uploadUrl:$,assetUrn:f}=B,Y=await this.fetch($,{method:"PUT",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":Q.mimeType},body:new Uint8Array(Q.data)});if(!Y.ok)return this.logger.warn("LinkedIn image binary upload failed",{status:Y.status}),null;return this.logger.info("LinkedIn image uploaded",{assetUrn:f}),f}catch(w){return this.logger.warn("LinkedIn image upload error",{error:w}),null}}async uploadDocument(A,Q){let w=await this.fetch(`${this.restApiBaseUrl}/documents?action=initializeUpload`,{method:"POST",headers:this.getRestHeaders(),body:JSON.stringify({initializeUploadRequest:{owner:A}})});if(!w.ok){let f=bo(await w.text());throw Error(`LinkedIn document upload initialization failed: ${w.status} - ${f}`)}let B=GDw(await w.json());if(!B)throw Error("LinkedIn document upload initialization was malformed");let $=await this.fetch(B.uploadUrl,{method:"PUT",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":Q.mimeType},body:new Uint8Array(Q.data)});if(!$.ok)throw Error(`LinkedIn document binary upload failed: ${$.status}`);return this.logger.info("LinkedIn document uploaded",{documentUrn:B.documentUrn,filename:Q.filename}),B.documentUrn}async publishDocumentPost(A,Q,w,B){let $=await this.fetch(`${this.restApiBaseUrl}/posts`,{method:"POST",headers:this.getRestHeaders(),body:JSON.stringify({author:A,commentary:Q,visibility:"PUBLIC",distribution:{feedDistribution:"MAIN_FEED",targetEntities:[],thirdPartyDistributionChannels:[]},content:{media:{id:w,title:B}},lifecycleState:"PUBLISHED",isReshareDisabledByAuthor:!1})});if(!$.ok){let X=bo(await $.text());throw this.logger.error("LinkedIn document post API error",{status:$.status,error:X}),Error(`LinkedIn document post API error: ${$.status} - ${X}`)}let f=$.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn document post created",{postId:f,documentUrn:w});let Y={id:f};if(f)Y.url=`https://www.linkedin.com/feed/update/${f}`;return Y}async validateCredentials(){if(!this.config.accessToken)return!1;try{if(this.config.organizationId)return(await this.fetch(`${this.apiBaseUrl}/organizations/${this.config.organizationId}`,{headers:{Authorization:`Bearer ${this.config.accessToken}`}})).ok;return await this.getUserId(),!0}catch{return!1}}async getAuthor(){if(this.config.organizationId)return`urn:li:organization:${this.config.organizationId}`;return this.getUserId()}async getUserId(){if(this.cachedUserId)return this.cachedUserId;if(!this.config.accessToken)throw Error("LinkedIn access token not configured");try{let w=await this.fetch("https://api.linkedin.com/v2/userinfo",{headers:{Authorization:`Bearer ${this.config.accessToken}`}});if(w.ok){let B=ZDw.safeParse(await w.json());if(B.success)return this.cachedUserId=`urn:li:person:${B.data.sub}`,this.cachedUserId}}catch{}let A=await this.fetch("https://api.linkedin.com/v2/me",{headers:{Authorization:`Bearer ${this.config.accessToken}`}});if(!A.ok){let w=bo(await A.text());throw Error(`Failed to get LinkedIn user ID: ${A.status} - ${w}`)}let Q=WDw.parse(await A.json());return this.cachedUserId=`urn:li:person:${Q.id}`,this.cachedUserId}}function qs0(A,Q,w={}){return new zs0(A,Q,w)}N0();NB();Ds0();var qDw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),bDw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),AA2=Z.enum(["linkedin"]),QA2=Z.enum(["generating","draft","queued","published","failed"]),VDw=Z.enum(["post","deck"]),IDw=Z.object({id:Z.string().min(1)}),JDw=Z.object({title:Z.string(),platform:AA2,status:QA2,coverImageId:Z.string().optional(),documents:Z.array(IDw).optional(),publishedAt:Z.string().optional(),platformPostId:Z.string().optional(),sourceEntityId:Z.string().optional(),sourceEntityType:VDw.optional()}),FDw=Z.object({title:Z.string(),platform:AA2,status:QA2,publishedAt:Z.string().optional(),platformPostId:Z.string().optional(),slug:Z.string(),error:Z.string().optional()}),wA2=Z.object({id:Z.string(),entityType:Z.literal("social-post"),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:bDw,metadata:FDw,contentHash:Z.string(),frontmatter:JDw,body:Z.string(),url:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),LDw=Z.object({posts:Z.array(wA2),totalCount:Z.number().optional(),pagination:qDw.nullable(),baseUrl:Z.string().optional()}),kDw=Z.object({post:wA2});function BA2(){return{linkedin:oY0,"social-post-list":i1({name:"social-post-list",description:"Social post list page template",schema:LDw,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:sY0}}),"social-post-detail":i1({name:"social-post-detail",description:"Individual social post template",schema:kDw,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:aY0}})}}N0();var _Dw=Z.object({prompt:Z.string().optional(),content:Z.string().optional(),platform:Z.enum(["linkedin"]).default("linkedin")}),NDw=Z.object({prompt:Z.string().optional(),content:Z.string().optional(),title:Z.string().optional(),platform:Z.enum(["linkedin"]).optional()});function $A2(A){A.eval.registerHandler("generation",async(Q)=>{let w=_Dw.parse(Q),B=w.content?`Create an engaging LinkedIn post to share this content:
6793
6793
 
6794
- ${w.content}`:w.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:B,templateName:`social-media:${w.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let w=NDw.parse(Q),B=[],$=Xf.from(async(H)=>{let K={progress:H.progress};if(H.message!==void 0)K.message=H.message;B.push(K)});if(!$)throw Error("Failed to create progress reporter");let Y=await new ZP(A.logger,A).process(w,`eval-${Date.now()}`,$),X=!1,W;if(Y.success&&Y.entityId){let H=await A.entityService.getEntity({entityType:"social-post",id:Y.entityId});X=!!H,W=H?.content.slice(0,300)}return{...Y,entityExists:X,entityPreview:W,progressSteps:B}})}wA();class Vo{sendMessage;logger;entityService;providers;permissions;resolveAttachment;constructor(A){this.sendMessage=A.sendMessage,this.logger=A.logger,this.entityService=A.entityService,this.providers=A.providers,this.permissions=A.permissions,this.resolveAttachment=A.resolveAttachment}async handle(A){let{entityType:Q,entityId:w}=A;if(Q!=="social-post")return;this.permissions.assertEntityActionAllowed(Q,"publish",A.authContext??{userPermissionLevel:"anchor"}),this.logger.debug("Handling publish:execute",{entityId:w});try{let B=await this.entityService.getEntity({entityType:"social-post",id:w});if(!B){await this.reportFailure(Q,w,`Post not found: ${w}`);return}let $=B;if($.metadata.status==="published"){this.logger.debug("Post already published, skipping",{entityId:w});return}let f=$.metadata.platform,Y=this.providers.get(f);if(!Y){await this.reportFailure(Q,w,`No provider configured for platform: ${f}`);return}let X=o2($.content,OU),W;if(X.metadata.coverImageId)W=await this.fetchImageData(X.metadata.coverImageId);let H=X.metadata.documents??[],K=await this.fetchDocumentData(H);try{if(H.length>0&&K.length===0)throw Error(`Refusing to publish: ${H.length} document(s) referenced but none could be fetched`);let U=H.length===0?await this.resolveSourceAttachment(X.metadata):[],D=K.length>0?K:U,q=D.length?await Y.publish(X.content,$.metadata,W,D):await Y.publish(X.content,$.metadata,W),b=new Date().toISOString(),I=q.id||void 0,V={...X.metadata,status:"published",publishedAt:b,...I&&{platformPostId:I}},L=p7.createPostContent(V,X.content);await this.entityService.updateEntity({entity:{...$,content:L,metadata:{...$.metadata,status:"published",publishedAt:b,platformPostId:I}}}),await this.reportSuccess(Q,w,q.id),this.logger.info(`Post published successfully: ${w}`,{platform:f,platformPostId:I})}catch(U){let D=U instanceof Error?U.message:String(U),q={...X.metadata,status:"failed"},b=p7.createPostContent(q,X.content);await this.entityService.updateEntity({entity:{...$,content:b,metadata:{...$.metadata,status:"failed"}}}),await this.reportFailure(Q,w,D),this.logger.error(`Post publish failed: ${w}`,{platform:f,error:D})}}catch(B){let $=mA(B);this.logger.error("Unexpected error in publish handler",{entityId:w,error:$}),await this.reportFailure(Q,w,$)}}async reportSuccess(A,Q,w){await this.sendMessage({type:"publish:report:success",payload:{entityType:A,entityId:Q,result:{id:w}}})}async reportFailure(A,Q,w){await this.sendMessage({type:"publish:report:failure",payload:{entityType:A,entityId:Q,error:w}})}async resolveSourceAttachment(A){if(!this.resolveAttachment||!A.sourceEntityType||!A.sourceEntityId)return[];let Q=await this.resolveAttachment({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:"carousel"});return Q?[Q]:[]}async fetchDocumentData(A){if(!A?.length)return[];let Q=[];for(let w of A){let B=await this.fetchSingleDocumentData(w.id);if(B)Q.push(B)}return Q}async fetchSingleDocumentData(A){try{let Q=await this.entityService.getEntity({entityType:"document",id:A});if(!Q){this.logger.warn("Document not found",{documentId:A});return}let w=Q.content.match(/^data:application\/pdf;base64,(.+)$/);if(!w?.[1]){this.logger.warn("Invalid document data URL format",{documentId:A});return}let B=typeof Q.metadata.filename==="string"?Q.metadata.filename:`${A}.pdf`;return{type:"document",data:Buffer.from(w[1],"base64"),mimeType:"application/pdf",filename:B}}catch(Q){this.logger.warn("Failed to fetch document",{documentId:A,error:Q});return}}async fetchImageData(A){try{let Q=await this.entityService.getEntity({entityType:"image",id:A});if(!Q){this.logger.warn("Cover image not found",{imageId:A});return}let B=Q.content.match(/^data:([^;]+);base64,(.+)$/);if(!B?.[1]||!B[2]){this.logger.warn("Invalid image data URL format",{imageId:A});return}let $=B[1],f=B[2];return{data:Buffer.from(f,"base64"),mimeType:$}}catch(Q){this.logger.warn("Failed to fetch cover image",{imageId:A,error:Q});return}}}function fA2(A,Q,w){if(Q.size===0){w.debug("No providers configured, skipping publish-pipeline registration");return}A.messaging.subscribe("system:plugins:ready",async()=>{let B=Q.values().next().value;return await A.messaging.send({type:"publish:register",payload:{entityType:"social-post",provider:B,config:{publishResultIdField:"platformPostId"}}}),w.info("Registered social-post with publish-pipeline"),{success:!0}})}function YA2(A,Q,w){let B=new Vo({sendMessage:A.messaging.send,logger:w.child("PublishExecuteHandler"),entityService:A.entityService,providers:Q,permissions:A.permissions,resolveAttachment:A.attachments.resolve});A.messaging.subscribe("publish:execute",async($)=>{return await B.handle($.payload),{success:!0}}),w.debug("Subscribed to publish:execute messages")}function XA2(A,Q){A.messaging.subscribe("entity:updated",async(w)=>{let{entityType:B,entityId:$,entity:f}=w.payload;if(B!=="post")return{success:!0};if(f.metadata?.status!=="queued")return{success:!0};try{if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:$}},limit:1}})).length>0)return Q.debug(`Social post already exists for ${$}, skipping auto-generate`),{success:!0};return await A.messaging.send({type:"social:auto-generate",payload:{sourceEntityType:B,sourceEntityId:$,platform:"linkedin"}}),Q.info(`Auto-generate social post triggered for queued post ${$}`),{success:!0}}catch(X){let W=mA(X);return Q.error(`Failed to trigger auto-generate for ${$}:`,{error:W}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function ZA2(A,Q){A.messaging.subscribe("social:auto-generate",async(w)=>{let{sourceEntityType:B,sourceEntityId:$,platform:f}=w.payload;try{let Y=await A.jobs.enqueue({type:`${p7.entityType}:generation`,data:{sourceEntityType:B,sourceEntityId:$,platform:f,addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info(`Social post generation job enqueued for ${B}/${$}`,{jobId:Y}),{success:!0,jobId:Y}}catch(Y){let X=mA(Y);return Q.error(`Failed to enqueue social post generation for ${$}:`,{error:X}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function WA2(A,Q){A.messaging.subscribe("generate:execute",async(w)=>{let{entityType:B}=w.payload;if(B!=="social-post")return{success:!0};Q.info("Received generate:execute for social-post");try{let $=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:5}});if($.length===0)return Q.info("No published posts found for social post generation"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"No published posts available for social post generation"}}),{success:!0};let f=null;for(let X of $)if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:X.id}},limit:1}})).length===0){f=X;break}if(!f)return Q.info("All recent posts already have social posts"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"All recent posts already have social posts generated"}}),{success:!0};let Y=await A.jobs.enqueue({type:`${p7.entityType}:generation`,data:{sourceEntityType:"post",sourceEntityId:f.id,platform:"linkedin",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info("Social post generation job queued",{jobId:Y,sourcePostId:f.id}),{success:!0}}catch($){let f=mA($);return Q.error("Failed to handle generate:execute:",{error:f}),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:f}}),{success:!0}}}),Q.debug("Subscribed to generate:execute messages")}async function HA2({entity:A,config:Q}){let w=xF.parse(A),B=p7.parsePostFrontmatter(w),$=p7.getPostContent(w);return{$type:"ai.rizom.brain.socialPost",title:B.title,platform:B.platform,body:$,format:"text/markdown",status:B.status,...B.publishedAt&&{publishedAt:B.publishedAt},...B.platformPostId&&{platformPostId:B.platformPostId},...B.sourceEntityType&&{sourceLocalEntityType:B.sourceEntityType},...B.sourceEntityId&&{sourceLocalEntityId:B.sourceEntityId},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"social-post",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function bs0(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:L6["ai.rizom.brain.socialPost"],validate:!1,buildRecord:HA2}}var KA2={name:"@brains/social-media",version:"0.2.0-alpha.142",description:"Multi-provider social media posting with queue-based publishing",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class Vs0 extends nQ{entityType=p7.entityType;schema=xF;adapter=p7;providers=new Map;unregisterAtprotoProjection;constructor(A={}){super("social-media",KA2,A,Ks0)}createGenerationHandler(A){return new ZP(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return BA2()}getDataSources(){return[new rY0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),fA2(A,this.providers,this.logger),YA2(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)XA2(A,this.logger),ZA2(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");WA2(A,this.logger),$A2(A),this.unregisterAtprotoProjection=A8.getInstance().register(bs0()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=qs0(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function Io(A={}){return new Vs0(A)}N0();var PDw=Z.enum(["draft","queued","published","failed"]),UA2=Z.object({status:PDw.default("draft"),queueOrder:Z.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:Z.string().datetime().optional()});class Is0{name="internal";async publish(A,Q){return{id:"internal"}}}var Jo={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},of={REGISTER:"publish:register",QUEUE:"publish:queue",DIRECT:"publish:direct",REMOVE:"publish:remove",REORDER:"publish:reorder",LIST:"publish:list",REPORT_SUCCESS:"publish:report:success",REPORT_FAILURE:"publish:report:failure",QUEUED:"publish:queued",COMPLETED:"publish:completed",FAILED:"publish:failed",LIST_RESPONSE:"publish:list:response"},RF={REGISTER:"generate:register",REPORT_SUCCESS:"generate:report:success",REPORT_FAILURE:"generate:report:failure",EXECUTE:"generate:execute",COMPLETED:"generate:completed",FAILED:"generate:failed",SKIPPED:"generate:skipped"},DA2={REGISTER:"publish-assets:register"};N0();var MDw=Z.enum(["provider"]),GA2=Z.object({executionMode:MDw.optional(),publishResultIdField:Z.string().min(1).optional(),publishTimestampField:Z.string().min(1).optional(),enabled:Z.boolean().optional()}).strict();var ODw=Z.object({skipIfDraftExists:Z.boolean().optional(),minSourceEntities:Z.number().optional(),maxUnpublishedDrafts:Z.number().optional(),sourceEntityType:Z.string().optional()}),zA2=Z.object({entitySchedules:Z.record(Z.string(),Z.string()).optional(),generationSchedules:Z.record(Z.string(),Z.string()).optional(),generationConditions:Z.record(Z.string(),ODw).optional()});class Q3{static instance=null;queues=new Map;static getInstance(){return Q3.instance??=new Q3,Q3.instance}static resetInstance(){Q3.instance=null}static createFresh(){return new Q3}constructor(){}async add(A,Q,w=Jo){let B=this.getOrCreateQueue(A),$=B.find((X)=>X.entityId===Q);if($)return{position:$.position};let f=B.length+1,Y={entityId:Q,entityType:A,position:f,queuedAt:new Date().toISOString(),authContext:{...w}};return B.push(Y),{position:f}}async remove(A,Q){let w=this.queues.get(A);if(!w)return;let B=w.findIndex(($)=>$.entityId===Q);if(B===-1)return;w.splice(B,1),this.recalculatePositions(w)}async reorder(A,Q,w){let B=this.queues.get(A);if(!B)return;let $=B.findIndex((X)=>X.entityId===Q);if($===-1)return;let[f]=B.splice($,1);if(!f)return;let Y=Math.max(0,Math.min(w-1,B.length));B.splice(Y,0,f),this.recalculatePositions(B)}async list(A){let Q=this.queues.get(A);if(!Q)return[];return[...Q]}async getNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;return Q[0]??null}async getNextAcrossTypes(){let A=null;for(let Q of this.queues.values()){let w=Q[0];if(!w)continue;if(!A||w.queuedAt<A.queuedAt)A=w}return A}async popNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let w=Q.shift()??null;if(w)this.recalculatePositions(Q);return w}getRegisteredTypes(){return Array.from(this.queues.keys())}async getQueuedEntityTypes(){let A=[];for(let[Q,w]of this.queues.entries())if(w.length>0)A.push(Q);return A}getOrCreateQueue(A){let Q=this.queues.get(A);if(!Q)Q=[],this.queues.set(A,Q);return Q}recalculatePositions(A){A.forEach((Q,w)=>{Q.position=w+1})}}class w3{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new Is0;static getInstance(){return w3.instance??=new w3,w3.instance}static resetInstance(){w3.instance=null}static createFresh(){return new w3}constructor(){}register(A,Q,w){let B=this.providers.get(A);if(B&&B.name!=="internal"&&Q.name==="internal")return;if(this.providers.set(A,Q),this.executionModes.set(A,w?.executionMode??"provider"),w?.publishResultIdField)this.publishResultIdFields.set(A,w.publishResultIdField);else this.publishResultIdFields.delete(A);if(w?.publishTimestampField)this.publishTimestampFields.set(A,w.publishTimestampField);else this.publishTimestampFields.delete(A)}get(A){return this.providers.get(A)??this.defaultProvider}getExecutionMode(A){return this.executionModes.get(A)??"provider"}getPublishResultIdField(A){return this.publishResultIdFields.get(A)}getPublishTimestampField(A){return this.publishTimestampFields.get(A)}has(A){return this.providers.has(A)}unregister(A){this.providers.delete(A),this.executionModes.delete(A),this.publishResultIdFields.delete(A),this.publishTimestampFields.delete(A)}getRegisteredTypes(){return Array.from(this.providers.keys())}}async function qA2(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await xDw(A,Q)}async function xDw(A,Q){if(!Q.publishExecutor)return;try{let w=await Q.publishExecutor.publish({entityType:A.entityType,id:A.entityId});if("error"in w){let B={entityType:A.entityType,entityId:A.entityId,error:w.error,retryCount:0,willRetry:!1};if(Q.messageBus)await Q.messageBus.send({type:of.FAILED,payload:B,sender:"publish-service",broadcast:!0});Q.onFailed?.(B);return}Js0(A.entityType,A.entityId,w.result,Q)}catch(w){let B=mA(w);Q.retryTracker.recordFailure(A.entityId,B);let $=Q.retryTracker.getRetryInfo(A.entityId);Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:B,retryCount:$?.retryCount??1,willRetry:!1})}}function Js0(A,Q,w,B){if(B.retryTracker.clearRetries(Q),B.messageBus)B.messageBus.send({type:of.COMPLETED,payload:{entityType:A,entityId:Q,result:w},sender:"publish-service",broadcast:!0});B.onPublish?.({entityType:A,entityId:Q,result:w})}function bA2(A,Q,w,B){B.retryTracker.recordFailure(Q,w);let $=B.retryTracker.getRetryInfo(Q),f={entityType:A,entityId:Q,error:w,retryCount:$?.retryCount??1,willRetry:!1};if(B.messageBus)B.messageBus.send({type:of.FAILED,payload:f,sender:"publish-service",broadcast:!0});B.onFailed?.(f)}async function VA2(A,Q){let w=Q.generationConditions[A];if(w&&Q.onCheckGenerationConditions){let $=await Q.onCheckGenerationConditions(A,w);if(!$.shouldGenerate){if(Q.messageBus)Q.messageBus.send({type:RF.SKIPPED,payload:{entityType:A,reason:$.reason??"Conditions not met"},sender:"content-pipeline"});return}}let B={entityType:A};if(Q.messageBus)await Q.messageBus.send({type:RF.EXECUTE,payload:B,sender:"content-pipeline"});Q.onGenerate?.(B)}function IA2(A,Q,w){if(w)w.send({type:RF.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function JA2(A,Q,w){if(w)w.send({type:RF.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var RDw=1000;class Fs0{deps;publishJobs=new Map;immediateIntervalJob=null;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.entitySchedules)){let w=this.deps.config.backend.scheduleCron(Q,()=>this.processEntityType(A));this.publishJobs.set(A,w)}this.immediateIntervalJob=this.deps.config.backend.scheduleInterval(RDw,()=>this.processUnscheduledTypes())}stop(){if(vDw(this.publishJobs),this.immediateIntervalJob)this.immediateIntervalJob.stop(),this.immediateIntervalJob=null}async processEntityType(A){if(!this.deps.isRunning())return;try{let Q=await this.deps.config.queueManager.getNext(A);if(Q)await this.processEntry(Q)}catch(Q){this.deps.config.logger.error(`Scheduler error for ${A}:`,Q)}}async processUnscheduledTypes(){if(!this.deps.isRunning())return;try{let A=await this.deps.config.queueManager.getQueuedEntityTypes();for(let Q of A)if(!this.entitySchedules[Q]){let w=await this.deps.config.queueManager.getNext(Q);if(w){await this.processEntry(w);break}}}catch(A){this.deps.config.logger.error("Scheduler error for unscheduled types:",A)}}async processEntry(A){await this.deps.config.queueManager.remove(A.entityType,A.entityId);let Q=this.deps.getPublishDeps();await qA2(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}function vDw(A){for(let Q of A.values())Q.stop();A.clear()}class Ls0{deps;generationJobs=new Map;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.generationSchedules)){let w=this.deps.config.backend.scheduleCron(Q,()=>this.handleTriggerGeneration(A));this.generationJobs.set(A,w)}}stop(){hDw(this.generationJobs)}async handleTriggerGeneration(A){if(!this.deps.isRunning())return;try{await VA2(A,this.deps.getGenerationDeps())}catch(Q){this.deps.config.logger.error(`Generation trigger error for ${A}:`,Q)}}get generationSchedules(){return this.deps.config.generationSchedules}}function hDw(A){for(let Q of A.values())Q.stop();A.clear()}class xU{static instance=null;config;publishRunner;generationRunner;running=!1;static getInstance(A){return xU.instance??=new xU(A),xU.instance}static resetInstance(){if(xU.instance)xU.instance.stop();xU.instance=null}static createFresh(A){return new xU(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new Fs0({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new Ls0({config:this.config,getGenerationDeps:()=>this.generationDeps,isRunning:()=>this.running})}async start(){if(this.running)return;this.running=!0,this.publishRunner.start(),this.generationRunner.start()}async stop(){this.running=!1,this.publishRunner.stop(),this.generationRunner.stop()}isRunning(){return this.running}completePublish(A,Q,w){Js0(A,Q,w,this.publishDeps)}failPublish(A,Q,w){bA2(A,Q,w,this.publishDeps)}completeGeneration(A,Q){IA2(A,Q,this.config.messageBus)}failGeneration(A,Q){JA2(A,Q,this.config.messageBus)}get entitySchedules(){return this.config.entitySchedules}get generationSchedules(){return this.config.generationSchedules}get publishDeps(){return{retryTracker:this.config.retryTracker,messageBus:this.config.messageBus,publishExecutor:this.config.publishExecutor,onPublish:this.config.onPublish,onFailed:this.config.onFailed}}get generationDeps(){return{logger:this.config.logger,messageBus:this.config.messageBus,generationConditions:this.config.generationConditions,onCheckGenerationConditions:this.config.onCheckGenerationConditions,onGenerate:this.config.onGenerate}}validateCronExpressions(){for(let[A,Q]of Object.entries(this.entitySchedules))this.validateCronExpression(A,Q,"publish");for(let[A,Q]of Object.entries(this.generationSchedules))this.validateCronExpression(A,Q,"generation")}validateCronExpression(A,Q,w){try{this.config.backend.validateCron(Q)}catch(B){throw Error(`Invalid ${w} cron expression for ${A}: "${Q}" - ${mA(B)}`,{cause:B})}}}class B3{static instance=null;retries=new Map;static getInstance(){return B3.instance??=new B3,B3.instance}static resetInstance(){B3.instance=null}static createFresh(){return new B3}constructor(){}recordFailure(A,Q){let B=(this.retries.get(A)?.retryCount??0)+1;this.retries.set(A,{entityId:A,retryCount:B,lastError:Q})}clearRetries(A){this.retries.delete(A)}getRetryInfo(A){let Q=this.retries.get(A);if(!Q)return null;return{entityId:Q.entityId,retryCount:Q.retryCount,lastError:Q.lastError}}}function Fo(A){return Date.UTC(A.y,A.m-1,A.d,A.h,A.i,A.s)}function ks0(A,Q){return A.y===Q.y&&A.m===Q.m&&A.d===Q.d&&A.h===Q.h&&A.i===Q.i&&A.s===Q.s}function CDw(A,Q){let w=new Date(Date.parse(A));if(isNaN(w))throw Error("Invalid ISO8601 passed to timezone parser.");let B=A.substring(9);return B.includes("Z")||B.includes("+")||B.includes("-")?Ns0(w.getUTCFullYear(),w.getUTCMonth()+1,w.getUTCDate(),w.getUTCHours(),w.getUTCMinutes(),w.getUTCSeconds(),"Etc/UTC"):Ns0(w.getFullYear(),w.getMonth()+1,w.getDate(),w.getHours(),w.getMinutes(),w.getSeconds(),Q)}function FA2(A,Q,w){return _A2(CDw(A,Q),w)}function _A2(A,Q){let w=new Date(Fo(A)),B=Lo(w,A.tz),$=Fo(A),f=Fo(B),Y=$-f,X=new Date(w.getTime()+Y),W=Lo(X,A.tz);if(ks0(W,A)){let U=new Date(X.getTime()-3600000),D=Lo(U,A.tz);return ks0(D,A)?U:X}let H=new Date(X.getTime()+Fo(A)-Fo(W)),K=Lo(H,A.tz);if(ks0(K,A))return H;if(Q)throw Error("Invalid date passed to fromTZ()");return X.getTime()>H.getTime()?X:H}function Lo(A,Q){let w,B;try{w=new Intl.DateTimeFormat("en-US",{timeZone:Q,year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric",hour12:!1}),B=w.formatToParts(A)}catch(f){let Y=f instanceof Error?f.message:String(f);throw RangeError(`toTZ: Invalid timezone '${Q}' or date. Please provide a valid IANA timezone (e.g., 'America/New_York', 'Europe/Stockholm'). Original error: ${Y}`)}let $={year:0,month:0,day:0,hour:0,minute:0,second:0};for(let f of B)(f.type==="year"||f.type==="month"||f.type==="day"||f.type==="hour"||f.type==="minute"||f.type==="second")&&($[f.type]=parseInt(f.value,10));if(isNaN($.year)||isNaN($.month)||isNaN($.day)||isNaN($.hour)||isNaN($.minute)||isNaN($.second))throw Error(`toTZ: Failed to parse all date components from timezone '${Q}'. This may indicate an invalid date or timezone configuration. Parsed components: ${JSON.stringify($)}`);return $.hour===24&&($.hour=0),{y:$.year,m:$.month,d:$.day,h:$.hour,i:$.minute,s:$.second,tz:Q}}function Ns0(A,Q,w,B,$,f,Y){return{y:A,m:Q,d:w,h:B,i:$,s:f,tz:Y}}var NA2=[1,2,4,8,16],LA2=class{pattern;timezone;mode;alternativeWeekdays;sloppyRanges;second;minute;hour;day;month;dayOfWeek;year;lastDayOfMonth;lastWeekday;nearestWeekdays;starDOM;starDOW;starYear;useAndLogic;constructor(A,Q,w){this.pattern=A,this.timezone=Q,this.mode=w?.mode??"auto",this.alternativeWeekdays=w?.alternativeWeekdays??!1,this.sloppyRanges=w?.sloppyRanges??!1,this.second=Array(60).fill(0),this.minute=Array(60).fill(0),this.hour=Array(24).fill(0),this.day=Array(31).fill(0),this.month=Array(12).fill(0),this.dayOfWeek=Array(7).fill(0),this.year=Array(1e4).fill(0),this.lastDayOfMonth=!1,this.lastWeekday=!1,this.nearestWeekdays=Array(31).fill(0),this.starDOM=!1,this.starDOW=!1,this.starYear=!1,this.useAndLogic=!1,this.parse()}parse(){if(!(typeof this.pattern=="string"||this.pattern instanceof String))throw TypeError("CronPattern: Pattern has to be of type string.");this.pattern.indexOf("@")>=0&&(this.pattern=this.handleNicknames(this.pattern).trim());let A=this.pattern.match(/\S+/g)||[""],Q=A.length;if(A.length<5||A.length>7)throw TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exactly five, six, or seven space separated parts are required.");if(this.mode!=="auto"){let B;switch(this.mode){case"5-part":B=5;break;case"6-part":B=6;break;case"7-part":B=7;break;case"5-or-6-parts":B=[5,6];break;case"6-or-7-parts":B=[6,7];break;default:B=0}if(!(Array.isArray(B)?B.includes(Q):Q===B)){let $=Array.isArray(B)?B.join(" or "):B.toString();throw TypeError(`CronPattern: mode '${this.mode}' requires exactly ${$} parts, but pattern '${this.pattern}' has ${Q} parts.`)}}if(A.length===5&&A.unshift("0"),A.length===6&&A.push("*"),A[3].toUpperCase()==="LW"?(this.lastWeekday=!0,A[3]=""):A[3].toUpperCase().indexOf("L")>=0&&(A[3]=A[3].replace(/L/gi,""),this.lastDayOfMonth=!0),A[3]=="*"&&(this.starDOM=!0),A[6]=="*"&&(this.starYear=!0),A[4].length>=3&&(A[4]=this.replaceAlphaMonths(A[4])),A[5].length>=3&&(A[5]=this.alternativeWeekdays?this.replaceAlphaDaysQuartz(A[5]):this.replaceAlphaDays(A[5])),A[5].startsWith("+")&&(this.useAndLogic=!0,A[5]=A[5].substring(1),A[5]===""))throw TypeError("CronPattern: Day-of-week field cannot be empty after '+' modifier.");switch(A[5]=="*"&&(this.starDOW=!0),this.pattern.indexOf("?")>=0&&(A[0]=A[0].replace(/\?/g,"*"),A[1]=A[1].replace(/\?/g,"*"),A[2]=A[2].replace(/\?/g,"*"),A[3]=A[3].replace(/\?/g,"*"),A[4]=A[4].replace(/\?/g,"*"),A[5]=A[5].replace(/\?/g,"*"),A[6]&&(A[6]=A[6].replace(/\?/g,"*"))),this.mode){case"5-part":A[0]="0",A[6]="*";break;case"6-part":A[6]="*";break;case"5-or-6-parts":A[6]="*";break;case"6-or-7-parts":break;case"7-part":case"auto":break}this.throwAtIllegalCharacters(A),this.partToArray("second",A[0],0,1),this.partToArray("minute",A[1],0,1),this.partToArray("hour",A[2],0,1),this.partToArray("day",A[3],-1,1),this.partToArray("month",A[4],-1,1);let w=this.alternativeWeekdays?-1:0;this.partToArray("dayOfWeek",A[5],w,63),this.partToArray("year",A[6],0,1),!this.alternativeWeekdays&&this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(A,Q,w,B){let $=this[A],f=A==="day"&&this.lastDayOfMonth,Y=A==="day"&&this.lastWeekday;if(Q===""&&!f&&!Y)throw TypeError("CronPattern: configuration entry "+A+" ("+Q+") is empty, check for trailing spaces.");if(Q==="*")return $.fill(B);let X=Q.split(",");if(X.length>1)for(let W=0;W<X.length;W++)this.partToArray(A,X[W],w,B);else Q.indexOf("-")!==-1&&Q.indexOf("/")!==-1?this.handleRangeWithStepping(Q,A,w,B):Q.indexOf("-")!==-1?this.handleRange(Q,A,w,B):Q.indexOf("/")!==-1?this.handleStepping(Q,A,w,B):Q!==""&&this.handleNumber(Q,A,w,B)}throwAtIllegalCharacters(A){for(let Q=0;Q<A.length;Q++)if((Q===3?/[^/*0-9,\-WwLl]+/:Q===5?/[^/*0-9,\-#Ll]+/:/[^/*0-9,\-]+/).test(A[Q]))throw TypeError("CronPattern: configuration entry "+Q+" ("+A[Q]+") contains illegal characters.")}handleNumber(A,Q,w,B){let $=this.extractNth(A,Q),f=A.toUpperCase().includes("W");if(Q!=="day"&&f)throw TypeError("CronPattern: Nearest weekday modifier (W) only allowed in day-of-month.");f&&(Q="nearestWeekdays");let Y=parseInt($[0],10)+w;if(isNaN(Y))throw TypeError("CronPattern: "+Q+" is not a number: '"+A+"'");this.setPart(Q,Y,$[1]||B)}setPart(A,Q,w){if(!Object.prototype.hasOwnProperty.call(this,A))throw TypeError("CronPattern: Invalid part specified: "+A);if(A==="dayOfWeek"){if(Q===7&&(Q=0),Q<0||Q>6)throw RangeError("CronPattern: Invalid value for dayOfWeek: "+Q);this.setNthWeekdayOfMonth(Q,w);return}if(A==="second"||A==="minute"){if(Q<0||Q>=60)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="hour"){if(Q<0||Q>=24)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="day"||A==="nearestWeekdays"){if(Q<0||Q>=31)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="month"){if(Q<0||Q>=12)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="year"&&(Q<1||Q>=1e4))throw RangeError("CronPattern: Invalid value for "+A+": "+Q+" (supported range: 1-9999)");this[A][Q]=w}validateNotNaN(A,Q){if(isNaN(A))throw TypeError(Q)}validateRange(A,Q,w,B,$){if(A>Q)throw TypeError("CronPattern: From value is larger than to value: '"+$+"'");if(w!==void 0){if(w===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(w>this[B].length)throw TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[B].length+")")}}handleRangeWithStepping(A,Q,w,B){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in ranges with stepping.");let $=this.extractNth(A,Q),f=$[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(f===null)throw TypeError("CronPattern: Syntax error, illegal range with stepping: '"+A+"'");let[,Y,X,W]=f,H=parseInt(Y,10)+w,K=parseInt(X,10)+w,U=parseInt(W,10);this.validateNotNaN(H,"CronPattern: Syntax error, illegal lower range (NaN)"),this.validateNotNaN(K,"CronPattern: Syntax error, illegal upper range (NaN)"),this.validateNotNaN(U,"CronPattern: Syntax error, illegal stepping: (NaN)"),this.validateRange(H,K,U,Q,A);for(let D=H;D<=K;D+=U)this.setPart(Q,D,$[1]||B)}extractNth(A,Q){let w=A,B;if(w.includes("#")){if(Q!=="dayOfWeek")throw Error("CronPattern: nth (#) only allowed in day-of-week field");B=w.split("#")[1],w=w.split("#")[0]}else if(w.toUpperCase().endsWith("L")){if(Q!=="dayOfWeek")throw Error("CronPattern: L modifier only allowed in day-of-week field (use L alone for day-of-month)");B="L",w=w.slice(0,-1)}return[w,B]}handleRange(A,Q,w,B){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in a range.");let $=this.extractNth(A,Q),f=$[0].split("-");if(f.length!==2)throw TypeError("CronPattern: Syntax error, illegal range: '"+A+"'");let Y=parseInt(f[0],10)+w,X=parseInt(f[1],10)+w;this.validateNotNaN(Y,"CronPattern: Syntax error, illegal lower range (NaN)"),this.validateNotNaN(X,"CronPattern: Syntax error, illegal upper range (NaN)"),this.validateRange(Y,X,void 0,Q,A);for(let W=Y;W<=X;W++)this.setPart(Q,W,$[1]||B)}handleStepping(A,Q,w,B){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in parts with stepping.");let $=this.extractNth(A,Q),f=$[0].split("/");if(f.length!==2)throw TypeError("CronPattern: Syntax error, illegal stepping: '"+A+"'");if(this.sloppyRanges)f[0]===""&&(f[0]="*");else{if(f[0]==="")throw TypeError("CronPattern: Syntax error, stepping with missing prefix ('"+A+"') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.");if(f[0]!=="*")throw TypeError("CronPattern: Syntax error, stepping with numeric prefix ('"+A+"') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.")}let Y=0;f[0]!=="*"&&(Y=parseInt(f[0],10)+w);let X=parseInt(f[1],10);this.validateNotNaN(X,"CronPattern: Syntax error, illegal stepping: (NaN)"),this.validateRange(0,this[Q].length-1,X,Q,A);for(let W=Y;W<this[Q].length;W+=X)this.setPart(Q,W,$[1]||B)}replaceAlphaDays(A){return A.replace(/-sun/gi,"-7").replace(/sun/gi,"0").replace(/mon/gi,"1").replace(/tue/gi,"2").replace(/wed/gi,"3").replace(/thu/gi,"4").replace(/fri/gi,"5").replace(/sat/gi,"6")}replaceAlphaDaysQuartz(A){return A.replace(/sun/gi,"1").replace(/mon/gi,"2").replace(/tue/gi,"3").replace(/wed/gi,"4").replace(/thu/gi,"5").replace(/fri/gi,"6").replace(/sat/gi,"7")}replaceAlphaMonths(A){return A.replace(/jan/gi,"1").replace(/feb/gi,"2").replace(/mar/gi,"3").replace(/apr/gi,"4").replace(/may/gi,"5").replace(/jun/gi,"6").replace(/jul/gi,"7").replace(/aug/gi,"8").replace(/sep/gi,"9").replace(/oct/gi,"10").replace(/nov/gi,"11").replace(/dec/gi,"12")}handleNicknames(A){let Q=A.trim().toLowerCase();if(Q==="@yearly"||Q==="@annually")return"0 0 1 1 *";if(Q==="@monthly")return"0 0 1 * *";if(Q==="@weekly")return"0 0 * * 0";if(Q==="@daily"||Q==="@midnight")return"0 0 * * *";if(Q==="@hourly")return"0 * * * *";if(Q==="@reboot")throw TypeError("CronPattern: @reboot is not supported in this environment. This is an event-based trigger that requires system startup detection.");return A}setNthWeekdayOfMonth(A,Q){if(typeof Q!="number"&&Q.toUpperCase()==="L")this.dayOfWeek[A]=this.dayOfWeek[A]|32;else if(Q===63)this.dayOfWeek[A]=63;else if(Q<6&&Q>0)this.dayOfWeek[A]=this.dayOfWeek[A]|NA2[Q-1];else throw TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${Q}, Type: ${typeof Q}`)}},_s0=[31,28,31,30,31,30,31,31,30,31,30,31],K$=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],i7=class A{tz;ms;second;minute;hour;day;month;year;constructor(Q,w){if(this.tz=w,Q&&Q instanceof Date)if(!isNaN(Q))this.fromDate(Q);else throw TypeError("CronDate: Invalid date passed to CronDate constructor");else if(Q==null)this.fromDate(new Date);else if(Q&&typeof Q=="string")this.fromString(Q);else if(Q instanceof A)this.fromCronDate(Q);else throw TypeError("CronDate: Invalid type ("+typeof Q+") passed to CronDate constructor")}getLastDayOfMonth(Q,w){return w!==1?_s0[w]:new Date(Date.UTC(Q,w+1,0)).getUTCDate()}getLastWeekday(Q,w){let B=this.getLastDayOfMonth(Q,w),$=new Date(Date.UTC(Q,w,B)).getUTCDay();return $===0?B-2:$===6?B-1:B}getNearestWeekday(Q,w,B){let $=this.getLastDayOfMonth(Q,w);if(B>$)return-1;let f=new Date(Date.UTC(Q,w,B)).getUTCDay();return f===0?B===$?B-2:B+1:f===6?B===1?B+2:B-1:B}isNthWeekdayOfMonth(Q,w,B,$){let f=new Date(Date.UTC(Q,w,B)).getUTCDay(),Y=0;for(let X=1;X<=B;X++)new Date(Date.UTC(Q,w,X)).getUTCDay()===f&&Y++;if($&63&&NA2[Y-1]&$)return!0;if($&32){let X=this.getLastDayOfMonth(Q,w);for(let W=B+1;W<=X;W++)if(new Date(Date.UTC(Q,w,W)).getUTCDay()===f)return!1;return!0}return!1}fromDate(Q){if(this.tz!==void 0)if(typeof this.tz=="number")this.ms=Q.getUTCMilliseconds(),this.second=Q.getUTCSeconds(),this.minute=Q.getUTCMinutes()+this.tz,this.hour=Q.getUTCHours(),this.day=Q.getUTCDate(),this.month=Q.getUTCMonth(),this.year=Q.getUTCFullYear(),this.apply();else try{let w=Lo(Q,this.tz);this.ms=Q.getMilliseconds(),this.second=w.s,this.minute=w.i,this.hour=w.h,this.day=w.d,this.month=w.m-1,this.year=w.y}catch(w){let B=w instanceof Error?w.message:String(w);throw TypeError(`CronDate: Failed to convert date to timezone '${this.tz}'. This may happen with invalid timezone names or dates. Original error: ${B}`)}else this.ms=Q.getMilliseconds(),this.second=Q.getSeconds(),this.minute=Q.getMinutes(),this.hour=Q.getHours(),this.day=Q.getDate(),this.month=Q.getMonth(),this.year=Q.getFullYear()}fromCronDate(Q){this.tz=Q.tz,this.year=Q.year,this.month=Q.month,this.day=Q.day,this.hour=Q.hour,this.minute=Q.minute,this.second=Q.second,this.ms=Q.ms}apply(){if(this.month>11||this.month<0||this.day>_s0[this.month]||this.day<1||this.hour>59||this.minute>59||this.second>59||this.hour<0||this.minute<0||this.second<0){let Q=new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms));return this.ms=Q.getUTCMilliseconds(),this.second=Q.getUTCSeconds(),this.minute=Q.getUTCMinutes(),this.hour=Q.getUTCHours(),this.day=Q.getUTCDate(),this.month=Q.getUTCMonth(),this.year=Q.getUTCFullYear(),!0}else return!1}fromString(Q){if(typeof this.tz=="number"){let w=FA2(Q);this.ms=w.getUTCMilliseconds(),this.second=w.getUTCSeconds(),this.minute=w.getUTCMinutes(),this.hour=w.getUTCHours(),this.day=w.getUTCDate(),this.month=w.getUTCMonth(),this.year=w.getUTCFullYear(),this.apply()}else return this.fromDate(FA2(Q,this.tz))}findNext(Q,w,B,$){return this._findMatch(Q,w,B,$,1)}_findMatch(Q,w,B,$,f){let Y=this[w],X;B.lastDayOfMonth&&(X=this.getLastDayOfMonth(this.year,this.month));let W=!B.starDOW&&w=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0,H=this[w]+$,K=f===1?(U)=>U<B[w].length:(U)=>U>=0;for(let U=H;K(U);U+=f){let D=B[w][U];if(w==="day"&&!D){for(let q=0;q<B.nearestWeekdays.length;q++)if(B.nearestWeekdays[q]){let b=this.getNearestWeekday(this.year,this.month,q-$);if(b===-1)continue;if(b===U-$){D=1;break}}}if(w==="day"&&B.lastWeekday){let q=this.getLastWeekday(this.year,this.month);U-$===q&&(D=1)}if(w==="day"&&B.lastDayOfMonth&&U-$==X&&(D=1),w==="day"&&!B.starDOW){let q=B.dayOfWeek[(W+(U-$-1))%7];if(q&&q&63)q=this.isNthWeekdayOfMonth(this.year,this.month,U-$,q)?1:0;else if(q)throw Error(`CronDate: Invalid value for dayOfWeek encountered. ${q}`);B.useAndLogic?D=D&&q:!Q.domAndDow&&!B.starDOM?D=D||q:D=D&&q}if(D)return this[w]=U-$,Y!==this[w]?2:1}return 3}recurse(Q,w,B){if(B===0&&!Q.starYear){if(this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0){let f=-1;for(let Y=this.year+1;Y<Q.year.length&&Y<1e4;Y++)if(Q.year[Y]===1){f=Y;break}if(f===-1)return null;this.year=f,this.month=0,this.day=1,this.hour=0,this.minute=0,this.second=0,this.ms=0}if(this.year>=1e4)return null}let $=this.findNext(w,K$[B][0],Q,K$[B][2]);if($>1){let f=B+1;for(;f<K$.length;)this[K$[f][0]]=-K$[f][2],f++;if($===3){if(this[K$[B][1]]++,this[K$[B][0]]=-K$[B][2],this.apply(),B===0&&!Q.starYear){for(;this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0&&this.year<1e4;)this.year++;if(this.year>=1e4||this.year>=Q.year.length)return null}return this.recurse(Q,w,0)}else if(this.apply())return this.recurse(Q,w,B-1)}return B+=1,B>=K$.length?this:(Q.starYear?this.year>=3000:this.year>=1e4)?null:this.recurse(Q,w,B)}increment(Q,w,B){return this.second+=w.interval!==void 0&&w.interval>1&&B?w.interval:1,this.ms=0,this.apply(),this.recurse(Q,w,0)}decrement(Q,w){return this.second-=w.interval!==void 0&&w.interval>1?w.interval:1,this.ms=0,this.apply(),this.recurseBackward(Q,w,0,0)}recurseBackward(Q,w,B,$=0){if($>1e4)return null;if(B===0&&!Q.starYear){if(this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0){let Y=-1;for(let X=this.year-1;X>=0;X--)if(Q.year[X]===1){Y=X;break}if(Y===-1)return null;this.year=Y,this.month=11,this.day=31,this.hour=23,this.minute=59,this.second=59,this.ms=0}if(this.year<0)return null}let f=this.findPrevious(w,K$[B][0],Q,K$[B][2]);if(f>1){let Y=B+1;for(;Y<K$.length;){let X=K$[Y][0],W=K$[Y][2],H=this.getMaxPatternValue(X,Q,W);this[X]=H,Y++}if(f===3){if(this[K$[B][1]]--,B===0){let K=this.getLastDayOfMonth(this.year,this.month);this.day>K&&(this.day=K)}if(B===1)if(this.day<=0)this.day=1;else{let K=this.year,U=this.month;for(;U<0;)U+=12,K--;for(;U>11;)U-=12,K++;let D=U!==1?_s0[U]:new Date(Date.UTC(K,U+1,0)).getUTCDate();this.day>D&&(this.day=D)}this.apply();let X=K$[B][0],W=K$[B][2],H=this.getMaxPatternValue(X,Q,W);if(X==="day"){let K=this.getLastDayOfMonth(this.year,this.month);this[X]=Math.min(H,K)}else this[X]=H;if(this.apply(),B===0){let K=K$[1][2],U=this.getMaxPatternValue("day",Q,K),D=this.getLastDayOfMonth(this.year,this.month),q=Math.min(U,D);q!==this.day&&(this.day=q,this.hour=this.getMaxPatternValue("hour",Q,K$[2][2]),this.minute=this.getMaxPatternValue("minute",Q,K$[3][2]),this.second=this.getMaxPatternValue("second",Q,K$[4][2]))}if(B===0&&!Q.starYear){for(;this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0;)this.year--;if(this.year<0)return null}return this.recurseBackward(Q,w,0,$+1)}else if(this.apply())return this.recurseBackward(Q,w,B-1,$+1)}return B+=1,B>=K$.length?this:this.year<0?null:this.recurseBackward(Q,w,B,$+1)}getMaxPatternValue(Q,w,B){if(Q==="day"&&w.lastDayOfMonth)return this.getLastDayOfMonth(this.year,this.month);if(Q==="day"&&!w.starDOW)return this.getLastDayOfMonth(this.year,this.month);for(let $=w[Q].length-1;$>=0;$--)if(w[Q][$])return $-B;return w[Q].length-1-B}findPrevious(Q,w,B,$){return this._findMatch(Q,w,B,$,-1)}getDate(Q){return Q||this.tz===void 0?new Date(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms):typeof this.tz=="number"?new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute-this.tz,this.second,this.ms)):_A2(Ns0(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}match(Q,w){if(!Q.starYear&&(this.year<0||this.year>=Q.year.length||Q.year[this.year]===0))return!1;for(let B=0;B<K$.length;B++){let $=K$[B][0],f=K$[B][2],Y=this[$];if(Y+f<0||Y+f>=Q[$].length)return!1;let X=Q[$][Y+f];if($==="day"){if(!X){for(let W=0;W<Q.nearestWeekdays.length;W++)if(Q.nearestWeekdays[W]){let H=this.getNearestWeekday(this.year,this.month,W-f);if(H!==-1&&H===Y){X=1;break}}}if(Q.lastWeekday){let W=this.getLastWeekday(this.year,this.month);Y===W&&(X=1)}if(Q.lastDayOfMonth){let W=this.getLastDayOfMonth(this.year,this.month);Y===W&&(X=1)}if(!Q.starDOW){let W=new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay(),H=Q.dayOfWeek[(W+(Y-1))%7];H&&H&63&&(H=this.isNthWeekdayOfMonth(this.year,this.month,Y,H)?1:0),Q.useAndLogic?X=X&&H:!w.domAndDow&&!Q.starDOM?X=X||H:X=X&&H}}if(!X)return!1}return!0}};function gDw(A){if(A===void 0&&(A={}),delete A.name,A.legacyMode!==void 0&&A.domAndDow===void 0?A.domAndDow=!A.legacyMode:A.domAndDow===void 0&&(A.domAndDow=!1),A.legacyMode=!A.domAndDow,A.paused=A.paused===void 0?!1:A.paused,A.maxRuns=A.maxRuns===void 0?1/0:A.maxRuns,A.catch=A.catch===void 0?!1:A.catch,A.interval=A.interval===void 0?0:parseInt(A.interval.toString(),10),A.utcOffset=A.utcOffset===void 0?void 0:parseInt(A.utcOffset.toString(),10),A.dayOffset=A.dayOffset===void 0?0:parseInt(A.dayOffset.toString(),10),A.unref=A.unref===void 0?!1:A.unref,A.mode=A.mode===void 0?"auto":A.mode,A.alternativeWeekdays=A.alternativeWeekdays===void 0?!1:A.alternativeWeekdays,A.sloppyRanges=A.sloppyRanges===void 0?!1:A.sloppyRanges,!["auto","5-part","6-part","7-part","5-or-6-parts","6-or-7-parts"].includes(A.mode))throw Error("CronOptions: mode must be one of 'auto', '5-part', '6-part', '7-part', '5-or-6-parts', or '6-or-7-parts'.");if(A.startAt&&(A.startAt=new i7(A.startAt,A.timezone)),A.stopAt&&(A.stopAt=new i7(A.stopAt,A.timezone)),A.interval!==null){if(isNaN(A.interval))throw Error("CronOptions: Supplied value for interval is not a number");if(A.interval<0)throw Error("CronOptions: Supplied value for interval can not be negative")}if(A.utcOffset!==void 0){if(isNaN(A.utcOffset))throw Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.");if(A.utcOffset<-870||A.utcOffset>870)throw Error("CronOptions: utcOffset out of bounds.");if(A.utcOffset!==void 0&&A.timezone)throw Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.")}if(A.unref!==!0&&A.unref!==!1)throw Error("CronOptions: Unref should be either true, false or undefined(false).");if(A.dayOffset!==void 0&&A.dayOffset!==0&&isNaN(A.dayOffset))throw Error("CronOptions: Invalid value passed for dayOffset, should be a number representing days to offset.");return A}function ko(A){return Object.prototype.toString.call(A)==="[object Function]"||typeof A=="function"||A instanceof Function}function yDw(A){return ko(A)}function EDw(A){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(A):A&&typeof A.unref<"u"&&A.unref()}var kA2=30000,tY0=[],js0=class{name;options;_states;fn;getTz(){return this.options.timezone||this.options.utcOffset}applyDayOffset(A){if(this.options.dayOffset!==void 0&&this.options.dayOffset!==0){let Q=this.options.dayOffset*24*60*60*1000;return new Date(A.getTime()+Q)}return A}constructor(A,Q,w){let B,$;if(ko(Q))$=Q;else if(typeof Q=="object")B=Q;else if(Q!==void 0)throw Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if(ko(w))$=w;else if(typeof w=="object")B=w;else if(w!==void 0)throw Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");if(this.name=B?.name,this.options=gDw(B),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:B?B.maxRuns:void 0,paused:B?B.paused:!1,pattern:new LA2("* * * * *",void 0,{mode:"auto"})},A&&(A instanceof Date||typeof A=="string"&&A.indexOf(":")>0)?this._states.once=new i7(A,this.getTz()):this._states.pattern=new LA2(A,this.options.timezone,{mode:this.options.mode,alternativeWeekdays:this.options.alternativeWeekdays,sloppyRanges:this.options.sloppyRanges}),this.name){if(tY0.find((f)=>f.name===this.name))throw Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");tY0.push(this)}return $!==void 0&&yDw($)&&(this.fn=$,this.schedule()),this}nextRun(A){let Q=this._next(A);return Q?this.applyDayOffset(Q.getDate(!1)):null}nextRuns(A,Q){this._states.maxRuns!==void 0&&A>this._states.maxRuns&&(A=this._states.maxRuns);let w=Q||this._states.currentRun||void 0;return this._enumerateRuns(A,w,"next")}previousRuns(A,Q){return this._enumerateRuns(A,Q||void 0,"previous")}_enumerateRuns(A,Q,w){let B=[],$=Q?new i7(Q,this.getTz()):null,f=w==="next"?this._next:this._previous;for(;A--;){let Y=f.call(this,$);if(!Y)break;let X=Y.getDate(!1);B.push(this.applyDayOffset(X)),$=Y}return B}match(A){if(this._states.once){let w=new i7(A,this.getTz());w.ms=0;let B=new i7(this._states.once,this.getTz());return B.ms=0,w.getTime()===B.getTime()}let Q=new i7(A,this.getTz());return Q.ms=0,Q.match(this._states.pattern,this.options)}getPattern(){if(!this._states.once)return this._states.pattern?this._states.pattern.pattern:void 0}getOnce(){return this._states.once?this._states.once.getDate():null}isRunning(){let A=this.nextRun(this._states.currentRun),Q=!this._states.paused,w=this.fn!==void 0,B=!this._states.kill;return Q&&w&&B&&A!==null}isStopped(){return this._states.kill}isBusy(){return this._states.blocking}currentRun(){return this._states.currentRun?this._states.currentRun.getDate():null}previousRun(){return this._states.previousRun?this._states.previousRun.getDate():null}msToNext(A){let Q=this._next(A);return Q?A instanceof i7||A instanceof Date?Q.getTime()-A.getTime():Q.getTime()-new i7(A).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let A=tY0.indexOf(this);A>=0&&tY0.splice(A,1)}pause(){return this._states.paused=!0,!this._states.kill}resume(){return this._states.paused=!1,!this._states.kill}schedule(A){if(A&&this.fn)throw Error("Cron: It is not allowed to schedule two functions using the same Croner instance.");A&&(this.fn=A);let Q=this.msToNext(),w=this.nextRun(this._states.currentRun);return Q==null||isNaN(Q)||w===null?this:(Q>kA2&&(Q=kA2),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(w),Q),this._states.currentTimeout&&this.options.unref&&EDw(this._states.currentTimeout),this)}async _trigger(A){this._states.blocking=!0,this._states.currentRun=new i7(void 0,this.getTz());try{if(this.options.catch)try{this.fn!==void 0&&await this.fn(this,this.options.context)}catch(Q){if(ko(this.options.catch))try{this.options.catch(Q,this)}catch{}}else this.fn!==void 0&&await this.fn(this,this.options.context)}finally{this._states.previousRun=new i7(A,this.getTz()),this._states.blocking=!1}}async trigger(){await this._trigger()}runsLeft(){return this._states.maxRuns}_checkTrigger(A){let Q=new Date,w=!this._states.paused&&Q.getTime()>=A.getTime(),B=this._states.blocking&&this.options.protect;w&&!B?(this._states.maxRuns!==void 0&&this._states.maxRuns--,this._trigger()):w&&B&&ko(this.options.protect)&&setTimeout(()=>this.options.protect(this),0),this.schedule()}_next(A){let Q=!!(A||this._states.currentRun),w=!1;!A&&this.options.startAt&&this.options.interval&&([A,Q]=this._calculatePreviousRun(A,Q),w=!A),A=new i7(A,this.getTz()),this.options.startAt&&A&&A.getTime()<this.options.startAt.getTime()&&(A=this.options.startAt);let B=this._states.once||new i7(A,this.getTz());return!w&&B!==this._states.once&&(B=B.increment(this._states.pattern,this.options,Q)),this._states.once&&this._states.once.getTime()<=A.getTime()||B===null||this._states.maxRuns!==void 0&&this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&B.getTime()>=this.options.stopAt.getTime()?null:B}_previous(A){let Q=new i7(A,this.getTz());this.options.stopAt&&Q.getTime()>this.options.stopAt.getTime()&&(Q=this.options.stopAt);let w=new i7(Q,this.getTz());return this._states.once?this._states.once.getTime()<Q.getTime()?this._states.once:null:(w=w.decrement(this._states.pattern,this.options),w===null||this.options.startAt&&w.getTime()<this.options.startAt.getTime()?null:w)}_calculatePreviousRun(A,Q){let w=new i7(void 0,this.getTz()),B=A;if(this.options.startAt.getTime()<=w.getTime()){B=this.options.startAt;let $=B.getTime()+this.options.interval*1000;for(;$<=w.getTime();)B=new i7(B,this.getTz()).increment(this._states.pattern,this.options,!0),$=B.getTime()+this.options.interval*1000;Q=!0}return B===null&&(B=void 0),[B,Q]}};class eY0{scheduleCron(A,Q){let w=new js0(A,()=>{Q()});return{stop:()=>w.stop()}}scheduleInterval(A,Q){let w=setInterval(()=>{Q()},A);return{stop:()=>clearInterval(w)}}validateCron(A){new js0(A).stop()}}N0();var jA2=Z.union([Z.string().min(1),Z.object({location:Z.enum(["metadata","frontmatter"]),field:Z.string().min(1)})]),AX0=Z.object({entityType:Z.string().min(1),attachmentType:Z.string().min(1),mediaEntityType:Z.enum(["image","document"]),targetEntityField:jA2.optional(),requiredWhen:Z.object({status:Z.string().min(1).optional(),visibility:Z.string().min(1).optional()}).optional(),autoGenerate:Z.boolean().optional(),requiredForPublish:Z.boolean().optional(),jobType:Z.string().min(1).optional()});function Ps0(A){return`${A.entityType}:${A.attachmentType}`}class $3{static instance=null;definitions=new Map;static getInstance(){return $3.instance??=new $3,$3.instance}static resetInstance(){$3.instance=null}static createFresh(){return new $3}constructor(){}register(A){let Q=AX0.parse(A),w=Ps0(Q);return this.definitions.set(w,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(Ps0({entityType:A,attachmentType:Q}))}list(A){let Q=Array.from(this.definitions.values());return A?Q.filter((w)=>w.entityType===A):Q}has(A,Q){return this.get(A,Q)!==void 0}unregister(A,Q){this.definitions.delete(Ps0({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}S9();K2();class QX0{deps;constructor(A){this.deps=A}async ensureForEntity(A,Q={}){let w=this.deps.registry.list(A.entityType).filter(($)=>$.autoGenerate===!0).filter(($)=>!Q.attachmentType||$.attachmentType===Q.attachmentType),B={checked:w.length,enqueued:0,skipped:0};for(let $ of w)if(await this.ensureDefinition(A,$))B.enqueued+=1;else B.skipped+=1;return B}async ensureDefinition(A,Q){if(!this.matchesPolicy(A,Q))return!1;if(this.hasTargetField(A,Q.targetEntityField))return!1;if(!this.deps.context.attachments.hasProvider(A.entityType,Q.attachmentType))return!1;let w=this.resolveJobType(Q);if(!w)return!1;let B=this.getPredictedMediaId(A,Q),$=this.getDeduplicationKey(A,Q);return await this.deps.context.jobs.enqueue({type:w,data:{sourceEntityType:A.entityType,sourceEntityId:A.id,attachmentType:Q.attachmentType,imageId:B,dedupKey:$,targetEntityType:A.entityType,targetEntityId:A.id,...this.getTargetImageFieldData(Q.targetEntityField)},options:{source:"content-pipeline",metadata:{operationType:"content_operations"},deduplication:"skip",deduplicationKey:$}}),this.deps.context.logger.debug("Queued publish asset generation",{entityType:A.entityType,entityId:A.id,attachmentType:Q.attachmentType,jobType:w}),!0}matchesPolicy(A,Q){let{requiredWhen:w}=Q;if(!w)return!0;if(w.status&&A.metadata.status!==w.status)return!1;if(w.visibility&&A.visibility!==w.visibility)return!1;return!0}hasTargetField(A,Q){if(!Q)return!1;if(typeof Q==="string")return Ms0(A.metadata[Q]);if(Q.location==="metadata")return Ms0(A.metadata[Q.field]);let{frontmatter:w}=j6(A.content);return Ms0(w[Q.field])}resolveJobType(A){if(A.jobType)return A.jobType;if(A.mediaEntityType==="image")return"image:image-render-source";return}getPredictedMediaId(A,Q){let w=Q.attachmentType==="og-image"?"og":Q.attachmentType;return Z1(`${w}-${A.entityType}-${A.id}`)}getDeduplicationKey(A,Q){return`publish-asset:${Q.attachmentType}:${A.entityType}:${A.id}`}getTargetImageFieldData(A){let Q=typeof A==="string"?A:A?.field;if(Q==="coverImageId"||Q==="ogImageId")return{targetImageField:Q};return{}}}function Ms0(A){return typeof A==="string"?A.length>0:A!==void 0}wA();N0();var TDw=Z.object({id:Z.string().min(1)});async function MA2(A,Q){let{bodyContent:w,coverImageId:B,documents:$,sourceEntityType:f,sourceEntityId:Y}=SDw(Q.content),X=B?await cDw(A,B):void 0,W;if($&&$.length>0){let K=await lDw(A,$);if(K.length>0)W=K}W??=await uDw(A,f,Y);let H={bodyContent:w};if(X)H.imageData=X;if(W&&W.length>0)H.documentData=W;return H}function SDw(A){try{let Q=o2(A,Z.record(Z.string(),Z.unknown())),w=Q.metadata.coverImageId,B=typeof w==="string"?w:void 0,$=mDw(Q.metadata.documents),f=PA2(Q.metadata.sourceEntityType),Y=PA2(Q.metadata.sourceEntityId);return{bodyContent:Q.content,...B&&{coverImageId:B},...$.length>0&&{documents:$},...f&&{sourceEntityType:f},...Y&&{sourceEntityId:Y}}}catch{return{bodyContent:A}}}function mDw(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let w=TDw.safeParse(Q);return w.success?[w.data]:[]})}function PA2(A){return typeof A==="string"&&A.length>0?A:void 0}async function uDw(A,Q,w){if(!Q||!w)return;let B=await A.attachments.resolve({sourceEntityType:Q,sourceEntityId:w,attachmentType:"carousel"});return B?[B]:void 0}async function cDw(A,Q){let w=await A.entityService.getEntity({entityType:"image",id:Q});if(!w?.content)return;let B=OA2(w.content);if(!B?.mimeType.startsWith("image/"))return;return{data:B.data,mimeType:B.mimeType}}async function lDw(A,Q){return(await Promise.all(Q.map((B)=>pDw(A,B)))).filter((B)=>B!==void 0)}async function pDw(A,Q){let w=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!w?.content)return;let B=OA2(w.content);if(B?.mimeType!=="application/pdf")return;return{type:"document",data:B.data,mimeType:"application/pdf",filename:iDw(w,Q.id)}}function OA2(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function iDw(A,Q){let w=A.metadata.filename;return typeof w==="string"&&w.length>0?w:`${Q}.pdf`}S9();var dDw=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function Os0(A,Q,w,B={}){let $=B.publishTimestampField??"publishedAt",f=Q.metadata[$],Y=B.publishedAt??(typeof f==="string"?f:void 0)??new Date().toISOString(),X={...Q.metadata,status:"published",[$]:Y,platformId:w.id,...nDw(w.id,B.publishResultIdField)},W={...Q,content:xA2(Q.content,Y,w.id,B.publishResultIdField,$),metadata:X};return await A.entityService.updateEntity({entity:W}),W}function xA2(A,Q,w,B,$="publishedAt"){if(!dDw.test(A))return A;let f=D4(D4(A,"status","published"),$,Q);if(!w||!B)return f;return D4(f,B,w)}function nDw(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class Jy{deps;constructor(A){this.deps=A}async resolveCandidate(A){let{entityType:Q,id:w,slug:B}=A;if(!w&&!B)return{error:"Either 'id' or 'slug' must be provided"};let $=await this.findPublishableEntity(Q,w,B);if(!$)return{error:`Entity not found: ${Q}:${w??B}`};if($.visibility!=="public")return{error:`Cannot publish ${Q}:${$.id} to a public provider because visibility is ${$.visibility}`};if($.metadata.status==="published")return{error:"Entity is already published"};if(!this.deps.providerRegistry.has(Q))return{error:`No publish provider registered for ${Q}. Check that the required credentials are configured.`};return{entity:$}}async publish(A){let Q=await this.resolveCandidate(A);if("error"in Q)return Q;let{entity:w}=Q,{entityType:B}=A,$=this.deps.providerRegistry.get(B),{bodyContent:f,imageData:Y,documentData:X}=await MA2(this.deps.context,w),W=await $.publish(f,w.metadata,Y,X),H=this.deps.providerRegistry.getPublishResultIdField(B),K=this.deps.providerRegistry.getPublishTimestampField(B),U=await Os0(this.deps.context,w,W,{...H?{publishResultIdField:H}:{},...K?{publishTimestampField:K}:{}});return await this.runPublishAssetPreflight(U),{entity:U,result:W}}async runPublishAssetPreflight(A){if(!this.deps.publishAssetPreflight)return;try{await this.deps.publishAssetPreflight.ensureForEntity(A)}catch(Q){this.deps.context.logger.warn("Publish asset preflight failed",{entityType:A.entityType,entityId:A.id,error:Q instanceof Error?Q.message:String(Q)})}}async findPublishableEntity(A,Q,w){if(Q)return this.deps.context.entityService.getEntity({entityType:A,id:Q});if(!w)return null;return(await this.deps.context.entityService.listEntities({entityType:A,options:{filter:{metadata:{slug:w}},limit:1}}))[0]??null}}wA();N0();var xs0=Z.object({action:Z.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:Z.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:Z.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:Z.number().optional().describe("New position for reorder action (1-based)")}),Rs0=Z.object({position:Z.number(),entityType:Z.string(),entityId:Z.string(),queuedAt:Z.string()}),rDw=Z.object({success:Z.literal(!0),message:Z.string().optional(),data:Z.object({queue:Z.array(Rs0).optional(),entityType:Z.string().optional(),entityId:Z.string().optional(),position:Z.number().optional()}).optional()}),oDw=Z.object({success:Z.literal(!1),error:Z.string(),code:Z.string().optional()}),vs0=Z.union([rDw,oDw]);function wX0(A,Q,w){return{...P6(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",xs0,async($,f)=>{let{action:Y,entityType:X,entityId:W,position:H}=$;switch(Y){case"list":return sDw(w,X);case"add":return aDw(A,w,X,W,f);case"remove":return tDw(A,w,X,W,f);case"reorder":return eDw(A,w,X,W,H,f);default:return{success:!1,error:`Unknown action: ${Y}`}}},{sideEffects:"writes"}),outputSchema:vs0}}async function sDw(A,Q){let w=[];if(Q)w=await A.list(Q);else{let $=A.getRegisteredTypes();for(let f of $){let Y=await A.list(f);w.push(...Y)}w.sort((f,Y)=>new Date(f.queuedAt).getTime()-new Date(Y.queuedAt).getTime())}if(w.length===0)return{success:!0,data:{queue:[]},message:"No items in queue"};return{success:!0,data:{queue:w.map(($,f)=>({position:f+1,entityType:$.entityType,entityId:$.entityId,queuedAt:$.queuedAt}))},message:`${w.length} items in queue`}}async function aDw(A,Q,w,B,$){let f=hs0("add",w,B);if(!f.success)return f.error;A.permissions.assertEntityActionAllowed(f.entityType,"publish",$??{});let Y=await Q.add(f.entityType,f.entityId,{...$,authorization:"user"});return{success:!0,data:{entityType:f.entityType,entityId:f.entityId,position:Y.position},message:`Added to queue at position ${Y.position}`}}async function tDw(A,Q,w,B,$){let f=hs0("remove",w,B);if(!f.success)return f.error;return A.permissions.assertEntityActionAllowed(f.entityType,"update",$??{}),await Q.remove(f.entityType,f.entityId),{success:!0,data:{entityType:f.entityType,entityId:f.entityId},message:"Removed from queue"}}async function eDw(A,Q,w,B,$,f){let Y=hs0("reorder",w,B);if(!Y.success)return Y.error;let X=AGw($);if(!X.success)return X.error;return A.permissions.assertEntityActionAllowed(Y.entityType,"update",f??{}),await Q.reorder(Y.entityType,Y.entityId,X.position),{success:!0,data:{entityType:Y.entityType,entityId:Y.entityId,position:X.position},message:`Moved to position ${X.position}`}}function hs0(A,Q,w){if(!Q)return{success:!1,error:{success:!1,error:`entityType is required for ${A} action`}};if(!w)return{success:!1,error:{success:!1,error:`entityId is required for ${A} action`}};return{success:!0,entityType:Q,entityId:w}}function AGw(A){if(A===void 0)return{success:!1,error:{success:!1,error:"position is required for reorder action"}};if(A<1)return{success:!1,error:{success:!1,error:"position must be a positive number"}};return{success:!0,position:A}}N0();import{createHash as QGw}from"crypto";var Cs0=Z.object({entityType:Z.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:Z.string().optional().describe("Entity ID to publish"),slug:Z.string().optional().describe("Entity slug to publish"),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional(),contentHash:Z.string().optional(),expiresAt:Z.string().datetime().optional()}),wGw=Z.object({entityType:Z.string(),id:Z.string().optional(),slug:Z.string().optional(),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional(),contentHash:Z.string().optional(),expiresAt:Z.string().datetime().optional()}),BGw=Z.object({success:Z.literal(!0),message:Z.string().optional(),data:Z.object({entityType:Z.string().optional(),entityId:Z.string().optional(),platformId:Z.string().optional(),url:Z.string().optional()}).optional()}),$Gw=Z.object({success:Z.literal(!1),error:Z.string(),code:Z.string().optional()}),fGw=Z.object({success:Z.literal(!1).optional(),error:Z.string().optional(),needsConfirmation:Z.literal(!0),toolName:Z.string(),summary:Z.string(),preview:Z.string().optional(),args:Z.unknown()}),gs0=Z.union([BGw,$Gw,fGw]),YGw=900000;function BX0(A,Q,w,B){let $=B??new Jy({context:A,providerRegistry:w}),f=`${Q}_publish`;return{name:f,description:"Publish an entity directly to its platform. Call this when the user asks to publish; the tool will request confirmation itself. Works with any registered entity type (social-post, post, deck, etc.). For follow-up requests like 'publish it now', use the entity just read, generated, or updated in the conversation, including a post just changed to draft.",inputSchema:Cs0.shape,outputSchema:gs0,visibility:"anchor",sideEffects:"external",handler:async(Y,X)=>{let W=wGw.safeParse(Y);if(!W.success)return{success:!1,error:`Invalid input: ${W.error.issues.map((I)=>`${I.path.join(".")}: ${I.message}`).join(", ")}`};let H=W.data,{entityType:K,id:U,slug:D}=H;try{A.permissions.assertEntityActionAllowed(K,"publish",X)}catch(I){return{success:!1,error:I instanceof Error?I.message:String(I)}}let q=await $.resolveCandidate({entityType:K,id:U,slug:D});if("error"in q)return{success:!1,error:q.error};let{entity:b}=q;if(H.confirmed){let I=ZGw(f,H,b);if(I!==null)return I;let V;try{V=await $.publish({entityType:K,id:b.id})}catch(k){return{success:!1,error:k instanceof Error?k.message:String(k)}}if("error"in V)return{success:!1,error:V.error};let{entity:L,result:N}=V;return{success:!0,data:{entityType:K,entityId:L.id,platformId:N.id,url:N.url},message:`Published ${K}:${L.id}`}}return XGw(f,H,b)}}}function XGw(A,Q,w){let B=new Date(Date.now()+YGw).toISOString(),$=RA2(A,w,B),f=WGw(w);return{needsConfirmation:!0,toolName:A,summary:`Publish "${f}"?`,preview:`This will publish ${w.entityType}:${w.id} to its registered public publish provider.`,args:{...Q,id:w.id,slug:void 0,confirmed:!0,confirmationToken:$,contentHash:w.contentHash,expiresAt:B}}}function ZGw(A,Q,w){let{confirmationToken:B,contentHash:$,expiresAt:f}=Q;if(!B||!f)return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};let Y=Date.parse(f);if(Number.isNaN(Y))return{success:!1,error:"Invalid publish confirmation expiry. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};if(Y<=Date.now())return{success:!1,error:"Publish confirmation expired. Request confirmation again before publishing.",code:"EXPIRED_CONFIRMATION_TOKEN"};if($&&$!==w.contentHash)return{success:!1,error:`Cannot publish ${w.entityType}:${w.id} because it changed after confirmation. Review it and try again.`};if(B!==RA2(A,w,f))return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};return null}function RA2(A,Q,w){return QGw("sha256").update(A).update("\x00").update(Q.entityType).update("\x00").update(Q.id).update("\x00").update(Q.contentHash).update("\x00").update(w).digest("hex")}function WGw(A){let Q=A.metadata.title;if(typeof Q==="string"&&Q.length>0)return Q;let w=A.metadata.subject;if(typeof w==="string"&&w.length>0)return w;let B=A.metadata.slug;if(typeof B==="string"&&B.length>0)return B;return A.id}wA();N0();var ys0=Z.object({entityType:Z.string().min(1).describe("Entity type to reconcile"),status:Z.string().min(1).optional().describe("Optional metadata status filter, e.g. published"),assetType:Z.string().min(1).optional().describe("Optional attachment type filter, e.g. og-image")}),Es0=Z.object({success:Z.literal(!0),data:Z.object({entityType:Z.string(),assetType:Z.string().optional(),checkedEntities:Z.number(),checkedAssets:Z.number(),enqueued:Z.number(),skipped:Z.number()}),message:Z.string().optional()});function $X0(A,Q,w,B){return{...P6(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",ys0,async(f,Y)=>{if(A.permissions.assertEntityActionAllowed(f.entityType,"publish",Y),w.list(f.entityType).filter((D)=>D.autoGenerate===!0).filter((D)=>!f.assetType||D.attachmentType===f.assetType).length===0)return{success:!0,data:{entityType:f.entityType,...f.assetType&&{assetType:f.assetType},checkedEntities:0,checkedAssets:0,enqueued:0,skipped:0},message:`No publish assets configured for ${f.entityType}`};let W=await A.entityService.listEntities({entityType:f.entityType,options:{...f.status&&{filter:{metadata:{status:f.status}}}}}),H=0,K=0,U=0;for(let D of W){let q=await B.ensureForEntity(D,{...f.assetType&&{attachmentType:f.assetType}});H+=q.checked,K+=q.enqueued,U+=q.skipped}return{success:!0,data:{entityType:f.entityType,...f.assetType&&{assetType:f.assetType},checkedEntities:W.length,checkedAssets:H,enqueued:K,skipped:U},message:`Queued ${K} publish asset job(s)`}},{sideEffects:"writes"}),outputSchema:Es0}}wA();function vA2(A,Q){HGw(A,Q),KGw(A,Q),UGw(A,Q),DGw(A,Q)}function HGw(A,Q){A.messaging.subscribe(of.REGISTER,async(w)=>GGw(Q,w.payload)),A.messaging.subscribe(of.QUEUE,async(w)=>VGw(A,Q,w.payload)),A.messaging.subscribe(of.DIRECT,async(w)=>IGw(A,Q,w.payload)),A.messaging.subscribe(of.REMOVE,async(w)=>JGw(Q,w.payload)),A.messaging.subscribe(of.REORDER,async(w)=>FGw(Q,w.payload)),A.messaging.subscribe(of.LIST,async(w)=>LGw(A,Q,w.payload)),A.messaging.subscribe(of.REPORT_SUCCESS,async(w)=>kGw(Q,w.payload)),A.messaging.subscribe(of.REPORT_FAILURE,async(w)=>_Gw(Q,w.payload)),Q.logger.debug("Subscribed to publish messages")}function KGw(A,Q){A.messaging.subscribe(RF.REPORT_SUCCESS,async(w)=>NGw(Q,w.payload)),A.messaging.subscribe(RF.REPORT_FAILURE,async(w)=>jGw(Q,w.payload)),Q.logger.debug("Subscribed to generation messages")}function UGw(A,Q){A.messaging.subscribe(DA2.REGISTER,async(w)=>zGw(Q,w.payload)),Q.logger.debug("Subscribed to publish asset messages")}function DGw(A,Q){let w=async(B)=>qGw(A,Q,B.payload);A.messaging.subscribe("entity:created",w),A.messaging.subscribe("entity:updated",w),Q.logger.debug("Subscribed to entity change messages for publish assets")}async function GGw(A,Q){let{entityType:w,provider:B,config:$}=Q;try{let f=$?GA2.safeParse($):void 0;if(f&&!f.success)return A.logger.warn("Invalid publish provider config",{entityType:w,error:f.error.message}),{success:!1};if(B)A.providerRegistry.register(w,B,f?.data),A.logger.info(`Registered provider for entity type: ${w}`,{providerName:B.name,executionMode:A.providerRegistry.getExecutionMode(w)});return{success:!0}}catch(f){let Y=mA(f);return A.logger.error(`Failed to register provider: ${Y}`),{success:!1}}}async function zGw(A,Q){let w=AX0.safeParse(Q);if(!w.success)return A.logger.warn("Invalid publish asset registration",{error:w.error.message}),{success:!1};return A.publishAssetRegistry.register(w.data),A.logger.info("Registered publish asset",{entityType:w.data.entityType,attachmentType:w.data.attachmentType,mediaEntityType:w.data.mediaEntityType}),{success:!0}}async function qGw(A,Q,w){try{if(Q.publishAssetRegistry.list(w.entityType).length===0)return{success:!0};let B=w.entity??await A.entityService.getEntity({entityType:w.entityType,id:w.entityId});if(!bGw(B))return{success:!0};return await Q.publishAssetPreflight.ensureForEntity(B),{success:!0}}catch(B){return Q.logger.warn("Failed to run publish asset preflight for entity event",{entityType:w.entityType,entityId:w.entityId,error:mA(B)}),{success:!1}}}function bGw(A){if(!A)return!1;let Q=UA2.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function VGw(A,Q,w){let{entityType:B,entityId:$}=w;try{let f=w.authContext??Jo;A.permissions.assertEntityActionAllowed(B,"publish",f);let Y=await Q.queueManager.add(B,$,f);return await A.messaging.send({type:of.QUEUED,payload:{entityType:B,entityId:$,position:Y.position}}),Q.logger.debug(`Entity queued: ${$}`,{entityType:B,position:Y.position}),{success:!0}}catch(f){let Y=mA(f);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function IGw(A,Q,w){let{entityType:B,entityId:$}=w,f=w.authContext??Jo;try{if(A.permissions.assertEntityActionAllowed(B,"publish",f),!Q.providerRegistry.has(B))return Q.scheduler.failPublish(B,$,`No publish provider registered for ${B}`),{success:!1};let Y=await Q.publishExecutor.publish({entityType:B,id:$});if("error"in Y)return Q.scheduler.failPublish(B,$,Y.error),{success:!1};return Q.scheduler.completePublish(B,$,Y.result),Q.logger.debug(`Direct publish completed: ${$}`,{entityType:B}),{success:!0}}catch(Y){let X=mA(Y);return Q.logger.error(`Failed direct publish request: ${X}`),{success:!1}}}async function JGw(A,Q){let{entityType:w,entityId:B}=Q;try{return await A.queueManager.remove(w,B),A.logger.debug(`Entity removed from queue: ${B}`,{entityType:w}),{success:!0}}catch($){let f=mA($);return A.logger.error(`Failed to remove entity: ${f}`),{success:!1}}}async function FGw(A,Q){let{entityType:w,entityId:B,position:$}=Q;try{return await A.queueManager.reorder(w,B,$),A.logger.debug(`Entity reordered: ${B}`,{entityType:w,newPosition:$}),{success:!0}}catch(f){let Y=mA(f);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function LGw(A,Q,w){let{entityType:B}=w;try{let $=await Q.queueManager.list(B);return await A.messaging.send({type:of.LIST_RESPONSE,payload:{entityType:B,queue:$.map((f)=>({entityId:f.entityId,position:f.position,queuedAt:f.queuedAt}))}}),{success:!0}}catch($){let f=mA($);return Q.logger.error(`Failed to list queue: ${f}`),{success:!1}}}async function kGw(A,Q){let{entityType:w,entityId:B,result:$}=Q;return A.scheduler.completePublish(w,B,$),A.logger.info(`Publish reported success: ${B}`,{entityType:w}),{success:!0}}async function _Gw(A,Q){let{entityType:w,entityId:B,error:$}=Q;A.scheduler.failPublish(w,B,$);let f=A.retryTracker.getRetryInfo(B);return A.logger.info(`Publish reported failure: ${B}`,{entityType:w,error:$,retryCount:f?.retryCount}),{success:!0}}async function NGw(A,Q){let{entityType:w,entityId:B}=Q;return A.scheduler.completeGeneration(w,B),A.logger.info("Generation completed",{entityType:w,entityId:B}),{success:!0}}async function jGw(A,Q){let{entityType:w,error:B}=Q;return A.scheduler.failGeneration(w,B),A.logger.warn("Generation failed",{entityType:w,error:B}),{success:!0}}async function hA2(A,Q,w,B){try{if(B.skipIfDraftExists!==!1){if((await A.listEntities({entityType:w,options:{filter:{metadata:{status:"draft"}},limit:1}})).length>0)return{shouldGenerate:!1,reason:"Draft already exists"}}if(B.maxUnpublishedDrafts!==void 0){let $=await A.listEntities({entityType:w,options:{filter:{metadata:{status:"draft"}},limit:B.maxUnpublishedDrafts+1}});if($.length>=B.maxUnpublishedDrafts)return{shouldGenerate:!1,reason:`Max unpublished drafts reached (${$.length}/${B.maxUnpublishedDrafts})`}}if(B.minSourceEntities!==void 0&&B.sourceEntityType){let $=await A.listEntities({entityType:B.sourceEntityType,options:{publishedOnly:!0,limit:B.minSourceEntities}});if($.length<B.minSourceEntities)return{shouldGenerate:!1,reason:`Not enough source entities (${$.length}/${B.minSourceEntities} ${B.sourceEntityType})`}}return{shouldGenerate:!0}}catch($){return Q.error("Failed to check generation conditions",{entityType:w,error:mA($)}),{shouldGenerate:!1,reason:`Condition check failed: ${mA($)}`}}}function CA2(A){let{context:Q,config:w,queueManager:B,providerRegistry:$,retryTracker:f,publishExecutor:Y,logger:X}=A,W=PGw(Q);return xU.createFresh({queueManager:B,providerRegistry:$,retryTracker:f,logger:X,backend:new eY0,...w.entitySchedules&&{entitySchedules:w.entitySchedules},...w.generationSchedules&&{generationSchedules:w.generationSchedules},...w.generationConditions&&{generationConditions:w.generationConditions},messageBus:W,publishExecutor:Y,onCheckGenerationConditions:(H,K)=>hA2(Q.entityService,X,H,K)})}function PGw(A){return{send:async($)=>{return A.messaging.send({type:$.type,payload:$.payload,...$.target!==void 0?{target:$.target}:{},...$.metadata!==void 0?{metadata:$.metadata}:{},...$.broadcast!==void 0?{broadcast:$.broadcast}:{}})},subscribe:()=>()=>{},unsubscribe:()=>{}}}async function gA2(A,Q,w){let B=A.getEntityTypes();for(let f of B){let Y=await A.listEntities({entityType:f,options:{filter:{metadata:{status:"queued"}}}});for(let X of Y)await Q.add(X.entityType,X.id)}let $=0;for(let f of B){let Y=await Q.list(f);$+=Y.length}if($>0)w.info(`Rebuilt queue with ${$} queued entities`)}var MGw=["draft","queued","published","failed"];async function yA2(A,Q){await A.messaging.send({type:"dashboard:register-widget",payload:{id:"publication-pipeline",pluginId:Q,title:"Publication Pipeline",section:"secondary",priority:100,rendererName:"PipelineWidget",visibility:"anchor",dataProvider:()=>OGw(A)}})}async function OGw(A){let Q=A.entityService.getEntityTypes(),w=[],B={draft:0,queued:0,published:0,failed:0};for(let $ of Q){let f=await A.entityService.listEntities({entityType:$});for(let Y of f){let X=xGw(Y.metadata.status);if(!X)continue;B[X]++,w.push({id:Y.id,title:RGw(Y.id,Y.metadata.title),type:$,status:X})}}return{summary:B,items:w}}function xGw(A){return MGw.find((Q)=>Q===A)}function RGw(A,Q){return typeof Q==="string"?Q:A}var EA2={name:"@brains/content-pipeline",version:"0.2.0-alpha.142",description:"Content pipeline plugin for managing entity publishing queues, scheduling, and generation",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",croner:"^10.0.1"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^6.0.3"},exports:{".":{types:"./src/index.ts",default:"./src/index.ts"}},files:["src"],main:"src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"src/index.ts"};class Ts0 extends aQ{pluginContext;queueManager;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A={}){super("content-pipeline",EA2,A,zA2)}async onRegister(A){this.pluginContext=A,this.queueManager=Q3.createFresh(),this.providerRegistry=w3.createFresh(),this.retryTracker=B3.createFresh(),this.publishAssetRegistry=$3.createFresh(),this.publishAssetPreflight=new QX0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new Jy({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=CA2({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),vA2(A,{queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,publishAssetRegistry:this.publishAssetRegistry,publishAssetPreflight:this.publishAssetPreflight,scheduler:this.scheduler,logger:this.logger})}async onReady(A){await gA2(A.entityService,this.queueManager,this.logger),await yA2(A,this.id),await this.scheduler.start(),this.logger.info("Content pipeline plugin started")}async getTools(){if(!this.pluginContext)throw Error("Plugin context not initialized");return[wX0(this.pluginContext,this.id,this.queueManager),BX0(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),$X0(this.pluginContext,this.id,this.publishAssetRegistry,this.publishAssetPreflight)]}async getInstructions(){return'## Publishing\n- Use `content-pipeline_queue` to manage the publish queue \u2014 list queued items, add entities to the queue, remove them, or reorder.\n- Use `content-pipeline_publish` to publish an entity directly to its platform (e.g. LinkedIn, Buttondown). This tool has its own confirmation flow; call it without `confirmed` when the user asks to publish instead of asking for plain-text confirmation. Follow-up requests like "publish it now" should target the entity just read, generated, or updated in the conversation, including a post just changed to draft.\n- Use `content-pipeline_ensure-assets` to reconcile missing publish assets such as generated OG images for already-published content.\n- When users ask about their "publish queue", "publishing queue", or "what\'s queued", use `content-pipeline_queue`.'}getQueueManager(){return this.queueManager}getProviderRegistry(){return this.providerRegistry}getRetryTracker(){return this.retryTracker}getPublishAssetRegistry(){return this.publishAssetRegistry}getScheduler(){return this.scheduler}async onShutdown(){await this.scheduler.stop(),Q3.resetInstance(),w3.resetInstance(),B3.resetInstance(),$3.resetInstance()}}function Ss0(A={}){return new Ts0(A)}wA();N0();var TA2=Z.object({accountId:Z.string().describe("Cloudflare account ID"),apiToken:Z.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:Z.string().describe("Cloudflare Web Analytics site tag")}),ms0=Z.object({cloudflare:TA2.optional()});wA();N0();var hGw=Z.object({date:Z.string().describe("Single date in YYYY-MM-DD format").optional(),days:Z.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:Z.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:Z.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:Z.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function CGw(A){if(A.date&&(A.days||A.startDate||A.endDate))return"Cannot combine 'date' with 'days' or 'startDate'/'endDate'";if(A.days&&(A.startDate||A.endDate))return"Cannot combine 'days' with 'startDate'/'endDate'";if(A.startDate&&!A.endDate||!A.startDate&&A.endDate)return"Both 'startDate' and 'endDate' must be provided for custom range";return null}function SA2(A,Q,w){let B=[];if(!w)return B;return B.push(P6(A,"query",`Query website analytics from Cloudflare.
6794
+ ${w.content}`:w.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:B,templateName:`social-media:${w.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let w=NDw.parse(Q),B=[],$=Xf.from(async(H)=>{let K={progress:H.progress};if(H.message!==void 0)K.message=H.message;B.push(K)});if(!$)throw Error("Failed to create progress reporter");let Y=await new ZP(A.logger,A).process(w,`eval-${Date.now()}`,$),X=!1,W;if(Y.success&&Y.entityId){let H=await A.entityService.getEntity({entityType:"social-post",id:Y.entityId});X=!!H,W=H?.content.slice(0,300)}return{...Y,entityExists:X,entityPreview:W,progressSteps:B}})}wA();class Vo{sendMessage;logger;entityService;providers;permissions;resolveAttachment;constructor(A){this.sendMessage=A.sendMessage,this.logger=A.logger,this.entityService=A.entityService,this.providers=A.providers,this.permissions=A.permissions,this.resolveAttachment=A.resolveAttachment}async handle(A){let{entityType:Q,entityId:w}=A;if(Q!=="social-post")return;this.permissions.assertEntityActionAllowed(Q,"publish",A.authContext??{userPermissionLevel:"anchor"}),this.logger.debug("Handling publish:execute",{entityId:w});try{let B=await this.entityService.getEntity({entityType:"social-post",id:w});if(!B){await this.reportFailure(Q,w,`Post not found: ${w}`);return}let $=B;if($.metadata.status==="published"){this.logger.debug("Post already published, skipping",{entityId:w});return}let f=$.metadata.platform,Y=this.providers.get(f);if(!Y){await this.reportFailure(Q,w,`No provider configured for platform: ${f}`);return}let X=o2($.content,OU),W;if(X.metadata.coverImageId)W=await this.fetchImageData(X.metadata.coverImageId);let H=X.metadata.documents??[],K=await this.fetchDocumentData(H);try{if(H.length>0&&K.length===0)throw Error(`Refusing to publish: ${H.length} document(s) referenced but none could be fetched`);let U=H.length===0?await this.resolveSourceAttachment(X.metadata):[],D=K.length>0?K:U,q=D.length?await Y.publish(X.content,$.metadata,W,D):await Y.publish(X.content,$.metadata,W),b=new Date().toISOString(),I=q.id||void 0,V={...X.metadata,status:"published",publishedAt:b,...I&&{platformPostId:I}},L=p7.createPostContent(V,X.content);await this.entityService.updateEntity({entity:{...$,content:L,metadata:{...$.metadata,status:"published",publishedAt:b,platformPostId:I}}}),await this.reportSuccess(Q,w,q.id),this.logger.info(`Post published successfully: ${w}`,{platform:f,platformPostId:I})}catch(U){let D=U instanceof Error?U.message:String(U),q={...X.metadata,status:"failed"},b=p7.createPostContent(q,X.content);await this.entityService.updateEntity({entity:{...$,content:b,metadata:{...$.metadata,status:"failed"}}}),await this.reportFailure(Q,w,D),this.logger.error(`Post publish failed: ${w}`,{platform:f,error:D})}}catch(B){let $=mA(B);this.logger.error("Unexpected error in publish handler",{entityId:w,error:$}),await this.reportFailure(Q,w,$)}}async reportSuccess(A,Q,w){await this.sendMessage({type:"publish:report:success",payload:{entityType:A,entityId:Q,result:{id:w}}})}async reportFailure(A,Q,w){await this.sendMessage({type:"publish:report:failure",payload:{entityType:A,entityId:Q,error:w}})}async resolveSourceAttachment(A){if(!this.resolveAttachment||!A.sourceEntityType||!A.sourceEntityId)return[];let Q=await this.resolveAttachment({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:"carousel"});return Q?[Q]:[]}async fetchDocumentData(A){if(!A?.length)return[];let Q=[];for(let w of A){let B=await this.fetchSingleDocumentData(w.id);if(B)Q.push(B)}return Q}async fetchSingleDocumentData(A){try{let Q=await this.entityService.getEntity({entityType:"document",id:A});if(!Q){this.logger.warn("Document not found",{documentId:A});return}let w=Q.content.match(/^data:application\/pdf;base64,(.+)$/);if(!w?.[1]){this.logger.warn("Invalid document data URL format",{documentId:A});return}let B=typeof Q.metadata.filename==="string"?Q.metadata.filename:`${A}.pdf`;return{type:"document",data:Buffer.from(w[1],"base64"),mimeType:"application/pdf",filename:B}}catch(Q){this.logger.warn("Failed to fetch document",{documentId:A,error:Q});return}}async fetchImageData(A){try{let Q=await this.entityService.getEntity({entityType:"image",id:A});if(!Q){this.logger.warn("Cover image not found",{imageId:A});return}let B=Q.content.match(/^data:([^;]+);base64,(.+)$/);if(!B?.[1]||!B[2]){this.logger.warn("Invalid image data URL format",{imageId:A});return}let $=B[1],f=B[2];return{data:Buffer.from(f,"base64"),mimeType:$}}catch(Q){this.logger.warn("Failed to fetch cover image",{imageId:A,error:Q});return}}}function fA2(A,Q,w){if(Q.size===0){w.debug("No providers configured, skipping publish-pipeline registration");return}A.messaging.subscribe("system:plugins:ready",async()=>{let B=Q.values().next().value;return await A.messaging.send({type:"publish:register",payload:{entityType:"social-post",provider:B,config:{publishResultIdField:"platformPostId"}}}),w.info("Registered social-post with publish-pipeline"),{success:!0}})}function YA2(A,Q,w){let B=new Vo({sendMessage:A.messaging.send,logger:w.child("PublishExecuteHandler"),entityService:A.entityService,providers:Q,permissions:A.permissions,resolveAttachment:A.attachments.resolve});A.messaging.subscribe("publish:execute",async($)=>{return await B.handle($.payload),{success:!0}}),w.debug("Subscribed to publish:execute messages")}function XA2(A,Q){A.messaging.subscribe("entity:updated",async(w)=>{let{entityType:B,entityId:$,entity:f}=w.payload;if(B!=="post")return{success:!0};if(f.metadata?.status!=="queued")return{success:!0};try{if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:$}},limit:1}})).length>0)return Q.debug(`Social post already exists for ${$}, skipping auto-generate`),{success:!0};return await A.messaging.send({type:"social:auto-generate",payload:{sourceEntityType:B,sourceEntityId:$,platform:"linkedin"}}),Q.info(`Auto-generate social post triggered for queued post ${$}`),{success:!0}}catch(X){let W=mA(X);return Q.error(`Failed to trigger auto-generate for ${$}:`,{error:W}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function ZA2(A,Q){A.messaging.subscribe("social:auto-generate",async(w)=>{let{sourceEntityType:B,sourceEntityId:$,platform:f}=w.payload;try{let Y=await A.jobs.enqueue({type:`${p7.entityType}:generation`,data:{sourceEntityType:B,sourceEntityId:$,platform:f,addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info(`Social post generation job enqueued for ${B}/${$}`,{jobId:Y}),{success:!0,jobId:Y}}catch(Y){let X=mA(Y);return Q.error(`Failed to enqueue social post generation for ${$}:`,{error:X}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function WA2(A,Q){A.messaging.subscribe("generate:execute",async(w)=>{let{entityType:B}=w.payload;if(B!=="social-post")return{success:!0};Q.info("Received generate:execute for social-post");try{let $=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:5}});if($.length===0)return Q.info("No published posts found for social post generation"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"No published posts available for social post generation"}}),{success:!0};let f=null;for(let X of $)if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:X.id}},limit:1}})).length===0){f=X;break}if(!f)return Q.info("All recent posts already have social posts"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"All recent posts already have social posts generated"}}),{success:!0};let Y=await A.jobs.enqueue({type:`${p7.entityType}:generation`,data:{sourceEntityType:"post",sourceEntityId:f.id,platform:"linkedin",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info("Social post generation job queued",{jobId:Y,sourcePostId:f.id}),{success:!0}}catch($){let f=mA($);return Q.error("Failed to handle generate:execute:",{error:f}),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:f}}),{success:!0}}}),Q.debug("Subscribed to generate:execute messages")}async function HA2({entity:A,config:Q}){let w=xF.parse(A),B=p7.parsePostFrontmatter(w),$=p7.getPostContent(w);return{$type:"ai.rizom.brain.socialPost",title:B.title,platform:B.platform,body:$,format:"text/markdown",status:B.status,...B.publishedAt&&{publishedAt:B.publishedAt},...B.platformPostId&&{platformPostId:B.platformPostId},...B.sourceEntityType&&{sourceLocalEntityType:B.sourceEntityType},...B.sourceEntityId&&{sourceLocalEntityId:B.sourceEntityId},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"social-post",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function bs0(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:L6["ai.rizom.brain.socialPost"],validate:!1,buildRecord:HA2}}var KA2={name:"@brains/social-media",version:"0.2.0-alpha.143",description:"Multi-provider social media posting with queue-based publishing",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class Vs0 extends nQ{entityType=p7.entityType;schema=xF;adapter=p7;providers=new Map;unregisterAtprotoProjection;constructor(A={}){super("social-media",KA2,A,Ks0)}createGenerationHandler(A){return new ZP(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return BA2()}getDataSources(){return[new rY0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),fA2(A,this.providers,this.logger),YA2(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)XA2(A,this.logger),ZA2(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");WA2(A,this.logger),$A2(A),this.unregisterAtprotoProjection=A8.getInstance().register(bs0()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=qs0(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function Io(A={}){return new Vs0(A)}N0();var PDw=Z.enum(["draft","queued","published","failed"]),UA2=Z.object({status:PDw.default("draft"),queueOrder:Z.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:Z.string().datetime().optional()});class Is0{name="internal";async publish(A,Q){return{id:"internal"}}}var Jo={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},of={REGISTER:"publish:register",QUEUE:"publish:queue",DIRECT:"publish:direct",REMOVE:"publish:remove",REORDER:"publish:reorder",LIST:"publish:list",REPORT_SUCCESS:"publish:report:success",REPORT_FAILURE:"publish:report:failure",QUEUED:"publish:queued",COMPLETED:"publish:completed",FAILED:"publish:failed",LIST_RESPONSE:"publish:list:response"},RF={REGISTER:"generate:register",REPORT_SUCCESS:"generate:report:success",REPORT_FAILURE:"generate:report:failure",EXECUTE:"generate:execute",COMPLETED:"generate:completed",FAILED:"generate:failed",SKIPPED:"generate:skipped"},DA2={REGISTER:"publish-assets:register"};N0();var MDw=Z.enum(["provider"]),GA2=Z.object({executionMode:MDw.optional(),publishResultIdField:Z.string().min(1).optional(),publishTimestampField:Z.string().min(1).optional(),enabled:Z.boolean().optional()}).strict();var ODw=Z.object({skipIfDraftExists:Z.boolean().optional(),minSourceEntities:Z.number().optional(),maxUnpublishedDrafts:Z.number().optional(),sourceEntityType:Z.string().optional()}),zA2=Z.object({entitySchedules:Z.record(Z.string(),Z.string()).optional(),generationSchedules:Z.record(Z.string(),Z.string()).optional(),generationConditions:Z.record(Z.string(),ODw).optional()});class Q3{static instance=null;queues=new Map;static getInstance(){return Q3.instance??=new Q3,Q3.instance}static resetInstance(){Q3.instance=null}static createFresh(){return new Q3}constructor(){}async add(A,Q,w=Jo){let B=this.getOrCreateQueue(A),$=B.find((X)=>X.entityId===Q);if($)return{position:$.position};let f=B.length+1,Y={entityId:Q,entityType:A,position:f,queuedAt:new Date().toISOString(),authContext:{...w}};return B.push(Y),{position:f}}async remove(A,Q){let w=this.queues.get(A);if(!w)return;let B=w.findIndex(($)=>$.entityId===Q);if(B===-1)return;w.splice(B,1),this.recalculatePositions(w)}async reorder(A,Q,w){let B=this.queues.get(A);if(!B)return;let $=B.findIndex((X)=>X.entityId===Q);if($===-1)return;let[f]=B.splice($,1);if(!f)return;let Y=Math.max(0,Math.min(w-1,B.length));B.splice(Y,0,f),this.recalculatePositions(B)}async list(A){let Q=this.queues.get(A);if(!Q)return[];return[...Q]}async getNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;return Q[0]??null}async getNextAcrossTypes(){let A=null;for(let Q of this.queues.values()){let w=Q[0];if(!w)continue;if(!A||w.queuedAt<A.queuedAt)A=w}return A}async popNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let w=Q.shift()??null;if(w)this.recalculatePositions(Q);return w}getRegisteredTypes(){return Array.from(this.queues.keys())}async getQueuedEntityTypes(){let A=[];for(let[Q,w]of this.queues.entries())if(w.length>0)A.push(Q);return A}getOrCreateQueue(A){let Q=this.queues.get(A);if(!Q)Q=[],this.queues.set(A,Q);return Q}recalculatePositions(A){A.forEach((Q,w)=>{Q.position=w+1})}}class w3{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new Is0;static getInstance(){return w3.instance??=new w3,w3.instance}static resetInstance(){w3.instance=null}static createFresh(){return new w3}constructor(){}register(A,Q,w){let B=this.providers.get(A);if(B&&B.name!=="internal"&&Q.name==="internal")return;if(this.providers.set(A,Q),this.executionModes.set(A,w?.executionMode??"provider"),w?.publishResultIdField)this.publishResultIdFields.set(A,w.publishResultIdField);else this.publishResultIdFields.delete(A);if(w?.publishTimestampField)this.publishTimestampFields.set(A,w.publishTimestampField);else this.publishTimestampFields.delete(A)}get(A){return this.providers.get(A)??this.defaultProvider}getExecutionMode(A){return this.executionModes.get(A)??"provider"}getPublishResultIdField(A){return this.publishResultIdFields.get(A)}getPublishTimestampField(A){return this.publishTimestampFields.get(A)}has(A){return this.providers.has(A)}unregister(A){this.providers.delete(A),this.executionModes.delete(A),this.publishResultIdFields.delete(A),this.publishTimestampFields.delete(A)}getRegisteredTypes(){return Array.from(this.providers.keys())}}async function qA2(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await xDw(A,Q)}async function xDw(A,Q){if(!Q.publishExecutor)return;try{let w=await Q.publishExecutor.publish({entityType:A.entityType,id:A.entityId});if("error"in w){let B={entityType:A.entityType,entityId:A.entityId,error:w.error,retryCount:0,willRetry:!1};if(Q.messageBus)await Q.messageBus.send({type:of.FAILED,payload:B,sender:"publish-service",broadcast:!0});Q.onFailed?.(B);return}Js0(A.entityType,A.entityId,w.result,Q)}catch(w){let B=mA(w);Q.retryTracker.recordFailure(A.entityId,B);let $=Q.retryTracker.getRetryInfo(A.entityId);Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:B,retryCount:$?.retryCount??1,willRetry:!1})}}function Js0(A,Q,w,B){if(B.retryTracker.clearRetries(Q),B.messageBus)B.messageBus.send({type:of.COMPLETED,payload:{entityType:A,entityId:Q,result:w},sender:"publish-service",broadcast:!0});B.onPublish?.({entityType:A,entityId:Q,result:w})}function bA2(A,Q,w,B){B.retryTracker.recordFailure(Q,w);let $=B.retryTracker.getRetryInfo(Q),f={entityType:A,entityId:Q,error:w,retryCount:$?.retryCount??1,willRetry:!1};if(B.messageBus)B.messageBus.send({type:of.FAILED,payload:f,sender:"publish-service",broadcast:!0});B.onFailed?.(f)}async function VA2(A,Q){let w=Q.generationConditions[A];if(w&&Q.onCheckGenerationConditions){let $=await Q.onCheckGenerationConditions(A,w);if(!$.shouldGenerate){if(Q.messageBus)Q.messageBus.send({type:RF.SKIPPED,payload:{entityType:A,reason:$.reason??"Conditions not met"},sender:"content-pipeline"});return}}let B={entityType:A};if(Q.messageBus)await Q.messageBus.send({type:RF.EXECUTE,payload:B,sender:"content-pipeline"});Q.onGenerate?.(B)}function IA2(A,Q,w){if(w)w.send({type:RF.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function JA2(A,Q,w){if(w)w.send({type:RF.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var RDw=1000;class Fs0{deps;publishJobs=new Map;immediateIntervalJob=null;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.entitySchedules)){let w=this.deps.config.backend.scheduleCron(Q,()=>this.processEntityType(A));this.publishJobs.set(A,w)}this.immediateIntervalJob=this.deps.config.backend.scheduleInterval(RDw,()=>this.processUnscheduledTypes())}stop(){if(vDw(this.publishJobs),this.immediateIntervalJob)this.immediateIntervalJob.stop(),this.immediateIntervalJob=null}async processEntityType(A){if(!this.deps.isRunning())return;try{let Q=await this.deps.config.queueManager.getNext(A);if(Q)await this.processEntry(Q)}catch(Q){this.deps.config.logger.error(`Scheduler error for ${A}:`,Q)}}async processUnscheduledTypes(){if(!this.deps.isRunning())return;try{let A=await this.deps.config.queueManager.getQueuedEntityTypes();for(let Q of A)if(!this.entitySchedules[Q]){let w=await this.deps.config.queueManager.getNext(Q);if(w){await this.processEntry(w);break}}}catch(A){this.deps.config.logger.error("Scheduler error for unscheduled types:",A)}}async processEntry(A){await this.deps.config.queueManager.remove(A.entityType,A.entityId);let Q=this.deps.getPublishDeps();await qA2(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}function vDw(A){for(let Q of A.values())Q.stop();A.clear()}class Ls0{deps;generationJobs=new Map;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.generationSchedules)){let w=this.deps.config.backend.scheduleCron(Q,()=>this.handleTriggerGeneration(A));this.generationJobs.set(A,w)}}stop(){hDw(this.generationJobs)}async handleTriggerGeneration(A){if(!this.deps.isRunning())return;try{await VA2(A,this.deps.getGenerationDeps())}catch(Q){this.deps.config.logger.error(`Generation trigger error for ${A}:`,Q)}}get generationSchedules(){return this.deps.config.generationSchedules}}function hDw(A){for(let Q of A.values())Q.stop();A.clear()}class xU{static instance=null;config;publishRunner;generationRunner;running=!1;static getInstance(A){return xU.instance??=new xU(A),xU.instance}static resetInstance(){if(xU.instance)xU.instance.stop();xU.instance=null}static createFresh(A){return new xU(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new Fs0({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new Ls0({config:this.config,getGenerationDeps:()=>this.generationDeps,isRunning:()=>this.running})}async start(){if(this.running)return;this.running=!0,this.publishRunner.start(),this.generationRunner.start()}async stop(){this.running=!1,this.publishRunner.stop(),this.generationRunner.stop()}isRunning(){return this.running}completePublish(A,Q,w){Js0(A,Q,w,this.publishDeps)}failPublish(A,Q,w){bA2(A,Q,w,this.publishDeps)}completeGeneration(A,Q){IA2(A,Q,this.config.messageBus)}failGeneration(A,Q){JA2(A,Q,this.config.messageBus)}get entitySchedules(){return this.config.entitySchedules}get generationSchedules(){return this.config.generationSchedules}get publishDeps(){return{retryTracker:this.config.retryTracker,messageBus:this.config.messageBus,publishExecutor:this.config.publishExecutor,onPublish:this.config.onPublish,onFailed:this.config.onFailed}}get generationDeps(){return{logger:this.config.logger,messageBus:this.config.messageBus,generationConditions:this.config.generationConditions,onCheckGenerationConditions:this.config.onCheckGenerationConditions,onGenerate:this.config.onGenerate}}validateCronExpressions(){for(let[A,Q]of Object.entries(this.entitySchedules))this.validateCronExpression(A,Q,"publish");for(let[A,Q]of Object.entries(this.generationSchedules))this.validateCronExpression(A,Q,"generation")}validateCronExpression(A,Q,w){try{this.config.backend.validateCron(Q)}catch(B){throw Error(`Invalid ${w} cron expression for ${A}: "${Q}" - ${mA(B)}`,{cause:B})}}}class B3{static instance=null;retries=new Map;static getInstance(){return B3.instance??=new B3,B3.instance}static resetInstance(){B3.instance=null}static createFresh(){return new B3}constructor(){}recordFailure(A,Q){let B=(this.retries.get(A)?.retryCount??0)+1;this.retries.set(A,{entityId:A,retryCount:B,lastError:Q})}clearRetries(A){this.retries.delete(A)}getRetryInfo(A){let Q=this.retries.get(A);if(!Q)return null;return{entityId:Q.entityId,retryCount:Q.retryCount,lastError:Q.lastError}}}function Fo(A){return Date.UTC(A.y,A.m-1,A.d,A.h,A.i,A.s)}function ks0(A,Q){return A.y===Q.y&&A.m===Q.m&&A.d===Q.d&&A.h===Q.h&&A.i===Q.i&&A.s===Q.s}function CDw(A,Q){let w=new Date(Date.parse(A));if(isNaN(w))throw Error("Invalid ISO8601 passed to timezone parser.");let B=A.substring(9);return B.includes("Z")||B.includes("+")||B.includes("-")?Ns0(w.getUTCFullYear(),w.getUTCMonth()+1,w.getUTCDate(),w.getUTCHours(),w.getUTCMinutes(),w.getUTCSeconds(),"Etc/UTC"):Ns0(w.getFullYear(),w.getMonth()+1,w.getDate(),w.getHours(),w.getMinutes(),w.getSeconds(),Q)}function FA2(A,Q,w){return _A2(CDw(A,Q),w)}function _A2(A,Q){let w=new Date(Fo(A)),B=Lo(w,A.tz),$=Fo(A),f=Fo(B),Y=$-f,X=new Date(w.getTime()+Y),W=Lo(X,A.tz);if(ks0(W,A)){let U=new Date(X.getTime()-3600000),D=Lo(U,A.tz);return ks0(D,A)?U:X}let H=new Date(X.getTime()+Fo(A)-Fo(W)),K=Lo(H,A.tz);if(ks0(K,A))return H;if(Q)throw Error("Invalid date passed to fromTZ()");return X.getTime()>H.getTime()?X:H}function Lo(A,Q){let w,B;try{w=new Intl.DateTimeFormat("en-US",{timeZone:Q,year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric",hour12:!1}),B=w.formatToParts(A)}catch(f){let Y=f instanceof Error?f.message:String(f);throw RangeError(`toTZ: Invalid timezone '${Q}' or date. Please provide a valid IANA timezone (e.g., 'America/New_York', 'Europe/Stockholm'). Original error: ${Y}`)}let $={year:0,month:0,day:0,hour:0,minute:0,second:0};for(let f of B)(f.type==="year"||f.type==="month"||f.type==="day"||f.type==="hour"||f.type==="minute"||f.type==="second")&&($[f.type]=parseInt(f.value,10));if(isNaN($.year)||isNaN($.month)||isNaN($.day)||isNaN($.hour)||isNaN($.minute)||isNaN($.second))throw Error(`toTZ: Failed to parse all date components from timezone '${Q}'. This may indicate an invalid date or timezone configuration. Parsed components: ${JSON.stringify($)}`);return $.hour===24&&($.hour=0),{y:$.year,m:$.month,d:$.day,h:$.hour,i:$.minute,s:$.second,tz:Q}}function Ns0(A,Q,w,B,$,f,Y){return{y:A,m:Q,d:w,h:B,i:$,s:f,tz:Y}}var NA2=[1,2,4,8,16],LA2=class{pattern;timezone;mode;alternativeWeekdays;sloppyRanges;second;minute;hour;day;month;dayOfWeek;year;lastDayOfMonth;lastWeekday;nearestWeekdays;starDOM;starDOW;starYear;useAndLogic;constructor(A,Q,w){this.pattern=A,this.timezone=Q,this.mode=w?.mode??"auto",this.alternativeWeekdays=w?.alternativeWeekdays??!1,this.sloppyRanges=w?.sloppyRanges??!1,this.second=Array(60).fill(0),this.minute=Array(60).fill(0),this.hour=Array(24).fill(0),this.day=Array(31).fill(0),this.month=Array(12).fill(0),this.dayOfWeek=Array(7).fill(0),this.year=Array(1e4).fill(0),this.lastDayOfMonth=!1,this.lastWeekday=!1,this.nearestWeekdays=Array(31).fill(0),this.starDOM=!1,this.starDOW=!1,this.starYear=!1,this.useAndLogic=!1,this.parse()}parse(){if(!(typeof this.pattern=="string"||this.pattern instanceof String))throw TypeError("CronPattern: Pattern has to be of type string.");this.pattern.indexOf("@")>=0&&(this.pattern=this.handleNicknames(this.pattern).trim());let A=this.pattern.match(/\S+/g)||[""],Q=A.length;if(A.length<5||A.length>7)throw TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exactly five, six, or seven space separated parts are required.");if(this.mode!=="auto"){let B;switch(this.mode){case"5-part":B=5;break;case"6-part":B=6;break;case"7-part":B=7;break;case"5-or-6-parts":B=[5,6];break;case"6-or-7-parts":B=[6,7];break;default:B=0}if(!(Array.isArray(B)?B.includes(Q):Q===B)){let $=Array.isArray(B)?B.join(" or "):B.toString();throw TypeError(`CronPattern: mode '${this.mode}' requires exactly ${$} parts, but pattern '${this.pattern}' has ${Q} parts.`)}}if(A.length===5&&A.unshift("0"),A.length===6&&A.push("*"),A[3].toUpperCase()==="LW"?(this.lastWeekday=!0,A[3]=""):A[3].toUpperCase().indexOf("L")>=0&&(A[3]=A[3].replace(/L/gi,""),this.lastDayOfMonth=!0),A[3]=="*"&&(this.starDOM=!0),A[6]=="*"&&(this.starYear=!0),A[4].length>=3&&(A[4]=this.replaceAlphaMonths(A[4])),A[5].length>=3&&(A[5]=this.alternativeWeekdays?this.replaceAlphaDaysQuartz(A[5]):this.replaceAlphaDays(A[5])),A[5].startsWith("+")&&(this.useAndLogic=!0,A[5]=A[5].substring(1),A[5]===""))throw TypeError("CronPattern: Day-of-week field cannot be empty after '+' modifier.");switch(A[5]=="*"&&(this.starDOW=!0),this.pattern.indexOf("?")>=0&&(A[0]=A[0].replace(/\?/g,"*"),A[1]=A[1].replace(/\?/g,"*"),A[2]=A[2].replace(/\?/g,"*"),A[3]=A[3].replace(/\?/g,"*"),A[4]=A[4].replace(/\?/g,"*"),A[5]=A[5].replace(/\?/g,"*"),A[6]&&(A[6]=A[6].replace(/\?/g,"*"))),this.mode){case"5-part":A[0]="0",A[6]="*";break;case"6-part":A[6]="*";break;case"5-or-6-parts":A[6]="*";break;case"6-or-7-parts":break;case"7-part":case"auto":break}this.throwAtIllegalCharacters(A),this.partToArray("second",A[0],0,1),this.partToArray("minute",A[1],0,1),this.partToArray("hour",A[2],0,1),this.partToArray("day",A[3],-1,1),this.partToArray("month",A[4],-1,1);let w=this.alternativeWeekdays?-1:0;this.partToArray("dayOfWeek",A[5],w,63),this.partToArray("year",A[6],0,1),!this.alternativeWeekdays&&this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(A,Q,w,B){let $=this[A],f=A==="day"&&this.lastDayOfMonth,Y=A==="day"&&this.lastWeekday;if(Q===""&&!f&&!Y)throw TypeError("CronPattern: configuration entry "+A+" ("+Q+") is empty, check for trailing spaces.");if(Q==="*")return $.fill(B);let X=Q.split(",");if(X.length>1)for(let W=0;W<X.length;W++)this.partToArray(A,X[W],w,B);else Q.indexOf("-")!==-1&&Q.indexOf("/")!==-1?this.handleRangeWithStepping(Q,A,w,B):Q.indexOf("-")!==-1?this.handleRange(Q,A,w,B):Q.indexOf("/")!==-1?this.handleStepping(Q,A,w,B):Q!==""&&this.handleNumber(Q,A,w,B)}throwAtIllegalCharacters(A){for(let Q=0;Q<A.length;Q++)if((Q===3?/[^/*0-9,\-WwLl]+/:Q===5?/[^/*0-9,\-#Ll]+/:/[^/*0-9,\-]+/).test(A[Q]))throw TypeError("CronPattern: configuration entry "+Q+" ("+A[Q]+") contains illegal characters.")}handleNumber(A,Q,w,B){let $=this.extractNth(A,Q),f=A.toUpperCase().includes("W");if(Q!=="day"&&f)throw TypeError("CronPattern: Nearest weekday modifier (W) only allowed in day-of-month.");f&&(Q="nearestWeekdays");let Y=parseInt($[0],10)+w;if(isNaN(Y))throw TypeError("CronPattern: "+Q+" is not a number: '"+A+"'");this.setPart(Q,Y,$[1]||B)}setPart(A,Q,w){if(!Object.prototype.hasOwnProperty.call(this,A))throw TypeError("CronPattern: Invalid part specified: "+A);if(A==="dayOfWeek"){if(Q===7&&(Q=0),Q<0||Q>6)throw RangeError("CronPattern: Invalid value for dayOfWeek: "+Q);this.setNthWeekdayOfMonth(Q,w);return}if(A==="second"||A==="minute"){if(Q<0||Q>=60)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="hour"){if(Q<0||Q>=24)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="day"||A==="nearestWeekdays"){if(Q<0||Q>=31)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="month"){if(Q<0||Q>=12)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="year"&&(Q<1||Q>=1e4))throw RangeError("CronPattern: Invalid value for "+A+": "+Q+" (supported range: 1-9999)");this[A][Q]=w}validateNotNaN(A,Q){if(isNaN(A))throw TypeError(Q)}validateRange(A,Q,w,B,$){if(A>Q)throw TypeError("CronPattern: From value is larger than to value: '"+$+"'");if(w!==void 0){if(w===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(w>this[B].length)throw TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[B].length+")")}}handleRangeWithStepping(A,Q,w,B){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in ranges with stepping.");let $=this.extractNth(A,Q),f=$[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(f===null)throw TypeError("CronPattern: Syntax error, illegal range with stepping: '"+A+"'");let[,Y,X,W]=f,H=parseInt(Y,10)+w,K=parseInt(X,10)+w,U=parseInt(W,10);this.validateNotNaN(H,"CronPattern: Syntax error, illegal lower range (NaN)"),this.validateNotNaN(K,"CronPattern: Syntax error, illegal upper range (NaN)"),this.validateNotNaN(U,"CronPattern: Syntax error, illegal stepping: (NaN)"),this.validateRange(H,K,U,Q,A);for(let D=H;D<=K;D+=U)this.setPart(Q,D,$[1]||B)}extractNth(A,Q){let w=A,B;if(w.includes("#")){if(Q!=="dayOfWeek")throw Error("CronPattern: nth (#) only allowed in day-of-week field");B=w.split("#")[1],w=w.split("#")[0]}else if(w.toUpperCase().endsWith("L")){if(Q!=="dayOfWeek")throw Error("CronPattern: L modifier only allowed in day-of-week field (use L alone for day-of-month)");B="L",w=w.slice(0,-1)}return[w,B]}handleRange(A,Q,w,B){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in a range.");let $=this.extractNth(A,Q),f=$[0].split("-");if(f.length!==2)throw TypeError("CronPattern: Syntax error, illegal range: '"+A+"'");let Y=parseInt(f[0],10)+w,X=parseInt(f[1],10)+w;this.validateNotNaN(Y,"CronPattern: Syntax error, illegal lower range (NaN)"),this.validateNotNaN(X,"CronPattern: Syntax error, illegal upper range (NaN)"),this.validateRange(Y,X,void 0,Q,A);for(let W=Y;W<=X;W++)this.setPart(Q,W,$[1]||B)}handleStepping(A,Q,w,B){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in parts with stepping.");let $=this.extractNth(A,Q),f=$[0].split("/");if(f.length!==2)throw TypeError("CronPattern: Syntax error, illegal stepping: '"+A+"'");if(this.sloppyRanges)f[0]===""&&(f[0]="*");else{if(f[0]==="")throw TypeError("CronPattern: Syntax error, stepping with missing prefix ('"+A+"') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.");if(f[0]!=="*")throw TypeError("CronPattern: Syntax error, stepping with numeric prefix ('"+A+"') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.")}let Y=0;f[0]!=="*"&&(Y=parseInt(f[0],10)+w);let X=parseInt(f[1],10);this.validateNotNaN(X,"CronPattern: Syntax error, illegal stepping: (NaN)"),this.validateRange(0,this[Q].length-1,X,Q,A);for(let W=Y;W<this[Q].length;W+=X)this.setPart(Q,W,$[1]||B)}replaceAlphaDays(A){return A.replace(/-sun/gi,"-7").replace(/sun/gi,"0").replace(/mon/gi,"1").replace(/tue/gi,"2").replace(/wed/gi,"3").replace(/thu/gi,"4").replace(/fri/gi,"5").replace(/sat/gi,"6")}replaceAlphaDaysQuartz(A){return A.replace(/sun/gi,"1").replace(/mon/gi,"2").replace(/tue/gi,"3").replace(/wed/gi,"4").replace(/thu/gi,"5").replace(/fri/gi,"6").replace(/sat/gi,"7")}replaceAlphaMonths(A){return A.replace(/jan/gi,"1").replace(/feb/gi,"2").replace(/mar/gi,"3").replace(/apr/gi,"4").replace(/may/gi,"5").replace(/jun/gi,"6").replace(/jul/gi,"7").replace(/aug/gi,"8").replace(/sep/gi,"9").replace(/oct/gi,"10").replace(/nov/gi,"11").replace(/dec/gi,"12")}handleNicknames(A){let Q=A.trim().toLowerCase();if(Q==="@yearly"||Q==="@annually")return"0 0 1 1 *";if(Q==="@monthly")return"0 0 1 * *";if(Q==="@weekly")return"0 0 * * 0";if(Q==="@daily"||Q==="@midnight")return"0 0 * * *";if(Q==="@hourly")return"0 * * * *";if(Q==="@reboot")throw TypeError("CronPattern: @reboot is not supported in this environment. This is an event-based trigger that requires system startup detection.");return A}setNthWeekdayOfMonth(A,Q){if(typeof Q!="number"&&Q.toUpperCase()==="L")this.dayOfWeek[A]=this.dayOfWeek[A]|32;else if(Q===63)this.dayOfWeek[A]=63;else if(Q<6&&Q>0)this.dayOfWeek[A]=this.dayOfWeek[A]|NA2[Q-1];else throw TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${Q}, Type: ${typeof Q}`)}},_s0=[31,28,31,30,31,30,31,31,30,31,30,31],K$=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],i7=class A{tz;ms;second;minute;hour;day;month;year;constructor(Q,w){if(this.tz=w,Q&&Q instanceof Date)if(!isNaN(Q))this.fromDate(Q);else throw TypeError("CronDate: Invalid date passed to CronDate constructor");else if(Q==null)this.fromDate(new Date);else if(Q&&typeof Q=="string")this.fromString(Q);else if(Q instanceof A)this.fromCronDate(Q);else throw TypeError("CronDate: Invalid type ("+typeof Q+") passed to CronDate constructor")}getLastDayOfMonth(Q,w){return w!==1?_s0[w]:new Date(Date.UTC(Q,w+1,0)).getUTCDate()}getLastWeekday(Q,w){let B=this.getLastDayOfMonth(Q,w),$=new Date(Date.UTC(Q,w,B)).getUTCDay();return $===0?B-2:$===6?B-1:B}getNearestWeekday(Q,w,B){let $=this.getLastDayOfMonth(Q,w);if(B>$)return-1;let f=new Date(Date.UTC(Q,w,B)).getUTCDay();return f===0?B===$?B-2:B+1:f===6?B===1?B+2:B-1:B}isNthWeekdayOfMonth(Q,w,B,$){let f=new Date(Date.UTC(Q,w,B)).getUTCDay(),Y=0;for(let X=1;X<=B;X++)new Date(Date.UTC(Q,w,X)).getUTCDay()===f&&Y++;if($&63&&NA2[Y-1]&$)return!0;if($&32){let X=this.getLastDayOfMonth(Q,w);for(let W=B+1;W<=X;W++)if(new Date(Date.UTC(Q,w,W)).getUTCDay()===f)return!1;return!0}return!1}fromDate(Q){if(this.tz!==void 0)if(typeof this.tz=="number")this.ms=Q.getUTCMilliseconds(),this.second=Q.getUTCSeconds(),this.minute=Q.getUTCMinutes()+this.tz,this.hour=Q.getUTCHours(),this.day=Q.getUTCDate(),this.month=Q.getUTCMonth(),this.year=Q.getUTCFullYear(),this.apply();else try{let w=Lo(Q,this.tz);this.ms=Q.getMilliseconds(),this.second=w.s,this.minute=w.i,this.hour=w.h,this.day=w.d,this.month=w.m-1,this.year=w.y}catch(w){let B=w instanceof Error?w.message:String(w);throw TypeError(`CronDate: Failed to convert date to timezone '${this.tz}'. This may happen with invalid timezone names or dates. Original error: ${B}`)}else this.ms=Q.getMilliseconds(),this.second=Q.getSeconds(),this.minute=Q.getMinutes(),this.hour=Q.getHours(),this.day=Q.getDate(),this.month=Q.getMonth(),this.year=Q.getFullYear()}fromCronDate(Q){this.tz=Q.tz,this.year=Q.year,this.month=Q.month,this.day=Q.day,this.hour=Q.hour,this.minute=Q.minute,this.second=Q.second,this.ms=Q.ms}apply(){if(this.month>11||this.month<0||this.day>_s0[this.month]||this.day<1||this.hour>59||this.minute>59||this.second>59||this.hour<0||this.minute<0||this.second<0){let Q=new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms));return this.ms=Q.getUTCMilliseconds(),this.second=Q.getUTCSeconds(),this.minute=Q.getUTCMinutes(),this.hour=Q.getUTCHours(),this.day=Q.getUTCDate(),this.month=Q.getUTCMonth(),this.year=Q.getUTCFullYear(),!0}else return!1}fromString(Q){if(typeof this.tz=="number"){let w=FA2(Q);this.ms=w.getUTCMilliseconds(),this.second=w.getUTCSeconds(),this.minute=w.getUTCMinutes(),this.hour=w.getUTCHours(),this.day=w.getUTCDate(),this.month=w.getUTCMonth(),this.year=w.getUTCFullYear(),this.apply()}else return this.fromDate(FA2(Q,this.tz))}findNext(Q,w,B,$){return this._findMatch(Q,w,B,$,1)}_findMatch(Q,w,B,$,f){let Y=this[w],X;B.lastDayOfMonth&&(X=this.getLastDayOfMonth(this.year,this.month));let W=!B.starDOW&&w=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0,H=this[w]+$,K=f===1?(U)=>U<B[w].length:(U)=>U>=0;for(let U=H;K(U);U+=f){let D=B[w][U];if(w==="day"&&!D){for(let q=0;q<B.nearestWeekdays.length;q++)if(B.nearestWeekdays[q]){let b=this.getNearestWeekday(this.year,this.month,q-$);if(b===-1)continue;if(b===U-$){D=1;break}}}if(w==="day"&&B.lastWeekday){let q=this.getLastWeekday(this.year,this.month);U-$===q&&(D=1)}if(w==="day"&&B.lastDayOfMonth&&U-$==X&&(D=1),w==="day"&&!B.starDOW){let q=B.dayOfWeek[(W+(U-$-1))%7];if(q&&q&63)q=this.isNthWeekdayOfMonth(this.year,this.month,U-$,q)?1:0;else if(q)throw Error(`CronDate: Invalid value for dayOfWeek encountered. ${q}`);B.useAndLogic?D=D&&q:!Q.domAndDow&&!B.starDOM?D=D||q:D=D&&q}if(D)return this[w]=U-$,Y!==this[w]?2:1}return 3}recurse(Q,w,B){if(B===0&&!Q.starYear){if(this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0){let f=-1;for(let Y=this.year+1;Y<Q.year.length&&Y<1e4;Y++)if(Q.year[Y]===1){f=Y;break}if(f===-1)return null;this.year=f,this.month=0,this.day=1,this.hour=0,this.minute=0,this.second=0,this.ms=0}if(this.year>=1e4)return null}let $=this.findNext(w,K$[B][0],Q,K$[B][2]);if($>1){let f=B+1;for(;f<K$.length;)this[K$[f][0]]=-K$[f][2],f++;if($===3){if(this[K$[B][1]]++,this[K$[B][0]]=-K$[B][2],this.apply(),B===0&&!Q.starYear){for(;this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0&&this.year<1e4;)this.year++;if(this.year>=1e4||this.year>=Q.year.length)return null}return this.recurse(Q,w,0)}else if(this.apply())return this.recurse(Q,w,B-1)}return B+=1,B>=K$.length?this:(Q.starYear?this.year>=3000:this.year>=1e4)?null:this.recurse(Q,w,B)}increment(Q,w,B){return this.second+=w.interval!==void 0&&w.interval>1&&B?w.interval:1,this.ms=0,this.apply(),this.recurse(Q,w,0)}decrement(Q,w){return this.second-=w.interval!==void 0&&w.interval>1?w.interval:1,this.ms=0,this.apply(),this.recurseBackward(Q,w,0,0)}recurseBackward(Q,w,B,$=0){if($>1e4)return null;if(B===0&&!Q.starYear){if(this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0){let Y=-1;for(let X=this.year-1;X>=0;X--)if(Q.year[X]===1){Y=X;break}if(Y===-1)return null;this.year=Y,this.month=11,this.day=31,this.hour=23,this.minute=59,this.second=59,this.ms=0}if(this.year<0)return null}let f=this.findPrevious(w,K$[B][0],Q,K$[B][2]);if(f>1){let Y=B+1;for(;Y<K$.length;){let X=K$[Y][0],W=K$[Y][2],H=this.getMaxPatternValue(X,Q,W);this[X]=H,Y++}if(f===3){if(this[K$[B][1]]--,B===0){let K=this.getLastDayOfMonth(this.year,this.month);this.day>K&&(this.day=K)}if(B===1)if(this.day<=0)this.day=1;else{let K=this.year,U=this.month;for(;U<0;)U+=12,K--;for(;U>11;)U-=12,K++;let D=U!==1?_s0[U]:new Date(Date.UTC(K,U+1,0)).getUTCDate();this.day>D&&(this.day=D)}this.apply();let X=K$[B][0],W=K$[B][2],H=this.getMaxPatternValue(X,Q,W);if(X==="day"){let K=this.getLastDayOfMonth(this.year,this.month);this[X]=Math.min(H,K)}else this[X]=H;if(this.apply(),B===0){let K=K$[1][2],U=this.getMaxPatternValue("day",Q,K),D=this.getLastDayOfMonth(this.year,this.month),q=Math.min(U,D);q!==this.day&&(this.day=q,this.hour=this.getMaxPatternValue("hour",Q,K$[2][2]),this.minute=this.getMaxPatternValue("minute",Q,K$[3][2]),this.second=this.getMaxPatternValue("second",Q,K$[4][2]))}if(B===0&&!Q.starYear){for(;this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0;)this.year--;if(this.year<0)return null}return this.recurseBackward(Q,w,0,$+1)}else if(this.apply())return this.recurseBackward(Q,w,B-1,$+1)}return B+=1,B>=K$.length?this:this.year<0?null:this.recurseBackward(Q,w,B,$+1)}getMaxPatternValue(Q,w,B){if(Q==="day"&&w.lastDayOfMonth)return this.getLastDayOfMonth(this.year,this.month);if(Q==="day"&&!w.starDOW)return this.getLastDayOfMonth(this.year,this.month);for(let $=w[Q].length-1;$>=0;$--)if(w[Q][$])return $-B;return w[Q].length-1-B}findPrevious(Q,w,B,$){return this._findMatch(Q,w,B,$,-1)}getDate(Q){return Q||this.tz===void 0?new Date(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms):typeof this.tz=="number"?new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute-this.tz,this.second,this.ms)):_A2(Ns0(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}match(Q,w){if(!Q.starYear&&(this.year<0||this.year>=Q.year.length||Q.year[this.year]===0))return!1;for(let B=0;B<K$.length;B++){let $=K$[B][0],f=K$[B][2],Y=this[$];if(Y+f<0||Y+f>=Q[$].length)return!1;let X=Q[$][Y+f];if($==="day"){if(!X){for(let W=0;W<Q.nearestWeekdays.length;W++)if(Q.nearestWeekdays[W]){let H=this.getNearestWeekday(this.year,this.month,W-f);if(H!==-1&&H===Y){X=1;break}}}if(Q.lastWeekday){let W=this.getLastWeekday(this.year,this.month);Y===W&&(X=1)}if(Q.lastDayOfMonth){let W=this.getLastDayOfMonth(this.year,this.month);Y===W&&(X=1)}if(!Q.starDOW){let W=new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay(),H=Q.dayOfWeek[(W+(Y-1))%7];H&&H&63&&(H=this.isNthWeekdayOfMonth(this.year,this.month,Y,H)?1:0),Q.useAndLogic?X=X&&H:!w.domAndDow&&!Q.starDOM?X=X||H:X=X&&H}}if(!X)return!1}return!0}};function gDw(A){if(A===void 0&&(A={}),delete A.name,A.legacyMode!==void 0&&A.domAndDow===void 0?A.domAndDow=!A.legacyMode:A.domAndDow===void 0&&(A.domAndDow=!1),A.legacyMode=!A.domAndDow,A.paused=A.paused===void 0?!1:A.paused,A.maxRuns=A.maxRuns===void 0?1/0:A.maxRuns,A.catch=A.catch===void 0?!1:A.catch,A.interval=A.interval===void 0?0:parseInt(A.interval.toString(),10),A.utcOffset=A.utcOffset===void 0?void 0:parseInt(A.utcOffset.toString(),10),A.dayOffset=A.dayOffset===void 0?0:parseInt(A.dayOffset.toString(),10),A.unref=A.unref===void 0?!1:A.unref,A.mode=A.mode===void 0?"auto":A.mode,A.alternativeWeekdays=A.alternativeWeekdays===void 0?!1:A.alternativeWeekdays,A.sloppyRanges=A.sloppyRanges===void 0?!1:A.sloppyRanges,!["auto","5-part","6-part","7-part","5-or-6-parts","6-or-7-parts"].includes(A.mode))throw Error("CronOptions: mode must be one of 'auto', '5-part', '6-part', '7-part', '5-or-6-parts', or '6-or-7-parts'.");if(A.startAt&&(A.startAt=new i7(A.startAt,A.timezone)),A.stopAt&&(A.stopAt=new i7(A.stopAt,A.timezone)),A.interval!==null){if(isNaN(A.interval))throw Error("CronOptions: Supplied value for interval is not a number");if(A.interval<0)throw Error("CronOptions: Supplied value for interval can not be negative")}if(A.utcOffset!==void 0){if(isNaN(A.utcOffset))throw Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.");if(A.utcOffset<-870||A.utcOffset>870)throw Error("CronOptions: utcOffset out of bounds.");if(A.utcOffset!==void 0&&A.timezone)throw Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.")}if(A.unref!==!0&&A.unref!==!1)throw Error("CronOptions: Unref should be either true, false or undefined(false).");if(A.dayOffset!==void 0&&A.dayOffset!==0&&isNaN(A.dayOffset))throw Error("CronOptions: Invalid value passed for dayOffset, should be a number representing days to offset.");return A}function ko(A){return Object.prototype.toString.call(A)==="[object Function]"||typeof A=="function"||A instanceof Function}function yDw(A){return ko(A)}function EDw(A){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(A):A&&typeof A.unref<"u"&&A.unref()}var kA2=30000,tY0=[],js0=class{name;options;_states;fn;getTz(){return this.options.timezone||this.options.utcOffset}applyDayOffset(A){if(this.options.dayOffset!==void 0&&this.options.dayOffset!==0){let Q=this.options.dayOffset*24*60*60*1000;return new Date(A.getTime()+Q)}return A}constructor(A,Q,w){let B,$;if(ko(Q))$=Q;else if(typeof Q=="object")B=Q;else if(Q!==void 0)throw Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if(ko(w))$=w;else if(typeof w=="object")B=w;else if(w!==void 0)throw Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");if(this.name=B?.name,this.options=gDw(B),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:B?B.maxRuns:void 0,paused:B?B.paused:!1,pattern:new LA2("* * * * *",void 0,{mode:"auto"})},A&&(A instanceof Date||typeof A=="string"&&A.indexOf(":")>0)?this._states.once=new i7(A,this.getTz()):this._states.pattern=new LA2(A,this.options.timezone,{mode:this.options.mode,alternativeWeekdays:this.options.alternativeWeekdays,sloppyRanges:this.options.sloppyRanges}),this.name){if(tY0.find((f)=>f.name===this.name))throw Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");tY0.push(this)}return $!==void 0&&yDw($)&&(this.fn=$,this.schedule()),this}nextRun(A){let Q=this._next(A);return Q?this.applyDayOffset(Q.getDate(!1)):null}nextRuns(A,Q){this._states.maxRuns!==void 0&&A>this._states.maxRuns&&(A=this._states.maxRuns);let w=Q||this._states.currentRun||void 0;return this._enumerateRuns(A,w,"next")}previousRuns(A,Q){return this._enumerateRuns(A,Q||void 0,"previous")}_enumerateRuns(A,Q,w){let B=[],$=Q?new i7(Q,this.getTz()):null,f=w==="next"?this._next:this._previous;for(;A--;){let Y=f.call(this,$);if(!Y)break;let X=Y.getDate(!1);B.push(this.applyDayOffset(X)),$=Y}return B}match(A){if(this._states.once){let w=new i7(A,this.getTz());w.ms=0;let B=new i7(this._states.once,this.getTz());return B.ms=0,w.getTime()===B.getTime()}let Q=new i7(A,this.getTz());return Q.ms=0,Q.match(this._states.pattern,this.options)}getPattern(){if(!this._states.once)return this._states.pattern?this._states.pattern.pattern:void 0}getOnce(){return this._states.once?this._states.once.getDate():null}isRunning(){let A=this.nextRun(this._states.currentRun),Q=!this._states.paused,w=this.fn!==void 0,B=!this._states.kill;return Q&&w&&B&&A!==null}isStopped(){return this._states.kill}isBusy(){return this._states.blocking}currentRun(){return this._states.currentRun?this._states.currentRun.getDate():null}previousRun(){return this._states.previousRun?this._states.previousRun.getDate():null}msToNext(A){let Q=this._next(A);return Q?A instanceof i7||A instanceof Date?Q.getTime()-A.getTime():Q.getTime()-new i7(A).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let A=tY0.indexOf(this);A>=0&&tY0.splice(A,1)}pause(){return this._states.paused=!0,!this._states.kill}resume(){return this._states.paused=!1,!this._states.kill}schedule(A){if(A&&this.fn)throw Error("Cron: It is not allowed to schedule two functions using the same Croner instance.");A&&(this.fn=A);let Q=this.msToNext(),w=this.nextRun(this._states.currentRun);return Q==null||isNaN(Q)||w===null?this:(Q>kA2&&(Q=kA2),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(w),Q),this._states.currentTimeout&&this.options.unref&&EDw(this._states.currentTimeout),this)}async _trigger(A){this._states.blocking=!0,this._states.currentRun=new i7(void 0,this.getTz());try{if(this.options.catch)try{this.fn!==void 0&&await this.fn(this,this.options.context)}catch(Q){if(ko(this.options.catch))try{this.options.catch(Q,this)}catch{}}else this.fn!==void 0&&await this.fn(this,this.options.context)}finally{this._states.previousRun=new i7(A,this.getTz()),this._states.blocking=!1}}async trigger(){await this._trigger()}runsLeft(){return this._states.maxRuns}_checkTrigger(A){let Q=new Date,w=!this._states.paused&&Q.getTime()>=A.getTime(),B=this._states.blocking&&this.options.protect;w&&!B?(this._states.maxRuns!==void 0&&this._states.maxRuns--,this._trigger()):w&&B&&ko(this.options.protect)&&setTimeout(()=>this.options.protect(this),0),this.schedule()}_next(A){let Q=!!(A||this._states.currentRun),w=!1;!A&&this.options.startAt&&this.options.interval&&([A,Q]=this._calculatePreviousRun(A,Q),w=!A),A=new i7(A,this.getTz()),this.options.startAt&&A&&A.getTime()<this.options.startAt.getTime()&&(A=this.options.startAt);let B=this._states.once||new i7(A,this.getTz());return!w&&B!==this._states.once&&(B=B.increment(this._states.pattern,this.options,Q)),this._states.once&&this._states.once.getTime()<=A.getTime()||B===null||this._states.maxRuns!==void 0&&this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&B.getTime()>=this.options.stopAt.getTime()?null:B}_previous(A){let Q=new i7(A,this.getTz());this.options.stopAt&&Q.getTime()>this.options.stopAt.getTime()&&(Q=this.options.stopAt);let w=new i7(Q,this.getTz());return this._states.once?this._states.once.getTime()<Q.getTime()?this._states.once:null:(w=w.decrement(this._states.pattern,this.options),w===null||this.options.startAt&&w.getTime()<this.options.startAt.getTime()?null:w)}_calculatePreviousRun(A,Q){let w=new i7(void 0,this.getTz()),B=A;if(this.options.startAt.getTime()<=w.getTime()){B=this.options.startAt;let $=B.getTime()+this.options.interval*1000;for(;$<=w.getTime();)B=new i7(B,this.getTz()).increment(this._states.pattern,this.options,!0),$=B.getTime()+this.options.interval*1000;Q=!0}return B===null&&(B=void 0),[B,Q]}};class eY0{scheduleCron(A,Q){let w=new js0(A,()=>{Q()});return{stop:()=>w.stop()}}scheduleInterval(A,Q){let w=setInterval(()=>{Q()},A);return{stop:()=>clearInterval(w)}}validateCron(A){new js0(A).stop()}}N0();var jA2=Z.union([Z.string().min(1),Z.object({location:Z.enum(["metadata","frontmatter"]),field:Z.string().min(1)})]),AX0=Z.object({entityType:Z.string().min(1),attachmentType:Z.string().min(1),mediaEntityType:Z.enum(["image","document"]),targetEntityField:jA2.optional(),requiredWhen:Z.object({status:Z.string().min(1).optional(),visibility:Z.string().min(1).optional()}).optional(),autoGenerate:Z.boolean().optional(),requiredForPublish:Z.boolean().optional(),jobType:Z.string().min(1).optional()});function Ps0(A){return`${A.entityType}:${A.attachmentType}`}class $3{static instance=null;definitions=new Map;static getInstance(){return $3.instance??=new $3,$3.instance}static resetInstance(){$3.instance=null}static createFresh(){return new $3}constructor(){}register(A){let Q=AX0.parse(A),w=Ps0(Q);return this.definitions.set(w,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(Ps0({entityType:A,attachmentType:Q}))}list(A){let Q=Array.from(this.definitions.values());return A?Q.filter((w)=>w.entityType===A):Q}has(A,Q){return this.get(A,Q)!==void 0}unregister(A,Q){this.definitions.delete(Ps0({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}S9();K2();class QX0{deps;constructor(A){this.deps=A}async ensureForEntity(A,Q={}){let w=this.deps.registry.list(A.entityType).filter(($)=>$.autoGenerate===!0).filter(($)=>!Q.attachmentType||$.attachmentType===Q.attachmentType),B={checked:w.length,enqueued:0,skipped:0};for(let $ of w)if(await this.ensureDefinition(A,$))B.enqueued+=1;else B.skipped+=1;return B}async ensureDefinition(A,Q){if(!this.matchesPolicy(A,Q))return!1;if(this.hasTargetField(A,Q.targetEntityField))return!1;if(!this.deps.context.attachments.hasProvider(A.entityType,Q.attachmentType))return!1;let w=this.resolveJobType(Q);if(!w)return!1;let B=this.getPredictedMediaId(A,Q),$=this.getDeduplicationKey(A,Q);return await this.deps.context.jobs.enqueue({type:w,data:{sourceEntityType:A.entityType,sourceEntityId:A.id,attachmentType:Q.attachmentType,imageId:B,dedupKey:$,targetEntityType:A.entityType,targetEntityId:A.id,...this.getTargetImageFieldData(Q.targetEntityField)},options:{source:"content-pipeline",metadata:{operationType:"content_operations"},deduplication:"skip",deduplicationKey:$}}),this.deps.context.logger.debug("Queued publish asset generation",{entityType:A.entityType,entityId:A.id,attachmentType:Q.attachmentType,jobType:w}),!0}matchesPolicy(A,Q){let{requiredWhen:w}=Q;if(!w)return!0;if(w.status&&A.metadata.status!==w.status)return!1;if(w.visibility&&A.visibility!==w.visibility)return!1;return!0}hasTargetField(A,Q){if(!Q)return!1;if(typeof Q==="string")return Ms0(A.metadata[Q]);if(Q.location==="metadata")return Ms0(A.metadata[Q.field]);let{frontmatter:w}=j6(A.content);return Ms0(w[Q.field])}resolveJobType(A){if(A.jobType)return A.jobType;if(A.mediaEntityType==="image")return"image:image-render-source";return}getPredictedMediaId(A,Q){let w=Q.attachmentType==="og-image"?"og":Q.attachmentType;return Z1(`${w}-${A.entityType}-${A.id}`)}getDeduplicationKey(A,Q){return`publish-asset:${Q.attachmentType}:${A.entityType}:${A.id}`}getTargetImageFieldData(A){let Q=typeof A==="string"?A:A?.field;if(Q==="coverImageId"||Q==="ogImageId")return{targetImageField:Q};return{}}}function Ms0(A){return typeof A==="string"?A.length>0:A!==void 0}wA();N0();var TDw=Z.object({id:Z.string().min(1)});async function MA2(A,Q){let{bodyContent:w,coverImageId:B,documents:$,sourceEntityType:f,sourceEntityId:Y}=SDw(Q.content),X=B?await cDw(A,B):void 0,W;if($&&$.length>0){let K=await lDw(A,$);if(K.length>0)W=K}W??=await uDw(A,f,Y);let H={bodyContent:w};if(X)H.imageData=X;if(W&&W.length>0)H.documentData=W;return H}function SDw(A){try{let Q=o2(A,Z.record(Z.string(),Z.unknown())),w=Q.metadata.coverImageId,B=typeof w==="string"?w:void 0,$=mDw(Q.metadata.documents),f=PA2(Q.metadata.sourceEntityType),Y=PA2(Q.metadata.sourceEntityId);return{bodyContent:Q.content,...B&&{coverImageId:B},...$.length>0&&{documents:$},...f&&{sourceEntityType:f},...Y&&{sourceEntityId:Y}}}catch{return{bodyContent:A}}}function mDw(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let w=TDw.safeParse(Q);return w.success?[w.data]:[]})}function PA2(A){return typeof A==="string"&&A.length>0?A:void 0}async function uDw(A,Q,w){if(!Q||!w)return;let B=await A.attachments.resolve({sourceEntityType:Q,sourceEntityId:w,attachmentType:"carousel"});return B?[B]:void 0}async function cDw(A,Q){let w=await A.entityService.getEntity({entityType:"image",id:Q});if(!w?.content)return;let B=OA2(w.content);if(!B?.mimeType.startsWith("image/"))return;return{data:B.data,mimeType:B.mimeType}}async function lDw(A,Q){return(await Promise.all(Q.map((B)=>pDw(A,B)))).filter((B)=>B!==void 0)}async function pDw(A,Q){let w=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!w?.content)return;let B=OA2(w.content);if(B?.mimeType!=="application/pdf")return;return{type:"document",data:B.data,mimeType:"application/pdf",filename:iDw(w,Q.id)}}function OA2(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function iDw(A,Q){let w=A.metadata.filename;return typeof w==="string"&&w.length>0?w:`${Q}.pdf`}S9();var dDw=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function Os0(A,Q,w,B={}){let $=B.publishTimestampField??"publishedAt",f=Q.metadata[$],Y=B.publishedAt??(typeof f==="string"?f:void 0)??new Date().toISOString(),X={...Q.metadata,status:"published",[$]:Y,platformId:w.id,...nDw(w.id,B.publishResultIdField)},W={...Q,content:xA2(Q.content,Y,w.id,B.publishResultIdField,$),metadata:X};return await A.entityService.updateEntity({entity:W}),W}function xA2(A,Q,w,B,$="publishedAt"){if(!dDw.test(A))return A;let f=D4(D4(A,"status","published"),$,Q);if(!w||!B)return f;return D4(f,B,w)}function nDw(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class Jy{deps;constructor(A){this.deps=A}async resolveCandidate(A){let{entityType:Q,id:w,slug:B}=A;if(!w&&!B)return{error:"Either 'id' or 'slug' must be provided"};let $=await this.findPublishableEntity(Q,w,B);if(!$)return{error:`Entity not found: ${Q}:${w??B}`};if($.visibility!=="public")return{error:`Cannot publish ${Q}:${$.id} to a public provider because visibility is ${$.visibility}`};if($.metadata.status==="published")return{error:"Entity is already published"};if(!this.deps.providerRegistry.has(Q))return{error:`No publish provider registered for ${Q}. Check that the required credentials are configured.`};return{entity:$}}async publish(A){let Q=await this.resolveCandidate(A);if("error"in Q)return Q;let{entity:w}=Q,{entityType:B}=A,$=this.deps.providerRegistry.get(B),{bodyContent:f,imageData:Y,documentData:X}=await MA2(this.deps.context,w),W=await $.publish(f,w.metadata,Y,X),H=this.deps.providerRegistry.getPublishResultIdField(B),K=this.deps.providerRegistry.getPublishTimestampField(B),U=await Os0(this.deps.context,w,W,{...H?{publishResultIdField:H}:{},...K?{publishTimestampField:K}:{}});return await this.runPublishAssetPreflight(U),{entity:U,result:W}}async runPublishAssetPreflight(A){if(!this.deps.publishAssetPreflight)return;try{await this.deps.publishAssetPreflight.ensureForEntity(A)}catch(Q){this.deps.context.logger.warn("Publish asset preflight failed",{entityType:A.entityType,entityId:A.id,error:Q instanceof Error?Q.message:String(Q)})}}async findPublishableEntity(A,Q,w){if(Q)return this.deps.context.entityService.getEntity({entityType:A,id:Q});if(!w)return null;return(await this.deps.context.entityService.listEntities({entityType:A,options:{filter:{metadata:{slug:w}},limit:1}}))[0]??null}}wA();N0();var xs0=Z.object({action:Z.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:Z.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:Z.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:Z.number().optional().describe("New position for reorder action (1-based)")}),Rs0=Z.object({position:Z.number(),entityType:Z.string(),entityId:Z.string(),queuedAt:Z.string()}),rDw=Z.object({success:Z.literal(!0),message:Z.string().optional(),data:Z.object({queue:Z.array(Rs0).optional(),entityType:Z.string().optional(),entityId:Z.string().optional(),position:Z.number().optional()}).optional()}),oDw=Z.object({success:Z.literal(!1),error:Z.string(),code:Z.string().optional()}),vs0=Z.union([rDw,oDw]);function wX0(A,Q,w){return{...P6(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",xs0,async($,f)=>{let{action:Y,entityType:X,entityId:W,position:H}=$;switch(Y){case"list":return sDw(w,X);case"add":return aDw(A,w,X,W,f);case"remove":return tDw(A,w,X,W,f);case"reorder":return eDw(A,w,X,W,H,f);default:return{success:!1,error:`Unknown action: ${Y}`}}},{sideEffects:"writes"}),outputSchema:vs0}}async function sDw(A,Q){let w=[];if(Q)w=await A.list(Q);else{let $=A.getRegisteredTypes();for(let f of $){let Y=await A.list(f);w.push(...Y)}w.sort((f,Y)=>new Date(f.queuedAt).getTime()-new Date(Y.queuedAt).getTime())}if(w.length===0)return{success:!0,data:{queue:[]},message:"No items in queue"};return{success:!0,data:{queue:w.map(($,f)=>({position:f+1,entityType:$.entityType,entityId:$.entityId,queuedAt:$.queuedAt}))},message:`${w.length} items in queue`}}async function aDw(A,Q,w,B,$){let f=hs0("add",w,B);if(!f.success)return f.error;A.permissions.assertEntityActionAllowed(f.entityType,"publish",$??{});let Y=await Q.add(f.entityType,f.entityId,{...$,authorization:"user"});return{success:!0,data:{entityType:f.entityType,entityId:f.entityId,position:Y.position},message:`Added to queue at position ${Y.position}`}}async function tDw(A,Q,w,B,$){let f=hs0("remove",w,B);if(!f.success)return f.error;return A.permissions.assertEntityActionAllowed(f.entityType,"update",$??{}),await Q.remove(f.entityType,f.entityId),{success:!0,data:{entityType:f.entityType,entityId:f.entityId},message:"Removed from queue"}}async function eDw(A,Q,w,B,$,f){let Y=hs0("reorder",w,B);if(!Y.success)return Y.error;let X=AGw($);if(!X.success)return X.error;return A.permissions.assertEntityActionAllowed(Y.entityType,"update",f??{}),await Q.reorder(Y.entityType,Y.entityId,X.position),{success:!0,data:{entityType:Y.entityType,entityId:Y.entityId,position:X.position},message:`Moved to position ${X.position}`}}function hs0(A,Q,w){if(!Q)return{success:!1,error:{success:!1,error:`entityType is required for ${A} action`}};if(!w)return{success:!1,error:{success:!1,error:`entityId is required for ${A} action`}};return{success:!0,entityType:Q,entityId:w}}function AGw(A){if(A===void 0)return{success:!1,error:{success:!1,error:"position is required for reorder action"}};if(A<1)return{success:!1,error:{success:!1,error:"position must be a positive number"}};return{success:!0,position:A}}N0();import{createHash as QGw}from"crypto";var Cs0=Z.object({entityType:Z.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:Z.string().optional().describe("Entity ID to publish"),slug:Z.string().optional().describe("Entity slug to publish"),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional(),contentHash:Z.string().optional(),expiresAt:Z.string().datetime().optional()}),wGw=Z.object({entityType:Z.string(),id:Z.string().optional(),slug:Z.string().optional(),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional(),contentHash:Z.string().optional(),expiresAt:Z.string().datetime().optional()}),BGw=Z.object({success:Z.literal(!0),message:Z.string().optional(),data:Z.object({entityType:Z.string().optional(),entityId:Z.string().optional(),platformId:Z.string().optional(),url:Z.string().optional()}).optional()}),$Gw=Z.object({success:Z.literal(!1),error:Z.string(),code:Z.string().optional()}),fGw=Z.object({success:Z.literal(!1).optional(),error:Z.string().optional(),needsConfirmation:Z.literal(!0),toolName:Z.string(),summary:Z.string(),preview:Z.string().optional(),args:Z.unknown()}),gs0=Z.union([BGw,$Gw,fGw]),YGw=900000;function BX0(A,Q,w,B){let $=B??new Jy({context:A,providerRegistry:w}),f=`${Q}_publish`;return{name:f,description:"Publish an entity directly to its platform. Call this when the user asks to publish; the tool will request confirmation itself. Works with any registered entity type (social-post, post, deck, etc.). For follow-up requests like 'publish it now', use the entity just read, generated, or updated in the conversation, including a post just changed to draft.",inputSchema:Cs0.shape,outputSchema:gs0,visibility:"anchor",sideEffects:"external",handler:async(Y,X)=>{let W=wGw.safeParse(Y);if(!W.success)return{success:!1,error:`Invalid input: ${W.error.issues.map((I)=>`${I.path.join(".")}: ${I.message}`).join(", ")}`};let H=W.data,{entityType:K,id:U,slug:D}=H;try{A.permissions.assertEntityActionAllowed(K,"publish",X)}catch(I){return{success:!1,error:I instanceof Error?I.message:String(I)}}let q=await $.resolveCandidate({entityType:K,id:U,slug:D});if("error"in q)return{success:!1,error:q.error};let{entity:b}=q;if(H.confirmed){let I=ZGw(f,H,b);if(I!==null)return I;let V;try{V=await $.publish({entityType:K,id:b.id})}catch(k){return{success:!1,error:k instanceof Error?k.message:String(k)}}if("error"in V)return{success:!1,error:V.error};let{entity:L,result:N}=V;return{success:!0,data:{entityType:K,entityId:L.id,platformId:N.id,url:N.url},message:`Published ${K}:${L.id}`}}return XGw(f,H,b)}}}function XGw(A,Q,w){let B=new Date(Date.now()+YGw).toISOString(),$=RA2(A,w,B),f=WGw(w);return{needsConfirmation:!0,toolName:A,summary:`Publish "${f}"?`,preview:`This will publish ${w.entityType}:${w.id} to its registered public publish provider.`,args:{...Q,id:w.id,slug:void 0,confirmed:!0,confirmationToken:$,contentHash:w.contentHash,expiresAt:B}}}function ZGw(A,Q,w){let{confirmationToken:B,contentHash:$,expiresAt:f}=Q;if(!B||!f)return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};let Y=Date.parse(f);if(Number.isNaN(Y))return{success:!1,error:"Invalid publish confirmation expiry. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};if(Y<=Date.now())return{success:!1,error:"Publish confirmation expired. Request confirmation again before publishing.",code:"EXPIRED_CONFIRMATION_TOKEN"};if($&&$!==w.contentHash)return{success:!1,error:`Cannot publish ${w.entityType}:${w.id} because it changed after confirmation. Review it and try again.`};if(B!==RA2(A,w,f))return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};return null}function RA2(A,Q,w){return QGw("sha256").update(A).update("\x00").update(Q.entityType).update("\x00").update(Q.id).update("\x00").update(Q.contentHash).update("\x00").update(w).digest("hex")}function WGw(A){let Q=A.metadata.title;if(typeof Q==="string"&&Q.length>0)return Q;let w=A.metadata.subject;if(typeof w==="string"&&w.length>0)return w;let B=A.metadata.slug;if(typeof B==="string"&&B.length>0)return B;return A.id}wA();N0();var ys0=Z.object({entityType:Z.string().min(1).describe("Entity type to reconcile"),status:Z.string().min(1).optional().describe("Optional metadata status filter, e.g. published"),assetType:Z.string().min(1).optional().describe("Optional attachment type filter, e.g. og-image")}),Es0=Z.object({success:Z.literal(!0),data:Z.object({entityType:Z.string(),assetType:Z.string().optional(),checkedEntities:Z.number(),checkedAssets:Z.number(),enqueued:Z.number(),skipped:Z.number()}),message:Z.string().optional()});function $X0(A,Q,w,B){return{...P6(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",ys0,async(f,Y)=>{if(A.permissions.assertEntityActionAllowed(f.entityType,"publish",Y),w.list(f.entityType).filter((D)=>D.autoGenerate===!0).filter((D)=>!f.assetType||D.attachmentType===f.assetType).length===0)return{success:!0,data:{entityType:f.entityType,...f.assetType&&{assetType:f.assetType},checkedEntities:0,checkedAssets:0,enqueued:0,skipped:0},message:`No publish assets configured for ${f.entityType}`};let W=await A.entityService.listEntities({entityType:f.entityType,options:{...f.status&&{filter:{metadata:{status:f.status}}}}}),H=0,K=0,U=0;for(let D of W){let q=await B.ensureForEntity(D,{...f.assetType&&{attachmentType:f.assetType}});H+=q.checked,K+=q.enqueued,U+=q.skipped}return{success:!0,data:{entityType:f.entityType,...f.assetType&&{assetType:f.assetType},checkedEntities:W.length,checkedAssets:H,enqueued:K,skipped:U},message:`Queued ${K} publish asset job(s)`}},{sideEffects:"writes"}),outputSchema:Es0}}wA();function vA2(A,Q){HGw(A,Q),KGw(A,Q),UGw(A,Q),DGw(A,Q)}function HGw(A,Q){A.messaging.subscribe(of.REGISTER,async(w)=>GGw(Q,w.payload)),A.messaging.subscribe(of.QUEUE,async(w)=>VGw(A,Q,w.payload)),A.messaging.subscribe(of.DIRECT,async(w)=>IGw(A,Q,w.payload)),A.messaging.subscribe(of.REMOVE,async(w)=>JGw(Q,w.payload)),A.messaging.subscribe(of.REORDER,async(w)=>FGw(Q,w.payload)),A.messaging.subscribe(of.LIST,async(w)=>LGw(A,Q,w.payload)),A.messaging.subscribe(of.REPORT_SUCCESS,async(w)=>kGw(Q,w.payload)),A.messaging.subscribe(of.REPORT_FAILURE,async(w)=>_Gw(Q,w.payload)),Q.logger.debug("Subscribed to publish messages")}function KGw(A,Q){A.messaging.subscribe(RF.REPORT_SUCCESS,async(w)=>NGw(Q,w.payload)),A.messaging.subscribe(RF.REPORT_FAILURE,async(w)=>jGw(Q,w.payload)),Q.logger.debug("Subscribed to generation messages")}function UGw(A,Q){A.messaging.subscribe(DA2.REGISTER,async(w)=>zGw(Q,w.payload)),Q.logger.debug("Subscribed to publish asset messages")}function DGw(A,Q){let w=async(B)=>qGw(A,Q,B.payload);A.messaging.subscribe("entity:created",w),A.messaging.subscribe("entity:updated",w),Q.logger.debug("Subscribed to entity change messages for publish assets")}async function GGw(A,Q){let{entityType:w,provider:B,config:$}=Q;try{let f=$?GA2.safeParse($):void 0;if(f&&!f.success)return A.logger.warn("Invalid publish provider config",{entityType:w,error:f.error.message}),{success:!1};if(B)A.providerRegistry.register(w,B,f?.data),A.logger.info(`Registered provider for entity type: ${w}`,{providerName:B.name,executionMode:A.providerRegistry.getExecutionMode(w)});return{success:!0}}catch(f){let Y=mA(f);return A.logger.error(`Failed to register provider: ${Y}`),{success:!1}}}async function zGw(A,Q){let w=AX0.safeParse(Q);if(!w.success)return A.logger.warn("Invalid publish asset registration",{error:w.error.message}),{success:!1};return A.publishAssetRegistry.register(w.data),A.logger.info("Registered publish asset",{entityType:w.data.entityType,attachmentType:w.data.attachmentType,mediaEntityType:w.data.mediaEntityType}),{success:!0}}async function qGw(A,Q,w){try{if(Q.publishAssetRegistry.list(w.entityType).length===0)return{success:!0};let B=w.entity??await A.entityService.getEntity({entityType:w.entityType,id:w.entityId});if(!bGw(B))return{success:!0};return await Q.publishAssetPreflight.ensureForEntity(B),{success:!0}}catch(B){return Q.logger.warn("Failed to run publish asset preflight for entity event",{entityType:w.entityType,entityId:w.entityId,error:mA(B)}),{success:!1}}}function bGw(A){if(!A)return!1;let Q=UA2.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function VGw(A,Q,w){let{entityType:B,entityId:$}=w;try{let f=w.authContext??Jo;A.permissions.assertEntityActionAllowed(B,"publish",f);let Y=await Q.queueManager.add(B,$,f);return await A.messaging.send({type:of.QUEUED,payload:{entityType:B,entityId:$,position:Y.position}}),Q.logger.debug(`Entity queued: ${$}`,{entityType:B,position:Y.position}),{success:!0}}catch(f){let Y=mA(f);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function IGw(A,Q,w){let{entityType:B,entityId:$}=w,f=w.authContext??Jo;try{if(A.permissions.assertEntityActionAllowed(B,"publish",f),!Q.providerRegistry.has(B))return Q.scheduler.failPublish(B,$,`No publish provider registered for ${B}`),{success:!1};let Y=await Q.publishExecutor.publish({entityType:B,id:$});if("error"in Y)return Q.scheduler.failPublish(B,$,Y.error),{success:!1};return Q.scheduler.completePublish(B,$,Y.result),Q.logger.debug(`Direct publish completed: ${$}`,{entityType:B}),{success:!0}}catch(Y){let X=mA(Y);return Q.logger.error(`Failed direct publish request: ${X}`),{success:!1}}}async function JGw(A,Q){let{entityType:w,entityId:B}=Q;try{return await A.queueManager.remove(w,B),A.logger.debug(`Entity removed from queue: ${B}`,{entityType:w}),{success:!0}}catch($){let f=mA($);return A.logger.error(`Failed to remove entity: ${f}`),{success:!1}}}async function FGw(A,Q){let{entityType:w,entityId:B,position:$}=Q;try{return await A.queueManager.reorder(w,B,$),A.logger.debug(`Entity reordered: ${B}`,{entityType:w,newPosition:$}),{success:!0}}catch(f){let Y=mA(f);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function LGw(A,Q,w){let{entityType:B}=w;try{let $=await Q.queueManager.list(B);return await A.messaging.send({type:of.LIST_RESPONSE,payload:{entityType:B,queue:$.map((f)=>({entityId:f.entityId,position:f.position,queuedAt:f.queuedAt}))}}),{success:!0}}catch($){let f=mA($);return Q.logger.error(`Failed to list queue: ${f}`),{success:!1}}}async function kGw(A,Q){let{entityType:w,entityId:B,result:$}=Q;return A.scheduler.completePublish(w,B,$),A.logger.info(`Publish reported success: ${B}`,{entityType:w}),{success:!0}}async function _Gw(A,Q){let{entityType:w,entityId:B,error:$}=Q;A.scheduler.failPublish(w,B,$);let f=A.retryTracker.getRetryInfo(B);return A.logger.info(`Publish reported failure: ${B}`,{entityType:w,error:$,retryCount:f?.retryCount}),{success:!0}}async function NGw(A,Q){let{entityType:w,entityId:B}=Q;return A.scheduler.completeGeneration(w,B),A.logger.info("Generation completed",{entityType:w,entityId:B}),{success:!0}}async function jGw(A,Q){let{entityType:w,error:B}=Q;return A.scheduler.failGeneration(w,B),A.logger.warn("Generation failed",{entityType:w,error:B}),{success:!0}}async function hA2(A,Q,w,B){try{if(B.skipIfDraftExists!==!1){if((await A.listEntities({entityType:w,options:{filter:{metadata:{status:"draft"}},limit:1}})).length>0)return{shouldGenerate:!1,reason:"Draft already exists"}}if(B.maxUnpublishedDrafts!==void 0){let $=await A.listEntities({entityType:w,options:{filter:{metadata:{status:"draft"}},limit:B.maxUnpublishedDrafts+1}});if($.length>=B.maxUnpublishedDrafts)return{shouldGenerate:!1,reason:`Max unpublished drafts reached (${$.length}/${B.maxUnpublishedDrafts})`}}if(B.minSourceEntities!==void 0&&B.sourceEntityType){let $=await A.listEntities({entityType:B.sourceEntityType,options:{publishedOnly:!0,limit:B.minSourceEntities}});if($.length<B.minSourceEntities)return{shouldGenerate:!1,reason:`Not enough source entities (${$.length}/${B.minSourceEntities} ${B.sourceEntityType})`}}return{shouldGenerate:!0}}catch($){return Q.error("Failed to check generation conditions",{entityType:w,error:mA($)}),{shouldGenerate:!1,reason:`Condition check failed: ${mA($)}`}}}function CA2(A){let{context:Q,config:w,queueManager:B,providerRegistry:$,retryTracker:f,publishExecutor:Y,logger:X}=A,W=PGw(Q);return xU.createFresh({queueManager:B,providerRegistry:$,retryTracker:f,logger:X,backend:new eY0,...w.entitySchedules&&{entitySchedules:w.entitySchedules},...w.generationSchedules&&{generationSchedules:w.generationSchedules},...w.generationConditions&&{generationConditions:w.generationConditions},messageBus:W,publishExecutor:Y,onCheckGenerationConditions:(H,K)=>hA2(Q.entityService,X,H,K)})}function PGw(A){return{send:async($)=>{return A.messaging.send({type:$.type,payload:$.payload,...$.target!==void 0?{target:$.target}:{},...$.metadata!==void 0?{metadata:$.metadata}:{},...$.broadcast!==void 0?{broadcast:$.broadcast}:{}})},subscribe:()=>()=>{},unsubscribe:()=>{}}}async function gA2(A,Q,w){let B=A.getEntityTypes();for(let f of B){let Y=await A.listEntities({entityType:f,options:{filter:{metadata:{status:"queued"}}}});for(let X of Y)await Q.add(X.entityType,X.id)}let $=0;for(let f of B){let Y=await Q.list(f);$+=Y.length}if($>0)w.info(`Rebuilt queue with ${$} queued entities`)}var MGw=["draft","queued","published","failed"];async function yA2(A,Q){await A.messaging.send({type:"dashboard:register-widget",payload:{id:"publication-pipeline",pluginId:Q,title:"Publication Pipeline",section:"secondary",priority:100,rendererName:"PipelineWidget",visibility:"anchor",dataProvider:()=>OGw(A)}})}async function OGw(A){let Q=A.entityService.getEntityTypes(),w=[],B={draft:0,queued:0,published:0,failed:0};for(let $ of Q){let f=await A.entityService.listEntities({entityType:$});for(let Y of f){let X=xGw(Y.metadata.status);if(!X)continue;B[X]++,w.push({id:Y.id,title:RGw(Y.id,Y.metadata.title),type:$,status:X})}}return{summary:B,items:w}}function xGw(A){return MGw.find((Q)=>Q===A)}function RGw(A,Q){return typeof Q==="string"?Q:A}var EA2={name:"@brains/content-pipeline",version:"0.2.0-alpha.143",description:"Content pipeline plugin for managing entity publishing queues, scheduling, and generation",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",croner:"^10.0.1"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^6.0.3"},exports:{".":{types:"./src/index.ts",default:"./src/index.ts"}},files:["src"],main:"src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"src/index.ts"};class Ts0 extends aQ{pluginContext;queueManager;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A={}){super("content-pipeline",EA2,A,zA2)}async onRegister(A){this.pluginContext=A,this.queueManager=Q3.createFresh(),this.providerRegistry=w3.createFresh(),this.retryTracker=B3.createFresh(),this.publishAssetRegistry=$3.createFresh(),this.publishAssetPreflight=new QX0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new Jy({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=CA2({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),vA2(A,{queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,publishAssetRegistry:this.publishAssetRegistry,publishAssetPreflight:this.publishAssetPreflight,scheduler:this.scheduler,logger:this.logger})}async onReady(A){await gA2(A.entityService,this.queueManager,this.logger),await yA2(A,this.id),await this.scheduler.start(),this.logger.info("Content pipeline plugin started")}async getTools(){if(!this.pluginContext)throw Error("Plugin context not initialized");return[wX0(this.pluginContext,this.id,this.queueManager),BX0(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),$X0(this.pluginContext,this.id,this.publishAssetRegistry,this.publishAssetPreflight)]}async getInstructions(){return'## Publishing\n- Use `content-pipeline_queue` to manage the publish queue \u2014 list queued items, add entities to the queue, remove them, or reorder.\n- Use `content-pipeline_publish` to publish an entity directly to its platform (e.g. LinkedIn, Buttondown). This tool has its own confirmation flow; call it without `confirmed` when the user asks to publish instead of asking for plain-text confirmation. Follow-up requests like "publish it now" should target the entity just read, generated, or updated in the conversation, including a post just changed to draft.\n- Use `content-pipeline_ensure-assets` to reconcile missing publish assets such as generated OG images for already-published content.\n- When users ask about their "publish queue", "publishing queue", or "what\'s queued", use `content-pipeline_queue`.'}getQueueManager(){return this.queueManager}getProviderRegistry(){return this.providerRegistry}getRetryTracker(){return this.retryTracker}getPublishAssetRegistry(){return this.publishAssetRegistry}getScheduler(){return this.scheduler}async onShutdown(){await this.scheduler.stop(),Q3.resetInstance(),w3.resetInstance(),B3.resetInstance(),$3.resetInstance()}}function Ss0(A={}){return new Ts0(A)}wA();N0();var TA2=Z.object({accountId:Z.string().describe("Cloudflare account ID"),apiToken:Z.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:Z.string().describe("Cloudflare Web Analytics site tag")}),ms0=Z.object({cloudflare:TA2.optional()});wA();N0();var hGw=Z.object({date:Z.string().describe("Single date in YYYY-MM-DD format").optional(),days:Z.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:Z.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:Z.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:Z.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function CGw(A){if(A.date&&(A.days||A.startDate||A.endDate))return"Cannot combine 'date' with 'days' or 'startDate'/'endDate'";if(A.days&&(A.startDate||A.endDate))return"Cannot combine 'days' with 'startDate'/'endDate'";if(A.startDate&&!A.endDate||!A.startDate&&A.endDate)return"Both 'startDate' and 'endDate' must be provided for custom range";return null}function SA2(A,Q,w){let B=[];if(!w)return B;return B.push(P6(A,"query",`Query website analytics from Cloudflare.
6795
6795
 
6796
6796
  Date range options (use only one):
6797
6797
  - No params: yesterday only
@@ -6929,7 +6929,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,hGw,
6929
6929
  }
6930
6930
  }
6931
6931
  }
6932
- `,{...this.baseVariables(A),limit:A.limit??20})).map((B)=>({country:B.dimensions.countryName,visits:B.sum.visits}))}}var cs0=7,gGw=10;function uA2(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=oQ0(),w=gOA(cs0),B=SR(w),$=SR(Q);try{let[f,Y]=await Promise.all([A.getWebsiteStats({startDate:B,endDate:$}),A.getTopPages({startDate:B,endDate:$,limit:gGw})]);return{days:cs0,startDate:B,endDate:$,pageviews:f.pageviews,visitors:f.visitors,topPages:Y}}catch(f){return{error:f instanceof Error?f.message:"Failed to fetch analytics",days:cs0}}}}var cA2={name:"@brains/analytics",version:"0.2.0-alpha.142",description:"Analytics plugin for collecting website and social media metrics",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class lA2 extends aQ{cloudflareClient;constructor(A={}){super("analytics",cA2,A,ms0)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new us0(this.config.cloudflare):void 0,A.insights.register("traffic-overview",uA2(this.cloudflareClient))}async onReady(A){let Q=this.config.cloudflare?.siteTag;if(!Q)return;await A.messaging.send({type:"plugin:site-builder:head-script:register",payload:{pluginId:this.id,script:mA2(Q)}})}async getTools(){return SA2(this.id,this.getContext(),this.cloudflareClient)}}function EGw(A={}){return new lA2(A)}var fX0=EGw;import{randomBytes as rGw}from"crypto";wA();K2();var pA2="note",TGw=new Set(["description","excerpt","summary","tagline","story"]);function SGw(A){if(A.endsWith("s"))return A;return eH(A)}function _o(A){return typeof A==="object"&&A!==null}function WP(A){if(!_o(A))return;let Q=A.def;return _o(Q)?Q:void 0}function dA2(A){let Q=WP(A)?.type;return typeof Q==="string"?Q:void 0}function mGw(A){return typeof A==="function"?A():A}function ls0(A,Q=!1,w){let B=dA2(A),$=WP(A);if(B==="optional"||B==="nullable")return ls0($?.innerType,!0,w);if(B==="default")return ls0($?.innerType,!0,mGw($?.defaultValue));let f={inner:A,isOptional:Q};if(w!==void 0)f.defaultValue=w;return f}function uGw(A){let Q=WP(A)?.entries;if(!_o(Q))return;let w=Object.values(Q);return w.every((B)=>typeof B==="string")?w:void 0}function cGw(A){let Q=WP(A)?.values;return Array.isArray(Q)?Q[0]:void 0}function lGw(A){let Q=WP(A)?.checks;if(!Array.isArray(Q))return!1;return Q.some((w)=>{return WP(w)?.format==="datetime"})}function pGw(A){if(!_o(A))return;let Q=A.shape;return _o(Q)?Q:void 0}function ps0(A,Q){let{inner:w,isOptional:B,defaultValue:$}=ls0(Q),f=dA2(w),Y=$??cGw(w),X={name:A,label:bV(A),widget:"string",...B&&{required:!1},...Y!==void 0&&{default:Y}};switch(f){case"string":{if(lGw(w))return{...X,widget:"datetime"};if(TGw.has(A))return{...X,widget:"text"};return{...X,widget:"string"}}case"number":return{...X,widget:"number"};case"boolean":return{...X,widget:"boolean"};case"enum":{let W=uGw(w);return{...X,widget:"select",...W?{options:W}:{}}}case"array":{let W=WP(w)?.element,H=ps0("item",W);if(H.widget==="object"&&H.fields)return{...X,widget:"list",fields:H.fields};return{...X,widget:"list",field:{name:A,label:bV(A),widget:H.widget}}}case"object":{let W=Object.entries(pGw(w)??{}).map(([H,K])=>ps0(H,K));return{...X,widget:"object",fields:W}}case"literal":return{...X,widget:"string"};default:return{...X,widget:"string"}}}function iA2(A,Q){let w=Object.entries(A.shape).map(([B,$])=>ps0(B,$));if(Q)w.push({name:"body",label:"Body",widget:"markdown"});return w}function nA2(A){let Q=[],w=[];for(let B of A.entityTypes){let $=A.getFrontmatterSchema(B);if(!$)continue;let f=A.getAdapter(B),Y=f?.hasBody!==!1,X=A.entityDisplay?.[B],W=B===pA2?"Note":bV(B),H=X?.label??W,K=X?.pluralName??SGw(H);if(f?.isSingleton){w.push({name:B,label:H,file:`${B}/${B}.md`,fields:iA2($,Y)});continue}if(B===pA2){Q.push({name:B,label:K,folder:".",create:!0,extension:"md",format:"raw",fields:[{name:"body",label:"Body",widget:"markdown"}]});continue}Q.push({name:B,label:K,folder:B,create:!0,extension:"md",format:"frontmatter",fields:iA2($,Y)})}if(w.length>0)Q.push({name:"settings",label:"Settings",files:w});return{backend:{name:"github",repo:A.repo,branch:A.branch,...A.baseUrl&&{base_url:A.baseUrl},...A.authEndpoint&&{auth_endpoint:A.authEndpoint}},media_folder:"image",public_folder:"/images",collections:Q}}var iGw=new RegExp("[<>&\\u2028\\u2029]","g");function Fy(A){return JSON.stringify(A).replace(iGw,(Q)=>`\\u${Q.charCodeAt(0).toString(16).padStart(4,"0")}`)}var rA2="https://unpkg.com/@sveltia/cms@0.165.1/dist/sveltia-cms.js";function YX0(A){let Q=`<script src="${rA2}"></script>`;return`<!doctype html>
6932
+ `,{...this.baseVariables(A),limit:A.limit??20})).map((B)=>({country:B.dimensions.countryName,visits:B.sum.visits}))}}var cs0=7,gGw=10;function uA2(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=oQ0(),w=gOA(cs0),B=SR(w),$=SR(Q);try{let[f,Y]=await Promise.all([A.getWebsiteStats({startDate:B,endDate:$}),A.getTopPages({startDate:B,endDate:$,limit:gGw})]);return{days:cs0,startDate:B,endDate:$,pageviews:f.pageviews,visitors:f.visitors,topPages:Y}}catch(f){return{error:f instanceof Error?f.message:"Failed to fetch analytics",days:cs0}}}}var cA2={name:"@brains/analytics",version:"0.2.0-alpha.143",description:"Analytics plugin for collecting website and social media metrics",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class lA2 extends aQ{cloudflareClient;constructor(A={}){super("analytics",cA2,A,ms0)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new us0(this.config.cloudflare):void 0,A.insights.register("traffic-overview",uA2(this.cloudflareClient))}async onReady(A){let Q=this.config.cloudflare?.siteTag;if(!Q)return;await A.messaging.send({type:"plugin:site-builder:head-script:register",payload:{pluginId:this.id,script:mA2(Q)}})}async getTools(){return SA2(this.id,this.getContext(),this.cloudflareClient)}}function EGw(A={}){return new lA2(A)}var fX0=EGw;import{randomBytes as rGw}from"crypto";wA();K2();var pA2="note",TGw=new Set(["description","excerpt","summary","tagline","story"]);function SGw(A){if(A.endsWith("s"))return A;return eH(A)}function _o(A){return typeof A==="object"&&A!==null}function WP(A){if(!_o(A))return;let Q=A.def;return _o(Q)?Q:void 0}function dA2(A){let Q=WP(A)?.type;return typeof Q==="string"?Q:void 0}function mGw(A){return typeof A==="function"?A():A}function ls0(A,Q=!1,w){let B=dA2(A),$=WP(A);if(B==="optional"||B==="nullable")return ls0($?.innerType,!0,w);if(B==="default")return ls0($?.innerType,!0,mGw($?.defaultValue));let f={inner:A,isOptional:Q};if(w!==void 0)f.defaultValue=w;return f}function uGw(A){let Q=WP(A)?.entries;if(!_o(Q))return;let w=Object.values(Q);return w.every((B)=>typeof B==="string")?w:void 0}function cGw(A){let Q=WP(A)?.values;return Array.isArray(Q)?Q[0]:void 0}function lGw(A){let Q=WP(A)?.checks;if(!Array.isArray(Q))return!1;return Q.some((w)=>{return WP(w)?.format==="datetime"})}function pGw(A){if(!_o(A))return;let Q=A.shape;return _o(Q)?Q:void 0}function ps0(A,Q){let{inner:w,isOptional:B,defaultValue:$}=ls0(Q),f=dA2(w),Y=$??cGw(w),X={name:A,label:bV(A),widget:"string",...B&&{required:!1},...Y!==void 0&&{default:Y}};switch(f){case"string":{if(lGw(w))return{...X,widget:"datetime"};if(TGw.has(A))return{...X,widget:"text"};return{...X,widget:"string"}}case"number":return{...X,widget:"number"};case"boolean":return{...X,widget:"boolean"};case"enum":{let W=uGw(w);return{...X,widget:"select",...W?{options:W}:{}}}case"array":{let W=WP(w)?.element,H=ps0("item",W);if(H.widget==="object"&&H.fields)return{...X,widget:"list",fields:H.fields};return{...X,widget:"list",field:{name:A,label:bV(A),widget:H.widget}}}case"object":{let W=Object.entries(pGw(w)??{}).map(([H,K])=>ps0(H,K));return{...X,widget:"object",fields:W}}case"literal":return{...X,widget:"string"};default:return{...X,widget:"string"}}}function iA2(A,Q){let w=Object.entries(A.shape).map(([B,$])=>ps0(B,$));if(Q)w.push({name:"body",label:"Body",widget:"markdown"});return w}function nA2(A){let Q=[],w=[];for(let B of A.entityTypes){let $=A.getFrontmatterSchema(B);if(!$)continue;let f=A.getAdapter(B),Y=f?.hasBody!==!1,X=A.entityDisplay?.[B],W=B===pA2?"Note":bV(B),H=X?.label??W,K=X?.pluralName??SGw(H);if(f?.isSingleton){w.push({name:B,label:H,file:`${B}/${B}.md`,fields:iA2($,Y)});continue}if(B===pA2){Q.push({name:B,label:K,folder:".",create:!0,extension:"md",format:"raw",fields:[{name:"body",label:"Body",widget:"markdown"}]});continue}Q.push({name:B,label:K,folder:B,create:!0,extension:"md",format:"frontmatter",fields:iA2($,Y)})}if(w.length>0)Q.push({name:"settings",label:"Settings",files:w});return{backend:{name:"github",repo:A.repo,branch:A.branch,...A.baseUrl&&{base_url:A.baseUrl},...A.authEndpoint&&{auth_endpoint:A.authEndpoint}},media_folder:"image",public_folder:"/images",collections:Q}}var iGw=new RegExp("[<>&\\u2028\\u2029]","g");function Fy(A){return JSON.stringify(A).replace(iGw,(Q)=>`\\u${Q.charCodeAt(0).toString(16).padStart(4,"0")}`)}var rA2="https://unpkg.com/@sveltia/cms@0.165.1/dist/sveltia-cms.js";function YX0(A){let Q=`<script src="${rA2}"></script>`;return`<!doctype html>
6933
6933
  <html>
6934
6934
  <head>
6935
6935
  <meta charset="utf-8" />
@@ -6968,7 +6968,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,hGw,
6968
6968
  showError(error instanceof Error ? error.message : String(error));
6969
6969
  }
6970
6970
  })();
6971
- `}dk();N0();var oA2={name:"@brains/cms",version:"0.2.0-alpha.142",description:"CMS plugin for config and browser authoring routes",dependencies:{"@brains/auth-service":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var is0="brains_cms_oauth_state",oGw=600,sGw="auth",aGw=Z.looseObject({label:Z.string().optional(),pluralName:Z.string().optional()}),tGw=Z.object({clientId:Z.string().optional(),clientSecret:Z.string().optional(),scope:Z.string().optional()}),eGw=Z.object({contentRepoToken:Z.string().optional()}),A3w=Z.object({entityDisplay:Z.record(Z.string(),aGw).optional(),routePath:Z.string().default("/cms"),githubOAuth:tGw.optional(),passkeyLogin:eGw.optional()}).refine((A)=>{let Q=Boolean(HP(A.githubOAuth?.clientId)&&HP(A.githubOAuth?.clientSecret)),w=Boolean(HP(A.passkeyLogin?.contentRepoToken));return!(Q&&w)},{message:"CMS login supports a single method per brain: configure githubOAuth or passkeyLogin, not both."}),Q3w=Z.looseObject({error:Z.string().optional(),error_description:Z.string().optional()}).transform((A)=>A.error_description??A.error),w3w=Z.looseObject({access_token:Z.string().min(1)});function B3w(A){return`${A.endsWith("/")?A:`${A}/`}config.yml`}function HP(A){if(!A)return;let Q=A.trim();return Q.length>0?Q:void 0}function $3w(A){let Q=HP(A.githubOAuth?.clientId),w=HP(A.githubOAuth?.clientSecret),B=HP(A.passkeyLogin?.contentRepoToken);return{...Q&&w?{githubOAuth:{clientId:Q,clientSecret:w,scope:HP(A.githubOAuth?.scope)??"repo"}}:{},...B?{passkeyLogin:{contentRepoToken:B}}:{}}}function f3w(A){return Boolean(A.githubOAuth??A.passkeyLogin)}function Y3w(A,Q,w){let B=A.entityDisplay??w?.entityDisplay;return{...B?{entityDisplay:B}:{},...f3w(Q)?{authEndpoint:sGw}:{}}}async function X3w(A){let Q=await A.messaging.send({type:"git-sync:get-repo-info",payload:{}});if("noop"in Q||!Q.success||!Q.data)throw Error("CMS config unavailable: git-sync repo info unavailable");let{repo:w,branch:B}=Q.data;if(!w||!B)throw Error("CMS config unavailable: git-sync repo info incomplete");return{repo:w,branch:B}}async function Z3w(A,Q={}){let{repo:w,branch:B}=await X3w(A);return nA2({repo:w,branch:B,...Q.baseUrl&&{baseUrl:Q.baseUrl},...Q.authEndpoint&&{authEndpoint:Q.authEndpoint},entityTypes:A.entityService.getEntityTypes(),getFrontmatterSchema:($)=>A.entities.getEffectiveFrontmatterSchema($),getAdapter:($)=>A.entities.getAdapter($),...Q.entityDisplay&&{entityDisplay:Q.entityDisplay}})}async function tA2(A,Q={}){return tV(await Z3w(A,Q))}class ds0 extends aQ{constructor(A={}){super("cms",oA2,A,A3w)}async onRegister(A){await super.onRegister(A),A.endpoints.register({label:"CMS",url:this.config.routePath,priority:40,visibility:"anchor"}),A.interactions.register({id:"cms",label:"CMS",description:"Edit and manage content through the browser CMS.",href:this.config.routePath,kind:"admin",priority:40,visibility:"anchor"})}getWebRoutes(){let A=B3w(this.config.routePath),Q=$3w(this.config),w=[];if(Q.githubOAuth||Q.passkeyLogin)w.push({path:"/auth",method:"GET",public:!0,handler:async(B)=>this.handleAuth(B,Q)});if(Q.githubOAuth){let B=Q.githubOAuth;w.push({path:"/auth/callback",method:"GET",public:!0,handler:async($)=>this.handleGitHubCallback($,B)})}if(Q.passkeyLogin){let B=Q.passkeyLogin;w.push({path:"/auth/cms-token",method:"POST",public:!0,handler:async($)=>this.handleCmsToken($,B)})}return[{path:this.config.routePath,method:"GET",public:!0,handler:async(B)=>{if(Q.passkeyLogin){if(!await aA2(B))return new Response(null,{status:302,headers:{Location:`/login?return_to=${encodeURIComponent(this.config.routePath)}`,"Cache-Control":"no-store"}});return jo(YX0({cmsConfigPath:A,authTokenEndpoint:"/auth/cms-token"}))}return jo(YX0({cmsConfigPath:A}))}},{path:A,method:"GET",public:!0,handler:async(B)=>{try{let $=Y3w(this.config,Q,this.getContext()),f=await tA2(this.getContext(),{...$,...$.authEndpoint?{baseUrl:No(this.getContext(),B)}:{}});return new Response(f,{headers:{"Content-Type":"application/yaml; charset=utf-8"}})}catch($){return new Response($ instanceof Error?$.message:"CMS unavailable",{status:503,headers:{"Content-Type":"text/plain; charset=utf-8"}})}}},...w]}async handleAuth(A,Q){if(Q.githubOAuth)return this.redirectToGitHub(A,Q.githubOAuth);if(Q.passkeyLogin){let w=await aA2(A)?G3w:D3w;return jo(w(No(this.getContext(),A)))}return U3w("CMS login is not enabled",404)}redirectToGitHub(A,Q){let w=rGw(32).toString("base64url"),B=`${No(this.getContext(),A)}/auth/callback`,$=new URL("https://github.com/login/oauth/authorize");return $.searchParams.set("client_id",Q.clientId),$.searchParams.set("redirect_uri",B),$.searchParams.set("scope",Q.scope),$.searchParams.set("state",w),new Response(null,{status:302,headers:{Location:$.toString(),"Set-Cookie":H3w(w,A),"Cache-Control":"no-store"}})}async handleGitHubCallback(A,Q){let w=new URL(A.url),B=w.searchParams.get("error");if(B){let H=w.searchParams.get("error_description")??B;return XX0(`GitHub OAuth failed: ${H}`)}let $=w.searchParams.get("state"),f=K3w(A.headers.get("cookie"),is0);if(!$||!f||$!==f)return XX0("GitHub OAuth state did not match");let Y=w.searchParams.get("code");if(!Y)return XX0("GitHub OAuth callback did not include a code");let X=`${No(this.getContext(),A)}/auth/callback`,W=await W3w(Q,Y,X);if(!W.success)return XX0(W.error);return jo(z3w(W.token,No(this.getContext(),A)),200,{"Set-Cookie":A12()})}async handleCmsToken(A,Q){if(!await P7()?.getOperatorSession(A))return sA2({error:"Operator session required"},401);return sA2({token:Q.contentRepoToken,provider:"github"},200,{"Cache-Control":"no-store"})}}function KP(A={}){return new ds0(A)}async function W3w(A,Q,w){let B=new URLSearchParams({client_id:A.clientId,client_secret:A.clientSecret,code:Q,redirect_uri:w}),$=await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/x-www-form-urlencoded"},body:B}),f;try{f=await $.json()}catch{return{success:!1,error:"GitHub token response was not JSON"}}let Y=Q3w.safeParse(f);if(!$.ok)return{success:!1,error:Y.success?Y.data??"GitHub token exchange failed":"GitHub token exchange failed"};if(Y.success&&Y.data)return{success:!1,error:Y.data};let X=w3w.safeParse(f);if(!X.success)return{success:!1,error:"GitHub token response omitted token"};return{success:!0,token:X.data.access_token}}function No(A,Q){let w=new URL(Q.url).origin;if(eA2(w))return w;return A.siteUrl??w}function eA2(A){let{hostname:Q}=new URL(A);return Q==="localhost"||Q==="127.0.0.1"||Q==="::1"||Q==="[::1]"}function H3w(A,Q){let w=eA2(new URL(Q.url).origin)?"":"; Secure";return`${is0}=${A}; Path=/auth; HttpOnly; SameSite=Lax; Max-Age=${oGw}${w}`}function A12(){return`${is0}=; Path=/auth; HttpOnly; SameSite=Lax; Max-Age=0`}function K3w(A,Q){if(!A)return;for(let w of A.split(";")){let[B,...$]=w.trim().split("=");if(B===Q)return $.join("=")}return}function jo(A,Q=200,w={}){return new Response(A,{status:Q,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store",...w}})}function U3w(A,Q=200){return new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8","Cache-Control":"no-store"}})}function sA2(A,Q=200,w={}){return new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store",...w}})}function XX0(A){return jo(`<!doctype html><html><body><h1>CMS login failed</h1><p>${V3w(A)}</p></body></html>`,400,{"Set-Cookie":A12()})}async function aA2(A){return Boolean(await P7()?.getOperatorSession(A))}function D3w(A){return`<!doctype html>
6971
+ `}dk();N0();var oA2={name:"@brains/cms",version:"0.2.0-alpha.143",description:"CMS plugin for config and browser authoring routes",dependencies:{"@brains/auth-service":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var is0="brains_cms_oauth_state",oGw=600,sGw="auth",aGw=Z.looseObject({label:Z.string().optional(),pluralName:Z.string().optional()}),tGw=Z.object({clientId:Z.string().optional(),clientSecret:Z.string().optional(),scope:Z.string().optional()}),eGw=Z.object({contentRepoToken:Z.string().optional()}),A3w=Z.object({entityDisplay:Z.record(Z.string(),aGw).optional(),routePath:Z.string().default("/cms"),githubOAuth:tGw.optional(),passkeyLogin:eGw.optional()}).refine((A)=>{let Q=Boolean(HP(A.githubOAuth?.clientId)&&HP(A.githubOAuth?.clientSecret)),w=Boolean(HP(A.passkeyLogin?.contentRepoToken));return!(Q&&w)},{message:"CMS login supports a single method per brain: configure githubOAuth or passkeyLogin, not both."}),Q3w=Z.looseObject({error:Z.string().optional(),error_description:Z.string().optional()}).transform((A)=>A.error_description??A.error),w3w=Z.looseObject({access_token:Z.string().min(1)});function B3w(A){return`${A.endsWith("/")?A:`${A}/`}config.yml`}function HP(A){if(!A)return;let Q=A.trim();return Q.length>0?Q:void 0}function $3w(A){let Q=HP(A.githubOAuth?.clientId),w=HP(A.githubOAuth?.clientSecret),B=HP(A.passkeyLogin?.contentRepoToken);return{...Q&&w?{githubOAuth:{clientId:Q,clientSecret:w,scope:HP(A.githubOAuth?.scope)??"repo"}}:{},...B?{passkeyLogin:{contentRepoToken:B}}:{}}}function f3w(A){return Boolean(A.githubOAuth??A.passkeyLogin)}function Y3w(A,Q,w){let B=A.entityDisplay??w?.entityDisplay;return{...B?{entityDisplay:B}:{},...f3w(Q)?{authEndpoint:sGw}:{}}}async function X3w(A){let Q=await A.messaging.send({type:"git-sync:get-repo-info",payload:{}});if("noop"in Q||!Q.success||!Q.data)throw Error("CMS config unavailable: git-sync repo info unavailable");let{repo:w,branch:B}=Q.data;if(!w||!B)throw Error("CMS config unavailable: git-sync repo info incomplete");return{repo:w,branch:B}}async function Z3w(A,Q={}){let{repo:w,branch:B}=await X3w(A);return nA2({repo:w,branch:B,...Q.baseUrl&&{baseUrl:Q.baseUrl},...Q.authEndpoint&&{authEndpoint:Q.authEndpoint},entityTypes:A.entityService.getEntityTypes(),getFrontmatterSchema:($)=>A.entities.getEffectiveFrontmatterSchema($),getAdapter:($)=>A.entities.getAdapter($),...Q.entityDisplay&&{entityDisplay:Q.entityDisplay}})}async function tA2(A,Q={}){return tV(await Z3w(A,Q))}class ds0 extends aQ{constructor(A={}){super("cms",oA2,A,A3w)}async onRegister(A){await super.onRegister(A),A.endpoints.register({label:"CMS",url:this.config.routePath,priority:40,visibility:"anchor"}),A.interactions.register({id:"cms",label:"CMS",description:"Edit and manage content through the browser CMS.",href:this.config.routePath,kind:"admin",priority:40,visibility:"anchor"})}getWebRoutes(){let A=B3w(this.config.routePath),Q=$3w(this.config),w=[];if(Q.githubOAuth||Q.passkeyLogin)w.push({path:"/auth",method:"GET",public:!0,handler:async(B)=>this.handleAuth(B,Q)});if(Q.githubOAuth){let B=Q.githubOAuth;w.push({path:"/auth/callback",method:"GET",public:!0,handler:async($)=>this.handleGitHubCallback($,B)})}if(Q.passkeyLogin){let B=Q.passkeyLogin;w.push({path:"/auth/cms-token",method:"POST",public:!0,handler:async($)=>this.handleCmsToken($,B)})}return[{path:this.config.routePath,method:"GET",public:!0,handler:async(B)=>{if(Q.passkeyLogin){if(!await aA2(B))return new Response(null,{status:302,headers:{Location:`/login?return_to=${encodeURIComponent(this.config.routePath)}`,"Cache-Control":"no-store"}});return jo(YX0({cmsConfigPath:A,authTokenEndpoint:"/auth/cms-token"}))}return jo(YX0({cmsConfigPath:A}))}},{path:A,method:"GET",public:!0,handler:async(B)=>{try{let $=Y3w(this.config,Q,this.getContext()),f=await tA2(this.getContext(),{...$,...$.authEndpoint?{baseUrl:No(this.getContext(),B)}:{}});return new Response(f,{headers:{"Content-Type":"application/yaml; charset=utf-8"}})}catch($){return new Response($ instanceof Error?$.message:"CMS unavailable",{status:503,headers:{"Content-Type":"text/plain; charset=utf-8"}})}}},...w]}async handleAuth(A,Q){if(Q.githubOAuth)return this.redirectToGitHub(A,Q.githubOAuth);if(Q.passkeyLogin){let w=await aA2(A)?G3w:D3w;return jo(w(No(this.getContext(),A)))}return U3w("CMS login is not enabled",404)}redirectToGitHub(A,Q){let w=rGw(32).toString("base64url"),B=`${No(this.getContext(),A)}/auth/callback`,$=new URL("https://github.com/login/oauth/authorize");return $.searchParams.set("client_id",Q.clientId),$.searchParams.set("redirect_uri",B),$.searchParams.set("scope",Q.scope),$.searchParams.set("state",w),new Response(null,{status:302,headers:{Location:$.toString(),"Set-Cookie":H3w(w,A),"Cache-Control":"no-store"}})}async handleGitHubCallback(A,Q){let w=new URL(A.url),B=w.searchParams.get("error");if(B){let H=w.searchParams.get("error_description")??B;return XX0(`GitHub OAuth failed: ${H}`)}let $=w.searchParams.get("state"),f=K3w(A.headers.get("cookie"),is0);if(!$||!f||$!==f)return XX0("GitHub OAuth state did not match");let Y=w.searchParams.get("code");if(!Y)return XX0("GitHub OAuth callback did not include a code");let X=`${No(this.getContext(),A)}/auth/callback`,W=await W3w(Q,Y,X);if(!W.success)return XX0(W.error);return jo(z3w(W.token,No(this.getContext(),A)),200,{"Set-Cookie":A12()})}async handleCmsToken(A,Q){if(!await P7()?.getOperatorSession(A))return sA2({error:"Operator session required"},401);return sA2({token:Q.contentRepoToken,provider:"github"},200,{"Cache-Control":"no-store"})}}function KP(A={}){return new ds0(A)}async function W3w(A,Q,w){let B=new URLSearchParams({client_id:A.clientId,client_secret:A.clientSecret,code:Q,redirect_uri:w}),$=await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/x-www-form-urlencoded"},body:B}),f;try{f=await $.json()}catch{return{success:!1,error:"GitHub token response was not JSON"}}let Y=Q3w.safeParse(f);if(!$.ok)return{success:!1,error:Y.success?Y.data??"GitHub token exchange failed":"GitHub token exchange failed"};if(Y.success&&Y.data)return{success:!1,error:Y.data};let X=w3w.safeParse(f);if(!X.success)return{success:!1,error:"GitHub token response omitted token"};return{success:!0,token:X.data.access_token}}function No(A,Q){let w=new URL(Q.url).origin;if(eA2(w))return w;return A.siteUrl??w}function eA2(A){let{hostname:Q}=new URL(A);return Q==="localhost"||Q==="127.0.0.1"||Q==="::1"||Q==="[::1]"}function H3w(A,Q){let w=eA2(new URL(Q.url).origin)?"":"; Secure";return`${is0}=${A}; Path=/auth; HttpOnly; SameSite=Lax; Max-Age=${oGw}${w}`}function A12(){return`${is0}=; Path=/auth; HttpOnly; SameSite=Lax; Max-Age=0`}function K3w(A,Q){if(!A)return;for(let w of A.split(";")){let[B,...$]=w.trim().split("=");if(B===Q)return $.join("=")}return}function jo(A,Q=200,w={}){return new Response(A,{status:Q,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store",...w}})}function U3w(A,Q=200){return new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8","Cache-Control":"no-store"}})}function sA2(A,Q=200,w={}){return new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store",...w}})}function XX0(A){return jo(`<!doctype html><html><body><h1>CMS login failed</h1><p>${V3w(A)}</p></body></html>`,400,{"Set-Cookie":A12()})}async function aA2(A){return Boolean(await P7()?.getOperatorSession(A))}function D3w(A){return`<!doctype html>
6972
6972
  <html lang="en">
6973
6973
  <head>
6974
6974
  <meta charset="utf-8" />
@@ -8373,7 +8373,7 @@ ${w12}`;import{jsxDEV as RU,Fragment as f12}from"preact/jsx-dev-runtime";functio
8373
8373
  }
8374
8374
  });
8375
8375
  })();`;function wzw({input:A}){let Q=A.appInfo.entities,w=A.appInfo.entityCounts,B=e3w(A.widgets),$=Boolean(A.character.role)||Boolean(A.character.purpose)||A.character.values.length>0,f=A.appInfo.interactions,Y=`layout${$?" has-identity":""}`,X=A.operatorAccess&&!A.operatorAccess.isOperator&&A.operatorAccess.hiddenWidgetCount>0,W=new Date;return rw("html",{lang:"en","data-theme":"dark",children:[rw("head",{children:[rw("meta",{charSet:"utf-8"},void 0,!1,void 0,this),rw("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"},void 0,!1,void 0,this),rw("title",{children:A.title},void 0,!1,void 0,this),rw("link",{rel:"preconnect",href:"https://fonts.googleapis.com"},void 0,!1,void 0,this),rw("link",{rel:"preconnect",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"},void 0,!1,void 0,this),rw("link",{href:t3w,rel:"stylesheet"},void 0,!1,void 0,this),A.themeCSS!==void 0&&rw("style",{"data-dashboard-theme":!0,dangerouslySetInnerHTML:{__html:A.themeCSS}},void 0,!1,void 0,this),rw("style",{"data-dashboard-styles":!0,dangerouslySetInnerHTML:{__html:$12}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),rw("body",{children:[rw("main",{class:"console","data-component":"dashboard:dashboard",children:[rw(Y12,{title:A.title,tagline:A.profile.description,operatorAccess:A.operatorAccess},void 0,!1,void 0,this),rw("section",{class:Y,children:[$&&rw("div",{class:"identity-column",children:[rw(Z12,{character:A.character},void 0,!1,void 0,this),rw(ss0,{interactions:f,baseUrl:A.baseUrl},void 0,!1,void 0,this),X&&A.operatorAccess&&rw(z12,{hiddenWidgetCount:A.operatorAccess.hiddenWidgetCount,loginUrl:A.operatorAccess.loginUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),rw("div",{class:"main-column",children:[rw(X12,{total:Q,entityCounts:w},void 0,!1,void 0,this),!$&&X&&A.operatorAccess&&rw(z12,{hiddenWidgetCount:A.operatorAccess.hiddenWidgetCount,loginUrl:A.operatorAccess.loginUrl},void 0,!1,void 0,this),B.primary.map((H)=>rw(KX0,{widget:H},`${H.widget.pluginId}:${H.widget.id}`,!1,void 0,this)),B.secondary.map((H)=>rw(KX0,{widget:H},`${H.widget.pluginId}:${H.widget.id}`,!1,void 0,this))]},void 0,!0,void 0,this),rw("div",{class:"sidebar-column",children:[!$&&rw(ss0,{interactions:f,baseUrl:A.baseUrl},void 0,!1,void 0,this),B.sidebar.map((H)=>rw(KX0,{widget:H},`${H.widget.pluginId}:${H.widget.id}`,!1,void 0,this)),rw(W12,{endpoints:A.appInfo.endpoints,baseUrl:A.baseUrl},void 0,!1,void 0,this),rw(D12,{appInfo:A.appInfo,now:W},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),rw(G12,{title:A.title,appInfo:A.appInfo,baseUrl:A.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),rw("script",{dangerouslySetInnerHTML:{__html:Azw}},void 0,!1,void 0,this),rw("script",{dangerouslySetInnerHTML:{__html:Qzw}},void 0,!1,void 0,this),A.widgetScripts.map((H,K)=>rw("script",{dangerouslySetInnerHTML:{__html:H}},`widget-script:${K}`,!1,void 0,this))]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function q12(A){return`<!doctype html>
8376
- ${a3w(rw(wzw,{input:A},void 0,!1,void 0,this))}`}function b12(A,Q){let w={},B=new Set;for(let[$,f]of Object.entries(A)){let Y=Q?.get(f.widget.pluginId,f.widget.id);if(w[$]={...f,...Y?.component?{component:Y.component}:{}},Y?.clientScript)B.add(Y.clientScript)}return{widgets:w,widgetScripts:Array.from(B)}}var V12={name:"@brains/dashboard",version:"0.2.0-alpha.142",description:"Dashboard plugin with extensible widget system",dependencies:{"@brains/auth-service":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2","preact-render-to-string":"^6.7.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var $zw=Z.object({version:Z.string().default("1.0.0"),routePath:Z.string().default("/dashboard"),themeCSS:Z.string().optional()}),fzw=Z.object({id:Z.string(),pluginId:Z.string(),title:Z.string(),description:Z.string().optional(),priority:Z.number().default(50),section:Z.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:Z.string(),visibility:Z.enum(["public","trusted","anchor"]).default("public"),component:Z.custom().optional(),clientScript:Z.string().optional(),dataProvider:Z.custom((A)=>typeof A==="function",{message:"Expected dashboard widget data provider function"})}).superRefine((A,Q)=>{if(!os0(A.rendererName)&&!A.component)Q.addIssue({code:"custom",message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),Yzw=Z.object({pluginId:Z.string(),widgetId:Z.string().optional()});function Xzw(A){return{id:A.id,pluginId:A.pluginId,title:A.title,...A.description?{description:A.description}:{},priority:A.priority,section:A.section,rendererName:A.rendererName,visibility:A.visibility,...A.component?{component:A.component}:{},...A.clientScript?{clientScript:A.clientScript}:{},dataProvider:A.dataProvider}}class ts0 extends aQ{widgetRegistry=null;datasource=null;siteUrl;ctx;constructor(A={}){super("dashboard",V12,A,$zw)}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new WX0(this.logger),this.datasource=new HX0(this.widgetRegistry,this.logger),A.entities.registerDataSource(this.datasource),A.endpoints.register({label:"Dashboard",url:this.config.routePath,priority:30,visibility:"public"}),A.interactions.register({id:"dashboard",label:"Dashboard",description:"Inspect runtime status, endpoints, and dashboard widgets.",href:this.config.routePath,kind:"admin",priority:30,visibility:"public"}),A.messaging.subscribe("dashboard:register-widget",async(Q)=>{try{let w=fzw.parse(Q.payload),B=Xzw(w);return this.widgetRegistry?.register(B),this.logger.debug("Widget registered via messaging",{widgetId:w.id,pluginId:w.pluginId,rendererName:w.rendererName,builtIn:ZX0.includes(w.rendererName)}),{success:!0}}catch(w){return this.logger.error("Failed to register widget",{error:mA(w),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{try{let w=Yzw.parse(Q.payload);return this.widgetRegistry?.unregister(w.pluginId,w.widgetId),this.logger.debug("Widget unregistered via messaging",{pluginId:w.pluginId,widgetId:w.widgetId}),{success:!0}}catch(w){return this.logger.error("Failed to unregister widget",{error:mA(w),payload:Q.payload}),{success:!1,error:"Widget unregistration failed"}}}),this.logger.info("Dashboard plugin registered")}getWebRoutes(){return[{path:this.config.routePath,method:"GET",public:!0,handler:async(A)=>{if(!this.datasource||!this.ctx)return new Response("Dashboard unavailable",{status:503,headers:{"Content-Type":"text/plain; charset=utf-8"}});let Q=this.ctx,w=await P7()?.getOperatorSession(A),B=Boolean(w),$=B?"anchor":"public",f=this.widgetRegistry?.list({permissionLevel:"anchor"})??[],Y=f.filter((x)=>A9.hasPermission($,x.visibility)),X=f.length-Y.length,[W,H]=await Promise.all([this.datasource.getDashboardData({permissionLevel:$,widgets:Y}),Q.appInfo()]),K=Q.identity.get(),U=Q.identity.getProfile(),D=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),q={...H,endpoints:H.endpoints.filter((x)=>A9.hasPermission($,x.visibility)),interactions:H.interactions.filter((x)=>A9.hasPermission($,x.visibility))},b=U.name||H.model||"Brain Dashboard",I=new URL(A.url),V=`${I.pathname}${I.search}`,L=encodeURIComponent(V),N=b12(W.widgets,this.widgetRegistry),k={title:b,baseUrl:D,widgets:N.widgets,widgetScripts:N.widgetScripts,character:K,profile:U,appInfo:q,...this.config.themeCSS!==void 0&&{themeCSS:this.config.themeCSS},operatorAccess:{isOperator:B,hiddenWidgetCount:X,loginUrl:`/login?return_to=${L}`,logoutUrl:`/logout?return_to=${L}`}};return new Response(q12(k),{headers:{"Content-Type":"text/html; charset=utf-8"}})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function hF(A={}){return new ts0(A)}N0();var Zzw=Z.enum(["public","trusted","anchor"]),Wzw=Z.object({id:Z.string(),pluginId:Z.string(),title:Z.string(),description:Z.string().optional(),priority:Z.number(),section:Z.enum(["primary","secondary","sidebar"]),rendererName:Z.string(),visibility:Zzw,component:Z.custom().optional()}),Hzw=Z.object({widget:Wzw,data:Z.unknown()}),Kzw=Z.object({widgets:Z.record(Z.string(),Hzw)});wA();N0();wA();N0();import{h as Ozw}from"preact";wA();xX();K2();N0();var UX0=Z.enum(["generating","draft","queued","published","failed"]),Uzw=Z.enum(["generating","draft","queued","published","failed"]),DX0=Z.object({subject:Z.string(),status:UX0,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional()}),I12=Z.object({subject:Z.string(),status:UX0,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional(),error:Z.string().optional()}),Dzw=Z.object({subject:Z.string(),status:Uzw,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional(),error:Z.string().optional()}),Ly=LQ.extend({entityType:Z.literal("newsletter"),metadata:Dzw});wA();class J12 extends C2{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:Ly,frontmatterSchema:DX0})}toMarkdown(A){let Q=this.extractBody(A.content);return this.buildMarkdown(Q,A.metadata)}fromMarkdown(A){let Q=this.parseFrontmatter(A);return{entityType:"newsletter",content:A,metadata:Q}}buildStub(A){let Q={subject:A.title,status:"generating"};return{content:this.buildMarkdown("",Q),metadata:Q}}}var F12=new J12;wA();wA();K2();N0();var Gzw=Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional(),baseUrl:Z.string().optional(),status:Z.enum(["generating","draft","queued","published","failed"]).optional()}),zzw=Z.looseObject({entityType:Z.string().optional(),query:Gzw.optional()});function L12(A){try{let{content:Q}=o2(A.content,DX0);return Q}catch{return A.content}}class es0 extends q5{id="newsletter:entities";name="Newsletter Entity DataSource";description="Fetches and transforms newsletter entities for rendering";config={entityType:"newsletter",defaultSort:[{field:"created",direction:"desc"}],defaultLimit:10,lookupField:"id",enableNavigation:!0};constructor(A){super(A);this.logger.debug("NewsletterDataSource initialized")}parseQuery(A){let Q=zzw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=L12(A),w={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:Gf(Q,150),created:A.created,url:`/newsletters/${A.id}`};if(A.metadata.sentAt)w.sentAt=A.metadata.sentAt;return w}buildListResult(A,Q,w){return{newsletters:A,totalCount:Q?.totalItems??A.length,pagination:Q}}async fetch(A,Q,w){let{query:B}=this.parseQuery(A),$=w.entityService;if(B.id)return this.fetchSingleNewsletter(B.id,Q,$);let f=B.status,Y=f?{filter:{metadata:{status:f}}}:void 0,{items:X,pagination:W}=await this.fetchList(B,$,Y);return Q.parse(this.buildListResult(X,W,B))}async fetchSingleNewsletter(A,Q,w){let B=await w.getEntity({entityType:this.config.entityType,id:A});if(!B)throw Error(`Newsletter not found: ${A}`);let $=await this.resolveNavigation(B,w),f=[];if(B.metadata.entityIds?.length){let W=B.metadata.sourceEntityType??"post";f=(await Promise.all(B.metadata.entityIds.map(async(K)=>{let U=await w.getEntity({entityType:W,id:K});if(U){let D=U.metadata;return{id:K,title:D.title??K,url:`/${W}s/${D.slug??K}`}}return null}))).filter((K)=>K!==null)}let Y=L12(B),X={id:B.id,subject:B.metadata.subject,status:B.metadata.status,content:Y,created:B.created,updated:B.updated,sentAt:B.metadata.sentAt,scheduledFor:B.metadata.scheduledFor,newsletter:B,prevNewsletter:$.prev?{id:$.prev.id,subject:$.prev.subject,url:$.prev.url}:null,nextNewsletter:$.next?{id:$.next.id,subject:$.next.subject,url:$.next.url}:null,sourceEntities:f.length>0?f:void 0};return Q.parse(X)}}wA();K2();N0();var qzw=Z.object({prompt:Z.string().optional().describe("AI generation prompt"),sourceEntityIds:Z.array(Z.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:Z.enum(["post"]).optional().describe("Type of source entities"),content:Z.string().optional().describe("Direct content (skip AI)"),subject:Z.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:Z.boolean().optional().describe("Create as queued (true) or draft (false)")});class Aa0 extends z4{constructor(A,Q){super(A,Q,{schema:qzw,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let w=A.addToQueue??!1,{prompt:B,sourceEntityIds:$,sourceEntityType:f}=A,{content:Y,subject:X}=A;if(Y){if(!X)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if($&&$.length>0){let D=f??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${$.length} source entities`});let b=(await Promise.all($.map((k)=>this.context.entityService.getEntity({entityType:D,id:k})))).filter((k)=>k!=null);if(b.length===0)this.failEarly(`No source entities found for IDs: ${$.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${b.length} posts`});let V=`Create an engaging newsletter that highlights these blog posts:
8376
+ ${a3w(rw(wzw,{input:A},void 0,!1,void 0,this))}`}function b12(A,Q){let w={},B=new Set;for(let[$,f]of Object.entries(A)){let Y=Q?.get(f.widget.pluginId,f.widget.id);if(w[$]={...f,...Y?.component?{component:Y.component}:{}},Y?.clientScript)B.add(Y.clientScript)}return{widgets:w,widgetScripts:Array.from(B)}}var V12={name:"@brains/dashboard",version:"0.2.0-alpha.143",description:"Dashboard plugin with extensible widget system",dependencies:{"@brains/auth-service":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2","preact-render-to-string":"^6.7.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var $zw=Z.object({version:Z.string().default("1.0.0"),routePath:Z.string().default("/dashboard"),themeCSS:Z.string().optional()}),fzw=Z.object({id:Z.string(),pluginId:Z.string(),title:Z.string(),description:Z.string().optional(),priority:Z.number().default(50),section:Z.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:Z.string(),visibility:Z.enum(["public","trusted","anchor"]).default("public"),component:Z.custom().optional(),clientScript:Z.string().optional(),dataProvider:Z.custom((A)=>typeof A==="function",{message:"Expected dashboard widget data provider function"})}).superRefine((A,Q)=>{if(!os0(A.rendererName)&&!A.component)Q.addIssue({code:"custom",message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),Yzw=Z.object({pluginId:Z.string(),widgetId:Z.string().optional()});function Xzw(A){return{id:A.id,pluginId:A.pluginId,title:A.title,...A.description?{description:A.description}:{},priority:A.priority,section:A.section,rendererName:A.rendererName,visibility:A.visibility,...A.component?{component:A.component}:{},...A.clientScript?{clientScript:A.clientScript}:{},dataProvider:A.dataProvider}}class ts0 extends aQ{widgetRegistry=null;datasource=null;siteUrl;ctx;constructor(A={}){super("dashboard",V12,A,$zw)}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new WX0(this.logger),this.datasource=new HX0(this.widgetRegistry,this.logger),A.entities.registerDataSource(this.datasource),A.endpoints.register({label:"Dashboard",url:this.config.routePath,priority:30,visibility:"public"}),A.interactions.register({id:"dashboard",label:"Dashboard",description:"Inspect runtime status, endpoints, and dashboard widgets.",href:this.config.routePath,kind:"admin",priority:30,visibility:"public"}),A.messaging.subscribe("dashboard:register-widget",async(Q)=>{try{let w=fzw.parse(Q.payload),B=Xzw(w);return this.widgetRegistry?.register(B),this.logger.debug("Widget registered via messaging",{widgetId:w.id,pluginId:w.pluginId,rendererName:w.rendererName,builtIn:ZX0.includes(w.rendererName)}),{success:!0}}catch(w){return this.logger.error("Failed to register widget",{error:mA(w),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{try{let w=Yzw.parse(Q.payload);return this.widgetRegistry?.unregister(w.pluginId,w.widgetId),this.logger.debug("Widget unregistered via messaging",{pluginId:w.pluginId,widgetId:w.widgetId}),{success:!0}}catch(w){return this.logger.error("Failed to unregister widget",{error:mA(w),payload:Q.payload}),{success:!1,error:"Widget unregistration failed"}}}),this.logger.info("Dashboard plugin registered")}getWebRoutes(){return[{path:this.config.routePath,method:"GET",public:!0,handler:async(A)=>{if(!this.datasource||!this.ctx)return new Response("Dashboard unavailable",{status:503,headers:{"Content-Type":"text/plain; charset=utf-8"}});let Q=this.ctx,w=await P7()?.getOperatorSession(A),B=Boolean(w),$=B?"anchor":"public",f=this.widgetRegistry?.list({permissionLevel:"anchor"})??[],Y=f.filter((x)=>A9.hasPermission($,x.visibility)),X=f.length-Y.length,[W,H]=await Promise.all([this.datasource.getDashboardData({permissionLevel:$,widgets:Y}),Q.appInfo()]),K=Q.identity.get(),U=Q.identity.getProfile(),D=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),q={...H,endpoints:H.endpoints.filter((x)=>A9.hasPermission($,x.visibility)),interactions:H.interactions.filter((x)=>A9.hasPermission($,x.visibility))},b=U.name||H.model||"Brain Dashboard",I=new URL(A.url),V=`${I.pathname}${I.search}`,L=encodeURIComponent(V),N=b12(W.widgets,this.widgetRegistry),k={title:b,baseUrl:D,widgets:N.widgets,widgetScripts:N.widgetScripts,character:K,profile:U,appInfo:q,...this.config.themeCSS!==void 0&&{themeCSS:this.config.themeCSS},operatorAccess:{isOperator:B,hiddenWidgetCount:X,loginUrl:`/login?return_to=${L}`,logoutUrl:`/logout?return_to=${L}`}};return new Response(q12(k),{headers:{"Content-Type":"text/html; charset=utf-8"}})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function hF(A={}){return new ts0(A)}N0();var Zzw=Z.enum(["public","trusted","anchor"]),Wzw=Z.object({id:Z.string(),pluginId:Z.string(),title:Z.string(),description:Z.string().optional(),priority:Z.number(),section:Z.enum(["primary","secondary","sidebar"]),rendererName:Z.string(),visibility:Zzw,component:Z.custom().optional()}),Hzw=Z.object({widget:Wzw,data:Z.unknown()}),Kzw=Z.object({widgets:Z.record(Z.string(),Hzw)});wA();N0();wA();N0();import{h as Ozw}from"preact";wA();xX();K2();N0();var UX0=Z.enum(["generating","draft","queued","published","failed"]),Uzw=Z.enum(["generating","draft","queued","published","failed"]),DX0=Z.object({subject:Z.string(),status:UX0,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional()}),I12=Z.object({subject:Z.string(),status:UX0,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional(),error:Z.string().optional()}),Dzw=Z.object({subject:Z.string(),status:Uzw,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional(),error:Z.string().optional()}),Ly=LQ.extend({entityType:Z.literal("newsletter"),metadata:Dzw});wA();class J12 extends C2{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:Ly,frontmatterSchema:DX0})}toMarkdown(A){let Q=this.extractBody(A.content);return this.buildMarkdown(Q,A.metadata)}fromMarkdown(A){let Q=this.parseFrontmatter(A);return{entityType:"newsletter",content:A,metadata:Q}}buildStub(A){let Q={subject:A.title,status:"generating"};return{content:this.buildMarkdown("",Q),metadata:Q}}}var F12=new J12;wA();wA();K2();N0();var Gzw=Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional(),baseUrl:Z.string().optional(),status:Z.enum(["generating","draft","queued","published","failed"]).optional()}),zzw=Z.looseObject({entityType:Z.string().optional(),query:Gzw.optional()});function L12(A){try{let{content:Q}=o2(A.content,DX0);return Q}catch{return A.content}}class es0 extends q5{id="newsletter:entities";name="Newsletter Entity DataSource";description="Fetches and transforms newsletter entities for rendering";config={entityType:"newsletter",defaultSort:[{field:"created",direction:"desc"}],defaultLimit:10,lookupField:"id",enableNavigation:!0};constructor(A){super(A);this.logger.debug("NewsletterDataSource initialized")}parseQuery(A){let Q=zzw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=L12(A),w={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:Gf(Q,150),created:A.created,url:`/newsletters/${A.id}`};if(A.metadata.sentAt)w.sentAt=A.metadata.sentAt;return w}buildListResult(A,Q,w){return{newsletters:A,totalCount:Q?.totalItems??A.length,pagination:Q}}async fetch(A,Q,w){let{query:B}=this.parseQuery(A),$=w.entityService;if(B.id)return this.fetchSingleNewsletter(B.id,Q,$);let f=B.status,Y=f?{filter:{metadata:{status:f}}}:void 0,{items:X,pagination:W}=await this.fetchList(B,$,Y);return Q.parse(this.buildListResult(X,W,B))}async fetchSingleNewsletter(A,Q,w){let B=await w.getEntity({entityType:this.config.entityType,id:A});if(!B)throw Error(`Newsletter not found: ${A}`);let $=await this.resolveNavigation(B,w),f=[];if(B.metadata.entityIds?.length){let W=B.metadata.sourceEntityType??"post";f=(await Promise.all(B.metadata.entityIds.map(async(K)=>{let U=await w.getEntity({entityType:W,id:K});if(U){let D=U.metadata;return{id:K,title:D.title??K,url:`/${W}s/${D.slug??K}`}}return null}))).filter((K)=>K!==null)}let Y=L12(B),X={id:B.id,subject:B.metadata.subject,status:B.metadata.status,content:Y,created:B.created,updated:B.updated,sentAt:B.metadata.sentAt,scheduledFor:B.metadata.scheduledFor,newsletter:B,prevNewsletter:$.prev?{id:$.prev.id,subject:$.prev.subject,url:$.prev.url}:null,nextNewsletter:$.next?{id:$.next.id,subject:$.next.subject,url:$.next.url}:null,sourceEntities:f.length>0?f:void 0};return Q.parse(X)}}wA();K2();N0();var qzw=Z.object({prompt:Z.string().optional().describe("AI generation prompt"),sourceEntityIds:Z.array(Z.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:Z.enum(["post"]).optional().describe("Type of source entities"),content:Z.string().optional().describe("Direct content (skip AI)"),subject:Z.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:Z.boolean().optional().describe("Create as queued (true) or draft (false)")});class Aa0 extends z4{constructor(A,Q){super(A,Q,{schema:qzw,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let w=A.addToQueue??!1,{prompt:B,sourceEntityIds:$,sourceEntityType:f}=A,{content:Y,subject:X}=A;if(Y){if(!X)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if($&&$.length>0){let D=f??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${$.length} source entities`});let b=(await Promise.all($.map((k)=>this.context.entityService.getEntity({entityType:D,id:k})))).filter((k)=>k!=null);if(b.length===0)this.failEarly(`No source entities found for IDs: ${$.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${b.length} posts`});let V=`Create an engaging newsletter that highlights these blog posts:
8377
8377
 
8378
8378
  ${b.map((k)=>`## ${k.metadata.title}
8379
8379
 
@@ -8442,17 +8442,17 @@ Newsletter-specific guidelines:
8442
8442
  - "Reply and let me know..."
8443
8443
  - "Until next time..."
8444
8444
 
8445
- The goal is to build a relationship with readers through valuable, authentic content.`});N0();wA();import{jsxDEV as sf,Fragment as Lzw}from"preact/jsx-dev-runtime";var Vzw=Z.enum(["generating","draft","queued","published","failed"]),Izw=Z.object({id:Z.string(),subject:Z.string(),status:Vzw,excerpt:Z.string(),created:Z.string(),sentAt:Z.string().optional(),url:Z.string()}),Jzw=Z.object({newsletters:Z.array(Izw),totalCount:Z.number(),pagination:KA0.nullable()}),Fzw=({newsletters:A,totalCount:Q,pageTitle:w,pagination:B,baseUrl:$="/newsletters"})=>{let f=w??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return sf(Lzw,{children:[sf(lQ,{title:f,description:Y},void 0,!1,void 0,this),sf("div",{className:"newsletter-list bg-theme",children:sf("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[sf("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:f},void 0,!1,void 0,this),A.length===0?sf("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):sf("div",{className:"space-y-4",children:A.map((X)=>sf(U6,{href:X.url,children:[sf($7,{className:"text-lg",children:X.subject},void 0,!1,void 0,this),sf(C7,{children:sf("div",{className:"flex items-center gap-3",children:[sf(pY,{status:X.status},void 0,!1,void 0,this),sf("span",{className:"text-sm text-theme-muted",children:L8(X.sentAt??X.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),X.excerpt&&sf("p",{className:"text-theme-muted line-clamp-2",children:X.excerpt},void 0,!1,void 0,this)]},X.id,!0,void 0,this))},void 0,!1,void 0,this),B&&B.totalPages>1&&sf(iq,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},_12=i1({name:"newsletter-list",description:"Newsletter list page template",schema:Jzw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:Fzw}});N0();wA();import{jsxDEV as oB,Fragment as Pzw}from"preact/jsx-dev-runtime";var kzw=Z.enum(["generating","draft","queued","published","failed"]),_zw=Z.object({id:Z.string(),title:Z.string(),url:Z.string()}),N12=Z.object({id:Z.string(),subject:Z.string(),url:Z.string()}),Nzw=Z.object({id:Z.string(),subject:Z.string(),status:kzw,content:Z.string(),created:Z.string(),updated:Z.string(),sentAt:Z.string().optional(),scheduledFor:Z.string().optional(),sourceEntities:Z.array(_zw).optional(),prevNewsletter:N12.nullable().optional(),nextNewsletter:N12.nullable().optional()}),jzw=({subject:A,status:Q,content:w,created:B,sentAt:$,scheduledFor:f,sourceEntities:Y,prevNewsletter:X,nextNewsletter:W})=>{let H=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],K=$??B,U=$?"Sent":"Created";return oB(Pzw,{children:[oB(lQ,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),oB("section",{className:"newsletter-detail-section",children:oB("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:oB("div",{className:"max-w-3xl mx-auto",children:[oB(vG,{items:H},void 0,!1,void 0,this),oB("h1",{className:"text-3xl md:text-4xl font-bold text-heading leading-tight tracking-tight mb-4",children:A},void 0,!1,void 0,this),oB("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[oB(pY,{status:Q},void 0,!1,void 0,this),oB("span",{children:[U,": ",L8(K,{style:"long"})]},void 0,!0,void 0,this),f&&Q==="queued"&&oB("span",{children:["Scheduled for: ",L8(f,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&oB(U6,{variant:"compact",className:"mb-8",children:[oB("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),oB("ul",{className:"space-y-1",children:Y.map((D)=>oB("li",{children:oB("a",{href:D.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:D.title},void 0,!1,void 0,this)},D.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),oB(V9,{markdown:w},void 0,!1,void 0,this),(X??W)&&oB("nav",{className:"mt-12 pt-8 border-t border-theme",children:oB("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[X?oB(U6,{href:X.url,variant:"compact",children:[oB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),oB("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:X.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this):oB("div",{},void 0,!1,void 0,this),W&&oB(U6,{href:W.url,variant:"compact",className:"md:text-right",children:[oB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),oB("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:W.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},j12=i1({name:"newsletter-detail",description:"Individual newsletter detail template",schema:Nzw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:jzw}});var GX0={name:"@brains/newsletter",version:"0.2.0-alpha.142",description:"Newsletter composite \u2014 bundles the newsletter entity with the buttondown service plugin",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var xzw=Z.looseObject({}),Rzw=Z.object({prompt:Z.string().optional(),content:Z.string().optional()});class zX0 extends nQ{entityType="newsletter";schema=Ly;adapter=F12;constructor(A={}){super("newsletter",GX0,A,xzw)}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}createGenerationHandler(A){return new Aa0(this.logger,A)}getTemplates(){return{generation:k12,"newsletter-list":_12,"newsletter-detail":j12}}getDataSources(){return[new es0(this.logger.child("NewsletterDataSource"))]}async onRegister(A){this.deferPublishRegistration(A),this.subscribeToGenerateExecute(A),this.registerEvalHandlers(A),A.messaging.subscribe("system:plugins:ready",async()=>{let Q=await A.messaging.send({type:"buttondown:is-configured",payload:{}});if(!("noop"in Q)&&Q.success)await A.messaging.send({type:"plugin:site-builder:slot:register",payload:{pluginId:this.id,slotName:"footer-top",render:()=>Ozw($i0,{variant:"inline"})}});return{success:!0}}),this.logger.debug("Newsletter plugin registered")}deferPublishRegistration(A){let Q={name:"internal",publish:async(w,B)=>{let $=typeof B.subject==="string"?B.subject:"",f=await A.messaging.send({type:"buttondown:send",payload:{entityId:"",subject:$,content:w}});return{id:!("noop"in f)&&f.data?.emailId?f.data.emailId:"internal"}}};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"newsletter",provider:Q,config:{publishResultIdField:"buttondownId",publishTimestampField:"sentAt"}}}),{success:!0}})}subscribeToGenerateExecute(A){A.messaging.subscribe("generate:execute",async(Q)=>{if(Q.payload.entityType!=="newsletter")return{success:!0};try{let w=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:10}});if(w.length===0)return await A.messaging.send({type:"generate:report:failure",payload:{entityType:"newsletter",error:"No published posts available for newsletter"}}),{success:!0};return await A.jobs.enqueue({type:"newsletter:generation",data:{sourceEntityIds:w.map((B)=>B.id),sourceEntityType:"post",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}}),{success:!0}}catch(w){return await A.messaging.send({type:"generate:report:failure",payload:{entityType:"newsletter",error:mA(w)}}),{success:!0}}})}registerEvalHandlers(A){A.eval.registerHandler("generation",async(Q)=>{let w=Rzw.parse(Q),B=w.content?`Create an engaging newsletter based on this content:
8445
+ The goal is to build a relationship with readers through valuable, authentic content.`});N0();wA();import{jsxDEV as sf,Fragment as Lzw}from"preact/jsx-dev-runtime";var Vzw=Z.enum(["generating","draft","queued","published","failed"]),Izw=Z.object({id:Z.string(),subject:Z.string(),status:Vzw,excerpt:Z.string(),created:Z.string(),sentAt:Z.string().optional(),url:Z.string()}),Jzw=Z.object({newsletters:Z.array(Izw),totalCount:Z.number(),pagination:KA0.nullable()}),Fzw=({newsletters:A,totalCount:Q,pageTitle:w,pagination:B,baseUrl:$="/newsletters"})=>{let f=w??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return sf(Lzw,{children:[sf(lQ,{title:f,description:Y},void 0,!1,void 0,this),sf("div",{className:"newsletter-list bg-theme",children:sf("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[sf("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:f},void 0,!1,void 0,this),A.length===0?sf("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):sf("div",{className:"space-y-4",children:A.map((X)=>sf(U6,{href:X.url,children:[sf($7,{className:"text-lg",children:X.subject},void 0,!1,void 0,this),sf(C7,{children:sf("div",{className:"flex items-center gap-3",children:[sf(pY,{status:X.status},void 0,!1,void 0,this),sf("span",{className:"text-sm text-theme-muted",children:L8(X.sentAt??X.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),X.excerpt&&sf("p",{className:"text-theme-muted line-clamp-2",children:X.excerpt},void 0,!1,void 0,this)]},X.id,!0,void 0,this))},void 0,!1,void 0,this),B&&B.totalPages>1&&sf(iq,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},_12=i1({name:"newsletter-list",description:"Newsletter list page template",schema:Jzw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:Fzw}});N0();wA();import{jsxDEV as oB,Fragment as Pzw}from"preact/jsx-dev-runtime";var kzw=Z.enum(["generating","draft","queued","published","failed"]),_zw=Z.object({id:Z.string(),title:Z.string(),url:Z.string()}),N12=Z.object({id:Z.string(),subject:Z.string(),url:Z.string()}),Nzw=Z.object({id:Z.string(),subject:Z.string(),status:kzw,content:Z.string(),created:Z.string(),updated:Z.string(),sentAt:Z.string().optional(),scheduledFor:Z.string().optional(),sourceEntities:Z.array(_zw).optional(),prevNewsletter:N12.nullable().optional(),nextNewsletter:N12.nullable().optional()}),jzw=({subject:A,status:Q,content:w,created:B,sentAt:$,scheduledFor:f,sourceEntities:Y,prevNewsletter:X,nextNewsletter:W})=>{let H=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],K=$??B,U=$?"Sent":"Created";return oB(Pzw,{children:[oB(lQ,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),oB("section",{className:"newsletter-detail-section",children:oB("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:oB("div",{className:"max-w-3xl mx-auto",children:[oB(vG,{items:H},void 0,!1,void 0,this),oB("h1",{className:"text-3xl md:text-4xl font-bold text-heading leading-tight tracking-tight mb-4",children:A},void 0,!1,void 0,this),oB("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[oB(pY,{status:Q},void 0,!1,void 0,this),oB("span",{children:[U,": ",L8(K,{style:"long"})]},void 0,!0,void 0,this),f&&Q==="queued"&&oB("span",{children:["Scheduled for: ",L8(f,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&oB(U6,{variant:"compact",className:"mb-8",children:[oB("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),oB("ul",{className:"space-y-1",children:Y.map((D)=>oB("li",{children:oB("a",{href:D.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:D.title},void 0,!1,void 0,this)},D.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),oB(V9,{markdown:w},void 0,!1,void 0,this),(X??W)&&oB("nav",{className:"mt-12 pt-8 border-t border-theme",children:oB("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[X?oB(U6,{href:X.url,variant:"compact",children:[oB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),oB("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:X.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this):oB("div",{},void 0,!1,void 0,this),W&&oB(U6,{href:W.url,variant:"compact",className:"md:text-right",children:[oB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),oB("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:W.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},j12=i1({name:"newsletter-detail",description:"Individual newsletter detail template",schema:Nzw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:jzw}});var GX0={name:"@brains/newsletter",version:"0.2.0-alpha.143",description:"Newsletter composite \u2014 bundles the newsletter entity with the buttondown service plugin",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var xzw=Z.looseObject({}),Rzw=Z.object({prompt:Z.string().optional(),content:Z.string().optional()});class zX0 extends nQ{entityType="newsletter";schema=Ly;adapter=F12;constructor(A={}){super("newsletter",GX0,A,xzw)}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}createGenerationHandler(A){return new Aa0(this.logger,A)}getTemplates(){return{generation:k12,"newsletter-list":_12,"newsletter-detail":j12}}getDataSources(){return[new es0(this.logger.child("NewsletterDataSource"))]}async onRegister(A){this.deferPublishRegistration(A),this.subscribeToGenerateExecute(A),this.registerEvalHandlers(A),A.messaging.subscribe("system:plugins:ready",async()=>{let Q=await A.messaging.send({type:"buttondown:is-configured",payload:{}});if(!("noop"in Q)&&Q.success)await A.messaging.send({type:"plugin:site-builder:slot:register",payload:{pluginId:this.id,slotName:"footer-top",render:()=>Ozw($i0,{variant:"inline"})}});return{success:!0}}),this.logger.debug("Newsletter plugin registered")}deferPublishRegistration(A){let Q={name:"internal",publish:async(w,B)=>{let $=typeof B.subject==="string"?B.subject:"",f=await A.messaging.send({type:"buttondown:send",payload:{entityId:"",subject:$,content:w}});return{id:!("noop"in f)&&f.data?.emailId?f.data.emailId:"internal"}}};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"newsletter",provider:Q,config:{publishResultIdField:"buttondownId",publishTimestampField:"sentAt"}}}),{success:!0}})}subscribeToGenerateExecute(A){A.messaging.subscribe("generate:execute",async(Q)=>{if(Q.payload.entityType!=="newsletter")return{success:!0};try{let w=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:10}});if(w.length===0)return await A.messaging.send({type:"generate:report:failure",payload:{entityType:"newsletter",error:"No published posts available for newsletter"}}),{success:!0};return await A.jobs.enqueue({type:"newsletter:generation",data:{sourceEntityIds:w.map((B)=>B.id),sourceEntityType:"post",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}}),{success:!0}}catch(w){return await A.messaging.send({type:"generate:report:failure",payload:{entityType:"newsletter",error:mA(w)}}),{success:!0}}})}registerEvalHandlers(A){A.eval.registerHandler("generation",async(Q)=>{let w=Rzw.parse(Q),B=w.content?`Create an engaging newsletter based on this content:
8446
8446
 
8447
8447
  ${w.content}`:w.prompt??"Write an engaging newsletter";return A.ai.generate({prompt:B,templateName:"newsletter:generation"})})}}function qX0(A={}){return new zX0(A)}wA();N0();N0();var hzw="https://api.buttondown.email/v1",Czw=Z.enum(["unactivated","regular","unsubscribed","already_subscribed"]),gzw=Z.enum(["draft","about_to_send","scheduled","sent"]),Qa0=Z.looseObject({id:Z.string(),email:Z.string(),subscriber_type:Czw,metadata:Z.record(Z.string(),Z.string()).optional()}),P12=Z.looseObject({id:Z.string(),subject:Z.string(),body:Z.string().optional(),status:gzw,publish_date:Z.string().optional()}),yzw=Z.looseObject({results:Z.array(Qa0),count:Z.number()}),Ezw=Z.looseObject({detail:Z.string().optional(),message:Z.string().optional(),code:Z.string().optional()});class wa0 extends Error{status;code;constructor(A,Q,w){super(A);this.name="ButtondownApiError",this.status=Q,this.code=w}}class UP{config;logger;constructor(A,Q){this.config=A,this.logger=Q}async request(A,Q={}){let w=`${hzw}${A}`;this.logger.debug("Buttondown API request",{endpoint:A,method:Q.method??"GET"});let B=await fetch(w,{...Q,headers:{Authorization:`Token ${this.config.apiKey}`,"Content-Type":"application/json",...Q.headers}});if(!B.ok){let $=await B.json().catch(()=>({})),f=Ezw.safeParse($),Y=f.success?f.data.detail??f.data.message??`HTTP ${B.status}`:`HTTP ${B.status}`,X=f.success?f.data.code:void 0;throw this.logger.error("Buttondown API error",{endpoint:A,status:B.status,code:X,error:Y}),new wa0(`Buttondown API error: ${Y}`,B.status,X)}return B.json()}async createSubscriber(A){let Q={email_address:A.email,type:this.config.doubleOptIn?"unactivated":"regular"};if(A.name)Q.metadata={name:A.name};if(A.tags&&A.tags.length>0)Q.tags=A.tags;this.logger.info("Creating subscriber",{email:A.email});try{return Qa0.parse(await this.request("/subscribers",{method:"POST",body:JSON.stringify(Q)}))}catch(w){if(w instanceof wa0&&w.code==="email_already_exists")return this.logger.info("Subscriber already exists",{email:A.email}),{...await this.getSubscriberByEmail(A.email),subscriber_type:"already_subscribed"};throw w}}async getSubscriberByEmail(A){return Qa0.parse(await this.request(`/subscribers/${encodeURIComponent(A)}`))}async unsubscribe(A){this.logger.info("Unsubscribing",{email:A}),await this.request(`/subscribers/${encodeURIComponent(A)}`,{method:"DELETE"})}async listSubscribers(A){let Q=new URLSearchParams;if(A?.type)Q.set("type",A.type);if(A?.limit)Q.set("page_size",String(A.limit));let w=Q.toString(),B=w?`/subscribers?${w}`:"/subscribers";return yzw.parse(await this.request(B))}async createEmail(A){let Q={subject:A.subject,body:A.body,status:A.status??"draft"};if(A.publish_date)Q.publish_date=A.publish_date;return this.logger.info("Creating email",{subject:A.subject,status:A.status??"draft"}),P12.parse(await this.request("/emails",{method:"POST",body:JSON.stringify(Q)}))}async getEmail(A){return P12.parse(await this.request(`/emails/${A}`))}async validateCredentials(){try{return await this.request("/subscribers?page_size=1"),!0}catch{return!1}}}wA();N0();var Tzw=Z.object({email:Z.string().email().describe("Email address to subscribe"),name:Z.string().optional().describe("Subscriber name (optional)"),tags:Z.array(Z.string()).optional().describe("Tags to apply to subscriber (optional)")}),Szw=Z.object({email:Z.string().email().describe("Email address to unsubscribe")}),mzw=Z.object({type:Z.enum(["unactivated","regular","unsubscribed"]).optional().describe("Filter by subscriber status"),limit:Z.number().optional().describe("Maximum number of results")});function M12(A,Q,w){let B=new UP(Q,w);return[P6(A,"subscribe","Subscribe an email address to the newsletter. Uses double opt-in by default.",Tzw,async($)=>{try{let f=await B.createSubscriber({email:$.email,...$.name&&{name:$.name},...$.tags&&{tags:$.tags}}),Y=f.subscriber_type==="already_subscribed";return z5({subscriberId:f.id,email:f.email,status:f.subscriber_type,message:Y?"already_subscribed":"subscribed"},Y?`${$.email} is already subscribed`:`Subscribed ${$.email} successfully`)}catch(f){return k7(mA(f))}}),P6(A,"unsubscribe","Unsubscribe an email address from the newsletter.",Szw,async($)=>{try{return await B.unsubscribe($.email),z5({email:$.email},`Unsubscribed ${$.email} successfully`)}catch(f){return k7(mA(f))}}),P6(A,"list_subscribers","List newsletter subscribers with optional filtering by status.",mzw,async($)=>{try{let f=await B.listSubscribers({...$.type&&{type:$.type},...$.limit&&{limit:$.limit}});return z5({subscribers:f.results.map((Y)=>({id:Y.id,email:Y.email,status:Y.subscriber_type})),count:f.count},`Found ${f.count} subscribers`)}catch(f){return k7(mA(f))}})]}async function O12(A,Q,w,B){if(A.entityType!=="post")return{success:!0,skipped:!0,reason:"Only post entity types trigger auto-send"};let $=await w.getEntity({entityType:"post",id:A.entityId});if(!$)return{success:!1,error:`Post ${A.entityId} not found`};B.info("Auto-sending newsletter for published post",{postId:$.id,title:$.metadata.title});try{let f=await Q.createEmail({subject:$.metadata.title,body:$.content,status:"about_to_send"});return B.info("Newsletter sent for post",{postId:$.id,emailId:f.id}),{success:!0,emailId:f.id}}catch(f){let Y=mA(f);return B.error("Failed to send newsletter for post",{postId:$.id,error:Y}),{success:!1,error:Y}}}var uzw=Z.object({apiKey:Z.string().optional().describe("Buttondown API key"),doubleOptIn:Z.boolean().default(!0).describe("Require email confirmation for new subscribers"),autoSendOnPublish:Z.boolean().default(!1).describe("Automatically send newsletter when a blog post is published")});class bX0 extends aQ{constructor(A={}){super("buttondown",GX0,A,uzw)}async onRegister(A){if(A.messaging.subscribe("buttondown:is-configured",async()=>{return{success:!!this.config.apiKey}}),this.config.apiKey){let Q=new UP({apiKey:this.config.apiKey,doubleOptIn:this.config.doubleOptIn},this.logger);if(A.messaging.subscribe("buttondown:send",async(w)=>{try{return{success:!0,data:{emailId:(await Q.createEmail({subject:w.payload.subject,body:w.payload.content,status:"about_to_send"})).id}}}catch(B){return this.logger.error("Buttondown send failed",{error:mA(B)}),{success:!1}}}),this.config.autoSendOnPublish)A.messaging.subscribe("publish:completed",async(w)=>{let B=await O12(w.payload,Q,A.entityService,this.logger);if(!B.success)return this.logger.error("Buttondown auto-send failed",{entityId:w.payload.entityId,error:B.error}),{success:!1,error:B.error};return{success:!0}}),this.logger.info("Buttondown auto-send on publish enabled")}}async getTools(){if(!this.config.apiKey)return[];return M12(this.id,{apiKey:this.config.apiKey,doubleOptIn:this.config.doubleOptIn},this.logger)}getApiRoutes(){if(!this.config.apiKey)return[];return[{path:"/subscribe",method:"POST",tool:"subscribe",public:!0,successRedirect:"/subscribe/thanks",errorRedirect:"/subscribe/error"}]}}function VX0(A={}){return new bX0(A)}var czw=Z.object({apiKey:Z.string().optional().describe("Buttondown API key"),doubleOptIn:Z.boolean().optional().describe("Require email confirmation for new subscribers"),autoSendOnPublish:Z.boolean().optional().describe("Automatically send newsletter when a blog post is published")});function x12(A={}){let Q=czw.safeParse(A);if(!Q.success)throw new s3("newsletter",Q.error.issues.map((B)=>({path:B.path.map(String).join("."),code:B.code,message:B.message})));let w=Q.data;return[qX0({}),VX0({...w.apiKey!==void 0&&{apiKey:w.apiKey},...w.doubleOptIn!==void 0&&{doubleOptIn:w.doubleOptIn},...w.autoSendOnPublish!==void 0&&{autoSendOnPublish:w.autoSendOnPublish}})]}wA();N0();import{existsSync as wqw,mkdirSync as Bqw,writeFileSync as $qw}from"fs";import{join as Kb}from"path";N0();var Ba0=Z.object({baseFolder:Z.string().default("_obsidian")});function $a0(A){return typeof A==="object"&&A!==null}function Mo(A){if(!$a0(A))return;let Q=A.def;return $a0(Q)?Q:void 0}function R12(A){let Q=Mo(A)?.type;return typeof Q==="string"?Q:void 0}function lzw(A){return typeof A==="function"?A():A}function pzw(A){let Q=A,w=!0,B=void 0,$=!1,f=!0;while(f){f=!1;let X=Mo(Q),W=R12(Q);if(W==="optional"||W==="nullable"){w=!1,Q=X?.innerType,f=!0;continue}if(W==="default")w=!1,$=!0,B=lzw(X?.defaultValue),Q=X?.innerType,f=!0}let Y={inner:Q,required:w};if($)Y.defaultValue=B;return Y}function izw(A){let w=Mo(A)?.entries;if(!$a0(w))return;let B=Object.values(w);if(!B.every(($)=>typeof $==="string"))return;return B}function dzw(A){let Q=Mo(A),w=Q?.values;if(Array.isArray(w))return w[0];return Q?.value}function v12(A){let Q=R12(A);if(Q==="enum"){let w=izw(A);return w?{type:"enum",enumValues:w}:{type:"enum"}}if(Q==="literal")return{type:"string",defaultValue:dzw(A)};if(Q==="string")return{type:"string"};if(Q==="number")return{type:"number"};if(Q==="boolean")return{type:"boolean"};if(Q==="array")return{type:"array"};if(Q==="date")return{type:"date"};if(Q==="pipeline"||Q==="pipe"){let w=Mo(A);return v12(w?.out)}return{type:"unknown"}}function h12(A){let Q=[];for(let[w,B]of Object.entries(A.shape)){let{inner:$,required:f,defaultValue:Y}=pzw(B),X=v12($),W={name:w,type:X.type,required:f},H=Y!==void 0?Y:X.defaultValue;if(H!==void 0)W.defaultValue=H;if(X.enumValues)W.enumValues=X.enumValues;Q.push(W)}return Q}function nzw(A,Q){if(A.name==="entityType")return String(A.defaultValue??Q);if(A.name==="title")return'"{{title}}"';if(A.type==="date"&&(A.name==="created"||A.name==="updated"))return'"{{date}}"';if(A.defaultValue!==void 0){if(Array.isArray(A.defaultValue))return"[]";if(typeof A.defaultValue==="boolean")return String(A.defaultValue);if(typeof A.defaultValue==="number")return String(A.defaultValue);return String(A.defaultValue)}if(A.type==="enum"&&A.enumValues&&A.enumValues.length>0)return A.enumValues[0]??"";switch(A.type){case"string":return'""';case"number":return"";case"boolean":return"false";case"array":return"[]";case"date":return'""';default:return'""'}}function C12(A,Q,w=""){let B=["---"];for(let $ of Q){let f=nzw($,A);if(f==="")B.push(`${$.name}:`);else B.push(`${$.name}: ${f}`)}if(B.push("---"),B.push(""),w)B.push(w);else B.push("<!-- Write your content here -->"),B.push("");return B.join(`
8448
8448
  `)}dk();var rzw={string:"Input",number:"Number",boolean:"Boolean",date:"Date",enum:"Select",array:"Multi",unknown:"Input"};function ozw(A){let Q={name:A.name,id:A.name,type:rzw[A.type]};if(A.type==="enum"&&A.enumValues){let w={};A.enumValues.forEach((B,$)=>{w[String($)]=B}),Q.options=w}return Q}function g12(A,Q){let w={filesPaths:A,fields:Q.map(ozw)};return`---
8449
8449
  ${tV(w)}---
8450
- `}K2();dk();var szw=new Set(["entityType"]),azw={base:"Notes"},tzw=new Set(["note"]);function ezw(A){let Q=["file.name"];for(let w of A)if(!szw.has(w.name))Q.push(w.name);return Q}function Aqw(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function y12(A,Q){let w=azw[A]??t5A(A),B=Aqw(Q),$=ezw(Q),f=[{type:"table",name:`All ${w}`,order:$}];if(B)f.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:$});let X={filters:{and:[tzw.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:f};return{filename:`${w}.base`,content:tV(X),hasStatus:B}}function E12(A){if(A.length===0)return null;let Q=A.map((B)=>`file.inFolder("${B}")`),w={filters:{and:[Q.length===1?Q[0]:{or:Q}]},views:[{type:"table",name:"Settings",order:["file.name","file.folder"]}]};return tV(w)}function T12(A){if(A.length===0)return null;let Q=A.map((B)=>`file.inFolder("${B.entityType}")`),w={filters:{and:[Q.length===1?Q[0]:{or:Q},'status != "published"']},views:[{type:"table",name:"Pipeline",groupBy:{property:"status",direction:"ASC"},order:["file.name","file.folder","status"]}]};return tV(w)}var S12={name:"@brains/obsidian-vault",version:"0.2.0-alpha.142",description:"Obsidian vault integration \u2014 generates templates from entity schemas",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var fqw={mkdir:Bqw,writeFile:$qw,existsFile:wqw},Yqw=Z.object({entityTypes:Z.array(Z.string()).optional().describe("Entity types to generate templates for (default: all)")});class fa0 extends aQ{deps;constructor(A={},Q={}){super("obsidian-vault",S12,A,Ba0);this.deps={...fqw,...Q}}async onReady(A){this.logger.info("Auto-syncing Obsidian templates, fileClasses, and bases"),await this.sync(A)}async getTools(){let A=this.getContext();return[P6(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",Yqw,async(Q)=>{return this.sync(A,Q.entityTypes)},{sideEffects:"external"})]}async sync(A,Q){try{let w=A.entityService.getEntityTypes(),B=Q?w.filter((V)=>Q.includes(V)):w,$=Kb(A.dataDir,this.config.baseFolder),f=Kb($,"templates"),Y=Kb($,"fileClasses"),X=Kb($,"bases");this.deps.mkdir(f,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0}),this.deps.mkdir(X,{recursive:!0});let W=[],H=[],K=[],U=[],D=[],q=[];for(let V of B){let L=A.entities.getEffectiveFrontmatterSchema(V);if(!L){this.logger.debug(`Skipping ${V}: no frontmatter schema`),H.push(V);continue}let N=h12(L),k=A.entities.getAdapter(V),x=k?.isSingleton===!0,R=g12(V,N);if(this.deps.writeFile(Kb(Y,`${V}.md`),R),K.push(V),x){D.push(V),this.logger.debug(`Generated fileClass (singleton): ${V}`);continue}let h=k?.getBodyTemplate()??"",P=C12(V,N,h);this.deps.writeFile(Kb(f,`${V}.md`),P),W.push(V);let E=y12(V,N),S=Kb(X,E.filename);if(!this.deps.existsFile(S))this.deps.writeFile(S,E.content),U.push(V),this.logger.debug(`Generated base: ${E.filename}`);if(E.hasStatus)q.push({entityType:V,fields:N});this.logger.debug(`Generated template + fileClass: ${V}`)}let b=E12(D);if(b){let V=Kb(X,"Settings.base");if(!this.deps.existsFile(V))this.deps.writeFile(V,b),U.push("Settings"),this.logger.debug("Generated Settings.base")}let I=T12(q);if(I){let V=Kb(X,"Pipeline.base");if(!this.deps.existsFile(V))this.deps.writeFile(V,I),U.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${W.length} templates, ${K.length} fileClasses, ${U.length} bases (${H.length} skipped)`),z5({generated:W,skipped:H,fileClasses:K,bases:U})}catch(w){return this.logger.error("Failed to sync",{error:w}),k7(w instanceof Error?w.message:"Unknown error")}}}function Ya0(A={},Q){return new fa0(A,Q)}g6();wA();wA();K2();o5();wA();N0();var IX0=Z.enum(["draft","active","archived"]),JX0=Z.enum(["anchor","trusted","public"]),FX0=Z.enum(["agent-confirmed","manual"]),Xqw=Z.enum(["draft","active","archived"]),Zqw=Z.enum(["anchor","trusted","public"]),Wqw=Z.enum(["agent-confirmed","manual"]),f3=Z.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,Z.string().min(1).optional()),Ub=Z.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,Z.string().min(1).optional()),Xa0=Z.object({event:Z.string().min(1),target:Z.string().min(1),operatorAction:Z.boolean().optional(),label:Ub,description:Ub,operatorDescription:Ub}),Za0=Z.object({id:Z.string().min(1),title:Z.string().min(1),prompt:Ub,requiredDetails:Z.array(Z.string().min(1)).default([]),instructions:Z.array(Z.string().min(1)).default([]),doneWhen:Z.array(Z.string().min(1)).default([]),transitions:Z.array(Xa0).default([])}),LX0=Z.object({purpose:Z.string().min(1),operatingRules:Z.array(Z.string().min(1)).default([]),initialState:Z.string().min(1),states:Z.array(Za0).min(1),finalStates:Z.array(Z.string().min(1)).min(1),nextPrompts:Z.array(Z.string().min(1)).default([])}),ky=Z.object({title:Z.string(),status:IX0.default("active"),audience:JX0.default("anchor"),trigger:f3.optional(),lifecycle:f3.optional(),once:Z.boolean().optional(),starterText:f3.optional(),description:f3.optional(),starterPrompt:f3.optional(),completionMode:FX0.default("agent-confirmed")}),m12=Z.object({title:Z.string(),status:IX0,audience:JX0,trigger:f3.optional(),lifecycle:f3.optional(),once:Z.boolean().optional(),starterText:f3.optional(),description:f3.optional(),starterPrompt:f3.optional(),completionMode:FX0}),Hqw=Z.object({title:Z.string(),status:Xqw,audience:Zqw,trigger:Ub.optional(),lifecycle:Ub.optional(),once:Z.boolean().optional(),starterText:Ub.optional(),description:Ub.optional(),starterPrompt:Ub.optional(),completionMode:Wqw}),_y=LQ.extend({entityType:Z.literal("playbook"),metadata:Hqw});class kX0 extends G6{constructor(){super(LX0,{title:"Playbook",mappings:[{key:"purpose",label:"Purpose",type:"string"},{key:"operatingRules",label:"Operating Rules",type:"array",itemType:"string"},{key:"initialState",label:"Initial State",type:"string"},{key:"states",label:"States",type:"array",itemType:"object",itemMappings:[{key:"id",label:"ID",type:"string"},{key:"title",label:"Title",type:"string"},{key:"prompt",label:"Prompt",type:"custom",formatter:Wa0,parser:Ha0},{key:"requiredDetails",label:"Required Details",type:"array",itemType:"string"},{key:"instructions",label:"Instructions",type:"array",itemType:"string"},{key:"doneWhen",label:"Done When",type:"array",itemType:"string"},{key:"transitions",label:"Transitions",type:"array",itemType:"object",itemMappings:[{key:"event",label:"Event",type:"string"},{key:"target",label:"Target",type:"string"},{key:"operatorAction",label:"User Choice",type:"custom",formatter:Kqw,parser:Uqw},{key:"label",label:"Label",type:"custom",formatter:Wa0,parser:Ha0},{key:"description",label:"Description",type:"string"},{key:"operatorDescription",label:"Operator Description",type:"custom",formatter:Wa0,parser:Ha0}]}]},{key:"finalStates",label:"Final States",type:"array",itemType:"string"},{key:"nextPrompts",label:"Next Prompts",type:"array",itemType:"string"}]})}}var Oo=new kX0;function Wa0(A){return typeof A==="string"?A:""}function Ha0(A){let Q=A.trim();return Q.length>0?Q:void 0}function Kqw(A){return typeof A==="boolean"?String(A):""}function Uqw(A){let Q=A.trim().toLowerCase();if(Q==="true")return!0;if(Q==="false")return!1;return}function Ka0(A){let Q=[],w=new Set,B=new Set;for(let $ of A.states){if(w.has($.id))B.add($.id);w.add($.id)}if(!w.has(A.initialState))Q.push(`Playbook initial state '${A.initialState}' is not defined.`);for(let $ of B)Q.push(`Duplicate playbook state id '${$}'.`);for(let $ of A.finalStates)if(!w.has($))Q.push(`Playbook final state '${$}' is not defined.`);for(let $ of A.states)for(let f of $.transitions)if(!w.has(f.target))Q.push(`Playbook transition '${$.id}' -> '${f.target}' targets an undefined state.`);for(let $ of Dqw(A,w))Q.push(`Playbook state '${$}' is unreachable.`);return{valid:Q.length===0,errors:Q}}function Ny(A){let Q=Ka0(A);if(!Q.valid)throw Error(Q.errors.join(`
8450
+ `}K2();dk();var szw=new Set(["entityType"]),azw={base:"Notes"},tzw=new Set(["note"]);function ezw(A){let Q=["file.name"];for(let w of A)if(!szw.has(w.name))Q.push(w.name);return Q}function Aqw(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function y12(A,Q){let w=azw[A]??t5A(A),B=Aqw(Q),$=ezw(Q),f=[{type:"table",name:`All ${w}`,order:$}];if(B)f.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:$});let X={filters:{and:[tzw.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:f};return{filename:`${w}.base`,content:tV(X),hasStatus:B}}function E12(A){if(A.length===0)return null;let Q=A.map((B)=>`file.inFolder("${B}")`),w={filters:{and:[Q.length===1?Q[0]:{or:Q}]},views:[{type:"table",name:"Settings",order:["file.name","file.folder"]}]};return tV(w)}function T12(A){if(A.length===0)return null;let Q=A.map((B)=>`file.inFolder("${B.entityType}")`),w={filters:{and:[Q.length===1?Q[0]:{or:Q},'status != "published"']},views:[{type:"table",name:"Pipeline",groupBy:{property:"status",direction:"ASC"},order:["file.name","file.folder","status"]}]};return tV(w)}var S12={name:"@brains/obsidian-vault",version:"0.2.0-alpha.143",description:"Obsidian vault integration \u2014 generates templates from entity schemas",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var fqw={mkdir:Bqw,writeFile:$qw,existsFile:wqw},Yqw=Z.object({entityTypes:Z.array(Z.string()).optional().describe("Entity types to generate templates for (default: all)")});class fa0 extends aQ{deps;constructor(A={},Q={}){super("obsidian-vault",S12,A,Ba0);this.deps={...fqw,...Q}}async onReady(A){this.logger.info("Auto-syncing Obsidian templates, fileClasses, and bases"),await this.sync(A)}async getTools(){let A=this.getContext();return[P6(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",Yqw,async(Q)=>{return this.sync(A,Q.entityTypes)},{sideEffects:"external"})]}async sync(A,Q){try{let w=A.entityService.getEntityTypes(),B=Q?w.filter((V)=>Q.includes(V)):w,$=Kb(A.dataDir,this.config.baseFolder),f=Kb($,"templates"),Y=Kb($,"fileClasses"),X=Kb($,"bases");this.deps.mkdir(f,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0}),this.deps.mkdir(X,{recursive:!0});let W=[],H=[],K=[],U=[],D=[],q=[];for(let V of B){let L=A.entities.getEffectiveFrontmatterSchema(V);if(!L){this.logger.debug(`Skipping ${V}: no frontmatter schema`),H.push(V);continue}let N=h12(L),k=A.entities.getAdapter(V),x=k?.isSingleton===!0,R=g12(V,N);if(this.deps.writeFile(Kb(Y,`${V}.md`),R),K.push(V),x){D.push(V),this.logger.debug(`Generated fileClass (singleton): ${V}`);continue}let h=k?.getBodyTemplate()??"",P=C12(V,N,h);this.deps.writeFile(Kb(f,`${V}.md`),P),W.push(V);let E=y12(V,N),S=Kb(X,E.filename);if(!this.deps.existsFile(S))this.deps.writeFile(S,E.content),U.push(V),this.logger.debug(`Generated base: ${E.filename}`);if(E.hasStatus)q.push({entityType:V,fields:N});this.logger.debug(`Generated template + fileClass: ${V}`)}let b=E12(D);if(b){let V=Kb(X,"Settings.base");if(!this.deps.existsFile(V))this.deps.writeFile(V,b),U.push("Settings"),this.logger.debug("Generated Settings.base")}let I=T12(q);if(I){let V=Kb(X,"Pipeline.base");if(!this.deps.existsFile(V))this.deps.writeFile(V,I),U.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${W.length} templates, ${K.length} fileClasses, ${U.length} bases (${H.length} skipped)`),z5({generated:W,skipped:H,fileClasses:K,bases:U})}catch(w){return this.logger.error("Failed to sync",{error:w}),k7(w instanceof Error?w.message:"Unknown error")}}}function Ya0(A={},Q){return new fa0(A,Q)}g6();wA();wA();K2();o5();wA();N0();var IX0=Z.enum(["draft","active","archived"]),JX0=Z.enum(["anchor","trusted","public"]),FX0=Z.enum(["agent-confirmed","manual"]),Xqw=Z.enum(["draft","active","archived"]),Zqw=Z.enum(["anchor","trusted","public"]),Wqw=Z.enum(["agent-confirmed","manual"]),f3=Z.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,Z.string().min(1).optional()),Ub=Z.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,Z.string().min(1).optional()),Xa0=Z.object({event:Z.string().min(1),target:Z.string().min(1),operatorAction:Z.boolean().optional(),label:Ub,description:Ub,operatorDescription:Ub}),Za0=Z.object({id:Z.string().min(1),title:Z.string().min(1),prompt:Ub,requiredDetails:Z.array(Z.string().min(1)).default([]),instructions:Z.array(Z.string().min(1)).default([]),doneWhen:Z.array(Z.string().min(1)).default([]),transitions:Z.array(Xa0).default([])}),LX0=Z.object({purpose:Z.string().min(1),operatingRules:Z.array(Z.string().min(1)).default([]),initialState:Z.string().min(1),states:Z.array(Za0).min(1),finalStates:Z.array(Z.string().min(1)).min(1),nextPrompts:Z.array(Z.string().min(1)).default([])}),ky=Z.object({title:Z.string(),status:IX0.default("active"),audience:JX0.default("anchor"),trigger:f3.optional(),lifecycle:f3.optional(),once:Z.boolean().optional(),starterText:f3.optional(),description:f3.optional(),starterPrompt:f3.optional(),completionMode:FX0.default("agent-confirmed")}),m12=Z.object({title:Z.string(),status:IX0,audience:JX0,trigger:f3.optional(),lifecycle:f3.optional(),once:Z.boolean().optional(),starterText:f3.optional(),description:f3.optional(),starterPrompt:f3.optional(),completionMode:FX0}),Hqw=Z.object({title:Z.string(),status:Xqw,audience:Zqw,trigger:Ub.optional(),lifecycle:Ub.optional(),once:Z.boolean().optional(),starterText:Ub.optional(),description:Ub.optional(),starterPrompt:Ub.optional(),completionMode:Wqw}),_y=LQ.extend({entityType:Z.literal("playbook"),metadata:Hqw});class kX0 extends G6{constructor(){super(LX0,{title:"Playbook",mappings:[{key:"purpose",label:"Purpose",type:"string"},{key:"operatingRules",label:"Operating Rules",type:"array",itemType:"string"},{key:"initialState",label:"Initial State",type:"string"},{key:"states",label:"States",type:"array",itemType:"object",itemMappings:[{key:"id",label:"ID",type:"string"},{key:"title",label:"Title",type:"string"},{key:"prompt",label:"Prompt",type:"custom",formatter:Wa0,parser:Ha0},{key:"requiredDetails",label:"Required Details",type:"array",itemType:"string"},{key:"instructions",label:"Instructions",type:"array",itemType:"string"},{key:"doneWhen",label:"Done When",type:"array",itemType:"string"},{key:"transitions",label:"Transitions",type:"array",itemType:"object",itemMappings:[{key:"event",label:"Event",type:"string"},{key:"target",label:"Target",type:"string"},{key:"operatorAction",label:"User Choice",type:"custom",formatter:Kqw,parser:Uqw},{key:"label",label:"Label",type:"custom",formatter:Wa0,parser:Ha0},{key:"description",label:"Description",type:"string"},{key:"operatorDescription",label:"Operator Description",type:"custom",formatter:Wa0,parser:Ha0}]}]},{key:"finalStates",label:"Final States",type:"array",itemType:"string"},{key:"nextPrompts",label:"Next Prompts",type:"array",itemType:"string"}]})}}var Oo=new kX0;function Wa0(A){return typeof A==="string"?A:""}function Ha0(A){let Q=A.trim();return Q.length>0?Q:void 0}function Kqw(A){return typeof A==="boolean"?String(A):""}function Uqw(A){let Q=A.trim().toLowerCase();if(Q==="true")return!0;if(Q==="false")return!1;return}function Ka0(A){let Q=[],w=new Set,B=new Set;for(let $ of A.states){if(w.has($.id))B.add($.id);w.add($.id)}if(!w.has(A.initialState))Q.push(`Playbook initial state '${A.initialState}' is not defined.`);for(let $ of B)Q.push(`Duplicate playbook state id '${$}'.`);for(let $ of A.finalStates)if(!w.has($))Q.push(`Playbook final state '${$}' is not defined.`);for(let $ of A.states)for(let f of $.transitions)if(!w.has(f.target))Q.push(`Playbook transition '${$.id}' -> '${f.target}' targets an undefined state.`);for(let $ of Dqw(A,w))Q.push(`Playbook state '${$}' is unreachable.`);return{valid:Q.length===0,errors:Q}}function Ny(A){let Q=Ka0(A);if(!Q.valid)throw Error(Q.errors.join(`
8451
8451
  `))}function Dqw(A,Q){if(!Q.has(A.initialState))return[];let w=new Set,B=[A.initialState];while(B.length>0){let $=B.shift();if(!$||w.has($))continue;w.add($);let f=A.states.find((Y)=>Y.id===$);if(!f)continue;for(let Y of f.transitions)if(Q.has(Y.target)&&!w.has(Y.target))B.push(Y.target)}return A.states.map(($)=>$.id).filter(($)=>!w.has($))}class NX0 extends C2{constructor(){super({entityType:"playbook",purpose:"A guided multi-step workflow the assistant runs together with the user.",schema:_y,frontmatterSchema:ky})}createPlaybookContent(A,Q){return this.buildMarkdown(Oo.format(Q),A)}parsePlaybookContent(A){let Q=this.parseFrontMatter(A,ky),w=this.extractBody(A).trim(),B=Gqw(w)?zqw(w):Oo.parse(w);return Ny(B),{frontmatter:ky.parse(Q),body:B,bodyMarkdown:w}}fromMarkdown(A){let{frontmatter:Q}=this.parsePlaybookContent(A);return{content:A,entityType:"playbook",metadata:{title:Q.title,status:Q.status,audience:Q.audience,...Q.trigger?{trigger:Q.trigger}:{},...Q.lifecycle?{lifecycle:Q.lifecycle}:{},...Q.once!==void 0?{once:Q.once}:{},...Q.starterText?{starterText:Q.starterText}:{},...Q.description?{description:Q.description}:{},...Q.starterPrompt?{starterPrompt:Q.starterPrompt}:{},completionMode:Q.completionMode}}}}var DP=new NX0;function Gqw(A){return/^##\s+Steps\s*$/im.test(A)}function zqw(A){let Q=qqw(Ua0(A,"Steps"));if(Q.length===0)throw Error("Playbook must declare at least one step.");let w=Q.map((B,$)=>{let f=$===Q.length-1;if(!f&&B.doneWhen.length===0&&B.choices.length===0&&!B.skip)throw Error(`Playbook step '${B.title}' must declare Done when, Choices, or Skip.`);return{id:B.id,title:B.title,...B.prompt?{prompt:B.prompt}:{},requiredDetails:B.requiredDetails,instructions:B.instructions,doneWhen:B.doneWhen,transitions:[...B.doneWhen.length>0&&!f?[{event:"NEXT",target:Q[$+1]?.id??B.id}]:[],...B.choices.map((Y,X)=>({event:`CHOICE_${X+1}`,target:Z1(Y.target),operatorAction:!0,label:Y.label})),...B.skip?[{event:"SKIP",target:Z1(B.skip.target),operatorAction:!0,label:B.skip.label}]:[]]}});return{purpose:bqw(A,"Purpose"),operatingRules:u12(A,"Operating Rules"),initialState:Q[0]?.id??"",states:w,finalStates:[Q.at(-1)?.id??""],nextPrompts:u12(A,"Next Prompts")}}function qqw(A){let Q=[],w;for(let B of A.split(/\r?\n/)){let $=/^###\s+(.+?)\s*$/.exec(B);if($){w={title:$[1]??"",content:[]},Q.push(w);continue}w?.content.push(B)}return Q.map((B)=>{let $=B.content.join(`
8452
8452
  `);return{title:B.title,id:Z1(B.title),...c12($,"Say")?{prompt:c12($,"Say")}:{},requiredDetails:_X0($,"Required details"),instructions:_X0($,"To do"),doneWhen:_X0($,"Done when"),choices:Vqw($,"Choices"),...l12($)?{skip:l12($)}:{}}})}function Ua0(A,Q){let w=A.split(/\r?\n/),B=w.findIndex((f)=>f.trim().toLowerCase()===`## ${Q.toLowerCase()}`);if(B===-1)return"";let $=[];for(let f of w.slice(B+1)){if(/^##\s+/.test(f))break;$.push(f)}return $.join(`
8453
8453
  `).trim()}function bqw(A,Q){return Ua0(A,Q).split(/\r?\n/).map((w)=>w.trim()).filter((w)=>w.length>0&&!w.startsWith("#")).join(`
8454
8454
  `).trim()}function u12(A,Q){return p12(Ua0(A,Q))}function c12(A,Q){return new RegExp(`^${Jqw(Q)}:\\s*(.+?)\\s*$`,"im").exec(A)?.[1]?.trim()}function _X0(A,Q){let w=A.split(/\r?\n/),B=w.findIndex((f)=>f.trim().toLowerCase()===`${Q.toLowerCase()}:`);if(B===-1)return[];let $=[];for(let f of w.slice(B+1)){let Y=f.trim();if(Y.length===0)continue;if(/^[A-Za-z][A-Za-z ]+:/.test(Y)||/^#{1,6}\s+/.test(Y))break;$.push(f)}return p12($.join(`
8455
- `))}function Vqw(A,Q){return _X0(A,Q).map(Iqw)}function Iqw(A){let Q=/^(.+?)\s*(?:\u2192|->)\s*(.+)$/.exec(A);if(!Q)throw Error(`Invalid playbook choice '${A}'. Expected "Label \u2192 Step".`);return{label:Q[1]?.trim()??"",target:Q[2]?.trim()??""}}function l12(A){let Q=/^Skip:\s*(.+?)\s*(?:\u2192|->)\s*(.+?)\s*$/im.exec(A);if(!Q)return;return{label:Q[1]?.trim()??"",target:Q[2]?.trim()??""}}function p12(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function Jqw(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}N0();var jX0=Z.object({}).catchall(Z.unknown()).transform(()=>({}));var PX0={name:"@brains/playbooks",version:"0.2.0-alpha.142",description:"Runtime orchestration for chat-native playbook runs",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/runtime-state":"workspace:*","@brains/utils":"workspace:*",xstate:"^5.32.1"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Lqw="playbook";class Da0 extends nQ{entityType=Lqw;schema=_y;adapter=DP;constructor(A={}){super("playbook",PX0,A,jX0)}async getInstructions(){return"Playbook entities describe durable, editable guided workflows for the agent. Use them as operating guidance when a playbook run is active; do not treat them as content to publish unless the user explicitly asks."}}function Ga0(A={}){return new Da0(A)}g6();wA();N0();xX();bu();function MX0(A,Q){return A.length===Q.length&&A.every((w,B)=>w===Q[B])}function za0(A,Q){return Q==="NEXT"&&A.doneWhen.length>0}function OX0(A,Q){return Q.gateVerdicts.some((w)=>w.stateId===A.id&&MX0(w.goal,A.doneWhen)&&w.met)}function kqw(A,Q,w){return d1.createMachine({id:A,initial:Q.initialState,states:Object.fromEntries(Q.states.map((B)=>{let $=Q.finalStates.includes(B.id);return[B.id,{...$?{type:"final"}:{},...$?{}:{on:Object.fromEntries(B.transitions.map((f)=>[f.event,{target:f.target,...za0(B,f.event)?{guard:()=>OX0(B,w)}:{}}]))}}]}))})}function qa0(A,Q){let w=kqw(Q.playbookId,A,Q);return d1.createActor(w,{snapshot:w.resolveState({value:Q.currentState})})}function _qw(A,Q,w){let B=qa0(Q,A);B.start();let $=B.getSnapshot().can({type:w});return B.stop(),$}function jy(A,Q,w){return w.transitions.filter((B)=>_qw(A,Q,B.event))}function xo(A,Q,w){let B=new Set(jy(A,Q,w).map(($)=>`${$.event}\x00${$.target}`));return w.transitions.filter(($)=>!B.has(`${$.event}\x00${$.target}`))}function i12(A,Q){return A.evidence.filter((w)=>!w.stateId||w.stateId===Q)}function GP(A,Q){return A.states.find((w)=>w.id===Q)}function zP(A){let Q=A.operatorDescription??A.description??A.label;return Q?`- ${A.event} -> ${A.target}: ${Q}`:`- ${A.event} -> ${A.target}`}function d12(A,Q){if(Q.doneWhen.length===0)return"- no gated Done When conditions";let w=A.gateVerdicts.find((B)=>B.stateId===Q.id&&MX0(B.goal,Q.doneWhen));if(!w)return`- Not yet met: ${Q.doneWhen.join("; ")}`;return w.met?`- Met: ${w.reason}`:`- Not yet met: ${w.reason}`}function n12(A,Q,w){let B=jy(A,Q,w),$=B.filter((W)=>W.operatorAction!==!0),f=B.filter((W)=>W.operatorAction===!0),Y=xo(A,Q,w),X=A.gateVerdicts.find((W)=>W.stateId===w.id&&MX0(W.goal,w.doneWhen));return[`Current state: ${w.id} (${w.title})`,"Instructions:",...w.instructions.map((W)=>`- ${W}`),"Done When:",...w.doneWhen.length>0?w.doneWhen.map((W)=>`- ${W}`):["- none"],"Goal status:",X?`- ${X.met?"Met":"Not yet met"}: ${X.reason}`:"- Not checked yet.","Current-state information rules:","- If this state asks the operator for information, ask the operator for the missing current-run information.","- If the current operator message partially answers the state's prompt, do not repeat the original prompt; ask only for the next missing detail required by the state instructions.","- Do not answer the state's operator-facing prompt from memory, existing durable records, profile data, search, or retrieval tools.","- Setup facts must come from current-run evidence or current operator input, not ambient records.","Event selection rules:","- Blocked events are not valid events; do not call playbook_send_event with a blocked event.","- For gated durable states, operator-provided details are not enough to send NEXT; first complete the required system_create/system_update/system_delete action or use existing current-run evidence that the Done When condition has already been met.","- If the operator explicitly says they have not chosen, selected, asked for, or used one of the available actions, do not send any event.",'- Operator actions and choices are not generic continuation events; even if only one operator action is available, generic continuation like "yes", "next", or "continue" is not a valid selection.',"- If multiple events are available, ask the operator to pick one labeled action.","- A Skip-style operator action is never a default continuation; send it only when the operator positively selects or asks to skip.","Valid continuation events:",...$.length>0?$.map((W)=>zP(W)):["- none"],"Available operator actions:",...f.length>0?f.map((W)=>zP(W)):["- none"],"Blocked events:",...Y.length>0?Y.map((W)=>zP(W)):["- none"]].join(`
8455
+ `))}function Vqw(A,Q){return _X0(A,Q).map(Iqw)}function Iqw(A){let Q=/^(.+?)\s*(?:\u2192|->)\s*(.+)$/.exec(A);if(!Q)throw Error(`Invalid playbook choice '${A}'. Expected "Label \u2192 Step".`);return{label:Q[1]?.trim()??"",target:Q[2]?.trim()??""}}function l12(A){let Q=/^Skip:\s*(.+?)\s*(?:\u2192|->)\s*(.+?)\s*$/im.exec(A);if(!Q)return;return{label:Q[1]?.trim()??"",target:Q[2]?.trim()??""}}function p12(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function Jqw(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}N0();var jX0=Z.object({}).catchall(Z.unknown()).transform(()=>({}));var PX0={name:"@brains/playbooks",version:"0.2.0-alpha.143",description:"Runtime orchestration for chat-native playbook runs",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/runtime-state":"workspace:*","@brains/utils":"workspace:*",xstate:"^5.32.1"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Lqw="playbook";class Da0 extends nQ{entityType=Lqw;schema=_y;adapter=DP;constructor(A={}){super("playbook",PX0,A,jX0)}async getInstructions(){return"Playbook entities describe durable, editable guided workflows for the agent. Use them as operating guidance when a playbook run is active; do not treat them as content to publish unless the user explicitly asks."}}function Ga0(A={}){return new Da0(A)}g6();wA();N0();xX();bu();function MX0(A,Q){return A.length===Q.length&&A.every((w,B)=>w===Q[B])}function za0(A,Q){return Q==="NEXT"&&A.doneWhen.length>0}function OX0(A,Q){return Q.gateVerdicts.some((w)=>w.stateId===A.id&&MX0(w.goal,A.doneWhen)&&w.met)}function kqw(A,Q,w){return d1.createMachine({id:A,initial:Q.initialState,states:Object.fromEntries(Q.states.map((B)=>{let $=Q.finalStates.includes(B.id);return[B.id,{...$?{type:"final"}:{},...$?{}:{on:Object.fromEntries(B.transitions.map((f)=>[f.event,{target:f.target,...za0(B,f.event)?{guard:()=>OX0(B,w)}:{}}]))}}]}))})}function qa0(A,Q){let w=kqw(Q.playbookId,A,Q);return d1.createActor(w,{snapshot:w.resolveState({value:Q.currentState})})}function _qw(A,Q,w){let B=qa0(Q,A);B.start();let $=B.getSnapshot().can({type:w});return B.stop(),$}function jy(A,Q,w){return w.transitions.filter((B)=>_qw(A,Q,B.event))}function xo(A,Q,w){let B=new Set(jy(A,Q,w).map(($)=>`${$.event}\x00${$.target}`));return w.transitions.filter(($)=>!B.has(`${$.event}\x00${$.target}`))}function i12(A,Q){return A.evidence.filter((w)=>!w.stateId||w.stateId===Q)}function GP(A,Q){return A.states.find((w)=>w.id===Q)}function zP(A){let Q=A.operatorDescription??A.description??A.label;return Q?`- ${A.event} -> ${A.target}: ${Q}`:`- ${A.event} -> ${A.target}`}function d12(A,Q){if(Q.doneWhen.length===0)return"- no gated Done When conditions";let w=A.gateVerdicts.find((B)=>B.stateId===Q.id&&MX0(B.goal,Q.doneWhen));if(!w)return`- Not yet met: ${Q.doneWhen.join("; ")}`;return w.met?`- Met: ${w.reason}`:`- Not yet met: ${w.reason}`}function n12(A,Q,w){let B=jy(A,Q,w),$=B.filter((W)=>W.operatorAction!==!0),f=B.filter((W)=>W.operatorAction===!0),Y=xo(A,Q,w),X=A.gateVerdicts.find((W)=>W.stateId===w.id&&MX0(W.goal,w.doneWhen));return[`Current state: ${w.id} (${w.title})`,"Instructions:",...w.instructions.map((W)=>`- ${W}`),"Done When:",...w.doneWhen.length>0?w.doneWhen.map((W)=>`- ${W}`):["- none"],"Goal status:",X?`- ${X.met?"Met":"Not yet met"}: ${X.reason}`:"- Not checked yet.","Current-state information rules:","- If this state asks the operator for information, ask the operator for the missing current-run information.","- If the current operator message partially answers the state's prompt, do not repeat the original prompt; ask only for the next missing detail required by the state instructions.","- Do not answer the state's operator-facing prompt from memory, existing durable records, profile data, search, or retrieval tools.","- Setup facts must come from current-run evidence or current operator input, not ambient records.","Event selection rules:","- Blocked events are not valid events; do not call playbook_send_event with a blocked event.","- For gated durable states, operator-provided details are not enough to send NEXT; first complete the required system_create/system_update/system_delete action or use existing current-run evidence that the Done When condition has already been met.","- If the operator explicitly says they have not chosen, selected, asked for, or used one of the available actions, do not send any event.",'- Operator actions and choices are not generic continuation events; even if only one operator action is available, generic continuation like "yes", "next", or "continue" is not a valid selection.',"- If multiple events are available, ask the operator to pick one labeled action.","- A Skip-style operator action is never a default continuation; send it only when the operator positively selects or asks to skip.","Valid continuation events:",...$.length>0?$.map((W)=>zP(W)):["- none"],"Available operator actions:",...f.length>0?f.map((W)=>zP(W)):["- none"],"Blocked events:",...Y.length>0?Y.map((W)=>zP(W)):["- none"]].join(`
8456
8456
  `)}function r12(A){let{run:Q,body:w,state:B,playbookTitle:$}=A,f=jy(Q,w,B),Y=f.filter((V)=>V.operatorAction!==!0),X=f.filter((V)=>V.operatorAction===!0),W=xo(Q,w,B),H=Y.map((V)=>zP(V)).join(`
8457
8457
  `),K=X.map((V)=>zP(V)).join(`
8458
8458
  `),U=W.map((V)=>zP(V)).join(`
@@ -8526,9 +8526,9 @@ ${Object.entries(A).map(([w,B])=>`- ${w}: playbookId=${B.playbookId}, trigger=${
8526
8526
  ${A.guidance}`:$}}function Y22(A){return{...A,evidence:A.evidence.map((Q)=>({...Q,data:Sqw(Q.data)}))}}function Sqw(A){return Object.fromEntries(["entityType","entityId","operation"].flatMap((Q)=>A[Q]!==void 0?[[Q,A[Q]]]:[]))}function mqw(A){return{kind:"actions",id:`actions:playbook:${A.run.id}`,title:A.title,defaultOpen:!0,actions:A.transitions.map((Q)=>({type:"event",id:`playbook:${A.run.id}:${Q.event}`,label:Q.label??Q.operatorDescription??Q.description??Q.event,event:Q.event,fromState:A.run.currentState,...Q.operatorDescription??Q.description?{description:Q.operatorDescription??Q.description}:{}}))}}function uqw(A){if(!A)return"Continuing.";return A.prompt??`Continuing to ${A.title}.`}function X22(){return{promptTokens:0,completionTokens:0,totalTokens:0}}function Z22(A,Q){let w=A.filter(Q),B=w.filter(($)=>$.status==="active"||$.status==="offered");return La0(B)??La0(w)}function La0(A){return[...A].sort((Q,w)=>(w.completedAt??w.updatedAt).localeCompare(Q.completedAt??Q.updatedAt))[0]}function cqw(A){return{async evaluate(Q){let w=Q.goal.join(`
8527
8527
  `),B=await A.entityService.search({query:w,options:{limit:8,excludeTypes:["playbook"],visibilityScope:w$("anchor")}}),$=lqw(Q,B),{verdict:f}=await A.judge({instruction:"Decide whether the playbook goal is satisfied by the supplied current-run runtime evidence and KB excerpts. Current-run runtime evidence is authoritative for playbook completion; use KB excerpts as supporting context, not to override clear runtime evidence from this run. Return met=true only when the outcome clearly holds. If evidence is missing or ambiguous, return met=false with a short reason.",material:$,schema:Cqw});return f}}}function lqw(A,Q){return["## Playbook run",`runId: ${A.run.id}`,`playbookId: ${A.run.playbookId}`,`currentState: ${A.state.id} (${A.state.title})`,"","## State instructions",...A.state.instructions.map((w)=>`- ${w}`),"","## Done When goal",...A.goal.map((w)=>`- ${w}`),"","## Runtime evidence",...A.evidence.length>0?A.evidence.map((w,B)=>pqw(B+1,w)):["No runtime evidence collected for this state."],"","## KB excerpts",...Q.length>0?Q.map((w,B)=>iqw(B+1,w)):["No relevant KB excerpts found."]].join(`
8528
8528
  `)}function pqw(A,Q){return`${A}. ${Q.kind} at ${Q.observedAt}: ${H22(Q.data)}`}function iqw(A,Q){return[`${A}. ${Q.entity.entityType}/${Q.entity.id} (score ${Q.score})`,`Excerpt: ${Q.excerpt}`,`Content: ${K22(Q.entity.content,1200)}`,`Metadata: ${H22(Q.entity.metadata)}`].join(`
8529
- `)}function H22(A){try{return K22(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function K22(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var dqw={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function _a0(A={},Q={}){return new ka0(A,Q)}g6();wA();N0();import{readFile as rqw}from"fs/promises";import{join as oqw}from"path";var U22={name:"@brains/rover-onboarding",version:"0.2.0-alpha.142",description:"Rover onboarding playbook bundle and activation plugin",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/playbooks":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"latest",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var sqw=Z.object({enabled:Z.boolean().default(!1)}).strict(),D22=[{id:"rover-onboarding",fileName:"rover-onboarding.md",starter:{id:"onboarding",trigger:"first-anchor-web-chat",playbookId:"rover-onboarding",once:!0,starterText:"Set up Rover",description:"Tune Rover's identity and anchor profile before using the knowledge loop.",starterPrompt:"Start playbook rover-onboarding."}},{id:"rover-first-knowledge-loop",fileName:"rover-first-knowledge-loop.md"}];class G22 extends aQ{dependencies=["playbook","playbooks"];constructor(A={}){super("rover-onboarding",U22,A,sqw)}async onReady(A){if(!this.config.enabled)return;for(let Q of D22)await this.seedPlaybookIfMissing(A,Q);for(let Q of D22){if(!Q.starter)continue;await A.messaging.send({type:QO,payload:Q.starter})}}async seedPlaybookIfMissing(A,Q){if(await A.entityService.getEntity({entityType:"playbook",id:Q.id,visibilityScope:"restricted"}))return;let B=await rqw(oqw(import.meta.dir,"..","content","playbook",Q.fileName),"utf8");await A.entityService.createEntityFromMarkdown({input:{entityType:"playbook",id:Q.id,markdown:B}})}}function z22(A={}){return new G22(A)}wA();N0();wA();var Na0=Z.enum(["new","planned","in-progress","done","declined"]),ja0=Z.enum(["low","medium","high","critical"]),aqw=Z.enum(["new","planned","in-progress","done","declined"]),tqw=Z.enum(["low","medium","high","critical"]),Ro=Z.object({title:Z.string(),status:Na0,priority:ja0.default("medium"),requested:Z.number().int().default(1),declinedReason:Z.string().optional()}),eqw=Z.object({title:Z.string(),status:Na0,priority:ja0,requested:Z.number().int(),slug:Z.string()}),Abw=Z.object({title:Z.string(),status:aqw,priority:tqw,requested:Z.number().int(),slug:Z.string()}),vo=LQ.extend({entityType:Z.literal("wish"),metadata:Abw});N0();var Pa0=Z.object({}).catchall(Z.unknown()).transform(()=>({}));wA();K2();class ho extends C2{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:vo,frontmatterSchema:Ro})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,Ro);return{frontmatter:Ro.parse(Q),description:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),w=Z1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:w}}}}var q22=new ho;K2();K2();async function b22(A,Q){let w=`${Q.title}: ${Q.description}`,$=(await A.search({query:w,options:{types:["wish"],limit:1}}))[0];if($&&$.score>=A.similarityThreshold)return $.entity;let f=Z1(Q.title);return A.getEntity({entityType:"wish",id:f})}class hX0{logger;context;adapter=new ho;constructor(A,Q){this.logger=A,this.context=Q}async process(A,Q,w){let B=A.title??A.prompt??"Untitled wish",$=A.content??A.prompt??"",f=await b22({search:(H)=>this.context.entityService.search(H),getEntity:(H)=>this.context.entityService.getEntity(H),similarityThreshold:0.85},{title:B,description:$});if(f){let{frontmatter:H,description:K}=this.adapter.parseWishContent(f.content),U=H.requested+1,D=this.adapter.createWishContent({...H,requested:U},K);return await this.context.entityService.updateEntity({entity:{...f,content:D,metadata:{...f.metadata,requested:U}}}),this.logger.info("Incremented wish request count",{id:f.id,requested:U}),{success:!0,entityId:f.id,existed:!0,requested:U}}let Y=Z1(B),X=A.options?.priority??"medium",W=this.adapter.createWishContent({title:B,status:"new",priority:X,requested:1},$);return await this.context.entityService.createEntity({entity:{id:Y,entityType:"wish",content:W,metadata:{title:B,status:"new",priority:X,requested:1,slug:Y}}}),this.logger.info("Created new wish",{id:Y,title:B}),{success:!0,entityId:Y,existed:!1,requested:1}}}var V22={critical:0,high:1,medium:2,low:3};function I22(A){A.sort((Q,w)=>{let B=w.metadata.requested-Q.metadata.requested;if(B!==0)return B;return V22[Q.metadata.priority]-V22[w.metadata.priority]})}var J22={name:"@brains/wishlist",version:"0.2.0-alpha.142",description:"Wishlist plugin for tracking unfulfilled user requests",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var wbw="wish";class F22 extends nQ{entityType=wbw;schema=vo;adapter=q22;constructor(A={}){super("wishlist",J22,A,Pa0)}async interceptCreate(A,Q,w){let B=await new hX0(this.logger,w).process({...A.title?{title:A.title}:{},...A.prompt?{prompt:A.prompt}:{},...A.content?{content:A.content}:{}},`wish-create-${Date.now()}`,{});if(!B.success)return{kind:"handled",result:{success:!1,error:B.error??"Failed to create wish"}};return{kind:"handled",result:{success:!0,data:{...B.entityId?{entityId:B.entityId}:{},status:B.existed?"updated":"created"}}}}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:"top-wishes",pluginId:this.id,title:"Top Wishes",section:"secondary",priority:30,rendererName:"ListWidget",dataProvider:async()=>{let w=await A.entityService.listEntities({entityType:"wish",options:{limit:10}});return I22(w),{items:w.map((B)=>({id:B.id,name:B.metadata.title,count:B.metadata.requested,priority:B.metadata.priority,status:B.metadata.status}))}}}}),{success:!0}});let Q=new hX0(this.logger,A);A.jobs.registerHandler("wish:create",{process:Q.process.bind(Q),validateAndParse:(w)=>w})}async getInstructions(){return"Wish entities record explicitly requested capabilities or desired end states whose literal completion is outside the available toolset. They may capture outcomes the assistant can advise about but cannot directly perform. They track demand, priority, and status for future capability planning; they are not a substitute for first-class entities that already support the requested action. To show the whole wishlist, call system_list once with entityType wish and omit status; only include status when the user asks for a specific wish status."}}function Bbw(A={}){return new F22(A)}var CX0=Bbw;wA();wA();N0();var Co=Z.object({title:Z.string(),target:Z.string()}),L22=Z.object({title:Z.string(),target:Z.string(),slug:Z.string().optional()}),go=LQ.extend({entityType:Z.literal("prompt"),metadata:L22});wA();K2();class Ma0 extends C2{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:go,frontmatterSchema:Co})}toMarkdown(A){let Q=this.extractBody(A.content),w=this.parseFrontMatter(A.content,Co);return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,Co),w=Z1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:w}}}}var Oa0=new Ma0;var k22={name:"@brains/prompt",version:"0.2.0-alpha.142",description:"Prompt entity type \u2014 AI prompts as editable markdown entities",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","bun-types":"^1.3.14",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var fbw="prompt";class xa0 extends nQ{entityType=fbw;schema=go;adapter=Oa0;constructor(){super("prompt",k22,{},L7)}getEntityTypeConfig(){return{embeddable:!1}}}function bP(){return new xa0}wA();N0();N0();class gX0{apiKey;fetchFn;baseUrl="https://api.unsplash.com";constructor(A,Q){this.apiKey=A,this.fetchFn=Q}async searchPhotos(A,Q){let w=new URL(`${this.baseUrl}/search/photos`);w.searchParams.set("query",A),w.searchParams.set("page",String(Q.page)),w.searchParams.set("per_page",String(Q.perPage));let B=await this.fetchFn(w.toString(),{headers:{Authorization:`Client-ID ${this.apiKey}`}});if(!B.ok)throw Error(`Unsplash API error: ${B.status} ${B.statusText}`);let $=Xbw.parse(await B.json());return{photos:$.results.map(Zbw),total:$.total,totalPages:$.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}var Ybw=Z.looseObject({id:Z.string(),description:Z.string().nullable(),alt_description:Z.string().nullable(),urls:Z.looseObject({raw:Z.url(),full:Z.url(),regular:Z.url(),small:Z.url(),thumb:Z.url()}),links:Z.looseObject({html:Z.url(),download_location:Z.url()}),user:Z.looseObject({name:Z.string(),links:Z.looseObject({html:Z.url()})}),width:Z.number().int().nonnegative(),height:Z.number().int().nonnegative()}),Xbw=Z.looseObject({total:Z.number().int().nonnegative(),total_pages:Z.number().int().nonnegative(),results:Z.array(Ybw)});function Zbw(A){return{id:A.id,description:A.description,altDescription:A.alt_description,thumbnailUrl:A.urls.thumb,imageUrl:A.urls.regular,photographerName:A.user.name,photographerUrl:A.user.links.html,sourceUrl:A.links.html,downloadLocation:A.links.download_location,width:A.width,height:A.height}}N0();async function yX0(A,Q,w,B){let $=await A.getEntity({entityType:Q,id:w});if(!$)return!1;return await A.updateEntity({entity:{...$,metadata:{...$.metadata,coverImageId:B}}}),!0}var Wbw={query:Z.string().describe("Search terms for stock photos"),perPage:Z.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:Z.number().min(1).default(1).describe("Page number")},Hbw={photoId:Z.string().describe("Photo ID from search results"),downloadLocation:Z.url().describe("Download tracking URL (required by provider ToS)"),photographerName:Z.string().describe("Photographer name for attribution"),photographerUrl:Z.url().describe("Photographer profile URL for attribution"),sourceUrl:Z.url().describe("Photo page URL on provider"),imageUrl:Z.url().describe("Image URL to download"),title:Z.string().optional().describe("Image entity title"),alt:Z.string().optional().describe("Alt text for the image"),targetEntityType:Z.string().optional().describe("Entity type to set cover image on"),targetEntityId:Z.string().optional().describe("Entity ID to set cover image on")},Kbw=Z.object({query:Z.string(),perPage:Z.number().min(1).max(30).default(10),page:Z.number().min(1).default(1)}),Ubw=Z.object({photoId:Z.string(),downloadLocation:Z.url(),photographerName:Z.string(),photographerUrl:Z.url(),sourceUrl:Z.url(),imageUrl:Z.url(),title:Z.string().optional(),alt:Z.string().optional(),targetEntityType:Z.string().optional(),targetEntityId:Z.string().optional()});function _22(A,Q){return[Dbw(A,Q),Gbw(A,Q)]}function Dbw(A,Q){return{name:`${A}_search`,description:"Search for stock photos. Returns photo candidates with preview URLs and metadata. Use stock-photo_select to materialize a chosen photo into an image entity.",inputSchema:Wbw,visibility:"anchor",sideEffects:"none",handler:async(w)=>{let B=Kbw.safeParse(w);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};try{return{success:!0,data:await Q.provider.searchPhotos(B.data.query,{page:B.data.page,perPage:B.data.perPage})}}catch($){return{success:!1,error:$ instanceof Error?$.message:"Search failed"}}}}}function Gbw(A,Q){return{name:`${A}_select`,description:"Select a stock photo from search results and materialize it as an image entity. Triggers provider download tracking per ToS. Optionally sets as cover image on a target entity.",inputSchema:Hbw,visibility:"anchor",sideEffects:"external",handler:async(w)=>{let B=Ubw.safeParse(w);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};let{photoId:$,downloadLocation:f,photographerName:Y,photographerUrl:X,sourceUrl:W,imageUrl:H,title:K,alt:U,targetEntityType:D,targetEntityId:q}=B.data,b={photographerName:Y,photographerUrl:X,sourceUrl:W},I=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:H}}}});if(I[0]){let N={imageEntityId:I[0].id,alreadyExisted:!0,attribution:b};if(D&&q)N.coverSet=await yX0(Q.entityService,D,q,I[0].id);return{success:!0,data:N}}let V=await Q.jobs.enqueue({type:"select-photo",data:{photoId:$,downloadLocation:f,photographerName:Y,photographerUrl:X,sourceUrl:W,imageUrl:H,...K!==void 0?{title:K}:{},...U!==void 0?{alt:U}:{},...D!==void 0?{targetEntityType:D}:{},...q!==void 0?{targetEntityId:q}:{}}}),L={imageEntityId:$,alreadyExisted:!1,attribution:b,jobId:V,status:"generating"};if(D&&q)L.coverSet=!1;return{success:!0,data:L}}}}wA();N0();J4();var zbw=Z.object({photoId:Z.string(),downloadLocation:Z.url(),photographerName:Z.string(),photographerUrl:Z.url(),sourceUrl:Z.url(),imageUrl:Z.url(),title:Z.string().optional(),alt:Z.string().optional(),targetEntityType:Z.string().optional(),targetEntityId:Z.string().optional()});class Ra0 extends aw{deps;constructor(A,Q){super(A,{schema:zbw,jobTypeName:"select-photo"});this.deps=Q}async process(A,Q,w){await this.reportProgress(w,{progress:10,message:"Tracking stock photo download"}),await this.deps.provider.triggerDownload(A.downloadLocation),await this.reportProgress(w,{progress:35,message:"Downloading stock photo"});let B=await this.deps.fetchImage(A.imageUrl),$=A.title??`Stock photo ${A.photoId}`,f=mX.createImageEntity({dataUrl:B,title:$,alt:A.alt??$});await this.reportProgress(w,{progress:75,message:"Saving stock photo"});let{entityId:Y}=await this.deps.entityService.createEntity({entity:{id:A.photoId,...f,metadata:{...f.metadata,sourceUrl:A.imageUrl}}}),X={imageEntityId:Y,alreadyExisted:!1};if(A.targetEntityType&&A.targetEntityId){if(X.coverSet=await yX0(this.deps.entityService,A.targetEntityType,A.targetEntityId,Y),!X.coverSet)X.warning=`Target entity ${A.targetEntityType}:${A.targetEntityId} not found; cover image not set`}return await this.reportProgress(w,{progress:100,message:"Stock photo selected"}),X}summarizeDataForLog(A){return{photoId:A.photoId,hasTarget:A.targetEntityType!==void 0}}}J4();var N22={name:"@brains/stock-photo",version:"0.2.0-alpha.142",description:"Stock photo search and selection \u2014 Unsplash provider",dependencies:{"@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var bbw=Z.object({provider:Z.enum(["unsplash"]).default("unsplash"),apiKey:Z.string().optional().describe("Stock photo provider API key")});class va0 extends aQ{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",N22,A,bbw);this.deps=Q}async getTools(){if(!this.config.apiKey)return[];if(this.cachedTools)return this.cachedTools;let A=this.getContext(),Q=this.createProvider();return this.cachedTools=_22(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??TW,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new Ra0(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??TW}))}createProvider(){return new gX0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function ha0(A={},Q={}){return new va0(A,Q)}wA();N0();wA();wA();N0();var j22=Z.enum(["ai","foundation","work"]),P22=Z.object({suffix:j22,title:Z.string(),body:Z.string(),linkLabel:Z.string(),linkHref:Z.string()}),yo=Z.object({eyebrow:Z.string(),headline:Z.string(),cards:Z.array(P22).min(1)}),Ca0=Z.object({title:Z.string(),slug:Z.string(),status:Z.enum(["draft","published"])}),Vbw=Z.object({title:Z.string(),slug:Z.string(),status:Z.enum(["draft","published"])}),Eo=LQ.extend({entityType:Z.literal("ecosystem-section"),metadata:Vbw});class M22 extends C2{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:Eo,frontmatterSchema:Ca0})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var ga0=new M22;N0();function Ibw(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function ya0(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function To(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function EX0(A){let Q=Ibw(A),B=ya0(Q,"Cards").split(/^### Card \d+\s*$/m).map(($)=>$.trim()).filter(Boolean);return yo.parse({eyebrow:ya0(Q,"Eyebrow"),headline:ya0(Q,"Headline"),cards:B.map(($)=>({suffix:To($,"Suffix"),title:To($,"Title"),body:To($,"Body"),linkLabel:To($,"Link Label"),linkHref:To($,"Link Href")}))})}function O22(A){return["# Ecosystem Section","","## Eyebrow",A.eyebrow,"","## Headline",A.headline,"","## Cards","",...A.cards.flatMap((Q,w)=>[`### Card ${w+1}`,"","#### Suffix",Q.suffix,"","#### Title",Q.title,"","#### Body",Q.body,"","#### Link Label",Q.linkLabel,"","#### Link Href",Q.linkHref,""])].join(`
8529
+ `)}function H22(A){try{return K22(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function K22(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var dqw={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function _a0(A={},Q={}){return new ka0(A,Q)}g6();wA();N0();import{readFile as rqw}from"fs/promises";import{join as oqw}from"path";var U22={name:"@brains/rover-onboarding",version:"0.2.0-alpha.143",description:"Rover onboarding playbook bundle and activation plugin",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/playbooks":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"latest",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var sqw=Z.object({enabled:Z.boolean().default(!1)}).strict(),D22=[{id:"rover-onboarding",fileName:"rover-onboarding.md",starter:{id:"onboarding",trigger:"first-anchor-web-chat",playbookId:"rover-onboarding",once:!0,starterText:"Set up Rover",description:"Tune Rover's identity and anchor profile before using the knowledge loop.",starterPrompt:"Start playbook rover-onboarding."}},{id:"rover-first-knowledge-loop",fileName:"rover-first-knowledge-loop.md"}];class G22 extends aQ{dependencies=["playbook","playbooks"];constructor(A={}){super("rover-onboarding",U22,A,sqw)}async onReady(A){if(!this.config.enabled)return;for(let Q of D22)await this.seedPlaybookIfMissing(A,Q);for(let Q of D22){if(!Q.starter)continue;await A.messaging.send({type:QO,payload:Q.starter})}}async seedPlaybookIfMissing(A,Q){if(await A.entityService.getEntity({entityType:"playbook",id:Q.id,visibilityScope:"restricted"}))return;let B=await rqw(oqw(import.meta.dir,"..","content","playbook",Q.fileName),"utf8");await A.entityService.createEntityFromMarkdown({input:{entityType:"playbook",id:Q.id,markdown:B}})}}function z22(A={}){return new G22(A)}wA();N0();wA();var Na0=Z.enum(["new","planned","in-progress","done","declined"]),ja0=Z.enum(["low","medium","high","critical"]),aqw=Z.enum(["new","planned","in-progress","done","declined"]),tqw=Z.enum(["low","medium","high","critical"]),Ro=Z.object({title:Z.string(),status:Na0,priority:ja0.default("medium"),requested:Z.number().int().default(1),declinedReason:Z.string().optional()}),eqw=Z.object({title:Z.string(),status:Na0,priority:ja0,requested:Z.number().int(),slug:Z.string()}),Abw=Z.object({title:Z.string(),status:aqw,priority:tqw,requested:Z.number().int(),slug:Z.string()}),vo=LQ.extend({entityType:Z.literal("wish"),metadata:Abw});N0();var Pa0=Z.object({}).catchall(Z.unknown()).transform(()=>({}));wA();K2();class ho extends C2{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:vo,frontmatterSchema:Ro})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,Ro);return{frontmatter:Ro.parse(Q),description:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),w=Z1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:w}}}}var q22=new ho;K2();K2();async function b22(A,Q){let w=`${Q.title}: ${Q.description}`,$=(await A.search({query:w,options:{types:["wish"],limit:1}}))[0];if($&&$.score>=A.similarityThreshold)return $.entity;let f=Z1(Q.title);return A.getEntity({entityType:"wish",id:f})}class hX0{logger;context;adapter=new ho;constructor(A,Q){this.logger=A,this.context=Q}async process(A,Q,w){let B=A.title??A.prompt??"Untitled wish",$=A.content??A.prompt??"",f=await b22({search:(H)=>this.context.entityService.search(H),getEntity:(H)=>this.context.entityService.getEntity(H),similarityThreshold:0.85},{title:B,description:$});if(f){let{frontmatter:H,description:K}=this.adapter.parseWishContent(f.content),U=H.requested+1,D=this.adapter.createWishContent({...H,requested:U},K);return await this.context.entityService.updateEntity({entity:{...f,content:D,metadata:{...f.metadata,requested:U}}}),this.logger.info("Incremented wish request count",{id:f.id,requested:U}),{success:!0,entityId:f.id,existed:!0,requested:U}}let Y=Z1(B),X=A.options?.priority??"medium",W=this.adapter.createWishContent({title:B,status:"new",priority:X,requested:1},$);return await this.context.entityService.createEntity({entity:{id:Y,entityType:"wish",content:W,metadata:{title:B,status:"new",priority:X,requested:1,slug:Y}}}),this.logger.info("Created new wish",{id:Y,title:B}),{success:!0,entityId:Y,existed:!1,requested:1}}}var V22={critical:0,high:1,medium:2,low:3};function I22(A){A.sort((Q,w)=>{let B=w.metadata.requested-Q.metadata.requested;if(B!==0)return B;return V22[Q.metadata.priority]-V22[w.metadata.priority]})}var J22={name:"@brains/wishlist",version:"0.2.0-alpha.143",description:"Wishlist plugin for tracking unfulfilled user requests",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var wbw="wish";class F22 extends nQ{entityType=wbw;schema=vo;adapter=q22;constructor(A={}){super("wishlist",J22,A,Pa0)}async interceptCreate(A,Q,w){let B=await new hX0(this.logger,w).process({...A.title?{title:A.title}:{},...A.prompt?{prompt:A.prompt}:{},...A.content?{content:A.content}:{}},`wish-create-${Date.now()}`,{});if(!B.success)return{kind:"handled",result:{success:!1,error:B.error??"Failed to create wish"}};return{kind:"handled",result:{success:!0,data:{...B.entityId?{entityId:B.entityId}:{},status:B.existed?"updated":"created"}}}}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:"top-wishes",pluginId:this.id,title:"Top Wishes",section:"secondary",priority:30,rendererName:"ListWidget",dataProvider:async()=>{let w=await A.entityService.listEntities({entityType:"wish",options:{limit:10}});return I22(w),{items:w.map((B)=>({id:B.id,name:B.metadata.title,count:B.metadata.requested,priority:B.metadata.priority,status:B.metadata.status}))}}}}),{success:!0}});let Q=new hX0(this.logger,A);A.jobs.registerHandler("wish:create",{process:Q.process.bind(Q),validateAndParse:(w)=>w})}async getInstructions(){return"Wish entities record explicitly requested capabilities or desired end states whose literal completion is outside the available toolset. They may capture outcomes the assistant can advise about but cannot directly perform. They track demand, priority, and status for future capability planning; they are not a substitute for first-class entities that already support the requested action. To show the whole wishlist, call system_list once with entityType wish and omit status; only include status when the user asks for a specific wish status."}}function Bbw(A={}){return new F22(A)}var CX0=Bbw;wA();wA();N0();var Co=Z.object({title:Z.string(),target:Z.string()}),L22=Z.object({title:Z.string(),target:Z.string(),slug:Z.string().optional()}),go=LQ.extend({entityType:Z.literal("prompt"),metadata:L22});wA();K2();class Ma0 extends C2{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:go,frontmatterSchema:Co})}toMarkdown(A){let Q=this.extractBody(A.content),w=this.parseFrontMatter(A.content,Co);return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,Co),w=Z1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:w}}}}var Oa0=new Ma0;var k22={name:"@brains/prompt",version:"0.2.0-alpha.143",description:"Prompt entity type \u2014 AI prompts as editable markdown entities",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","bun-types":"^1.3.14",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var fbw="prompt";class xa0 extends nQ{entityType=fbw;schema=go;adapter=Oa0;constructor(){super("prompt",k22,{},L7)}getEntityTypeConfig(){return{embeddable:!1}}}function bP(){return new xa0}wA();N0();N0();class gX0{apiKey;fetchFn;baseUrl="https://api.unsplash.com";constructor(A,Q){this.apiKey=A,this.fetchFn=Q}async searchPhotos(A,Q){let w=new URL(`${this.baseUrl}/search/photos`);w.searchParams.set("query",A),w.searchParams.set("page",String(Q.page)),w.searchParams.set("per_page",String(Q.perPage));let B=await this.fetchFn(w.toString(),{headers:{Authorization:`Client-ID ${this.apiKey}`}});if(!B.ok)throw Error(`Unsplash API error: ${B.status} ${B.statusText}`);let $=Xbw.parse(await B.json());return{photos:$.results.map(Zbw),total:$.total,totalPages:$.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}var Ybw=Z.looseObject({id:Z.string(),description:Z.string().nullable(),alt_description:Z.string().nullable(),urls:Z.looseObject({raw:Z.url(),full:Z.url(),regular:Z.url(),small:Z.url(),thumb:Z.url()}),links:Z.looseObject({html:Z.url(),download_location:Z.url()}),user:Z.looseObject({name:Z.string(),links:Z.looseObject({html:Z.url()})}),width:Z.number().int().nonnegative(),height:Z.number().int().nonnegative()}),Xbw=Z.looseObject({total:Z.number().int().nonnegative(),total_pages:Z.number().int().nonnegative(),results:Z.array(Ybw)});function Zbw(A){return{id:A.id,description:A.description,altDescription:A.alt_description,thumbnailUrl:A.urls.thumb,imageUrl:A.urls.regular,photographerName:A.user.name,photographerUrl:A.user.links.html,sourceUrl:A.links.html,downloadLocation:A.links.download_location,width:A.width,height:A.height}}N0();async function yX0(A,Q,w,B){let $=await A.getEntity({entityType:Q,id:w});if(!$)return!1;return await A.updateEntity({entity:{...$,metadata:{...$.metadata,coverImageId:B}}}),!0}var Wbw={query:Z.string().describe("Search terms for stock photos"),perPage:Z.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:Z.number().min(1).default(1).describe("Page number")},Hbw={photoId:Z.string().describe("Photo ID from search results"),downloadLocation:Z.url().describe("Download tracking URL (required by provider ToS)"),photographerName:Z.string().describe("Photographer name for attribution"),photographerUrl:Z.url().describe("Photographer profile URL for attribution"),sourceUrl:Z.url().describe("Photo page URL on provider"),imageUrl:Z.url().describe("Image URL to download"),title:Z.string().optional().describe("Image entity title"),alt:Z.string().optional().describe("Alt text for the image"),targetEntityType:Z.string().optional().describe("Entity type to set cover image on"),targetEntityId:Z.string().optional().describe("Entity ID to set cover image on")},Kbw=Z.object({query:Z.string(),perPage:Z.number().min(1).max(30).default(10),page:Z.number().min(1).default(1)}),Ubw=Z.object({photoId:Z.string(),downloadLocation:Z.url(),photographerName:Z.string(),photographerUrl:Z.url(),sourceUrl:Z.url(),imageUrl:Z.url(),title:Z.string().optional(),alt:Z.string().optional(),targetEntityType:Z.string().optional(),targetEntityId:Z.string().optional()});function _22(A,Q){return[Dbw(A,Q),Gbw(A,Q)]}function Dbw(A,Q){return{name:`${A}_search`,description:"Search for stock photos. Returns photo candidates with preview URLs and metadata. Use stock-photo_select to materialize a chosen photo into an image entity.",inputSchema:Wbw,visibility:"anchor",sideEffects:"none",handler:async(w)=>{let B=Kbw.safeParse(w);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};try{return{success:!0,data:await Q.provider.searchPhotos(B.data.query,{page:B.data.page,perPage:B.data.perPage})}}catch($){return{success:!1,error:$ instanceof Error?$.message:"Search failed"}}}}}function Gbw(A,Q){return{name:`${A}_select`,description:"Select a stock photo from search results and materialize it as an image entity. Triggers provider download tracking per ToS. Optionally sets as cover image on a target entity.",inputSchema:Hbw,visibility:"anchor",sideEffects:"external",handler:async(w)=>{let B=Ubw.safeParse(w);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};let{photoId:$,downloadLocation:f,photographerName:Y,photographerUrl:X,sourceUrl:W,imageUrl:H,title:K,alt:U,targetEntityType:D,targetEntityId:q}=B.data,b={photographerName:Y,photographerUrl:X,sourceUrl:W},I=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:H}}}});if(I[0]){let N={imageEntityId:I[0].id,alreadyExisted:!0,attribution:b};if(D&&q)N.coverSet=await yX0(Q.entityService,D,q,I[0].id);return{success:!0,data:N}}let V=await Q.jobs.enqueue({type:"select-photo",data:{photoId:$,downloadLocation:f,photographerName:Y,photographerUrl:X,sourceUrl:W,imageUrl:H,...K!==void 0?{title:K}:{},...U!==void 0?{alt:U}:{},...D!==void 0?{targetEntityType:D}:{},...q!==void 0?{targetEntityId:q}:{}}}),L={imageEntityId:$,alreadyExisted:!1,attribution:b,jobId:V,status:"generating"};if(D&&q)L.coverSet=!1;return{success:!0,data:L}}}}wA();N0();J4();var zbw=Z.object({photoId:Z.string(),downloadLocation:Z.url(),photographerName:Z.string(),photographerUrl:Z.url(),sourceUrl:Z.url(),imageUrl:Z.url(),title:Z.string().optional(),alt:Z.string().optional(),targetEntityType:Z.string().optional(),targetEntityId:Z.string().optional()});class Ra0 extends aw{deps;constructor(A,Q){super(A,{schema:zbw,jobTypeName:"select-photo"});this.deps=Q}async process(A,Q,w){await this.reportProgress(w,{progress:10,message:"Tracking stock photo download"}),await this.deps.provider.triggerDownload(A.downloadLocation),await this.reportProgress(w,{progress:35,message:"Downloading stock photo"});let B=await this.deps.fetchImage(A.imageUrl),$=A.title??`Stock photo ${A.photoId}`,f=mX.createImageEntity({dataUrl:B,title:$,alt:A.alt??$});await this.reportProgress(w,{progress:75,message:"Saving stock photo"});let{entityId:Y}=await this.deps.entityService.createEntity({entity:{id:A.photoId,...f,metadata:{...f.metadata,sourceUrl:A.imageUrl}}}),X={imageEntityId:Y,alreadyExisted:!1};if(A.targetEntityType&&A.targetEntityId){if(X.coverSet=await yX0(this.deps.entityService,A.targetEntityType,A.targetEntityId,Y),!X.coverSet)X.warning=`Target entity ${A.targetEntityType}:${A.targetEntityId} not found; cover image not set`}return await this.reportProgress(w,{progress:100,message:"Stock photo selected"}),X}summarizeDataForLog(A){return{photoId:A.photoId,hasTarget:A.targetEntityType!==void 0}}}J4();var N22={name:"@brains/stock-photo",version:"0.2.0-alpha.143",description:"Stock photo search and selection \u2014 Unsplash provider",dependencies:{"@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var bbw=Z.object({provider:Z.enum(["unsplash"]).default("unsplash"),apiKey:Z.string().optional().describe("Stock photo provider API key")});class va0 extends aQ{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",N22,A,bbw);this.deps=Q}async getTools(){if(!this.config.apiKey)return[];if(this.cachedTools)return this.cachedTools;let A=this.getContext(),Q=this.createProvider();return this.cachedTools=_22(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??TW,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new Ra0(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??TW}))}createProvider(){return new gX0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function ha0(A={},Q={}){return new va0(A,Q)}wA();N0();wA();wA();N0();var j22=Z.enum(["ai","foundation","work"]),P22=Z.object({suffix:j22,title:Z.string(),body:Z.string(),linkLabel:Z.string(),linkHref:Z.string()}),yo=Z.object({eyebrow:Z.string(),headline:Z.string(),cards:Z.array(P22).min(1)}),Ca0=Z.object({title:Z.string(),slug:Z.string(),status:Z.enum(["draft","published"])}),Vbw=Z.object({title:Z.string(),slug:Z.string(),status:Z.enum(["draft","published"])}),Eo=LQ.extend({entityType:Z.literal("ecosystem-section"),metadata:Vbw});class M22 extends C2{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:Eo,frontmatterSchema:Ca0})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var ga0=new M22;N0();function Ibw(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function ya0(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function To(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function EX0(A){let Q=Ibw(A),B=ya0(Q,"Cards").split(/^### Card \d+\s*$/m).map(($)=>$.trim()).filter(Boolean);return yo.parse({eyebrow:ya0(Q,"Eyebrow"),headline:ya0(Q,"Headline"),cards:B.map(($)=>({suffix:To($,"Suffix"),title:To($,"Title"),body:To($,"Body"),linkLabel:To($,"Link Label"),linkHref:To($,"Link Href")}))})}function O22(A){return["# Ecosystem Section","","## Eyebrow",A.eyebrow,"","## Headline",A.headline,"","## Cards","",...A.cards.flatMap((Q,w)=>[`### Card ${w+1}`,"","#### Suffix",Q.suffix,"","#### Title",Q.title,"","#### Body",Q.body,"","#### Link Label",Q.linkLabel,"","#### Link Href",Q.linkHref,""])].join(`
8530
8530
  `)}var Jbw=Z.looseObject({query:Z.object({id:Z.string().optional()}).optional()});class TX0{id="rizom-ecosystem:entities";name="Rizom Ecosystem";description="Fetches an ecosystem-section entity for rendering";async fetch(A,Q,w){let $=Jbw.parse(A??{}).query?.id??"rizom-ecosystem",f=await w.entityService.getEntity({entityType:"ecosystem-section",id:$});if(!f)throw Error(`Ecosystem section not found: ${$}`);return Q.parse(EX0(f.content))}}import{jsxDEV as kbw}from"preact/jsx-dev-runtime";var Fbw="px-6 md:px-10 xl:px-20",Lbw=`${Fbw} relative z-[1]`,x22=({id:A,className:Q,children:w})=>kbw("section",{id:A,className:_2(Lbw,Q),children:w},void 0,!1,void 0,this);import{jsxDEV as SX0}from"preact/jsx-dev-runtime";var _bw=new Map([["work","text-accent"],["foundation","text-secondary"],["ai","text-accent-bright"]]),R22=({name:A="rizom",brandSuffix:Q,className:w,dotClassName:B,suffixClassName:$})=>{let f=_bw.get(Q);return SX0("span",{className:_2("inline-flex items-baseline gap-0 font-display font-medium tracking-[-0.015em] [font-variation-settings:'opsz'_24]",w),children:[SX0("span",{className:"text-theme",children:A},void 0,!1,void 0,this),SX0("span",{className:_2(f??"text-accent",B),children:"."},void 0,!1,void 0,this),SX0("span",{className:_2("italic font-normal text-theme-muted",$),children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{Fragment as Ea0}from"preact";import{jsxDEV as So}from"preact/jsx-dev-runtime";var Nbw=/(\*[^*]+\*)/;function v22(A,Q){let w=A.split(`
8531
- `);return So(Ea0,{children:w.map((B,$)=>So(Ea0,{children:[$>0&&So("br",{},void 0,!1,void 0,this),B.split(Nbw).map((f,Y)=>{if(f.length>=3&&f.startsWith("*")&&f.endsWith("*"))return So("span",{className:Q,children:f.slice(1,-1)},Y,!1,void 0,this);return So(Ea0,{children:f},Y,!1,void 0,this)})]},$,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as aY,Fragment as ybw}from"preact/jsx-dev-runtime";var jbw="italic text-accent font-normal",Pbw="You are here",Mbw={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},Obw={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},xbw={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},Rbw="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",vbw="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",hbw="font-label text-[10.5px] uppercase tracking-[0.22em] text-theme-muted self-start mt-[18px] pb-1 border-b border-white/10 transition-colors hover:text-theme",Cbw="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",gbw=({card:A})=>{let Q=A.linkLabel===Pbw,w=A.linkHref.trim().length===0,B=aY(ybw,{children:[aY(R22,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),aY("span",{className:`${Rbw} ${Mbw[A.suffix]}`,children:A.title},void 0,!1,void 0,this),aY("p",{className:vbw,children:A.body},void 0,!1,void 0,this),Q?aY("span",{className:Cbw,children:A.linkLabel},void 0,!1,void 0,this):aY("span",{className:hbw,children:A.linkLabel},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$=`flex flex-col gap-[14px] border-t pt-7 ${Q?Obw[A.suffix]:"border-white/10"}`;return Q||w?aY("div",{className:$,children:B},void 0,!1,void 0,this):aY("a",{href:A.linkHref,className:`${$} text-inherit no-underline transition-colors ${xbw[A.suffix]}`,children:B},void 0,!1,void 0,this)},h22=({eyebrow:A,headline:Q,cards:w})=>aY(x22,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[aY("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[aY("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),aY("h2",{className:"mt-5 font-display text-[clamp(34px,4.4vw,60px)] font-[380] leading-[1.04] tracking-[-0.02em] text-heading [font-variation-settings:'opsz'_96]",children:v22(Q,jbw)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),aY("div",{className:"mx-auto grid max-w-[1180px] grid-cols-3 gap-16 max-[768px]:grid-cols-1 max-[768px]:gap-7",children:w.map((B)=>aY(gbw,{card:B},B.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);wA();var Ta0=i1({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:yo,formatter:{parse:EX0,format:O22},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:h22}});var C22={name:"@brains/rizom-ecosystem",version:"0.2.0-alpha.142",description:"Entity-backed Rizom ecosystem section",dependencies:{"@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Tbw=Z.object({}).catchall(Z.unknown()).transform(()=>({})),Sbw="ecosystem-section";class Sa0 extends nQ{entityType=Sbw;schema=Eo;adapter=ga0;constructor(A={}){super("rizom-ecosystem",C22,A,Tbw)}getTemplates(){return{ecosystem:Ta0}}getDataSources(){return[new TX0]}}function VP(A={}){return new Sa0(A)}N0();wA();wA();K2();N0();o5();N0();wA();var y$="agent",g22="agent-discovery";var y22="agent-network",E22="AgentNetworkWidget",mo="agent-discovery:entities",ma0="agent-list",ua0="agent-detail",_8="skill",T22="skill",mX0="skill-derivation",S22="skill:project",m22="skill-derivation",u22="skill:skill-derivation",c22="skills";var uX0=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),My=Z.enum(["discovered","approved"]).describe("Discovered for review or approved for calling"),l22=Z.enum(["discovered","approved"]).describe("Discovered for review or approved for calling"),mbw=Z.enum(["professional","team","collective"]),Db=Z.object({name:Z.string(),kind:mbw,organization:Z.string().optional(),brainName:Z.string().describe("Name of the brain instance"),url:Z.string().url().describe("Brain endpoint URL"),did:Z.string().optional().describe("Decentralized identifier (public)"),repoDid:Z.string().optional().describe("ATProto repo DID"),brainDid:Z.string().optional().describe("ATProto brain DID"),anchorDid:Z.string().optional().describe("ATProto anchor DID"),cardUri:Z.string().optional().describe("ATProto brain card URI"),cardCid:Z.string().optional().describe("ATProto brain card CID"),a2aEndpoint:Z.string().url().optional().describe("A2A endpoint URL"),status:My,discoveredAt:Z.string().datetime().describe("When this agent was first discovered")}),p22=Z.object({name:Z.string(),url:Z.string().url(),status:My,discoveredAt:Z.string().datetime().optional(),slug:Z.string(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.string().url().optional()}),ubw=Z.object({name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),brainName:Z.string(),url:Z.string().url(),did:Z.string().optional(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.string().url().optional(),status:l22,discoveredAt:Z.string().datetime()}),cbw=Z.object({name:Z.string(),url:Z.string().url(),status:l22,discoveredAt:Z.string().datetime().optional(),slug:Z.string(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.string().url().optional()}),uo=F$.extend({entityType:Z.literal(y$),metadata:p22}),lbw=LQ.extend({entityType:Z.literal(y$),metadata:cbw}),co=lbw.extend({frontmatter:ubw,about:Z.string(),skills:Z.array(uX0),notes:Z.string()}),pbw=co.extend({url:Z.string().optional(),typeLabel:Z.string().optional()}),ibw=co.extend({url:Z.string(),typeLabel:Z.string()});N0();var dbw=Z.array(uX0);function i22(A){let Q=dbw.safeParse(A);if(!Q.success||Q.data.length===0)return"";return Q.data.map((w)=>{let B=w.tags.length>0?` [${w.tags.join(", ")}]`:"";return`- ${w.name}: ${w.description}${B}`}).join(`
8531
+ `);return So(Ea0,{children:w.map((B,$)=>So(Ea0,{children:[$>0&&So("br",{},void 0,!1,void 0,this),B.split(Nbw).map((f,Y)=>{if(f.length>=3&&f.startsWith("*")&&f.endsWith("*"))return So("span",{className:Q,children:f.slice(1,-1)},Y,!1,void 0,this);return So(Ea0,{children:f},Y,!1,void 0,this)})]},$,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as aY,Fragment as ybw}from"preact/jsx-dev-runtime";var jbw="italic text-accent font-normal",Pbw="You are here",Mbw={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},Obw={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},xbw={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},Rbw="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",vbw="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",hbw="font-label text-[10.5px] uppercase tracking-[0.22em] text-theme-muted self-start mt-[18px] pb-1 border-b border-white/10 transition-colors hover:text-theme",Cbw="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",gbw=({card:A})=>{let Q=A.linkLabel===Pbw,w=A.linkHref.trim().length===0,B=aY(ybw,{children:[aY(R22,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),aY("span",{className:`${Rbw} ${Mbw[A.suffix]}`,children:A.title},void 0,!1,void 0,this),aY("p",{className:vbw,children:A.body},void 0,!1,void 0,this),Q?aY("span",{className:Cbw,children:A.linkLabel},void 0,!1,void 0,this):aY("span",{className:hbw,children:A.linkLabel},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$=`flex flex-col gap-[14px] border-t pt-7 ${Q?Obw[A.suffix]:"border-white/10"}`;return Q||w?aY("div",{className:$,children:B},void 0,!1,void 0,this):aY("a",{href:A.linkHref,className:`${$} text-inherit no-underline transition-colors ${xbw[A.suffix]}`,children:B},void 0,!1,void 0,this)},h22=({eyebrow:A,headline:Q,cards:w})=>aY(x22,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[aY("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[aY("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),aY("h2",{className:"mt-5 font-display text-[clamp(34px,4.4vw,60px)] font-[380] leading-[1.04] tracking-[-0.02em] text-heading [font-variation-settings:'opsz'_96]",children:v22(Q,jbw)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),aY("div",{className:"mx-auto grid max-w-[1180px] grid-cols-3 gap-16 max-[768px]:grid-cols-1 max-[768px]:gap-7",children:w.map((B)=>aY(gbw,{card:B},B.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);wA();var Ta0=i1({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:yo,formatter:{parse:EX0,format:O22},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:h22}});var C22={name:"@brains/rizom-ecosystem",version:"0.2.0-alpha.143",description:"Entity-backed Rizom ecosystem section",dependencies:{"@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Tbw=Z.object({}).catchall(Z.unknown()).transform(()=>({})),Sbw="ecosystem-section";class Sa0 extends nQ{entityType=Sbw;schema=Eo;adapter=ga0;constructor(A={}){super("rizom-ecosystem",C22,A,Tbw)}getTemplates(){return{ecosystem:Ta0}}getDataSources(){return[new TX0]}}function VP(A={}){return new Sa0(A)}N0();wA();wA();K2();N0();o5();N0();wA();var y$="agent",g22="agent-discovery";var y22="agent-network",E22="AgentNetworkWidget",mo="agent-discovery:entities",ma0="agent-list",ua0="agent-detail",_8="skill",T22="skill",mX0="skill-derivation",S22="skill:project",m22="skill-derivation",u22="skill:skill-derivation",c22="skills";var uX0=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),My=Z.enum(["discovered","approved"]).describe("Discovered for review or approved for calling"),l22=Z.enum(["discovered","approved"]).describe("Discovered for review or approved for calling"),mbw=Z.enum(["professional","team","collective"]),Db=Z.object({name:Z.string(),kind:mbw,organization:Z.string().optional(),brainName:Z.string().describe("Name of the brain instance"),url:Z.string().url().describe("Brain endpoint URL"),did:Z.string().optional().describe("Decentralized identifier (public)"),repoDid:Z.string().optional().describe("ATProto repo DID"),brainDid:Z.string().optional().describe("ATProto brain DID"),anchorDid:Z.string().optional().describe("ATProto anchor DID"),cardUri:Z.string().optional().describe("ATProto brain card URI"),cardCid:Z.string().optional().describe("ATProto brain card CID"),a2aEndpoint:Z.string().url().optional().describe("A2A endpoint URL"),status:My,discoveredAt:Z.string().datetime().describe("When this agent was first discovered")}),p22=Z.object({name:Z.string(),url:Z.string().url(),status:My,discoveredAt:Z.string().datetime().optional(),slug:Z.string(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.string().url().optional()}),ubw=Z.object({name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),brainName:Z.string(),url:Z.string().url(),did:Z.string().optional(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.string().url().optional(),status:l22,discoveredAt:Z.string().datetime()}),cbw=Z.object({name:Z.string(),url:Z.string().url(),status:l22,discoveredAt:Z.string().datetime().optional(),slug:Z.string(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.string().url().optional()}),uo=F$.extend({entityType:Z.literal(y$),metadata:p22}),lbw=LQ.extend({entityType:Z.literal(y$),metadata:cbw}),co=lbw.extend({frontmatter:ubw,about:Z.string(),skills:Z.array(uX0),notes:Z.string()}),pbw=co.extend({url:Z.string().optional(),typeLabel:Z.string().optional()}),ibw=co.extend({url:Z.string(),typeLabel:Z.string()});N0();var dbw=Z.array(uX0);function i22(A){let Q=dbw.safeParse(A);if(!Q.success||Q.data.length===0)return"";return Q.data.map((w)=>{let B=w.tags.length>0?` [${w.tags.join(", ")}]`:"";return`- ${w.name}: ${w.description}${B}`}).join(`
8532
8532
  `)}function d22(A){if(!A.trim())return[];let Q=[];for(let w of A.split(`
8533
8533
  `)){let B=w.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/);if(!B)continue;let $=B[1]??"",f=B[2]??"",Y=B[3],X=Y?Y.split(",").map((W)=>W.trim()).filter(Boolean):[];Q.push({name:$,description:f,tags:X})}return Q}var nbw=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),rbw=Z.object({about:Z.string(),skills:Z.array(nbw),notes:Z.string()}),n22=new G6(rbw,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:i22,parser:d22},{key:"notes",label:"Notes",type:"string"}]});class p4 extends C2{constructor(){super({entityType:y$,purpose:"A saved remote peer-brain contact in the local agent directory.",schema:uo,frontmatterSchema:Db})}fromMarkdown(A){let Q=this.parseFrontMatter(A,Db),w=zO(Q.url);return{content:A,entityType:y$,metadata:{name:Q.name,url:Q.url,status:Q.status,discoveredAt:Q.discoveredAt,slug:w,...Q.repoDid&&{repoDid:Q.repoDid},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},...Q.cardUri&&{cardUri:Q.cardUri},...Q.cardCid&&{cardCid:Q.cardCid},...Q.a2aEndpoint&&{a2aEndpoint:Q.a2aEndpoint}}}}createAgentContent(A){let Q={name:A.name,kind:A.kind,...A.organization&&{organization:A.organization},brainName:A.brainName,url:A.url,...A.did&&{did:A.did},...A.repoDid&&{repoDid:A.repoDid},...A.brainDid&&{brainDid:A.brainDid},...A.anchorDid&&{anchorDid:A.anchorDid},...A.cardUri&&{cardUri:A.cardUri},...A.cardCid&&{cardCid:A.cardCid},...A.a2aEndpoint&&{a2aEndpoint:A.a2aEndpoint},status:My.parse(A.status),discoveredAt:A.discoveredAt},w=n22.format({about:A.about,skills:A.skills,notes:A.notes});return this.buildMarkdown(w,Q)}parseAgentContent(A){let Q=this.extractBody(A);if(!Q.trim())return{about:"",skills:[],notes:""};try{let w=n22.parse(Q);return{about:w.about,skills:w.skills,notes:w.notes}}catch{return{about:"",skills:[],notes:""}}}parseEntity(A){return{frontmatter:this.parseFrontMatter(A.content,Db),body:this.parseAgentContent(A.content)}}}wA();N0();var obw=new p4,r22=Z.enum(["discovered","approved"]),sbw=Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional(),baseUrl:Z.string().optional(),status:r22.optional()}),abw=Z.looseObject({entityType:Z.string().optional(),query:sbw.optional()});function tbw(A){let Q=o2(A.content,Db),w=obw.parseAgentContent(A.content);return co.parse({...A,frontmatter:Q.metadata,about:w.about,skills:w.skills,notes:w.notes})}class cX0 extends q5{id=mo;name="Agent Directory DataSource";description="Fetches and transforms agent entities for rendering";config={entityType:y$,defaultSort:[{field:"discoveredAt",direction:"desc"}],defaultLimit:50,lookupField:"slug",enableNavigation:!0};constructor(A){super(A)}transformEntity(A){return tbw(A)}buildDetailResult(A,Q){return{agent:A,prevAgent:Q?.prev??null,nextAgent:Q?.next??null}}parseQuery(A){let Q=abw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}buildListResult(A,Q,w){let B=r22.safeParse(w.status);return{agents:A,pagination:Q,baseUrl:w.baseUrl,selectedStatus:B.success?B.data:"all"}}async fetch(A,Q,w){let{query:B}=this.parseQuery(A);if(B.id)return super.fetch(A,Q,w);let{items:$,pagination:f}=await this.fetchList(B,w.entityService,B.status?{filter:{metadata:{status:B.status}}}:void 0);return Q.parse(this.buildListResult($,f,B))}}wA();N0();g6();wA();async function lX0(A,Q){let B=`${(A.startsWith("http")?A:`https://${A}`).replace(/\/$/,"")}/.well-known/agent-card.json`;try{let $=await Q(B);if(!$.ok)return null;let f=await $.json();return Gm(f)}catch{return null}}function IP(A){let Q=A.trim();if(Q.startsWith("http://")||Q.startsWith("https://"))try{return new URL(Q).hostname}catch{return Q}let w=Q.match(/https?:\/\/[^\s]+?(?=[.,;:!?)]*(?:\s|$))/);if(w)try{return new URL(w[0]).hostname}catch{return w[0]}if(/^[^\s]+\.[^\s]+$/.test(Q))return Q;return""}K2();var ebw=new p4;function o22(A){return A.trim().toLowerCase().replace(/[_\s]+/g,"-")}function CF(A){let Q=new Set,w=[];for(let B of A){let $=o22(B);if(!$||Q.has($))continue;Q.add($),w.push($)}return w}function AVw(A,Q){if(Q.count!==A.count)return Q.count-A.count;return A.tag.localeCompare(Q.tag)}async function s22(A,Q={}){let w=Q.minCount??1,B=Q.topN??12,$=Q.visibilityScope??"public",f=new Map,[Y,X]=await Promise.all([A.entityService.listEntities({entityType:_8,options:{filter:{visibilityScope:$}}}),A.entityService.listEntities({entityType:y$,options:{filter:{visibilityScope:$}}})]),W=(H)=>{for(let K of CF(H))f.set(K,(f.get(K)??0)+1)};for(let H of Y)W(H.metadata.tags);for(let H of X){let K=ebw.parseAgentContent(H.content);W(K.skills.flatMap((U)=>U.tags))}return Array.from(f.entries()).map(([H,K])=>({tag:H,count:K})).filter((H)=>H.count>=w).sort(AVw).slice(0,B)}function a22(A){if(A.length===0)return"";return["Current agent-directory tag vocabulary (reuse existing tags where they fit; propose new only when nothing does):",...A.map(({tag:Q,count:w})=>`- ${Q} (${w})`)].join(`
8534
8534
  `)}var QVw=new p4;function pX0(A,Q={}){let w=A.anchor?.name??A.brainName,B=A.anchor?.kind??"professional",$=[];if(A.anchor?.description)$.push(A.anchor.description);if(A.description)$.push(A.description);let f=Q.status??"discovered",Y=new Date().toISOString();return{content:QVw.createAgentContent({name:w,kind:B,...A.anchor?.organization&&{organization:A.anchor.organization},brainName:A.brainName,url:A.url,status:f,discoveredAt:Y,about:$.join(`
@@ -8629,7 +8629,7 @@ ${A.guidance}`:$}}function Y22(A){return{...A,evidence:A.evidence.map((Q)=>({...
8629
8629
  setTagFilter("all");
8630
8630
  });
8631
8631
  })();`;import{jsxDEV as Jw}from"preact/jsx-dev-runtime";function HVw({item:A}){return Jw("li",{class:"list-item",children:[Jw("div",{class:"list-main",children:[Jw("span",{class:"list-name",children:A.name},void 0,!1,void 0,this),Jw("span",{class:"list-desc",children:A.description},void 0,!1,void 0,this),A.tags.length>0&&Jw("div",{class:"list-tags",children:A.tags.map((Q)=>Jw("span",{class:"tag",children:Q},`${A.id}:${Q}`,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Jw("div",{class:"list-meta",children:A.status==="discovered"&&Jw("span",{class:"pill pill--warn",children:"review"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function KVw({item:A}){return Jw("li",{class:"list-item agent-network-skill-row","data-agent-network-skill-row":!0,"data-agent-network-tags":JSON.stringify(A.tags),children:[Jw("div",{class:"list-main",children:Jw("span",{class:"list-name",children:A.name},void 0,!1,void 0,this)},void 0,!1,void 0,this),Jw("div",{class:"list-meta",children:Jw("span",{class:`agent-network-source${A.sourceType==="brain"?" is-brain":""}`,children:A.sourceLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function UVw({kind:A,items:Q,active:w}){return Jw("div",{class:`agent-network-panel${w?" is-active":""}`,"data-agent-network-panel":A,children:Q.length>0?Jw("ul",{class:"list agent-network-list",children:Q.map((B)=>Jw(HVw,{item:B},B.id,!1,void 0,this))},void 0,!1,void 0,this):Jw("p",{class:"agent-network-empty",children:"Nothing to show yet."},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function DVw({skills:A,count:Q,filters:w}){return Jw("div",{class:"agent-network-panel","data-agent-network-panel":"skills",children:[Jw("div",{class:"agent-network-filter-row",role:"tablist","aria-label":"Filter skills by tag",children:[Jw("button",{class:"agent-network-filter is-active",type:"button","data-agent-network-tag-filter":"all","aria-pressed":"true",children:[Jw("span",{class:"count",children:Q},void 0,!1,void 0,this),Jw("span",{class:"label",children:"all"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),w.map((B)=>Jw("button",{class:`agent-network-filter${B.variant==="gap"?" is-gap":""}`,type:"button","data-agent-network-tag-filter":B.tag,"aria-pressed":"false",children:[Jw("span",{class:"count",children:B.count},void 0,!1,void 0,this),Jw("span",{class:"label",children:B.tag},void 0,!1,void 0,this)]},B.tag,!0,void 0,this))]},void 0,!0,void 0,this),A.length>0?Jw("ul",{class:"list agent-network-list agent-network-skills-list",children:A.map((B)=>Jw(KVw,{item:B},B.id,!1,void 0,this))},void 0,!1,void 0,this):Jw("p",{class:"agent-network-empty",children:"Nothing to show yet."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function pa0({data:A}){let Q=la0.safeParse(A);if(!Q.success)return Jw("p",{class:"muted",children:"Nothing to show yet."},void 0,!1,void 0,this);let w=Q.data;return Jw("div",{"data-agent-network-widget":!0,"data-agent-network-view":"agents",children:[Jw("div",{class:"agent-network-view-tabs",role:"tablist","aria-label":"Browse the agent network",children:[Jw("button",{class:"agent-network-view-tab is-active",type:"button","data-agent-network-view-tab":"agents","aria-pressed":"true",children:["Agents",Jw("span",{class:"agent-network-view-count",children:w.counts.agents},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Jw("button",{class:"agent-network-view-tab",type:"button","data-agent-network-view-tab":"skills","aria-pressed":"false",children:["Skills",Jw("span",{class:"agent-network-view-count",children:w.counts.skills},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Jw("div",{class:"agent-network-kind-tabs",role:"tablist","aria-label":"Filter agents by kind",children:iX0.map((B)=>{let $=B==="all";return Jw("button",{class:`agent-network-kind-tab${$?" is-active":""}`,type:"button","data-agent-network-kind-tab":B,"aria-pressed":$?"true":"false",children:[Jw("span",{class:"agent-network-kind-count",children:w.agents[B].length},void 0,!1,void 0,this),Jw("span",{class:"agent-network-kind-label",children:B},void 0,!1,void 0,this)]},B,!0,void 0,this)})},void 0,!1,void 0,this),iX0.map((B)=>Jw(UVw,{kind:B,items:w.agents[B],active:B==="all"},B,!1,void 0,this)),Jw(DVw,{skills:w.skills,count:w.counts.skills,filters:w.skillFilters},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function $Q2(A,Q){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:y22,pluginId:Q,title:"Agent Network",section:"secondary",priority:15,rendererName:E22,component:pa0,clientScript:dX0,dataProvider:async()=>BQ2(A)}}),{success:!0}})}K2();var fQ2=new p4;function GVw(A){return A.skills.map((Q)=>({name:Q.name,description:Q.description,tags:Q.tags??[]}))}function zVw(A){return new URL(A).hostname}function qVw(A){return[`ATProto card: ${A.uri}`,`ATProto card CID: ${A.cid}`,`ATProto repo DID: ${A.repoDid}`].join(`
8632
- `)}function bVw(A){let Q=A.record.brain.did,w=A.record.anchor.did;return{agentId:A.agent.id,name:A.agent.metadata.name,url:A.agent.metadata.url,status:A.agent.metadata.status,repoDid:A.repoDid,...Q&&{brainDid:Q},...w&&{anchorDid:w},cardUri:A.uri,cardCid:A.cid}}async function VVw(A,Q,w){await A.messaging.send({type:Q,payload:w,broadcast:!0})}async function IVw(A,Q,w=new Date().toISOString()){let{record:B}=Q,$=zVw(B.siteUrl),f=await A.entityService.getEntity({entityType:"agent",id:$}),Y=f?fQ2.parseEntity(f):void 0,X=B.brain.did,W=B.anchor.did,H=GVw(B),K=f?.metadata.status??"discovered",U=f?.metadata.url??B.siteUrl,D=f?.metadata.slug??zO(U),q=f?.metadata.name??B.anchor.name,b=Y?.frontmatter.kind??B.anchor.kind,I=f?.metadata.discoveredAt??w,V=B.brain.purpose.length>0?B.brain.purpose:Y?.body.about??"",L=H.length>0?H:Y?.body.skills??[],N={...f?.metadata??{},name:q,url:U,status:K,discoveredAt:I,slug:D,repoDid:Q.repoDid,...X&&{brainDid:X},...W&&{anchorDid:W},cardUri:Q.uri,cardCid:Q.cid},k=fQ2.createAgentContent({name:q,kind:b,...Y?.frontmatter.organization&&{organization:Y.frontmatter.organization},brainName:B.brain.name,url:U,...X&&{did:X,brainDid:X},...W&&{anchorDid:W},repoDid:Q.repoDid,cardUri:Q.uri,cardCid:Q.cid,...Y?.frontmatter.a2aEndpoint&&{a2aEndpoint:Y.frontmatter.a2aEndpoint},status:K,discoveredAt:I,about:V,skills:L,notes:qVw({repoDid:Q.repoDid,uri:Q.uri,cid:Q.cid})});if(f){let R={...f,content:k,metadata:N,updated:w};return await A.entityService.updateEntity({entity:R}),{agent:R,created:!1}}let x={id:$,entityType:"agent",content:k,metadata:N,contentHash:"",visibility:"public",created:w,updated:w};return await A.entityService.createEntity({entity:x}),{agent:x,created:!0}}function YQ2(A){A.messaging.subscribe(Md,async(Q)=>{let w=ku0.parse(Q.payload),B=await IVw(A,w),$=bVw({agent:B.agent,repoDid:w.repoDid,uri:w.uri,cid:w.cid,record:w.record});return await VVw(A,B.created?Fu0:Lu0,$),{success:!0,data:$}})}function XQ2(){return["Agent entities represent saved peer-brain contacts in the local agent directory. List saved agent contacts with system_list on entityType agent. For expertise-match or recommendation questions over the user's agent network (for example who to consult/ask about a topic), immediately call one system_search with scope.kind type, scope.entityType agent, and the requested topic/skill; do not run parallel synonym searches unless the first result is inconclusive. Do not answer with generic role categories or offer to search later. If any result is plausible, suggest the saved agent by name/domain, include its exact callable id/domain from the search result (for example: Brand Studio, agent id brand-studio.example), and briefly explain the matching skill evidence. Prefer approved contacts over discovered contacts when both plausibly match; mention discovered contacts only with a clear review/confidence caveat.","If the previous assistant turn offered to search or narrow down the agent network, treat short affirmative follow-ups like please, yes, yes please, do that, or go ahead as consent to run that same agent expertise search using the topic from the prior user request.","Agent contact records are verified A2A peer contacts: connect/save them with agent_connect and a url source; a raw domain is a valid source, so preserve a bare domain as the bare domain string. agent_connect verifies the remote Agent Card and saves the contact as approved for future outbound calls; it does not grant the remote agent inbound trusted access. If an exact-domain agent_call cannot verify or contact an unsaved domain, tell the user they can add/save/connect that domain as a contact, and a short follow-up like 'please add' should call agent_connect for the same domain without requiring a separate approval gate.","Agent lifecycle is tracked with status fields such as discovered and approved; approval operations are system_update field changes for already saved discovered contacts. If the user asks to approve a saved agent contact by exact id such as approval-candidate.io, call system_update on entityType agent with that id and the requested status; do not use agent_connect for approval. If the user asks to trust or untrust a saved agent for inbound A2A access, use agent_set_trust_level; do not use system_update because inbound trust is runtime auth state, not agent entity metadata.","When the user asks to contact/call/ask a saved contact by a human display name or anchor/contact name (for example 'Ask my contact Yeehaa ...'), first resolve that name against saved agent entities with system_search scoped to entityType agent unless the user already supplied an exact domain-like id. Then pass agent_call.agent as the saved agent entity id/domain from the search result (for example yeehaa.io or brand-studio.example), not the display name, anchorName, or brainName. When calling a recommended or previously searched saved agent, also use the saved agent entity id/domain from the search result. Calling remote agents and saving local contact records are separate capabilities. Only approved saved agents are active call targets; do not contact discovered or otherwise unapproved contacts."].join(" ")}NB();N0();import{jsxDEV as ZQ2}from"preact/jsx-dev-runtime";function nX0(A){try{return new URL(A).hostname}catch{return A}}var rX0=({name:A,className:Q=""})=>{let w=A.charAt(0).toUpperCase(),B=0;for(let f=0;f<A.length;f++)B=A.charCodeAt(f)+((B<<5)-B);let $=Math.abs(B)%360;return ZQ2("div",{className:`flex items-center justify-center rounded-full text-white font-bold flex-shrink-0 ${Q}`,style:{backgroundColor:`hsl(${$}, 55%, 45%)`},children:w},void 0,!1,void 0,this)},oX0=({kind:A,size:Q="md"})=>{let B={professional:"bg-status-success text-status-success",team:"bg-status-info text-status-info",collective:"bg-brand/10 text-brand"}[A]??"bg-status-neutral text-status-neutral";return ZQ2("span",{className:`inline-flex items-center rounded-full font-medium ${Q==="sm"?"px-2 py-0.5 text-xs":"px-2.5 py-0.5 text-[13px]"} ${B}`,children:A},void 0,!1,void 0,this)};import{jsxDEV as c2,Fragment as LVw}from"preact/jsx-dev-runtime";var JVw=({skills:A})=>{if(A.length===0)return null;return c2("div",{className:"flex gap-1.5 flex-wrap mt-2",children:A.map((Q)=>c2("span",{className:"text-[11px] px-2 py-0.5 bg-theme-subtle rounded-md text-theme-muted",children:Q.name},Q.name,!1,void 0,this))},void 0,!1,void 0,this)};function FVw(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric"})}function WQ2(A,Q,w){let B=new URLSearchParams({status:Q});if(w>1)B.set("page",String(w));return`${A}?${B.toString()}`}var ia0=({agent:A})=>{let{frontmatter:Q,about:w,skills:B,url:$}=A,f=Q.status==="approved";return c2("a",{href:$,className:`flex items-start gap-5 p-6 rounded-xl border border-theme bg-theme-subtle hover:shadow-lg transition-shadow ${f?"":"opacity-70"}`,children:[c2(rX0,{name:Q.name,className:"w-12 h-12 text-lg"},void 0,!1,void 0,this),c2("div",{className:"flex-1 min-w-0",children:[c2("div",{className:"flex items-center gap-2 mb-1 flex-wrap",children:[c2("span",{className:"text-lg font-semibold text-heading",children:Q.name},void 0,!1,void 0,this),c2(oX0,{kind:Q.kind,size:"sm"},void 0,!1,void 0,this),Q.organization&&c2("span",{className:"text-xs text-theme-muted",children:["\xB7 ",Q.organization]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),c2("div",{className:"text-sm text-theme-muted mb-1",children:Q.brainName},void 0,!1,void 0,this),w&&c2("p",{className:"text-sm text-theme-muted line-clamp-2 mb-0",children:w},void 0,!1,void 0,this),f&&c2(JVw,{skills:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c2("div",{className:"flex flex-col items-end gap-1 flex-shrink-0 text-right",children:[c2("span",{className:"text-xs text-theme-muted",children:nX0(Q.url)},void 0,!1,void 0,this),c2("span",{className:"text-[11px] text-theme-muted opacity-60",children:f?`Discovered ${FVw(Q.discoveredAt)}`:"Discovered \xB7 approve before calling"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},HQ2=({agents:A,pageTitle:Q,pagination:w,baseUrl:B="/agents",selectedStatus:$})=>{let f=Q??"Agent Directory",Y=w?.totalItems??A.length,X=A.filter((D)=>D.frontmatter.status==="approved"),W=A.filter((D)=>D.frontmatter.status==="discovered"),H=X.length,K=W.length,U=`Your network of ${Y} ${Y===1?"brain":"brains"} and their anchors`;return c2(LVw,{children:[c2(lQ,{title:f,description:U},void 0,!1,void 0,this),c2("div",{className:"agent-list bg-theme",children:c2("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[c2("div",{className:"mb-8 pb-6 border-b border-theme",children:[c2("h1",{className:"text-4xl font-bold text-heading mb-2",children:f},void 0,!1,void 0,this),c2("p",{className:"text-theme-muted mb-4",children:U},void 0,!1,void 0,this),c2("div",{className:"flex flex-wrap gap-2 text-sm mb-4",children:[c2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-heading",children:[Y," total"]},void 0,!0,void 0,this),c2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-status-success",children:[H," approved"]},void 0,!0,void 0,this),c2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-theme-muted",children:[K," discovered"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),c2("div",{className:"flex flex-wrap gap-2 text-sm",children:[c2("a",{href:B,className:`px-3 py-1 rounded-full border transition-colors ${$==="all"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"All"},void 0,!1,void 0,this),c2("a",{href:`${B}?status=approved`,className:`px-3 py-1 rounded-full border transition-colors ${$==="approved"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"Approved"},void 0,!1,void 0,this),c2("a",{href:`${B}?status=discovered`,className:`px-3 py-1 rounded-full border transition-colors ${$==="discovered"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"Discovered"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),$==="all"&&X.length>0&&c2("section",{className:"mb-10",children:[c2("div",{className:"flex items-center justify-between mb-4",children:[c2("h2",{className:"text-lg font-semibold text-heading",children:"Approved brains"},void 0,!1,void 0,this),c2("span",{className:"text-sm text-theme-muted",children:X.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c2("div",{className:"flex flex-col gap-4",children:X.map((D)=>c2(ia0,{agent:D},D.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$==="all"&&W.length>0&&c2("section",{children:[c2("div",{className:"flex items-center justify-between mb-4",children:[c2("div",{children:[c2("h2",{className:"text-lg font-semibold text-heading",children:"Discovered brains"},void 0,!1,void 0,this),c2("p",{className:"text-sm text-theme-muted",children:"Review and approve these before calling them."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c2("span",{className:"text-sm text-theme-muted",children:W.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c2("div",{className:"flex flex-col gap-4",children:W.map((D)=>c2(ia0,{agent:D},D.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$!=="all"&&A.length>0&&c2("section",{children:[c2("div",{className:"flex items-center justify-between mb-4",children:[c2("h2",{className:"text-lg font-semibold text-heading",children:$==="approved"?"Approved brains":"Discovered brains"},void 0,!1,void 0,this),c2("span",{className:"text-sm text-theme-muted",children:A.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c2("div",{className:"flex flex-col gap-4",children:A.map((D)=>c2(ia0,{agent:D},D.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length===0&&c2("p",{className:"text-center text-theme-muted py-16",children:"No agents in your directory yet."},void 0,!1,void 0,this),w&&w.totalPages>1&&$==="all"&&c2("div",{className:"mt-12",children:c2(iq,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:B},void 0,!1,void 0,this)},void 0,!1,void 0,this),w&&w.totalPages>1&&$!=="all"&&c2("nav",{"aria-label":"Pagination",className:"flex items-center justify-center gap-3 mt-12",children:[w.hasPrevPage?c2("a",{href:WQ2(B,$,w.currentPage-1),className:"px-3 py-2 rounded-md border border-theme text-sm text-theme-muted hover:text-heading transition-colors",children:"\u2190 Prev"},void 0,!1,void 0,this):c2("span",{className:"px-3 py-2 rounded-md border border-theme text-sm text-theme-muted opacity-50",children:"\u2190 Prev"},void 0,!1,void 0,this),c2("span",{className:"text-sm text-theme-muted",children:["Page ",w.currentPage," of ",w.totalPages]},void 0,!0,void 0,this),w.hasNextPage?c2("a",{href:WQ2(B,$,w.currentPage+1),className:"px-3 py-2 rounded-md border border-theme text-sm text-theme-muted hover:text-heading transition-colors",children:"Next \u2192"},void 0,!1,void 0,this):c2("span",{className:"px-3 py-2 rounded-md border border-theme text-sm text-theme-muted opacity-50",children:"Next \u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as j2,Fragment as jVw}from"preact/jsx-dev-runtime";function kVw(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}var po=({children:A})=>j2("h2",{className:"text-sm font-semibold text-theme-muted uppercase tracking-wide mb-3",children:A},void 0,!1,void 0,this),_Vw=({skill:A})=>j2("div",{className:"flex items-start gap-3 px-4 py-3 bg-theme-subtle rounded-lg",children:[j2("div",{className:"flex-1",children:[j2("div",{className:"text-sm font-semibold text-heading",children:A.name},void 0,!1,void 0,this),j2("div",{className:"text-[13px] text-theme-muted",children:A.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.tags.length>0&&j2("div",{className:"flex gap-1 flex-shrink-0",children:A.tags.map((Q)=>j2("span",{className:"text-[11px] px-2 py-0.5 bg-theme rounded-md text-theme-muted",children:Q},Q,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),NVw=({label:A,value:Q,valueClassName:w})=>j2("div",{className:"flex justify-between text-[13px]",children:[j2("span",{className:"text-theme-muted",children:A},void 0,!1,void 0,this),j2("span",{className:w??"text-heading",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),KQ2=({agent:A,prevAgent:Q,nextAgent:w})=>{let{frontmatter:B,about:$,skills:f,notes:Y}=A,X=nX0(B.url),W=B.status==="approved";return j2(jVw,{children:[j2(lQ,{title:B.name,description:$||`Agent profile for ${B.name}`},void 0,!1,void 0,this),j2("article",{className:"agent-detail",children:j2("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:[j2("a",{href:"/agents",className:"text-sm text-theme-muted hover:text-brand transition-colors mb-6 inline-block",children:"\u2190 Back to Directory"},void 0,!1,void 0,this),j2("div",{className:"flex items-start gap-6 mb-8",children:[j2(rX0,{name:B.name,className:"w-[72px] h-[72px] text-3xl"},void 0,!1,void 0,this),j2("div",{children:[j2("div",{className:"flex items-center gap-3 mb-1",children:[j2("h1",{className:"text-3xl md:text-4xl font-bold text-heading",children:B.name},void 0,!1,void 0,this),j2(oX0,{kind:B.kind},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"text-base text-theme-muted mb-2",children:B.brainName},void 0,!1,void 0,this),j2("div",{className:"flex items-center gap-3 text-theme-muted",children:[B.organization&&j2("span",{className:"text-[15px]",children:B.organization},void 0,!1,void 0,this),B.organization&&j2("span",{className:"text-theme-muted opacity-40",children:"\xB7"},void 0,!1,void 0,this),j2("span",{className:"text-sm",children:["Discovered ",kVw(B.discoveredAt)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"border-b border-theme mb-8"},void 0,!1,void 0,this),!W&&j2("div",{className:"mb-8 rounded-xl border border-theme bg-theme-subtle px-5 py-4",children:[j2("div",{className:"text-sm font-semibold text-heading mb-1",children:"Saved for review"},void 0,!1,void 0,this),j2("p",{className:"text-sm text-theme-muted",children:"This brain is discovered but not approved yet, so it cannot be called until you approve it."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"flex flex-col md:flex-row gap-12",children:[j2("div",{className:"flex-[2] min-w-0",children:[$&&j2("section",{className:"mb-8",children:[j2(po,{children:"About"},void 0,!1,void 0,this),j2("p",{className:"text-[15px] text-theme leading-relaxed",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),f.length>0&&j2("section",{className:"mb-8",children:[j2(po,{children:"Skills"},void 0,!1,void 0,this),j2("div",{className:"flex flex-col gap-2.5",children:f.map((H)=>j2(_Vw,{skill:H},H.name,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Y&&j2("section",{className:"mb-8",children:[j2(po,{children:"Notes"},void 0,!1,void 0,this),j2("p",{className:"text-[15px] text-theme leading-relaxed",children:Y},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j2("aside",{className:"flex-1 md:pl-8 md:border-l border-theme-muted/20",children:[j2("section",{className:"mb-8",children:[j2(po,{children:"Brain"},void 0,!1,void 0,this),j2("div",{className:"p-4 bg-theme-subtle rounded-xl",children:[j2("div",{className:"text-[15px] font-semibold text-heading mb-1",children:B.brainName},void 0,!1,void 0,this),B.did&&j2("div",{className:"text-xs text-theme-muted font-mono",children:B.did},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j2("section",{className:"mb-8",children:[j2(po,{children:"Connection"},void 0,!1,void 0,this),j2("div",{className:"flex flex-col gap-3",children:[j2("div",{children:[j2("div",{className:"text-[13px] text-theme-muted mb-0.5",children:"Endpoint"},void 0,!1,void 0,this),j2("div",{className:"text-xs text-heading font-mono",children:B.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2(NVw,{label:"Status",value:B.status==="approved"?"Approved":"Discovered",valueClassName:B.status==="approved"?"text-status-success font-medium":"text-theme-muted"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j2("a",{href:B.url.replace(/\/a2a\/?$/,""),target:"_blank",rel:"noopener noreferrer",className:"flex items-center justify-center px-5 py-3 bg-theme-dark text-theme-inverse rounded-lg text-sm font-medium hover:opacity-90 transition-opacity",children:["Visit ",X," \u2197"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),(Q??w)&&j2("nav",{className:"mt-12 pt-6 border-t border-theme flex flex-col gap-3 md:flex-row md:items-center md:justify-between",children:[j2("div",{className:"min-h-[1px]",children:Q&&j2("a",{href:Q.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[j2("span",{children:"\u2190 Previous"},void 0,!1,void 0,this),j2("span",{className:"text-heading font-medium",children:Q.frontmatter.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),j2("div",{className:"min-h-[1px] md:text-right",children:w&&j2("a",{href:w.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[j2("span",{children:"Next \u2192"},void 0,!1,void 0,this),j2("span",{className:"text-heading font-medium",children:w.frontmatter.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};var PVw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),MVw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),OVw=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),da0=Z.enum(["discovered","approved"]),xVw=Z.enum(["professional","team","collective"]),RVw=Z.object({name:Z.string(),kind:xVw,organization:Z.string().optional(),brainName:Z.string(),url:Z.url(),did:Z.string().optional(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.url().optional(),status:da0,discoveredAt:Z.string()}),vVw=Z.object({name:Z.string(),url:Z.url(),status:da0,discoveredAt:Z.string().optional(),slug:Z.string(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.url().optional()}),sX0=Z.object({id:Z.string(),entityType:Z.literal(y$),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:PVw,metadata:vVw,contentHash:Z.string(),frontmatter:RVw,about:Z.string(),skills:Z.array(OVw),notes:Z.string(),url:Z.string(),typeLabel:Z.string()}),hVw=Z.object({agents:Z.array(sX0),pageTitle:Z.string().optional(),pagination:MVw.nullable(),baseUrl:Z.string().optional(),selectedStatus:Z.union([Z.literal("all"),da0])});function UQ2(){return{[ma0]:i1({name:ma0,description:"Agent directory list page template",schema:hVw,dataSourceId:mo,requiredPermission:"public",layout:{component:HQ2}}),[ua0]:i1({name:ua0,description:"Individual agent profile template",schema:Z.object({agent:sX0,prevAgent:sX0.nullable(),nextAgent:sX0.nullable()}),dataSourceId:mo,requiredPermission:"public",layout:{component:KQ2}})}}var Oy={name:"@brains/agent-discovery",version:"0.2.0-alpha.142",description:"Agent discovery \u2014 brain+anchor contacts and skills",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/auth-service":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/dashboard":"workspace:*","@brains/http-signatures":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var gVw=new p4;class na0 extends nQ{entityType=y$;schema=uo;adapter=gVw;constructor(){super(g22,Oy,{},L7)}createGenerationHandler(A){return new ca0(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return UQ2()}getDataSources(){return[new cX0(this.logger.child("AgentDataSource"))]}async onRegister(A){YQ2(A),$Q2(A,this.id)}async getInstructions(){return XQ2()}}function ra0(){return new na0}wA();N0();Q9();N0();var DQ2=Z.object({source:Z.object({kind:Z.literal("url"),url:Z.string().min(1).describe("Remote agent domain or URL to verify and connect. Preserve bare domains as bare domains.")}),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional()}),yVw=new p4;function EVw(A){let Q=IP(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function TVw(A,Q){return(IP(Q)||A).toLowerCase()}async function SVw(A){let{context:Q,entityId:w,card:B}=A,$=new Date().toISOString(),f=await Q.entityService.getEntity({entityType:y$,id:w}),Y=pX0(B,{status:"approved"}),W={...yVw.fromMarkdown(Y.content).metadata,...Y.metadata,a2aEndpoint:B.url};if(f){let K={...f,content:Y.content,metadata:W,updated:$};return await Q.entityService.updateEntity({entity:K}),{entity:K,created:!1}}let H={id:w,entityType:y$,content:Y.content,metadata:W,contentHash:"",visibility:"public",created:$,updated:$};return await Q.entityService.createEntity({entity:H}),{entity:H,created:!0}}function GQ2(A,Q=globalThis.fetch){let B=new vX;return{name:"agent_connect",description:"Verify and connect a remote A2A agent by fetching its Agent Card from /.well-known/agent-card.json, then save the verified contact in the local agent directory as approved for future outbound calls. This adds a directory contact; it does not message the remote agent or grant it inbound trusted access. Requires confirmation before verification and persistence. Call this tool without confirmed on the initial request; the tool returns confirmation args for the user to approve.",inputSchema:DQ2.shape,visibility:"trusted",sideEffects:"external",handler:async($,f)=>{let Y=DQ2.safeParse($);if(!Y.success)return{success:!1,error:`Invalid input: ${Y.error.issues.map((K)=>`${K.path.join(".")}: ${K.message}`).join(", ")}`};let X=Y.data,W=EVw(X.source.url);if(!W)return{success:!1,error:"Provide a valid remote agent domain or URL to connect.",code:"invalid_agent_url"};try{A.permissions.assertEntityActionAllowed(y$,"create",f)}catch(K){return{success:!1,error:K instanceof Error?K.message:String(K)}}if(X.confirmed){let K=X.confirmationToken,U=B.validate(K,X);if(U.status==="missing")return{success:!1,error:"No pending agent connection confirmation found. Please request connection again and confirm the new approval."};if(U.status==="mismatch")return{success:!1,error:"Confirmed agent connection arguments do not match the pending approval. Please request connection again and confirm the new approval."};let D=await lX0(W.fetchTarget,Q);if(!D)return{success:!1,error:`Could not verify an A2A Agent Card for ${W.domain}.`,code:"not_an_agent"};let q=TVw(W.domain,D.url),{entity:b,created:I}=await SVw({context:A,entityId:q,sourceUrl:X.source.url,card:D});return{success:!0,data:{status:b.metadata.status,entityId:b.id,connected:!0,created:I,a2aEndpoint:D.url,skills:D.skills.map((V)=>({name:V.name,description:V.description,tags:V.tags}))}}}let H=B.create((K)=>({source:X.source,confirmed:!0,confirmationToken:K}));return{needsConfirmation:!0,toolName:"agent_connect",summary:`Verify and connect agent ${W.domain}?`,preview:`This will fetch and validate ${W.domain}'s A2A Agent Card, then save the verified contact as approved for future outbound calls. It will not message the remote agent or grant it inbound trusted access.`,args:H}}}}Q9();N0();var mVw=Z.enum(["public","trusted"]),zQ2=Z.object({agent:Z.string().min(1).describe("Saved agent id, domain, or URL whose inbound A2A trust to set."),level:mVw.describe("Inbound A2A trust level. Use trusted to grant trusted inbound access, public to revoke it."),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional(),keyFingerprint:Z.string().optional()}),uVw=Z.object({keys:Z.array(Z.unknown())}),cVw=Z.object({kty:Z.literal("OKP"),crv:Z.literal("Ed25519"),x:Z.string(),kid:Z.string().optional(),alg:Z.literal("EdDSA").optional()}).passthrough();function qQ2(A){return(IP(A)||A.trim()).toLowerCase()}async function lVw(A,Q){let w=qQ2(Q),B=await A.entityService.getEntity({entityType:y$,id:w});if(!B)return null;let $=qQ2(B.metadata.a2aEndpoint??B.metadata.url);if(!$)return null;return{domain:$}}async function pVw(A,Q){try{let w=await Q(`https://${A}/.well-known/jwks.json`);if(!w.ok)return null;let B=uVw.safeParse(await w.json());if(!B.success)return null;let $=B.data.keys.map((f)=>cVw.safeParse(f)).find((f)=>f.success);if(!$?.success)return null;return zu0($.data)}catch{return null}}function bQ2(A,Q=globalThis.fetch){let B=new vX;return{name:"agent_set_trust_level",description:"Set inbound A2A trust for a saved agent contact. Use level trusted to grant inbound trusted access after fetching and pinning the peer JWKS key fingerprint; use level public to revoke inbound trusted access. This affects inbound A2A trust only and does not add or remove the directory contact or affect outbound calling. Requires confirmation.",inputSchema:zQ2.shape,visibility:"anchor",sideEffects:"external",handler:async($)=>{let f=zQ2.safeParse($);if(!f.success)return{success:!1,error:`Invalid input: ${f.error.issues.map((D)=>`${D.path.join(".")}: ${D.message}`).join(", ")}`};let Y=P7();if(!Y)return{success:!1,error:"Auth service is required to set inbound A2A trust.",code:"auth_service_unavailable"};let X=await lVw(A,f.data.agent);if(!X)return{success:!1,error:`No saved agent contact found for ${f.data.agent}. Connect the agent before setting inbound trust.`,code:"agent_not_found"};let W=f.data;if(W.confirmed){let D=B.validate(W.confirmationToken,W);if(D.status==="missing")return{success:!1,error:"No pending agent trust confirmation found. Please request the trust change again and confirm the new approval."};if(D.status==="mismatch")return{success:!1,error:"Confirmed agent trust arguments do not match the pending approval. Please request the trust change again and confirm the new approval."};if(W.level==="trusted"){if(!W.keyFingerprint)return{success:!1,error:"Missing key fingerprint for trusted A2A grant."};let q=await Y.grantA2APeerTrust({domain:X.domain,keyFingerprint:W.keyFingerprint,grantedLevel:"trusted"});return{success:!0,data:{agent:X.domain,level:q.grantedLevel,keyFingerprint:q.keyFingerprint}}}return await Y.revokeA2APeerTrust(X.domain),{success:!0,data:{agent:X.domain,level:"public"}}}let H=W.level==="trusted"?await pVw(X.domain,Q):void 0;if(W.level==="trusted"&&!H)return{success:!1,error:`Could not fetch an A2A signing key from ${X.domain}.`,code:"jwks_unavailable"};let K=B.create((D)=>({agent:X.domain,level:W.level,confirmed:!0,confirmationToken:D,...H?{keyFingerprint:H}:{}})),U=W.level==="trusted";return{needsConfirmation:!0,toolName:"agent_set_trust_level",summary:U?`Grant inbound trusted A2A access to ${X.domain}?`:`Revoke inbound trusted A2A access from ${X.domain}?`,preview:U?`This will grant inbound trusted A2A access to ${X.domain} and pin key fingerprint ${H}. It will not add or remove the directory contact.`:`This will revoke inbound trusted A2A access from ${X.domain}. The directory contact remains saved for outbound calls.`,args:K}}}}var iVw=Z.object({}).strict();class oa0 extends aQ{fetchFn;constructor(A){super("agent",Oy,{},iVw);this.fetchFn=A}async getTools(){return[GQ2(this.getContext(),this.fetchFn),bQ2(this.getContext(),this.fetchFn)]}}function sa0(){return new oa0}wA();wA();N0();var JP=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),examples:Z.array(Z.string())}),VQ2=JP,io=F$.extend({entityType:Z.literal(_8),metadata:VQ2});wA();class xy extends C2{constructor(){super({entityType:_8,purpose:"A capability advertised by a remote agent.",schema:io,frontmatterSchema:JP})}fromMarkdown(A){let Q=this.parseFrontMatter(A,JP);return{content:A,entityType:_8,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}wA();N0();var dVw=Z.object({skills:Z.array(JP).max(8)}),IQ2=i1({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:dVw,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
8632
+ `)}function bVw(A){let Q=A.record.brain.did,w=A.record.anchor.did;return{agentId:A.agent.id,name:A.agent.metadata.name,url:A.agent.metadata.url,status:A.agent.metadata.status,repoDid:A.repoDid,...Q&&{brainDid:Q},...w&&{anchorDid:w},cardUri:A.uri,cardCid:A.cid}}async function VVw(A,Q,w){await A.messaging.send({type:Q,payload:w,broadcast:!0})}async function IVw(A,Q,w=new Date().toISOString()){let{record:B}=Q,$=zVw(B.siteUrl),f=await A.entityService.getEntity({entityType:"agent",id:$}),Y=f?fQ2.parseEntity(f):void 0,X=B.brain.did,W=B.anchor.did,H=GVw(B),K=f?.metadata.status??"discovered",U=f?.metadata.url??B.siteUrl,D=f?.metadata.slug??zO(U),q=f?.metadata.name??B.anchor.name,b=Y?.frontmatter.kind??B.anchor.kind,I=f?.metadata.discoveredAt??w,V=B.brain.purpose.length>0?B.brain.purpose:Y?.body.about??"",L=H.length>0?H:Y?.body.skills??[],N={...f?.metadata??{},name:q,url:U,status:K,discoveredAt:I,slug:D,repoDid:Q.repoDid,...X&&{brainDid:X},...W&&{anchorDid:W},cardUri:Q.uri,cardCid:Q.cid},k=fQ2.createAgentContent({name:q,kind:b,...Y?.frontmatter.organization&&{organization:Y.frontmatter.organization},brainName:B.brain.name,url:U,...X&&{did:X,brainDid:X},...W&&{anchorDid:W},repoDid:Q.repoDid,cardUri:Q.uri,cardCid:Q.cid,...Y?.frontmatter.a2aEndpoint&&{a2aEndpoint:Y.frontmatter.a2aEndpoint},status:K,discoveredAt:I,about:V,skills:L,notes:qVw({repoDid:Q.repoDid,uri:Q.uri,cid:Q.cid})});if(f){let R={...f,content:k,metadata:N,updated:w};return await A.entityService.updateEntity({entity:R}),{agent:R,created:!1}}let x={id:$,entityType:"agent",content:k,metadata:N,contentHash:"",visibility:"public",created:w,updated:w};return await A.entityService.createEntity({entity:x}),{agent:x,created:!0}}function YQ2(A){A.messaging.subscribe(Md,async(Q)=>{let w=ku0.parse(Q.payload),B=await IVw(A,w),$=bVw({agent:B.agent,repoDid:w.repoDid,uri:w.uri,cid:w.cid,record:w.record});return await VVw(A,B.created?Fu0:Lu0,$),{success:!0,data:$}})}function XQ2(){return["Agent entities represent saved peer-brain contacts in the local agent directory. List saved agent contacts with system_list on entityType agent. For expertise-match or recommendation questions over the user's agent network (for example who to consult/ask about a topic), immediately call one system_search with scope.kind type, scope.entityType agent, and the requested topic/skill; do not run parallel synonym searches unless the first result is inconclusive. Do not answer with generic role categories or offer to search later. If any result is plausible, suggest the saved agent by name/domain, include its exact callable id/domain from the search result (for example: Brand Studio, agent id brand-studio.example), and briefly explain the matching skill evidence. Prefer approved contacts over discovered contacts when both plausibly match; mention discovered contacts only with a clear review/confidence caveat.","If the previous assistant turn offered to search or narrow down the agent network, treat short affirmative follow-ups like please, yes, yes please, do that, or go ahead as consent to run that same agent expertise search using the topic from the prior user request.","Agent contact records are verified A2A peer contacts: connect/save them with agent_connect and a url source; a raw domain is a valid source, so preserve a bare domain as the bare domain string. agent_connect verifies the remote Agent Card and saves the contact as approved for future outbound calls; it does not grant the remote agent inbound trusted access. If an exact-domain agent_call cannot verify or contact an unsaved domain, tell the user they can add/save/connect that domain as a contact, and a short follow-up like 'please add' should call agent_connect for the same domain without requiring a separate approval gate.","Agent lifecycle is tracked with status fields such as discovered and approved; approval operations are system_update field changes for already saved discovered contacts. If the user asks to approve a saved agent contact by exact id such as approval-candidate.io, call system_update on entityType agent with that id and the requested status; do not use agent_connect for approval. If the user asks to trust or untrust a saved agent for inbound A2A access, use agent_set_trust_level; do not use system_update because inbound trust is runtime auth state, not agent entity metadata.","When the user asks to contact/call/ask a saved contact by a human display name or anchor/contact name (for example 'Ask my contact Yeehaa ...'), first resolve that name against saved agent entities with system_search scoped to entityType agent unless the user already supplied an exact domain-like id. Then pass agent_call.agent as the saved agent entity id/domain from the search result (for example yeehaa.io or brand-studio.example), not the display name, anchorName, or brainName. When calling a recommended or previously searched saved agent, also use the saved agent entity id/domain from the search result. Calling remote agents and saving local contact records are separate capabilities. Only approved saved agents are active call targets; do not contact discovered or otherwise unapproved contacts."].join(" ")}NB();N0();import{jsxDEV as ZQ2}from"preact/jsx-dev-runtime";function nX0(A){try{return new URL(A).hostname}catch{return A}}var rX0=({name:A,className:Q=""})=>{let w=A.charAt(0).toUpperCase(),B=0;for(let f=0;f<A.length;f++)B=A.charCodeAt(f)+((B<<5)-B);let $=Math.abs(B)%360;return ZQ2("div",{className:`flex items-center justify-center rounded-full text-white font-bold flex-shrink-0 ${Q}`,style:{backgroundColor:`hsl(${$}, 55%, 45%)`},children:w},void 0,!1,void 0,this)},oX0=({kind:A,size:Q="md"})=>{let B={professional:"bg-status-success text-status-success",team:"bg-status-info text-status-info",collective:"bg-brand/10 text-brand"}[A]??"bg-status-neutral text-status-neutral";return ZQ2("span",{className:`inline-flex items-center rounded-full font-medium ${Q==="sm"?"px-2 py-0.5 text-xs":"px-2.5 py-0.5 text-[13px]"} ${B}`,children:A},void 0,!1,void 0,this)};import{jsxDEV as c2,Fragment as LVw}from"preact/jsx-dev-runtime";var JVw=({skills:A})=>{if(A.length===0)return null;return c2("div",{className:"flex gap-1.5 flex-wrap mt-2",children:A.map((Q)=>c2("span",{className:"text-[11px] px-2 py-0.5 bg-theme-subtle rounded-md text-theme-muted",children:Q.name},Q.name,!1,void 0,this))},void 0,!1,void 0,this)};function FVw(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric"})}function WQ2(A,Q,w){let B=new URLSearchParams({status:Q});if(w>1)B.set("page",String(w));return`${A}?${B.toString()}`}var ia0=({agent:A})=>{let{frontmatter:Q,about:w,skills:B,url:$}=A,f=Q.status==="approved";return c2("a",{href:$,className:`flex items-start gap-5 p-6 rounded-xl border border-theme bg-theme-subtle hover:shadow-lg transition-shadow ${f?"":"opacity-70"}`,children:[c2(rX0,{name:Q.name,className:"w-12 h-12 text-lg"},void 0,!1,void 0,this),c2("div",{className:"flex-1 min-w-0",children:[c2("div",{className:"flex items-center gap-2 mb-1 flex-wrap",children:[c2("span",{className:"text-lg font-semibold text-heading",children:Q.name},void 0,!1,void 0,this),c2(oX0,{kind:Q.kind,size:"sm"},void 0,!1,void 0,this),Q.organization&&c2("span",{className:"text-xs text-theme-muted",children:["\xB7 ",Q.organization]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),c2("div",{className:"text-sm text-theme-muted mb-1",children:Q.brainName},void 0,!1,void 0,this),w&&c2("p",{className:"text-sm text-theme-muted line-clamp-2 mb-0",children:w},void 0,!1,void 0,this),f&&c2(JVw,{skills:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c2("div",{className:"flex flex-col items-end gap-1 flex-shrink-0 text-right",children:[c2("span",{className:"text-xs text-theme-muted",children:nX0(Q.url)},void 0,!1,void 0,this),c2("span",{className:"text-[11px] text-theme-muted opacity-60",children:f?`Discovered ${FVw(Q.discoveredAt)}`:"Discovered \xB7 approve before calling"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},HQ2=({agents:A,pageTitle:Q,pagination:w,baseUrl:B="/agents",selectedStatus:$})=>{let f=Q??"Agent Directory",Y=w?.totalItems??A.length,X=A.filter((D)=>D.frontmatter.status==="approved"),W=A.filter((D)=>D.frontmatter.status==="discovered"),H=X.length,K=W.length,U=`Your network of ${Y} ${Y===1?"brain":"brains"} and their anchors`;return c2(LVw,{children:[c2(lQ,{title:f,description:U},void 0,!1,void 0,this),c2("div",{className:"agent-list bg-theme",children:c2("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[c2("div",{className:"mb-8 pb-6 border-b border-theme",children:[c2("h1",{className:"text-4xl font-bold text-heading mb-2",children:f},void 0,!1,void 0,this),c2("p",{className:"text-theme-muted mb-4",children:U},void 0,!1,void 0,this),c2("div",{className:"flex flex-wrap gap-2 text-sm mb-4",children:[c2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-heading",children:[Y," total"]},void 0,!0,void 0,this),c2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-status-success",children:[H," approved"]},void 0,!0,void 0,this),c2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-theme-muted",children:[K," discovered"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),c2("div",{className:"flex flex-wrap gap-2 text-sm",children:[c2("a",{href:B,className:`px-3 py-1 rounded-full border transition-colors ${$==="all"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"All"},void 0,!1,void 0,this),c2("a",{href:`${B}?status=approved`,className:`px-3 py-1 rounded-full border transition-colors ${$==="approved"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"Approved"},void 0,!1,void 0,this),c2("a",{href:`${B}?status=discovered`,className:`px-3 py-1 rounded-full border transition-colors ${$==="discovered"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"Discovered"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),$==="all"&&X.length>0&&c2("section",{className:"mb-10",children:[c2("div",{className:"flex items-center justify-between mb-4",children:[c2("h2",{className:"text-lg font-semibold text-heading",children:"Approved brains"},void 0,!1,void 0,this),c2("span",{className:"text-sm text-theme-muted",children:X.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c2("div",{className:"flex flex-col gap-4",children:X.map((D)=>c2(ia0,{agent:D},D.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$==="all"&&W.length>0&&c2("section",{children:[c2("div",{className:"flex items-center justify-between mb-4",children:[c2("div",{children:[c2("h2",{className:"text-lg font-semibold text-heading",children:"Discovered brains"},void 0,!1,void 0,this),c2("p",{className:"text-sm text-theme-muted",children:"Review and approve these before calling them."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c2("span",{className:"text-sm text-theme-muted",children:W.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c2("div",{className:"flex flex-col gap-4",children:W.map((D)=>c2(ia0,{agent:D},D.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$!=="all"&&A.length>0&&c2("section",{children:[c2("div",{className:"flex items-center justify-between mb-4",children:[c2("h2",{className:"text-lg font-semibold text-heading",children:$==="approved"?"Approved brains":"Discovered brains"},void 0,!1,void 0,this),c2("span",{className:"text-sm text-theme-muted",children:A.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c2("div",{className:"flex flex-col gap-4",children:A.map((D)=>c2(ia0,{agent:D},D.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length===0&&c2("p",{className:"text-center text-theme-muted py-16",children:"No agents in your directory yet."},void 0,!1,void 0,this),w&&w.totalPages>1&&$==="all"&&c2("div",{className:"mt-12",children:c2(iq,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:B},void 0,!1,void 0,this)},void 0,!1,void 0,this),w&&w.totalPages>1&&$!=="all"&&c2("nav",{"aria-label":"Pagination",className:"flex items-center justify-center gap-3 mt-12",children:[w.hasPrevPage?c2("a",{href:WQ2(B,$,w.currentPage-1),className:"px-3 py-2 rounded-md border border-theme text-sm text-theme-muted hover:text-heading transition-colors",children:"\u2190 Prev"},void 0,!1,void 0,this):c2("span",{className:"px-3 py-2 rounded-md border border-theme text-sm text-theme-muted opacity-50",children:"\u2190 Prev"},void 0,!1,void 0,this),c2("span",{className:"text-sm text-theme-muted",children:["Page ",w.currentPage," of ",w.totalPages]},void 0,!0,void 0,this),w.hasNextPage?c2("a",{href:WQ2(B,$,w.currentPage+1),className:"px-3 py-2 rounded-md border border-theme text-sm text-theme-muted hover:text-heading transition-colors",children:"Next \u2192"},void 0,!1,void 0,this):c2("span",{className:"px-3 py-2 rounded-md border border-theme text-sm text-theme-muted opacity-50",children:"Next \u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as j2,Fragment as jVw}from"preact/jsx-dev-runtime";function kVw(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}var po=({children:A})=>j2("h2",{className:"text-sm font-semibold text-theme-muted uppercase tracking-wide mb-3",children:A},void 0,!1,void 0,this),_Vw=({skill:A})=>j2("div",{className:"flex items-start gap-3 px-4 py-3 bg-theme-subtle rounded-lg",children:[j2("div",{className:"flex-1",children:[j2("div",{className:"text-sm font-semibold text-heading",children:A.name},void 0,!1,void 0,this),j2("div",{className:"text-[13px] text-theme-muted",children:A.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.tags.length>0&&j2("div",{className:"flex gap-1 flex-shrink-0",children:A.tags.map((Q)=>j2("span",{className:"text-[11px] px-2 py-0.5 bg-theme rounded-md text-theme-muted",children:Q},Q,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),NVw=({label:A,value:Q,valueClassName:w})=>j2("div",{className:"flex justify-between text-[13px]",children:[j2("span",{className:"text-theme-muted",children:A},void 0,!1,void 0,this),j2("span",{className:w??"text-heading",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),KQ2=({agent:A,prevAgent:Q,nextAgent:w})=>{let{frontmatter:B,about:$,skills:f,notes:Y}=A,X=nX0(B.url),W=B.status==="approved";return j2(jVw,{children:[j2(lQ,{title:B.name,description:$||`Agent profile for ${B.name}`},void 0,!1,void 0,this),j2("article",{className:"agent-detail",children:j2("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:[j2("a",{href:"/agents",className:"text-sm text-theme-muted hover:text-brand transition-colors mb-6 inline-block",children:"\u2190 Back to Directory"},void 0,!1,void 0,this),j2("div",{className:"flex items-start gap-6 mb-8",children:[j2(rX0,{name:B.name,className:"w-[72px] h-[72px] text-3xl"},void 0,!1,void 0,this),j2("div",{children:[j2("div",{className:"flex items-center gap-3 mb-1",children:[j2("h1",{className:"text-3xl md:text-4xl font-bold text-heading",children:B.name},void 0,!1,void 0,this),j2(oX0,{kind:B.kind},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"text-base text-theme-muted mb-2",children:B.brainName},void 0,!1,void 0,this),j2("div",{className:"flex items-center gap-3 text-theme-muted",children:[B.organization&&j2("span",{className:"text-[15px]",children:B.organization},void 0,!1,void 0,this),B.organization&&j2("span",{className:"text-theme-muted opacity-40",children:"\xB7"},void 0,!1,void 0,this),j2("span",{className:"text-sm",children:["Discovered ",kVw(B.discoveredAt)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"border-b border-theme mb-8"},void 0,!1,void 0,this),!W&&j2("div",{className:"mb-8 rounded-xl border border-theme bg-theme-subtle px-5 py-4",children:[j2("div",{className:"text-sm font-semibold text-heading mb-1",children:"Saved for review"},void 0,!1,void 0,this),j2("p",{className:"text-sm text-theme-muted",children:"This brain is discovered but not approved yet, so it cannot be called until you approve it."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"flex flex-col md:flex-row gap-12",children:[j2("div",{className:"flex-[2] min-w-0",children:[$&&j2("section",{className:"mb-8",children:[j2(po,{children:"About"},void 0,!1,void 0,this),j2("p",{className:"text-[15px] text-theme leading-relaxed",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),f.length>0&&j2("section",{className:"mb-8",children:[j2(po,{children:"Skills"},void 0,!1,void 0,this),j2("div",{className:"flex flex-col gap-2.5",children:f.map((H)=>j2(_Vw,{skill:H},H.name,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Y&&j2("section",{className:"mb-8",children:[j2(po,{children:"Notes"},void 0,!1,void 0,this),j2("p",{className:"text-[15px] text-theme leading-relaxed",children:Y},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j2("aside",{className:"flex-1 md:pl-8 md:border-l border-theme-muted/20",children:[j2("section",{className:"mb-8",children:[j2(po,{children:"Brain"},void 0,!1,void 0,this),j2("div",{className:"p-4 bg-theme-subtle rounded-xl",children:[j2("div",{className:"text-[15px] font-semibold text-heading mb-1",children:B.brainName},void 0,!1,void 0,this),B.did&&j2("div",{className:"text-xs text-theme-muted font-mono",children:B.did},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j2("section",{className:"mb-8",children:[j2(po,{children:"Connection"},void 0,!1,void 0,this),j2("div",{className:"flex flex-col gap-3",children:[j2("div",{children:[j2("div",{className:"text-[13px] text-theme-muted mb-0.5",children:"Endpoint"},void 0,!1,void 0,this),j2("div",{className:"text-xs text-heading font-mono",children:B.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2(NVw,{label:"Status",value:B.status==="approved"?"Approved":"Discovered",valueClassName:B.status==="approved"?"text-status-success font-medium":"text-theme-muted"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j2("a",{href:B.url.replace(/\/a2a\/?$/,""),target:"_blank",rel:"noopener noreferrer",className:"flex items-center justify-center px-5 py-3 bg-theme-dark text-theme-inverse rounded-lg text-sm font-medium hover:opacity-90 transition-opacity",children:["Visit ",X," \u2197"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),(Q??w)&&j2("nav",{className:"mt-12 pt-6 border-t border-theme flex flex-col gap-3 md:flex-row md:items-center md:justify-between",children:[j2("div",{className:"min-h-[1px]",children:Q&&j2("a",{href:Q.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[j2("span",{children:"\u2190 Previous"},void 0,!1,void 0,this),j2("span",{className:"text-heading font-medium",children:Q.frontmatter.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),j2("div",{className:"min-h-[1px] md:text-right",children:w&&j2("a",{href:w.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[j2("span",{children:"Next \u2192"},void 0,!1,void 0,this),j2("span",{className:"text-heading font-medium",children:w.frontmatter.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};var PVw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),MVw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),OVw=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),da0=Z.enum(["discovered","approved"]),xVw=Z.enum(["professional","team","collective"]),RVw=Z.object({name:Z.string(),kind:xVw,organization:Z.string().optional(),brainName:Z.string(),url:Z.url(),did:Z.string().optional(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.url().optional(),status:da0,discoveredAt:Z.string()}),vVw=Z.object({name:Z.string(),url:Z.url(),status:da0,discoveredAt:Z.string().optional(),slug:Z.string(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.url().optional()}),sX0=Z.object({id:Z.string(),entityType:Z.literal(y$),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:PVw,metadata:vVw,contentHash:Z.string(),frontmatter:RVw,about:Z.string(),skills:Z.array(OVw),notes:Z.string(),url:Z.string(),typeLabel:Z.string()}),hVw=Z.object({agents:Z.array(sX0),pageTitle:Z.string().optional(),pagination:MVw.nullable(),baseUrl:Z.string().optional(),selectedStatus:Z.union([Z.literal("all"),da0])});function UQ2(){return{[ma0]:i1({name:ma0,description:"Agent directory list page template",schema:hVw,dataSourceId:mo,requiredPermission:"public",layout:{component:HQ2}}),[ua0]:i1({name:ua0,description:"Individual agent profile template",schema:Z.object({agent:sX0,prevAgent:sX0.nullable(),nextAgent:sX0.nullable()}),dataSourceId:mo,requiredPermission:"public",layout:{component:KQ2}})}}var Oy={name:"@brains/agent-discovery",version:"0.2.0-alpha.143",description:"Agent discovery \u2014 brain+anchor contacts and skills",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/auth-service":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/dashboard":"workspace:*","@brains/http-signatures":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var gVw=new p4;class na0 extends nQ{entityType=y$;schema=uo;adapter=gVw;constructor(){super(g22,Oy,{},L7)}createGenerationHandler(A){return new ca0(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return UQ2()}getDataSources(){return[new cX0(this.logger.child("AgentDataSource"))]}async onRegister(A){YQ2(A),$Q2(A,this.id)}async getInstructions(){return XQ2()}}function ra0(){return new na0}wA();N0();Q9();N0();var DQ2=Z.object({source:Z.object({kind:Z.literal("url"),url:Z.string().min(1).describe("Remote agent domain or URL to verify and connect. Preserve bare domains as bare domains.")}),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional()}),yVw=new p4;function EVw(A){let Q=IP(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function TVw(A,Q){return(IP(Q)||A).toLowerCase()}async function SVw(A){let{context:Q,entityId:w,card:B}=A,$=new Date().toISOString(),f=await Q.entityService.getEntity({entityType:y$,id:w}),Y=pX0(B,{status:"approved"}),W={...yVw.fromMarkdown(Y.content).metadata,...Y.metadata,a2aEndpoint:B.url};if(f){let K={...f,content:Y.content,metadata:W,updated:$};return await Q.entityService.updateEntity({entity:K}),{entity:K,created:!1}}let H={id:w,entityType:y$,content:Y.content,metadata:W,contentHash:"",visibility:"public",created:$,updated:$};return await Q.entityService.createEntity({entity:H}),{entity:H,created:!0}}function GQ2(A,Q=globalThis.fetch){let B=new vX;return{name:"agent_connect",description:"Verify and connect a remote A2A agent by fetching its Agent Card from /.well-known/agent-card.json, then save the verified contact in the local agent directory as approved for future outbound calls. This adds a directory contact; it does not message the remote agent or grant it inbound trusted access. Requires confirmation before verification and persistence. Call this tool without confirmed on the initial request; the tool returns confirmation args for the user to approve.",inputSchema:DQ2.shape,visibility:"trusted",sideEffects:"external",handler:async($,f)=>{let Y=DQ2.safeParse($);if(!Y.success)return{success:!1,error:`Invalid input: ${Y.error.issues.map((K)=>`${K.path.join(".")}: ${K.message}`).join(", ")}`};let X=Y.data,W=EVw(X.source.url);if(!W)return{success:!1,error:"Provide a valid remote agent domain or URL to connect.",code:"invalid_agent_url"};try{A.permissions.assertEntityActionAllowed(y$,"create",f)}catch(K){return{success:!1,error:K instanceof Error?K.message:String(K)}}if(X.confirmed){let K=X.confirmationToken,U=B.validate(K,X);if(U.status==="missing")return{success:!1,error:"No pending agent connection confirmation found. Please request connection again and confirm the new approval."};if(U.status==="mismatch")return{success:!1,error:"Confirmed agent connection arguments do not match the pending approval. Please request connection again and confirm the new approval."};let D=await lX0(W.fetchTarget,Q);if(!D)return{success:!1,error:`Could not verify an A2A Agent Card for ${W.domain}.`,code:"not_an_agent"};let q=TVw(W.domain,D.url),{entity:b,created:I}=await SVw({context:A,entityId:q,sourceUrl:X.source.url,card:D});return{success:!0,data:{status:b.metadata.status,entityId:b.id,connected:!0,created:I,a2aEndpoint:D.url,skills:D.skills.map((V)=>({name:V.name,description:V.description,tags:V.tags}))}}}let H=B.create((K)=>({source:X.source,confirmed:!0,confirmationToken:K}));return{needsConfirmation:!0,toolName:"agent_connect",summary:`Verify and connect agent ${W.domain}?`,preview:`This will fetch and validate ${W.domain}'s A2A Agent Card, then save the verified contact as approved for future outbound calls. It will not message the remote agent or grant it inbound trusted access.`,args:H}}}}Q9();N0();var mVw=Z.enum(["public","trusted"]),zQ2=Z.object({agent:Z.string().min(1).describe("Saved agent id, domain, or URL whose inbound A2A trust to set."),level:mVw.describe("Inbound A2A trust level. Use trusted to grant trusted inbound access, public to revoke it."),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional(),keyFingerprint:Z.string().optional()}),uVw=Z.object({keys:Z.array(Z.unknown())}),cVw=Z.object({kty:Z.literal("OKP"),crv:Z.literal("Ed25519"),x:Z.string(),kid:Z.string().optional(),alg:Z.literal("EdDSA").optional()}).passthrough();function qQ2(A){return(IP(A)||A.trim()).toLowerCase()}async function lVw(A,Q){let w=qQ2(Q),B=await A.entityService.getEntity({entityType:y$,id:w});if(!B)return null;let $=qQ2(B.metadata.a2aEndpoint??B.metadata.url);if(!$)return null;return{domain:$}}async function pVw(A,Q){try{let w=await Q(`https://${A}/.well-known/jwks.json`);if(!w.ok)return null;let B=uVw.safeParse(await w.json());if(!B.success)return null;let $=B.data.keys.map((f)=>cVw.safeParse(f)).find((f)=>f.success);if(!$?.success)return null;return zu0($.data)}catch{return null}}function bQ2(A,Q=globalThis.fetch){let B=new vX;return{name:"agent_set_trust_level",description:"Set inbound A2A trust for a saved agent contact. Use level trusted to grant inbound trusted access after fetching and pinning the peer JWKS key fingerprint; use level public to revoke inbound trusted access. This affects inbound A2A trust only and does not add or remove the directory contact or affect outbound calling. Requires confirmation.",inputSchema:zQ2.shape,visibility:"anchor",sideEffects:"external",handler:async($)=>{let f=zQ2.safeParse($);if(!f.success)return{success:!1,error:`Invalid input: ${f.error.issues.map((D)=>`${D.path.join(".")}: ${D.message}`).join(", ")}`};let Y=P7();if(!Y)return{success:!1,error:"Auth service is required to set inbound A2A trust.",code:"auth_service_unavailable"};let X=await lVw(A,f.data.agent);if(!X)return{success:!1,error:`No saved agent contact found for ${f.data.agent}. Connect the agent before setting inbound trust.`,code:"agent_not_found"};let W=f.data;if(W.confirmed){let D=B.validate(W.confirmationToken,W);if(D.status==="missing")return{success:!1,error:"No pending agent trust confirmation found. Please request the trust change again and confirm the new approval."};if(D.status==="mismatch")return{success:!1,error:"Confirmed agent trust arguments do not match the pending approval. Please request the trust change again and confirm the new approval."};if(W.level==="trusted"){if(!W.keyFingerprint)return{success:!1,error:"Missing key fingerprint for trusted A2A grant."};let q=await Y.grantA2APeerTrust({domain:X.domain,keyFingerprint:W.keyFingerprint,grantedLevel:"trusted"});return{success:!0,data:{agent:X.domain,level:q.grantedLevel,keyFingerprint:q.keyFingerprint}}}return await Y.revokeA2APeerTrust(X.domain),{success:!0,data:{agent:X.domain,level:"public"}}}let H=W.level==="trusted"?await pVw(X.domain,Q):void 0;if(W.level==="trusted"&&!H)return{success:!1,error:`Could not fetch an A2A signing key from ${X.domain}.`,code:"jwks_unavailable"};let K=B.create((D)=>({agent:X.domain,level:W.level,confirmed:!0,confirmationToken:D,...H?{keyFingerprint:H}:{}})),U=W.level==="trusted";return{needsConfirmation:!0,toolName:"agent_set_trust_level",summary:U?`Grant inbound trusted A2A access to ${X.domain}?`:`Revoke inbound trusted A2A access from ${X.domain}?`,preview:U?`This will grant inbound trusted A2A access to ${X.domain} and pin key fingerprint ${H}. It will not add or remove the directory contact.`:`This will revoke inbound trusted A2A access from ${X.domain}. The directory contact remains saved for outbound calls.`,args:K}}}}var iVw=Z.object({}).strict();class oa0 extends aQ{fetchFn;constructor(A){super("agent",Oy,{},iVw);this.fetchFn=A}async getTools(){return[GQ2(this.getContext(),this.fetchFn),bQ2(this.getContext(),this.fetchFn)]}}function sa0(){return new oa0}wA();wA();N0();var JP=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),examples:Z.array(Z.string())}),VQ2=JP,io=F$.extend({entityType:Z.literal(_8),metadata:VQ2});wA();class xy extends C2{constructor(){super({entityType:_8,purpose:"A capability advertised by a remote agent.",schema:io,frontmatterSchema:JP})}fromMarkdown(A){let Q=this.parseFrontMatter(A,JP);return{content:A,entityType:_8,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}wA();N0();var dVw=Z.object({skills:Z.array(JP).max(8)}),IQ2=i1({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:dVw,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
8633
8633
 
8634
8634
  Given knowledge domains, CONSOLIDATE related topics into broader skills.
8635
8635
  There should be FEWER skills than topics \u2014 combine related domains.
@@ -8779,9 +8779,9 @@ Context:
8779
8779
  ${JSON.stringify(B,null,2)}
8780
8780
 
8781
8781
  Draft SWOT:
8782
- ${JSON.stringify(w,null,2)}`}function $Z0(A){return A.map((Q)=>Q.detail===null?{title:Q.title}:{title:Q.title,detail:Q.detail})}function qIw(A,Q){let w=["strengths","weaknesses","opportunities","threats"];for(let B of w){let $=new Set(A[B].map((f)=>f.theme.trim().toLowerCase()));for(let f of Q[B]){let Y=f.sourceTheme.trim().toLowerCase();if(!$.has(Y))throw Error(`SWOT refinement invented theme "${f.sourceTheme}" in ${B}`)}}}class fZ0{logger;context;adapter=new Gb;constructor(A,Q){this.logger=A,this.context=Q}validateAndParse(A){let Q=ea0.safeParse(A??{});return Q.success?Q.data:null}async process(A,Q,w){await w.report({progress:0.2,message:"Building SWOT context"});let B=await $t0(this.context),$;if(B.summary.brainSkillCount+B.summary.approvedAgentCount+B.summary.discoveredAgentCount===0)$={strengths:[],weaknesses:[],opportunities:[],threats:[]};else{await w.report({progress:0.6,message:"Synthesizing SWOT analysis"});let{object:H}=await this.context.ai.generateObject(await DIw(this.context,B),At0),K=At0.parse(H);await w.report({progress:0.75,message:"Refining SWOT language"});let U=await this.context.ai.generateObject(await zIw(this.context,B,K),QZ0);$=QZ0.parse(U.object),qIw(K,$)}let Y=new Date().toISOString(),X=this.adapter.createSwotContent({strengths:$Z0($.strengths),weaknesses:$Z0($.weaknesses),opportunities:$Z0($.opportunities),threats:$Z0($.threats),derivedAt:Y});await w.report({progress:0.9,message:"Saving SWOT entity"});let W=await this.context.entityService.getEntity({entityType:"swot",id:"swot"});if(W)await this.context.entityService.updateEntity({entity:{...W,content:X,metadata:{derivedAt:Y}}});else await this.context.entityService.createEntity({entity:{id:"swot",entityType:"swot",content:X,metadata:{derivedAt:Y}}});return this.logger.info("SWOT derivation complete",{derivedAt:Y,brainSkillCount:B.summary.brainSkillCount,approvedAgentCount:B.summary.approvedAgentCount,discoveredAgentCount:B.summary.discoveredAgentCount}),{entityId:"swot"}}}N0();import{jsxDEV as i4}from"preact/jsx-dev-runtime";var YZ0=Z.object({title:Z.string(),detail:Z.string().optional()}),bIw=Z.discriminatedUnion("status",[Z.object({status:Z.literal("generating")}),Z.object({status:Z.literal("ready"),strengths:Z.array(YZ0).default([]),weaknesses:Z.array(YZ0).default([]),opportunities:Z.array(YZ0).default([]),threats:Z.array(YZ0).default([]),derivedAt:Z.string()})]);function VIw({items:A}){if(A.length===0)return i4("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return i4("ul",{class:"swot-list",children:A.map((Q)=>i4("li",{class:"swot-item",children:[i4("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?i4("span",{children:[" \u2014 ",Q.detail]},void 0,!0,void 0,this):null]},`${Q.title}:${Q.detail??""}`,!0,void 0,this))},void 0,!1,void 0,this)}function XZ0({title:A,tone:Q,items:w}){return i4("section",{class:`swot-cell is-${Q}`,children:[i4("div",{class:"swot-head",children:A},void 0,!1,void 0,this),i4(VIw,{items:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Xt0({data:A}){let Q=bIw.safeParse(A);if(!Q.success||Q.data.status==="generating")return i4("div",{"data-swot-widget":!0,children:i4("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let w=Q.data;return i4("div",{"data-swot-widget":!0,children:i4("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[i4(XZ0,{title:"Strengths",tone:"s",items:w.strengths},void 0,!1,void 0,this),i4(XZ0,{title:"Weaknesses",tone:"w",items:w.weaknesses},void 0,!1,void 0,this),i4(XZ0,{title:"Opportunities",tone:"o",items:w.opportunities},void 0,!1,void 0,this),i4(XZ0,{title:"Threats",tone:"t",items:w.threats},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}var Zt0={name:"@brains/assessment",version:"0.2.0-alpha.142",description:"Assessment outputs and capability-profile analysis",dependencies:{"@brains/content-formatters":"workspace:*","@brains/dashboard":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Wt0=new Gb;class Ht0 extends nQ{entityType="swot";schema=Ry;adapter=Wt0;initialSyncComplete=!1;constructor(){super("swot",Zt0,{},L7)}async onRegister(A){let Q=new fZ0(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q),A.eval.registerHandler("deriveSwot",async()=>{let f=Xf.from(async()=>{});if(!f)throw Error("Expected progress reporter to be created");await Q.process({reason:"eval"},"eval-swot-derive",f);let Y=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!Y)throw Error("Expected SWOT entity to be created during eval");return Wt0.parseSwotContent(Y.content).frontmatter});let w=async(f)=>{try{return await A.jobs.enqueue({type:"derive",data:{reason:f},options:{source:this.id,priority:10,deduplication:"coalesce",deduplicationKey:"swot",metadata:{operationType:"data_processing",operationTarget:`swot:${f}`}}})}catch(Y){return this.logger.error("Failed to queue SWOT derivation",{error:Y,reason:f}),null}},B=async(f)=>{if(!await A.entityService.getEntity({entityType:"swot",id:"swot"}))await w(f)};A.messaging.subscribe("sync:initial:completed",async()=>{return this.initialSyncComplete=!0,await B("initial-missing-entity"),{success:!0}}),A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:"swot",pluginId:this.id,title:"SWOT",section:"secondary",priority:14,rendererName:"SwotWidget",component:Xt0,dataProvider:async()=>{let f=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!f)return{status:"generating"};let{frontmatter:Y}=Wt0.parseSwotContent(f.content);return{status:"ready",...Y}}}}),{success:!0}});let $=async(f)=>{let{entityType:Y}=f.payload;if(!this.initialSyncComplete)return{success:!0};if(Y!=="agent"&&Y!=="skill")return{success:!0};return await w("entity-change"),{success:!0}};A.messaging.subscribe("entity:created",$),A.messaging.subscribe("entity:updated",$),A.messaging.subscribe("entity:deleted",$)}}function Kt0(){return new Ht0}wA();o5();N0();var _3$=new Gb,hQ2=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),CQ2=Z.enum(["discovered","approved"]),JIw=Z.object({name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),brainName:Z.string(),url:Z.string().url(),did:Z.string().optional(),status:CQ2,discoveredAt:Z.string().datetime()}),FIw=F$.extend({entityType:Z.literal("agent"),metadata:Z.object({name:Z.string(),url:Z.string().url(),status:CQ2,slug:Z.string()})}),Ut0=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),examples:Z.array(Z.string())}),LIw=F$.extend({entityType:Z.literal("skill"),metadata:Ut0}),kIw=Z.object({about:Z.string(),skills:Z.array(hQ2),notes:Z.string()});function _Iw(A){if(!Array.isArray(A)||A.length===0)return"";return A.map((w)=>{let B=w.tags.length>0?` [${w.tags.join(", ")}]`:"";return`- ${w.name}: ${w.description}${B}`}).join(`
8782
+ ${JSON.stringify(w,null,2)}`}function $Z0(A){return A.map((Q)=>Q.detail===null?{title:Q.title}:{title:Q.title,detail:Q.detail})}function qIw(A,Q){let w=["strengths","weaknesses","opportunities","threats"];for(let B of w){let $=new Set(A[B].map((f)=>f.theme.trim().toLowerCase()));for(let f of Q[B]){let Y=f.sourceTheme.trim().toLowerCase();if(!$.has(Y))throw Error(`SWOT refinement invented theme "${f.sourceTheme}" in ${B}`)}}}class fZ0{logger;context;adapter=new Gb;constructor(A,Q){this.logger=A,this.context=Q}validateAndParse(A){let Q=ea0.safeParse(A??{});return Q.success?Q.data:null}async process(A,Q,w){await w.report({progress:0.2,message:"Building SWOT context"});let B=await $t0(this.context),$;if(B.summary.brainSkillCount+B.summary.approvedAgentCount+B.summary.discoveredAgentCount===0)$={strengths:[],weaknesses:[],opportunities:[],threats:[]};else{await w.report({progress:0.6,message:"Synthesizing SWOT analysis"});let{object:H}=await this.context.ai.generateObject(await DIw(this.context,B),At0),K=At0.parse(H);await w.report({progress:0.75,message:"Refining SWOT language"});let U=await this.context.ai.generateObject(await zIw(this.context,B,K),QZ0);$=QZ0.parse(U.object),qIw(K,$)}let Y=new Date().toISOString(),X=this.adapter.createSwotContent({strengths:$Z0($.strengths),weaknesses:$Z0($.weaknesses),opportunities:$Z0($.opportunities),threats:$Z0($.threats),derivedAt:Y});await w.report({progress:0.9,message:"Saving SWOT entity"});let W=await this.context.entityService.getEntity({entityType:"swot",id:"swot"});if(W)await this.context.entityService.updateEntity({entity:{...W,content:X,metadata:{derivedAt:Y}}});else await this.context.entityService.createEntity({entity:{id:"swot",entityType:"swot",content:X,metadata:{derivedAt:Y}}});return this.logger.info("SWOT derivation complete",{derivedAt:Y,brainSkillCount:B.summary.brainSkillCount,approvedAgentCount:B.summary.approvedAgentCount,discoveredAgentCount:B.summary.discoveredAgentCount}),{entityId:"swot"}}}N0();import{jsxDEV as i4}from"preact/jsx-dev-runtime";var YZ0=Z.object({title:Z.string(),detail:Z.string().optional()}),bIw=Z.discriminatedUnion("status",[Z.object({status:Z.literal("generating")}),Z.object({status:Z.literal("ready"),strengths:Z.array(YZ0).default([]),weaknesses:Z.array(YZ0).default([]),opportunities:Z.array(YZ0).default([]),threats:Z.array(YZ0).default([]),derivedAt:Z.string()})]);function VIw({items:A}){if(A.length===0)return i4("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return i4("ul",{class:"swot-list",children:A.map((Q)=>i4("li",{class:"swot-item",children:[i4("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?i4("span",{children:[" \u2014 ",Q.detail]},void 0,!0,void 0,this):null]},`${Q.title}:${Q.detail??""}`,!0,void 0,this))},void 0,!1,void 0,this)}function XZ0({title:A,tone:Q,items:w}){return i4("section",{class:`swot-cell is-${Q}`,children:[i4("div",{class:"swot-head",children:A},void 0,!1,void 0,this),i4(VIw,{items:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Xt0({data:A}){let Q=bIw.safeParse(A);if(!Q.success||Q.data.status==="generating")return i4("div",{"data-swot-widget":!0,children:i4("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let w=Q.data;return i4("div",{"data-swot-widget":!0,children:i4("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[i4(XZ0,{title:"Strengths",tone:"s",items:w.strengths},void 0,!1,void 0,this),i4(XZ0,{title:"Weaknesses",tone:"w",items:w.weaknesses},void 0,!1,void 0,this),i4(XZ0,{title:"Opportunities",tone:"o",items:w.opportunities},void 0,!1,void 0,this),i4(XZ0,{title:"Threats",tone:"t",items:w.threats},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}var Zt0={name:"@brains/assessment",version:"0.2.0-alpha.143",description:"Assessment outputs and capability-profile analysis",dependencies:{"@brains/content-formatters":"workspace:*","@brains/dashboard":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Wt0=new Gb;class Ht0 extends nQ{entityType="swot";schema=Ry;adapter=Wt0;initialSyncComplete=!1;constructor(){super("swot",Zt0,{},L7)}async onRegister(A){let Q=new fZ0(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q),A.eval.registerHandler("deriveSwot",async()=>{let f=Xf.from(async()=>{});if(!f)throw Error("Expected progress reporter to be created");await Q.process({reason:"eval"},"eval-swot-derive",f);let Y=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!Y)throw Error("Expected SWOT entity to be created during eval");return Wt0.parseSwotContent(Y.content).frontmatter});let w=async(f)=>{try{return await A.jobs.enqueue({type:"derive",data:{reason:f},options:{source:this.id,priority:10,deduplication:"coalesce",deduplicationKey:"swot",metadata:{operationType:"data_processing",operationTarget:`swot:${f}`}}})}catch(Y){return this.logger.error("Failed to queue SWOT derivation",{error:Y,reason:f}),null}},B=async(f)=>{if(!await A.entityService.getEntity({entityType:"swot",id:"swot"}))await w(f)};A.messaging.subscribe("sync:initial:completed",async()=>{return this.initialSyncComplete=!0,await B("initial-missing-entity"),{success:!0}}),A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:"swot",pluginId:this.id,title:"SWOT",section:"secondary",priority:14,rendererName:"SwotWidget",component:Xt0,dataProvider:async()=>{let f=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!f)return{status:"generating"};let{frontmatter:Y}=Wt0.parseSwotContent(f.content);return{status:"ready",...Y}}}}),{success:!0}});let $=async(f)=>{let{entityType:Y}=f.payload;if(!this.initialSyncComplete)return{success:!0};if(Y!=="agent"&&Y!=="skill")return{success:!0};return await w("entity-change"),{success:!0}};A.messaging.subscribe("entity:created",$),A.messaging.subscribe("entity:updated",$),A.messaging.subscribe("entity:deleted",$)}}function Kt0(){return new Ht0}wA();o5();N0();var _3$=new Gb,hQ2=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),CQ2=Z.enum(["discovered","approved"]),JIw=Z.object({name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),brainName:Z.string(),url:Z.string().url(),did:Z.string().optional(),status:CQ2,discoveredAt:Z.string().datetime()}),FIw=F$.extend({entityType:Z.literal("agent"),metadata:Z.object({name:Z.string(),url:Z.string().url(),status:CQ2,slug:Z.string()})}),Ut0=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),examples:Z.array(Z.string())}),LIw=F$.extend({entityType:Z.literal("skill"),metadata:Ut0}),kIw=Z.object({about:Z.string(),skills:Z.array(hQ2),notes:Z.string()});function _Iw(A){if(!Array.isArray(A)||A.length===0)return"";return A.map((w)=>{let B=w.tags.length>0?` [${w.tags.join(", ")}]`:"";return`- ${w.name}: ${w.description}${B}`}).join(`
8783
8783
  `)}function NIw(A){if(!A.trim())return[];return A.split(`
8784
- `).map((Q)=>Q.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/)).filter((Q)=>Q!==null).map((Q)=>({name:Q[1]??"",description:Q[2]??"",tags:Q[3]?Q[3].split(",").map((w)=>w.trim()).filter(Boolean):[]}))}var jIw=new G6(kIw,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:_Iw,parser:NIw},{key:"notes",label:"Notes",type:"string"}]});class gQ2 extends C2{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:FIw,frontmatterSchema:JIw})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=jIw.format({about:A.about,skills:A.skills,notes:A.notes});return this.buildMarkdown(Q,{name:A.name,kind:A.kind,...A.organization?{organization:A.organization}:{},brainName:A.brainName,url:A.url,...A.did?{did:A.did}:{},status:A.status,discoveredAt:A.discoveredAt})}}class yQ2 extends C2{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:LIw,frontmatterSchema:Ut0})}fromMarkdown(A){let Q=this.parseFrontMatter(A,Ut0);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var N3$=new gQ2,j3$=new yQ2,PIw=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),examples:Z.array(Z.string())}),P3$=Z.object({skills:Z.array(PIw),agents:Z.array(Z.object({id:Z.string().optional(),name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),brainName:Z.string(),url:Z.url(),did:Z.string().optional(),status:Z.enum(["discovered","approved"]),discoveredAt:Z.string().datetime().optional(),about:Z.string(),skills:Z.array(hQ2),notes:Z.string().default("")}))});var MIw=Z.object({}).strict();function ZZ0(A={}){return MIw.parse(A),[Kt0()]}wA();N0();N0();var Dt0=Z.object({enabled:Z.boolean().default(!0),pdsEndpoint:Z.url().default("https://bsky.social").describe("AT Protocol PDS service endpoint"),identifier:Z.string().optional().describe("PDS login identifier, usually a handle or account DID"),repoDid:Z.string().optional().describe("DID of the PDS repo that owns records"),appPassword:Z.string().optional().describe("App password for prototype authentication; supply via ${ENV_VAR} interpolation, never a committed literal"),anchorDid:Z.string().optional().describe("Optional human/operator DID referenced from records; defaults to did:web:<site-host>:anchor when omitted"),brainDid:Z.string().optional().describe("Optional public brain DID referenced from records; defaults to did:web:<site-host> when omitted")});N0();var OIw=Z.looseObject({message:Z.string()}),xIw=Z.looseObject({did:Z.string(),handle:Z.string(),accessJwt:Z.string(),refreshJwt:Z.string()}),Gt0=Z.looseObject({uri:Z.string(),cid:Z.string()}),RIw=Gt0.extend({value:Z.record(Z.string(),Z.unknown())}),vIw=Z.looseObject({$type:Z.literal("blob").optional(),ref:Z.looseObject({$link:Z.string()}),mimeType:Z.string(),size:Z.number().int().nonnegative()}).transform((A)=>({...A.$type!==void 0?{$type:A.$type}:{},ref:{$link:A.ref.$link},mimeType:A.mimeType,size:A.size})),hIw=Z.looseObject({blob:vIw});function CIw(A){return A.replace(/\/+$/,"")}var gIw=(A,Q)=>fetch(A,Q);async function ro(A,Q){let w=await A.text(),B;try{B=w.length>0?JSON.parse(w):void 0}catch{if(!A.ok)throw Error(`AT Protocol request failed with ${A.status}`);throw Error("Failed to parse JSON")}if(!A.ok){let $=OIw.safeParse(B);throw Error($.success?$.data.message:`AT Protocol request failed with ${A.status}`)}return Q.parse(B)}class oo{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=CIw(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??gIw}async createSession(){let A=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.server.createSession`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({identifier:this.identifier,password:this.appPassword})}),Q=await ro(A,xIw);return this.session=Q,Q}async createRecord(A){let Q=await this.getSession(),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.createRecord`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":"application/json"},body:JSON.stringify({repo:A.repo,collection:A.collection,record:A.record,...A.rkey&&{rkey:A.rkey},...A.validate!==void 0&&{validate:A.validate}})});return ro(w,Gt0)}async putRecord(A){let Q=await this.getSession(),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.putRecord`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":"application/json"},body:JSON.stringify({repo:A.repo,collection:A.collection,record:A.record,rkey:A.rkey,...A.validate!==void 0&&{validate:A.validate},...A.swapRecord!==void 0&&{swapRecord:A.swapRecord}})});return ro(w,Gt0)}async getRecord(A){let Q=new URLSearchParams({repo:A.repo,collection:A.collection,rkey:A.rkey}),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.getRecord?${Q.toString()}`,{method:"GET"});return ro(w,RIw)}async uploadBlob(A){let Q=await this.getSession(),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.uploadBlob`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":A.mimeType},body:new Blob([new Uint8Array(A.data)],{type:A.mimeType})});return ro(w,hIw)}async getSession(){return this.session??=await this.createSession(),this.session}}function LP(A){return A?.startsWith("did:web:")??!1}function WZ0(A){if(!LP(A))return;let Q=A.slice(8);if(!Q)return;let[w]=Q.split(":");if(!w)return;try{return decodeURIComponent(w)}catch{return w}}function TQ2(A){if(!LP(A))return;let Q=A.slice(8);if(!Q)return;let[,...w]=Q.split(":");if(w.length===0)return"/.well-known/did.json";return`/${w.map(($)=>{try{return decodeURIComponent($)}catch{return $}}).join("/")}/did.json`}function SQ2(A){return A.replace(/\/+$/,"")}function so(A){return`did:web:${encodeURIComponent(A)}`}function HZ0(A){return`${so(A)}:anchor`}function zt0(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function mQ2(A,Q){let w=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...zt0(Q),...w&&{alsoKnownAs:w},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:SQ2(A.pdsEndpoint)}]}}function uQ2(A){if(!LP(A.brainDid))return null;return mQ2(A,A.brainDid)}function EQ2(A,Q){if(!A||!Q)return;let w=WZ0(A),B=TQ2(A);if(!w||!B)return;return{path:B,hostname:w,document:Q}}function KZ0(A){let Q=[],w=EQ2(A.brainDid,uQ2(A));if(w)Q.push(w);if(LP(A.anchorDid)&&A.anchorDid!==A.brainDid){let B=EQ2(A.anchorDid,zt0(A.anchorDid));if(B)Q.push(B)}return Q}function qt0(A,Q){let w=[];if(!A.brainDid){let B=so(Q);w.push({path:"/.well-known/did.json",hostname:Q,document:mQ2(A,B)})}if(!A.anchorDid){let B=HZ0(Q);w.push({path:"/anchor/did.json",hostname:Q,document:zt0(B)})}return w}function yIw(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function EIw(A){let Q=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,200);return Q.length>0?Q:"skill"}function cQ2(A,Q){let w=A[Q];return typeof w==="string"&&w.length>0?w:void 0}function lQ2(A,Q){let w=A[Q];if(!Array.isArray(w))return;let B=w.filter(($)=>typeof $==="string"&&$.length>0);return B.length>0?B:void 0}function TIw(A){let Q=A.metadata,w=cQ2(Q,"name"),B=cQ2(Q,"description");if(!w||!B)return;let $=lQ2(Q,"tags"),f=lQ2(Q,"examples");return{id:EIw(w),name:w,description:B,...$&&{tags:$},...f&&{examples:f}}}async function SIw(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map((w)=>TIw(w)).filter((w)=>w!==void 0).slice(0,100)}async function bt0(A,Q,w=new Date){let B=A.identity.get(),$=A.identity.getProfile(),f=await A.identity.getAppInfo(),Y=yIw(A.siteUrl??$.website,void 0);if(!Y)throw Error("AT Protocol brain card publishing requires siteUrl");let X=new URL(Y).hostname,W=Q.brainDid??so(X),H=Q.anchorDid??HZ0(X);if(LP(W)){if(WZ0(W)!==X)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let K=await SIw(A);return{$type:"ai.rizom.brain.card",siteUrl:Y,brain:{did:W,name:B.name,role:B.role,purpose:B.purpose,values:B.values},anchor:{did:H,name:$.name,kind:$.kind},skills:K,model:f.model,version:f.version,createdAt:w.toISOString(),updatedAt:w.toISOString()}}var pQ2={name:"@brains/atproto",version:"0.2.0-alpha.142",description:"AT Protocol integration for identity, publishing, discovery, and feeds",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var iQ2=L6["ai.rizom.brain.card"],uIw=Z.looseObject({did:Z.string()}),cIw=Z.looseObject({service:Z.array(Z.looseObject({id:Z.string().optional(),type:Z.string().optional(),serviceEndpoint:Z.string().optional()})).optional()}),lIw="ai.rizom.brain.card",pIw="self",dQ2=50;class Vt0 extends aQ{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",pQ2,A,Dt0);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??A8.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=KZ0(this.config),Q=[...!this.config.brainDid?["/.well-known/did.json"]:[],...!this.config.anchorDid?["/anchor/did.json"]:[]];return[...new Set([...A.map((B)=>B.path),...Q])].map((B)=>({path:B,method:"GET",public:!0,handler:($)=>{let f=new URL($.url).hostname,Y=[...KZ0(this.config),...qt0(this.config,f)].filter((W)=>W.path===B),X=Y.find((W)=>W.hostname===f)??Y[0];if(!X)return new Response("Not found",{status:404});return new Response(JSON.stringify(X.document),{headers:{"Content-Type":"application/did+json"}})}}))}async publishBrainCard(A,Q={}){let w=await bt0(A,this.config);Rq(iQ2,w);let B=this.config.repoDid;if(Q.dryRun)return{record:w,dryRun:!0,...B&&{repo:B}};let $=this.resolveAppPassword();if(!this.config.identifier||!$)throw Error("AT Protocol publishing requires identifier and app password configuration");let f=this.createPdsClient($),Y=await f.createSession(),X=B??Y.did;if(!f.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let W=await f.putRecord({repo:X,collection:"ai.rizom.brain.card",rkey:"self",validate:!1,record:w});return{record:w,repo:X,uri:W.uri,cid:W.cid,dryRun:!1}}async publishEntity(A,Q){let w=this.projectionRegistry.get(Q.entityType);if(!w)throw Error(`No AT Protocol projection registered for ${Q.entityType}`);return this.publishProjectedEntity(A,Q,w)}async publishPost(A,Q){let w=this.projectionRegistry.get("post");if(!w)throw Error("No AT Protocol projection registered for post");return this.publishProjectedEntity(A,{entityType:"post",...Q},w)}async discoverBrainCards(A,Q){let w=[...new Set(Q.repos.map((f)=>f.trim()))].filter((f)=>f.length>0);if(w.length===0)throw Error("AT Protocol discovery requires at least one repo DID or handle");if(w.length>dQ2)throw Error(`AT Protocol discovery accepts at most ${dQ2} repos per batch`);let B=new Set,$=[];for(let f of w)try{let Y=await this.resolveRepoPdsEndpoint(f),X=this.createPublicPdsClient(Y.pdsEndpoint);if(!X.getRecord)throw Error("AT Protocol PDS client does not support record reads");let W=await X.getRecord({repo:Y.repoDid,collection:lIw,rkey:pIw});Rq(iQ2,W.value);let H=dIw(W.uri)??Y.repoDid,K=`${H}:${W.uri}:${W.cid}`;if(B.has(K)){$.push({repo:f,status:"skipped",repoDid:H,uri:W.uri,cid:W.cid,error:"Duplicate brain card in discovery batch"});continue}B.add(K),await A.messaging.send({type:Md,payload:{repoDid:H,uri:W.uri,cid:W.cid,record:W.value},broadcast:!0}),$.push({repo:f,status:"discovered",repoDid:H,uri:W.uri,cid:W.cid})}catch(Y){$.push({repo:f,status:"skipped",error:mA(Y)})}return{discovered:$.filter((f)=>f.status==="discovered").length,skipped:$.filter((f)=>f.status==="skipped").length,results:$}}async validatePdsCredentials(){let A=this.resolveAppPassword();if(!this.config.identifier||!A)return!1;try{return await this.createPdsClient(A).createSession(),!0}catch(Q){return this.logger.warn("AT Protocol PDS authentication failed",{error:mA(Q)}),!1}}async getTools(){return[]}async publishProjectedEntity(A,Q,w){let B=await this.findPublishEntity(A,Q),$=Q.entityId??Q.slug;if(!$)throw Error(`${Q.entityType} publish requires entityId or slug`);if(!B)throw Error(`${Q.entityType} not found: ${$}`);if(B.visibility!=="public")throw Error(`Cannot publish non-public ${Q.entityType}: ${$}`);let f=this.config.repoDid;if(Q.dryRun){let D=await w.buildRecord({entity:B,context:A,config:this.config,...Q.topics&&{topics:Q.topics},dryRun:!0});return Rq(w.lexicon,D),{record:D,dryRun:!0,...f&&{repo:f}}}let Y=this.resolveAppPassword();if(!this.config.identifier||!Y)throw Error("AT Protocol publishing requires identifier and app password configuration");let X=this.createPdsClient(Y),W=await X.createSession(),H=f??W.did,K=await w.buildRecord({entity:B,context:A,config:this.config,client:X,...Q.topics&&{topics:Q.topics}});if(Rq(w.lexicon,K),!X.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let U=await X.putRecord({repo:H,collection:w.collection,rkey:iIw(B.id),...w.validate!==void 0&&{validate:w.validate},record:K});return await w.onPublished?.({entity:B,context:A,record:K,uri:U.uri,cid:U.cid}),{record:K,repo:H,uri:U.uri,cid:U.cid,dryRun:!1}}async findPublishEntity(A,Q){if(Q.entityId)return A.entityService.getEntity({entityType:Q.entityType,id:Q.entityId});if(Q.slug)return(await A.entityService.listEntities({entityType:Q.entityType,options:{filter:{metadata:{slug:Q.slug}}}}))[0]??null;return null}createPublicPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""});return new oo({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""})}async resolveRepoPdsEndpoint(A){let Q=A.startsWith("did:")?A:await this.resolveHandleToDid(A);if(!Q)throw Error(`Could not resolve AT Protocol repo: ${A}`);let w=await this.resolveDidToPdsEndpoint(Q);if(!w)throw Error(`Could not resolve AT Protocol PDS for repo: ${Q}`);return{repoDid:Q,pdsEndpoint:w}}async resolveHandleToDid(A){let Q=new URL("/xrpc/com.atproto.identity.resolveHandle",this.config.pdsEndpoint);Q.searchParams.set("handle",A);let w=await this.fetch(Q.toString());if(!w.ok)return;let B=uIw.safeParse(await w.json());return B.success?B.data.did:void 0}async resolveDidToPdsEndpoint(A){let Q=A.startsWith("did:plc:")?await this.fetchJson(`https://plc.directory/${encodeURIComponent(A)}`):A.startsWith("did:web:")?await this.fetchJson(nIw(A)):void 0,w=cIw.safeParse(Q);if(!w.success)return;return w.data.service?.find(($)=>$.id==="#atproto_pds"||$.type==="AtprotoPersonalDataServer")?.serviceEndpoint}async fetchJson(A){let Q=await this.fetch(A);if(!Q.ok)return;return Q.json()}fetch(A){return(this.deps.fetch??fetch)(A)}createPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A});return new oo({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function iIw(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function dIw(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function nIw(A){let Q=A.slice(8).split(":").map(decodeURIComponent),[w,...B]=Q;if(!w)throw Error(`Invalid did:web value: ${A}`);if(B.length===0)return`https://${w}/.well-known/did.json`;return`https://${w}/${B.join("/")}/did.json`}function UZ0(A,Q){return new Vt0(A,Q)}wA();N0();var DZ0={name:"@brains/rover",version:"0.2.0-alpha.142",dependencies:{"@brains/a2a":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/analytics":"workspace:*","@brains/app":"workspace:*","@brains/assessment":"workspace:*","@brains/atproto":"workspace:*","@brains/atproto-registry":"workspace:*","@brains/auth-service":"workspace:*","@brains/blog":"workspace:*","@brains/chat":"workspace:*","@brains/cms":"workspace:*","@brains/content-pipeline":"workspace:*","@brains/dashboard":"workspace:*","@brains/decks":"workspace:*","@brains/directory-sync":"workspace:*","@brains/discord":"workspace:*","@brains/doc":"workspace:*","@brains/document-plugin":"workspace:*","@brains/email-resend":"workspace:*","@brains/image-plugin":"workspace:*","@brains/link":"workspace:*","@brains/mcp":"workspace:*","@brains/newsletter":"workspace:*","@brains/note":"workspace:*","@brains/notifications":"workspace:*","@brains/obsidian-vault":"workspace:*","@brains/playbooks":"workspace:*","@brains/portfolio":"workspace:*","@brains/prompt":"workspace:*","@brains/rizom-ecosystem":"workspace:*","@brains/rover-onboarding":"workspace:*","@brains/series":"workspace:*","@brains/site-builder-plugin":"workspace:*","@brains/site-default":"workspace:*","@brains/site-info":"workspace:*","@brains/social-media":"workspace:*","@brains/stock-photo":"workspace:*","@brains/theme-default":"workspace:*","@brains/topics":"workspace:*","@brains/web-chat":"workspace:*","@brains/webserver":"workspace:*","@brains/wishlist":"workspace:*"},devDependencies:{"@brains/ai-evaluation":"workspace:*","@brains/typescript-config":"workspace:*",typescript:"^6.0.3"},files:["src","brain.eval.yaml","env.schema.template"],main:"./src/index.ts",private:!0,scripts:{"build:web-chat":"turbo run build --filter=@brains/web-chat",eval:"brain-eval","eval:core":"brain-eval --suite core","eval:core:coverage":"brain-eval --suite core --tool-coverage","eval:default":"brain-eval --suite default","eval:default:coverage":"brain-eval --suite default --tool-coverage","eval:full":"brain-eval --suite full","eval:full:coverage":"brain-eval --suite full --tool-coverage",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix","start:core":"bun run build:web-chat && cd test-apps/core && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","start:default":"bun run build:web-chat && cd test-apps/default && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","start:full":"bun run build:web-chat && cd test-apps/full && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var oIw=Z.looseObject({});class nQ2 extends aQ{constructor(A={}){super("rover-profile",DZ0,A,oIw)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",_k)}}function rQ2(A={}){return new nQ2(A)}wA();N0();NB();wA();wA();var ao=bz.extend(_k.shape);class GZ0{postsListUrl;decksListUrl;id="professional:homepage-list";name="Homepage List DataSource";description="Fetches profile, blog posts, and presentation decks for homepage";constructor(A,Q){this.postsListUrl=A,this.decksListUrl=Q}async fetch(A,Q,w){let B=w.entityService,[$,f,Y,X]=await Promise.all([Hx(B,ao),_f0(B,{entityType:"post",count:3,parse:Nr}),_f0(B,{entityType:"deck",count:3,parse:vr}),kr(B)]),W={profile:$,posts:f,decks:Y,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:mn0(X.cta),sections:X.sections??{}};return Q.parse(W)}}wA();class zZ0{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,w){let $={profile:await Hx(w.entityService,ao)};return Q.parse($)}}import{jsxDEV as xB,Fragment as tIw}from"preact/jsx-dev-runtime";var sIw="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",aIw="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",It0=({number:A,title:Q,blurb:w,children:B})=>xB("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:xB("div",{className:"max-w-6xl mx-auto",children:xB("div",{className:sIw,children:[xB(ep0,{title:Q,number:A,blurb:w},void 0,!1,void 0,this),xB("div",{className:aIw,"aria-hidden":"true"},void 0,!1,void 0,this),xB("div",{className:"mt-6 md:mt-0",children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),Jt0=({profile:A,posts:Q,decks:w,postsListUrl:B,decksListUrl:$,cta:f,sections:Y})=>{let X=A.tagline?.length?A.tagline:A.description,W=Q.map((q)=>({id:q.id,url:q.url,title:q.metadata.title,date:q.metadata.publishedAt??q.created,description:q.frontmatter.excerpt,series:q.frontmatter.seriesName&&q.frontmatter.seriesIndex?{name:q.frontmatter.seriesName,index:q.frontmatter.seriesIndex}:void 0})),H=w.map((q)=>({id:q.id,url:q.url,title:q.frontmatter.title||q.id,date:q.frontmatter.publishedAt??q.created,description:q.frontmatter.description})),K=A.name||"Home",U=[A.intro,A.description,X].find((q)=>q)??"Professional site",D=Boolean(A.description)||A.expertise!==void 0&&A.expertise.length>0;return xB(tIw,{children:[xB(lQ,{title:K,description:U,ogType:"website"},void 0,!1,void 0,this),xB("div",{className:"homepage-list bg-theme",children:[xB("header",{className:"hero-bg-pattern relative w-full px-6 md:px-12 pt-28 pb-24 md:pt-28 md:pb-24 overflow-hidden border-b border-rule",children:xB("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&xB("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[xB("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),xB("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),X&&xB("h1",{className:"font-heading text-[clamp(2.75rem,6.5vw,5.5rem)] font-normal text-heading leading-[1.02] tracking-[-0.025em] max-w-[18ch] [font-variation-settings:'opsz'_144,'SOFT'_30]",children:T70(X,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&xB("p",{className:"font-heading font-light text-[clamp(1.1rem,1.8vw,1.4rem)] leading-[1.5] text-theme-muted max-w-[42ch] mt-8 [font-variation-settings:'opsz'_24]",children:T70(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),xB(It0,{number:"01",title:"Essays",blurb:Y.essays?.blurb,children:xB(E70,{items:W,viewAllUrl:B,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),H.length>0&&xB(It0,{number:"02",title:"Presentations",blurb:Y.presentations?.blurb,children:xB(E70,{items:H,viewAllUrl:$,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D&&xB(It0,{number:"03",title:"About",blurb:Y.about?.blurb,children:xB("div",{className:"flex flex-col gap-8",children:[A.description&&xB("p",{className:"font-heading font-light text-[1.25rem] leading-[1.55] text-theme max-w-[55ch] [font-variation-settings:'opsz'_24,'SOFT'_50]",children:A.description},void 0,!1,void 0,this),A.expertise&&A.expertise.length>0&&xB(Ai0,{subjects:A.expertise},void 0,!1,void 0,this),xB("a",{href:"/about",className:"mt-6 inline-flex items-center gap-2 font-mono text-[0.7rem] font-medium uppercase tracking-[0.18em] text-accent pb-1 relative before:content-[''] before:absolute before:left-0 before:right-full before:bottom-0 before:h-px before:bg-accent before:transition-[right] before:duration-300 hover:before:right-0",children:["Learn more",xB("span",{"aria-hidden":"true",children:"\u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),xB(Tp0,{cta:f,variant:"editorial",socialLinks:A.socialLinks},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as s6,Fragment as eIw}from"preact/jsx-dev-runtime";var Ft0=({profile:A})=>{let Q=`About ${A.name||"Me"}`,w=[A.description,A.intro].find(($)=>$)??"About page",B=A.expertise!==void 0&&A.expertise.length>0||Boolean(A.currentFocus)||Boolean(A.availability)||Boolean(A.email)||Boolean(A.website)||A.socialLinks!==void 0&&A.socialLinks.length>0;return s6(eIw,{children:[s6(lQ,{title:Q,description:w,ogType:"profile"},void 0,!1,void 0,this),s6("div",{className:"about-page bg-theme",children:[s6("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:s6("div",{className:"relative z-10 max-w-4xl mx-auto",children:[s6("h1",{className:"text-5xl md:text-6xl font-semibold mb-6 text-heading",children:["About ",A.name||"Me"]},void 0,!0,void 0,this),A.description&&s6("p",{className:"text-xl md:text-2xl text-theme-muted leading-relaxed",children:A.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),s6("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&s6("section",{className:"content-section-reveal mb-20 md:mb-28",children:s6(V9,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),B&&s6("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&s6("section",{children:[s6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),s6("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map(($,f)=>s6("li",{className:Jn({variant:"accent",size:"lg"}),children:$},f,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&s6("section",{children:[s6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),s6("p",{className:"text-lg text-theme leading-relaxed",children:A.currentFocus},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.availability&&s6("section",{children:[s6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),s6("p",{className:"text-lg text-theme leading-relaxed",children:A.availability},void 0,!1,void 0,this)]},void 0,!0,void 0,this),(Boolean(A.email)||Boolean(A.website)||A.socialLinks!==void 0&&A.socialLinks.length>0)&&s6("section",{children:[s6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),s6("div",{className:"space-y-4",children:[A.email&&s6("p",{className:"text-lg",children:s6("a",{href:`mailto:${A.email}`,className:"text-brand hover:text-brand-dark transition-colors",children:A.email},void 0,!1,void 0,this)},void 0,!1,void 0,this),A.website&&s6("p",{className:"text-lg",children:s6("a",{href:A.website,target:"_blank",rel:"noopener noreferrer",className:"text-brand hover:text-brand-dark transition-colors",children:A.website},void 0,!1,void 0,this)},void 0,!1,void 0,this),A.socialLinks&&A.socialLinks.length>0&&s6("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map(($,f)=>s6(b9,{href:$.url,external:!0,variant:"secondary",size:"md",children:$.label?.length?$.label:$.platform},f,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as d4,Fragment as oQ2}from"preact/jsx-dev-runtime";var Lt0=()=>{return d4(oQ2,{children:[d4(lQ,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),d4("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:d4("div",{className:"text-center max-w-md",children:[d4("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),d4("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),d4("p",{className:"text-lg text-theme-muted mb-8",children:"You'll receive a confirmation email shortly. Check your inbox to confirm your subscription."},void 0,!1,void 0,this),d4(b9,{href:"/",variant:"primary",children:"Back to Home"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},kt0=()=>{return d4(oQ2,{children:[d4(lQ,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),d4("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:d4("div",{className:"text-center max-w-md",children:[d4("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),d4("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),d4("p",{className:"text-lg text-theme-muted mb-8",children:"We couldn't process your subscription. Please try again or contact us if the problem persists."},void 0,!1,void 0,this),d4(b9,{href:"/",variant:"primary",children:"Back to Home"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};N0();var sQ2=Z.object({label:Z.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:Z.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),AJw={post:{label:"Post"},deck:{label:"Deck"}},aQ2=Z.object({entityDisplay:Z.object({post:sQ2,deck:sQ2}).default(AJw).describe("Display metadata for post and deck entity types used by the homepage")});var tQ2={name:"@brains/site-professional",version:"0.2.0-alpha.142",description:"Professional site composition package",dependencies:{"@brains/blog":"workspace:*","@brains/decks":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-engine":"workspace:*","@brains/site-info":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},files:["src"],private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",typecheck:"tsc --noEmit"},type:"module"};var wJw=Z.object({blurb:Z.string().optional().describe("Short italic subtitle under the section title")}),BJw=Z.object({heading:Z.string(),buttonText:Z.string(),buttonLink:Z.string()}),eQ2=Z.looseObject({name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),description:Z.string().optional(),avatar:Z.string().optional(),website:Z.string().optional(),email:Z.string().optional(),socialLinks:Z.array(Z.object({platform:Z.enum(["github","instagram","linkedin","email","website"]),url:Z.string(),label:Z.string().optional()})).optional(),tagline:Z.string().optional(),intro:Z.string().optional(),story:Z.string().optional(),role:Z.string().optional(),audience:Z.string().optional(),expertise:Z.array(Z.string()).optional(),currentFocus:Z.string().optional(),availability:Z.string().optional(),desiredTone:Z.string().optional()}),$Jw=Z.looseObject({id:Z.string(),entityType:Z.literal("post"),content:Z.string(),created:Z.string(),updated:Z.string(),contentHash:Z.string(),metadata:Z.looseObject({title:Z.string(),publishedAt:Z.string().optional()}),frontmatter:Z.looseObject({excerpt:Z.string(),seriesName:Z.string().optional(),seriesIndex:Z.number().optional()}),body:Z.string(),url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),seriesUrl:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional(),coverImageSrcset:Z.string().optional(),coverImageSizes:Z.string().optional()}),fJw=Z.looseObject({id:Z.string(),entityType:Z.literal("deck"),content:Z.string(),created:Z.string(),updated:Z.string(),contentHash:Z.string(),metadata:Z.looseObject({title:Z.string(),publishedAt:Z.string().optional()}),frontmatter:Z.looseObject({title:Z.string(),description:Z.string().optional(),publishedAt:Z.string().optional()}),body:Z.string(),url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});class _t0 extends aQ{dependencies=["blog","decks"];constructor(A){super("professional-site",tQ2,A,aQ2)}async onRegister(A){let Q=this.config.entityDisplay.post,w=this.config.entityDisplay.deck,B=`/${Q.pluralName??Q.label.toLowerCase()+"s"}`,$=`/${w.pluralName??w.label.toLowerCase()+"s"}`,f=new GZ0(B,$);A.entities.registerDataSource(f);let Y=new zZ0;A.entities.registerDataSource(Y);let X=Z.object({profile:eQ2,posts:Z.array($Jw),decks:Z.array(fJw),postsListUrl:Z.string(),decksListUrl:Z.string(),cta:BJw,sections:Z.record(Z.string(),wJw)}),W=Z.object({profile:eQ2}),H=Z.object({});A.templates.register({"homepage-list":i1({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:X,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:Jt0}}),about:i1({name:"about",description:"About page with full profile information",schema:W,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:Ft0}}),"subscribe-thanks":i1({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:H,requiredPermission:"public",layout:{component:Lt0}}),"subscribe-error":i1({name:"subscribe-error",description:"Newsletter subscription error page",schema:H,requiredPermission:"public",layout:{component:kt0}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function Aw2(A){return new _t0(A??{})}var Qw2=[{id:"home",path:"/",title:"Home",description:"Professional site homepage",layout:"default",navigation:{show:!0,label:"Home",slot:"secondary",priority:10},sections:[{id:"homepage",template:"professional-site:homepage-list",dataQuery:{}}]},{id:"about",path:"/about",title:"About",description:"About page",layout:"default",navigation:{show:!0,label:"About",slot:"primary",priority:90},sections:[{id:"about",template:"professional-site:about",dataQuery:{}}]},{id:"subscribe-thanks",path:"/subscribe/thanks",title:"Thanks for subscribing",description:"Newsletter subscription confirmation",layout:"default",navigation:{show:!1},sections:[{id:"subscribe-thanks",template:"professional-site:subscribe-thanks",dataQuery:{},content:{}}]},{id:"subscribe-error",path:"/subscribe/error",title:"Subscription failed",description:"Newsletter subscription error",layout:"default",navigation:{show:!1},sections:[{id:"subscribe-error",template:"professional-site:subscribe-error",dataQuery:{},content:{}}]}];import{jsxDEV as qZ0}from"preact/jsx-dev-runtime";function ww2({sections:A,siteInfo:Q,slots:w,wordmark:B}){return qZ0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[qZ0(cp0,{title:Q.title,navigation:Q.navigation.primary,showThemeToggle:!0,...Q.logo!==void 0?{logo:Q.logo}:{},...B!==void 0?{wordmark:B}:{}},void 0,!1,void 0,this),qZ0("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),qZ0(up0,{primaryNavigation:Q.navigation.primary,secondaryNavigation:Q.navigation.secondary,copyright:Q.copyright,socialLinks:Q.socialLinks,title:Q.title,tagline:Q.description,children:w?.getSlot("footer-top").map(($)=>$.render())},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var YJw={layouts:{default:ww2},routes:Qw2,plugin:Aw2,entityDisplay:{post:{label:"Post"},deck:{label:"Deck"},project:{label:"Project"},series:{label:"Series",navigation:{slot:"secondary"}},topic:{label:"Topic",navigation:{slot:"secondary"}},link:{label:"Link",navigation:{slot:"secondary"}},base:{label:"Note",navigation:{show:!1}},"social-post":{label:"Social Post",pluralName:"social-posts",navigation:{slot:"secondary"}},newsletter:{label:"Newsletter",navigation:{slot:"secondary"}}}},to=YJw;var Bw2=`/*
8784
+ `).map((Q)=>Q.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/)).filter((Q)=>Q!==null).map((Q)=>({name:Q[1]??"",description:Q[2]??"",tags:Q[3]?Q[3].split(",").map((w)=>w.trim()).filter(Boolean):[]}))}var jIw=new G6(kIw,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:_Iw,parser:NIw},{key:"notes",label:"Notes",type:"string"}]});class gQ2 extends C2{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:FIw,frontmatterSchema:JIw})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=jIw.format({about:A.about,skills:A.skills,notes:A.notes});return this.buildMarkdown(Q,{name:A.name,kind:A.kind,...A.organization?{organization:A.organization}:{},brainName:A.brainName,url:A.url,...A.did?{did:A.did}:{},status:A.status,discoveredAt:A.discoveredAt})}}class yQ2 extends C2{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:LIw,frontmatterSchema:Ut0})}fromMarkdown(A){let Q=this.parseFrontMatter(A,Ut0);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var N3$=new gQ2,j3$=new yQ2,PIw=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),examples:Z.array(Z.string())}),P3$=Z.object({skills:Z.array(PIw),agents:Z.array(Z.object({id:Z.string().optional(),name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),brainName:Z.string(),url:Z.url(),did:Z.string().optional(),status:Z.enum(["discovered","approved"]),discoveredAt:Z.string().datetime().optional(),about:Z.string(),skills:Z.array(hQ2),notes:Z.string().default("")}))});var MIw=Z.object({}).strict();function ZZ0(A={}){return MIw.parse(A),[Kt0()]}wA();N0();N0();var Dt0=Z.object({enabled:Z.boolean().default(!0),pdsEndpoint:Z.url().default("https://bsky.social").describe("AT Protocol PDS service endpoint"),identifier:Z.string().optional().describe("PDS login identifier, usually a handle or account DID"),repoDid:Z.string().optional().describe("DID of the PDS repo that owns records"),appPassword:Z.string().optional().describe("App password for prototype authentication; supply via ${ENV_VAR} interpolation, never a committed literal"),anchorDid:Z.string().optional().describe("Optional human/operator DID referenced from records; defaults to did:web:<site-host>:anchor when omitted"),brainDid:Z.string().optional().describe("Optional public brain DID referenced from records; defaults to did:web:<site-host> when omitted")});N0();var OIw=Z.looseObject({message:Z.string()}),xIw=Z.looseObject({did:Z.string(),handle:Z.string(),accessJwt:Z.string(),refreshJwt:Z.string()}),Gt0=Z.looseObject({uri:Z.string(),cid:Z.string()}),RIw=Gt0.extend({value:Z.record(Z.string(),Z.unknown())}),vIw=Z.looseObject({$type:Z.literal("blob").optional(),ref:Z.looseObject({$link:Z.string()}),mimeType:Z.string(),size:Z.number().int().nonnegative()}).transform((A)=>({...A.$type!==void 0?{$type:A.$type}:{},ref:{$link:A.ref.$link},mimeType:A.mimeType,size:A.size})),hIw=Z.looseObject({blob:vIw});function CIw(A){return A.replace(/\/+$/,"")}var gIw=(A,Q)=>fetch(A,Q);async function ro(A,Q){let w=await A.text(),B;try{B=w.length>0?JSON.parse(w):void 0}catch{if(!A.ok)throw Error(`AT Protocol request failed with ${A.status}`);throw Error("Failed to parse JSON")}if(!A.ok){let $=OIw.safeParse(B);throw Error($.success?$.data.message:`AT Protocol request failed with ${A.status}`)}return Q.parse(B)}class oo{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=CIw(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??gIw}async createSession(){let A=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.server.createSession`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({identifier:this.identifier,password:this.appPassword})}),Q=await ro(A,xIw);return this.session=Q,Q}async createRecord(A){let Q=await this.getSession(),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.createRecord`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":"application/json"},body:JSON.stringify({repo:A.repo,collection:A.collection,record:A.record,...A.rkey&&{rkey:A.rkey},...A.validate!==void 0&&{validate:A.validate}})});return ro(w,Gt0)}async putRecord(A){let Q=await this.getSession(),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.putRecord`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":"application/json"},body:JSON.stringify({repo:A.repo,collection:A.collection,record:A.record,rkey:A.rkey,...A.validate!==void 0&&{validate:A.validate},...A.swapRecord!==void 0&&{swapRecord:A.swapRecord}})});return ro(w,Gt0)}async getRecord(A){let Q=new URLSearchParams({repo:A.repo,collection:A.collection,rkey:A.rkey}),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.getRecord?${Q.toString()}`,{method:"GET"});return ro(w,RIw)}async uploadBlob(A){let Q=await this.getSession(),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.uploadBlob`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":A.mimeType},body:new Blob([new Uint8Array(A.data)],{type:A.mimeType})});return ro(w,hIw)}async getSession(){return this.session??=await this.createSession(),this.session}}function LP(A){return A?.startsWith("did:web:")??!1}function WZ0(A){if(!LP(A))return;let Q=A.slice(8);if(!Q)return;let[w]=Q.split(":");if(!w)return;try{return decodeURIComponent(w)}catch{return w}}function TQ2(A){if(!LP(A))return;let Q=A.slice(8);if(!Q)return;let[,...w]=Q.split(":");if(w.length===0)return"/.well-known/did.json";return`/${w.map(($)=>{try{return decodeURIComponent($)}catch{return $}}).join("/")}/did.json`}function SQ2(A){return A.replace(/\/+$/,"")}function so(A){return`did:web:${encodeURIComponent(A)}`}function HZ0(A){return`${so(A)}:anchor`}function zt0(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function mQ2(A,Q){let w=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...zt0(Q),...w&&{alsoKnownAs:w},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:SQ2(A.pdsEndpoint)}]}}function uQ2(A){if(!LP(A.brainDid))return null;return mQ2(A,A.brainDid)}function EQ2(A,Q){if(!A||!Q)return;let w=WZ0(A),B=TQ2(A);if(!w||!B)return;return{path:B,hostname:w,document:Q}}function KZ0(A){let Q=[],w=EQ2(A.brainDid,uQ2(A));if(w)Q.push(w);if(LP(A.anchorDid)&&A.anchorDid!==A.brainDid){let B=EQ2(A.anchorDid,zt0(A.anchorDid));if(B)Q.push(B)}return Q}function qt0(A,Q){let w=[];if(!A.brainDid){let B=so(Q);w.push({path:"/.well-known/did.json",hostname:Q,document:mQ2(A,B)})}if(!A.anchorDid){let B=HZ0(Q);w.push({path:"/anchor/did.json",hostname:Q,document:zt0(B)})}return w}function yIw(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function EIw(A){let Q=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,200);return Q.length>0?Q:"skill"}function cQ2(A,Q){let w=A[Q];return typeof w==="string"&&w.length>0?w:void 0}function lQ2(A,Q){let w=A[Q];if(!Array.isArray(w))return;let B=w.filter(($)=>typeof $==="string"&&$.length>0);return B.length>0?B:void 0}function TIw(A){let Q=A.metadata,w=cQ2(Q,"name"),B=cQ2(Q,"description");if(!w||!B)return;let $=lQ2(Q,"tags"),f=lQ2(Q,"examples");return{id:EIw(w),name:w,description:B,...$&&{tags:$},...f&&{examples:f}}}async function SIw(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map((w)=>TIw(w)).filter((w)=>w!==void 0).slice(0,100)}async function bt0(A,Q,w=new Date){let B=A.identity.get(),$=A.identity.getProfile(),f=await A.identity.getAppInfo(),Y=yIw(A.siteUrl??$.website,void 0);if(!Y)throw Error("AT Protocol brain card publishing requires siteUrl");let X=new URL(Y).hostname,W=Q.brainDid??so(X),H=Q.anchorDid??HZ0(X);if(LP(W)){if(WZ0(W)!==X)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let K=await SIw(A);return{$type:"ai.rizom.brain.card",siteUrl:Y,brain:{did:W,name:B.name,role:B.role,purpose:B.purpose,values:B.values},anchor:{did:H,name:$.name,kind:$.kind},skills:K,model:f.model,version:f.version,createdAt:w.toISOString(),updatedAt:w.toISOString()}}var pQ2={name:"@brains/atproto",version:"0.2.0-alpha.143",description:"AT Protocol integration for identity, publishing, discovery, and feeds",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var iQ2=L6["ai.rizom.brain.card"],uIw=Z.looseObject({did:Z.string()}),cIw=Z.looseObject({service:Z.array(Z.looseObject({id:Z.string().optional(),type:Z.string().optional(),serviceEndpoint:Z.string().optional()})).optional()}),lIw="ai.rizom.brain.card",pIw="self",dQ2=50;class Vt0 extends aQ{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",pQ2,A,Dt0);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??A8.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=KZ0(this.config),Q=[...!this.config.brainDid?["/.well-known/did.json"]:[],...!this.config.anchorDid?["/anchor/did.json"]:[]];return[...new Set([...A.map((B)=>B.path),...Q])].map((B)=>({path:B,method:"GET",public:!0,handler:($)=>{let f=new URL($.url).hostname,Y=[...KZ0(this.config),...qt0(this.config,f)].filter((W)=>W.path===B),X=Y.find((W)=>W.hostname===f)??Y[0];if(!X)return new Response("Not found",{status:404});return new Response(JSON.stringify(X.document),{headers:{"Content-Type":"application/did+json"}})}}))}async publishBrainCard(A,Q={}){let w=await bt0(A,this.config);Rq(iQ2,w);let B=this.config.repoDid;if(Q.dryRun)return{record:w,dryRun:!0,...B&&{repo:B}};let $=this.resolveAppPassword();if(!this.config.identifier||!$)throw Error("AT Protocol publishing requires identifier and app password configuration");let f=this.createPdsClient($),Y=await f.createSession(),X=B??Y.did;if(!f.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let W=await f.putRecord({repo:X,collection:"ai.rizom.brain.card",rkey:"self",validate:!1,record:w});return{record:w,repo:X,uri:W.uri,cid:W.cid,dryRun:!1}}async publishEntity(A,Q){let w=this.projectionRegistry.get(Q.entityType);if(!w)throw Error(`No AT Protocol projection registered for ${Q.entityType}`);return this.publishProjectedEntity(A,Q,w)}async publishPost(A,Q){let w=this.projectionRegistry.get("post");if(!w)throw Error("No AT Protocol projection registered for post");return this.publishProjectedEntity(A,{entityType:"post",...Q},w)}async discoverBrainCards(A,Q){let w=[...new Set(Q.repos.map((f)=>f.trim()))].filter((f)=>f.length>0);if(w.length===0)throw Error("AT Protocol discovery requires at least one repo DID or handle");if(w.length>dQ2)throw Error(`AT Protocol discovery accepts at most ${dQ2} repos per batch`);let B=new Set,$=[];for(let f of w)try{let Y=await this.resolveRepoPdsEndpoint(f),X=this.createPublicPdsClient(Y.pdsEndpoint);if(!X.getRecord)throw Error("AT Protocol PDS client does not support record reads");let W=await X.getRecord({repo:Y.repoDid,collection:lIw,rkey:pIw});Rq(iQ2,W.value);let H=dIw(W.uri)??Y.repoDid,K=`${H}:${W.uri}:${W.cid}`;if(B.has(K)){$.push({repo:f,status:"skipped",repoDid:H,uri:W.uri,cid:W.cid,error:"Duplicate brain card in discovery batch"});continue}B.add(K),await A.messaging.send({type:Md,payload:{repoDid:H,uri:W.uri,cid:W.cid,record:W.value},broadcast:!0}),$.push({repo:f,status:"discovered",repoDid:H,uri:W.uri,cid:W.cid})}catch(Y){$.push({repo:f,status:"skipped",error:mA(Y)})}return{discovered:$.filter((f)=>f.status==="discovered").length,skipped:$.filter((f)=>f.status==="skipped").length,results:$}}async validatePdsCredentials(){let A=this.resolveAppPassword();if(!this.config.identifier||!A)return!1;try{return await this.createPdsClient(A).createSession(),!0}catch(Q){return this.logger.warn("AT Protocol PDS authentication failed",{error:mA(Q)}),!1}}async getTools(){return[]}async publishProjectedEntity(A,Q,w){let B=await this.findPublishEntity(A,Q),$=Q.entityId??Q.slug;if(!$)throw Error(`${Q.entityType} publish requires entityId or slug`);if(!B)throw Error(`${Q.entityType} not found: ${$}`);if(B.visibility!=="public")throw Error(`Cannot publish non-public ${Q.entityType}: ${$}`);let f=this.config.repoDid;if(Q.dryRun){let D=await w.buildRecord({entity:B,context:A,config:this.config,...Q.topics&&{topics:Q.topics},dryRun:!0});return Rq(w.lexicon,D),{record:D,dryRun:!0,...f&&{repo:f}}}let Y=this.resolveAppPassword();if(!this.config.identifier||!Y)throw Error("AT Protocol publishing requires identifier and app password configuration");let X=this.createPdsClient(Y),W=await X.createSession(),H=f??W.did,K=await w.buildRecord({entity:B,context:A,config:this.config,client:X,...Q.topics&&{topics:Q.topics}});if(Rq(w.lexicon,K),!X.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let U=await X.putRecord({repo:H,collection:w.collection,rkey:iIw(B.id),...w.validate!==void 0&&{validate:w.validate},record:K});return await w.onPublished?.({entity:B,context:A,record:K,uri:U.uri,cid:U.cid}),{record:K,repo:H,uri:U.uri,cid:U.cid,dryRun:!1}}async findPublishEntity(A,Q){if(Q.entityId)return A.entityService.getEntity({entityType:Q.entityType,id:Q.entityId});if(Q.slug)return(await A.entityService.listEntities({entityType:Q.entityType,options:{filter:{metadata:{slug:Q.slug}}}}))[0]??null;return null}createPublicPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""});return new oo({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""})}async resolveRepoPdsEndpoint(A){let Q=A.startsWith("did:")?A:await this.resolveHandleToDid(A);if(!Q)throw Error(`Could not resolve AT Protocol repo: ${A}`);let w=await this.resolveDidToPdsEndpoint(Q);if(!w)throw Error(`Could not resolve AT Protocol PDS for repo: ${Q}`);return{repoDid:Q,pdsEndpoint:w}}async resolveHandleToDid(A){let Q=new URL("/xrpc/com.atproto.identity.resolveHandle",this.config.pdsEndpoint);Q.searchParams.set("handle",A);let w=await this.fetch(Q.toString());if(!w.ok)return;let B=uIw.safeParse(await w.json());return B.success?B.data.did:void 0}async resolveDidToPdsEndpoint(A){let Q=A.startsWith("did:plc:")?await this.fetchJson(`https://plc.directory/${encodeURIComponent(A)}`):A.startsWith("did:web:")?await this.fetchJson(nIw(A)):void 0,w=cIw.safeParse(Q);if(!w.success)return;return w.data.service?.find(($)=>$.id==="#atproto_pds"||$.type==="AtprotoPersonalDataServer")?.serviceEndpoint}async fetchJson(A){let Q=await this.fetch(A);if(!Q.ok)return;return Q.json()}fetch(A){return(this.deps.fetch??fetch)(A)}createPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A});return new oo({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function iIw(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function dIw(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function nIw(A){let Q=A.slice(8).split(":").map(decodeURIComponent),[w,...B]=Q;if(!w)throw Error(`Invalid did:web value: ${A}`);if(B.length===0)return`https://${w}/.well-known/did.json`;return`https://${w}/${B.join("/")}/did.json`}function UZ0(A,Q){return new Vt0(A,Q)}wA();N0();var DZ0={name:"@brains/rover",version:"0.2.0-alpha.143",dependencies:{"@brains/a2a":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/analytics":"workspace:*","@brains/app":"workspace:*","@brains/assessment":"workspace:*","@brains/atproto":"workspace:*","@brains/atproto-registry":"workspace:*","@brains/auth-service":"workspace:*","@brains/blog":"workspace:*","@brains/chat":"workspace:*","@brains/cms":"workspace:*","@brains/content-pipeline":"workspace:*","@brains/dashboard":"workspace:*","@brains/decks":"workspace:*","@brains/directory-sync":"workspace:*","@brains/discord":"workspace:*","@brains/doc":"workspace:*","@brains/document-plugin":"workspace:*","@brains/email-resend":"workspace:*","@brains/image-plugin":"workspace:*","@brains/link":"workspace:*","@brains/mcp":"workspace:*","@brains/newsletter":"workspace:*","@brains/note":"workspace:*","@brains/notifications":"workspace:*","@brains/obsidian-vault":"workspace:*","@brains/playbooks":"workspace:*","@brains/portfolio":"workspace:*","@brains/prompt":"workspace:*","@brains/rizom-ecosystem":"workspace:*","@brains/rover-onboarding":"workspace:*","@brains/series":"workspace:*","@brains/site-builder-plugin":"workspace:*","@brains/site-default":"workspace:*","@brains/site-info":"workspace:*","@brains/social-media":"workspace:*","@brains/stock-photo":"workspace:*","@brains/theme-default":"workspace:*","@brains/topics":"workspace:*","@brains/web-chat":"workspace:*","@brains/webserver":"workspace:*","@brains/wishlist":"workspace:*"},devDependencies:{"@brains/ai-evaluation":"workspace:*","@brains/typescript-config":"workspace:*",typescript:"^6.0.3"},files:["src","brain.eval.yaml","env.schema.template"],main:"./src/index.ts",private:!0,scripts:{"build:web-chat":"turbo run build --filter=@brains/web-chat",eval:"brain-eval","eval:core":"brain-eval --suite core","eval:core:coverage":"brain-eval --suite core --tool-coverage","eval:default":"brain-eval --suite default","eval:default:coverage":"brain-eval --suite default --tool-coverage","eval:full":"brain-eval --suite full","eval:full:coverage":"brain-eval --suite full --tool-coverage",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix","start:core":"bun run build:web-chat && cd test-apps/core && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","start:default":"bun run build:web-chat && cd test-apps/default && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","start:full":"bun run build:web-chat && cd test-apps/full && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var oIw=Z.looseObject({});class nQ2 extends aQ{constructor(A={}){super("rover-profile",DZ0,A,oIw)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",_k)}}function rQ2(A={}){return new nQ2(A)}wA();N0();NB();wA();wA();var ao=bz.extend(_k.shape);class GZ0{postsListUrl;decksListUrl;id="professional:homepage-list";name="Homepage List DataSource";description="Fetches profile, blog posts, and presentation decks for homepage";constructor(A,Q){this.postsListUrl=A,this.decksListUrl=Q}async fetch(A,Q,w){let B=w.entityService,[$,f,Y,X]=await Promise.all([Hx(B,ao),_f0(B,{entityType:"post",count:3,parse:Nr}),_f0(B,{entityType:"deck",count:3,parse:vr}),kr(B)]),W={profile:$,posts:f,decks:Y,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:mn0(X.cta),sections:X.sections??{}};return Q.parse(W)}}wA();class zZ0{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,w){let $={profile:await Hx(w.entityService,ao)};return Q.parse($)}}import{jsxDEV as xB,Fragment as tIw}from"preact/jsx-dev-runtime";var sIw="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",aIw="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",It0=({number:A,title:Q,blurb:w,children:B})=>xB("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:xB("div",{className:"max-w-6xl mx-auto",children:xB("div",{className:sIw,children:[xB(ep0,{title:Q,number:A,blurb:w},void 0,!1,void 0,this),xB("div",{className:aIw,"aria-hidden":"true"},void 0,!1,void 0,this),xB("div",{className:"mt-6 md:mt-0",children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),Jt0=({profile:A,posts:Q,decks:w,postsListUrl:B,decksListUrl:$,cta:f,sections:Y})=>{let X=A.tagline?.length?A.tagline:A.description,W=Q.map((q)=>({id:q.id,url:q.url,title:q.metadata.title,date:q.metadata.publishedAt??q.created,description:q.frontmatter.excerpt,series:q.frontmatter.seriesName&&q.frontmatter.seriesIndex?{name:q.frontmatter.seriesName,index:q.frontmatter.seriesIndex}:void 0})),H=w.map((q)=>({id:q.id,url:q.url,title:q.frontmatter.title||q.id,date:q.frontmatter.publishedAt??q.created,description:q.frontmatter.description})),K=A.name||"Home",U=[A.intro,A.description,X].find((q)=>q)??"Professional site",D=Boolean(A.description)||A.expertise!==void 0&&A.expertise.length>0;return xB(tIw,{children:[xB(lQ,{title:K,description:U,ogType:"website"},void 0,!1,void 0,this),xB("div",{className:"homepage-list bg-theme",children:[xB("header",{className:"hero-bg-pattern relative w-full px-6 md:px-12 pt-28 pb-24 md:pt-28 md:pb-24 overflow-hidden border-b border-rule",children:xB("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&xB("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[xB("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),xB("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),X&&xB("h1",{className:"font-heading text-[clamp(2.75rem,6.5vw,5.5rem)] font-normal text-heading leading-[1.02] tracking-[-0.025em] max-w-[18ch] [font-variation-settings:'opsz'_144,'SOFT'_30]",children:T70(X,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&xB("p",{className:"font-heading font-light text-[clamp(1.1rem,1.8vw,1.4rem)] leading-[1.5] text-theme-muted max-w-[42ch] mt-8 [font-variation-settings:'opsz'_24]",children:T70(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),xB(It0,{number:"01",title:"Essays",blurb:Y.essays?.blurb,children:xB(E70,{items:W,viewAllUrl:B,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),H.length>0&&xB(It0,{number:"02",title:"Presentations",blurb:Y.presentations?.blurb,children:xB(E70,{items:H,viewAllUrl:$,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D&&xB(It0,{number:"03",title:"About",blurb:Y.about?.blurb,children:xB("div",{className:"flex flex-col gap-8",children:[A.description&&xB("p",{className:"font-heading font-light text-[1.25rem] leading-[1.55] text-theme max-w-[55ch] [font-variation-settings:'opsz'_24,'SOFT'_50]",children:A.description},void 0,!1,void 0,this),A.expertise&&A.expertise.length>0&&xB(Ai0,{subjects:A.expertise},void 0,!1,void 0,this),xB("a",{href:"/about",className:"mt-6 inline-flex items-center gap-2 font-mono text-[0.7rem] font-medium uppercase tracking-[0.18em] text-accent pb-1 relative before:content-[''] before:absolute before:left-0 before:right-full before:bottom-0 before:h-px before:bg-accent before:transition-[right] before:duration-300 hover:before:right-0",children:["Learn more",xB("span",{"aria-hidden":"true",children:"\u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),xB(Tp0,{cta:f,variant:"editorial",socialLinks:A.socialLinks},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as s6,Fragment as eIw}from"preact/jsx-dev-runtime";var Ft0=({profile:A})=>{let Q=`About ${A.name||"Me"}`,w=[A.description,A.intro].find(($)=>$)??"About page",B=A.expertise!==void 0&&A.expertise.length>0||Boolean(A.currentFocus)||Boolean(A.availability)||Boolean(A.email)||Boolean(A.website)||A.socialLinks!==void 0&&A.socialLinks.length>0;return s6(eIw,{children:[s6(lQ,{title:Q,description:w,ogType:"profile"},void 0,!1,void 0,this),s6("div",{className:"about-page bg-theme",children:[s6("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:s6("div",{className:"relative z-10 max-w-4xl mx-auto",children:[s6("h1",{className:"text-5xl md:text-6xl font-semibold mb-6 text-heading",children:["About ",A.name||"Me"]},void 0,!0,void 0,this),A.description&&s6("p",{className:"text-xl md:text-2xl text-theme-muted leading-relaxed",children:A.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),s6("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&s6("section",{className:"content-section-reveal mb-20 md:mb-28",children:s6(V9,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),B&&s6("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&s6("section",{children:[s6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),s6("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map(($,f)=>s6("li",{className:Jn({variant:"accent",size:"lg"}),children:$},f,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&s6("section",{children:[s6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),s6("p",{className:"text-lg text-theme leading-relaxed",children:A.currentFocus},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.availability&&s6("section",{children:[s6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),s6("p",{className:"text-lg text-theme leading-relaxed",children:A.availability},void 0,!1,void 0,this)]},void 0,!0,void 0,this),(Boolean(A.email)||Boolean(A.website)||A.socialLinks!==void 0&&A.socialLinks.length>0)&&s6("section",{children:[s6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),s6("div",{className:"space-y-4",children:[A.email&&s6("p",{className:"text-lg",children:s6("a",{href:`mailto:${A.email}`,className:"text-brand hover:text-brand-dark transition-colors",children:A.email},void 0,!1,void 0,this)},void 0,!1,void 0,this),A.website&&s6("p",{className:"text-lg",children:s6("a",{href:A.website,target:"_blank",rel:"noopener noreferrer",className:"text-brand hover:text-brand-dark transition-colors",children:A.website},void 0,!1,void 0,this)},void 0,!1,void 0,this),A.socialLinks&&A.socialLinks.length>0&&s6("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map(($,f)=>s6(b9,{href:$.url,external:!0,variant:"secondary",size:"md",children:$.label?.length?$.label:$.platform},f,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as d4,Fragment as oQ2}from"preact/jsx-dev-runtime";var Lt0=()=>{return d4(oQ2,{children:[d4(lQ,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),d4("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:d4("div",{className:"text-center max-w-md",children:[d4("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),d4("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),d4("p",{className:"text-lg text-theme-muted mb-8",children:"You'll receive a confirmation email shortly. Check your inbox to confirm your subscription."},void 0,!1,void 0,this),d4(b9,{href:"/",variant:"primary",children:"Back to Home"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},kt0=()=>{return d4(oQ2,{children:[d4(lQ,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),d4("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:d4("div",{className:"text-center max-w-md",children:[d4("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),d4("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),d4("p",{className:"text-lg text-theme-muted mb-8",children:"We couldn't process your subscription. Please try again or contact us if the problem persists."},void 0,!1,void 0,this),d4(b9,{href:"/",variant:"primary",children:"Back to Home"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};N0();var sQ2=Z.object({label:Z.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:Z.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),AJw={post:{label:"Post"},deck:{label:"Deck"}},aQ2=Z.object({entityDisplay:Z.object({post:sQ2,deck:sQ2}).default(AJw).describe("Display metadata for post and deck entity types used by the homepage")});var tQ2={name:"@brains/site-professional",version:"0.2.0-alpha.143",description:"Professional site composition package",dependencies:{"@brains/blog":"workspace:*","@brains/decks":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-engine":"workspace:*","@brains/site-info":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},files:["src"],private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",typecheck:"tsc --noEmit"},type:"module"};var wJw=Z.object({blurb:Z.string().optional().describe("Short italic subtitle under the section title")}),BJw=Z.object({heading:Z.string(),buttonText:Z.string(),buttonLink:Z.string()}),eQ2=Z.looseObject({name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),description:Z.string().optional(),avatar:Z.string().optional(),website:Z.string().optional(),email:Z.string().optional(),socialLinks:Z.array(Z.object({platform:Z.enum(["github","instagram","linkedin","email","website"]),url:Z.string(),label:Z.string().optional()})).optional(),tagline:Z.string().optional(),intro:Z.string().optional(),story:Z.string().optional(),role:Z.string().optional(),audience:Z.string().optional(),expertise:Z.array(Z.string()).optional(),currentFocus:Z.string().optional(),availability:Z.string().optional(),desiredTone:Z.string().optional()}),$Jw=Z.looseObject({id:Z.string(),entityType:Z.literal("post"),content:Z.string(),created:Z.string(),updated:Z.string(),contentHash:Z.string(),metadata:Z.looseObject({title:Z.string(),publishedAt:Z.string().optional()}),frontmatter:Z.looseObject({excerpt:Z.string(),seriesName:Z.string().optional(),seriesIndex:Z.number().optional()}),body:Z.string(),url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),seriesUrl:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional(),coverImageSrcset:Z.string().optional(),coverImageSizes:Z.string().optional()}),fJw=Z.looseObject({id:Z.string(),entityType:Z.literal("deck"),content:Z.string(),created:Z.string(),updated:Z.string(),contentHash:Z.string(),metadata:Z.looseObject({title:Z.string(),publishedAt:Z.string().optional()}),frontmatter:Z.looseObject({title:Z.string(),description:Z.string().optional(),publishedAt:Z.string().optional()}),body:Z.string(),url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});class _t0 extends aQ{dependencies=["blog","decks"];constructor(A){super("professional-site",tQ2,A,aQ2)}async onRegister(A){let Q=this.config.entityDisplay.post,w=this.config.entityDisplay.deck,B=`/${Q.pluralName??Q.label.toLowerCase()+"s"}`,$=`/${w.pluralName??w.label.toLowerCase()+"s"}`,f=new GZ0(B,$);A.entities.registerDataSource(f);let Y=new zZ0;A.entities.registerDataSource(Y);let X=Z.object({profile:eQ2,posts:Z.array($Jw),decks:Z.array(fJw),postsListUrl:Z.string(),decksListUrl:Z.string(),cta:BJw,sections:Z.record(Z.string(),wJw)}),W=Z.object({profile:eQ2}),H=Z.object({});A.templates.register({"homepage-list":i1({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:X,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:Jt0}}),about:i1({name:"about",description:"About page with full profile information",schema:W,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:Ft0}}),"subscribe-thanks":i1({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:H,requiredPermission:"public",layout:{component:Lt0}}),"subscribe-error":i1({name:"subscribe-error",description:"Newsletter subscription error page",schema:H,requiredPermission:"public",layout:{component:kt0}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function Aw2(A){return new _t0(A??{})}var Qw2=[{id:"home",path:"/",title:"Home",description:"Professional site homepage",layout:"default",navigation:{show:!0,label:"Home",slot:"secondary",priority:10},sections:[{id:"homepage",template:"professional-site:homepage-list",dataQuery:{}}]},{id:"about",path:"/about",title:"About",description:"About page",layout:"default",navigation:{show:!0,label:"About",slot:"primary",priority:90},sections:[{id:"about",template:"professional-site:about",dataQuery:{}}]},{id:"subscribe-thanks",path:"/subscribe/thanks",title:"Thanks for subscribing",description:"Newsletter subscription confirmation",layout:"default",navigation:{show:!1},sections:[{id:"subscribe-thanks",template:"professional-site:subscribe-thanks",dataQuery:{},content:{}}]},{id:"subscribe-error",path:"/subscribe/error",title:"Subscription failed",description:"Newsletter subscription error",layout:"default",navigation:{show:!1},sections:[{id:"subscribe-error",template:"professional-site:subscribe-error",dataQuery:{},content:{}}]}];import{jsxDEV as qZ0}from"preact/jsx-dev-runtime";function ww2({sections:A,siteInfo:Q,slots:w,wordmark:B}){return qZ0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[qZ0(cp0,{title:Q.title,navigation:Q.navigation.primary,showThemeToggle:!0,...Q.logo!==void 0?{logo:Q.logo}:{},...B!==void 0?{wordmark:B}:{}},void 0,!1,void 0,this),qZ0("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),qZ0(up0,{primaryNavigation:Q.navigation.primary,secondaryNavigation:Q.navigation.secondary,copyright:Q.copyright,socialLinks:Q.socialLinks,title:Q.title,tagline:Q.description,children:w?.getSlot("footer-top").map(($)=>$.render())},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var YJw={layouts:{default:ww2},routes:Qw2,plugin:Aw2,entityDisplay:{post:{label:"Post"},deck:{label:"Deck"},project:{label:"Project"},series:{label:"Series",navigation:{slot:"secondary"}},topic:{label:"Topic",navigation:{slot:"secondary"}},link:{label:"Link",navigation:{slot:"secondary"}},base:{label:"Note",navigation:{show:!1}},"social-post":{label:"Social Post",pluralName:"social-posts",navigation:{slot:"secondary"}},newsletter:{label:"Newsletter",navigation:{slot:"secondary"}}}},to=YJw;var Bw2=`/*
8785
8785
  * Default theme \u2014 simplified editorial base inspired by the Rizom family.
8786
8786
  *
8787
8787
  * This theme is intentionally less branded than @brains/theme-rizom. It
@@ -9169,7 +9169,7 @@ ${JSON.stringify(w,null,2)}`}function $Z0(A){return A.map((Q)=>Q.detail===null?{
9169
9169
 
9170
9170
  .btn-primary:disabled { opacity: 0.5; }
9171
9171
  }
9172
- `;var hy=Bw2;import{join as ZJw}from"path";var $w2=["prompt","rover-profile","image","document","note","link","wishlist","topics","directory-sync","atproto","agents","assessment","auth-service","notifications","playbook","playbooks","rover-onboarding","email-resend","cms","dashboard-root","mcp","webserver","web-chat","discord","a2a"],fw2=[...$w2.filter((A)=>A!=="dashboard-root"),"dashboard","blog","series","decks","analytics","obsidian-vault","site-info","site-builder"],WJw=[...fw2,"portfolio","topics","content-pipeline","social-media","newsletter","stock-photo"],HJw=["Rover is a personal professional knowledge and publishing brain for an independent professional. Prioritize personal knowledge management, professional website content, essays, projects, decks, newsletters, and social distribution workflows.","When a user asks for a publishing/content overview, use the available publishing entity types directly instead of treating the request as generic team memory.",`When answering questions like "what have I written about X" or "which posts relate to this deck/source", search first and use semantic search results as candidates, not proof. Summarize only clearly relevant entities whose title or content directly matches the asked topic or has substantial overlap with the source's main themes; omit weak/tangential candidates rather than presenting them as definite matches. A match based on only an isolated shared term or pattern is not enough; when one candidate is clearly stronger than the rest, list only the strongest clear match and say the others were tangential rather than naming them as matches.`,'Draft blog posts are only post entities with status draft. If the user asks whether draft blog posts exist, call only system_list for entityType post with status draft; do not also list social-post, newsletter, deck, or other draft entity types. After telling the user there are no draft blog posts, treat follow-ups like "make one draft" or "make one a draft" as requests to change an existing published post back to draft: ask which existing published post they want changed; do not offer to create a brand-new post and do not call system_generate to create a fresh draft from that ambiguous follow-up.'],KJw=UI({name:"rover",version:DZ0.version,model:"gpt-5.4-mini",site:to,theme:hy,presets:{core:$w2,default:fw2,full:WJw},evalDisable:["discord","chat","webserver","web-chat","mcp","atproto","analytics","dashboard","dashboard-root","email-resend"],agentInstructions:HJw,capabilities:[["prompt",bP,void 0],["rover-profile",rQ2,{}],["image",Mc,void 0],["cms",KP,(A)=>({...A.CMS_CONTENT_REPO_PAT?{passkeyLogin:{contentRepoToken:A.CMS_CONTENT_REPO_PAT}}:{}})],["auth-service",Vp,void 0],["notifications",m60,void 0],["playbook",Ga0,{}],["playbooks",_a0,{}],["rover-onboarding",z22,{}],["email-resend",T90,void 0],["dashboard",hF,void 0],["dashboard-root",hF,{routePath:"/"}],["blog",wr0,{}],["series",Zr0,void 0],["decks",hr,void 0],["docs",yr,void 0],["document",ko0,void 0],["note",QP,{}],["link",BP,{}],["portfolio",ao0,{}],["topics",dY0,{includeEntityTypes:["post","deck","project","link","anchor-profile"]}],["content-pipeline",Ss0,{generationSchedules:{newsletter:"0 9 * * 1","social-post":"0 10 * * *"},generationConditions:{newsletter:{skipIfDraftExists:!0,minSourceEntities:1,sourceEntityType:"post"},"social-post":{skipIfDraftExists:!0,maxUnpublishedDrafts:5}}}],["social-media",Io,{autoGenerateOnBlogPublish:!0}],["newsletter",x12,{doubleOptIn:!0}],["obsidian-vault",Ya0,{autoSync:!0}],["wishlist",CX0,{}],["stock-photo",ha0,{}],["agents",tX0,void 0],["assessment",ZZ0,void 0],["atproto",UZ0,(A)=>({...A.ATPROTO_APP_PASSWORD?{appPassword:A.ATPROTO_APP_PASSWORD}:{}})],["atproto-registry",Od,{}],["directory-sync",fj,()=>({seedContent:!0,seedContentPath:ZJw(import.meta.dir,"..","seed-content-core"),initialSync:!0})],["analytics",fX0,{}],["rizom-ecosystem",VP,void 0],["site-info",lj,void 0],["site-builder",cj,{cms:{}}]],interfaces:[["mcp",oI,()=>({})],["discord",CJ,()=>({})],["chat",N50,()=>({})],["webserver",mJ,()=>({})],["web-chat",OC,()=>({})],["a2a",xC,()=>({})]],permissions:{rules:[{pattern:"cli:*",level:"anchor"},{pattern:"mcp:stdio",level:"anchor"},{pattern:"mcp:http",level:"public"},{pattern:"discord:*",level:"public"},{pattern:"web-chat:*",level:"anchor"}],entityActions:{"*":{create:"anchor",update:"anchor",delete:"anchor",extract:"anchor"}}},deployment:{cdn:{enabled:!0,provider:"bunny"},dns:{enabled:!0,provider:"bunny"}}}),Yw2=KJw;qI();wA();wA();N0();var Nt0=Z.object({routeId:Z.string(),sectionId:Z.string()}),UJw=Z.object({routeId:Z.string(),sectionId:Z.string()}),eo=LQ.extend({entityType:Z.literal("site-content"),template:Z.string().optional(),content:Z.string(),metadata:UJw});wA();class Xw2 extends C2{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:eo,frontmatterSchema:Nt0})}toMarkdown(A){let Q=this.extractBody(A.content);return this.buildMarkdown(Q,A.metadata)}fromMarkdown(A){return{content:A,entityType:"site-content",metadata:this.parseFrontmatter(A)}}}var jt0=new Xw2;N0();var bZ0=Z.object({routeId:Z.string().optional().describe("Optional: specific route filter"),sectionId:Z.string().optional().describe("Optional: specific section filter"),dryRun:Z.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:Z.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),bb$=Z.object({jobs:Z.array(Z.object({jobId:Z.string(),routeId:Z.string(),sectionId:Z.string()})),totalSections:Z.number(),queuedSections:Z.number(),skippedSections:Z.number().optional(),batchId:Z.string().optional()});N0();var DJw=Z.looseObject({id:Z.string(),template:Z.string().optional(),content:Z.unknown().optional()}),GJw=Z.looseObject({id:Z.string(),title:Z.string().optional(),description:Z.string().optional(),sections:Z.array(DJw)}),zJw=Z.array(GJw);class Pt0{context;constructor(A){this.context=A}createJobOptions(A,Q){if(!A)return;return{source:A.operationType??Q,rootJobId:A.rootJobId??`${Q}-${Date.now()}`,metadata:{operationType:A.operationType??"content_operations",progressToken:A.progressToken,pluginId:A.pluginId??"site-content"}}}async fetchRoutes(){let A=await this.context.messaging.send({type:"site-builder:routes:list",payload:{}});if("noop"in A)throw Error("No handler for site-builder:routes:list \u2014 is site-builder plugin loaded?");if(!A.success||!A.data)throw Error("Failed to fetch routes from site-builder");let Q=zJw.safeParse(A.data);if(!Q.success)throw Error("Failed to parse routes from site-builder");return Q.data}async generate(A,Q,w){let B=this.context.logger.child("SiteContentOperations"),$=await this.fetchRoutes(),f=$;if(A.routeId){if(f=$.filter((K)=>K.id===A.routeId),f.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let K of f)for(let U of K.sections){if(A.sectionId&&U.id!==A.sectionId)continue;if(U.content){B.debug("Section has static content, skipping",{routeId:K.id,sectionId:U.id});continue}if(U.template){let D=this.context.templates.getCapabilities(U.template);if(!D){B.warn("Template not found, skipping section",{routeId:K.id,sectionId:U.id,templateName:U.template});continue}if(!D.canGenerate){B.debug("Template doesn't support generation, skipping",{routeId:K.id,sectionId:U.id,templateName:U.template,capabilities:D});continue}}else{B.debug("Section has no template, skipping",{routeId:K.id,sectionId:U.id});continue}if(!A.force&&!A.dryRun){let D=`${K.id}:${U.id}`;if(await this.context.entityService.getEntity({entityType:"site-content",id:D})){B.debug("Content already exists, skipping",{routeId:K.id,sectionId:U.id});continue}}Y.push({route:K,section:U})}let X=Y.length;if(A.dryRun)return{jobs:[],totalSections:X,queuedSections:X,batchId:`dry-run-${Date.now()}`};let W=[],H=[];for(let{route:K,section:U}of Y){let D=`${K.id}:${U.id}`,q=U.template,b={routeId:K.id,sectionId:U.id,entityId:D,entityType:"site-content",templateName:q,context:{prompt:typeof U.content==="string"?U.content:void 0,data:{routeId:K.id,sectionId:U.id,routeTitle:K.title,routeDescription:K.description,sectionContent:U.content},conversationId:"system"},siteConfig:Q};H.push({type:"shell:content-generation",data:b})}if(H.length>0){let K=this.createJobOptions(w,"site:content-generation"),U=await this.context.jobs.enqueueBatch(H,K);for(let D=0;D<Y.length;D++){let q=Y[D];if(q)W.push({jobId:`${U}-${D}`,routeId:q.route.id,sectionId:q.section.id})}return{jobs:W,totalSections:X,queuedSections:W.length,batchId:U}}return{jobs:[],totalSections:X,queuedSections:0,batchId:`empty-${Date.now()}`}}}class Mt0{siteConfig;operations;constructor(A,Q){this.siteConfig=Q,this.operations=new Pt0(A)}async generateContent(A,Q){let w=bZ0.parse(A);return this.operations.generate(w,this.siteConfig,Q)}}s5();N0();var qJw=Z.object({namespace:Z.string(),sections:Z.record(Z.string(),Z.any())}),Zw2=Z.custom((A)=>qJw.safeParse(A).success),Ot0=Z.object({definitions:Z.union([Zw2,Z.array(Zw2)]).optional()});wA();function Ww2(A,Q){return[P6(Q,"generate","Generate content for all routes, a specific route, or a specific section",bZ0,async(w,B)=>{let $=A();if(!$)return{success:!1,error:"Site content service not initialized"};if(w.sectionId&&!w.routeId)return{success:!1,error:"sectionId requires routeId to be specified"};let f={rootJobId:`generate-${Date.now()}`,progressToken:B.progressToken,pluginId:Q,operationType:"content_operations",interfaceType:B.interfaceType,channelId:B.channelId},Y=await $.generateContent(w,f);return{success:!0,message:`Generated ${Y.queuedSections} of ${Y.totalSections} sections. ${Y.queuedSections>0?"Jobs are running in the background.":"No new content to generate."}`,data:{batchId:Y.batchId,jobsQueued:Y.queuedSections,totalSections:Y.totalSections,jobs:Y.jobs}}})]}var Hw2={name:"@brains/site-content",version:"0.2.0-alpha.142",description:"Site content entity and generation orchestration",dependencies:{"@brains/content-formatters":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class xt0 extends aQ{siteContentService;constructor(A={}){super("site-content",Hw2,A,Ot0)}async onRegister(A){A.entities.register("site-content",eo,jt0);for(let Q of DI(this.config.definitions))A.templates.register(qV(Q),Q.namespace);this.siteContentService=new Mt0(A)}async getTools(){return Ww2(()=>this.siteContentService,this.id)}}function As(A={}){return new xt0(A)}wA();N0();NB();N0();wA();var Kw2=Z.enum(["available","early access","coming soon","planned"]),Uw2=Z.enum(["available","early access","coming soon","planned"]),Dw2=Z.object({title:Z.string(),description:Z.string()}),PH=Z.object({name:Z.string(),availability:Kw2,order:Z.number(),ogImageId:Z.string().optional()}),VZ0=Z.object({tagline:Z.string(),promise:Z.string(),role:Z.string(),purpose:Z.string(),audience:Z.string(),values:Z.array(Z.string()).min(1),features:Z.array(Dw2).min(1).max(6),story:Z.string()}),sb$=PH.pick({name:!0,availability:!0,order:!0}).extend({slug:Z.string()}),VJw=Z.object({name:Z.string(),availability:Uw2,order:Z.number(),slug:Z.string()}),IJw=Z.object({name:Z.string(),availability:Uw2,order:Z.number(),ogImageId:Z.string().optional()}),Cy=LQ.extend({entityType:Z.literal("product"),metadata:VJw}),IZ0=Cy.extend({frontmatter:IJw,body:VZ0,labels:Z.record(Z.string(),Z.string()),ogImageUrl:Z.string().optional()}),JJw=IZ0.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),ogImageUrl:Z.string().optional()});wA();K2();o5();class gy extends G6{constructor(){super(VZ0,{title:"Product",mappings:[{key:"tagline",label:"Tagline",type:"string"},{key:"promise",label:"Promise",type:"string"},{key:"role",label:"Role",type:"string"},{key:"purpose",label:"Purpose",type:"string"},{key:"audience",label:"Audience",type:"string"},{key:"values",label:"Values",type:"array",itemType:"string"},{key:"features",label:"Capabilities",type:"array",itemType:"object",itemMappings:[{key:"title",label:"Title",type:"string"},{key:"description",label:"Description",type:"string"}]},{key:"story",label:"Story",type:"string"}]})}}class Rt0 extends C2{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:Cy,frontmatterSchema:PH,bodyFormatter:new gy})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,PH);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,PH),w=Z1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:w,availability:Q.availability,order:Q.order}}}}var JZ0=new Rt0;N0();wA();var Gw2=Z.object({title:Z.string(),description:Z.string()}),zw2=Z.object({title:Z.string(),description:Z.string()}),FJw=Z.object({title:Z.string(),description:Z.string()}),qw2=Z.object({heading:Z.string(),buttonText:Z.string(),link:Z.string()}),gF=Z.object({headline:Z.string(),tagline:Z.string()}),LJw=Z.object({title:Z.string(),description:Z.string()}),FZ0=Z.object({vision:Z.string(),pillars:Z.array(Gw2).min(1).max(6),approach:Z.array(LJw).min(1).max(6),productsIntro:Z.string(),technologies:Z.array(FJw).min(1).max(6),benefits:Z.array(zw2).min(1).max(6),cta:qw2}),kJw=gF.pick({headline:!0}).extend({slug:Z.string()}),_Jw=Z.object({headline:Z.string(),slug:Z.string()}),NJw=Z.object({headline:Z.string(),tagline:Z.string()}),yy=LQ.extend({entityType:Z.literal("products-overview"),metadata:_Jw}),vt0=yy.extend({frontmatter:NJw,body:FZ0,labels:Z.record(Z.string(),Z.string())});wA();K2();o5();class Ey extends G6{constructor(){super(FZ0,{title:"Products Overview",mappings:[{key:"vision",label:"Vision",type:"string"},{key:"pillars",label:"Core Principles",type:"array",itemType:"object",itemMappings:[{key:"title",label:"Title",type:"string"},{key:"description",label:"Description",type:"string"}]},{key:"approach",label:"How It Works",type:"array",itemType:"object",itemMappings:[{key:"title",label:"Title",type:"string"},{key:"description",label:"Description",type:"string"}]},{key:"productsIntro",label:"Products",type:"string"},{key:"technologies",label:"Built With",type:"array",itemType:"object",itemMappings:[{key:"title",label:"Title",type:"string"},{key:"description",label:"Description",type:"string"}]},{key:"benefits",label:"Why Brains",type:"array",itemType:"object",itemMappings:[{key:"title",label:"Title",type:"string"},{key:"description",label:"Description",type:"string"}]},{key:"cta",label:"Ready to Build",type:"object",children:[{key:"heading",label:"Heading",type:"string"},{key:"buttonText",label:"Button Text",type:"string"},{key:"link",label:"Link",type:"string"}]}]})}}class ht0 extends C2{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:yy,frontmatterSchema:gF,bodyFormatter:new Ey})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,gF);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,gF),w=Z1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:w}}}}var Ct0=new ht0;wA();N0();var jJw=Z.object({entityType:Z.string(),query:Z.object({id:Z.string().optional()}).optional()});function bw2(A,Q){let w=o2(A.content,PH),B=Q.parse(w.content),$=Q.getLabels();return IZ0.parse({...A,frontmatter:w.metadata,body:B,labels:$})}function Vw2(A,Q){let w=o2(A.content,gF),B=Q.parse(w.content),$=Q.getLabels();return vt0.parse({...A,frontmatter:w.metadata,body:B,labels:$})}class LZ0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new Ey;productFormatter=new gy;constructor(A){this.logger=A,this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,w){let B=jJw.parse(A),$=w.entityService;if(B.entityType==="products-overview"){let H=(await $.listEntities({entityType:"products-overview",options:{limit:1}}))[0];if(!H)throw Error("Products overview entity not found");let K=Vw2(H,this.overviewFormatter);return Q.parse(K)}if(B.query?.id){let H=(await $.listEntities({entityType:"product",options:{filter:{metadata:{slug:B.query.id}},limit:1}}))[0];if(!H)throw Error(`Product not found: ${B.query.id}`);return Q.parse({product:bw2(H,this.productFormatter)})}let[f,Y]=await Promise.all([$.listEntities({entityType:"products-overview",options:{limit:1}}),$.listEntities({entityType:"product",options:{sortFields:[{field:"order",direction:"asc"}]}})]),X=f[0];if(!X)throw Error("Products overview entity not found");return Q.parse({overview:Vw2(X,this.overviewFormatter),products:Y.map((W)=>bw2(W,this.productFormatter))})}}import{jsxDEV as U1,Fragment as OJw}from"preact/jsx-dev-runtime";var Iw2=({overview:A,products:Q})=>{let{frontmatter:w,body:B,labels:$}=A;return U1(OJw,{children:[U1(lQ,{title:w.headline,description:w.tagline},void 0,!1,void 0,this),U1("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[U1("style",{children:`
9172
+ `;var hy=Bw2;import{join as ZJw}from"path";var $w2=["prompt","rover-profile","image","document","note","link","wishlist","topics","directory-sync","atproto","agents","assessment","auth-service","notifications","playbook","playbooks","rover-onboarding","email-resend","cms","dashboard-root","mcp","webserver","web-chat","discord","a2a"],fw2=[...$w2.filter((A)=>A!=="dashboard-root"),"dashboard","blog","series","decks","analytics","obsidian-vault","site-info","site-builder"],WJw=[...fw2,"portfolio","topics","content-pipeline","social-media","newsletter","stock-photo"],HJw=["Rover is a personal professional knowledge and publishing brain for an independent professional. Prioritize personal knowledge management, professional website content, essays, projects, decks, newsletters, and social distribution workflows.","When a user asks for a publishing/content overview, use the available publishing entity types directly instead of treating the request as generic team memory.",`When answering questions like "what have I written about X" or "which posts relate to this deck/source", search first and use semantic search results as candidates, not proof. Summarize only clearly relevant entities whose title or content directly matches the asked topic or has substantial overlap with the source's main themes; omit weak/tangential candidates rather than presenting them as definite matches. A match based on only an isolated shared term or pattern is not enough; when one candidate is clearly stronger than the rest, list only the strongest clear match and say the others were tangential rather than naming them as matches.`,'Draft blog posts are only post entities with status draft. If the user asks whether draft blog posts exist, call only system_list for entityType post with status draft; do not also list social-post, newsletter, deck, or other draft entity types. After telling the user there are no draft blog posts, treat follow-ups like "make one draft" or "make one a draft" as requests to change an existing published post back to draft: ask which existing published post they want changed; do not offer to create a brand-new post and do not call system_generate to create a fresh draft from that ambiguous follow-up.'],KJw=UI({name:"rover",version:DZ0.version,model:"gpt-5.4-mini",site:to,theme:hy,presets:{core:$w2,default:fw2,full:WJw},evalDisable:["discord","chat","webserver","web-chat","mcp","atproto","analytics","dashboard","dashboard-root","email-resend"],agentInstructions:HJw,capabilities:[["prompt",bP,void 0],["rover-profile",rQ2,{}],["image",Mc,void 0],["cms",KP,(A)=>({...A.CMS_CONTENT_REPO_PAT?{passkeyLogin:{contentRepoToken:A.CMS_CONTENT_REPO_PAT}}:{}})],["auth-service",Vp,void 0],["notifications",m60,void 0],["playbook",Ga0,{}],["playbooks",_a0,{}],["rover-onboarding",z22,{}],["email-resend",T90,void 0],["dashboard",hF,void 0],["dashboard-root",hF,{routePath:"/"}],["blog",wr0,{}],["series",Zr0,void 0],["decks",hr,void 0],["docs",yr,void 0],["document",ko0,void 0],["note",QP,{}],["link",BP,{}],["portfolio",ao0,{}],["topics",dY0,{includeEntityTypes:["post","deck","project","link","anchor-profile"]}],["content-pipeline",Ss0,{generationSchedules:{newsletter:"0 9 * * 1","social-post":"0 10 * * *"},generationConditions:{newsletter:{skipIfDraftExists:!0,minSourceEntities:1,sourceEntityType:"post"},"social-post":{skipIfDraftExists:!0,maxUnpublishedDrafts:5}}}],["social-media",Io,{autoGenerateOnBlogPublish:!0}],["newsletter",x12,{doubleOptIn:!0}],["obsidian-vault",Ya0,{autoSync:!0}],["wishlist",CX0,{}],["stock-photo",ha0,{}],["agents",tX0,void 0],["assessment",ZZ0,void 0],["atproto",UZ0,(A)=>({...A.ATPROTO_APP_PASSWORD?{appPassword:A.ATPROTO_APP_PASSWORD}:{}})],["atproto-registry",Od,{}],["directory-sync",fj,()=>({seedContent:!0,seedContentPath:ZJw(import.meta.dir,"..","seed-content-core"),initialSync:!0})],["analytics",fX0,{}],["rizom-ecosystem",VP,void 0],["site-info",lj,void 0],["site-builder",cj,{cms:{}}]],interfaces:[["mcp",oI,()=>({})],["discord",CJ,()=>({})],["chat",N50,()=>({})],["webserver",mJ,()=>({})],["web-chat",OC,()=>({})],["a2a",xC,()=>({})]],permissions:{rules:[{pattern:"cli:*",level:"anchor"},{pattern:"mcp:stdio",level:"anchor"},{pattern:"mcp:http",level:"public"},{pattern:"discord:*",level:"public"},{pattern:"web-chat:*",level:"anchor"}],entityActions:{"*":{create:"anchor",update:"anchor",delete:"anchor",extract:"anchor"}}},deployment:{cdn:{enabled:!0,provider:"bunny"},dns:{enabled:!0,provider:"bunny"}}}),Yw2=KJw;qI();wA();wA();N0();var Nt0=Z.object({routeId:Z.string(),sectionId:Z.string()}),UJw=Z.object({routeId:Z.string(),sectionId:Z.string()}),eo=LQ.extend({entityType:Z.literal("site-content"),template:Z.string().optional(),content:Z.string(),metadata:UJw});wA();class Xw2 extends C2{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:eo,frontmatterSchema:Nt0})}toMarkdown(A){let Q=this.extractBody(A.content);return this.buildMarkdown(Q,A.metadata)}fromMarkdown(A){return{content:A,entityType:"site-content",metadata:this.parseFrontmatter(A)}}}var jt0=new Xw2;N0();var bZ0=Z.object({routeId:Z.string().optional().describe("Optional: specific route filter"),sectionId:Z.string().optional().describe("Optional: specific section filter"),dryRun:Z.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:Z.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),bb$=Z.object({jobs:Z.array(Z.object({jobId:Z.string(),routeId:Z.string(),sectionId:Z.string()})),totalSections:Z.number(),queuedSections:Z.number(),skippedSections:Z.number().optional(),batchId:Z.string().optional()});N0();var DJw=Z.looseObject({id:Z.string(),template:Z.string().optional(),content:Z.unknown().optional()}),GJw=Z.looseObject({id:Z.string(),title:Z.string().optional(),description:Z.string().optional(),sections:Z.array(DJw)}),zJw=Z.array(GJw);class Pt0{context;constructor(A){this.context=A}createJobOptions(A,Q){if(!A)return;return{source:A.operationType??Q,rootJobId:A.rootJobId??`${Q}-${Date.now()}`,metadata:{operationType:A.operationType??"content_operations",progressToken:A.progressToken,pluginId:A.pluginId??"site-content"}}}async fetchRoutes(){let A=await this.context.messaging.send({type:"site-builder:routes:list",payload:{}});if("noop"in A)throw Error("No handler for site-builder:routes:list \u2014 is site-builder plugin loaded?");if(!A.success||!A.data)throw Error("Failed to fetch routes from site-builder");let Q=zJw.safeParse(A.data);if(!Q.success)throw Error("Failed to parse routes from site-builder");return Q.data}async generate(A,Q,w){let B=this.context.logger.child("SiteContentOperations"),$=await this.fetchRoutes(),f=$;if(A.routeId){if(f=$.filter((K)=>K.id===A.routeId),f.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let K of f)for(let U of K.sections){if(A.sectionId&&U.id!==A.sectionId)continue;if(U.content){B.debug("Section has static content, skipping",{routeId:K.id,sectionId:U.id});continue}if(U.template){let D=this.context.templates.getCapabilities(U.template);if(!D){B.warn("Template not found, skipping section",{routeId:K.id,sectionId:U.id,templateName:U.template});continue}if(!D.canGenerate){B.debug("Template doesn't support generation, skipping",{routeId:K.id,sectionId:U.id,templateName:U.template,capabilities:D});continue}}else{B.debug("Section has no template, skipping",{routeId:K.id,sectionId:U.id});continue}if(!A.force&&!A.dryRun){let D=`${K.id}:${U.id}`;if(await this.context.entityService.getEntity({entityType:"site-content",id:D})){B.debug("Content already exists, skipping",{routeId:K.id,sectionId:U.id});continue}}Y.push({route:K,section:U})}let X=Y.length;if(A.dryRun)return{jobs:[],totalSections:X,queuedSections:X,batchId:`dry-run-${Date.now()}`};let W=[],H=[];for(let{route:K,section:U}of Y){let D=`${K.id}:${U.id}`,q=U.template,b={routeId:K.id,sectionId:U.id,entityId:D,entityType:"site-content",templateName:q,context:{prompt:typeof U.content==="string"?U.content:void 0,data:{routeId:K.id,sectionId:U.id,routeTitle:K.title,routeDescription:K.description,sectionContent:U.content},conversationId:"system"},siteConfig:Q};H.push({type:"shell:content-generation",data:b})}if(H.length>0){let K=this.createJobOptions(w,"site:content-generation"),U=await this.context.jobs.enqueueBatch(H,K);for(let D=0;D<Y.length;D++){let q=Y[D];if(q)W.push({jobId:`${U}-${D}`,routeId:q.route.id,sectionId:q.section.id})}return{jobs:W,totalSections:X,queuedSections:W.length,batchId:U}}return{jobs:[],totalSections:X,queuedSections:0,batchId:`empty-${Date.now()}`}}}class Mt0{siteConfig;operations;constructor(A,Q){this.siteConfig=Q,this.operations=new Pt0(A)}async generateContent(A,Q){let w=bZ0.parse(A);return this.operations.generate(w,this.siteConfig,Q)}}s5();N0();var qJw=Z.object({namespace:Z.string(),sections:Z.record(Z.string(),Z.any())}),Zw2=Z.custom((A)=>qJw.safeParse(A).success),Ot0=Z.object({definitions:Z.union([Zw2,Z.array(Zw2)]).optional()});wA();function Ww2(A,Q){return[P6(Q,"generate","Generate content for all routes, a specific route, or a specific section",bZ0,async(w,B)=>{let $=A();if(!$)return{success:!1,error:"Site content service not initialized"};if(w.sectionId&&!w.routeId)return{success:!1,error:"sectionId requires routeId to be specified"};let f={rootJobId:`generate-${Date.now()}`,progressToken:B.progressToken,pluginId:Q,operationType:"content_operations",interfaceType:B.interfaceType,channelId:B.channelId},Y=await $.generateContent(w,f);return{success:!0,message:`Generated ${Y.queuedSections} of ${Y.totalSections} sections. ${Y.queuedSections>0?"Jobs are running in the background.":"No new content to generate."}`,data:{batchId:Y.batchId,jobsQueued:Y.queuedSections,totalSections:Y.totalSections,jobs:Y.jobs}}})]}var Hw2={name:"@brains/site-content",version:"0.2.0-alpha.143",description:"Site content entity and generation orchestration",dependencies:{"@brains/content-formatters":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class xt0 extends aQ{siteContentService;constructor(A={}){super("site-content",Hw2,A,Ot0)}async onRegister(A){A.entities.register("site-content",eo,jt0);for(let Q of DI(this.config.definitions))A.templates.register(qV(Q),Q.namespace);this.siteContentService=new Mt0(A)}async getTools(){return Ww2(()=>this.siteContentService,this.id)}}function As(A={}){return new xt0(A)}wA();N0();NB();N0();wA();var Kw2=Z.enum(["available","early access","coming soon","planned"]),Uw2=Z.enum(["available","early access","coming soon","planned"]),Dw2=Z.object({title:Z.string(),description:Z.string()}),PH=Z.object({name:Z.string(),availability:Kw2,order:Z.number(),ogImageId:Z.string().optional()}),VZ0=Z.object({tagline:Z.string(),promise:Z.string(),role:Z.string(),purpose:Z.string(),audience:Z.string(),values:Z.array(Z.string()).min(1),features:Z.array(Dw2).min(1).max(6),story:Z.string()}),sb$=PH.pick({name:!0,availability:!0,order:!0}).extend({slug:Z.string()}),VJw=Z.object({name:Z.string(),availability:Uw2,order:Z.number(),slug:Z.string()}),IJw=Z.object({name:Z.string(),availability:Uw2,order:Z.number(),ogImageId:Z.string().optional()}),Cy=LQ.extend({entityType:Z.literal("product"),metadata:VJw}),IZ0=Cy.extend({frontmatter:IJw,body:VZ0,labels:Z.record(Z.string(),Z.string()),ogImageUrl:Z.string().optional()}),JJw=IZ0.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),ogImageUrl:Z.string().optional()});wA();K2();o5();class gy extends G6{constructor(){super(VZ0,{title:"Product",mappings:[{key:"tagline",label:"Tagline",type:"string"},{key:"promise",label:"Promise",type:"string"},{key:"role",label:"Role",type:"string"},{key:"purpose",label:"Purpose",type:"string"},{key:"audience",label:"Audience",type:"string"},{key:"values",label:"Values",type:"array",itemType:"string"},{key:"features",label:"Capabilities",type:"array",itemType:"object",itemMappings:[{key:"title",label:"Title",type:"string"},{key:"description",label:"Description",type:"string"}]},{key:"story",label:"Story",type:"string"}]})}}class Rt0 extends C2{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:Cy,frontmatterSchema:PH,bodyFormatter:new gy})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,PH);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,PH),w=Z1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:w,availability:Q.availability,order:Q.order}}}}var JZ0=new Rt0;N0();wA();var Gw2=Z.object({title:Z.string(),description:Z.string()}),zw2=Z.object({title:Z.string(),description:Z.string()}),FJw=Z.object({title:Z.string(),description:Z.string()}),qw2=Z.object({heading:Z.string(),buttonText:Z.string(),link:Z.string()}),gF=Z.object({headline:Z.string(),tagline:Z.string()}),LJw=Z.object({title:Z.string(),description:Z.string()}),FZ0=Z.object({vision:Z.string(),pillars:Z.array(Gw2).min(1).max(6),approach:Z.array(LJw).min(1).max(6),productsIntro:Z.string(),technologies:Z.array(FJw).min(1).max(6),benefits:Z.array(zw2).min(1).max(6),cta:qw2}),kJw=gF.pick({headline:!0}).extend({slug:Z.string()}),_Jw=Z.object({headline:Z.string(),slug:Z.string()}),NJw=Z.object({headline:Z.string(),tagline:Z.string()}),yy=LQ.extend({entityType:Z.literal("products-overview"),metadata:_Jw}),vt0=yy.extend({frontmatter:NJw,body:FZ0,labels:Z.record(Z.string(),Z.string())});wA();K2();o5();class Ey extends G6{constructor(){super(FZ0,{title:"Products Overview",mappings:[{key:"vision",label:"Vision",type:"string"},{key:"pillars",label:"Core Principles",type:"array",itemType:"object",itemMappings:[{key:"title",label:"Title",type:"string"},{key:"description",label:"Description",type:"string"}]},{key:"approach",label:"How It Works",type:"array",itemType:"object",itemMappings:[{key:"title",label:"Title",type:"string"},{key:"description",label:"Description",type:"string"}]},{key:"productsIntro",label:"Products",type:"string"},{key:"technologies",label:"Built With",type:"array",itemType:"object",itemMappings:[{key:"title",label:"Title",type:"string"},{key:"description",label:"Description",type:"string"}]},{key:"benefits",label:"Why Brains",type:"array",itemType:"object",itemMappings:[{key:"title",label:"Title",type:"string"},{key:"description",label:"Description",type:"string"}]},{key:"cta",label:"Ready to Build",type:"object",children:[{key:"heading",label:"Heading",type:"string"},{key:"buttonText",label:"Button Text",type:"string"},{key:"link",label:"Link",type:"string"}]}]})}}class ht0 extends C2{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:yy,frontmatterSchema:gF,bodyFormatter:new Ey})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,gF);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,gF),w=Z1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:w}}}}var Ct0=new ht0;wA();N0();var jJw=Z.object({entityType:Z.string(),query:Z.object({id:Z.string().optional()}).optional()});function bw2(A,Q){let w=o2(A.content,PH),B=Q.parse(w.content),$=Q.getLabels();return IZ0.parse({...A,frontmatter:w.metadata,body:B,labels:$})}function Vw2(A,Q){let w=o2(A.content,gF),B=Q.parse(w.content),$=Q.getLabels();return vt0.parse({...A,frontmatter:w.metadata,body:B,labels:$})}class LZ0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new Ey;productFormatter=new gy;constructor(A){this.logger=A,this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,w){let B=jJw.parse(A),$=w.entityService;if(B.entityType==="products-overview"){let H=(await $.listEntities({entityType:"products-overview",options:{limit:1}}))[0];if(!H)throw Error("Products overview entity not found");let K=Vw2(H,this.overviewFormatter);return Q.parse(K)}if(B.query?.id){let H=(await $.listEntities({entityType:"product",options:{filter:{metadata:{slug:B.query.id}},limit:1}}))[0];if(!H)throw Error(`Product not found: ${B.query.id}`);return Q.parse({product:bw2(H,this.productFormatter)})}let[f,Y]=await Promise.all([$.listEntities({entityType:"products-overview",options:{limit:1}}),$.listEntities({entityType:"product",options:{sortFields:[{field:"order",direction:"asc"}]}})]),X=f[0];if(!X)throw Error("Products overview entity not found");return Q.parse({overview:Vw2(X,this.overviewFormatter),products:Y.map((W)=>bw2(W,this.productFormatter))})}}import{jsxDEV as U1,Fragment as OJw}from"preact/jsx-dev-runtime";var Iw2=({overview:A,products:Q})=>{let{frontmatter:w,body:B,labels:$}=A;return U1(OJw,{children:[U1(lQ,{title:w.headline,description:w.tagline},void 0,!1,void 0,this),U1("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[U1("style",{children:`
9173
9173
  @keyframes wave-drift {
9174
9174
  from { transform: translateX(0); }
9175
9175
  to { transform: translateX(-50%); }
@@ -9364,7 +9364,7 @@ ${JSON.stringify(w,null,2)}`}function $Z0(A){return A.map((Q)=>Q.detail===null?{
9364
9364
  font: 10px/1.45 var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
9365
9365
  }
9366
9366
  `}},void 0,!1,void 0,this),lZ("section",{className:"product-shell",children:[lZ("header",{className:"product-hero",children:[Q.brandLabel&&lZ("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),lZ("h1",{className:"printable-title",children:Q.name},void 0,!1,void 0,this),Q.availability&&lZ("div",{className:"printable-meta",children:lZ("span",{children:Q.availability},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),lZ("div",{className:"product-body-wrap",children:[lZ("aside",{className:"product-rail","aria-hidden":"true",children:lZ("p",{className:"product-rail-label",children:"Product brief / capabilities"},void 0,!1,void 0,this)},void 0,!1,void 0,this),lZ(V9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q.brandLabel&&lZ("footer",{className:"printable-footer",children:Q.brandLabel},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var EJw=26214400,TJw=60000;class yt0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??kU}async resolve(A){if(A.sourceEntityType!=="product"||A.attachmentType!==kZ0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let w=SJw(Q,{brandLabel:this.resolveBrandLabel()}),B=await hJw(yJw(gJw(),"brain-product-printable-"));try{let $=await vZ({outputDir:B,mediaPath:`/_media/printable/product/${Q.id}`,template:Lw2,format:"pdf",content:w,siteConfig:{title:w.name,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await hZ({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:EJw,timeoutMs:TJw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${mJw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await CJw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}}function SJw(A,Q={}){let{frontmatter:w,content:B}=j6(A.content),$=PH.parse(w);return{name:$.name,body:B,availability:$.availability,...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function mJw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.name)}S9();K2();N0();import{jsxDEV as lJw}from"preact/jsx-dev-runtime";var _Z0="og-image",uJw="products:og-image",kw2=Z.object({name:Z.string().min(1),tagline:Z.string().optional(),availability:Z.string().optional(),brandLabel:Z.string().optional()}),_w2={name:uJw,pluginId:"products",schema:kw2,renderers:{image:cJw}};function cJw(A){let Q=kw2.parse(A);return lJw(cq,{cover:!0,brandLabel:Q.brandLabel??Q.name,eyebrow:"Product",title:Q.name,subtitle:Q.tagline,tag:Q.availability},void 0,!1,void 0,this)}class Et0{metadata={outputEntityType:"image",targetField:"ogImageId"};context;deps;constructor(A,Q={}){this.context=A,this.deps=Q}async resolve(A){if(A.sourceEntityType!=="product"||A.attachmentType!==_Z0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:B}=j6(Q.content),$=PH.parse(w),f=pJw(B,"Tagline"),Y=this.resolveBrandLabel(),X={name:$.name,availability:$.availability,...f?{tagline:f}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await ij({mediaPath:`/_media/og/product/${Q.id}`,template:_w2,content:X,title:X.name,themeMode:"light",themeCSS:this.context.themeCSS,tmpPrefix:"brain-product-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${iJw(Q)}-og.png`}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}}function pJw(A,Q){let w=A.split(/\r?\n/),B=w.findIndex((Y)=>Y.trim().toLowerCase()===`## ${Q.toLowerCase()}`);if(B===-1)return;let $=[];for(let Y of w.slice(B+1)){if(Y.trim().startsWith("## "))break;$.push(Y)}let f=$.join(`
9367
- `).trim();return f.length>0?f:void 0}function iJw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.name)}var Nw2={name:"@brains/products",version:"0.2.0-alpha.142",description:"Product entity management and overview page for marketing showcase",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var nJw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),jw2=Z.object({id:Z.string(),entityType:Z.string(),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:nJw,metadata:Z.record(Z.string(),Z.unknown()),contentHash:Z.string()}),Pw2=Z.enum(["available","early access","coming soon","planned"]),rJw=Z.object({title:Z.string(),description:Z.string()}),oJw=Z.object({name:Z.string(),availability:Pw2,order:Z.number(),ogImageId:Z.string().optional()}),sJw=Z.object({tagline:Z.string(),promise:Z.string(),role:Z.string(),purpose:Z.string(),audience:Z.string(),values:Z.array(Z.string()).min(1),features:Z.array(rJw).min(1).max(6),story:Z.string()}),aJw=Z.object({name:Z.string(),availability:Pw2,order:Z.number(),slug:Z.string()}),Mw2=jw2.extend({entityType:Z.literal("product"),metadata:aJw,frontmatter:oJw,body:sJw,labels:Z.record(Z.string(),Z.string()),url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),ogImageUrl:Z.string().optional()}),NZ0=Z.object({title:Z.string(),description:Z.string()}),tJw=Z.object({heading:Z.string(),buttonText:Z.string(),link:Z.string()}),eJw=Z.object({headline:Z.string(),tagline:Z.string()}),AFw=Z.object({vision:Z.string(),pillars:Z.array(NZ0).min(1).max(6),approach:Z.array(NZ0).min(1).max(6),productsIntro:Z.string(),technologies:Z.array(NZ0).min(1).max(6),benefits:Z.array(NZ0).min(1).max(6),cta:tJw}),QFw=Z.object({headline:Z.string(),slug:Z.string()}),wFw=jw2.extend({entityType:Z.literal("products-overview"),metadata:QFw,frontmatter:eJw,body:AFw,labels:Z.record(Z.string(),Z.string())}),BFw=Z.object({overview:wFw,products:Z.array(Mw2)}),$Fw=Z.object({product:Mw2});class Tt0 extends nQ{entityType=JZ0.entityType;schema=Cy;adapter=JZ0;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("products",Nw2,A,gt0)}getTemplates(){return{"product-list":i1({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:BFw,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:Iw2}}),"product-detail":i1({name:"product-detail",description:"Individual product detail page",schema:$Fw,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:Jw2}})}}getDataSources(){return[new LZ0(this.logger.child("ProductsDataSource"))]}async onRegister(A){this.unregisterPrintableAttachmentProvider=A.attachments.register("product",kZ0,new yt0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("product",_Z0,new Et0(A)),A.entities.register("products-overview",yy,Ct0)}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0}}function St0(A={}){return new Tt0(A)}import{join as lFw}from"path";import{jsxDEV as jZ0,Fragment as fFw}from"preact/jsx-dev-runtime";var Ty=({children:A})=>jZ0(fFw,{children:[jZ0("div",{id:"bgCanvasWrap",className:"rizom-frame-canvas-wrap fixed top-0 left-0 w-full h-full pointer-events-none",children:jZ0("canvas",{id:"heroCanvas",className:"w-full h-full block"},void 0,!1,void 0,this)},void 0,!1,void 0,this),jZ0("div",{className:"max-w-[1440px] mx-auto relative overflow-x-clip",children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this);import{jsxDEV as gI$}from"preact/jsx-dev-runtime";var XFw=l90({extend:{classGroups:{"font-size":[{text:["display-2xl","display-xl","display-lg","display-md","display-sm","heading-lg","heading-md","heading-sm","body-xl","body-lg","body-md","body-sm","body-xs","label-md","label-sm","label-xs"]}]}}});function af(...A){return XFw(pC(A))}import{jsxDEV as cI$}from"preact/jsx-dev-runtime";import{jsxDEV as dI$}from"preact/jsx-dev-runtime";import{jsxDEV as sI$}from"preact/jsx-dev-runtime";import{jsxDEV as QJ$}from"preact/jsx-dev-runtime";var mt0="px-6 md:px-10 xl:px-20",eI$=`${mt0} relative z-[1]`;import{jsxDEV as fJ$}from"preact/jsx-dev-runtime";import{jsxDEV as KJ$}from"preact/jsx-dev-runtime";import{jsxDEV as zJ$}from"preact/jsx-dev-runtime";import{jsxDEV as IJ$,Fragment as VJ$}from"preact/jsx-dev-runtime";import{jsxDEV as LJ$}from"preact/jsx-dev-runtime";import{Fragment as NJ$}from"preact";import{jsxDEV as PJ$}from"preact/jsx-dev-runtime";import{jsxDEV as CJ$,Fragment as hJ$}from"preact/jsx-dev-runtime";var HFw=[{suffix:"work",title:"The service",body:"Workshops and consulting that apply the methodology in live engagements.",linkLabel:"Visit rizom.work \u2192",linkHref:"https://rizom.work"},{suffix:"foundation",title:"The source",body:"The non-profit that holds the IP and stewards the methodology independently.",linkLabel:"Read the manifesto \u2192",linkHref:"https://rizom.foundation"},{suffix:"ai",title:"The tools",body:"Open-source AI agents built on the methodology, the technical layer underneath.",linkLabel:"See the platform \u2192",linkHref:"https://rizom.ai"}];function Ow2(A){return{eyebrow:"The Ecosystem",headline:"One practice. *Three faces.*",cards:HFw.map((Q)=>Q.suffix===A?{...Q,linkLabel:"You are here",linkHref:""}:Q)}}var KFw=Ow2();import{jsxDEV as GFw}from"preact/jsx-dev-runtime";var MZ0="px-6 md:px-10 xl:px-20",DFw=`${MZ0} relative z-[1]`,yF=({id:A,className:Q,children:w})=>GFw("section",{id:A,className:af(DFw,Q),children:w},void 0,!1,void 0,this);import{jsxDEV as DF$}from"preact/jsx-dev-runtime";import{jsxDEV as qF$}from"preact/jsx-dev-runtime";import{jsxDEV as IFw}from"preact/jsx-dev-runtime";var zFw="inline-flex items-center justify-center cursor-pointer border border-solid transition-all [gap:var(--rizom-btn-gap)] [border-radius:var(--rizom-btn-radius)] [font-family:var(--rizom-btn-font-family)] [font-style:var(--rizom-btn-font-style)] [letter-spacing:var(--rizom-btn-letter-spacing)] [text-transform:var(--rizom-btn-text-transform)]",qFw={primary:"[font-weight:var(--rizom-btn-primary-font-weight)] [color:var(--rizom-btn-primary-color)] [background:var(--rizom-btn-primary-bg)] [border-color:var(--rizom-btn-primary-border-color)] [border-width:var(--rizom-btn-primary-border-width)] [box-shadow:var(--rizom-btn-primary-shadow)] hover:[color:var(--rizom-btn-primary-hover-color)] hover:[background:var(--rizom-btn-primary-hover-bg)] hover:[border-color:var(--rizom-btn-primary-hover-border-color)] hover:[border-width:var(--rizom-btn-primary-hover-border-width)] hover:[box-shadow:var(--rizom-btn-primary-hover-shadow)] hover:[transform:var(--rizom-btn-primary-hover-transform)]","primary-strong":"duration-400 ease-[cubic-bezier(0.2,0.8,0.2,1)] [font-weight:var(--rizom-btn-primary-strong-font-weight)] [color:var(--rizom-btn-primary-strong-color)] [background:var(--rizom-btn-primary-strong-bg)] [border-color:var(--rizom-btn-primary-strong-border-color)] [border-width:var(--rizom-btn-primary-strong-border-width)] [box-shadow:var(--rizom-btn-primary-strong-shadow)] hover:[color:var(--rizom-btn-primary-strong-hover-color)] hover:[background:var(--rizom-btn-primary-strong-hover-bg)] hover:[border-color:var(--rizom-btn-primary-strong-hover-border-color)] hover:[border-width:var(--rizom-btn-primary-strong-hover-border-width)] hover:[box-shadow:var(--rizom-btn-primary-strong-hover-shadow)] hover:[transform:var(--rizom-btn-primary-strong-hover-transform)]",secondary:"[font-weight:var(--rizom-btn-secondary-font-weight)] [color:var(--rizom-btn-secondary-color)] [background:var(--rizom-btn-secondary-bg)] [border-color:var(--rizom-btn-secondary-border-color)] [border-width:var(--rizom-btn-secondary-border-width)] [box-shadow:var(--rizom-btn-secondary-shadow)] hover:[color:var(--rizom-btn-secondary-hover-color)] hover:[background:var(--rizom-btn-secondary-hover-bg)] hover:[border-color:var(--rizom-btn-secondary-hover-border-color)] hover:[border-width:var(--rizom-btn-secondary-hover-border-width)] hover:[box-shadow:var(--rizom-btn-secondary-hover-shadow)] hover:[transform:var(--rizom-btn-secondary-hover-transform)]"},bFw={md:"text-base [padding:var(--rizom-btn-md-padding)]",lg:"text-body-md md:text-body-lg [padding:var(--rizom-btn-lg-padding-mobile)] md:[padding:var(--rizom-btn-lg-padding-desktop)]"},VFw="w-full md:w-auto",kP=({href:A,variant:Q="primary",size:w="md",block:B=!1,className:$,children:f})=>IFw("a",{href:A,className:af("rizom-btn",`rizom-btn-${Q}`,`rizom-btn-${w}`,B&&"rizom-btn-block",zFw,qFw[Q],bFw[w],B&&VFw,$),children:f},void 0,!1,void 0,this);import{jsxDEV as kF$}from"preact/jsx-dev-runtime";import{jsxDEV as PF$}from"preact/jsx-dev-runtime";import{Fragment as xF$}from"preact";import{jsxDEV as vF$}from"preact/jsx-dev-runtime";import{jsxDEV as xw2}from"preact/jsx-dev-runtime";var OZ0=({sections:A})=>xw2(Ty,{children:xw2("main",{children:A},void 0,!1,void 0,this)},void 0,!1,void 0,this);var Rw2=`/*
9367
+ `).trim();return f.length>0?f:void 0}function iJw(A){let Q=A.metadata.slug;return Q.length>0?Q:Z1(A.metadata.name)}var Nw2={name:"@brains/products",version:"0.2.0-alpha.143",description:"Product entity management and overview page for marketing showcase",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var nJw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),jw2=Z.object({id:Z.string(),entityType:Z.string(),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:nJw,metadata:Z.record(Z.string(),Z.unknown()),contentHash:Z.string()}),Pw2=Z.enum(["available","early access","coming soon","planned"]),rJw=Z.object({title:Z.string(),description:Z.string()}),oJw=Z.object({name:Z.string(),availability:Pw2,order:Z.number(),ogImageId:Z.string().optional()}),sJw=Z.object({tagline:Z.string(),promise:Z.string(),role:Z.string(),purpose:Z.string(),audience:Z.string(),values:Z.array(Z.string()).min(1),features:Z.array(rJw).min(1).max(6),story:Z.string()}),aJw=Z.object({name:Z.string(),availability:Pw2,order:Z.number(),slug:Z.string()}),Mw2=jw2.extend({entityType:Z.literal("product"),metadata:aJw,frontmatter:oJw,body:sJw,labels:Z.record(Z.string(),Z.string()),url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),ogImageUrl:Z.string().optional()}),NZ0=Z.object({title:Z.string(),description:Z.string()}),tJw=Z.object({heading:Z.string(),buttonText:Z.string(),link:Z.string()}),eJw=Z.object({headline:Z.string(),tagline:Z.string()}),AFw=Z.object({vision:Z.string(),pillars:Z.array(NZ0).min(1).max(6),approach:Z.array(NZ0).min(1).max(6),productsIntro:Z.string(),technologies:Z.array(NZ0).min(1).max(6),benefits:Z.array(NZ0).min(1).max(6),cta:tJw}),QFw=Z.object({headline:Z.string(),slug:Z.string()}),wFw=jw2.extend({entityType:Z.literal("products-overview"),metadata:QFw,frontmatter:eJw,body:AFw,labels:Z.record(Z.string(),Z.string())}),BFw=Z.object({overview:wFw,products:Z.array(Mw2)}),$Fw=Z.object({product:Mw2});class Tt0 extends nQ{entityType=JZ0.entityType;schema=Cy;adapter=JZ0;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("products",Nw2,A,gt0)}getTemplates(){return{"product-list":i1({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:BFw,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:Iw2}}),"product-detail":i1({name:"product-detail",description:"Individual product detail page",schema:$Fw,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:Jw2}})}}getDataSources(){return[new LZ0(this.logger.child("ProductsDataSource"))]}async onRegister(A){this.unregisterPrintableAttachmentProvider=A.attachments.register("product",kZ0,new yt0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("product",_Z0,new Et0(A)),A.entities.register("products-overview",yy,Ct0)}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0}}function St0(A={}){return new Tt0(A)}import{join as lFw}from"path";import{jsxDEV as jZ0,Fragment as fFw}from"preact/jsx-dev-runtime";var Ty=({children:A})=>jZ0(fFw,{children:[jZ0("div",{id:"bgCanvasWrap",className:"rizom-frame-canvas-wrap fixed top-0 left-0 w-full h-full pointer-events-none",children:jZ0("canvas",{id:"heroCanvas",className:"w-full h-full block"},void 0,!1,void 0,this)},void 0,!1,void 0,this),jZ0("div",{className:"max-w-[1440px] mx-auto relative overflow-x-clip",children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this);import{jsxDEV as gI$}from"preact/jsx-dev-runtime";var XFw=l90({extend:{classGroups:{"font-size":[{text:["display-2xl","display-xl","display-lg","display-md","display-sm","heading-lg","heading-md","heading-sm","body-xl","body-lg","body-md","body-sm","body-xs","label-md","label-sm","label-xs"]}]}}});function af(...A){return XFw(pC(A))}import{jsxDEV as cI$}from"preact/jsx-dev-runtime";import{jsxDEV as dI$}from"preact/jsx-dev-runtime";import{jsxDEV as sI$}from"preact/jsx-dev-runtime";import{jsxDEV as QJ$}from"preact/jsx-dev-runtime";var mt0="px-6 md:px-10 xl:px-20",eI$=`${mt0} relative z-[1]`;import{jsxDEV as fJ$}from"preact/jsx-dev-runtime";import{jsxDEV as KJ$}from"preact/jsx-dev-runtime";import{jsxDEV as zJ$}from"preact/jsx-dev-runtime";import{jsxDEV as IJ$,Fragment as VJ$}from"preact/jsx-dev-runtime";import{jsxDEV as LJ$}from"preact/jsx-dev-runtime";import{Fragment as NJ$}from"preact";import{jsxDEV as PJ$}from"preact/jsx-dev-runtime";import{jsxDEV as CJ$,Fragment as hJ$}from"preact/jsx-dev-runtime";var HFw=[{suffix:"work",title:"The service",body:"Workshops and consulting that apply the methodology in live engagements.",linkLabel:"Visit rizom.work \u2192",linkHref:"https://rizom.work"},{suffix:"foundation",title:"The source",body:"The non-profit that holds the IP and stewards the methodology independently.",linkLabel:"Read the manifesto \u2192",linkHref:"https://rizom.foundation"},{suffix:"ai",title:"The tools",body:"Open-source AI agents built on the methodology, the technical layer underneath.",linkLabel:"See the platform \u2192",linkHref:"https://rizom.ai"}];function Ow2(A){return{eyebrow:"The Ecosystem",headline:"One practice. *Three faces.*",cards:HFw.map((Q)=>Q.suffix===A?{...Q,linkLabel:"You are here",linkHref:""}:Q)}}var KFw=Ow2();import{jsxDEV as GFw}from"preact/jsx-dev-runtime";var MZ0="px-6 md:px-10 xl:px-20",DFw=`${MZ0} relative z-[1]`,yF=({id:A,className:Q,children:w})=>GFw("section",{id:A,className:af(DFw,Q),children:w},void 0,!1,void 0,this);import{jsxDEV as DF$}from"preact/jsx-dev-runtime";import{jsxDEV as qF$}from"preact/jsx-dev-runtime";import{jsxDEV as IFw}from"preact/jsx-dev-runtime";var zFw="inline-flex items-center justify-center cursor-pointer border border-solid transition-all [gap:var(--rizom-btn-gap)] [border-radius:var(--rizom-btn-radius)] [font-family:var(--rizom-btn-font-family)] [font-style:var(--rizom-btn-font-style)] [letter-spacing:var(--rizom-btn-letter-spacing)] [text-transform:var(--rizom-btn-text-transform)]",qFw={primary:"[font-weight:var(--rizom-btn-primary-font-weight)] [color:var(--rizom-btn-primary-color)] [background:var(--rizom-btn-primary-bg)] [border-color:var(--rizom-btn-primary-border-color)] [border-width:var(--rizom-btn-primary-border-width)] [box-shadow:var(--rizom-btn-primary-shadow)] hover:[color:var(--rizom-btn-primary-hover-color)] hover:[background:var(--rizom-btn-primary-hover-bg)] hover:[border-color:var(--rizom-btn-primary-hover-border-color)] hover:[border-width:var(--rizom-btn-primary-hover-border-width)] hover:[box-shadow:var(--rizom-btn-primary-hover-shadow)] hover:[transform:var(--rizom-btn-primary-hover-transform)]","primary-strong":"duration-400 ease-[cubic-bezier(0.2,0.8,0.2,1)] [font-weight:var(--rizom-btn-primary-strong-font-weight)] [color:var(--rizom-btn-primary-strong-color)] [background:var(--rizom-btn-primary-strong-bg)] [border-color:var(--rizom-btn-primary-strong-border-color)] [border-width:var(--rizom-btn-primary-strong-border-width)] [box-shadow:var(--rizom-btn-primary-strong-shadow)] hover:[color:var(--rizom-btn-primary-strong-hover-color)] hover:[background:var(--rizom-btn-primary-strong-hover-bg)] hover:[border-color:var(--rizom-btn-primary-strong-hover-border-color)] hover:[border-width:var(--rizom-btn-primary-strong-hover-border-width)] hover:[box-shadow:var(--rizom-btn-primary-strong-hover-shadow)] hover:[transform:var(--rizom-btn-primary-strong-hover-transform)]",secondary:"[font-weight:var(--rizom-btn-secondary-font-weight)] [color:var(--rizom-btn-secondary-color)] [background:var(--rizom-btn-secondary-bg)] [border-color:var(--rizom-btn-secondary-border-color)] [border-width:var(--rizom-btn-secondary-border-width)] [box-shadow:var(--rizom-btn-secondary-shadow)] hover:[color:var(--rizom-btn-secondary-hover-color)] hover:[background:var(--rizom-btn-secondary-hover-bg)] hover:[border-color:var(--rizom-btn-secondary-hover-border-color)] hover:[border-width:var(--rizom-btn-secondary-hover-border-width)] hover:[box-shadow:var(--rizom-btn-secondary-hover-shadow)] hover:[transform:var(--rizom-btn-secondary-hover-transform)]"},bFw={md:"text-base [padding:var(--rizom-btn-md-padding)]",lg:"text-body-md md:text-body-lg [padding:var(--rizom-btn-lg-padding-mobile)] md:[padding:var(--rizom-btn-lg-padding-desktop)]"},VFw="w-full md:w-auto",kP=({href:A,variant:Q="primary",size:w="md",block:B=!1,className:$,children:f})=>IFw("a",{href:A,className:af("rizom-btn",`rizom-btn-${Q}`,`rizom-btn-${w}`,B&&"rizom-btn-block",zFw,qFw[Q],bFw[w],B&&VFw,$),children:f},void 0,!1,void 0,this);import{jsxDEV as kF$}from"preact/jsx-dev-runtime";import{jsxDEV as PF$}from"preact/jsx-dev-runtime";import{Fragment as xF$}from"preact";import{jsxDEV as vF$}from"preact/jsx-dev-runtime";import{jsxDEV as xw2}from"preact/jsx-dev-runtime";var OZ0=({sections:A})=>xw2(Ty,{children:xw2("main",{children:A},void 0,!1,void 0,this)},void 0,!1,void 0,this);var Rw2=`/*
9368
9368
  * Shared globals + helpers used by tree / constellation / roots canvas
9369
9369
  * scripts. Loaded as a shared static asset by the Rizom runtime package
9370
9370
  * so the variant canvases
@@ -11854,7 +11854,7 @@ facts, owners, or tasks. Return only the required structured JSON.`});N0();var K
11854
11854
  `);return this.truncateContent(B||Q||ry(A))}truncateContent(A){if(A.length<=V62)return A;let Q=A.slice(0,V62-1),w=Q.search(/\s\S*$/);return`${(w>0?Q.slice(0,w):Q).trimEnd()}\u2026`}isSummaryEntity(A){return A.entityType===N8}isDecisionEntity(A){return A.entityType===pZ}getEntitySpaceId(A){let Q=A.metadata;if("spaceId"in Q&&typeof Q.spaceId==="string")return Q.spaceId;return vU(Q)}}var TLw=5,SLw=3;function at0(A){A.messaging.subscribe(uL,async(Q)=>{let w=oT.parse(Q.payload);return{success:!0,data:await cZ0(A,w)}})}async function cZ0(A,Q){let w=w$(Q.userPermissionLevel);if(!Q.channelId)return I62(A,Q,{visibilityScope:w,reason:"no-channel-context",items:[]}),{items:[]};let B=new oy(A),$=await B.retrieve({query:Q.message,conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:TLw,visibilityScope:w}),f=$.results.length===0?await B.retrieve({conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:SLw,visibilityScope:w}):void 0,Y=$.results.length>0,X=Y?$.results:f?.results??[];return I62(A,Q,{visibilityScope:w,spaceId:$.spaceId??f?.spaceId,reason:X.length>0?"memory-injected":"no-same-space-memory",items:X.map((W)=>mLw(W,Y))}),{items:X.map(uLw)}}function I62(A,Q,w){A.logger.info("Conversation memory agent context audit",{conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,channelName:Q.channelName,userPermissionLevel:Q.userPermissionLevel,visibilityScope:w.visibilityScope,spaceId:w.spaceId,reason:w.reason,itemCount:w.items.length,items:w.items})}function mLw(A,Q){return{id:A.id,entityType:A.entityType,conversationId:A.conversationId,spaceId:A.spaceId,visibility:A.visibility,score:A.score,updated:A.updated,eligibilityReason:Q?"same-space-query-match":"recent-same-space-memory"}}function uLw(A){let Q=A.channelName??A.channelId;return{id:A.id,source:"conversation-memory",title:`${A.entityType} from ${Q}`,content:A.content,provenance:{entityType:A.entityType,entityId:A.id,conversationId:A.conversationId,spaceId:A.spaceId,interfaceType:A.interfaceType,channelId:A.channelId,channelName:A.channelName,updated:A.updated,score:A.score,messageCount:A.messageCount,entryCount:A.entryCount,status:A.status}}}N0();xX();var L62=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),k62=Z.enum(["user","assistant"]),cLw=Z.object({actorId:Z.string(),canonicalId:Z.string().optional(),interfaceType:Z.string(),role:k62,displayName:Z.string().optional(),username:Z.string().optional(),isBot:Z.boolean().optional()}),lLw=Z.object({messageId:Z.string().optional(),channelId:Z.string().optional(),channelName:Z.string().optional(),threadId:Z.string().optional(),metadata:Z.record(Z.string(),Z.unknown()).optional()}),et0=Z.object({role:k62,content:Z.string(),timestamp:Z.string().datetime().optional(),actor:cLw.optional(),source:lLw.optional()}),pLw=Z.object({conversationId:Z.string().default("eval-conversation"),messages:Z.array(et0)}),iLw=Z.object({conversationId:Z.string()}),dLw=Z.object({conversationId:Z.string().default("eval-conversation"),interfaceType:Z.string().default("eval"),channelId:Z.string().default("eval-channel"),channelName:Z.string().optional(),projectionDecision:Z.enum(["update","append"]).default("update"),existingSummary:Z.string().optional(),existingMessageCount:Z.number().int().min(0).default(0),messages:Z.array(et0)}),lZ0=Z.object({actorId:Z.string(),canonicalId:Z.string().optional(),displayName:Z.string().optional()}),nLw=lZ0.extend({roles:Z.array(Z.enum(["user","assistant","system"])).default(["user"]),sourceActorIds:Z.array(Z.string()).optional()}),rLw=Z.object({actorId:Z.string().optional(),canonicalId:Z.string().optional(),displayName:Z.string()}),_62=Z.object({id:Z.string(),entityType:Z.enum(["summary","decision","action-item"]),content:Z.string(),excerpt:Z.string().optional(),score:Z.number().optional(),conversationId:Z.string(),interfaceType:Z.string(),channelId:Z.string(),channelName:Z.string().optional(),updated:Z.string().datetime().optional(),visibility:L62,status:Z.string().optional(),participants:Z.array(nLw).optional(),decidedBy:Z.array(lZ0).optional(),mentionedBy:Z.array(lZ0).optional(),assignedTo:Z.array(rLw).optional(),requestedBy:Z.array(lZ0).optional()}),oLw=Z.object({query:Z.string().optional(),conversationId:Z.string().optional(),interfaceType:Z.string().optional(),channelId:Z.string().optional(),limit:Z.number().int().min(1).optional(),includeOtherSpaces:Z.boolean().optional(),actorId:Z.string().optional(),canonicalId:Z.string().optional(),visibilityScope:L62.optional(),memory:Z.array(_62).optional()}),sLw=Z.object({conversationId:Z.string().default("eval-conversation"),message:Z.string(),interfaceType:Z.string().default("eval"),channelId:Z.string().optional(),channelName:Z.string().optional(),userPermissionLevel:Z.enum(["anchor","trusted","public"]).default("trusted"),memory:Z.array(_62).optional()}),aLw=Z.object({conversationId:Z.string().default("eval-conversation"),existingSummary:Z.string().optional(),existingMessageCount:Z.number().int().min(0).default(0),messages:Z.array(et0)});function N62(A){let{context:Q,logger:w,config:B}=A;Q.eval.registerHandler("summarizeMessages",async($)=>{let f=pLw.parse($),Y=tt0(f.messages,f.conversationId),W=await new iy(Q,w,B).extract(Y);return W.entries.map((H)=>{let K=W.decisions.filter((D)=>D.timeRange.start>=H.timeRange.start).filter((D)=>D.timeRange.end<=H.timeRange.end).map((D)=>D.text),U=W.actionItems.filter((D)=>D.timeRange.start>=H.timeRange.start).filter((D)=>D.timeRange.end<=H.timeRange.end).map((D)=>D.text);return{...H,decisions:K,actionItems:U,keyPointsText:H.keyPoints.join(`
11855
11855
  `),decisionsText:K.join(`
11856
11856
  `),actionItemsText:U.join(`
11857
- `)}})}),Q.eval.registerHandler("decideProjection",async($)=>{let f=aLw.parse($),Y=tt0(f.messages,f.conversationId),X=f.existingSummary?J62({conversationId:f.conversationId,content:f.existingSummary,messageCount:f.existingMessageCount,projectionVersion:B.projectionVersion,visibility:B.memoryVisibility}):null;return new EF(Q,w,B).decideProjection(Y,X)}),Q.eval.registerHandler("retrieveMemory",async($)=>{let f=oLw.parse($),Y=f.memory?F62(Q,f.memory):Q;return new oy(Y).retrieve(f)}),Q.eval.registerHandler("buildAgentContext",async($)=>{let f=sLw.parse($),Y=f.memory?F62(Q,f.memory):Q;return cZ0(Y,f)}),Q.eval.registerHandler("projectMessages",async($)=>{let f=dLw.parse($),Y=tt0(f.messages,f.conversationId),X=tLw({conversationId:f.conversationId,interfaceType:f.interfaceType,channelId:f.channelId,channelName:f.channelName,messages:Y}),W=f.existingSummary?J62({conversationId:f.conversationId,content:f.existingSummary,messageCount:f.existingMessageCount,projectionVersion:B.projectionVersion,visibility:B.memoryVisibility}):null,H=[],K=[],U=eLw({context:Q,conversation:X,messages:Y,existing:W,upserted:H,deleted:K,projectionDecision:f.projectionDecision});return{result:await new EF(U,w,B).projectConversation(f.conversationId),summaries:H.filter((b)=>b.entityType==="summary"),decisions:H.filter((b)=>b.entityType==="decision"),actionItems:H.filter((b)=>b.entityType==="action-item"),deleted:K}}),Q.eval.registerHandler("projectConversation",async($)=>{let f=iLw.parse($);return new EF(Q,w,B).projectConversation(f.conversationId)})}function J62(A){return{id:A.conversationId,entityType:"summary",content:A.content,contentHash:"eval-existing-summary",visibility:A.visibility,created:"2026-01-01T00:00:00.000Z",updated:"2026-01-01T00:00:00.000Z",metadata:{conversationId:A.conversationId,channelId:"eval-channel",interfaceType:"eval",messageCount:A.messageCount,entryCount:1,sourceHash:"eval-source-hash",projectionVersion:A.projectionVersion}}}function tt0(A,Q){return A.map((w,B)=>{let $=w.timestamp??new Date(Date.UTC(2026,0,1,0,B)).toISOString();return{id:`eval-message-${B+1}`,conversationId:Q,role:w.role,content:w.content,timestamp:$,metadata:{...w.actor?{actor:w.actor}:{},...w.source?{source:w.source}:{}}}})}function tLw(A){let Q=A.messages[0],w=A.messages[A.messages.length-1],B=Q?.timestamp??"2026-01-01T00:00:00.000Z",$=w?.timestamp??B;return{id:A.conversationId,sessionId:A.conversationId,interfaceType:A.interfaceType,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},startedAt:B,lastActiveAt:$,createdAt:B,updatedAt:$,metadata:{}}}function eLw(A){let Q=vU(A.conversation);return{...A.context,spaces:[Q],conversations:{...A.context.conversations,get:async()=>A.conversation,getMessages:async()=>A.messages},ai:{...A.context.ai,generateObject:async()=>({object:{decision:A.projectionDecision,rationale:"Forced by eval input"}})},entityService:{...A.context.entityService,getEntity:async({entityType:w})=>w==="summary"?A.existing:null,listEntities:async()=>[],deleteEntity:async(w)=>{return A.deleted.push(w),!0},upsertEntity:async({entity:w})=>{return A.upserted.push(w),{entityId:w.id,jobId:"eval-upsert",created:!0,skipped:!1}}}}}function F62(A,Q){let w=Q.map(Akw),B=w.map(($,f)=>({entity:$,score:Q[f]?.score??1,excerpt:Q[f]?.excerpt??ry($)}));return{...A,entityService:{...A.entityService,search:async()=>B,listEntities:async({entityType:$})=>w.filter((f)=>f.entityType===$)}}}function Akw(A){if(A.entityType==="summary")return Qkw(A);if(A.entityType==="decision")return wkw(A);return Bkw(A)}function Ae0(A){let Q=A.updated??"2026-01-01T00:00:00.000Z";return{id:A.id,content:A.content,contentHash:w6(A.content),visibility:A.visibility,created:Q,updated:Q}}function Qkw(A){return{...Ae0(A),entityType:"summary",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,messageCount:3,entryCount:1,sourceHash:`source-${A.id}`,projectionVersion:1,...A.participants?{participants:A.participants}:{}}}}function wkw(A){return{...Ae0(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:vU(A),timeRange:{start:"2026-01-01T00:00:00.000Z",end:"2026-01-01T00:01:00.000Z"},sourceSummaryId:A.conversationId,sourceMessageCount:2,projectionVersion:1,status:A.status==="superseded"?"superseded":"active",...A.decidedBy?{decidedBy:A.decidedBy}:{},...A.mentionedBy?{mentionedBy:A.mentionedBy}:{}}}}function Bkw(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...Ae0(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:vU(A),timeRange:{start:"2026-01-01T00:00:00.000Z",end:"2026-01-01T00:01:00.000Z"},sourceSummaryId:A.conversationId,sourceMessageCount:2,projectionVersion:1,status:Q,...A.assignedTo?{assignedTo:A.assignedTo}:{},...A.requestedBy?{requestedBy:A.requestedBy}:{}}}}var j62={name:"@brains/conversation-memory",version:"0.2.0-alpha.142",description:"Plugin for deriving durable conversation memory",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/conversation-service":"workspace:*","@brains/dashboard":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/node":"^20.19.43",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},main:"./src/index.ts",private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var fkw=new OH,Ykw=new cy,Xkw=new ly,Zkw=Z.object({conversationId:Z.string()});class Qe0 extends nQ{entityType=N8;schema=ws;adapter=fkw;constructor(A={}){super(RZ0,j62,A,nt0)}getConfig(){return this.config}getTemplates(){return{"summary-list":sw2,"summary-detail":aw2,"ai-response":tw2}}getDataSources(){return[new st0(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:N8,job:{type:mw2,handler:new EZ0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await qk(A,N8,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:lt0,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:RZ0}}},sourceChange:{sourceKind:OS,sourceTypes:[OS],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[vO],jobData:(Q)=>{let{conversationId:w}=this.parseConversationMessagePayload(Q);return{mode:"conversation",conversationId:w,reason:"message-added"}},jobOptions:(Q)=>{let{conversationId:w}=this.parseConversationMessagePayload(Q);return{priority:5,delayMs:this.config.projectionDelayMs,source:lt0,deduplication:"skip",deduplicationKey:`conversation-memory:${w}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${w}`,pluginId:RZ0}}}}}]}parseConversationMessagePayload(A){return Zkw.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:w}=this.parseConversationMessagePayload(Q),B=await A.conversations.get(w);if(!B)return!1;return NP({conversation:B,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(pZ,Bs,Ykw),A.entities.register(MH,$s,Xkw),Q62({context:A,pluginId:this.id}),B62({context:A,pluginId:this.id}),D62({context:A,pluginId:this.id}),q62({context:A,pluginId:this.id,config:this.config}),at0(A),N62({context:A,logger:this.logger,config:this.config})}}function we0(A={}){return new Qe0(A)}wA();N0();N0();o5();var P62=Z.object({label:Z.string(),href:Z.string()}),M62=Z.object({label:Z.string(),title:Z.string(),detail:Z.string()}),Wkw=Z.object({eyebrow:Z.string(),name:Z.string(),sub:Z.string()}),Hkw=Z.object({tone:Z.enum(["capture","synthesis","share"]),title:Z.string(),text:Z.string()}),Be0=Z.object({captures:Z.number(),links:Z.number(),topics:Z.number(),summaries:Z.number(),peers:Z.number()}),sy=Z.object({eyebrow:Z.string(),headline:Z.string(),intro:Z.string(),primaryCta:P62,secondaryCta:P62,inputs:Z.array(M62).min(1),outputs:Z.array(M62).min(1),core:Wkw,legend:Z.array(Hkw).min(1)}),$e0=sy.extend({counts:Be0}),O62={eyebrow:"A team brain, diagrammed",headline:"Relay sits between the work and the world, and keeps both honest.",intro:"Capture sources flow into a shared brain; the brain organizes, summarizes, and \u2014 selectively \u2014 exposes a public surface. Everything else stays private and operational.",primaryCta:{label:"See it on a real team",href:"#diagram"},secondaryCta:{label:"Read the model",href:"/about"},inputs:[{label:"Source \xB7 chat",title:"Discord",detail:"Shared decisions and field notes captured in flow."},{label:"Source \xB7 agent",title:"MCP / CLI",detail:"Structured captures from tools and assistants."},{label:"Source \xB7 web",title:"Links & docs",detail:"External material indexed with sourceable metadata."}],outputs:[{label:"Surface \xB7 public",title:"Default site",detail:"A small, durable face onto what the team currently knows."},{label:"Surface \xB7 agents",title:"A2A exchange",detail:"Peer brains coordinate over an approved, signed protocol."},{label:"Surface \xB7 query",title:"Team Q&A",detail:"Ask the brain in chat; answers cite the captures behind them."}],core:{eyebrow:"The relay",name:"brain",sub:"capture \u2192 topics \u2192 summaries"},legend:[{tone:"capture",title:"Capture",text:"Anything the team already does that produces a trace \u2014 chat messages, links, deploys, decisions."},{tone:"synthesis",title:"Synthesis",text:"The work the brain does on its own time \u2014 clustering captures into topics, summaries, and durable memory."},{tone:"share",title:"Share",text:"A small, opinionated public surface and an approved agent-to-agent protocol. Most memory stays private."}]},x62=new G6(sy,{title:"Home diagram",mappings:[{key:"eyebrow",label:"Eyebrow",type:"string"},{key:"headline",label:"Headline",type:"string"},{key:"intro",label:"Intro",type:"string"},{key:"primaryCta",label:"Primary CTA",type:"object",children:[{key:"label",label:"Label",type:"string"},{key:"href",label:"Href",type:"string"}]},{key:"secondaryCta",label:"Secondary CTA",type:"object",children:[{key:"label",label:"Label",type:"string"},{key:"href",label:"Href",type:"string"}]},{key:"inputs",label:"Inputs",type:"array",itemType:"object",itemMappings:[{key:"label",label:"Label",type:"string"},{key:"title",label:"Title",type:"string"},{key:"detail",label:"Detail",type:"string"}]},{key:"outputs",label:"Outputs",type:"array",itemType:"object",itemMappings:[{key:"label",label:"Label",type:"string"},{key:"title",label:"Title",type:"string"},{key:"detail",label:"Detail",type:"string"}]},{key:"core",label:"Core",type:"object",children:[{key:"eyebrow",label:"Eyebrow",type:"string"},{key:"name",label:"Name",type:"string"},{key:"sub",label:"Sub",type:"string"}]},{key:"legend",label:"Legend",type:"array",itemType:"object",itemMappings:[{key:"tone",label:"Tone",type:"string"},{key:"title",label:"Title",type:"string"},{key:"text",label:"Text",type:"string"}]}]});function pZ0(A){return x62.parse(A)}function R62(A){return x62.format(A)}N0();var Kkw=Z.looseObject({query:Z.object({routeId:Z.string().default("home"),sectionId:Z.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}),Ukw={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class fe0{id="relay-site:home-counts";name="Relay homepage counts";description="Fetches Relay homepage content and live entity counts for the system diagram";async fetch(A,Q,w){let B=Kkw.parse(A??{}),$=await this.fetchContent(w,B.query.routeId,B.query.sectionId),f=await this.fetchCounts(w);return Q.parse({...$,counts:f})}async fetchContent(A,Q,w){let B=await A.entityService.getEntity({entityType:"site-content",id:`${Q}:${w}`});if(!B?.content)return O62;return sy.parse(pZ0(B.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(Ukw).map(async([w,B])=>[w,await this.countOrZero(A,B)]));return Be0.parse(Object.fromEntries(Q))}async countOrZero(A,Q){if(!A.entityService.hasEntityType(Q))return 0;try{return await A.entityService.countEntities({entityType:Q})}catch{return 0}}}import{jsxDEV as D1}from"preact/jsx-dev-runtime";var v62=Z.object({label:Z.string(),href:Z.string()}),Dkw=Z.object({label:Z.string(),value:Z.string(),note:Z.string()}),Gkw=Z.object({eyebrow:Z.string(),headline:Z.string(),intro:Z.string(),primaryCta:v62,secondaryCta:v62,signals:Z.array(Dkw)}),zkw=Z.object({phase:Z.string(),title:Z.string(),text:Z.string()}),qkw=Z.object({eyebrow:Z.string(),title:Z.string(),intro:Z.string(),steps:Z.array(zkw)}),bkw=Z.object({label:Z.string(),title:Z.string(),text:Z.string()}),Vkw=Z.object({title:Z.string(),intro:Z.string(),cards:Z.array(bkw)}),Ikw=Z.object({title:Z.string(),intro:Z.string(),points:Z.array(Z.string())}),Jkw={title:"Relay is a collaborative team-memory brain.",intro:"It exists for teams that need to remember together: capturing what happened, summarizing why it matters, and coordinating with trusted peer brains when work crosses boundaries.",points:["Not a personal blog engine or portfolio shell.","Not a marketing automation stack.","A small public face for a larger private knowledge workflow."]},Fkw="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function h62({href:A,label:Q}){return D1("a",{href:A,className:Fkw,children:Q},void 0,!1,void 0,this)}function Lkw({siteInfo:A,children:Q}){let w=[...A.navigation.primary,...A.navigation.secondary],B=A.cta??{buttonText:"Start here",buttonLink:"/about"};return D1(Ty,{children:[D1("nav",{className:"fixed left-0 right-0 top-0 z-[100] flex items-center justify-between border-b border-theme-light bg-nav-fade px-6 py-4 backdrop-blur-[12px] md:px-10 xl:px-20",children:[D1("a",{href:"/",className:"font-nav text-[20px]","aria-label":"Relay home",children:[D1("span",{className:"font-bold text-theme",children:"relay"},void 0,!1,void 0,this),D1("span",{className:"font-bold text-accent",children:"."},void 0,!1,void 0,this),D1("span",{className:"text-theme-muted",children:"brain"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"flex items-center gap-5 md:gap-8",children:[D1("div",{className:"hidden items-center gap-6 md:flex",children:w.map(($)=>D1(h62,{...$},`${$.href}-${$.label}`,!1,void 0,this))},void 0,!1,void 0,this),D1("a",{href:B.buttonLink,className:"rounded-[999px] border border-theme px-4 py-2 font-body text-[13px] font-semibold text-theme transition-colors hover:border-accent hover:text-accent md:px-5",children:B.buttonText},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("main",{children:Q},void 0,!1,void 0,this),D1("footer",{className:"relative z-[1] border-t border-theme-light px-6 py-8 md:px-10 xl:px-20",children:D1("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[D1("div",{children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.22em] text-theme-light",children:A.copyright},void 0,!1,void 0,this),D1("p",{className:"mt-2 max-w-[560px] font-body text-body-xs text-theme-muted",children:A.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"flex flex-wrap items-center gap-5",children:[w.map(($)=>D1(h62,{...$},`footer-${$.href}-${$.label}`,!1,void 0,this)),D1("button",{id:"themeToggle","aria-label":"Toggle light mode",className:"rounded-md border border-theme-light bg-transparent px-2.5 py-1.5 font-body text-label-md text-theme-light transition-colors hover:border-theme hover:text-theme",children:"\u2600 Light"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var kkw=({sections:A,siteInfo:Q})=>D1(Lkw,{siteInfo:Q,children:A},void 0,!1,void 0,this);function _kw({eyebrow:A,headline:Q,intro:w,primaryCta:B,secondaryCta:$,signals:f}){return D1(yF,{className:"min-h-[92vh] pt-[152px] pb-20 md:pt-[190px]",children:D1("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_420px] lg:items-end",children:[D1("div",{children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),D1("h1",{className:"mt-7 max-w-[980px] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),D1("p",{className:"mt-7 max-w-[720px] font-body text-body-lg text-theme-muted",children:w},void 0,!1,void 0,this),D1("div",{className:"mt-10 flex flex-col gap-3 sm:flex-row",children:[D1(kP,{href:B.href,size:"lg",variant:"primary-strong",children:B.label},void 0,!1,void 0,this),D1(kP,{href:$.href,size:"lg",variant:"secondary",children:$.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"rounded-[32px] border border-card-relay-border bg-card-relay-bg p-5 shadow-[0_24px_90px_var(--color-glow-relay)] backdrop-blur-sm",children:[D1("p",{className:"font-label text-label-xs uppercase tracking-[0.24em] text-theme-light",children:"Live relay signals"},void 0,!1,void 0,this),D1("div",{className:"mt-5 grid gap-3",children:f.map((Y)=>D1("div",{className:"rounded-[22px] border border-card-divider bg-bg-muted p-5",children:[D1("div",{className:"flex items-center justify-between gap-4",children:[D1("p",{className:"font-label text-label-xs uppercase tracking-[0.18em] text-secondary",children:Y.label},void 0,!1,void 0,this),D1("span",{className:"h-2 w-2 rounded-full bg-accent shadow-[0_0_22px_var(--color-accent)]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("p",{className:"mt-4 font-display text-display-sm text-theme",children:Y.value},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-body text-body-xs text-theme-muted",children:Y.note},void 0,!1,void 0,this)]},Y.label,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function Nkw({eyebrow:A,title:Q,intro:w,steps:B}){return D1(yF,{id:"operating-loop",className:"py-section",children:[D1("div",{className:"max-w-[840px]",children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-secondary",children:A},void 0,!1,void 0,this),D1("h2",{className:"mt-5 font-display text-display-md text-theme",children:Q},void 0,!1,void 0,this),D1("p",{className:"mt-5 font-body text-body-md text-theme-muted",children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:B.map(($)=>D1("article",{className:"min-h-[300px] rounded-[28px] border border-card-panel-border bg-card-panel-bg p-6",children:[D1("p",{className:"font-label text-label-sm text-accent",children:$.phase},void 0,!1,void 0,this),D1("h3",{className:"mt-16 font-display text-display-sm text-theme",children:$.title},void 0,!1,void 0,this),D1("p",{className:"mt-4 font-body text-body-sm text-theme-muted",children:$.text},void 0,!1,void 0,this)]},$.phase,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function jkw({title:A,intro:Q,cards:w}){return D1(yF,{className:"py-section",children:D1("div",{className:"rounded-[36px] border border-theme-light bg-bg-muted p-6 md:p-10",children:D1("div",{className:"grid gap-8 lg:grid-cols-[360px_1fr]",children:[D1("div",{children:[D1("h2",{className:"font-display text-display-md text-theme",children:A},void 0,!1,void 0,this),D1("p",{className:"mt-5 font-body text-body-md text-theme-muted",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"grid gap-4",children:w.map((B)=>D1("article",{className:"rounded-[24px] border border-card-divider bg-bg-subtle/70 p-5",children:[D1("p",{className:"font-label text-label-xs uppercase tracking-[0.22em] text-accent",children:B.label},void 0,!1,void 0,this),D1("h3",{className:"mt-3 font-nav text-heading-lg text-theme",children:B.title},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-body text-body-sm text-theme-muted",children:B.text},void 0,!1,void 0,this)]},B.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Pkw({title:A,intro:Q,points:w}){return D1(yF,{className:"min-h-[78vh] pt-[150px] pb-section md:pt-[190px]",children:[D1("div",{className:"max-w-[920px]",children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:"Relay model"},void 0,!1,void 0,this),D1("h1",{className:"mt-6 font-display text-display-lg text-theme",children:A},void 0,!1,void 0,this),D1("p",{className:"mt-7 font-body text-body-lg text-theme-muted",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:w.map((B)=>D1("div",{className:"rounded-[24px] border border-card-panel-current-border bg-card-panel-current-bg p-6 font-body text-body-md text-theme",children:B},B,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Mkw=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},Okw=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),Xs=(A,Q,w=`${Q}s`)=>`${Okw(A)} ${A===1?Q:w}`;function xkw({eyebrow:A,headline:Q,intro:w,primaryCta:B,secondaryCta:$,inputs:f,outputs:Y,core:X,legend:W,counts:H}){let K=[{key:"captures",className:"top-[-10px] left-1/2 -translate-x-1/2",label:Xs(H.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:Xs(H.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:Xs(H.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:Xs(H.summaries,"summary","summaries")}];return D1(yF,{className:"pt-[150px] pb-section md:pt-[190px]",id:"diagram",children:[D1("div",{className:"mx-auto max-w-[1040px] text-center",children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),D1("h1",{className:"mx-auto mt-7 max-w-[22ch] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),D1("p",{className:"mx-auto mt-7 max-w-[64ch] font-body text-body-lg text-theme-muted",children:w},void 0,!1,void 0,this),D1("div",{className:"mt-10 flex flex-col justify-center gap-3 sm:flex-row",children:[D1(kP,{href:B.href,size:"lg",variant:"primary-strong",children:B.label},void 0,!1,void 0,this),D1(kP,{href:$.href,size:"lg",variant:"secondary",children:$.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"mx-auto mt-20 max-w-[1020px] rounded-[32px] border border-theme-light bg-[radial-gradient(circle_at_1px_1px,rgb(255_255_255_/_0.05)_1px,transparent_0),linear-gradient(180deg,rgb(255_255_255_/_0.02),transparent)] bg-[length:24px_24px,100%_100%] px-6 py-14",children:[D1("div",{className:"grid items-center gap-8 lg:grid-cols-[1fr_1.4fr_1fr]",children:[D1("div",{className:"flex flex-col gap-3.5",children:f.map((U)=>D1("div",{className:"rounded-2xl border border-card-panel-border border-l-2 border-l-accent bg-card-panel-bg px-4 py-4 text-left backdrop-blur-sm",children:[D1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:U.label},void 0,!1,void 0,this),D1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:U.title},void 0,!1,void 0,this),D1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:U.detail},void 0,!1,void 0,this)]},`${U.label}-${U.title}`,!0,void 0,this))},void 0,!1,void 0,this),D1("div",{className:"relative mx-auto grid aspect-square w-full max-w-[320px] place-items-center rounded-full bg-[radial-gradient(circle_at_center,rgb(232_119_34_/_0.25),transparent_65%)]",children:[D1("div",{className:"absolute inset-0 rounded-full border border-dashed border-accent/30"},void 0,!1,void 0,this),D1("div",{className:"absolute inset-6 animate-spin rounded-full border border-dashed border-secondary/40 [animation-duration:28s]"},void 0,!1,void 0,this),K.map((U)=>D1("span",{className:`absolute whitespace-nowrap rounded-full border border-theme bg-bg px-2.5 py-1 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light ${U.className}`,children:U.label},U.key,!1,void 0,this)),D1("div",{className:"relative z-[1] px-6 text-center",children:[D1("p",{className:"font-label text-[10px] uppercase tracking-[0.28em] text-accent",children:X.eyebrow},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-display text-[36px] leading-none text-theme",children:X.name},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-body text-[13px] text-theme-muted",children:X.sub},void 0,!1,void 0,this),D1("p",{className:"mt-4 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light",children:[Xs(H.links,"link")," indexed"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"flex flex-col gap-3.5",children:Y.map((U)=>D1("div",{className:"rounded-2xl border border-card-panel-border border-r-2 border-r-secondary bg-card-panel-bg px-4 py-4 text-left backdrop-blur-sm",children:[D1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:U.label},void 0,!1,void 0,this),D1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:U.title},void 0,!1,void 0,this),D1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:U.detail},void 0,!1,void 0,this)]},`${U.label}-${U.title}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"mt-14 grid gap-4 border-t border-theme-light pt-8 md:grid-cols-3",children:W.map((U)=>D1("div",{className:"text-left",children:[D1("h2",{className:"font-display text-[16px] font-medium text-theme",children:[D1("span",{className:`mr-2.5 inline-block h-3 w-3 rounded-[3px] align-middle ${Mkw(U.tone)}`},void 0,!1,void 0,this),U.title]},void 0,!0,void 0,this),D1("p",{className:"mt-1.5 font-body text-[13px] leading-[1.6] text-theme-muted",children:U.text},void 0,!1,void 0,this)]},U.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var Rkw=i1({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:$e0,formatter:{parse:(A)=>$e0.parse({...pZ0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>R62(sy.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:xkw}}),vkw=(A)=>_kw(Gkw.parse(A)),hkw=(A)=>Nkw(qkw.parse(A)),Ckw=(A)=>jkw(Vkw.parse(A)),gkw=(A)=>Pkw(Ikw.parse(A)),C62={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},g62={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:vkw,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...C62,label:"Primary CTA"},secondaryCta:{...C62,label:"Secondary CTA"},signals:{type:"array",label:"Signals",minItems:1,items:{type:"object",label:"Signal",fields:{label:{type:"string",label:"Label"},value:{type:"string",label:"Value"},note:{type:"string",label:"Note"}}}}}},"home-loop":{title:"Home operating loop",description:"Relay capture, synthesis, and sharing loop",layout:hkw,fields:{eyebrow:{type:"string",label:"Eyebrow"},title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},steps:{type:"array",label:"Steps",minItems:1,items:{type:"object",label:"Step",fields:{phase:{type:"string",label:"Phase"},title:{type:"string",label:"Title"},text:{type:"string",label:"Text"}}}}}},"home-surface":{title:"Home surface",description:"Relay default template explanation cards",layout:Ckw,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},cards:{type:"array",label:"Cards",minItems:1,items:{type:"object",label:"Card",fields:{label:{type:"string",label:"Label"},title:{type:"string",label:"Title"},text:{type:"string",label:"Text"}}}}}},about:{title:"About Relay",description:"Default Relay about page",layout:gkw,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},ykw=[{id:"home",path:"/",title:"Relay",description:"Collaborative team memory and synthesis brain",layout:"default",navigation:{show:!0,label:"Home",slot:"secondary",priority:10},sections:[{id:"diagram",template:"relay-site:home-diagram"}]},{id:"about",path:"/about",title:"About Relay",description:"What Relay is designed to do",layout:"default",navigation:{show:!0,label:"About",slot:"primary",priority:20},sections:[{id:"about",template:"relay-site:about",content:Jkw}]}],y62=ct0({packageName:"@brains/relay/site",themeProfile:"studio",layout:kkw,routes:ykw,runtime:{contentNamespace:"relay-site",templates:{"home-diagram":Rkw},dataSources:[new fe0]}});var E62={name:"@brains/relay",version:"0.2.0-alpha.142",description:"Relay brain model \u2014 collaborative knowledge management",dependencies:{"@brains/a2a":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/app":"workspace:*","@brains/assessment":"workspace:*","@brains/auth-service":"workspace:*","@brains/cms":"workspace:*","@brains/content-formatters":"workspace:*","@brains/conversation-memory":"workspace:*","@brains/dashboard":"workspace:*","@brains/decks":"workspace:*","@brains/directory-sync":"workspace:*","@brains/discord":"workspace:*","@brains/doc":"workspace:*","@brains/email-resend":"workspace:*","@brains/image-plugin":"workspace:*","@brains/link":"workspace:*","@brains/mcp":"workspace:*","@brains/note":"workspace:*","@brains/notifications":"workspace:*","@brains/plugins":"workspace:*","@brains/prompt":"workspace:*","@brains/rizom-ecosystem":"workspace:*","@brains/site-builder-plugin":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-content":"workspace:*","@brains/site-info":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/topics":"workspace:*","@brains/utils":"workspace:*","@brains/web-chat":"workspace:*","@brains/webserver":"workspace:*","@rizom/site-rizom":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/ai-evaluation":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},files:["src","brain.eval.yaml","env.schema.template"],private:!0,scripts:{"build:web-chat":"turbo run build --filter=@brains/web-chat",eval:"brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix","start:core":"bun run build:web-chat && cd test-apps/core && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","start:default":"bun run build:web-chat && cd test-apps/default && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","start:docs":"bun run build:web-chat && cd test-apps/docs && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","start:full":"bun run build:web-chat && cd test-apps/full && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var T62=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],S62=[...T62,"image","site-info","site-content","site-builder"],Skw=[...S62,"docs","decks"],mkw=["Relay is a collaborative team-memory and synthesis brain. Optimize for capturing shared context, finding what the team already knows, summarizing cross-source evidence, and coordinating with peer brains.","Relay is not Rover-for-teams: do not default to personal branding, blog publishing, newsletters, social media, portfolio, or marketing workflows unless the installed plugins and user request explicitly support them."],ukw=UI({name:"relay",version:E62.version,model:"gpt-5.4-mini",site:y62,theme:my,presets:{core:T62,default:S62,full:Skw},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:mkw,capabilities:[["prompt",bP,void 0],["note",QP,{}],["link",BP,{}],["image",Mc,void 0],["topics",dY0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",we0,{memoryVisibility:"shared"}],["docs",yr,void 0],["decks",hr,void 0],["agents",tX0,void 0],["assessment",ZZ0,void 0],["auth-service",Vp,void 0],["notifications",m60,void 0],["email-resend",T90,void 0],["cms",KP,{}],["dashboard",hF,void 0],["directory-sync",fj,{seedContent:!0,seedContentPath:Tkw(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",As,{definitions:g62}],["rizom-ecosystem",VP,void 0],["site-info",lj,void 0],["site-builder",cj,{}]],interfaces:[["mcp",oI,()=>({})],["discord",CJ,()=>({captureUrls:!0})],["a2a",xC,()=>({})],["webserver",mJ,()=>({})],["web-chat",OC,()=>({})]],permissions:{rules:[{pattern:"cli:*",level:"anchor"},{pattern:"mcp:stdio",level:"anchor"},{pattern:"mcp:http",level:"anchor"},{pattern:"discord:*",level:"public"},{pattern:"web-chat:*",level:"anchor"}],entityActions:{note:{create:"trusted",update:"trusted",delete:"anchor"},link:{create:"trusted",update:"trusted",delete:"anchor"},doc:{create:"trusted",update:"trusted",delete:"anchor"},deck:{create:"trusted",update:"trusted",delete:"anchor"},decision:{create:"trusted",update:"trusted",delete:"anchor"},"action-item":{create:"trusted",update:"trusted",delete:"anchor"},image:{create:"trusted",update:"trusted",delete:"anchor"}}},deployment:{cdn:{enabled:!0,provider:"bunny"}}}),m62=ukw;import{readFileSync as LPw}from"fs";import{join as kPw}from"path";import{execSync as _Pw}from"child_process";import{parseArgs as pkw}from"util";var ikw={model:{type:"string"},domain:{type:"string"},"content-repo":{type:"string"},backend:{type:"string"},"push-to":{type:"string"},"ai-api-key":{type:"string"},"no-interactive":{type:"boolean"},preview:{type:"boolean"},deploy:{type:"boolean"},regen:{type:"boolean"},all:{type:"boolean"},only:{type:"string"},"dry-run":{type:"boolean"},"startup-check":{type:"boolean"},"storage-dir":{type:"string"},yes:{type:"boolean"},remote:{type:"string"},token:{type:"string"},outputDir:{type:"string"},help:{type:"boolean",short:"h"},version:{type:"boolean",short:"v"}};function hU(A,Q){let w=A[Q];return typeof w==="string"?w:void 0}function TF(A,Q){let w=A[Q];return typeof w==="boolean"?w:void 0}function u62(A){let{values:Q,positionals:w}=pkw({args:A,options:ikw,allowPositionals:!0,strict:!1});if(Q.help)return{command:"help",args:[],flags:{help:!0}};if(Q.version)return{command:"version",args:[],flags:{version:!0}};return{command:w[0]??"help",args:w.slice(1),flags:{model:hU(Q,"model"),domain:hU(Q,"domain"),"content-repo":hU(Q,"content-repo"),backend:hU(Q,"backend"),"push-to":hU(Q,"push-to"),"ai-api-key":hU(Q,"ai-api-key"),"no-interactive":TF(Q,"no-interactive"),preview:TF(Q,"preview"),deploy:TF(Q,"deploy"),regen:TF(Q,"regen"),all:TF(Q,"all"),only:hU(Q,"only"),"dry-run":TF(Q,"dry-run"),"startup-check":TF(Q,"startup-check"),"storage-dir":hU(Q,"storage-dir"),yes:TF(Q,"yes"),remote:hU(Q,"remote"),token:hU(Q,"token"),outputDir:hU(Q,"outputDir")}}}Zs();import{mkdirSync as UPw}from"fs";import{join as DPw}from"path";import{execSync as GPw}from"child_process";var dZ0={name:"@rizom/brain",version:"0.2.0-alpha.142",description:"Brain runtime + CLI \u2014 scaffold, run, and manage AI brain instances",keywords:["brain","ai","cli","mcp","agent","personal-ai","knowledge-management"],license:"Apache-2.0",author:"Yeehaa <yeehaa@rizom.ai> (https://rizom.ai)",bin:{brain:"./dist/brain.js"},bugs:"https://github.com/rizom-ai/brains/issues",dependencies:{"@clack/prompts":"^1.5.1","@modelcontextprotocol/sdk":"^1.29.0","@tailwindcss/postcss":"^4.3.1","@tailwindcss/typography":"^0.5.20",postcss:"^8.5.15",preact:"^10.27.2","preact-render-to-string":"^6.7.0",tailwindcss:"^4.3.1",zod:"^4.1.8"},devDependencies:{"@brains/app":"workspace:*","@brains/build-tools":"workspace:*","@brains/content-formatters":"workspace:*","@brains/deploy-support":"workspace:*","@brains/eslint-config":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@brains/ranger":"workspace:*","@brains/relay":"workspace:*","@brains/rover":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-default":"workspace:*","@brains/site-personal":"workspace:*","@brains/site-professional":"workspace:*","@brains/theme-default":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/typescript-config":"workspace:*","@brains/utils":"workspace:*","@types/bun":"^1.3.14",rollup:"^4.62.0","rollup-plugin-dts":"^6.4.1",typescript:"^6.0.3"},engines:{bun:">=1.3.3"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./cli":"./dist/brain.js","./plugins":{types:"./dist/plugins.d.ts",import:"./dist/plugins.js"},"./entities":{types:"./dist/entities.d.ts",import:"./dist/entities.js"},"./services":{types:"./dist/services.d.ts",import:"./dist/services.js"},"./interfaces":{types:"./dist/interfaces.d.ts",import:"./dist/interfaces.js"},"./templates":{types:"./dist/templates.d.ts",import:"./dist/templates.js"},"./site":{types:"./dist/site.d.ts",import:"./dist/site.js"},"./themes":{types:"./dist/themes.d.ts",import:"./dist/themes.js"},"./deploy":{types:"./dist/deploy.d.ts",import:"./dist/deploy.js"},"./tsconfig.instance.json":"./tsconfig.instance.json"},files:["dist","templates","tsconfig.instance.json"],homepage:"https://github.com/rizom-ai/brains/tree/main/packages/brain-cli#readme",optionalDependencies:{"@bitwarden/sdk-napi":"^1.0.0","@libsql/client":"^0.17.4","@tailwindcss/oxide":"^4.1.4",lightningcss:"^1.29.2","playwright-core":"^1.61.0","react-devtools-core":"^7.0.1",sharp:"^0.35.1"},publishConfig:{access:"public"},repository:{type:"git",url:"https://github.com/rizom-ai/brains.git",directory:"packages/brain-cli"},scripts:{build:"bun scripts/build.ts","dev:start":"bun scripts/build.ts && bun dist/brain.js start",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",prepublishOnly:"bun scripts/build.ts",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};import{mkdirSync as wB2,writeFileSync as Hs,chmodSync as Ks,existsSync as ze0,readFileSync as qe0}from"fs";import{basename as be0,dirname as Ve0,join as E$,resolve as N_w}from"path";import{fileURLToPath as j_w}from"url";var c62=`ARG BUN_VERSION=1.3.10
11857
+ `)}})}),Q.eval.registerHandler("decideProjection",async($)=>{let f=aLw.parse($),Y=tt0(f.messages,f.conversationId),X=f.existingSummary?J62({conversationId:f.conversationId,content:f.existingSummary,messageCount:f.existingMessageCount,projectionVersion:B.projectionVersion,visibility:B.memoryVisibility}):null;return new EF(Q,w,B).decideProjection(Y,X)}),Q.eval.registerHandler("retrieveMemory",async($)=>{let f=oLw.parse($),Y=f.memory?F62(Q,f.memory):Q;return new oy(Y).retrieve(f)}),Q.eval.registerHandler("buildAgentContext",async($)=>{let f=sLw.parse($),Y=f.memory?F62(Q,f.memory):Q;return cZ0(Y,f)}),Q.eval.registerHandler("projectMessages",async($)=>{let f=dLw.parse($),Y=tt0(f.messages,f.conversationId),X=tLw({conversationId:f.conversationId,interfaceType:f.interfaceType,channelId:f.channelId,channelName:f.channelName,messages:Y}),W=f.existingSummary?J62({conversationId:f.conversationId,content:f.existingSummary,messageCount:f.existingMessageCount,projectionVersion:B.projectionVersion,visibility:B.memoryVisibility}):null,H=[],K=[],U=eLw({context:Q,conversation:X,messages:Y,existing:W,upserted:H,deleted:K,projectionDecision:f.projectionDecision});return{result:await new EF(U,w,B).projectConversation(f.conversationId),summaries:H.filter((b)=>b.entityType==="summary"),decisions:H.filter((b)=>b.entityType==="decision"),actionItems:H.filter((b)=>b.entityType==="action-item"),deleted:K}}),Q.eval.registerHandler("projectConversation",async($)=>{let f=iLw.parse($);return new EF(Q,w,B).projectConversation(f.conversationId)})}function J62(A){return{id:A.conversationId,entityType:"summary",content:A.content,contentHash:"eval-existing-summary",visibility:A.visibility,created:"2026-01-01T00:00:00.000Z",updated:"2026-01-01T00:00:00.000Z",metadata:{conversationId:A.conversationId,channelId:"eval-channel",interfaceType:"eval",messageCount:A.messageCount,entryCount:1,sourceHash:"eval-source-hash",projectionVersion:A.projectionVersion}}}function tt0(A,Q){return A.map((w,B)=>{let $=w.timestamp??new Date(Date.UTC(2026,0,1,0,B)).toISOString();return{id:`eval-message-${B+1}`,conversationId:Q,role:w.role,content:w.content,timestamp:$,metadata:{...w.actor?{actor:w.actor}:{},...w.source?{source:w.source}:{}}}})}function tLw(A){let Q=A.messages[0],w=A.messages[A.messages.length-1],B=Q?.timestamp??"2026-01-01T00:00:00.000Z",$=w?.timestamp??B;return{id:A.conversationId,sessionId:A.conversationId,interfaceType:A.interfaceType,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},startedAt:B,lastActiveAt:$,createdAt:B,updatedAt:$,metadata:{}}}function eLw(A){let Q=vU(A.conversation);return{...A.context,spaces:[Q],conversations:{...A.context.conversations,get:async()=>A.conversation,getMessages:async()=>A.messages},ai:{...A.context.ai,generateObject:async()=>({object:{decision:A.projectionDecision,rationale:"Forced by eval input"}})},entityService:{...A.context.entityService,getEntity:async({entityType:w})=>w==="summary"?A.existing:null,listEntities:async()=>[],deleteEntity:async(w)=>{return A.deleted.push(w),!0},upsertEntity:async({entity:w})=>{return A.upserted.push(w),{entityId:w.id,jobId:"eval-upsert",created:!0,skipped:!1}}}}}function F62(A,Q){let w=Q.map(Akw),B=w.map(($,f)=>({entity:$,score:Q[f]?.score??1,excerpt:Q[f]?.excerpt??ry($)}));return{...A,entityService:{...A.entityService,search:async()=>B,listEntities:async({entityType:$})=>w.filter((f)=>f.entityType===$)}}}function Akw(A){if(A.entityType==="summary")return Qkw(A);if(A.entityType==="decision")return wkw(A);return Bkw(A)}function Ae0(A){let Q=A.updated??"2026-01-01T00:00:00.000Z";return{id:A.id,content:A.content,contentHash:w6(A.content),visibility:A.visibility,created:Q,updated:Q}}function Qkw(A){return{...Ae0(A),entityType:"summary",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,messageCount:3,entryCount:1,sourceHash:`source-${A.id}`,projectionVersion:1,...A.participants?{participants:A.participants}:{}}}}function wkw(A){return{...Ae0(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:vU(A),timeRange:{start:"2026-01-01T00:00:00.000Z",end:"2026-01-01T00:01:00.000Z"},sourceSummaryId:A.conversationId,sourceMessageCount:2,projectionVersion:1,status:A.status==="superseded"?"superseded":"active",...A.decidedBy?{decidedBy:A.decidedBy}:{},...A.mentionedBy?{mentionedBy:A.mentionedBy}:{}}}}function Bkw(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...Ae0(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:vU(A),timeRange:{start:"2026-01-01T00:00:00.000Z",end:"2026-01-01T00:01:00.000Z"},sourceSummaryId:A.conversationId,sourceMessageCount:2,projectionVersion:1,status:Q,...A.assignedTo?{assignedTo:A.assignedTo}:{},...A.requestedBy?{requestedBy:A.requestedBy}:{}}}}var j62={name:"@brains/conversation-memory",version:"0.2.0-alpha.143",description:"Plugin for deriving durable conversation memory",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/conversation-service":"workspace:*","@brains/dashboard":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/node":"^20.19.43",eslint:"^10.5.0",typescript:"^6.0.3"},exports:{".":"./src/index.ts"},main:"./src/index.ts",private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var fkw=new OH,Ykw=new cy,Xkw=new ly,Zkw=Z.object({conversationId:Z.string()});class Qe0 extends nQ{entityType=N8;schema=ws;adapter=fkw;constructor(A={}){super(RZ0,j62,A,nt0)}getConfig(){return this.config}getTemplates(){return{"summary-list":sw2,"summary-detail":aw2,"ai-response":tw2}}getDataSources(){return[new st0(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:N8,job:{type:mw2,handler:new EZ0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await qk(A,N8,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:lt0,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:RZ0}}},sourceChange:{sourceKind:OS,sourceTypes:[OS],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[vO],jobData:(Q)=>{let{conversationId:w}=this.parseConversationMessagePayload(Q);return{mode:"conversation",conversationId:w,reason:"message-added"}},jobOptions:(Q)=>{let{conversationId:w}=this.parseConversationMessagePayload(Q);return{priority:5,delayMs:this.config.projectionDelayMs,source:lt0,deduplication:"skip",deduplicationKey:`conversation-memory:${w}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${w}`,pluginId:RZ0}}}}}]}parseConversationMessagePayload(A){return Zkw.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:w}=this.parseConversationMessagePayload(Q),B=await A.conversations.get(w);if(!B)return!1;return NP({conversation:B,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(pZ,Bs,Ykw),A.entities.register(MH,$s,Xkw),Q62({context:A,pluginId:this.id}),B62({context:A,pluginId:this.id}),D62({context:A,pluginId:this.id}),q62({context:A,pluginId:this.id,config:this.config}),at0(A),N62({context:A,logger:this.logger,config:this.config})}}function we0(A={}){return new Qe0(A)}wA();N0();N0();o5();var P62=Z.object({label:Z.string(),href:Z.string()}),M62=Z.object({label:Z.string(),title:Z.string(),detail:Z.string()}),Wkw=Z.object({eyebrow:Z.string(),name:Z.string(),sub:Z.string()}),Hkw=Z.object({tone:Z.enum(["capture","synthesis","share"]),title:Z.string(),text:Z.string()}),Be0=Z.object({captures:Z.number(),links:Z.number(),topics:Z.number(),summaries:Z.number(),peers:Z.number()}),sy=Z.object({eyebrow:Z.string(),headline:Z.string(),intro:Z.string(),primaryCta:P62,secondaryCta:P62,inputs:Z.array(M62).min(1),outputs:Z.array(M62).min(1),core:Wkw,legend:Z.array(Hkw).min(1)}),$e0=sy.extend({counts:Be0}),O62={eyebrow:"A team brain, diagrammed",headline:"Relay sits between the work and the world, and keeps both honest.",intro:"Capture sources flow into a shared brain; the brain organizes, summarizes, and \u2014 selectively \u2014 exposes a public surface. Everything else stays private and operational.",primaryCta:{label:"See it on a real team",href:"#diagram"},secondaryCta:{label:"Read the model",href:"/about"},inputs:[{label:"Source \xB7 chat",title:"Discord",detail:"Shared decisions and field notes captured in flow."},{label:"Source \xB7 agent",title:"MCP / CLI",detail:"Structured captures from tools and assistants."},{label:"Source \xB7 web",title:"Links & docs",detail:"External material indexed with sourceable metadata."}],outputs:[{label:"Surface \xB7 public",title:"Default site",detail:"A small, durable face onto what the team currently knows."},{label:"Surface \xB7 agents",title:"A2A exchange",detail:"Peer brains coordinate over an approved, signed protocol."},{label:"Surface \xB7 query",title:"Team Q&A",detail:"Ask the brain in chat; answers cite the captures behind them."}],core:{eyebrow:"The relay",name:"brain",sub:"capture \u2192 topics \u2192 summaries"},legend:[{tone:"capture",title:"Capture",text:"Anything the team already does that produces a trace \u2014 chat messages, links, deploys, decisions."},{tone:"synthesis",title:"Synthesis",text:"The work the brain does on its own time \u2014 clustering captures into topics, summaries, and durable memory."},{tone:"share",title:"Share",text:"A small, opinionated public surface and an approved agent-to-agent protocol. Most memory stays private."}]},x62=new G6(sy,{title:"Home diagram",mappings:[{key:"eyebrow",label:"Eyebrow",type:"string"},{key:"headline",label:"Headline",type:"string"},{key:"intro",label:"Intro",type:"string"},{key:"primaryCta",label:"Primary CTA",type:"object",children:[{key:"label",label:"Label",type:"string"},{key:"href",label:"Href",type:"string"}]},{key:"secondaryCta",label:"Secondary CTA",type:"object",children:[{key:"label",label:"Label",type:"string"},{key:"href",label:"Href",type:"string"}]},{key:"inputs",label:"Inputs",type:"array",itemType:"object",itemMappings:[{key:"label",label:"Label",type:"string"},{key:"title",label:"Title",type:"string"},{key:"detail",label:"Detail",type:"string"}]},{key:"outputs",label:"Outputs",type:"array",itemType:"object",itemMappings:[{key:"label",label:"Label",type:"string"},{key:"title",label:"Title",type:"string"},{key:"detail",label:"Detail",type:"string"}]},{key:"core",label:"Core",type:"object",children:[{key:"eyebrow",label:"Eyebrow",type:"string"},{key:"name",label:"Name",type:"string"},{key:"sub",label:"Sub",type:"string"}]},{key:"legend",label:"Legend",type:"array",itemType:"object",itemMappings:[{key:"tone",label:"Tone",type:"string"},{key:"title",label:"Title",type:"string"},{key:"text",label:"Text",type:"string"}]}]});function pZ0(A){return x62.parse(A)}function R62(A){return x62.format(A)}N0();var Kkw=Z.looseObject({query:Z.object({routeId:Z.string().default("home"),sectionId:Z.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}),Ukw={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class fe0{id="relay-site:home-counts";name="Relay homepage counts";description="Fetches Relay homepage content and live entity counts for the system diagram";async fetch(A,Q,w){let B=Kkw.parse(A??{}),$=await this.fetchContent(w,B.query.routeId,B.query.sectionId),f=await this.fetchCounts(w);return Q.parse({...$,counts:f})}async fetchContent(A,Q,w){let B=await A.entityService.getEntity({entityType:"site-content",id:`${Q}:${w}`});if(!B?.content)return O62;return sy.parse(pZ0(B.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(Ukw).map(async([w,B])=>[w,await this.countOrZero(A,B)]));return Be0.parse(Object.fromEntries(Q))}async countOrZero(A,Q){if(!A.entityService.hasEntityType(Q))return 0;try{return await A.entityService.countEntities({entityType:Q})}catch{return 0}}}import{jsxDEV as D1}from"preact/jsx-dev-runtime";var v62=Z.object({label:Z.string(),href:Z.string()}),Dkw=Z.object({label:Z.string(),value:Z.string(),note:Z.string()}),Gkw=Z.object({eyebrow:Z.string(),headline:Z.string(),intro:Z.string(),primaryCta:v62,secondaryCta:v62,signals:Z.array(Dkw)}),zkw=Z.object({phase:Z.string(),title:Z.string(),text:Z.string()}),qkw=Z.object({eyebrow:Z.string(),title:Z.string(),intro:Z.string(),steps:Z.array(zkw)}),bkw=Z.object({label:Z.string(),title:Z.string(),text:Z.string()}),Vkw=Z.object({title:Z.string(),intro:Z.string(),cards:Z.array(bkw)}),Ikw=Z.object({title:Z.string(),intro:Z.string(),points:Z.array(Z.string())}),Jkw={title:"Relay is a collaborative team-memory brain.",intro:"It exists for teams that need to remember together: capturing what happened, summarizing why it matters, and coordinating with trusted peer brains when work crosses boundaries.",points:["Not a personal blog engine or portfolio shell.","Not a marketing automation stack.","A small public face for a larger private knowledge workflow."]},Fkw="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function h62({href:A,label:Q}){return D1("a",{href:A,className:Fkw,children:Q},void 0,!1,void 0,this)}function Lkw({siteInfo:A,children:Q}){let w=[...A.navigation.primary,...A.navigation.secondary],B=A.cta??{buttonText:"Start here",buttonLink:"/about"};return D1(Ty,{children:[D1("nav",{className:"fixed left-0 right-0 top-0 z-[100] flex items-center justify-between border-b border-theme-light bg-nav-fade px-6 py-4 backdrop-blur-[12px] md:px-10 xl:px-20",children:[D1("a",{href:"/",className:"font-nav text-[20px]","aria-label":"Relay home",children:[D1("span",{className:"font-bold text-theme",children:"relay"},void 0,!1,void 0,this),D1("span",{className:"font-bold text-accent",children:"."},void 0,!1,void 0,this),D1("span",{className:"text-theme-muted",children:"brain"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"flex items-center gap-5 md:gap-8",children:[D1("div",{className:"hidden items-center gap-6 md:flex",children:w.map(($)=>D1(h62,{...$},`${$.href}-${$.label}`,!1,void 0,this))},void 0,!1,void 0,this),D1("a",{href:B.buttonLink,className:"rounded-[999px] border border-theme px-4 py-2 font-body text-[13px] font-semibold text-theme transition-colors hover:border-accent hover:text-accent md:px-5",children:B.buttonText},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("main",{children:Q},void 0,!1,void 0,this),D1("footer",{className:"relative z-[1] border-t border-theme-light px-6 py-8 md:px-10 xl:px-20",children:D1("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[D1("div",{children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.22em] text-theme-light",children:A.copyright},void 0,!1,void 0,this),D1("p",{className:"mt-2 max-w-[560px] font-body text-body-xs text-theme-muted",children:A.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"flex flex-wrap items-center gap-5",children:[w.map(($)=>D1(h62,{...$},`footer-${$.href}-${$.label}`,!1,void 0,this)),D1("button",{id:"themeToggle","aria-label":"Toggle light mode",className:"rounded-md border border-theme-light bg-transparent px-2.5 py-1.5 font-body text-label-md text-theme-light transition-colors hover:border-theme hover:text-theme",children:"\u2600 Light"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var kkw=({sections:A,siteInfo:Q})=>D1(Lkw,{siteInfo:Q,children:A},void 0,!1,void 0,this);function _kw({eyebrow:A,headline:Q,intro:w,primaryCta:B,secondaryCta:$,signals:f}){return D1(yF,{className:"min-h-[92vh] pt-[152px] pb-20 md:pt-[190px]",children:D1("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_420px] lg:items-end",children:[D1("div",{children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),D1("h1",{className:"mt-7 max-w-[980px] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),D1("p",{className:"mt-7 max-w-[720px] font-body text-body-lg text-theme-muted",children:w},void 0,!1,void 0,this),D1("div",{className:"mt-10 flex flex-col gap-3 sm:flex-row",children:[D1(kP,{href:B.href,size:"lg",variant:"primary-strong",children:B.label},void 0,!1,void 0,this),D1(kP,{href:$.href,size:"lg",variant:"secondary",children:$.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"rounded-[32px] border border-card-relay-border bg-card-relay-bg p-5 shadow-[0_24px_90px_var(--color-glow-relay)] backdrop-blur-sm",children:[D1("p",{className:"font-label text-label-xs uppercase tracking-[0.24em] text-theme-light",children:"Live relay signals"},void 0,!1,void 0,this),D1("div",{className:"mt-5 grid gap-3",children:f.map((Y)=>D1("div",{className:"rounded-[22px] border border-card-divider bg-bg-muted p-5",children:[D1("div",{className:"flex items-center justify-between gap-4",children:[D1("p",{className:"font-label text-label-xs uppercase tracking-[0.18em] text-secondary",children:Y.label},void 0,!1,void 0,this),D1("span",{className:"h-2 w-2 rounded-full bg-accent shadow-[0_0_22px_var(--color-accent)]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("p",{className:"mt-4 font-display text-display-sm text-theme",children:Y.value},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-body text-body-xs text-theme-muted",children:Y.note},void 0,!1,void 0,this)]},Y.label,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function Nkw({eyebrow:A,title:Q,intro:w,steps:B}){return D1(yF,{id:"operating-loop",className:"py-section",children:[D1("div",{className:"max-w-[840px]",children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-secondary",children:A},void 0,!1,void 0,this),D1("h2",{className:"mt-5 font-display text-display-md text-theme",children:Q},void 0,!1,void 0,this),D1("p",{className:"mt-5 font-body text-body-md text-theme-muted",children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:B.map(($)=>D1("article",{className:"min-h-[300px] rounded-[28px] border border-card-panel-border bg-card-panel-bg p-6",children:[D1("p",{className:"font-label text-label-sm text-accent",children:$.phase},void 0,!1,void 0,this),D1("h3",{className:"mt-16 font-display text-display-sm text-theme",children:$.title},void 0,!1,void 0,this),D1("p",{className:"mt-4 font-body text-body-sm text-theme-muted",children:$.text},void 0,!1,void 0,this)]},$.phase,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function jkw({title:A,intro:Q,cards:w}){return D1(yF,{className:"py-section",children:D1("div",{className:"rounded-[36px] border border-theme-light bg-bg-muted p-6 md:p-10",children:D1("div",{className:"grid gap-8 lg:grid-cols-[360px_1fr]",children:[D1("div",{children:[D1("h2",{className:"font-display text-display-md text-theme",children:A},void 0,!1,void 0,this),D1("p",{className:"mt-5 font-body text-body-md text-theme-muted",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"grid gap-4",children:w.map((B)=>D1("article",{className:"rounded-[24px] border border-card-divider bg-bg-subtle/70 p-5",children:[D1("p",{className:"font-label text-label-xs uppercase tracking-[0.22em] text-accent",children:B.label},void 0,!1,void 0,this),D1("h3",{className:"mt-3 font-nav text-heading-lg text-theme",children:B.title},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-body text-body-sm text-theme-muted",children:B.text},void 0,!1,void 0,this)]},B.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Pkw({title:A,intro:Q,points:w}){return D1(yF,{className:"min-h-[78vh] pt-[150px] pb-section md:pt-[190px]",children:[D1("div",{className:"max-w-[920px]",children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:"Relay model"},void 0,!1,void 0,this),D1("h1",{className:"mt-6 font-display text-display-lg text-theme",children:A},void 0,!1,void 0,this),D1("p",{className:"mt-7 font-body text-body-lg text-theme-muted",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:w.map((B)=>D1("div",{className:"rounded-[24px] border border-card-panel-current-border bg-card-panel-current-bg p-6 font-body text-body-md text-theme",children:B},B,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Mkw=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},Okw=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),Xs=(A,Q,w=`${Q}s`)=>`${Okw(A)} ${A===1?Q:w}`;function xkw({eyebrow:A,headline:Q,intro:w,primaryCta:B,secondaryCta:$,inputs:f,outputs:Y,core:X,legend:W,counts:H}){let K=[{key:"captures",className:"top-[-10px] left-1/2 -translate-x-1/2",label:Xs(H.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:Xs(H.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:Xs(H.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:Xs(H.summaries,"summary","summaries")}];return D1(yF,{className:"pt-[150px] pb-section md:pt-[190px]",id:"diagram",children:[D1("div",{className:"mx-auto max-w-[1040px] text-center",children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),D1("h1",{className:"mx-auto mt-7 max-w-[22ch] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),D1("p",{className:"mx-auto mt-7 max-w-[64ch] font-body text-body-lg text-theme-muted",children:w},void 0,!1,void 0,this),D1("div",{className:"mt-10 flex flex-col justify-center gap-3 sm:flex-row",children:[D1(kP,{href:B.href,size:"lg",variant:"primary-strong",children:B.label},void 0,!1,void 0,this),D1(kP,{href:$.href,size:"lg",variant:"secondary",children:$.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"mx-auto mt-20 max-w-[1020px] rounded-[32px] border border-theme-light bg-[radial-gradient(circle_at_1px_1px,rgb(255_255_255_/_0.05)_1px,transparent_0),linear-gradient(180deg,rgb(255_255_255_/_0.02),transparent)] bg-[length:24px_24px,100%_100%] px-6 py-14",children:[D1("div",{className:"grid items-center gap-8 lg:grid-cols-[1fr_1.4fr_1fr]",children:[D1("div",{className:"flex flex-col gap-3.5",children:f.map((U)=>D1("div",{className:"rounded-2xl border border-card-panel-border border-l-2 border-l-accent bg-card-panel-bg px-4 py-4 text-left backdrop-blur-sm",children:[D1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:U.label},void 0,!1,void 0,this),D1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:U.title},void 0,!1,void 0,this),D1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:U.detail},void 0,!1,void 0,this)]},`${U.label}-${U.title}`,!0,void 0,this))},void 0,!1,void 0,this),D1("div",{className:"relative mx-auto grid aspect-square w-full max-w-[320px] place-items-center rounded-full bg-[radial-gradient(circle_at_center,rgb(232_119_34_/_0.25),transparent_65%)]",children:[D1("div",{className:"absolute inset-0 rounded-full border border-dashed border-accent/30"},void 0,!1,void 0,this),D1("div",{className:"absolute inset-6 animate-spin rounded-full border border-dashed border-secondary/40 [animation-duration:28s]"},void 0,!1,void 0,this),K.map((U)=>D1("span",{className:`absolute whitespace-nowrap rounded-full border border-theme bg-bg px-2.5 py-1 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light ${U.className}`,children:U.label},U.key,!1,void 0,this)),D1("div",{className:"relative z-[1] px-6 text-center",children:[D1("p",{className:"font-label text-[10px] uppercase tracking-[0.28em] text-accent",children:X.eyebrow},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-display text-[36px] leading-none text-theme",children:X.name},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-body text-[13px] text-theme-muted",children:X.sub},void 0,!1,void 0,this),D1("p",{className:"mt-4 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light",children:[Xs(H.links,"link")," indexed"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"flex flex-col gap-3.5",children:Y.map((U)=>D1("div",{className:"rounded-2xl border border-card-panel-border border-r-2 border-r-secondary bg-card-panel-bg px-4 py-4 text-left backdrop-blur-sm",children:[D1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:U.label},void 0,!1,void 0,this),D1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:U.title},void 0,!1,void 0,this),D1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:U.detail},void 0,!1,void 0,this)]},`${U.label}-${U.title}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"mt-14 grid gap-4 border-t border-theme-light pt-8 md:grid-cols-3",children:W.map((U)=>D1("div",{className:"text-left",children:[D1("h2",{className:"font-display text-[16px] font-medium text-theme",children:[D1("span",{className:`mr-2.5 inline-block h-3 w-3 rounded-[3px] align-middle ${Mkw(U.tone)}`},void 0,!1,void 0,this),U.title]},void 0,!0,void 0,this),D1("p",{className:"mt-1.5 font-body text-[13px] leading-[1.6] text-theme-muted",children:U.text},void 0,!1,void 0,this)]},U.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var Rkw=i1({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:$e0,formatter:{parse:(A)=>$e0.parse({...pZ0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>R62(sy.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:xkw}}),vkw=(A)=>_kw(Gkw.parse(A)),hkw=(A)=>Nkw(qkw.parse(A)),Ckw=(A)=>jkw(Vkw.parse(A)),gkw=(A)=>Pkw(Ikw.parse(A)),C62={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},g62={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:vkw,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...C62,label:"Primary CTA"},secondaryCta:{...C62,label:"Secondary CTA"},signals:{type:"array",label:"Signals",minItems:1,items:{type:"object",label:"Signal",fields:{label:{type:"string",label:"Label"},value:{type:"string",label:"Value"},note:{type:"string",label:"Note"}}}}}},"home-loop":{title:"Home operating loop",description:"Relay capture, synthesis, and sharing loop",layout:hkw,fields:{eyebrow:{type:"string",label:"Eyebrow"},title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},steps:{type:"array",label:"Steps",minItems:1,items:{type:"object",label:"Step",fields:{phase:{type:"string",label:"Phase"},title:{type:"string",label:"Title"},text:{type:"string",label:"Text"}}}}}},"home-surface":{title:"Home surface",description:"Relay default template explanation cards",layout:Ckw,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},cards:{type:"array",label:"Cards",minItems:1,items:{type:"object",label:"Card",fields:{label:{type:"string",label:"Label"},title:{type:"string",label:"Title"},text:{type:"string",label:"Text"}}}}}},about:{title:"About Relay",description:"Default Relay about page",layout:gkw,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},ykw=[{id:"home",path:"/",title:"Relay",description:"Collaborative team memory and synthesis brain",layout:"default",navigation:{show:!0,label:"Home",slot:"secondary",priority:10},sections:[{id:"diagram",template:"relay-site:home-diagram"}]},{id:"about",path:"/about",title:"About Relay",description:"What Relay is designed to do",layout:"default",navigation:{show:!0,label:"About",slot:"primary",priority:20},sections:[{id:"about",template:"relay-site:about",content:Jkw}]}],y62=ct0({packageName:"@brains/relay/site",themeProfile:"studio",layout:kkw,routes:ykw,runtime:{contentNamespace:"relay-site",templates:{"home-diagram":Rkw},dataSources:[new fe0]}});var E62={name:"@brains/relay",version:"0.2.0-alpha.143",description:"Relay brain model \u2014 collaborative knowledge management",dependencies:{"@brains/a2a":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/app":"workspace:*","@brains/assessment":"workspace:*","@brains/auth-service":"workspace:*","@brains/cms":"workspace:*","@brains/content-formatters":"workspace:*","@brains/conversation-memory":"workspace:*","@brains/dashboard":"workspace:*","@brains/decks":"workspace:*","@brains/directory-sync":"workspace:*","@brains/discord":"workspace:*","@brains/doc":"workspace:*","@brains/email-resend":"workspace:*","@brains/image-plugin":"workspace:*","@brains/link":"workspace:*","@brains/mcp":"workspace:*","@brains/note":"workspace:*","@brains/notifications":"workspace:*","@brains/plugins":"workspace:*","@brains/prompt":"workspace:*","@brains/rizom-ecosystem":"workspace:*","@brains/site-builder-plugin":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-content":"workspace:*","@brains/site-info":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/topics":"workspace:*","@brains/utils":"workspace:*","@brains/web-chat":"workspace:*","@brains/webserver":"workspace:*","@rizom/site-rizom":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/ai-evaluation":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*",typescript:"^6.0.3"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},files:["src","brain.eval.yaml","env.schema.template"],private:!0,scripts:{"build:web-chat":"turbo run build --filter=@brains/web-chat",eval:"brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix","start:core":"bun run build:web-chat && cd test-apps/core && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","start:default":"bun run build:web-chat && cd test-apps/default && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","start:docs":"bun run build:web-chat && cd test-apps/docs && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","start:full":"bun run build:web-chat && cd test-apps/full && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var T62=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],S62=[...T62,"image","site-info","site-content","site-builder"],Skw=[...S62,"docs","decks"],mkw=["Relay is a collaborative team-memory and synthesis brain. Optimize for capturing shared context, finding what the team already knows, summarizing cross-source evidence, and coordinating with peer brains.","Relay is not Rover-for-teams: do not default to personal branding, blog publishing, newsletters, social media, portfolio, or marketing workflows unless the installed plugins and user request explicitly support them."],ukw=UI({name:"relay",version:E62.version,model:"gpt-5.4-mini",site:y62,theme:my,presets:{core:T62,default:S62,full:Skw},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:mkw,capabilities:[["prompt",bP,void 0],["note",QP,{}],["link",BP,{}],["image",Mc,void 0],["topics",dY0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",we0,{memoryVisibility:"shared"}],["docs",yr,void 0],["decks",hr,void 0],["agents",tX0,void 0],["assessment",ZZ0,void 0],["auth-service",Vp,void 0],["notifications",m60,void 0],["email-resend",T90,void 0],["cms",KP,{}],["dashboard",hF,void 0],["directory-sync",fj,{seedContent:!0,seedContentPath:Tkw(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",As,{definitions:g62}],["rizom-ecosystem",VP,void 0],["site-info",lj,void 0],["site-builder",cj,{}]],interfaces:[["mcp",oI,()=>({})],["discord",CJ,()=>({captureUrls:!0})],["a2a",xC,()=>({})],["webserver",mJ,()=>({})],["web-chat",OC,()=>({})]],permissions:{rules:[{pattern:"cli:*",level:"anchor"},{pattern:"mcp:stdio",level:"anchor"},{pattern:"mcp:http",level:"anchor"},{pattern:"discord:*",level:"public"},{pattern:"web-chat:*",level:"anchor"}],entityActions:{note:{create:"trusted",update:"trusted",delete:"anchor"},link:{create:"trusted",update:"trusted",delete:"anchor"},doc:{create:"trusted",update:"trusted",delete:"anchor"},deck:{create:"trusted",update:"trusted",delete:"anchor"},decision:{create:"trusted",update:"trusted",delete:"anchor"},"action-item":{create:"trusted",update:"trusted",delete:"anchor"},image:{create:"trusted",update:"trusted",delete:"anchor"}}},deployment:{cdn:{enabled:!0,provider:"bunny"}}}),m62=ukw;import{readFileSync as LPw}from"fs";import{join as kPw}from"path";import{execSync as _Pw}from"child_process";import{parseArgs as pkw}from"util";var ikw={model:{type:"string"},domain:{type:"string"},"content-repo":{type:"string"},backend:{type:"string"},"push-to":{type:"string"},"ai-api-key":{type:"string"},"no-interactive":{type:"boolean"},preview:{type:"boolean"},deploy:{type:"boolean"},regen:{type:"boolean"},all:{type:"boolean"},only:{type:"string"},"dry-run":{type:"boolean"},"startup-check":{type:"boolean"},"storage-dir":{type:"string"},yes:{type:"boolean"},remote:{type:"string"},token:{type:"string"},outputDir:{type:"string"},help:{type:"boolean",short:"h"},version:{type:"boolean",short:"v"}};function hU(A,Q){let w=A[Q];return typeof w==="string"?w:void 0}function TF(A,Q){let w=A[Q];return typeof w==="boolean"?w:void 0}function u62(A){let{values:Q,positionals:w}=pkw({args:A,options:ikw,allowPositionals:!0,strict:!1});if(Q.help)return{command:"help",args:[],flags:{help:!0}};if(Q.version)return{command:"version",args:[],flags:{version:!0}};return{command:w[0]??"help",args:w.slice(1),flags:{model:hU(Q,"model"),domain:hU(Q,"domain"),"content-repo":hU(Q,"content-repo"),backend:hU(Q,"backend"),"push-to":hU(Q,"push-to"),"ai-api-key":hU(Q,"ai-api-key"),"no-interactive":TF(Q,"no-interactive"),preview:TF(Q,"preview"),deploy:TF(Q,"deploy"),regen:TF(Q,"regen"),all:TF(Q,"all"),only:hU(Q,"only"),"dry-run":TF(Q,"dry-run"),"startup-check":TF(Q,"startup-check"),"storage-dir":hU(Q,"storage-dir"),yes:TF(Q,"yes"),remote:hU(Q,"remote"),token:hU(Q,"token"),outputDir:hU(Q,"outputDir")}}}Zs();import{mkdirSync as UPw}from"fs";import{join as DPw}from"path";import{execSync as GPw}from"child_process";var dZ0={name:"@rizom/brain",version:"0.2.0-alpha.143",description:"Brain runtime + CLI \u2014 scaffold, run, and manage AI brain instances",keywords:["brain","ai","cli","mcp","agent","personal-ai","knowledge-management"],license:"Apache-2.0",author:"Yeehaa <yeehaa@rizom.ai> (https://rizom.ai)",bin:{brain:"./dist/brain.js"},bugs:"https://github.com/rizom-ai/brains/issues",dependencies:{"@clack/prompts":"^1.5.1","@modelcontextprotocol/sdk":"^1.29.0","@tailwindcss/postcss":"^4.3.1","@tailwindcss/typography":"^0.5.20",postcss:"^8.5.15",preact:"^10.27.2","preact-render-to-string":"^6.7.0",tailwindcss:"^4.3.1",zod:"^4.1.8"},devDependencies:{"@brains/app":"workspace:*","@brains/build-tools":"workspace:*","@brains/content-formatters":"workspace:*","@brains/deploy-support":"workspace:*","@brains/eslint-config":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@brains/ranger":"workspace:*","@brains/relay":"workspace:*","@brains/rover":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-default":"workspace:*","@brains/site-personal":"workspace:*","@brains/site-professional":"workspace:*","@brains/theme-default":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/typescript-config":"workspace:*","@brains/utils":"workspace:*","@types/bun":"^1.3.14",rollup:"^4.62.0","rollup-plugin-dts":"^6.4.1",typescript:"^6.0.3"},engines:{bun:">=1.3.3"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./cli":"./dist/brain.js","./plugins":{types:"./dist/plugins.d.ts",import:"./dist/plugins.js"},"./entities":{types:"./dist/entities.d.ts",import:"./dist/entities.js"},"./services":{types:"./dist/services.d.ts",import:"./dist/services.js"},"./interfaces":{types:"./dist/interfaces.d.ts",import:"./dist/interfaces.js"},"./templates":{types:"./dist/templates.d.ts",import:"./dist/templates.js"},"./site":{types:"./dist/site.d.ts",import:"./dist/site.js"},"./themes":{types:"./dist/themes.d.ts",import:"./dist/themes.js"},"./deploy":{types:"./dist/deploy.d.ts",import:"./dist/deploy.js"},"./tsconfig.instance.json":"./tsconfig.instance.json"},files:["dist","templates","tsconfig.instance.json"],homepage:"https://github.com/rizom-ai/brains/tree/main/packages/brain-cli#readme",optionalDependencies:{"@bitwarden/sdk-napi":"^1.0.0","@libsql/client":"^0.17.4","@tailwindcss/oxide":"^4.1.4",lightningcss:"^1.29.2","playwright-core":"^1.61.0","react-devtools-core":"^7.0.1",sharp:"^0.35.1"},publishConfig:{access:"public"},repository:{type:"git",url:"https://github.com/rizom-ai/brains.git",directory:"packages/brain-cli"},scripts:{build:"bun scripts/build.ts","dev:start":"bun scripts/build.ts && bun dist/brain.js start",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",prepublishOnly:"bun scripts/build.ts",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};import{mkdirSync as wB2,writeFileSync as Hs,chmodSync as Ks,existsSync as ze0,readFileSync as qe0}from"fs";import{basename as be0,dirname as Ve0,join as E$,resolve as N_w}from"path";import{fileURLToPath as j_w}from"url";var c62=`ARG BUN_VERSION=1.3.10
11858
11858
  FROM oven/bun:\${BUN_VERSION}-slim AS runtime
11859
11859
 
11860
11860
  WORKDIR /app