@rizom/brain 0.2.0-alpha.133 → 0.2.0-alpha.134

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
@@ -324,7 +324,7 @@ ${A.map((w)=>{return`- ${[w.entityType!==void 0?`entityType: ${w.entityType}`:vo
324
324
 
325
325
  `),D=B.filter((Y)=>Y.kind==="file");if(D.length===0)return f;return[...f.length>0?[{type:"text",text:f}]:[],...D.map((Y)=>({type:"file",data:Y.data,mediaType:Y.mediaType,filename:Y.filename}))]}function hO2(A){return`User uploaded a file "${A.filename}":
326
326
 
327
- ${A.content}`}function vO2(A,Q,w){let B=A.map(f3A).filter(fb0),$=Db0([...Q,...B]).map(CO2),f=w?["Available system_create candidate for saving the prior assistant response (call without confirmed to request confirmation):",`{ entityType: "note", source: { kind: "prior-response", messageId: "${w.messageId}" } }`].join(" "):"";if($.length===0)return f;return['Available upload refs from this conversation. Refs are ordered newest-first. Treat this as structured candidate data; resolve any user reference to a specific upload in typed tool arguments, or ask a clarification if the candidates are insufficient. For phrases like "the uploaded image" or "the uploaded PDF" without a filename, use the newest ref matching that media type; do not ask for clarification just because older uploads exist. Describe, summarize, analyze, or discuss uploads directly from the file bytes as read-only chat responses; do not call system_create unless the user explicitly asks to save, import, preserve, or create an entity. Upload candidates are file bytes; previous assistant answers are saved separately. Use system_create source.kind upload with transform "preserve" for preserving raw file bytes as a document/image, or transform "extract-markdown" for extracting/importing upload text as a note. Choose exactly one transform for the user request.',f,...$].filter((Y)=>Y.length>0).join(`
327
+ ${A.content}`}function vO2(A,Q,w){let B=A.map(f3A).filter(fb0),$=Db0([...Q,...B]).map(CO2),f=w?["Available system_create candidate for saving the prior assistant response (call without confirmed to request confirmation):",`{ entityType: "note", source: { kind: "prior-response", messageId: "${w.messageId}" } }`].join(" "):"";if($.length===0)return f;return['Available upload refs from this conversation. Refs are ordered newest-first. Treat this as structured candidate data; resolve any user reference to a specific upload in typed tool arguments, or ask a clarification if the candidates are insufficient. For phrases like "the uploaded image" or "the uploaded PDF" without a filename, use the newest ref matching that media type; do not ask for clarification just because older uploads exist. Describe, summarize, analyze, or discuss uploads directly from the file bytes as read-only chat responses; do not call system_create unless the user explicitly asks to save, import, preserve, or create an entity. In read-only upload summaries, answer the request directly and do not offer to save/import/create unless asked. Upload candidates are file bytes; previous assistant answers are saved separately. If the user says "save it" after your summary/answer about an upload, save the prior assistant response as a note with source.kind "prior-response" unless they explicitly ask to save the uploaded file/document itself. Use system_create source.kind upload with transform "preserve" for preserving raw file bytes as a document/image, or transform "extract-markdown" for extracting/importing upload text as a note. Choose exactly one transform for the user request.',f,...$].filter((Y)=>Y.length>0).join(`
328
328
  `)}function CO2(A){return[`- ${A.filename}`,`upload: { kind: "${A.source.kind}", id: "${A.source.id}" }`,`mediaType: ${A.mediaType}`].join("; ")}function Yb0(A){if(A===void 0)return;return A.length===0?yO2():EO2(A)}function yO2(){return"No relevant conversation memory was retrieved for this turn. If the user asks about conversation memory available in this turn, say none was retrieved rather than inferring from general instructions or other background knowledge."}function EO2(A){return["Relevant conversation memory retrieved for this turn.",'Use it only when it helps answer the user. If the user asks what conversation memory says, explicitly ground the answer in the retrieved memory (for example, "According to conversation memory...") rather than general background knowledge. Preserve source/provenance when referencing memory. Ignore unrelated memory; when memory conflicts, prefer the most specific or newest source and mention uncertainty if the conflict remains unresolved.',"",A.map((w,B)=>gO2(w,B)).join(`
329
329
 
330
330
  `)].join(`
@@ -383,22 +383,22 @@ ${w.join(`
383
383
 
384
384
  ### Retrieved Conversation Memory (CONTEXT)
385
385
 
386
- ${f}`:"")}function Kb0(A,Q,w,B){return async($,f)=>{if(B){let D={toolName:A,args:$,conversationId:w.conversationId,interfaceType:w.interfaceType,...w.channelId!==void 0&&{channelId:w.channelId},...w.channelName!==void 0&&{channelName:w.channelName},...f?.toolCallId!==void 0&&{toolCallId:f.toolCallId}};await B.emit("tool:invoking",D)}try{let D=f?await Q($,f):await Q($);if(B){let Y={toolName:A,conversationId:w.conversationId,interfaceType:w.interfaceType,...w.channelId!==void 0&&{channelId:w.channelId},...w.channelName!==void 0&&{channelName:w.channelName},...f?.toolCallId!==void 0&&{toolCallId:f.toolCallId}};await B.emit("tool:completed",Y)}return D}catch(D){if(B){let Y={toolName:A,error:vA(D),conversationId:w.conversationId,interfaceType:w.interfaceType,...w.channelId!==void 0&&{channelId:w.channelId},...w.channelName!==void 0&&{channelName:w.channelName},...f?.toolCallId!==void 0&&{toolCallId:f.toolCallId}};await B.emit("tool:failed",Y)}throw D}}}function Ub0(A,Q="brain-agent"){return{emit:async(w,B)=>{await A.send({type:w,payload:B,sender:Q,broadcast:!0}).catch(()=>{return})}}}var N10=i(()=>{Z0()});function $x2(A,Q={}){return Object.fromEntries(Object.entries(A).filter(([w])=>{if(Qx2.has(w))return!1;if(Q.toolName!=="system_create")return!0;return!wx2.has(w)}))}function fx2(A){let Q=Bx2.safeParse(A);if(!Q.success)return{type:"json",value:q3A(A)};let{attachment:w}=Q.data.data,B={mediaType:w.mediaType,...w.filename!==void 0?{filename:w.filename}:{},...w.sizeBytes!==void 0?{sizeBytes:w.sizeBytes}:{},...w.source!==void 0?{source:w.source}:{}};return{type:"json",value:q3A({...Q.data,data:{...Q.data.data,attachment:B,artifactCard:{rendered:!0,message:"The UI has rendered this artifact as an attachment card with Open and Download controls. Do not print raw attachment URLs in the assistant response."}}})}}function Dx2(A){if(typeof A!=="object"||A===null||Array.isArray(A))return A;if(A.success!==!0)return A;return{...A,cached:!0}}function q3A(A){if(A===void 0)return null;return Gb0.parse(JSON.parse(JSON.stringify(A)))}function zb0(A,Q,w){let B={},$=new Map;for(let f of A){let D=Kb0(f.name,async(Y,X)=>{let H={interfaceType:Q.interfaceType,userId:"agent-user",conversationId:Q.conversationId,...Q.channelId&&{channelId:Q.channelId},...X?.toolCallId&&{toolCallId:X.toolCallId},...Q.channelName&&{channelName:Q.channelName},...Q.userPermissionLevel&&{userPermissionLevel:Q.userPermissionLevel}};if(f.sideEffects!=="none"){if(f.sideEffects==="writes"||f.sideEffects==="external")$.clear();return f.handler(Y,H)}let W=`${f.name}:${JSON.stringify(Y)}`;if($.has(W))return Dx2($.get(W));let Z=await f.handler(Y,H);return $.set(W,Z),Z},Q,w);B[f.name]=IV0({description:f.description,inputSchema:K.object($x2(f.inputSchema,{toolName:f.name,...Q.enableCreateUpload!==void 0&&{enableCreateUpload:Q.enableCreateUpload},...Q.enableCreateTransform!==void 0&&{enableCreateTransform:Q.enableCreateTransform}})),execute:D,toModelOutput:({output:Y})=>fx2(Y)})}return B}var Qx2,wx2,Gb0,Bx2;var F3A=i(()=>{ux();Z0();N10();Qx2=new Set(["confirmed","confirmationToken","contentHash"]),wx2=new Set(["content","prompt","url","from","upload","transform","sourceAttachment"]),Gb0=K.lazy(()=>K.union([K.null(),K.string(),K.number(),K.boolean(),K.array(Gb0),K.record(Gb0)])),Bx2=K.object({success:K.literal(!0),data:K.object({documentId:K.string().min(1).optional(),entityId:K.string().min(1).optional(),attachment:K.object({mediaType:K.string().min(1),url:K.string().min(1),downloadUrl:K.string().min(1).optional(),previewUrl:K.string().min(1).optional(),filename:K.string().min(1).optional(),sizeBytes:K.number().nonnegative().optional(),source:K.object({entityType:K.string().optional(),entityId:K.string().optional(),attachmentType:K.string().optional()}).optional()}).passthrough()}).passthrough()}).passthrough()});function Xx2(A,Q){return A}function Hx2(A){return A.steps.at(-1)?.toolResults?.some((w)=>YN.safeParse(w.output).success||w.toolName==="playbook_start")??!1}function qb0(A){let{model:Q,modelId:w,webSearch:B,temperature:$,maxTokens:f,messageBus:D}=A,Y=YUA(w),X=Ub0(D);return function(W){let Z=zb0(W.tools,{conversationId:"",interfaceType:"agent"},X);return new AUA({model:Q,callOptionsSchema:Yx2,prepareCall:({options:G,...F})=>{let V=G.disableTools?[]:Xx2(W.getToolsForPermission(G.userPermissionLevel),G),b=V.map((N)=>N.name),L=zb0(V,{conversationId:G.conversationId,channelId:G.channelId,channelName:G.channelName,interfaceType:G.interfaceType,userPermissionLevel:G.userPermissionLevel,enableCreateUpload:G.enableCreateUpload,enableCreateTransform:G.enableCreateTransform},X);return{...F,instructions:z3A(W.identity,G.userPermissionLevel,W.pluginInstructions,W.profile,W.agentInstructions,G.agentContextInstructions),tools:L,activeTools:b,...$!==void 0&&Y&&{temperature:$},...f!==void 0&&{maxTokens:f},...B&&{providerOptions:{anthropic:{webSearch:!0}}}}},tools:Z,stopWhen:[Hx2,rm(W.stepLimit??10)]})}}var Yx2;var V3A=i(()=>{ux();Z0();k9();lx();N10();F3A();Yx2=K.object({userPermissionLevel:K.enum(["anchor","trusted","public"]),conversationId:K.string(),channelId:K.string().optional(),channelName:K.string().optional(),interfaceType:K.string(),agentContextInstructions:K.string().optional(),disableTools:K.boolean().optional(),enableCreateUpload:K.boolean().optional(),enableCreateTransform:K.boolean().optional(),hasPriorResponseCandidate:K.boolean().optional()})});var j10=i(()=>{izA();lx();dzA();G3A();Wb0();V3A();N10()});function b3A(A){return{...A,...A.source!==void 0&&{source:I3A(A.source)},...A.target!==void 0&&{target:I3A(A.target)}}}function I3A(A){if(A instanceof RegExp)return A;if(!A.includes("*"))return A;let Q=A.split("*").map((w)=>w.replace(/[.+?^${}()|[\]\\]/g,"\\$&")).join(".*");return new RegExp(`^${Q}$`)}function L3A(A,Q){if(!Q)return!0;if(!J3A(A.source,Q.source))return!1;if(!J3A(A.target,Q.target,!0))return!1;if(!Wx2(A.metadata,Q.metadata))return!1;return Q.predicate?Q.predicate(A):!0}function J3A(A,Q,w=!1){if(!Q)return!0;if(w&&!A)return!1;return Zx2(A,Q)}function Wx2(A,Q){if(!Q)return!0;if(!A)return!1;return Object.entries(Q).every(([w,B])=>A[w]===B)}function Zx2(A,Q){if(!A)return!1;if(Q instanceof RegExp){Q.lastIndex=0;let w=Q.test(A);return Q.lastIndex=0,w}return A===Q}var M10,N3A;var Fb0=i(()=>{Z0();M10=K.object({success:K.boolean(),data:K.unknown().optional(),error:K.string().optional()}),N3A=K.object({id:K.string().min(1),timestamp:K.string(),type:K.string().min(1),source:K.string().min(1),target:K.string().optional(),metadata:K.record(K.string(),K.unknown()).optional()})});function j3A(A){let Q=Kx2.safeParse(A);if(!Q.success)throw Error("Invalid message response format");return Q.data}var Kx2;var M3A=i(()=>{Z0();Fb0();Kx2=K.union([K.object({noop:K.literal(!0)}),M10])});function P3A(A,Q,w,B,$){return{id:x3A("msg"),type:A,timestamp:R3A(),source:w,target:B,metadata:$,payload:Q}}function k3A(A,Q){let w=j3A(Q);if("noop"in w)return _3A(A,!0);return _3A(A,w.success,w.data,w.error)}function O3A(A,Q){if(Q?.success)return{success:!0,data:Q.data};return{success:!1,error:Q?.error?.message??`No handler found for message type: ${A}`}}function _3A(A,Q,w,B){return{id:x3A("resp"),requestId:A,timestamp:R3A(),success:Q,data:w,error:B?{message:B}:void 0}}function x3A(A){return`${A}-${Date.now()}-${Math.random().toString(36).slice(2,11)}`}function R3A(){return new Date().toISOString()}var Vb0=i(()=>{M3A()});class Ib0{handlers=new Map;add(A,Q,w){let B=this.createHandlerEntry(Q,w);return this.getOrCreateHandlers(A).add(B),B}remove(A,Q){let w=this.handlers.get(A);if(!w)return!1;let B=w.delete(Q);return this.deleteEmptyHandlerSet(A,w),B}removeHandler(A,Q){let w=this.handlers.get(A);if(!w)return;for(let B of Array.from(w))if(B.originalHandler===Q)w.delete(B);this.deleteEmptyHandlerSet(A,w)}getMatchingHandlers(A,Q){let w=this.handlers.get(A);if(!w||w.size===0)return;return{entries:Array.from(w).filter((B)=>L3A(Q,B.filter)),totalHandlers:w.size}}hasHandlers(A){let Q=this.handlers.get(A);return Q!==void 0&&Q.size>0}clearHandlers(A){return this.handlers.delete(A)}clearAllHandlers(){this.handlers.clear()}getHandlerCount(A){return this.handlers.get(A)?.size??0}getTargetedHandlerCount(A,Q){let w=this.handlers.get(A);if(!w)return 0;return Array.from(w).filter((B)=>B.filter?.target===Q).length}createHandlerEntry(A,Q){let w={handler:this.wrapHandler(A),originalHandler:A};return Q?{...w,filter:b3A(Q)}:w}wrapHandler(A){return async(Q)=>{let B=await A(Q);return k3A(Q.id,B)}}getOrCreateHandlers(A){let Q=this.handlers.get(A);if(!Q)Q=new Set,this.handlers.set(A,Q);return Q}deleteEmptyHandlerSet(A,Q){if(Q.size===0)this.handlers.delete(A)}}var h3A=i(()=>{Vb0()});async function v3A(A,Q,w){for(let B of Q)await y3A(B,A,w);return null}async function C3A(A,Q,w){for(let B of Q){let $=await y3A(B,A,w);if($)return $}return null}async function y3A(A,Q,w){try{return await A.handler(Q)}catch(B){return w.error(`Error in message handler for ${Q.type}`,B),null}}class Jb0{registry;logger;constructor(A,Q){this.registry=A;this.logger=Q}async publish(A,Q){if(typeof A!=="object"||!A.type||!A.id)return this.logger.error("Invalid message structure - missing required fields 'id' or 'type'"),null;let{type:w}=A;this.logger.debug(`Publishing message of type: ${w}`,{source:A.source,target:A.target,hasMetadata:!!A.metadata});let B=this.registry.getMatchingHandlers(w,A);if(!B)return this.logger.debug(`No handlers found for message type: ${w}`),null;if(B.entries.length===0)return this.logger.debug(`No matching handlers for message type: ${w}`,{totalHandlers:B.totalHandlers,target:A.target}),null;return Q===!0?v3A(A,B.entries,this.logger):C3A(A,B.entries,this.logger)}}var E3A=()=>{};function g3A(A,Q){try{return{valid:!0,data:Q.parse(A)}}catch(w){if(w instanceof K.ZodError)return{valid:!1,error:w.issues[0]?.message??"Validation failed"};return{valid:!1,error:"Unknown validation error"}}}var T3A=i(()=>{Z0()});class zZ{static instance=null;registry=new Ib0;publisher;logger;static getInstance(A){return zZ.instance??=new zZ(A),zZ.instance}static resetInstance(){zZ.instance=null}static createFresh(A){return new zZ(A)}constructor(A){this.logger=A,this.publisher=new Jb0(this.registry,A)}subscribe(A,Q,w){let B=this.registry.add(A,Q,w);return this.logger.debug(`Registered handler for message type: ${A}`,{hasFilter:!!w,filterTarget:w?.target}),()=>{this.registry.remove(A,B)}}async send(A){let{type:Q,payload:w,sender:B,target:$,metadata:f,broadcast:D}=A,Y=P3A(Q,w,B,$,f),X=await this.publisher.publish(Y,D);return O3A(Q,X)}validateMessage(A,Q){return g3A(A,Q)}hasHandlers(A){return this.registry.hasHandlers(A)}unsubscribe(A,Q){this.registry.removeHandler(A,Q)}clearHandlers(A){if(this.registry.clearHandlers(A))this.logger.info(`Cleared all handlers for message type: ${A}`)}clearAllHandlers(){this.registry.clearAllHandlers(),this.logger.info("Cleared all message handlers")}getHandlerCount(A){return this.registry.getHandlerCount(A)}getTargetedHandlerCount(A,Q){return this.registry.getTargetedHandlerCount(A,Q)}}var S3A=i(()=>{h3A();Vb0();E3A();T3A()});var Gx2;var m3A=i(()=>{Z0();Fb0();Gx2=K.object({id:K.string().min(1),requestId:K.string().min(1),success:K.boolean(),data:K.unknown().optional(),error:K.object({message:K.string(),code:K.string().optional()}).optional(),timestamp:K.string().datetime()})});var bb0=i(()=>{S3A();m3A()});var U6;var Lb0=i(()=>{uV();U6=KH("runtime_state_records",{namespace:IQ("namespace").notNull(),key:IQ("key").notNull(),value:IQ("value",{mode:"json"}).notNull(),createdAt:x9("created_at").notNull(),updatedAt:x9("updated_at").notNull()},(A)=>({pk:SO({columns:[A.namespace,A.key]}),namespaceUpdatedAtIdx:VY("idx_runtime_state_namespace_updated_at").on(A.namespace,A.updatedAt)}))});import{createClient as u3A}from"@libsql/client";function _10(A){let Q=A.url,w=A.authToken??process.env.RUNTIME_STATE_DATABASE_AUTH_TOKEN,B=w?u3A({url:Q,authToken:w}):u3A({url:Q});return{db:UH(B,{schema:{runtimeStateRecords:U6}}),client:B,url:Q}}async function P10(A,Q){if(Q.startsWith("file:"))await A.execute("PRAGMA journal_mode = WAL"),await A.execute("PRAGMA busy_timeout = 5000")}var Nb0=i(()=>{iO();Lb0()});class k10{db;namespace;schema;now;constructor(A,Q,w,B=()=>new Date){this.db=A;this.namespace=Q;this.schema=w;this.now=B;qx2(Q)}async get(A){let Q=Wu(A),B=(await this.db.select().from(U6).where(LB(_2(U6.namespace,this.namespace),_2(U6.key,Q))).limit(1))[0];if(!B)return null;return this.schema.parse(B.value)}async has(A){let Q=Wu(A);return(await this.db.select({key:U6.key}).from(U6).where(LB(_2(U6.namespace,this.namespace),_2(U6.key,Q))).limit(1)).length>0}async set(A,Q){let w=Wu(A),B=this.schema.parse(Q),$=this.now().getTime();await this.db.insert(U6).values({namespace:this.namespace,key:w,value:B,createdAt:$,updatedAt:$}).onConflictDoUpdate({target:[U6.namespace,U6.key],set:{value:B,updatedAt:$}})}async setIfNotExists(A,Q){let w=Wu(A),B=this.schema.parse(Q),$=this.now().getTime(),f=await this.db.insert(U6).values({namespace:this.namespace,key:w,value:B,createdAt:$,updatedAt:$}).onConflictDoNothing({target:[U6.namespace,U6.key]});return Number(f.rowsAffected)>0}async delete(A){let Q=Wu(A),w=await this.db.delete(U6).where(LB(_2(U6.namespace,this.namespace),_2(U6.key,Q)));return Number(w.rowsAffected)>0}async list(A={}){let Q=await this.listRows(),w=A.keyPrefix;if(w!==void 0)c3A(w);return Q.filter((B)=>w===void 0||B.key.startsWith(w)).map((B)=>({key:B.key,value:this.schema.parse(B.value),createdAt:new Date(B.createdAt),updatedAt:new Date(B.updatedAt)}))}async clear(A={}){let Q=A.keyPrefix;if(Q===void 0){let B=await this.db.delete(U6).where(_2(U6.namespace,this.namespace));return Number(B.rowsAffected)}c3A(Q);let w=await this.list({keyPrefix:Q});return await Promise.all(w.map((B)=>this.delete(B.key))),w.length}async listRows(){return this.db.select().from(U6).where(_2(U6.namespace,this.namespace))}}function qx2(A){if(!zx2.test(A))throw Error(`Invalid runtime state namespace: ${A}. Use 1-128 alphanumeric, _, ., :, or - characters.`)}function Wu(A){if(A.length===0||A.length>l3A)throw Error("Runtime state keys must be 1-512 characters long");return A}function c3A(A){if(A.length>l3A)throw Error("Runtime state key prefixes must be 512 characters or shorter");return A}var zx2,l3A=512;var jb0=i(()=>{$q();Lb0();zx2=/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,127}$/});class JH{static instance=null;db;client;logger;static getInstance(A,Q){return JH.instance??=new JH(A,Q??e2.getInstance()),JH.instance}static createFresh(A,Q){return new JH(A,Q??e2.getInstance())}static resetInstance(){JH.instance?.close(),JH.instance=null}constructor(A,Q){let{db:w,client:B,url:$}=_10(A);this.db=w,this.client=B,this.logger=Q.child("RuntimeStateService"),P10(B,$).catch((f)=>{this.logger.warn("Failed to enable runtime state WAL mode (non-fatal)",f)})}scoped(A){return new k10(this.db,A.namespace,A.schema)}close(){this.client.close()}}var p3A=i(()=>{Z0();Nb0();jb0()});var Mb0=i(()=>{p3A();jb0()});async function i3A(A,Q){if(A.status==="running"){Q.warn(`Daemon already running: ${A.name}`);return}A.status="starting",delete A.error;try{await A.daemon.start(),A.status="running",A.startedAt=new Date,Q.debug(`Daemon started successfully: ${A.name}`)}catch(w){throw A.status="error",A.error=fH(w),Q.warn(`Daemon ${A.name} failed to start: ${vA(w)}`),w}}async function d3A(A,Q){if(A.status==="stopped"){Q.warn(`Daemon already stopped: ${A.name}`);return}A.status="stopping";try{await A.daemon.stop(),A.status="stopped",A.stoppedAt=new Date,Q.debug(`Daemon stopped successfully: ${A.name}`)}catch(w){throw A.status="error",A.error=fH(w),Q.error(`Failed to stop daemon: ${A.name}`,w),w}}async function n3A(A){if(!A.daemon.healthCheck)return;try{let Q=await A.daemon.healthCheck();return A.health=Q,Q}catch(Q){let w={status:"error",message:vA(Q),lastCheck:new Date};return A.health=w,w}}function r3A(A){return{name:A.name,pluginId:A.pluginId,status:A.status,health:A.health}}var o3A=i(()=>{Z0()});class _U{static instance=null;daemons=new Map;logger;static getInstance(A=e2.getInstance()){return _U.instance??=new _U(A),_U.instance}static resetInstance(){_U.instance=null}static createFresh(A){return new _U(A)}constructor(A){this.logger=A.child("DaemonRegistry")}register(A,Q,w){if(this.daemons.has(A))this.logger.warn(`Daemon already registered: ${A}, overwriting`);let B={name:A,daemon:Q,pluginId:w,status:"stopped"};this.daemons.set(A,B),this.logger.debug(`Registered daemon: ${A} from plugin: ${w}`)}has(A){return this.daemons.has(A)}get(A){return this.daemons.get(A)}async start(A){let Q=this.daemons.get(A);if(!Q)throw Error(`Daemon not registered: ${A}`);await i3A(Q,this.logger)}async stop(A){let Q=this.daemons.get(A);if(!Q)throw Error(`Daemon not registered: ${A}`);await d3A(Q,this.logger)}async checkHealth(A){let Q=this.daemons.get(A);if(!Q)throw Error(`Daemon not registered: ${A}`);return n3A(Q)}getByPlugin(A){return Array.from(this.daemons.values()).filter((Q)=>Q.pluginId===A)}getAll(){return Array.from(this.daemons.keys())}getAllInfo(){return Array.from(this.daemons.values())}async getStatuses(){let A=this.getAllInfo();for(let Q of A)if(Q.daemon.healthCheck)await this.checkHealth(Q.name);return A.map(r3A)}async unregister(A){let Q=this.daemons.get(A);if(!Q){this.logger.warn(`Daemon not registered: ${A}`);return}if(Q.status==="running")await this.stop(A);this.daemons.delete(A),this.logger.debug(`Unregistered daemon: ${A}`)}async startPlugin(A){let Q=this.getByPlugin(A);this.logger.debug(`Starting ${Q.length} daemons for plugin: ${A}`);let w;for(let B of Q)try{await this.start(B.name)}catch($){w??=fH($)}if(w)throw w}async stopPlugin(A){let Q=this.getByPlugin(A);this.logger.debug(`Stopping ${Q.length} daemons for plugin: ${A}`);for(let w of Q)try{await this.stop(w.name)}catch(B){this.logger.error(`Failed to stop daemon: ${w.name}`,B)}}async clear(){this.logger.debug("Clearing all daemons");let A=Array.from(this.daemons.values()).filter((Q)=>Q.status==="running");for(let Q of A)try{await this.stop(Q.name)}catch(w){this.logger.error(`Failed to stop daemon during clear: ${Q.name}`,w)}this.daemons.clear(),this.logger.debug("All daemons cleared")}}var _b0=i(()=>{Z0();o3A()});function Pb0(A,Q,w,B,$){return["entity:created","entity:updated","entity:deleted"].map((D)=>A.subscribe(D,async(Y)=>{if(Y.payload.entityType===Q&&(w===null||Y.payload.entityId===w)){await B();let X=D.replace("entity:","");$.debug(`${Q} entity ${X}, cache refreshed`)}return{success:!0}}))}async function Fx2(A,Q,w){let B=Vx2(A.kind);if(!B)return null;try{let $=Q.scoped({namespace:B,refKind:A.kind,routePath:""});return Ix2(await $.read(A.id),A)}catch($){return w.debug("Skipped unavailable prior runtime upload",{uploadKind:A.kind,uploadId:A.id,error:$ instanceof Error?$.message:String($)}),null}}function Vx2(A){return A==="upload"?"upload":null}function Ix2(A,Q){let{record:w,content:B}=A;if(Jx2(w.mediaType))return{kind:"text",filename:w.filename,mediaType:w.mediaType,content:new TextDecoder("utf-8").decode(B).replace(/^\uFEFF/,""),sizeBytes:w.sizeBytes,source:Q};return{kind:"file",filename:w.filename,mediaType:w.mediaType,data:new Uint8Array(B),sizeBytes:w.sizeBytes,source:Q}}function Jx2(A){let Q=A.toLowerCase();return Q.startsWith("text/")||Q==="application/json"}function s3A(A){let{config:Q,entityService:w,logger:B,messageBus:$,aiService:f,mcpService:D,conversationService:Y,runtimeUploadRegistry:X,disposables:H}=A,W=GH.getInstance(w,B,Q.identity);H.push(...Pb0($,Af.BRAIN_CHARACTER,Af.BRAIN_CHARACTER,()=>W.refreshCache(),B));let Z=e4.getInstance(w,B,Q.profile),G=Gq.getInstance(B),F=qb0({model:f.getModel(),modelId:f.getConfig().model,webSearch:f.getConfig().webSearch,temperature:f.getConfig().temperature,maxTokens:f.getConfig().maxTokens,messageBus:$}),V=Xb0(Q.name),b=BD.getInstance(D,Y,W,Z,B,{agentFactory:F,canonicalIdentityResolver:G,indexReadiness:w,uploadAttachmentResolver:(L)=>Fx2(L,X,B),agentContextProvider:async(L)=>{let N=await $.send({type:BN,sender:"shell:agent-service",payload:L});if("noop"in N||!N.success)return[];return vZ0(N.data)},...V?{assistantActorId:V}:{},...Q.agentInstructions&&{agentInstructions:Q.agentInstructions}});H.push(...Pb0($,Af.ANCHOR_PROFILE,Af.ANCHOR_PROFILE,()=>Z.refreshCache(),B));for(let L of[Af.BRAIN_CHARACTER,Af.ANCHOR_PROFILE])H.push(...Pb0($,L,L,async()=>b.invalidateAgent(),B));return{identityService:W,profileService:Z,canonicalIdentityService:G,agentService:b}}var a3A=i(()=>{j10();CB();zq();xN()});function t3A(A){let{dependencies:Q,jobQueueService:w,messageBus:B,logger:$}=A,f=Q?.batchJobManager??sW.getInstance(w,$),D=Q?.jobProgressMonitor??aW.getInstance(w,B,f,$),Y=Q?.jobQueueWorker??oW.getInstance(w,D,$,{pollInterval:100,concurrency:1,autoStart:!1});return{batchJobManager:f,jobProgressMonitor:D,jobQueueWorker:Y}}var e3A=i(()=>{fq()});function AFA(A,Q){if(Q)return Q;let w={debug:2,info:3,warn:4,error:5}[A.logging.level];return e2.createFresh({level:w,context:A.logging.context,format:A.logging.format==="json"?"json":"text",...A.logging.file?{logFile:A.logging.file}:{}})}function QFA(A){return{apiKey:A.ai.apiKey,model:A.ai.model,temperature:A.ai.temperature,maxTokens:A.ai.maxTokens,webSearch:A.ai.webSearch,...A.ai.imageApiKey?{imageApiKey:A.ai.imageApiKey}:{}}}function WR(A){return{url:A.url,...A.authToken?{authToken:A.authToken}:{}}}var wFA=i(()=>{Z0()});function BFA(A){let{config:Q,dependencies:w,initializerLogger:B}=A;B.debug("Initializing Shell services");let $=AFA(Q,w?.logger),f=[],D=w?.embeddingService??UZ.getInstance({apiKey:Q.ai.apiKey,logger:$}),Y=w?.aiService??KZ.getInstance(QFA(Q),$),X=JY.getInstance($),H=w?.messageBus??zZ.getInstance($),W=w?.templateRegistry??DH.getInstance($),Z=w?.dataSourceRegistry??tW.getInstance($),G=w?.renderService??lW.getInstance(W),F=w?.daemonRegistry??_U.getInstance($),V=w?.pluginManager??zH.getInstance($,F),b=w?.permissionService??new m$(Q.permissions,{spaces:Q.spaces}),L=w?.attachmentRegistry??eW.getInstance(),N=w?.runtimeUploadRegistry??bS.createFresh({dataDir:Q.dataDir}),_=w?.runtimeStateService??JH.createFresh(WR(Q.runtimeStateDatabase),$),j=w?.mcpService??YH.getInstance(H,$),g=w?.jobQueueService??IY.getInstance(WR(Q.jobQueueDatabase),$),E=LY.getInstance({embeddingService:D,entityRegistry:X,logger:$,jobQueueService:g,messageBus:H,dbConfig:WR(Q.database),embeddingDbConfig:WR(Q.embeddingDatabase)}),y=w?.conversationService??of.getInstance($,H,WR(Q.conversationDatabase)),h=w?.contentService??new j00({logger:$,entityService:E,aiService:Y,templateRegistry:W,dataSourceRegistry:Z}),{identityService:T,profileService:S,canonicalIdentityService:c,agentService:m}=s3A({config:Q,entityService:E,entityRegistry:X,logger:$,messageBus:H,aiService:Y,mcpService:j,conversationService:y,runtimeUploadRegistry:N,disposables:f}),{batchJobManager:B0,jobProgressMonitor:a,jobQueueWorker:v}=t3A({dependencies:w,jobQueueService:g,messageBus:H,logger:$});return{logger:$,disposables:f,entityRegistry:X,messageBus:H,renderService:G,daemonRegistry:F,pluginManager:V,templateRegistry:W,dataSourceRegistry:Z,mcpService:j,embeddingService:D,entityService:E,aiService:Y,conversationService:y,contentService:h,jobQueueService:g,jobQueueWorker:v,batchJobManager:B0,jobProgressMonitor:a,permissionService:b,identityService:T,profileService:S,canonicalIdentityService:c,agentService:m,attachmentRegistry:L,runtimeUploadRegistry:N,runtimeStateService:_}}var $FA=i(()=>{j10();_00();NN();aB();aB();fq();k9();bb0();c0();Mb0();JB();_b0();a3A();e3A();wFA()});function fFA(A,Q){A.register(uS.name,uS),Q.debug("Shell system templates registered")}function DFA(A,Q){A.register(Ux.BASE_ENTITY_DISPLAY,{name:"base-entity-display",description:"Display template for base entities",schema:o1,formatter:new Ee,requiredPermission:"public"}),Q.debug("Base entity display template registered")}function YFA(A,Q){A.registerEntityType(Af.NOTE,o1,new IS),Q.debug("Fallback base entity adapter registered")}function XFA(A,Q){let w=new Hx;A.registerEntityType(Af.BRAIN_CHARACTER,w.schema,w),Q.debug("Brain character entity support registered")}function HFA(A,Q){let w=new VU;A.registerEntityType(Af.ANCHOR_PROFILE,w.schema,w),Q.debug("Anchor profile entity support registered")}async function WFA(A){let{plugins:Q,pluginManager:w,logger:B,initOptions:$}=A;B.debug(`Found ${Q.length} plugins to register`);for(let f of Q)B.debug(`Registering plugin: ${f.id}`),w.registerPlugin(f);if(await w.initializePlugins($?.registrationContext),!$?.registerOnly){for(let{id:f,error:D}of w.getFailedPlugins())if(w.getPlugin(f)?.requiresDaemonStartup?.())throw D}B.debug("Plugin initialization complete")}var ZFA=i(()=>{_00();aB();zq();xN()});function KFA(){LY.resetInstance(),JY.resetInstance(),tW.resetInstance(),UZ.resetInstance(),of.resetInstance(),zH.resetInstance(),YH.resetInstance(),zZ.resetInstance(),DH.resetInstance(),lW.resetInstance(),_U.resetInstance(),KZ.resetInstance(),BD.resetInstance(),GH.resetInstance(),e4.resetInstance(),IY.resetInstance(),sW.resetInstance(),oW.resetInstance(),aW.resetInstance(),eW.resetInstance(),JH.resetInstance()}var UFA=i(()=>{j10();NN();aB();zq();fq();k9();bb0();c0();Mb0();JB();_b0()});class qZ{static instance=null;logger;config;static getInstance(A,Q){return qZ.instance??=new qZ(A,Q),qZ.instance}static resetInstance(){qZ.instance=null}static createFresh(A,Q){return new qZ(A,Q)}constructor(A,Q){this.logger=A.child("ShellInitializer"),this.config=Q}registerShellTemplates(A){fFA(A,this.logger)}registerBaseEntityDisplayTemplate(A){DFA(A,this.logger)}registerFallbackBaseEntity(A){YFA(A,this.logger)}registerBrainCharacterSupport(A){XFA(A,this.logger)}registerAnchorProfileSupport(A){HFA(A,this.logger)}async initializePlugins(A,Q){await WFA({plugins:this.config.plugins,pluginManager:A,logger:this.logger,initOptions:Q})}initializeServices(A){return BFA({config:this.config,dependencies:A,initializerLogger:this.logger})}registerJobHandlers(A,Q,w){let B=qq.createFresh(Q,w);A.registerHandler("shell:content-generation",B,"shell")}wireShell(A,Q){A.pluginManager.setShell(Q)}async initializeAll(A,Q,w,B){this.logger.debug("Starting Shell initialization");try{if(this.registerShellTemplates(A),this.registerBaseEntityDisplayTemplate(A),this.registerBrainCharacterSupport(Q),this.registerAnchorProfileSupport(Q),await this.initializePlugins(w,B),!Q.hasEntityType(Af.NOTE))this.registerFallbackBaseEntity(Q);this.logger.debug("Shell registration phase complete")}catch($){throw this.logger.error("Shell initialization failed",$),$}}}function Zu(){qZ.resetInstance(),KFA()}async function GFA(){let{Shell:A}=await Promise.resolve().then(() => (kb0(),zFA));await A.resetInstance(),Zu()}var O10=i(()=>{_00();xN();$FA();ZFA();UFA()});class Ob0{config;services;hooks;constructor(A,Q,w){this.config=A;this.services=Q;this.hooks=w}async boot(A){this.services.logger.debug("Starting Shell boot");let Q=qZ.getInstance(this.services.logger,this.config);if(await this.services.entityService.initialize(),await Q.initializeAll(this.services.templateRegistry,this.services.entityRegistry,this.services.pluginManager,{...A?.mode==="register-only"&&{registerOnly:!0},...this.config.entityDisplay!==void 0&&{registrationContext:{entityDisplay:this.config.entityDisplay}}}),Q.registerJobHandlers(this.services.jobQueueService,this.services.contentService,this.services.entityService),this.hooks.registerCoreDataSources(),this.hooks.registerSystemCapabilities(),A?.mode==="register-only"){this.services.logger.debug("Shell boot complete (register-only mode)");return}if(A?.mode!=="startup-check"){await this.startEarlyWebserver(),await this.emitPluginsRegistered();let w=await this.services.entityService.backfillMissingEmbeddings();this.services.logger.debug("Queued missing embedding backfill jobs",{queued:w.queued,skipped:w.skipped})}if(await this.prepareReadyState(),await this.services.pluginManager.readyPlugins(),A?.mode==="startup-check"){this.services.logger.debug("Shell boot complete (startup-check mode)");return}await this.startRuntimeServices(),this.startIndexReadinessMonitor(),this.services.logger.debug("Shell boot complete")}async startEarlyWebserver(){if(!this.services.daemonRegistry.has("webserver:webserver"))return;await this.services.daemonRegistry.start("webserver:webserver"),this.services.logger.debug("Started webserver before initial sync")}async emitPluginsRegistered(){await this.services.messageBus.send({type:VN.pluginsRegistered,payload:{timestamp:new Date().toISOString(),pluginCount:this.services.pluginManager.getAllPluginIds().length},sender:"shell",broadcast:!0}),this.services.logger.debug("Emitted plugins registered event")}async prepareReadyState(){await Promise.all([this.services.identityService.initialize(),this.services.profileService.initialize(),this.services.canonicalIdentityService.refreshCache()]),this.services.logger.debug("Identity services initialized");let A=await RU0(this.services.templateRegistry,this.services.entityService);if(A>0)this.services.logger.debug(`Materialized ${A} prompt entities`)}async startRuntimeServices(){await this.services.pluginManager.startPluginDaemons(),await this.services.jobQueueWorker.start(),this.services.jobProgressMonitor.start(),this.services.batchJobManager.start()}startIndexReadinessMonitor(){this.runIndexReadinessMonitor()}async runIndexReadinessMonitor(){for(;;){try{let A=await this.services.entityService.awaitIndexReady({timeoutMs:Lx2});if(A.ready){if(A.degraded)this.services.logger.warn("Semantic index ready with degraded embeddings",A);else this.services.logger.debug("Semantic index ready",A);return}this.services.logger.warn("Semantic index not ready yet; retrying readiness monitor",A)}catch(A){this.services.logger.warn("Semantic index readiness monitor failed; retrying",A)}await this.delayIndexReadinessRetry()}}async delayIndexReadinessRetry(){await new Promise((A)=>{setTimeout(A,Nx2).unref()})}}var Lx2=30000,Nx2=5000;var qFA=i(()=>{c0();O10()});class FFA{handlers=new Map;register(A,Q){this.handlers.set(A,Q)}getTypes(){return Array.from(this.handlers.keys())}async get(A,Q,w){let B=this.handlers.get(A);if(!B)throw Error(`Unknown insight type: ${A}. Available: ${this.getTypes().join(", ")}`);return B(Q,w)}}function VFA(){let A=new FFA;return A.register("overview",jx2),A.register("publishing-cadence",Mx2),A.register("content-health",_x2),A}async function jx2(A,Q){let w=await A.getEntityCounts(Q),B={},$=0;for(let{entityType:F,count:V}of w)B[F]=V,$+=V;let f=await xb0(A,Q),D=Date.now(),Y=D-604800000,X=D-2592000000,H=0,W=0;for(let F of f){let V=new Date(F.created).getTime();if(V>=Y)H++;if(V>=X)W++}let Z=IFA(f),G=f.filter((F)=>F.metadata.status==="published");return{entityCounts:B,totalEntities:$,recentActivity:{last7days:H,last30days:W},contentHealth:{drafts:Z.length,published:G.length}}}async function Mx2(A,Q){let w=await xb0(A,Q),B=new Map;for(let f of w){let D=new Date(f.created);if(isNaN(D.getTime()))continue;let Y=`${D.getUTCFullYear()}-${String(D.getUTCMonth()+1).padStart(2,"0")}`,X=B.get(Y);if(!X)X={},B.set(Y,X);X[f.entityType]=(X[f.entityType]??0)+1}return{months:Array.from(B.entries()).sort((f,D)=>D[0].localeCompare(f[0])).map(([f,D])=>{let Y=0;for(let X of Object.values(D))Y+=X;return{month:f,counts:D,total:Y}})}}async function _x2(A,Q){let w=await xb0(A,Q),B=IFA(w).map((Y)=>({id:Y.id,entityType:Y.entityType,title:typeof Y.metadata.title==="string"?Y.metadata.title:Y.id,created:Y.created})),$=Date.now(),f=$-7776000000,D=w.filter((Y)=>{if(Y.entityType==="image")return!1;let X=new Date(Y.updated).getTime();return!isNaN(X)&&X<f}).map((Y)=>({id:Y.id,entityType:Y.entityType,title:typeof Y.metadata.title==="string"?Y.metadata.title:Y.id,updated:Y.updated,daysSinceUpdate:Math.floor(($-new Date(Y.updated).getTime())/86400000)}));return{drafts:B,stale:D}}function IFA(A){return A.filter((Q)=>Q.metadata.status==="draft")}async function xb0(A,Q){let w=A.getEntityTypes(),B=[];for(let $ of w){let f=await A.listEntities({entityType:$,options:{limit:1000,filter:{visibilityScope:Q}}});B.push(...f)}return B}class Ku{parse;idOf;items=new Map;constructor(A,Q){this.parse=A;this.idOf=Q}register(A){let Q=this.parse(A);this.items.set(this.keyFor(Q.pluginId,this.idOf(Q)),Q)}unregister(A,Q){if(Q!==void 0){this.items.delete(this.keyFor(A,Q));return}let w=`${A}:`;for(let B of this.items.keys())if(B.startsWith(w))this.items.delete(B)}list(){return Array.from(this.items.values()).sort((A,Q)=>A.priority-Q.priority||A.label.localeCompare(Q.label))}keyFor(A,Q){return`${A}:${Q}`}}var Rb0;var JFA=i(()=>{c0();Rb0=class Rb0 extends Ku{constructor(){super((A)=>RO.parse(A),(A)=>A.url)}}});var hb0;var bFA=i(()=>{c0();hb0=class hb0 extends Ku{constructor(){super((A)=>hO.parse(A),(A)=>A.id)}}});function LFA(A,Q){return{enqueueBatch:A.enqueueBatch.bind(A),getActiveBatches:A.getActiveBatches.bind(A),getBatchStatus:A.getBatchStatus.bind(A),getActiveJobs:Q.getActiveJobs.bind(Q),getStatus:Q.getStatus.bind(Q)}}function NFA(A){let Q=[];for(let[w,B]of A.getAllPlugins()){let{plugin:$}=B;if("getApiRoutes"in $&&typeof $.getApiRoutes==="function")for(let f of $.getApiRoutes())Q.push({pluginId:w,fullPath:`/api/${w}${f.path}`,definition:f})}return Q}function jFA(A){let Q=[];for(let[w,B]of A.getAllPlugins()){let{plugin:$}=B;if("getWebRoutes"in $&&typeof $.getWebRoutes==="function")for(let f of $.getWebRoutes())Q.push({pluginId:w,fullPath:f.path,definition:f})}return Q}async function MFA(A){A.batchJobManager.stop(),A.jobProgressMonitor.stop(),await A.jobQueueWorker.stop();for(let[Q]of A.pluginManager.getAllPlugins())await A.pluginManager.disablePlugin(Q);for(let Q of A.disposables.splice(0))try{Q()}catch(w){A.logger.warn("Failed to dispose shell subscription",w)}A.entityService.close(),A.jobQueueService.close(),A.conversationService.close(),A.runtimeStateService.close()}var Px2,_FA,PFA,kFA,kx2,Ox2,xx2,OFA,xFA,RFA,hFA,vFA,CFA,yFA,Z5B,K5B;var Rq=i(()=>{aB();Z0();Px2=K.discriminatedUnion("kind",[K.object({kind:K.literal("all")}).strict().describe("Search across all entity types"),K.object({kind:K.literal("type"),entityType:K.string().min(1).describe("Entity type to search")}).strict().describe("Search within one entity type")]),_FA=K.object({query:K.string().describe("Search term"),scope:Px2.describe("Structured search scope. Use { kind: 'all' } for broad search across all entity types. Use { kind: 'type', entityType } only when the user asks for a specific entity type."),limit:K.number().optional().describe("Maximum number of results"),includeUngenerated:K.boolean().optional().describe("Include queued/failed generation stubs in results")}),PFA=K.object({entityType:K.string().describe("Entity type"),id:K.string().describe("Entity ID, slug, or title")}),kFA=K.object({entityType:K.string().describe("Entity type to list"),status:K.string().optional().describe("Filter by status. Omit unless the user asks for a known status; do not invent generic statuses. For wish statuses: new, planned, in-progress, done, declined."),limit:K.number().optional().describe("Maximum number of results (default: 20)")}),kx2=K.object({kind:K.literal("upload").describe("Upload ref kind"),id:K.string().min(1).describe("Upload ID")}),Ox2=K.discriminatedUnion("kind",[K.object({kind:K.literal("text").describe("Store exact/direct user-provided content without generation"),content:K.string().min(1).describe("Exact markdown/text/content to persist as provided. For direct save requests where the user includes the content in the same message, use that provided content directly.")}).strict(),K.object({kind:K.literal("url").describe("Create URL/domain-backed entities such as links"),url:K.string().min(1).describe("URL or domain to create from; preserve a bare domain as provided instead of adding a scheme.")}).strict(),K.object({kind:K.literal("upload").describe("Use extract-markdown to import upload text into a note, or preserve only when the user explicitly wants to save the uploaded file/document bytes themselves. Do not use for saving a previous assistant summary about an upload; use prior-response for that."),upload:kx2.describe("Exact upload candidate object from the current conversation"),transform:K.enum(["extract-markdown","preserve"]).describe("extract-markdown imports upload text into a note-like entity; preserve saves raw uploaded bytes via the registered upload-save handler and derives the durable entity type from media type. Use preserve only for explicit file/document preservation, not for saving an assistant summary response.")}).strict(),K.object({kind:K.literal("prior-response").describe("Save a previous assistant response as durable content, especially an assistant summary or answer about an upload."),messageId:K.string().min(1).optional().describe("Stored assistant message ID; omit for latest savable")}).strict()]),xx2=K.discriminatedUnion("kind",[K.object({kind:K.literal("prompt").describe("Generate a new non-image durable entity from a prompt. For general topical social/newsletter/blog/deck generation, omit source. Only include source when the user explicitly asks to generate from/based on a specific existing content entity that was resolved with a tool result."),entityType:K.string().min(1).describe("Entity type to generate from the prompt. Do not use image here; use standalone-image or cover-image."),title:K.string().optional().describe("Title for the generated entity"),source:K.object({entityType:K.string().min(1).describe("Resolved content source entity type, such as post for a newsletter from a blog post. Do not use brain-character or anchor-profile."),entityId:K.string().min(1).describe("Resolved source entity ID copied from a prior tool result or typed entity ref; never an upload id, filename, guessed slug, or future placeholder.")}).strict().optional().describe("Existing durable source entity to ground this generation. Use only when the user asked to generate from/based on that specific resolved content entity. Omit source for broad topical prompts, profile/brain-character context, uploads, conversation-only context, or unknown/guessed sources."),prompt:K.string().min(1).describe("Prompt for creating new generated content. Do not use for saving/importing existing uploads or prior responses.")}).strict(),K.object({kind:K.literal("standalone-image").describe("Generate a standalone image that is not attached to another entity. Do not use this as a cover image substitute; requested covers require cover-image after the target entity exists."),title:K.string().optional().describe("Title for the generated image"),prompt:K.string().min(1).describe("Prompt for creating an unattached image. Not for cover images requested for a generated post/entity.")}).strict(),K.object({kind:K.literal("cover-image").describe("Generate an image and attach it to an existing entity as coverImageId. Use only after the target entity already exists and its real entityId is known; do not use in the same initial turn as generating that target entity."),target:K.object({entityType:K.string().min(1).describe("Existing target entity type. Use the actual type of the entity being covered: social-post for LinkedIn/social posts, post for blog posts, etc."),entityId:K.string().min(1).describe("Existing target entity ID copied from a prior tool result or typed entity ref; never a placeholder or guessed future id")}).strict().describe("Existing entity that should receive the generated coverImageId"),title:K.string().optional().describe("Title for the generated image"),prompt:K.string().min(1).describe("Prompt for creating the cover image")}).strict(),K.object({kind:K.literal("attachment").describe("Generate a deterministic durable artifact from an existing entity attachment provider"),source:K.object({entityType:K.string().min(1).describe("Source entity type"),entityId:K.string().min(1).describe("Canonical source entity ID copied from a prior tool result or typed entity ref; never an upload id, filename, guessed slug, or future placeholder")}).strict().describe("Existing durable entity whose attachment provider should render the artifact. Use only resolved entity refs, not uploads or conversation-only context."),attachmentType:K.string().min(1).describe('Source artifact type such as "carousel", "printable", or "og-image"'),title:K.string().optional().describe("Title for the generated artifact"),replace:K.boolean().optional().describe("Regenerate instead of reusing a deterministic artifact")}).strict()]),OFA=K.object({entityType:K.string().describe("Entity type to create. Use wish for explicitly saved or tracked unmet requested capabilities or outcomes."),title:K.string().optional().describe("Title for a new entity."),source:Ox2.describe("Concrete source selector. Use exactly one source branch. For AI generation or source-derived artifacts, use system_generate instead."),replace:K.boolean().optional().describe("Create a new copy intentionally"),confirmed:K.literal(!0).optional().describe("Confirm the creation"),confirmationToken:K.string().optional().describe("Internal confirmation token returned by the confirmation flow")}).strict(),xFA=K.object({operation:xx2.describe("Generation operation selector. Use prompt for non-image AI-generated entities, standalone-image for unattached images, cover-image for generated covers on existing entities, and attachment for deterministic source-derived artifacts."),confirmed:K.literal(!0).optional().describe("Confirm generation"),confirmationToken:K.string().optional().describe("Internal confirmation token returned by the confirmation flow")}).strict(),RFA=K.object({entityType:K.string().describe("Entity type"),id:K.string().describe("Entity ID, slug, or title"),fields:K.record(K.unknown()).optional().describe("Partial frontmatter fields to update. Use this for status, title, coverImageId, ogImageId, and metadata changes such as approving an agent. To set an existing image as an entity cover, update fields.coverImageId to that image id. Do not use fields for anchor-profile; anchor-profile updates require full markdown content replacement via content."),content:K.string().optional().describe("Full markdown content replacement only. Do not use this for status/title/frontmatter updates; use fields instead."),confirmed:K.literal(!0).optional().describe("Confirm the update"),contentHash:K.string().optional().describe("Content hash for optimistic concurrency")}),hFA=K.object({entityType:K.string().describe("Entity type"),id:K.string().describe("Entity ID"),confirmed:K.literal(!0).optional().describe("Confirm the deletion"),confirmationToken:K.string().optional().describe("Internal confirmation token returned by the confirmation flow")}),vFA=K.object({entityType:K.string().describe("Entity type to extract"),source:K.string().optional().describe("Source entity ID \u2014 omit for batch"),mode:K.enum(["derive","rebuild"]).optional().describe("Batch mode: project incrementally or rebuild from scratch"),confirmed:K.literal(!0).optional().describe("Confirm destructive rebuild")}),CFA=K.object({batchId:K.string().optional().describe("Specific batch ID to check"),jobTypes:K.array(K.string()).optional().describe("Filter by job types")}),yFA=K.object({type:K.string().describe("Type of insight to retrieve. Built-in: overview, publishing-cadence, content-health. Plugins may register additional types.")}),Z5B=K.object({entityId:K.string().optional(),status:K.enum(["created","generating"]),jobId:K.string().optional(),attachment:qU0.optional()}),K5B=K.object({status:K.literal("extracting"),jobId:K.string(),entityType:K.string(),source:K.string().optional(),mode:K.enum(["derive","rebuild"]).optional()})});function bH(A,Q,w,B){try{A.permissionService.assertEntityActionAllowed(Q,w,B.userPermissionLevel);return}catch($){if($ instanceof ST||$ instanceof Error)return{success:!1,error:$.message};throw $}}var ZR=i(()=>{JB()});function LH(A,Q,w,B,$={}){let{visibility:f="anchor",sideEffects:D}=$;return{name:`${Rx2}_${A}`,description:Q,inputSchema:w.shape,handler:async(Y,X)=>{let H=w.safeParse(Y);if(!H.success)return{success:!1,error:`Invalid input: ${H.error.errors.map((W)=>`${W.path.join(".")}: ${W.message}`).join(", ")}`};try{return await B(H.data,X)}catch(W){return{success:!1,error:vA(W)}}},visibility:f,...D?{sideEffects:D}:{}}}function hq(A,Q){if(A.entityRegistry.hasEntityType(Q))return;let w=A.entityService.getEntityTypes();return{success:!1,error:`Entity type "${Q}" is not available in this brain. Available types: ${w.join(", ")}.`}}function KR(A){let Q={...A.conversationId?{conversationId:A.conversationId}:{},...A.channelId?{channelId:A.channelId}:{},...A.runId?{runId:A.runId}:{},...A.toolCallId?{toolCallId:A.toolCallId}:{}};return Object.keys(Q).length>0?Q:void 0}function vb0(A){if(A.entityType==="image"&&A.content.startsWith("data:"))return{...A,content:"[binary image data \u2014 use metadata for image info]"};return A}function Dj(A){if(A===void 0)return;let Q=A.trim();return Q.length>0?Q:void 0}function gFA(A){if(A.fields)return{fields:A.fields};if(!A.content)return{};try{let Q=JSON.parse(A.content);if(typeof Q==="object"&&Q!==null&&!Array.isArray(Q)){if("fields"in Q&&typeof Q.fields==="object"&&Q.fields!==null&&!Array.isArray(Q.fields))return{fields:Q.fields};return{fields:Q}}}catch{}return{content:A.content}}function TFA(A){return hx2[A]??A.replaceAll("-"," ")}function x10(A){return[A.metadata.title,A.metadata.name,A.metadata.subject,A.metadata.slug].find((B)=>typeof B==="string"&&B.trim().length>0)??A.id}function SFA(A){return!!A&&Object.keys(A.shape).length>0}function EFA(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}async function mFA(A,Q,w){if(!w)return!1;let B=await A.conversationService.getMessages(w,{limit:100});for(let $ of B){let D=le($.metadata)?.attachments;if(!Array.isArray(D))continue;for(let Y of D){if(!EFA(Y))continue;let X=Y.source;if(!EFA(X))continue;if(X.kind===Q.kind&&X.id===Q.id)return!0}}return!1}var Rx2="system",hx2;var $I=i(()=>{NN();Z0();hx2={base:"note"}});function Cx2(A){return{summary:`Save uploaded file${A.title?` as "${A.title}"`:""}?`,preview:[`Filename: ${A.filename}`,`Media type: ${A.mediaType}`,`Entity type: ${A.entityType}`,...A.title?[`Title: ${A.title}`]:[]].join(`
386
+ ${f}`:"")}function Kb0(A,Q,w,B){return async($,f)=>{if(B){let D={toolName:A,args:$,conversationId:w.conversationId,interfaceType:w.interfaceType,...w.channelId!==void 0&&{channelId:w.channelId},...w.channelName!==void 0&&{channelName:w.channelName},...f?.toolCallId!==void 0&&{toolCallId:f.toolCallId}};await B.emit("tool:invoking",D)}try{let D=f?await Q($,f):await Q($);if(B){let Y={toolName:A,conversationId:w.conversationId,interfaceType:w.interfaceType,...w.channelId!==void 0&&{channelId:w.channelId},...w.channelName!==void 0&&{channelName:w.channelName},...f?.toolCallId!==void 0&&{toolCallId:f.toolCallId}};await B.emit("tool:completed",Y)}return D}catch(D){if(B){let Y={toolName:A,error:vA(D),conversationId:w.conversationId,interfaceType:w.interfaceType,...w.channelId!==void 0&&{channelId:w.channelId},...w.channelName!==void 0&&{channelName:w.channelName},...f?.toolCallId!==void 0&&{toolCallId:f.toolCallId}};await B.emit("tool:failed",Y)}throw D}}}function Ub0(A,Q="brain-agent"){return{emit:async(w,B)=>{await A.send({type:w,payload:B,sender:Q,broadcast:!0}).catch(()=>{return})}}}var N10=i(()=>{Z0()});function $x2(A,Q={}){return Object.fromEntries(Object.entries(A).filter(([w])=>{if(Qx2.has(w))return!1;if(Q.toolName!=="system_create")return!0;return!wx2.has(w)}))}function fx2(A){let Q=Bx2.safeParse(A);if(!Q.success)return{type:"json",value:q3A(A)};let{attachment:w}=Q.data.data,B={mediaType:w.mediaType,...w.filename!==void 0?{filename:w.filename}:{},...w.sizeBytes!==void 0?{sizeBytes:w.sizeBytes}:{},...w.source!==void 0?{source:w.source}:{}};return{type:"json",value:q3A({...Q.data,data:{...Q.data.data,attachment:B,artifactCard:{rendered:!0,message:"The UI has rendered this artifact as an attachment card with Open and Download controls. Do not print raw attachment URLs in the assistant response."}}})}}function Dx2(A){if(typeof A!=="object"||A===null||Array.isArray(A))return A;if(A.success!==!0)return A;return{...A,cached:!0}}function q3A(A){if(A===void 0)return null;return Gb0.parse(JSON.parse(JSON.stringify(A)))}function zb0(A,Q,w){let B={},$=new Map;for(let f of A){let D=Kb0(f.name,async(Y,X)=>{let H={interfaceType:Q.interfaceType,userId:"agent-user",conversationId:Q.conversationId,...Q.channelId&&{channelId:Q.channelId},...X?.toolCallId&&{toolCallId:X.toolCallId},...Q.channelName&&{channelName:Q.channelName},...Q.userPermissionLevel&&{userPermissionLevel:Q.userPermissionLevel}};if(f.sideEffects!=="none"){if(f.sideEffects==="writes"||f.sideEffects==="external")$.clear();return f.handler(Y,H)}let W=`${f.name}:${JSON.stringify(Y)}`;if($.has(W))return Dx2($.get(W));let Z=await f.handler(Y,H);return $.set(W,Z),Z},Q,w);B[f.name]=IV0({description:f.description,inputSchema:K.object($x2(f.inputSchema,{toolName:f.name,...Q.enableCreateUpload!==void 0&&{enableCreateUpload:Q.enableCreateUpload},...Q.enableCreateTransform!==void 0&&{enableCreateTransform:Q.enableCreateTransform}})),execute:D,toModelOutput:({output:Y})=>fx2(Y)})}return B}var Qx2,wx2,Gb0,Bx2;var F3A=i(()=>{ux();Z0();N10();Qx2=new Set(["confirmed","confirmationToken","contentHash"]),wx2=new Set(["content","prompt","url","from","upload","transform","sourceAttachment"]),Gb0=K.lazy(()=>K.union([K.null(),K.string(),K.number(),K.boolean(),K.array(Gb0),K.record(Gb0)])),Bx2=K.object({success:K.literal(!0),data:K.object({documentId:K.string().min(1).optional(),entityId:K.string().min(1).optional(),attachment:K.object({mediaType:K.string().min(1),url:K.string().min(1),downloadUrl:K.string().min(1).optional(),previewUrl:K.string().min(1).optional(),filename:K.string().min(1).optional(),sizeBytes:K.number().nonnegative().optional(),source:K.object({entityType:K.string().optional(),entityId:K.string().optional(),attachmentType:K.string().optional()}).optional()}).passthrough()}).passthrough()}).passthrough()});function Xx2(A,Q){return A}function Hx2(A){return A.steps.at(-1)?.toolResults?.some((w)=>YN.safeParse(w.output).success||w.toolName==="playbook_start")??!1}function qb0(A){let{model:Q,modelId:w,webSearch:B,temperature:$,maxTokens:f,messageBus:D}=A,Y=YUA(w),X=Ub0(D);return function(W){let Z=zb0(W.tools,{conversationId:"",interfaceType:"agent"},X);return new AUA({model:Q,callOptionsSchema:Yx2,prepareCall:({options:G,...F})=>{let V=G.disableTools?[]:Xx2(W.getToolsForPermission(G.userPermissionLevel),G),b=V.map((N)=>N.name),L=zb0(V,{conversationId:G.conversationId,channelId:G.channelId,channelName:G.channelName,interfaceType:G.interfaceType,userPermissionLevel:G.userPermissionLevel,enableCreateUpload:G.enableCreateUpload,enableCreateTransform:G.enableCreateTransform},X);return{...F,instructions:z3A(W.identity,G.userPermissionLevel,W.pluginInstructions,W.profile,W.agentInstructions,G.agentContextInstructions),tools:L,activeTools:b,...$!==void 0&&Y&&{temperature:$},...f!==void 0&&{maxTokens:f},...B&&{providerOptions:{anthropic:{webSearch:!0}}}}},tools:Z,stopWhen:[Hx2,rm(W.stepLimit??10)]})}}var Yx2;var V3A=i(()=>{ux();Z0();k9();lx();N10();F3A();Yx2=K.object({userPermissionLevel:K.enum(["anchor","trusted","public"]),conversationId:K.string(),channelId:K.string().optional(),channelName:K.string().optional(),interfaceType:K.string(),agentContextInstructions:K.string().optional(),disableTools:K.boolean().optional(),enableCreateUpload:K.boolean().optional(),enableCreateTransform:K.boolean().optional(),hasPriorResponseCandidate:K.boolean().optional()})});var j10=i(()=>{izA();lx();dzA();G3A();Wb0();V3A();N10()});function b3A(A){return{...A,...A.source!==void 0&&{source:I3A(A.source)},...A.target!==void 0&&{target:I3A(A.target)}}}function I3A(A){if(A instanceof RegExp)return A;if(!A.includes("*"))return A;let Q=A.split("*").map((w)=>w.replace(/[.+?^${}()|[\]\\]/g,"\\$&")).join(".*");return new RegExp(`^${Q}$`)}function L3A(A,Q){if(!Q)return!0;if(!J3A(A.source,Q.source))return!1;if(!J3A(A.target,Q.target,!0))return!1;if(!Wx2(A.metadata,Q.metadata))return!1;return Q.predicate?Q.predicate(A):!0}function J3A(A,Q,w=!1){if(!Q)return!0;if(w&&!A)return!1;return Zx2(A,Q)}function Wx2(A,Q){if(!Q)return!0;if(!A)return!1;return Object.entries(Q).every(([w,B])=>A[w]===B)}function Zx2(A,Q){if(!A)return!1;if(Q instanceof RegExp){Q.lastIndex=0;let w=Q.test(A);return Q.lastIndex=0,w}return A===Q}var M10,N3A;var Fb0=i(()=>{Z0();M10=K.object({success:K.boolean(),data:K.unknown().optional(),error:K.string().optional()}),N3A=K.object({id:K.string().min(1),timestamp:K.string(),type:K.string().min(1),source:K.string().min(1),target:K.string().optional(),metadata:K.record(K.string(),K.unknown()).optional()})});function j3A(A){let Q=Kx2.safeParse(A);if(!Q.success)throw Error("Invalid message response format");return Q.data}var Kx2;var M3A=i(()=>{Z0();Fb0();Kx2=K.union([K.object({noop:K.literal(!0)}),M10])});function P3A(A,Q,w,B,$){return{id:x3A("msg"),type:A,timestamp:R3A(),source:w,target:B,metadata:$,payload:Q}}function k3A(A,Q){let w=j3A(Q);if("noop"in w)return _3A(A,!0);return _3A(A,w.success,w.data,w.error)}function O3A(A,Q){if(Q?.success)return{success:!0,data:Q.data};return{success:!1,error:Q?.error?.message??`No handler found for message type: ${A}`}}function _3A(A,Q,w,B){return{id:x3A("resp"),requestId:A,timestamp:R3A(),success:Q,data:w,error:B?{message:B}:void 0}}function x3A(A){return`${A}-${Date.now()}-${Math.random().toString(36).slice(2,11)}`}function R3A(){return new Date().toISOString()}var Vb0=i(()=>{M3A()});class Ib0{handlers=new Map;add(A,Q,w){let B=this.createHandlerEntry(Q,w);return this.getOrCreateHandlers(A).add(B),B}remove(A,Q){let w=this.handlers.get(A);if(!w)return!1;let B=w.delete(Q);return this.deleteEmptyHandlerSet(A,w),B}removeHandler(A,Q){let w=this.handlers.get(A);if(!w)return;for(let B of Array.from(w))if(B.originalHandler===Q)w.delete(B);this.deleteEmptyHandlerSet(A,w)}getMatchingHandlers(A,Q){let w=this.handlers.get(A);if(!w||w.size===0)return;return{entries:Array.from(w).filter((B)=>L3A(Q,B.filter)),totalHandlers:w.size}}hasHandlers(A){let Q=this.handlers.get(A);return Q!==void 0&&Q.size>0}clearHandlers(A){return this.handlers.delete(A)}clearAllHandlers(){this.handlers.clear()}getHandlerCount(A){return this.handlers.get(A)?.size??0}getTargetedHandlerCount(A,Q){let w=this.handlers.get(A);if(!w)return 0;return Array.from(w).filter((B)=>B.filter?.target===Q).length}createHandlerEntry(A,Q){let w={handler:this.wrapHandler(A),originalHandler:A};return Q?{...w,filter:b3A(Q)}:w}wrapHandler(A){return async(Q)=>{let B=await A(Q);return k3A(Q.id,B)}}getOrCreateHandlers(A){let Q=this.handlers.get(A);if(!Q)Q=new Set,this.handlers.set(A,Q);return Q}deleteEmptyHandlerSet(A,Q){if(Q.size===0)this.handlers.delete(A)}}var h3A=i(()=>{Vb0()});async function v3A(A,Q,w){for(let B of Q)await y3A(B,A,w);return null}async function C3A(A,Q,w){for(let B of Q){let $=await y3A(B,A,w);if($)return $}return null}async function y3A(A,Q,w){try{return await A.handler(Q)}catch(B){return w.error(`Error in message handler for ${Q.type}`,B),null}}class Jb0{registry;logger;constructor(A,Q){this.registry=A;this.logger=Q}async publish(A,Q){if(typeof A!=="object"||!A.type||!A.id)return this.logger.error("Invalid message structure - missing required fields 'id' or 'type'"),null;let{type:w}=A;this.logger.debug(`Publishing message of type: ${w}`,{source:A.source,target:A.target,hasMetadata:!!A.metadata});let B=this.registry.getMatchingHandlers(w,A);if(!B)return this.logger.debug(`No handlers found for message type: ${w}`),null;if(B.entries.length===0)return this.logger.debug(`No matching handlers for message type: ${w}`,{totalHandlers:B.totalHandlers,target:A.target}),null;return Q===!0?v3A(A,B.entries,this.logger):C3A(A,B.entries,this.logger)}}var E3A=()=>{};function g3A(A,Q){try{return{valid:!0,data:Q.parse(A)}}catch(w){if(w instanceof K.ZodError)return{valid:!1,error:w.issues[0]?.message??"Validation failed"};return{valid:!1,error:"Unknown validation error"}}}var T3A=i(()=>{Z0()});class zZ{static instance=null;registry=new Ib0;publisher;logger;static getInstance(A){return zZ.instance??=new zZ(A),zZ.instance}static resetInstance(){zZ.instance=null}static createFresh(A){return new zZ(A)}constructor(A){this.logger=A,this.publisher=new Jb0(this.registry,A)}subscribe(A,Q,w){let B=this.registry.add(A,Q,w);return this.logger.debug(`Registered handler for message type: ${A}`,{hasFilter:!!w,filterTarget:w?.target}),()=>{this.registry.remove(A,B)}}async send(A){let{type:Q,payload:w,sender:B,target:$,metadata:f,broadcast:D}=A,Y=P3A(Q,w,B,$,f),X=await this.publisher.publish(Y,D);return O3A(Q,X)}validateMessage(A,Q){return g3A(A,Q)}hasHandlers(A){return this.registry.hasHandlers(A)}unsubscribe(A,Q){this.registry.removeHandler(A,Q)}clearHandlers(A){if(this.registry.clearHandlers(A))this.logger.info(`Cleared all handlers for message type: ${A}`)}clearAllHandlers(){this.registry.clearAllHandlers(),this.logger.info("Cleared all message handlers")}getHandlerCount(A){return this.registry.getHandlerCount(A)}getTargetedHandlerCount(A,Q){return this.registry.getTargetedHandlerCount(A,Q)}}var S3A=i(()=>{h3A();Vb0();E3A();T3A()});var Gx2;var m3A=i(()=>{Z0();Fb0();Gx2=K.object({id:K.string().min(1),requestId:K.string().min(1),success:K.boolean(),data:K.unknown().optional(),error:K.object({message:K.string(),code:K.string().optional()}).optional(),timestamp:K.string().datetime()})});var bb0=i(()=>{S3A();m3A()});var U6;var Lb0=i(()=>{uV();U6=KH("runtime_state_records",{namespace:IQ("namespace").notNull(),key:IQ("key").notNull(),value:IQ("value",{mode:"json"}).notNull(),createdAt:x9("created_at").notNull(),updatedAt:x9("updated_at").notNull()},(A)=>({pk:SO({columns:[A.namespace,A.key]}),namespaceUpdatedAtIdx:VY("idx_runtime_state_namespace_updated_at").on(A.namespace,A.updatedAt)}))});import{createClient as u3A}from"@libsql/client";function _10(A){let Q=A.url,w=A.authToken??process.env.RUNTIME_STATE_DATABASE_AUTH_TOKEN,B=w?u3A({url:Q,authToken:w}):u3A({url:Q});return{db:UH(B,{schema:{runtimeStateRecords:U6}}),client:B,url:Q}}async function P10(A,Q){if(Q.startsWith("file:"))await A.execute("PRAGMA journal_mode = WAL"),await A.execute("PRAGMA busy_timeout = 5000")}var Nb0=i(()=>{iO();Lb0()});class k10{db;namespace;schema;now;constructor(A,Q,w,B=()=>new Date){this.db=A;this.namespace=Q;this.schema=w;this.now=B;qx2(Q)}async get(A){let Q=Wu(A),B=(await this.db.select().from(U6).where(LB(_2(U6.namespace,this.namespace),_2(U6.key,Q))).limit(1))[0];if(!B)return null;return this.schema.parse(B.value)}async has(A){let Q=Wu(A);return(await this.db.select({key:U6.key}).from(U6).where(LB(_2(U6.namespace,this.namespace),_2(U6.key,Q))).limit(1)).length>0}async set(A,Q){let w=Wu(A),B=this.schema.parse(Q),$=this.now().getTime();await this.db.insert(U6).values({namespace:this.namespace,key:w,value:B,createdAt:$,updatedAt:$}).onConflictDoUpdate({target:[U6.namespace,U6.key],set:{value:B,updatedAt:$}})}async setIfNotExists(A,Q){let w=Wu(A),B=this.schema.parse(Q),$=this.now().getTime(),f=await this.db.insert(U6).values({namespace:this.namespace,key:w,value:B,createdAt:$,updatedAt:$}).onConflictDoNothing({target:[U6.namespace,U6.key]});return Number(f.rowsAffected)>0}async delete(A){let Q=Wu(A),w=await this.db.delete(U6).where(LB(_2(U6.namespace,this.namespace),_2(U6.key,Q)));return Number(w.rowsAffected)>0}async list(A={}){let Q=await this.listRows(),w=A.keyPrefix;if(w!==void 0)c3A(w);return Q.filter((B)=>w===void 0||B.key.startsWith(w)).map((B)=>({key:B.key,value:this.schema.parse(B.value),createdAt:new Date(B.createdAt),updatedAt:new Date(B.updatedAt)}))}async clear(A={}){let Q=A.keyPrefix;if(Q===void 0){let B=await this.db.delete(U6).where(_2(U6.namespace,this.namespace));return Number(B.rowsAffected)}c3A(Q);let w=await this.list({keyPrefix:Q});return await Promise.all(w.map((B)=>this.delete(B.key))),w.length}async listRows(){return this.db.select().from(U6).where(_2(U6.namespace,this.namespace))}}function qx2(A){if(!zx2.test(A))throw Error(`Invalid runtime state namespace: ${A}. Use 1-128 alphanumeric, _, ., :, or - characters.`)}function Wu(A){if(A.length===0||A.length>l3A)throw Error("Runtime state keys must be 1-512 characters long");return A}function c3A(A){if(A.length>l3A)throw Error("Runtime state key prefixes must be 512 characters or shorter");return A}var zx2,l3A=512;var jb0=i(()=>{$q();Lb0();zx2=/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,127}$/});class JH{static instance=null;db;client;logger;static getInstance(A,Q){return JH.instance??=new JH(A,Q??e2.getInstance()),JH.instance}static createFresh(A,Q){return new JH(A,Q??e2.getInstance())}static resetInstance(){JH.instance?.close(),JH.instance=null}constructor(A,Q){let{db:w,client:B,url:$}=_10(A);this.db=w,this.client=B,this.logger=Q.child("RuntimeStateService"),P10(B,$).catch((f)=>{this.logger.warn("Failed to enable runtime state WAL mode (non-fatal)",f)})}scoped(A){return new k10(this.db,A.namespace,A.schema)}close(){this.client.close()}}var p3A=i(()=>{Z0();Nb0();jb0()});var Mb0=i(()=>{p3A();jb0()});async function i3A(A,Q){if(A.status==="running"){Q.warn(`Daemon already running: ${A.name}`);return}A.status="starting",delete A.error;try{await A.daemon.start(),A.status="running",A.startedAt=new Date,Q.debug(`Daemon started successfully: ${A.name}`)}catch(w){throw A.status="error",A.error=fH(w),Q.warn(`Daemon ${A.name} failed to start: ${vA(w)}`),w}}async function d3A(A,Q){if(A.status==="stopped"){Q.warn(`Daemon already stopped: ${A.name}`);return}A.status="stopping";try{await A.daemon.stop(),A.status="stopped",A.stoppedAt=new Date,Q.debug(`Daemon stopped successfully: ${A.name}`)}catch(w){throw A.status="error",A.error=fH(w),Q.error(`Failed to stop daemon: ${A.name}`,w),w}}async function n3A(A){if(!A.daemon.healthCheck)return;try{let Q=await A.daemon.healthCheck();return A.health=Q,Q}catch(Q){let w={status:"error",message:vA(Q),lastCheck:new Date};return A.health=w,w}}function r3A(A){return{name:A.name,pluginId:A.pluginId,status:A.status,health:A.health}}var o3A=i(()=>{Z0()});class _U{static instance=null;daemons=new Map;logger;static getInstance(A=e2.getInstance()){return _U.instance??=new _U(A),_U.instance}static resetInstance(){_U.instance=null}static createFresh(A){return new _U(A)}constructor(A){this.logger=A.child("DaemonRegistry")}register(A,Q,w){if(this.daemons.has(A))this.logger.warn(`Daemon already registered: ${A}, overwriting`);let B={name:A,daemon:Q,pluginId:w,status:"stopped"};this.daemons.set(A,B),this.logger.debug(`Registered daemon: ${A} from plugin: ${w}`)}has(A){return this.daemons.has(A)}get(A){return this.daemons.get(A)}async start(A){let Q=this.daemons.get(A);if(!Q)throw Error(`Daemon not registered: ${A}`);await i3A(Q,this.logger)}async stop(A){let Q=this.daemons.get(A);if(!Q)throw Error(`Daemon not registered: ${A}`);await d3A(Q,this.logger)}async checkHealth(A){let Q=this.daemons.get(A);if(!Q)throw Error(`Daemon not registered: ${A}`);return n3A(Q)}getByPlugin(A){return Array.from(this.daemons.values()).filter((Q)=>Q.pluginId===A)}getAll(){return Array.from(this.daemons.keys())}getAllInfo(){return Array.from(this.daemons.values())}async getStatuses(){let A=this.getAllInfo();for(let Q of A)if(Q.daemon.healthCheck)await this.checkHealth(Q.name);return A.map(r3A)}async unregister(A){let Q=this.daemons.get(A);if(!Q){this.logger.warn(`Daemon not registered: ${A}`);return}if(Q.status==="running")await this.stop(A);this.daemons.delete(A),this.logger.debug(`Unregistered daemon: ${A}`)}async startPlugin(A){let Q=this.getByPlugin(A);this.logger.debug(`Starting ${Q.length} daemons for plugin: ${A}`);let w;for(let B of Q)try{await this.start(B.name)}catch($){w??=fH($)}if(w)throw w}async stopPlugin(A){let Q=this.getByPlugin(A);this.logger.debug(`Stopping ${Q.length} daemons for plugin: ${A}`);for(let w of Q)try{await this.stop(w.name)}catch(B){this.logger.error(`Failed to stop daemon: ${w.name}`,B)}}async clear(){this.logger.debug("Clearing all daemons");let A=Array.from(this.daemons.values()).filter((Q)=>Q.status==="running");for(let Q of A)try{await this.stop(Q.name)}catch(w){this.logger.error(`Failed to stop daemon during clear: ${Q.name}`,w)}this.daemons.clear(),this.logger.debug("All daemons cleared")}}var _b0=i(()=>{Z0();o3A()});function Pb0(A,Q,w,B,$){return["entity:created","entity:updated","entity:deleted"].map((D)=>A.subscribe(D,async(Y)=>{if(Y.payload.entityType===Q&&(w===null||Y.payload.entityId===w)){await B();let X=D.replace("entity:","");$.debug(`${Q} entity ${X}, cache refreshed`)}return{success:!0}}))}async function Fx2(A,Q,w){let B=Vx2(A.kind);if(!B)return null;try{let $=Q.scoped({namespace:B,refKind:A.kind,routePath:""});return Ix2(await $.read(A.id),A)}catch($){return w.debug("Skipped unavailable prior runtime upload",{uploadKind:A.kind,uploadId:A.id,error:$ instanceof Error?$.message:String($)}),null}}function Vx2(A){return A==="upload"?"upload":null}function Ix2(A,Q){let{record:w,content:B}=A;if(Jx2(w.mediaType))return{kind:"text",filename:w.filename,mediaType:w.mediaType,content:new TextDecoder("utf-8").decode(B).replace(/^\uFEFF/,""),sizeBytes:w.sizeBytes,source:Q};return{kind:"file",filename:w.filename,mediaType:w.mediaType,data:new Uint8Array(B),sizeBytes:w.sizeBytes,source:Q}}function Jx2(A){let Q=A.toLowerCase();return Q.startsWith("text/")||Q==="application/json"}function s3A(A){let{config:Q,entityService:w,logger:B,messageBus:$,aiService:f,mcpService:D,conversationService:Y,runtimeUploadRegistry:X,disposables:H}=A,W=GH.getInstance(w,B,Q.identity);H.push(...Pb0($,Af.BRAIN_CHARACTER,Af.BRAIN_CHARACTER,()=>W.refreshCache(),B));let Z=e4.getInstance(w,B,Q.profile),G=Gq.getInstance(B),F=qb0({model:f.getModel(),modelId:f.getConfig().model,webSearch:f.getConfig().webSearch,temperature:f.getConfig().temperature,maxTokens:f.getConfig().maxTokens,messageBus:$}),V=Xb0(Q.name),b=BD.getInstance(D,Y,W,Z,B,{agentFactory:F,canonicalIdentityResolver:G,indexReadiness:w,uploadAttachmentResolver:(L)=>Fx2(L,X,B),agentContextProvider:async(L)=>{let N=await $.send({type:BN,sender:"shell:agent-service",payload:L});if("noop"in N||!N.success)return[];return vZ0(N.data)},...V?{assistantActorId:V}:{},...Q.agentInstructions&&{agentInstructions:Q.agentInstructions}});H.push(...Pb0($,Af.ANCHOR_PROFILE,Af.ANCHOR_PROFILE,()=>Z.refreshCache(),B));for(let L of[Af.BRAIN_CHARACTER,Af.ANCHOR_PROFILE])H.push(...Pb0($,L,L,async()=>b.invalidateAgent(),B));return{identityService:W,profileService:Z,canonicalIdentityService:G,agentService:b}}var a3A=i(()=>{j10();CB();zq();xN()});function t3A(A){let{dependencies:Q,jobQueueService:w,messageBus:B,logger:$}=A,f=Q?.batchJobManager??sW.getInstance(w,$),D=Q?.jobProgressMonitor??aW.getInstance(w,B,f,$),Y=Q?.jobQueueWorker??oW.getInstance(w,D,$,{pollInterval:100,concurrency:1,autoStart:!1});return{batchJobManager:f,jobProgressMonitor:D,jobQueueWorker:Y}}var e3A=i(()=>{fq()});function AFA(A,Q){if(Q)return Q;let w={debug:2,info:3,warn:4,error:5}[A.logging.level];return e2.createFresh({level:w,context:A.logging.context,format:A.logging.format==="json"?"json":"text",...A.logging.file?{logFile:A.logging.file}:{}})}function QFA(A){return{apiKey:A.ai.apiKey,model:A.ai.model,temperature:A.ai.temperature,maxTokens:A.ai.maxTokens,webSearch:A.ai.webSearch,...A.ai.imageApiKey?{imageApiKey:A.ai.imageApiKey}:{}}}function WR(A){return{url:A.url,...A.authToken?{authToken:A.authToken}:{}}}var wFA=i(()=>{Z0()});function BFA(A){let{config:Q,dependencies:w,initializerLogger:B}=A;B.debug("Initializing Shell services");let $=AFA(Q,w?.logger),f=[],D=w?.embeddingService??UZ.getInstance({apiKey:Q.ai.apiKey,logger:$}),Y=w?.aiService??KZ.getInstance(QFA(Q),$),X=JY.getInstance($),H=w?.messageBus??zZ.getInstance($),W=w?.templateRegistry??DH.getInstance($),Z=w?.dataSourceRegistry??tW.getInstance($),G=w?.renderService??lW.getInstance(W),F=w?.daemonRegistry??_U.getInstance($),V=w?.pluginManager??zH.getInstance($,F),b=w?.permissionService??new m$(Q.permissions,{spaces:Q.spaces}),L=w?.attachmentRegistry??eW.getInstance(),N=w?.runtimeUploadRegistry??bS.createFresh({dataDir:Q.dataDir}),_=w?.runtimeStateService??JH.createFresh(WR(Q.runtimeStateDatabase),$),j=w?.mcpService??YH.getInstance(H,$),g=w?.jobQueueService??IY.getInstance(WR(Q.jobQueueDatabase),$),E=LY.getInstance({embeddingService:D,entityRegistry:X,logger:$,jobQueueService:g,messageBus:H,dbConfig:WR(Q.database),embeddingDbConfig:WR(Q.embeddingDatabase)}),y=w?.conversationService??of.getInstance($,H,WR(Q.conversationDatabase)),h=w?.contentService??new j00({logger:$,entityService:E,aiService:Y,templateRegistry:W,dataSourceRegistry:Z}),{identityService:T,profileService:S,canonicalIdentityService:c,agentService:m}=s3A({config:Q,entityService:E,entityRegistry:X,logger:$,messageBus:H,aiService:Y,mcpService:j,conversationService:y,runtimeUploadRegistry:N,disposables:f}),{batchJobManager:B0,jobProgressMonitor:a,jobQueueWorker:v}=t3A({dependencies:w,jobQueueService:g,messageBus:H,logger:$});return{logger:$,disposables:f,entityRegistry:X,messageBus:H,renderService:G,daemonRegistry:F,pluginManager:V,templateRegistry:W,dataSourceRegistry:Z,mcpService:j,embeddingService:D,entityService:E,aiService:Y,conversationService:y,contentService:h,jobQueueService:g,jobQueueWorker:v,batchJobManager:B0,jobProgressMonitor:a,permissionService:b,identityService:T,profileService:S,canonicalIdentityService:c,agentService:m,attachmentRegistry:L,runtimeUploadRegistry:N,runtimeStateService:_}}var $FA=i(()=>{j10();_00();NN();aB();aB();fq();k9();bb0();c0();Mb0();JB();_b0();a3A();e3A();wFA()});function fFA(A,Q){A.register(uS.name,uS),Q.debug("Shell system templates registered")}function DFA(A,Q){A.register(Ux.BASE_ENTITY_DISPLAY,{name:"base-entity-display",description:"Display template for base entities",schema:o1,formatter:new Ee,requiredPermission:"public"}),Q.debug("Base entity display template registered")}function YFA(A,Q){A.registerEntityType(Af.NOTE,o1,new IS),Q.debug("Fallback base entity adapter registered")}function XFA(A,Q){let w=new Hx;A.registerEntityType(Af.BRAIN_CHARACTER,w.schema,w),Q.debug("Brain character entity support registered")}function HFA(A,Q){let w=new VU;A.registerEntityType(Af.ANCHOR_PROFILE,w.schema,w),Q.debug("Anchor profile entity support registered")}async function WFA(A){let{plugins:Q,pluginManager:w,logger:B,initOptions:$}=A;B.debug(`Found ${Q.length} plugins to register`);for(let f of Q)B.debug(`Registering plugin: ${f.id}`),w.registerPlugin(f);if(await w.initializePlugins($?.registrationContext),!$?.registerOnly){for(let{id:f,error:D}of w.getFailedPlugins())if(w.getPlugin(f)?.requiresDaemonStartup?.())throw D}B.debug("Plugin initialization complete")}var ZFA=i(()=>{_00();aB();zq();xN()});function KFA(){LY.resetInstance(),JY.resetInstance(),tW.resetInstance(),UZ.resetInstance(),of.resetInstance(),zH.resetInstance(),YH.resetInstance(),zZ.resetInstance(),DH.resetInstance(),lW.resetInstance(),_U.resetInstance(),KZ.resetInstance(),BD.resetInstance(),GH.resetInstance(),e4.resetInstance(),IY.resetInstance(),sW.resetInstance(),oW.resetInstance(),aW.resetInstance(),eW.resetInstance(),JH.resetInstance()}var UFA=i(()=>{j10();NN();aB();zq();fq();k9();bb0();c0();Mb0();JB();_b0()});class qZ{static instance=null;logger;config;static getInstance(A,Q){return qZ.instance??=new qZ(A,Q),qZ.instance}static resetInstance(){qZ.instance=null}static createFresh(A,Q){return new qZ(A,Q)}constructor(A,Q){this.logger=A.child("ShellInitializer"),this.config=Q}registerShellTemplates(A){fFA(A,this.logger)}registerBaseEntityDisplayTemplate(A){DFA(A,this.logger)}registerFallbackBaseEntity(A){YFA(A,this.logger)}registerBrainCharacterSupport(A){XFA(A,this.logger)}registerAnchorProfileSupport(A){HFA(A,this.logger)}async initializePlugins(A,Q){await WFA({plugins:this.config.plugins,pluginManager:A,logger:this.logger,initOptions:Q})}initializeServices(A){return BFA({config:this.config,dependencies:A,initializerLogger:this.logger})}registerJobHandlers(A,Q,w){let B=qq.createFresh(Q,w);A.registerHandler("shell:content-generation",B,"shell")}wireShell(A,Q){A.pluginManager.setShell(Q)}async initializeAll(A,Q,w,B){this.logger.debug("Starting Shell initialization");try{if(this.registerShellTemplates(A),this.registerBaseEntityDisplayTemplate(A),this.registerBrainCharacterSupport(Q),this.registerAnchorProfileSupport(Q),await this.initializePlugins(w,B),!Q.hasEntityType(Af.NOTE))this.registerFallbackBaseEntity(Q);this.logger.debug("Shell registration phase complete")}catch($){throw this.logger.error("Shell initialization failed",$),$}}}function Zu(){qZ.resetInstance(),KFA()}async function GFA(){let{Shell:A}=await Promise.resolve().then(() => (kb0(),zFA));await A.resetInstance(),Zu()}var O10=i(()=>{_00();xN();$FA();ZFA();UFA()});class Ob0{config;services;hooks;constructor(A,Q,w){this.config=A;this.services=Q;this.hooks=w}async boot(A){this.services.logger.debug("Starting Shell boot");let Q=qZ.getInstance(this.services.logger,this.config);if(await this.services.entityService.initialize(),await Q.initializeAll(this.services.templateRegistry,this.services.entityRegistry,this.services.pluginManager,{...A?.mode==="register-only"&&{registerOnly:!0},...this.config.entityDisplay!==void 0&&{registrationContext:{entityDisplay:this.config.entityDisplay}}}),Q.registerJobHandlers(this.services.jobQueueService,this.services.contentService,this.services.entityService),this.hooks.registerCoreDataSources(),this.hooks.registerSystemCapabilities(),A?.mode==="register-only"){this.services.logger.debug("Shell boot complete (register-only mode)");return}if(A?.mode!=="startup-check"){await this.startEarlyWebserver(),await this.emitPluginsRegistered();let w=await this.services.entityService.backfillMissingEmbeddings();this.services.logger.debug("Queued missing embedding backfill jobs",{queued:w.queued,skipped:w.skipped})}if(await this.prepareReadyState(),await this.services.pluginManager.readyPlugins(),A?.mode==="startup-check"){this.services.logger.debug("Shell boot complete (startup-check mode)");return}await this.startRuntimeServices(),this.startIndexReadinessMonitor(),this.services.logger.debug("Shell boot complete")}async startEarlyWebserver(){if(!this.services.daemonRegistry.has("webserver:webserver"))return;await this.services.daemonRegistry.start("webserver:webserver"),this.services.logger.debug("Started webserver before initial sync")}async emitPluginsRegistered(){await this.services.messageBus.send({type:VN.pluginsRegistered,payload:{timestamp:new Date().toISOString(),pluginCount:this.services.pluginManager.getAllPluginIds().length},sender:"shell",broadcast:!0}),this.services.logger.debug("Emitted plugins registered event")}async prepareReadyState(){await Promise.all([this.services.identityService.initialize(),this.services.profileService.initialize(),this.services.canonicalIdentityService.refreshCache()]),this.services.logger.debug("Identity services initialized");let A=await RU0(this.services.templateRegistry,this.services.entityService);if(A>0)this.services.logger.debug(`Materialized ${A} prompt entities`)}async startRuntimeServices(){await this.services.pluginManager.startPluginDaemons(),await this.services.jobQueueWorker.start(),this.services.jobProgressMonitor.start(),this.services.batchJobManager.start()}startIndexReadinessMonitor(){this.runIndexReadinessMonitor()}async runIndexReadinessMonitor(){for(;;){try{let A=await this.services.entityService.awaitIndexReady({timeoutMs:Lx2});if(A.ready){if(A.degraded)this.services.logger.warn("Semantic index ready with degraded embeddings",A);else this.services.logger.debug("Semantic index ready",A);return}this.services.logger.warn("Semantic index not ready yet; retrying readiness monitor",A)}catch(A){this.services.logger.warn("Semantic index readiness monitor failed; retrying",A)}await this.delayIndexReadinessRetry()}}async delayIndexReadinessRetry(){await new Promise((A)=>{setTimeout(A,Nx2).unref()})}}var Lx2=30000,Nx2=5000;var qFA=i(()=>{c0();O10()});class FFA{handlers=new Map;register(A,Q){this.handlers.set(A,Q)}getTypes(){return Array.from(this.handlers.keys())}async get(A,Q,w){let B=this.handlers.get(A);if(!B)throw Error(`Unknown insight type: ${A}. Available: ${this.getTypes().join(", ")}`);return B(Q,w)}}function VFA(){let A=new FFA;return A.register("overview",jx2),A.register("publishing-cadence",Mx2),A.register("content-health",_x2),A}async function jx2(A,Q){let w=await A.getEntityCounts(Q),B={},$=0;for(let{entityType:F,count:V}of w)B[F]=V,$+=V;let f=await xb0(A,Q),D=Date.now(),Y=D-604800000,X=D-2592000000,H=0,W=0;for(let F of f){let V=new Date(F.created).getTime();if(V>=Y)H++;if(V>=X)W++}let Z=IFA(f),G=f.filter((F)=>F.metadata.status==="published");return{entityCounts:B,totalEntities:$,recentActivity:{last7days:H,last30days:W},contentHealth:{drafts:Z.length,published:G.length}}}async function Mx2(A,Q){let w=await xb0(A,Q),B=new Map;for(let f of w){let D=new Date(f.created);if(isNaN(D.getTime()))continue;let Y=`${D.getUTCFullYear()}-${String(D.getUTCMonth()+1).padStart(2,"0")}`,X=B.get(Y);if(!X)X={},B.set(Y,X);X[f.entityType]=(X[f.entityType]??0)+1}return{months:Array.from(B.entries()).sort((f,D)=>D[0].localeCompare(f[0])).map(([f,D])=>{let Y=0;for(let X of Object.values(D))Y+=X;return{month:f,counts:D,total:Y}})}}async function _x2(A,Q){let w=await xb0(A,Q),B=IFA(w).map((Y)=>({id:Y.id,entityType:Y.entityType,title:typeof Y.metadata.title==="string"?Y.metadata.title:Y.id,created:Y.created})),$=Date.now(),f=$-7776000000,D=w.filter((Y)=>{if(Y.entityType==="image")return!1;let X=new Date(Y.updated).getTime();return!isNaN(X)&&X<f}).map((Y)=>({id:Y.id,entityType:Y.entityType,title:typeof Y.metadata.title==="string"?Y.metadata.title:Y.id,updated:Y.updated,daysSinceUpdate:Math.floor(($-new Date(Y.updated).getTime())/86400000)}));return{drafts:B,stale:D}}function IFA(A){return A.filter((Q)=>Q.metadata.status==="draft")}async function xb0(A,Q){let w=A.getEntityTypes(),B=[];for(let $ of w){let f=await A.listEntities({entityType:$,options:{limit:1000,filter:{visibilityScope:Q}}});B.push(...f)}return B}class Ku{parse;idOf;items=new Map;constructor(A,Q){this.parse=A;this.idOf=Q}register(A){let Q=this.parse(A);this.items.set(this.keyFor(Q.pluginId,this.idOf(Q)),Q)}unregister(A,Q){if(Q!==void 0){this.items.delete(this.keyFor(A,Q));return}let w=`${A}:`;for(let B of this.items.keys())if(B.startsWith(w))this.items.delete(B)}list(){return Array.from(this.items.values()).sort((A,Q)=>A.priority-Q.priority||A.label.localeCompare(Q.label))}keyFor(A,Q){return`${A}:${Q}`}}var Rb0;var JFA=i(()=>{c0();Rb0=class Rb0 extends Ku{constructor(){super((A)=>RO.parse(A),(A)=>A.url)}}});var hb0;var bFA=i(()=>{c0();hb0=class hb0 extends Ku{constructor(){super((A)=>hO.parse(A),(A)=>A.id)}}});function LFA(A,Q){return{enqueueBatch:A.enqueueBatch.bind(A),getActiveBatches:A.getActiveBatches.bind(A),getBatchStatus:A.getBatchStatus.bind(A),getActiveJobs:Q.getActiveJobs.bind(Q),getStatus:Q.getStatus.bind(Q)}}function NFA(A){let Q=[];for(let[w,B]of A.getAllPlugins()){let{plugin:$}=B;if("getApiRoutes"in $&&typeof $.getApiRoutes==="function")for(let f of $.getApiRoutes())Q.push({pluginId:w,fullPath:`/api/${w}${f.path}`,definition:f})}return Q}function jFA(A){let Q=[];for(let[w,B]of A.getAllPlugins()){let{plugin:$}=B;if("getWebRoutes"in $&&typeof $.getWebRoutes==="function")for(let f of $.getWebRoutes())Q.push({pluginId:w,fullPath:f.path,definition:f})}return Q}async function MFA(A){A.batchJobManager.stop(),A.jobProgressMonitor.stop(),await A.jobQueueWorker.stop();for(let[Q]of A.pluginManager.getAllPlugins())await A.pluginManager.disablePlugin(Q);for(let Q of A.disposables.splice(0))try{Q()}catch(w){A.logger.warn("Failed to dispose shell subscription",w)}A.entityService.close(),A.jobQueueService.close(),A.conversationService.close(),A.runtimeStateService.close()}var Px2,_FA,PFA,kFA,kx2,Ox2,xx2,OFA,xFA,RFA,hFA,vFA,CFA,yFA,Z5B,K5B;var Rq=i(()=>{aB();Z0();Px2=K.discriminatedUnion("kind",[K.object({kind:K.literal("all")}).strict().describe("Search across all entity types"),K.object({kind:K.literal("type"),entityType:K.string().min(1).describe("Entity type to search")}).strict().describe("Search within one entity type")]),_FA=K.object({query:K.string().describe("Search term"),scope:Px2.describe("Structured search scope. Use { kind: 'all' } for broad search across all entity types. Use { kind: 'type', entityType } only when the user asks for a specific entity type."),limit:K.number().optional().describe("Maximum number of results"),includeUngenerated:K.boolean().optional().describe("Include queued/failed generation stubs in results")}),PFA=K.object({entityType:K.string().describe("Entity type"),id:K.string().describe("Entity ID, slug, or title")}),kFA=K.object({entityType:K.string().describe("Entity type to list"),status:K.string().optional().describe("Filter by status. Omit unless the user asks for a known status; do not invent generic statuses. For wish statuses: new, planned, in-progress, done, declined."),limit:K.number().optional().describe("Maximum number of results (default: 20)")}),kx2=K.object({kind:K.literal("upload").describe("Upload ref kind"),id:K.string().min(1).describe("Upload ID")}),Ox2=K.discriminatedUnion("kind",[K.object({kind:K.literal("text").describe("Store exact/direct user-provided content without generation"),content:K.string().min(1).describe("Exact markdown/text/content to persist as provided. For direct save requests where the user includes the content in the same message, use that provided content directly.")}).strict(),K.object({kind:K.literal("url").describe("Create URL/domain-backed entities such as links"),url:K.string().min(1).describe("URL or domain to create from; preserve a bare domain as provided instead of adding a scheme.")}).strict(),K.object({kind:K.literal("upload").describe("Use extract-markdown to import upload text into a note, or preserve only when the user explicitly wants to save the uploaded file/document bytes themselves. Do not use for saving a previous assistant summary about an upload; use prior-response for that."),upload:kx2.describe("Exact upload candidate object from the current conversation"),transform:K.enum(["extract-markdown","preserve"]).describe("extract-markdown imports upload text into a note-like entity; preserve saves raw uploaded bytes via the registered upload-save handler and derives the durable entity type from media type. Use preserve only for explicit file/document preservation, not for saving an assistant summary response.")}).strict(),K.object({kind:K.literal("prior-response").describe("Save a previous assistant response as durable content, especially an assistant summary or answer about an upload."),messageId:K.string().min(1).optional().describe("Stored assistant message ID; omit for latest savable")}).strict()]),xx2=K.discriminatedUnion("kind",[K.object({kind:K.literal("prompt").describe("Generate a new non-image durable entity from a broad prompt with no durable source entity. Use this for general topical social/newsletter/blog/deck generation. This branch has no source field; use prompt-from-source only after resolving a specific existing content entity."),entityType:K.string().min(1).describe("Entity type to generate from the prompt. Do not use image here; use standalone-image or cover-image."),title:K.string().optional().describe("Title for the generated entity"),prompt:K.string().min(1).describe("Prompt for creating new generated content. Do not use for saving/importing existing uploads or prior responses.")}).strict(),K.object({kind:K.literal("prompt-from-source").describe("Generate a new non-image durable entity from a specific resolved existing content entity. Use when the user asks to generate from/based on a source, including requests like 'create a newsletter based on my latest blog post'. After resolving the source with a tool result, call this operation in the same turn; do not merely say you can generate it."),entityType:K.string().min(1).describe("Entity type to generate from the source and prompt. Do not use image here; use standalone-image or cover-image."),title:K.string().optional().describe("Title for the generated entity"),source:K.object({entityType:K.string().min(1).describe("Resolved content source entity type, such as post for a newsletter from a blog post. Do not use brain-character or anchor-profile."),entityId:K.string().min(1).describe("Resolved source entity ID copied from a prior tool result or typed entity ref; never an upload id, filename, guessed slug, or future placeholder.")}).strict().describe("Existing durable source entity to ground this generation. Use only resolved entity refs, not uploads, filenames, profile/brain-character context, conversation-only context, unknown sources, or guessed sources."),prompt:K.string().min(1).describe("Prompt for creating new generated content from the resolved source. Do not use for saving/importing existing uploads or prior responses.")}).strict(),K.object({kind:K.literal("standalone-image").describe("Generate a standalone image that is not attached to another entity. Do not use this as a cover image substitute; requested covers require cover-image after the target entity exists."),title:K.string().optional().describe("Title for the generated image"),prompt:K.string().min(1).describe("Prompt for creating an unattached image. Not for cover images requested for a generated post/entity.")}).strict(),K.object({kind:K.literal("cover-image").describe("Generate an image and attach it to an existing entity as coverImageId. Use only after the target entity already exists and its real entityId is known; do not use in the same initial turn as generating that target entity."),target:K.object({entityType:K.string().min(1).describe("Existing target entity type. Use the actual type of the entity being covered: social-post for LinkedIn/social posts, post for blog posts, etc."),entityId:K.string().min(1).describe("Existing target entity ID copied from a prior tool result or typed entity ref; never a placeholder or guessed future id")}).strict().describe("Existing entity that should receive the generated coverImageId"),title:K.string().optional().describe("Title for the generated image"),prompt:K.string().min(1).describe("Prompt for creating the cover image")}).strict(),K.object({kind:K.literal("attachment").describe("Generate a deterministic durable artifact from an existing entity attachment provider"),source:K.object({entityType:K.string().min(1).describe("Source entity type"),entityId:K.string().min(1).describe("Canonical source entity ID copied from a prior tool result or typed entity ref; never an upload id, filename, guessed slug, or future placeholder")}).strict().describe("Existing durable entity whose attachment provider should render the artifact. Use only resolved entity refs, not uploads or conversation-only context."),attachmentType:K.string().min(1).describe('Source artifact type such as "carousel", "printable", or "og-image"'),title:K.string().optional().describe("Title for the generated artifact"),replace:K.boolean().optional().describe("Set true for regenerate, replace, refresh, or update requests so a deterministic artifact is regenerated instead of reused")}).strict()]),OFA=K.object({entityType:K.string().describe("Entity type to create. Use wish for explicitly saved or tracked unmet requested capabilities or outcomes."),title:K.string().optional().describe("Title for a new entity."),source:Ox2.describe("Concrete source selector. Use exactly one source branch. For AI generation or source-derived artifacts, use system_generate instead."),replace:K.boolean().optional().describe("Create a new copy intentionally"),confirmed:K.literal(!0).optional().describe("Confirm the creation"),confirmationToken:K.string().optional().describe("Internal confirmation token returned by the confirmation flow")}).strict(),xFA=K.object({operation:xx2.describe("Generation operation selector. Use prompt for broad non-image AI-generated entities with no source, prompt-from-source for generation from a resolved existing entity, standalone-image for unattached images, cover-image for generated covers on existing entities, and attachment for deterministic source-derived artifacts; for regenerate/replace/refresh artifact requests use attachment with replace:true."),confirmed:K.literal(!0).optional().describe("Confirm generation"),confirmationToken:K.string().optional().describe("Internal confirmation token returned by the confirmation flow")}).strict(),RFA=K.object({entityType:K.string().describe("Entity type"),id:K.string().describe("Entity ID, slug, or title"),fields:K.record(K.unknown()).optional().describe("Partial frontmatter fields to update. Use this for status, title, coverImageId, ogImageId, and metadata changes such as approving an agent. To set an existing image as an entity cover, update fields.coverImageId to that image id. To remove or clear a cover image, set fields.coverImageId to null, not an empty string. Do not use fields for anchor-profile; anchor-profile updates require full markdown content replacement via content."),content:K.string().optional().describe("Full markdown content replacement only. Do not use this for status/title/frontmatter updates; use fields instead."),confirmed:K.literal(!0).optional().describe("Confirm the update"),contentHash:K.string().optional().describe("Content hash for optimistic concurrency")}),hFA=K.object({entityType:K.string().describe("Entity type"),id:K.string().describe("Entity ID"),confirmed:K.literal(!0).optional().describe("Confirm the deletion"),confirmationToken:K.string().optional().describe("Internal confirmation token returned by the confirmation flow")}),vFA=K.object({entityType:K.string().describe("Entity type to extract"),source:K.string().optional().describe("Source entity ID \u2014 omit for batch"),mode:K.enum(["derive","rebuild"]).optional().describe("Batch mode: project incrementally or rebuild from scratch"),confirmed:K.literal(!0).optional().describe("Confirm destructive rebuild")}),CFA=K.object({batchId:K.string().optional().describe("Specific batch ID to check"),jobTypes:K.array(K.string()).optional().describe("Filter by job types")}),yFA=K.object({type:K.string().describe("Type of insight to retrieve. Built-in: overview, publishing-cadence, content-health. Plugins may register additional types.")}),Z5B=K.object({entityId:K.string().optional(),status:K.enum(["created","generating"]),jobId:K.string().optional(),attachment:qU0.optional()}),K5B=K.object({status:K.literal("extracting"),jobId:K.string(),entityType:K.string(),source:K.string().optional(),mode:K.enum(["derive","rebuild"]).optional()})});function bH(A,Q,w,B){try{A.permissionService.assertEntityActionAllowed(Q,w,B.userPermissionLevel);return}catch($){if($ instanceof ST||$ instanceof Error)return{success:!1,error:$.message};throw $}}var ZR=i(()=>{JB()});function LH(A,Q,w,B,$={}){let{visibility:f="anchor",sideEffects:D}=$;return{name:`${Rx2}_${A}`,description:Q,inputSchema:w.shape,handler:async(Y,X)=>{let H=w.safeParse(Y);if(!H.success)return{success:!1,error:`Invalid input: ${H.error.errors.map((W)=>`${W.path.join(".")}: ${W.message}`).join(", ")}`};try{return await B(H.data,X)}catch(W){return{success:!1,error:vA(W)}}},visibility:f,...D?{sideEffects:D}:{}}}function hq(A,Q){if(A.entityRegistry.hasEntityType(Q))return;let w=A.entityService.getEntityTypes();return{success:!1,error:`Entity type "${Q}" is not available in this brain. Available types: ${w.join(", ")}.`}}function KR(A){let Q={...A.conversationId?{conversationId:A.conversationId}:{},...A.channelId?{channelId:A.channelId}:{},...A.runId?{runId:A.runId}:{},...A.toolCallId?{toolCallId:A.toolCallId}:{}};return Object.keys(Q).length>0?Q:void 0}function vb0(A){if(A.entityType==="image"&&A.content.startsWith("data:"))return{...A,content:"[binary image data \u2014 use metadata for image info]"};return A}function Dj(A){if(A===void 0)return;let Q=A.trim();return Q.length>0?Q:void 0}function gFA(A){if(A.fields)return{fields:A.fields};if(!A.content)return{};try{let Q=JSON.parse(A.content);if(typeof Q==="object"&&Q!==null&&!Array.isArray(Q)){if("fields"in Q&&typeof Q.fields==="object"&&Q.fields!==null&&!Array.isArray(Q.fields))return{fields:Q.fields};return{fields:Q}}}catch{}return{content:A.content}}function TFA(A){return hx2[A]??A.replaceAll("-"," ")}function x10(A){return[A.metadata.title,A.metadata.name,A.metadata.subject,A.metadata.slug].find((B)=>typeof B==="string"&&B.trim().length>0)??A.id}function SFA(A){return!!A&&Object.keys(A.shape).length>0}function EFA(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}async function mFA(A,Q,w){if(!w)return!1;let B=await A.conversationService.getMessages(w,{limit:100});for(let $ of B){let D=le($.metadata)?.attachments;if(!Array.isArray(D))continue;for(let Y of D){if(!EFA(Y))continue;let X=Y.source;if(!EFA(X))continue;if(X.kind===Q.kind&&X.id===Q.id)return!0}}return!1}var Rx2="system",hx2;var $I=i(()=>{NN();Z0();hx2={base:"note"}});function Cx2(A){return{summary:`Save uploaded file${A.title?` as "${A.title}"`:""}?`,preview:[`Filename: ${A.filename}`,`Media type: ${A.mediaType}`,`Entity type: ${A.entityType}`,...A.title?[`Title: ${A.title}`]:[]].join(`
387
387
  `)}}function yx2(A){let{entityType:Q,title:w,prompt:B,content:$,url:f,from:D}=A,Y=w?` "${w}"`:` ${Q}`,X=`${B?"Generate":"Create"}${Y}?`,H=D?.kind==="entity-attachment"?D:void 0,W=[`Entity type: ${Q}`,...w?[`Title: ${w}`]:[],...f?[`URL: ${f}`]:[],...D?.kind==="upload"?["Upload: uploaded file"]:[],...H?[`Source attachment: ${H.sourceEntityType}/${H.sourceEntityId} (${H.attachmentType})`]:[],...B?[`Prompt: ${B}`]:[],...$?[`Content preview: ${$.slice(0,500)}`]:[]];return{summary:X,preview:W.join(`
388
- `)}}async function Ex2(A,Q,w){if(!w)return{success:!1,error:"Conversation message is not accessible in this conversation or does not exist."};let B=await A.conversationService.getMessages(w,{limit:100}),$=Q.messageId?B.find((f)=>f.id===Q.messageId&&f.role==="assistant"):[...B].reverse().find(pe);if(!$||!pe($))return{success:!1,error:"Conversation message is not accessible in this conversation or does not exist."};return{success:!0,messageId:$.id,content:$.content}}function gx2(A){switch(A.kind){case"text":return{success:!0,source:{content:A.content}};case"url":return{success:!0,source:{url:A.url}};case"upload":return{success:!0,source:{from:A.upload,uploadRef:A.upload,transform:A.transform}};case"prior-response":return{success:!0,source:{conversationMessageRef:{kind:"conversation-message",...A.messageId?{messageId:A.messageId}:{}}}}}}function Tx2(A){if(A.source.kind==="prior-response"){let Q=A.source.messageId??A.resolvedMessageId;return{kind:"prior-response",...Q?{messageId:Q}:{}}}return A.source}async function Sx2(A,Q,w,B){let $={interfaceType:B.interfaceType,userId:B.userId,...B.channelId&&{channelId:B.channelId},...B.channelName&&{channelName:B.channelName}},f=await Q(w,$);if(f.kind==="handled")return{kind:"handled",result:f.result};let D=f.input,Y=bH(A,D.entityType,"create",B);if(Y)return{kind:"error",result:Y};return{kind:"continue",createInput:D}}async function mx2(A,Q){let w={interfaceType:Q.interfaceType,userId:Q.userId,...Q.channelId&&{channelId:Q.channelId},...Q.channelName&&{channelName:Q.channelName}};return A.handler({upload:A.upload,...A.title&&{title:A.title}},w)}async function ux2(A,Q,w){let{entityService:B,entityRegistry:$}=A,f=w1(Q.title??`${Q.entityType}-${Date.now()}`),D=$.getEffectiveFrontmatterSchema(Q.entityType);try{let Y={deduplicateId:!0,...w?{eventContext:w}:{}};return{success:!0,data:{entityId:(Q.content&&SFA(D)?await B.createEntityFromMarkdown({input:{entityType:Q.entityType,id:f,markdown:Q.content},options:Y}):await B.createEntity({entity:{id:f,entityType:Q.entityType,content:Q.content??"",metadata:{title:Q.title??f},created:new Date().toISOString(),updated:new Date().toISOString()},options:Y})).entityId,status:"created"}}}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:"Failed to create entity"}}}async function cx2(A,Q,w){if(!(Q.source.kind==="upload"&&Q.source.transform==="preserve")){let y=hq(A,Q.entityType);if(y)return{kind:"error",result:y}}let $=gx2(Q.source),{content:f,url:D,from:Y,uploadRef:X,conversationMessageRef:H,transform:W}=$.source,Z=H?await Ex2(A,H,w.conversationId??w.channelId):void 0;if(Z&&!Z.success)return{kind:"error",result:Z};let G=Z?.success===!0?Z.content:f,F=Dj(Q.title);if(W==="extract-markdown"&&(!X||Q.entityType!=="note"))return{kind:"error",result:{success:!1,error:'Transform "extract-markdown" requires entityType "note" and an upload ref. Omit transform for raw file promotion to document/image.'}};let V=Q.replace===!0;if(!G&&!D&&!Y)return{kind:"error",result:{success:!1,error:'Provide `source` with kind "text", "url", "prior-response", or "upload". Use system_generate for generated content or artifacts.'}};let b,L=Q.entityType;if(X){if(!await mFA(A,X,w.conversationId??w.channelId))return{kind:"error",result:{success:!1,error:"Upload ref is not accessible in this conversation or no longer exists."}};if(W==="preserve"){let h;try{h=await A.runtimeUploads.scoped(vx2).readRecord(X.id)}catch{return{kind:"error",result:{success:!1,error:"Upload ref not found"}}}let T=A.entityRegistry.getUploadSaveHandler(h.mediaType);if(!T)return{kind:"error",result:{success:!1,error:`No installed plugin can save uploads with media type "${h.mediaType}".`}};L=T.entityType,b={upload:X,filename:h.filename,mediaType:h.mediaType,handler:T.handler}}}let N=hq(A,L);if(N)return{kind:"error",result:N};if(G&&Ce(G)){let y=GN(G);if(!dO(w.userPermissionLevel,y))return{kind:"error",result:{success:!1,error:`Cannot create entity with visibility "${y}" \u2014 caller permission "${w.userPermissionLevel??"public"}" is not allowed to write at that level.`}}}let _=KR(w),j={entityType:L,...F&&{title:F},...G&&{content:G},...D&&{url:D},...Y&&{from:Y},...W&&{transform:W},...V&&{replace:V}},g=bH(A,j.entityType,"create",w);if(g)return{kind:"error",result:g};let E=A.entityRegistry.getCreateInterceptor(j.entityType);if(!j.content&&!E&&!b)return{kind:"error",result:{success:!1,error:'URL or upload source creation is supported only for entity types that explicitly handle it. Provide source kind "text" for this entity type, or use system_generate for generated content/artifacts.'}};if(!E&&!V){let y=j.title?w1(j.title):void 0;if(y){if(await A.entityService.getEntity({entityType:j.entityType,id:y}))return{kind:"error",result:{success:!1,error:`A ${j.entityType} already exists for "${y}". To change its fields or status, use system_update; pass replace:true to create a new copy intentionally.`}}}}return{kind:"ok",prepared:{createInput:j,resolvedMessageId:Z?.success===!0?Z.messageId:void 0,interceptor:E,eventContext:_,...b&&{uploadPreserve:b}}}}function uFA(A){let Q=new pW;return LH("create","Create a new entity from existing material. Requires confirmation. Use source to choose exactly one concrete source: text for exact user-provided content, url for URL-first flows, prior-response for saving a previous assistant response, or upload with transform extract-markdown to import text into a note or transform preserve to save raw uploaded bytes as their durable file entity. Use system_generate for AI generation, generated images, cover images, and source-derived artifacts such as carousel/printable PDFs or OG images. If the user includes content in the same direct save request, use source.kind text with that content instead of asking them to paste it again. Use entityType wish for explicitly saved or tracked unmet requested capabilities or outcomes. On the initial create request, do not pass confirmed; the tool will return confirmation args after the user confirms.",OFA,async(w,B)=>{let $=await cx2(A,w,B);if($.kind==="error")return $.result;let{createInput:f}=$.prepared,{resolvedMessageId:D,interceptor:Y,eventContext:X,uploadPreserve:H}=$.prepared;if(w.confirmed){let W=w.confirmationToken,Z=Q.validate(W,w);if(Z.status==="missing")return{success:!1,error:"No pending create confirmation found. Please request creation again and confirm the new approval."};if(Z.status==="mismatch")return{success:!1,error:"Confirmed create arguments do not match the pending approval. Please request creation again and confirm the new approval."}}else{let W=H?Cx2({...f.title&&{title:f.title},filename:H.filename,mediaType:H.mediaType,entityType:f.entityType}):yx2(f),Z=Tx2({source:w.source,...D&&{resolvedMessageId:D}}),G=Q.create((F)=>({entityType:f.entityType,...f.title&&{title:f.title},source:Z,...f.replace&&{replace:f.replace},confirmed:!0,confirmationToken:F}));return{needsConfirmation:!0,toolName:"system_create",summary:W.summary,preview:W.preview,args:G}}if(H)return mx2({upload:H.upload,...f.title&&{title:f.title},handler:H.handler},B);if(Y){let W=await Sx2(A,Y,f,B);if(W.kind==="handled"||W.kind==="error")return W.result;f=W.createInput}if(!f.content)return{success:!1,error:'URL or upload source creation is supported only for entity types that explicitly handle it. Provide source kind "text" for this entity type, or use system_generate for generated content/artifacts.'};return ux2(A,f,X)},{visibility:"trusted",sideEffects:"writes"})}var vx2;var cFA=i(()=>{NN();aB();k9();Z0();Rq();ZR();$I();vx2={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"}});function lx2(A){let Q=A.title?` "${A.title}"`:` ${A.entityType}`,w=A.from?.kind==="entity-attachment"?A.from:void 0,B=[`Entity type: ${A.entityType}`,...A.title?[`Title: ${A.title}`]:[],...A.prompt?[`Prompt: ${A.prompt}`]:[],...w?[`Source attachment: ${w.sourceEntityType}/${w.sourceEntityId} (${w.attachmentType})`]:[],...A.targetEntityType&&A.targetEntityId?[`Target: ${A.targetEntityType}/${A.targetEntityId}`]:[]];return{summary:`Generate${Q}?`,preview:B.join(`
389
- `)}}async function px2(A,Q,w){if(!Q)return{kind:"ok",sourceAttachment:void 0};let B=await A4(A.entityService,Q.sourceEntityType,Q.sourceEntityId,A.logger,void 0,w);if(!B.ok)return{kind:"error",result:{success:!1,error:B.error,code:"source-not-found"}};let $={...Q,sourceEntityId:B.entity.id};if(!A.attachments.hasProvider($.sourceEntityType,$.attachmentType))return{kind:"error",result:{success:!1,error:`No attachment provider found for ${$.sourceEntityType}/${$.attachmentType}.`,code:"no-provider"}};let f=A.attachments.getProviderMetadata($.sourceEntityType,$.attachmentType);if(!f)return{kind:"error",result:{success:!1,error:`Attachment provider for ${$.sourceEntityType}/${$.attachmentType} is missing output metadata.`,code:"provider-missing-metadata"}};return{kind:"ok",sourceAttachment:$,metadata:f}}async function ix2(A,Q,w){if(!Q)return{kind:"ok",source:void 0};let B=await A4(A.entityService,Q.entityType,Q.entityId,A.logger,void 0,w);if(!B.ok)return{kind:"error",result:{success:!1,error:B.error,code:"source-not-found"}};return{kind:"ok",source:{...Q,entityId:B.entity.id}}}async function dx2(A,Q,w){if(!Q)return{kind:"ok",target:void 0};let B=await A4(A.entityService,Q.entityType,Q.entityId,A.logger,void 0,w);if(!B.ok)return{kind:"error",result:{success:!1,error:B.error}};return{kind:"ok",target:{...Q,entityId:B.entity.id}}}async function nx2(A,Q,w,B){let $={interfaceType:B.interfaceType,userId:B.userId,...B.channelId&&{channelId:B.channelId},...B.channelName&&{channelName:B.channelName}},f=await Q(w,$);if(f.kind==="handled")return{kind:"handled",result:f.result};let D=f.input,Y=bH(A,D.entityType,"create",B);if(Y)return{kind:"error",result:Y};return{kind:"continue",createInput:D}}async function rx2(A,Q,w,B,$){let{entityService:f,jobs:D}=A,Y=w1(Q.title??w).slice(0,100);if(!Y)return{success:!1,error:"Could not derive a slug from the provided title/prompt. Provide a 'title' with at least one URL-safe character."};let X=Q.title??Y,H=kU0(A.entityRegistry,{entityType:Q.entityType,id:Y,title:X});if(!H)return{success:!1,error:`Entity type '${Q.entityType}' does not support queued generation. Provide an exact source to system_create instead.`};let W;try{W=(await f.createEntity({entity:H,options:{deduplicateId:!0,...B?{eventContext:B}:{}}})).entityId}catch(Z){return{success:!1,error:Z instanceof Error?Z.message:"Failed to persist generation stub"}}try{let Z=await D.enqueue({type:`${Q.entityType}:generation`,data:{entityId:W,prompt:w,...Q.title&&{title:Q.title},...Q.sourceEntityType&&{sourceEntityType:Q.sourceEntityType},...Q.sourceEntityId&&{sourceEntityId:Q.sourceEntityId},...Q.sourceEntityIds&&{sourceEntityIds:Q.sourceEntityIds},...Q.targetEntityType&&{targetEntityType:Q.targetEntityType},...Q.targetEntityId&&{targetEntityId:Q.targetEntityId}},toolContext:$});return{success:!0,data:{entityId:W,status:"generating",jobId:Z}}}catch(Z){return{success:!1,error:Z instanceof Error?Z.message:"Failed to queue generation job"}}}async function ox2(A,Q,w){let B=Q.operation,$=p8(w.userPermissionLevel),f,D,Y=B.kind==="attachment"&&B.replace===!0;if(B.kind==="prompt"){if(B.entityType==="image")return{kind:"error",result:{success:!1,error:"Use operation.kind 'standalone-image' or 'cover-image' for image generation.",code:"unsupported-generation"}};let Z=await ix2(A,B.source,$);if(Z.kind==="error")return Z;let G=Dj(B.title);f={entityType:B.entityType,...G?{title:G}:{},prompt:B.prompt,...Z.source?.entityType&&{sourceEntityType:Z.source.entityType},...Z.source?.entityId&&{sourceEntityId:Z.source.entityId,sourceEntityIds:[Z.source.entityId]}}}else if(B.kind==="standalone-image"){let Z=Dj(B.title);f={entityType:"image",...Z?{title:Z}:{},prompt:B.prompt}}else if(B.kind==="cover-image"){let Z=await dx2(A,B.target,$);if(Z.kind==="error"){let F=Z.result;return{kind:"error",result:"success"in F&&F.success===!1?{...F,code:"target-not-found"}:F}}let G=Dj(B.title);f={entityType:"image",...G?{title:G}:{},prompt:B.prompt,...Z.target?.entityType&&{targetEntityType:Z.target.entityType},...Z.target?.entityId&&{targetEntityId:Z.target.entityId}}}else{let Z=await px2(A,{sourceEntityType:B.source.entityType,sourceEntityId:B.source.entityId,attachmentType:B.attachmentType},$);if(Z.kind==="error")return Z;D=Z.sourceAttachment;let G=Z.metadata;if(!G||!D)return{kind:"error",result:{success:!1,error:"Attachment generation requires provider metadata.",code:"provider-missing-metadata"}};let F=Dj(B.title);f={entityType:G.outputEntityType,...F?{title:F}:{},from:{kind:"entity-attachment",...D},...Y&&{replace:Y},...G.targetField&&{targetEntityType:D.sourceEntityType,targetEntityId:D.sourceEntityId}}}let X=hq(A,f.entityType);if(X)return{kind:"error",result:X};let H=bH(A,f.entityType,"create",w);if(H)return{kind:"error",result:H};let W=A.entityRegistry.getCreateInterceptor(f.entityType);if(!f.prompt&&!f.from)return{kind:"error",result:{success:!1,error:"Provide a generation source."}};if(f.from&&!W)return{kind:"error",result:{success:!1,error:`Entity type '${f.entityType}' does not support attachment-based generation. Use operation.kind prompt for AI-generated content based on referenced source material, or choose an entity type with an attachment provider.`,code:"unsupported-generation"}};if(!W&&!Y){let Z=f.prompt?w1(f.title??f.prompt).slice(0,100):f.title?w1(f.title):void 0;if(Z){if(await A.entityService.getEntity({entityType:f.entityType,id:Z}))return{kind:"error",result:{success:!1,error:`A ${f.entityType} already exists for "${Z}". To change its fields or status, use system_update; pass replace:true to generate a new copy intentionally.`}}}}return{kind:"ok",prepared:{createInput:f,operation:sx2(B,f,D),sourceAttachment:D,interceptor:W,eventContext:KR(w)}}}function sx2(A,Q,w){if(A.kind==="attachment"){let B=w??{sourceEntityType:A.source.entityType,sourceEntityId:A.source.entityId,attachmentType:A.attachmentType};return{kind:"attachment",source:{entityType:B.sourceEntityType,entityId:B.sourceEntityId},attachmentType:B.attachmentType,...Q.title&&{title:Q.title},...Q.replace&&{replace:Q.replace}}}if(A.kind==="cover-image")return{kind:"cover-image",target:{entityType:Q.targetEntityType??A.target.entityType,entityId:Q.targetEntityId??A.target.entityId},...Q.title&&{title:Q.title},prompt:A.prompt};if(A.kind==="standalone-image")return{kind:"standalone-image",...Q.title&&{title:Q.title},prompt:A.prompt};return{kind:"prompt",entityType:Q.entityType,...Q.title&&{title:Q.title},...Q.sourceEntityType&&Q.sourceEntityId&&{source:{entityType:Q.sourceEntityType,entityId:Q.sourceEntityId}},prompt:A.prompt}}function lFA(A){let Q=new pW;return LH("generate","Generate durable content or artifacts. Critical: for a request to generate a post/social-post/newsletter/etc. with a cover image, call only the prompt generation first; do not call standalone-image or cover-image until the target entity exists after confirmation. Critical: for broad topical prompt generation, omit operation.source; never use brain-character/profile, uploads, filenames, guessed ids, or placeholders as source refs. Requires confirmation. Calling this tool without confirmed is how you request that confirmation; do not respond with separate prose such as 'I can generate it if you want' or 'I need to queue it first.' Use operation.kind prompt for non-image AI-generated entities, with operation.source only when generating from a resolved existing durable source entity, for example a newsletter from a resolved post: { kind: 'prompt', entityType: 'newsletter', source: { entityType: 'post', entityId: '...' }, prompt: '...' }. Use standalone-image only for unattached generated images, cover-image with operation.target only for generated covers on existing entities, and attachment with operation.source for source-derived artifacts such as carousel/printable PDFs or OG/social preview images. When the user asks to create/write/draft/generate new durable content, call this tool without confirmed to request confirmation instead of asking for separate prose approval. If you first resolve a clear source entity for the requested generation, still call this tool in the same turn. Use system_create instead for saving/importing existing text, URLs, uploads, prior assistant responses, or raw uploaded file preservation with upload transform preserve. On the initial generation request, do not pass confirmed; the tool returns confirmation args.",xFA,async(w,B)=>{let $=await ox2(A,w,B);if($.kind==="error")return $.result;let{createInput:f}=$.prepared,{operation:D,interceptor:Y,eventContext:X}=$.prepared;if(w.confirmed){let H=Q.validate(w.confirmationToken,w);if(H.status==="missing")return{success:!1,error:"No pending generate confirmation found. Please request generation again and confirm the new approval."};if(H.status==="mismatch")return{success:!1,error:"Confirmed generate arguments do not match the pending approval. Please request generation again and confirm the new approval."}}else{let H=lx2(f),W=Q.create((Z)=>({operation:D,confirmed:!0,confirmationToken:Z}));return{needsConfirmation:!0,toolName:"system_generate",summary:H.summary,preview:H.preview,args:W}}if(Y){let H=await nx2(A,Y,f,B);if(H.kind==="handled"||H.kind==="error")return H.result;f=H.createInput}if(!f.prompt)return{success:!1,error:"Attachment generation is supported only for entity types that explicitly handle source-derived artifacts."};return rx2(A,f,f.prompt,X,B)},{visibility:"trusted",sideEffects:"writes"})}var pFA=i(()=>{aB();k9();Z0();Rq();ZR();$I()});function iFA(A){let{entityService:Q,entityRegistry:w,logger:B}=A,$=new pW;return LH("delete","Request entity deletion by id. Unauthorized callers get a permission error; authorized callers get confirmation first. Do not pass confirmed on the initial request.",hFA,async(f,D)=>{if((D.userPermissionLevel??"public")==="public")return{success:!1,error:"Changing content requires higher permission; current permission is Public."};let Y=bH(A,f.entityType,"delete",D);if(Y)return Y;let X=hq(A,f.entityType);if(X)return X;if(w.getAdapter(f.entityType).isSingleton===!0)return{success:!1,error:`${f.entityType} is a singleton entity and cannot be deleted through system tools. Update it instead.`};let H=p8(D.userPermissionLevel),W=await A4(Q,f.entityType,f.id,B,void 0,H);if(!W.ok)return{success:!1,error:W.error};let{entity:Z}=W;if(f.confirmed){let V=$.validate(f.confirmationToken,f);if(V.status==="missing")return{success:!1,error:"No pending delete confirmation found. Please request deletion again and confirm the new approval."};if(V.status==="mismatch")return{success:!1,error:"Confirmed delete arguments do not match the pending approval. Please request deletion again and confirm the new approval."};try{await Q.deleteEntity({entityType:f.entityType,id:Z.id})}catch(b){return{success:!1,error:b instanceof Error?b.message:"Failed to delete entity"}}return{success:!0,data:{deleted:Z.id}}}let G=x10(Z),F=$.create((V)=>({...f,id:Z.id,confirmed:!0,confirmationToken:V}));return{needsConfirmation:!0,toolName:"system_delete",summary:`Delete "${G}"?`,preview:Z.content.slice(0,200),args:F}},{visibility:"anchor",sideEffects:"writes"})}var dFA=i(()=>{aB();k9();Rq();ZR();$I()});function nFA(A){let{entityService:Q,jobs:w}=A;return LH("extract",'Generate derived entities (e.g. topics) from existing content. Use this for explicit requests like "generate topics for me", "extract topics", "derive topics from my notes" \u2014 call once with `entityType` (typically `"topic"`); do not preflight with search/list. After a successful non-confirmation extract call, report that extraction started or was queued and do not append optional follow-up offers like "If you want...". Do not call this for vague continuations such as "go ahead", "continue", or "do that" unless the operator clearly chose extraction or topic derivation. Provide `source` to derive from a single entity, omit for a batch over all sources. `mode: "rebuild"` is currently only supported for `entityType: "topic"` and requires confirmation; other entity types fall back to normal projection mode.',vFA,async(B,$)=>{let{entityType:f,source:D}=B,X=(B.mode??"derive")==="rebuild",H=f==="topic"&&!D,W=X&&H?"rebuild":"derive",Z=hq(A,f);if(Z)return Z;let G=bH(A,f,"extract",$);if(G)return G;if(X&&H&&!B.confirmed)return{needsConfirmation:!0,toolName:"system_extract",summary:"Rebuild all derived topic entities from current source content?",preview:"This will delete existing topics and regenerate them from scratch.",args:{...B,confirmed:!0}};try{let F={mode:W};if(D){let b=p8($.userPermissionLevel);for(let L of Q.getEntityTypes()){let N=await Q.getEntity({entityType:L,id:D,visibilityScope:b});if(N){F.mode="source",F.entityId=N.id,F.entityType=N.entityType;break}}if(!F.entityId)return{success:!1,error:`Source entity not found: ${D}`}}return{success:!0,data:{status:"extracting",jobId:await w.enqueue({type:`${f}:project`,data:F,toolContext:$}),entityType:f,mode:W,...D&&{source:D}},...X&&!H?{message:D||f!=="topic"?`Rebuild is currently only supported for batch topic extraction. Ran normal projection mode for ${f} instead.`:void 0}:{}}}catch(F){return{success:!1,error:F instanceof Error?F.message:"Failed to queue extraction job"}}},{visibility:"trusted",sideEffects:"writes"})}var rFA=i(()=>{aB();Rq();ZR();$I()});var oFA,sFA,aFA,Uu,ax2;var Cb0=i(()=>{Z0();aB();oFA=K.enum(["png","jpg","jpeg","webp","gif","svg"]),sFA=K.enum(["pending","draft","failed"]),aFA=K.object({title:K.string().optional(),alt:K.string().optional(),format:oFA,width:K.number(),height:K.number(),status:sFA.optional(),processingJobId:K.string().optional(),processingError:K.string().optional(),sourceUrl:K.string().url().optional(),sourceEntityType:K.string().optional(),sourceEntityId:K.string().optional(),sourceUploadId:K.string().optional(),sourceFilename:K.string().optional(),sourceMediaType:K.string().optional(),attachmentType:K.string().optional(),dedupKey:K.string().optional()}),Uu=o1.extend({entityType:K.literal("image"),metadata:aFA}),ax2=K.object({url:K.string(),alt:K.string(),title:K.string(),width:K.number(),height:K.number()})});function fI(A){let Q=A.trim().match(/^data:image\/([a-z+]+);base64,(.+)$/i);if(!Q?.[1]||!Q[2])throw Error("Invalid image data URL");return{format:Q[1].toLowerCase(),base64:Q[2]}}function yb0(A,Q){return`data:image/${Q==="jpg"?"jpeg":Q};base64,${A}`}function Yj(A){for(let[Q,w]of Object.entries(tx2))if(A.startsWith(w))return Q;return null}async function NH(A){return Lt(A,"image/")}function DI(A){let Q=Buffer.from(A,"base64");if(Q[0]===137&&Q[1]===80&&Q[2]===78&&Q[3]===71){let w=Q.readUInt32BE(16),B=Q.readUInt32BE(20);return{width:w,height:B}}if(Q[0]===255&&Q[1]===216){let w=2;while(w<Q.length-8){if(Q[w]!==255){w++;continue}let B=Q[w+1];if(B===192||B===194){let f=Q.readUInt16BE(w+5);return{width:Q.readUInt16BE(w+7),height:f}}let $=Q.readUInt16BE(w+2);w+=2+$}}if(Q[0]===71&&Q[1]===73&&Q[2]===70){let w=Q.readUInt16LE(6),B=Q.readUInt16LE(8);return{width:w,height:B}}if(Q.length>=30&&Q[0]===82&&Q[1]===73&&Q[2]===70&&Q[3]===70){if(Q[12]===86&&Q[13]===80&&Q[14]===56){if(Q[15]===32){let w=Q[26]??0,B=Q[27]??0,$=Q[28]??0,f=Q[29]??0,D=(w|B<<8)&16383,Y=($|f<<8)&16383;return{width:D,height:Y}}if(Q[15]===76&&Q.length>=25){let w=Q.readUInt32LE(21),B=(w&16383)+1,$=(w>>14&16383)+1;return{width:B,height:$}}}}return null}var tx2;var Eb0=i(()=>{Z0();tx2={png:"iVBORw",jpg:"/9j/",gif:"R0lGOD",webp:"UklGR"}});class gb0{entityType="image";purpose="Image assets such as generated covers, social previews, and uploaded images.";schema=Uu;toMarkdown(A){return A.content}fromMarkdown(A){let{format:Q,base64:w}=fI(A),B=DI(w);return{entityType:"image",content:A,metadata:{format:Q,width:B?.width??0,height:B?.height??0}}}extractMetadata(A){return A.metadata}parseFrontMatter(A,Q){return Q.parse({})}generateFrontMatter(A){return""}getBodyTemplate(){return""}createImageEntity(A){let{dataUrl:Q,title:w,alt:B}=A,{format:$,base64:f}=fI(Q),D=DI(f),X=Yj(f)??$;return{entityType:"image",content:Q,metadata:{title:w,alt:B??w,format:X,width:D?.width??0,height:D?.height??0,...A.status&&{status:A.status},...A.sourceUrl&&{sourceUrl:A.sourceUrl},...A.sourceEntityType&&{sourceEntityType:A.sourceEntityType},...A.sourceEntityId&&{sourceEntityId:A.sourceEntityId},...A.sourceUploadId&&{sourceUploadId:A.sourceUploadId},...A.sourceFilename&&{sourceFilename:A.sourceFilename},...A.sourceMediaType&&{sourceMediaType:A.sourceMediaType},...A.attachmentType&&{attachmentType:A.attachmentType},...A.dedupKey&&{dedupKey:A.dedupKey}}}}}var vY;var tFA=i(()=>{Cb0();Eb0();vY=new gb0});async function eFA(A,Q){let w=await Q.getEntity({entityType:"image",id:A});if(!w)return;return{url:w.content,alt:w.metadata.alt??"",title:w.metadata.title??"",width:w.metadata.width,height:w.metadata.height}}function AVA(A,Q){let w=ex2.exec(A.content);if(!w?.[1])return;try{let B=qt(w[1]);if(B&&typeof B==="object"&&!Array.isArray(B)){let $=B[Q];return typeof $==="string"?$:void 0}}catch{return}return}function Gu(A){return AVA(A,"coverImageId")}function R10(A){return AVA(A,"ogImageId")}function Xj(A,Q){return{...A,content:o4(A.content,"coverImageId",Q)}}function zu(A,Q){return{...A,content:o4(A.content,"ogImageId",Q)}}async function Tb0(A,Q){let w=Gu(A);if(!w)return;return eFA(w,Q)}var ex2;var QVA=i(()=>{Z0();ex2=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/});function Sb0(A){let Q=[],w=AR2.parse(A);return bT(w,"image",(B)=>{Q.push({url:B.url,alt:B.alt??"",title:B.title??void 0})}),Q}var AR2;var wVA=i(()=>{Dt();EW0();AR2=AO()});var D4=i(()=>{Cb0();tFA();QVA();wVA();Eb0()});function BVA(A,Q,w,B){let $=B.getEntityTypeConfig(A).publish?.publishStatuses;if(!$?.length)return"non-publish";if(typeof w!=="string")return"non-publish";let f=typeof Q==="string"&&$.includes(Q);if(!$.includes(w))return"non-publish";return f?"within-publish-set":"boundary"}function QR2(A,Q){return Q==="visibility"?A.visibility:A.metadata[Q]}function wR2(A,Q){let{visibility:w,coverImageId:B,ogImageId:$,...f}=Q,D=w===void 0?A.visibility:X7.parse(w),Y=Object.hasOwn(Q,"coverImageId")?Xj(A,typeof B==="string"?B:null):A,X=Object.hasOwn(Q,"ogImageId")?zu(Y,typeof $==="string"?$:null):Y,H={...A.metadata};for(let[Z,G]of Object.entries(f))if(G===null)delete H[Z];else H[Z]=G;let W={...X,visibility:D,metadata:H};for(let[Z,G]of Object.entries(f))if(G===null)delete W[Z];else W[Z]=G;return W}function BR2(A,Q){if(A!=="anchor-profile")return;if(Q.fields)return{success:!1,error:"anchor-profile updates require full markdown content replacement, not fields-only updates."};return}function $R2(A,Q,w){if(Q.content===void 0)return;let B=Q.content.trim(),$=w.getEffectiveFrontmatterSchema(A);if(!$)return;if(!B)return{success:!1,error:"Full content replacement cannot be empty for this entity type. Use 'fields' for partial updates."};try{w.getAdapter(A).parseFrontMatter(Q.content,$)}catch{return{success:!1,error:"Invalid content replacement for this entity type. Provide full markdown with valid frontmatter, or use 'fields' for partial updates."}}return}function fR2(A,Q,w){if(!Q.fields||!("coverImageId"in Q.fields))return;let B=Q.fields.coverImageId;if(B!==null&&B!==void 0&&typeof B!=="string")return{success:!1,error:"coverImageId must be a string or null"};if(B==="__PENDING__")return{success:!1,error:"coverImageId must reference an existing image id or be null"};if(w.getAdapter(A).supportsCoverImage)return;return{success:!1,error:`Entity type '${A}' doesn't support cover images`}}function DR2(A,Q,w){if(Q.fields&&"status"in Q.fields)return Q.fields.status;if(Q.content!==void 0){let B=w.getEffectiveFrontmatterSchema(A.entityType);if(!B)return A.metadata.status;try{return w.getAdapter(A.entityType).parseFrontMatter(Q.content,B).status}catch{return A.metadata.status}}return A.metadata.status}function YR2(A,Q){if(Q.fields)return Object.entries(Q.fields).map(([f,D])=>`${f}: ${String(QR2(A,f)??"(empty)")} \u2192 ${String(D)}`).join(`
388
+ `)}}async function Ex2(A,Q,w){if(!w)return{success:!1,error:"Conversation message is not accessible in this conversation or does not exist."};let B=await A.conversationService.getMessages(w,{limit:100}),$=Q.messageId?B.find((f)=>f.id===Q.messageId&&f.role==="assistant"):[...B].reverse().find(pe);if(!$||!pe($))return{success:!1,error:"Conversation message is not accessible in this conversation or does not exist."};return{success:!0,messageId:$.id,content:$.content}}function gx2(A){switch(A.kind){case"text":return{success:!0,source:{content:A.content}};case"url":return{success:!0,source:{url:A.url}};case"upload":return{success:!0,source:{from:A.upload,uploadRef:A.upload,transform:A.transform}};case"prior-response":return{success:!0,source:{conversationMessageRef:{kind:"conversation-message",...A.messageId?{messageId:A.messageId}:{}}}}}}function Tx2(A){if(A.source.kind==="prior-response"){let Q=A.source.messageId??A.resolvedMessageId;return{kind:"prior-response",...Q?{messageId:Q}:{}}}return A.source}async function Sx2(A,Q,w,B){let $={interfaceType:B.interfaceType,userId:B.userId,...B.channelId&&{channelId:B.channelId},...B.channelName&&{channelName:B.channelName}},f=await Q(w,$);if(f.kind==="handled")return{kind:"handled",result:f.result};let D=f.input,Y=bH(A,D.entityType,"create",B);if(Y)return{kind:"error",result:Y};return{kind:"continue",createInput:D}}async function mx2(A,Q){let w={interfaceType:Q.interfaceType,userId:Q.userId,...Q.channelId&&{channelId:Q.channelId},...Q.channelName&&{channelName:Q.channelName}};return A.handler({upload:A.upload,...A.title&&{title:A.title}},w)}async function ux2(A,Q,w){let{entityService:B,entityRegistry:$}=A,f=w1(Q.title??`${Q.entityType}-${Date.now()}`),D=$.getEffectiveFrontmatterSchema(Q.entityType);try{let Y={deduplicateId:!0,...w?{eventContext:w}:{}};return{success:!0,data:{entityId:(Q.content&&SFA(D)?await B.createEntityFromMarkdown({input:{entityType:Q.entityType,id:f,markdown:Q.content},options:Y}):await B.createEntity({entity:{id:f,entityType:Q.entityType,content:Q.content??"",metadata:{title:Q.title??f},created:new Date().toISOString(),updated:new Date().toISOString()},options:Y})).entityId,status:"created"}}}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:"Failed to create entity"}}}async function cx2(A,Q,w){if(!(Q.source.kind==="upload"&&Q.source.transform==="preserve")){let y=hq(A,Q.entityType);if(y)return{kind:"error",result:y}}let $=gx2(Q.source),{content:f,url:D,from:Y,uploadRef:X,conversationMessageRef:H,transform:W}=$.source,Z=H?await Ex2(A,H,w.conversationId??w.channelId):void 0;if(Z&&!Z.success)return{kind:"error",result:Z};let G=Z?.success===!0?Z.content:f,F=Dj(Q.title);if(W==="extract-markdown"&&(!X||Q.entityType!=="note"))return{kind:"error",result:{success:!1,error:'Transform "extract-markdown" requires entityType "note" and an upload ref. Omit transform for raw file promotion to document/image.'}};let V=Q.replace===!0;if(!G&&!D&&!Y)return{kind:"error",result:{success:!1,error:'Provide `source` with kind "text", "url", "prior-response", or "upload". Use system_generate for generated content or artifacts.'}};let b,L=Q.entityType;if(X){if(!await mFA(A,X,w.conversationId??w.channelId))return{kind:"error",result:{success:!1,error:"Upload ref is not accessible in this conversation or no longer exists."}};if(W==="preserve"){let h;try{h=await A.runtimeUploads.scoped(vx2).readRecord(X.id)}catch{return{kind:"error",result:{success:!1,error:"Upload ref not found"}}}let T=A.entityRegistry.getUploadSaveHandler(h.mediaType);if(!T)return{kind:"error",result:{success:!1,error:`No installed plugin can save uploads with media type "${h.mediaType}".`}};L=T.entityType,b={upload:X,filename:h.filename,mediaType:h.mediaType,handler:T.handler}}}let N=hq(A,L);if(N)return{kind:"error",result:N};if(G&&Ce(G)){let y=GN(G);if(!dO(w.userPermissionLevel,y))return{kind:"error",result:{success:!1,error:`Cannot create entity with visibility "${y}" \u2014 caller permission "${w.userPermissionLevel??"public"}" is not allowed to write at that level.`}}}let _=KR(w),j={entityType:L,...F&&{title:F},...G&&{content:G},...D&&{url:D},...Y&&{from:Y},...W&&{transform:W},...V&&{replace:V}},g=bH(A,j.entityType,"create",w);if(g)return{kind:"error",result:g};let E=A.entityRegistry.getCreateInterceptor(j.entityType);if(!j.content&&!E&&!b)return{kind:"error",result:{success:!1,error:'URL or upload source creation is supported only for entity types that explicitly handle it. Provide source kind "text" for this entity type, or use system_generate for generated content/artifacts.'}};if(!E&&!V){let y=j.title?w1(j.title):void 0;if(y){if(await A.entityService.getEntity({entityType:j.entityType,id:y}))return{kind:"error",result:{success:!1,error:`A ${j.entityType} already exists for "${y}". To change its fields or status, use system_update; pass replace:true to create a new copy intentionally.`}}}}return{kind:"ok",prepared:{createInput:j,resolvedMessageId:Z?.success===!0?Z.messageId:void 0,interceptor:E,eventContext:_,...b&&{uploadPreserve:b}}}}function uFA(A){let Q=new pW;return LH("create","Create a new entity from existing material. Requires confirmation. Use source to choose exactly one concrete source: text for exact user-provided content, url for URL-first flows, prior-response for saving a previous assistant response, or upload with transform extract-markdown to import text into a note or transform preserve to save raw uploaded bytes as their durable file entity. Use system_generate for AI generation, generated images, cover images, and source-derived artifacts such as carousel/printable PDFs or OG images. If the user includes content in the same direct save request, use source.kind text with that content instead of asking them to paste it again; for example, 'Save this as a note: ...' already supplies the content. If the user says save it after your immediately preceding upload summary/answer, use entityType note with source.kind prior-response unless they explicitly ask to save the uploaded file/document itself. Use entityType wish for explicitly saved or tracked unmet requested capabilities or outcomes. On the initial create request, do not pass confirmed; the tool will return confirmation args after the user confirms.",OFA,async(w,B)=>{let $=await cx2(A,w,B);if($.kind==="error")return $.result;let{createInput:f}=$.prepared,{resolvedMessageId:D,interceptor:Y,eventContext:X,uploadPreserve:H}=$.prepared;if(w.confirmed){let W=w.confirmationToken,Z=Q.validate(W,w);if(Z.status==="missing")return{success:!1,error:"No pending create confirmation found. Please request creation again and confirm the new approval."};if(Z.status==="mismatch")return{success:!1,error:"Confirmed create arguments do not match the pending approval. Please request creation again and confirm the new approval."}}else{let W=H?Cx2({...f.title&&{title:f.title},filename:H.filename,mediaType:H.mediaType,entityType:f.entityType}):yx2(f),Z=Tx2({source:w.source,...D&&{resolvedMessageId:D}}),G=Q.create((F)=>({entityType:f.entityType,...f.title&&{title:f.title},source:Z,...f.replace&&{replace:f.replace},confirmed:!0,confirmationToken:F}));return{needsConfirmation:!0,toolName:"system_create",summary:W.summary,preview:W.preview,args:G}}if(H)return mx2({upload:H.upload,...f.title&&{title:f.title},handler:H.handler},B);if(Y){let W=await Sx2(A,Y,f,B);if(W.kind==="handled"||W.kind==="error")return W.result;f=W.createInput}if(!f.content)return{success:!1,error:'URL or upload source creation is supported only for entity types that explicitly handle it. Provide source kind "text" for this entity type, or use system_generate for generated content/artifacts.'};return ux2(A,f,X)},{visibility:"trusted",sideEffects:"writes"})}var vx2;var cFA=i(()=>{NN();aB();k9();Z0();Rq();ZR();$I();vx2={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"}});function lx2(A){let Q=A.title?` "${A.title}"`:` ${A.entityType}`,w=A.from?.kind==="entity-attachment"?A.from:void 0,B=[`Entity type: ${A.entityType}`,...A.title?[`Title: ${A.title}`]:[],...A.prompt?[`Prompt: ${A.prompt}`]:[],...w?[`Source attachment: ${w.sourceEntityType}/${w.sourceEntityId} (${w.attachmentType})`]:[],...A.targetEntityType&&A.targetEntityId?[`Target: ${A.targetEntityType}/${A.targetEntityId}`]:[]];return{summary:`Generate${Q}?`,preview:B.join(`
389
+ `)}}async function px2(A,Q,w){if(!Q)return{kind:"ok",sourceAttachment:void 0};let B=await A4(A.entityService,Q.sourceEntityType,Q.sourceEntityId,A.logger,void 0,w);if(!B.ok)return{kind:"error",result:{success:!1,error:B.error,code:"source-not-found"}};let $={...Q,sourceEntityId:B.entity.id};if(!A.attachments.hasProvider($.sourceEntityType,$.attachmentType))return{kind:"error",result:{success:!1,error:`No attachment provider found for ${$.sourceEntityType}/${$.attachmentType}.`,code:"no-provider"}};let f=A.attachments.getProviderMetadata($.sourceEntityType,$.attachmentType);if(!f)return{kind:"error",result:{success:!1,error:`Attachment provider for ${$.sourceEntityType}/${$.attachmentType} is missing output metadata.`,code:"provider-missing-metadata"}};return{kind:"ok",sourceAttachment:$,metadata:f}}async function ix2(A,Q,w){if(!Q)return{kind:"ok",source:void 0};let B=await A4(A.entityService,Q.entityType,Q.entityId,A.logger,void 0,w);if(!B.ok)return{kind:"error",result:{success:!1,error:B.error,code:"source-not-found"}};return{kind:"ok",source:{...Q,entityId:B.entity.id}}}async function dx2(A,Q,w){if(!Q)return{kind:"ok",target:void 0};let B=await A4(A.entityService,Q.entityType,Q.entityId,A.logger,void 0,w);if(!B.ok)return{kind:"error",result:{success:!1,error:B.error}};return{kind:"ok",target:{...Q,entityId:B.entity.id}}}async function nx2(A,Q,w,B){let $={interfaceType:B.interfaceType,userId:B.userId,...B.channelId&&{channelId:B.channelId},...B.channelName&&{channelName:B.channelName}},f=await Q(w,$);if(f.kind==="handled")return{kind:"handled",result:f.result};let D=f.input,Y=bH(A,D.entityType,"create",B);if(Y)return{kind:"error",result:Y};return{kind:"continue",createInput:D}}async function rx2(A,Q,w,B,$){let{entityService:f,jobs:D}=A,Y=w1(Q.title??w).slice(0,100);if(!Y)return{success:!1,error:"Could not derive a slug from the provided title/prompt. Provide a 'title' with at least one URL-safe character."};let X=Q.title??Y,H=kU0(A.entityRegistry,{entityType:Q.entityType,id:Y,title:X});if(!H)return{success:!1,error:`Entity type '${Q.entityType}' does not support queued generation. Provide an exact source to system_create instead.`};let W;try{W=(await f.createEntity({entity:H,options:{deduplicateId:!0,...B?{eventContext:B}:{}}})).entityId}catch(Z){return{success:!1,error:Z instanceof Error?Z.message:"Failed to persist generation stub"}}try{let Z=await D.enqueue({type:`${Q.entityType}:generation`,data:{entityId:W,prompt:w,...Q.title&&{title:Q.title},...Q.sourceEntityType&&{sourceEntityType:Q.sourceEntityType},...Q.sourceEntityId&&{sourceEntityId:Q.sourceEntityId},...Q.sourceEntityIds&&{sourceEntityIds:Q.sourceEntityIds},...Q.targetEntityType&&{targetEntityType:Q.targetEntityType},...Q.targetEntityId&&{targetEntityId:Q.targetEntityId}},toolContext:$});return{success:!0,data:{entityId:W,status:"generating",jobId:Z}}}catch(Z){return{success:!1,error:Z instanceof Error?Z.message:"Failed to queue generation job"}}}async function ox2(A,Q,w){let B=Q.operation,$=p8(w.userPermissionLevel),f,D,Y=B.kind==="attachment"&&B.replace===!0;if(B.kind==="prompt"||B.kind==="prompt-from-source"){if(B.entityType==="image")return{kind:"error",result:{success:!1,error:"Use operation.kind 'standalone-image' or 'cover-image' for image generation.",code:"unsupported-generation"}};let Z=B.kind==="prompt-from-source"?await ix2(A,B.source,$):{kind:"ok",source:void 0};if(Z.kind==="error")return Z;let G=Dj(B.title);f={entityType:B.entityType,...G?{title:G}:{},prompt:B.prompt,...Z.source?.entityType&&{sourceEntityType:Z.source.entityType},...Z.source?.entityId&&{sourceEntityId:Z.source.entityId,sourceEntityIds:[Z.source.entityId]}}}else if(B.kind==="standalone-image"){let Z=Dj(B.title);f={entityType:"image",...Z?{title:Z}:{},prompt:B.prompt}}else if(B.kind==="cover-image"){let Z=await dx2(A,B.target,$);if(Z.kind==="error"){let F=Z.result;return{kind:"error",result:"success"in F&&F.success===!1?{...F,code:"target-not-found"}:F}}let G=Dj(B.title);f={entityType:"image",...G?{title:G}:{},prompt:B.prompt,...Z.target?.entityType&&{targetEntityType:Z.target.entityType},...Z.target?.entityId&&{targetEntityId:Z.target.entityId}}}else{let Z=await px2(A,{sourceEntityType:B.source.entityType,sourceEntityId:B.source.entityId,attachmentType:B.attachmentType},$);if(Z.kind==="error")return Z;D=Z.sourceAttachment;let G=Z.metadata;if(!G||!D)return{kind:"error",result:{success:!1,error:"Attachment generation requires provider metadata.",code:"provider-missing-metadata"}};let F=Dj(B.title);f={entityType:G.outputEntityType,...F?{title:F}:{},from:{kind:"entity-attachment",...D},...Y&&{replace:Y},...G.targetField&&{targetEntityType:D.sourceEntityType,targetEntityId:D.sourceEntityId}}}let X=hq(A,f.entityType);if(X)return{kind:"error",result:X};let H=bH(A,f.entityType,"create",w);if(H)return{kind:"error",result:H};let W=A.entityRegistry.getCreateInterceptor(f.entityType);if(!f.prompt&&!f.from)return{kind:"error",result:{success:!1,error:"Provide a generation source."}};if(f.from&&!W)return{kind:"error",result:{success:!1,error:`Entity type '${f.entityType}' does not support attachment-based generation. Use operation.kind prompt-from-source for AI-generated content based on referenced source material, or choose an entity type with an attachment provider.`,code:"unsupported-generation"}};if(!W&&!Y){let Z=f.prompt?w1(f.title??f.prompt).slice(0,100):f.title?w1(f.title):void 0;if(Z){if(await A.entityService.getEntity({entityType:f.entityType,id:Z}))return{kind:"error",result:{success:!1,error:`A ${f.entityType} already exists for "${Z}". To change its fields or status, use system_update; pass replace:true to generate a new copy intentionally.`}}}}return{kind:"ok",prepared:{createInput:f,operation:sx2(B,f,D),sourceAttachment:D,interceptor:W,eventContext:KR(w)}}}function sx2(A,Q,w){if(A.kind==="attachment"){let B=w??{sourceEntityType:A.source.entityType,sourceEntityId:A.source.entityId,attachmentType:A.attachmentType};return{kind:"attachment",source:{entityType:B.sourceEntityType,entityId:B.sourceEntityId},attachmentType:B.attachmentType,...Q.title&&{title:Q.title},...Q.replace&&{replace:Q.replace}}}if(A.kind==="cover-image")return{kind:"cover-image",target:{entityType:Q.targetEntityType??A.target.entityType,entityId:Q.targetEntityId??A.target.entityId},...Q.title&&{title:Q.title},prompt:A.prompt};if(A.kind==="standalone-image")return{kind:"standalone-image",...Q.title&&{title:Q.title},prompt:A.prompt};if(A.kind==="prompt-from-source")return{kind:"prompt-from-source",entityType:Q.entityType,...Q.title&&{title:Q.title},source:{entityType:Q.sourceEntityType??A.source.entityType,entityId:Q.sourceEntityId??A.source.entityId},prompt:A.prompt};return{kind:"prompt",entityType:Q.entityType,...Q.title&&{title:Q.title},prompt:A.prompt}}function lFA(A){let Q=new pW;return LH("generate","Generate durable content or artifacts. Critical: for a request to generate a post/social-post/newsletter/etc. with a cover image, call only the prompt generation first; do not call standalone-image or cover-image until the target entity exists after confirmation. Critical: broad topical prompt generation uses operation.kind prompt and has no source field. Never invent source IDs, use brain-character/profile, uploads, filenames, guessed ids, or placeholders as source refs. Critical: when the user asks to generate from a source such as 'my latest blog post', resolve the source, then call operation.kind prompt-from-source in the same turn; if dated candidates such as publishedAt are visible, choose the newest candidate and do not stop with prose like 'I found it and can generate it' or 'if that is the one you mean.' Requires confirmation. Calling this tool without confirmed is how you request that confirmation; do not respond with separate prose such as 'I can generate it if you want' or 'I need to queue it first.' Use operation.kind prompt for broad non-image AI-generated entities with no source. Use operation.kind prompt-from-source only when generating from a resolved existing durable source entity, for example a newsletter from a resolved post: { kind: 'prompt-from-source', entityType: 'newsletter', source: { entityType: 'post', entityId: '...' }, prompt: '...' }. Use standalone-image only for unattached generated images, cover-image with operation.target only for generated covers on existing entities, and attachment with operation.source for source-derived artifacts such as carousel/printable PDFs or OG/social preview images. For regenerate/replace/refresh source-derived artifact requests, call attachment with replace:true immediately; do not say you can queue it later. When the user asks to create/write/draft/generate new durable content, call this tool without confirmed to request confirmation instead of asking for separate prose approval. If you first resolve a clear source entity for the requested generation, still call this tool in the same turn using prompt-from-source. Use system_create instead for saving/importing existing text, URLs, uploads, prior assistant responses, or raw uploaded file preservation with upload transform preserve. On the initial generation request, do not pass confirmed; the tool returns confirmation args.",xFA,async(w,B)=>{let $=await ox2(A,w,B);if($.kind==="error")return $.result;let{createInput:f}=$.prepared,{operation:D,interceptor:Y,eventContext:X}=$.prepared;if(w.confirmed){let H=Q.validate(w.confirmationToken,w);if(H.status==="missing")return{success:!1,error:"No pending generate confirmation found. Please request generation again and confirm the new approval."};if(H.status==="mismatch")return{success:!1,error:"Confirmed generate arguments do not match the pending approval. Please request generation again and confirm the new approval."}}else{let H=lx2(f),W=Q.create((Z)=>({operation:D,confirmed:!0,confirmationToken:Z}));return{needsConfirmation:!0,toolName:"system_generate",summary:H.summary,preview:H.preview,args:W}}if(Y){let H=await nx2(A,Y,f,B);if(H.kind==="handled"||H.kind==="error")return H.result;f=H.createInput}if(!f.prompt)return{success:!1,error:"Attachment generation is supported only for entity types that explicitly handle source-derived artifacts."};return rx2(A,f,f.prompt,X,B)},{visibility:"trusted",sideEffects:"writes"})}var pFA=i(()=>{aB();k9();Z0();Rq();ZR();$I()});function iFA(A){let{entityService:Q,entityRegistry:w,logger:B}=A,$=new pW;return LH("delete","Request entity deletion by id. Unauthorized callers get a permission error; authorized callers get confirmation first. Do not pass confirmed on the initial request.",hFA,async(f,D)=>{if((D.userPermissionLevel??"public")==="public")return{success:!1,error:"Changing content requires higher permission; current permission is Public."};let Y=bH(A,f.entityType,"delete",D);if(Y)return Y;let X=hq(A,f.entityType);if(X)return X;if(w.getAdapter(f.entityType).isSingleton===!0)return{success:!1,error:`${f.entityType} is a singleton entity and cannot be deleted through system tools. Update it instead.`};let H=p8(D.userPermissionLevel),W=await A4(Q,f.entityType,f.id,B,void 0,H);if(!W.ok)return{success:!1,error:W.error};let{entity:Z}=W;if(f.confirmed){let V=$.validate(f.confirmationToken,f);if(V.status==="missing")return{success:!1,error:"No pending delete confirmation found. Please request deletion again and confirm the new approval."};if(V.status==="mismatch")return{success:!1,error:"Confirmed delete arguments do not match the pending approval. Please request deletion again and confirm the new approval."};try{await Q.deleteEntity({entityType:f.entityType,id:Z.id})}catch(b){return{success:!1,error:b instanceof Error?b.message:"Failed to delete entity"}}return{success:!0,data:{deleted:Z.id}}}let G=x10(Z),F=$.create((V)=>({...f,id:Z.id,confirmed:!0,confirmationToken:V}));return{needsConfirmation:!0,toolName:"system_delete",summary:`Delete "${G}"?`,preview:Z.content.slice(0,200),args:F}},{visibility:"anchor",sideEffects:"writes"})}var dFA=i(()=>{aB();k9();Rq();ZR();$I()});function nFA(A){let{entityService:Q,jobs:w}=A;return LH("extract",'Generate derived entities (e.g. topics) from existing content. Use this for explicit requests like "generate topics for me", "extract topics", "derive topics from my notes" \u2014 call once with `entityType` (typically `"topic"`); do not preflight with search/list. After a successful non-confirmation extract call, report that extraction started or was queued and do not append optional follow-up offers like "If you want...". Do not call this for vague continuations such as "go ahead", "continue", or "do that" unless the operator clearly chose extraction or topic derivation. Provide `source` to derive from a single entity, omit for a batch over all sources. `mode: "rebuild"` is currently only supported for `entityType: "topic"` and requires confirmation; other entity types fall back to normal projection mode.',vFA,async(B,$)=>{let{entityType:f,source:D}=B,X=(B.mode??"derive")==="rebuild",H=f==="topic"&&!D,W=X&&H?"rebuild":"derive",Z=hq(A,f);if(Z)return Z;let G=bH(A,f,"extract",$);if(G)return G;if(X&&H&&!B.confirmed)return{needsConfirmation:!0,toolName:"system_extract",summary:"Rebuild all derived topic entities from current source content?",preview:"This will delete existing topics and regenerate them from scratch.",args:{...B,confirmed:!0}};try{let F={mode:W};if(D){let b=p8($.userPermissionLevel);for(let L of Q.getEntityTypes()){let N=await Q.getEntity({entityType:L,id:D,visibilityScope:b});if(N){F.mode="source",F.entityId=N.id,F.entityType=N.entityType;break}}if(!F.entityId)return{success:!1,error:`Source entity not found: ${D}`}}return{success:!0,data:{status:"extracting",jobId:await w.enqueue({type:`${f}:project`,data:F,toolContext:$}),entityType:f,mode:W,...D&&{source:D}},...X&&!H?{message:D||f!=="topic"?`Rebuild is currently only supported for batch topic extraction. Ran normal projection mode for ${f} instead.`:void 0}:{}}}catch(F){return{success:!1,error:F instanceof Error?F.message:"Failed to queue extraction job"}}},{visibility:"trusted",sideEffects:"writes"})}var rFA=i(()=>{aB();Rq();ZR();$I()});var oFA,sFA,aFA,Uu,ax2;var Cb0=i(()=>{Z0();aB();oFA=K.enum(["png","jpg","jpeg","webp","gif","svg"]),sFA=K.enum(["pending","draft","failed"]),aFA=K.object({title:K.string().optional(),alt:K.string().optional(),format:oFA,width:K.number(),height:K.number(),status:sFA.optional(),processingJobId:K.string().optional(),processingError:K.string().optional(),sourceUrl:K.string().url().optional(),sourceEntityType:K.string().optional(),sourceEntityId:K.string().optional(),sourceUploadId:K.string().optional(),sourceFilename:K.string().optional(),sourceMediaType:K.string().optional(),attachmentType:K.string().optional(),dedupKey:K.string().optional()}),Uu=o1.extend({entityType:K.literal("image"),metadata:aFA}),ax2=K.object({url:K.string(),alt:K.string(),title:K.string(),width:K.number(),height:K.number()})});function fI(A){let Q=A.trim().match(/^data:image\/([a-z+]+);base64,(.+)$/i);if(!Q?.[1]||!Q[2])throw Error("Invalid image data URL");return{format:Q[1].toLowerCase(),base64:Q[2]}}function yb0(A,Q){return`data:image/${Q==="jpg"?"jpeg":Q};base64,${A}`}function Yj(A){for(let[Q,w]of Object.entries(tx2))if(A.startsWith(w))return Q;return null}async function NH(A){return Lt(A,"image/")}function DI(A){let Q=Buffer.from(A,"base64");if(Q[0]===137&&Q[1]===80&&Q[2]===78&&Q[3]===71){let w=Q.readUInt32BE(16),B=Q.readUInt32BE(20);return{width:w,height:B}}if(Q[0]===255&&Q[1]===216){let w=2;while(w<Q.length-8){if(Q[w]!==255){w++;continue}let B=Q[w+1];if(B===192||B===194){let f=Q.readUInt16BE(w+5);return{width:Q.readUInt16BE(w+7),height:f}}let $=Q.readUInt16BE(w+2);w+=2+$}}if(Q[0]===71&&Q[1]===73&&Q[2]===70){let w=Q.readUInt16LE(6),B=Q.readUInt16LE(8);return{width:w,height:B}}if(Q.length>=30&&Q[0]===82&&Q[1]===73&&Q[2]===70&&Q[3]===70){if(Q[12]===86&&Q[13]===80&&Q[14]===56){if(Q[15]===32){let w=Q[26]??0,B=Q[27]??0,$=Q[28]??0,f=Q[29]??0,D=(w|B<<8)&16383,Y=($|f<<8)&16383;return{width:D,height:Y}}if(Q[15]===76&&Q.length>=25){let w=Q.readUInt32LE(21),B=(w&16383)+1,$=(w>>14&16383)+1;return{width:B,height:$}}}}return null}var tx2;var Eb0=i(()=>{Z0();tx2={png:"iVBORw",jpg:"/9j/",gif:"R0lGOD",webp:"UklGR"}});class gb0{entityType="image";purpose="Image assets such as generated covers, social previews, and uploaded images.";schema=Uu;toMarkdown(A){return A.content}fromMarkdown(A){let{format:Q,base64:w}=fI(A),B=DI(w);return{entityType:"image",content:A,metadata:{format:Q,width:B?.width??0,height:B?.height??0}}}extractMetadata(A){return A.metadata}parseFrontMatter(A,Q){return Q.parse({})}generateFrontMatter(A){return""}getBodyTemplate(){return""}createImageEntity(A){let{dataUrl:Q,title:w,alt:B}=A,{format:$,base64:f}=fI(Q),D=DI(f),X=Yj(f)??$;return{entityType:"image",content:Q,metadata:{title:w,alt:B??w,format:X,width:D?.width??0,height:D?.height??0,...A.status&&{status:A.status},...A.sourceUrl&&{sourceUrl:A.sourceUrl},...A.sourceEntityType&&{sourceEntityType:A.sourceEntityType},...A.sourceEntityId&&{sourceEntityId:A.sourceEntityId},...A.sourceUploadId&&{sourceUploadId:A.sourceUploadId},...A.sourceFilename&&{sourceFilename:A.sourceFilename},...A.sourceMediaType&&{sourceMediaType:A.sourceMediaType},...A.attachmentType&&{attachmentType:A.attachmentType},...A.dedupKey&&{dedupKey:A.dedupKey}}}}}var vY;var tFA=i(()=>{Cb0();Eb0();vY=new gb0});async function eFA(A,Q){let w=await Q.getEntity({entityType:"image",id:A});if(!w)return;return{url:w.content,alt:w.metadata.alt??"",title:w.metadata.title??"",width:w.metadata.width,height:w.metadata.height}}function AVA(A,Q){let w=ex2.exec(A.content);if(!w?.[1])return;try{let B=qt(w[1]);if(B&&typeof B==="object"&&!Array.isArray(B)){let $=B[Q];return typeof $==="string"?$:void 0}}catch{return}return}function Gu(A){return AVA(A,"coverImageId")}function R10(A){return AVA(A,"ogImageId")}function Xj(A,Q){return{...A,content:o4(A.content,"coverImageId",Q)}}function zu(A,Q){return{...A,content:o4(A.content,"ogImageId",Q)}}async function Tb0(A,Q){let w=Gu(A);if(!w)return;return eFA(w,Q)}var ex2;var QVA=i(()=>{Z0();ex2=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/});function Sb0(A){let Q=[],w=AR2.parse(A);return bT(w,"image",(B)=>{Q.push({url:B.url,alt:B.alt??"",title:B.title??void 0})}),Q}var AR2;var wVA=i(()=>{Dt();EW0();AR2=AO()});var D4=i(()=>{Cb0();tFA();QVA();wVA();Eb0()});function BVA(A,Q,w,B){let $=B.getEntityTypeConfig(A).publish?.publishStatuses;if(!$?.length)return"non-publish";if(typeof w!=="string")return"non-publish";let f=typeof Q==="string"&&$.includes(Q);if(!$.includes(w))return"non-publish";return f?"within-publish-set":"boundary"}function QR2(A,Q){return Q==="visibility"?A.visibility:A.metadata[Q]}function wR2(A,Q){let{visibility:w,coverImageId:B,ogImageId:$,...f}=Q,D=w===void 0?A.visibility:X7.parse(w),Y=Object.hasOwn(Q,"coverImageId")?Xj(A,typeof B==="string"?B:null):A,X=Object.hasOwn(Q,"ogImageId")?zu(Y,typeof $==="string"?$:null):Y,H={...A.metadata};for(let[Z,G]of Object.entries(f))if(G===null)delete H[Z];else H[Z]=G;let W={...X,visibility:D,metadata:H};for(let[Z,G]of Object.entries(f))if(G===null)delete W[Z];else W[Z]=G;return W}function BR2(A,Q){if(A!=="anchor-profile")return;if(Q.fields)return{success:!1,error:"anchor-profile updates require full markdown content replacement, not fields-only updates."};return}function $R2(A,Q,w){if(Q.content===void 0)return;let B=Q.content.trim(),$=w.getEffectiveFrontmatterSchema(A);if(!$)return;if(!B)return{success:!1,error:"Full content replacement cannot be empty for this entity type. Use 'fields' for partial updates."};try{w.getAdapter(A).parseFrontMatter(Q.content,$)}catch{return{success:!1,error:"Invalid content replacement for this entity type. Provide full markdown with valid frontmatter, or use 'fields' for partial updates."}}return}function fR2(A,Q,w){if(!Q.fields||!("coverImageId"in Q.fields))return;let B=Q.fields.coverImageId;if(B!==null&&B!==void 0&&typeof B!=="string")return{success:!1,error:"coverImageId must be a string or null"};if(B==="__PENDING__"||typeof B==="string"&&B.startsWith("upload-"))return{success:!1,error:"coverImageId must reference an existing image id or be null"};if(w.getAdapter(A).supportsCoverImage)return;return{success:!1,error:`Entity type '${A}' doesn't support cover images`}}function DR2(A,Q,w){if(Q.fields&&"status"in Q.fields)return Q.fields.status;if(Q.content!==void 0){let B=w.getEffectiveFrontmatterSchema(A.entityType);if(!B)return A.metadata.status;try{return w.getAdapter(A.entityType).parseFrontMatter(Q.content,B).status}catch{return A.metadata.status}}return A.metadata.status}function YR2(A,Q){if(Q.fields)return Object.entries(Q.fields).map(([f,D])=>`${f}: ${String(QR2(A,f)??"(empty)")} \u2192 ${String(D)}`).join(`
390
390
  `);let w=A.content.split(`
391
391
  `),B=(Q.content??"").split(`
392
392
  `),$=[];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(`
393
393
  `)}function $VA(A){let{entityService:Q,logger:w,entityRegistry:B}=A;return LH("update","Update an entity's fields or content. Requires confirmation. 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.",RFA,async($,f)=>{let D=p8(f.userPermissionLevel),Y=await A4(Q,$.entityType,$.id,w,void 0,D);if(!Y.ok)return{success:!1,error:Y.error};let{entity:X}=Y,H=gFA({...$.fields!==void 0?{fields:$.fields}:{},...$.content!==void 0?{content:$.content}:{}}),W=H.content?.trim().length===0&&H.fields===void 0,Z=X.metadata.status;if($.confirmed&&X.entityType==="agent"&&(Z==="discovered"||Z==="approved")&&(!H.content&&!H.fields||W))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 G=BR2(X.entityType,H);if(G)return G;let F=$R2(X.entityType,H,B);if(F)return F;let V=fR2(X.entityType,H,B);if(V)return V;let b=X.metadata.status,L=DR2(X,H,B),_=BVA(X.entityType,b,L,B)==="non-publish"?"update":"publish",j=bH(A,$.entityType,_,f);if(j)return j;if($.confirmed){if($.contentHash&&X.contentHash!==$.contentHash)return{success:!1,error:"Entity was modified since you reviewed the changes. Please try again."};let y=H.content!==void 0?{...X,content:H.content,visibility:GN(H.content)}:wR2(X,H.fields??{});if(y.visibility!==X.visibility&&!dO(f.userPermissionLevel,y.visibility))return{success:!1,error:`Cannot set entity visibility to "${y.visibility}" \u2014 caller permission "${f.userPermissionLevel??"public"}" is not allowed to write at that level.`};try{let h=KR(f);await Q.updateEntity({entity:y,...h?{options:{eventContext:h}}:{}})}catch(h){return{success:!1,error:h instanceof Error?h.message:"Failed to update entity"}}return{success:!0,data:{updated:X.id}}}let g=x10(X),E=YR2(X,H);return{needsConfirmation:!0,toolName:"system_update",summary:`Update "${g}"?`,completionSummary:`Updated ${TFA(X.entityType)}.`,preview:E,args:{...$,...H,id:X.id,confirmed:!0,contentHash:X.contentHash}}},{visibility:"trusted",sideEffects:"writes"})}var fVA=i(()=>{aB();D4();Rq();ZR();$I()});function DVA(A){return[uFA(A),lFA(A),iFA(A),$VA(A),nFA(A)]}var YVA=i(()=>{cFA();pFA();dFA();rFA();fVA()});function XVA(A){let{entityService:Q,logger:w}=A;return[Sw("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. Search results are candidates; do not present weak or unrelated candidates as exact matches.",_FA,async(B,$)=>{let f=p8($.userPermissionLevel);return{success:!0,data:{guidance:"Search results are semantic candidates, not guaranteed exact matches. If the results do not clearly answer the requested item/category, say no clear matching content was found instead of presenting weak candidates as matches.",results:(await Q.search({query:B.query,options:{limit:B.limit??A.searchLimit,...B.scope.kind==="type"&&{types:[B.scope.entityType]},...B.includeUngenerated!==void 0&&{includeUngenerated:B.includeUngenerated},visibilityScope:f}})).map((D)=>({...D,entity:vb0(D.entity)}))}}},{visibility:"public",sideEffects:"none",cli:{name:"search"}}),Sw("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.",PFA,async(B,$)=>{if(!Q.getEntityTypes().includes(B.entityType))return{success:!1,error:`Unknown entity type: ${B.entityType}. Available: ${Q.getEntityTypes().join(", ")}`};let f=p8($.userPermissionLevel),D=await A4(Q,B.entityType,B.id,w,void 0,f);if(!D.ok)return{success:!1,error:D.error};return{success:!0,data:{entity:vb0(D.entity)}}},{visibility:"public",sideEffects:"none",cli:{name:"get"}}),Sw("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.",kFA,async(B,$)=>{if(!Q.getEntityTypes().includes(B.entityType))return{success:!1,error:`Unknown entity type: ${B.entityType}. Available: ${Q.getEntityTypes().join(", ")}`};let D={visibilityScope:p8($.userPermissionLevel)};if(B.status&&B.status!=="any")D.metadata={status:B.status};let X=(await Q.listEntities({entityType:B.entityType,options:{limit:B.limit??20,filter:D}})).map(({content:H,contentHash:W,...Z})=>Z);return{success:!0,data:{entities:X,count:X.length}}},{visibility:"public",sideEffects:"none",cli:{name:"list"}})]}var HVA=i(()=>{k9();aB();Rq();$I()});function WVA(A){let{entityService:Q}=A;return[Sw("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(", ")}.`,yFA,async(w,B)=>{let $=p8(B.userPermissionLevel);return{success:!0,data:await A.insights.get(w.type,Q,$)}},{visibility:"public",sideEffects:"none"})]}var ZVA=i(()=>{k9();aB();Rq()});function KVA(A){let{jobs:Q}=A;return[LH("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.",CFA,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 D=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:D},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 UVA=i(()=>{Rq();$I()});function XR2(A){let{entityCounts:Q,daemons:w,endpoints:B,interactions:$,...f}=A;return f}function GVA(A){return[Sw("system","status","Get system status including model, version, interfaces, and tools",K.object({}),async()=>({success:!0,data:XR2(await A.getAppInfo())}),{visibility:"public",sideEffects:"none",cli:{name:"status"}})]}var zVA=i(()=>{k9();Z0()});function qVA(A){return[...XVA(A),...KVA(A),...GVA(A),...DVA(A),...WVA(A)]}var FVA=i(()=>{YVA();HVA();ZVA();UVA();zVA()});function VVA(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(`
394
- `)}]})},{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 IVA(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((D)=>({id:D.id,entityType:D.entityType,...D.metadata,updated:D.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 JVA(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 bVA(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:","",`- **system_create**: Create an entity from existing/concrete material. Requires confirmation before persisting; 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 the immediate context is an assistant summary/answer about an upload and the user asks to save that response, create a note with \`source.kind: "prior-response"\`; only use upload \`preserve\` 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, then call system_generate in the same turn when a clear source is found. If no existing durable source entity is resolved, omit `operation.source`; 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', omit `operation.source`. If the user asks for the latest source and candidates include dates such as publishedAt, choose the newest matching candidate and proceed with system_generate rather than asking for separate prose approval. 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, source?: { entityType, entityId } }` generates a new non-image durable entity; include `source` when generating from an existing 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 requests for source-derived artifacts, call `system_generate` with `operation.kind: \"attachment\"` immediately. 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; 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. 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. 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.',"- **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.","- **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.","","Entity types \u2014 select `entityType` by what the type is for:",...w].join(`
394
+ `)}]})},{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 IVA(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((D)=>({id:D.id,entityType:D.entityType,...D.metadata,updated:D.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 JVA(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 bVA(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:","",`- **system_create**: Create an entity from existing/concrete material. Requires confirmation before persisting; 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; 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 that response, create a note with \`source.kind: "prior-response"\`; only use upload \`preserve\` 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, 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 source and candidates include dates such as publishedAt, choose the newest matching candidate 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; 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. 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.',"- **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.","- **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.","","Entity types \u2014 select `entityType` by what the type is for:",...w].join(`
395
395
  `)}function h10(A,Q,w,B,$){for(let f of A)try{Q(f)}catch{$.debug(`System ${B} ${w(f)} already registered, skipping`)}}function LVA(A,Q,w,B){let $=qVA(A);h10($,(W)=>Q.registerTool(UR,W),(W)=>W.name,"tool",B);let f=w.subscribe(`plugin:${UR}:tool:execute`,async(W)=>{let Z=HR2.safeParse(W.payload);if(!Z.success)return{success:!1,error:"Invalid system tool execute payload"};let{toolName:G,args:F,interfaceType:V,userId:b,conversationId:L,channelId:N,userPermissionLevel:_}=Z.data,j=$.find((y)=>y.name===G);if(!j)return{success:!1,error:`System tool not found: ${G}`};let g={interfaceType:V??"system",userId:b??"system"};if(L)g.conversationId=L;if(N)g.channelId=N;if(_)g.userPermissionLevel=_;return{success:!0,data:await j.handler(F,g)}});B.debug(`Registered ${$.length} system tools`);let D=VVA(A);h10(D,(W)=>Q.registerResource(UR,W),(W)=>W.uri,"resource",B),B.debug(`Registered ${D.length} system resources`);let Y=IVA(A);h10(Y,(W)=>Q.registerResourceTemplate(UR,W),(W)=>W.uriTemplate,"resource template",B),B.debug(`Registered ${Y.length} system resource templates`);let X=JVA(A);h10(X,(W)=>Q.registerPrompt(UR,W),(W)=>W.name,"prompt",B),B.debug(`Registered ${X.length} system prompts`);let H=bVA(A);try{Q.registerInstructions(UR,H)}catch{B.debug("System instructions already registered, skipping")}return B.debug("Registered system instructions"),f}var UR="system",HR2;var NVA=i(()=>{k9();Z0();FVA();HR2=K.object({toolName:K.string(),args:K.unknown()}).extend(fN.partial().shape)});function jVA(A){let{services:Q,jobs:w,insights:B,query:$,getAppInfo:f}=A,D=Q.jobQueueService,Y=Q.logger.child("system"),X=LVA({entityService:Q.entityService,entityRegistry:Q.entityRegistry,jobs:{...w,enqueue:ZS(D,"system",!1),enqueueBatch:KS(w,"system"),registerHandler:US(D,"system")},conversationService:Q.conversationService,runtimeUploads:Q.runtimeUploadRegistry,attachments:JS(Q.attachmentRegistry),logger:Y,query:$,getIdentity:()=>Q.identityService.getCharacter(),getProfile:()=>Q.profileService.getProfile(),getAppInfo:f,searchLimit:10,insights:B,permissionService:Q.permissionService},Q.mcpService,Q.messageBus,Y);Q.disposables.push(X)}var MVA=i(()=>{fq();c0();NVA()});var zFA={};sw(zFA,{Shell:()=>CY});class CY{config;static instance=null;services;bootloader;initialized=!1;insightsRegistry;bootTime=Date.now();endpointRegistry=new Rb0;interactionRegistry=new hb0;jobs;static getInstance(A){return CY.instance??=new CY(Kx(A??{})),CY.instance}static async resetInstance(){if(CY.instance)await CY.instance.shutdown(),CY.instance=null}static createFresh(A,Q){Zu();let w=Kx(A);return new CY(w,Q)}constructor(A,Q){this.config=A;let w=qZ.getInstance(Q?.logger??e2.getInstance(),this.config);this.services=w.initializeServices(Q),this.jobs=LFA(this.services.batchJobManager,this.services.jobQueueService),this.insightsRegistry=VFA(),this.bootloader=new Ob0(this.config,this.services,{registerCoreDataSources:()=>t9A(this.services,this.config),registerSystemCapabilities:()=>jVA({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 MFA(this.services),this.initialized=!1,this.services.logger.debug("Shell shutdown complete")}async generateContent(A){return this.requireInitialized("Shell content generation"),A7A(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:Ux.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 JS(this.services.attachmentRegistry)}getRuntimeUploadRegistry(){return lU0(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 NFA(this.services.pluginManager)}getPluginWebRoutes(){return jFA(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 p9A({config:this.config,services:this.services,bootTime:this.bootTime,endpoints:()=>this.listEndpoints(),interactions:()=>this.listInteractions()})}}var kb0=i(()=>{c0();Z0();i9A();MG0();xN();e9A();O10();qFA();JFA();bFA();MVA()});var _VA={};sw(_VA,{shellConfigSchema:()=>J00,resetServiceSingletons:()=>Zu,resetAllSingletons:()=>GFA,getStandardConfigWithDirectories:()=>SS,getStandardConfig:()=>TS,createShellConfig:()=>Kx,Shell:()=>CY,STANDARD_PATHS:()=>rV,SHELL_TEMPLATE_NAMES:()=>Ux,SHELL_ENTITY_TYPES:()=>Af,SHELL_DATASOURCE_IDS:()=>b00});var v10=i(()=>{kb0();MG0();xN();O10()});var YI,mb0,C10;var GR=i(()=>{Z0();c0();zq();YI=K.enum(["debug","info","warn","error"]),mb0=K.object({provider:K.enum(["hetzner","docker"]).default("hetzner"),serverSize:K.string().default("cx33"),location:K.string().default("fsn1"),domain:K.string().optional(),docker:K.object({enabled:K.boolean().default(!0),image:K.string().optional()}).default({}),ports:K.object({default:K.number().default(3333),preview:K.number().default(4321),production:K.number().default(8080)}).default({}),cdn:K.object({enabled:K.boolean().default(!1),provider:K.enum(["bunny","none"]).default("none")}).default({}),dns:K.object({enabled:K.boolean().default(!1),provider:K.enum(["bunny","none"]).default("none")}).default({}),paths:K.object({install:K.string().optional(),data:K.string().optional()}).default({})}),C10=K.object({name:K.string().default("brain-app"),version:K.string().default("1.0.0"),database:K.string().optional(),aiApiKey:K.string().optional(),aiImageKey:K.string().optional(),aiModel:K.string().optional(),logLevel:YI.optional(),logFile:K.string().optional(),plugins:K.array(dT).default([]),spaces:K.array(K.string()).default([]),identity:Xx.optional(),agentInstructions:K.array(K.string()).optional(),deployment:mb0.default({})})});import WR2 from"crypto";import ub0 from"fs";function PVA(A){let Q=A.migrationsFolder,w=[],B=`${Q}/meta/_journal.json`;if(!ub0.existsSync(B))throw Error("Can't find meta/_journal.json file");let $=ub0.readFileSync(`${Q}/meta/_journal.json`).toString(),f=JSON.parse($);for(let D of f.entries){let Y=`${Q}/${D.tag}.sql`;try{let X=ub0.readFileSync(`${Q}/${D.tag}.sql`).toString(),H=X.split("--> statement-breakpoint").map((W)=>{return W});w.push({sql:H,bps:D.breakpoints,folderMillis:D.when,hash:WR2.createHash("sha256").update(X).digest("hex")})}catch{throw Error(`No file ${Y} found in ${Q} folder`)}}return w}var kVA=()=>{};async function XI(A,Q){let w=PVA(Q),B=Q.migrationsTable??"__drizzle_migrations",$=g0`
396
396
  CREATE TABLE IF NOT EXISTS ${g0.identifier(B)} (
397
397
  id SERIAL PRIMARY KEY,
398
398
  hash text NOT NULL,
399
399
  created_at numeric
400
400
  )
401
- `;await A.session.run($);let D=(await A.values(g0`SELECT id, hash, created_at FROM ${g0.identifier(B)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,Y=[];for(let X of w)if(!D||Number(D[2])<X.folderMillis){for(let H of X.sql)Y.push(A.run(g0.raw(H)));Y.push(A.run(g0`INSERT INTO ${g0.identifier(B)} ("hash", "created_at") VALUES(${X.hash}, ${X.folderMillis})`))}await A.session.migrate(Y)}var qu=i(()=>{kVA();c$()});async function OVA(A,Q){let w=Q?.child("entity-migrate")??e2.getInstance().child("entity-migrate"),{db:B,client:$,url:f}=ke(A);w.debug("Running entity database migrations...");try{await Oe($,f);let Y=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await XI(B,{migrationsFolder:Y}),await xe($),w.debug("Entity database migrations completed successfully")}catch(D){throw w.error("Entity database migration failed:",D),D}finally{$.close()}}var xVA=i(()=>{qu();YU0();Z0()});async function RVA(A,Q){let w=Q?.child("job-queue-migrate")??e2.getInstance().child("job-queue-migrate"),{db:B,client:$,url:f}=Me(A);w.debug("Running job queue migrations...");try{await _e($,f);let Y=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await XI(B,{migrationsFolder:Y}),w.debug("Job queue migrations completed successfully")}catch(D){throw w.error("Job queue migration failed:",D),D}finally{$.close()}}var hVA=i(()=>{qu();aK0();Z0()});async function vVA(A,Q){let w=Q?.child("conversation-migrate")??e2.getInstance().child("conversation-migrate"),{db:B,client:$,url:f}=ce(A);w.debug("Running conversation database migrations...");try{if(f.startsWith("file:"))await $.execute("PRAGMA journal_mode = WAL");let Y=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await XI(B,{migrationsFolder:Y}),w.debug("Conversation database migrations completed successfully")}catch(D){throw w.error("Conversation database migration failed:",D),D}finally{$.close()}}var CVA=i(()=>{qu();nU0();Z0()});async function yVA(A,Q){let w=Q?.child("runtime-state-migrate")??e2.getInstance().child("runtime-state-migrate"),{db:B,client:$,url:f}=_10(A);w.debug("Running runtime state migrations...");try{await P10($,f);let Y=import.meta.url.includes("/dist/")?new URL("./migrations/runtime-state",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await XI(B,{migrationsFolder:Y}),w.debug("Runtime state migrations completed successfully")}catch(D){throw w.error("Runtime state migration failed:",D),D}finally{$.close()}}var EVA=i(()=>{qu();Z0();Nb0()});class Fu{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:SS,migrateEntities:OVA,migrateJobQueue:RVA,migrateConversations:vVA,migrateRuntimeState:yVA}}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 cb0=i(()=>{v10();xVA();hVA();CVA();EVA()});function KR2(){return process.env[ZR2]}function gVA(){return KR2()!=="production"}var ZR2="NODE_ENV";var y10;var lb0=i(()=>{Z0();y10=K.object({theme:K.object({primaryColor:K.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:K.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var SVA;var TVA=i(()=>{SVA={name:"@brains/chat-repl",private:!0,version:"0.2.0-alpha.133",type:"module",main:"./src/index.ts",module:"./src/index.ts",types:"./src/index.ts",files:["src"],scripts:{dev:"tsc --watch",typecheck:"tsc --noEmit",lint:"eslint --max-warnings 0 .","lint:fix":"eslint --fix .",test:"bun test"},dependencies:{"@brains/plugins":"workspace:*",chalk:"^5.4.1",ink:"^6.0.1","ink-spinner":"^5.0.0","ink-text-input":"^6.0.0",marked:"^12.0.0",react:"^19.2.6"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14","@types/react":"^19.0.3",typescript:"^5.3.3"}}});var Hw=O((GR2,E10)=>{(function(){function A(Y0,u0){Object.defineProperty(B.prototype,Y0,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",u0[0],u0[1])}})}function Q(Y0){if(Y0===null||typeof Y0!=="object")return null;return Y0=C0&&Y0[C0]||Y0["@@iterator"],typeof Y0==="function"?Y0:null}function w(Y0,u0){Y0=(Y0=Y0.constructor)&&(Y0.displayName||Y0.name)||"ReactClass";var R0=Y0+"."+u0;G0[R0]||(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.",u0,Y0),G0[R0]=!0)}function B(Y0,u0,R0){this.props=Y0,this.context=u0,this.refs=p0,this.updater=R0||J0}function $(){}function f(Y0,u0,R0){this.props=Y0,this.context=u0,this.refs=p0,this.updater=R0||J0}function D(){}function Y(Y0){return""+Y0}function X(Y0){try{Y(Y0);var u0=!1}catch(zA){u0=!0}if(u0){u0=console;var R0=u0.error,n0=typeof Symbol==="function"&&Symbol.toStringTag&&Y0[Symbol.toStringTag]||Y0.constructor.name||"Object";return R0.call(u0,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",n0),Y(Y0)}}function H(Y0){if(Y0==null)return null;if(typeof Y0==="function")return Y0.$$typeof===YA?null:Y0.displayName||Y0.name||null;if(typeof Y0==="string")return Y0;switch(Y0){case A0:return"Fragment";case K0:return"Profiler";case o:return"StrictMode";case fA:return"Suspense";case D0:return"SuspenseList";case z0:return"Activity"}if(typeof Y0==="object")switch(typeof Y0.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),Y0.$$typeof){case p:return"Portal";case $0:return Y0.displayName||"Context";case V0:return(Y0._context.displayName||"Context")+".Consumer";case i0:var u0=Y0.render;return Y0=Y0.displayName,Y0||(Y0=u0.displayName||u0.name||"",Y0=Y0!==""?"ForwardRef("+Y0+")":"ForwardRef"),Y0;case _0:return u0=Y0.displayName||null,u0!==null?u0:H(Y0.type)||"Memo";case x0:u0=Y0._payload,Y0=Y0._init;try{return H(Y0(u0))}catch(R0){}}return null}function W(Y0){if(Y0===A0)return"<>";if(typeof Y0==="object"&&Y0!==null&&Y0.$$typeof===x0)return"<...>";try{var u0=H(Y0);return u0?"<"+u0+">":"<...>"}catch(R0){return"<...>"}}function Z(){var Y0=BA.A;return Y0===null?null:Y0.getOwner()}function G(){return Error("react-stack-top-frame")}function F(Y0){if(k0.call(Y0,"key")){var u0=Object.getOwnPropertyDescriptor(Y0,"key").get;if(u0&&u0.isReactWarning)return!1}return Y0.key!==void 0}function V(Y0,u0){function R0(){H0||(H0=!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)",u0))}R0.isReactWarning=!0,Object.defineProperty(Y0,"key",{get:R0,configurable:!0})}function b(){var Y0=H(this.type);return Q1[Y0]||(Q1[Y0]=!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.")),Y0=this.props.ref,Y0!==void 0?Y0:null}function L(Y0,u0,R0,n0,zA,MA){var $A=R0.ref;return Y0={$$typeof:l,type:Y0,key:u0,props:R0,_owner:n0},($A!==void 0?$A:null)!==null?Object.defineProperty(Y0,"ref",{enumerable:!1,get:b}):Object.defineProperty(Y0,"ref",{enumerable:!1,value:null}),Y0._store={},Object.defineProperty(Y0._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(Y0,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(Y0,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:zA}),Object.defineProperty(Y0,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:MA}),Object.freeze&&(Object.freeze(Y0.props),Object.freeze(Y0)),Y0}function N(Y0,u0){return u0=L(Y0.type,u0,Y0.props,Y0._owner,Y0._debugStack,Y0._debugTask),Y0._store&&(u0._store.validated=Y0._store.validated),u0}function _(Y0){j(Y0)?Y0._store&&(Y0._store.validated=1):typeof Y0==="object"&&Y0!==null&&Y0.$$typeof===x0&&(Y0._payload.status==="fulfilled"?j(Y0._payload.value)&&Y0._payload.value._store&&(Y0._payload.value._store.validated=1):Y0._store&&(Y0._store.validated=1))}function j(Y0){return typeof Y0==="object"&&Y0!==null&&Y0.$$typeof===l}function g(Y0){var u0={"=":"=0",":":"=2"};return"$"+Y0.replace(/[=:]/g,function(R0){return u0[R0]})}function E(Y0,u0){return typeof Y0==="object"&&Y0!==null&&Y0.key!=null?(X(Y0.key),g(""+Y0.key)):u0.toString(36)}function y(Y0){switch(Y0.status){case"fulfilled":return Y0.value;case"rejected":throw Y0.reason;default:switch(typeof Y0.status==="string"?Y0.then(D,D):(Y0.status="pending",Y0.then(function(u0){Y0.status==="pending"&&(Y0.status="fulfilled",Y0.value=u0)},function(u0){Y0.status==="pending"&&(Y0.status="rejected",Y0.reason=u0)})),Y0.status){case"fulfilled":return Y0.value;case"rejected":throw Y0.reason}}throw Y0}function h(Y0,u0,R0,n0,zA){var MA=typeof Y0;if(MA==="undefined"||MA==="boolean")Y0=null;var $A=!1;if(Y0===null)$A=!0;else switch(MA){case"bigint":case"string":case"number":$A=!0;break;case"object":switch(Y0.$$typeof){case l:case p:$A=!0;break;case x0:return $A=Y0._init,h($A(Y0._payload),u0,R0,n0,zA)}}if($A){$A=Y0,zA=zA($A);var tA=n0===""?"."+E($A,0):n0;return FA(zA)?(R0="",tA!=null&&(R0=tA.replace(y0,"$&/")+"/"),h(zA,u0,R0,"",function(l1){return l1})):zA!=null&&(j(zA)&&(zA.key!=null&&($A&&$A.key===zA.key||X(zA.key)),R0=N(zA,R0+(zA.key==null||$A&&$A.key===zA.key?"":(""+zA.key).replace(y0,"$&/")+"/")+tA),n0!==""&&$A!=null&&j($A)&&$A.key==null&&$A._store&&!$A._store.validated&&(R0._store.validated=2),zA=R0),u0.push(zA)),1}if($A=0,tA=n0===""?".":n0+":",FA(Y0))for(var gA=0;gA<Y0.length;gA++)n0=Y0[gA],MA=tA+E(n0,gA),$A+=h(n0,u0,R0,MA,zA);else if(gA=Q(Y0),typeof gA==="function")for(gA===Y0.entries&&(o0||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),o0=!0),Y0=gA.call(Y0),gA=0;!(n0=Y0.next()).done;)n0=n0.value,MA=tA+E(n0,gA++),$A+=h(n0,u0,R0,MA,zA);else if(MA==="object"){if(typeof Y0.then==="function")return h(y(Y0),u0,R0,n0,zA);throw u0=String(Y0),Error("Objects are not valid as a React child (found: "+(u0==="[object Object]"?"object with keys {"+Object.keys(Y0).join(", ")+"}":u0)+"). If you meant to render a collection of children, use an array instead.")}return $A}function T(Y0,u0,R0){if(Y0==null)return Y0;var n0=[],zA=0;return h(Y0,n0,"","",function(MA){return u0.call(R0,MA,zA++)}),n0}function S(Y0){if(Y0._status===-1){var u0=Y0._ioInfo;u0!=null&&(u0.start=u0.end=performance.now()),u0=Y0._result;var R0=u0();if(R0.then(function(zA){if(Y0._status===0||Y0._status===-1){Y0._status=1,Y0._result=zA;var MA=Y0._ioInfo;MA!=null&&(MA.end=performance.now()),R0.status===void 0&&(R0.status="fulfilled",R0.value=zA)}},function(zA){if(Y0._status===0||Y0._status===-1){Y0._status=2,Y0._result=zA;var MA=Y0._ioInfo;MA!=null&&(MA.end=performance.now()),R0.status===void 0&&(R0.status="rejected",R0.reason=zA)}}),u0=Y0._ioInfo,u0!=null){u0.value=R0;var n0=R0.displayName;typeof n0==="string"&&(u0.name=n0)}Y0._status===-1&&(Y0._status=0,Y0._result=R0)}if(Y0._status===1)return u0=Y0._result,u0===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
401
+ `;await A.session.run($);let D=(await A.values(g0`SELECT id, hash, created_at FROM ${g0.identifier(B)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,Y=[];for(let X of w)if(!D||Number(D[2])<X.folderMillis){for(let H of X.sql)Y.push(A.run(g0.raw(H)));Y.push(A.run(g0`INSERT INTO ${g0.identifier(B)} ("hash", "created_at") VALUES(${X.hash}, ${X.folderMillis})`))}await A.session.migrate(Y)}var qu=i(()=>{kVA();c$()});async function OVA(A,Q){let w=Q?.child("entity-migrate")??e2.getInstance().child("entity-migrate"),{db:B,client:$,url:f}=ke(A);w.debug("Running entity database migrations...");try{await Oe($,f);let Y=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await XI(B,{migrationsFolder:Y}),await xe($),w.debug("Entity database migrations completed successfully")}catch(D){throw w.error("Entity database migration failed:",D),D}finally{$.close()}}var xVA=i(()=>{qu();YU0();Z0()});async function RVA(A,Q){let w=Q?.child("job-queue-migrate")??e2.getInstance().child("job-queue-migrate"),{db:B,client:$,url:f}=Me(A);w.debug("Running job queue migrations...");try{await _e($,f);let Y=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await XI(B,{migrationsFolder:Y}),w.debug("Job queue migrations completed successfully")}catch(D){throw w.error("Job queue migration failed:",D),D}finally{$.close()}}var hVA=i(()=>{qu();aK0();Z0()});async function vVA(A,Q){let w=Q?.child("conversation-migrate")??e2.getInstance().child("conversation-migrate"),{db:B,client:$,url:f}=ce(A);w.debug("Running conversation database migrations...");try{if(f.startsWith("file:"))await $.execute("PRAGMA journal_mode = WAL");let Y=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await XI(B,{migrationsFolder:Y}),w.debug("Conversation database migrations completed successfully")}catch(D){throw w.error("Conversation database migration failed:",D),D}finally{$.close()}}var CVA=i(()=>{qu();nU0();Z0()});async function yVA(A,Q){let w=Q?.child("runtime-state-migrate")??e2.getInstance().child("runtime-state-migrate"),{db:B,client:$,url:f}=_10(A);w.debug("Running runtime state migrations...");try{await P10($,f);let Y=import.meta.url.includes("/dist/")?new URL("./migrations/runtime-state",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await XI(B,{migrationsFolder:Y}),w.debug("Runtime state migrations completed successfully")}catch(D){throw w.error("Runtime state migration failed:",D),D}finally{$.close()}}var EVA=i(()=>{qu();Z0();Nb0()});class Fu{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:SS,migrateEntities:OVA,migrateJobQueue:RVA,migrateConversations:vVA,migrateRuntimeState:yVA}}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 cb0=i(()=>{v10();xVA();hVA();CVA();EVA()});function KR2(){return process.env[ZR2]}function gVA(){return KR2()!=="production"}var ZR2="NODE_ENV";var y10;var lb0=i(()=>{Z0();y10=K.object({theme:K.object({primaryColor:K.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:K.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var SVA;var TVA=i(()=>{SVA={name:"@brains/chat-repl",private:!0,version:"0.2.0-alpha.134",type:"module",main:"./src/index.ts",module:"./src/index.ts",types:"./src/index.ts",files:["src"],scripts:{dev:"tsc --watch",typecheck:"tsc --noEmit",lint:"eslint --max-warnings 0 .","lint:fix":"eslint --fix .",test:"bun test"},dependencies:{"@brains/plugins":"workspace:*",chalk:"^5.4.1",ink:"^6.0.1","ink-spinner":"^5.0.0","ink-text-input":"^6.0.0",marked:"^12.0.0",react:"^19.2.6"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14","@types/react":"^19.0.3",typescript:"^5.3.3"}}});var Hw=O((GR2,E10)=>{(function(){function A(Y0,u0){Object.defineProperty(B.prototype,Y0,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",u0[0],u0[1])}})}function Q(Y0){if(Y0===null||typeof Y0!=="object")return null;return Y0=C0&&Y0[C0]||Y0["@@iterator"],typeof Y0==="function"?Y0:null}function w(Y0,u0){Y0=(Y0=Y0.constructor)&&(Y0.displayName||Y0.name)||"ReactClass";var R0=Y0+"."+u0;G0[R0]||(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.",u0,Y0),G0[R0]=!0)}function B(Y0,u0,R0){this.props=Y0,this.context=u0,this.refs=p0,this.updater=R0||J0}function $(){}function f(Y0,u0,R0){this.props=Y0,this.context=u0,this.refs=p0,this.updater=R0||J0}function D(){}function Y(Y0){return""+Y0}function X(Y0){try{Y(Y0);var u0=!1}catch(zA){u0=!0}if(u0){u0=console;var R0=u0.error,n0=typeof Symbol==="function"&&Symbol.toStringTag&&Y0[Symbol.toStringTag]||Y0.constructor.name||"Object";return R0.call(u0,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",n0),Y(Y0)}}function H(Y0){if(Y0==null)return null;if(typeof Y0==="function")return Y0.$$typeof===YA?null:Y0.displayName||Y0.name||null;if(typeof Y0==="string")return Y0;switch(Y0){case A0:return"Fragment";case K0:return"Profiler";case o:return"StrictMode";case fA:return"Suspense";case D0:return"SuspenseList";case z0:return"Activity"}if(typeof Y0==="object")switch(typeof Y0.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),Y0.$$typeof){case p:return"Portal";case $0:return Y0.displayName||"Context";case V0:return(Y0._context.displayName||"Context")+".Consumer";case i0:var u0=Y0.render;return Y0=Y0.displayName,Y0||(Y0=u0.displayName||u0.name||"",Y0=Y0!==""?"ForwardRef("+Y0+")":"ForwardRef"),Y0;case _0:return u0=Y0.displayName||null,u0!==null?u0:H(Y0.type)||"Memo";case x0:u0=Y0._payload,Y0=Y0._init;try{return H(Y0(u0))}catch(R0){}}return null}function W(Y0){if(Y0===A0)return"<>";if(typeof Y0==="object"&&Y0!==null&&Y0.$$typeof===x0)return"<...>";try{var u0=H(Y0);return u0?"<"+u0+">":"<...>"}catch(R0){return"<...>"}}function Z(){var Y0=BA.A;return Y0===null?null:Y0.getOwner()}function G(){return Error("react-stack-top-frame")}function F(Y0){if(k0.call(Y0,"key")){var u0=Object.getOwnPropertyDescriptor(Y0,"key").get;if(u0&&u0.isReactWarning)return!1}return Y0.key!==void 0}function V(Y0,u0){function R0(){H0||(H0=!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)",u0))}R0.isReactWarning=!0,Object.defineProperty(Y0,"key",{get:R0,configurable:!0})}function b(){var Y0=H(this.type);return Q1[Y0]||(Q1[Y0]=!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.")),Y0=this.props.ref,Y0!==void 0?Y0:null}function L(Y0,u0,R0,n0,zA,MA){var $A=R0.ref;return Y0={$$typeof:l,type:Y0,key:u0,props:R0,_owner:n0},($A!==void 0?$A:null)!==null?Object.defineProperty(Y0,"ref",{enumerable:!1,get:b}):Object.defineProperty(Y0,"ref",{enumerable:!1,value:null}),Y0._store={},Object.defineProperty(Y0._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(Y0,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(Y0,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:zA}),Object.defineProperty(Y0,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:MA}),Object.freeze&&(Object.freeze(Y0.props),Object.freeze(Y0)),Y0}function N(Y0,u0){return u0=L(Y0.type,u0,Y0.props,Y0._owner,Y0._debugStack,Y0._debugTask),Y0._store&&(u0._store.validated=Y0._store.validated),u0}function _(Y0){j(Y0)?Y0._store&&(Y0._store.validated=1):typeof Y0==="object"&&Y0!==null&&Y0.$$typeof===x0&&(Y0._payload.status==="fulfilled"?j(Y0._payload.value)&&Y0._payload.value._store&&(Y0._payload.value._store.validated=1):Y0._store&&(Y0._store.validated=1))}function j(Y0){return typeof Y0==="object"&&Y0!==null&&Y0.$$typeof===l}function g(Y0){var u0={"=":"=0",":":"=2"};return"$"+Y0.replace(/[=:]/g,function(R0){return u0[R0]})}function E(Y0,u0){return typeof Y0==="object"&&Y0!==null&&Y0.key!=null?(X(Y0.key),g(""+Y0.key)):u0.toString(36)}function y(Y0){switch(Y0.status){case"fulfilled":return Y0.value;case"rejected":throw Y0.reason;default:switch(typeof Y0.status==="string"?Y0.then(D,D):(Y0.status="pending",Y0.then(function(u0){Y0.status==="pending"&&(Y0.status="fulfilled",Y0.value=u0)},function(u0){Y0.status==="pending"&&(Y0.status="rejected",Y0.reason=u0)})),Y0.status){case"fulfilled":return Y0.value;case"rejected":throw Y0.reason}}throw Y0}function h(Y0,u0,R0,n0,zA){var MA=typeof Y0;if(MA==="undefined"||MA==="boolean")Y0=null;var $A=!1;if(Y0===null)$A=!0;else switch(MA){case"bigint":case"string":case"number":$A=!0;break;case"object":switch(Y0.$$typeof){case l:case p:$A=!0;break;case x0:return $A=Y0._init,h($A(Y0._payload),u0,R0,n0,zA)}}if($A){$A=Y0,zA=zA($A);var tA=n0===""?"."+E($A,0):n0;return FA(zA)?(R0="",tA!=null&&(R0=tA.replace(y0,"$&/")+"/"),h(zA,u0,R0,"",function(l1){return l1})):zA!=null&&(j(zA)&&(zA.key!=null&&($A&&$A.key===zA.key||X(zA.key)),R0=N(zA,R0+(zA.key==null||$A&&$A.key===zA.key?"":(""+zA.key).replace(y0,"$&/")+"/")+tA),n0!==""&&$A!=null&&j($A)&&$A.key==null&&$A._store&&!$A._store.validated&&(R0._store.validated=2),zA=R0),u0.push(zA)),1}if($A=0,tA=n0===""?".":n0+":",FA(Y0))for(var gA=0;gA<Y0.length;gA++)n0=Y0[gA],MA=tA+E(n0,gA),$A+=h(n0,u0,R0,MA,zA);else if(gA=Q(Y0),typeof gA==="function")for(gA===Y0.entries&&(o0||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),o0=!0),Y0=gA.call(Y0),gA=0;!(n0=Y0.next()).done;)n0=n0.value,MA=tA+E(n0,gA++),$A+=h(n0,u0,R0,MA,zA);else if(MA==="object"){if(typeof Y0.then==="function")return h(y(Y0),u0,R0,n0,zA);throw u0=String(Y0),Error("Objects are not valid as a React child (found: "+(u0==="[object Object]"?"object with keys {"+Object.keys(Y0).join(", ")+"}":u0)+"). If you meant to render a collection of children, use an array instead.")}return $A}function T(Y0,u0,R0){if(Y0==null)return Y0;var n0=[],zA=0;return h(Y0,n0,"","",function(MA){return u0.call(R0,MA,zA++)}),n0}function S(Y0){if(Y0._status===-1){var u0=Y0._ioInfo;u0!=null&&(u0.start=u0.end=performance.now()),u0=Y0._result;var R0=u0();if(R0.then(function(zA){if(Y0._status===0||Y0._status===-1){Y0._status=1,Y0._result=zA;var MA=Y0._ioInfo;MA!=null&&(MA.end=performance.now()),R0.status===void 0&&(R0.status="fulfilled",R0.value=zA)}},function(zA){if(Y0._status===0||Y0._status===-1){Y0._status=2,Y0._result=zA;var MA=Y0._ioInfo;MA!=null&&(MA.end=performance.now()),R0.status===void 0&&(R0.status="rejected",R0.reason=zA)}}),u0=Y0._ioInfo,u0!=null){u0.value=R0;var n0=R0.displayName;typeof n0==="string"&&(u0.name=n0)}Y0._status===-1&&(Y0._status=0,Y0._result=R0)}if(Y0._status===1)return u0=Y0._result,u0===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
402
402
 
403
403
  Your code should look like:
404
404
  const MyComponent = lazy(() => import('./MyComponent'))
@@ -1695,7 +1695,7 @@ Example bad output: "A dreamlike crystal formation glowing with ethereal light i
1695
1695
  Title: "${A.entityTitle??Y}"
1696
1696
 
1697
1697
  Content:
1698
- ${W}`,ig2);H=`${B.trim()} ${N.imagePrompt}`}catch(N){this.logger.warn("AI prompt distillation failed, using fallback",{error:vA(N)})}}await this.reportProgress(w,{progress:_Q.PROCESS,message:"Generating image"});let Z=this.context.identity.get(),G=this.context.identity.getProfile(),V=WjA(Z,G)+H,b;try{b=await this.context.ai.generateImage(V,{...$&&{aspectRatio:$}})}catch(N){return this.logger.error("Image generation failed",{jobId:Q,error:vA(N)}),x6.failure(N)}await this.reportProgress(w,{progress:_Q.GENERATE,message:"Creating image entity"});let L=vY.createImageEntity({dataUrl:b.dataUrl,title:Y,status:"draft",attachmentType:"generated",...f&&{sourceEntityType:f},...D&&{sourceEntityId:D}});if(await NY({entityService:this.context.entityService,entity:{...L,id:X}}),this.logger.debug("Created image entity",{imageId:X}),f&&D){await this.reportProgress(w,{progress:_Q.SAVE,message:`Updating ${f} with cover image`});let N=await zN(this.context.entityService,f,D,this.logger);if(!N)return x6.failure(Error(`Target entity not found: ${f}/${D}`));let _=Xj(N,X);await this.context.entities.update(_),this.logger.debug("Updated target entity with cover image",{targetEntityType:f,targetEntityId:D,imageId:X})}return await this.reportProgress(w,{progress:_Q.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:X,targetEntityType:f,targetEntityId:D}),{success:!0,imageId:X}}catch(H){let W=vA(H);return this.logger.error("Image generation job failed",{jobId:Q,error:W}),await UU({entityService:this.context.entityService,entityType:"image",id:X,error:W}),x6.failure(H)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}c0();Z0();CB();D4();var ng2=K.object({sourceEntityType:K.string().min(1),sourceEntityId:K.string().min(1),attachmentType:K.string().min(1),imageId:K.string().min(1),dedupKey:K.string().min(1).optional(),replace:K.boolean().optional(),targetEntityType:K.string().min(1).optional(),targetEntityId:K.string().min(1).optional(),targetImageField:K.enum(["coverImageId","ogImageId"]).optional()});class fj0 extends _w{context;constructor(A,Q){super(Q,{schema:ng2,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 D=await this.findImageByDedupKey(A.dedupKey);if(D)return await this.updateTarget(A,D.id),await this.reportProgress(w,{progress:_Q.COMPLETE,message:"Reusing existing generated image"}),{success:!0,imageId:D.id,reused:!0}}await this.reportProgress(w,{progress:_Q.PROCESS,message:"Rendering source image"});let B=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!B)return x6.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if(B.type!=="image")return x6.failure(Error(`Attachment provider returned ${B.type}; expected image`));await this.reportProgress(w,{progress:_Q.GENERATE,message:"Creating image entity"});let $=B.mimeType.split("/")[1]??"png",f=vY.createImageEntity({dataUrl:yb0(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 NY({entityService:this.context.entityService,entity:{...f,id:A.imageId}}),await this.updateTarget(A,A.imageId),await this.reportProgress(w,{progress:_Q.COMPLETE,message:"Image render complete"}),{success:!0,imageId:A.imageId,reused:!1}}catch(B){let $=vA(B);return this.logger.error("Source image render job failed",{jobId:Q,error:$}),await UU({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:$}),x6.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 zN(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"?zu(w,Q):Xj(w,Q);await this.context.entities.update($)}}c0();Z0();CB();D4();Z0();var nR={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function BQ0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function $Q0(A){let Q=rg2(A.title,A.filename),w=w1(Q);if(!w)throw Error("Could not derive an image id from the uploaded filename. Provide a title.");return{id:w,title:Q}}function ZjA(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function rg2(A,Q){let w=A?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}var og2=K.object({uploadId:K.string().min(1),imageId:K.string().min(1).optional(),title:K.string().optional()});class Dj0 extends _w{context;constructor(A,Q){super(A,{schema:og2,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(nR).read(A.uploadId);if(!BQ0(B.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let $=$Q0({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 D=new Date().toISOString(),Y=vY.createImageEntity({dataUrl:ZjA(B.record.mediaType,B.content),title:$.title,status:"draft",sourceUploadId:A.uploadId,sourceFilename:B.record.filename,sourceMediaType:B.record.mediaType,attachmentType:"uploaded"}),X=await NY({entityService:this.context.entityService,entity:{id:f,...Y,created:D,updated:D}});return await this.reportProgress(w,{progress:100,message:"Uploaded image promoted"}),{entityId:X.entityId,status:"created"}}catch(B){if(A.imageId)await UU({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:vA(B)});return x6.failure(B)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var KjA={name:"@brains/image-plugin",private:!0,version:"0.2.0-alpha.133",description:"Plugin for AI-powered image generation and management",type:"module",main:"./src/index.ts",exports:{".":"./src/index.ts"},scripts:{test:"bun test",typecheck:"tsc --noEmit",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","@types/node":"^20.0.0",typescript:"^5.3.3"}};var ag2="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",tg2=K.object({defaultAspectRatio:K.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});function NZ(A){let Q=A?.trim();if(!Q)return;return Q}function eg2(A){let Q=NZ(A.prompt);if(Q)return Q;let w=NZ(A.content);if(w&&!$j0(w))return w;return}function AT2(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return w1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function UjA(A){let Q=NZ(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return w1(Q)}async function QT2(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 Yj0(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 wT2(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 Xj0 extends PQ{entityType=vY.entityType;schema=Uu;adapter=vY;constructor(A={}){super("image",KjA,A,tg2)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,w){if(A.from?.kind===nR.refKind)return this.promoteUpload(A,w);let B=eg2(A),$=NZ(A.targetEntityType),f=NZ(A.targetEntityId),D=$===this.entityType?f:void 0,Y=A.from;if(Y?.kind==="entity-attachment")return this.enqueueSourceImageRender({...A,from:Y},w);if(!$||!f||D){if(!B)return{kind:"continue",input:A};let G=NZ(A.title)??D,F=UjA({prompt:B,...G&&{title:G}});await this.createPendingImage(w,{id:F,title:G??B.slice(0,60).trim(),alt:G??B.slice(0,60).trim(),attachmentType:"generated"});let V=await w.jobs.enqueue({type:"image-generate",data:{prompt:B,...G&&{title:G}}});return{kind:"handled",result:{success:!0,data:{entityId:F,status:"generating",jobId:V,attachment:Yj0(F)}}}}let X=await A4(w.entityService,$,f,this.logger,"Target entity");if(!X.ok)return{kind:"handled",result:{success:!1,error:X.error}};if(!B)return{kind:"continue",input:{...A,targetEntityId:X.entity.id}};let H=QQ0(X.entity.content),W=UjA({prompt:B,...A.title&&{title:A.title},targetEntityId:X.entity.id});await this.createPendingImage(w,{id:W,title:A.title??`cover-${X.entity.id}`,alt:A.title??`cover-${X.entity.id}`,attachmentType:"generated",sourceEntityType:$,sourceEntityId:X.entity.id});let Z=await w.jobs.enqueue({type:"image-generate",data:{prompt:B,...A.title&&{title:A.title},targetEntityType:$,targetEntityId:X.entity.id,entityTitle:typeof X.entity.metadata.title==="string"?X.entity.metadata.title:X.entity.id,...H&&{entityContent:H}}});return{kind:"handled",result:{success:!0,data:{entityId:W,status:"generating",jobId:Z,attachment:Yj0(W)}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==nR.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let B=w.id,$;try{$=await Q.uploads.scoped(nR).readRecord(B)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!BQ0($.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let f;try{f=$Q0({filename:$.filename,...A.title!==void 0?{title:A.title}:{}})}catch(Y){return{kind:"handled",result:{success:!1,error:Y instanceof Error?Y.message:String(Y)}}}await this.createPendingImage(Q,{id:f.id,title:f.title,alt:f.title,sourceUploadId:B,sourceFilename:$.filename,sourceMediaType:$.mediaType,attachmentType:"uploaded"});let D=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:D,attachment:wT2({mediaType:$.mediaType,entityId:f.id,filename:$.filename})}}}}async enqueueSourceImageRender(A,Q){let w=NZ(A.from.sourceEntityType),B=NZ(A.from.sourceEntityId),$=NZ(A.from.attachmentType);if(!w||!B||!$)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let f=await A4(Q.entityService,w,B,this.logger,"Source entity");if(!f.ok)return{kind:"handled",result:{success:!1,error:f.error}};let D=NZ(A.targetEntityType),Y=NZ(A.targetEntityId),X;if(D&&Y){let F=await A4(Q.entityService,D,Y,this.logger,"Target entity");if(!F.ok)return{kind:"handled",result:{success:!1,error:F.error}};X=F.entity.id}let H={sourceEntityType:w,sourceEntityId:f.entity.id,attachmentType:$},W=await QT2(Q,H),Z=AT2(H);await this.createPendingImage(Q,{id:Z,title:Z,alt:Z,sourceEntityType:H.sourceEntityType,sourceEntityId:H.sourceEntityId,attachmentType:$,dedupKey:W});let G=await Q.jobs.enqueue({type:"image-render-source",data:{...H,imageId:Z,dedupKey:W,...A.replace===!0&&{replace:!0},...D&&{targetEntityType:D},...X&&{targetEntityId:X},...$==="og-image"&&{targetImageField:"ogImageId"}}});return{kind:"handled",result:{success:!0,data:{entityId:Z,status:"generating",jobId:G,attachment:Yj0(Z,$)}}}}async createPendingImage(A,Q){let w=new Date().toISOString(),B=vY.createImageEntity({dataUrl:ag2,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 FN({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 wQ0(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 wQ0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new fj0(A,this.logger)),A.jobs.registerHandler("upload-promote",new Dj0(this.logger.child("UploadPromotionJobHandler"),A))}}function Uc(A){return new Xj0(A)}c0();import{StdioServerTransport as BT2}from"@modelcontextprotocol/sdk/server/stdio.js";function GjA(){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 Hj0(){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 fQ0(A){if(A&&typeof A==="object"&&"info"in A&&"debug"in A&&"error"in A&&"warn"in A){let Q=A;return{info:(w,...B)=>Q.info(w,...B),debug:(w,...B)=>Q.debug(w,...B),error:(w,...B)=>Q.error(w,...B),warn:(w,...B)=>Q.warn(w,...B)}}return Hj0()}class jZ{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return jZ.instance??=new jZ(A),jZ.instance}static resetInstance(){if(jZ.instance)jZ.instance.stop(),jZ.instance=null}static createFresh(A){return new jZ(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?fQ0(this.config.logger):GjA()}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 BT2,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 zjA}from"crypto";import{WebStandardStreamableHTTPServerTransport as $T2}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as fT2}from"@modelcontextprotocol/sdk/types.js";c0();var DT2={"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"};function YT2(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 gq{static instance=null;transports={};mcpServer=null;mcpTransport=null;agentService=null;server=null;boundPort=null;config;logger;authConfig;constructor(A={}){if(this.config=A,this.logger=this.config.logger?fQ0(this.config.logger):Hj0(),this.authConfig=A.auth??{},!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 gq.instance??=new gq(A),gq.instance}static resetInstance(){gq.instance=null}static createFresh(A){return new gq(A)}withCors(A){let Q=new Headers(A.headers);for(let[w,B]of Object.entries(DT2))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 B={resource_metadata:`${YT2(A)}/.well-known/oauth-protected-resource`,...Q};return`Bearer ${Object.entries(B).map(([f,D])=>`${f}="${XT2(D)}"`).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){if(w.substring(7)!==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((D)=>!B.scope?.includes(D));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"}))}}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.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=await A.json();this.logger.debug(`POST /mcp - Session: ${Q??"new"}`);try{let B;if(Q&&this.transports[Q])B=this.transports[Q];else if(!Q&&fT2(w))B=new $T2({sessionIdGenerator:()=>zjA(),onsessioninitialized:(f)=>{this.logger.info(`Session initialized: ${f}`),this.transports[f]=B},onsessionclosed:(f)=>{this.logger.info(`Session closed: ${f}`),delete this.transports[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 handleAgentChatRequest(A){if(!this.agentService)return this.createJsonResponse({error:"Agent service not connected"},503);let{message:Q,conversationId:w}=await A.json();if(!Q||typeof Q!=="string")return this.createJsonResponse({error:"Missing or invalid 'message' field"},400);let B=w??zjA();this.logger.debug(`POST /api/chat - conversation: ${B}`);try{let $=await this.agentService.chat(Q,B);return this.createJsonResponse($)}catch($){return this.logger.error("Agent chat error:",$),this.createJsonResponse({error:$ instanceof Error?$.message:"Internal error"},500)}}async handleAgentConfirmRequest(A){if(!this.agentService)return this.createJsonResponse({error:"Agent service not connected"},503);let{conversationId:Q,confirmed:w,approvalId:B,context:$}=await A.json();if(!Q||typeof Q!=="string")return this.createJsonResponse({error:"Missing or invalid 'conversationId' field"},400);if(typeof w!=="boolean")return this.createJsonResponse({error:"Missing or invalid 'confirmed' field"},400);if(typeof B!=="string"||B.length===0)return this.createJsonResponse({error:"Missing or invalid 'approvalId' field"},400);let f=eU0.safeParse($);if(!f.success||!f.data.userPermissionLevel)return this.createJsonResponse({error:"Missing or invalid 'context' field"},400);this.logger.debug(`POST /api/chat/confirm - conversation: ${Q}`);try{let D=await this.agentService.confirmPendingAction(Q,w,B,f.data);return this.createJsonResponse(D)}catch(D){return this.logger.error("Agent confirm error:",D),this.createJsonResponse({error:D instanceof Error?D.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({sessions:Object.keys(this.transports).length,uptime:process.uptime(),memory:process.memoryUsage(),port:this.boundPort??this.config.port??3333});if(Q.pathname==="/mcp")return this.handleMcpRequest(A);if(Q.pathname==="/api/chat"&&A.method==="POST")return this.handleAgentChatRequest(A);if(Q.pathname==="/api/chat/confirm"&&A.method==="POST")return this.handleAgentConfirmRequest(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")}connectAgentService(A){this.agentService=A,this.logger.debug("Agent service 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){if(w.code==="EADDRINUSE")this.logger.error(`Port ${A} is already in use`);throw w}}async stop(){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 XT2(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}import{randomUUID as WT2}from"crypto";import{mkdir as ZT2,readFile as KT2,writeFile as UT2,chmod as GT2}from"fs/promises";import{dirname as zT2,join as qT2}from"path";function qjA(A){let Q=A.toLowerCase();return Q==="localhost"||Q==="[::1]"||Q==="::1"||Q.startsWith("127.")}function FjA(A){try{return new URL(A)}catch{return}}function Wj0(A,Q){if(A===Q)return!0;let w=FjA(A),B=FjA(Q);if(!w||!B)return!1;if(!qjA(w.hostname)||!qjA(B.hostname))return!1;return w.protocol===B.protocol&&w.port===B.port&&HT2(w.pathname,B.pathname)&&w.search===B.search&&w.hash===B.hash}function HT2(A,Q){return A===Q||A===`${Q}/debug`||Q===`${A}/debug`}function Zj0(A,Q){return A.some((w)=>Wj0(w,Q))}var FT2="oauth-auth-codes.json",VT2=600;function VjA(){return Math.floor(Date.now()/1000)}function IT2(A){if(!A||typeof A!=="object")return!1;let Q=A;return typeof Q.code==="string"&&typeof Q.client_id==="string"&&typeof Q.redirect_uri==="string"&&typeof Q.code_challenge==="string"&&Q.code_challenge_method==="S256"&&typeof Q.subject==="string"&&typeof Q.created_at==="number"&&typeof Q.expires_at==="number"}function JT2(A){if(!A||typeof A!=="object")return{codes:[]};let Q=A.codes;if(!Array.isArray(Q))return{codes:[]};return{codes:Q.filter(IT2)}}async function bT2(A){let Q=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(A));return Buffer.from(Q).toString("base64url")}class DQ0{storeFile;writeQueue=Promise.resolve();constructor(A){this.storeFile=qT2(A.storageDir,A.storeFile??FT2)}async createCode(A){let Q=VjA(),w={code:`ocd_${WT2()}`,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+VT2};return await this.enqueueWrite(async()=>{let B=await this.readStore();B.codes=B.codes.filter(($)=>$.expires_at>Q),B.codes.push(w),await this.writeStore(B)}),w}async consumeCode(A){let Q=VjA(),w;if(await this.enqueueWrite(async()=>{let B=await this.readStore(),$=B.codes.findIndex((Y)=>Y.code===A.code),f=$>=0?B.codes[$]:void 0;if(!f)throw new MZ("Authorization code not found");if(f.consumed_at!==void 0)throw new MZ("Authorization code already consumed");if(f.expires_at<=Q)throw new MZ("Authorization code expired");if(f.client_id!==A.clientId)throw new MZ("Authorization code client mismatch");if(!Wj0(f.redirect_uri,A.redirectUri))throw new MZ("Authorization code redirect URI mismatch");let D=await bT2(A.codeVerifier);if(f.code_challenge!==D)throw new MZ("PKCE verification failed");w={...f,consumed_at:Q},B.codes[$]=w,await this.writeStore(B)}),!w)throw new MZ("Authorization code not consumed");return w}async enqueueWrite(A){return this.writeQueue=this.writeQueue.then(A,A),this.writeQueue}async readStore(){try{return JT2(JSON.parse(await KT2(this.storeFile,"utf8")))}catch(A){if(A.code==="ENOENT")return{codes:[]};throw A}}async writeStore(A){await ZT2(zT2(this.storeFile),{recursive:!0,mode:448}),await UT2(this.storeFile,`${JSON.stringify(A,null,2)}
1698
+ ${W}`,ig2);H=`${B.trim()} ${N.imagePrompt}`}catch(N){this.logger.warn("AI prompt distillation failed, using fallback",{error:vA(N)})}}await this.reportProgress(w,{progress:_Q.PROCESS,message:"Generating image"});let Z=this.context.identity.get(),G=this.context.identity.getProfile(),V=WjA(Z,G)+H,b;try{b=await this.context.ai.generateImage(V,{...$&&{aspectRatio:$}})}catch(N){return this.logger.error("Image generation failed",{jobId:Q,error:vA(N)}),x6.failure(N)}await this.reportProgress(w,{progress:_Q.GENERATE,message:"Creating image entity"});let L=vY.createImageEntity({dataUrl:b.dataUrl,title:Y,status:"draft",attachmentType:"generated",...f&&{sourceEntityType:f},...D&&{sourceEntityId:D}});if(await NY({entityService:this.context.entityService,entity:{...L,id:X}}),this.logger.debug("Created image entity",{imageId:X}),f&&D){await this.reportProgress(w,{progress:_Q.SAVE,message:`Updating ${f} with cover image`});let N=await zN(this.context.entityService,f,D,this.logger);if(!N)return x6.failure(Error(`Target entity not found: ${f}/${D}`));let _=Xj(N,X);await this.context.entities.update(_),this.logger.debug("Updated target entity with cover image",{targetEntityType:f,targetEntityId:D,imageId:X})}return await this.reportProgress(w,{progress:_Q.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:X,targetEntityType:f,targetEntityId:D}),{success:!0,imageId:X}}catch(H){let W=vA(H);return this.logger.error("Image generation job failed",{jobId:Q,error:W}),await UU({entityService:this.context.entityService,entityType:"image",id:X,error:W}),x6.failure(H)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}c0();Z0();CB();D4();var ng2=K.object({sourceEntityType:K.string().min(1),sourceEntityId:K.string().min(1),attachmentType:K.string().min(1),imageId:K.string().min(1),dedupKey:K.string().min(1).optional(),replace:K.boolean().optional(),targetEntityType:K.string().min(1).optional(),targetEntityId:K.string().min(1).optional(),targetImageField:K.enum(["coverImageId","ogImageId"]).optional()});class fj0 extends _w{context;constructor(A,Q){super(Q,{schema:ng2,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 D=await this.findImageByDedupKey(A.dedupKey);if(D)return await this.updateTarget(A,D.id),await this.reportProgress(w,{progress:_Q.COMPLETE,message:"Reusing existing generated image"}),{success:!0,imageId:D.id,reused:!0}}await this.reportProgress(w,{progress:_Q.PROCESS,message:"Rendering source image"});let B=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!B)return x6.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if(B.type!=="image")return x6.failure(Error(`Attachment provider returned ${B.type}; expected image`));await this.reportProgress(w,{progress:_Q.GENERATE,message:"Creating image entity"});let $=B.mimeType.split("/")[1]??"png",f=vY.createImageEntity({dataUrl:yb0(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 NY({entityService:this.context.entityService,entity:{...f,id:A.imageId}}),await this.updateTarget(A,A.imageId),await this.reportProgress(w,{progress:_Q.COMPLETE,message:"Image render complete"}),{success:!0,imageId:A.imageId,reused:!1}}catch(B){let $=vA(B);return this.logger.error("Source image render job failed",{jobId:Q,error:$}),await UU({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:$}),x6.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 zN(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"?zu(w,Q):Xj(w,Q);await this.context.entities.update($)}}c0();Z0();CB();D4();Z0();var nR={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function BQ0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function $Q0(A){let Q=rg2(A.title,A.filename),w=w1(Q);if(!w)throw Error("Could not derive an image id from the uploaded filename. Provide a title.");return{id:w,title:Q}}function ZjA(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function rg2(A,Q){let w=A?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}var og2=K.object({uploadId:K.string().min(1),imageId:K.string().min(1).optional(),title:K.string().optional()});class Dj0 extends _w{context;constructor(A,Q){super(A,{schema:og2,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(nR).read(A.uploadId);if(!BQ0(B.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let $=$Q0({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 D=new Date().toISOString(),Y=vY.createImageEntity({dataUrl:ZjA(B.record.mediaType,B.content),title:$.title,status:"draft",sourceUploadId:A.uploadId,sourceFilename:B.record.filename,sourceMediaType:B.record.mediaType,attachmentType:"uploaded"}),X=await NY({entityService:this.context.entityService,entity:{id:f,...Y,created:D,updated:D}});return await this.reportProgress(w,{progress:100,message:"Uploaded image promoted"}),{entityId:X.entityId,status:"created"}}catch(B){if(A.imageId)await UU({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:vA(B)});return x6.failure(B)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var KjA={name:"@brains/image-plugin",private:!0,version:"0.2.0-alpha.134",description:"Plugin for AI-powered image generation and management",type:"module",main:"./src/index.ts",exports:{".":"./src/index.ts"},scripts:{test:"bun test",typecheck:"tsc --noEmit",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","@types/node":"^20.0.0",typescript:"^5.3.3"}};var ag2="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",tg2=K.object({defaultAspectRatio:K.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});function NZ(A){let Q=A?.trim();if(!Q)return;return Q}function eg2(A){let Q=NZ(A.prompt);if(Q)return Q;let w=NZ(A.content);if(w&&!$j0(w))return w;return}function AT2(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return w1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function UjA(A){let Q=NZ(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return w1(Q)}async function QT2(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 Yj0(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 wT2(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 Xj0 extends PQ{entityType=vY.entityType;schema=Uu;adapter=vY;constructor(A={}){super("image",KjA,A,tg2)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,w){if(A.from?.kind===nR.refKind)return this.promoteUpload(A,w);let B=eg2(A),$=NZ(A.targetEntityType),f=NZ(A.targetEntityId),D=$===this.entityType?f:void 0,Y=A.from;if(Y?.kind==="entity-attachment")return this.enqueueSourceImageRender({...A,from:Y},w);if(!$||!f||D){if(!B)return{kind:"continue",input:A};let G=NZ(A.title)??D,F=UjA({prompt:B,...G&&{title:G}});await this.createPendingImage(w,{id:F,title:G??B.slice(0,60).trim(),alt:G??B.slice(0,60).trim(),attachmentType:"generated"});let V=await w.jobs.enqueue({type:"image-generate",data:{prompt:B,...G&&{title:G}}});return{kind:"handled",result:{success:!0,data:{entityId:F,status:"generating",jobId:V,attachment:Yj0(F)}}}}let X=await A4(w.entityService,$,f,this.logger,"Target entity");if(!X.ok)return{kind:"handled",result:{success:!1,error:X.error}};if(!B)return{kind:"continue",input:{...A,targetEntityId:X.entity.id}};let H=QQ0(X.entity.content),W=UjA({prompt:B,...A.title&&{title:A.title},targetEntityId:X.entity.id});await this.createPendingImage(w,{id:W,title:A.title??`cover-${X.entity.id}`,alt:A.title??`cover-${X.entity.id}`,attachmentType:"generated",sourceEntityType:$,sourceEntityId:X.entity.id});let Z=await w.jobs.enqueue({type:"image-generate",data:{prompt:B,...A.title&&{title:A.title},targetEntityType:$,targetEntityId:X.entity.id,entityTitle:typeof X.entity.metadata.title==="string"?X.entity.metadata.title:X.entity.id,...H&&{entityContent:H}}});return{kind:"handled",result:{success:!0,data:{entityId:W,status:"generating",jobId:Z,attachment:Yj0(W)}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==nR.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let B=w.id,$;try{$=await Q.uploads.scoped(nR).readRecord(B)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!BQ0($.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let f;try{f=$Q0({filename:$.filename,...A.title!==void 0?{title:A.title}:{}})}catch(Y){return{kind:"handled",result:{success:!1,error:Y instanceof Error?Y.message:String(Y)}}}await this.createPendingImage(Q,{id:f.id,title:f.title,alt:f.title,sourceUploadId:B,sourceFilename:$.filename,sourceMediaType:$.mediaType,attachmentType:"uploaded"});let D=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:D,attachment:wT2({mediaType:$.mediaType,entityId:f.id,filename:$.filename})}}}}async enqueueSourceImageRender(A,Q){let w=NZ(A.from.sourceEntityType),B=NZ(A.from.sourceEntityId),$=NZ(A.from.attachmentType);if(!w||!B||!$)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let f=await A4(Q.entityService,w,B,this.logger,"Source entity");if(!f.ok)return{kind:"handled",result:{success:!1,error:f.error}};let D=NZ(A.targetEntityType),Y=NZ(A.targetEntityId),X;if(D&&Y){let F=await A4(Q.entityService,D,Y,this.logger,"Target entity");if(!F.ok)return{kind:"handled",result:{success:!1,error:F.error}};X=F.entity.id}let H={sourceEntityType:w,sourceEntityId:f.entity.id,attachmentType:$},W=await QT2(Q,H),Z=AT2(H);await this.createPendingImage(Q,{id:Z,title:Z,alt:Z,sourceEntityType:H.sourceEntityType,sourceEntityId:H.sourceEntityId,attachmentType:$,dedupKey:W});let G=await Q.jobs.enqueue({type:"image-render-source",data:{...H,imageId:Z,dedupKey:W,...A.replace===!0&&{replace:!0},...D&&{targetEntityType:D},...X&&{targetEntityId:X},...$==="og-image"&&{targetImageField:"ogImageId"}}});return{kind:"handled",result:{success:!0,data:{entityId:Z,status:"generating",jobId:G,attachment:Yj0(Z,$)}}}}async createPendingImage(A,Q){let w=new Date().toISOString(),B=vY.createImageEntity({dataUrl:ag2,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 FN({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 wQ0(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 wQ0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new fj0(A,this.logger)),A.jobs.registerHandler("upload-promote",new Dj0(this.logger.child("UploadPromotionJobHandler"),A))}}function Uc(A){return new Xj0(A)}c0();import{StdioServerTransport as BT2}from"@modelcontextprotocol/sdk/server/stdio.js";function GjA(){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 Hj0(){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 fQ0(A){if(A&&typeof A==="object"&&"info"in A&&"debug"in A&&"error"in A&&"warn"in A){let Q=A;return{info:(w,...B)=>Q.info(w,...B),debug:(w,...B)=>Q.debug(w,...B),error:(w,...B)=>Q.error(w,...B),warn:(w,...B)=>Q.warn(w,...B)}}return Hj0()}class jZ{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return jZ.instance??=new jZ(A),jZ.instance}static resetInstance(){if(jZ.instance)jZ.instance.stop(),jZ.instance=null}static createFresh(A){return new jZ(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?fQ0(this.config.logger):GjA()}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 BT2,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 zjA}from"crypto";import{WebStandardStreamableHTTPServerTransport as $T2}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as fT2}from"@modelcontextprotocol/sdk/types.js";c0();var DT2={"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"};function YT2(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 gq{static instance=null;transports={};mcpServer=null;mcpTransport=null;agentService=null;server=null;boundPort=null;config;logger;authConfig;constructor(A={}){if(this.config=A,this.logger=this.config.logger?fQ0(this.config.logger):Hj0(),this.authConfig=A.auth??{},!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 gq.instance??=new gq(A),gq.instance}static resetInstance(){gq.instance=null}static createFresh(A){return new gq(A)}withCors(A){let Q=new Headers(A.headers);for(let[w,B]of Object.entries(DT2))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 B={resource_metadata:`${YT2(A)}/.well-known/oauth-protected-resource`,...Q};return`Bearer ${Object.entries(B).map(([f,D])=>`${f}="${XT2(D)}"`).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){if(w.substring(7)!==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((D)=>!B.scope?.includes(D));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"}))}}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.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=await A.json();this.logger.debug(`POST /mcp - Session: ${Q??"new"}`);try{let B;if(Q&&this.transports[Q])B=this.transports[Q];else if(!Q&&fT2(w))B=new $T2({sessionIdGenerator:()=>zjA(),onsessioninitialized:(f)=>{this.logger.info(`Session initialized: ${f}`),this.transports[f]=B},onsessionclosed:(f)=>{this.logger.info(`Session closed: ${f}`),delete this.transports[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 handleAgentChatRequest(A){if(!this.agentService)return this.createJsonResponse({error:"Agent service not connected"},503);let{message:Q,conversationId:w}=await A.json();if(!Q||typeof Q!=="string")return this.createJsonResponse({error:"Missing or invalid 'message' field"},400);let B=w??zjA();this.logger.debug(`POST /api/chat - conversation: ${B}`);try{let $=await this.agentService.chat(Q,B);return this.createJsonResponse($)}catch($){return this.logger.error("Agent chat error:",$),this.createJsonResponse({error:$ instanceof Error?$.message:"Internal error"},500)}}async handleAgentConfirmRequest(A){if(!this.agentService)return this.createJsonResponse({error:"Agent service not connected"},503);let{conversationId:Q,confirmed:w,approvalId:B,context:$}=await A.json();if(!Q||typeof Q!=="string")return this.createJsonResponse({error:"Missing or invalid 'conversationId' field"},400);if(typeof w!=="boolean")return this.createJsonResponse({error:"Missing or invalid 'confirmed' field"},400);if(typeof B!=="string"||B.length===0)return this.createJsonResponse({error:"Missing or invalid 'approvalId' field"},400);let f=eU0.safeParse($);if(!f.success||!f.data.userPermissionLevel)return this.createJsonResponse({error:"Missing or invalid 'context' field"},400);this.logger.debug(`POST /api/chat/confirm - conversation: ${Q}`);try{let D=await this.agentService.confirmPendingAction(Q,w,B,f.data);return this.createJsonResponse(D)}catch(D){return this.logger.error("Agent confirm error:",D),this.createJsonResponse({error:D instanceof Error?D.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({sessions:Object.keys(this.transports).length,uptime:process.uptime(),memory:process.memoryUsage(),port:this.boundPort??this.config.port??3333});if(Q.pathname==="/mcp")return this.handleMcpRequest(A);if(Q.pathname==="/api/chat"&&A.method==="POST")return this.handleAgentChatRequest(A);if(Q.pathname==="/api/chat/confirm"&&A.method==="POST")return this.handleAgentConfirmRequest(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")}connectAgentService(A){this.agentService=A,this.logger.debug("Agent service 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){if(w.code==="EADDRINUSE")this.logger.error(`Port ${A} is already in use`);throw w}}async stop(){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 XT2(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}import{randomUUID as WT2}from"crypto";import{mkdir as ZT2,readFile as KT2,writeFile as UT2,chmod as GT2}from"fs/promises";import{dirname as zT2,join as qT2}from"path";function qjA(A){let Q=A.toLowerCase();return Q==="localhost"||Q==="[::1]"||Q==="::1"||Q.startsWith("127.")}function FjA(A){try{return new URL(A)}catch{return}}function Wj0(A,Q){if(A===Q)return!0;let w=FjA(A),B=FjA(Q);if(!w||!B)return!1;if(!qjA(w.hostname)||!qjA(B.hostname))return!1;return w.protocol===B.protocol&&w.port===B.port&&HT2(w.pathname,B.pathname)&&w.search===B.search&&w.hash===B.hash}function HT2(A,Q){return A===Q||A===`${Q}/debug`||Q===`${A}/debug`}function Zj0(A,Q){return A.some((w)=>Wj0(w,Q))}var FT2="oauth-auth-codes.json",VT2=600;function VjA(){return Math.floor(Date.now()/1000)}function IT2(A){if(!A||typeof A!=="object")return!1;let Q=A;return typeof Q.code==="string"&&typeof Q.client_id==="string"&&typeof Q.redirect_uri==="string"&&typeof Q.code_challenge==="string"&&Q.code_challenge_method==="S256"&&typeof Q.subject==="string"&&typeof Q.created_at==="number"&&typeof Q.expires_at==="number"}function JT2(A){if(!A||typeof A!=="object")return{codes:[]};let Q=A.codes;if(!Array.isArray(Q))return{codes:[]};return{codes:Q.filter(IT2)}}async function bT2(A){let Q=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(A));return Buffer.from(Q).toString("base64url")}class DQ0{storeFile;writeQueue=Promise.resolve();constructor(A){this.storeFile=qT2(A.storageDir,A.storeFile??FT2)}async createCode(A){let Q=VjA(),w={code:`ocd_${WT2()}`,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+VT2};return await this.enqueueWrite(async()=>{let B=await this.readStore();B.codes=B.codes.filter(($)=>$.expires_at>Q),B.codes.push(w),await this.writeStore(B)}),w}async consumeCode(A){let Q=VjA(),w;if(await this.enqueueWrite(async()=>{let B=await this.readStore(),$=B.codes.findIndex((Y)=>Y.code===A.code),f=$>=0?B.codes[$]:void 0;if(!f)throw new MZ("Authorization code not found");if(f.consumed_at!==void 0)throw new MZ("Authorization code already consumed");if(f.expires_at<=Q)throw new MZ("Authorization code expired");if(f.client_id!==A.clientId)throw new MZ("Authorization code client mismatch");if(!Wj0(f.redirect_uri,A.redirectUri))throw new MZ("Authorization code redirect URI mismatch");let D=await bT2(A.codeVerifier);if(f.code_challenge!==D)throw new MZ("PKCE verification failed");w={...f,consumed_at:Q},B.codes[$]=w,await this.writeStore(B)}),!w)throw new MZ("Authorization code not consumed");return w}async enqueueWrite(A){return this.writeQueue=this.writeQueue.then(A,A),this.writeQueue}async readStore(){try{return JT2(JSON.parse(await KT2(this.storeFile,"utf8")))}catch(A){if(A.code==="ENOENT")return{codes:[]};throw A}}async writeStore(A){await ZT2(zT2(this.storeFile),{recursive:!0,mode:448}),await UT2(this.storeFile,`${JSON.stringify(A,null,2)}
1699
1699
  `,{mode:384}),await GT2(this.storeFile,384)}}class MZ extends Error{constructor(A){super(A);this.name="InvalidGrantError"}}Z0();import{randomUUID as IjA}from"crypto";import{mkdir as LT2,readFile as NT2,writeFile as jT2,chmod as MT2}from"fs/promises";import{dirname as _T2,join as PT2}from"path";var kT2="oauth-clients.json",OT2=K.enum(["none","client_secret_basic","client_secret_post"]),xT2=K.object({redirect_uris:K.array(K.string().url()).min(1),token_endpoint_auth_method:OT2.default("none"),grant_types:K.array(K.enum(["authorization_code","refresh_token"])).default(["authorization_code","refresh_token"]),response_types:K.array(K.literal("code")).default(["code"]),scope:K.string().optional(),client_name:K.string().optional(),client_uri:K.string().url().optional(),logo_uri:K.string().url().optional(),contacts:K.array(K.string()).optional()});function RT2(){return Math.floor(Date.now()/1000)}function hT2(){return`ocs_${IjA().replaceAll("-","")}`}function vT2(A){if(!A||typeof A!=="object")return{clients:[]};let Q=A.clients;if(!Array.isArray(Q))return{clients:[]};return{clients:Q.filter(CT2)}}function CT2(A){if(!A||typeof A!=="object")return!1;let Q=A;return typeof Q.client_id==="string"&&Array.isArray(Q.redirect_uris)&&Q.redirect_uris.every((w)=>typeof w==="string")&&typeof Q.client_id_issued_at==="number"}class YQ0{storeFile;writeQueue=Promise.resolve();constructor(A){this.storeFile=PT2(A.storageDir,A.storeFile??kT2)}async registerClient(A){let Q=xT2.safeParse(A);if(!Q.success)throw new Gc(Q.error.message);let w=Q.data,B=RT2(),$=`oc_${IjA()}`,f=w.token_endpoint_auth_method==="none",D={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:hT2(),client_secret_expires_at:0}:{}};return await this.enqueueWrite(async()=>{let Y=await this.readStore();Y.clients.push(D),await this.writeStore(Y)}),D}async getClient(A){return(await this.readStore()).clients.find((w)=>w.client_id===A)}async enqueueWrite(A){return this.writeQueue=this.writeQueue.then(A,A),this.writeQueue}async readStore(){try{return vT2(JSON.parse(await NT2(this.storeFile,"utf8")))}catch(A){if(A.code==="ENOENT")return{clients:[]};throw A}}async writeStore(A){await LT2(_T2(this.storeFile),{recursive:!0,mode:448}),await jT2(this.storeFile,`${JSON.stringify(A,null,2)}
1700
1700
  `,{mode:384}),await MT2(this.storeFile,384)}}class Gc extends Error{constructor(A){super(A);this.name="InvalidClientMetadataError"}}import{createHash as yT2}from"crypto";import{mkdir as ET2,readFile as gT2,writeFile as TT2,chmod as ST2}from"fs/promises";import{dirname as mT2,join as uT2}from"path";var cT2="oauth-signing-key.jwk";function JjA(A){if(!A||typeof A!=="object")return!1;let Q=A;return Q.kty==="EC"&&Q.crv==="P-256"&&typeof Q.x==="string"&&typeof Q.y==="string"&&typeof Q.d==="string"}function bjA(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x,y:A.y});return yT2("sha256").update(Q).digest("base64url")}function lT2(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,kid:A.kid,use:"sig",alg:"ES256"}}async function pT2(){let A=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!0,["sign","verify"]),Q=await crypto.subtle.exportKey("jwk",A.privateKey);if(!JjA(Q))throw Error("Generated OAuth signing key is not a P-256 private JWK");let w=bjA(Q);return{...Q,kid:w,use:"sig",alg:"ES256"}}class XQ0{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=uT2(A.storageDir,A.keyFile??cT2)}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 pT2();return await ET2(mT2(this.keyFile),{recursive:!0,mode:448}),await TT2(this.keyFile,`${JSON.stringify(Q,null,2)}
1701
1701
  `,{mode:384}),await ST2(this.keyFile,384),Q}async getPublicJwk(){return lT2(await this.getPrivateJwk())}async readExistingKey(){try{let A=JSON.parse(await gT2(this.keyFile,"utf8"));if(!JjA(A))throw Error(`OAuth signing key at ${this.keyFile} is not a private P-256 JWK`);let Q=typeof A.kid==="string"?A.kid:bjA(A);return{...A,kid:Q,use:"sig",alg:"ES256"}}catch(A){if(A.code==="ENOENT")return;throw A}}}var $Q={};sw($Q,{trimPadding:()=>NjA,toUTF8String:()=>eT2,toBuffer:()=>oT2,toBase64:()=>aT2,isBase64URL:()=>QS2,isBase64:()=>AS2,fromUTF8String:()=>tT2,fromBuffer:()=>sT2});var LjA=(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},iT2=LjA("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),dT2=LjA("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"),nT2=/^[-A-Za-z0-9\-_]*$/,rT2=/^[-A-Za-z0-9+/]*={0,3}$/,yU={};yU.toArrayBuffer=(A,Q)=>{let w=A.length,B=A.length*0.75,$,f=0,D,Y,X,H;if(A[A.length-1]==="="){if(B--,A[A.length-2]==="=")B--}let W=new ArrayBuffer(B),Z=new Uint8Array(W),G=Q?dT2:iT2;for($=0;$<w;$+=4)D=G[A.charCodeAt($)],Y=G[A.charCodeAt($+1)],X=G[A.charCodeAt($+2)],H=G[A.charCodeAt($+3)],Z[f++]=D<<2|Y>>4,Z[f++]=(Y&15)<<4|X>>2,Z[f++]=(X&3)<<6|H&63;return W};yU.fromArrayBuffer=(A,Q)=>{let w=new Uint8Array(A),B,$="",f=w.length,D=Q?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(B=0;B<f;B+=3)$+=D[w[B]>>2],$+=D[(w[B]&3)<<4|w[B+1]>>4],$+=D[(w[B+1]&15)<<2|w[B+2]>>6],$+=D[w[B+2]&63];let Y=f%3;if(Y===2)$=$.substring(0,$.length-1)+(Q?"":"=");else if(Y===1)$=$.substring(0,$.length-2)+(Q?"":"==");return $};yU.toString=(A,Q)=>{return new TextDecoder().decode(yU.toArrayBuffer(A,Q))};yU.fromString=(A,Q)=>{return yU.fromArrayBuffer(new TextEncoder().encode(A),Q)};yU.validate=(A,Q)=>{if(!(typeof A==="string"||A instanceof String))return!1;try{return Q?nT2.test(A):rT2.test(A)}catch(w){return!1}};yU.base64=yU;var Tq=yU;function oT2(A,Q="base64url"){let w=Tq.toArrayBuffer(A,Q==="base64url");return new Uint8Array(w)}function sT2(A,Q="base64url"){let w=new Uint8Array(A);return Tq.fromArrayBuffer(w.buffer,Q==="base64url")}function aT2(A){let Q=Tq.toArrayBuffer(A,!0);return Tq.fromArrayBuffer(Q)}function tT2(A){return Tq.fromString(A,!0)}function eT2(A){return Tq.toString(A,!0)}function AS2(A){return Tq.validate(A,!1)}function QS2(A){return A=NjA(A),Tq.validate(A,!0)}function NjA(A){return A.replace(/=/g,"")}var Yf={};sw(Yf,{encode:()=>LS2,decodeFirst:()=>bS2});function rR(A,Q,w){if(Q<24)return[Q,1];let B=A.byteLength-w-1,$=new DataView(A.buffer,w+1),f,D=0;switch(Q){case 24:{if(B>0)f=$.getUint8(0),D=2;break}case 25:{if(B>1)f=$.getUint16(0,!1),D=3;break}case 26:{if(B>3)f=$.getUint32(0,!1),D=5;break}case 27:{if(B>7){let Y=$.getBigUint64(0,!1);if(Y>=24n&&Y<=Number.MAX_SAFE_INTEGER)return[Number(Y),9]}break}}if(f&&f>=24)return[f,D];throw Error("Length not supported or not well formed")}var HQ0=0,zc=1,Kj0=2,Uj0=3,Gj0=4,zj0=5,qj0=6,jjA=7;function EU(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==zc){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 ZQ0{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 MjA(A,Q,w){return rR(A,Q,w)}function wS2(A,Q,w){let[B,$]=MjA(A,Q,w);return[-B-1,$]}function _jA(A,Q,w){let[B,$]=rR(A,Q,w),f=w+$;return[new Uint8Array(A.buffer.slice(f,f+B)),$+B]}var BS2=new TextDecoder;function $S2(A,Q,w){let[B,$]=_jA(A,Q,w);return[BS2.decode(B),$]}function fS2(A,Q,w){if(Q===0)return[[],1];let[B,$]=rR(A,Q,w),f=$,D=[];for(let Y=0;Y<B;Y++){if(A.byteLength-w-f<=0)throw Error("array is not supported or well formed");let[H,W]=_j(A,w+f);D.push(H),f+=W}return[D,f]}var WQ0="Map is not supported or well formed";function DS2(A,Q,w){if(Q===0)return[new Map,1];let[B,$]=rR(A,Q,w),f=$,D=new Map;for(let Y=0;Y<B;Y++){let X=A.byteLength-w-f;if(X<=0)throw Error(WQ0);let[H,W]=_j(A,w+f);if(f+=W,X-=W,X<=0)throw Error(WQ0);if(typeof H!=="string"&&typeof H!=="number")throw Error(WQ0);if(D.has(H))throw Error(WQ0);let[Z,G]=_j(A,w+f);f+=G,D.set(H,Z)}return[D,f]}function YS2(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 XS2(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 HS2(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 WS2(A,Q,w){let[B,$]=rR(A,Q,w),[f,D]=_j(A,w+$);return[new ZQ0(B,f),$+D]}function _j(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 HQ0:return MjA(A,$,Q);case zc:return wS2(A,$,Q);case Kj0:return _jA(A,$,Q);case Uj0:return $S2(A,$,Q);case Gj0:return fS2(A,$,Q);case zj0:return DS2(A,$,Q);case qj0:return WS2(A,$,Q);case jjA: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 YS2(A,Q);case 26:return XS2(A,Q);case 27:return HS2(A,Q)}}throw Error(`Unsupported or not well formed at ${Q}`)}function ZS2(A){if(A===!0)return 245;else if(A===!1)return 244;else if(A===null)return 246;return 247}function KS2(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 US2(A){if(typeof A=="number"){if(Number.isSafeInteger(A))if(A<0)return EU(zc,Math.abs(A));else return EU(HQ0,A);return[KS2(A)]}else if(A<0n)return EU(zc,A*-1n);else return EU(HQ0,A)}var GS2=new TextEncoder;function zS2(A,Q){Q.push(...EU(Uj0,A.length)),Q.push(GS2.encode(A))}function qS2(A,Q){Q.push(...EU(Kj0,A.length)),Q.push(A)}function FS2(A,Q){Q.push(...EU(Gj0,A.length));for(let w of A)qc(w,Q)}function VS2(A,Q){Q.push(new Uint8Array(EU(zj0,A.size)));for(let[w,B]of A.entries())qc(w,Q),qc(B,Q)}function IS2(A,Q){Q.push(...EU(qj0,A.tag)),qc(A.value,Q)}function qc(A,Q){if(typeof A=="boolean"||A===null||A==null){Q.push(ZS2(A));return}if(typeof A=="number"||typeof A=="bigint"){Q.push(...US2(A));return}if(typeof A=="string"){zS2(A,Q);return}if(A instanceof Uint8Array){qS2(A,Q);return}if(Array.isArray(A)){FS2(A,Q);return}if(A instanceof Map){VS2(A,Q);return}if(A instanceof ZQ0){IS2(A,Q);return}throw Error("Not implemented")}function Fj0(A,Q){if(A.byteLength===0||A.byteLength<=Q||Q<0)throw Error("No data");if(A instanceof Uint8Array)return _j(new DataView(A.buffer),Q);else if(A instanceof ArrayBuffer)return _j(new DataView(A),Q);return _j(A,Q)}function Vj0(A){let Q=[];qc(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 bS2(A){let Q=new Uint8Array(A),w=Fj0(Q,0),[B]=w;return B}function LS2(A){return Vj0(A)}var TU={};sw(TU,{verify:()=>YOA,getRandomValues:()=>RjA,digest:()=>xjA});function PjA(A){let Q=A.get(QQ.kty);return Ij0(Q)&&Q===EY.OKP}function LI(A){let Q=A.get(QQ.kty);return Ij0(Q)&&Q===EY.EC2}function oR(A){let Q=A.get(QQ.kty);return Ij0(Q)&&Q===EY.RSA}var QQ;(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"})(QQ||(QQ={}));var EY;(function(A){A[A.OKP=1]="OKP",A[A.EC2=2]="EC2",A[A.RSA=3]="RSA"})(EY||(EY={}));function Ij0(A){return Object.values(EY).indexOf(A)>=0}var X4;(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"})(X4||(X4={}));function kjA(A){return Object.values(X4).indexOf(A)>=0}var hQ;(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"})(hQ||(hQ={}));function gU(A){return Object.values(hQ).indexOf(A)>=0}function NI(A){if([hQ.RS1].indexOf(A)>=0)return"SHA-1";else if([hQ.ES256,hQ.PS256,hQ.RS256].indexOf(A)>=0)return"SHA-256";else if([hQ.ES384,hQ.PS384,hQ.RS384].indexOf(A)>=0)return"SHA-384";else if([hQ.ES512,hQ.PS512,hQ.RS512,hQ.EdDSA].indexOf(A)>=0)return"SHA-512";throw Error(`Could not map COSE alg value of ${A} to a WebCrypto alg`)}var Fc=void 0;function $D(){return new Promise((Q,w)=>{if(Fc)return Q(Fc);let B=jS2.stubThisGlobalThisCrypto();if(B)return Fc=B,Q(Fc);return w(new OjA)})}class OjA extends Error{constructor(){super("An instance of the Crypto API could not be located");this.name="MissingWebCrypto"}}var jS2={stubThisGlobalThisCrypto:()=>globalThis.crypto,setCachedCrypto:(A)=>{Fc=A}};async function xjA(A,Q){let w=await $D(),B=NI(Q),$=await w.subtle.digest(B,A);return new Uint8Array($)}async function RjA(A){return(await $D()).getRandomValues(A),A}async function sR(A){let Q=await $D(),{keyData:w,algorithm:B}=A;return Q.subtle.importKey("jwk",w,B,!1,["verify"])}async function KQ0(A){let{cosePublicKey:Q,signature:w,data:B,shaHashOverride:$}=A,f=await $D(),D=Q.get(QQ.alg),Y=Q.get(QQ.crv),X=Q.get(QQ.x),H=Q.get(QQ.y);if(!D)throw Error("Public key was missing alg (EC2)");if(!Y)throw Error("Public key was missing crv (EC2)");if(!X)throw Error("Public key was missing x (EC2)");if(!H)throw Error("Public key was missing y (EC2)");let W;if(Y===X4.P256)W="P-256";else if(Y===X4.P384)W="P-384";else if(Y===X4.P521)W="P-521";else throw Error(`Unexpected COSE crv value of ${Y} (EC2)`);let Z={kty:"EC",crv:W,x:$Q.fromBuffer(X),y:$Q.fromBuffer(H),ext:!1},F=await sR({keyData:Z,algorithm:{name:"ECDSA",namedCurve:W}}),V=NI(D);if($)V=NI($);let b={name:"ECDSA",hash:{name:V}};return f.subtle.verify(b,F,w,B)}function Jj0(A){if([hQ.EdDSA].indexOf(A)>=0)return"Ed25519";else if([hQ.ES256,hQ.ES384,hQ.ES512,hQ.ES256K].indexOf(A)>=0)return"ECDSA";else if([hQ.RS256,hQ.RS384,hQ.RS512,hQ.RS1].indexOf(A)>=0)return"RSASSA-PKCS1-v1_5";else if([hQ.PS256,hQ.PS384,hQ.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 UQ0(A){let{cosePublicKey:Q,signature:w,data:B,shaHashOverride:$}=A,f=await $D(),D=Q.get(QQ.alg),Y=Q.get(QQ.n),X=Q.get(QQ.e);if(!D)throw Error("Public key was missing alg (RSA)");if(!gU(D))throw Error(`Public key had invalid alg ${D} (RSA)`);if(!Y)throw Error("Public key was missing n (RSA)");if(!X)throw Error("Public key was missing e (RSA)");let H={kty:"RSA",alg:"",n:$Q.fromBuffer(Y),e:$Q.fromBuffer(X),ext:!1},W={name:Jj0(D),hash:{name:NI(D)}},Z={name:Jj0(D)};if($)W.hash.name=NI($);if(W.name==="RSASSA-PKCS1-v1_5"){if(W.hash.name==="SHA-256")H.alg="RS256";else if(W.hash.name==="SHA-384")H.alg="RS384";else if(W.hash.name==="SHA-512")H.alg="RS512";else if(W.hash.name==="SHA-1")H.alg="RS1"}else if(W.name==="RSA-PSS"){let F=0;if(W.hash.name==="SHA-256")H.alg="PS256",F=32;else if(W.hash.name==="SHA-384")H.alg="PS384",F=48;else if(W.hash.name==="SHA-512")H.alg="PS512",F=64;Z.saltLength=F}else throw Error(`Unexpected RSA key algorithm ${D} (${W.name})`);let G=await sR({keyData:H,algorithm:W});return f.subtle.verify(Z,G,w,B)}function GQ0(A){let Q=q2.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 G$(A){let Q;if(typeof A==="string")if($Q.isBase64URL(A))Q=$Q.toBase64(A);else if($Q.isBase64(A))Q=A;else throw Error("Certificate is not a valid base64 or base64url string");else Q=$Q.fromBuffer(A,"base64");let w="";for(let B=0;B<Math.ceil(Q.length/64);B+=1){let $=64*B;w+=`${Q.substr($,64)}
@@ -2274,8 +2274,8 @@ ${N}`)}if(B!==void 0&&f?.algorithms!==void 0){let L=f.algorithms.map((N)=>N.alg)
2274
2274
  </form>
2275
2275
  </main>
2276
2276
  </body>
2277
- </html>`}function wp(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(yP0(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function eU(A){return A.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;")}import{randomUUID as wl2}from"crypto";function JxA(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function Ql2(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 D=Q[w+1];if(D===void 0)throw Error("Invalid DER ECDSA signature");let Y=w+2,X=Q.slice(Y,Y+D);return new Uint8Array([...bxA(f),...bxA(X)])}function bxA(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 gP0(A,Q){let w={typ:"JWT",alg:"ES256",kid:A.kid},B=`${JxA(w)}.${JxA(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(Ql2(f)).toString("base64url")}`}var Bl2=600;class TP0{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 wp(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 qv(IxA(w.params,B))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return wp(A);let w=await A.formData(),B=await this.validateAuthorizationRequest(new URLSearchParams(RP0(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 D=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}),Y=new URL(B.params.redirectUri);if(Y.searchParams.set("code",D.code),B.params.state)Y.searchParams.set("state",B.params.state);return Response.redirect(Y.toString(),302)}createAuthorizationApprovalToken(A,Q){this.pruneExpiredAuthorizationApprovalTokens();let w=`oat_${wl2()}`;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)+Bl2}),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"),D=A.get("scope")??void 0,Y=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 X=await this.clientStore.getClient(w);if(!X)return{success:!1,error:"Unknown client_id"};if(!Zj0(X.redirect_uris,B))return{success:!1,error:"Unregistered redirect_uri"};let H=D??X.scope;return{success:!0,params:{clientId:w,redirectUri:B,codeChallenge:$,...H?{scope:H}:{},...Y?{state:Y}:{},clientName:X.client_name??X.client_id}}}async handleClientRegistration(A){let Q;try{Q=await A.json()}catch{return y6("invalid_client_metadata","Request body must be JSON")}try{let w=await this.clientStore.registerClient(Q);return pY(w,201)}catch(w){if(w instanceof Gc)return y6("invalid_client_metadata",w.message);throw w}}async handleTokenRequest(A,Q){let w=await xP0(A),B=w.get("grant_type"),$=vP0(A,w),f=$.clientId??w.get("client_id");if($.error)return y6("invalid_client",$.error);if(!f)return y6("invalid_request","client_id is required");let D=await this.clientStore.getClient(f),Y=hP0(D,$);if(Y)return y6("invalid_client",Y);if(B==="authorization_code")return this.handleAuthorizationCodeGrant(w,f,Q);if(B==="refresh_token")return this.handleRefreshTokenGrant(w,f,Q);return y6("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 y6("invalid_request","code, redirect_uri, and code_verifier are required");let D=await this.clientStore.getClient(Q);if(!D||!Zj0(D.redirect_uris,$))return y6("invalid_grant","Unregistered redirect_uri");try{let Y=await this.authCodeStore.consumeCode({code:B,clientId:Q,redirectUri:$,codeVerifier:f});return await this.createTokenResponse({issuer:w,clientId:Q,subject:Y.subject,...Y.scope?{scope:Y.scope}:{}})}catch(Y){if(Y instanceof MZ)return y6("invalid_grant",Y.message);throw Y}}async handleRefreshTokenGrant(A,Q,w){let B=A.get("refresh_token");if(!B)return y6("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 Y3)return y6("invalid_grant",$.message);throw $}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),w=900,B=await gP0(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 pY({access_token:B,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:$})}async handleRevokeRequest(A){let Q=await xP0(A),w=vP0(A,Q),B=w.clientId??Q.get("client_id")??void 0,$=Q.get("token");if(w.error)return y6("invalid_client",w.error);if(!$)return y6("invalid_request","token is required");if(B){let f=await this.clientStore.getClient(B),D=hP0(f,w);if(D)return y6("invalid_client",D)}return await this.refreshTokenStore.revokeToken($,B),new Response(null,{status:200})}}class SP0{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 y6("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return y6("access_denied","Invalid setup token");let Q=await this.passkeyService.generateRegistrationOptions(dw0(A));return pY(Q)}async handleRegistrationVerify(A){if(await this.passkeyService.hasCredentials())return y6("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return y6("access_denied","Invalid setup token");let Q=await this.passkeyService.verifyRegistrationResponse(await A.json(),dw0(A));if(!Q.verified)return y6("access_denied","Passkey registration failed");await this.setupFlow.clearSetupState();let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:tl(A)});return pY({verified:!0},200,{"Set-Cookie":w.cookie})}async handleAuthenticationOptions(A){if(!await this.passkeyService.hasCredentials())return y6("access_denied","No passkey registered");let Q=await this.passkeyService.generateAuthenticationOptions(dw0(A));return pY(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),dw0(A));if(!Q.verified)return y6("access_denied","Passkey authentication failed");let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:tl(A)});return pY({verified:!0},200,{"Set-Cookie":w.cookie})}}function dw0(A){let Q=Hv(A),w=new URL(Q);return{origin:w.origin,rpID:w.hostname}}import{randomUUID as $l2}from"crypto";var Bp=86400;class mP0{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_${$l2()}`,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 tU(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:tU(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:HP0(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 qv(FxA(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupStateStore.recordDelivery(A,Q,w)}}class nw0{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;clientStore;authCodeStore;sessionStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=EZ(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>EZ(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??Xv(this.issuer),this.keyStore=new XQ0({storageDir:A.storageDir}),this.clientStore=new YQ0({storageDir:A.storageDir}),this.authCodeStore=new DQ0({storageDir:A.storageDir}),this.sessionStore=new uw0({storageDir:A.storageDir}),this.passkeyService=new Ew0({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new mP0({setupStateStore:new WP0({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??Bp}),this.oauthEndpoints=new TP0({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new Tw0({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new SP0({passkeyService:this.passkeyService,sessionStore:this.sessionStore,setupFlow:this.setupFlow}),this.logger=A.logger}getIssuer(){return this.issuer}async initialize(){if(await this.keyStore.getPrivateJwk(),this.logger?.debug("Auth service signing key loaded"),!await this.hasPasskeyCredentials()){await this.setupFlow.ensureSetupToken();let A=this.getSetupUrl();if(A)if(Xv(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(){return{keys:[await this.keyStore.getPublicJwk()]}}getAuthorizationServerMetadata(A=this.issuer){let Q=EZ(A);return{issuer:Q,authorization_endpoint:tU(Q,"/authorize"),token_endpoint:tU(Q,"/token"),registration_endpoint:tU(Q,"/register"),revocation_endpoint:tU(Q,"/revoke"),jwks_uri:tU(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:[EZ(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 wp(A)}async verifyBearerToken(A,Q={}){let w=OP0(A);if(!w)return;let B=Q.issuer?EZ(Q.issuer):this.resolveRequestIssuer(A);return kP0(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"&&GxA(w))return zxA();if(A.method==="GET"){if(w==="/.well-known/oauth-authorization-server")return tI(pY(this.getAuthorizationServerMetadata(Q)));if(w==="/.well-known/jwks.json")return tI(pY(await this.getJwks()));if(w==="/.well-known/oauth-protected-resource")return tI(pY(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 tI(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&w==="/token")return tI(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&w==="/revoke")return tI(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=Hv(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&Xv(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=CP0(new URL(A.url).searchParams.get("return_to"));return qv(yP0(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=CP0(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":UP0(tl(A)),"Cache-Control":"no-store"}})}}Z0();var rw0="email:send",LxA=K.object({to:K.string().email(),subject:K.string().min(1),text:K.string().min(1),html:K.string().min(1).optional(),sensitivity:K.enum(["normal","secret"]).default("normal")}).strict();c0();Z0();var NxA={name:"@brains/notifications",private:!0,version:"0.2.0-alpha.133",description:"Generic notification routing for transactional and administrative messages",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var uP0="notifications:send",Dl2=K.object({}),Yl2=K.discriminatedUnion("type",[K.object({type:K.literal("email"),address:K.string().email()}).strict()]),Xl2=K.object({recipient:Yl2,title:K.string().min(1),body:K.string().min(1),html:K.string().min(1).optional(),sensitivity:K.enum(["normal","secret"]).default("normal")}).strict(),jxA=K.discriminatedUnion("status",[K.object({status:K.literal("sent"),deliveryId:K.string().optional()}).strict(),K.object({status:K.literal("failed")}).strict()]);class MxA extends RQ{constructor(A={}){super("notifications",NxA,A,Dl2)}async onRegister(A){A.messaging.subscribe(uP0,async(Q)=>{let w=Xl2.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:rw0,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 ow0(A={}){return new MxA(A)}c0();Z0();var _xA={name:"@brains/auth-service",private:!0,version:"0.2.0-alpha.133",description:"Embedded OAuth/OIDC auth service for brain operator authentication",type:"module",main:"./src/index.ts",types:"./src/index.ts",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/notifications":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@simplewebauthn/server":"^13.3.0",jose:"^6.2.3"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","@types/node":"^20.0.0",typescript:"^5.3.3"},files:["src"]};var Wl2=K.union([K.string().email(),K.object({to:K.string().email(),subject:K.string().min(1),body:K.string().min(1)}).strict()]),Zl2=K.object({issuer:K.string().optional(),trustedIssuers:K.array(K.string()).default([]),allowLocalhostIssuers:K.boolean().optional(),storageDir:K.string().default("./data/auth"),setupTokenTtlSeconds:K.number().int().positive().default(Bp),setupEmail:Wl2.optional()}),Kl2=K.object({}),sw0;function gH(){return sw0}class cP0 extends RQ{service;constructor(A={}){super("auth-service",_xA,A,Zl2)}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 nw0({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(),sw0=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(sw0===this.service)sw0=void 0;this.service=void 0}async getTools(){return[Sw(this.id,"get_passkey_setup_url","Get the first-passkey setup URL when operator setup is required. Anchor-only.",Kl2,async()=>{let A=this.getService();if(await A.hasPasskeyCredentials())return l8({status:"complete"});let Q=await A.getOperatorSetupRequired();if(Q)return l8({status:"setup_required",setupUrl:Q.setupUrl,expiresAt:Q.expiresAt});return l8({status:"unavailable",reason:"Passkey setup URL is not available."})},{visibility:"anchor",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=Ul2(this.config.setupEmail,w);if(await Q.hasSetupEmailDelivery(w.setupTokenId,B.to))return;let $=await A.messaging.send({type:uP0,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=jxA.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 Ul2(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(`
2278
- `)}}return{to:A.to,subject:PxA(A.subject,Q),body:PxA(A.body,Q)}}function PxA(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 $p(A){return new cP0(A)}Z0();var lP0=K.object({transport:K.enum(["stdio","http"]).default("http"),httpPort:K.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:K.string().describe("Bearer token for HTTP transport authentication").optional()});function kxA(A,Q){return[]}c0();function pP0(A,Q){A.messaging.subscribe("job-progress",async(w)=>{let B=vO.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,D=$.status,Y=$.id;if(Q.debug(`${f} ${Y} - ${D}:`,{id:$.id,message:$.message,progress:$.progress,metadata:$.metadata}),$.batchDetails)Q.debug(`Batch details for ${Y}:`,{totalOperations:$.batchDetails.totalOperations,completedOperations:$.batchDetails.completedOperations,failedOperations:$.batchDetails.failedOperations,currentOperation:$.batchDetails.currentOperation,errors:$.batchDetails.errors});if($.jobDetails)Q.debug(`Job details for ${Y}:`,{jobType:$.jobDetails.jobType,priority:$.jobDetails.priority,retryCount:$.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var OxA={name:"@brains/mcp",private:!0,version:"0.2.0-alpha.133",type:"module",main:"./src/index.ts",module:"./src/index.ts",types:"./src/index.ts",files:["src"],scripts:{typecheck:"tsc --noEmit",lint:"eslint --max-warnings 0 .","lint:fix":"eslint --fix .",test:"bun test"},dependencies:{"@brains/auth-service":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@modelcontextprotocol/sdk":"^1.24.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.1.14","@types/cors":"^2.8.17","@types/express":"^4.17.21",typescript:"^5.3.3"}};class eI extends GU{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",OxA,Q,lP0)}async getTools(){return kxA(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"});pP0(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;let A=gH();return this.httpServer=gq.createFresh({port:this.config.httpPort,logger:this.logger,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,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);if(this.config.transport==="http"&&(this.config.authToken||gH()))w="anchor",this.logger.debug("HTTP authentication configured - authenticated users will have anchor permissions");if(this.mcpTransport.setPermissionLevel(w),this.logger.debug(`Starting MCP ${this.config.transport} transport with ${w} permissions`),this.config.transport==="stdio"){this.stdioServer=jZ.createFresh();let B=this.mcpTransport.getMcpServer();this.stdioServer.connectMCPServer(B),await this.stdioServer.start(),this.logger.debug("MCP STDIO transport started")}else{this.httpServer=this.getOrCreateHttpServer();let B=this.mcpTransport.getMcpServer();this.httpServer.connectMCPServer(B,this.mcpTransport),this.httpServer.connectAgentService(A.agent),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(){jZ.resetInstance(),gq.resetInstance()}}c0();Z0();var AX=Y1(eC0(),1);Z0();c0();var Ay0=K.object({botToken:K.string().min(1).describe("Discord bot token"),allowedChannels:K.array(K.string()).default([]),requireMention:K.boolean().default(!0),allowDMs:K.boolean().default(!0),showTypingIndicator:K.boolean().default(!0),statusMessage:K.string().default("Mention me to chat"),useThreads:K.boolean().default(!0),threadAutoArchive:K.union([K.literal(60),K.literal(1440),K.literal(4320),K.literal(10080)]).default(1440),...jN.shape,captureUrlEmoji:K.string().default("\uD83D\uDD16")});var kH1={name:"@brains/discord",private:!0,version:"0.2.0-alpha.133",description:"Discord interface for Brains",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",test:"bun test"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","discord.js":"^14.14.1"},devDependencies:{"@brains/core":"workspace:*","@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest"}};var A50=2000,ybQ=8000,EbQ=100;function Q50(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class gJ extends AZ{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;constructor(A,Q={}){super("discord",kH1,A,Ay0);this.fetchText=Q.fetchText??Nt}async onRegister(A){await super.onRegister(A),this.client=new AX.Client({intents:[AX.GatewayIntentBits.Guilds,AX.GatewayIntentBits.GuildMessages,AX.GatewayIntentBits.MessageContent,AX.GatewayIntentBits.DirectMessages],partials:[AX.Partials.Channel]}),this.client.on(AX.Events.MessageCreate,(Q)=>{this.handleMessage(Q)}),this.client.on(AX.Events.InteractionCreate,(Q)=>{this.handleInteraction(Q)}),this.client.once(AX.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(!Q50(w))return;let B=sL(Q,A50);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(!Q50(w))return;if(typeof Q!=="string")return(await w.send(Q)).id;let B=sL(Q,A50),$;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(!Q50(B))return!1;try{return await(await B.messages.fetch(Q)).edit(w.slice(0,A50)),!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),D=!Q&&this.isConfiguredSpace(f),Y={channelId:f,isBot:A.author.bot};if(this.config.allowedChannels.length>0&&!Q&&!this.isAllowedChannel(A.channel.id,f))return;let X=Q||$||!this.config.requireMention||B;if(D&&(!X||this.willRouteUseNonSpaceConversation(A)))await this.capturePassiveSpaceMessage(A,f).catch((Z)=>this.logger.error("Passive Discord space capture failed",{error:Z,channelId:f}));if(!X){if(this.config.captureUrls){let Z=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(Z.length>0){await A.react(this.config.captureUrlEmoji).catch((G)=>this.logger.debug("React failed",{error:G}));for(let G of Z)await this.captureUrlViaAgent(G,A.channel.id,A.author.id,"discord",Y).catch((F)=>this.logger.error("URL capture failed",{error:F,url:G}))}}return}let H=this.stripMention(A.content);if(A.attachments.size>0){let Z=this.context.permissions.getUserLevel("discord",A.author.id,Y);if(Z==="anchor"||Z==="trusted")for(let F of A.attachments.values()){let V=F.name,b=F.contentType??void 0,L=F.size;if(!this.isUploadableTextFile(V,b))continue;if(!this.isFileSizeAllowed(L))continue;try{let N=await this.fetchText(F.url);H+=`
2277
+ </html>`}function wp(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(yP0(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function eU(A){return A.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;")}import{randomUUID as wl2}from"crypto";function JxA(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function Ql2(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 D=Q[w+1];if(D===void 0)throw Error("Invalid DER ECDSA signature");let Y=w+2,X=Q.slice(Y,Y+D);return new Uint8Array([...bxA(f),...bxA(X)])}function bxA(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 gP0(A,Q){let w={typ:"JWT",alg:"ES256",kid:A.kid},B=`${JxA(w)}.${JxA(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(Ql2(f)).toString("base64url")}`}var Bl2=600;class TP0{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 wp(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 qv(IxA(w.params,B))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return wp(A);let w=await A.formData(),B=await this.validateAuthorizationRequest(new URLSearchParams(RP0(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 D=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}),Y=new URL(B.params.redirectUri);if(Y.searchParams.set("code",D.code),B.params.state)Y.searchParams.set("state",B.params.state);return Response.redirect(Y.toString(),302)}createAuthorizationApprovalToken(A,Q){this.pruneExpiredAuthorizationApprovalTokens();let w=`oat_${wl2()}`;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)+Bl2}),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"),D=A.get("scope")??void 0,Y=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 X=await this.clientStore.getClient(w);if(!X)return{success:!1,error:"Unknown client_id"};if(!Zj0(X.redirect_uris,B))return{success:!1,error:"Unregistered redirect_uri"};let H=D??X.scope;return{success:!0,params:{clientId:w,redirectUri:B,codeChallenge:$,...H?{scope:H}:{},...Y?{state:Y}:{},clientName:X.client_name??X.client_id}}}async handleClientRegistration(A){let Q;try{Q=await A.json()}catch{return y6("invalid_client_metadata","Request body must be JSON")}try{let w=await this.clientStore.registerClient(Q);return pY(w,201)}catch(w){if(w instanceof Gc)return y6("invalid_client_metadata",w.message);throw w}}async handleTokenRequest(A,Q){let w=await xP0(A),B=w.get("grant_type"),$=vP0(A,w),f=$.clientId??w.get("client_id");if($.error)return y6("invalid_client",$.error);if(!f)return y6("invalid_request","client_id is required");let D=await this.clientStore.getClient(f),Y=hP0(D,$);if(Y)return y6("invalid_client",Y);if(B==="authorization_code")return this.handleAuthorizationCodeGrant(w,f,Q);if(B==="refresh_token")return this.handleRefreshTokenGrant(w,f,Q);return y6("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 y6("invalid_request","code, redirect_uri, and code_verifier are required");let D=await this.clientStore.getClient(Q);if(!D||!Zj0(D.redirect_uris,$))return y6("invalid_grant","Unregistered redirect_uri");try{let Y=await this.authCodeStore.consumeCode({code:B,clientId:Q,redirectUri:$,codeVerifier:f});return await this.createTokenResponse({issuer:w,clientId:Q,subject:Y.subject,...Y.scope?{scope:Y.scope}:{}})}catch(Y){if(Y instanceof MZ)return y6("invalid_grant",Y.message);throw Y}}async handleRefreshTokenGrant(A,Q,w){let B=A.get("refresh_token");if(!B)return y6("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 Y3)return y6("invalid_grant",$.message);throw $}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),w=900,B=await gP0(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 pY({access_token:B,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:$})}async handleRevokeRequest(A){let Q=await xP0(A),w=vP0(A,Q),B=w.clientId??Q.get("client_id")??void 0,$=Q.get("token");if(w.error)return y6("invalid_client",w.error);if(!$)return y6("invalid_request","token is required");if(B){let f=await this.clientStore.getClient(B),D=hP0(f,w);if(D)return y6("invalid_client",D)}return await this.refreshTokenStore.revokeToken($,B),new Response(null,{status:200})}}class SP0{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 y6("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return y6("access_denied","Invalid setup token");let Q=await this.passkeyService.generateRegistrationOptions(dw0(A));return pY(Q)}async handleRegistrationVerify(A){if(await this.passkeyService.hasCredentials())return y6("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return y6("access_denied","Invalid setup token");let Q=await this.passkeyService.verifyRegistrationResponse(await A.json(),dw0(A));if(!Q.verified)return y6("access_denied","Passkey registration failed");await this.setupFlow.clearSetupState();let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:tl(A)});return pY({verified:!0},200,{"Set-Cookie":w.cookie})}async handleAuthenticationOptions(A){if(!await this.passkeyService.hasCredentials())return y6("access_denied","No passkey registered");let Q=await this.passkeyService.generateAuthenticationOptions(dw0(A));return pY(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),dw0(A));if(!Q.verified)return y6("access_denied","Passkey authentication failed");let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:tl(A)});return pY({verified:!0},200,{"Set-Cookie":w.cookie})}}function dw0(A){let Q=Hv(A),w=new URL(Q);return{origin:w.origin,rpID:w.hostname}}import{randomUUID as $l2}from"crypto";var Bp=86400;class mP0{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_${$l2()}`,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 tU(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:tU(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:HP0(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 qv(FxA(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupStateStore.recordDelivery(A,Q,w)}}class nw0{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;clientStore;authCodeStore;sessionStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=EZ(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>EZ(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??Xv(this.issuer),this.keyStore=new XQ0({storageDir:A.storageDir}),this.clientStore=new YQ0({storageDir:A.storageDir}),this.authCodeStore=new DQ0({storageDir:A.storageDir}),this.sessionStore=new uw0({storageDir:A.storageDir}),this.passkeyService=new Ew0({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new mP0({setupStateStore:new WP0({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??Bp}),this.oauthEndpoints=new TP0({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new Tw0({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new SP0({passkeyService:this.passkeyService,sessionStore:this.sessionStore,setupFlow:this.setupFlow}),this.logger=A.logger}getIssuer(){return this.issuer}async initialize(){if(await this.keyStore.getPrivateJwk(),this.logger?.debug("Auth service signing key loaded"),!await this.hasPasskeyCredentials()){await this.setupFlow.ensureSetupToken();let A=this.getSetupUrl();if(A)if(Xv(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(){return{keys:[await this.keyStore.getPublicJwk()]}}getAuthorizationServerMetadata(A=this.issuer){let Q=EZ(A);return{issuer:Q,authorization_endpoint:tU(Q,"/authorize"),token_endpoint:tU(Q,"/token"),registration_endpoint:tU(Q,"/register"),revocation_endpoint:tU(Q,"/revoke"),jwks_uri:tU(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:[EZ(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 wp(A)}async verifyBearerToken(A,Q={}){let w=OP0(A);if(!w)return;let B=Q.issuer?EZ(Q.issuer):this.resolveRequestIssuer(A);return kP0(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"&&GxA(w))return zxA();if(A.method==="GET"){if(w==="/.well-known/oauth-authorization-server")return tI(pY(this.getAuthorizationServerMetadata(Q)));if(w==="/.well-known/jwks.json")return tI(pY(await this.getJwks()));if(w==="/.well-known/oauth-protected-resource")return tI(pY(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 tI(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&w==="/token")return tI(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&w==="/revoke")return tI(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=Hv(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&Xv(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=CP0(new URL(A.url).searchParams.get("return_to"));return qv(yP0(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=CP0(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":UP0(tl(A)),"Cache-Control":"no-store"}})}}Z0();var rw0="email:send",LxA=K.object({to:K.string().email(),subject:K.string().min(1),text:K.string().min(1),html:K.string().min(1).optional(),sensitivity:K.enum(["normal","secret"]).default("normal")}).strict();c0();Z0();var NxA={name:"@brains/notifications",private:!0,version:"0.2.0-alpha.134",description:"Generic notification routing for transactional and administrative messages",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var uP0="notifications:send",Dl2=K.object({}),Yl2=K.discriminatedUnion("type",[K.object({type:K.literal("email"),address:K.string().email()}).strict()]),Xl2=K.object({recipient:Yl2,title:K.string().min(1),body:K.string().min(1),html:K.string().min(1).optional(),sensitivity:K.enum(["normal","secret"]).default("normal")}).strict(),jxA=K.discriminatedUnion("status",[K.object({status:K.literal("sent"),deliveryId:K.string().optional()}).strict(),K.object({status:K.literal("failed")}).strict()]);class MxA extends RQ{constructor(A={}){super("notifications",NxA,A,Dl2)}async onRegister(A){A.messaging.subscribe(uP0,async(Q)=>{let w=Xl2.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:rw0,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 ow0(A={}){return new MxA(A)}c0();Z0();var _xA={name:"@brains/auth-service",private:!0,version:"0.2.0-alpha.134",description:"Embedded OAuth/OIDC auth service for brain operator authentication",type:"module",main:"./src/index.ts",types:"./src/index.ts",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/notifications":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@simplewebauthn/server":"^13.3.0",jose:"^6.2.3"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","@types/node":"^20.0.0",typescript:"^5.3.3"},files:["src"]};var Wl2=K.union([K.string().email(),K.object({to:K.string().email(),subject:K.string().min(1),body:K.string().min(1)}).strict()]),Zl2=K.object({issuer:K.string().optional(),trustedIssuers:K.array(K.string()).default([]),allowLocalhostIssuers:K.boolean().optional(),storageDir:K.string().default("./data/auth"),setupTokenTtlSeconds:K.number().int().positive().default(Bp),setupEmail:Wl2.optional()}),Kl2=K.object({}),sw0;function gH(){return sw0}class cP0 extends RQ{service;constructor(A={}){super("auth-service",_xA,A,Zl2)}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 nw0({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(),sw0=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(sw0===this.service)sw0=void 0;this.service=void 0}async getTools(){return[Sw(this.id,"get_passkey_setup_url","Get the first-passkey setup URL when operator setup is required. Anchor-only.",Kl2,async()=>{let A=this.getService();if(await A.hasPasskeyCredentials())return l8({status:"complete"});let Q=await A.getOperatorSetupRequired();if(Q)return l8({status:"setup_required",setupUrl:Q.setupUrl,expiresAt:Q.expiresAt});return l8({status:"unavailable",reason:"Passkey setup URL is not available."})},{visibility:"anchor",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=Ul2(this.config.setupEmail,w);if(await Q.hasSetupEmailDelivery(w.setupTokenId,B.to))return;let $=await A.messaging.send({type:uP0,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=jxA.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 Ul2(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(`
2278
+ `)}}return{to:A.to,subject:PxA(A.subject,Q),body:PxA(A.body,Q)}}function PxA(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 $p(A){return new cP0(A)}Z0();var lP0=K.object({transport:K.enum(["stdio","http"]).default("http"),httpPort:K.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:K.string().describe("Bearer token for HTTP transport authentication").optional()});function kxA(A,Q){return[]}c0();function pP0(A,Q){A.messaging.subscribe("job-progress",async(w)=>{let B=vO.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,D=$.status,Y=$.id;if(Q.debug(`${f} ${Y} - ${D}:`,{id:$.id,message:$.message,progress:$.progress,metadata:$.metadata}),$.batchDetails)Q.debug(`Batch details for ${Y}:`,{totalOperations:$.batchDetails.totalOperations,completedOperations:$.batchDetails.completedOperations,failedOperations:$.batchDetails.failedOperations,currentOperation:$.batchDetails.currentOperation,errors:$.batchDetails.errors});if($.jobDetails)Q.debug(`Job details for ${Y}:`,{jobType:$.jobDetails.jobType,priority:$.jobDetails.priority,retryCount:$.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var OxA={name:"@brains/mcp",private:!0,version:"0.2.0-alpha.134",type:"module",main:"./src/index.ts",module:"./src/index.ts",types:"./src/index.ts",files:["src"],scripts:{typecheck:"tsc --noEmit",lint:"eslint --max-warnings 0 .","lint:fix":"eslint --fix .",test:"bun test"},dependencies:{"@brains/auth-service":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@modelcontextprotocol/sdk":"^1.24.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.1.14","@types/cors":"^2.8.17","@types/express":"^4.17.21",typescript:"^5.3.3"}};class eI extends GU{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",OxA,Q,lP0)}async getTools(){return kxA(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"});pP0(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;let A=gH();return this.httpServer=gq.createFresh({port:this.config.httpPort,logger:this.logger,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,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);if(this.config.transport==="http"&&(this.config.authToken||gH()))w="anchor",this.logger.debug("HTTP authentication configured - authenticated users will have anchor permissions");if(this.mcpTransport.setPermissionLevel(w),this.logger.debug(`Starting MCP ${this.config.transport} transport with ${w} permissions`),this.config.transport==="stdio"){this.stdioServer=jZ.createFresh();let B=this.mcpTransport.getMcpServer();this.stdioServer.connectMCPServer(B),await this.stdioServer.start(),this.logger.debug("MCP STDIO transport started")}else{this.httpServer=this.getOrCreateHttpServer();let B=this.mcpTransport.getMcpServer();this.httpServer.connectMCPServer(B,this.mcpTransport),this.httpServer.connectAgentService(A.agent),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(){jZ.resetInstance(),gq.resetInstance()}}c0();Z0();var AX=Y1(eC0(),1);Z0();c0();var Ay0=K.object({botToken:K.string().min(1).describe("Discord bot token"),allowedChannels:K.array(K.string()).default([]),requireMention:K.boolean().default(!0),allowDMs:K.boolean().default(!0),showTypingIndicator:K.boolean().default(!0),statusMessage:K.string().default("Mention me to chat"),useThreads:K.boolean().default(!0),threadAutoArchive:K.union([K.literal(60),K.literal(1440),K.literal(4320),K.literal(10080)]).default(1440),...jN.shape,captureUrlEmoji:K.string().default("\uD83D\uDD16")});var kH1={name:"@brains/discord",private:!0,version:"0.2.0-alpha.134",description:"Discord interface for Brains",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",test:"bun test"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","discord.js":"^14.14.1"},devDependencies:{"@brains/core":"workspace:*","@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest"}};var A50=2000,ybQ=8000,EbQ=100;function Q50(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class gJ extends AZ{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;constructor(A,Q={}){super("discord",kH1,A,Ay0);this.fetchText=Q.fetchText??Nt}async onRegister(A){await super.onRegister(A),this.client=new AX.Client({intents:[AX.GatewayIntentBits.Guilds,AX.GatewayIntentBits.GuildMessages,AX.GatewayIntentBits.MessageContent,AX.GatewayIntentBits.DirectMessages],partials:[AX.Partials.Channel]}),this.client.on(AX.Events.MessageCreate,(Q)=>{this.handleMessage(Q)}),this.client.on(AX.Events.InteractionCreate,(Q)=>{this.handleInteraction(Q)}),this.client.once(AX.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(!Q50(w))return;let B=sL(Q,A50);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(!Q50(w))return;if(typeof Q!=="string")return(await w.send(Q)).id;let B=sL(Q,A50),$;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(!Q50(B))return!1;try{return await(await B.messages.fetch(Q)).edit(w.slice(0,A50)),!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),D=!Q&&this.isConfiguredSpace(f),Y={channelId:f,isBot:A.author.bot};if(this.config.allowedChannels.length>0&&!Q&&!this.isAllowedChannel(A.channel.id,f))return;let X=Q||$||!this.config.requireMention||B;if(D&&(!X||this.willRouteUseNonSpaceConversation(A)))await this.capturePassiveSpaceMessage(A,f).catch((Z)=>this.logger.error("Passive Discord space capture failed",{error:Z,channelId:f}));if(!X){if(this.config.captureUrls){let Z=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(Z.length>0){await A.react(this.config.captureUrlEmoji).catch((G)=>this.logger.debug("React failed",{error:G}));for(let G of Z)await this.captureUrlViaAgent(G,A.channel.id,A.author.id,"discord",Y).catch((F)=>this.logger.error("URL capture failed",{error:F,url:G}))}}return}let H=this.stripMention(A.content);if(A.attachments.size>0){let Z=this.context.permissions.getUserLevel("discord",A.author.id,Y);if(Z==="anchor"||Z==="trusted")for(let F of A.attachments.values()){let V=F.name,b=F.contentType??void 0,L=F.size;if(!this.isUploadableTextFile(V,b))continue;if(!this.isFileSizeAllowed(L))continue;try{let N=await this.fetchText(F.url);H+=`
2279
2279
 
2280
2280
  `+this.formatFileUploadMessage(V,N)}catch(N){this.logger.error("Failed to download attachment",{error:N,filename:V})}}}if(H=H.trim(),!H)return;let W=A.channel.id;await this.routeToAgent(H,W,A,Y)}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((f)=>this.logger.debug("Failed to reply to stale approval button",{error:f}));return}await A.deferUpdate().catch((f)=>this.logger.debug("Failed to defer approval button",{error:f}));let $=await this.context.agent.confirmPendingAction(w,Q.confirmed,Q.approvalId,this.buildInteractionConfirmationContext(A));await this.handleAgentResponseToolStatuses($,w),this.syncPendingApprovalsAfterResolution(w,Q.approvalId,$),await this.sendApprovalResultMessage({channelId:A.channelId,response:$})}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:r7(A,EbQ),autoArchiveDuration:this.config.threadAutoArchive})).id}catch(H){this.logger.error("Failed to create thread",{error:H})}let D=`discord-${f}`,Y=this.context.permissions.getUserLevel("discord",w.author.id,B),X=this.getChannelName(w);this.startProcessingInput(f);try{let H=this.client?.channels.cache.get(f);if(Q50(H))this.startTypingIndicator(H);if(this.pendingConfirmations.has(D)){await this.handleConfirmationResponse(A,D,f,w,B);return}let W=await $.chat(A,D,{userPermissionLevel:Y,interfaceType:"discord",channelId:f,channelName:X,...this.buildUserMessageMetadata(w,Q,X,{threadId:f!==Q||w.channel.isThread()?f:void 0})});await this.handleAgentResponseToolStatuses(W,D);let Z=this.getPendingApprovalCards(W.cards);if(Z.length>0)this.pendingConfirmations.set(D,new Set(Z.map((F)=>F.id)));else if(W.pendingConfirmations)this.pendingConfirmations.set(D,new Set(W.pendingConfirmations.map((F)=>F.id)));let G=await this.sendMessageWithId({channelId:f,message:this.formatAgentResponseText(W.text,Z),approvalCards:Z});if(G&&W.toolResults){for(let F of W.toolResults)if(F.jobId)this.trackAgentResponseForJob(F.jobId,G,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:r7(A.trim().length>0?`${A}
2281
2281
 
@@ -2343,7 +2343,7 @@ ${A.value}
2343
2343
  `);if(f50(A))return this.renderList(A,0,(Q)=>this.nodeToDiscordMarkdown(Q));if(A.type==="break")return`
2344
2344
  `;if(A.type==="thematicBreak")return"---";if(WE0(A))return`\`\`\`
2345
2345
  ${ZE0(A)}
2346
- \`\`\``;return this.defaultNodeToText(A,(Q)=>this.nodeToDiscordMarkdown(Q))}},uI1={DeferredChannelMessageWithSource:5,DeferredUpdateMessage:6},z50="https://discord.com/api/v10",cI1=2000,KOQ=/^[0-9a-f]{64}$/,UOQ=/^[0-9a-f]+$/,GOQ=class A{name="discord";userName;botUserId;apiBaseUrl;botToken;publicKey;applicationId;mentionRoleIds;chat=null;logger;formatConverter=new ZOQ;requestContext=new QOQ;threadParentCache=new Map;static THREAD_PARENT_CACHE_TTL=300000;constructor(Q={}){let w=Q.botToken??process.env.DISCORD_BOT_TOKEN;if(!w)throw new rH("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 rH("discord","publicKey is required. Set DISCORD_PUBLIC_KEY or provide it in config.");let $=Q.applicationId??process.env.DISCORD_APPLICATION_ID;if(!$)throw new rH("discord","applicationId is required. Set DISCORD_APPLICATION_ID or provide it in config.");if(this.apiBaseUrl=Q.apiUrl??process.env.DISCORD_API_URL??z50,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.logger=Q.logger??new K50("info").child("discord"),this.userName=Q.userName??"bot",!KOQ.test(this.publicKey))this.logger.error("Invalid Discord public key format",{length:this.publicKey.length,isHex:UOQ.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($),D=Q.headers.get("x-discord-gateway-token");if(D){if(D!==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 Z=JSON.parse(f);return this.handleForwardedGatewayEvent(Z,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 Y=Q.headers.get("x-signature-ed25519"),X=Q.headers.get("x-signature-timestamp");if(!await this.verifySignature($,Y,X))return this.logger.warn("Discord signature verification failed, returning 401"),new Response("Invalid signature",{status:401});this.logger.info("Discord signature verification passed");let W;try{W=JSON.parse(f)}catch{return new Response("Invalid JSON",{status:400})}if(this.logger.info("Discord interaction parsed",{type:W.type,typeIsPing:W.type===xC.Ping,expectedPingType:xC.Ping,id:W.id}),W.type===xC.Ping){let Z=JSON.stringify({type:ei.InteractionResponseType.PONG});return this.logger.info("Discord PING received, responding with PONG",{responseBody:Z,responseType:ei.InteractionResponseType.PONG}),new Response(Z,{status:200,headers:{"Content-Type":"application/json"}})}if(W.type===xC.MessageComponent)return this.handleComponentInteraction(W,w),this.respondToInteraction({type:uI1.DeferredUpdateMessage});if(W.type===xC.ApplicationCommand)return this.handleApplicationCommandInteraction(W,w),this.respondToInteraction({type:uI1.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 ei.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,D=Q.guild_id||"@me",Y=Q.message?.id;if(!(f&&Y)){this.logger.warn("Missing channel_id or message_id in interaction");return}let X=Q.channel,H=X?.type===11||X?.type===12,W=H&&X?.parent_id?X.parent_id:f,Z=H?this.encodeThreadId({guildId:D,channelId:W,threadId:f}):this.encodeThreadId({guildId:D,channelId:f}),G=BOQ(B),F={actionId:G.actionId,value:G.value??G.actionId,user:{userId:$.id,userName:$.username,fullName:$.global_name||$.username,isBot:$.bot??!1,isMe:!1},messageId:Y,threadId:Z,adapter:this,raw:Q};this.logger.debug("Processing Discord button action",{actionId:B,messageId:Y,threadId:Z}),this.chat.processAction(F,w)}handleApplicationCommandInteraction(Q,w){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring interaction");return}let B=Q.data?.name;if(!B){this.logger.warn("No command name in application command interaction");return}let $=Q.member?.user||Q.user;if(!$){this.logger.warn("No user in application command interaction");return}let f=Q.channel_id;if(!f){this.logger.warn("Missing channel_id in application command interaction");return}let D=Q.guild_id||"@me",Y=Q.channel,X=Y?.type===11||Y?.type===12,H=X&&Y?.parent_id?Y.parent_id:f,W=X?this.encodeThreadId({guildId:D,channelId:H,threadId:f}):this.encodeThreadId({guildId:D,channelId:f}),{command:Z,text:G}=this.parseSlashCommand(B,Q.data?.options);this.logger.debug("Processing Discord slash command",{command:Z,text:G,userId:$.id,channelId:W}),this.requestContext.run({slashCommand:{channelId:W,interactionToken:Q.token,initialResponseSent:!1}},()=>{this.chat?.processSlashCommand({command:Z,text:G,user:{userId:$.id,userName:$.username,fullName:$.global_name||$.username,isBot:$.bot??!1,isMe:$.id===this.applicationId},adapter:this,raw:Q,channelId:W},w)})}parseSlashCommand(Q,w){let B=[Q.startsWith("/")?Q:`/${Q}`],$=[],f=(D)=>{for(let Y of D){if(Y.value!==void 0){$.push(String(Y.value));continue}if(Y.options&&Y.options.length>0)B.push(Y.name),f(Y.options)}};if(w&&w.length>0)f(w);return{command:B.join(" "),text:$.join(" ").trim()}}async handleGatewayInteraction(Q){if(Q.isChatInputCommand()){await Q.deferReply(),this.handleApplicationCommandInteraction(this.normalizeGatewaySlashCommandInteraction(Q));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,D=$;if(Q.thread)f=Q.thread.id,D=Q.thread.parent_id;else if(Q.channel_type===11||Q.channel_type===12)try{let F=await(await this.discordFetch(`/channels/${$}`,"GET")).json();if(F.parent_id)f=$,D=F.parent_id,this.logger.debug("Fetched thread parent for forwarded message",{threadId:$,parentId:F.parent_id})}catch(G){this.logger.error("Failed to fetch thread parent",{error:String(G),channelId:$})}let Y=Q.is_mention||Q.mentions.some((G)=>G.id===this.applicationId),X=this.mentionRoleIds.length>0&&Q.mention_roles?.some((G)=>this.mentionRoleIds.includes(G)),H=Y||X;if(!f&&H)try{let G=await this.createDiscordThread($,Q.id);f=G.id,this.logger.debug("Created Discord thread for forwarded mention",{channelId:$,messageId:Q.id,threadId:G.id})}catch(G){this.logger.error("Failed to create Discord thread for mention",{error:String(G),messageId:Q.id})}let W=this.encodeThreadId({guildId:B,channelId:D,threadId:f}),Z=new x5({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.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((G)=>({type:this.getAttachmentType(G.content_type),url:G.url,name:G.filename,mimeType:G.content_type,size:G.size})),raw:Q,isMention:H});try{await this.chat.handleIncomingMessage(this,W,Z)}catch(G){this.logger.error("Error handling forwarded message",{error:String(G),messageId:Q.id})}}async handleForwardedReaction(Q,w,B){if(!this.chat)return;let $=Q.guild_id||"@me",f=Q.channel_id,D,Y=f;if(Q.channel_type===H_.GuildPublicThread||Q.channel_type===H_.GuildPrivateThread){let F=this.threadParentCache.get(f);if(F&&F.expiresAt>Date.now())D=f,Y=F.parentId;else try{let b=await(await this.discordFetch(`/channels/${f}`,"GET")).json();if(b.parent_id)D=f,Y=b.parent_id,this.threadParentCache.set(f,{parentId:b.parent_id,expiresAt:Date.now()+A.THREAD_PARENT_CACHE_TTL})}catch(V){this.logger.error("Failed to fetch thread parent for reaction",{error:String(V),channelId:f})}}let X=this.encodeThreadId({guildId:$,channelId:Y,threadId:D}),H=Q.emoji.name||"unknown",W=this.normalizeDiscordEmoji(H),Z=Q.user??Q.member?.user;if(!Z){this.logger.warn("Reaction event missing user info",{data:Q});return}let G={adapter:this,threadId:X,messageId:Q.message_id,emoji:W,rawEmoji:Q.emoji.id?`<:${H}:${Q.emoji.id}>`:H,added:w,user:{userId:Z.id,userName:Z.username,fullName:Z.username,isBot:Z.bot===!0,isMe:Z.id===this.applicationId},raw:Q};this.chat.processReaction(G)}async postMessage(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=Q;if($)B=$;let D={},Y=[],X=[],H=G50(w);if(H){let V=rE0(H);Y.push(...V.embeds),X.push(...V.components)}else D.content=this.truncateContent(f_(this.formatConverter.renderPostable(w),"discord"));if(Y.length>0)D.embeds=Y;if(X.length>0)D.components=X;let W=PE0(w),Z=this.tryPostSlashResponse(f,D,W);if(Z)return Z;if(W.length>0)return this.postMessageWithFiles(B,f,D,W);this.logger.debug("Discord API: POST message",{channelId:B,contentLength:D.content?.length||0,embedCount:Y.length,componentCount:X.length});let F=await(await this.discordFetch(`/channels/${B}/messages`,"POST",D)).json();return this.logger.debug("Discord API: POST message response",{messageId:F.id}),{id:F.id,threadId:f,raw:F}}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 D=f?`/webhooks/${this.applicationId}/${Q.interactionToken}/messages/@original`:`/webhooks/${this.applicationId}/${Q.interactionToken}?wait=true`,Y=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(D,Y,B,$):await this.discordInteractionFetch(D,Y,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 PC&&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<=cI1)return Q;return`${Q.slice(0,cI1-3)}...`}async postMessageWithFiles(Q,w,B,$){let f=new FormData;f.append("payload_json",JSON.stringify(B));for(let X=0;X<$.length;X++){let H=$[X];if(!H)continue;let W=await kE0(H.data,{platform:"discord"});if(!W)continue;let Z=new Blob([new Uint8Array(W)],{type:H.mimeType||"application/octet-stream"});f.append(`files[${X}]`,Z,H.filename)}let D=await fetch(`${z50}/channels/${Q}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.botToken}`},body:f});if(!D.ok){let X=await D.text();throw new PC("discord",`Failed to post message: ${D.status} ${X}`)}let Y=await D.json();return{id:Y.id,threadId:w,raw:Y}}async discordInteractionFetch(Q,w,B){let $=await fetch(`${z50}${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 PC("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 Y=0;Y<$.length;Y++){let X=$[Y];if(!X)continue;let H=await kE0(X.data,{platform:"discord"});if(!H)continue;let W=new Blob([new Uint8Array(H)],{type:X.mimeType||"application/octet-stream"});f.append(`files[${Y}]`,W,X.filename)}let D=await fetch(`${z50}${Q}`,{method:w,body:f});if(!D.ok){let Y=await D.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:D.status,error:Y}),new PC("discord",`Discord interaction API error: ${D.status} ${Y}`)}return D}async editMessage(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),D=f||$,Y={},X=[],H=[],W=G50(B);if(W){let F=rE0(W);X.push(...F.embeds),H.push(...F.components),Y.content=""}else Y.content=this.truncateContent(f_(this.formatConverter.renderPostable(B),"discord"));if(X.length>0)Y.embeds=X;if(H.length>0)Y.components=H;this.logger.debug("Discord API: PATCH message",{channelId:D,messageId:w,contentLength:Y.content?.length||0});let G=await(await this.discordFetch(`/channels/${D}/messages/${w}`,"PATCH",Y)).json();return this.logger.debug("Discord API: PATCH message response",{messageId:G.id}),{id:G.id,threadId:Q,raw:G}}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),D=f||$,Y=this.encodeEmoji(B);this.logger.debug("Discord API: PUT reaction",{channelId:D,messageId:w,emoji:Y}),await this.discordFetch(`/channels/${D}/messages/${w}/reactions/${Y}/@me`,"PUT"),this.logger.debug("Discord API: PUT reaction response",{ok:!0})}async removeReaction(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),D=f||$,Y=this.encodeEmoji(B);this.logger.debug("Discord API: DELETE reaction",{channelId:D,messageId:w,emoji:Y}),await this.discordFetch(`/channels/${D}/messages/${w}/reactions/${Y}/@me`,"DELETE"),this.logger.debug("Discord API: DELETE reaction response",{ok:!0})}encodeEmoji(Q){let w=ri.toDiscord?ri.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,D=w.limit||50,Y=w.direction??"backward",X=new URLSearchParams;if(X.set("limit",String(D)),w.cursor)if(Y==="backward")X.set("before",w.cursor);else X.set("after",w.cursor);this.logger.debug("Discord API: GET messages",{channelId:f,limit:D,direction:Y,cursor:w.cursor});let W=await(await this.discordFetch(`/channels/${f}/messages?${X.toString()}`,"GET")).json();this.logger.debug("Discord API: GET messages response",{messageCount:W.length});let G=[...W].reverse().map((V)=>this.parseDiscordMessage(V,Q)),F;if(W.length===D)if(Y==="backward")F=W.at(-1)?.id;else F=W[0]?.id;return{messages:G,nextCursor:F}}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===H_.DM||f.type===H_.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 rH("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===Sz1.ThreadStarterMessage&&Q.referenced_message?Q.referenced_message:Q,$=B.author,f=$.bot??!1,D=$.id===this.botUserId;return new x5({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:D},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((Y)=>({type:this.getAttachmentType(Y.content_type),url:Y.url,name:Y.filename,mimeType:Y.content_type,size:Y.size,width:Y.width??void 0,height:Y.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"}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 D=await fetch($,{method:w,headers:f,body:B?JSON.stringify(B):void 0});if(!D.ok){let Y=await D.text();throw this.logger.error("Discord API error",{path:Q,method:w,status:D.status,error:Y}),new PC("discord",`Discord API error: ${D.status} ${Y}`)}return D}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 S9.Client({intents:[S9.GatewayIntentBits.Guilds,S9.GatewayIntentBits.GuildMessages,S9.GatewayIntentBits.MessageContent,S9.GatewayIntentBits.DirectMessages,S9.GatewayIntentBits.GuildMessageReactions,S9.GatewayIntentBits.DirectMessageReactions],partials:[S9.Partials.Channel]}),f=!1;if(B)$.on("raw",async(D)=>{if(f)return;if(!D.t)return;this.logger.info("Discord Gateway forwarding event",{type:D.t}),await this.forwardGatewayEvent(B,{type:`GATEWAY_${D.t}`,timestamp:Date.now(),data:D.d})});else this.setupLegacyGatewayHandlers($,()=>f);$.on(S9.Events.ClientReady,()=>{this.logger.info("Discord Gateway connected",{username:$.user?.username,id:$.user?.id})}),$.on(S9.Events.Error,(D)=>{this.logger.error("Discord Gateway error",{error:String(D)})});try{await $.login(this.botToken),await new Promise((D)=>{let Y=setTimeout(D,Q);if(w){if(w.aborted){clearTimeout(Y),D();return}w.addEventListener("abort",()=>{this.logger.info("Discord Gateway listener received abort signal (new listener started)"),clearTimeout(Y),D()},{once:!0})}}),this.logger.info("Discord Gateway listener duration elapsed, disconnecting")}catch(D){this.logger.error("Discord Gateway listener error",{error:String(D)})}finally{f=!0,$.destroy(),this.logger.info("Discord Gateway listener stopped")}}setupLegacyGatewayHandlers(Q,w){Q.on(S9.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((Y)=>this.mentionRoleIds.includes(Y.id)),D=$||f;this.logger.info("Discord Gateway message received",{channelId:B.channelId,guildId:B.guildId,authorId:B.author.id,isMentioned:D,isUserMentioned:$,isRoleMentioned:f,content:B.content.slice(0,100)}),await this.handleGatewayMessage(B,D)}),Q.on(S9.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(S9.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(S9.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(),D,Y=$;if(f&&"parentId"in Q.channel&&Q.channel.parentId)D=$,Y=Q.channel.parentId;if(!D&&w)try{let W=await this.createDiscordThread($,Q.id);D=W.id,this.logger.debug("Created Discord thread for incoming mention",{channelId:$,messageId:Q.id,threadId:W.id})}catch(W){this.logger.error("Failed to create Discord thread for mention",{error:String(W),messageId:Q.id})}let X=this.encodeThreadId({guildId:B,channelId:Y,threadId:D}),H=new x5({id:Q.id,threadId:X,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((W)=>({type:this.getAttachmentType(W.contentType),url:W.url,name:W.name,mimeType:W.contentType??void 0,size:W.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,X,H)}catch(W){this.logger.error("Error handling Gateway message",{error:String(W),messageId:Q.id})}}async handleGatewayReaction(Q,w,B){if(!this.chat)return;let $=Q.message.guildId||"@me",f=Q.message.channelId,D=Q.message.channel?.isThread?.(),Y=f,X;if(D&&Q.message.channel?.parentId)X=f,Y=Q.message.channel.parentId;let H=this.encodeThreadId({guildId:$,channelId:Y,threadId:X}),W=Q.emoji.name||"unknown",Z=this.normalizeDiscordEmoji(W),G={adapter:this,threadId:H,messageId:Q.message.id,emoji:Z,rawEmoji:Q.emoji.id?`<:${W}:${Q.emoji.id}>`:W,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(G)}channelIdFromThreadId(Q){return Q.split(":").slice(0,3).join(":")}async fetchChannelMessages(Q,w={}){let $=Q.split(":")[2];if(!$)throw new rH("discord",`Invalid Discord channel ID: ${Q}`);let f=w.limit||50,D=w.direction??"backward",Y=new URLSearchParams;if(Y.set("limit",String(f)),w.cursor)if(D==="backward")Y.set("before",w.cursor);else Y.set("after",w.cursor);this.logger.debug("Discord API: GET channel messages",{channelId:$,limit:f,direction:D,cursor:w.cursor});let H=await(await this.discordFetch(`/channels/${$}/messages?${Y.toString()}`,"GET")).json();this.logger.debug("Discord API: GET channel messages response",{messageCount:H.length});let Z=[...H].reverse().map((F)=>this.parseDiscordMessage(F,Q)),G;if(H.length===f)if(D==="backward")G=H.at(-1)?.id;else G=H[0]?.id;return{messages:Z,nextCursor:G}}async listThreads(Q,w={}){let B=Q.split(":"),$=B[1],f=B[2];if(!($&&f))throw new rH("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET threads",{guildId:$,channelId:f});let X=((await(await this.discordFetch(`/guilds/${$}/threads/active`,"GET")).json()).threads||[]).filter((L)=>L.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 W=[...X,...H],Z=new Set,G=W.filter((L)=>{if(Z.has(L.id))return!1;return Z.add(L.id),!0}),F=w.limit||50,V=G.slice(0,F),b=[];for(let L of V){let N=this.encodeThreadId({guildId:$,channelId:f,threadId:L.id});try{let g=(await(await this.discordFetch(`/channels/${L.id}/messages?limit=1&after=0`,"GET")).json())[0];if(g)b.push({id:N,rootMessage:this.parseDiscordMessage(g,N),replyCount:L.total_message_sent??L.message_count,lastReplyAt:L.thread_metadata?.archive_timestamp?new Date(L.thread_metadata.archive_timestamp):void 0})}catch{b.push({id:N,rootMessage:new x5({id:L.id,threadId:N,text:L.name,formatted:this.formatConverter.toAst(L.name),raw:L,author:{userId:"unknown",userName:"unknown",fullName:"unknown",isBot:!1,isMe:!1},metadata:{dateSent:new Date,edited:!1},attachments:[]}),replyCount:L.total_message_sent??L.message_count})}}return this.logger.debug("Discord API: listThreads result",{threadCount:b.length}),{threads:b,nextCursor:G.length>F?String(F):void 0}}async fetchChannelInfo(Q){let B=Q.split(":")[2];if(!B)throw new rH("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===H_.DM||f.type===H_.GroupDM,memberCount:f.member_count,metadata:{channelType:f.type,raw:f}}}async postChannelMessage(Q,w){let $=Q.split(":")[2];if(!$)throw new rH("discord",`Invalid Discord channel ID: ${Q}`);let f={},D=[],Y=[],X=G50(w);if(X){let F=rE0(X);D.push(...F.embeds),Y.push(...F.components)}else f.content=this.truncateContent(f_(this.formatConverter.renderPostable(w),"discord"));if(D.length>0)f.embeds=D;if(Y.length>0)f.components=Y;let H=PE0(w),W=this.tryPostSlashResponse(Q,f,H);if(W)return W;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 G=await(await this.discordFetch(`/channels/${$}/messages`,"POST",f)).json();return{id:G.id,threadId:Q,raw:G}}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 mJ(B)}};function iI1(A){return new GOQ(A??{})}var zOQ=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:qOQ(),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 qOQ(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function q50(A){return new zOQ}Z0();var FOQ=K.object({subscribedAt:K.string().datetime(),routingMode:K.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:K.boolean().optional()}),VOQ="chat.discord.subscriptions";function oE0(A){return A.scoped({namespace:VOQ,schema:FOQ})}function dI1(A,Q=q50()){let w=oE0(A);return new nI1(Q,w)}class nI1{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 rI1(A){let{discord:Q}=A;if(!Q)return new ME0({userName:A.userName,adapters:{},state:q50()});let w=iI1({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds});return A.gatewayLoop.setAdapter(w),new ME0({userName:A.userName,adapters:{discord:w},concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"},state:dI1(A.runtimeState)})}class sE0{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}}}c0();class aE0{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 D=this.deps.getUploadStore();if(!D)return $;for(let Y of w.attachments){let X=Y.name;if(!X)continue;let H=Zq(X,"upload"),W=dV(H,Y.mimeType),Z=Y.size??0,G=H00(H,W);if(!G){$.notices.push(`Unsupported file upload type: ${H}`);continue}if(!W00(G,Z)){$.notices.push(`File upload too large: ${H}`);continue}try{let F=await this.readAttachmentData(Y);if(!F)continue;let V=Kq({filename:H,mediaType:W,content:F,fallbackFilename:"upload"});if(!V.ok){$.notices.push(V.message);continue}let b=await D.save({filename:V.filename,mediaType:V.mediaType,content:F,metadata:this.buildMetadata(A,Q,w)});$.attachments.push(sI1(b.filename,b.mediaType,F,b.ref,V.kind==="text"))}catch(F){this.deps.logger.error("Failed to read chat attachment",{error:F,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 oI1(A,Q,w,B){return sI1(A,Q,w,B,nV(A,Q))}function sI1(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 Ad(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}var aI1={name:"@brains/chat",private:!0,version:"0.2.0-alpha.133",description:"Discord Chat SDK interface for Brains",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",test:"bun test"},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":"latest"}};var JOQ=/https?:\/\/\S+/i,bOQ=/[\s\S]+/,LOQ="https://discord.com/api/v10",NOQ=K.object({type:K.literal("card"),children:K.array(K.object({type:K.string()}).passthrough()),imageUrl:K.string().optional(),subtitle:K.string().optional(),title:K.string().optional()}).passthrough(),jOQ=K.object({card:K.custom((A)=>NOQ.safeParse(A).success),fallbackText:K.string().optional()});class F50 extends AZ{threadRegistry=new w50;pendingApprovals;uploadContinuity;promptActions=new Map;toolStatusMessenger=new wy0(this.threadRegistry);cardBuilder=new Dy0({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new Xy0({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new Hy0({cardBuilder:this.cardBuilder,clearMessageComponents:(A,Q)=>this.clearDiscordMessageComponents(A,Q)});subscriptionRouter=new sE0({getSubscriptions:()=>this.discordSubscriptions,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:(A,Q)=>this.isBotCreatedDiscordThread(A,Q),logger:this.logger});chatInputBuilder=new aE0({getUploadStore:()=>this.context?.uploads.scoped(Ad()),getThreadIdParts:(A)=>this.getThreadIdParts(A),logger:this.logger});gatewayLoop;discordApp;discordSubscriptions;constructor(A={}){super("chat",aI1,A,Qy0);this.gatewayLoop=new Wy0({getApp:()=>this.discordApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.discordApp=new Zy0({discord:this.config.adapters.discord,getUploadStore:()=>this.context?.uploads.scoped(Ad()),buildApp:(Q)=>rI1({userName:this.config.userName,discord:this.config.adapters.discord,gatewayLoop:this.gatewayLoop,runtimeState:Q})}),this.pendingApprovals=new OS({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 yS({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(Ad());if(!w)throw Error("Chat upload store unavailable");let B=await w.read(Q);return oI1(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=oE0(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 ci(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 ci(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=jOQ.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 fy0(A)}formatCompletionOutput(A){return fy0(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 hH1(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($&&this.shouldRouteDiscordMessage(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(bOQ,async(Q,w,B)=>{await this.handleRoutedMessage(Q,w,B)});A.onNewMessage(JOQ,async(Q,w)=>{await this.handlePassiveUrlCapture(Q,w)}),A.onAction([B50,By0],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction($y0,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(!this.shouldHandleDiscordAction(w,Q))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}let $=this.getThreadIdParts(w.id),f=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:$.channelId??w.channelId,isBot:Boolean(A.user.isBot)}),D=this.getConversationId(Q,w.id),Y=w.id;await this.runAgentTurn({thread:w,channelId:Y,logLabel:"Error handling chat prompt action",body:async()=>{if(!this.context)return;let X=await this.context.agent.chat(B.prompt,D,{userPermissionLevel:f,interfaceType:Q,channelId:Y,channelName:w.isDM?"DM":w.channelId,...this.buildActionEventMetadata(Q,w,A)});await this.renderAgentResponse({thread:w,channelId:Y,conversationId:D,response:X,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(!this.shouldHandleDiscordAction($,Q))return;let f=this.getThreadIdParts($.id),D=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===B50,userPermissionLevel:D,metadata:this.buildActionEventMetadata(Q,$,A)})}shouldHandleDiscordAction(A,Q){if(Q!=="discord")return!0;let w=this.config.adapters.discord;if(!w)return!1;if(A.isDM&&!w.allowDMs)return!1;return this.isAllowedChannel(A,w)}isBotCreatedDiscordThread(A,Q){if(A.isDM)return!1;let w=this.getThreadIdParts(A.id);if(!w.threadId)return!1;let B=this.getRawDiscordChannelId(Q);return B!==void 0&&B!==w.threadId}getRawDiscordChannelId(A){let Q=A.raw;if(typeof Q!=="object"||Q===null)return;let w=Q.channel_id;return typeof w==="string"?w:void 0}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(!this.shouldRouteDiscordMessage(A,Q,$))return;await this.routeToAgent(B,A,Q,w)}shouldRouteDiscordMessage(A,Q,w){if(A.isDM&&!w.allowDMs)return!1;if(Q.author.isMe)return!1;if(Q.author.isBot&&!Q.isMention)return!1;if(!this.isAllowedChannel(A,w))return!1;return!0}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 D of ci(Q,f))await A.post(D)}async routeToAgent(A,Q,w,B){if(!this.context)return;this.threadRegistry.set(Q);let $=this.getConversationId(A,Q.id),f=Q.id,D=this.getPermissionContext(Q,w),Y=this.context.permissions.getUserLevel(A,w.author.userId,D),X=await this.chatInputBuilder.build(A,Q,w,Y),H=[...X.attachments];if(await this.attachPriorUploads($,X,Y),await this.postUploadNotices(Q,X.notices),!X.message&&X.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 W=await this.getPendingApprovalIds($);if(W.size>0){await this.handleConfirmationResponse(X.message,$,Q,W,Y,this.buildUserMessageMetadata(A,Q,w));return}let Z=this.buildCoalescedAgentInput(X.message,B),G=await this.context.agent.chat(Z.message,$,{userPermissionLevel:Y,interfaceType:A,channelId:f,channelName:this.getChannelName(Q),...this.buildUserMessageMetadata(A,Q,w,Z.metadata),...X.attachments.length>0?{attachments:X.attachments}:{}});await this.renderAgentResponse({thread:Q,channelId:f,conversationId:$,response:G,userPermissionLevel:Y})}})}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);if(A.confirmation)await this.approvalCards.resolve(A.conversationId,A.confirmation.approvalId,A.confirmation.confirmed);let w=A.confirmation?this.formatConfirmationResponsePayload(A.response,A.confirmation.confirmed,this.getRemainingApprovalHelp(A.conversationId,A.response),Q.deniedCardIds):this.formatAgentResponseText(A.response.text,A.response.cards,A.response.pendingConfirmations,Q.deniedCardIds),B=await this.sendAgentResponseWithFiles({thread:A.thread,channelId:A.channelId,message:w,files:Q.files}),$=await this.sendArtifactCards(A.thread,A.response.cards,Q.deniedCardIds);await this.sendSupplementalCards(A.thread,A.response.cards,A.response.pendingConfirmations),await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,A.response.pendingConfirmations);let f=$??B;if(f)for(let D of B00(A.response))this.trackAgentResponseForJob(D,f,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){let D=ie({message:A,approvalIds:B});if(D.kind==="not-confirmation"){this.pendingApprovals.deleteConversation(Q),await w.post(this.formatNoticePayload("No pending approval to resolve."));return}if(D.kind==="notice"){await w.post(this.formatNoticePayload(D.message));return}await this.confirmApproval({thread:w,conversationId:Q,approvalId:D.approvalId,confirmed:D.confirmed,userPermissionLevel:$,...f?{metadata:f}:{}})}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:A.thread.isDM?"DM":A.thread.channelId,...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,w,B){return ee({text:A,cards:Q,pendingConfirmations:w,deniedCardIds:B,formatCard:($)=>this.cardBuilder.formatStructuredCard($,B)}).join(`
2346
+ \`\`\``;return this.defaultNodeToText(A,(Q)=>this.nodeToDiscordMarkdown(Q))}},uI1={DeferredChannelMessageWithSource:5,DeferredUpdateMessage:6},z50="https://discord.com/api/v10",cI1=2000,KOQ=/^[0-9a-f]{64}$/,UOQ=/^[0-9a-f]+$/,GOQ=class A{name="discord";userName;botUserId;apiBaseUrl;botToken;publicKey;applicationId;mentionRoleIds;chat=null;logger;formatConverter=new ZOQ;requestContext=new QOQ;threadParentCache=new Map;static THREAD_PARENT_CACHE_TTL=300000;constructor(Q={}){let w=Q.botToken??process.env.DISCORD_BOT_TOKEN;if(!w)throw new rH("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 rH("discord","publicKey is required. Set DISCORD_PUBLIC_KEY or provide it in config.");let $=Q.applicationId??process.env.DISCORD_APPLICATION_ID;if(!$)throw new rH("discord","applicationId is required. Set DISCORD_APPLICATION_ID or provide it in config.");if(this.apiBaseUrl=Q.apiUrl??process.env.DISCORD_API_URL??z50,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.logger=Q.logger??new K50("info").child("discord"),this.userName=Q.userName??"bot",!KOQ.test(this.publicKey))this.logger.error("Invalid Discord public key format",{length:this.publicKey.length,isHex:UOQ.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($),D=Q.headers.get("x-discord-gateway-token");if(D){if(D!==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 Z=JSON.parse(f);return this.handleForwardedGatewayEvent(Z,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 Y=Q.headers.get("x-signature-ed25519"),X=Q.headers.get("x-signature-timestamp");if(!await this.verifySignature($,Y,X))return this.logger.warn("Discord signature verification failed, returning 401"),new Response("Invalid signature",{status:401});this.logger.info("Discord signature verification passed");let W;try{W=JSON.parse(f)}catch{return new Response("Invalid JSON",{status:400})}if(this.logger.info("Discord interaction parsed",{type:W.type,typeIsPing:W.type===xC.Ping,expectedPingType:xC.Ping,id:W.id}),W.type===xC.Ping){let Z=JSON.stringify({type:ei.InteractionResponseType.PONG});return this.logger.info("Discord PING received, responding with PONG",{responseBody:Z,responseType:ei.InteractionResponseType.PONG}),new Response(Z,{status:200,headers:{"Content-Type":"application/json"}})}if(W.type===xC.MessageComponent)return this.handleComponentInteraction(W,w),this.respondToInteraction({type:uI1.DeferredUpdateMessage});if(W.type===xC.ApplicationCommand)return this.handleApplicationCommandInteraction(W,w),this.respondToInteraction({type:uI1.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 ei.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,D=Q.guild_id||"@me",Y=Q.message?.id;if(!(f&&Y)){this.logger.warn("Missing channel_id or message_id in interaction");return}let X=Q.channel,H=X?.type===11||X?.type===12,W=H&&X?.parent_id?X.parent_id:f,Z=H?this.encodeThreadId({guildId:D,channelId:W,threadId:f}):this.encodeThreadId({guildId:D,channelId:f}),G=BOQ(B),F={actionId:G.actionId,value:G.value??G.actionId,user:{userId:$.id,userName:$.username,fullName:$.global_name||$.username,isBot:$.bot??!1,isMe:!1},messageId:Y,threadId:Z,adapter:this,raw:Q};this.logger.debug("Processing Discord button action",{actionId:B,messageId:Y,threadId:Z}),this.chat.processAction(F,w)}handleApplicationCommandInteraction(Q,w){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring interaction");return}let B=Q.data?.name;if(!B){this.logger.warn("No command name in application command interaction");return}let $=Q.member?.user||Q.user;if(!$){this.logger.warn("No user in application command interaction");return}let f=Q.channel_id;if(!f){this.logger.warn("Missing channel_id in application command interaction");return}let D=Q.guild_id||"@me",Y=Q.channel,X=Y?.type===11||Y?.type===12,H=X&&Y?.parent_id?Y.parent_id:f,W=X?this.encodeThreadId({guildId:D,channelId:H,threadId:f}):this.encodeThreadId({guildId:D,channelId:f}),{command:Z,text:G}=this.parseSlashCommand(B,Q.data?.options);this.logger.debug("Processing Discord slash command",{command:Z,text:G,userId:$.id,channelId:W}),this.requestContext.run({slashCommand:{channelId:W,interactionToken:Q.token,initialResponseSent:!1}},()=>{this.chat?.processSlashCommand({command:Z,text:G,user:{userId:$.id,userName:$.username,fullName:$.global_name||$.username,isBot:$.bot??!1,isMe:$.id===this.applicationId},adapter:this,raw:Q,channelId:W},w)})}parseSlashCommand(Q,w){let B=[Q.startsWith("/")?Q:`/${Q}`],$=[],f=(D)=>{for(let Y of D){if(Y.value!==void 0){$.push(String(Y.value));continue}if(Y.options&&Y.options.length>0)B.push(Y.name),f(Y.options)}};if(w&&w.length>0)f(w);return{command:B.join(" "),text:$.join(" ").trim()}}async handleGatewayInteraction(Q){if(Q.isChatInputCommand()){await Q.deferReply(),this.handleApplicationCommandInteraction(this.normalizeGatewaySlashCommandInteraction(Q));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,D=$;if(Q.thread)f=Q.thread.id,D=Q.thread.parent_id;else if(Q.channel_type===11||Q.channel_type===12)try{let F=await(await this.discordFetch(`/channels/${$}`,"GET")).json();if(F.parent_id)f=$,D=F.parent_id,this.logger.debug("Fetched thread parent for forwarded message",{threadId:$,parentId:F.parent_id})}catch(G){this.logger.error("Failed to fetch thread parent",{error:String(G),channelId:$})}let Y=Q.is_mention||Q.mentions.some((G)=>G.id===this.applicationId),X=this.mentionRoleIds.length>0&&Q.mention_roles?.some((G)=>this.mentionRoleIds.includes(G)),H=Y||X;if(!f&&H)try{let G=await this.createDiscordThread($,Q.id);f=G.id,this.logger.debug("Created Discord thread for forwarded mention",{channelId:$,messageId:Q.id,threadId:G.id})}catch(G){this.logger.error("Failed to create Discord thread for mention",{error:String(G),messageId:Q.id})}let W=this.encodeThreadId({guildId:B,channelId:D,threadId:f}),Z=new x5({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.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((G)=>({type:this.getAttachmentType(G.content_type),url:G.url,name:G.filename,mimeType:G.content_type,size:G.size})),raw:Q,isMention:H});try{await this.chat.handleIncomingMessage(this,W,Z)}catch(G){this.logger.error("Error handling forwarded message",{error:String(G),messageId:Q.id})}}async handleForwardedReaction(Q,w,B){if(!this.chat)return;let $=Q.guild_id||"@me",f=Q.channel_id,D,Y=f;if(Q.channel_type===H_.GuildPublicThread||Q.channel_type===H_.GuildPrivateThread){let F=this.threadParentCache.get(f);if(F&&F.expiresAt>Date.now())D=f,Y=F.parentId;else try{let b=await(await this.discordFetch(`/channels/${f}`,"GET")).json();if(b.parent_id)D=f,Y=b.parent_id,this.threadParentCache.set(f,{parentId:b.parent_id,expiresAt:Date.now()+A.THREAD_PARENT_CACHE_TTL})}catch(V){this.logger.error("Failed to fetch thread parent for reaction",{error:String(V),channelId:f})}}let X=this.encodeThreadId({guildId:$,channelId:Y,threadId:D}),H=Q.emoji.name||"unknown",W=this.normalizeDiscordEmoji(H),Z=Q.user??Q.member?.user;if(!Z){this.logger.warn("Reaction event missing user info",{data:Q});return}let G={adapter:this,threadId:X,messageId:Q.message_id,emoji:W,rawEmoji:Q.emoji.id?`<:${H}:${Q.emoji.id}>`:H,added:w,user:{userId:Z.id,userName:Z.username,fullName:Z.username,isBot:Z.bot===!0,isMe:Z.id===this.applicationId},raw:Q};this.chat.processReaction(G)}async postMessage(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=Q;if($)B=$;let D={},Y=[],X=[],H=G50(w);if(H){let V=rE0(H);Y.push(...V.embeds),X.push(...V.components)}else D.content=this.truncateContent(f_(this.formatConverter.renderPostable(w),"discord"));if(Y.length>0)D.embeds=Y;if(X.length>0)D.components=X;let W=PE0(w),Z=this.tryPostSlashResponse(f,D,W);if(Z)return Z;if(W.length>0)return this.postMessageWithFiles(B,f,D,W);this.logger.debug("Discord API: POST message",{channelId:B,contentLength:D.content?.length||0,embedCount:Y.length,componentCount:X.length});let F=await(await this.discordFetch(`/channels/${B}/messages`,"POST",D)).json();return this.logger.debug("Discord API: POST message response",{messageId:F.id}),{id:F.id,threadId:f,raw:F}}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 D=f?`/webhooks/${this.applicationId}/${Q.interactionToken}/messages/@original`:`/webhooks/${this.applicationId}/${Q.interactionToken}?wait=true`,Y=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(D,Y,B,$):await this.discordInteractionFetch(D,Y,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 PC&&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<=cI1)return Q;return`${Q.slice(0,cI1-3)}...`}async postMessageWithFiles(Q,w,B,$){let f=new FormData;f.append("payload_json",JSON.stringify(B));for(let X=0;X<$.length;X++){let H=$[X];if(!H)continue;let W=await kE0(H.data,{platform:"discord"});if(!W)continue;let Z=new Blob([new Uint8Array(W)],{type:H.mimeType||"application/octet-stream"});f.append(`files[${X}]`,Z,H.filename)}let D=await fetch(`${z50}/channels/${Q}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.botToken}`},body:f});if(!D.ok){let X=await D.text();throw new PC("discord",`Failed to post message: ${D.status} ${X}`)}let Y=await D.json();return{id:Y.id,threadId:w,raw:Y}}async discordInteractionFetch(Q,w,B){let $=await fetch(`${z50}${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 PC("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 Y=0;Y<$.length;Y++){let X=$[Y];if(!X)continue;let H=await kE0(X.data,{platform:"discord"});if(!H)continue;let W=new Blob([new Uint8Array(H)],{type:X.mimeType||"application/octet-stream"});f.append(`files[${Y}]`,W,X.filename)}let D=await fetch(`${z50}${Q}`,{method:w,body:f});if(!D.ok){let Y=await D.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:D.status,error:Y}),new PC("discord",`Discord interaction API error: ${D.status} ${Y}`)}return D}async editMessage(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),D=f||$,Y={},X=[],H=[],W=G50(B);if(W){let F=rE0(W);X.push(...F.embeds),H.push(...F.components),Y.content=""}else Y.content=this.truncateContent(f_(this.formatConverter.renderPostable(B),"discord"));if(X.length>0)Y.embeds=X;if(H.length>0)Y.components=H;this.logger.debug("Discord API: PATCH message",{channelId:D,messageId:w,contentLength:Y.content?.length||0});let G=await(await this.discordFetch(`/channels/${D}/messages/${w}`,"PATCH",Y)).json();return this.logger.debug("Discord API: PATCH message response",{messageId:G.id}),{id:G.id,threadId:Q,raw:G}}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),D=f||$,Y=this.encodeEmoji(B);this.logger.debug("Discord API: PUT reaction",{channelId:D,messageId:w,emoji:Y}),await this.discordFetch(`/channels/${D}/messages/${w}/reactions/${Y}/@me`,"PUT"),this.logger.debug("Discord API: PUT reaction response",{ok:!0})}async removeReaction(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),D=f||$,Y=this.encodeEmoji(B);this.logger.debug("Discord API: DELETE reaction",{channelId:D,messageId:w,emoji:Y}),await this.discordFetch(`/channels/${D}/messages/${w}/reactions/${Y}/@me`,"DELETE"),this.logger.debug("Discord API: DELETE reaction response",{ok:!0})}encodeEmoji(Q){let w=ri.toDiscord?ri.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,D=w.limit||50,Y=w.direction??"backward",X=new URLSearchParams;if(X.set("limit",String(D)),w.cursor)if(Y==="backward")X.set("before",w.cursor);else X.set("after",w.cursor);this.logger.debug("Discord API: GET messages",{channelId:f,limit:D,direction:Y,cursor:w.cursor});let W=await(await this.discordFetch(`/channels/${f}/messages?${X.toString()}`,"GET")).json();this.logger.debug("Discord API: GET messages response",{messageCount:W.length});let G=[...W].reverse().map((V)=>this.parseDiscordMessage(V,Q)),F;if(W.length===D)if(Y==="backward")F=W.at(-1)?.id;else F=W[0]?.id;return{messages:G,nextCursor:F}}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===H_.DM||f.type===H_.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 rH("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===Sz1.ThreadStarterMessage&&Q.referenced_message?Q.referenced_message:Q,$=B.author,f=$.bot??!1,D=$.id===this.botUserId;return new x5({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:D},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((Y)=>({type:this.getAttachmentType(Y.content_type),url:Y.url,name:Y.filename,mimeType:Y.content_type,size:Y.size,width:Y.width??void 0,height:Y.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"}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 D=await fetch($,{method:w,headers:f,body:B?JSON.stringify(B):void 0});if(!D.ok){let Y=await D.text();throw this.logger.error("Discord API error",{path:Q,method:w,status:D.status,error:Y}),new PC("discord",`Discord API error: ${D.status} ${Y}`)}return D}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 S9.Client({intents:[S9.GatewayIntentBits.Guilds,S9.GatewayIntentBits.GuildMessages,S9.GatewayIntentBits.MessageContent,S9.GatewayIntentBits.DirectMessages,S9.GatewayIntentBits.GuildMessageReactions,S9.GatewayIntentBits.DirectMessageReactions],partials:[S9.Partials.Channel]}),f=!1;if(B)$.on("raw",async(D)=>{if(f)return;if(!D.t)return;this.logger.info("Discord Gateway forwarding event",{type:D.t}),await this.forwardGatewayEvent(B,{type:`GATEWAY_${D.t}`,timestamp:Date.now(),data:D.d})});else this.setupLegacyGatewayHandlers($,()=>f);$.on(S9.Events.ClientReady,()=>{this.logger.info("Discord Gateway connected",{username:$.user?.username,id:$.user?.id})}),$.on(S9.Events.Error,(D)=>{this.logger.error("Discord Gateway error",{error:String(D)})});try{await $.login(this.botToken),await new Promise((D)=>{let Y=setTimeout(D,Q);if(w){if(w.aborted){clearTimeout(Y),D();return}w.addEventListener("abort",()=>{this.logger.info("Discord Gateway listener received abort signal (new listener started)"),clearTimeout(Y),D()},{once:!0})}}),this.logger.info("Discord Gateway listener duration elapsed, disconnecting")}catch(D){this.logger.error("Discord Gateway listener error",{error:String(D)})}finally{f=!0,$.destroy(),this.logger.info("Discord Gateway listener stopped")}}setupLegacyGatewayHandlers(Q,w){Q.on(S9.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((Y)=>this.mentionRoleIds.includes(Y.id)),D=$||f;this.logger.info("Discord Gateway message received",{channelId:B.channelId,guildId:B.guildId,authorId:B.author.id,isMentioned:D,isUserMentioned:$,isRoleMentioned:f,content:B.content.slice(0,100)}),await this.handleGatewayMessage(B,D)}),Q.on(S9.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(S9.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(S9.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(),D,Y=$;if(f&&"parentId"in Q.channel&&Q.channel.parentId)D=$,Y=Q.channel.parentId;if(!D&&w)try{let W=await this.createDiscordThread($,Q.id);D=W.id,this.logger.debug("Created Discord thread for incoming mention",{channelId:$,messageId:Q.id,threadId:W.id})}catch(W){this.logger.error("Failed to create Discord thread for mention",{error:String(W),messageId:Q.id})}let X=this.encodeThreadId({guildId:B,channelId:Y,threadId:D}),H=new x5({id:Q.id,threadId:X,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((W)=>({type:this.getAttachmentType(W.contentType),url:W.url,name:W.name,mimeType:W.contentType??void 0,size:W.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,X,H)}catch(W){this.logger.error("Error handling Gateway message",{error:String(W),messageId:Q.id})}}async handleGatewayReaction(Q,w,B){if(!this.chat)return;let $=Q.message.guildId||"@me",f=Q.message.channelId,D=Q.message.channel?.isThread?.(),Y=f,X;if(D&&Q.message.channel?.parentId)X=f,Y=Q.message.channel.parentId;let H=this.encodeThreadId({guildId:$,channelId:Y,threadId:X}),W=Q.emoji.name||"unknown",Z=this.normalizeDiscordEmoji(W),G={adapter:this,threadId:H,messageId:Q.message.id,emoji:Z,rawEmoji:Q.emoji.id?`<:${W}:${Q.emoji.id}>`:W,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(G)}channelIdFromThreadId(Q){return Q.split(":").slice(0,3).join(":")}async fetchChannelMessages(Q,w={}){let $=Q.split(":")[2];if(!$)throw new rH("discord",`Invalid Discord channel ID: ${Q}`);let f=w.limit||50,D=w.direction??"backward",Y=new URLSearchParams;if(Y.set("limit",String(f)),w.cursor)if(D==="backward")Y.set("before",w.cursor);else Y.set("after",w.cursor);this.logger.debug("Discord API: GET channel messages",{channelId:$,limit:f,direction:D,cursor:w.cursor});let H=await(await this.discordFetch(`/channels/${$}/messages?${Y.toString()}`,"GET")).json();this.logger.debug("Discord API: GET channel messages response",{messageCount:H.length});let Z=[...H].reverse().map((F)=>this.parseDiscordMessage(F,Q)),G;if(H.length===f)if(D==="backward")G=H.at(-1)?.id;else G=H[0]?.id;return{messages:Z,nextCursor:G}}async listThreads(Q,w={}){let B=Q.split(":"),$=B[1],f=B[2];if(!($&&f))throw new rH("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET threads",{guildId:$,channelId:f});let X=((await(await this.discordFetch(`/guilds/${$}/threads/active`,"GET")).json()).threads||[]).filter((L)=>L.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 W=[...X,...H],Z=new Set,G=W.filter((L)=>{if(Z.has(L.id))return!1;return Z.add(L.id),!0}),F=w.limit||50,V=G.slice(0,F),b=[];for(let L of V){let N=this.encodeThreadId({guildId:$,channelId:f,threadId:L.id});try{let g=(await(await this.discordFetch(`/channels/${L.id}/messages?limit=1&after=0`,"GET")).json())[0];if(g)b.push({id:N,rootMessage:this.parseDiscordMessage(g,N),replyCount:L.total_message_sent??L.message_count,lastReplyAt:L.thread_metadata?.archive_timestamp?new Date(L.thread_metadata.archive_timestamp):void 0})}catch{b.push({id:N,rootMessage:new x5({id:L.id,threadId:N,text:L.name,formatted:this.formatConverter.toAst(L.name),raw:L,author:{userId:"unknown",userName:"unknown",fullName:"unknown",isBot:!1,isMe:!1},metadata:{dateSent:new Date,edited:!1},attachments:[]}),replyCount:L.total_message_sent??L.message_count})}}return this.logger.debug("Discord API: listThreads result",{threadCount:b.length}),{threads:b,nextCursor:G.length>F?String(F):void 0}}async fetchChannelInfo(Q){let B=Q.split(":")[2];if(!B)throw new rH("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===H_.DM||f.type===H_.GroupDM,memberCount:f.member_count,metadata:{channelType:f.type,raw:f}}}async postChannelMessage(Q,w){let $=Q.split(":")[2];if(!$)throw new rH("discord",`Invalid Discord channel ID: ${Q}`);let f={},D=[],Y=[],X=G50(w);if(X){let F=rE0(X);D.push(...F.embeds),Y.push(...F.components)}else f.content=this.truncateContent(f_(this.formatConverter.renderPostable(w),"discord"));if(D.length>0)f.embeds=D;if(Y.length>0)f.components=Y;let H=PE0(w),W=this.tryPostSlashResponse(Q,f,H);if(W)return W;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 G=await(await this.discordFetch(`/channels/${$}/messages`,"POST",f)).json();return{id:G.id,threadId:Q,raw:G}}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 mJ(B)}};function iI1(A){return new GOQ(A??{})}var zOQ=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:qOQ(),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 qOQ(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function q50(A){return new zOQ}Z0();var FOQ=K.object({subscribedAt:K.string().datetime(),routingMode:K.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:K.boolean().optional()}),VOQ="chat.discord.subscriptions";function oE0(A){return A.scoped({namespace:VOQ,schema:FOQ})}function dI1(A,Q=q50()){let w=oE0(A);return new nI1(Q,w)}class nI1{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 rI1(A){let{discord:Q}=A;if(!Q)return new ME0({userName:A.userName,adapters:{},state:q50()});let w=iI1({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds});return A.gatewayLoop.setAdapter(w),new ME0({userName:A.userName,adapters:{discord:w},concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"},state:dI1(A.runtimeState)})}class sE0{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}}}c0();class aE0{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 D=this.deps.getUploadStore();if(!D)return $;for(let Y of w.attachments){let X=Y.name;if(!X)continue;let H=Zq(X,"upload"),W=dV(H,Y.mimeType),Z=Y.size??0,G=H00(H,W);if(!G){$.notices.push(`Unsupported file upload type: ${H}`);continue}if(!W00(G,Z)){$.notices.push(`File upload too large: ${H}`);continue}try{let F=await this.readAttachmentData(Y);if(!F)continue;let V=Kq({filename:H,mediaType:W,content:F,fallbackFilename:"upload"});if(!V.ok){$.notices.push(V.message);continue}let b=await D.save({filename:V.filename,mediaType:V.mediaType,content:F,metadata:this.buildMetadata(A,Q,w)});$.attachments.push(sI1(b.filename,b.mediaType,F,b.ref,V.kind==="text"))}catch(F){this.deps.logger.error("Failed to read chat attachment",{error:F,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 oI1(A,Q,w,B){return sI1(A,Q,w,B,nV(A,Q))}function sI1(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 Ad(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}var aI1={name:"@brains/chat",private:!0,version:"0.2.0-alpha.134",description:"Discord Chat SDK interface for Brains",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",test:"bun test"},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":"latest"}};var JOQ=/https?:\/\/\S+/i,bOQ=/[\s\S]+/,LOQ="https://discord.com/api/v10",NOQ=K.object({type:K.literal("card"),children:K.array(K.object({type:K.string()}).passthrough()),imageUrl:K.string().optional(),subtitle:K.string().optional(),title:K.string().optional()}).passthrough(),jOQ=K.object({card:K.custom((A)=>NOQ.safeParse(A).success),fallbackText:K.string().optional()});class F50 extends AZ{threadRegistry=new w50;pendingApprovals;uploadContinuity;promptActions=new Map;toolStatusMessenger=new wy0(this.threadRegistry);cardBuilder=new Dy0({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new Xy0({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new Hy0({cardBuilder:this.cardBuilder,clearMessageComponents:(A,Q)=>this.clearDiscordMessageComponents(A,Q)});subscriptionRouter=new sE0({getSubscriptions:()=>this.discordSubscriptions,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:(A,Q)=>this.isBotCreatedDiscordThread(A,Q),logger:this.logger});chatInputBuilder=new aE0({getUploadStore:()=>this.context?.uploads.scoped(Ad()),getThreadIdParts:(A)=>this.getThreadIdParts(A),logger:this.logger});gatewayLoop;discordApp;discordSubscriptions;constructor(A={}){super("chat",aI1,A,Qy0);this.gatewayLoop=new Wy0({getApp:()=>this.discordApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.discordApp=new Zy0({discord:this.config.adapters.discord,getUploadStore:()=>this.context?.uploads.scoped(Ad()),buildApp:(Q)=>rI1({userName:this.config.userName,discord:this.config.adapters.discord,gatewayLoop:this.gatewayLoop,runtimeState:Q})}),this.pendingApprovals=new OS({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 yS({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(Ad());if(!w)throw Error("Chat upload store unavailable");let B=await w.read(Q);return oI1(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=oE0(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 ci(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 ci(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=jOQ.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 fy0(A)}formatCompletionOutput(A){return fy0(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 hH1(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($&&this.shouldRouteDiscordMessage(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(bOQ,async(Q,w,B)=>{await this.handleRoutedMessage(Q,w,B)});A.onNewMessage(JOQ,async(Q,w)=>{await this.handlePassiveUrlCapture(Q,w)}),A.onAction([B50,By0],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction($y0,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(!this.shouldHandleDiscordAction(w,Q))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}let $=this.getThreadIdParts(w.id),f=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:$.channelId??w.channelId,isBot:Boolean(A.user.isBot)}),D=this.getConversationId(Q,w.id),Y=w.id;await this.runAgentTurn({thread:w,channelId:Y,logLabel:"Error handling chat prompt action",body:async()=>{if(!this.context)return;let X=await this.context.agent.chat(B.prompt,D,{userPermissionLevel:f,interfaceType:Q,channelId:Y,channelName:w.isDM?"DM":w.channelId,...this.buildActionEventMetadata(Q,w,A)});await this.renderAgentResponse({thread:w,channelId:Y,conversationId:D,response:X,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(!this.shouldHandleDiscordAction($,Q))return;let f=this.getThreadIdParts($.id),D=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===B50,userPermissionLevel:D,metadata:this.buildActionEventMetadata(Q,$,A)})}shouldHandleDiscordAction(A,Q){if(Q!=="discord")return!0;let w=this.config.adapters.discord;if(!w)return!1;if(A.isDM&&!w.allowDMs)return!1;return this.isAllowedChannel(A,w)}isBotCreatedDiscordThread(A,Q){if(A.isDM)return!1;let w=this.getThreadIdParts(A.id);if(!w.threadId)return!1;let B=this.getRawDiscordChannelId(Q);return B!==void 0&&B!==w.threadId}getRawDiscordChannelId(A){let Q=A.raw;if(typeof Q!=="object"||Q===null)return;let w=Q.channel_id;return typeof w==="string"?w:void 0}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(!this.shouldRouteDiscordMessage(A,Q,$))return;await this.routeToAgent(B,A,Q,w)}shouldRouteDiscordMessage(A,Q,w){if(A.isDM&&!w.allowDMs)return!1;if(Q.author.isMe)return!1;if(Q.author.isBot&&!Q.isMention)return!1;if(!this.isAllowedChannel(A,w))return!1;return!0}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 D of ci(Q,f))await A.post(D)}async routeToAgent(A,Q,w,B){if(!this.context)return;this.threadRegistry.set(Q);let $=this.getConversationId(A,Q.id),f=Q.id,D=this.getPermissionContext(Q,w),Y=this.context.permissions.getUserLevel(A,w.author.userId,D),X=await this.chatInputBuilder.build(A,Q,w,Y),H=[...X.attachments];if(await this.attachPriorUploads($,X,Y),await this.postUploadNotices(Q,X.notices),!X.message&&X.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 W=await this.getPendingApprovalIds($);if(W.size>0){await this.handleConfirmationResponse(X.message,$,Q,W,Y,this.buildUserMessageMetadata(A,Q,w));return}let Z=this.buildCoalescedAgentInput(X.message,B),G=await this.context.agent.chat(Z.message,$,{userPermissionLevel:Y,interfaceType:A,channelId:f,channelName:this.getChannelName(Q),...this.buildUserMessageMetadata(A,Q,w,Z.metadata),...X.attachments.length>0?{attachments:X.attachments}:{}});await this.renderAgentResponse({thread:Q,channelId:f,conversationId:$,response:G,userPermissionLevel:Y})}})}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);if(A.confirmation)await this.approvalCards.resolve(A.conversationId,A.confirmation.approvalId,A.confirmation.confirmed);let w=A.confirmation?this.formatConfirmationResponsePayload(A.response,A.confirmation.confirmed,this.getRemainingApprovalHelp(A.conversationId,A.response),Q.deniedCardIds):this.formatAgentResponseText(A.response.text,A.response.cards,A.response.pendingConfirmations,Q.deniedCardIds),B=await this.sendAgentResponseWithFiles({thread:A.thread,channelId:A.channelId,message:w,files:Q.files}),$=await this.sendArtifactCards(A.thread,A.response.cards,Q.deniedCardIds);await this.sendSupplementalCards(A.thread,A.response.cards,A.response.pendingConfirmations),await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,A.response.pendingConfirmations);let f=$??B;if(f)for(let D of B00(A.response))this.trackAgentResponseForJob(D,f,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){let D=ie({message:A,approvalIds:B});if(D.kind==="not-confirmation"){this.pendingApprovals.deleteConversation(Q),await w.post(this.formatNoticePayload("No pending approval to resolve."));return}if(D.kind==="notice"){await w.post(this.formatNoticePayload(D.message));return}await this.confirmApproval({thread:w,conversationId:Q,approvalId:D.approvalId,confirmed:D.confirmed,userPermissionLevel:$,...f?{metadata:f}:{}})}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:A.thread.isDM?"DM":A.thread.channelId,...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,w,B){return ee({text:A,cards:Q,pendingConfirmations:w,deniedCardIds:B,formatCard:($)=>this.cardBuilder.formatStructuredCard($,B)}).join(`
2347
2347
 
2348
2348
  `)}formatConfirmationResponsePayload(A,Q,w,B){let $=A00({response:A,confirmed:Q,remainingApprovalHelp:w,deniedCardIds:B,formatCard:(f)=>this.cardBuilder.formatStructuredCard(f,B),formatPendingConfirmationHelp:Bx});return{card:{type:"card",title:te($.variant),children:$.parts.map((f)=>({type:"text",content:f}))},fallbackText:$.parts.join(`
2349
2349
 
@@ -2415,7 +2415,7 @@ ${ZE0(A)}
2415
2415
  <p>Once built, this page will be replaced with your actual website.</p>
2416
2416
  </div>
2417
2417
  </body>
2418
- </html>`;var xJ1={name:"@brains/webserver",private:!0,version:"0.2.0-alpha.133",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts"},dependencies:{"@brains/plugins":"workspace:*","@hono/bun-compress":"^0.1.0",hono:"^4.7.10"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/messaging-service":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14","@types/node":"^20.0.0",eslint:"^8.56.0",typescript:"^5.3.3"}};class uJ extends GU{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",xJ1,A,Kg0)}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 O50({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&&!RJ1(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(hJ1(this.config.previewDistDir,"index.html"),Ug0),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!RJ1(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(hJ1(this.config.productionDistDir,"index.html"),Ug0),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}CB();c0();Z0();var Yb1="vercel.ai.error",UxQ=Symbol.for(Yb1),vJ1,CJ1,mw=class A extends(CJ1=Error,vJ1=UxQ,CJ1){constructor({name:Q,message:w,cause:B}){super(w);this[vJ1]=!0,this.name=Q,this.cause=B}static isInstance(Q){return A.hasMarker(Q,Yb1)}static hasMarker(Q,w){let B=Symbol.for(w);return Q!=null&&typeof Q==="object"&&B in Q&&typeof Q[B]==="boolean"&&Q[B]===!0}},Xb1="AI_APICallError",Hb1=`vercel.ai.error.${Xb1}`,GxQ=Symbol.for(Hb1),yJ1,EJ1,OG8=class extends(EJ1=mw,yJ1=GxQ,EJ1){constructor({message:A,url:Q,requestBodyValues:w,statusCode:B,responseHeaders:$,responseBody:f,cause:D,isRetryable:Y=B!=null&&(B===408||B===409||B===429||B>=500),data:X}){super({name:Xb1,message:A,cause:D});this[yJ1]=!0,this.url=Q,this.requestBodyValues=w,this.statusCode=B,this.responseHeaders=$,this.responseBody=f,this.isRetryable=Y,this.data=X}static isInstance(A){return mw.hasMarker(A,Hb1)}},Wb1="AI_EmptyResponseBodyError",Zb1=`vercel.ai.error.${Wb1}`,zxQ=Symbol.for(Zb1),gJ1,TJ1,xG8=class extends(TJ1=mw,gJ1=zxQ,TJ1){constructor({message:A="Empty response body"}={}){super({name:Wb1,message:A});this[gJ1]=!0}static isInstance(A){return mw.hasMarker(A,Zb1)}};function Kb1(A){if(A==null)return"unknown error";if(typeof A==="string")return A;if(A instanceof Error)return A.message;return JSON.stringify(A)}var Ub1="AI_InvalidArgumentError",Gb1=`vercel.ai.error.${Ub1}`,qxQ=Symbol.for(Gb1),SJ1,mJ1,zb1=class extends(mJ1=mw,SJ1=qxQ,mJ1){constructor({message:A,cause:Q,argument:w}){super({name:Ub1,message:A,cause:Q});this[SJ1]=!0,this.argument=w}static isInstance(A){return mw.hasMarker(A,Gb1)}},qb1="AI_InvalidPromptError",Fb1=`vercel.ai.error.${qb1}`,FxQ=Symbol.for(Fb1),uJ1,cJ1,RG8=class extends(cJ1=mw,uJ1=FxQ,cJ1){constructor({prompt:A,message:Q,cause:w}){super({name:qb1,message:`Invalid prompt: ${Q}`,cause:w});this[uJ1]=!0,this.prompt=A}static isInstance(A){return mw.hasMarker(A,Fb1)}},Vb1="AI_InvalidResponseDataError",Ib1=`vercel.ai.error.${Vb1}`,VxQ=Symbol.for(Ib1),lJ1,pJ1,hG8=class extends(pJ1=mw,lJ1=VxQ,pJ1){constructor({data:A,message:Q=`Invalid response data: ${JSON.stringify(A)}.`}){super({name:Vb1,message:Q});this[lJ1]=!0,this.data=A}static isInstance(A){return mw.hasMarker(A,Ib1)}},Jb1="AI_JSONParseError",bb1=`vercel.ai.error.${Jb1}`,IxQ=Symbol.for(bb1),iJ1,dJ1,Gg0=class extends(dJ1=mw,iJ1=IxQ,dJ1){constructor({text:A,cause:Q}){super({name:Jb1,message:`JSON parsing failed: Text: ${A}.
2418
+ </html>`;var xJ1={name:"@brains/webserver",private:!0,version:"0.2.0-alpha.134",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts"},dependencies:{"@brains/plugins":"workspace:*","@hono/bun-compress":"^0.1.0",hono:"^4.7.10"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/messaging-service":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14","@types/node":"^20.0.0",eslint:"^8.56.0",typescript:"^5.3.3"}};class uJ extends GU{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",xJ1,A,Kg0)}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 O50({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&&!RJ1(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(hJ1(this.config.previewDistDir,"index.html"),Ug0),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!RJ1(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(hJ1(this.config.productionDistDir,"index.html"),Ug0),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}CB();c0();Z0();var Yb1="vercel.ai.error",UxQ=Symbol.for(Yb1),vJ1,CJ1,mw=class A extends(CJ1=Error,vJ1=UxQ,CJ1){constructor({name:Q,message:w,cause:B}){super(w);this[vJ1]=!0,this.name=Q,this.cause=B}static isInstance(Q){return A.hasMarker(Q,Yb1)}static hasMarker(Q,w){let B=Symbol.for(w);return Q!=null&&typeof Q==="object"&&B in Q&&typeof Q[B]==="boolean"&&Q[B]===!0}},Xb1="AI_APICallError",Hb1=`vercel.ai.error.${Xb1}`,GxQ=Symbol.for(Hb1),yJ1,EJ1,OG8=class extends(EJ1=mw,yJ1=GxQ,EJ1){constructor({message:A,url:Q,requestBodyValues:w,statusCode:B,responseHeaders:$,responseBody:f,cause:D,isRetryable:Y=B!=null&&(B===408||B===409||B===429||B>=500),data:X}){super({name:Xb1,message:A,cause:D});this[yJ1]=!0,this.url=Q,this.requestBodyValues=w,this.statusCode=B,this.responseHeaders=$,this.responseBody=f,this.isRetryable=Y,this.data=X}static isInstance(A){return mw.hasMarker(A,Hb1)}},Wb1="AI_EmptyResponseBodyError",Zb1=`vercel.ai.error.${Wb1}`,zxQ=Symbol.for(Zb1),gJ1,TJ1,xG8=class extends(TJ1=mw,gJ1=zxQ,TJ1){constructor({message:A="Empty response body"}={}){super({name:Wb1,message:A});this[gJ1]=!0}static isInstance(A){return mw.hasMarker(A,Zb1)}};function Kb1(A){if(A==null)return"unknown error";if(typeof A==="string")return A;if(A instanceof Error)return A.message;return JSON.stringify(A)}var Ub1="AI_InvalidArgumentError",Gb1=`vercel.ai.error.${Ub1}`,qxQ=Symbol.for(Gb1),SJ1,mJ1,zb1=class extends(mJ1=mw,SJ1=qxQ,mJ1){constructor({message:A,cause:Q,argument:w}){super({name:Ub1,message:A,cause:Q});this[SJ1]=!0,this.argument=w}static isInstance(A){return mw.hasMarker(A,Gb1)}},qb1="AI_InvalidPromptError",Fb1=`vercel.ai.error.${qb1}`,FxQ=Symbol.for(Fb1),uJ1,cJ1,RG8=class extends(cJ1=mw,uJ1=FxQ,cJ1){constructor({prompt:A,message:Q,cause:w}){super({name:qb1,message:`Invalid prompt: ${Q}`,cause:w});this[uJ1]=!0,this.prompt=A}static isInstance(A){return mw.hasMarker(A,Fb1)}},Vb1="AI_InvalidResponseDataError",Ib1=`vercel.ai.error.${Vb1}`,VxQ=Symbol.for(Ib1),lJ1,pJ1,hG8=class extends(pJ1=mw,lJ1=VxQ,pJ1){constructor({data:A,message:Q=`Invalid response data: ${JSON.stringify(A)}.`}){super({name:Vb1,message:Q});this[lJ1]=!0,this.data=A}static isInstance(A){return mw.hasMarker(A,Ib1)}},Jb1="AI_JSONParseError",bb1=`vercel.ai.error.${Jb1}`,IxQ=Symbol.for(bb1),iJ1,dJ1,Gg0=class extends(dJ1=mw,iJ1=IxQ,dJ1){constructor({text:A,cause:Q}){super({name:Jb1,message:`JSON parsing failed: Text: ${A}.
2419
2419
  Error message: ${Kb1(Q)}`,cause:Q});this[iJ1]=!0,this.text=A}static isInstance(A){return mw.hasMarker(A,bb1)}},Lb1="AI_LoadAPIKeyError",Nb1=`vercel.ai.error.${Lb1}`,JxQ=Symbol.for(Nb1),nJ1,rJ1,vG8=class extends(rJ1=mw,nJ1=JxQ,rJ1){constructor({message:A}){super({name:Lb1,message:A});this[nJ1]=!0}static isInstance(A){return mw.hasMarker(A,Nb1)}},jb1="AI_LoadSettingError",Mb1=`vercel.ai.error.${jb1}`,bxQ=Symbol.for(Mb1),oJ1,sJ1,CG8=class extends(sJ1=mw,oJ1=bxQ,sJ1){constructor({message:A}){super({name:jb1,message:A});this[oJ1]=!0}static isInstance(A){return mw.hasMarker(A,Mb1)}},_b1="AI_NoContentGeneratedError",Pb1=`vercel.ai.error.${_b1}`,LxQ=Symbol.for(Pb1),aJ1,tJ1,yG8=class extends(tJ1=mw,aJ1=LxQ,tJ1){constructor({message:A="No content generated."}={}){super({name:_b1,message:A});this[aJ1]=!0}static isInstance(A){return mw.hasMarker(A,Pb1)}},kb1="AI_NoSuchModelError",Ob1=`vercel.ai.error.${kb1}`,NxQ=Symbol.for(Ob1),eJ1,Ab1,EG8=class extends(Ab1=mw,eJ1=NxQ,Ab1){constructor({errorName:A=kb1,modelId:Q,modelType:w,message:B=`No such ${w}: ${Q}`}){super({name:A,message:B});this[eJ1]=!0,this.modelId=Q,this.modelType=w}static isInstance(A){return mw.hasMarker(A,Ob1)}},xb1="AI_TooManyEmbeddingValuesForCallError",Rb1=`vercel.ai.error.${xb1}`,jxQ=Symbol.for(Rb1),Qb1,wb1,gG8=class extends(wb1=mw,Qb1=jxQ,wb1){constructor(A){super({name:xb1,message:`Too many values for a single embedding call. The ${A.provider} model "${A.modelId}" can only embed up to ${A.maxEmbeddingsPerCall} values per call, but ${A.values.length} values were provided.`});this[Qb1]=!0,this.provider=A.provider,this.modelId=A.modelId,this.maxEmbeddingsPerCall=A.maxEmbeddingsPerCall,this.values=A.values}static isInstance(A){return mw.hasMarker(A,Rb1)}},hb1="AI_TypeValidationError",vb1=`vercel.ai.error.${hb1}`,MxQ=Symbol.for(vb1),Bb1,$b1,FG=class A extends($b1=mw,Bb1=MxQ,$b1){constructor({value:Q,cause:w,context:B}){let $="Type validation failed";if(B==null?void 0:B.field)$+=` for ${B.field}`;if((B==null?void 0:B.entityName)||(B==null?void 0:B.entityId)){$+=" (";let f=[];if(B.entityName)f.push(B.entityName);if(B.entityId)f.push(`id: "${B.entityId}"`);$+=f.join(", "),$+=")"}super({name:hb1,message:`${$}: Value: ${JSON.stringify(Q)}.
2420
2420
  Error message: ${Kb1(w)}`,cause:w});this[Bb1]=!0,this.value=Q,this.context=B}static isInstance(Q){return mw.hasMarker(Q,vb1)}static wrap({value:Q,cause:w,context:B}){var $,f,D;if(A.isInstance(w)&&w.value===Q&&(($=w.context)==null?void 0:$.field)===(B==null?void 0:B.field)&&((f=w.context)==null?void 0:f.entityName)===(B==null?void 0:B.entityName)&&((D=w.context)==null?void 0:D.entityId)===(B==null?void 0:B.entityId))return w;return new A({value:Q,cause:w,context:B})}},Cb1="AI_UnsupportedFunctionalityError",yb1=`vercel.ai.error.${Cb1}`,_xQ=Symbol.for(yb1),fb1,Db1,TG8=class extends(Db1=mw,fb1=_xQ,Db1){constructor({functionality:A,message:Q=`'${A}' functionality not supported.`}){super({name:Cb1,message:Q});this[fb1]=!0,this.functionality=A}static isInstance(A){return mw.hasMarker(A,yb1)}};F1();JU();JU();JU();var ub1="AI_DownloadError",cb1=`vercel.ai.error.${ub1}`,PxQ=Symbol.for(cb1),Eb1,gb1,oH=class extends(gb1=mw,Eb1=PxQ,gb1){constructor({url:A,statusCode:Q,statusText:w,cause:B,message:$=B==null?`Failed to download ${A}: ${Q} ${w}`:`Failed to download ${A}: ${B}`}){super({name:ub1,message:$,cause:B});this[Eb1]=!0,this.url=A,this.statusCode=Q,this.statusText=w}static isInstance(A){return mw.hasMarker(A,cb1)}},Jg0=2147483648;async function lb1({response:A,url:Q,maxBytes:w=Jg0}){let B=A.headers.get("content-length");if(B!=null){let W=parseInt(B,10);if(!isNaN(W)&&W>w)throw new oH({url:Q,message:`Download of ${Q} exceeded maximum size of ${w} bytes (Content-Length: ${W}).`})}let $=A.body;if($==null)return new Uint8Array(0);let f=$.getReader(),D=[],Y=0;try{while(!0){let{done:W,value:Z}=await f.read();if(W)break;if(Y+=Z.length,Y>w)throw new oH({url:Q,message:`Download of ${Q} exceeded maximum size of ${w} bytes.`});D.push(Z)}}finally{try{await f.cancel()}finally{f.releaseLock()}}let X=new Uint8Array(Y),H=0;for(let W of D)X.set(W,H),H+=W.length;return X}function bg0(A){let Q;try{Q=new URL(A)}catch(B){throw new oH({url:A,message:`Invalid URL: ${A}`})}if(Q.protocol==="data:")return;if(Q.protocol!=="http:"&&Q.protocol!=="https:")throw new oH({url:A,message:`URL scheme must be http, https, or data, got ${Q.protocol}`});let w=Q.hostname;if(!w)throw new oH({url:A,message:"URL must have a hostname"});if(w==="localhost"||w.endsWith(".local")||w.endsWith(".localhost"))throw new oH({url:A,message:`URL with hostname ${w} is not allowed`});if(w.startsWith("[")&&w.endsWith("]")){let B=w.slice(1,-1);if(kxQ(B))throw new oH({url:A,message:`URL with IPv6 address ${w} is not allowed`});return}if(pb1(w)){if(Fg0(w))throw new oH({url:A,message:`URL with IP address ${w} is not allowed`});return}}function pb1(A){let Q=A.split(".");if(Q.length!==4)return!1;return Q.every((w)=>{let B=Number(w);return Number.isInteger(B)&&B>=0&&B<=255&&String(B)===w})}function Fg0(A){let Q=A.split(".").map(Number),[w,B]=Q;if(w===0)return!0;if(w===10)return!0;if(w===127)return!0;if(w===169&&B===254)return!0;if(w===172&&B>=16&&B<=31)return!0;if(w===192&&B===168)return!0;return!1}function kxQ(A){let Q=A.toLowerCase();if(Q==="::1")return!0;if(Q==="::")return!0;if(Q.startsWith("::ffff:")){let w=Q.slice(7);if(pb1(w))return Fg0(w);let B=w.split(":");if(B.length===2){let $=parseInt(B[0],16),f=parseInt(B[1],16);if(!isNaN($)&&!isNaN(f)){let D=$>>8&255,Y=$&255,X=f>>8&255,H=f&255;return Fg0(`${D}.${Y}.${X}.${H}`)}}}if(Q.startsWith("fc")||Q.startsWith("fd"))return!0;if(Q.startsWith("fe80"))return!0;return!1}var O3=({prefix:A,size:Q=16,alphabet:w="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",separator:B="-"}={})=>{let $=()=>{let f=w.length,D=Array(Q);for(let Y=0;Y<Q;Y++)D[Y]=w[Math.random()*f|0];return D.join("")};if(A==null)return $;if(w.includes(B))throw new zb1({argument:"separator",message:`The separator "${B}" must not be part of the alphabet "${w}".`});return()=>`${A}${B}${$()}`},ib1=O3();function Lg0(A){if(A==null)return"unknown error";if(typeof A==="string")return A;if(A instanceof Error)return A.message;return JSON.stringify(A)}function db1(A=globalThis){var Q,w,B;if(A.window)return"runtime/browser";if((Q=A.navigator)==null?void 0:Q.userAgent)return`runtime/${A.navigator.userAgent.toLowerCase()}`;if((B=(w=A.process)==null?void 0:w.versions)==null?void 0:B.node)return`runtime/node.js/${A.process.version.substring(0)}`;if(A.EdgeRuntime)return"runtime/vercel-edge";return"runtime/unknown"}function OxQ(A){if(A==null)return{};let Q={};if(A instanceof Headers)A.forEach((w,B)=>{Q[B.toLowerCase()]=w});else{if(!Array.isArray(A))A=Object.entries(A);for(let[w,B]of A)if(B!=null)Q[w.toLowerCase()]=B}return Q}function x50(A,...Q){let w=new Headers(OxQ(A)),B=w.get("user-agent")||"";return w.set("user-agent",[B,...Q].filter(Boolean).join(" ")),Object.fromEntries(w.entries())}var xxQ=/"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/,RxQ=/"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;function Tb1(A){let Q=JSON.parse(A);if(Q===null||typeof Q!=="object")return Q;if(xxQ.test(A)===!1&&RxQ.test(A)===!1)return Q;return hxQ(Q)}function hxQ(A){let Q=[A];while(Q.length){let w=Q;Q=[];for(let B of w){if(Object.prototype.hasOwnProperty.call(B,"__proto__"))throw SyntaxError("Object contains forbidden prototype property");if(Object.prototype.hasOwnProperty.call(B,"constructor")&&B.constructor!==null&&typeof B.constructor==="object"&&Object.prototype.hasOwnProperty.call(B.constructor,"prototype"))throw SyntaxError("Object contains forbidden prototype property");for(let $ in B){let f=B[$];if(f&&typeof f==="object")Q.push(f)}}}return A}function vxQ(A){let{stackTraceLimit:Q}=Error;try{Error.stackTraceLimit=0}catch(w){return Tb1(A)}try{return Tb1(A)}finally{Error.stackTraceLimit=Q}}function Ng0(A){if(A.type==="object"||Array.isArray(A.type)&&A.type.includes("object")){A.additionalProperties=!1;let{properties:w}=A;if(w!=null)for(let B of Object.keys(w))w[B]=G_(w[B])}if(A.items!=null)A.items=Array.isArray(A.items)?A.items.map(G_):G_(A.items);if(A.anyOf!=null)A.anyOf=A.anyOf.map(G_);if(A.allOf!=null)A.allOf=A.allOf.map(G_);if(A.oneOf!=null)A.oneOf=A.oneOf.map(G_);let{definitions:Q}=A;if(Q!=null)for(let w of Object.keys(Q))Q[w]=G_(Q[w]);return A}function G_(A){if(typeof A==="boolean")return A;return Ng0(A)}var CxQ=Symbol("Let zodToJsonSchema decide on which parser to use"),Sb1={name:void 0,$refStrategy:"root",basePath:["#"],effectStrategy:"input",pipeStrategy:"all",dateStrategy:"format:date-time",mapStrategy:"entries",removeAdditionalStrategy:"passthrough",allowedAdditionalProperties:!0,rejectedAdditionalProperties:!1,definitionPath:"definitions",strictUnions:!1,definitions:{},errorMessages:!1,patternStrategy:"escape",applyRegexFlags:!1,emailStrategy:"format:email",base64Strategy:"contentEncoding:base64",nameStrategy:"ref"},yxQ=(A)=>typeof A==="string"?{...Sb1,name:A}:{...Sb1,...A};function XX(){return{}}function ExQ(A,Q){var w,B,$;let f={type:"array"};if(((w=A.type)==null?void 0:w._def)&&(($=(B=A.type)==null?void 0:B._def)==null?void 0:$.typeName)!==KA.ZodAny)f.items=lB(A.type._def,{...Q,currentPath:[...Q.currentPath,"items"]});if(A.minLength)f.minItems=A.minLength.value;if(A.maxLength)f.maxItems=A.maxLength.value;if(A.exactLength)f.minItems=A.exactLength.value,f.maxItems=A.exactLength.value;return f}function gxQ(A){let Q={type:"integer",format:"int64"};if(!A.checks)return Q;for(let w of A.checks)switch(w.kind){case"min":if(w.inclusive)Q.minimum=w.value;else Q.exclusiveMinimum=w.value;break;case"max":if(w.inclusive)Q.maximum=w.value;else Q.exclusiveMaximum=w.value;break;case"multipleOf":Q.multipleOf=w.value;break}return Q}function TxQ(){return{type:"boolean"}}function nb1(A,Q){return lB(A.type._def,Q)}var SxQ=(A,Q)=>{return lB(A.innerType._def,Q)};function rb1(A,Q,w){let B=w!=null?w:Q.dateStrategy;if(Array.isArray(B))return{anyOf:B.map(($,f)=>rb1(A,Q,$))};switch(B){case"string":case"format:date-time":return{type:"string",format:"date-time"};case"format:date":return{type:"string",format:"date"};case"integer":return mxQ(A)}}var mxQ=(A)=>{let Q={type:"integer",format:"unix-time"};for(let w of A.checks)switch(w.kind){case"min":Q.minimum=w.value;break;case"max":Q.maximum=w.value;break}return Q};function uxQ(A,Q){return{...lB(A.innerType._def,Q),default:A.defaultValue()}}function cxQ(A,Q){return Q.effectStrategy==="input"?lB(A.schema._def,Q):XX()}function lxQ(A){return{type:"string",enum:Array.from(A.values)}}var pxQ=(A)=>{if("type"in A&&A.type==="string")return!1;return"allOf"in A};function ixQ(A,Q){let w=[lB(A.left._def,{...Q,currentPath:[...Q.currentPath,"allOf","0"]}),lB(A.right._def,{...Q,currentPath:[...Q.currentPath,"allOf","1"]})].filter(($)=>!!$),B=[];return w.forEach(($)=>{if(pxQ($))B.push(...$.allOf);else{let f=$;if("additionalProperties"in $&&$.additionalProperties===!1){let{additionalProperties:D,...Y}=$;f=Y}B.push(f)}}),B.length?{allOf:B}:void 0}function dxQ(A){let Q=typeof A.value;if(Q!=="bigint"&&Q!=="number"&&Q!=="boolean"&&Q!=="string")return{type:Array.isArray(A.value)?"array":"object"};return{type:Q==="bigint"?"integer":Q,const:A.value}}var zg0=void 0,sZ={cuid:/^[cC][^\s-]{8,}$/,cuid2:/^[0-9a-z]+$/,ulid:/^[0-9A-HJKMNP-TV-Z]{26}$/,email:/^(?!\.)(?!.*\.\.)([a-zA-Z0-9_'+\-\.]*)[a-zA-Z0-9_+-]@([a-zA-Z0-9][a-zA-Z0-9\-]*\.)+[a-zA-Z]{2,}$/,emoji:()=>{if(zg0===void 0)zg0=RegExp("^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$","u");return zg0},uuid:/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/,ipv4:/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,ipv4Cidr:/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/,ipv6:/^(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$/,ipv6Cidr:/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,base64:/^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/,base64url:/^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/,nanoid:/^[a-zA-Z0-9_-]{21}$/,jwt:/^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/};function ob1(A,Q){let w={type:"string"};if(A.checks)for(let B of A.checks)switch(B.kind){case"min":w.minLength=typeof w.minLength==="number"?Math.max(w.minLength,B.value):B.value;break;case"max":w.maxLength=typeof w.maxLength==="number"?Math.min(w.maxLength,B.value):B.value;break;case"email":switch(Q.emailStrategy){case"format:email":aZ(w,"email",B.message,Q);break;case"format:idn-email":aZ(w,"idn-email",B.message,Q);break;case"pattern:zod":Mf(w,sZ.email,B.message,Q);break}break;case"url":aZ(w,"uri",B.message,Q);break;case"uuid":aZ(w,"uuid",B.message,Q);break;case"regex":Mf(w,B.regex,B.message,Q);break;case"cuid":Mf(w,sZ.cuid,B.message,Q);break;case"cuid2":Mf(w,sZ.cuid2,B.message,Q);break;case"startsWith":Mf(w,RegExp(`^${qg0(B.value,Q)}`),B.message,Q);break;case"endsWith":Mf(w,RegExp(`${qg0(B.value,Q)}$`),B.message,Q);break;case"datetime":aZ(w,"date-time",B.message,Q);break;case"date":aZ(w,"date",B.message,Q);break;case"time":aZ(w,"time",B.message,Q);break;case"duration":aZ(w,"duration",B.message,Q);break;case"length":w.minLength=typeof w.minLength==="number"?Math.max(w.minLength,B.value):B.value,w.maxLength=typeof w.maxLength==="number"?Math.min(w.maxLength,B.value):B.value;break;case"includes":{Mf(w,RegExp(qg0(B.value,Q)),B.message,Q);break}case"ip":{if(B.version!=="v6")aZ(w,"ipv4",B.message,Q);if(B.version!=="v4")aZ(w,"ipv6",B.message,Q);break}case"base64url":Mf(w,sZ.base64url,B.message,Q);break;case"jwt":Mf(w,sZ.jwt,B.message,Q);break;case"cidr":{if(B.version!=="v6")Mf(w,sZ.ipv4Cidr,B.message,Q);if(B.version!=="v4")Mf(w,sZ.ipv6Cidr,B.message,Q);break}case"emoji":Mf(w,sZ.emoji(),B.message,Q);break;case"ulid":{Mf(w,sZ.ulid,B.message,Q);break}case"base64":{switch(Q.base64Strategy){case"format:binary":{aZ(w,"binary",B.message,Q);break}case"contentEncoding:base64":{w.contentEncoding="base64";break}case"pattern:zod":{Mf(w,sZ.base64,B.message,Q);break}}break}case"nanoid":Mf(w,sZ.nanoid,B.message,Q);case"toLowerCase":case"toUpperCase":case"trim":break;default:}return w}function qg0(A,Q){return Q.patternStrategy==="escape"?rxQ(A):A}var nxQ=new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");function rxQ(A){let Q="";for(let w=0;w<A.length;w++){if(!nxQ.has(A[w]))Q+="\\";Q+=A[w]}return Q}function aZ(A,Q,w,B){var $;if(A.format||(($=A.anyOf)==null?void 0:$.some((f)=>f.format))){if(!A.anyOf)A.anyOf=[];if(A.format)A.anyOf.push({format:A.format}),delete A.format;A.anyOf.push({format:Q,...w&&B.errorMessages&&{errorMessage:{format:w}}})}else A.format=Q}function Mf(A,Q,w,B){var $;if(A.pattern||(($=A.allOf)==null?void 0:$.some((f)=>f.pattern))){if(!A.allOf)A.allOf=[];if(A.pattern)A.allOf.push({pattern:A.pattern}),delete A.pattern;A.allOf.push({pattern:mb1(Q,B),...w&&B.errorMessages&&{errorMessage:{pattern:w}}})}else A.pattern=mb1(Q,B)}function mb1(A,Q){var w;if(!Q.applyRegexFlags||!A.flags)return A.source;let B={i:A.flags.includes("i"),m:A.flags.includes("m"),s:A.flags.includes("s")},$=B.i?A.source.toLowerCase():A.source,f="",D=!1,Y=!1,X=!1;for(let H=0;H<$.length;H++){if(D){f+=$[H],D=!1;continue}if(B.i){if(Y){if($[H].match(/[a-z]/)){if(X)f+=$[H],f+=`${$[H-2]}-${$[H]}`.toUpperCase(),X=!1;else if($[H+1]==="-"&&((w=$[H+2])==null?void 0:w.match(/[a-z]/)))f+=$[H],X=!0;else f+=`${$[H]}${$[H].toUpperCase()}`;continue}}else if($[H].match(/[a-z]/)){f+=`[${$[H]}${$[H].toUpperCase()}]`;continue}}if(B.m){if($[H]==="^"){f+=`(^|(?<=[\r
2421
2421
  ]))`;continue}else if($[H]==="$"){f+=`($|(?=[\r
@@ -2425,7 +2425,7 @@ Error message: ${Kb1(w)}`,cause:w});this[Bb1]=!0,this.value=Q,this.context=B}sta
2425
2425
 
2426
2426
  `)},flush(A){A.enqueue(`data: [DONE]
2427
2427
 
2428
- `)}})}},ZvQ={"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive","x-vercel-ai-ui-message-stream":"v1","x-accel-buffering":"no"};function WL1({status:A,statusText:Q,headers:w,stream:B,consumeSseStream:$}){let f=B.pipeThrough(new WvQ);if($){let[D,Y]=f.tee();f=D,$({stream:Y})}return new Response(f.pipeThrough(new TextEncoderStream),{status:A,statusText:Q,headers:HvQ(w,ZvQ)})}var Yd=z.record(z.string(),z_.optional()),Pz8=R50(()=>Dd(z.union([z.strictObject({type:z.literal("text-start"),id:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("text-delta"),id:z.string(),delta:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("text-end"),id:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("error"),errorText:z.string()}),z.strictObject({type:z.literal("tool-input-start"),toolCallId:z.string(),toolName:z.string(),providerExecuted:z.boolean().optional(),providerMetadata:b2.optional(),toolMetadata:Yd.optional(),dynamic:z.boolean().optional(),title:z.string().optional()}),z.strictObject({type:z.literal("tool-input-delta"),toolCallId:z.string(),inputTextDelta:z.string()}),z.strictObject({type:z.literal("tool-input-available"),toolCallId:z.string(),toolName:z.string(),input:z.unknown(),providerExecuted:z.boolean().optional(),providerMetadata:b2.optional(),toolMetadata:Yd.optional(),dynamic:z.boolean().optional(),title:z.string().optional()}),z.strictObject({type:z.literal("tool-input-error"),toolCallId:z.string(),toolName:z.string(),input:z.unknown(),providerExecuted:z.boolean().optional(),providerMetadata:b2.optional(),toolMetadata:Yd.optional(),dynamic:z.boolean().optional(),errorText:z.string(),title:z.string().optional()}),z.strictObject({type:z.literal("tool-approval-request"),approvalId:z.string(),toolCallId:z.string()}),z.strictObject({type:z.literal("tool-output-available"),toolCallId:z.string(),output:z.unknown(),providerExecuted:z.boolean().optional(),providerMetadata:b2.optional(),toolMetadata:Yd.optional(),dynamic:z.boolean().optional(),preliminary:z.boolean().optional()}),z.strictObject({type:z.literal("tool-output-error"),toolCallId:z.string(),errorText:z.string(),providerExecuted:z.boolean().optional(),providerMetadata:b2.optional(),toolMetadata:Yd.optional(),dynamic:z.boolean().optional()}),z.strictObject({type:z.literal("tool-output-denied"),toolCallId:z.string()}),z.strictObject({type:z.literal("reasoning-start"),id:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("reasoning-delta"),id:z.string(),delta:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("reasoning-end"),id:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("source-url"),sourceId:z.string(),url:z.string(),title:z.string().optional(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("source-document"),sourceId:z.string(),mediaType:z.string(),title:z.string(),filename:z.string().optional(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("file"),url:z.string(),mediaType:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.custom((A)=>typeof A==="string"&&A.startsWith("data-"),{message:'Type must start with "data-"'}),id:z.string().optional(),data:z.unknown(),transient:z.boolean().optional()}),z.strictObject({type:z.literal("start-step")}),z.strictObject({type:z.literal("finish-step")}),z.strictObject({type:z.literal("start"),messageId:z.string().optional(),messageMetadata:z.unknown().optional()}),z.strictObject({type:z.literal("finish"),finishReason:z.enum(["stop","length","content-filter","tool-calls","error","other"]).optional(),messageMetadata:z.unknown().optional()}),z.strictObject({type:z.literal("abort"),reason:z.string().optional()}),z.strictObject({type:z.literal("message-metadata"),messageMetadata:z.unknown()})])));function KvQ(A){return A.type.startsWith("data-")}function Mg0(A){return A.type.startsWith("tool-")}function UvQ(A){return A.type==="dynamic-tool"}function ab1(A){return Mg0(A)||UvQ(A)}function tb1(A){return A.type.split("-").slice(1).join("-")}function GvQ({lastMessage:A,messageId:Q}){return{message:(A==null?void 0:A.role)==="assistant"?A:{id:Q,metadata:void 0,role:"assistant",parts:[]},activeTextParts:{},activeReasoningParts:{},partialToolCalls:{}}}function zvQ({stream:A,messageMetadataSchema:Q,dataPartSchemas:w,runUpdateMessageJob:B,onError:$,onToolCall:f,onData:D}){return A.pipeThrough(new TransformStream({async transform(Y,X){await B(async({state:H,write:W})=>{var Z,G,F,V;function b(j){let E=H.message.parts.filter(ab1).find((y)=>y.toolCallId===j);if(E==null)throw new gC({chunkType:"tool-invocation",chunkId:j,message:`No tool invocation found for tool call ID "${j}".`});return E}function L(j){var g;let E=H.message.parts.find((T)=>Mg0(T)&&T.toolCallId===j.toolCallId),y=j,h=E;if(E!=null){if(E.state=j.state,h.input=y.input,h.output=y.output,h.errorText=y.errorText,h.rawInput=y.rawInput,h.preliminary=y.preliminary,j.title!==void 0)h.title=j.title;if(j.toolMetadata!==void 0)h.toolMetadata=j.toolMetadata;h.providerExecuted=(g=y.providerExecuted)!=null?g:E.providerExecuted;let T=y.providerMetadata;if(T!=null)if(j.state==="output-available"||j.state==="output-error"){let S=E;S.resultProviderMetadata=T}else E.callProviderMetadata=T}else H.message.parts.push({type:`tool-${j.toolName}`,toolCallId:j.toolCallId,state:j.state,title:j.title,...j.toolMetadata!==void 0?{toolMetadata:j.toolMetadata}:{},input:y.input,output:y.output,rawInput:y.rawInput,errorText:y.errorText,providerExecuted:y.providerExecuted,preliminary:y.preliminary,...y.providerMetadata!=null&&(j.state==="output-available"||j.state==="output-error")?{resultProviderMetadata:y.providerMetadata}:{},...y.providerMetadata!=null&&!(j.state==="output-available"||j.state==="output-error")?{callProviderMetadata:y.providerMetadata}:{}})}function N(j){var g,E;let y=H.message.parts.find((S)=>S.type==="dynamic-tool"&&S.toolCallId===j.toolCallId),h=j,T=y;if(y!=null){if(y.state=j.state,T.toolName=j.toolName,T.input=h.input,T.output=h.output,T.errorText=h.errorText,T.rawInput=(g=h.rawInput)!=null?g:T.rawInput,T.preliminary=h.preliminary,j.title!==void 0)T.title=j.title;if(j.toolMetadata!==void 0)T.toolMetadata=j.toolMetadata;T.providerExecuted=(E=h.providerExecuted)!=null?E:y.providerExecuted;let S=h.providerMetadata;if(S!=null)if(j.state==="output-available"||j.state==="output-error"){let c=y;c.resultProviderMetadata=S}else y.callProviderMetadata=S}else H.message.parts.push({type:"dynamic-tool",toolName:j.toolName,toolCallId:j.toolCallId,state:j.state,input:h.input,output:h.output,errorText:h.errorText,preliminary:h.preliminary,providerExecuted:h.providerExecuted,title:j.title,...j.toolMetadata!==void 0?{toolMetadata:j.toolMetadata}:{},...h.providerMetadata!=null&&(j.state==="output-available"||j.state==="output-error")?{resultProviderMetadata:h.providerMetadata}:{},...h.providerMetadata!=null&&!(j.state==="output-available"||j.state==="output-error")?{callProviderMetadata:h.providerMetadata}:{}})}async function _(j){if(j!=null){let g=H.message.metadata!=null?HL1(H.message.metadata,j):j;if(Q!=null)await C50({value:g,schema:Q,context:{field:"message.metadata",entityId:H.message.id}});H.message.metadata=g}}switch(Y.type){case"text-start":{let j={type:"text",text:"",providerMetadata:Y.providerMetadata,state:"streaming"};H.activeTextParts[Y.id]=j,H.message.parts.push(j),W();break}case"text-delta":{let j=H.activeTextParts[Y.id];if(j==null)throw new gC({chunkType:"text-delta",chunkId:Y.id,message:`Received text-delta for missing text part with ID "${Y.id}". Ensure a "text-start" chunk is sent before any "text-delta" chunks.`});j.text+=Y.delta,j.providerMetadata=(Z=Y.providerMetadata)!=null?Z:j.providerMetadata,W();break}case"text-end":{let j=H.activeTextParts[Y.id];if(j==null)throw new gC({chunkType:"text-end",chunkId:Y.id,message:`Received text-end for missing text part with ID "${Y.id}". Ensure a "text-start" chunk is sent before any "text-end" chunks.`});j.state="done",j.providerMetadata=(G=Y.providerMetadata)!=null?G:j.providerMetadata,delete H.activeTextParts[Y.id],W();break}case"reasoning-start":{let j={type:"reasoning",text:"",providerMetadata:Y.providerMetadata,state:"streaming"};H.activeReasoningParts[Y.id]=j,H.message.parts.push(j),W();break}case"reasoning-delta":{let j=H.activeReasoningParts[Y.id];if(j==null)throw new gC({chunkType:"reasoning-delta",chunkId:Y.id,message:`Received reasoning-delta for missing reasoning part with ID "${Y.id}". Ensure a "reasoning-start" chunk is sent before any "reasoning-delta" chunks.`});j.text+=Y.delta,j.providerMetadata=(F=Y.providerMetadata)!=null?F:j.providerMetadata,W();break}case"reasoning-end":{let j=H.activeReasoningParts[Y.id];if(j==null)throw new gC({chunkType:"reasoning-end",chunkId:Y.id,message:`Received reasoning-end for missing reasoning part with ID "${Y.id}". Ensure a "reasoning-start" chunk is sent before any "reasoning-end" chunks.`});j.providerMetadata=(V=Y.providerMetadata)!=null?V:j.providerMetadata,j.state="done",delete H.activeReasoningParts[Y.id],W();break}case"file":{H.message.parts.push({type:"file",mediaType:Y.mediaType,url:Y.url,...Y.providerMetadata!=null?{providerMetadata:Y.providerMetadata}:{}}),W();break}case"source-url":{H.message.parts.push({type:"source-url",sourceId:Y.sourceId,url:Y.url,title:Y.title,providerMetadata:Y.providerMetadata}),W();break}case"source-document":{H.message.parts.push({type:"source-document",sourceId:Y.sourceId,mediaType:Y.mediaType,title:Y.title,filename:Y.filename,providerMetadata:Y.providerMetadata}),W();break}case"tool-input-start":{let j=H.message.parts.filter(Mg0);if(H.partialToolCalls[Y.toolCallId]={text:"",toolName:Y.toolName,index:j.length,dynamic:Y.dynamic,title:Y.title,toolMetadata:Y.toolMetadata},Y.dynamic)N({toolCallId:Y.toolCallId,toolName:Y.toolName,state:"input-streaming",input:void 0,providerExecuted:Y.providerExecuted,title:Y.title,toolMetadata:Y.toolMetadata,providerMetadata:Y.providerMetadata});else L({toolCallId:Y.toolCallId,toolName:Y.toolName,state:"input-streaming",input:void 0,providerExecuted:Y.providerExecuted,title:Y.title,toolMetadata:Y.toolMetadata,providerMetadata:Y.providerMetadata});W();break}case"tool-input-delta":{let j=H.partialToolCalls[Y.toolCallId];if(j==null)throw new gC({chunkType:"tool-input-delta",chunkId:Y.toolCallId,message:`Received tool-input-delta for missing tool call with ID "${Y.toolCallId}". Ensure a "tool-input-start" chunk is sent before any "tool-input-delta" chunks.`});j.text+=Y.inputTextDelta;let{value:g}=await Xd(j.text);if(j.dynamic)N({toolCallId:Y.toolCallId,toolName:j.toolName,state:"input-streaming",input:g,title:j.title,toolMetadata:j.toolMetadata});else L({toolCallId:Y.toolCallId,toolName:j.toolName,state:"input-streaming",input:g,title:j.title,toolMetadata:j.toolMetadata});W();break}case"tool-input-available":{if(Y.dynamic)N({toolCallId:Y.toolCallId,toolName:Y.toolName,state:"input-available",input:Y.input,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,title:Y.title,toolMetadata:Y.toolMetadata});else L({toolCallId:Y.toolCallId,toolName:Y.toolName,state:"input-available",input:Y.input,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,title:Y.title,toolMetadata:Y.toolMetadata});if(W(),f&&!Y.providerExecuted)await f({toolCall:Y});break}case"tool-input-error":{let j=H.message.parts.filter(ab1).find((E)=>E.toolCallId===Y.toolCallId);if(j!=null?j.type==="dynamic-tool":!!Y.dynamic)N({toolCallId:Y.toolCallId,toolName:Y.toolName,state:"output-error",input:Y.input,errorText:Y.errorText,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,toolMetadata:Y.toolMetadata});else L({toolCallId:Y.toolCallId,toolName:Y.toolName,state:"output-error",input:void 0,rawInput:Y.input,errorText:Y.errorText,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,toolMetadata:Y.toolMetadata});W();break}case"tool-approval-request":{let j=b(Y.toolCallId);j.state="approval-requested",j.approval={id:Y.approvalId},W();break}case"tool-output-denied":{let j=b(Y.toolCallId);j.state="output-denied",W();break}case"tool-output-available":{let j=b(Y.toolCallId);if(j.type==="dynamic-tool")N({toolCallId:Y.toolCallId,toolName:j.toolName,state:"output-available",input:j.input,output:Y.output,preliminary:Y.preliminary,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,title:j.title,toolMetadata:j.toolMetadata});else L({toolCallId:Y.toolCallId,toolName:tb1(j),state:"output-available",input:j.input,output:Y.output,providerExecuted:Y.providerExecuted,preliminary:Y.preliminary,providerMetadata:Y.providerMetadata,title:j.title,toolMetadata:j.toolMetadata});W();break}case"tool-output-error":{let j=b(Y.toolCallId);if(j.type==="dynamic-tool")N({toolCallId:Y.toolCallId,toolName:j.toolName,state:"output-error",input:j.input,errorText:Y.errorText,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,title:j.title,toolMetadata:j.toolMetadata});else L({toolCallId:Y.toolCallId,toolName:tb1(j),state:"output-error",input:j.input,rawInput:j.rawInput,errorText:Y.errorText,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,title:j.title,toolMetadata:j.toolMetadata});W();break}case"start-step":{H.message.parts.push({type:"step-start"});break}case"finish-step":{H.activeTextParts={},H.activeReasoningParts={};break}case"start":{if(Y.messageId!=null)H.message.id=Y.messageId;if(await _(Y.messageMetadata),Y.messageId!=null||Y.messageMetadata!=null)W();break}case"finish":{if(Y.finishReason!=null)H.finishReason=Y.finishReason;if(await _(Y.messageMetadata),Y.messageMetadata!=null)W();break}case"message-metadata":{if(await _(Y.messageMetadata),Y.messageMetadata!=null)W();break}case"error":{$==null||$(Error(Y.errorText));break}default:if(KvQ(Y)){if((w==null?void 0:w[Y.type])!=null){let E=H.message.parts.findIndex((h)=>("id"in h)&&("data"in h)&&h.id===Y.id&&h.type===Y.type),y=E>=0?E:H.message.parts.length;await C50({value:Y.data,schema:w[Y.type],context:{field:`message.parts[${y}].data`,entityName:Y.type,entityId:Y.id}})}let j=Y;if(j.transient){D==null||D(j);break}let g=j.id!=null?H.message.parts.find((E)=>j.type===E.type&&j.id===E.id):void 0;if(g!=null)g.data=j.data;else H.message.parts.push(j);D==null||D(j),W()}}X.enqueue(Y)})}}))}function qvQ({messageId:A,originalMessages:Q=[],onStepFinish:w,onFinish:B,onError:$,stream:f}){let D=Q==null?void 0:Q[Q.length-1];if((D==null?void 0:D.role)!=="assistant")D=void 0;else A=D.id;let Y=!1,X=f.pipeThrough(new TransformStream({transform(V,b){if(V.type==="start"){let L=V;if(L.messageId==null&&A!=null)L.messageId=A}if(V.type==="abort")Y=!0;b.enqueue(V)}}));if(B==null&&w==null)return X;let H=GvQ({lastMessage:D?structuredClone(D):void 0,messageId:A!=null?A:""}),W=async(V)=>{await V({state:H,write:()=>{}})},Z=!1,G=async()=>{if(Z||!B)return;Z=!0;let V=H.message.id===(D==null?void 0:D.id);await B({isAborted:Y,isContinuation:V,responseMessage:H.message,messages:[...V?Q.slice(0,-1):Q,H.message],finishReason:H.finishReason})},F=async()=>{if(!w)return;let V=H.message.id===(D==null?void 0:D.id);try{await w({isContinuation:V,responseMessage:structuredClone(H.message),messages:[...V?Q.slice(0,-1):Q,structuredClone(H.message)]})}catch(b){$(b)}};return zvQ({stream:X,runUpdateMessageJob:W,onError:$}).pipeThrough(new TransformStream({async transform(V,b){if(V.type==="finish-step")await F();b.enqueue(V)},async cancel(){await G()},async flush(){await G()}}))}var kz8=O3({prefix:"aitxt",size:24});function ZL1({execute:A,onError:Q=Lg0,originalMessages:w,onStepFinish:B,onFinish:$,generateId:f=ib1}){let D,Y=[],X=new ReadableStream({start(Z){D=Z}});function H(Z){try{D.enqueue(Z)}catch(G){}}try{let Z=A({writer:{write(G){H(G)},merge(G){Y.push((async()=>{let F=G.getReader();while(!0){let{done:V,value:b}=await F.read();if(V)break;H(b)}})().catch((F)=>{H({type:"error",errorText:Q(F)})}))},onError:Q}});if(Z)Y.push(Z.catch((G)=>{H({type:"error",errorText:Q(G)})}))}catch(Z){H({type:"error",errorText:Q(Z)})}return new Promise(async(Z)=>{while(Y.length>0)await Y.shift();Z()}).finally(()=>{try{D.close()}catch(Z){}}),qvQ({stream:X,messageId:f(),originalMessages:w,onStepFinish:B,onFinish:$,onError:Q})}var kD=z.record(z.string(),z_.optional()),hz8=R50(()=>Dd(z.array(z.object({id:z.string(),role:z.enum(["system","user","assistant"]),metadata:z.unknown().optional(),parts:z.array(z.union([z.object({type:z.literal("text"),text:z.string(),state:z.enum(["streaming","done"]).optional(),providerMetadata:b2.optional()}),z.object({type:z.literal("reasoning"),text:z.string(),state:z.enum(["streaming","done"]).optional(),providerMetadata:b2.optional()}),z.object({type:z.literal("source-url"),sourceId:z.string(),url:z.string(),title:z.string().optional(),providerMetadata:b2.optional()}),z.object({type:z.literal("source-document"),sourceId:z.string(),mediaType:z.string(),title:z.string(),filename:z.string().optional(),providerMetadata:b2.optional()}),z.object({type:z.literal("file"),mediaType:z.string(),filename:z.string().optional(),url:z.string(),providerMetadata:b2.optional()}),z.object({type:z.literal("step-start")}),z.object({type:z.string().startsWith("data-"),id:z.string().optional(),data:z.unknown()}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("input-streaming"),input:z.unknown().optional(),providerExecuted:z.boolean().optional(),callProviderMetadata:b2.optional(),output:z.never().optional(),errorText:z.never().optional(),approval:z.never().optional()}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("input-available"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.never().optional()}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("approval-requested"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.never().optional(),reason:z.never().optional()})}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("approval-responded"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.boolean(),reason:z.string().optional()})}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("output-available"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.unknown(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),resultProviderMetadata:b2.optional(),preliminary:z.boolean().optional(),approval:z.object({id:z.string(),approved:z.literal(!0),reason:z.string().optional()}).optional()}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("output-error"),input:z.unknown().optional(),rawInput:z.unknown().optional(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.string(),callProviderMetadata:b2.optional(),resultProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.literal(!0),reason:z.string().optional()}).optional()}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("output-denied"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.literal(!1),reason:z.string().optional()})}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("input-streaming"),providerExecuted:z.boolean().optional(),callProviderMetadata:b2.optional(),input:z.unknown().optional(),output:z.never().optional(),errorText:z.never().optional(),approval:z.never().optional()}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("input-available"),providerExecuted:z.boolean().optional(),input:z.unknown(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.never().optional()}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("approval-requested"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.never().optional(),reason:z.never().optional()})}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("approval-responded"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.boolean(),reason:z.string().optional()})}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("output-available"),providerExecuted:z.boolean().optional(),input:z.unknown(),output:z.unknown(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),resultProviderMetadata:b2.optional(),preliminary:z.boolean().optional(),approval:z.object({id:z.string(),approved:z.literal(!0),reason:z.string().optional()}).optional()}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("output-error"),providerExecuted:z.boolean().optional(),input:z.unknown().optional(),rawInput:z.unknown().optional(),output:z.never().optional(),errorText:z.string(),callProviderMetadata:b2.optional(),resultProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.literal(!0),reason:z.string().optional()}).optional()}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("output-denied"),providerExecuted:z.boolean().optional(),input:z.unknown(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.literal(!1),reason:z.string().optional()})})])).nonempty("Message must contain at least one part")})).nonempty("Messages array must not be empty")));var Cz8=O3({prefix:"aiobj",size:24});function KL1(A){return({url:Q,abortSignal:w})=>ihQ({url:Q,maxBytes:A==null?void 0:A.maxBytes,abortSignal:w})}var Ez8=O3({prefix:"aiobj",size:24});var gz8=KL1();var FvQ="AI_NoSuchProviderError",VvQ=`vercel.ai.error.${FvQ}`,IvQ=Symbol.for(VvQ),JvQ;JvQ=IvQ;var Tz8=KL1();var UL1={name:"@brains/web-chat",private:!0,version:"0.2.0-alpha.133",description:"Web chat interface for Brains",type:"module",exports:{".":"./src/index.ts"},files:["src","dist","package.json"],scripts:{build:"bun scripts/build-ui.ts","build:ui":"bun scripts/build-ui.ts",typecheck:"tsc --noEmit && tsc --noEmit -p ui-react/tsconfig.json",lint:"eslint . --ext .ts,.tsx","lint:fix":"eslint . --ext .ts,.tsx --fix",test:"bun test"},dependencies:{"@ai-sdk/react":"^3.0.116","@brains/auth-service":"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.86","class-variance-authority":"^0.7.0",cmdk:"^1.1.1","lucide-react":"^1.16.0",nanoid:"^5.0.4","radix-ui":"^1.4.3",react:"^19.2.6","react-dom":"^19.2.6",shiki:"^4.1.0",streamdown:"^2.5.0","use-stick-to-bottom":"^1.1.4"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","@types/react":"^19.0.3","@types/react-dom":"^19.0.3",typescript:"^5.3.3",vite:"^7.2.4"}};c0();async function GL1(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 qL1({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 D=MN("document",f.content);if(!D)return new Response("Document content is not a PDF",{status:415});let Y=_N(f.metadata,$,"document",D.mimeType);return FL1({requestUrl:B,data:D.data,mediaType:D.mimeType,filename:Y})}async function zL1(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 qL1({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 D=MN("image",f.content);if(!D)return new Response("Image content is not an image",{status:415});let Y=_N(f.metadata,$,"image",D.mimeType);return FL1({requestUrl:B,data:D.data,mediaType:D.mimeType,filename:Y})}async function qL1(A){let Q={entityType:A.entityType,id:A.id},w=await PN({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 FL1(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":pV({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}Z0();c0();var Hd="upload",VL1=aO;var LvQ={namespace:"upload",refKind:Hd,routePath:"/api/chat/uploads"};function y50(){return LvQ}c0();UG0();var IL1=Y00;var JL1=X00;var NvQ="file",jvQ=16384;async function bL1(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>JL1+jvQ)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(NvQ);if(!($ instanceof File))return new Response("Missing upload file",{status:400});let f=Buffer.from(await $.arrayBuffer()),D=Kq({filename:$.name,mediaType:$.type,content:f});if(!D.ok)return new Response(D.message,{status:400});let Y=Q.getUploadStore(),X=await Y.save({filename:D.filename,mediaType:D.mediaType,content:f});return Response.json(Y.toResponseBody(X),{status:201})}async function LL1(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 ML1(w,Q.getUploadStore());if(B instanceof Response)return B;let{record:$,content:f}=B,D=_L1($,f);if(D instanceof Response)return D;let Y=new URL(A.url).searchParams.has("download")?"attachment":"inline",X=new Uint8Array(f).buffer;return new Response(X,{headers:{"Content-Type":$.mediaType,"Content-Length":String(f.byteLength),"Content-Disposition":pV({disposition:Y,filename:$.filename})}})}function NL1(A){let Q=Zq(A.filename??IL1),w=_vQ(A.url);if(!w)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let B=Kq({filename:Q,mediaType:A.mediaType,content:w.buffer});if(!B.ok)return new Response(B.message,{status:400});return PL1(B,w.buffer)}async function jL1(A,Q){let w=await ML1(A,Q);if(w instanceof Response)return w;let{record:B,content:$}=w,f=_L1(B,$);if(f instanceof Response)return f;return PL1(f,$,{kind:Hd,id:A})}async function ML1(A,Q){try{return await Q.read(A)}catch(w){if(w instanceof zU)return MvQ(w);throw w}}function _L1(A,Q){let w=Kq({filename:A.filename,mediaType:A.mediaType,content:Q});if(!w.ok)return new Response(w.message,{status:400});return w}function PL1(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 MvQ(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 _vQ(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 PvQ=K.object({type:K.literal("text"),text:K.string()}),kvQ=K.object({type:K.literal("file"),mediaType:K.string().optional(),filename:K.string().optional(),url:K.string()}),OvQ=K.object({state:K.literal("approval-responded"),approval:K.object({id:K.string(),approved:K.boolean()})}).passthrough(),xvQ=K.object({id:K.string().optional(),role:K.string(),parts:K.array(K.unknown()).optional(),content:K.string().optional()}),kL1=K.object({id:K.string().optional(),messages:K.array(xvQ).min(1),trigger:K.string().optional()}),RvQ=K.object({kind:K.literal(Hd),id:K.string().regex(VL1)}),hvQ=K.object({type:K.literal("data-upload"),data:K.object({ref:RvQ})});async function OL1(A,Q){let w=vvQ(A);if(!w)return{message:"",attachments:[]};let B=[],$=[];for(let D of w.parts??[]){let Y=PvQ.safeParse(D);if(Y.success){if(Y.data.text.length>0)B.push(Y.data.text);continue}let X=kvQ.safeParse(D);if(X.success){let W=NL1(X.data);if(W instanceof Response)return W;$.push(W);continue}let H=hvQ.safeParse(D);if(H.success){let W=await jL1(H.data.data.ref.id,Q.uploadStore);if(W instanceof Response)return W;$.push(W);continue}if(CvQ(D)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:B.length>0?B.join(`
2428
+ `)}})}},ZvQ={"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive","x-vercel-ai-ui-message-stream":"v1","x-accel-buffering":"no"};function WL1({status:A,statusText:Q,headers:w,stream:B,consumeSseStream:$}){let f=B.pipeThrough(new WvQ);if($){let[D,Y]=f.tee();f=D,$({stream:Y})}return new Response(f.pipeThrough(new TextEncoderStream),{status:A,statusText:Q,headers:HvQ(w,ZvQ)})}var Yd=z.record(z.string(),z_.optional()),Pz8=R50(()=>Dd(z.union([z.strictObject({type:z.literal("text-start"),id:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("text-delta"),id:z.string(),delta:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("text-end"),id:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("error"),errorText:z.string()}),z.strictObject({type:z.literal("tool-input-start"),toolCallId:z.string(),toolName:z.string(),providerExecuted:z.boolean().optional(),providerMetadata:b2.optional(),toolMetadata:Yd.optional(),dynamic:z.boolean().optional(),title:z.string().optional()}),z.strictObject({type:z.literal("tool-input-delta"),toolCallId:z.string(),inputTextDelta:z.string()}),z.strictObject({type:z.literal("tool-input-available"),toolCallId:z.string(),toolName:z.string(),input:z.unknown(),providerExecuted:z.boolean().optional(),providerMetadata:b2.optional(),toolMetadata:Yd.optional(),dynamic:z.boolean().optional(),title:z.string().optional()}),z.strictObject({type:z.literal("tool-input-error"),toolCallId:z.string(),toolName:z.string(),input:z.unknown(),providerExecuted:z.boolean().optional(),providerMetadata:b2.optional(),toolMetadata:Yd.optional(),dynamic:z.boolean().optional(),errorText:z.string(),title:z.string().optional()}),z.strictObject({type:z.literal("tool-approval-request"),approvalId:z.string(),toolCallId:z.string()}),z.strictObject({type:z.literal("tool-output-available"),toolCallId:z.string(),output:z.unknown(),providerExecuted:z.boolean().optional(),providerMetadata:b2.optional(),toolMetadata:Yd.optional(),dynamic:z.boolean().optional(),preliminary:z.boolean().optional()}),z.strictObject({type:z.literal("tool-output-error"),toolCallId:z.string(),errorText:z.string(),providerExecuted:z.boolean().optional(),providerMetadata:b2.optional(),toolMetadata:Yd.optional(),dynamic:z.boolean().optional()}),z.strictObject({type:z.literal("tool-output-denied"),toolCallId:z.string()}),z.strictObject({type:z.literal("reasoning-start"),id:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("reasoning-delta"),id:z.string(),delta:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("reasoning-end"),id:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("source-url"),sourceId:z.string(),url:z.string(),title:z.string().optional(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("source-document"),sourceId:z.string(),mediaType:z.string(),title:z.string(),filename:z.string().optional(),providerMetadata:b2.optional()}),z.strictObject({type:z.literal("file"),url:z.string(),mediaType:z.string(),providerMetadata:b2.optional()}),z.strictObject({type:z.custom((A)=>typeof A==="string"&&A.startsWith("data-"),{message:'Type must start with "data-"'}),id:z.string().optional(),data:z.unknown(),transient:z.boolean().optional()}),z.strictObject({type:z.literal("start-step")}),z.strictObject({type:z.literal("finish-step")}),z.strictObject({type:z.literal("start"),messageId:z.string().optional(),messageMetadata:z.unknown().optional()}),z.strictObject({type:z.literal("finish"),finishReason:z.enum(["stop","length","content-filter","tool-calls","error","other"]).optional(),messageMetadata:z.unknown().optional()}),z.strictObject({type:z.literal("abort"),reason:z.string().optional()}),z.strictObject({type:z.literal("message-metadata"),messageMetadata:z.unknown()})])));function KvQ(A){return A.type.startsWith("data-")}function Mg0(A){return A.type.startsWith("tool-")}function UvQ(A){return A.type==="dynamic-tool"}function ab1(A){return Mg0(A)||UvQ(A)}function tb1(A){return A.type.split("-").slice(1).join("-")}function GvQ({lastMessage:A,messageId:Q}){return{message:(A==null?void 0:A.role)==="assistant"?A:{id:Q,metadata:void 0,role:"assistant",parts:[]},activeTextParts:{},activeReasoningParts:{},partialToolCalls:{}}}function zvQ({stream:A,messageMetadataSchema:Q,dataPartSchemas:w,runUpdateMessageJob:B,onError:$,onToolCall:f,onData:D}){return A.pipeThrough(new TransformStream({async transform(Y,X){await B(async({state:H,write:W})=>{var Z,G,F,V;function b(j){let E=H.message.parts.filter(ab1).find((y)=>y.toolCallId===j);if(E==null)throw new gC({chunkType:"tool-invocation",chunkId:j,message:`No tool invocation found for tool call ID "${j}".`});return E}function L(j){var g;let E=H.message.parts.find((T)=>Mg0(T)&&T.toolCallId===j.toolCallId),y=j,h=E;if(E!=null){if(E.state=j.state,h.input=y.input,h.output=y.output,h.errorText=y.errorText,h.rawInput=y.rawInput,h.preliminary=y.preliminary,j.title!==void 0)h.title=j.title;if(j.toolMetadata!==void 0)h.toolMetadata=j.toolMetadata;h.providerExecuted=(g=y.providerExecuted)!=null?g:E.providerExecuted;let T=y.providerMetadata;if(T!=null)if(j.state==="output-available"||j.state==="output-error"){let S=E;S.resultProviderMetadata=T}else E.callProviderMetadata=T}else H.message.parts.push({type:`tool-${j.toolName}`,toolCallId:j.toolCallId,state:j.state,title:j.title,...j.toolMetadata!==void 0?{toolMetadata:j.toolMetadata}:{},input:y.input,output:y.output,rawInput:y.rawInput,errorText:y.errorText,providerExecuted:y.providerExecuted,preliminary:y.preliminary,...y.providerMetadata!=null&&(j.state==="output-available"||j.state==="output-error")?{resultProviderMetadata:y.providerMetadata}:{},...y.providerMetadata!=null&&!(j.state==="output-available"||j.state==="output-error")?{callProviderMetadata:y.providerMetadata}:{}})}function N(j){var g,E;let y=H.message.parts.find((S)=>S.type==="dynamic-tool"&&S.toolCallId===j.toolCallId),h=j,T=y;if(y!=null){if(y.state=j.state,T.toolName=j.toolName,T.input=h.input,T.output=h.output,T.errorText=h.errorText,T.rawInput=(g=h.rawInput)!=null?g:T.rawInput,T.preliminary=h.preliminary,j.title!==void 0)T.title=j.title;if(j.toolMetadata!==void 0)T.toolMetadata=j.toolMetadata;T.providerExecuted=(E=h.providerExecuted)!=null?E:y.providerExecuted;let S=h.providerMetadata;if(S!=null)if(j.state==="output-available"||j.state==="output-error"){let c=y;c.resultProviderMetadata=S}else y.callProviderMetadata=S}else H.message.parts.push({type:"dynamic-tool",toolName:j.toolName,toolCallId:j.toolCallId,state:j.state,input:h.input,output:h.output,errorText:h.errorText,preliminary:h.preliminary,providerExecuted:h.providerExecuted,title:j.title,...j.toolMetadata!==void 0?{toolMetadata:j.toolMetadata}:{},...h.providerMetadata!=null&&(j.state==="output-available"||j.state==="output-error")?{resultProviderMetadata:h.providerMetadata}:{},...h.providerMetadata!=null&&!(j.state==="output-available"||j.state==="output-error")?{callProviderMetadata:h.providerMetadata}:{}})}async function _(j){if(j!=null){let g=H.message.metadata!=null?HL1(H.message.metadata,j):j;if(Q!=null)await C50({value:g,schema:Q,context:{field:"message.metadata",entityId:H.message.id}});H.message.metadata=g}}switch(Y.type){case"text-start":{let j={type:"text",text:"",providerMetadata:Y.providerMetadata,state:"streaming"};H.activeTextParts[Y.id]=j,H.message.parts.push(j),W();break}case"text-delta":{let j=H.activeTextParts[Y.id];if(j==null)throw new gC({chunkType:"text-delta",chunkId:Y.id,message:`Received text-delta for missing text part with ID "${Y.id}". Ensure a "text-start" chunk is sent before any "text-delta" chunks.`});j.text+=Y.delta,j.providerMetadata=(Z=Y.providerMetadata)!=null?Z:j.providerMetadata,W();break}case"text-end":{let j=H.activeTextParts[Y.id];if(j==null)throw new gC({chunkType:"text-end",chunkId:Y.id,message:`Received text-end for missing text part with ID "${Y.id}". Ensure a "text-start" chunk is sent before any "text-end" chunks.`});j.state="done",j.providerMetadata=(G=Y.providerMetadata)!=null?G:j.providerMetadata,delete H.activeTextParts[Y.id],W();break}case"reasoning-start":{let j={type:"reasoning",text:"",providerMetadata:Y.providerMetadata,state:"streaming"};H.activeReasoningParts[Y.id]=j,H.message.parts.push(j),W();break}case"reasoning-delta":{let j=H.activeReasoningParts[Y.id];if(j==null)throw new gC({chunkType:"reasoning-delta",chunkId:Y.id,message:`Received reasoning-delta for missing reasoning part with ID "${Y.id}". Ensure a "reasoning-start" chunk is sent before any "reasoning-delta" chunks.`});j.text+=Y.delta,j.providerMetadata=(F=Y.providerMetadata)!=null?F:j.providerMetadata,W();break}case"reasoning-end":{let j=H.activeReasoningParts[Y.id];if(j==null)throw new gC({chunkType:"reasoning-end",chunkId:Y.id,message:`Received reasoning-end for missing reasoning part with ID "${Y.id}". Ensure a "reasoning-start" chunk is sent before any "reasoning-end" chunks.`});j.providerMetadata=(V=Y.providerMetadata)!=null?V:j.providerMetadata,j.state="done",delete H.activeReasoningParts[Y.id],W();break}case"file":{H.message.parts.push({type:"file",mediaType:Y.mediaType,url:Y.url,...Y.providerMetadata!=null?{providerMetadata:Y.providerMetadata}:{}}),W();break}case"source-url":{H.message.parts.push({type:"source-url",sourceId:Y.sourceId,url:Y.url,title:Y.title,providerMetadata:Y.providerMetadata}),W();break}case"source-document":{H.message.parts.push({type:"source-document",sourceId:Y.sourceId,mediaType:Y.mediaType,title:Y.title,filename:Y.filename,providerMetadata:Y.providerMetadata}),W();break}case"tool-input-start":{let j=H.message.parts.filter(Mg0);if(H.partialToolCalls[Y.toolCallId]={text:"",toolName:Y.toolName,index:j.length,dynamic:Y.dynamic,title:Y.title,toolMetadata:Y.toolMetadata},Y.dynamic)N({toolCallId:Y.toolCallId,toolName:Y.toolName,state:"input-streaming",input:void 0,providerExecuted:Y.providerExecuted,title:Y.title,toolMetadata:Y.toolMetadata,providerMetadata:Y.providerMetadata});else L({toolCallId:Y.toolCallId,toolName:Y.toolName,state:"input-streaming",input:void 0,providerExecuted:Y.providerExecuted,title:Y.title,toolMetadata:Y.toolMetadata,providerMetadata:Y.providerMetadata});W();break}case"tool-input-delta":{let j=H.partialToolCalls[Y.toolCallId];if(j==null)throw new gC({chunkType:"tool-input-delta",chunkId:Y.toolCallId,message:`Received tool-input-delta for missing tool call with ID "${Y.toolCallId}". Ensure a "tool-input-start" chunk is sent before any "tool-input-delta" chunks.`});j.text+=Y.inputTextDelta;let{value:g}=await Xd(j.text);if(j.dynamic)N({toolCallId:Y.toolCallId,toolName:j.toolName,state:"input-streaming",input:g,title:j.title,toolMetadata:j.toolMetadata});else L({toolCallId:Y.toolCallId,toolName:j.toolName,state:"input-streaming",input:g,title:j.title,toolMetadata:j.toolMetadata});W();break}case"tool-input-available":{if(Y.dynamic)N({toolCallId:Y.toolCallId,toolName:Y.toolName,state:"input-available",input:Y.input,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,title:Y.title,toolMetadata:Y.toolMetadata});else L({toolCallId:Y.toolCallId,toolName:Y.toolName,state:"input-available",input:Y.input,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,title:Y.title,toolMetadata:Y.toolMetadata});if(W(),f&&!Y.providerExecuted)await f({toolCall:Y});break}case"tool-input-error":{let j=H.message.parts.filter(ab1).find((E)=>E.toolCallId===Y.toolCallId);if(j!=null?j.type==="dynamic-tool":!!Y.dynamic)N({toolCallId:Y.toolCallId,toolName:Y.toolName,state:"output-error",input:Y.input,errorText:Y.errorText,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,toolMetadata:Y.toolMetadata});else L({toolCallId:Y.toolCallId,toolName:Y.toolName,state:"output-error",input:void 0,rawInput:Y.input,errorText:Y.errorText,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,toolMetadata:Y.toolMetadata});W();break}case"tool-approval-request":{let j=b(Y.toolCallId);j.state="approval-requested",j.approval={id:Y.approvalId},W();break}case"tool-output-denied":{let j=b(Y.toolCallId);j.state="output-denied",W();break}case"tool-output-available":{let j=b(Y.toolCallId);if(j.type==="dynamic-tool")N({toolCallId:Y.toolCallId,toolName:j.toolName,state:"output-available",input:j.input,output:Y.output,preliminary:Y.preliminary,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,title:j.title,toolMetadata:j.toolMetadata});else L({toolCallId:Y.toolCallId,toolName:tb1(j),state:"output-available",input:j.input,output:Y.output,providerExecuted:Y.providerExecuted,preliminary:Y.preliminary,providerMetadata:Y.providerMetadata,title:j.title,toolMetadata:j.toolMetadata});W();break}case"tool-output-error":{let j=b(Y.toolCallId);if(j.type==="dynamic-tool")N({toolCallId:Y.toolCallId,toolName:j.toolName,state:"output-error",input:j.input,errorText:Y.errorText,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,title:j.title,toolMetadata:j.toolMetadata});else L({toolCallId:Y.toolCallId,toolName:tb1(j),state:"output-error",input:j.input,rawInput:j.rawInput,errorText:Y.errorText,providerExecuted:Y.providerExecuted,providerMetadata:Y.providerMetadata,title:j.title,toolMetadata:j.toolMetadata});W();break}case"start-step":{H.message.parts.push({type:"step-start"});break}case"finish-step":{H.activeTextParts={},H.activeReasoningParts={};break}case"start":{if(Y.messageId!=null)H.message.id=Y.messageId;if(await _(Y.messageMetadata),Y.messageId!=null||Y.messageMetadata!=null)W();break}case"finish":{if(Y.finishReason!=null)H.finishReason=Y.finishReason;if(await _(Y.messageMetadata),Y.messageMetadata!=null)W();break}case"message-metadata":{if(await _(Y.messageMetadata),Y.messageMetadata!=null)W();break}case"error":{$==null||$(Error(Y.errorText));break}default:if(KvQ(Y)){if((w==null?void 0:w[Y.type])!=null){let E=H.message.parts.findIndex((h)=>("id"in h)&&("data"in h)&&h.id===Y.id&&h.type===Y.type),y=E>=0?E:H.message.parts.length;await C50({value:Y.data,schema:w[Y.type],context:{field:`message.parts[${y}].data`,entityName:Y.type,entityId:Y.id}})}let j=Y;if(j.transient){D==null||D(j);break}let g=j.id!=null?H.message.parts.find((E)=>j.type===E.type&&j.id===E.id):void 0;if(g!=null)g.data=j.data;else H.message.parts.push(j);D==null||D(j),W()}}X.enqueue(Y)})}}))}function qvQ({messageId:A,originalMessages:Q=[],onStepFinish:w,onFinish:B,onError:$,stream:f}){let D=Q==null?void 0:Q[Q.length-1];if((D==null?void 0:D.role)!=="assistant")D=void 0;else A=D.id;let Y=!1,X=f.pipeThrough(new TransformStream({transform(V,b){if(V.type==="start"){let L=V;if(L.messageId==null&&A!=null)L.messageId=A}if(V.type==="abort")Y=!0;b.enqueue(V)}}));if(B==null&&w==null)return X;let H=GvQ({lastMessage:D?structuredClone(D):void 0,messageId:A!=null?A:""}),W=async(V)=>{await V({state:H,write:()=>{}})},Z=!1,G=async()=>{if(Z||!B)return;Z=!0;let V=H.message.id===(D==null?void 0:D.id);await B({isAborted:Y,isContinuation:V,responseMessage:H.message,messages:[...V?Q.slice(0,-1):Q,H.message],finishReason:H.finishReason})},F=async()=>{if(!w)return;let V=H.message.id===(D==null?void 0:D.id);try{await w({isContinuation:V,responseMessage:structuredClone(H.message),messages:[...V?Q.slice(0,-1):Q,structuredClone(H.message)]})}catch(b){$(b)}};return zvQ({stream:X,runUpdateMessageJob:W,onError:$}).pipeThrough(new TransformStream({async transform(V,b){if(V.type==="finish-step")await F();b.enqueue(V)},async cancel(){await G()},async flush(){await G()}}))}var kz8=O3({prefix:"aitxt",size:24});function ZL1({execute:A,onError:Q=Lg0,originalMessages:w,onStepFinish:B,onFinish:$,generateId:f=ib1}){let D,Y=[],X=new ReadableStream({start(Z){D=Z}});function H(Z){try{D.enqueue(Z)}catch(G){}}try{let Z=A({writer:{write(G){H(G)},merge(G){Y.push((async()=>{let F=G.getReader();while(!0){let{done:V,value:b}=await F.read();if(V)break;H(b)}})().catch((F)=>{H({type:"error",errorText:Q(F)})}))},onError:Q}});if(Z)Y.push(Z.catch((G)=>{H({type:"error",errorText:Q(G)})}))}catch(Z){H({type:"error",errorText:Q(Z)})}return new Promise(async(Z)=>{while(Y.length>0)await Y.shift();Z()}).finally(()=>{try{D.close()}catch(Z){}}),qvQ({stream:X,messageId:f(),originalMessages:w,onStepFinish:B,onFinish:$,onError:Q})}var kD=z.record(z.string(),z_.optional()),hz8=R50(()=>Dd(z.array(z.object({id:z.string(),role:z.enum(["system","user","assistant"]),metadata:z.unknown().optional(),parts:z.array(z.union([z.object({type:z.literal("text"),text:z.string(),state:z.enum(["streaming","done"]).optional(),providerMetadata:b2.optional()}),z.object({type:z.literal("reasoning"),text:z.string(),state:z.enum(["streaming","done"]).optional(),providerMetadata:b2.optional()}),z.object({type:z.literal("source-url"),sourceId:z.string(),url:z.string(),title:z.string().optional(),providerMetadata:b2.optional()}),z.object({type:z.literal("source-document"),sourceId:z.string(),mediaType:z.string(),title:z.string(),filename:z.string().optional(),providerMetadata:b2.optional()}),z.object({type:z.literal("file"),mediaType:z.string(),filename:z.string().optional(),url:z.string(),providerMetadata:b2.optional()}),z.object({type:z.literal("step-start")}),z.object({type:z.string().startsWith("data-"),id:z.string().optional(),data:z.unknown()}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("input-streaming"),input:z.unknown().optional(),providerExecuted:z.boolean().optional(),callProviderMetadata:b2.optional(),output:z.never().optional(),errorText:z.never().optional(),approval:z.never().optional()}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("input-available"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.never().optional()}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("approval-requested"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.never().optional(),reason:z.never().optional()})}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("approval-responded"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.boolean(),reason:z.string().optional()})}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("output-available"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.unknown(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),resultProviderMetadata:b2.optional(),preliminary:z.boolean().optional(),approval:z.object({id:z.string(),approved:z.literal(!0),reason:z.string().optional()}).optional()}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("output-error"),input:z.unknown().optional(),rawInput:z.unknown().optional(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.string(),callProviderMetadata:b2.optional(),resultProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.literal(!0),reason:z.string().optional()}).optional()}),z.object({type:z.literal("dynamic-tool"),toolName:z.string(),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("output-denied"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.literal(!1),reason:z.string().optional()})}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("input-streaming"),providerExecuted:z.boolean().optional(),callProviderMetadata:b2.optional(),input:z.unknown().optional(),output:z.never().optional(),errorText:z.never().optional(),approval:z.never().optional()}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("input-available"),providerExecuted:z.boolean().optional(),input:z.unknown(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.never().optional()}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("approval-requested"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.never().optional(),reason:z.never().optional()})}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("approval-responded"),input:z.unknown(),providerExecuted:z.boolean().optional(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.boolean(),reason:z.string().optional()})}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("output-available"),providerExecuted:z.boolean().optional(),input:z.unknown(),output:z.unknown(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),resultProviderMetadata:b2.optional(),preliminary:z.boolean().optional(),approval:z.object({id:z.string(),approved:z.literal(!0),reason:z.string().optional()}).optional()}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("output-error"),providerExecuted:z.boolean().optional(),input:z.unknown().optional(),rawInput:z.unknown().optional(),output:z.never().optional(),errorText:z.string(),callProviderMetadata:b2.optional(),resultProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.literal(!0),reason:z.string().optional()}).optional()}),z.object({type:z.string().startsWith("tool-"),toolCallId:z.string(),toolMetadata:kD.optional(),state:z.literal("output-denied"),providerExecuted:z.boolean().optional(),input:z.unknown(),output:z.never().optional(),errorText:z.never().optional(),callProviderMetadata:b2.optional(),approval:z.object({id:z.string(),approved:z.literal(!1),reason:z.string().optional()})})])).nonempty("Message must contain at least one part")})).nonempty("Messages array must not be empty")));var Cz8=O3({prefix:"aiobj",size:24});function KL1(A){return({url:Q,abortSignal:w})=>ihQ({url:Q,maxBytes:A==null?void 0:A.maxBytes,abortSignal:w})}var Ez8=O3({prefix:"aiobj",size:24});var gz8=KL1();var FvQ="AI_NoSuchProviderError",VvQ=`vercel.ai.error.${FvQ}`,IvQ=Symbol.for(VvQ),JvQ;JvQ=IvQ;var Tz8=KL1();var UL1={name:"@brains/web-chat",private:!0,version:"0.2.0-alpha.134",description:"Web chat interface for Brains",type:"module",exports:{".":"./src/index.ts"},files:["src","dist","package.json"],scripts:{build:"bun scripts/build-ui.ts","build:ui":"bun scripts/build-ui.ts",typecheck:"tsc --noEmit && tsc --noEmit -p ui-react/tsconfig.json",lint:"eslint . --ext .ts,.tsx","lint:fix":"eslint . --ext .ts,.tsx --fix",test:"bun test"},dependencies:{"@ai-sdk/react":"^3.0.116","@brains/auth-service":"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.86","class-variance-authority":"^0.7.0",cmdk:"^1.1.1","lucide-react":"^1.16.0",nanoid:"^5.0.4","radix-ui":"^1.4.3",react:"^19.2.6","react-dom":"^19.2.6",shiki:"^4.1.0",streamdown:"^2.5.0","use-stick-to-bottom":"^1.1.4"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","@types/react":"^19.0.3","@types/react-dom":"^19.0.3",typescript:"^5.3.3",vite:"^7.2.4"}};c0();async function GL1(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 qL1({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 D=MN("document",f.content);if(!D)return new Response("Document content is not a PDF",{status:415});let Y=_N(f.metadata,$,"document",D.mimeType);return FL1({requestUrl:B,data:D.data,mediaType:D.mimeType,filename:Y})}async function zL1(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 qL1({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 D=MN("image",f.content);if(!D)return new Response("Image content is not an image",{status:415});let Y=_N(f.metadata,$,"image",D.mimeType);return FL1({requestUrl:B,data:D.data,mediaType:D.mimeType,filename:Y})}async function qL1(A){let Q={entityType:A.entityType,id:A.id},w=await PN({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 FL1(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":pV({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}Z0();c0();var Hd="upload",VL1=aO;var LvQ={namespace:"upload",refKind:Hd,routePath:"/api/chat/uploads"};function y50(){return LvQ}c0();UG0();var IL1=Y00;var JL1=X00;var NvQ="file",jvQ=16384;async function bL1(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>JL1+jvQ)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(NvQ);if(!($ instanceof File))return new Response("Missing upload file",{status:400});let f=Buffer.from(await $.arrayBuffer()),D=Kq({filename:$.name,mediaType:$.type,content:f});if(!D.ok)return new Response(D.message,{status:400});let Y=Q.getUploadStore(),X=await Y.save({filename:D.filename,mediaType:D.mediaType,content:f});return Response.json(Y.toResponseBody(X),{status:201})}async function LL1(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 ML1(w,Q.getUploadStore());if(B instanceof Response)return B;let{record:$,content:f}=B,D=_L1($,f);if(D instanceof Response)return D;let Y=new URL(A.url).searchParams.has("download")?"attachment":"inline",X=new Uint8Array(f).buffer;return new Response(X,{headers:{"Content-Type":$.mediaType,"Content-Length":String(f.byteLength),"Content-Disposition":pV({disposition:Y,filename:$.filename})}})}function NL1(A){let Q=Zq(A.filename??IL1),w=_vQ(A.url);if(!w)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let B=Kq({filename:Q,mediaType:A.mediaType,content:w.buffer});if(!B.ok)return new Response(B.message,{status:400});return PL1(B,w.buffer)}async function jL1(A,Q){let w=await ML1(A,Q);if(w instanceof Response)return w;let{record:B,content:$}=w,f=_L1(B,$);if(f instanceof Response)return f;return PL1(f,$,{kind:Hd,id:A})}async function ML1(A,Q){try{return await Q.read(A)}catch(w){if(w instanceof zU)return MvQ(w);throw w}}function _L1(A,Q){let w=Kq({filename:A.filename,mediaType:A.mediaType,content:Q});if(!w.ok)return new Response(w.message,{status:400});return w}function PL1(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 MvQ(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 _vQ(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 PvQ=K.object({type:K.literal("text"),text:K.string()}),kvQ=K.object({type:K.literal("file"),mediaType:K.string().optional(),filename:K.string().optional(),url:K.string()}),OvQ=K.object({state:K.literal("approval-responded"),approval:K.object({id:K.string(),approved:K.boolean()})}).passthrough(),xvQ=K.object({id:K.string().optional(),role:K.string(),parts:K.array(K.unknown()).optional(),content:K.string().optional()}),kL1=K.object({id:K.string().optional(),messages:K.array(xvQ).min(1),trigger:K.string().optional()}),RvQ=K.object({kind:K.literal(Hd),id:K.string().regex(VL1)}),hvQ=K.object({type:K.literal("data-upload"),data:K.object({ref:RvQ})});async function OL1(A,Q){let w=vvQ(A);if(!w)return{message:"",attachments:[]};let B=[],$=[];for(let D of w.parts??[]){let Y=PvQ.safeParse(D);if(Y.success){if(Y.data.text.length>0)B.push(Y.data.text);continue}let X=kvQ.safeParse(D);if(X.success){let W=NL1(X.data);if(W instanceof Response)return W;$.push(W);continue}let H=hvQ.safeParse(D);if(H.success){let W=await jL1(H.data.data.ref.id,Q.uploadStore);if(W instanceof Response)return W;$.push(W);continue}if(CvQ(D)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:B.length>0?B.join(`
2429
2429
 
2430
2430
  `):w.content??"",attachments:$,...w.id?{messageId:w.id}:{}}}function xL1(A){let Q=A.messages.at(-1);if(!Q||Q.role==="user")return[];return(Q.parts??[]).map((w)=>OvQ.safeParse(w)).filter((w)=>w.success).map((w)=>w.data.approval)}function vvQ(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 CvQ(A){if(typeof A!=="object"||A===null||!("type"in A))return;let Q=A.type;return typeof Q==="string"?Q:void 0}c0();var yvQ=/\n{0,2}\[Entities affected this turn: [\s\S]*? Reference these IDs directly in follow-ups instead of searching for them\.\]\s*$/;function E50(A){return A.replace(yvQ,"").trimEnd()}c0();function RL1(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 _g0(A,Q,w=new Set){for(let B of Q){if(B.kind==="attachment"&&w.has(B.id))continue;let $=G00(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,D=$.input??{};switch(A.write({type:"tool-input-available",toolCallId:f,toolName:$.toolName,input:D,dynamic:!0,title:$.preview?`${$.summary}
2431
2431
 
@@ -4726,7 +4726,7 @@ details.web-chat-data-part[open] > summary > .web-chat-data-part-chevron {
4726
4726
 
4727
4727
  `);$=D.pop()??"";for(let Y of D){let X=Y.split(`
4728
4728
  `).find((L)=>L.startsWith("data: "));if(!X)continue;let H;try{H=JSON.parse(X.slice(6))}catch{return w.cancel().catch(()=>{}),{success:!1,error:"Malformed SSE event from remote agent"}}let W=H.result;if(!W)continue;if(W.final!==!0)continue;w.cancel().catch(()=>{});let G=W.status,F=G?.state??"unknown",b=(G?.message?.parts??[]).filter((L)=>L.kind==="text"&&typeof L.text==="string").map((L)=>L.text).join(`
4729
- `)||"No response text";return{success:!0,data:{state:F,response:b}}}f=await DN1(w,Q)}return{success:!1,error:"Stream ended without a terminal event"}}class Wd extends Error{timeoutMs;constructor(A){super(`request timed out after ${A}ms`);this.timeoutMs=A;this.name="A2ARequestTimeoutError"}}class Zd extends Error{timeoutMs;constructor(A){super(`A2A stream stalled waiting for final event after ${A}ms`);this.timeoutMs=A;this.name="A2AStreamIdleTimeoutError"}}async function XCQ(A,Q,w,B){let $=new AbortController,f;try{return await Promise.race([A(Q,{...w,signal:$.signal}),new Promise((D,Y)=>{f=setTimeout(()=>{$.abort(),Y(new Wd(B))},B)})])}catch(D){if(D instanceof Wd)throw D;if($.signal.aborted)throw new Wd(B);throw D}finally{if(f)clearTimeout(f)}}async function DN1(A,Q){let w;try{return await Promise.race([A.read(),new Promise((B,$)=>{w=setTimeout(()=>$(new Zd(Q)),Q)})])}catch(B){if(B instanceof Zd)A.cancel().catch(()=>{});throw B}finally{if(w)clearTimeout(w)}}function HCQ(A){if(A instanceof Wd||A instanceof Zd)return!0;return A instanceof Error}function WCQ(A,Q){let w=Q>1?` after ${Q} attempts`:"";if(A instanceof Zd)return`${A.message}${w}`;let B=A instanceof Error?A.message:"Unknown network error";return`Failed to reach remote agent${w}: ${B}`}function XN1(A={}){let Q=A.fetch??globalThis.fetch,w={requestTimeoutMs:A.requestTimeoutMs??wCQ,streamIdleTimeoutMs:A.streamIdleTimeoutMs??BCQ,maxNetworkAttempts:A.maxNetworkAttempts??$CQ};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:BN1,visibility:"trusted",sideEffects:"external",handler:async(B)=>{let $=K.object(BN1).safeParse(B);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};let{agent:f,message:D}=$.data,Y=fCQ(f);if(!Y.ok)return{success:!1,error:Y.error};let{agentId:X}=Y;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:X,visibilityScope:R9("agent_call tool is anchor-only and resolves saved remote agents at any visibility")});if(!H){if(!DCQ(X))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 V=`https://${X}`,b=await $N1(V,Q);if(!b)return{success:!1,error:`Could not verify an A2A Agent Card for ${X}. Connect/save it first if you want to add it to the directory.`,code:"agent_card_unavailable"};let L=await fN1(b.url,D,Q,void 0,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:X},agentContactCandidate:{source:{kind:"url",url:Y.sourceUrl??X}}}}}return L}if(H.metadata.status==="archived")return{success:!1,error:`Agent ${X} 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 ${X} is discovered but not approved yet. Approve it first.`,code:"agent_not_approved"};let W=`https://${X}`,Z=await $N1(W,Q);if(!Z)return{success:!1,error:`Could not fetch Agent Card from ${W}`};let G=Z.url,F;if(A.outboundTokens)try{let V=new URL(G).hostname;F=A.outboundTokens[V]}catch{}return fN1(G,D,Q,F,w)}}}var Cg0={name:"@brains/a2a",private:!0,version:"0.2.0-alpha.133",type:"module",main:"./src/index.ts",module:"./src/index.ts",types:"./src/index.ts",files:["src"],scripts:{typecheck:"tsc --noEmit",lint:"eslint --max-warnings 0 .","lint:fix":"eslint --fix .",test:"bun test"},dependencies:{"@a2a-js/sdk":"^0.3.12","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",hono:"^4.7.10"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14",typescript:"^5.3.3"}};var KCQ={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization","X-Content-Type-Options":"nosniff"};class SC extends GU{agentCard;taskManager=new hg0;agentService;permissionContext;app;hasWebserver=!1;constructor(A={}){super("a2a",Cg0,A,oL1)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,this.permissionContext=A.permissions,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"),$=this.config.trustedTokens&&Object.keys(this.config.trustedTokens).length>0,f;if(A.entityService.hasEntityType("skill"))try{let D=await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}});if(D.length>0)f=D.map((Y)=>jY.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=sL1({character:Q,profile:w,version:Cg0.version,domain:A.domain,organization:this.config.organization,tools:B,skills:f,authEnabled:$}),this.logger.debug("Agent Card rebuilt",{skills:this.agentCard.skills.length})}getAgentCard(){return this.agentCard}resolveCallerPermission(A){if(!A?.startsWith("Bearer ")||!this.config.trustedTokens)return"public";let Q=A.slice(7),w=this.config.trustedTokens[Q];if(!w||!this.permissionContext)return"public";return this.permissionContext.getUserLevel("a2a",w)}withCors(A){let Q=new Headers(A.headers);for(let[w,B]of Object.entries(KCQ))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 vC;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;try{w=await Q.req.json()}catch{return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32700,message:"Parse error"},id:null}))}let B=eL1.safeParse(w);if(!B.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32600,message:"Invalid request"},id:null}));let $=this.resolveCallerPermission(Q.req.header("Authorization"));if(B.data.method==="message/stream"){let D=QN1.safeParse(B.data.params??{});if(!D.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${D.error.message}`},id:B.data.id}));let{stream:Y}=wN1(B.data.id,D.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$});return this.withCors(new Response(Y,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let f=await AN1(B.data,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$});return this.withCors(Q.json(f))}),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}]}async getTools(){return[XN1({outboundTokens:this.config.outboundTokens,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")}}}}c0();class yg0{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 D=await w({type:"directory-import",data:{paths:[f]}});this.logger.debug("Queued import job for file change",{jobId:D,path:f})},this.handleDelete=async(f)=>{if(!this.deleteOnFileRemoval){this.logger.warn("File deleted but deleteOnFileRemoval is disabled",{path:f});return}try{let{entityType:D,id:Y}=this.fileOperations.parseEntityFromPath(f),X=await w({type:"directory-delete",data:{entityId:Y,entityType:D,filePath:f}});this.logger.info("Queued delete job for removed file",{jobId:X,path:f,entityId:Y,entityType:D})}catch(D){this.logger.warn("Could not extract entity info from deleted file",{path:f,error:D})}};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})}}}var _M1=Y1(NM1(),1);import{extname as WSQ}from"path";var B$0=[".png",".jpg",".jpeg",".webp",".gif",".svg"];function I_(A){let Q=WSQ(A).toLowerCase();return B$0.includes(Q)}function jM1(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 CT0(A){switch(A.toLowerCase()){case"jpeg":return".jpg";case"svg+xml":return".svg";default:return`.${A.toLowerCase()}`}}import{isAbsolute as ZSQ,relative as KSQ,sep as MM1,join as USQ}from"path";function sH(A,Q){return ZSQ(Q)?Q:USQ(A,Q)}function dC(A,Q){let w=sH(A,Q),B=KSQ(A,w);return MM1==="/"?B:B.split(MM1).join("/")}function GSQ(A,Q){if(!dC(Q,A).startsWith("image/"))return!1;return I_(A)}function zSQ(A,Q){if(dC(Q,A).split("/")[0]?.startsWith("_"))return!1;if(A.endsWith(".md"))return!0;return GSQ(A,Q)}class yT0{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=_M1.default.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(!zSQ(Q,this.syncPath))return;this.logger.debug("File change detected",{event:A,path:Q});let w=dC(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=sH(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 PM1(A,Q){if(A?.isWatching())return Q.logger.debug("Already watching directory"),A;return qSQ(Q)}function kM1(A){if(A)A.stop();return}function OM1(A,Q){if(A)A.setCallback(Q)}async function qSQ(A){let{logger:Q,syncPath:w,watchInterval:B,importEntities:$,jobQueueCallback:f,fileOperations:D,deleteOnFileRemoval:Y}=A,X=new yg0(Q,$,f,D,Y),H=new yT0({syncPath:w,watchInterval:B,logger:Q,onFileChange:async(W,Z)=>{await X.handleFileChange(W,Z)}});return await H.start(),H}async function xM1(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:$}}c0();class ET0{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??S$(),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 gT0{syncInProgress=!1;logger;fileOperations;batchOperationsManager;constructor(A){this.logger=A.logger,this.fileOperations=A.fileOperations,this.batchOperationsManager=new ET0({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 TT0{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 LSQ,dirname as NSQ,extname as jSQ}from"path";import{extname as FSQ}from"path";var $$0=[".pdf"],RM1=".meta.json";function J_(A){let Q=FSQ(A).toLowerCase();return $$0.includes(Q)}function hM1(A){return A.toLowerCase().endsWith(RM1)}function ST0(A){return`${A}${RM1}`}function vM1(A){switch(A.toLowerCase().replace(".","")){case"pdf":default:return"application/pdf"}}import{extname as VSQ,join as f$0}from"path";function D$0(A,Q){let B=dC(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 D;if(f.length>1){let Y=f[f.length-1];if(Y)f[f.length-1]=CM1(Y);D=f.join(":")}else D=CM1(f[0]??"");return{entityType:$,id:D}}function yM1(A,Q,w,B=".md"){let $=Q.split(":").filter((H)=>H.length>0),f=w==="note";if($.length===1)return f?f$0(A,`${$[0]}${B}`):f$0(A,w,`${$[0]}${B}`);let D=$;if($[0]===w)D=$.slice(1);let Y=D[D.length-1],X=D.slice(0,-1);if(f)return f$0(A,...X,`${Y}${B}`);return f$0(A,w,...X,`${Y}${B}`)}function EM1(A){if(A.entityType==="document")return".pdf";if(A.entityType!=="image")return".md";let Q=A.metadata.format;if(Q)return CT0(Q);let w=A.content.match(/^data:image\/([a-z+]+);base64,/i);return w?.[1]?CT0(w[1]):".md"}function CM1(A){let Q=VSQ(A).toLowerCase();return Q===".md"||B$0.includes(Q)||$$0.includes(Q)?A.slice(0,-Q.length):A}bY();import{mkdir as MSQ,readFile as nC,writeFile as uT0,stat as _SQ,utimes as PSQ}from"fs/promises";import{join as Y$0}from"path";import{mkdir as gM1,readdir as JSQ,stat as bSQ}from"fs/promises";import{access as ISQ}from"fs/promises";async function y5(A){try{return await ISQ(A),!0}catch{return!1}}async function mT0(A,Q){return uM1(A,Q,{includeDocuments:!1,includeImages:!1})}async function TM1(A,Q){return uM1(A,Q,{includeDocuments:!0,includeImages:!0})}async function SM1(A,Q){if(!await y5(A))await gM1(A,{recursive:!0});for(let w of Q)if(w!=="note")await gM1(Y$0(A,w),{recursive:!0})}async function mM1(A,Q){let w=[],B={totalFiles:0,byEntityType:{}};if(!await y5(A))return{files:w,stats:B};let $=await mT0(A,Q);for(let f of $)try{let D=Y$0(A,f),Y=await bSQ(D),{entityType:X}=D$0(A,f);w.push({path:f,entityType:X,modified:Y.mtime}),B.totalFiles++,B.byEntityType[X]=(B.byEntityType[X]??0)+1}catch{continue}return{files:w,stats:B}}async function uM1(A,Q,w){let B=[];if(!await y5(A))return B;let $=async(f,D="",Y=!1,X=!1)=>{let H=await JSQ(f,{withFileTypes:!0});for(let W of H){let Z=D?Y$0(D,W.name):W.name;if(W.isFile()&&!W.name.endsWith(".invalid")&&!hM1(W.name)){if(W.name.endsWith(".md"))B.push(Z);else if(w.includeImages&&Y&&I_(W.name))B.push(Z);else if(w.includeDocuments&&X&&J_(W.name))B.push(Z)}else if(W.isDirectory()&&!W.name.startsWith(".")){if(D===""&&!Q.hasEntityType(W.name))continue;let G=Y$0(f,W.name),F=W.name==="image"&&D==="",V=W.name==="document"&&D==="";await $(G,Z,Y||F,X||V)}}};return await $(A),B}function kSQ(A){return typeof A==="object"&&A!==null}class cT0{syncPath;entityService;constructor(A,Q){this.syncPath=A,this.entityService=Q}parseEntityFromPath(A){return D$0(this.syncPath,A)}async readEntity(A){let Q=sH(this.syncPath,A),w=await _SQ(Q),{entityType:B,id:$}=this.parseEntityFromPath(A),f=w.birthtime.getTime()>0?w.birthtime:w.mtime,D=w.mtime,Y,X;if(I_(A)||J_(A)){let Z=(await nC(Q)).toString("base64"),G=jSQ(A);if(Y=`data:${J_(A)?vM1(G):jM1(G)};base64,${Z}`,J_(A))X=await this.readDocumentSidecar(Q,A)}else Y=await nC(Q,"utf-8");let H={entityType:B,id:$,content:Y,created:f,updated:D};if(X)H.metadata=X;return H}async readDocumentSidecar(A,Q){let w={mimeType:"application/pdf",filename:LSQ(Q)},B=ST0(A);if(!await y5(B))return w;try{let $=await nC(B,"utf-8"),f=JSON.parse($),D=kSQ(f)?f:{};return{...w,...D}}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,D=A.content.match(f),Y=D?.[1]?Buffer.from(D[1],"base64"):Buffer.from(A.content,"base64"),X=!1;if(await y5(Q)){let H=await nC(Q),W=xw(H.toString("base64")),Z=xw(Y.toString("base64"));if(W===Z)X=!0}if(!X)await this.ensureEntityDirectory(A,Q),await uT0(Q,Y);if(B)await this.writeDocumentSidecar(A,Q);if(X)return}else{let f=this.entityService.serializeEntity(A);if(await y5(Q)){let D=await nC(Q,"utf-8"),Y=xw(D),X=xw(f);if(Y===X)return}await this.ensureEntityDirectory(A,Q),await uT0(Q,f,"utf-8")}let $=new Date(A.updated);await PSQ(Q,$,$)}async ensureEntityDirectory(A,Q){if(A.entityType!=="note")await MSQ(NSQ(Q),{recursive:!0})}async writeDocumentSidecar(A,Q){let w=A.metadata,B={};for(let[D,Y]of Object.entries(w)){if(D==="mimeType")continue;if(Y===void 0)continue;B[D]=Y}let $=ST0(Q),f=`${JSON.stringify(B,null,2)}
4729
+ `)||"No response text";return{success:!0,data:{state:F,response:b}}}f=await DN1(w,Q)}return{success:!1,error:"Stream ended without a terminal event"}}class Wd extends Error{timeoutMs;constructor(A){super(`request timed out after ${A}ms`);this.timeoutMs=A;this.name="A2ARequestTimeoutError"}}class Zd extends Error{timeoutMs;constructor(A){super(`A2A stream stalled waiting for final event after ${A}ms`);this.timeoutMs=A;this.name="A2AStreamIdleTimeoutError"}}async function XCQ(A,Q,w,B){let $=new AbortController,f;try{return await Promise.race([A(Q,{...w,signal:$.signal}),new Promise((D,Y)=>{f=setTimeout(()=>{$.abort(),Y(new Wd(B))},B)})])}catch(D){if(D instanceof Wd)throw D;if($.signal.aborted)throw new Wd(B);throw D}finally{if(f)clearTimeout(f)}}async function DN1(A,Q){let w;try{return await Promise.race([A.read(),new Promise((B,$)=>{w=setTimeout(()=>$(new Zd(Q)),Q)})])}catch(B){if(B instanceof Zd)A.cancel().catch(()=>{});throw B}finally{if(w)clearTimeout(w)}}function HCQ(A){if(A instanceof Wd||A instanceof Zd)return!0;return A instanceof Error}function WCQ(A,Q){let w=Q>1?` after ${Q} attempts`:"";if(A instanceof Zd)return`${A.message}${w}`;let B=A instanceof Error?A.message:"Unknown network error";return`Failed to reach remote agent${w}: ${B}`}function XN1(A={}){let Q=A.fetch??globalThis.fetch,w={requestTimeoutMs:A.requestTimeoutMs??wCQ,streamIdleTimeoutMs:A.streamIdleTimeoutMs??BCQ,maxNetworkAttempts:A.maxNetworkAttempts??$CQ};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:BN1,visibility:"trusted",sideEffects:"external",handler:async(B)=>{let $=K.object(BN1).safeParse(B);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};let{agent:f,message:D}=$.data,Y=fCQ(f);if(!Y.ok)return{success:!1,error:Y.error};let{agentId:X}=Y;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:X,visibilityScope:R9("agent_call tool is anchor-only and resolves saved remote agents at any visibility")});if(!H){if(!DCQ(X))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 V=`https://${X}`,b=await $N1(V,Q);if(!b)return{success:!1,error:`Could not verify an A2A Agent Card for ${X}. Connect/save it first if you want to add it to the directory.`,code:"agent_card_unavailable"};let L=await fN1(b.url,D,Q,void 0,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:X},agentContactCandidate:{source:{kind:"url",url:Y.sourceUrl??X}}}}}return L}if(H.metadata.status==="archived")return{success:!1,error:`Agent ${X} 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 ${X} is discovered but not approved yet. Approve it first.`,code:"agent_not_approved"};let W=`https://${X}`,Z=await $N1(W,Q);if(!Z)return{success:!1,error:`Could not fetch Agent Card from ${W}`};let G=Z.url,F;if(A.outboundTokens)try{let V=new URL(G).hostname;F=A.outboundTokens[V]}catch{}return fN1(G,D,Q,F,w)}}}var Cg0={name:"@brains/a2a",private:!0,version:"0.2.0-alpha.134",type:"module",main:"./src/index.ts",module:"./src/index.ts",types:"./src/index.ts",files:["src"],scripts:{typecheck:"tsc --noEmit",lint:"eslint --max-warnings 0 .","lint:fix":"eslint --fix .",test:"bun test"},dependencies:{"@a2a-js/sdk":"^0.3.12","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",hono:"^4.7.10"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14",typescript:"^5.3.3"}};var KCQ={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization","X-Content-Type-Options":"nosniff"};class SC extends GU{agentCard;taskManager=new hg0;agentService;permissionContext;app;hasWebserver=!1;constructor(A={}){super("a2a",Cg0,A,oL1)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,this.permissionContext=A.permissions,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"),$=this.config.trustedTokens&&Object.keys(this.config.trustedTokens).length>0,f;if(A.entityService.hasEntityType("skill"))try{let D=await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}});if(D.length>0)f=D.map((Y)=>jY.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=sL1({character:Q,profile:w,version:Cg0.version,domain:A.domain,organization:this.config.organization,tools:B,skills:f,authEnabled:$}),this.logger.debug("Agent Card rebuilt",{skills:this.agentCard.skills.length})}getAgentCard(){return this.agentCard}resolveCallerPermission(A){if(!A?.startsWith("Bearer ")||!this.config.trustedTokens)return"public";let Q=A.slice(7),w=this.config.trustedTokens[Q];if(!w||!this.permissionContext)return"public";return this.permissionContext.getUserLevel("a2a",w)}withCors(A){let Q=new Headers(A.headers);for(let[w,B]of Object.entries(KCQ))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 vC;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;try{w=await Q.req.json()}catch{return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32700,message:"Parse error"},id:null}))}let B=eL1.safeParse(w);if(!B.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32600,message:"Invalid request"},id:null}));let $=this.resolveCallerPermission(Q.req.header("Authorization"));if(B.data.method==="message/stream"){let D=QN1.safeParse(B.data.params??{});if(!D.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${D.error.message}`},id:B.data.id}));let{stream:Y}=wN1(B.data.id,D.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$});return this.withCors(new Response(Y,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let f=await AN1(B.data,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$});return this.withCors(Q.json(f))}),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}]}async getTools(){return[XN1({outboundTokens:this.config.outboundTokens,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")}}}}c0();class yg0{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 D=await w({type:"directory-import",data:{paths:[f]}});this.logger.debug("Queued import job for file change",{jobId:D,path:f})},this.handleDelete=async(f)=>{if(!this.deleteOnFileRemoval){this.logger.warn("File deleted but deleteOnFileRemoval is disabled",{path:f});return}try{let{entityType:D,id:Y}=this.fileOperations.parseEntityFromPath(f),X=await w({type:"directory-delete",data:{entityId:Y,entityType:D,filePath:f}});this.logger.info("Queued delete job for removed file",{jobId:X,path:f,entityId:Y,entityType:D})}catch(D){this.logger.warn("Could not extract entity info from deleted file",{path:f,error:D})}};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})}}}var _M1=Y1(NM1(),1);import{extname as WSQ}from"path";var B$0=[".png",".jpg",".jpeg",".webp",".gif",".svg"];function I_(A){let Q=WSQ(A).toLowerCase();return B$0.includes(Q)}function jM1(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 CT0(A){switch(A.toLowerCase()){case"jpeg":return".jpg";case"svg+xml":return".svg";default:return`.${A.toLowerCase()}`}}import{isAbsolute as ZSQ,relative as KSQ,sep as MM1,join as USQ}from"path";function sH(A,Q){return ZSQ(Q)?Q:USQ(A,Q)}function dC(A,Q){let w=sH(A,Q),B=KSQ(A,w);return MM1==="/"?B:B.split(MM1).join("/")}function GSQ(A,Q){if(!dC(Q,A).startsWith("image/"))return!1;return I_(A)}function zSQ(A,Q){if(dC(Q,A).split("/")[0]?.startsWith("_"))return!1;if(A.endsWith(".md"))return!0;return GSQ(A,Q)}class yT0{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=_M1.default.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(!zSQ(Q,this.syncPath))return;this.logger.debug("File change detected",{event:A,path:Q});let w=dC(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=sH(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 PM1(A,Q){if(A?.isWatching())return Q.logger.debug("Already watching directory"),A;return qSQ(Q)}function kM1(A){if(A)A.stop();return}function OM1(A,Q){if(A)A.setCallback(Q)}async function qSQ(A){let{logger:Q,syncPath:w,watchInterval:B,importEntities:$,jobQueueCallback:f,fileOperations:D,deleteOnFileRemoval:Y}=A,X=new yg0(Q,$,f,D,Y),H=new yT0({syncPath:w,watchInterval:B,logger:Q,onFileChange:async(W,Z)=>{await X.handleFileChange(W,Z)}});return await H.start(),H}async function xM1(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:$}}c0();class ET0{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??S$(),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 gT0{syncInProgress=!1;logger;fileOperations;batchOperationsManager;constructor(A){this.logger=A.logger,this.fileOperations=A.fileOperations,this.batchOperationsManager=new ET0({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 TT0{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 LSQ,dirname as NSQ,extname as jSQ}from"path";import{extname as FSQ}from"path";var $$0=[".pdf"],RM1=".meta.json";function J_(A){let Q=FSQ(A).toLowerCase();return $$0.includes(Q)}function hM1(A){return A.toLowerCase().endsWith(RM1)}function ST0(A){return`${A}${RM1}`}function vM1(A){switch(A.toLowerCase().replace(".","")){case"pdf":default:return"application/pdf"}}import{extname as VSQ,join as f$0}from"path";function D$0(A,Q){let B=dC(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 D;if(f.length>1){let Y=f[f.length-1];if(Y)f[f.length-1]=CM1(Y);D=f.join(":")}else D=CM1(f[0]??"");return{entityType:$,id:D}}function yM1(A,Q,w,B=".md"){let $=Q.split(":").filter((H)=>H.length>0),f=w==="note";if($.length===1)return f?f$0(A,`${$[0]}${B}`):f$0(A,w,`${$[0]}${B}`);let D=$;if($[0]===w)D=$.slice(1);let Y=D[D.length-1],X=D.slice(0,-1);if(f)return f$0(A,...X,`${Y}${B}`);return f$0(A,w,...X,`${Y}${B}`)}function EM1(A){if(A.entityType==="document")return".pdf";if(A.entityType!=="image")return".md";let Q=A.metadata.format;if(Q)return CT0(Q);let w=A.content.match(/^data:image\/([a-z+]+);base64,/i);return w?.[1]?CT0(w[1]):".md"}function CM1(A){let Q=VSQ(A).toLowerCase();return Q===".md"||B$0.includes(Q)||$$0.includes(Q)?A.slice(0,-Q.length):A}bY();import{mkdir as MSQ,readFile as nC,writeFile as uT0,stat as _SQ,utimes as PSQ}from"fs/promises";import{join as Y$0}from"path";import{mkdir as gM1,readdir as JSQ,stat as bSQ}from"fs/promises";import{access as ISQ}from"fs/promises";async function y5(A){try{return await ISQ(A),!0}catch{return!1}}async function mT0(A,Q){return uM1(A,Q,{includeDocuments:!1,includeImages:!1})}async function TM1(A,Q){return uM1(A,Q,{includeDocuments:!0,includeImages:!0})}async function SM1(A,Q){if(!await y5(A))await gM1(A,{recursive:!0});for(let w of Q)if(w!=="note")await gM1(Y$0(A,w),{recursive:!0})}async function mM1(A,Q){let w=[],B={totalFiles:0,byEntityType:{}};if(!await y5(A))return{files:w,stats:B};let $=await mT0(A,Q);for(let f of $)try{let D=Y$0(A,f),Y=await bSQ(D),{entityType:X}=D$0(A,f);w.push({path:f,entityType:X,modified:Y.mtime}),B.totalFiles++,B.byEntityType[X]=(B.byEntityType[X]??0)+1}catch{continue}return{files:w,stats:B}}async function uM1(A,Q,w){let B=[];if(!await y5(A))return B;let $=async(f,D="",Y=!1,X=!1)=>{let H=await JSQ(f,{withFileTypes:!0});for(let W of H){let Z=D?Y$0(D,W.name):W.name;if(W.isFile()&&!W.name.endsWith(".invalid")&&!hM1(W.name)){if(W.name.endsWith(".md"))B.push(Z);else if(w.includeImages&&Y&&I_(W.name))B.push(Z);else if(w.includeDocuments&&X&&J_(W.name))B.push(Z)}else if(W.isDirectory()&&!W.name.startsWith(".")){if(D===""&&!Q.hasEntityType(W.name))continue;let G=Y$0(f,W.name),F=W.name==="image"&&D==="",V=W.name==="document"&&D==="";await $(G,Z,Y||F,X||V)}}};return await $(A),B}function kSQ(A){return typeof A==="object"&&A!==null}class cT0{syncPath;entityService;constructor(A,Q){this.syncPath=A,this.entityService=Q}parseEntityFromPath(A){return D$0(this.syncPath,A)}async readEntity(A){let Q=sH(this.syncPath,A),w=await _SQ(Q),{entityType:B,id:$}=this.parseEntityFromPath(A),f=w.birthtime.getTime()>0?w.birthtime:w.mtime,D=w.mtime,Y,X;if(I_(A)||J_(A)){let Z=(await nC(Q)).toString("base64"),G=jSQ(A);if(Y=`data:${J_(A)?vM1(G):jM1(G)};base64,${Z}`,J_(A))X=await this.readDocumentSidecar(Q,A)}else Y=await nC(Q,"utf-8");let H={entityType:B,id:$,content:Y,created:f,updated:D};if(X)H.metadata=X;return H}async readDocumentSidecar(A,Q){let w={mimeType:"application/pdf",filename:LSQ(Q)},B=ST0(A);if(!await y5(B))return w;try{let $=await nC(B,"utf-8"),f=JSON.parse($),D=kSQ(f)?f:{};return{...w,...D}}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,D=A.content.match(f),Y=D?.[1]?Buffer.from(D[1],"base64"):Buffer.from(A.content,"base64"),X=!1;if(await y5(Q)){let H=await nC(Q),W=xw(H.toString("base64")),Z=xw(Y.toString("base64"));if(W===Z)X=!0}if(!X)await this.ensureEntityDirectory(A,Q),await uT0(Q,Y);if(B)await this.writeDocumentSidecar(A,Q);if(X)return}else{let f=this.entityService.serializeEntity(A);if(await y5(Q)){let D=await nC(Q,"utf-8"),Y=xw(D),X=xw(f);if(Y===X)return}await this.ensureEntityDirectory(A,Q),await uT0(Q,f,"utf-8")}let $=new Date(A.updated);await PSQ(Q,$,$)}async ensureEntityDirectory(A,Q){if(A.entityType!=="note")await MSQ(NSQ(Q),{recursive:!0})}async writeDocumentSidecar(A,Q){let w=A.metadata,B={};for(let[D,Y]of Object.entries(w)){if(D==="mimeType")continue;if(Y===void 0)continue;B[D]=Y}let $=ST0(Q),f=`${JSON.stringify(B,null,2)}
4730
4730
  `;if(await y5($)){if(await nC($,"utf-8")===f)return}await this.ensureEntityDirectory(A,$),await uT0($,f,"utf-8")}getFilePath(A,Q,w=".md"){return yM1(this.syncPath,A,Q,w)}getEntityFilePath(A){return this.getFilePath(A.id,A.entityType,EM1(A))}async getAllMarkdownFiles(){return mT0(this.syncPath,this.entityService)}async getAllSyncFiles(){return TM1(this.syncPath,this.entityService)}async ensureDirectoryStructure(A){await SM1(this.syncPath,A)}shouldUpdateEntity(A,Q){let w=xw(Q.content);return A.contentHash!==w}async gatherFileStatus(){return mM1(this.syncPath,this.entityService)}async syncDirectoryExists(){return y5(this.syncPath)}async fileExists(A){return y5(A)}}D4();Z0();D4();async function X$0(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 D=await w($),{base64:Y}=fI(D),X=Yj(Y),H=DI(Y);if(!X||!H)throw Error("Could not detect image format or dimensions");let W=await Q.createEntity({entity:{id:A.id,entityType:"image",content:D,metadata:{title:A.title,alt:A.alt,format:X,width:H.width,height:H.height,sourceUrl:$}}});return B.debug("Created image entity from URL",{sourceUrl:$,imageId:W.entityId}),W.entityId}var cM1=K.object({title:K.string(),slug:K.string().optional(),coverImageUrl:K.string().url(),coverImageId:K.string().optional(),coverImageAlt:K.string().optional()});class lT0{entityService;fetcher;logger;constructor(A,Q,w=NH){this.entityService=A;this.fetcher=w;this.logger=Q.child("FrontmatterImageConverter")}detectCoverImageUrl(A){let Q;try{Q=lw(A)}catch{return null}let{frontmatter:w}=Q,B=cM1.safeParse(w);if(!B.success)return null;if(B.data.coverImageId)return null;let{title:$,slug:f,coverImageUrl:D,coverImageAlt:Y}=B.data;if(!rz(D))return null;return{sourceUrl:D,postTitle:$,postSlug:f??w1($),customAlt:Y}}async convert(A){let Q;try{Q=lw(A)}catch(H){return this.logger.debug("Parse failed",{error:H}),{content:A,converted:!1}}let{frontmatter:w}=Q,B=cM1.safeParse(w);if(!B.success)return{content:A,converted:!1};if(B.data.coverImageId)return{content:A,converted:!1};let{title:$,slug:f,coverImageUrl:D,coverImageAlt:Y}=B.data;if(!rz(D))return{content:A,converted:!1};let X={postTitle:$,postSlug:f??w1($),sourceUrl:D,customAlt:Y};try{let H=await this.createImageEntity(X),W={...w};return delete W.coverImageUrl,delete W.coverImageAlt,W.coverImageId=H,{content:iz(W,Q.content),converted:!0,imageId:H}}catch(H){return this.logger.warn("Failed to convert coverImageUrl",{url:D,error:vA(H)}),{content:A,converted:!1}}}async createImageEntity(A){let{postTitle:Q,postSlug:w,sourceUrl:B,customAlt:$}=A,f=`Cover image for ${Q}`;return X$0({id:`${w}-cover`,title:f,alt:$??f,sourceUrl:B},this.entityService,this.fetcher,this.logger)}}D4();Z0();class Md{entityService;fetcher;logger;constructor(A,Q,w=NH){this.entityService=A;this.fetcher=w;this.logger=Q.child("MarkdownImageConverter")}detectInlineImages(A,Q){let w=[],B=Sb0(A);for(let $ of B){if(!rz($.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 D of w)try{let Y=await this.createImageEntity(D,f++),X=`![${D.alt}](entity://image/${Y})`;B=B.replace(D.originalMarkdown,X),$++,this.logger.debug("Converted inline image",{sourceUrl:D.sourceUrl,imageId:Y})}catch(Y){this.logger.warn("Failed to convert inline image",{sourceUrl:D.sourceUrl,error:vA(Y)})}return{content:B,converted:$>0,convertedCount:$}}async createImageEntity(A,Q){let{sourceUrl:w,alt:B,postSlug:$}=A;return X$0({id:`${$}-inline-${Q}`,title:B||`Inline image ${Q+1} for ${$}`,alt:B||"",sourceUrl:w},this.entityService,this.fetcher,this.logger)}}class pT0{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(),D=f.length;await Q.report({progress:0,message:`Starting import of ${D} files`});for(let Y=0;Y<D;Y+=w){let X=f.slice(Y,Y+w),H=await B(X);$.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 W=Math.min(Y+w,D),Z=Math.round(W/D*40);await Q.report({progress:Z,message:`Imported ${W}/${D} 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}}Z0();import{rename as OSQ,appendFile as xSQ,readFile as RSQ,writeFile as hSQ,access as vSQ}from"fs/promises";import{join as lM1}from"path";class iT0{logger;syncPath;constructor(A,Q){this.logger=A;this.syncPath=Q}isValidationError(A){if(A instanceof K.ZodError)return!0;let Q=vA(A);return Q.includes("invalid_type")||Q.includes("invalid_enum_value")||Q.includes("Required")||Q.includes("Invalid frontmatter")||Q.includes("Unknown entity type")}async quarantineInvalidFile(A,Q,w,B){let $=B(A),f=`${$}.invalid`;try{await OSQ($,f),w.quarantined++,w.quarantinedFiles.push(A);let D=lM1(this.syncPath,".import-errors.log"),Y=new Date().toISOString(),X=vA(Q),H=`${Y} - ${A}: ${X}
4731
4731
  \u2192 ${A}.invalid
4732
4732
 
@@ -4754,7 +4754,7 @@ details.web-chat-data-part[open] > summary > .web-chat-data-part-chevron {
4754
4754
  *...and ${A.files.length-10} more files*`)}if(A.exists&&A.stats.totalFiles===0)Q.push(`
4755
4755
  ## Getting Started
4756
4756
  `),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(`
4757
- `)}}c0();class y$0 extends _w{directorySync;constructor(A,Q,w){super(A,{schema:iS0,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}}}c0();class E$0 extends _w{directorySync;constructor(A,Q,w){super(A,{schema:pS0,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}}}c0();class g$0 extends _w{directorySync;context;constructor(A,Q,w){super(A,{schema:cS0,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:[]},D={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 X=$==="export"?10:60;await w.report({progress:X,message:"Exporting entities to directory"}),D=await this.exportWithProgress(A.entityTypes,w),await w.report({progress:100,message:$==="export"?`Export complete: ${D.exported} exported`:`Sync complete: ${f.imported} imported, ${D.exported} exported`})}let Y=Date.now()-B;return this.logger.info("Directory sync job completed",{jobId:Q,duration:Y,imported:f.imported,exported:D.exported}),{import:f,export:D,duration:Y}}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(),D=async()=>{let X=(await Promise.all(A.map((W)=>w.getAsyncJobStatus(W)))).filter((W)=>W&&(W.status==="completed"||W.status==="failed")).length;if(X===A.length){this.logger.debug("All import jobs completed");return}if(Date.now()-f>B){this.logger.warn(`Timeout waiting for import jobs (${X}/${A.length} completed)`);return}let H=Math.round(X/A.length*100);return await Q.report({progress:50+Math.round(H*0.05),message:`Processing ${X}/${A.length} entities`}),await new Promise((W)=>setTimeout(W,$)),D()};return D()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}c0();class T$0 extends _w{context;directorySync;gitSync;constructor(A,Q,w,B){super(A,{schema:lS0,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`}),klQ(B)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function klQ(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}c0();class S$0 extends _w{context;constructor(A,Q,w){super(A,{schema:v$0,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,w){let B=v$0.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}}}c0();Z0();var OlQ=K.object({});class m$0 extends _w{directorySync;constructor(A,Q){super(A,{schema:OlQ,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}}c0();D4();Z0();CB();D4();import{readFile as xlQ,writeFile as RlQ}from"fs/promises";var hlQ=dS0;class u$0 extends _w{context;fetcher;constructor(A,Q,w=NH){super(Q,{schema:hlQ,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=w}async process(A,Q,w){let{filePath:B,sourceUrl:$,postTitle:f,postSlug:D,customAlt:Y}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:B,sourceUrl:$,postSlug:D});try{await this.reportProgress(w,{progress:_Q.INIT,message:`Reading file: ${B}`});let X;try{X=await xlQ(B,"utf-8")}catch(b){return this.logger.error("Failed to read file",{filePath:B,error:vA(b)}),x6.failure(b)}let H;try{H=lw(X)}catch(b){return this.logger.warn("Failed to parse markdown",{filePath:B,error:vA(b)}),x6.failure(b)}let W=H.frontmatter;if(W.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:B}),await this.reportProgress(w,{progress:_Q.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(w,{progress:_Q.FETCH,message:"Checking for existing image"});let Z=await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:$}},limit:1}}),G;if(Z[0])G=Z[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:$,imageId:G}),await this.reportProgress(w,{progress:_Q.EXTRACT,message:`Reusing existing image: ${G}`});else{await this.reportProgress(w,{progress:_Q.PROCESS,message:`Fetching image from ${$}`});let b;try{b=await this.fetcher($)}catch(E){return this.logger.error("Failed to fetch image",{sourceUrl:$,error:vA(E)}),x6.failure(E)}await this.reportProgress(w,{progress:_Q.GENERATE,message:"Creating image entity"});let{base64:L}=fI(b),N=Yj(L),_=DI(L);if(!N||!_)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:$}),x6.failure(Error("Could not detect image format or dimensions"));G=`${D}-cover`;let j=`Cover image for ${f}`,g=Y??j;await this.context.entityService.createEntity({entity:{id:G,entityType:"image",content:b,metadata:{title:j,alt:g,format:N,width:_.width,height:_.height,sourceUrl:$}}}),this.logger.debug("Created image entity",{imageId:G,sourceUrl:$}),await this.reportProgress(w,{progress:_Q.EXTRACT,message:`Created image: ${G}`})}await this.reportProgress(w,{progress:_Q.SAVE,message:"Updating file"});let F={...W};delete F.coverImageUrl,delete F.coverImageAlt,F.coverImageId=G;let V=iz(F,H.content);try{await RlQ(B,V,"utf-8")}catch(b){return this.logger.error("Failed to write file",{filePath:B,error:vA(b)}),x6.failure(b)}return await this.reportProgress(w,{progress:_Q.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:B,imageId:G,sourceUrl:$}),{success:!0,imageId:G}}catch(X){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:B,error:vA(X)}),x6.failure(X)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}c0();D4();Z0();CB();import{readFile as vlQ,writeFile as ClQ}from"fs/promises";class c$0 extends _w{converter;constructor(A,Q,w=NH){super(Q,{schema:nS0,jobTypeName:"inline-image-convert"});this.converter=new Md(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:_Q.INIT,message:`Reading file: ${B}`});let f;try{f=await vlQ(B,"utf-8")}catch(X){let H=vA(X);return this.logger.error("Failed to read file",{filePath:B,error:H}),{success:!1,error:H}}await this.reportProgress(w,{progress:_Q.FETCH,message:"Detecting inline images"});let D=this.converter.detectInlineImages(f,$);if(D.length===0)return this.logger.debug("No inline images to convert",{filePath:B}),await this.reportProgress(w,{progress:_Q.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:B,count:D.length}),await this.reportProgress(w,{progress:_Q.PROCESS,message:`Converting ${D.length} images`});let Y=await this.converter.convert(f,$);if(!Y.converted)return this.logger.debug("No images were converted",{filePath:B}),await this.reportProgress(w,{progress:_Q.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(w,{progress:_Q.SAVE,message:"Writing updated file"});try{await ClQ(B,Y.content,"utf-8")}catch(X){let H=vA(X);return this.logger.error("Failed to write file",{filePath:B,error:H}),{success:!1,error:H}}return await this.reportProgress(w,{progress:_Q.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:B,convertedCount:Y.convertedCount}),{success:!0,convertedCount:Y.convertedCount}}catch(f){let D=vA(f);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:B,error:D}),{success:!1,error:D}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function bO1(A,Q,w){let B=($)=>w.child($);A.jobs.registerHandler("directory-sync",new g$0(B("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new y$0(B("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new E$0(B("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new S$0(B("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new m$0(B("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new u$0(A,B("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new c$0(A,B("InlineImageConversionJobHandler"))),w.debug("Registered async job handlers")}c0();import{unlink as ylQ,access as ElQ}from"fs/promises";function LO1(A,Q,w,B){let{subscribe:$}=A.messaging,{entityService:f}=A;$("entity:created",async(D)=>{let{entity:Y}=D.payload;try{await Q.fileOps.writeEntity(Y),w.debug("Auto-exported created entity",{id:Y.id,entityType:Y.entityType})}catch(X){w.error("Auto-export FAILED for created entity",{id:Y.id,entityType:Y.entityType,error:X instanceof Error?X.message:String(X),stack:X instanceof Error?X.stack:void 0})}return{success:!0}}),$("entity:updated",async(D)=>{let{entityType:Y,entityId:X}=D.payload;try{let H=await f.getEntity({entityType:Y,id:X});if(!H)return w.debug("Entity not found in DB, skipping export",{entityType:Y,entityId:X}),{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:Y,entityId:X,error:H instanceof Error?H.message:String(H),stack:H instanceof Error?H.stack:void 0})}return{success:!0}}),$("entity:deleted",async(D)=>{let{entityId:Y,entityType:X}=D.payload,H=Q.fileOps.getFilePath(Y,X);if(await ElQ(H).then(()=>!0,()=>!1))await ylQ(H),w.debug("Auto-deleted entity file",{id:Y,entityType:X,path:H});return{success:!0}}),w.debug("Setup auto-sync for entity events",{entityTypes:B})}function NO1(A,Q,w){Q.setJobQueueCallback(async(B)=>{let $=[{type:B.type,data:B.data}];return A.jobs.enqueueBatch($,{priority:5,source:"directory-sync-watcher",rootJobId:S$(),metadata:{operationType:"file_operations",operationTarget:w,pluginId:"directory-sync"}})})}Z0();c0();import{readdir as _O1,mkdir as TlQ,copyFile as SlQ}from"fs/promises";import{join as MO1,resolve as rS0}from"path";import{join as glQ}from"path";async function jO1(A){if(!await y5(glQ(A,".git")))return!1;try{return await AK(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function mlQ(A,Q){if(!await y5(A))return!0;if((await _O1(A)).filter(($)=>!$.startsWith(".")&&!$.startsWith("_")).length>0)return!1;if(await jO1(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function PO1(A,Q){let w=await _O1(A,{withFileTypes:!0});for(let B of w){let $=MO1(A,B.name),f=MO1(Q,B.name);if(B.isDirectory()){if(!await y5(f))await TlQ(f,{recursive:!0});await PO1($,f)}else await SlQ($,f)}}async function kO1(A,Q,w){let B=rS0(process.cwd(),A);w=w?rS0(w):rS0(process.cwd(),"seed-content");let $=await mlQ(B,Q);if($&&await y5(w))Q.debug("Copying seed content to brain-data directory"),await PO1(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 OO1(A,Q,w,B,$){let f=!1,D=async()=>{if(f)return;f=!0;let Y=Q();if(w.seedContent){let X=w.syncPath??A.dataDir;await kO1(X,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 X=await Y.sync();B.debug("Initial sync completed",{imported:X.import.imported,failed:X.import.failed,duration:X.duration}),await A.messaging.send({type:VN.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(X){B.error("Initial sync failed",X),await A.messaging.send({type:VN.initialSyncCompleted,payload:{success:!1,error:vA(X)},...{broadcast:!0}})}};A.messaging.subscribe(VN.pluginsRegistered,async()=>{return B.debug("Plugins registered, starting initial sync"),await D(),{success:!0}})}Z0();function xO1(A,Q,w,B){let $=new wN(()=>{Q.withLock(async()=>{try{await Q.commit(),await Q.push()}catch(Y){B.error("Git auto-commit failed",{error:Y})}})},w),f=["entity:created","entity:updated","entity:deleted"],D=[];for(let Y of f){let X=A.subscribe(Y,async()=>{return $.trigger(),{success:!0}});D.push(X)}return()=>{$.dispose();for(let Y of D)Y()}}function RO1(A,Q,w,B,$){if(B<=0)return()=>{};let f=B*60*1000,D=!1,Y=async()=>{if(D)return;D=!0;try{let{files:H,result:W}=await A.withLock(async()=>{let Z=await A.pull();if(Z.files.length===0)return{files:[],result:null};let G=await Q.queueSyncBatch(w,"periodic-sync");return{files:Z.files,result:G}});if(H.length>0)$.info("Periodic sync: pulled changes",{filesChanged:H.length});if(W)$.debug("Periodic sync: queued imports",{importOperations:W.importOperationsCount,totalFiles:W.totalFiles})}catch(H){$.error("Periodic git sync failed",{error:H})}finally{D=!1}},X=setInterval(()=>{Y()},f);return $.info("Started periodic git sync",{intervalMinutes:B}),()=>{clearInterval(X)}}import{spawnSync as vO1}from"child_process";import{cpSync as ulQ,existsSync as hO1,mkdirSync as clQ,mkdtempSync as llQ,rmSync as plQ}from"fs";import{tmpdir as ilQ}from"os";import{fileURLToPath as dlQ}from"url";import{join as nlQ,resolve as rlQ}from"path";function dJ(A,Q){let w=vO1("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 olQ(A){return A.startsWith("file://")}function slQ(A){return dlQ(A)}function alQ(A,Q){return vO1("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function CO1(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!olQ(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",w=slQ(A.gitUrl),B=rlQ(A.seedContentPath);if(!hO1(B))throw Error(`Seed content path not found: ${B}`);if(!hO1(w))A.logger.debug("Creating local bare content remote",{remotePath:w,branch:Q}),clQ(w,{recursive:!0}),dJ(process.cwd(),["init","--bare",`--initial-branch=${Q}`,w]);if(alQ(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 $=llQ(nlQ(ilQ(),"directory-sync-seed-"));try{dJ($,["init",`--initial-branch=${Q}`]),dJ($,["config","user.name",A.authorName??"Brain"]),dJ($,["config","user.email",A.authorEmail??"brain@localhost"]),ulQ(B,$,{recursive:!0}),dJ($,["add","."]),dJ($,["commit","-m","seed content remote"]),dJ($,["remote","add","origin",A.gitUrl]),dJ($,["push","-u","origin",Q])}finally{plQ($,{recursive:!0,force:!0})}}function yO1(A,Q,w,B,$){let{subscribe:f}=A.messaging;f("entity:export:request",async(D)=>{try{return{success:!0,data:await Q().exportEntities(D.payload.entityTypes)}}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:"Export failed"}}}),f("entity:import:request",async(D)=>{try{let Y=Q(),X=D.payload.paths,H=await Y.importEntities(X);if(X&&X.length>0)await Y.removeOrphanedEntities();return{success:!0,data:H}}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:"Import failed"}}}),f("sync:status:request",async()=>{try{let Y=await Q().getStatus();return{success:!0,data:{syncPath:Y.syncPath,isInitialized:Y.exists,watchEnabled:Y.watching}}}catch(D){return{success:!1,error:D instanceof Error?D.message:"Status check failed"}}}),f("sync:configure:request",async(D)=>{try{return await w({syncPath:D.payload.syncPath}),{success:!0,data:{syncPath:D.payload.syncPath,configured:!0}}}catch(Y){return{success:!1,error:Y instanceof Error?Y.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")}c0();Z0();c0();Z0();function EO1(A,Q){return Sw(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",K.object({entityType:K.string().describe("Entity type (e.g. post, note, link)"),id:K.string().describe("Entity ID"),sha:K.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:K.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 l8({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 l8({commits:[]},`No history found for ${w.entityType}/${w.id}`);return l8({commits:$,entityType:w.entityType,id:w.id},`${$.length} version${$.length===1?"":"s"} found`)}catch($){return P9($ instanceof Error?$.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function gO1(A,Q,w,B){let $=[Sw(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.",K.object({}),async(f,D)=>{try{let Y=D.channelId?`${D.interfaceType}:${D.channelId}`:`plugin:${w}`,X={interfaceType:D.interfaceType,channelId:D.channelId};if(B){let W=await Q.jobs.enqueue({type:"sync-request",data:{source:Y,interfaceType:X.interfaceType,channelId:X.channelId},toolContext:D});return l8({jobId:W,status:"queued",gitPulled:!0},"Sync queued: git pull and filesystem scan will run in the background")}let H=await A.queueSyncBatch(Q,Y,X);if(!H)return l8({gitPulled:!1},"No files to sync");return l8({batchId:H.batchId,importOperations:H.importOperationsCount,totalFiles:H.totalFiles,gitPulled:!1},`Sync started: ${H.importOperationsCount} import jobs queued for ${H.totalFiles} files`)}catch(Y){return P9(Y instanceof Error?Y.message:"Sync failed")}},{visibility:"anchor",sideEffects:"external",cli:{name:"sync"}}),Sw(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.",K.object({}),async()=>{try{let f=await A.getStatus(),D={syncPath:f.syncPath,lastSync:f.lastSync?.toISOString(),watching:f.watching};if(B){let Y=await B.getStatus();D.git={isRepo:Y.isRepo,branch:Y.branch,hasChanges:Y.hasChanges,ahead:Y.ahead,behind:Y.behind,remote:Y.remote}}return l8(D)}catch(f){return P9(f instanceof Error?f.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if(B)$.push(EO1(w,B));return $}var TO1={name:"@brains/directory-sync",private:!0,version:"0.2.0-alpha.133",description:"Directory-based entity synchronization plugin for Brains",type:"module",main:"./src/index.ts",types:"./src/index.ts",exports:{".":{types:"./src/index.ts",import:"./src/index.ts"}},scripts:{test:"bun test",typecheck:"tsc --noEmit",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",clean:"rm -rf .turbo"},dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",chokidar:"^3.5.3","simple-git":"^3.21.0"},devDependencies:{"@brains/typescript-config":"workspace:*","@types/bun":"latest","@types/node":"^20.0.0",typescript:"^5.3.3"},peerDependencies:{}};class oS0 extends RQ{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",TO1,A,Td)}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:Sd,basePrompt:"",formatter:new C$0,requiredPermission:"anchor"}});let B=this.config.syncPath??A.dataDir;this.directorySync=new _d({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(D){throw this.logger.error("Failed to initialize directory",D),D}await this.registerJobHandlers(A);let $=this.requireDirectorySync();if(LO1(A,$,this.logger,this.config.entityTypes),this.config.autoSync)NO1(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 CO1({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 D=this.config.syncPath??A.dataDir;if(this.gitSync=new uS0({logger:this.logger.child("GitSync"),dataDir:D,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 T$0(this.logger.child("DirectorySyncRequestJobHandler"),A,this.requireDirectorySync(),this.gitSync)),this.gitCleanups.push(xO1(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(RO1(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)OO1(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync);yO1(A,()=>this.requireDirectorySync(),(D)=>this.configure(D),this.logger,this.config.git)}async getTools(){let A=this.requireDirectorySync();return gO1(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 _d({...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){bO1(A,this.requireDirectorySync(),this.logger)}}function j_(A={}){return new oS0(A)}c0();Z0();var SO1={name:"@brains/email-resend",private:!0,version:"0.2.0-alpha.133",description:"Generic email delivery adapter for Resend",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var ApQ=K.object({apiKey:K.string().min(1).optional(),from:K.string().min(1).optional()});class mO1 extends RQ{fetchImpl;constructor(A={},Q={}){super("email-resend",SO1,A,ApQ);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(rw0,async(w)=>{let B=LxA.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 $=await B.json();return $.id?{status:"sent",id:$.id}:{status:"sent"}}}function l$0(A={}){return new mO1(A)}c0();import{render as el1}from"preact-render-to-string";import{h as YP}from"preact";function uO1(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=uO1(A[Q]))&&(B&&(B+=" "),B+=w)}else for(w in A)A[w]&&(B&&(B+=" "),B+=w);return B}function Ay(){for(var A,Q,w=0,B="",$=arguments.length;w<$;w++)(A=arguments[w])&&(Q=uO1(A))&&(B&&(B+=" "),B+=Q);return B}var QpQ=(A)=>{let Q=BpQ(A),{conflictingClassGroups:w,conflictingClassGroupModifiers:B}=A;return{getClassGroupId:(D)=>{let Y=D.split("-");if(Y[0]===""&&Y.length!==1)Y.shift();return dO1(Y,Q)||wpQ(D)},getConflictingClassGroupIds:(D,Y)=>{let X=w[D]||[];if(Y&&B[D])return[...X,...B[D]];return X}}},dO1=(A,Q)=>{if(A.length===0)return Q.classGroupId;let w=A[0],B=Q.nextPart.get(w),$=B?dO1(A.slice(1),B):void 0;if($)return $;if(Q.validators.length===0)return;let f=A.join("-");return Q.validators.find(({validator:D})=>D(f))?.classGroupId},cO1=/^\[(.+)\]$/,wpQ=(A)=>{if(cO1.test(A)){let Q=cO1.exec(A)[1],w=Q?.substring(0,Q.indexOf(":"));if(w)return"arbitrary.."+w}},BpQ=(A)=>{let{theme:Q,prefix:w}=A,B={nextPart:new Map,validators:[]};return fpQ(Object.entries(A.classGroups),w).forEach(([f,D])=>{aS0(D,B,f,Q)}),B},aS0=(A,Q,w,B)=>{A.forEach(($)=>{if(typeof $==="string"){let f=$===""?Q:lO1(Q,$);f.classGroupId=w;return}if(typeof $==="function"){if($pQ($)){aS0($(B),Q,w,B);return}Q.validators.push({validator:$,classGroupId:w});return}Object.entries($).forEach(([f,D])=>{aS0(D,lO1(Q,f),w,B)})})},lO1=(A,Q)=>{let w=A;return Q.split("-").forEach((B)=>{if(!w.nextPart.has(B))w.nextPart.set(B,{nextPart:new Map,validators:[]});w=w.nextPart.get(B)}),w},$pQ=(A)=>A.isThemeGetter,fpQ=(A,Q)=>{if(!Q)return A;return A.map(([w,B])=>{let $=B.map((f)=>{if(typeof f==="string")return Q+f;if(typeof f==="object")return Object.fromEntries(Object.entries(f).map(([D,Y])=>[Q+D,Y]));return f});return[w,$]})},DpQ=(A)=>{if(A<1)return{get:()=>{return},set:()=>{}};let Q=0,w=new Map,B=new Map,$=(f,D)=>{if(w.set(f,D),Q++,Q>A)Q=0,B=w,w=new Map};return{get(f){let D=w.get(f);if(D!==void 0)return D;if((D=B.get(f))!==void 0)return $(f,D),D},set(f,D){if(w.has(f))w.set(f,D);else $(f,D)}}};var YpQ=(A)=>{let{separator:Q,experimentalParseClassName:w}=A,B=Q.length===1,$=Q[0],f=Q.length,D=(Y)=>{let X=[],H=0,W=0,Z;for(let L=0;L<Y.length;L++){let N=Y[L];if(H===0){if(N===$&&(B||Y.slice(L,L+f)===Q)){X.push(Y.slice(W,L)),W=L+f;continue}if(N==="/"){Z=L;continue}}if(N==="[")H++;else if(N==="]")H--}let G=X.length===0?Y:Y.substring(W),F=G.startsWith("!"),V=F?G.substring(1):G,b=Z&&Z>W?Z-W:void 0;return{modifiers:X,hasImportantModifier:F,baseClassName:V,maybePostfixModifierPosition:b}};if(w)return(Y)=>w({className:Y,parseClassName:D});return D},XpQ=(A)=>{if(A.length<=1)return A;let Q=[],w=[];return A.forEach((B)=>{if(B[0]==="[")Q.push(...w.sort(),B),w=[];else w.push(B)}),Q.push(...w.sort()),Q},HpQ=(A)=>({cache:DpQ(A.cacheSize),parseClassName:YpQ(A),...QpQ(A)}),WpQ=/\s+/,ZpQ=(A,Q)=>{let{parseClassName:w,getClassGroupId:B,getConflictingClassGroupIds:$}=Q,f=[],D=A.trim().split(WpQ),Y="";for(let X=D.length-1;X>=0;X-=1){let H=D[X],{modifiers:W,hasImportantModifier:Z,baseClassName:G,maybePostfixModifierPosition:F}=w(H),V=Boolean(F),b=B(V?G.substring(0,F):G);if(!b){if(!V){Y=H+(Y.length>0?" "+Y:Y);continue}if(b=B(G),!b){Y=H+(Y.length>0?" "+Y:Y);continue}V=!1}let L=XpQ(W).join(":"),N=Z?L+"!":L,_=N+b;if(f.includes(_))continue;f.push(_);let j=$(b,V);for(let g=0;g<j.length;++g){let E=j[g];f.push(N+E)}Y=H+(Y.length>0?" "+Y:Y)}return Y};function KpQ(){let A=0,Q,w,B="";while(A<arguments.length)if(Q=arguments[A++]){if(w=nO1(Q))B&&(B+=" "),B+=w}return B}var nO1=(A)=>{if(typeof A==="string")return A;let Q,w="";for(let B=0;B<A.length;B++)if(A[B]){if(Q=nO1(A[B]))w&&(w+=" "),w+=Q}return w};function pO1(A,...Q){let w,B,$,f=D;function D(X){let H=Q.reduce((W,Z)=>Z(W),A());return w=HpQ(H),B=w.cache.get,$=w.cache.set,f=Y,Y(X)}function Y(X){let H=B(X);if(H)return H;let W=ZpQ(X,w);return $(X,W),W}return function(){return f(KpQ.apply(null,arguments))}}var a8=(A)=>{let Q=(w)=>w[A]||[];return Q.isThemeGetter=!0,Q},rO1=/^\[(?:([a-z-]+):)?(.+)\]$/i,UpQ=/^\d+\/\d+$/,GpQ=new Set(["px","full","screen"]),zpQ=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,qpQ=/\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$/,FpQ=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,VpQ=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,IpQ=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,v3=(A)=>Qy(A)||GpQ.has(A)||UpQ.test(A),nJ=(A)=>wy(A,"length",PpQ),Qy=(A)=>Boolean(A)&&!Number.isNaN(Number(A)),sS0=(A)=>wy(A,"number",Qy),md=(A)=>Boolean(A)&&Number.isInteger(Number(A)),JpQ=(A)=>A.endsWith("%")&&Qy(A.slice(0,-1)),tQ=(A)=>rO1.test(A),rJ=(A)=>zpQ.test(A),bpQ=new Set(["length","size","percentage"]),LpQ=(A)=>wy(A,bpQ,oO1),NpQ=(A)=>wy(A,"position",oO1),jpQ=new Set(["image","url"]),MpQ=(A)=>wy(A,jpQ,OpQ),_pQ=(A)=>wy(A,"",kpQ),ud=()=>!0,wy=(A,Q,w)=>{let B=rO1.exec(A);if(B){if(B[1])return typeof Q==="string"?B[1]===Q:Q.has(B[1]);return w(B[2])}return!1},PpQ=(A)=>qpQ.test(A)&&!FpQ.test(A),oO1=()=>!1,kpQ=(A)=>VpQ.test(A),OpQ=(A)=>IpQ.test(A);var iO1=()=>{let A=a8("colors"),Q=a8("spacing"),w=a8("blur"),B=a8("brightness"),$=a8("borderColor"),f=a8("borderRadius"),D=a8("borderSpacing"),Y=a8("borderWidth"),X=a8("contrast"),H=a8("grayscale"),W=a8("hueRotate"),Z=a8("invert"),G=a8("gap"),F=a8("gradientColorStops"),V=a8("gradientColorStopPositions"),b=a8("inset"),L=a8("margin"),N=a8("opacity"),_=a8("padding"),j=a8("saturate"),g=a8("scale"),E=a8("sepia"),y=a8("skew"),h=a8("space"),T=a8("translate"),S=()=>["auto","contain","none"],c=()=>["auto","hidden","clip","visible","scroll"],m=()=>["auto",tQ,Q],B0=()=>[tQ,Q],a=()=>["",v3,nJ],v=()=>["auto",Qy,tQ],P=()=>["bottom","center","left","left-bottom","left-top","right","right-bottom","right-top","top"],x=()=>["solid","dashed","dotted","double","none"],l=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],p=()=>["start","end","center","between","around","evenly","stretch"],A0=()=>["","0",tQ],o=()=>["auto","avoid","all","avoid-page","page","left","right","column"],K0=()=>[Qy,tQ];return{cacheSize:500,separator:":",theme:{colors:[ud],spacing:[v3,nJ],blur:["none","",rJ,tQ],brightness:K0(),borderColor:[A],borderRadius:["none","","full",rJ,tQ],borderSpacing:B0(),borderWidth:a(),contrast:K0(),grayscale:A0(),hueRotate:K0(),invert:A0(),gap:B0(),gradientColorStops:[A],gradientColorStopPositions:[JpQ,nJ],inset:m(),margin:m(),opacity:K0(),padding:B0(),saturate:K0(),scale:K0(),sepia:A0(),skew:K0(),space:B0(),translate:B0()},classGroups:{aspect:[{aspect:["auto","square","video",tQ]}],container:["container"],columns:[{columns:[rJ]}],"break-after":[{"break-after":o()}],"break-before":[{"break-before":o()}],"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"],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:[...P(),tQ]}],overflow:[{overflow:c()}],"overflow-x":[{"overflow-x":c()}],"overflow-y":[{"overflow-y":c()}],overscroll:[{overscroll:S()}],"overscroll-x":[{"overscroll-x":S()}],"overscroll-y":[{"overscroll-y":S()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:[b]}],"inset-x":[{"inset-x":[b]}],"inset-y":[{"inset-y":[b]}],start:[{start:[b]}],end:[{end:[b]}],top:[{top:[b]}],right:[{right:[b]}],bottom:[{bottom:[b]}],left:[{left:[b]}],visibility:["visible","invisible","collapse"],z:[{z:["auto",md,tQ]}],basis:[{basis:m()}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["wrap","wrap-reverse","nowrap"]}],flex:[{flex:["1","auto","initial","none",tQ]}],grow:[{grow:A0()}],shrink:[{shrink:A0()}],order:[{order:["first","last","none",md,tQ]}],"grid-cols":[{"grid-cols":[ud]}],"col-start-end":[{col:["auto",{span:["full",md,tQ]},tQ]}],"col-start":[{"col-start":v()}],"col-end":[{"col-end":v()}],"grid-rows":[{"grid-rows":[ud]}],"row-start-end":[{row:["auto",{span:[md,tQ]},tQ]}],"row-start":[{"row-start":v()}],"row-end":[{"row-end":v()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":["auto","min","max","fr",tQ]}],"auto-rows":[{"auto-rows":["auto","min","max","fr",tQ]}],gap:[{gap:[G]}],"gap-x":[{"gap-x":[G]}],"gap-y":[{"gap-y":[G]}],"justify-content":[{justify:["normal",...p()]}],"justify-items":[{"justify-items":["start","end","center","stretch"]}],"justify-self":[{"justify-self":["auto","start","end","center","stretch"]}],"align-content":[{content:["normal",...p(),"baseline"]}],"align-items":[{items:["start","end","center","baseline","stretch"]}],"align-self":[{self:["auto","start","end","center","stretch","baseline"]}],"place-content":[{"place-content":[...p(),"baseline"]}],"place-items":[{"place-items":["start","end","center","baseline","stretch"]}],"place-self":[{"place-self":["auto","start","end","center","stretch"]}],p:[{p:[_]}],px:[{px:[_]}],py:[{py:[_]}],ps:[{ps:[_]}],pe:[{pe:[_]}],pt:[{pt:[_]}],pr:[{pr:[_]}],pb:[{pb:[_]}],pl:[{pl:[_]}],m:[{m:[L]}],mx:[{mx:[L]}],my:[{my:[L]}],ms:[{ms:[L]}],me:[{me:[L]}],mt:[{mt:[L]}],mr:[{mr:[L]}],mb:[{mb:[L]}],ml:[{ml:[L]}],"space-x":[{"space-x":[h]}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":[h]}],"space-y-reverse":["space-y-reverse"],w:[{w:["auto","min","max","fit","svw","lvw","dvw",tQ,Q]}],"min-w":[{"min-w":[tQ,Q,"min","max","fit"]}],"max-w":[{"max-w":[tQ,Q,"none","full","min","max","fit","prose",{screen:[rJ]},rJ]}],h:[{h:[tQ,Q,"auto","min","max","fit","svh","lvh","dvh"]}],"min-h":[{"min-h":[tQ,Q,"min","max","fit","svh","lvh","dvh"]}],"max-h":[{"max-h":[tQ,Q,"min","max","fit","svh","lvh","dvh"]}],size:[{size:[tQ,Q,"auto","min","max","fit"]}],"font-size":[{text:["base",rJ,nJ]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:["thin","extralight","light","normal","medium","semibold","bold","extrabold","black",sS0]}],"font-family":[{font:[ud]}],"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:["tighter","tight","normal","wide","wider","widest",tQ]}],"line-clamp":[{"line-clamp":["none",Qy,sS0]}],leading:[{leading:["none","tight","snug","normal","relaxed","loose",v3,tQ]}],"list-image":[{"list-image":["none",tQ]}],"list-style-type":[{list:["none","disc","decimal",tQ]}],"list-style-position":[{list:["inside","outside"]}],"placeholder-color":[{placeholder:[A]}],"placeholder-opacity":[{"placeholder-opacity":[N]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"text-color":[{text:[A]}],"text-opacity":[{"text-opacity":[N]}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...x(),"wavy"]}],"text-decoration-thickness":[{decoration:["auto","from-font",v3,nJ]}],"underline-offset":[{"underline-offset":["auto",v3,tQ]}],"text-decoration-color":[{decoration:[A]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:B0()}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",tQ]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",tQ]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-opacity":[{"bg-opacity":[N]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:[...P(),NpQ]}],"bg-repeat":[{bg:["no-repeat",{repeat:["","x","y","round","space"]}]}],"bg-size":[{bg:["auto","cover","contain",LpQ]}],"bg-image":[{bg:["none",{"gradient-to":["t","tr","r","br","b","bl","l","tl"]},MpQ]}],"bg-color":[{bg:[A]}],"gradient-from-pos":[{from:[V]}],"gradient-via-pos":[{via:[V]}],"gradient-to-pos":[{to:[V]}],"gradient-from":[{from:[F]}],"gradient-via":[{via:[F]}],"gradient-to":[{to:[F]}],rounded:[{rounded:[f]}],"rounded-s":[{"rounded-s":[f]}],"rounded-e":[{"rounded-e":[f]}],"rounded-t":[{"rounded-t":[f]}],"rounded-r":[{"rounded-r":[f]}],"rounded-b":[{"rounded-b":[f]}],"rounded-l":[{"rounded-l":[f]}],"rounded-ss":[{"rounded-ss":[f]}],"rounded-se":[{"rounded-se":[f]}],"rounded-ee":[{"rounded-ee":[f]}],"rounded-es":[{"rounded-es":[f]}],"rounded-tl":[{"rounded-tl":[f]}],"rounded-tr":[{"rounded-tr":[f]}],"rounded-br":[{"rounded-br":[f]}],"rounded-bl":[{"rounded-bl":[f]}],"border-w":[{border:[Y]}],"border-w-x":[{"border-x":[Y]}],"border-w-y":[{"border-y":[Y]}],"border-w-s":[{"border-s":[Y]}],"border-w-e":[{"border-e":[Y]}],"border-w-t":[{"border-t":[Y]}],"border-w-r":[{"border-r":[Y]}],"border-w-b":[{"border-b":[Y]}],"border-w-l":[{"border-l":[Y]}],"border-opacity":[{"border-opacity":[N]}],"border-style":[{border:[...x(),"hidden"]}],"divide-x":[{"divide-x":[Y]}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":[Y]}],"divide-y-reverse":["divide-y-reverse"],"divide-opacity":[{"divide-opacity":[N]}],"divide-style":[{divide:x()}],"border-color":[{border:[$]}],"border-color-x":[{"border-x":[$]}],"border-color-y":[{"border-y":[$]}],"border-color-s":[{"border-s":[$]}],"border-color-e":[{"border-e":[$]}],"border-color-t":[{"border-t":[$]}],"border-color-r":[{"border-r":[$]}],"border-color-b":[{"border-b":[$]}],"border-color-l":[{"border-l":[$]}],"divide-color":[{divide:[$]}],"outline-style":[{outline:["",...x()]}],"outline-offset":[{"outline-offset":[v3,tQ]}],"outline-w":[{outline:[v3,nJ]}],"outline-color":[{outline:[A]}],"ring-w":[{ring:a()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:[A]}],"ring-opacity":[{"ring-opacity":[N]}],"ring-offset-w":[{"ring-offset":[v3,nJ]}],"ring-offset-color":[{"ring-offset":[A]}],shadow:[{shadow:["","inner","none",rJ,_pQ]}],"shadow-color":[{shadow:[ud]}],opacity:[{opacity:[N]}],"mix-blend":[{"mix-blend":[...l(),"plus-lighter","plus-darker"]}],"bg-blend":[{"bg-blend":l()}],filter:[{filter:["","none"]}],blur:[{blur:[w]}],brightness:[{brightness:[B]}],contrast:[{contrast:[X]}],"drop-shadow":[{"drop-shadow":["","none",rJ,tQ]}],grayscale:[{grayscale:[H]}],"hue-rotate":[{"hue-rotate":[W]}],invert:[{invert:[Z]}],saturate:[{saturate:[j]}],sepia:[{sepia:[E]}],"backdrop-filter":[{"backdrop-filter":["","none"]}],"backdrop-blur":[{"backdrop-blur":[w]}],"backdrop-brightness":[{"backdrop-brightness":[B]}],"backdrop-contrast":[{"backdrop-contrast":[X]}],"backdrop-grayscale":[{"backdrop-grayscale":[H]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[W]}],"backdrop-invert":[{"backdrop-invert":[Z]}],"backdrop-opacity":[{"backdrop-opacity":[N]}],"backdrop-saturate":[{"backdrop-saturate":[j]}],"backdrop-sepia":[{"backdrop-sepia":[E]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":[D]}],"border-spacing-x":[{"border-spacing-x":[D]}],"border-spacing-y":[{"border-spacing-y":[D]}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["none","all","","colors","opacity","shadow","transform",tQ]}],duration:[{duration:K0()}],ease:[{ease:["linear","in","out","in-out",tQ]}],delay:[{delay:K0()}],animate:[{animate:["none","spin","ping","pulse","bounce",tQ]}],transform:[{transform:["","gpu","none"]}],scale:[{scale:[g]}],"scale-x":[{"scale-x":[g]}],"scale-y":[{"scale-y":[g]}],rotate:[{rotate:[md,tQ]}],"translate-x":[{"translate-x":[T]}],"translate-y":[{"translate-y":[T]}],"skew-x":[{"skew-x":[y]}],"skew-y":[{"skew-y":[y]}],"transform-origin":[{origin:["center","top","top-right","right","bottom-right","bottom","bottom-left","left","top-left",tQ]}],accent:[{accent:["auto",A]}],appearance:[{appearance:["none","auto"]}],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",tQ]}],"caret-color":[{caret:[A]}],"pointer-events":[{"pointer-events":["none","auto"]}],resize:[{resize:["none","y","x",""]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scroll-m":[{"scroll-m":B0()}],"scroll-mx":[{"scroll-mx":B0()}],"scroll-my":[{"scroll-my":B0()}],"scroll-ms":[{"scroll-ms":B0()}],"scroll-me":[{"scroll-me":B0()}],"scroll-mt":[{"scroll-mt":B0()}],"scroll-mr":[{"scroll-mr":B0()}],"scroll-mb":[{"scroll-mb":B0()}],"scroll-ml":[{"scroll-ml":B0()}],"scroll-p":[{"scroll-p":B0()}],"scroll-px":[{"scroll-px":B0()}],"scroll-py":[{"scroll-py":B0()}],"scroll-ps":[{"scroll-ps":B0()}],"scroll-pe":[{"scroll-pe":B0()}],"scroll-pt":[{"scroll-pt":B0()}],"scroll-pr":[{"scroll-pr":B0()}],"scroll-pb":[{"scroll-pb":B0()}],"scroll-pl":[{"scroll-pl":B0()}],"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",tQ]}],fill:[{fill:[A,"none"]}],"stroke-w":[{stroke:[v3,nJ,sS0]}],stroke:[{stroke:[A,"none"]}],sr:["sr-only","not-sr-only"],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","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","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","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-s","border-w-e","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-s","border-color-e","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"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","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-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"]}}},xpQ=(A,{cacheSize:Q,prefix:w,separator:B,experimentalParseClassName:$,extend:f={},override:D={}})=>{cd(A,"cacheSize",Q),cd(A,"prefix",w),cd(A,"separator",B),cd(A,"experimentalParseClassName",$);for(let Y in D)RpQ(A[Y],D[Y]);for(let Y in f)hpQ(A[Y],f[Y]);return A},cd=(A,Q,w)=>{if(w!==void 0)A[Q]=w},RpQ=(A,Q)=>{if(Q)for(let w in Q)cd(A,w,Q[w])},hpQ=(A,Q)=>{if(Q)for(let w in Q){let B=Q[w];if(B!==void 0)A[w]=(A[w]||[]).concat(B)}},p$0=(A,...Q)=>typeof A==="function"?pO1(iO1,A,...Q):pO1(()=>xpQ(iO1(),A),...Q);var vpQ=p$0({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 vpQ(Ay(A))}var sO1=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,aO1=Ay,D8=(A,Q)=>(w)=>{var B;if((Q===null||Q===void 0?void 0:Q.variants)==null)return aO1(A,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className);let{variants:$,defaultVariants:f}=Q,D=Object.keys($).map((H)=>{let W=w===null||w===void 0?void 0:w[H],Z=f===null||f===void 0?void 0:f[H];if(W===null)return null;let G=sO1(W)||sO1(Z);return $[H][G]}),Y=w&&Object.entries(w).reduce((H,W)=>{let[Z,G]=W;if(G===void 0)return H;return H[Z]=G,H},{}),X=Q===null||Q===void 0?void 0:(B=Q.compoundVariants)===null||B===void 0?void 0:B.reduce((H,W)=>{let{class:Z,className:G,...F}=W;return Object.entries(F).every((V)=>{let[b,L]=V;return Array.isArray(L)?L.includes({...f,...Y}[b]):{...f,...Y}[b]===L})?[...H,Z,G]:H},[]);return aO1(A,D,X,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className)};import{jsxDEV as tS0}from"preact/jsx-dev-runtime";var tO1=D8("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 eS0({variant:A,title:Q,children:w,className:B}){return tS0("div",{className:$2(tO1({variant:A}),B),role:"alert",children:[Q&&tS0("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),tS0("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 CpQ}from"preact/jsx-dev-runtime";var eO1=D8("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 M_({variant:A,size:Q,className:w,children:B,ssrOnClick:$,type:f="button",...D}){return CpQ("button",{type:f,className:$2(eO1({variant:A,size:Q}),w),...D,...$&&{onclick:$},children:B},void 0,!1,void 0,this)}import{jsxDEV as ypQ}from"preact/jsx-dev-runtime";var Ax1=D8("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":D}){let Y=$?{target:"_blank",rel:"noopener noreferrer"}:{};return ypQ("a",{href:A,className:$2(Ax1({variant:w,size:B}),f),"aria-label":D,...Y,children:Q},void 0,!1,void 0,this)}import{jsxDEV as i$0}from"preact/jsx-dev-runtime";var Qx1=D8("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"}}),EpQ={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function By({variant:A,size:Q,className:w}){let B=EpQ[Q??"md"];return i$0("button",{onclick:"toggleTheme()",type:"button",className:$2(Qx1({variant:A,size:Q}),w),"aria-label":"Toggle dark mode",children:i$0("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:[i$0("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),i$0("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 Am0}from"preact/jsx-dev-runtime";var wx1=D8("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function d$0({items:A,className:Q,linkClassName:w="hover:text-accent transition-colors",orientation:B,children:$}){if(A.length===0&&!$)return null;let f=[...A].sort((D,Y)=>D.priority-Y.priority);return Am0("ul",{className:$2(wx1({orientation:B}),Q),children:[f.map((D)=>Am0("li",{children:Am0("a",{href:D.href,className:w,children:D.label},void 0,!1,void 0,this)},D.href,!1,void 0,this)),$]},void 0,!0,void 0,this)}import{jsxDEV as PN8}from"preact/jsx-dev-runtime";import{jsxDEV as xN8}from"preact/jsx-dev-runtime";import{createContext as gpQ,h as TpQ}from"preact";import{useContext as SpQ}from"preact/hooks";var Qm0=gpQ(null);function $y({headCollector:A,children:Q}){return TpQ(Qm0.Provider,{value:A},Q)}function Bx1(){return SpQ(Qm0)}function NQ(A){let Q=Bx1();if(Q)Q.setHeadProps(A);return null}import{createContext as GaQ,h as zaQ}from"preact";import{useContext as qaQ}from"preact/hooks";TN0();var UC1=Y1(KC1(),1),KaQ=new Yc({gfm:!0,breaks:!0}),UaQ={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 ju0(A,Q){let{imageRenderer:w}=Q??{},$=(w?new Yc({gfm:!0,breaks:!0}).use({renderer:{image(f,D,Y){return w(f,D,Y)??!1}}}):KaQ).parse(A);return $=$.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
4757
+ `)}}c0();class y$0 extends _w{directorySync;constructor(A,Q,w){super(A,{schema:iS0,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}}}c0();class E$0 extends _w{directorySync;constructor(A,Q,w){super(A,{schema:pS0,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}}}c0();class g$0 extends _w{directorySync;context;constructor(A,Q,w){super(A,{schema:cS0,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:[]},D={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 X=$==="export"?10:60;await w.report({progress:X,message:"Exporting entities to directory"}),D=await this.exportWithProgress(A.entityTypes,w),await w.report({progress:100,message:$==="export"?`Export complete: ${D.exported} exported`:`Sync complete: ${f.imported} imported, ${D.exported} exported`})}let Y=Date.now()-B;return this.logger.info("Directory sync job completed",{jobId:Q,duration:Y,imported:f.imported,exported:D.exported}),{import:f,export:D,duration:Y}}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(),D=async()=>{let X=(await Promise.all(A.map((W)=>w.getAsyncJobStatus(W)))).filter((W)=>W&&(W.status==="completed"||W.status==="failed")).length;if(X===A.length){this.logger.debug("All import jobs completed");return}if(Date.now()-f>B){this.logger.warn(`Timeout waiting for import jobs (${X}/${A.length} completed)`);return}let H=Math.round(X/A.length*100);return await Q.report({progress:50+Math.round(H*0.05),message:`Processing ${X}/${A.length} entities`}),await new Promise((W)=>setTimeout(W,$)),D()};return D()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}c0();class T$0 extends _w{context;directorySync;gitSync;constructor(A,Q,w,B){super(A,{schema:lS0,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`}),klQ(B)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function klQ(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}c0();class S$0 extends _w{context;constructor(A,Q,w){super(A,{schema:v$0,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,w){let B=v$0.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}}}c0();Z0();var OlQ=K.object({});class m$0 extends _w{directorySync;constructor(A,Q){super(A,{schema:OlQ,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}}c0();D4();Z0();CB();D4();import{readFile as xlQ,writeFile as RlQ}from"fs/promises";var hlQ=dS0;class u$0 extends _w{context;fetcher;constructor(A,Q,w=NH){super(Q,{schema:hlQ,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=w}async process(A,Q,w){let{filePath:B,sourceUrl:$,postTitle:f,postSlug:D,customAlt:Y}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:B,sourceUrl:$,postSlug:D});try{await this.reportProgress(w,{progress:_Q.INIT,message:`Reading file: ${B}`});let X;try{X=await xlQ(B,"utf-8")}catch(b){return this.logger.error("Failed to read file",{filePath:B,error:vA(b)}),x6.failure(b)}let H;try{H=lw(X)}catch(b){return this.logger.warn("Failed to parse markdown",{filePath:B,error:vA(b)}),x6.failure(b)}let W=H.frontmatter;if(W.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:B}),await this.reportProgress(w,{progress:_Q.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(w,{progress:_Q.FETCH,message:"Checking for existing image"});let Z=await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:$}},limit:1}}),G;if(Z[0])G=Z[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:$,imageId:G}),await this.reportProgress(w,{progress:_Q.EXTRACT,message:`Reusing existing image: ${G}`});else{await this.reportProgress(w,{progress:_Q.PROCESS,message:`Fetching image from ${$}`});let b;try{b=await this.fetcher($)}catch(E){return this.logger.error("Failed to fetch image",{sourceUrl:$,error:vA(E)}),x6.failure(E)}await this.reportProgress(w,{progress:_Q.GENERATE,message:"Creating image entity"});let{base64:L}=fI(b),N=Yj(L),_=DI(L);if(!N||!_)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:$}),x6.failure(Error("Could not detect image format or dimensions"));G=`${D}-cover`;let j=`Cover image for ${f}`,g=Y??j;await this.context.entityService.createEntity({entity:{id:G,entityType:"image",content:b,metadata:{title:j,alt:g,format:N,width:_.width,height:_.height,sourceUrl:$}}}),this.logger.debug("Created image entity",{imageId:G,sourceUrl:$}),await this.reportProgress(w,{progress:_Q.EXTRACT,message:`Created image: ${G}`})}await this.reportProgress(w,{progress:_Q.SAVE,message:"Updating file"});let F={...W};delete F.coverImageUrl,delete F.coverImageAlt,F.coverImageId=G;let V=iz(F,H.content);try{await RlQ(B,V,"utf-8")}catch(b){return this.logger.error("Failed to write file",{filePath:B,error:vA(b)}),x6.failure(b)}return await this.reportProgress(w,{progress:_Q.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:B,imageId:G,sourceUrl:$}),{success:!0,imageId:G}}catch(X){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:B,error:vA(X)}),x6.failure(X)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}c0();D4();Z0();CB();import{readFile as vlQ,writeFile as ClQ}from"fs/promises";class c$0 extends _w{converter;constructor(A,Q,w=NH){super(Q,{schema:nS0,jobTypeName:"inline-image-convert"});this.converter=new Md(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:_Q.INIT,message:`Reading file: ${B}`});let f;try{f=await vlQ(B,"utf-8")}catch(X){let H=vA(X);return this.logger.error("Failed to read file",{filePath:B,error:H}),{success:!1,error:H}}await this.reportProgress(w,{progress:_Q.FETCH,message:"Detecting inline images"});let D=this.converter.detectInlineImages(f,$);if(D.length===0)return this.logger.debug("No inline images to convert",{filePath:B}),await this.reportProgress(w,{progress:_Q.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:B,count:D.length}),await this.reportProgress(w,{progress:_Q.PROCESS,message:`Converting ${D.length} images`});let Y=await this.converter.convert(f,$);if(!Y.converted)return this.logger.debug("No images were converted",{filePath:B}),await this.reportProgress(w,{progress:_Q.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(w,{progress:_Q.SAVE,message:"Writing updated file"});try{await ClQ(B,Y.content,"utf-8")}catch(X){let H=vA(X);return this.logger.error("Failed to write file",{filePath:B,error:H}),{success:!1,error:H}}return await this.reportProgress(w,{progress:_Q.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:B,convertedCount:Y.convertedCount}),{success:!0,convertedCount:Y.convertedCount}}catch(f){let D=vA(f);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:B,error:D}),{success:!1,error:D}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function bO1(A,Q,w){let B=($)=>w.child($);A.jobs.registerHandler("directory-sync",new g$0(B("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new y$0(B("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new E$0(B("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new S$0(B("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new m$0(B("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new u$0(A,B("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new c$0(A,B("InlineImageConversionJobHandler"))),w.debug("Registered async job handlers")}c0();import{unlink as ylQ,access as ElQ}from"fs/promises";function LO1(A,Q,w,B){let{subscribe:$}=A.messaging,{entityService:f}=A;$("entity:created",async(D)=>{let{entity:Y}=D.payload;try{await Q.fileOps.writeEntity(Y),w.debug("Auto-exported created entity",{id:Y.id,entityType:Y.entityType})}catch(X){w.error("Auto-export FAILED for created entity",{id:Y.id,entityType:Y.entityType,error:X instanceof Error?X.message:String(X),stack:X instanceof Error?X.stack:void 0})}return{success:!0}}),$("entity:updated",async(D)=>{let{entityType:Y,entityId:X}=D.payload;try{let H=await f.getEntity({entityType:Y,id:X});if(!H)return w.debug("Entity not found in DB, skipping export",{entityType:Y,entityId:X}),{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:Y,entityId:X,error:H instanceof Error?H.message:String(H),stack:H instanceof Error?H.stack:void 0})}return{success:!0}}),$("entity:deleted",async(D)=>{let{entityId:Y,entityType:X}=D.payload,H=Q.fileOps.getFilePath(Y,X);if(await ElQ(H).then(()=>!0,()=>!1))await ylQ(H),w.debug("Auto-deleted entity file",{id:Y,entityType:X,path:H});return{success:!0}}),w.debug("Setup auto-sync for entity events",{entityTypes:B})}function NO1(A,Q,w){Q.setJobQueueCallback(async(B)=>{let $=[{type:B.type,data:B.data}];return A.jobs.enqueueBatch($,{priority:5,source:"directory-sync-watcher",rootJobId:S$(),metadata:{operationType:"file_operations",operationTarget:w,pluginId:"directory-sync"}})})}Z0();c0();import{readdir as _O1,mkdir as TlQ,copyFile as SlQ}from"fs/promises";import{join as MO1,resolve as rS0}from"path";import{join as glQ}from"path";async function jO1(A){if(!await y5(glQ(A,".git")))return!1;try{return await AK(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function mlQ(A,Q){if(!await y5(A))return!0;if((await _O1(A)).filter(($)=>!$.startsWith(".")&&!$.startsWith("_")).length>0)return!1;if(await jO1(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function PO1(A,Q){let w=await _O1(A,{withFileTypes:!0});for(let B of w){let $=MO1(A,B.name),f=MO1(Q,B.name);if(B.isDirectory()){if(!await y5(f))await TlQ(f,{recursive:!0});await PO1($,f)}else await SlQ($,f)}}async function kO1(A,Q,w){let B=rS0(process.cwd(),A);w=w?rS0(w):rS0(process.cwd(),"seed-content");let $=await mlQ(B,Q);if($&&await y5(w))Q.debug("Copying seed content to brain-data directory"),await PO1(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 OO1(A,Q,w,B,$){let f=!1,D=async()=>{if(f)return;f=!0;let Y=Q();if(w.seedContent){let X=w.syncPath??A.dataDir;await kO1(X,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 X=await Y.sync();B.debug("Initial sync completed",{imported:X.import.imported,failed:X.import.failed,duration:X.duration}),await A.messaging.send({type:VN.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(X){B.error("Initial sync failed",X),await A.messaging.send({type:VN.initialSyncCompleted,payload:{success:!1,error:vA(X)},...{broadcast:!0}})}};A.messaging.subscribe(VN.pluginsRegistered,async()=>{return B.debug("Plugins registered, starting initial sync"),await D(),{success:!0}})}Z0();function xO1(A,Q,w,B){let $=new wN(()=>{Q.withLock(async()=>{try{await Q.commit(),await Q.push()}catch(Y){B.error("Git auto-commit failed",{error:Y})}})},w),f=["entity:created","entity:updated","entity:deleted"],D=[];for(let Y of f){let X=A.subscribe(Y,async()=>{return $.trigger(),{success:!0}});D.push(X)}return()=>{$.dispose();for(let Y of D)Y()}}function RO1(A,Q,w,B,$){if(B<=0)return()=>{};let f=B*60*1000,D=!1,Y=async()=>{if(D)return;D=!0;try{let{files:H,result:W}=await A.withLock(async()=>{let Z=await A.pull();if(Z.files.length===0)return{files:[],result:null};let G=await Q.queueSyncBatch(w,"periodic-sync");return{files:Z.files,result:G}});if(H.length>0)$.info("Periodic sync: pulled changes",{filesChanged:H.length});if(W)$.debug("Periodic sync: queued imports",{importOperations:W.importOperationsCount,totalFiles:W.totalFiles})}catch(H){$.error("Periodic git sync failed",{error:H})}finally{D=!1}},X=setInterval(()=>{Y()},f);return $.info("Started periodic git sync",{intervalMinutes:B}),()=>{clearInterval(X)}}import{spawnSync as vO1}from"child_process";import{cpSync as ulQ,existsSync as hO1,mkdirSync as clQ,mkdtempSync as llQ,rmSync as plQ}from"fs";import{tmpdir as ilQ}from"os";import{fileURLToPath as dlQ}from"url";import{join as nlQ,resolve as rlQ}from"path";function dJ(A,Q){let w=vO1("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 olQ(A){return A.startsWith("file://")}function slQ(A){return dlQ(A)}function alQ(A,Q){return vO1("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function CO1(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!olQ(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",w=slQ(A.gitUrl),B=rlQ(A.seedContentPath);if(!hO1(B))throw Error(`Seed content path not found: ${B}`);if(!hO1(w))A.logger.debug("Creating local bare content remote",{remotePath:w,branch:Q}),clQ(w,{recursive:!0}),dJ(process.cwd(),["init","--bare",`--initial-branch=${Q}`,w]);if(alQ(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 $=llQ(nlQ(ilQ(),"directory-sync-seed-"));try{dJ($,["init",`--initial-branch=${Q}`]),dJ($,["config","user.name",A.authorName??"Brain"]),dJ($,["config","user.email",A.authorEmail??"brain@localhost"]),ulQ(B,$,{recursive:!0}),dJ($,["add","."]),dJ($,["commit","-m","seed content remote"]),dJ($,["remote","add","origin",A.gitUrl]),dJ($,["push","-u","origin",Q])}finally{plQ($,{recursive:!0,force:!0})}}function yO1(A,Q,w,B,$){let{subscribe:f}=A.messaging;f("entity:export:request",async(D)=>{try{return{success:!0,data:await Q().exportEntities(D.payload.entityTypes)}}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:"Export failed"}}}),f("entity:import:request",async(D)=>{try{let Y=Q(),X=D.payload.paths,H=await Y.importEntities(X);if(X&&X.length>0)await Y.removeOrphanedEntities();return{success:!0,data:H}}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:"Import failed"}}}),f("sync:status:request",async()=>{try{let Y=await Q().getStatus();return{success:!0,data:{syncPath:Y.syncPath,isInitialized:Y.exists,watchEnabled:Y.watching}}}catch(D){return{success:!1,error:D instanceof Error?D.message:"Status check failed"}}}),f("sync:configure:request",async(D)=>{try{return await w({syncPath:D.payload.syncPath}),{success:!0,data:{syncPath:D.payload.syncPath,configured:!0}}}catch(Y){return{success:!1,error:Y instanceof Error?Y.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")}c0();Z0();c0();Z0();function EO1(A,Q){return Sw(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",K.object({entityType:K.string().describe("Entity type (e.g. post, note, link)"),id:K.string().describe("Entity ID"),sha:K.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:K.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 l8({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 l8({commits:[]},`No history found for ${w.entityType}/${w.id}`);return l8({commits:$,entityType:w.entityType,id:w.id},`${$.length} version${$.length===1?"":"s"} found`)}catch($){return P9($ instanceof Error?$.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function gO1(A,Q,w,B){let $=[Sw(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.",K.object({}),async(f,D)=>{try{let Y=D.channelId?`${D.interfaceType}:${D.channelId}`:`plugin:${w}`,X={interfaceType:D.interfaceType,channelId:D.channelId};if(B){let W=await Q.jobs.enqueue({type:"sync-request",data:{source:Y,interfaceType:X.interfaceType,channelId:X.channelId},toolContext:D});return l8({jobId:W,status:"queued",gitPulled:!0},"Sync queued: git pull and filesystem scan will run in the background")}let H=await A.queueSyncBatch(Q,Y,X);if(!H)return l8({gitPulled:!1},"No files to sync");return l8({batchId:H.batchId,importOperations:H.importOperationsCount,totalFiles:H.totalFiles,gitPulled:!1},`Sync started: ${H.importOperationsCount} import jobs queued for ${H.totalFiles} files`)}catch(Y){return P9(Y instanceof Error?Y.message:"Sync failed")}},{visibility:"anchor",sideEffects:"external",cli:{name:"sync"}}),Sw(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.",K.object({}),async()=>{try{let f=await A.getStatus(),D={syncPath:f.syncPath,lastSync:f.lastSync?.toISOString(),watching:f.watching};if(B){let Y=await B.getStatus();D.git={isRepo:Y.isRepo,branch:Y.branch,hasChanges:Y.hasChanges,ahead:Y.ahead,behind:Y.behind,remote:Y.remote}}return l8(D)}catch(f){return P9(f instanceof Error?f.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if(B)$.push(EO1(w,B));return $}var TO1={name:"@brains/directory-sync",private:!0,version:"0.2.0-alpha.134",description:"Directory-based entity synchronization plugin for Brains",type:"module",main:"./src/index.ts",types:"./src/index.ts",exports:{".":{types:"./src/index.ts",import:"./src/index.ts"}},scripts:{test:"bun test",typecheck:"tsc --noEmit",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",clean:"rm -rf .turbo"},dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",chokidar:"^3.5.3","simple-git":"^3.21.0"},devDependencies:{"@brains/typescript-config":"workspace:*","@types/bun":"latest","@types/node":"^20.0.0",typescript:"^5.3.3"},peerDependencies:{}};class oS0 extends RQ{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",TO1,A,Td)}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:Sd,basePrompt:"",formatter:new C$0,requiredPermission:"anchor"}});let B=this.config.syncPath??A.dataDir;this.directorySync=new _d({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(D){throw this.logger.error("Failed to initialize directory",D),D}await this.registerJobHandlers(A);let $=this.requireDirectorySync();if(LO1(A,$,this.logger,this.config.entityTypes),this.config.autoSync)NO1(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 CO1({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 D=this.config.syncPath??A.dataDir;if(this.gitSync=new uS0({logger:this.logger.child("GitSync"),dataDir:D,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 T$0(this.logger.child("DirectorySyncRequestJobHandler"),A,this.requireDirectorySync(),this.gitSync)),this.gitCleanups.push(xO1(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(RO1(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)OO1(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync);yO1(A,()=>this.requireDirectorySync(),(D)=>this.configure(D),this.logger,this.config.git)}async getTools(){let A=this.requireDirectorySync();return gO1(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 _d({...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){bO1(A,this.requireDirectorySync(),this.logger)}}function j_(A={}){return new oS0(A)}c0();Z0();var SO1={name:"@brains/email-resend",private:!0,version:"0.2.0-alpha.134",description:"Generic email delivery adapter for Resend",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var ApQ=K.object({apiKey:K.string().min(1).optional(),from:K.string().min(1).optional()});class mO1 extends RQ{fetchImpl;constructor(A={},Q={}){super("email-resend",SO1,A,ApQ);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(rw0,async(w)=>{let B=LxA.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 $=await B.json();return $.id?{status:"sent",id:$.id}:{status:"sent"}}}function l$0(A={}){return new mO1(A)}c0();import{render as el1}from"preact-render-to-string";import{h as YP}from"preact";function uO1(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=uO1(A[Q]))&&(B&&(B+=" "),B+=w)}else for(w in A)A[w]&&(B&&(B+=" "),B+=w);return B}function Ay(){for(var A,Q,w=0,B="",$=arguments.length;w<$;w++)(A=arguments[w])&&(Q=uO1(A))&&(B&&(B+=" "),B+=Q);return B}var QpQ=(A)=>{let Q=BpQ(A),{conflictingClassGroups:w,conflictingClassGroupModifiers:B}=A;return{getClassGroupId:(D)=>{let Y=D.split("-");if(Y[0]===""&&Y.length!==1)Y.shift();return dO1(Y,Q)||wpQ(D)},getConflictingClassGroupIds:(D,Y)=>{let X=w[D]||[];if(Y&&B[D])return[...X,...B[D]];return X}}},dO1=(A,Q)=>{if(A.length===0)return Q.classGroupId;let w=A[0],B=Q.nextPart.get(w),$=B?dO1(A.slice(1),B):void 0;if($)return $;if(Q.validators.length===0)return;let f=A.join("-");return Q.validators.find(({validator:D})=>D(f))?.classGroupId},cO1=/^\[(.+)\]$/,wpQ=(A)=>{if(cO1.test(A)){let Q=cO1.exec(A)[1],w=Q?.substring(0,Q.indexOf(":"));if(w)return"arbitrary.."+w}},BpQ=(A)=>{let{theme:Q,prefix:w}=A,B={nextPart:new Map,validators:[]};return fpQ(Object.entries(A.classGroups),w).forEach(([f,D])=>{aS0(D,B,f,Q)}),B},aS0=(A,Q,w,B)=>{A.forEach(($)=>{if(typeof $==="string"){let f=$===""?Q:lO1(Q,$);f.classGroupId=w;return}if(typeof $==="function"){if($pQ($)){aS0($(B),Q,w,B);return}Q.validators.push({validator:$,classGroupId:w});return}Object.entries($).forEach(([f,D])=>{aS0(D,lO1(Q,f),w,B)})})},lO1=(A,Q)=>{let w=A;return Q.split("-").forEach((B)=>{if(!w.nextPart.has(B))w.nextPart.set(B,{nextPart:new Map,validators:[]});w=w.nextPart.get(B)}),w},$pQ=(A)=>A.isThemeGetter,fpQ=(A,Q)=>{if(!Q)return A;return A.map(([w,B])=>{let $=B.map((f)=>{if(typeof f==="string")return Q+f;if(typeof f==="object")return Object.fromEntries(Object.entries(f).map(([D,Y])=>[Q+D,Y]));return f});return[w,$]})},DpQ=(A)=>{if(A<1)return{get:()=>{return},set:()=>{}};let Q=0,w=new Map,B=new Map,$=(f,D)=>{if(w.set(f,D),Q++,Q>A)Q=0,B=w,w=new Map};return{get(f){let D=w.get(f);if(D!==void 0)return D;if((D=B.get(f))!==void 0)return $(f,D),D},set(f,D){if(w.has(f))w.set(f,D);else $(f,D)}}};var YpQ=(A)=>{let{separator:Q,experimentalParseClassName:w}=A,B=Q.length===1,$=Q[0],f=Q.length,D=(Y)=>{let X=[],H=0,W=0,Z;for(let L=0;L<Y.length;L++){let N=Y[L];if(H===0){if(N===$&&(B||Y.slice(L,L+f)===Q)){X.push(Y.slice(W,L)),W=L+f;continue}if(N==="/"){Z=L;continue}}if(N==="[")H++;else if(N==="]")H--}let G=X.length===0?Y:Y.substring(W),F=G.startsWith("!"),V=F?G.substring(1):G,b=Z&&Z>W?Z-W:void 0;return{modifiers:X,hasImportantModifier:F,baseClassName:V,maybePostfixModifierPosition:b}};if(w)return(Y)=>w({className:Y,parseClassName:D});return D},XpQ=(A)=>{if(A.length<=1)return A;let Q=[],w=[];return A.forEach((B)=>{if(B[0]==="[")Q.push(...w.sort(),B),w=[];else w.push(B)}),Q.push(...w.sort()),Q},HpQ=(A)=>({cache:DpQ(A.cacheSize),parseClassName:YpQ(A),...QpQ(A)}),WpQ=/\s+/,ZpQ=(A,Q)=>{let{parseClassName:w,getClassGroupId:B,getConflictingClassGroupIds:$}=Q,f=[],D=A.trim().split(WpQ),Y="";for(let X=D.length-1;X>=0;X-=1){let H=D[X],{modifiers:W,hasImportantModifier:Z,baseClassName:G,maybePostfixModifierPosition:F}=w(H),V=Boolean(F),b=B(V?G.substring(0,F):G);if(!b){if(!V){Y=H+(Y.length>0?" "+Y:Y);continue}if(b=B(G),!b){Y=H+(Y.length>0?" "+Y:Y);continue}V=!1}let L=XpQ(W).join(":"),N=Z?L+"!":L,_=N+b;if(f.includes(_))continue;f.push(_);let j=$(b,V);for(let g=0;g<j.length;++g){let E=j[g];f.push(N+E)}Y=H+(Y.length>0?" "+Y:Y)}return Y};function KpQ(){let A=0,Q,w,B="";while(A<arguments.length)if(Q=arguments[A++]){if(w=nO1(Q))B&&(B+=" "),B+=w}return B}var nO1=(A)=>{if(typeof A==="string")return A;let Q,w="";for(let B=0;B<A.length;B++)if(A[B]){if(Q=nO1(A[B]))w&&(w+=" "),w+=Q}return w};function pO1(A,...Q){let w,B,$,f=D;function D(X){let H=Q.reduce((W,Z)=>Z(W),A());return w=HpQ(H),B=w.cache.get,$=w.cache.set,f=Y,Y(X)}function Y(X){let H=B(X);if(H)return H;let W=ZpQ(X,w);return $(X,W),W}return function(){return f(KpQ.apply(null,arguments))}}var a8=(A)=>{let Q=(w)=>w[A]||[];return Q.isThemeGetter=!0,Q},rO1=/^\[(?:([a-z-]+):)?(.+)\]$/i,UpQ=/^\d+\/\d+$/,GpQ=new Set(["px","full","screen"]),zpQ=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,qpQ=/\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$/,FpQ=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,VpQ=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,IpQ=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,v3=(A)=>Qy(A)||GpQ.has(A)||UpQ.test(A),nJ=(A)=>wy(A,"length",PpQ),Qy=(A)=>Boolean(A)&&!Number.isNaN(Number(A)),sS0=(A)=>wy(A,"number",Qy),md=(A)=>Boolean(A)&&Number.isInteger(Number(A)),JpQ=(A)=>A.endsWith("%")&&Qy(A.slice(0,-1)),tQ=(A)=>rO1.test(A),rJ=(A)=>zpQ.test(A),bpQ=new Set(["length","size","percentage"]),LpQ=(A)=>wy(A,bpQ,oO1),NpQ=(A)=>wy(A,"position",oO1),jpQ=new Set(["image","url"]),MpQ=(A)=>wy(A,jpQ,OpQ),_pQ=(A)=>wy(A,"",kpQ),ud=()=>!0,wy=(A,Q,w)=>{let B=rO1.exec(A);if(B){if(B[1])return typeof Q==="string"?B[1]===Q:Q.has(B[1]);return w(B[2])}return!1},PpQ=(A)=>qpQ.test(A)&&!FpQ.test(A),oO1=()=>!1,kpQ=(A)=>VpQ.test(A),OpQ=(A)=>IpQ.test(A);var iO1=()=>{let A=a8("colors"),Q=a8("spacing"),w=a8("blur"),B=a8("brightness"),$=a8("borderColor"),f=a8("borderRadius"),D=a8("borderSpacing"),Y=a8("borderWidth"),X=a8("contrast"),H=a8("grayscale"),W=a8("hueRotate"),Z=a8("invert"),G=a8("gap"),F=a8("gradientColorStops"),V=a8("gradientColorStopPositions"),b=a8("inset"),L=a8("margin"),N=a8("opacity"),_=a8("padding"),j=a8("saturate"),g=a8("scale"),E=a8("sepia"),y=a8("skew"),h=a8("space"),T=a8("translate"),S=()=>["auto","contain","none"],c=()=>["auto","hidden","clip","visible","scroll"],m=()=>["auto",tQ,Q],B0=()=>[tQ,Q],a=()=>["",v3,nJ],v=()=>["auto",Qy,tQ],P=()=>["bottom","center","left","left-bottom","left-top","right","right-bottom","right-top","top"],x=()=>["solid","dashed","dotted","double","none"],l=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],p=()=>["start","end","center","between","around","evenly","stretch"],A0=()=>["","0",tQ],o=()=>["auto","avoid","all","avoid-page","page","left","right","column"],K0=()=>[Qy,tQ];return{cacheSize:500,separator:":",theme:{colors:[ud],spacing:[v3,nJ],blur:["none","",rJ,tQ],brightness:K0(),borderColor:[A],borderRadius:["none","","full",rJ,tQ],borderSpacing:B0(),borderWidth:a(),contrast:K0(),grayscale:A0(),hueRotate:K0(),invert:A0(),gap:B0(),gradientColorStops:[A],gradientColorStopPositions:[JpQ,nJ],inset:m(),margin:m(),opacity:K0(),padding:B0(),saturate:K0(),scale:K0(),sepia:A0(),skew:K0(),space:B0(),translate:B0()},classGroups:{aspect:[{aspect:["auto","square","video",tQ]}],container:["container"],columns:[{columns:[rJ]}],"break-after":[{"break-after":o()}],"break-before":[{"break-before":o()}],"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"],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:[...P(),tQ]}],overflow:[{overflow:c()}],"overflow-x":[{"overflow-x":c()}],"overflow-y":[{"overflow-y":c()}],overscroll:[{overscroll:S()}],"overscroll-x":[{"overscroll-x":S()}],"overscroll-y":[{"overscroll-y":S()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:[b]}],"inset-x":[{"inset-x":[b]}],"inset-y":[{"inset-y":[b]}],start:[{start:[b]}],end:[{end:[b]}],top:[{top:[b]}],right:[{right:[b]}],bottom:[{bottom:[b]}],left:[{left:[b]}],visibility:["visible","invisible","collapse"],z:[{z:["auto",md,tQ]}],basis:[{basis:m()}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["wrap","wrap-reverse","nowrap"]}],flex:[{flex:["1","auto","initial","none",tQ]}],grow:[{grow:A0()}],shrink:[{shrink:A0()}],order:[{order:["first","last","none",md,tQ]}],"grid-cols":[{"grid-cols":[ud]}],"col-start-end":[{col:["auto",{span:["full",md,tQ]},tQ]}],"col-start":[{"col-start":v()}],"col-end":[{"col-end":v()}],"grid-rows":[{"grid-rows":[ud]}],"row-start-end":[{row:["auto",{span:[md,tQ]},tQ]}],"row-start":[{"row-start":v()}],"row-end":[{"row-end":v()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":["auto","min","max","fr",tQ]}],"auto-rows":[{"auto-rows":["auto","min","max","fr",tQ]}],gap:[{gap:[G]}],"gap-x":[{"gap-x":[G]}],"gap-y":[{"gap-y":[G]}],"justify-content":[{justify:["normal",...p()]}],"justify-items":[{"justify-items":["start","end","center","stretch"]}],"justify-self":[{"justify-self":["auto","start","end","center","stretch"]}],"align-content":[{content:["normal",...p(),"baseline"]}],"align-items":[{items:["start","end","center","baseline","stretch"]}],"align-self":[{self:["auto","start","end","center","stretch","baseline"]}],"place-content":[{"place-content":[...p(),"baseline"]}],"place-items":[{"place-items":["start","end","center","baseline","stretch"]}],"place-self":[{"place-self":["auto","start","end","center","stretch"]}],p:[{p:[_]}],px:[{px:[_]}],py:[{py:[_]}],ps:[{ps:[_]}],pe:[{pe:[_]}],pt:[{pt:[_]}],pr:[{pr:[_]}],pb:[{pb:[_]}],pl:[{pl:[_]}],m:[{m:[L]}],mx:[{mx:[L]}],my:[{my:[L]}],ms:[{ms:[L]}],me:[{me:[L]}],mt:[{mt:[L]}],mr:[{mr:[L]}],mb:[{mb:[L]}],ml:[{ml:[L]}],"space-x":[{"space-x":[h]}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":[h]}],"space-y-reverse":["space-y-reverse"],w:[{w:["auto","min","max","fit","svw","lvw","dvw",tQ,Q]}],"min-w":[{"min-w":[tQ,Q,"min","max","fit"]}],"max-w":[{"max-w":[tQ,Q,"none","full","min","max","fit","prose",{screen:[rJ]},rJ]}],h:[{h:[tQ,Q,"auto","min","max","fit","svh","lvh","dvh"]}],"min-h":[{"min-h":[tQ,Q,"min","max","fit","svh","lvh","dvh"]}],"max-h":[{"max-h":[tQ,Q,"min","max","fit","svh","lvh","dvh"]}],size:[{size:[tQ,Q,"auto","min","max","fit"]}],"font-size":[{text:["base",rJ,nJ]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:["thin","extralight","light","normal","medium","semibold","bold","extrabold","black",sS0]}],"font-family":[{font:[ud]}],"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:["tighter","tight","normal","wide","wider","widest",tQ]}],"line-clamp":[{"line-clamp":["none",Qy,sS0]}],leading:[{leading:["none","tight","snug","normal","relaxed","loose",v3,tQ]}],"list-image":[{"list-image":["none",tQ]}],"list-style-type":[{list:["none","disc","decimal",tQ]}],"list-style-position":[{list:["inside","outside"]}],"placeholder-color":[{placeholder:[A]}],"placeholder-opacity":[{"placeholder-opacity":[N]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"text-color":[{text:[A]}],"text-opacity":[{"text-opacity":[N]}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...x(),"wavy"]}],"text-decoration-thickness":[{decoration:["auto","from-font",v3,nJ]}],"underline-offset":[{"underline-offset":["auto",v3,tQ]}],"text-decoration-color":[{decoration:[A]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:B0()}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",tQ]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",tQ]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-opacity":[{"bg-opacity":[N]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:[...P(),NpQ]}],"bg-repeat":[{bg:["no-repeat",{repeat:["","x","y","round","space"]}]}],"bg-size":[{bg:["auto","cover","contain",LpQ]}],"bg-image":[{bg:["none",{"gradient-to":["t","tr","r","br","b","bl","l","tl"]},MpQ]}],"bg-color":[{bg:[A]}],"gradient-from-pos":[{from:[V]}],"gradient-via-pos":[{via:[V]}],"gradient-to-pos":[{to:[V]}],"gradient-from":[{from:[F]}],"gradient-via":[{via:[F]}],"gradient-to":[{to:[F]}],rounded:[{rounded:[f]}],"rounded-s":[{"rounded-s":[f]}],"rounded-e":[{"rounded-e":[f]}],"rounded-t":[{"rounded-t":[f]}],"rounded-r":[{"rounded-r":[f]}],"rounded-b":[{"rounded-b":[f]}],"rounded-l":[{"rounded-l":[f]}],"rounded-ss":[{"rounded-ss":[f]}],"rounded-se":[{"rounded-se":[f]}],"rounded-ee":[{"rounded-ee":[f]}],"rounded-es":[{"rounded-es":[f]}],"rounded-tl":[{"rounded-tl":[f]}],"rounded-tr":[{"rounded-tr":[f]}],"rounded-br":[{"rounded-br":[f]}],"rounded-bl":[{"rounded-bl":[f]}],"border-w":[{border:[Y]}],"border-w-x":[{"border-x":[Y]}],"border-w-y":[{"border-y":[Y]}],"border-w-s":[{"border-s":[Y]}],"border-w-e":[{"border-e":[Y]}],"border-w-t":[{"border-t":[Y]}],"border-w-r":[{"border-r":[Y]}],"border-w-b":[{"border-b":[Y]}],"border-w-l":[{"border-l":[Y]}],"border-opacity":[{"border-opacity":[N]}],"border-style":[{border:[...x(),"hidden"]}],"divide-x":[{"divide-x":[Y]}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":[Y]}],"divide-y-reverse":["divide-y-reverse"],"divide-opacity":[{"divide-opacity":[N]}],"divide-style":[{divide:x()}],"border-color":[{border:[$]}],"border-color-x":[{"border-x":[$]}],"border-color-y":[{"border-y":[$]}],"border-color-s":[{"border-s":[$]}],"border-color-e":[{"border-e":[$]}],"border-color-t":[{"border-t":[$]}],"border-color-r":[{"border-r":[$]}],"border-color-b":[{"border-b":[$]}],"border-color-l":[{"border-l":[$]}],"divide-color":[{divide:[$]}],"outline-style":[{outline:["",...x()]}],"outline-offset":[{"outline-offset":[v3,tQ]}],"outline-w":[{outline:[v3,nJ]}],"outline-color":[{outline:[A]}],"ring-w":[{ring:a()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:[A]}],"ring-opacity":[{"ring-opacity":[N]}],"ring-offset-w":[{"ring-offset":[v3,nJ]}],"ring-offset-color":[{"ring-offset":[A]}],shadow:[{shadow:["","inner","none",rJ,_pQ]}],"shadow-color":[{shadow:[ud]}],opacity:[{opacity:[N]}],"mix-blend":[{"mix-blend":[...l(),"plus-lighter","plus-darker"]}],"bg-blend":[{"bg-blend":l()}],filter:[{filter:["","none"]}],blur:[{blur:[w]}],brightness:[{brightness:[B]}],contrast:[{contrast:[X]}],"drop-shadow":[{"drop-shadow":["","none",rJ,tQ]}],grayscale:[{grayscale:[H]}],"hue-rotate":[{"hue-rotate":[W]}],invert:[{invert:[Z]}],saturate:[{saturate:[j]}],sepia:[{sepia:[E]}],"backdrop-filter":[{"backdrop-filter":["","none"]}],"backdrop-blur":[{"backdrop-blur":[w]}],"backdrop-brightness":[{"backdrop-brightness":[B]}],"backdrop-contrast":[{"backdrop-contrast":[X]}],"backdrop-grayscale":[{"backdrop-grayscale":[H]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[W]}],"backdrop-invert":[{"backdrop-invert":[Z]}],"backdrop-opacity":[{"backdrop-opacity":[N]}],"backdrop-saturate":[{"backdrop-saturate":[j]}],"backdrop-sepia":[{"backdrop-sepia":[E]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":[D]}],"border-spacing-x":[{"border-spacing-x":[D]}],"border-spacing-y":[{"border-spacing-y":[D]}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["none","all","","colors","opacity","shadow","transform",tQ]}],duration:[{duration:K0()}],ease:[{ease:["linear","in","out","in-out",tQ]}],delay:[{delay:K0()}],animate:[{animate:["none","spin","ping","pulse","bounce",tQ]}],transform:[{transform:["","gpu","none"]}],scale:[{scale:[g]}],"scale-x":[{"scale-x":[g]}],"scale-y":[{"scale-y":[g]}],rotate:[{rotate:[md,tQ]}],"translate-x":[{"translate-x":[T]}],"translate-y":[{"translate-y":[T]}],"skew-x":[{"skew-x":[y]}],"skew-y":[{"skew-y":[y]}],"transform-origin":[{origin:["center","top","top-right","right","bottom-right","bottom","bottom-left","left","top-left",tQ]}],accent:[{accent:["auto",A]}],appearance:[{appearance:["none","auto"]}],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",tQ]}],"caret-color":[{caret:[A]}],"pointer-events":[{"pointer-events":["none","auto"]}],resize:[{resize:["none","y","x",""]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scroll-m":[{"scroll-m":B0()}],"scroll-mx":[{"scroll-mx":B0()}],"scroll-my":[{"scroll-my":B0()}],"scroll-ms":[{"scroll-ms":B0()}],"scroll-me":[{"scroll-me":B0()}],"scroll-mt":[{"scroll-mt":B0()}],"scroll-mr":[{"scroll-mr":B0()}],"scroll-mb":[{"scroll-mb":B0()}],"scroll-ml":[{"scroll-ml":B0()}],"scroll-p":[{"scroll-p":B0()}],"scroll-px":[{"scroll-px":B0()}],"scroll-py":[{"scroll-py":B0()}],"scroll-ps":[{"scroll-ps":B0()}],"scroll-pe":[{"scroll-pe":B0()}],"scroll-pt":[{"scroll-pt":B0()}],"scroll-pr":[{"scroll-pr":B0()}],"scroll-pb":[{"scroll-pb":B0()}],"scroll-pl":[{"scroll-pl":B0()}],"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",tQ]}],fill:[{fill:[A,"none"]}],"stroke-w":[{stroke:[v3,nJ,sS0]}],stroke:[{stroke:[A,"none"]}],sr:["sr-only","not-sr-only"],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","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","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","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-s","border-w-e","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-s","border-color-e","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"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","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-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"]}}},xpQ=(A,{cacheSize:Q,prefix:w,separator:B,experimentalParseClassName:$,extend:f={},override:D={}})=>{cd(A,"cacheSize",Q),cd(A,"prefix",w),cd(A,"separator",B),cd(A,"experimentalParseClassName",$);for(let Y in D)RpQ(A[Y],D[Y]);for(let Y in f)hpQ(A[Y],f[Y]);return A},cd=(A,Q,w)=>{if(w!==void 0)A[Q]=w},RpQ=(A,Q)=>{if(Q)for(let w in Q)cd(A,w,Q[w])},hpQ=(A,Q)=>{if(Q)for(let w in Q){let B=Q[w];if(B!==void 0)A[w]=(A[w]||[]).concat(B)}},p$0=(A,...Q)=>typeof A==="function"?pO1(iO1,A,...Q):pO1(()=>xpQ(iO1(),A),...Q);var vpQ=p$0({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 vpQ(Ay(A))}var sO1=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,aO1=Ay,D8=(A,Q)=>(w)=>{var B;if((Q===null||Q===void 0?void 0:Q.variants)==null)return aO1(A,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className);let{variants:$,defaultVariants:f}=Q,D=Object.keys($).map((H)=>{let W=w===null||w===void 0?void 0:w[H],Z=f===null||f===void 0?void 0:f[H];if(W===null)return null;let G=sO1(W)||sO1(Z);return $[H][G]}),Y=w&&Object.entries(w).reduce((H,W)=>{let[Z,G]=W;if(G===void 0)return H;return H[Z]=G,H},{}),X=Q===null||Q===void 0?void 0:(B=Q.compoundVariants)===null||B===void 0?void 0:B.reduce((H,W)=>{let{class:Z,className:G,...F}=W;return Object.entries(F).every((V)=>{let[b,L]=V;return Array.isArray(L)?L.includes({...f,...Y}[b]):{...f,...Y}[b]===L})?[...H,Z,G]:H},[]);return aO1(A,D,X,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className)};import{jsxDEV as tS0}from"preact/jsx-dev-runtime";var tO1=D8("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 eS0({variant:A,title:Q,children:w,className:B}){return tS0("div",{className:$2(tO1({variant:A}),B),role:"alert",children:[Q&&tS0("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),tS0("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 CpQ}from"preact/jsx-dev-runtime";var eO1=D8("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 M_({variant:A,size:Q,className:w,children:B,ssrOnClick:$,type:f="button",...D}){return CpQ("button",{type:f,className:$2(eO1({variant:A,size:Q}),w),...D,...$&&{onclick:$},children:B},void 0,!1,void 0,this)}import{jsxDEV as ypQ}from"preact/jsx-dev-runtime";var Ax1=D8("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":D}){let Y=$?{target:"_blank",rel:"noopener noreferrer"}:{};return ypQ("a",{href:A,className:$2(Ax1({variant:w,size:B}),f),"aria-label":D,...Y,children:Q},void 0,!1,void 0,this)}import{jsxDEV as i$0}from"preact/jsx-dev-runtime";var Qx1=D8("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"}}),EpQ={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function By({variant:A,size:Q,className:w}){let B=EpQ[Q??"md"];return i$0("button",{onclick:"toggleTheme()",type:"button",className:$2(Qx1({variant:A,size:Q}),w),"aria-label":"Toggle dark mode",children:i$0("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:[i$0("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),i$0("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 Am0}from"preact/jsx-dev-runtime";var wx1=D8("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function d$0({items:A,className:Q,linkClassName:w="hover:text-accent transition-colors",orientation:B,children:$}){if(A.length===0&&!$)return null;let f=[...A].sort((D,Y)=>D.priority-Y.priority);return Am0("ul",{className:$2(wx1({orientation:B}),Q),children:[f.map((D)=>Am0("li",{children:Am0("a",{href:D.href,className:w,children:D.label},void 0,!1,void 0,this)},D.href,!1,void 0,this)),$]},void 0,!0,void 0,this)}import{jsxDEV as PN8}from"preact/jsx-dev-runtime";import{jsxDEV as xN8}from"preact/jsx-dev-runtime";import{createContext as gpQ,h as TpQ}from"preact";import{useContext as SpQ}from"preact/hooks";var Qm0=gpQ(null);function $y({headCollector:A,children:Q}){return TpQ(Qm0.Provider,{value:A},Q)}function Bx1(){return SpQ(Qm0)}function NQ(A){let Q=Bx1();if(Q)Q.setHeadProps(A);return null}import{createContext as GaQ,h as zaQ}from"preact";import{useContext as qaQ}from"preact/hooks";TN0();var UC1=Y1(KC1(),1),KaQ=new Yc({gfm:!0,breaks:!0}),UaQ={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 ju0(A,Q){let{imageRenderer:w}=Q??{},$=(w?new Yc({gfm:!0,breaks:!0}).use({renderer:{image(f,D,Y){return w(f,D,Y)??!1}}}):KaQ).parse(A);return $=$.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
4758
4758
  <cite class="block-attribution"><span class="emdash">$1</span>$2</cite>`),UC1.default($,UaQ)}var GC1=GaQ(null);function by({imageRenderer:A,children:Q}){return zaQ(GC1.Provider,{value:A??null},Q)}function zC1(){return qaQ(GC1)}function c3(){let A=zC1();return(Q)=>ju0(Q,A?{imageRenderer:A}:void 0)}var FaQ=/<pre><code class="language-mermaid">([\s\S]*?)<\/code><\/pre>/g,VaQ={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'"},IaQ=/&(?:amp|lt|gt|quot|#39);/g;function JaQ(A){return A.replace(IaQ,(Q)=>VaQ[Q]??Q)}function Mu0(A){return A.replace(FaQ,(Q,w)=>{return`<div class="mermaid">${JaQ(w)}</div>`})}var qC1=/<!--\s*\.slide:\s*(.*?)\s*-->/g;function FC1(A){let Q={};for(let B of A.matchAll(qC1)){let $=B[1]??"";for(let D of $.matchAll(/([\w-]+)=["']([^"']*?)["']/g)){let Y=D[1],X=D[2];if(Y&&X!==void 0)Q[Y]=X}let f=$.replace(/([\w-]+)=["']([^"']*?)["']/g,"").trim();if(f)for(let D of f.matchAll(/(?:^|\s)([\w-]+)(?=\s|$)/g)){let Y=D[1];if(Y)Q[Y]="true"}}let w=A.replace(qC1,"").replace(/^\n+/,"").replace(/\n{3,}/g,`
4759
4759
 
4760
4760
  `).trim();return{attributes:Q,markdown:w}}var baQ=/<!--\s*\.break\s*-->/;function VC1(A){let Q=A.split(baQ);return Q.length>1?Q:null}import{jsxDEV as MG}from"preact/jsx-dev-runtime";var _u0=({markdown:A,deck:Q})=>{let w=c3(),$=A.split(/^---$/gm).map((W)=>W.trim()).map((W)=>{let{attributes:Z,markdown:G}=FC1(W),F=VC1(G),V;if(F)V=`<div class="slide-columns">${F.map((L)=>`<div class="slide-column">${Mu0(w(L.trim()))}</div>`).join("")}</div>`;else V=Mu0(w(G));return{attributes:Z,htmlContent:V}}),f=$.some((W)=>W.htmlContent.includes('class="mermaid"')),D=Q?.frontmatter?.title??Q?.metadata?.title,Y=Q?.frontmatter?.description??Q?.metadata?.description,X=Q?.ogImageUrl??Q?.coverImageUrl,H=$.map(({attributes:W,htmlContent:Z},G)=>MG("section",{...W,dangerouslySetInnerHTML:{__html:Z}},G,!1,void 0,this));return MG("section",{className:"presentation-section",children:[D&&MG(NQ,{title:D,...Y?{description:Y}:{},...X?{ogImage:X}:{},ogType:"article"},void 0,!1,void 0,this),MG("link",{rel:"stylesheet",href:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.css"},void 0,!1,void 0,this),MG("div",{className:"reveal",children:MG("div",{className:"slides",children:H},void 0,!1,void 0,this)},void 0,!1,void 0,this),MG("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&&MG("script",{src:"https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js",defer:!0},void 0,!1,void 0,this),MG("script",{dangerouslySetInnerHTML:{__html:`
@@ -5741,13 +5741,13 @@ ${A.map((f)=>({url:`${Q}${f.path}`,lastmod:w,changefreq:f.path==="/"?"daily":"we
5741
5741
  `+$:w,D=gG(this.outputDir,"styles","main.css");await this.cssProcessor.process(f,D,this.workingDir,this.outputDir,this.logger);let Y=await k7.readFile(D,"utf-8"),X=B.length>0?B:Q;if(X.length>0){let H=X.join(`
5742
5742
  `)+`
5743
5743
 
5744
- `+Y;await k7.writeFile(D,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=gG(process.cwd(),"public");try{await k7.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await k7.readdir(A,{withFileTypes:!0});for(let w of Q){let B=gG(A,w.name),$=gG(this.outputDir,w.name);if(w.isDirectory())await this.copyDirectory(B,$);else await k7.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=gG(this.outputDir,$);await k7.mkdir(M7w(f),{recursive:!0}),await k7.writeFile(f,B,"utf-8"),this.logger.debug(`Wrote inline static asset: ${$}`)}))}async copyDirectory(A,Q){await k7.mkdir(Q,{recursive:!0});let w=await k7.readdir(A,{withFileTypes:!0});for(let B of w){let $=gG(A,B.name),f=gG(Q,B.name);if(B.isDirectory())await this.copyDirectory($,f);else await k7.copyFile($,f)}}}function fp0(A){return new Ap1(A)}_5();Z0();Z0();_5();var Qp1=K.object({environment:K.enum(["preview","production"]),outputDir:K.string(),workingDir:K.string().optional(),sharedImagesDir:K.string().default("./dist/images"),enableContentGeneration:K.boolean().default(!1),cleanBeforeBuild:K.boolean().default(!0),siteConfig:zY,layouts:K.record(K.any()),themeCSS:K.string().optional()}),xy8=K.object({success:K.boolean(),outputDir:K.string(),filesGenerated:K.number(),routesBuilt:K.number(),errors:K.array(K.string()).optional(),warnings:K.array(K.string()).optional()});function wp1(A){let Q=A.list(),w=Q.length===0?["No routes registered for site build"]:[];return{routes:Q,warnings:w}}function Bp1(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"}}_5();D4();_5();Z0();var _7w=K.object({id:K.string(),entityType:K.string(),content:K.string(),metadata:K.object({slug:K.string()}).passthrough()}).passthrough(),P7w=K.object({content:K.string(),metadata:K.object({width:K.number().optional(),height:K.number().optional()}).passthrough()});async function L40(A,Q){let w=Q.urlGenerator??s7.getInstance();if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((g)=>L40(g,{...Q,urlGenerator:w})));if(typeof A!=="object")return A;let B={},$=Object.entries(A),f=await Promise.all($.map(([,g])=>L40(g,{...Q,urlGenerator:w})));for(let g=0;g<$.length;g++){let E=$[g];if(E)B[E[0]]=f[g]}let D=_7w.safeParse(A);if(!D.success)return B;let Y=D.data,X=Y.entityType,H=Y.metadata.slug,W=Q.pipelineContext.entityDisplay?.[X],Z=W?W.label:X.charAt(0).toUpperCase()+X.slice(1),G=W?W.pluralName??W.label.toLowerCase()+"s":UY(X),F=`/${G}`,V=G.charAt(0).toUpperCase()+G.slice(1),b=Gu(Y),L=await k7w(b,Q),N=R10(Y)??b,_=await O7w(N,Q);return{...B,...Y,url:w.generateUrl(X,H),typeLabel:Z,listUrl:F,listLabel:V,...L,..._&&{ogImageUrl:_}}}async function k7w(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 fp1(A,Q.pipelineContext.services.entityService);if(!B)return{};return{coverImageUrl:B.url,...B.width&&{coverImageWidth:B.width},...B.height&&{coverImageHeight:B.height}}}async function O7w(A,Q){if(!A)return;let w=Q.imageBuildService?.get(A);if(w)return $p1(w.src,Q.siteUrl);let B=await fp1(A,Q.pipelineContext.services.entityService);if(!B)return;if(B.url.startsWith("data:"))return;return $p1(B.url,Q.siteUrl)}function $p1(A,Q){if(/^https?:\/\//i.test(A)||A.startsWith("data:"))return A;if(!Q)return A;return`${Q.replace(/\/$/,"")}/${A.replace(/^\//,"")}`}async function fp1(A,Q){if(!A)return;let w=await Q.getEntity({entityType:"image",id:A}),B=P7w.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 Dp1(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 D of f){let Y=Gu(D);if(Y)w.add(Y);let X=R10(D);if(X)w.add(X)}}}catch(B){Q.warn("Failed to collect image IDs for pre-resolution",{error:vA(B)})}return[...w]}async function Yp1(A,Q,w,B,$){if(!A.template)return A.content??null;let f=A.template,D=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},Y=await $.pipelineContext.services.resolveTemplateContent(f,D);if(!Y)return null;return L40(Y,{pipelineContext:$.pipelineContext,imageBuildService:$.imageBuildService,siteUrl:$.siteUrl,urlGenerator:s7.getInstance()})}function Xp1(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 Yp1(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 Bp1(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 x7w}from"path";async function Hp1(A){let Q=A.parsedOptions.workingDir??x7w(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 Wp1(A){await new J40({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 Zp1(A){let Q=new I40(A.pipelineContext.services.entityService,A.pipelineContext.logger,A.sharedImagesDir),w=await Dp1(A.pipelineContext.services.entityService,A.pipelineContext.logger);if(w.length>0)await Q.resolveAll(w);return Q}async function Kp1(A){let Q=A.reporter?.createSub({scale:{start:85,end:95}});await A.staticSiteBuilder.build(A.buildContext,(w)=>{Q?.report(w).catch(()=>{})})}function Up1(A){return{success:!0,outputDir:A.outputDir,filesGenerated:A.routesBuilt+1,routesBuilt:A.routesBuilt,...A.warnings.length>0&&{warnings:A.warnings}}}function Gp1(A){return{success:!1,outputDir:A.outputDir,filesGenerated:0,routesBuilt:0,errors:[A.errorMessage]}}async function zp1(A){let Q=Qp1.parse(A.buildOptions),w=D7.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 Wp1({pipelineContext:A.pipelineContext,publishedOnly:Q.environment==="production"});let $=await Hp1({logger:A.pipelineContext.logger,parsedOptions:Q,staticSiteBuilderFactory:A.staticSiteBuilderFactory}),f=wp1(A.pipelineContext.routeRegistry);B.push(...f.warnings);let{routes:D}=f;await w?.report({message:`Building ${D.length} routes`,progress:20,total:100}),await w?.report({message:"Resolving images",progress:25,total:100});let Y=await Zp1({pipelineContext:A.pipelineContext,sharedImagesDir:Q.sharedImagesDir}),X=Xp1({routes:D,parsedOptions:Q,buildOptions:A.buildOptions,pipelineContext:A.pipelineContext,imageBuildService:Y,siteMetadata:Q.siteConfig});return await Kp1({staticSiteBuilder:$,buildContext:X,reporter:w}),await w?.report({message:"Site build complete",progress:100,total:100}),Up1({outputDir:Q.outputDir,routesBuilt:D.length,warnings:B})}catch($){let f=Error("Site build process failed");return A.pipelineContext.logger.error("Site build failed",{error:f,originalError:$}),Gp1({outputDir:Q.outputDir,errorMessage:f.message})}}class LX{static instance=null;static defaultStaticSiteBuilderFactory=fp0;pipelineContext;staticSiteBuilderFactory;static setDefaultStaticSiteBuilderFactory(A){LX.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,w,B,$=void 0){return LX.instance??=new LX(A,LX.defaultStaticSiteBuilderFactory,Q,w,B,$),LX.instance}static resetInstance(){LX.instance=null}static createFresh(A,Q,w,B,$,f=void 0){return new LX(A,$??LX.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,s7.getInstance().configure(f)}async build(A,Q){return zp1({buildOptions:A,progress:Q,pipelineContext:this.pipelineContext,staticSiteBuilderFactory:this.staticSiteBuilderFactory})}}Z0();class Dp0{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 wN(()=>{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})}}}_5();function R7w(A,Q){return A.map((w)=>({...w,template:w.template.includes(":")?w.template:`${Q}:${w.template}`}))}function N40(A,Q,w){for(let B of A)w.register({...B,pluginId:Q,sections:B.sections?R7w(B.sections,Q):[]})}function qp1(A,Q,w){A.messaging.subscribe("plugin:site-builder:route:register",async(B)=>{try{let $=nt.parse(B.payload),{routes:f,pluginId:D}=$;return N40(f,D,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 $=rt.parse(B.payload),{paths:f,pluginId:D}=$;if(f)for(let Y of f)Q.unregister(Y);else if(D)Q.unregisterByPlugin(D);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 $=ot.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 $=st.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 Fp1}from"fs";import{join as Vp1}from"path";async function h7w(A,Q,w){let B=A.siteConfig.url??"https://example.com",$=Q.list(),f=Bp0(B,A.environment);await Fp1.writeFile(Vp1(A.outputDir,"robots.txt"),f,"utf-8"),w.info(`Generated robots.txt for ${A.environment} environment`);let D=$p0($,B);await Fp1.writeFile(Vp1(A.outputDir,"sitemap.xml"),D,"utf-8"),w.info(`Generated sitemap.xml with ${$.length} URLs`)}function Ip1(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 h7w(f,w,B),{success:!0}}catch(f){return B.error("Failed to generate SEO files",f),{success:!1}}})}c0();Z0();_5();var Jp1=K.object({environment:K.enum(["preview","production"]).optional(),outputDir:K.string(),workingDir:K.string().optional(),enableContentGeneration:K.boolean().optional(),siteConfig:zY.optional()});_5();_5();async function Kr(A,Q){try{let w=await A({type:nT,payload:void 0});if("success"in w&&w.success&&w.data){let B=zY.safeParse(w.data);if(B.success)return zY.parse({...Q,...B.data})}}catch{}return Q}class Yp0 extends _w{sendMessage;cfg;constructor(A,Q,w){super(A,{schema:Jp1,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}}),D=await Kr(this.sendMessage,A.siteConfig??this.cfg.defaultSiteConfig),Y=await this.cfg.siteBuilder.build({outputDir:A.outputDir,workingDir:A.workingDir,sharedImagesDir:this.cfg.sharedImagesDir,enableContentGeneration:$,environment:B,cleanBeforeBuild:!0,siteConfig:D,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: ${Y.routesBuilt} routes built`}),this.logger.debug("Site build job completed",{jobId:Q,environment:B,routesBuilt:Y.routesBuilt,success:Y.success}),Y.success){this.logger.info(`Emitting site:build:completed event for ${B} environment`);let X=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:Y.routesBuilt,siteConfig:{...D,url:X},generateEntityUrl:(H,W)=>s7.getInstance().generateUrl(H,W)},broadcast:!0})}return{success:Y.success,routesBuilt:Y.routesBuilt,outputDir:A.outputDir,environment:B,...Y.errors&&{errors:Y.errors},...Y.warnings&&{warnings:Y.warnings}}}catch(f){throw this.logger.error("Site build job failed",f),f}}summarizeDataForLog(A){return{environment:A.environment,outputDir:A.outputDir}}}Z0();_5();var v7w=K.object({slot:K.enum(HN).optional().default("primary"),limit:K.number().optional()});class Xp0{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=v7w.parse(A??{});this.logger.debug("NavigationDataSource fetch called",{params:B});let $=this.routeRegistry.getNavigationItems(B.slot),f=B.limit?$.slice(0,B.limit):$,D=f.map((X)=>({label:X.label,href:X.href}));this.logger.debug("NavigationDataSource returning",{slot:B.slot,itemCount:f.length,items:D});let Y={navigation:D};return Q.parse(Y)}}_5();c0();Z0();var C7w=K.object({environment:K.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function bp1(A,Q){return[Sw(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'.",C7w,async(w)=>{return Q(w.environment),{success:!0,message:`Site build requested${w.environment?` for ${w.environment}`:""} (debounced)`,data:{}}},{sideEffects:"external",cli:{name:"build"}})]}Z0();_5();var Lp1=K.object({previewOutputDir:K.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:K.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:K.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:K.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:zY.default({title:"Brain",description:"A knowledge management system"}),themeCSS:K.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:K.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:K.any().optional().describe("Template definitions to register"),routes:K.array(WN).optional().describe("Routes to register"),layouts:K.record(K.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:K.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:K.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:K.record(K.object({label:K.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:K.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:K.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:K.boolean().optional().describe("Enable pagination for list pages"),pageSize:K.number().optional().describe("Items per page (default: 10)"),navigation:K.object({show:K.boolean().optional().describe("Show in navigation"),slot:K.enum(HN).optional().describe("Navigation slot (primary or secondary)"),priority:K.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:K.record(K.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 Np1={name:"@brains/site-builder-plugin",private:!0,version:"0.2.0-alpha.133",description:"Static site generation plugin for Brain system",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint .",clean:"rm -rf dist"},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.19",preact:"^10.27.2","preact-render-to-string":"^6.3.1"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14",eslint:"^8.56.0",typescript:"^5.3.3"}};class Hp0 extends RQ{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",Np1,{...A,layouts:Q},Lp1);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new b40(A.logger),this._slotRegistry=new A40,A.messaging.subscribe("plugin:site-builder:slot:register",async(w)=>{let{slotName:B,pluginId:$,render:f,priority:D}=w.payload;return this._slotRegistry?.register(B,{pluginId:$,render:f,...D!==void 0&&{priority:D}}),{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 Xp0(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService=e4.getInstance(A.entityService,A.logger),qp1(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)N40(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=LX.getInstance(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,this.config.entityDisplay),A.jobs.registerHandler("site-build",new Yp0(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 Dp0(this.config,A,this.id,this.logger),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();A.messaging.subscribe(rT,async()=>{let w=await this.getInstructions();if(w)A.registerInstructions(w);return{success:!0}}),Ip1({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 bp1(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 Kr(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 Kr(A.messaging.send,this.config.siteInfo);return`## Your Site
5744
+ `+Y;await k7.writeFile(D,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=gG(process.cwd(),"public");try{await k7.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await k7.readdir(A,{withFileTypes:!0});for(let w of Q){let B=gG(A,w.name),$=gG(this.outputDir,w.name);if(w.isDirectory())await this.copyDirectory(B,$);else await k7.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=gG(this.outputDir,$);await k7.mkdir(M7w(f),{recursive:!0}),await k7.writeFile(f,B,"utf-8"),this.logger.debug(`Wrote inline static asset: ${$}`)}))}async copyDirectory(A,Q){await k7.mkdir(Q,{recursive:!0});let w=await k7.readdir(A,{withFileTypes:!0});for(let B of w){let $=gG(A,B.name),f=gG(Q,B.name);if(B.isDirectory())await this.copyDirectory($,f);else await k7.copyFile($,f)}}}function fp0(A){return new Ap1(A)}_5();Z0();Z0();_5();var Qp1=K.object({environment:K.enum(["preview","production"]),outputDir:K.string(),workingDir:K.string().optional(),sharedImagesDir:K.string().default("./dist/images"),enableContentGeneration:K.boolean().default(!1),cleanBeforeBuild:K.boolean().default(!0),siteConfig:zY,layouts:K.record(K.any()),themeCSS:K.string().optional()}),xy8=K.object({success:K.boolean(),outputDir:K.string(),filesGenerated:K.number(),routesBuilt:K.number(),errors:K.array(K.string()).optional(),warnings:K.array(K.string()).optional()});function wp1(A){let Q=A.list(),w=Q.length===0?["No routes registered for site build"]:[];return{routes:Q,warnings:w}}function Bp1(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"}}_5();D4();_5();Z0();var _7w=K.object({id:K.string(),entityType:K.string(),content:K.string(),metadata:K.object({slug:K.string()}).passthrough()}).passthrough(),P7w=K.object({content:K.string(),metadata:K.object({width:K.number().optional(),height:K.number().optional()}).passthrough()});async function L40(A,Q){let w=Q.urlGenerator??s7.getInstance();if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((g)=>L40(g,{...Q,urlGenerator:w})));if(typeof A!=="object")return A;let B={},$=Object.entries(A),f=await Promise.all($.map(([,g])=>L40(g,{...Q,urlGenerator:w})));for(let g=0;g<$.length;g++){let E=$[g];if(E)B[E[0]]=f[g]}let D=_7w.safeParse(A);if(!D.success)return B;let Y=D.data,X=Y.entityType,H=Y.metadata.slug,W=Q.pipelineContext.entityDisplay?.[X],Z=W?W.label:X.charAt(0).toUpperCase()+X.slice(1),G=W?W.pluralName??W.label.toLowerCase()+"s":UY(X),F=`/${G}`,V=G.charAt(0).toUpperCase()+G.slice(1),b=Gu(Y),L=await k7w(b,Q),N=R10(Y)??b,_=await O7w(N,Q);return{...B,...Y,url:w.generateUrl(X,H),typeLabel:Z,listUrl:F,listLabel:V,...L,..._&&{ogImageUrl:_}}}async function k7w(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 fp1(A,Q.pipelineContext.services.entityService);if(!B)return{};return{coverImageUrl:B.url,...B.width&&{coverImageWidth:B.width},...B.height&&{coverImageHeight:B.height}}}async function O7w(A,Q){if(!A)return;let w=Q.imageBuildService?.get(A);if(w)return $p1(w.src,Q.siteUrl);let B=await fp1(A,Q.pipelineContext.services.entityService);if(!B)return;if(B.url.startsWith("data:"))return;return $p1(B.url,Q.siteUrl)}function $p1(A,Q){if(/^https?:\/\//i.test(A)||A.startsWith("data:"))return A;if(!Q)return A;return`${Q.replace(/\/$/,"")}/${A.replace(/^\//,"")}`}async function fp1(A,Q){if(!A)return;let w=await Q.getEntity({entityType:"image",id:A}),B=P7w.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 Dp1(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 D of f){let Y=Gu(D);if(Y)w.add(Y);let X=R10(D);if(X)w.add(X)}}}catch(B){Q.warn("Failed to collect image IDs for pre-resolution",{error:vA(B)})}return[...w]}async function Yp1(A,Q,w,B,$){if(!A.template)return A.content??null;let f=A.template,D=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},Y=await $.pipelineContext.services.resolveTemplateContent(f,D);if(!Y)return null;return L40(Y,{pipelineContext:$.pipelineContext,imageBuildService:$.imageBuildService,siteUrl:$.siteUrl,urlGenerator:s7.getInstance()})}function Xp1(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 Yp1(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 Bp1(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 x7w}from"path";async function Hp1(A){let Q=A.parsedOptions.workingDir??x7w(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 Wp1(A){await new J40({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 Zp1(A){let Q=new I40(A.pipelineContext.services.entityService,A.pipelineContext.logger,A.sharedImagesDir),w=await Dp1(A.pipelineContext.services.entityService,A.pipelineContext.logger);if(w.length>0)await Q.resolveAll(w);return Q}async function Kp1(A){let Q=A.reporter?.createSub({scale:{start:85,end:95}});await A.staticSiteBuilder.build(A.buildContext,(w)=>{Q?.report(w).catch(()=>{})})}function Up1(A){return{success:!0,outputDir:A.outputDir,filesGenerated:A.routesBuilt+1,routesBuilt:A.routesBuilt,...A.warnings.length>0&&{warnings:A.warnings}}}function Gp1(A){return{success:!1,outputDir:A.outputDir,filesGenerated:0,routesBuilt:0,errors:[A.errorMessage]}}async function zp1(A){let Q=Qp1.parse(A.buildOptions),w=D7.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 Wp1({pipelineContext:A.pipelineContext,publishedOnly:Q.environment==="production"});let $=await Hp1({logger:A.pipelineContext.logger,parsedOptions:Q,staticSiteBuilderFactory:A.staticSiteBuilderFactory}),f=wp1(A.pipelineContext.routeRegistry);B.push(...f.warnings);let{routes:D}=f;await w?.report({message:`Building ${D.length} routes`,progress:20,total:100}),await w?.report({message:"Resolving images",progress:25,total:100});let Y=await Zp1({pipelineContext:A.pipelineContext,sharedImagesDir:Q.sharedImagesDir}),X=Xp1({routes:D,parsedOptions:Q,buildOptions:A.buildOptions,pipelineContext:A.pipelineContext,imageBuildService:Y,siteMetadata:Q.siteConfig});return await Kp1({staticSiteBuilder:$,buildContext:X,reporter:w}),await w?.report({message:"Site build complete",progress:100,total:100}),Up1({outputDir:Q.outputDir,routesBuilt:D.length,warnings:B})}catch($){let f=Error("Site build process failed");return A.pipelineContext.logger.error("Site build failed",{error:f,originalError:$}),Gp1({outputDir:Q.outputDir,errorMessage:f.message})}}class LX{static instance=null;static defaultStaticSiteBuilderFactory=fp0;pipelineContext;staticSiteBuilderFactory;static setDefaultStaticSiteBuilderFactory(A){LX.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,w,B,$=void 0){return LX.instance??=new LX(A,LX.defaultStaticSiteBuilderFactory,Q,w,B,$),LX.instance}static resetInstance(){LX.instance=null}static createFresh(A,Q,w,B,$,f=void 0){return new LX(A,$??LX.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,s7.getInstance().configure(f)}async build(A,Q){return zp1({buildOptions:A,progress:Q,pipelineContext:this.pipelineContext,staticSiteBuilderFactory:this.staticSiteBuilderFactory})}}Z0();class Dp0{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 wN(()=>{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})}}}_5();function R7w(A,Q){return A.map((w)=>({...w,template:w.template.includes(":")?w.template:`${Q}:${w.template}`}))}function N40(A,Q,w){for(let B of A)w.register({...B,pluginId:Q,sections:B.sections?R7w(B.sections,Q):[]})}function qp1(A,Q,w){A.messaging.subscribe("plugin:site-builder:route:register",async(B)=>{try{let $=nt.parse(B.payload),{routes:f,pluginId:D}=$;return N40(f,D,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 $=rt.parse(B.payload),{paths:f,pluginId:D}=$;if(f)for(let Y of f)Q.unregister(Y);else if(D)Q.unregisterByPlugin(D);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 $=ot.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 $=st.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 Fp1}from"fs";import{join as Vp1}from"path";async function h7w(A,Q,w){let B=A.siteConfig.url??"https://example.com",$=Q.list(),f=Bp0(B,A.environment);await Fp1.writeFile(Vp1(A.outputDir,"robots.txt"),f,"utf-8"),w.info(`Generated robots.txt for ${A.environment} environment`);let D=$p0($,B);await Fp1.writeFile(Vp1(A.outputDir,"sitemap.xml"),D,"utf-8"),w.info(`Generated sitemap.xml with ${$.length} URLs`)}function Ip1(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 h7w(f,w,B),{success:!0}}catch(f){return B.error("Failed to generate SEO files",f),{success:!1}}})}c0();Z0();_5();var Jp1=K.object({environment:K.enum(["preview","production"]).optional(),outputDir:K.string(),workingDir:K.string().optional(),enableContentGeneration:K.boolean().optional(),siteConfig:zY.optional()});_5();_5();async function Kr(A,Q){try{let w=await A({type:nT,payload:void 0});if("success"in w&&w.success&&w.data){let B=zY.safeParse(w.data);if(B.success)return zY.parse({...Q,...B.data})}}catch{}return Q}class Yp0 extends _w{sendMessage;cfg;constructor(A,Q,w){super(A,{schema:Jp1,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}}),D=await Kr(this.sendMessage,A.siteConfig??this.cfg.defaultSiteConfig),Y=await this.cfg.siteBuilder.build({outputDir:A.outputDir,workingDir:A.workingDir,sharedImagesDir:this.cfg.sharedImagesDir,enableContentGeneration:$,environment:B,cleanBeforeBuild:!0,siteConfig:D,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: ${Y.routesBuilt} routes built`}),this.logger.debug("Site build job completed",{jobId:Q,environment:B,routesBuilt:Y.routesBuilt,success:Y.success}),Y.success){this.logger.info(`Emitting site:build:completed event for ${B} environment`);let X=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:Y.routesBuilt,siteConfig:{...D,url:X},generateEntityUrl:(H,W)=>s7.getInstance().generateUrl(H,W)},broadcast:!0})}return{success:Y.success,routesBuilt:Y.routesBuilt,outputDir:A.outputDir,environment:B,...Y.errors&&{errors:Y.errors},...Y.warnings&&{warnings:Y.warnings}}}catch(f){throw this.logger.error("Site build job failed",f),f}}summarizeDataForLog(A){return{environment:A.environment,outputDir:A.outputDir}}}Z0();_5();var v7w=K.object({slot:K.enum(HN).optional().default("primary"),limit:K.number().optional()});class Xp0{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=v7w.parse(A??{});this.logger.debug("NavigationDataSource fetch called",{params:B});let $=this.routeRegistry.getNavigationItems(B.slot),f=B.limit?$.slice(0,B.limit):$,D=f.map((X)=>({label:X.label,href:X.href}));this.logger.debug("NavigationDataSource returning",{slot:B.slot,itemCount:f.length,items:D});let Y={navigation:D};return Q.parse(Y)}}_5();c0();Z0();var C7w=K.object({environment:K.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function bp1(A,Q){return[Sw(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'.",C7w,async(w)=>{return Q(w.environment),{success:!0,message:`Site build requested${w.environment?` for ${w.environment}`:""} (debounced)`,data:{}}},{sideEffects:"external",cli:{name:"build"}})]}Z0();_5();var Lp1=K.object({previewOutputDir:K.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:K.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:K.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:K.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:zY.default({title:"Brain",description:"A knowledge management system"}),themeCSS:K.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:K.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:K.any().optional().describe("Template definitions to register"),routes:K.array(WN).optional().describe("Routes to register"),layouts:K.record(K.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:K.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:K.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:K.record(K.object({label:K.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:K.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:K.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:K.boolean().optional().describe("Enable pagination for list pages"),pageSize:K.number().optional().describe("Items per page (default: 10)"),navigation:K.object({show:K.boolean().optional().describe("Show in navigation"),slot:K.enum(HN).optional().describe("Navigation slot (primary or secondary)"),priority:K.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:K.record(K.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 Np1={name:"@brains/site-builder-plugin",private:!0,version:"0.2.0-alpha.134",description:"Static site generation plugin for Brain system",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint .",clean:"rm -rf dist"},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.19",preact:"^10.27.2","preact-render-to-string":"^6.3.1"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14",eslint:"^8.56.0",typescript:"^5.3.3"}};class Hp0 extends RQ{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",Np1,{...A,layouts:Q},Lp1);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new b40(A.logger),this._slotRegistry=new A40,A.messaging.subscribe("plugin:site-builder:slot:register",async(w)=>{let{slotName:B,pluginId:$,render:f,priority:D}=w.payload;return this._slotRegistry?.register(B,{pluginId:$,render:f,...D!==void 0&&{priority:D}}),{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 Xp0(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService=e4.getInstance(A.entityService,A.logger),qp1(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)N40(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=LX.getInstance(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,this.config.entityDisplay),A.jobs.registerHandler("site-build",new Yp0(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 Dp0(this.config,A,this.id,this.logger),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();A.messaging.subscribe(rT,async()=>{let w=await this.getInstructions();if(w)A.registerInstructions(w);return{success:!0}}),Ip1({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 bp1(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 Kr(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 Kr(A.messaging.send,this.config.siteInfo);return`## Your Site
5745
5745
  ${[`**Title:** ${w.title}`,`**Description:** ${w.description}`,A.domain&&`**Domain:** ${A.domain}`,A.siteUrl&&`**URL:** ${A.siteUrl}`].filter(Boolean).join(`
5746
5746
  `)}
5747
5747
 
5748
5748
  ## Site Builder Actions
5749
5749
  - When the user asks to build, rebuild, publish, or build the website/site again, call \`site-builder_build-site\` immediately.
5750
- - 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(),LX.resetInstance(),this.logger.debug("Cleaned up all event subscriptions")}}function XP(A={}){return new Hp0(A)}c0();_5();Z0();c0();_5();var jp1=K.object({}),Ur=o1.extend({id:K.literal("site-info"),entityType:K.literal("site-info"),metadata:jp1}),Wp0=tt,ay=zY.omit({url:!0,analyticsScript:!0});c0();class TG extends I2{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:Ur,frontmatterSchema:ay,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=ay.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("",Q)}}class SG{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,w){return SG.instance??=new SG(A,Q,w),SG.instance}static resetInstance(){SG.instance=null}static createFresh(A,Q,w){return new SG(A,Q,w)}constructor(A,Q,w){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new TG;let B=SG.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}}var E7w=new TG;class j40{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 Y=await B.getEntity({entityType:"site-info",id:"site-info"});$=Y?E7w.parseSiteInfoBody(Y.content):{title:"Brain",description:"A knowledge management system"}}catch{$={title:"Brain",description:"A knowledge management system"}}let f;try{let Y=await B.getEntity({entityType:"anchor-profile",id:"anchor-profile"});if(Y)f=Y.metadata.socialLinks}catch{}let D={...$,socialLinks:f,copyright:$.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:D.title,hasSocialLinks:!!D.socialLinks}),Q.parse(D)}}var Mp1={name:"@brains/site-info",private:!0,version:"0.2.0-alpha.133",description:"Site info entity \u2014 site metadata, title, description, CTA",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var T7w=new TG;class Zp0 extends PQ{entityType="site-info";schema=Ur;adapter=T7w;defaultSiteInfo;constructor(A){super("site-info",Mp1);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new j40(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=SG.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(nT,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:rT,payload:$,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function HP(A){return new Zp0(A)}var S7w=new TG;async function Gr(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 S7w.parseSiteInfoBody(w.content)}Z0();var m7w=ay.extend({navigation:K.object({primary:K.array(K.object({label:K.string(),href:K.string(),priority:K.number()})),secondary:K.array(K.object({label:K.string(),href:K.string(),priority:K.number()}))}),copyright:K.string(),socialLinks:K.array(K.object({platform:K.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:K.string().describe("Profile or contact URL"),label:K.string().optional().describe("Optional display label")})).optional().describe("Social media links from profile entity")});c0();Z0();var _p1={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 Pp1={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 kp1={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 Op1={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 xp1={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 Rp1={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 hp1={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 vp1={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 Cp1={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 s7w=K.object({type:K.string()}).catchall(K.unknown()),a7w=K.object({lexicon:K.literal(1),id:K.string(),defs:K.object({main:K.object({type:K.literal("record"),key:K.string().min(1),record:K.object({type:K.literal("object"),required:K.array(K.string()).optional(),properties:K.record(s7w)})})})});function mG(A){return a7w.parse(A)}var MB={"ai.rizom.brain.card":mG(_p1),"ai.rizom.brain.deck":mG(Pp1),"ai.rizom.brain.link":mG(kp1),"ai.rizom.brain.note":mG(Op1),"ai.rizom.brain.post":mG(xp1),"ai.rizom.brain.project":mG(Rp1),"ai.rizom.brain.series":mG(hp1),"ai.rizom.brain.socialPost":mG(vp1),"ai.rizom.brain.topic":mG(Cp1)},t7w="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function DF(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:t7w}}var e7w={"ai.rizom.brain.card":DF("@brains/atproto"),"ai.rizom.brain.deck":DF("@brains/decks"),"ai.rizom.brain.link":DF("@brains/link"),"ai.rizom.brain.note":DF("@brains/note"),"ai.rizom.brain.post":DF("@brains/blog"),"ai.rizom.brain.project":DF("@brains/portfolio"),"ai.rizom.brain.series":DF("@brains/series"),"ai.rizom.brain.socialPost":DF("@brains/social-media"),"ai.rizom.brain.topic":DF("@brains/topics")};function WP(){return Object.values(MB)}function Gp0(A){return MB[A]}function zp0(){return Object.entries(e7w).map(([A,Q])=>({id:A,...Q}))}function Up0(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var A4w=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function Q4w(A){let Q=K.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)=>A4w.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 yp1(A){switch(A.type){case"string":return Q4w(A);case"integer":return K.number().int();case"boolean":return K.boolean();case"array":{let Q=A.items?yp1(A.items):K.unknown(),w=K.array(Q);if(A.maxLength!==void 0)w=w.max(A.maxLength);return w}case"object":return w4w(A);case"blob":return K.custom(Up0,{message:"expected blob"});default:return K.unknown()}}function Ep1(A){let Q=new Set(A.required??[]),w={};for(let[B,$]of Object.entries(A.properties??{})){let f=yp1($);w[B]=Q.has(B)?f:f.optional()}return w}function w4w(A){return K.object(Ep1(A)).passthrough()}function Kp0(A,Q,w,B=[]){let $=Object.keys(A).filter((f)=>!Q.has(f));if($.length===0)return;w.addIssue({code:K.ZodIssueCode.custom,path:B,message:`unrecognized field(s): ${$.join(", ")}`})}function B4w(A,Q){if(Kp0(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),Up0(A.brain))Kp0(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(Up0(A.anchor))Kp0(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function uG(A){let Q=K.object({...Ep1(A.defs.main.record),$type:K.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(B4w):Q}var $4w={"ai.rizom.brain.card":uG(MB["ai.rizom.brain.card"]),"ai.rizom.brain.deck":uG(MB["ai.rizom.brain.deck"]),"ai.rizom.brain.link":uG(MB["ai.rizom.brain.link"]),"ai.rizom.brain.note":uG(MB["ai.rizom.brain.note"]),"ai.rizom.brain.post":uG(MB["ai.rizom.brain.post"]),"ai.rizom.brain.project":uG(MB["ai.rizom.brain.project"]),"ai.rizom.brain.series":uG(MB["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":uG(MB["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":uG(MB["ai.rizom.brain.topic"])};function f4w(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"&&w.received==="undefined")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 Vb(A,Q){let w=uG(A).safeParse(Q);if(w.success)return;let B=w.error.issues[0];if(!B)throw w.error;throw Error(f4w(A,Q,B))}var M40="atproto:brain-card-discovered",gp1="atproto:brain-discovered",Tp1="atproto:brain-card-refreshed",Sp1=K.object({repoDid:K.string().min(1),uri:K.string().min(1),cid:K.string().min(1),record:$4w["ai.rizom.brain.card"]}).strict(),DT8=K.object({agentId:K.string().min(1),name:K.string().min(1),url:K.string().url(),status:K.enum(["discovered","approved"]),repoDid:K.string().min(1).optional(),brainDid:K.string().min(1).optional(),anchorDid:K.string().min(1).optional(),cardUri:K.string().min(1).optional(),cardCid:K.string().min(1).optional()}).strict();class U5{static instance;projections=new Map;registrationCounts=new Map;static getInstance(){return this.instance??=new U5,this.instance}static createFresh(){return new U5}static resetInstance(){this.instance=void 0}register(A){this.validateProjection(A);let Q=this.projections.get(A.entityType);if(Q){if(!this.isEquivalentProjection(Q,A))throw Error(`AT Protocol projection already registered for entity type ${A.entityType}`);return this.registrationCounts.set(A.entityType,(this.registrationCounts.get(A.entityType)??1)+1),this.createUnregister(A.entityType)}return this.projections.set(A.entityType,A),this.registrationCounts.set(A.entityType,1),this.createUnregister(A.entityType)}get(A){return this.projections.get(A)}has(A){return this.projections.has(A)}list(){return Array.from(this.projections.values())}listLexicons(){return this.list().map((A)=>A.lexicon)}createUnregister(A){let Q=!0;return()=>{if(!Q)return;Q=!1;let w=this.registrationCounts.get(A)??0;if(w<=1){this.registrationCounts.delete(A),this.projections.delete(A);return}this.registrationCounts.set(A,w-1)}}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}`)}}NX();ey();Z0();var qp0=K.object({defaultPrompt:K.string().default("Write a blog post about my recent work and insights"),paginate:K.boolean().default(!0),pageSize:K.number().default(10)});c0();Z0();CB();var X4w=K.object({prompt:K.string().optional(),title:K.string().optional(),content:K.string().optional(),excerpt:K.string().optional(),coverImageId:K.string().optional(),seriesName:K.string().optional(),seriesIndex:K.number().optional(),skipAi:K.boolean().optional()}),IT8=GY.extend({title:K.string().optional(),slug:K.string().optional()});class Fp0 extends Q4{constructor(A,Q){super(A,Q,{schema:X4w,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:w,coverImageId:B,seriesName:$,seriesIndex:f,skipAi:D}=A,{title:Y,content:X,excerpt:H}=A;if(D){if(!Y)this.failEarly("Title is required when skipAi is true");X=X??`## Introduction
5750
+ - 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(),LX.resetInstance(),this.logger.debug("Cleaned up all event subscriptions")}}function XP(A={}){return new Hp0(A)}c0();_5();Z0();c0();_5();var jp1=K.object({}),Ur=o1.extend({id:K.literal("site-info"),entityType:K.literal("site-info"),metadata:jp1}),Wp0=tt,ay=zY.omit({url:!0,analyticsScript:!0});c0();class TG extends I2{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:Ur,frontmatterSchema:ay,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=ay.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("",Q)}}class SG{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,w){return SG.instance??=new SG(A,Q,w),SG.instance}static resetInstance(){SG.instance=null}static createFresh(A,Q,w){return new SG(A,Q,w)}constructor(A,Q,w){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new TG;let B=SG.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}}var E7w=new TG;class j40{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 Y=await B.getEntity({entityType:"site-info",id:"site-info"});$=Y?E7w.parseSiteInfoBody(Y.content):{title:"Brain",description:"A knowledge management system"}}catch{$={title:"Brain",description:"A knowledge management system"}}let f;try{let Y=await B.getEntity({entityType:"anchor-profile",id:"anchor-profile"});if(Y)f=Y.metadata.socialLinks}catch{}let D={...$,socialLinks:f,copyright:$.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:D.title,hasSocialLinks:!!D.socialLinks}),Q.parse(D)}}var Mp1={name:"@brains/site-info",private:!0,version:"0.2.0-alpha.134",description:"Site info entity \u2014 site metadata, title, description, CTA",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var T7w=new TG;class Zp0 extends PQ{entityType="site-info";schema=Ur;adapter=T7w;defaultSiteInfo;constructor(A){super("site-info",Mp1);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new j40(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=SG.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(nT,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:rT,payload:$,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function HP(A){return new Zp0(A)}var S7w=new TG;async function Gr(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 S7w.parseSiteInfoBody(w.content)}Z0();var m7w=ay.extend({navigation:K.object({primary:K.array(K.object({label:K.string(),href:K.string(),priority:K.number()})),secondary:K.array(K.object({label:K.string(),href:K.string(),priority:K.number()}))}),copyright:K.string(),socialLinks:K.array(K.object({platform:K.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:K.string().describe("Profile or contact URL"),label:K.string().optional().describe("Optional display label")})).optional().describe("Social media links from profile entity")});c0();Z0();var _p1={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 Pp1={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 kp1={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 Op1={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 xp1={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 Rp1={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 hp1={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 vp1={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 Cp1={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 s7w=K.object({type:K.string()}).catchall(K.unknown()),a7w=K.object({lexicon:K.literal(1),id:K.string(),defs:K.object({main:K.object({type:K.literal("record"),key:K.string().min(1),record:K.object({type:K.literal("object"),required:K.array(K.string()).optional(),properties:K.record(s7w)})})})});function mG(A){return a7w.parse(A)}var MB={"ai.rizom.brain.card":mG(_p1),"ai.rizom.brain.deck":mG(Pp1),"ai.rizom.brain.link":mG(kp1),"ai.rizom.brain.note":mG(Op1),"ai.rizom.brain.post":mG(xp1),"ai.rizom.brain.project":mG(Rp1),"ai.rizom.brain.series":mG(hp1),"ai.rizom.brain.socialPost":mG(vp1),"ai.rizom.brain.topic":mG(Cp1)},t7w="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function DF(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:t7w}}var e7w={"ai.rizom.brain.card":DF("@brains/atproto"),"ai.rizom.brain.deck":DF("@brains/decks"),"ai.rizom.brain.link":DF("@brains/link"),"ai.rizom.brain.note":DF("@brains/note"),"ai.rizom.brain.post":DF("@brains/blog"),"ai.rizom.brain.project":DF("@brains/portfolio"),"ai.rizom.brain.series":DF("@brains/series"),"ai.rizom.brain.socialPost":DF("@brains/social-media"),"ai.rizom.brain.topic":DF("@brains/topics")};function WP(){return Object.values(MB)}function Gp0(A){return MB[A]}function zp0(){return Object.entries(e7w).map(([A,Q])=>({id:A,...Q}))}function Up0(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var A4w=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function Q4w(A){let Q=K.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)=>A4w.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 yp1(A){switch(A.type){case"string":return Q4w(A);case"integer":return K.number().int();case"boolean":return K.boolean();case"array":{let Q=A.items?yp1(A.items):K.unknown(),w=K.array(Q);if(A.maxLength!==void 0)w=w.max(A.maxLength);return w}case"object":return w4w(A);case"blob":return K.custom(Up0,{message:"expected blob"});default:return K.unknown()}}function Ep1(A){let Q=new Set(A.required??[]),w={};for(let[B,$]of Object.entries(A.properties??{})){let f=yp1($);w[B]=Q.has(B)?f:f.optional()}return w}function w4w(A){return K.object(Ep1(A)).passthrough()}function Kp0(A,Q,w,B=[]){let $=Object.keys(A).filter((f)=>!Q.has(f));if($.length===0)return;w.addIssue({code:K.ZodIssueCode.custom,path:B,message:`unrecognized field(s): ${$.join(", ")}`})}function B4w(A,Q){if(Kp0(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),Up0(A.brain))Kp0(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(Up0(A.anchor))Kp0(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function uG(A){let Q=K.object({...Ep1(A.defs.main.record),$type:K.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(B4w):Q}var $4w={"ai.rizom.brain.card":uG(MB["ai.rizom.brain.card"]),"ai.rizom.brain.deck":uG(MB["ai.rizom.brain.deck"]),"ai.rizom.brain.link":uG(MB["ai.rizom.brain.link"]),"ai.rizom.brain.note":uG(MB["ai.rizom.brain.note"]),"ai.rizom.brain.post":uG(MB["ai.rizom.brain.post"]),"ai.rizom.brain.project":uG(MB["ai.rizom.brain.project"]),"ai.rizom.brain.series":uG(MB["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":uG(MB["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":uG(MB["ai.rizom.brain.topic"])};function f4w(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"&&w.received==="undefined")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 Vb(A,Q){let w=uG(A).safeParse(Q);if(w.success)return;let B=w.error.issues[0];if(!B)throw w.error;throw Error(f4w(A,Q,B))}var M40="atproto:brain-card-discovered",gp1="atproto:brain-discovered",Tp1="atproto:brain-card-refreshed",Sp1=K.object({repoDid:K.string().min(1),uri:K.string().min(1),cid:K.string().min(1),record:$4w["ai.rizom.brain.card"]}).strict(),DT8=K.object({agentId:K.string().min(1),name:K.string().min(1),url:K.string().url(),status:K.enum(["discovered","approved"]),repoDid:K.string().min(1).optional(),brainDid:K.string().min(1).optional(),anchorDid:K.string().min(1).optional(),cardUri:K.string().min(1).optional(),cardCid:K.string().min(1).optional()}).strict();class U5{static instance;projections=new Map;registrationCounts=new Map;static getInstance(){return this.instance??=new U5,this.instance}static createFresh(){return new U5}static resetInstance(){this.instance=void 0}register(A){this.validateProjection(A);let Q=this.projections.get(A.entityType);if(Q){if(!this.isEquivalentProjection(Q,A))throw Error(`AT Protocol projection already registered for entity type ${A.entityType}`);return this.registrationCounts.set(A.entityType,(this.registrationCounts.get(A.entityType)??1)+1),this.createUnregister(A.entityType)}return this.projections.set(A.entityType,A),this.registrationCounts.set(A.entityType,1),this.createUnregister(A.entityType)}get(A){return this.projections.get(A)}has(A){return this.projections.has(A)}list(){return Array.from(this.projections.values())}listLexicons(){return this.list().map((A)=>A.lexicon)}createUnregister(A){let Q=!0;return()=>{if(!Q)return;Q=!1;let w=this.registrationCounts.get(A)??0;if(w<=1){this.registrationCounts.delete(A),this.projections.delete(A);return}this.registrationCounts.set(A,w-1)}}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}`)}}NX();ey();Z0();var qp0=K.object({defaultPrompt:K.string().default("Write a blog post about my recent work and insights"),paginate:K.boolean().default(!0),pageSize:K.number().default(10)});c0();Z0();CB();var X4w=K.object({prompt:K.string().optional(),title:K.string().optional(),content:K.string().optional(),excerpt:K.string().optional(),coverImageId:K.string().optional(),seriesName:K.string().optional(),seriesIndex:K.number().optional(),skipAi:K.boolean().optional()}),IT8=GY.extend({title:K.string().optional(),slug:K.string().optional()});class Fp0 extends Q4{constructor(A,Q){super(A,Q,{schema:X4w,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:w,coverImageId:B,seriesName:$,seriesIndex:f,skipAi:D}=A,{title:Y,content:X,excerpt:H}=A;if(D){if(!Y)this.failEarly("Title is required when skipAi is true");X=X??`## Introduction
5751
5751
 
5752
5752
  Add your introduction here.
5753
5753
 
@@ -5967,7 +5967,7 @@ ${w.content}`,templateName:"blog:excerpt"})})}c0();ey();NX();function R4w(A){let
5967
5967
  letter-spacing: 0.02em;
5968
5968
  }
5969
5969
  .printable-footer a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
5970
- `}},void 0,!1,void 0,this),O7("header",{className:"printable-hero",children:[O7("div",{className:"printable-masthead",children:Q.brandLabel&&O7("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),O7("div",{children:[O7("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&O7("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),O7("div",{className:"printable-meta",children:[Q.author&&O7("span",{children:["By ",Q.author]},void 0,!0,void 0,this),w&&O7("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&&O7("figure",{className:"printable-cover-wrap",children:O7("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),O7($9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Q.canonicalUrl||Q.brandLabel)&&O7("footer",{className:"printable-footer",children:[O7("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&O7("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 Ufw=26214400,Gfw=60000;class kp0{context;metadata={outputEntityType:"document"};renderPdf;constructor(A,Q={}){this.context=A;this.renderPdf=Q.renderPdf??VK}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==O40)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=zfw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await Hfw(Kfw(Zfw(),"brain-blog-printable-"));try{let $=await MX({outputDir:B,mediaPath:`/_media/printable/post/${Q.id}`,template:$i1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await _X({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:Ufw,timeoutMs:Gfw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${qfw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await Wfw(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}=lw(A.content),w=C8.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 zfw(A,Q={}){let{frontmatter:w,content:B}=lw(A.content),$=C8.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 qfw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.title)}import{mkdtemp as bfw,rm as Lfw}from"fs/promises";import{tmpdir as Nfw}from"os";import{join as jfw}from"path";Z0();NX();Z0();import{jsxDEV as Jfw}from"preact/jsx-dev-runtime";var br="og-image",Ffw="blog:og-image",fi1=K.object({title:K.string().min(1),excerpt:K.string().optional(),author:K.string().optional(),publishedAt:K.string().optional(),brandLabel:K.string().optional(),coverImageUrl:K.string().optional()}),Di1={name:Ffw,pluginId:"blog",schema:fi1,renderers:{image:Ifw}};function Vfw(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 Ifw(A){let Q=fi1.parse(A);return Jfw(l3,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:Vfw(Q.publishedAt)},void 0,!1,void 0,this)}var Mfw={width:1200,height:630},_fw=60000;class Op0{context;metadata={outputEntityType:"image",targetField:"ogImageId"};screenshotPng;constructor(A,Q={}){this.context=A;this.screenshotPng=Q.screenshotPng??Jr}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==br)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=Pfw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await bfw(jfw(Nfw(),"brain-blog-og-image-"));try{let $=await MX({outputDir:B,mediaPath:`/_media/og/post/${Q.id}`,template:Di1,format:"image",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await _X({rootDir:B});try{return{type:"image",data:await this.screenshotPng(f.urlFor($.urlPath),Mfw,{timeoutMs:_fw,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${kfw(Q)}-og.png`}}finally{await f.close()}}finally{await Lfw(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}=lw(A.content),w=C8.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 Pfw(A,Q={}){let{frontmatter:w}=lw(A.content),B=C8.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 kfw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.title)}var Yi1={name:"@brains/blog",private:!0,version:"0.2.0-alpha.133",description:"AI-powered blog post generation from existing brain content",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class xp0 extends PQ{entityType=XF.entityType;schema=ty;adapter=XF;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",Yi1,A,qp0)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new Fp0(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return pp1()}getDataSources(){return[new Ip0(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (Wi1(),Hi1));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),ip1(A,this.logger),dp1(A,this.logger),rp1(A,this.logger),op1(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",O40,new kp0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",br,new Op0(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=U5.getInstance().register(Lp0()),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:br,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 Rp0(A={}){return new xp0(A)}NX();ey();c0();Z0();Z0();l$();c0();var wW=K.object({title:K.string(),slug:K.string(),coverImageId:K.string().optional()}),Zi1=wW.pick({title:!0,slug:!0}),Ib=o1.extend({metadata:Zi1}),x40=Ib.extend({frontmatter:wW}),R40=x40.extend({description:K.string().optional(),postCount:K.number(),coverImageUrl:K.string().optional(),coverImageWidth:K.number().optional(),coverImageHeight:K.number().optional()}),Ki1=K.object({description:K.string().optional()});function UP(A){return new pw(Ki1,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}c0();class hp0 extends I2{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:Ib,frontmatterSchema:wW,supportsCoverImage:!0,bodyFormatter:UP("")})}toMarkdown(A){let Q,w={};try{Q=this.parseFrontMatter(A.content,wW).coverImageId,w=UP(A.metadata.title).parse(this.extractBody(A.content))}catch{}let B={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},f=UP(A.metadata.title).format(w);return this.buildMarkdown(f,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,wW);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,wW);return UP(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var Jb=new hp0;c0();Z0();bY();Z0();var Rfw=K.object({seriesName:K.string().optional(),seriesIndex:K.number().optional()});function h40(A){let Q=Rfw.safeParse(A);return Q.success?Q.data:{}}function GP(A){return h40(A.metadata).seriesName}function Ui1(A){return h40(A.metadata).seriesIndex}function Gi1(A,Q){let w=Ui1(A)??Number.MAX_SAFE_INTEGER,B=Ui1(Q)??Number.MAX_SAFE_INTEGER;return w-B}class vp0{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=w1($);B.add(f);let D=w.get(f),Y=D?.content??this.createSeriesContent($),X=xw(Y);if(D?.contentHash===X)continue;let H={id:f,entityType:"series",content:Y,contentHash:X,created:D?.created??new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:$,slug:w1($)}};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=GP(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=w1(A);if(await this.entityService.getEntity({entityType:"series",id:Q}))return;let B=this.createSeriesContent(A),$={id:Q,entityType:"series",content:B,contentHash:xw(B),created:new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:A,slug:w1(A)}};await this.entityService.upsertEntity({entity:$}),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=w1(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=GP($);if(f)A.add(f)}}return A}createSeriesContent(A){let Q={title:A,slug:w1(A)};return H7("",Q)}}c0();Z0();var hfw=K.object({entityType:K.literal("series"),query:K.object({id:K.string().optional(),limit:K.number().optional(),page:K.number().optional(),pageSize:K.number().optional()}).passthrough()}),vfw=K.object({type:K.enum(["list","detail"]),seriesName:K.string().optional()});function Cfw(A){let Q=vfw.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let w=hfw.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 zi1(A){let Q=v2(A.content,wW);return x40.parse({...A,frontmatter:Q.metadata})}class Cp0{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=Cfw(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 D=zi1(f),Y=Jb.parseBody(f.content);return{...D,description:Y.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 $=zi1(B),f=Jb.parseBody(B.content),D=await this.getSeriesMembers(A,w);return this.logger.debug(`Found ${D.length} entities in series "${A}"`),Q.parse({seriesName:A,posts:D,series:{...$,description:f.description,postCount:D.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 D=GP(f);if(D)Q.set(D,(Q.get(D)??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(Gi1),w}}c0();Z0();bY();var yfw=K.object({prompt:K.string().optional(),title:K.string().optional(),seriesId:K.string().optional()}),Efw=K.object({title:K.string().optional(),excerpt:K.string().optional()});class v40{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}
5970
+ `}},void 0,!1,void 0,this),O7("header",{className:"printable-hero",children:[O7("div",{className:"printable-masthead",children:Q.brandLabel&&O7("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),O7("div",{children:[O7("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&O7("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),O7("div",{className:"printable-meta",children:[Q.author&&O7("span",{children:["By ",Q.author]},void 0,!0,void 0,this),w&&O7("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&&O7("figure",{className:"printable-cover-wrap",children:O7("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),O7($9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Q.canonicalUrl||Q.brandLabel)&&O7("footer",{className:"printable-footer",children:[O7("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&O7("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 Ufw=26214400,Gfw=60000;class kp0{context;metadata={outputEntityType:"document"};renderPdf;constructor(A,Q={}){this.context=A;this.renderPdf=Q.renderPdf??VK}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==O40)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=zfw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await Hfw(Kfw(Zfw(),"brain-blog-printable-"));try{let $=await MX({outputDir:B,mediaPath:`/_media/printable/post/${Q.id}`,template:$i1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await _X({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:Ufw,timeoutMs:Gfw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${qfw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await Wfw(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}=lw(A.content),w=C8.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 zfw(A,Q={}){let{frontmatter:w,content:B}=lw(A.content),$=C8.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 qfw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.title)}import{mkdtemp as bfw,rm as Lfw}from"fs/promises";import{tmpdir as Nfw}from"os";import{join as jfw}from"path";Z0();NX();Z0();import{jsxDEV as Jfw}from"preact/jsx-dev-runtime";var br="og-image",Ffw="blog:og-image",fi1=K.object({title:K.string().min(1),excerpt:K.string().optional(),author:K.string().optional(),publishedAt:K.string().optional(),brandLabel:K.string().optional(),coverImageUrl:K.string().optional()}),Di1={name:Ffw,pluginId:"blog",schema:fi1,renderers:{image:Ifw}};function Vfw(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 Ifw(A){let Q=fi1.parse(A);return Jfw(l3,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:Vfw(Q.publishedAt)},void 0,!1,void 0,this)}var Mfw={width:1200,height:630},_fw=60000;class Op0{context;metadata={outputEntityType:"image",targetField:"ogImageId"};screenshotPng;constructor(A,Q={}){this.context=A;this.screenshotPng=Q.screenshotPng??Jr}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==br)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=Pfw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await bfw(jfw(Nfw(),"brain-blog-og-image-"));try{let $=await MX({outputDir:B,mediaPath:`/_media/og/post/${Q.id}`,template:Di1,format:"image",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await _X({rootDir:B});try{return{type:"image",data:await this.screenshotPng(f.urlFor($.urlPath),Mfw,{timeoutMs:_fw,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${kfw(Q)}-og.png`}}finally{await f.close()}}finally{await Lfw(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}=lw(A.content),w=C8.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 Pfw(A,Q={}){let{frontmatter:w}=lw(A.content),B=C8.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 kfw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.title)}var Yi1={name:"@brains/blog",private:!0,version:"0.2.0-alpha.134",description:"AI-powered blog post generation from existing brain content",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class xp0 extends PQ{entityType=XF.entityType;schema=ty;adapter=XF;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",Yi1,A,qp0)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new Fp0(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return pp1()}getDataSources(){return[new Ip0(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (Wi1(),Hi1));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),ip1(A,this.logger),dp1(A,this.logger),rp1(A,this.logger),op1(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",O40,new kp0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",br,new Op0(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=U5.getInstance().register(Lp0()),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:br,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 Rp0(A={}){return new xp0(A)}NX();ey();c0();Z0();Z0();l$();c0();var wW=K.object({title:K.string(),slug:K.string(),coverImageId:K.string().optional()}),Zi1=wW.pick({title:!0,slug:!0}),Ib=o1.extend({metadata:Zi1}),x40=Ib.extend({frontmatter:wW}),R40=x40.extend({description:K.string().optional(),postCount:K.number(),coverImageUrl:K.string().optional(),coverImageWidth:K.number().optional(),coverImageHeight:K.number().optional()}),Ki1=K.object({description:K.string().optional()});function UP(A){return new pw(Ki1,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}c0();class hp0 extends I2{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:Ib,frontmatterSchema:wW,supportsCoverImage:!0,bodyFormatter:UP("")})}toMarkdown(A){let Q,w={};try{Q=this.parseFrontMatter(A.content,wW).coverImageId,w=UP(A.metadata.title).parse(this.extractBody(A.content))}catch{}let B={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},f=UP(A.metadata.title).format(w);return this.buildMarkdown(f,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,wW);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,wW);return UP(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var Jb=new hp0;c0();Z0();bY();Z0();var Rfw=K.object({seriesName:K.string().optional(),seriesIndex:K.number().optional()});function h40(A){let Q=Rfw.safeParse(A);return Q.success?Q.data:{}}function GP(A){return h40(A.metadata).seriesName}function Ui1(A){return h40(A.metadata).seriesIndex}function Gi1(A,Q){let w=Ui1(A)??Number.MAX_SAFE_INTEGER,B=Ui1(Q)??Number.MAX_SAFE_INTEGER;return w-B}class vp0{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=w1($);B.add(f);let D=w.get(f),Y=D?.content??this.createSeriesContent($),X=xw(Y);if(D?.contentHash===X)continue;let H={id:f,entityType:"series",content:Y,contentHash:X,created:D?.created??new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:$,slug:w1($)}};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=GP(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=w1(A);if(await this.entityService.getEntity({entityType:"series",id:Q}))return;let B=this.createSeriesContent(A),$={id:Q,entityType:"series",content:B,contentHash:xw(B),created:new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:A,slug:w1(A)}};await this.entityService.upsertEntity({entity:$}),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=w1(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=GP($);if(f)A.add(f)}}return A}createSeriesContent(A){let Q={title:A,slug:w1(A)};return H7("",Q)}}c0();Z0();var hfw=K.object({entityType:K.literal("series"),query:K.object({id:K.string().optional(),limit:K.number().optional(),page:K.number().optional(),pageSize:K.number().optional()}).passthrough()}),vfw=K.object({type:K.enum(["list","detail"]),seriesName:K.string().optional()});function Cfw(A){let Q=vfw.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let w=hfw.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 zi1(A){let Q=v2(A.content,wW);return x40.parse({...A,frontmatter:Q.metadata})}class Cp0{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=Cfw(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 D=zi1(f),Y=Jb.parseBody(f.content);return{...D,description:Y.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 $=zi1(B),f=Jb.parseBody(B.content),D=await this.getSeriesMembers(A,w);return this.logger.debug(`Found ${D.length} entities in series "${A}"`),Q.parse({seriesName:A,posts:D,series:{...$,description:f.description,postCount:D.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 D=GP(f);if(D)Q.set(D,(Q.get(D)??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(Gi1),w}}c0();Z0();bY();var yfw=K.object({prompt:K.string().optional(),title:K.string().optional(),seriesId:K.string().optional()}),Efw=K.object({title:K.string().optional(),excerpt:K.string().optional()});class v40{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}
5971
5971
 
5972
5972
  Content in this series:
5973
5973
  ${B.join(`
@@ -5979,7 +5979,7 @@ Your task is to write a series description (2-3 sentences) that:
5979
5979
  3. Is engaging and makes readers want to explore the content
5980
5980
  4. Works well as a series overview on a website
5981
5981
 
5982
- Be concise and focus on what makes this series unique and valuable.`});async function Li1({entity:A,config:Q}){let w=Ib.parse(A),B=Jb.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 yp0(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:MB["ai.rizom.brain.series"],validate:!1,buildRecord:Li1}}var Ni1={name:"@brains/series",private:!0,version:"0.2.0-alpha.133",description:"Cross-content series \u2014 auto-derived from entities with seriesName metadata",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts,.tsx","lint:fix":"eslint src test --ext .ts,.tsx --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var ji1=K.discriminatedUnion("mode",[K.object({mode:K.literal("derive"),reason:K.string().optional()}),K.object({mode:K.literal("source"),entityId:K.string(),entityType:K.string(),seriesName:K.string().optional(),previousSeriesName:K.string().optional()})]);class Ep0 extends PQ{entityType="series";schema=Ib;adapter=Jb;manager;unregisterAtprotoProjection;constructor(){super("series",Ni1)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new v40(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...Ji1(),description:bi1}}getDataSources(){return[new Cp0(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=GP(Q.entity),B=h40(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 vp0(A.entityService,this.logger.child("SeriesManager")),this.unregisterAtprotoProjection=U5.getInstance().register(yp0())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}createSeriesProjectionHandler(A){return{process:async(Q)=>{let w=ji1.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=ji1.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 v40(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 gp0(){return new Ep0}c0();Z0();c0();Z0();Z0();c0();var ufw=K.enum(["generating","draft","queued","published","failed"]),Mi1="publishedAt is required when deck status is published",_i1=(A)=>A.status==="published"&&!A.publishedAt,Tp0=(A)=>{if(_i1(A))throw Error(Mi1)},BW=K.object({title:K.string(),slug:K.string().optional(),description:K.string().optional(),author:K.string().optional(),status:ufw,publishedAt:K.string().datetime().optional(),event:K.string().optional(),coverImageId:K.string().optional(),ogImageId:K.string().optional()}),cfw=BW.pick({title:!0,description:!0,status:!0,publishedAt:!0,coverImageId:!0}).extend({slug:K.string(),error:K.string().optional()}).superRefine((A,Q)=>{if(!_i1(A))return;Q.addIssue({code:K.ZodIssueCode.custom,path:["publishedAt"],message:Mi1})}),QE=o1.extend({entityType:K.literal("deck"),metadata:cfw}),C40=QE.extend({frontmatter:BW,body:K.string(),ogImageUrl:K.string().optional()}),zP=C40.extend({url:K.string().optional(),typeLabel:K.string().optional(),listUrl:K.string().optional(),listLabel:K.string().optional(),coverImageUrl:K.string().optional(),ogImageUrl:K.string().optional(),coverImageWidth:K.number().optional(),coverImageHeight:K.number().optional()});class Sp0 extends I2{constructor(){super({entityType:"deck",purpose:"A slide-deck presentation.",schema:QE,frontmatterSchema:BW,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,BW);Tp0(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);Tp0(Q),this.validateSlideStructure(w);let B=Q.slug??w1(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(`---
5982
+ Be concise and focus on what makes this series unique and valuable.`});async function Li1({entity:A,config:Q}){let w=Ib.parse(A),B=Jb.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 yp0(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:MB["ai.rizom.brain.series"],validate:!1,buildRecord:Li1}}var Ni1={name:"@brains/series",private:!0,version:"0.2.0-alpha.134",description:"Cross-content series \u2014 auto-derived from entities with seriesName metadata",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts,.tsx","lint:fix":"eslint src test --ext .ts,.tsx --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var ji1=K.discriminatedUnion("mode",[K.object({mode:K.literal("derive"),reason:K.string().optional()}),K.object({mode:K.literal("source"),entityId:K.string(),entityType:K.string(),seriesName:K.string().optional(),previousSeriesName:K.string().optional()})]);class Ep0 extends PQ{entityType="series";schema=Ib;adapter=Jb;manager;unregisterAtprotoProjection;constructor(){super("series",Ni1)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new v40(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...Ji1(),description:bi1}}getDataSources(){return[new Cp0(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=GP(Q.entity),B=h40(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 vp0(A.entityService,this.logger.child("SeriesManager")),this.unregisterAtprotoProjection=U5.getInstance().register(yp0())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}createSeriesProjectionHandler(A){return{process:async(Q)=>{let w=ji1.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=ji1.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 v40(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 gp0(){return new Ep0}c0();Z0();c0();Z0();Z0();c0();var ufw=K.enum(["generating","draft","queued","published","failed"]),Mi1="publishedAt is required when deck status is published",_i1=(A)=>A.status==="published"&&!A.publishedAt,Tp0=(A)=>{if(_i1(A))throw Error(Mi1)},BW=K.object({title:K.string(),slug:K.string().optional(),description:K.string().optional(),author:K.string().optional(),status:ufw,publishedAt:K.string().datetime().optional(),event:K.string().optional(),coverImageId:K.string().optional(),ogImageId:K.string().optional()}),cfw=BW.pick({title:!0,description:!0,status:!0,publishedAt:!0,coverImageId:!0}).extend({slug:K.string(),error:K.string().optional()}).superRefine((A,Q)=>{if(!_i1(A))return;Q.addIssue({code:K.ZodIssueCode.custom,path:["publishedAt"],message:Mi1})}),QE=o1.extend({entityType:K.literal("deck"),metadata:cfw}),C40=QE.extend({frontmatter:BW,body:K.string(),ogImageUrl:K.string().optional()}),zP=C40.extend({url:K.string().optional(),typeLabel:K.string().optional(),listUrl:K.string().optional(),listLabel:K.string().optional(),coverImageUrl:K.string().optional(),ogImageUrl:K.string().optional(),coverImageWidth:K.number().optional(),coverImageHeight:K.number().optional()});class Sp0 extends I2{constructor(){super({entityType:"deck",purpose:"A slide-deck presentation.",schema:QE,frontmatterSchema:BW,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,BW);Tp0(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);Tp0(Q),this.validateSlideStructure(w);let B=Q.slug??w1(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(`---
5983
5983
  `,Q),metadata:{title:A.title,slug:A.id,status:"generating"}}}}var Lr=new Sp0;Z0();JB();var lfw=K.object({markdown:K.string().describe("Markdown content with slide separators (---)"),deck:zP.optional()}),mp0=R1({name:"deck-detail",description:"Render a presentation deck as Reveal.js slides",schema:lfw,dataSourceId:"decks:entities",requiredPermission:"public",layout:{component:_u0,fullscreen:!0}});JB();Z0();var up0=K.object({decks:K.array(C40)}),cp0=K.object({decks:K.array(zP),pageTitle:K.string().optional(),pageLabel:K.string().optional()});import{jsxDEV as lp0}from"preact/jsx-dev-runtime";var pfw="Presentations",pp0=({decks:A,pageLabel:Q})=>{let w=A.map(($)=>({id:$.id,url:$.url,title:$.frontmatter.title,date:$.frontmatter.publishedAt??$.created,description:$.frontmatter.description}));return lp0("div",{className:"deck-list bg-theme",children:lp0("div",{className:"container mx-auto max-w-[1100px] px-6 py-16 md:px-12 md:py-24",children:lp0(qn,{label:Q&&Q!=="Decks"?Q:pfw,items:w},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)};l$();class y40 extends pw{constructor(){super(up0,{title:"Deck List",mappings:[{key:"decks",label:"Decks",type:"array",itemType:"object"}]})}}var ip0=R1({name:"deck-list",description:"List view of all presentation decks",schema:cp0,dataSourceId:"decks:entities",requiredPermission:"public",formatter:new y40,layout:{component:pp0}});Z0();c0();var ifw=K.object({title:K.string().max(80).describe("A short, punchy title (2-5 words) that's memorable and evocative"),content:K.string().describe("Full slide deck content in markdown format with slide separators (---). Each slide should have a header and focused content."),description:K.string().describe("A concise 1-2 sentence summary that captures the essence of the talk")}),Pi1=R1({name:"decks:generation",description:"Template for AI to generate complete slide decks from prompts",schema:ifw,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are creating slide decks in a distinctive voice that blends philosophy, technology, and culture.
5984
5984
 
5985
5985
  Your task is to generate a complete slide deck based on the user's prompt.
@@ -6287,14 +6287,14 @@ ${Y}`,templateName:"decks:description"})).description,await this.reportProgress(
6287
6287
  color: var(--carousel-accent);
6288
6288
  font-weight: 600;
6289
6289
  }
6290
- `}},void 0,!1,void 0,this),$.map((H,W)=>_4("section",{className:`deck-carousel-slide${W===0?" is-cover":""}`,children:[_4("header",{className:"deck-carousel-header",children:_4("span",{className:"deck-carousel-wordmark","aria-label":w??Q,children:[_4("span",{className:"wm-primary",children:f.primary},void 0,!1,void 0,this),f.secondary!==void 0&&_4(afw,{children:[_4("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),_4("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),_4("div",{className:"deck-carousel-body",children:_4("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:X(H.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),_4("footer",{className:"deck-carousel-footer",children:[_4("span",{className:"deck-carousel-footer-meta",children:B??Q},void 0,!1,void 0,this),_4("span",{className:"deck-carousel-counter","aria-label":`Slide ${W+1} of ${D}`,children:[_4("span",{className:"deck-carousel-counter-current",children:String(W+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",_4("span",{children:Y},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},W,!0,void 0,this))]},void 0,!0,void 0,this)}import{mkdtemp as tfw,rm as efw}from"fs/promises";import{tmpdir as ADw}from"os";import{join as QDw}from"path";Z0();var wDw=26214400,BDw=60000,hi1=20;class rp0{context;metadata={outputEntityType:"document"};renderPdf;getThemeMode;constructor(A,Q={}){this.context=A;this.renderPdf=Q.renderPdf??VK,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=$Dw(Q,{brandLabel:this.resolveBrandLabel()});if(w.slides.length>hi1)throw Error(`Refusing to render carousel with ${w.slides.length} slides; maxSlides=${hi1}`);let B=await this.getThemeMode(),$=await tfw(QDw(ADw(),"brain-deck-carousel-"));try{let f=await MX({outputDir:$,mediaPath:`/_media/carousel/${Q.id}`,template:Ri1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:B},themeCSS:this.context.themeCSS}),D=await _X({rootDir:$});try{return{type:"document",data:await this.renderPdf(D.urlFor(f.urlPath),{maxBytes:wDw,timeoutMs:BDw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${fDw(Q)}-carousel.pdf`}}finally{await D.close()}}finally{await efw($,{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 $Dw(A,Q={}){let{frontmatter:w,content:B}=lw(A.content),$=typeof w.title==="string"?w.title:A.metadata.title,f=typeof w.event==="string"&&w.event.length>0?w.event:void 0,D=B.split(/^---$/gm).map((Y)=>Y.trim()).filter((Y)=>Y.length>0).map((Y)=>({markdown:Y}));return{title:$,slides:D,...Q.brandLabel?{brandLabel:Q.brandLabel}:{},...f?{eyebrow:f}:{}}}function fDw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.title)}Z0();import{jsxDEV as XDw}from"preact/jsx-dev-runtime";var E40="og-image",DDw="decks:og-image",vi1=K.object({title:K.string().min(1),description:K.string().optional(),event:K.string().optional(),brandLabel:K.string().optional(),slideCount:K.number().int().positive().optional(),coverImageUrl:K.string().optional()}),Ci1={name:DDw,pluginId:"decks",schema:vi1,renderers:{image:YDw}};function YDw(A){let Q=vi1.parse(A),w=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return XDw(l3,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Deck",title:Q.title,subtitle:Q.description,meta:[Q.event],tag:w},void 0,!1,void 0,this)}Z0();class op0{context;deps;metadata={outputEntityType:"image",targetField:"ogImageId"};constructor(A,Q={}){this.context=A;this.deps=Q}async resolve(A){if(A.sourceEntityType!=="deck"||A.attachmentType!==E40)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:B}=lw(Q.content),$=BW.parse(w),f=HDw(B),D=this.resolveBrandLabel(),Y=await this.resolveCoverImageUrl($.coverImageId),X={title:$.title,...$.description?{description:$.description}:{},...$.event?{event:$.event}:{},...f?{slideCount:f}:{},...Y?{coverImageUrl:Y}:{},...D?{brandLabel:D}:{}};return{type:"image",data:await KP({mediaPath:`/_media/og/deck/${Q.id}`,template:Ci1,content:X,title:X.title,themeMode:"dark",themeCSS:this.context.themeCSS,tmpPrefix:"brain-deck-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${WDw(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 HDw(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function WDw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.title)}c0();async function yi1({entity:A,config:Q}){let w=QE.parse(A),B=v2(w.content,BW),$=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 sp0(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:MB["ai.rizom.brain.deck"],validate:!1,buildRecord:yi1}}var Ei1={name:"@brains/decks",private:!0,version:"0.2.0-alpha.133",description:"Presentation decks plugin for creating and viewing slide presentations",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class ap0 extends PQ{deps;entityType=Lr.entityType;schema=Lr.schema;adapter=Lr;unregisterCarouselAttachmentProvider;unregisterOgImageAttachmentProvider;unregisterAtprotoProjection;constructor(A={}){super("decks",Ei1);this.deps=A}createGenerationHandler(A){return new np0(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":mp0,"deck-list":ip0,generation:Pi1,description:ki1}}getDataSources(){return[new dp0(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=U5.getInstance().register(sp0()),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(),D={...$,metadata:{...$.metadata,status:"published",publishedAt:f}};await A.entityService.updateEntity({entity:{...D,content:this.adapter.toMarkdown(D)}}),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:vA($)}})}return{success:!0}})}registerCarouselAttachmentProvider(A){let Q={...this.deps,getThemeMode:this.deps.getThemeMode??(async()=>{try{return(await Gr(A.entityService)).themeMode??"dark"}catch{return"dark"}})};this.unregisterCarouselAttachmentProvider=A.attachments.register("deck",Oi1,new rp0(A,Q))}registerOgImageAttachmentProvider(A){this.unregisterOgImageAttachmentProvider=A.attachments.register("deck",E40,new op0(A))}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let w=K.object({prompt:K.string(),event:K.string().optional()}).parse(Q);return A.ai.generate({prompt:`${w.prompt}${w.event?`
6290
+ `}},void 0,!1,void 0,this),$.map((H,W)=>_4("section",{className:`deck-carousel-slide${W===0?" is-cover":""}`,children:[_4("header",{className:"deck-carousel-header",children:_4("span",{className:"deck-carousel-wordmark","aria-label":w??Q,children:[_4("span",{className:"wm-primary",children:f.primary},void 0,!1,void 0,this),f.secondary!==void 0&&_4(afw,{children:[_4("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),_4("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),_4("div",{className:"deck-carousel-body",children:_4("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:X(H.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),_4("footer",{className:"deck-carousel-footer",children:[_4("span",{className:"deck-carousel-footer-meta",children:B??Q},void 0,!1,void 0,this),_4("span",{className:"deck-carousel-counter","aria-label":`Slide ${W+1} of ${D}`,children:[_4("span",{className:"deck-carousel-counter-current",children:String(W+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",_4("span",{children:Y},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},W,!0,void 0,this))]},void 0,!0,void 0,this)}import{mkdtemp as tfw,rm as efw}from"fs/promises";import{tmpdir as ADw}from"os";import{join as QDw}from"path";Z0();var wDw=26214400,BDw=60000,hi1=20;class rp0{context;metadata={outputEntityType:"document"};renderPdf;getThemeMode;constructor(A,Q={}){this.context=A;this.renderPdf=Q.renderPdf??VK,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=$Dw(Q,{brandLabel:this.resolveBrandLabel()});if(w.slides.length>hi1)throw Error(`Refusing to render carousel with ${w.slides.length} slides; maxSlides=${hi1}`);let B=await this.getThemeMode(),$=await tfw(QDw(ADw(),"brain-deck-carousel-"));try{let f=await MX({outputDir:$,mediaPath:`/_media/carousel/${Q.id}`,template:Ri1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:B},themeCSS:this.context.themeCSS}),D=await _X({rootDir:$});try{return{type:"document",data:await this.renderPdf(D.urlFor(f.urlPath),{maxBytes:wDw,timeoutMs:BDw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${fDw(Q)}-carousel.pdf`}}finally{await D.close()}}finally{await efw($,{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 $Dw(A,Q={}){let{frontmatter:w,content:B}=lw(A.content),$=typeof w.title==="string"?w.title:A.metadata.title,f=typeof w.event==="string"&&w.event.length>0?w.event:void 0,D=B.split(/^---$/gm).map((Y)=>Y.trim()).filter((Y)=>Y.length>0).map((Y)=>({markdown:Y}));return{title:$,slides:D,...Q.brandLabel?{brandLabel:Q.brandLabel}:{},...f?{eyebrow:f}:{}}}function fDw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.title)}Z0();import{jsxDEV as XDw}from"preact/jsx-dev-runtime";var E40="og-image",DDw="decks:og-image",vi1=K.object({title:K.string().min(1),description:K.string().optional(),event:K.string().optional(),brandLabel:K.string().optional(),slideCount:K.number().int().positive().optional(),coverImageUrl:K.string().optional()}),Ci1={name:DDw,pluginId:"decks",schema:vi1,renderers:{image:YDw}};function YDw(A){let Q=vi1.parse(A),w=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return XDw(l3,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Deck",title:Q.title,subtitle:Q.description,meta:[Q.event],tag:w},void 0,!1,void 0,this)}Z0();class op0{context;deps;metadata={outputEntityType:"image",targetField:"ogImageId"};constructor(A,Q={}){this.context=A;this.deps=Q}async resolve(A){if(A.sourceEntityType!=="deck"||A.attachmentType!==E40)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:B}=lw(Q.content),$=BW.parse(w),f=HDw(B),D=this.resolveBrandLabel(),Y=await this.resolveCoverImageUrl($.coverImageId),X={title:$.title,...$.description?{description:$.description}:{},...$.event?{event:$.event}:{},...f?{slideCount:f}:{},...Y?{coverImageUrl:Y}:{},...D?{brandLabel:D}:{}};return{type:"image",data:await KP({mediaPath:`/_media/og/deck/${Q.id}`,template:Ci1,content:X,title:X.title,themeMode:"dark",themeCSS:this.context.themeCSS,tmpPrefix:"brain-deck-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${WDw(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 HDw(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function WDw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.title)}c0();async function yi1({entity:A,config:Q}){let w=QE.parse(A),B=v2(w.content,BW),$=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 sp0(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:MB["ai.rizom.brain.deck"],validate:!1,buildRecord:yi1}}var Ei1={name:"@brains/decks",private:!0,version:"0.2.0-alpha.134",description:"Presentation decks plugin for creating and viewing slide presentations",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class ap0 extends PQ{deps;entityType=Lr.entityType;schema=Lr.schema;adapter=Lr;unregisterCarouselAttachmentProvider;unregisterOgImageAttachmentProvider;unregisterAtprotoProjection;constructor(A={}){super("decks",Ei1);this.deps=A}createGenerationHandler(A){return new np0(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":mp0,"deck-list":ip0,generation:Pi1,description:ki1}}getDataSources(){return[new dp0(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=U5.getInstance().register(sp0()),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(),D={...$,metadata:{...$.metadata,status:"published",publishedAt:f}};await A.entityService.updateEntity({entity:{...D,content:this.adapter.toMarkdown(D)}}),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:vA($)}})}return{success:!0}})}registerCarouselAttachmentProvider(A){let Q={...this.deps,getThemeMode:this.deps.getThemeMode??(async()=>{try{return(await Gr(A.entityService)).themeMode??"dark"}catch{return"dark"}})};this.unregisterCarouselAttachmentProvider=A.attachments.register("deck",Oi1,new rp0(A,Q))}registerOgImageAttachmentProvider(A){this.unregisterOgImageAttachmentProvider=A.attachments.register("deck",E40,new op0(A))}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let w=K.object({prompt:K.string(),event:K.string().optional()}).parse(Q);return A.ai.generate({prompt:`${w.prompt}${w.event?`
6291
6291
 
6292
6292
  Note: This presentation is for "${w.event}".`:""}`,templateName:"decks:generation"})}),A.eval.registerHandler("generateDescription",async(Q)=>{let w=K.object({title:K.string(),content:K.string()}).parse(Q);return A.ai.generate({prompt:`Title: ${w.title}
6293
6293
 
6294
6294
  Content:
6295
6295
  ${w.content}`,templateName:"decks:description"})})}}function jr(){return new ap0}c0();Z0();Z0();aB();var tp0=K.literal("application/pdf"),gi1=K.enum(["pending","draft","failed"]),ep0=K.object({title:K.string().optional(),mimeType:tp0,filename:K.string().min(1),pageCount:K.number().int().min(0).optional(),status:gi1.optional(),processingJobId:K.string().optional(),processingError:K.string().optional(),sourceEntityType:K.string().min(1).optional(),sourceEntityId:K.string().min(1).optional(),sourceUploadId:K.string().optional(),sourceFilename:K.string().optional(),sourceMediaType:K.string().optional(),attachmentType:K.string().min(1).optional(),dedupKey:K.string().min(1).optional()}),wE=o1.extend({entityType:K.literal("document"),content:K.string().regex(/^data:application\/pdf;base64,.+$/),metadata:ep0});function Mr(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 g40(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function Ai0(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 D=parseInt(f[1]??f[2]??"0",10);if(D>w)w=D}if(w>0)return w;return Q.match(/\/Type\s*\/Page(?!\w)/g)?.length??0}class T40{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=wE;toMarkdown(A){return A.content}fromMarkdown(A){return Mr(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}=Mr(Q);return{entityType:"document",content:Q,metadata:{mimeType:B,...w}}}}var HF=new T40;async function Ti0(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(await Promise.resolve().then(() => (dn1(),in1))).getDocument({data:new Uint8Array(A),disableFontFace:!1,useSystemFonts:!0,useWorkerFetch:!1}).promise;try{let f=Q.maxPages??50;if($.numPages>f)throw Error(`Uploaded PDF has ${$.numPages} pages; maximum supported for synchronous markdown extraction is ${f}`);let D=[];for(let X=1;X<=$.numPages;X+=1){let Z=(await(await $.getPage(X)).getTextContent()).items.flatMap((G)=>("str"in G)?[G.str]:[]).join(" ").replace(/\s+/g," ").trim();if(Z.length>0)D.push(Z)}let Y=D.join(`
6296
6296
 
6297
- `).trim();if(!Y)throw Error("Could not extract text from the uploaded PDF");return Y}finally{await $.destroy()}}c0();Z0();import{createHash as rDw}from"crypto";var oDw=26214400,sDw=20,aDw=60000,nn1=80,tDw=10,Si0=K.object({renderUrl:K.string().url().optional(),sourceEntityType:K.string().min(1),sourceEntityId:K.string().min(1),attachmentType:K.string().min(1),documentId:K.string().min(1).optional(),title:K.string().min(1).optional(),filename:K.string().min(1).optional(),dedupKey:K.string().min(1).optional(),replace:K.boolean().optional(),pageCount:K.number().int().min(0).optional(),maxPageCount:K.number().int().positive().optional(),maxBytes:K.number().int().positive().optional(),timeoutMs:K.number().int().positive().optional(),width:K.union([K.string(),K.number()]).optional(),height:K.union([K.string(),K.number()]).optional(),format:K.string().optional(),targetEntityType:K.string().min(1).optional(),targetEntityId:K.string().min(1).optional()}),ar=Si0.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 Mf0 extends _w{context;renderPdf;constructor(A,Q,w={}){super(A,{schema:ar,jobTypeName:"document-generate"});this.context=Q;this.renderPdf=w.renderPdf??VK}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??sDw,$=A.maxBytes??oDw,f=A.timeoutMs??aDw;if(A.pageCount!==void 0&&A.pageCount>B)throw Error(`Refusing to render ${A.pageCount} page PDF; maxPageCount=${B}`);let D=await this.getDedupKey(A),Y=_f0(A,D),X=A.documentId!==void 0||A.filename!==void 0;if(A.replace!==!0){let H=await this.findDocumentByDedupKey(D,X?Y:void 0);if(H&&(!X||H.id===Y)){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,Y,{timeoutMs:f,maxBytes:$}),W=H.data;if(W.byteLength>$)throw Error(`Rendered PDF exceeds maxBytes=${$}: ${W.byteLength} bytes`);let Z=Ai0(W);if(Z>B)throw Error(`Rendered PDF has ${Z} pages, exceeding maxPageCount=${B}`);let G=Z>0?Z:A.pageCount;await this.reportProgress(w,{progress:70,message:"Storing PDF document"});let F=A.filename??(A.renderUrl===void 0?H.filename:`${Y}.pdf`),V=HF.createDocumentEntity({dataUrl:g40(W),filename:F,...A.title&&{title:A.title},...G!==void 0&&{pageCount:G},status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,dedupKey:D});if(await NY({entityService:this.context.entityService,entity:{...V,id:Y}}),A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,Y,A);return await this.reportProgress(w,{progress:100,message:"PDF document generation complete"}),{success:!0,documentId:Y,reused:!1}}catch(H){let W=vA(H);throw this.logger.error("Document generation failed",{jobId:Q,error:W}),await UU({entityService:this.context.entityService,entityType:"document",id:Y,error:W}),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}=lw($.content),D=Array.isArray(f.documents)?f.documents.filter(AYw):[],Y=B.replace?await this.removeReferencesForSameSourceAttachment(D,w,B):D,X=Y.some((H)=>H.id===w)?Y:[...Y,{id:w}];await this.context.entityService.updateEntity({entity:{...$,content:o4($.content,"documents",X)}})}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||!QYw(f,w))B.push($)}return B}}function _f0(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 eDw($)}function eDw(A){let Q=w1(A.replace(/[/:]+/g," "))||`document-${rn1(A)}`;if(Q.length<=nn1)return Q;let w=`-${rn1(A)}`;return`${Q.slice(0,nn1-w.length).replace(/-+$/g,"")}${w}`}function rn1(A){return rDw("sha256").update(A).digest("hex").slice(0,tDw)}function AYw(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function QYw(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var on1={name:"@brains/document-plugin",private:!0,version:"0.2.0-alpha.133",description:"Document entity type for generated PDFs and publishable document attachments",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/contracts":"workspace:*","@brains/document":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/typescript-config":"workspace:*","bun-types":"latest",typescript:"^5.3.3"}};var BYw=`data:application/pdf;base64,${Buffer.from(`%PDF-1.4
6297
+ `).trim();if(!Y)throw Error("Could not extract text from the uploaded PDF");return Y}finally{await $.destroy()}}c0();Z0();import{createHash as rDw}from"crypto";var oDw=26214400,sDw=20,aDw=60000,nn1=80,tDw=10,Si0=K.object({renderUrl:K.string().url().optional(),sourceEntityType:K.string().min(1),sourceEntityId:K.string().min(1),attachmentType:K.string().min(1),documentId:K.string().min(1).optional(),title:K.string().min(1).optional(),filename:K.string().min(1).optional(),dedupKey:K.string().min(1).optional(),replace:K.boolean().optional(),pageCount:K.number().int().min(0).optional(),maxPageCount:K.number().int().positive().optional(),maxBytes:K.number().int().positive().optional(),timeoutMs:K.number().int().positive().optional(),width:K.union([K.string(),K.number()]).optional(),height:K.union([K.string(),K.number()]).optional(),format:K.string().optional(),targetEntityType:K.string().min(1).optional(),targetEntityId:K.string().min(1).optional()}),ar=Si0.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 Mf0 extends _w{context;renderPdf;constructor(A,Q,w={}){super(A,{schema:ar,jobTypeName:"document-generate"});this.context=Q;this.renderPdf=w.renderPdf??VK}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??sDw,$=A.maxBytes??oDw,f=A.timeoutMs??aDw;if(A.pageCount!==void 0&&A.pageCount>B)throw Error(`Refusing to render ${A.pageCount} page PDF; maxPageCount=${B}`);let D=await this.getDedupKey(A),Y=_f0(A,D),X=A.documentId!==void 0||A.filename!==void 0;if(A.replace!==!0){let H=await this.findDocumentByDedupKey(D,X?Y:void 0);if(H&&(!X||H.id===Y)){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,Y,{timeoutMs:f,maxBytes:$}),W=H.data;if(W.byteLength>$)throw Error(`Rendered PDF exceeds maxBytes=${$}: ${W.byteLength} bytes`);let Z=Ai0(W);if(Z>B)throw Error(`Rendered PDF has ${Z} pages, exceeding maxPageCount=${B}`);let G=Z>0?Z:A.pageCount;await this.reportProgress(w,{progress:70,message:"Storing PDF document"});let F=A.filename??(A.renderUrl===void 0?H.filename:`${Y}.pdf`),V=HF.createDocumentEntity({dataUrl:g40(W),filename:F,...A.title&&{title:A.title},...G!==void 0&&{pageCount:G},status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,dedupKey:D});if(await NY({entityService:this.context.entityService,entity:{...V,id:Y}}),A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,Y,A);return await this.reportProgress(w,{progress:100,message:"PDF document generation complete"}),{success:!0,documentId:Y,reused:!1}}catch(H){let W=vA(H);throw this.logger.error("Document generation failed",{jobId:Q,error:W}),await UU({entityService:this.context.entityService,entityType:"document",id:Y,error:W}),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}=lw($.content),D=Array.isArray(f.documents)?f.documents.filter(AYw):[],Y=B.replace?await this.removeReferencesForSameSourceAttachment(D,w,B):D,X=Y.some((H)=>H.id===w)?Y:[...Y,{id:w}];await this.context.entityService.updateEntity({entity:{...$,content:o4($.content,"documents",X)}})}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||!QYw(f,w))B.push($)}return B}}function _f0(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 eDw($)}function eDw(A){let Q=w1(A.replace(/[/:]+/g," "))||`document-${rn1(A)}`;if(Q.length<=nn1)return Q;let w=`-${rn1(A)}`;return`${Q.slice(0,nn1-w.length).replace(/-+$/g,"")}${w}`}function rn1(A){return rDw("sha256").update(A).digest("hex").slice(0,tDw)}function AYw(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function QYw(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var on1={name:"@brains/document-plugin",private:!0,version:"0.2.0-alpha.134",description:"Document entity type for generated PDFs and publishable document attachments",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/contracts":"workspace:*","@brains/document":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/typescript-config":"workspace:*","bun-types":"latest",typescript:"^5.3.3"}};var BYw=`data:application/pdf;base64,${Buffer.from(`%PDF-1.4
6298
6298
  % Pending document placeholder
6299
6299
  %%EOF
6300
6300
  `).toString("base64")}`,$Yw=K.object({}),mi0={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function fYw(A,Q){let w=A.title?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}function DYw(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function YYw(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 ui0 extends RQ{entityType=HF.entityType;schema=wE;adapter=HF;pluginContext;constructor(){super("document",on1,{},$Yw)}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 Mf0(this.logger.child("DocumentGenerationJobHandler"),A))}async interceptCreate(A){let Q=this.pluginContext;if(A.from?.kind===mi0.refKind){if(!Q)return{kind:"handled",result:{success:!1,error:"Plugin context not initialized"}};return this.promoteUpload(A,Q)}if(!A.from||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=ar.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??_f0(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 D=await Q.jobs.enqueue({type:"generate",data:{...w,dedupKey:B,documentId:f}}),Y=`${f}.pdf`;return{kind:"handled",result:{success:!0,data:{entityId:f,jobId:D,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:Y,source:{entityType:"document",entityId:f,attachmentType:w.attachmentType}}}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==mi0.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let B;try{B=await Q.uploads.scoped(mi0).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 $=fYw(A,B.record.filename),f=w1($);if(!f)return{kind:"handled",result:{success:!1,error:"Could not derive a document id from the uploaded filename. Provide a title."}};let D=new Date().toISOString(),Y=HF.createDocumentEntity({dataUrl:DYw(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}`}),X=await Q.entityService.createEntity({entity:{id:f,...Y,created:D,updated:D},options:{deduplicateId:!0}});return{kind:"handled",result:{success:!0,data:{entityId:X.entityId,status:"created",attachment:YYw({entityId:X.entityId,filename:B.record.filename})}}}}async createPendingDocument(A,Q){let w=new Date().toISOString(),B=HF.createDocumentEntity({dataUrl:BYw,filename:Q.filename,title:Q.title,status:"pending",sourceEntityType:Q.sourceEntityType,sourceEntityId:Q.sourceEntityId,attachmentType:Q.attachmentType,dedupKey:Q.dedupKey});await FN({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 ci0(){return new ui0}c0();c0();Z0();Z0();c0();var XYw=K.enum(["generating","failed"]),GF=K.object({title:K.string().optional(),status:XYw.optional(),error:K.string().optional()}),sn1=GF.pick({title:!0,status:!0,error:!0}).extend({title:K.string()}),_b=o1.extend({entityType:K.literal("note"),metadata:sn1}),HYw=_b.extend({frontmatter:GF,body:K.string()});c0();Z0();class li0 extends I2{constructor(){super({entityType:"note",purpose:"A short, free-form captured thought, reference, or snippet the user wants to keep.",schema:_b,frontmatterSchema:GF})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,GF);if(w.title)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,GF)}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,K.record(K.unknown()));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 Pb=new li0;Z0();var pi0=K.object({defaultPrompt:K.string().default("Create a note summarizing key concepts from my knowledge base")});Z0();c0();var an1=K.object({title:K.string().max(80).describe("A clear, descriptive title for the note (3-8 words)"),body:K.string().describe("Note content in markdown format with clear organization and structure")}),ii0=R1({name:"note:generation",description:"Template for AI to generate notes from prompts",schema:an1,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create personal knowledge notes for research and reference.
@@ -6312,7 +6312,7 @@ title: ${JSON.stringify(A)}
6312
6312
  ---
6313
6313
 
6314
6314
  ${Q.trim()}
6315
- `}var GYw={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},zYw=K.object({uploadId:K.string().min(1),title:K.string().optional()});class ni0 extends _w{context;constructor(A,Q){super(A,{schema:zYw,jobTypeName:"upload-import"});this.context=Q}async process(A,Q,w){await this.reportProgress(w,{progress:10,message:"Reading uploaded file"});let B=await this.context.uploads.scoped(GYw).read(A.uploadId);await this.reportProgress(w,{progress:35,message:"Extracting markdown from upload"});let $=await Qr1({upload:B,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress(w,{progress:80,message:"Saving imported note"});let f=new Date().toISOString(),D=Pb.fromMarkdown($.content),Y=await this.context.entityService.createEntity({entity:{id:$.id,entityType:"note",content:$.content,metadata:{title:$.title,...D.metadata},created:f,updated:f},options:{deduplicateId:!0}});return await this.reportProgress(w,{progress:100,message:"Upload imported as markdown note"}),{entityId:Y.entityId,status:"created"}}summarizeDataForLog(A){return{uploadId:A.uploadId,hasTitle:A.title!==void 0}}}c0();async function wr1({entity:A,config:Q}){let w=_b.parse(A),B=v2(w.content,GF);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 ri0(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:MB["ai.rizom.brain.note"],validate:!1,buildRecord:wr1}}var Br1={name:"@brains/note",private:!0,version:"0.2.0-alpha.133",description:"Personal knowledge capture with markdown-first workflow",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var $r1={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};class oi0 extends PQ{entityType=Pb.entityType;schema=_b;adapter=Pb;unregisterAtprotoProjection;constructor(A={}){super("note",Br1,A,pi0)}async interceptCreate(A,Q,w){if(A.from?.kind!==$r1.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($r1).readRecord(B)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}try{if(!Ar1($.mediaType))return{kind:"handled",result:{success:!1,error:"Only text, JSON, and PDF uploads can be imported as markdown notes"}};let f=di0({filename:$.filename,...A.title!==void 0?{title:A.title}:{}}),D=await w.jobs.enqueue({type:"upload-import",data:{uploadId:B,...A.title!==void 0?{title:A.title}:{}}});return{kind:"handled",result:{success:!0,data:{entityId:f.id,status:"generating",jobId:D}}}}catch(f){return{kind:"handled",result:{success:!1,error:f instanceof Error?f.message:"Failed to import upload as markdown"}}}}createGenerationHandler(A){return new Pf0(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:ii0}}async onRegister(A){A.jobs.registerHandler("upload-import",new ni0(this.logger.child("UploadMarkdownImportJobHandler"),A)),A.eval.registerHandler("generateNote",async(Q)=>{let w=K.object({prompt:K.string()}).parse(Q);return A.ai.generate({prompt:w.prompt,templateName:"note:generation"})}),this.unregisterAtprotoProjection=U5.getInstance().register(ri0())}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 bP(A={}){return new oi0(A)}c0();Z0();Z0();c0();var fr1=K.object({ref:K.string(),label:K.string()}),Dr1=K.enum(["pending","draft","published"]),zF=K.object({status:Dr1,title:K.string(),url:K.string().url(),description:K.string().optional(),domain:K.string(),capturedAt:K.string().datetime(),source:fr1}),Yr1=zF.pick({title:!0,status:!0}),LP=o1.extend({entityType:K.literal("link"),metadata:Yr1}),si0=K.object({enableSummarization:K.boolean().default(!0).describe("Generate AI summaries for captured links"),jinaApiKey:K.string().optional().describe("Jina Reader API key for higher rate limits (500 RPM vs 20 RPM without key)")});c0();class kb extends I2{constructor(){super({entityType:"link",purpose:"A saved external URL or web resource captured for later reference.",schema:LP,frontmatterSchema:zF})}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,zF),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 qE=new kb;c0();Z0();var FYw=K.object({success:K.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:K.string().describe("If success is false, explain why content could not be extracted. Use an empty string when success is true."),title:K.string().max(80).describe("The page title - extract from the content or create a descriptive one. Leave empty string if success is false."),description:K.string().describe("A one-sentence description of what the page is about. Leave empty string if success is false."),summary:K.string().describe("A 1-2 paragraph summary of the main content. Leave empty string if success is false.")}),Xr1=R1({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:FYw,basePrompt:`You are an expert at extracting key information from webpage content.
6315
+ `}var GYw={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},zYw=K.object({uploadId:K.string().min(1),title:K.string().optional()});class ni0 extends _w{context;constructor(A,Q){super(A,{schema:zYw,jobTypeName:"upload-import"});this.context=Q}async process(A,Q,w){await this.reportProgress(w,{progress:10,message:"Reading uploaded file"});let B=await this.context.uploads.scoped(GYw).read(A.uploadId);await this.reportProgress(w,{progress:35,message:"Extracting markdown from upload"});let $=await Qr1({upload:B,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress(w,{progress:80,message:"Saving imported note"});let f=new Date().toISOString(),D=Pb.fromMarkdown($.content),Y=await this.context.entityService.createEntity({entity:{id:$.id,entityType:"note",content:$.content,metadata:{title:$.title,...D.metadata},created:f,updated:f},options:{deduplicateId:!0}});return await this.reportProgress(w,{progress:100,message:"Upload imported as markdown note"}),{entityId:Y.entityId,status:"created"}}summarizeDataForLog(A){return{uploadId:A.uploadId,hasTitle:A.title!==void 0}}}c0();async function wr1({entity:A,config:Q}){let w=_b.parse(A),B=v2(w.content,GF);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 ri0(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:MB["ai.rizom.brain.note"],validate:!1,buildRecord:wr1}}var Br1={name:"@brains/note",private:!0,version:"0.2.0-alpha.134",description:"Personal knowledge capture with markdown-first workflow",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var $r1={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};class oi0 extends PQ{entityType=Pb.entityType;schema=_b;adapter=Pb;unregisterAtprotoProjection;constructor(A={}){super("note",Br1,A,pi0)}async interceptCreate(A,Q,w){if(A.from?.kind!==$r1.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($r1).readRecord(B)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}try{if(!Ar1($.mediaType))return{kind:"handled",result:{success:!1,error:"Only text, JSON, and PDF uploads can be imported as markdown notes"}};let f=di0({filename:$.filename,...A.title!==void 0?{title:A.title}:{}}),D=await w.jobs.enqueue({type:"upload-import",data:{uploadId:B,...A.title!==void 0?{title:A.title}:{}}});return{kind:"handled",result:{success:!0,data:{entityId:f.id,status:"generating",jobId:D}}}}catch(f){return{kind:"handled",result:{success:!1,error:f instanceof Error?f.message:"Failed to import upload as markdown"}}}}createGenerationHandler(A){return new Pf0(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:ii0}}async onRegister(A){A.jobs.registerHandler("upload-import",new ni0(this.logger.child("UploadMarkdownImportJobHandler"),A)),A.eval.registerHandler("generateNote",async(Q)=>{let w=K.object({prompt:K.string()}).parse(Q);return A.ai.generate({prompt:w.prompt,templateName:"note:generation"})}),this.unregisterAtprotoProjection=U5.getInstance().register(ri0())}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 bP(A={}){return new oi0(A)}c0();Z0();Z0();c0();var fr1=K.object({ref:K.string(),label:K.string()}),Dr1=K.enum(["pending","draft","published"]),zF=K.object({status:Dr1,title:K.string(),url:K.string().url(),description:K.string().optional(),domain:K.string(),capturedAt:K.string().datetime(),source:fr1}),Yr1=zF.pick({title:!0,status:!0}),LP=o1.extend({entityType:K.literal("link"),metadata:Yr1}),si0=K.object({enableSummarization:K.boolean().default(!0).describe("Generate AI summaries for captured links"),jinaApiKey:K.string().optional().describe("Jina Reader API key for higher rate limits (500 RPM vs 20 RPM without key)")});c0();class kb extends I2{constructor(){super({entityType:"link",purpose:"A saved external URL or web resource captured for later reference.",schema:LP,frontmatterSchema:zF})}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,zF),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 qE=new kb;c0();Z0();var FYw=K.object({success:K.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:K.string().describe("If success is false, explain why content could not be extracted. Use an empty string when success is true."),title:K.string().max(80).describe("The page title - extract from the content or create a descriptive one. Leave empty string if success is false."),description:K.string().describe("A one-sentence description of what the page is about. Leave empty string if success is false."),summary:K.string().describe("A 1-2 paragraph summary of the main content. Leave empty string if success is false.")}),Xr1=R1({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:FYw,basePrompt:`You are an expert at extracting key information from webpage content.
6316
6316
 
6317
6317
  You will receive webpage content in markdown format. Your job is to extract structured information from it.
6318
6318
 
@@ -6334,7 +6334,7 @@ Accuracy rules:
6334
6334
 
6335
6335
  `))return{success:!1,error:D.trim(),errorType:"fetch_failed"};return{success:!0,content:D}}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 bYw}from"crypto";class Ob{static URL_PATTERN=/https?:\/\/[^\s<>"{}|\\^`[\]]+?(?=[,;:\s]|$)/gi;static extractUrls(A){let Q=A.match(Ob.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=bYw("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}}}c0();Z0();CB();var LYw=K.object({url:K.string().url(),metadata:K.object({interfaceId:K.string().optional(),userId:K.string().optional(),channelId:K.string().optional(),channelName:K.string().optional(),timestamp:K.string().optional()}).optional()}),In8=K.object({success:K.boolean(),entityId:K.string().optional(),title:K.string().optional(),url:K.string().optional(),status:K.enum(["pending","draft","published"]).optional(),error:K.string().optional()});class Of0 extends _w{context;linkAdapter;urlFetcher;constructor(A,Q,w){super(A,{schema:LYw,jobTypeName:"link-capture"});this.context=Q,this.linkAdapter=new kb,this.urlFetcher=new FE(w?.jinaApiKey?{jinaApiKey:w.jinaApiKey}:void 0)}async process(A,Q,w){let{url:B,metadata:$}=A;try{await w.report({progress:_Q.START,total:100,message:"Starting link capture"});let f=Ob.generateEntityId(B);await w.report({progress:_Q.INIT,total:100,message:"Checking for existing link"});let D=await this.context.entityService.getEntity({entityType:"link",id:f});if(D){let{frontmatter:F}=this.linkAdapter.parseLinkContent(D.content),V=D.metadata.status;if(V!=="pending")return this.logger.info("Link already captured, returning existing",{url:B,entityId:f}),{success:!0,entityId:D.id,title:F.title,url:B,status:V};this.logger.info("Pending link exists, completing extraction",{url:B,entityId:f})}let Y=this.resolveSource($),X=new Date().toISOString();await w.report({progress:_Q.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 F=new URL(B).hostname,V=`Could not capture link: ${H.error}`,b=this.linkAdapter.createLinkContent({status:"pending",title:F,url:B,description:V,summary:V,domain:F,capturedAt:X,source:Y});return await NY({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:b,metadata:{status:"pending",title:F}}}),{success:!1,entityId:f,title:F,url:B,status:"pending",error:V}}}await w.report({progress:_Q.PROCESS,total:100,message:"Extracting content with AI"});let W=await this.context.ai.generate({templateName:"link:extraction",prompt:H.success?`Extract structured information from this webpage content:
6336
6336
 
6337
- ${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:W}),await w.report({progress:_Q.EXTRACT,total:100,message:"Processing extraction results"}),W.success===!1||!W.title||!W.description||!W.summary){let F=W.title||new URL(B).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:B}),await w.report({progress:_Q.SAVE,total:100,message:"Saving link as pending"});let V=this.linkAdapter.createLinkContent({status:"pending",title:F,url:B,description:W.description,summary:W.summary,domain:new URL(B).hostname,capturedAt:X,source:Y}),b=await NY({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:V,metadata:{status:"pending",title:F}}});return await w.report({progress:_Q.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:b.entityId,title:F,url:B,status:"pending"}}await w.report({progress:_Q.SAVE,total:100,message:`Saving link: "${W.title}"`});let Z=this.linkAdapter.createLinkContent({status:"draft",title:W.title,url:B,description:W.description,summary:W.summary,domain:new URL(B).hostname,capturedAt:X,source:Y}),G=await NY({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:Z,metadata:{status:"draft",title:W.title}}});return await w.report({progress:_Q.COMPLETE,total:100,message:`Link captured: "${W.title}"`}),{success:!0,entityId:G.entityId,title:W.title,url:B,status:"draft"}}catch(f){return this.logger.error("Link capture job failed",{error:f,jobId:Q,data:A}),x6.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 Zr1({entity:A,config:Q}){let w=LP.parse(A),{frontmatter:B,summary:$}=qE.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 wd0(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:MB["ai.rizom.brain.link"],validate:!1,buildRecord:Zr1}}var Kr1={name:"@brains/link",private:!0,version:"0.2.0-alpha.133",description:"Web content capture plugin with AI-powered extraction and structured storage",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class Bd0 extends PQ{entityType=qE.entityType;schema=LP;adapter=qE;shell;unregisterAtprotoProjection;constructor(A={}){super("link",Kr1,A,si0)}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 Of0(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,D=typeof f?.title==="string"?f.title:void 0,Y=typeof f?.status==="string"?f.status:void 0,X=this.extractFirstUrl(A.content);if(D&&Y&&X){let H=w1(X)||w1(D)||`${A.entityType}-${Date.now()}`,W=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:D,status:Y},created:W,updated:W}})).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 Of0(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:Xr1,"link-list":Hr1,"link-detail":Wr1}}getDataSources(){return[new Qd0(this.logger.child("LinksDataSource"))]}async onRegister(A){this.unregisterAtprotoProjection=U5.getInstance().register(wd0()),A.eval.registerHandler("extractContent",async(Q)=>{let{url:w}=K.object({url:K.string().url()}).parse(Q),$=await new FE(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:
6337
+ ${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:W}),await w.report({progress:_Q.EXTRACT,total:100,message:"Processing extraction results"}),W.success===!1||!W.title||!W.description||!W.summary){let F=W.title||new URL(B).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:B}),await w.report({progress:_Q.SAVE,total:100,message:"Saving link as pending"});let V=this.linkAdapter.createLinkContent({status:"pending",title:F,url:B,description:W.description,summary:W.summary,domain:new URL(B).hostname,capturedAt:X,source:Y}),b=await NY({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:V,metadata:{status:"pending",title:F}}});return await w.report({progress:_Q.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:b.entityId,title:F,url:B,status:"pending"}}await w.report({progress:_Q.SAVE,total:100,message:`Saving link: "${W.title}"`});let Z=this.linkAdapter.createLinkContent({status:"draft",title:W.title,url:B,description:W.description,summary:W.summary,domain:new URL(B).hostname,capturedAt:X,source:Y}),G=await NY({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:Z,metadata:{status:"draft",title:W.title}}});return await w.report({progress:_Q.COMPLETE,total:100,message:`Link captured: "${W.title}"`}),{success:!0,entityId:G.entityId,title:W.title,url:B,status:"draft"}}catch(f){return this.logger.error("Link capture job failed",{error:f,jobId:Q,data:A}),x6.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 Zr1({entity:A,config:Q}){let w=LP.parse(A),{frontmatter:B,summary:$}=qE.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 wd0(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:MB["ai.rizom.brain.link"],validate:!1,buildRecord:Zr1}}var Kr1={name:"@brains/link",private:!0,version:"0.2.0-alpha.134",description:"Web content capture plugin with AI-powered extraction and structured storage",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class Bd0 extends PQ{entityType=qE.entityType;schema=LP;adapter=qE;shell;unregisterAtprotoProjection;constructor(A={}){super("link",Kr1,A,si0)}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 Of0(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,D=typeof f?.title==="string"?f.title:void 0,Y=typeof f?.status==="string"?f.status:void 0,X=this.extractFirstUrl(A.content);if(D&&Y&&X){let H=w1(X)||w1(D)||`${A.entityType}-${Date.now()}`,W=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:D,status:Y},created:W,updated:W}})).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 Of0(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:Xr1,"link-list":Hr1,"link-detail":Wr1}}getDataSources(){return[new Qd0(this.logger.child("LinksDataSource"))]}async onRegister(A){this.unregisterAtprotoProjection=U5.getInstance().register(wd0()),A.eval.registerHandler("extractContent",async(Q)=>{let{url:w}=K.object({url:K.string().url()}).parse(Q),$=await new FE(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:
6338
6338
 
6339
6339
  ${$.content}`,data:{url:w,hasContent:!0},interfacePermissionGrant:"public"})})}async createPendingLink(A,Q,w,B){let $=Ob.generateEntityId(A),f=new URL(A),D=new Date().toISOString(),Y=Q?.trim()?Q.trim():f.hostname,X=this.adapter.createLinkContent({status:"pending",title:Y,url:A,description:"Link capture is in progress.",summary:`Pending link capture for ${A}.`,domain:f.hostname,capturedAt:D,source:this.resolveSource(w)});return(await FN({entityService:B.entityService,entity:{id:$,entityType:"link",content:X,metadata:{status:"pending",title:Y},created:D,updated:D}})).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]=Ob.extractUrls(Q);if(w)return w}return}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function Ur1(A={}){return new Bd0(A)}var NP=Ur1;Z0();var in8=K.object({id:K.string().optional(),metadata:K.object({conversationId:K.string().optional(),interfaceId:K.string().optional(),userId:K.string().optional(),messageId:K.string().optional(),timestamp:K.string().optional()}).optional()});c0();Z0();JB();Z0();c0();var Gr1=K.enum(["generating","draft","published","failed"]),X9=K.object({title:K.string(),slug:K.string().optional(),status:Gr1,publishedAt:K.string().datetime().optional(),description:K.string(),year:K.number(),coverImageId:K.string().optional(),ogImageId:K.string().optional(),url:K.string().url().optional()}),zr1=X9.pick({title:!0,status:!0,publishedAt:!0,year:!0}).extend({slug:K.string(),error:K.string().optional()}),xb=o1.extend({entityType:K.literal("project"),metadata:zr1}),xf0=K.object({context:K.string(),problem:K.string(),solution:K.string(),outcome:K.string()}),er=xb.extend({frontmatter:X9,body:K.string(),structuredContent:xf0.optional(),coverImageUrl:K.string().optional(),ogImageUrl:K.string().optional()}),VE=er.extend({url:K.string().optional(),typeLabel:K.string().optional(),coverImageUrl:K.string().optional(),ogImageUrl:K.string().optional(),coverImageWidth:K.number().optional(),coverImageHeight:K.number().optional()}),jYw=er.extend({url:K.string(),typeLabel:K.string(),coverImageUrl:K.string().optional(),ogImageUrl:K.string().optional(),coverImageWidth:K.number().optional(),coverImageHeight:K.number().optional()});c0();Z0();l$();class $d0 extends pw{constructor(){super(xf0,{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 fd0=new $d0;class Dd0 extends I2{constructor(){super({entityType:"project",purpose:"A project record in the user's portfolio.",schema:xb,frontmatterSchema:X9,supportsCoverImage:!0,bodyFormatter:fd0})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,X9),B={...w,slug:w.slug??A.metadata.slug};return this.buildMarkdown(Q,B)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,X9),w=Q.slug??w1(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,X9)}parseStructuredContent(A){return fd0.parse(this.extractBody(A.content))}createProjectContent(A,Q){let w=fd0.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 Rb=new Dd0;Z0();var Yd0=K.object({});import{jsxDEV as hX,Fragment as _Yw}from"preact/jsx-dev-runtime";var MYw=({project:A})=>{let{frontmatter:Q,url:w,coverImageUrl:B}=A;return hX(uw,{href:w,children:[B&&hX("img",{src:B,alt:Q.title,className:"w-full h-56 object-cover rounded-md mb-4"},void 0,!1,void 0,this),hX(d9,{children:Q.title},void 0,!1,void 0,this),hX("p",{className:"text-theme leading-relaxed",children:Q.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},Xd0=({projects:A,pageTitle:Q,pagination:w,baseUrl:B="/projects"})=>{let $=Q??"Projects",f=w?.totalItems??A.length,D=`Browse all ${f} ${f===1?"project":"projects"}`;return hX(_Yw,{children:[hX(NQ,{title:$,description:D},void 0,!1,void 0,this),hX("div",{className:"project-list bg-theme",children:hX("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[hX("h1",{className:"text-4xl font-bold text-heading mb-12",children:$},void 0,!1,void 0,this),hX("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:A.map((Y)=>hX(MYw,{project:Y},Y.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&hX("div",{className:"mt-12",children:hX(d3,{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 zB,Fragment as qr1}from"preact/jsx-dev-runtime";var PYw=({prevProject:A,nextProject:Q})=>{if(!A&&!Q)return null;return zB("nav",{className:"pt-12 mt-12 border-t border-theme-muted",children:zB("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[A?zB(uw,{href:A.url,variant:"compact",children:[zB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Previous"},void 0,!1,void 0,this),zB("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):zB("div",{},void 0,!1,void 0,this),Q&&zB(uw,{href:Q.url,variant:"compact",className:"md:text-right",children:[zB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Next"},void 0,!1,void 0,this),zB("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)},Rf0=({title:A,content:Q})=>{if(!Q)return null;return zB("section",{className:"mb-12",children:[zB("h2",{className:"text-2xl font-bold text-heading mb-4",children:A},void 0,!1,void 0,this),zB($9,{markdown:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},Hd0=({project:A,prevProject:Q,nextProject:w})=>{let{frontmatter:B,structuredContent:$,metadata:f,coverImageUrl:D}=A,Y=A.ogImageUrl??D;return zB(qr1,{children:[zB(NQ,{title:B.title,description:B.description,...Y?{ogImage:Y}:{},ogType:"article"},void 0,!1,void 0,this),zB("article",{className:"project-detail",children:zB("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:zB("div",{className:"max-w-3xl mx-auto",children:[D&&A.coverImageWidth&&A.coverImageHeight&&zB(p3,{src:D,alt:B.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8 shadow-lg"},void 0,!1,void 0,this),zB("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),zB("div",{className:"flex flex-wrap items-center gap-4 text-theme-muted mb-8",children:[zB("span",{className:"text-sm",children:f.year},void 0,!1,void 0,this),B.url&&zB(qr1,{children:[zB("span",{className:"text-theme-muted",children:"|"},void 0,!1,void 0,this),zB("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),zB("p",{className:"text-lg text-theme mb-12 leading-relaxed",children:B.description},void 0,!1,void 0,this),$&&zB("div",{className:"case-study",children:[zB(Rf0,{title:"Context",content:$.context},void 0,!1,void 0,this),zB(Rf0,{title:"Problem",content:$.problem},void 0,!1,void 0,this),zB(Rf0,{title:"Solution",content:$.solution},void 0,!1,void 0,this),zB(Rf0,{title:"Outcome",content:$.outcome},void 0,!1,void 0,this)]},void 0,!0,void 0,this),zB(PYw,{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)};Z0();c0();var kYw=K.object({title:K.string().max(80).describe("A clear, compelling project title (3-8 words). Should capture the essence of the project."),description:K.string().describe("A 1-2 sentence summary of the project for portfolio cards. Focus on the core value delivered."),context:K.string().describe("Background information: Who was the client/user? What was the situation? What constraints existed? (2-4 paragraphs)"),problem:K.string().describe("The challenge: What specific problem needed solving? What were the pain points? (2-3 paragraphs)"),solution:K.string().describe("The approach: What was built? What technologies/methods were used? How did it work? (3-5 paragraphs)"),outcome:K.string().describe("The results: What impact did this have? What metrics improved? What was learned? (2-3 paragraphs)")}),Wd0=R1({name:"portfolio:generation",description:"Template for AI to generate portfolio project case studies",schema:kYw,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create a professional portfolio case study based on REAL project information.
6340
6340
 
@@ -6510,7 +6510,7 @@ Use the project request as the primary source of truth. If retrieved knowledge c
6510
6510
  font: 10px/1.45 var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
6511
6511
  }
6512
6512
  .printable-footer a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
6513
- `}},void 0,!1,void 0,this),H9("section",{className:"project-shell",children:[H9("header",{className:"project-hero",children:[H9("div",{className:"project-index",children:[Q.brandLabel&&H9("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&H9("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),H9("div",{className:"project-title-panel",children:[H9("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),H9("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&H9("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),H9("div",{className:"printable-meta",children:[Q.year&&H9("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&H9("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&&H9("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),H9($9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Q.canonicalUrl||Q.url||Q.brandLabel)&&H9("footer",{className:"printable-footer",children:[H9("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?H9("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 gYw=26214400,TYw=60000;class Ud0{context;metadata={outputEntityType:"document"};renderPdf;constructor(A,Q={}){this.context=A;this.renderPdf=Q.renderPdf??VK}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==Cf0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let w=SYw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await vYw(EYw(yYw(),"brain-project-printable-"));try{let $=await MX({outputDir:B,mediaPath:`/_media/printable/project/${Q.id}`,template:Ir1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await _X({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:gYw,timeoutMs:TYw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${mYw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await CYw(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}=lw(A.content),w=X9.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 SYw(A,Q={}){let{frontmatter:w,content:B}=lw(A.content),$=X9.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 mYw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.title)}Z0();Z0();import{jsxDEV as lYw}from"preact/jsx-dev-runtime";var yf0="og-image",uYw="portfolio:og-image",Jr1=K.object({title:K.string().min(1),description:K.string().optional(),year:K.number().optional(),brandLabel:K.string().optional(),coverImageUrl:K.string().optional()}),br1={name:uYw,pluginId:"portfolio",schema:Jr1,renderers:{image:cYw}};function cYw(A){let Q=Jr1.parse(A);return lYw(l3,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class Gd0{context;deps;metadata={outputEntityType:"image",targetField:"ogImageId"};constructor(A,Q={}){this.context=A;this.deps=Q}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==yf0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w}=lw(Q.content),B=X9.parse(w),$=this.resolveBrandLabel(),f=await this.resolveCoverImageUrl(B.coverImageId),D={title:B.title,...B.description?{description:B.description}:{},year:B.year,...f?{coverImageUrl:f}:{},...$?{brandLabel:$}:{}};return{type:"image",data:await KP({mediaPath:`/_media/og/project/${Q.id}`,template:br1,content:D,title:D.title,themeMode:"light",themeCSS:this.context.themeCSS,tmpPrefix:"brain-project-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${pYw(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 pYw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.title)}var Lr1={name:"@brains/portfolio",private:!0,version:"0.2.0-alpha.133",description:"Portfolio showcase for projects and case studies",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest",typescript:"^5.3.3"}};var dYw=K.object({projects:K.array(VE),pageTitle:K.string().optional(),pagination:e7.nullable(),baseUrl:K.string().optional()});function nYw(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 zd0 extends PQ{entityType=Rb.entityType;schema=xb;adapter=Rb;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",Lr1,A,Yd0)}async interceptCreate(A,Q,w){if(!A.prompt||A.content)return{kind:"continue",input:A};let B=nYw(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 hf0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":R1({name:"project-list",description:"Portfolio project list page template",schema:dYw,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:Xd0}}),"project-detail":R1({name:"project-detail",description:"Individual project case study template",schema:K.object({project:VE,prevProject:VE.nullable(),nextProject:VE.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:Hd0}}),generation:Wd0}}getDataSources(){return[new vf0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",Cf0,new Ud0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",yf0,new Gd0(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=U5.getInstance().register(Kd0())}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=K.object({prompt:K.string(),year:K.number()}).parse(Q);return A.ai.generate({prompt:Zd0(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=v2($.content,X9),D=new Date().toISOString(),Y=H7(f.content,{...f.metadata,status:"published",publishedAt:D});await A.entityService.updateEntity({entity:{...$,content:Y,metadata:{...$.metadata,status:"published",publishedAt:D}}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:w,entityId:B,publishedAt:D}})}catch($){await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:vA($)}})}return{success:!0}})}}function qd0(A={}){return new zd0(A)}c0();Z0();var rYw=K.enum(["public","shared","restricted"]),Nr1=K.object({includeEntityTypes:K.array(K.string()).default([]),minRelevanceScore:K.number().min(0).max(1).default(0.5),mergeSimilarityThreshold:K.number().min(0).max(1).default(0.85),autoMerge:K.boolean().default(!0),extractableStatuses:K.array(K.string()).default(["published"]),enableAutoExtraction:K.boolean().default(!0),extractionVisibility:rYw.default("public"),sourceChangeBatchDelayMs:K.number().int().min(0).default(1000)});c0();Z0();c0();var oYw=K.object({}),IE=o1.extend({entityType:K.literal("topic"),metadata:oYw}),mo8=K.object({content:K.string()}),jr1=K.object({title:K.string().describe("Topic title")});var jP="topics",qB="topic",Fd0="topics-projection",Mr1="topic:project",Ef0="topics-plugin",_r1="topics:batch-completed",Pr1="topics-source-batch";class JK extends I2{constructor(){super({entityType:qB,purpose:"A recurring theme or subject derived from the user's content.",schema:IE,frontmatterSchema:jr1})}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:qB}}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))}}c0();Z0();Z0();var sYw=K.object({title:K.string().max(100),content:K.string(),relevanceScore:K.number().min(0).max(1)}),kr1=K.array(sYw);var aYw=K.object({topics:kr1}),Or1=R1({name:"topics:extraction",description:"Extract topics from conversation text",dataSourceId:"shell:ai-content",schema:aYw,basePrompt:`You are an expert at analyzing content and extracting key topics.
6513
+ `}},void 0,!1,void 0,this),H9("section",{className:"project-shell",children:[H9("header",{className:"project-hero",children:[H9("div",{className:"project-index",children:[Q.brandLabel&&H9("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&H9("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),H9("div",{className:"project-title-panel",children:[H9("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),H9("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&H9("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),H9("div",{className:"printable-meta",children:[Q.year&&H9("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&H9("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&&H9("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),H9($9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Q.canonicalUrl||Q.url||Q.brandLabel)&&H9("footer",{className:"printable-footer",children:[H9("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?H9("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 gYw=26214400,TYw=60000;class Ud0{context;metadata={outputEntityType:"document"};renderPdf;constructor(A,Q={}){this.context=A;this.renderPdf=Q.renderPdf??VK}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==Cf0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let w=SYw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await vYw(EYw(yYw(),"brain-project-printable-"));try{let $=await MX({outputDir:B,mediaPath:`/_media/printable/project/${Q.id}`,template:Ir1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await _X({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:gYw,timeoutMs:TYw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${mYw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await CYw(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}=lw(A.content),w=X9.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 SYw(A,Q={}){let{frontmatter:w,content:B}=lw(A.content),$=X9.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 mYw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.title)}Z0();Z0();import{jsxDEV as lYw}from"preact/jsx-dev-runtime";var yf0="og-image",uYw="portfolio:og-image",Jr1=K.object({title:K.string().min(1),description:K.string().optional(),year:K.number().optional(),brandLabel:K.string().optional(),coverImageUrl:K.string().optional()}),br1={name:uYw,pluginId:"portfolio",schema:Jr1,renderers:{image:cYw}};function cYw(A){let Q=Jr1.parse(A);return lYw(l3,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class Gd0{context;deps;metadata={outputEntityType:"image",targetField:"ogImageId"};constructor(A,Q={}){this.context=A;this.deps=Q}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==yf0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w}=lw(Q.content),B=X9.parse(w),$=this.resolveBrandLabel(),f=await this.resolveCoverImageUrl(B.coverImageId),D={title:B.title,...B.description?{description:B.description}:{},year:B.year,...f?{coverImageUrl:f}:{},...$?{brandLabel:$}:{}};return{type:"image",data:await KP({mediaPath:`/_media/og/project/${Q.id}`,template:br1,content:D,title:D.title,themeMode:"light",themeCSS:this.context.themeCSS,tmpPrefix:"brain-project-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${pYw(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 pYw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.title)}var Lr1={name:"@brains/portfolio",private:!0,version:"0.2.0-alpha.134",description:"Portfolio showcase for projects and case studies",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest",typescript:"^5.3.3"}};var dYw=K.object({projects:K.array(VE),pageTitle:K.string().optional(),pagination:e7.nullable(),baseUrl:K.string().optional()});function nYw(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 zd0 extends PQ{entityType=Rb.entityType;schema=xb;adapter=Rb;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",Lr1,A,Yd0)}async interceptCreate(A,Q,w){if(!A.prompt||A.content)return{kind:"continue",input:A};let B=nYw(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 hf0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":R1({name:"project-list",description:"Portfolio project list page template",schema:dYw,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:Xd0}}),"project-detail":R1({name:"project-detail",description:"Individual project case study template",schema:K.object({project:VE,prevProject:VE.nullable(),nextProject:VE.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:Hd0}}),generation:Wd0}}getDataSources(){return[new vf0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",Cf0,new Ud0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",yf0,new Gd0(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=U5.getInstance().register(Kd0())}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=K.object({prompt:K.string(),year:K.number()}).parse(Q);return A.ai.generate({prompt:Zd0(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=v2($.content,X9),D=new Date().toISOString(),Y=H7(f.content,{...f.metadata,status:"published",publishedAt:D});await A.entityService.updateEntity({entity:{...$,content:Y,metadata:{...$.metadata,status:"published",publishedAt:D}}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:w,entityId:B,publishedAt:D}})}catch($){await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:vA($)}})}return{success:!0}})}}function qd0(A={}){return new zd0(A)}c0();Z0();var rYw=K.enum(["public","shared","restricted"]),Nr1=K.object({includeEntityTypes:K.array(K.string()).default([]),minRelevanceScore:K.number().min(0).max(1).default(0.5),mergeSimilarityThreshold:K.number().min(0).max(1).default(0.85),autoMerge:K.boolean().default(!0),extractableStatuses:K.array(K.string()).default(["published"]),enableAutoExtraction:K.boolean().default(!0),extractionVisibility:rYw.default("public"),sourceChangeBatchDelayMs:K.number().int().min(0).default(1000)});c0();Z0();c0();var oYw=K.object({}),IE=o1.extend({entityType:K.literal("topic"),metadata:oYw}),mo8=K.object({content:K.string()}),jr1=K.object({title:K.string().describe("Topic title")});var jP="topics",qB="topic",Fd0="topics-projection",Mr1="topic:project",Ef0="topics-plugin",_r1="topics:batch-completed",Pr1="topics-source-batch";class JK extends I2{constructor(){super({entityType:qB,purpose:"A recurring theme or subject derived from the user's content.",schema:IE,frontmatterSchema:jr1})}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:qB}}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))}}c0();Z0();Z0();var sYw=K.object({title:K.string().max(100),content:K.string(),relevanceScore:K.number().min(0).max(1)}),kr1=K.array(sYw);var aYw=K.object({topics:kr1}),Or1=R1({name:"topics:extraction",description:"Extract topics from conversation text",dataSourceId:"shell:ai-content",schema:aYw,basePrompt:`You are an expert at analyzing content and extracting key topics.
6514
6514
 
6515
6515
  Analyze the provided content and extract meaningful topics discussed.
6516
6516
 
@@ -6613,13 +6613,13 @@ ${A.incomingTopic.content}`})}}function XXw(A){if(A.length===0)return"";return A
6613
6613
 
6614
6614
  ${Q.content}`}).join(`
6615
6615
 
6616
- `)}async function MP(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,D=B.mergeSimilarityThreshold??0.85,Y=B.targetVisibility??"public",X=mr1(A),H=new bK(Q.entityService,w),W=B.topicMergeSynthesizer??new Nd0(Q,w),Z=await uf0(Q.entityService,void 0,Y),G=new Map,F=0,V=0,b=0;for(let N of X){w.info(`Processing batch of ${N.length} entities`);let _=XXw(N),j=cf0({entityTitle:`Batch of ${N.length} entities`,entityType:"batch",content:_,existingTopicTitles:Z});try{let E=(await Q.ai.generate({prompt:j,templateName:"topics:extraction"})).topics.filter((y)=>y.relevanceScore>=$);for(let y of E)try{if(f){let S=await H.findMergeCandidate({incoming:y,threshold:D,additionalCandidates:Array.from(G.values()),targetVisibility:Y});if(S){let c=await W.synthesize({existingTopic:S.topic,incomingTopic:y}),m=await H.applySynthesizedMerge({existingId:S.topic.id,synthesized:{...c,title:S.title},visibility:Y});if(!m)throw Error(`Failed to merge topic: ${y.title}`);G.set(m.id,m),V++;continue}}let h=H.getTopicIdForTitle(y.title,Y);if(G.has(h)){b++;continue}let T=await H.createTopicOptimistic({title:y.title,content:y.content,visibility:Y});if(T.topic)G.set(T.topic.id,T.topic);if(T.created)F++;else b++}catch(h){w.error("Topic batch item failed",{title:y.title,error:vA(h)})}}catch(g){w.error("Batch topic extraction failed",{batchSize:N.length,promptChars:j.length,error:vA(g)})}}let L={created:F,merged:V,skipped:b,batches:X.length};if(F>0||V>0)await Q.messaging.send({type:_r1,payload:L,broadcast:!0});return L}c0();Z0();var HXw=K.discriminatedUnion("mode",[K.object({mode:K.literal("derive"),reason:K.string().optional()}),K.object({mode:K.literal("rebuild"),reason:K.string().optional()}),K.object({mode:K.literal("source-batch"),minRelevanceScore:K.number().min(0).max(1).optional()})]);class jd0{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 dr1(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 WXw({context:Q,logger:w,config:B,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:$.minRelevanceScore??B.minRelevanceScore})},validateAndParse:($)=>{let f=HXw.safeParse($??{});return f.success?f.data:null}}}async function WXw(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,D=0,Y=[];for(let{ref:H,entity:W}of w){if(!W){$++;continue}if(W.contentHash!==H.contentHash){B++;continue}if(!A.isEntityPublished(W)){f++;continue}if(!cV(W.visibility,A.config.extractionVisibility)){D++;continue}Y.push(W)}if(Y.length===0)return{success:!0,sources:Q.length,created:0,merged:0,skipped:0,batches:0,stale:B,missing:$,unpublished:f,hidden:D};let X=await MP(Y,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,...X,stale:B,missing:$,unpublished:f,hidden:D}}function nr1(){return{priority:5,source:Ef0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:jP}}}async function rr1(A){let Q=await sr1(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 MP(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 or1(A){let Q=await sr1(A),w=await Md0(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",w)}async function Md0(A,Q,w,B){let $=new bK(Q.entityService,w),f=await $.listTopics({visibility:B.extractionVisibility});for(let Y of f)await $.deleteTopic(Y.id);if(A.length===0)return{deleted:f.length,created:0,merged:0,skipped:0,batches:0};let D=await MP(A,Q,w,{minRelevanceScore:B.minRelevanceScore,autoMerge:B.autoMerge,mergeSimilarityThreshold:B.mergeSimilarityThreshold,targetVisibility:B.extractionVisibility});return{deleted:f.length,...D}}async function sr1(A){let Q=ZXw(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 ZXw(A){return A.context.entityService.getEntityTypes().filter((w)=>A.shouldProcessEntityType(w))}var LE=K.object({entityType:K.string(),content:K.string(),metadata:K.record(K.unknown()).optional()}),KXw=LE.extend({minRelevanceScore:K.number().optional()}),UXw=K.object({contentA:LE,contentB:LE,minRelevanceScore:K.number().optional(),threshold:K.number().min(0).max(1).optional()}),Bo=K.object({title:K.string(),content:K.string()}),GXw=K.object({existingTopics:K.array(Bo),incomingTopic:Bo,threshold:K.number().optional()}),zXw=K.object({existingTopics:K.array(Bo).default([]),incomingTopic:Bo.extend({relevanceScore:K.number().min(0).max(1).optional()}),threshold:K.number().optional()}),qXw=K.object({entities:K.array(LE).min(1),minRelevanceScore:K.number().optional()}),FXw=K.object({existingTopics:K.array(Bo).optional(),entities:K.array(LE)}),VXw=K.object({entities:K.array(LE)});function bE(A,Q=""){return{id:`eval${Q}-${Date.now()}`,entityType:A.entityType,content:A.content,contentHash:xw(A.content),visibility:"public",metadata:A.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}}function ar1(A){return{title:A.title,relevanceScore:A.relevanceScore}}function IXw(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function JXw(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:IXw(Q)}]}}async function _P(A){let Q=await A.entityService.listEntities({entityType:qB});await Promise.all(Q.map((w)=>A.entityService.deleteEntity({entityType:qB,id:w.id})))}async function bXw(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise((w)=>setTimeout(w,100))}}function tr1(A){let{context:Q,logger:w,config:B}=A,$=new Ld0(Q,w),f=async(D,Y,X="")=>{let H=bE(D,X);return $.extractFromEntity(H,Y)};Q.eval.registerHandler("extractFromEntity",async(D)=>{await _P(Q);let Y=KXw.parse(D),X=Y.minRelevanceScore??B.minRelevanceScore,H=bE(Y);return(await $.extractFromEntity(H,X)).map((Z)=>JXw(Z,H))}),Q.eval.registerHandler("checkMergeSimilarity",async(D)=>{await _P(Q);let Y=UXw.parse(D),X=Y.minRelevanceScore??B.minRelevanceScore,H=Y.threshold??B.mergeSimilarityThreshold,[W,Z]=await Promise.all([f(Y.contentA,X,"-a"),f(Y.contentB,X,"-b")]),G=new bK(Q.entityService,w),F=[];for(let L of W){let N=await G.createTopic(L);if(N)F.push(N)}let V=(await Promise.all(Z.map(async(L)=>{let N=await G.findMergeCandidate({incoming:L,threshold:H,additionalCandidates:F});if(!N)return null;return{incomingTitle:L.title,candidateTitle:N.title,candidateScore:N.score}}))).filter((L)=>L!==null),b=V.map((L)=>L.candidateTitle);return{topicsA:W.map(ar1),topicsB:Z.map(ar1),matchingTitles:b,mergeCandidates:V,wouldMerge:V.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(D)=>{await _P(Q);let Y=GXw.parse(D),X=Y.threshold??B.mergeSimilarityThreshold,H=new bK(Q.entityService,w),W=[];for(let G of Y.existingTopics){let F=await H.createTopic(G);if(F)W.push(F)}let Z=await H.findMergeCandidate({incoming:{title:Y.incomingTopic.title},threshold:X,additionalCandidates:W});return{found:Z!==null,candidateTitle:Z?.title,candidateScore:Z?.score}}),Q.eval.registerHandler("processTopicWithAutoMerge",async(D)=>{await _P(Q);let Y=zXw.parse(D),X=new bK(Q.entityService,w);for(let G of Y.existingTopics)await X.createTopic({title:G.title,content:G.content});await bXw(Q);let H=bE({entityType:"post",content:Y.incomingTopic.content,metadata:{title:Y.incomingTopic.title}},"-source"),W=await MP([H],Q,w,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:Y.threshold??B.mergeSimilarityThreshold}),Z=await Q.entityService.listEntities({entityType:qB});return{...W,topicCount:Z.length,topics:Z.map(Jd0)}}),Q.eval.registerHandler("rebuildTopics",async(D)=>{await _P(Q);let Y=FXw.parse(D),X=new bK(Q.entityService,w);for(let G of Y.existingTopics??[])await X.createTopic(G);let H=Y.entities.map((G,F)=>bE(G,`-rebuild-${F}`)),W=await Md0(H,Q,w,B),Z=await Q.entityService.listEntities({entityType:qB});return{...W,topicCount:Z.length,topics:Z.map(Jd0)}}),Q.eval.registerHandler("extractSequentially",async(D)=>{await _P(Q);let Y=qXw.parse(D),X=Y.minRelevanceScore??B.minRelevanceScore,H=new bK(Q.entityService,w),W=[];for(let[G,F]of Y.entities.entries()){let V=bE(F,`-sequential-${G}`),b=await $.extractFromEntity(V,X);for(let L of b)await H.createTopic({title:L.title,content:L.content});W.push({extractedTitles:b.map((L)=>L.title)})}let Z=await Q.entityService.listEntities({entityType:qB});return{totalTopics:Z.length,perEntity:W,topics:Z.map(JE)}}),Q.eval.registerHandler("batchExtract",async(D)=>{await _P(Q);let X=VXw.parse(D).entities.map((Z,G)=>bE(Z,`-batch-${G}`)),H=await MP(X,Q,w,{minRelevanceScore:B.minRelevanceScore}),W=await Q.entityService.listEntities({entityType:qB});return{...H,topics:W.map(JE)}})}var LXw=new JK;async function er1({entity:A,config:Q}){let w=IE.parse(A),B=LXw.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 _d0(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:MB["ai.rizom.brain.topic"],validate:!1,buildRecord:er1}}var Ao1={name:"@brains/topics",private:!0,version:"0.2.0-alpha.133",description:"Extract and manage topics from conversations",type:"module",main:"./src/index.ts",types:"./src/index.ts",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest","@types/node":"^20.0.0",typescript:"^5.3.3"}};var jXw=new JK;class Qo1 extends PQ{entityType=qB;schema=IE;adapter=jXw;unregisterAtprotoProjection;sourceBatch=new jd0;constructor(A={}){super(jP,Ao1,A,Nr1)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:Or1,"merge-synthesis":xr1,"topic-list":Rr1,"topic-detail":hr1}}getDataSources(){return[new bd0(this.logger.child("TopicsDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:Fd0,targetType:qB,job:{type:Mr1,handler:dr1({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 qN(A,qB,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:nr1()},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(!cV(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:Ef0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:Pr1,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:jP}})}}]}async onRegister(A){A.insights.register("topic-distribution",yr1()),Er1({context:A,pluginId:this.id}),tr1({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=U5.getInstance().register(_d0())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(Fd0)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===qB)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let w=A.metadata.status;if(w===void 0||w===null)return!0;if(typeof w!=="string")return!1;return this.config.extractableStatuses.includes(w)}async extractAllTopics(A){await rr1({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await or1({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function lf0(A){return new Qo1(A)}c0();Z0();c0();var Pd0=K.enum(["linkedin"]),kd0=K.enum(["generating","draft","queued","published","failed"]),wo1=K.enum(["post","deck"]),Bo1=K.object({id:K.string().min(1).describe("Document entity ID")}),YW=K.object({title:K.string().describe("Short descriptive title (3-6 words) for file naming"),platform:Pd0.describe("Target platform"),status:kd0,coverImageId:K.string().optional().describe("Image entity ID for post image"),documents:K.array(Bo1).optional().describe("Document attachments for publishing"),publishedAt:K.string().datetime().optional(),platformPostId:K.string().optional().describe("ID from platform after publishing"),sourceEntityId:K.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:wo1.optional().describe("Source entity type (post, deck)")}),$o1=YW.extend({platform:Pd0.optional(),status:kd0.optional()}),fo1=YW.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:K.string().describe("URL-friendly identifier: {platform}-{title}"),error:K.string().optional()}),hb=o1.extend({entityType:K.literal("social-post"),metadata:fo1}),pf0=hb.extend({frontmatter:YW,body:K.string()}),if0=pf0.extend({url:K.string().optional(),listUrl:K.string().optional(),listLabel:K.string().optional(),typeLabel:K.string().optional(),coverImageUrl:K.string().optional(),coverImageWidth:K.number().optional(),coverImageHeight:K.number().optional()});c0();Z0();class Od0 extends I2{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:hb,frontmatterSchema:YW,supportsCoverImage:!0})}toMarkdown(A){let Q="",w={};try{w=this.parseFrontMatter(A.content,YW),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,$o1),w=Q.platform??"linkedin",B=Q.status??"draft",$=`${w}-${w1(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,YW)}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-${w1(A.title)}`,platform:"linkedin",status:"generating"}}}}var R7=new Od0;c0();c0();Z0();var MXw=qU.extend({platform:K.enum(["linkedin"]).optional(),status:K.enum(["generating","draft","queued","published","failed"]).optional(),sortByQueue:K.boolean().optional(),nextInQueue:K.boolean().optional()}),_Xw=FU.extend({query:MXw.optional()});function Do1(A){let Q=v2(A.content,YW);return pf0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class df0 extends W${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=_Xw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return Do1(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:W}=await this.fetchDetail(B.id,$);return Q.parse(this.buildDetailResult(W,null))}let f={};if(B.platform)f.platform=B.platform;if(B.status)f.status=B.status;let D=Object.keys(f).length>0,Y=B.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:X,pagination:H}=await this.fetchList(B,$,{...D&&{filter:{metadata:f}},sortFields:Y});return Q.parse(this.buildListResult(X,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?Do1(B):null;return A.parse({post:$})}}Z0();var Yo1=K.object({accessToken:K.string().optional(),refreshToken:K.string().optional(),organizationId:K.string().optional(),apiVersion:K.string().regex(/^\d{6}$/).optional()}),xd0=K.object({linkedin:Yo1.optional(),publishInterval:K.number().default(3600000),enabled:K.boolean().default(!0),defaultPrompt:K.string().default("Create an engaging social media post that drives engagement"),maxRetries:K.number().default(3),autoGenerateOnBlogPublish:K.boolean().default(!1)});c0();Z0();CB();hd0();import{jsxDEV as c5,Fragment as OXw}from"preact/jsx-dev-runtime";function PXw(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function kXw(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var rf0=({posts:A,pageTitle:Q,pagination:w,baseUrl:B="/social-posts"})=>{let $=Q??"Social Posts",f=w?.totalItems??A.length,D=`Browse all ${f} social ${f===1?"post":"posts"}`;return c5(OXw,{children:[c5(NQ,{title:$,description:D},void 0,!1,void 0,this),c5("div",{className:"social-post-list bg-theme",children:c5("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[c5("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:$},void 0,!1,void 0,this),A.length===0?c5("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):c5("ul",{className:"space-y-6",children:A.map((Y)=>c5("li",{children:c5(uw,{href:Y.url,variant:"horizontal",children:c5("div",{className:"flex flex-col sm:flex-row gap-4",children:[Y.coverImageUrl&&c5("img",{src:Y.coverImageUrl,alt:Y.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),c5("div",{className:"flex-1 min-w-0",children:[c5("div",{className:"flex items-start justify-between gap-4 mb-2",children:[c5("h2",{className:"text-lg font-semibold text-heading",children:Y.frontmatter.title},void 0,!1,void 0,this),c5("time",{className:"text-sm text-theme-muted shrink-0",children:kXw(Y.frontmatter.publishedAt??Y.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c5("div",{className:"flex items-center gap-2 mb-3",children:[c5(CD,{status:Y.frontmatter.status},void 0,!1,void 0,this),c5("span",{className:"text-xs text-theme-muted uppercase",children:Y.frontmatter.platform},void 0,!1,void 0,this),c5("span",{className:"text-xs text-theme-muted font-mono",children:Y.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c5("p",{className:"text-theme leading-relaxed",children:PXw(Y.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)},Y.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&c5(d3,{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 l5,Fragment as xXw}from"preact/jsx-dev-runtime";function Xo1(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var of0=({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 l5(xXw,{children:[l5(NQ,{title:Q,description:w},void 0,!1,void 0,this),l5("section",{className:"social-post-detail",children:l5("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:l5("div",{className:"max-w-3xl mx-auto",children:[l5(_G,{items:B},void 0,!1,void 0,this),l5("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),l5("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[l5(CD,{status:A.frontmatter.status},void 0,!1,void 0,this),l5("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),l5("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&&l5(p3,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),l5(uw,{className:"p-8 mb-8",children:l5("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),l5("div",{className:"space-y-4 text-sm text-theme-muted",children:[l5("div",{children:[l5("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",Xo1(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&l5("div",{children:[l5("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",Xo1(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&l5("div",{children:l5("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 $o(A){return`social-media:${A}`}var RXw=K.union([K.boolean(),K.object({generate:K.boolean().optional(),prompt:K.string().optional()})]),vd0=K.object({prompt:K.string().optional(),platform:K.enum(["linkedin"]).optional(),sourceEntityType:K.enum(["post","deck"]).optional(),sourceEntityId:K.string().optional(),title:K.string().optional().describe("Required when content is provided directly"),content:K.string().optional(),addToQueue:K.boolean().optional(),generateImage:K.boolean().optional().describe("Auto-generate cover image for post"),coverImage:RXw.optional().describe("Generic cover image generation request")}),hXw=GY.extend({slug:K.string().optional()});class PP extends Q4{constructor(A,Q){super(A,Q,{schema:vd0,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let w=A.platform??"linkedin",B=A.addToQueue??!1,{prompt:$,sourceEntityType:f,sourceEntityId:D}=A,{content:Y,title:X}=A;if(Y&&X)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(Y&&!X){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let L=await this.context.ai.generate({prompt:Y,templateName:$o(w)});X=L.title,Y=L.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(D&&f){await this.reportProgress(Q,{progress:10,message:`Fetching source ${f}`});let L=await this.context.entityService.getEntity({entityType:f,id:D});if(!L)this.failEarly(`Source entity not found: ${f}/${D}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let _=K.object({slug:K.string()}).safeParse(L.metadata),j=_.success?_.data.slug:D,g=await this.context.ai.generate({prompt:`Create an engaging ${w} post to promote this ${f}:
6616
+ `)}async function MP(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,D=B.mergeSimilarityThreshold??0.85,Y=B.targetVisibility??"public",X=mr1(A),H=new bK(Q.entityService,w),W=B.topicMergeSynthesizer??new Nd0(Q,w),Z=await uf0(Q.entityService,void 0,Y),G=new Map,F=0,V=0,b=0;for(let N of X){w.info(`Processing batch of ${N.length} entities`);let _=XXw(N),j=cf0({entityTitle:`Batch of ${N.length} entities`,entityType:"batch",content:_,existingTopicTitles:Z});try{let E=(await Q.ai.generate({prompt:j,templateName:"topics:extraction"})).topics.filter((y)=>y.relevanceScore>=$);for(let y of E)try{if(f){let S=await H.findMergeCandidate({incoming:y,threshold:D,additionalCandidates:Array.from(G.values()),targetVisibility:Y});if(S){let c=await W.synthesize({existingTopic:S.topic,incomingTopic:y}),m=await H.applySynthesizedMerge({existingId:S.topic.id,synthesized:{...c,title:S.title},visibility:Y});if(!m)throw Error(`Failed to merge topic: ${y.title}`);G.set(m.id,m),V++;continue}}let h=H.getTopicIdForTitle(y.title,Y);if(G.has(h)){b++;continue}let T=await H.createTopicOptimistic({title:y.title,content:y.content,visibility:Y});if(T.topic)G.set(T.topic.id,T.topic);if(T.created)F++;else b++}catch(h){w.error("Topic batch item failed",{title:y.title,error:vA(h)})}}catch(g){w.error("Batch topic extraction failed",{batchSize:N.length,promptChars:j.length,error:vA(g)})}}let L={created:F,merged:V,skipped:b,batches:X.length};if(F>0||V>0)await Q.messaging.send({type:_r1,payload:L,broadcast:!0});return L}c0();Z0();var HXw=K.discriminatedUnion("mode",[K.object({mode:K.literal("derive"),reason:K.string().optional()}),K.object({mode:K.literal("rebuild"),reason:K.string().optional()}),K.object({mode:K.literal("source-batch"),minRelevanceScore:K.number().min(0).max(1).optional()})]);class jd0{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 dr1(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 WXw({context:Q,logger:w,config:B,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:$.minRelevanceScore??B.minRelevanceScore})},validateAndParse:($)=>{let f=HXw.safeParse($??{});return f.success?f.data:null}}}async function WXw(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,D=0,Y=[];for(let{ref:H,entity:W}of w){if(!W){$++;continue}if(W.contentHash!==H.contentHash){B++;continue}if(!A.isEntityPublished(W)){f++;continue}if(!cV(W.visibility,A.config.extractionVisibility)){D++;continue}Y.push(W)}if(Y.length===0)return{success:!0,sources:Q.length,created:0,merged:0,skipped:0,batches:0,stale:B,missing:$,unpublished:f,hidden:D};let X=await MP(Y,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,...X,stale:B,missing:$,unpublished:f,hidden:D}}function nr1(){return{priority:5,source:Ef0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:jP}}}async function rr1(A){let Q=await sr1(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 MP(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 or1(A){let Q=await sr1(A),w=await Md0(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",w)}async function Md0(A,Q,w,B){let $=new bK(Q.entityService,w),f=await $.listTopics({visibility:B.extractionVisibility});for(let Y of f)await $.deleteTopic(Y.id);if(A.length===0)return{deleted:f.length,created:0,merged:0,skipped:0,batches:0};let D=await MP(A,Q,w,{minRelevanceScore:B.minRelevanceScore,autoMerge:B.autoMerge,mergeSimilarityThreshold:B.mergeSimilarityThreshold,targetVisibility:B.extractionVisibility});return{deleted:f.length,...D}}async function sr1(A){let Q=ZXw(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 ZXw(A){return A.context.entityService.getEntityTypes().filter((w)=>A.shouldProcessEntityType(w))}var LE=K.object({entityType:K.string(),content:K.string(),metadata:K.record(K.unknown()).optional()}),KXw=LE.extend({minRelevanceScore:K.number().optional()}),UXw=K.object({contentA:LE,contentB:LE,minRelevanceScore:K.number().optional(),threshold:K.number().min(0).max(1).optional()}),Bo=K.object({title:K.string(),content:K.string()}),GXw=K.object({existingTopics:K.array(Bo),incomingTopic:Bo,threshold:K.number().optional()}),zXw=K.object({existingTopics:K.array(Bo).default([]),incomingTopic:Bo.extend({relevanceScore:K.number().min(0).max(1).optional()}),threshold:K.number().optional()}),qXw=K.object({entities:K.array(LE).min(1),minRelevanceScore:K.number().optional()}),FXw=K.object({existingTopics:K.array(Bo).optional(),entities:K.array(LE)}),VXw=K.object({entities:K.array(LE)});function bE(A,Q=""){return{id:`eval${Q}-${Date.now()}`,entityType:A.entityType,content:A.content,contentHash:xw(A.content),visibility:"public",metadata:A.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}}function ar1(A){return{title:A.title,relevanceScore:A.relevanceScore}}function IXw(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function JXw(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:IXw(Q)}]}}async function _P(A){let Q=await A.entityService.listEntities({entityType:qB});await Promise.all(Q.map((w)=>A.entityService.deleteEntity({entityType:qB,id:w.id})))}async function bXw(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise((w)=>setTimeout(w,100))}}function tr1(A){let{context:Q,logger:w,config:B}=A,$=new Ld0(Q,w),f=async(D,Y,X="")=>{let H=bE(D,X);return $.extractFromEntity(H,Y)};Q.eval.registerHandler("extractFromEntity",async(D)=>{await _P(Q);let Y=KXw.parse(D),X=Y.minRelevanceScore??B.minRelevanceScore,H=bE(Y);return(await $.extractFromEntity(H,X)).map((Z)=>JXw(Z,H))}),Q.eval.registerHandler("checkMergeSimilarity",async(D)=>{await _P(Q);let Y=UXw.parse(D),X=Y.minRelevanceScore??B.minRelevanceScore,H=Y.threshold??B.mergeSimilarityThreshold,[W,Z]=await Promise.all([f(Y.contentA,X,"-a"),f(Y.contentB,X,"-b")]),G=new bK(Q.entityService,w),F=[];for(let L of W){let N=await G.createTopic(L);if(N)F.push(N)}let V=(await Promise.all(Z.map(async(L)=>{let N=await G.findMergeCandidate({incoming:L,threshold:H,additionalCandidates:F});if(!N)return null;return{incomingTitle:L.title,candidateTitle:N.title,candidateScore:N.score}}))).filter((L)=>L!==null),b=V.map((L)=>L.candidateTitle);return{topicsA:W.map(ar1),topicsB:Z.map(ar1),matchingTitles:b,mergeCandidates:V,wouldMerge:V.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(D)=>{await _P(Q);let Y=GXw.parse(D),X=Y.threshold??B.mergeSimilarityThreshold,H=new bK(Q.entityService,w),W=[];for(let G of Y.existingTopics){let F=await H.createTopic(G);if(F)W.push(F)}let Z=await H.findMergeCandidate({incoming:{title:Y.incomingTopic.title},threshold:X,additionalCandidates:W});return{found:Z!==null,candidateTitle:Z?.title,candidateScore:Z?.score}}),Q.eval.registerHandler("processTopicWithAutoMerge",async(D)=>{await _P(Q);let Y=zXw.parse(D),X=new bK(Q.entityService,w);for(let G of Y.existingTopics)await X.createTopic({title:G.title,content:G.content});await bXw(Q);let H=bE({entityType:"post",content:Y.incomingTopic.content,metadata:{title:Y.incomingTopic.title}},"-source"),W=await MP([H],Q,w,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:Y.threshold??B.mergeSimilarityThreshold}),Z=await Q.entityService.listEntities({entityType:qB});return{...W,topicCount:Z.length,topics:Z.map(Jd0)}}),Q.eval.registerHandler("rebuildTopics",async(D)=>{await _P(Q);let Y=FXw.parse(D),X=new bK(Q.entityService,w);for(let G of Y.existingTopics??[])await X.createTopic(G);let H=Y.entities.map((G,F)=>bE(G,`-rebuild-${F}`)),W=await Md0(H,Q,w,B),Z=await Q.entityService.listEntities({entityType:qB});return{...W,topicCount:Z.length,topics:Z.map(Jd0)}}),Q.eval.registerHandler("extractSequentially",async(D)=>{await _P(Q);let Y=qXw.parse(D),X=Y.minRelevanceScore??B.minRelevanceScore,H=new bK(Q.entityService,w),W=[];for(let[G,F]of Y.entities.entries()){let V=bE(F,`-sequential-${G}`),b=await $.extractFromEntity(V,X);for(let L of b)await H.createTopic({title:L.title,content:L.content});W.push({extractedTitles:b.map((L)=>L.title)})}let Z=await Q.entityService.listEntities({entityType:qB});return{totalTopics:Z.length,perEntity:W,topics:Z.map(JE)}}),Q.eval.registerHandler("batchExtract",async(D)=>{await _P(Q);let X=VXw.parse(D).entities.map((Z,G)=>bE(Z,`-batch-${G}`)),H=await MP(X,Q,w,{minRelevanceScore:B.minRelevanceScore}),W=await Q.entityService.listEntities({entityType:qB});return{...H,topics:W.map(JE)}})}var LXw=new JK;async function er1({entity:A,config:Q}){let w=IE.parse(A),B=LXw.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 _d0(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:MB["ai.rizom.brain.topic"],validate:!1,buildRecord:er1}}var Ao1={name:"@brains/topics",private:!0,version:"0.2.0-alpha.134",description:"Extract and manage topics from conversations",type:"module",main:"./src/index.ts",types:"./src/index.ts",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest","@types/node":"^20.0.0",typescript:"^5.3.3"}};var jXw=new JK;class Qo1 extends PQ{entityType=qB;schema=IE;adapter=jXw;unregisterAtprotoProjection;sourceBatch=new jd0;constructor(A={}){super(jP,Ao1,A,Nr1)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:Or1,"merge-synthesis":xr1,"topic-list":Rr1,"topic-detail":hr1}}getDataSources(){return[new bd0(this.logger.child("TopicsDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:Fd0,targetType:qB,job:{type:Mr1,handler:dr1({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 qN(A,qB,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:nr1()},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(!cV(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:Ef0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:Pr1,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:jP}})}}]}async onRegister(A){A.insights.register("topic-distribution",yr1()),Er1({context:A,pluginId:this.id}),tr1({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=U5.getInstance().register(_d0())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(Fd0)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===qB)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let w=A.metadata.status;if(w===void 0||w===null)return!0;if(typeof w!=="string")return!1;return this.config.extractableStatuses.includes(w)}async extractAllTopics(A){await rr1({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await or1({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function lf0(A){return new Qo1(A)}c0();Z0();c0();var Pd0=K.enum(["linkedin"]),kd0=K.enum(["generating","draft","queued","published","failed"]),wo1=K.enum(["post","deck"]),Bo1=K.object({id:K.string().min(1).describe("Document entity ID")}),YW=K.object({title:K.string().describe("Short descriptive title (3-6 words) for file naming"),platform:Pd0.describe("Target platform"),status:kd0,coverImageId:K.string().optional().describe("Image entity ID for post image"),documents:K.array(Bo1).optional().describe("Document attachments for publishing"),publishedAt:K.string().datetime().optional(),platformPostId:K.string().optional().describe("ID from platform after publishing"),sourceEntityId:K.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:wo1.optional().describe("Source entity type (post, deck)")}),$o1=YW.extend({platform:Pd0.optional(),status:kd0.optional()}),fo1=YW.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:K.string().describe("URL-friendly identifier: {platform}-{title}"),error:K.string().optional()}),hb=o1.extend({entityType:K.literal("social-post"),metadata:fo1}),pf0=hb.extend({frontmatter:YW,body:K.string()}),if0=pf0.extend({url:K.string().optional(),listUrl:K.string().optional(),listLabel:K.string().optional(),typeLabel:K.string().optional(),coverImageUrl:K.string().optional(),coverImageWidth:K.number().optional(),coverImageHeight:K.number().optional()});c0();Z0();class Od0 extends I2{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:hb,frontmatterSchema:YW,supportsCoverImage:!0})}toMarkdown(A){let Q="",w={};try{w=this.parseFrontMatter(A.content,YW),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,$o1),w=Q.platform??"linkedin",B=Q.status??"draft",$=`${w}-${w1(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,YW)}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-${w1(A.title)}`,platform:"linkedin",status:"generating"}}}}var R7=new Od0;c0();c0();Z0();var MXw=qU.extend({platform:K.enum(["linkedin"]).optional(),status:K.enum(["generating","draft","queued","published","failed"]).optional(),sortByQueue:K.boolean().optional(),nextInQueue:K.boolean().optional()}),_Xw=FU.extend({query:MXw.optional()});function Do1(A){let Q=v2(A.content,YW);return pf0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class df0 extends W${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=_Xw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return Do1(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:W}=await this.fetchDetail(B.id,$);return Q.parse(this.buildDetailResult(W,null))}let f={};if(B.platform)f.platform=B.platform;if(B.status)f.status=B.status;let D=Object.keys(f).length>0,Y=B.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:X,pagination:H}=await this.fetchList(B,$,{...D&&{filter:{metadata:f}},sortFields:Y});return Q.parse(this.buildListResult(X,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?Do1(B):null;return A.parse({post:$})}}Z0();var Yo1=K.object({accessToken:K.string().optional(),refreshToken:K.string().optional(),organizationId:K.string().optional(),apiVersion:K.string().regex(/^\d{6}$/).optional()}),xd0=K.object({linkedin:Yo1.optional(),publishInterval:K.number().default(3600000),enabled:K.boolean().default(!0),defaultPrompt:K.string().default("Create an engaging social media post that drives engagement"),maxRetries:K.number().default(3),autoGenerateOnBlogPublish:K.boolean().default(!1)});c0();Z0();CB();hd0();import{jsxDEV as c5,Fragment as OXw}from"preact/jsx-dev-runtime";function PXw(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function kXw(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var rf0=({posts:A,pageTitle:Q,pagination:w,baseUrl:B="/social-posts"})=>{let $=Q??"Social Posts",f=w?.totalItems??A.length,D=`Browse all ${f} social ${f===1?"post":"posts"}`;return c5(OXw,{children:[c5(NQ,{title:$,description:D},void 0,!1,void 0,this),c5("div",{className:"social-post-list bg-theme",children:c5("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[c5("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:$},void 0,!1,void 0,this),A.length===0?c5("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):c5("ul",{className:"space-y-6",children:A.map((Y)=>c5("li",{children:c5(uw,{href:Y.url,variant:"horizontal",children:c5("div",{className:"flex flex-col sm:flex-row gap-4",children:[Y.coverImageUrl&&c5("img",{src:Y.coverImageUrl,alt:Y.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),c5("div",{className:"flex-1 min-w-0",children:[c5("div",{className:"flex items-start justify-between gap-4 mb-2",children:[c5("h2",{className:"text-lg font-semibold text-heading",children:Y.frontmatter.title},void 0,!1,void 0,this),c5("time",{className:"text-sm text-theme-muted shrink-0",children:kXw(Y.frontmatter.publishedAt??Y.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c5("div",{className:"flex items-center gap-2 mb-3",children:[c5(CD,{status:Y.frontmatter.status},void 0,!1,void 0,this),c5("span",{className:"text-xs text-theme-muted uppercase",children:Y.frontmatter.platform},void 0,!1,void 0,this),c5("span",{className:"text-xs text-theme-muted font-mono",children:Y.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c5("p",{className:"text-theme leading-relaxed",children:PXw(Y.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)},Y.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&c5(d3,{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 l5,Fragment as xXw}from"preact/jsx-dev-runtime";function Xo1(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var of0=({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 l5(xXw,{children:[l5(NQ,{title:Q,description:w},void 0,!1,void 0,this),l5("section",{className:"social-post-detail",children:l5("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:l5("div",{className:"max-w-3xl mx-auto",children:[l5(_G,{items:B},void 0,!1,void 0,this),l5("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),l5("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[l5(CD,{status:A.frontmatter.status},void 0,!1,void 0,this),l5("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),l5("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&&l5(p3,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),l5(uw,{className:"p-8 mb-8",children:l5("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),l5("div",{className:"space-y-4 text-sm text-theme-muted",children:[l5("div",{children:[l5("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",Xo1(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&l5("div",{children:[l5("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",Xo1(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&l5("div",{children:l5("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 $o(A){return`social-media:${A}`}var RXw=K.union([K.boolean(),K.object({generate:K.boolean().optional(),prompt:K.string().optional()})]),vd0=K.object({prompt:K.string().optional(),platform:K.enum(["linkedin"]).optional(),sourceEntityType:K.enum(["post","deck"]).optional(),sourceEntityId:K.string().optional(),title:K.string().optional().describe("Required when content is provided directly"),content:K.string().optional(),addToQueue:K.boolean().optional(),generateImage:K.boolean().optional().describe("Auto-generate cover image for post"),coverImage:RXw.optional().describe("Generic cover image generation request")}),hXw=GY.extend({slug:K.string().optional()});class PP extends Q4{constructor(A,Q){super(A,Q,{schema:vd0,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let w=A.platform??"linkedin",B=A.addToQueue??!1,{prompt:$,sourceEntityType:f,sourceEntityId:D}=A,{content:Y,title:X}=A;if(Y&&X)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(Y&&!X){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let L=await this.context.ai.generate({prompt:Y,templateName:$o(w)});X=L.title,Y=L.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(D&&f){await this.reportProgress(Q,{progress:10,message:`Fetching source ${f}`});let L=await this.context.entityService.getEntity({entityType:f,id:D});if(!L)this.failEarly(`Source entity not found: ${f}/${D}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let _=K.object({slug:K.string()}).safeParse(L.metadata),j=_.success?_.data.slug:D,g=await this.context.ai.generate({prompt:`Create an engaging ${w} post to promote this ${f}:
6617
6617
 
6618
6618
  Source: ${f}/${j}
6619
6619
 
6620
6620
  ${L.content}`,templateName:$o(w)});X=g.title,Y=g.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 L=await this.context.ai.generate({prompt:$,templateName:$o(w)});X=L.title,Y=L.content,await this.reportProgress(Q,{progress:50,message:"Social post generated"})}else this.failEarly("No content source provided (prompt, sourceEntityId, or content)");if(!Y||!X)this.failEarly("Content or title was not generated");let W={title:X,platform:w,status:B?"queued":"draft",...D&&{sourceEntityId:D},...f&&{sourceEntityType:f}},Z=R7.createPostContent(W,Y),F=R7.fromMarkdown(Z).metadata;if(!F)this.failEarly("Failed to parse social post metadata");let V=await Uq({entityType:"social-post",title:X,deriveId:(L)=>`${w}-${w1(L)}`,regeneratePrompt:"Generate a different social media post title on the same topic.",context:this.context}),b=Z;if(V!==X){F.title=V,F.slug=`${w}-${w1(V)}`;let L={...W,title:V};b=R7.createPostContent(L,Y)}return{id:F.slug,content:b,metadata:F,title:V,resultExtras:{slug:F.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}}}function fo(A){if(A.length<=200)return A;return`${A.slice(0,200)}\u2026 (truncated, ${A.length} bytes)`}function vXw(A){let Q={status:"READY",media:A.urn};if(A.title)Q.title={text:A.title};return Q}function CXw(A){if(!Cd0(A))return null;let Q=sf0(A,"value");if(!Q)return null;let w=sf0(Q,"uploadMechanism");if(!w)return null;let B=sf0(w,"com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest");if(!B)return null;let $=B.uploadUrl,f=Q.asset;if(typeof $!=="string"||typeof f!=="string")return null;return{uploadUrl:$,assetUrn:f}}function yXw(A){if(!Cd0(A))return null;let Q=sf0(A,"value");if(!Q)return null;let{uploadUrl:w,document:B}=Q;if(typeof w!=="string"||typeof B!=="string")return null;return{uploadUrl:w,documentUrn:B}}function sf0(A,Q){let w=A[Q];return Cd0(w)?w:null}function Cd0(A){return typeof A==="object"&&A!==null}var EXw="202604";class yd0{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 D=null;if(f){let Z=await this.uploadDocument($,f);return this.publishDocumentPost($,A,Z,f.filename)}else if(w){let Z=await this.uploadImage($,w);if(Z)D={category:"IMAGE",urn:Z}}let Y={shareCommentary:{text:A},shareMediaCategory:D?.category??"NONE",...D&&{media:[vXw(D)]}},X=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":Y},visibility:{"com.linkedin.ugc.MemberNetworkVisibility":"PUBLIC"}})});if(!X.ok){let Z=fo(await X.text());throw this.logger.error("LinkedIn API error",{status:X.status,error:Z}),Error(`LinkedIn API error: ${X.status} - ${Z}`)}let H=X.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn post created",{postId:H,mediaCategory:D?.category??"NONE"});let W={id:H};if(H)W.url=`https://www.linkedin.com/feed/update/${H}`;return W}getRestHeaders(){return{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","Linkedin-Version":this.config.apiVersion??EXw,"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 Y=fo(await w.text());return this.logger.warn("LinkedIn image upload registration failed",{status:w.status,error:Y}),null}let B=CXw(await w.json());if(!B)return this.logger.warn("LinkedIn image upload registration was malformed"),null;let{uploadUrl:$,assetUrn:f}=B,D=await this.fetch($,{method:"PUT",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":Q.mimeType},body:new Uint8Array(Q.data)});if(!D.ok)return this.logger.warn("LinkedIn image binary upload failed",{status:D.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=fo(await w.text());throw Error(`LinkedIn document upload initialization failed: ${w.status} - ${f}`)}let B=yXw(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 Y=fo(await $.text());throw this.logger.error("LinkedIn document post API error",{status:$.status,error:Y}),Error(`LinkedIn document post API error: ${$.status} - ${Y}`)}let f=$.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn document post created",{postId:f,documentUrn:w});let D={id:f};if(f)D.url=`https://www.linkedin.com/feed/update/${f}`;return D}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=await w.json();return this.cachedUserId=`urn:li:person:${B.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=fo(await A.text());throw Error(`Failed to get LinkedIn user ID: ${A.status} - ${w}`)}let Q=await A.json();return this.cachedUserId=`urn:li:person:${Q.id}`,this.cachedUserId}}function Ed0(A,Q,w={}){return new yd0(A,Q,w)}c0();Z0();JB();hd0();var gXw=K.object({posts:K.array(if0),totalCount:K.number().optional(),pagination:e7.nullable(),baseUrl:K.string().optional()}),TXw=K.object({post:if0});function Ho1(){return{linkedin:nf0,"social-post-list":R1({name:"social-post-list",description:"Social post list page template",schema:gXw,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:rf0}}),"social-post-detail":R1({name:"social-post-detail",description:"Individual social post template",schema:TXw,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:of0}})}}Z0();var SXw=K.object({prompt:K.string().optional(),content:K.string().optional(),platform:K.enum(["linkedin"]).default("linkedin")}),mXw=K.object({prompt:K.string().optional(),content:K.string().optional(),title:K.string().optional(),platform:K.enum(["linkedin"]).optional()});function Wo1(A){A.eval.registerHandler("generation",async(Q)=>{let w=SXw.parse(Q),B=w.content?`Create an engaging LinkedIn post to share this content:
6621
6621
 
6622
- ${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=mXw.parse(Q),B=[],$=D7.from(async(H)=>{let W={progress:H.progress};if(H.message!==void 0)W.message=H.message;B.push(W)});if(!$)throw Error("Failed to create progress reporter");let D=await new PP(A.logger,A).process(w,`eval-${Date.now()}`,$),Y=!1,X;if(D.success&&D.entityId){let H=await A.entityService.getEntity({entityType:"social-post",id:D.entityId});Y=!!H,X=H?.content.slice(0,300)}return{...D,entityExists:Y,entityPreview:X,progressSteps:B}})}Z0();c0();class Do{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,D=this.providers.get(f);if(!D){await this.reportFailure(Q,w,`No provider configured for platform: ${f}`);return}let Y=v2($.content,YW),X;if(Y.metadata.coverImageId)X=await this.fetchImageData(Y.metadata.coverImageId);let H=Y.metadata.documents??[],W=await this.fetchDocumentData(H);try{if(H.length>0&&W.length===0)throw Error(`Refusing to publish: ${H.length} document(s) referenced but none could be fetched`);let Z=H.length===0?await this.resolveSourceAttachment(Y.metadata):[],G=W.length>0?W:Z,F=G.length?await D.publish(Y.content,$.metadata,X,G):await D.publish(Y.content,$.metadata,X),V=new Date().toISOString(),b=F.id||void 0,L={...Y.metadata,status:"published",publishedAt:V,...b&&{platformPostId:b}},N=R7.createPostContent(L,Y.content);await this.entityService.updateEntity({entity:{...$,content:N,metadata:{...$.metadata,status:"published",publishedAt:V,platformPostId:b}}}),await this.reportSuccess(Q,w,F.id),this.logger.info(`Post published successfully: ${w}`,{platform:f,platformPostId:b})}catch(Z){let G=Z instanceof Error?Z.message:String(Z),F={...Y.metadata,status:"failed"},V=R7.createPostContent(F,Y.content);await this.entityService.updateEntity({entity:{...$,content:V,metadata:{...$.metadata,status:"failed"}}}),await this.reportFailure(Q,w,G),this.logger.error(`Post publish failed: ${w}`,{platform:f,error:G})}}catch(B){let $=vA(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 Zo1(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 Ko1(A,Q,w){let B=new Do({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")}Z0();function Uo1(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(Y){let X=vA(Y);return Q.error(`Failed to trigger auto-generate for ${$}:`,{error:X}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function Go1(A,Q){A.messaging.subscribe("social:auto-generate",async(w)=>{let{sourceEntityType:B,sourceEntityId:$,platform:f}=w.payload;try{let D=await A.jobs.enqueue({type:`${R7.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:D}),{success:!0,jobId:D}}catch(D){let Y=vA(D);return Q.error(`Failed to enqueue social post generation for ${$}:`,{error:Y}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function zo1(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 Y of $)if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:Y.id}},limit:1}})).length===0){f=Y;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 D=await A.jobs.enqueue({type:`${R7.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:D,sourcePostId:f.id}),{success:!0}}catch($){let f=vA($);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 qo1({entity:A,config:Q}){let w=hb.parse(A),B=R7.parsePostFrontmatter(w),$=R7.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 gd0(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:MB["ai.rizom.brain.socialPost"],validate:!1,buildRecord:qo1}}var Fo1={name:"@brains/social-media",private:!0,version:"0.2.0-alpha.133",description:"Multi-provider social media posting with queue-based publishing",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class Td0 extends PQ{entityType=R7.entityType;schema=hb;adapter=R7;providers=new Map;unregisterAtprotoProjection;constructor(A){super("social-media",Fo1,A,xd0)}createGenerationHandler(A){return new PP(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return Ho1()}getDataSources(){return[new df0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),Zo1(A,this.providers,this.logger),Ko1(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)Uo1(A,this.logger),Go1(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");zo1(A,this.logger),Wo1(A),this.unregisterAtprotoProjection=U5.getInstance().register(gd0()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=Ed0(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function Yo(A){return new Td0(A)}Z0();var cXw=K.enum(["draft","queued","published","failed"]),Vo1=K.object({status:cXw.default("draft"),queueOrder:K.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:K.string().datetime().optional()});class Sd0{name="internal";async publish(A,Q){return{id:"internal"}}}var Xo={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},Rf={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"},vb={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"},Io1={REGISTER:"publish-assets:register"};Z0();var lXw=K.enum(["provider"]),Jo1=K.object({executionMode:lXw.optional(),publishResultIdField:K.string().min(1).optional(),publishTimestampField:K.string().min(1).optional(),enabled:K.boolean().optional()}).strict();var pXw=K.object({skipIfDraftExists:K.boolean().optional(),minSourceEntities:K.number().optional(),maxUnpublishedDrafts:K.number().optional(),sourceEntityType:K.string().optional()}),bo1=K.object({entitySchedules:K.record(K.string(),K.string()).optional(),generationSchedules:K.record(K.string(),K.string()).optional(),generationConditions:K.record(K.string(),pXw).optional()});class sG{static instance=null;queues=new Map;static getInstance(){return sG.instance??=new sG,sG.instance}static resetInstance(){sG.instance=null}static createFresh(){return new sG}constructor(){}async add(A,Q,w=Xo){let B=this.getOrCreateQueue(A),$=B.find((Y)=>Y.entityId===Q);if($)return{position:$.position};let f=B.length+1,D={entityId:Q,entityType:A,position:f,queuedAt:new Date().toISOString(),authContext:{...w}};return B.push(D),{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((Y)=>Y.entityId===Q);if($===-1)return;let[f]=B.splice($,1);if(!f)return;let D=Math.max(0,Math.min(w-1,B.length));B.splice(D,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 aG{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new Sd0;static getInstance(){return aG.instance??=new aG,aG.instance}static resetInstance(){aG.instance=null}static createFresh(){return new aG}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())}}Z0();Z0();async function Lo1(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await iXw(A,Q)}async function iXw(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:Rf.FAILED,payload:B,sender:"publish-service"});Q.onFailed?.(B);return}md0(A.entityType,A.entityId,w.result,Q)}catch(w){let B=vA(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 md0(A,Q,w,B){if(B.retryTracker.clearRetries(Q),B.messageBus)B.messageBus.send({type:Rf.COMPLETED,payload:{entityType:A,entityId:Q,result:w},sender:"publish-service"});B.onPublish?.({entityType:A,entityId:Q,result:w})}function No1(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:Rf.FAILED,payload:f,sender:"publish-service"});B.onFailed?.(f)}async function jo1(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:vb.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:vb.EXECUTE,payload:B,sender:"content-pipeline"});Q.onGenerate?.(B)}function Mo1(A,Q,w){if(w)w.send({type:vb.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function _o1(A,Q,w){if(w)w.send({type:vb.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var dXw=1000;class ud0{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(dXw,()=>this.processUnscheduledTypes())}stop(){if(nXw(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 Lo1(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}function nXw(A){for(let Q of A.values())Q.stop();A.clear()}class cd0{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(){rXw(this.generationJobs)}async handleTriggerGeneration(A){if(!this.deps.isRunning())return;try{await jo1(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 rXw(A){for(let Q of A.values())Q.stop();A.clear()}class LK{static instance=null;config;publishRunner;generationRunner;running=!1;static getInstance(A){return LK.instance??=new LK(A),LK.instance}static resetInstance(){if(LK.instance)LK.instance.stop();LK.instance=null}static createFresh(A){return new LK(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new ud0({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new cd0({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){md0(A,Q,w,this.publishDeps)}failPublish(A,Q,w){No1(A,Q,w,this.publishDeps)}completeGeneration(A,Q){Mo1(A,Q,this.config.messageBus)}failGeneration(A,Q){_o1(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}" - ${vA(B)}`)}}}class tG{static instance=null;retries=new Map;static getInstance(){return tG.instance??=new tG,tG.instance}static resetInstance(){tG.instance=null}static createFresh(){return new tG}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 P4(A,Q,w,B,$,f,D,Y){return P4.fromTZ(P4.tp(A,Q,w,B,$,f,D),Y)}P4.fromTZISO=(A,Q,w)=>P4.fromTZ(oXw(A,Q),w);P4.fromTZ=function(A,Q){let w=new Date(Date.UTC(A.y,A.m-1,A.d,A.h,A.i,A.s)),B=ld0(A.tz,w),$=new Date(w.getTime()-B),f=ld0(A.tz,$);if(f-B===0)return $;{let D=new Date(w.getTime()-f),Y=ld0(A.tz,D);if(Y-f===0)return D;if(!Q&&Y-f>0)return D;if(Q)throw Error("Invalid date passed to fromTZ()");return $}};P4.toTZ=function(A,Q){let w=A.toLocaleString("en-US",{timeZone:Q}).replace(/[\u202f]/," "),B=new Date(w);return{y:B.getFullYear(),m:B.getMonth()+1,d:B.getDate(),h:B.getHours(),i:B.getMinutes(),s:B.getSeconds(),tz:Q}};P4.tp=(A,Q,w,B,$,f,D)=>({y:A,m:Q,d:w,h:B,i:$,s:f,tz:D});function ld0(A,Q=new Date){let w=Q.toLocaleString("en-US",{timeZone:A,timeZoneName:"shortOffset"}).split(" ").slice(-1)[0],B=Q.toLocaleString("en-US").replace(/[\u202f]/," ");return Date.parse(`${B} GMT`)-Date.parse(`${B} ${w}`)}function oXw(A,Q){let w=new Date(Date.parse(A));if(isNaN(w))throw Error("minitz: Invalid ISO8601 passed to parser.");let B=A.substring(9);return A.includes("Z")||B.includes("-")||B.includes("+")?P4.tp(w.getUTCFullYear(),w.getUTCMonth()+1,w.getUTCDate(),w.getUTCHours(),w.getUTCMinutes(),w.getUTCSeconds(),"Etc/UTC"):P4.tp(w.getFullYear(),w.getMonth()+1,w.getDate(),w.getHours(),w.getMinutes(),w.getSeconds(),Q)}P4.minitz=P4;var pd0=32,Wo=31|pd0,xo1=[1,2,4,8,16],Po1=class{pattern;timezone;second;minute;hour;day;month;dayOfWeek;lastDayOfMonth;starDOM;starDOW;constructor(A,Q){this.pattern=A,this.timezone=Q,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.lastDayOfMonth=!1,this.starDOM=!1,this.starDOW=!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.replace(/\s+/g," ").split(" ");if(A.length<5||A.length>6)throw TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exactly five or six space separated parts are required.");if(A.length===5&&A.unshift("0"),A[3].indexOf("L")>=0&&(A[3]=A[3].replace("L",""),this.lastDayOfMonth=!0),A[3]=="*"&&(this.starDOM=!0),A[4].length>=3&&(A[4]=this.replaceAlphaMonths(A[4])),A[5].length>=3&&(A[5]=this.replaceAlphaDays(A[5])),A[5]=="*"&&(this.starDOW=!0),this.pattern.indexOf("?")>=0){let Q=new XW(new Date,this.timezone).getDate(!0);A[0]=A[0].replace("?",Q.getSeconds().toString()),A[1]=A[1].replace("?",Q.getMinutes().toString()),A[2]=A[2].replace("?",Q.getHours().toString()),this.starDOM||(A[3]=A[3].replace("?",Q.getDate().toString())),A[4]=A[4].replace("?",(Q.getMonth()+1).toString()),this.starDOW||(A[5]=A[5].replace("?",Q.getDay().toString()))}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),this.partToArray("dayOfWeek",A[5],0,Wo),this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(A,Q,w,B){let $=this[A],f=A==="day"&&this.lastDayOfMonth;if(Q===""&&!f)throw TypeError("CronPattern: configuration entry "+A+" ("+Q+") is empty, check for trailing spaces.");if(Q==="*")return $.fill(B);let D=Q.split(",");if(D.length>1)for(let Y=0;Y<D.length;Y++)this.partToArray(A,D[Y],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===5?/[^/*0-9,\-#L]+/:/[^/*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=parseInt($[0],10)+w;if(isNaN(f))throw TypeError("CronPattern: "+Q+" is not a number: '"+A+"'");this.setPart(Q,f,$[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"){if(Q<0||Q>=31)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="month"&&(Q<0||Q>=12))throw RangeError("CronPattern: Invalid value for "+A+": "+Q);this[A][Q]=w}handleRangeWithStepping(A,Q,w,B){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[,D,Y,X]=f,H=parseInt(D,10)+w,W=parseInt(Y,10)+w,Z=parseInt(X,10);if(isNaN(H))throw TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(W))throw TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(isNaN(Z))throw TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(Z===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(Z>this[Q].length)throw TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[Q].length+")");if(H>W)throw TypeError("CronPattern: From value is larger than to value: '"+A+"'");for(let G=H;G<=W;G+=Z)this.setPart(Q,G,$[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]}return[w,B]}handleRange(A,Q,w,B){let $=this.extractNth(A,Q),f=$[0].split("-");if(f.length!==2)throw TypeError("CronPattern: Syntax error, illegal range: '"+A+"'");let D=parseInt(f[0],10)+w,Y=parseInt(f[1],10)+w;if(isNaN(D))throw TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(Y))throw TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(D>Y)throw TypeError("CronPattern: From value is larger than to value: '"+A+"'");for(let X=D;X<=Y;X++)this.setPart(Q,X,$[1]||B)}handleStepping(A,Q,w,B){let $=this.extractNth(A,Q),f=$[0].split("/");if(f.length!==2)throw TypeError("CronPattern: Syntax error, illegal stepping: '"+A+"'");f[0]===""&&(f[0]="*");let D=0;f[0]!=="*"&&(D=parseInt(f[0],10)+w);let Y=parseInt(f[1],10);if(isNaN(Y))throw TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(Y===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(Y>this[Q].length)throw TypeError("CronPattern: Syntax error, max steps for part is ("+this[Q].length+")");for(let X=D;X<this[Q].length;X+=Y)this.setPart(Q,X,$[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")}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();return Q==="@yearly"||Q==="@annually"?"0 0 1 1 *":Q==="@monthly"?"0 0 1 * *":Q==="@weekly"?"0 0 * * 0":Q==="@daily"?"0 0 * * *":Q==="@hourly"?"0 * * * *":A}setNthWeekdayOfMonth(A,Q){if(typeof Q!="number"&&Q==="L")this.dayOfWeek[A]=this.dayOfWeek[A]|pd0;else if(Q===Wo)this.dayOfWeek[A]=Wo;else if(Q<6&&Q>0)this.dayOfWeek[A]=this.dayOfWeek[A]|xo1[Q-1];else throw TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${Q}, Type: ${typeof Q}`)}},ko1=[31,28,31,30,31,30,31,31,30,31,30,31],qF=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],XW=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===void 0)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")}isNthWeekdayOfMonth(Q,w,B,$){let f=new Date(Date.UTC(Q,w,B)).getUTCDay(),D=0;for(let Y=1;Y<=B;Y++)new Date(Date.UTC(Q,w,Y)).getUTCDay()===f&&D++;if($&Wo&&xo1[D-1]&$)return!0;if($&pd0){let Y=new Date(Date.UTC(Q,w+1,0)).getUTCDate();for(let X=B+1;X<=Y;X++)if(new Date(Date.UTC(Q,w,X)).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{let w=P4.toTZ(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}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.day>ko1[this.month]||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=P4.fromTZISO(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(P4.fromTZISO(Q,this.tz))}findNext(Q,w,B,$){let f=this[w],D;B.lastDayOfMonth&&(this.month!==1?D=ko1[this.month]:D=new Date(Date.UTC(this.year,this.month+1,0,0,0,0,0)).getUTCDate());let Y=!B.starDOW&&w=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0;for(let X=this[w]+$;X<B[w].length;X++){let H=B[w][X];if(w==="day"&&B.lastDayOfMonth&&X-$==D&&(H=1),w==="day"&&!B.starDOW){let W=B.dayOfWeek[(Y+(X-$-1))%7];if(W&&W&Wo)W=this.isNthWeekdayOfMonth(this.year,this.month,X-$,W)?1:0;else if(W)throw Error(`CronDate: Invalid value for dayOfWeek encountered. ${W}`);Q.legacyMode&&!B.starDOM?H=H||W:H=H&&W}if(H)return this[w]=X-$,f!==this[w]?2:1}return 3}recurse(Q,w,B){let $=this.findNext(w,qF[B][0],Q,qF[B][2]);if($>1){let f=B+1;for(;f<qF.length;)this[qF[f][0]]=-qF[f][2],f++;if($===3)return this[qF[B][1]]++,this[qF[B][0]]=-qF[B][2],this.apply(),this.recurse(Q,w,0);if(this.apply())return this.recurse(Q,w,B-1)}return B+=1,B>=qF.length?this:this.year>=3000?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)}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)):P4.fromTZ(P4.tp(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}};function sXw(A){if(A===void 0&&(A={}),delete A.name,A.legacyMode=A.legacyMode===void 0?!0:A.legacyMode,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.unref=A.unref===void 0?!1:A.unref,A.startAt&&(A.startAt=new XW(A.startAt,A.timezone)),A.stopAt&&(A.stopAt=new XW(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).");return A}function Ho(A){return Object.prototype.toString.call(A)==="[object Function]"||typeof A=="function"||A instanceof Function}function aXw(A){return Ho(A)}function tXw(A){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(A):A&&typeof A.unref<"u"&&A.unref()}var Oo1=30000,af0=[],id0=class{name;options;_states;fn;constructor(A,Q,w){let B,$;if(Ho(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(Ho(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=sXw(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 Po1("* * * * *")},A&&(A instanceof Date||typeof A=="string"&&A.indexOf(":")>0)?this._states.once=new XW(A,this.options.timezone||this.options.utcOffset):this._states.pattern=new Po1(A,this.options.timezone),this.name){if(af0.find((f)=>f.name===this.name))throw Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");af0.push(this)}return $!==void 0&&aXw($)&&(this.fn=$,this.schedule()),this}nextRun(A){let Q=this._next(A);return Q?Q.getDate(!1):null}nextRuns(A,Q){this._states.maxRuns!==void 0&&A>this._states.maxRuns&&(A=this._states.maxRuns);let w=[],B=Q||this._states.currentRun||void 0;for(;A--&&(B=this.nextRun(B));)w.push(B);return w}getPattern(){return this._states.pattern?this._states.pattern.pattern:void 0}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 XW||A instanceof Date?Q.getTime()-A.getTime():Q.getTime()-new XW(A).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let A=af0.indexOf(this);A>=0&&af0.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>Oo1&&(Q=Oo1),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(w),Q),this._states.currentTimeout&&this.options.unref&&tXw(this._states.currentTimeout),this)}async _trigger(A){if(this._states.blocking=!0,this._states.currentRun=new XW(void 0,this.options.timezone||this.options.utcOffset),this.options.catch)try{this.fn!==void 0&&await this.fn(this,this.options.context)}catch(Q){Ho(this.options.catch)&&this.options.catch(Q,this)}else this.fn!==void 0&&await this.fn(this,this.options.context);this._states.previousRun=new XW(A,this.options.timezone||this.options.utcOffset),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&&Ho(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 XW(A,this.options.timezone||this.options.utcOffset),this.options.startAt&&A&&A.getTime()<this.options.startAt.getTime()&&(A=this.options.startAt);let B=this._states.once||new XW(A,this.options.timezone||this.options.utcOffset);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}_calculatePreviousRun(A,Q){let w=new XW(void 0,this.options.timezone||this.options.utcOffset),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 XW(B,this.options.timezone||this.options.utcOffset).increment(this._states.pattern,this.options,!0),$=B.getTime()+this.options.interval*1000;Q=!0}return B===null&&(B=void 0),[B,Q]}};class tf0{scheduleCron(A,Q){let w=new id0(A,()=>{Q()});return{stop:()=>w.stop()}}scheduleInterval(A,Q){let w=setInterval(()=>{Q()},A);return{stop:()=>clearInterval(w)}}validateCron(A){new id0(A).stop()}}Z0();var Ro1=K.union([K.string().min(1),K.object({location:K.enum(["metadata","frontmatter"]),field:K.string().min(1)})]),ef0=K.object({entityType:K.string().min(1),attachmentType:K.string().min(1),mediaEntityType:K.enum(["image","document"]),targetEntityField:Ro1.optional(),requiredWhen:K.object({status:K.string().min(1).optional(),visibility:K.string().min(1).optional()}).optional(),autoGenerate:K.boolean().optional(),requiredForPublish:K.boolean().optional(),jobType:K.string().min(1).optional()});function dd0(A){return`${A.entityType}:${A.attachmentType}`}class eG{static instance=null;definitions=new Map;static getInstance(){return eG.instance??=new eG,eG.instance}static resetInstance(){eG.instance=null}static createFresh(){return new eG}constructor(){}register(A){let Q=ef0.parse(A),w=dd0(Q);return this.definitions.set(w,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(dd0({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(dd0({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}Z0();class AD0{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 nd0(A.metadata[Q]);if(Q.location==="metadata")return nd0(A.metadata[Q.field]);let{frontmatter:w}=lw(A.content);return nd0(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 w1(`${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 nd0(A){return typeof A==="string"?A.length>0:A!==void 0}c0();Z0();var eXw=K.object({id:K.string().min(1)});async function vo1(A,Q){let{bodyContent:w,coverImageId:B,documents:$,sourceEntityType:f,sourceEntityId:D}=AHw(Q.content),Y=B?await BHw(A,B):void 0,X;if($&&$.length>0){let W=await $Hw(A,$);if(W.length>0)X=W}X??=await wHw(A,f,D);let H={bodyContent:w};if(Y)H.imageData=Y;if(X&&X.length>0)H.documentData=X;return H}function AHw(A){try{let Q=v2(A,K.record(K.unknown())),w=Q.metadata.coverImageId,B=typeof w==="string"?w:void 0,$=QHw(Q.metadata.documents),f=ho1(Q.metadata.sourceEntityType),D=ho1(Q.metadata.sourceEntityId);return{bodyContent:Q.content,...B&&{coverImageId:B},...$.length>0&&{documents:$},...f&&{sourceEntityType:f},...D&&{sourceEntityId:D}}}catch{return{bodyContent:A}}}function QHw(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let w=eXw.safeParse(Q);return w.success?[w.data]:[]})}function ho1(A){return typeof A==="string"&&A.length>0?A:void 0}async function wHw(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 BHw(A,Q){let w=await A.entityService.getEntity({entityType:"image",id:Q});if(!w?.content)return;let B=Co1(w.content);if(!B?.mimeType.startsWith("image/"))return;return{data:B.data,mimeType:B.mimeType}}async function $Hw(A,Q){return(await Promise.all(Q.map((B)=>fHw(A,B)))).filter((B)=>B!==void 0)}async function fHw(A,Q){let w=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!w?.content)return;let B=Co1(w.content);if(B?.mimeType!=="application/pdf")return;return{type:"document",data:B.data,mimeType:"application/pdf",filename:DHw(w,Q.id)}}function Co1(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function DHw(A,Q){let w=A.metadata.filename;return typeof w==="string"&&w.length>0?w:`${Q}.pdf`}Z0();var YHw=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function rd0(A,Q,w,B={}){let $=B.publishedAt??new Date().toISOString(),f=B.publishTimestampField??"publishedAt",D={...Q.metadata,status:"published",[f]:$,platformId:w.id,...XHw(w.id,B.publishResultIdField)},Y={...Q,content:yo1(Q.content,$,w.id,B.publishResultIdField,f),metadata:D};return await A.entityService.updateEntity({entity:Y}),Y}function yo1(A,Q,w,B,$="publishedAt"){if(!YHw.test(A))return A;let f=o4(o4(A,"status","published"),$,Q);if(!w||!B)return f;return o4(f,B,w)}function XHw(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class NE{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:D,documentData:Y}=await vo1(this.deps.context,w),X=await $.publish(f,w.metadata,D,Y),H=this.deps.providerRegistry.getPublishResultIdField(B),W=this.deps.providerRegistry.getPublishTimestampField(B),Z=await rd0(this.deps.context,w,X,{...H?{publishResultIdField:H}:{},...W?{publishTimestampField:W}:{}});return await this.runPublishAssetPreflight(Z),{entity:Z,result:X}}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}}c0();Z0();var od0=K.object({action:K.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:K.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:K.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:K.number().optional().describe("New position for reorder action (1-based)")}),sd0=K.object({position:K.number(),entityType:K.string(),entityId:K.string(),queuedAt:K.string()}),HHw=K.object({success:K.literal(!0),message:K.string().optional(),data:K.object({queue:K.array(sd0).optional(),entityType:K.string().optional(),entityId:K.string().optional(),position:K.number().optional()}).optional()}),WHw=K.object({success:K.literal(!1),error:K.string(),code:K.string().optional()}),ad0=K.union([HHw,WHw]);function QD0(A,Q,w){return{...Sw(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",od0,async($,f)=>{let{action:D,entityType:Y,entityId:X,position:H}=$;switch(D){case"list":return ZHw(w,Y);case"add":return KHw(A,w,Y,X,f);case"remove":return UHw(A,w,Y,X,f);case"reorder":return GHw(A,w,Y,X,H,f);default:return{success:!1,error:`Unknown action: ${D}`}}},{sideEffects:"writes"}),outputSchema:ad0}}async function ZHw(A,Q){let w=[];if(Q)w=await A.list(Q);else{let $=A.getRegisteredTypes();for(let f of $){let D=await A.list(f);w.push(...D)}w.sort((f,D)=>new Date(f.queuedAt).getTime()-new Date(D.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 KHw(A,Q,w,B,$){let f=td0("add",w,B);if(!f.success)return f.error;A.permissions.assertEntityActionAllowed(f.entityType,"publish",$??{});let D=await Q.add(f.entityType,f.entityId,{...$,authorization:"user"});return{success:!0,data:{entityType:f.entityType,entityId:f.entityId,position:D.position},message:`Added to queue at position ${D.position}`}}async function UHw(A,Q,w,B,$){let f=td0("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 GHw(A,Q,w,B,$,f){let D=td0("reorder",w,B);if(!D.success)return D.error;let Y=zHw($);if(!Y.success)return Y.error;return A.permissions.assertEntityActionAllowed(D.entityType,"update",f??{}),await Q.reorder(D.entityType,D.entityId,Y.position),{success:!0,data:{entityType:D.entityType,entityId:D.entityId,position:Y.position},message:`Moved to position ${Y.position}`}}function td0(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 zHw(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}}Z0();import{createHash as qHw}from"crypto";var wD0=K.object({entityType:K.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:K.string().optional().describe("Entity ID to publish"),slug:K.string().optional().describe("Entity slug to publish"),confirmed:K.boolean().optional(),confirmationToken:K.string().optional(),contentHash:K.string().optional(),expiresAt:K.string().datetime().optional()}),FHw=K.object({success:K.literal(!0),message:K.string().optional(),data:K.object({entityType:K.string().optional(),entityId:K.string().optional(),platformId:K.string().optional(),url:K.string().optional()}).optional()}),VHw=K.object({success:K.literal(!1),error:K.string(),code:K.string().optional()}),IHw=K.object({success:K.literal(!1).optional(),error:K.string().optional(),needsConfirmation:K.literal(!0),toolName:K.string(),summary:K.string(),preview:K.string().optional(),args:K.unknown()}),ed0=K.union([FHw,VHw,IHw]),JHw=900000;function BD0(A,Q,w,B){let $=B??new NE({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.)",inputSchema:wD0.shape,outputSchema:ed0,visibility:"anchor",sideEffects:"external",handler:async(D,Y)=>{let X=wD0.safeParse(D);if(!X.success)return{success:!1,error:`Invalid input: ${X.error.errors.map((b)=>`${b.path.join(".")}: ${b.message}`).join(", ")}`};let H=X.data,{entityType:W,id:Z,slug:G}=H;try{A.permissions.assertEntityActionAllowed(W,"publish",Y)}catch(b){return{success:!1,error:b instanceof Error?b.message:String(b)}}let F=await $.resolveCandidate({entityType:W,id:Z,slug:G});if("error"in F)return{success:!1,error:F.error};let{entity:V}=F;if(H.confirmed){let b=LHw(f,H,V);if(b!==null)return b;let L;try{L=await $.publish({entityType:W,id:V.id})}catch(j){return{success:!1,error:j instanceof Error?j.message:String(j)}}if("error"in L)return{success:!1,error:L.error};let{entity:N,result:_}=L;return{success:!0,data:{entityType:W,entityId:N.id,platformId:_.id,url:_.url},message:`Published ${W}:${N.id}`}}return bHw(f,H,V)}}}function bHw(A,Q,w){let B=new Date(Date.now()+JHw).toISOString(),$=Eo1(A,w,B),f=NHw(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 LHw(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 D=Date.parse(f);if(Number.isNaN(D))return{success:!1,error:"Invalid publish confirmation expiry. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};if(D<=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!==Eo1(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 Eo1(A,Q,w){return qHw("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 NHw(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}c0();Z0();var An0=K.object({entityType:K.string().min(1).describe("Entity type to reconcile"),status:K.string().min(1).optional().describe("Optional metadata status filter, e.g. published"),assetType:K.string().min(1).optional().describe("Optional attachment type filter, e.g. og-image")}),Qn0=K.object({success:K.literal(!0),data:K.object({entityType:K.string(),assetType:K.string().optional(),checkedEntities:K.number(),checkedAssets:K.number(),enqueued:K.number(),skipped:K.number()}),message:K.string().optional()});function $D0(A,Q,w,B){return{...Sw(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",An0,async(f,D)=>{if(A.permissions.assertEntityActionAllowed(f.entityType,"publish",D),w.list(f.entityType).filter((G)=>G.autoGenerate===!0).filter((G)=>!f.assetType||G.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 X=await A.entityService.listEntities({entityType:f.entityType,options:{...f.status&&{filter:{metadata:{status:f.status}}}}}),H=0,W=0,Z=0;for(let G of X){let F=await B.ensureForEntity(G,{...f.assetType&&{attachmentType:f.assetType}});H+=F.checked,W+=F.enqueued,Z+=F.skipped}return{success:!0,data:{entityType:f.entityType,...f.assetType&&{assetType:f.assetType},checkedEntities:X.length,checkedAssets:H,enqueued:W,skipped:Z},message:`Queued ${W} publish asset job(s)`}},{sideEffects:"writes"}),outputSchema:Qn0}}c0();Z0();function go1(A,Q){jHw(A,Q),MHw(A,Q),_Hw(A,Q),PHw(A,Q)}function jHw(A,Q){A.messaging.subscribe(Rf.REGISTER,async(w)=>kHw(Q,w.payload)),A.messaging.subscribe(Rf.QUEUE,async(w)=>hHw(A,Q,w.payload)),A.messaging.subscribe(Rf.DIRECT,async(w)=>vHw(A,Q,w.payload)),A.messaging.subscribe(Rf.REMOVE,async(w)=>CHw(Q,w.payload)),A.messaging.subscribe(Rf.REORDER,async(w)=>yHw(Q,w.payload)),A.messaging.subscribe(Rf.LIST,async(w)=>EHw(A,Q,w.payload)),A.messaging.subscribe(Rf.REPORT_SUCCESS,async(w)=>gHw(Q,w.payload)),A.messaging.subscribe(Rf.REPORT_FAILURE,async(w)=>THw(Q,w.payload)),Q.logger.debug("Subscribed to publish messages")}function MHw(A,Q){A.messaging.subscribe(vb.REPORT_SUCCESS,async(w)=>SHw(Q,w.payload)),A.messaging.subscribe(vb.REPORT_FAILURE,async(w)=>mHw(Q,w.payload)),Q.logger.debug("Subscribed to generation messages")}function _Hw(A,Q){A.messaging.subscribe(Io1.REGISTER,async(w)=>OHw(Q,w.payload)),Q.logger.debug("Subscribed to publish asset messages")}function PHw(A,Q){let w=async(B)=>xHw(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 kHw(A,Q){let{entityType:w,provider:B,config:$}=Q;try{let f=$?Jo1.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 D=vA(f);return A.logger.error(`Failed to register provider: ${D}`),{success:!1}}}async function OHw(A,Q){let w=ef0.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 xHw(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(!RHw(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:vA(B)}),{success:!1}}}function RHw(A){if(!A)return!1;let Q=Vo1.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function hHw(A,Q,w){let{entityType:B,entityId:$}=w;try{let f=w.authContext??Xo;A.permissions.assertEntityActionAllowed(B,"publish",f);let D=await Q.queueManager.add(B,$,f);return await A.messaging.send({type:Rf.QUEUED,payload:{entityType:B,entityId:$,position:D.position}}),Q.logger.debug(`Entity queued: ${$}`,{entityType:B,position:D.position}),{success:!0}}catch(f){let D=vA(f);return Q.logger.error(`Failed to queue entity: ${D}`),{success:!1}}}async function vHw(A,Q,w){let{entityType:B,entityId:$}=w,f=w.authContext??Xo;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 D=await Q.publishExecutor.publish({entityType:B,id:$});if("error"in D)return Q.scheduler.failPublish(B,$,D.error),{success:!1};return Q.scheduler.completePublish(B,$,D.result),Q.logger.debug(`Direct publish completed: ${$}`,{entityType:B}),{success:!0}}catch(D){let Y=vA(D);return Q.logger.error(`Failed direct publish request: ${Y}`),{success:!1}}}async function CHw(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=vA($);return A.logger.error(`Failed to remove entity: ${f}`),{success:!1}}}async function yHw(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 D=vA(f);return A.logger.error(`Failed to reorder entity: ${D}`),{success:!1}}}async function EHw(A,Q,w){let{entityType:B}=w;try{let $=await Q.queueManager.list(B);return await A.messaging.send({type:Rf.LIST_RESPONSE,payload:{entityType:B,queue:$.map((f)=>({entityId:f.entityId,position:f.position,queuedAt:f.queuedAt}))}}),{success:!0}}catch($){let f=vA($);return Q.logger.error(`Failed to list queue: ${f}`),{success:!1}}}async function gHw(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 THw(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 SHw(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 mHw(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}}Z0();async function To1(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:vA($)}),{shouldGenerate:!1,reason:`Condition check failed: ${vA($)}`}}}function So1(A){let{context:Q,config:w,queueManager:B,providerRegistry:$,retryTracker:f,publishExecutor:D,logger:Y}=A,X=uHw(Q);return LK.createFresh({queueManager:B,providerRegistry:$,retryTracker:f,logger:Y,backend:new tf0,...w.entitySchedules&&{entitySchedules:w.entitySchedules},...w.generationSchedules&&{generationSchedules:w.generationSchedules},...w.generationConditions&&{generationConditions:w.generationConditions},messageBus:X,publishExecutor:D,onCheckGenerationConditions:(H,W)=>To1(Q.entityService,Y,H,W)})}function uHw(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 mo1(A,Q,w){let B=A.getEntityTypes();for(let f of B){let D=await A.listEntities({entityType:f,options:{filter:{metadata:{status:"queued"}}}});for(let Y of D)await Q.add(Y.entityType,Y.id)}let $=0;for(let f of B){let D=await Q.list(f);$+=D.length}if($>0)w.info(`Rebuilt queue with ${$} queued entities`)}var cHw=["draft","queued","published","failed"];async function uo1(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:()=>lHw(A)}})}async function lHw(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 D of f){let Y=pHw(D.metadata.status);if(!Y)continue;B[Y]++,w.push({id:D.id,title:iHw(D.id,D.metadata.title),type:$,status:Y})}}return{summary:B,items:w}}function pHw(A){return cHw.find((Q)=>Q===A)}function iHw(A,Q){return typeof Q==="string"?Q:A}var co1={name:"@brains/content-pipeline",private:!0,version:"0.2.0-alpha.133",description:"Content pipeline plugin for managing entity publishing queues, scheduling, and generation",type:"module",main:"src/index.ts",types:"src/index.ts",scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",croner:"^9.1.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14",typescript:"^5.3.3"},exports:{".":{types:"./src/index.ts",default:"./src/index.ts"}},files:["src"]};class wn0 extends RQ{pluginContext;queueManager;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A){super("content-pipeline",co1,A??{},bo1)}async onRegister(A){this.pluginContext=A,this.queueManager=sG.createFresh(),this.providerRegistry=aG.createFresh(),this.retryTracker=tG.createFresh(),this.publishAssetRegistry=eG.createFresh(),this.publishAssetPreflight=new AD0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new NE({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=So1({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),go1(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 mo1(A.entityService,this.queueManager,this.logger),await uo1(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[QD0(this.pluginContext,this.id,this.queueManager),BD0(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),$D0(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.\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(),sG.resetInstance(),aG.resetInstance(),tG.resetInstance(),eG.resetInstance()}}function Bn0(A){return new wn0(A)}c0();Z0();var lo1=K.object({accountId:K.string().describe("Cloudflare account ID"),apiToken:K.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:K.string().describe("Cloudflare Web Analytics site tag")}),$n0=K.object({cloudflare:lo1.optional()});c0();Z0();var nHw=K.object({date:K.string().describe("Single date in YYYY-MM-DD format").optional(),days:K.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:K.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:K.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:K.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function rHw(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 po1(A,Q,w){let B=[];if(!w)return B;return B.push(Sw(A,"query",`Query website analytics from Cloudflare.
6622
+ ${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=mXw.parse(Q),B=[],$=D7.from(async(H)=>{let W={progress:H.progress};if(H.message!==void 0)W.message=H.message;B.push(W)});if(!$)throw Error("Failed to create progress reporter");let D=await new PP(A.logger,A).process(w,`eval-${Date.now()}`,$),Y=!1,X;if(D.success&&D.entityId){let H=await A.entityService.getEntity({entityType:"social-post",id:D.entityId});Y=!!H,X=H?.content.slice(0,300)}return{...D,entityExists:Y,entityPreview:X,progressSteps:B}})}Z0();c0();class Do{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,D=this.providers.get(f);if(!D){await this.reportFailure(Q,w,`No provider configured for platform: ${f}`);return}let Y=v2($.content,YW),X;if(Y.metadata.coverImageId)X=await this.fetchImageData(Y.metadata.coverImageId);let H=Y.metadata.documents??[],W=await this.fetchDocumentData(H);try{if(H.length>0&&W.length===0)throw Error(`Refusing to publish: ${H.length} document(s) referenced but none could be fetched`);let Z=H.length===0?await this.resolveSourceAttachment(Y.metadata):[],G=W.length>0?W:Z,F=G.length?await D.publish(Y.content,$.metadata,X,G):await D.publish(Y.content,$.metadata,X),V=new Date().toISOString(),b=F.id||void 0,L={...Y.metadata,status:"published",publishedAt:V,...b&&{platformPostId:b}},N=R7.createPostContent(L,Y.content);await this.entityService.updateEntity({entity:{...$,content:N,metadata:{...$.metadata,status:"published",publishedAt:V,platformPostId:b}}}),await this.reportSuccess(Q,w,F.id),this.logger.info(`Post published successfully: ${w}`,{platform:f,platformPostId:b})}catch(Z){let G=Z instanceof Error?Z.message:String(Z),F={...Y.metadata,status:"failed"},V=R7.createPostContent(F,Y.content);await this.entityService.updateEntity({entity:{...$,content:V,metadata:{...$.metadata,status:"failed"}}}),await this.reportFailure(Q,w,G),this.logger.error(`Post publish failed: ${w}`,{platform:f,error:G})}}catch(B){let $=vA(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 Zo1(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 Ko1(A,Q,w){let B=new Do({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")}Z0();function Uo1(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(Y){let X=vA(Y);return Q.error(`Failed to trigger auto-generate for ${$}:`,{error:X}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function Go1(A,Q){A.messaging.subscribe("social:auto-generate",async(w)=>{let{sourceEntityType:B,sourceEntityId:$,platform:f}=w.payload;try{let D=await A.jobs.enqueue({type:`${R7.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:D}),{success:!0,jobId:D}}catch(D){let Y=vA(D);return Q.error(`Failed to enqueue social post generation for ${$}:`,{error:Y}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function zo1(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 Y of $)if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:Y.id}},limit:1}})).length===0){f=Y;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 D=await A.jobs.enqueue({type:`${R7.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:D,sourcePostId:f.id}),{success:!0}}catch($){let f=vA($);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 qo1({entity:A,config:Q}){let w=hb.parse(A),B=R7.parsePostFrontmatter(w),$=R7.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 gd0(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:MB["ai.rizom.brain.socialPost"],validate:!1,buildRecord:qo1}}var Fo1={name:"@brains/social-media",private:!0,version:"0.2.0-alpha.134",description:"Multi-provider social media posting with queue-based publishing",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix",eval:"cd evals && bun run brain-eval"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class Td0 extends PQ{entityType=R7.entityType;schema=hb;adapter=R7;providers=new Map;unregisterAtprotoProjection;constructor(A){super("social-media",Fo1,A,xd0)}createGenerationHandler(A){return new PP(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return Ho1()}getDataSources(){return[new df0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),Zo1(A,this.providers,this.logger),Ko1(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)Uo1(A,this.logger),Go1(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");zo1(A,this.logger),Wo1(A),this.unregisterAtprotoProjection=U5.getInstance().register(gd0()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=Ed0(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function Yo(A){return new Td0(A)}Z0();var cXw=K.enum(["draft","queued","published","failed"]),Vo1=K.object({status:cXw.default("draft"),queueOrder:K.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:K.string().datetime().optional()});class Sd0{name="internal";async publish(A,Q){return{id:"internal"}}}var Xo={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},Rf={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"},vb={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"},Io1={REGISTER:"publish-assets:register"};Z0();var lXw=K.enum(["provider"]),Jo1=K.object({executionMode:lXw.optional(),publishResultIdField:K.string().min(1).optional(),publishTimestampField:K.string().min(1).optional(),enabled:K.boolean().optional()}).strict();var pXw=K.object({skipIfDraftExists:K.boolean().optional(),minSourceEntities:K.number().optional(),maxUnpublishedDrafts:K.number().optional(),sourceEntityType:K.string().optional()}),bo1=K.object({entitySchedules:K.record(K.string(),K.string()).optional(),generationSchedules:K.record(K.string(),K.string()).optional(),generationConditions:K.record(K.string(),pXw).optional()});class sG{static instance=null;queues=new Map;static getInstance(){return sG.instance??=new sG,sG.instance}static resetInstance(){sG.instance=null}static createFresh(){return new sG}constructor(){}async add(A,Q,w=Xo){let B=this.getOrCreateQueue(A),$=B.find((Y)=>Y.entityId===Q);if($)return{position:$.position};let f=B.length+1,D={entityId:Q,entityType:A,position:f,queuedAt:new Date().toISOString(),authContext:{...w}};return B.push(D),{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((Y)=>Y.entityId===Q);if($===-1)return;let[f]=B.splice($,1);if(!f)return;let D=Math.max(0,Math.min(w-1,B.length));B.splice(D,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 aG{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new Sd0;static getInstance(){return aG.instance??=new aG,aG.instance}static resetInstance(){aG.instance=null}static createFresh(){return new aG}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())}}Z0();Z0();async function Lo1(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await iXw(A,Q)}async function iXw(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:Rf.FAILED,payload:B,sender:"publish-service"});Q.onFailed?.(B);return}md0(A.entityType,A.entityId,w.result,Q)}catch(w){let B=vA(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 md0(A,Q,w,B){if(B.retryTracker.clearRetries(Q),B.messageBus)B.messageBus.send({type:Rf.COMPLETED,payload:{entityType:A,entityId:Q,result:w},sender:"publish-service"});B.onPublish?.({entityType:A,entityId:Q,result:w})}function No1(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:Rf.FAILED,payload:f,sender:"publish-service"});B.onFailed?.(f)}async function jo1(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:vb.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:vb.EXECUTE,payload:B,sender:"content-pipeline"});Q.onGenerate?.(B)}function Mo1(A,Q,w){if(w)w.send({type:vb.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function _o1(A,Q,w){if(w)w.send({type:vb.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var dXw=1000;class ud0{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(dXw,()=>this.processUnscheduledTypes())}stop(){if(nXw(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 Lo1(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}function nXw(A){for(let Q of A.values())Q.stop();A.clear()}class cd0{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(){rXw(this.generationJobs)}async handleTriggerGeneration(A){if(!this.deps.isRunning())return;try{await jo1(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 rXw(A){for(let Q of A.values())Q.stop();A.clear()}class LK{static instance=null;config;publishRunner;generationRunner;running=!1;static getInstance(A){return LK.instance??=new LK(A),LK.instance}static resetInstance(){if(LK.instance)LK.instance.stop();LK.instance=null}static createFresh(A){return new LK(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new ud0({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new cd0({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){md0(A,Q,w,this.publishDeps)}failPublish(A,Q,w){No1(A,Q,w,this.publishDeps)}completeGeneration(A,Q){Mo1(A,Q,this.config.messageBus)}failGeneration(A,Q){_o1(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}" - ${vA(B)}`)}}}class tG{static instance=null;retries=new Map;static getInstance(){return tG.instance??=new tG,tG.instance}static resetInstance(){tG.instance=null}static createFresh(){return new tG}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 P4(A,Q,w,B,$,f,D,Y){return P4.fromTZ(P4.tp(A,Q,w,B,$,f,D),Y)}P4.fromTZISO=(A,Q,w)=>P4.fromTZ(oXw(A,Q),w);P4.fromTZ=function(A,Q){let w=new Date(Date.UTC(A.y,A.m-1,A.d,A.h,A.i,A.s)),B=ld0(A.tz,w),$=new Date(w.getTime()-B),f=ld0(A.tz,$);if(f-B===0)return $;{let D=new Date(w.getTime()-f),Y=ld0(A.tz,D);if(Y-f===0)return D;if(!Q&&Y-f>0)return D;if(Q)throw Error("Invalid date passed to fromTZ()");return $}};P4.toTZ=function(A,Q){let w=A.toLocaleString("en-US",{timeZone:Q}).replace(/[\u202f]/," "),B=new Date(w);return{y:B.getFullYear(),m:B.getMonth()+1,d:B.getDate(),h:B.getHours(),i:B.getMinutes(),s:B.getSeconds(),tz:Q}};P4.tp=(A,Q,w,B,$,f,D)=>({y:A,m:Q,d:w,h:B,i:$,s:f,tz:D});function ld0(A,Q=new Date){let w=Q.toLocaleString("en-US",{timeZone:A,timeZoneName:"shortOffset"}).split(" ").slice(-1)[0],B=Q.toLocaleString("en-US").replace(/[\u202f]/," ");return Date.parse(`${B} GMT`)-Date.parse(`${B} ${w}`)}function oXw(A,Q){let w=new Date(Date.parse(A));if(isNaN(w))throw Error("minitz: Invalid ISO8601 passed to parser.");let B=A.substring(9);return A.includes("Z")||B.includes("-")||B.includes("+")?P4.tp(w.getUTCFullYear(),w.getUTCMonth()+1,w.getUTCDate(),w.getUTCHours(),w.getUTCMinutes(),w.getUTCSeconds(),"Etc/UTC"):P4.tp(w.getFullYear(),w.getMonth()+1,w.getDate(),w.getHours(),w.getMinutes(),w.getSeconds(),Q)}P4.minitz=P4;var pd0=32,Wo=31|pd0,xo1=[1,2,4,8,16],Po1=class{pattern;timezone;second;minute;hour;day;month;dayOfWeek;lastDayOfMonth;starDOM;starDOW;constructor(A,Q){this.pattern=A,this.timezone=Q,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.lastDayOfMonth=!1,this.starDOM=!1,this.starDOW=!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.replace(/\s+/g," ").split(" ");if(A.length<5||A.length>6)throw TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exactly five or six space separated parts are required.");if(A.length===5&&A.unshift("0"),A[3].indexOf("L")>=0&&(A[3]=A[3].replace("L",""),this.lastDayOfMonth=!0),A[3]=="*"&&(this.starDOM=!0),A[4].length>=3&&(A[4]=this.replaceAlphaMonths(A[4])),A[5].length>=3&&(A[5]=this.replaceAlphaDays(A[5])),A[5]=="*"&&(this.starDOW=!0),this.pattern.indexOf("?")>=0){let Q=new XW(new Date,this.timezone).getDate(!0);A[0]=A[0].replace("?",Q.getSeconds().toString()),A[1]=A[1].replace("?",Q.getMinutes().toString()),A[2]=A[2].replace("?",Q.getHours().toString()),this.starDOM||(A[3]=A[3].replace("?",Q.getDate().toString())),A[4]=A[4].replace("?",(Q.getMonth()+1).toString()),this.starDOW||(A[5]=A[5].replace("?",Q.getDay().toString()))}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),this.partToArray("dayOfWeek",A[5],0,Wo),this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(A,Q,w,B){let $=this[A],f=A==="day"&&this.lastDayOfMonth;if(Q===""&&!f)throw TypeError("CronPattern: configuration entry "+A+" ("+Q+") is empty, check for trailing spaces.");if(Q==="*")return $.fill(B);let D=Q.split(",");if(D.length>1)for(let Y=0;Y<D.length;Y++)this.partToArray(A,D[Y],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===5?/[^/*0-9,\-#L]+/:/[^/*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=parseInt($[0],10)+w;if(isNaN(f))throw TypeError("CronPattern: "+Q+" is not a number: '"+A+"'");this.setPart(Q,f,$[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"){if(Q<0||Q>=31)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="month"&&(Q<0||Q>=12))throw RangeError("CronPattern: Invalid value for "+A+": "+Q);this[A][Q]=w}handleRangeWithStepping(A,Q,w,B){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[,D,Y,X]=f,H=parseInt(D,10)+w,W=parseInt(Y,10)+w,Z=parseInt(X,10);if(isNaN(H))throw TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(W))throw TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(isNaN(Z))throw TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(Z===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(Z>this[Q].length)throw TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[Q].length+")");if(H>W)throw TypeError("CronPattern: From value is larger than to value: '"+A+"'");for(let G=H;G<=W;G+=Z)this.setPart(Q,G,$[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]}return[w,B]}handleRange(A,Q,w,B){let $=this.extractNth(A,Q),f=$[0].split("-");if(f.length!==2)throw TypeError("CronPattern: Syntax error, illegal range: '"+A+"'");let D=parseInt(f[0],10)+w,Y=parseInt(f[1],10)+w;if(isNaN(D))throw TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(Y))throw TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(D>Y)throw TypeError("CronPattern: From value is larger than to value: '"+A+"'");for(let X=D;X<=Y;X++)this.setPart(Q,X,$[1]||B)}handleStepping(A,Q,w,B){let $=this.extractNth(A,Q),f=$[0].split("/");if(f.length!==2)throw TypeError("CronPattern: Syntax error, illegal stepping: '"+A+"'");f[0]===""&&(f[0]="*");let D=0;f[0]!=="*"&&(D=parseInt(f[0],10)+w);let Y=parseInt(f[1],10);if(isNaN(Y))throw TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(Y===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(Y>this[Q].length)throw TypeError("CronPattern: Syntax error, max steps for part is ("+this[Q].length+")");for(let X=D;X<this[Q].length;X+=Y)this.setPart(Q,X,$[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")}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();return Q==="@yearly"||Q==="@annually"?"0 0 1 1 *":Q==="@monthly"?"0 0 1 * *":Q==="@weekly"?"0 0 * * 0":Q==="@daily"?"0 0 * * *":Q==="@hourly"?"0 * * * *":A}setNthWeekdayOfMonth(A,Q){if(typeof Q!="number"&&Q==="L")this.dayOfWeek[A]=this.dayOfWeek[A]|pd0;else if(Q===Wo)this.dayOfWeek[A]=Wo;else if(Q<6&&Q>0)this.dayOfWeek[A]=this.dayOfWeek[A]|xo1[Q-1];else throw TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${Q}, Type: ${typeof Q}`)}},ko1=[31,28,31,30,31,30,31,31,30,31,30,31],qF=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],XW=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===void 0)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")}isNthWeekdayOfMonth(Q,w,B,$){let f=new Date(Date.UTC(Q,w,B)).getUTCDay(),D=0;for(let Y=1;Y<=B;Y++)new Date(Date.UTC(Q,w,Y)).getUTCDay()===f&&D++;if($&Wo&&xo1[D-1]&$)return!0;if($&pd0){let Y=new Date(Date.UTC(Q,w+1,0)).getUTCDate();for(let X=B+1;X<=Y;X++)if(new Date(Date.UTC(Q,w,X)).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{let w=P4.toTZ(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}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.day>ko1[this.month]||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=P4.fromTZISO(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(P4.fromTZISO(Q,this.tz))}findNext(Q,w,B,$){let f=this[w],D;B.lastDayOfMonth&&(this.month!==1?D=ko1[this.month]:D=new Date(Date.UTC(this.year,this.month+1,0,0,0,0,0)).getUTCDate());let Y=!B.starDOW&&w=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0;for(let X=this[w]+$;X<B[w].length;X++){let H=B[w][X];if(w==="day"&&B.lastDayOfMonth&&X-$==D&&(H=1),w==="day"&&!B.starDOW){let W=B.dayOfWeek[(Y+(X-$-1))%7];if(W&&W&Wo)W=this.isNthWeekdayOfMonth(this.year,this.month,X-$,W)?1:0;else if(W)throw Error(`CronDate: Invalid value for dayOfWeek encountered. ${W}`);Q.legacyMode&&!B.starDOM?H=H||W:H=H&&W}if(H)return this[w]=X-$,f!==this[w]?2:1}return 3}recurse(Q,w,B){let $=this.findNext(w,qF[B][0],Q,qF[B][2]);if($>1){let f=B+1;for(;f<qF.length;)this[qF[f][0]]=-qF[f][2],f++;if($===3)return this[qF[B][1]]++,this[qF[B][0]]=-qF[B][2],this.apply(),this.recurse(Q,w,0);if(this.apply())return this.recurse(Q,w,B-1)}return B+=1,B>=qF.length?this:this.year>=3000?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)}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)):P4.fromTZ(P4.tp(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}};function sXw(A){if(A===void 0&&(A={}),delete A.name,A.legacyMode=A.legacyMode===void 0?!0:A.legacyMode,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.unref=A.unref===void 0?!1:A.unref,A.startAt&&(A.startAt=new XW(A.startAt,A.timezone)),A.stopAt&&(A.stopAt=new XW(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).");return A}function Ho(A){return Object.prototype.toString.call(A)==="[object Function]"||typeof A=="function"||A instanceof Function}function aXw(A){return Ho(A)}function tXw(A){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(A):A&&typeof A.unref<"u"&&A.unref()}var Oo1=30000,af0=[],id0=class{name;options;_states;fn;constructor(A,Q,w){let B,$;if(Ho(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(Ho(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=sXw(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 Po1("* * * * *")},A&&(A instanceof Date||typeof A=="string"&&A.indexOf(":")>0)?this._states.once=new XW(A,this.options.timezone||this.options.utcOffset):this._states.pattern=new Po1(A,this.options.timezone),this.name){if(af0.find((f)=>f.name===this.name))throw Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");af0.push(this)}return $!==void 0&&aXw($)&&(this.fn=$,this.schedule()),this}nextRun(A){let Q=this._next(A);return Q?Q.getDate(!1):null}nextRuns(A,Q){this._states.maxRuns!==void 0&&A>this._states.maxRuns&&(A=this._states.maxRuns);let w=[],B=Q||this._states.currentRun||void 0;for(;A--&&(B=this.nextRun(B));)w.push(B);return w}getPattern(){return this._states.pattern?this._states.pattern.pattern:void 0}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 XW||A instanceof Date?Q.getTime()-A.getTime():Q.getTime()-new XW(A).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let A=af0.indexOf(this);A>=0&&af0.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>Oo1&&(Q=Oo1),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(w),Q),this._states.currentTimeout&&this.options.unref&&tXw(this._states.currentTimeout),this)}async _trigger(A){if(this._states.blocking=!0,this._states.currentRun=new XW(void 0,this.options.timezone||this.options.utcOffset),this.options.catch)try{this.fn!==void 0&&await this.fn(this,this.options.context)}catch(Q){Ho(this.options.catch)&&this.options.catch(Q,this)}else this.fn!==void 0&&await this.fn(this,this.options.context);this._states.previousRun=new XW(A,this.options.timezone||this.options.utcOffset),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&&Ho(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 XW(A,this.options.timezone||this.options.utcOffset),this.options.startAt&&A&&A.getTime()<this.options.startAt.getTime()&&(A=this.options.startAt);let B=this._states.once||new XW(A,this.options.timezone||this.options.utcOffset);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}_calculatePreviousRun(A,Q){let w=new XW(void 0,this.options.timezone||this.options.utcOffset),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 XW(B,this.options.timezone||this.options.utcOffset).increment(this._states.pattern,this.options,!0),$=B.getTime()+this.options.interval*1000;Q=!0}return B===null&&(B=void 0),[B,Q]}};class tf0{scheduleCron(A,Q){let w=new id0(A,()=>{Q()});return{stop:()=>w.stop()}}scheduleInterval(A,Q){let w=setInterval(()=>{Q()},A);return{stop:()=>clearInterval(w)}}validateCron(A){new id0(A).stop()}}Z0();var Ro1=K.union([K.string().min(1),K.object({location:K.enum(["metadata","frontmatter"]),field:K.string().min(1)})]),ef0=K.object({entityType:K.string().min(1),attachmentType:K.string().min(1),mediaEntityType:K.enum(["image","document"]),targetEntityField:Ro1.optional(),requiredWhen:K.object({status:K.string().min(1).optional(),visibility:K.string().min(1).optional()}).optional(),autoGenerate:K.boolean().optional(),requiredForPublish:K.boolean().optional(),jobType:K.string().min(1).optional()});function dd0(A){return`${A.entityType}:${A.attachmentType}`}class eG{static instance=null;definitions=new Map;static getInstance(){return eG.instance??=new eG,eG.instance}static resetInstance(){eG.instance=null}static createFresh(){return new eG}constructor(){}register(A){let Q=ef0.parse(A),w=dd0(Q);return this.definitions.set(w,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(dd0({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(dd0({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}Z0();class AD0{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 nd0(A.metadata[Q]);if(Q.location==="metadata")return nd0(A.metadata[Q.field]);let{frontmatter:w}=lw(A.content);return nd0(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 w1(`${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 nd0(A){return typeof A==="string"?A.length>0:A!==void 0}c0();Z0();var eXw=K.object({id:K.string().min(1)});async function vo1(A,Q){let{bodyContent:w,coverImageId:B,documents:$,sourceEntityType:f,sourceEntityId:D}=AHw(Q.content),Y=B?await BHw(A,B):void 0,X;if($&&$.length>0){let W=await $Hw(A,$);if(W.length>0)X=W}X??=await wHw(A,f,D);let H={bodyContent:w};if(Y)H.imageData=Y;if(X&&X.length>0)H.documentData=X;return H}function AHw(A){try{let Q=v2(A,K.record(K.unknown())),w=Q.metadata.coverImageId,B=typeof w==="string"?w:void 0,$=QHw(Q.metadata.documents),f=ho1(Q.metadata.sourceEntityType),D=ho1(Q.metadata.sourceEntityId);return{bodyContent:Q.content,...B&&{coverImageId:B},...$.length>0&&{documents:$},...f&&{sourceEntityType:f},...D&&{sourceEntityId:D}}}catch{return{bodyContent:A}}}function QHw(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let w=eXw.safeParse(Q);return w.success?[w.data]:[]})}function ho1(A){return typeof A==="string"&&A.length>0?A:void 0}async function wHw(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 BHw(A,Q){let w=await A.entityService.getEntity({entityType:"image",id:Q});if(!w?.content)return;let B=Co1(w.content);if(!B?.mimeType.startsWith("image/"))return;return{data:B.data,mimeType:B.mimeType}}async function $Hw(A,Q){return(await Promise.all(Q.map((B)=>fHw(A,B)))).filter((B)=>B!==void 0)}async function fHw(A,Q){let w=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!w?.content)return;let B=Co1(w.content);if(B?.mimeType!=="application/pdf")return;return{type:"document",data:B.data,mimeType:"application/pdf",filename:DHw(w,Q.id)}}function Co1(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function DHw(A,Q){let w=A.metadata.filename;return typeof w==="string"&&w.length>0?w:`${Q}.pdf`}Z0();var YHw=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function rd0(A,Q,w,B={}){let $=B.publishTimestampField??"publishedAt",f=Q.metadata[$],D=B.publishedAt??(typeof f==="string"?f:void 0)??new Date().toISOString(),Y={...Q.metadata,status:"published",[$]:D,platformId:w.id,...XHw(w.id,B.publishResultIdField)},X={...Q,content:yo1(Q.content,D,w.id,B.publishResultIdField,$),metadata:Y};return await A.entityService.updateEntity({entity:X}),X}function yo1(A,Q,w,B,$="publishedAt"){if(!YHw.test(A))return A;let f=o4(o4(A,"status","published"),$,Q);if(!w||!B)return f;return o4(f,B,w)}function XHw(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class NE{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:D,documentData:Y}=await vo1(this.deps.context,w),X=await $.publish(f,w.metadata,D,Y),H=this.deps.providerRegistry.getPublishResultIdField(B),W=this.deps.providerRegistry.getPublishTimestampField(B),Z=await rd0(this.deps.context,w,X,{...H?{publishResultIdField:H}:{},...W?{publishTimestampField:W}:{}});return await this.runPublishAssetPreflight(Z),{entity:Z,result:X}}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}}c0();Z0();var od0=K.object({action:K.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:K.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:K.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:K.number().optional().describe("New position for reorder action (1-based)")}),sd0=K.object({position:K.number(),entityType:K.string(),entityId:K.string(),queuedAt:K.string()}),HHw=K.object({success:K.literal(!0),message:K.string().optional(),data:K.object({queue:K.array(sd0).optional(),entityType:K.string().optional(),entityId:K.string().optional(),position:K.number().optional()}).optional()}),WHw=K.object({success:K.literal(!1),error:K.string(),code:K.string().optional()}),ad0=K.union([HHw,WHw]);function QD0(A,Q,w){return{...Sw(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",od0,async($,f)=>{let{action:D,entityType:Y,entityId:X,position:H}=$;switch(D){case"list":return ZHw(w,Y);case"add":return KHw(A,w,Y,X,f);case"remove":return UHw(A,w,Y,X,f);case"reorder":return GHw(A,w,Y,X,H,f);default:return{success:!1,error:`Unknown action: ${D}`}}},{sideEffects:"writes"}),outputSchema:ad0}}async function ZHw(A,Q){let w=[];if(Q)w=await A.list(Q);else{let $=A.getRegisteredTypes();for(let f of $){let D=await A.list(f);w.push(...D)}w.sort((f,D)=>new Date(f.queuedAt).getTime()-new Date(D.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 KHw(A,Q,w,B,$){let f=td0("add",w,B);if(!f.success)return f.error;A.permissions.assertEntityActionAllowed(f.entityType,"publish",$??{});let D=await Q.add(f.entityType,f.entityId,{...$,authorization:"user"});return{success:!0,data:{entityType:f.entityType,entityId:f.entityId,position:D.position},message:`Added to queue at position ${D.position}`}}async function UHw(A,Q,w,B,$){let f=td0("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 GHw(A,Q,w,B,$,f){let D=td0("reorder",w,B);if(!D.success)return D.error;let Y=zHw($);if(!Y.success)return Y.error;return A.permissions.assertEntityActionAllowed(D.entityType,"update",f??{}),await Q.reorder(D.entityType,D.entityId,Y.position),{success:!0,data:{entityType:D.entityType,entityId:D.entityId,position:Y.position},message:`Moved to position ${Y.position}`}}function td0(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 zHw(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}}Z0();import{createHash as qHw}from"crypto";var wD0=K.object({entityType:K.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:K.string().optional().describe("Entity ID to publish"),slug:K.string().optional().describe("Entity slug to publish"),confirmed:K.boolean().optional(),confirmationToken:K.string().optional(),contentHash:K.string().optional(),expiresAt:K.string().datetime().optional()}),FHw=K.object({success:K.literal(!0),message:K.string().optional(),data:K.object({entityType:K.string().optional(),entityId:K.string().optional(),platformId:K.string().optional(),url:K.string().optional()}).optional()}),VHw=K.object({success:K.literal(!1),error:K.string(),code:K.string().optional()}),IHw=K.object({success:K.literal(!1).optional(),error:K.string().optional(),needsConfirmation:K.literal(!0),toolName:K.string(),summary:K.string(),preview:K.string().optional(),args:K.unknown()}),ed0=K.union([FHw,VHw,IHw]),JHw=900000;function BD0(A,Q,w,B){let $=B??new NE({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.)",inputSchema:wD0.shape,outputSchema:ed0,visibility:"anchor",sideEffects:"external",handler:async(D,Y)=>{let X=wD0.safeParse(D);if(!X.success)return{success:!1,error:`Invalid input: ${X.error.errors.map((b)=>`${b.path.join(".")}: ${b.message}`).join(", ")}`};let H=X.data,{entityType:W,id:Z,slug:G}=H;try{A.permissions.assertEntityActionAllowed(W,"publish",Y)}catch(b){return{success:!1,error:b instanceof Error?b.message:String(b)}}let F=await $.resolveCandidate({entityType:W,id:Z,slug:G});if("error"in F)return{success:!1,error:F.error};let{entity:V}=F;if(H.confirmed){let b=LHw(f,H,V);if(b!==null)return b;let L;try{L=await $.publish({entityType:W,id:V.id})}catch(j){return{success:!1,error:j instanceof Error?j.message:String(j)}}if("error"in L)return{success:!1,error:L.error};let{entity:N,result:_}=L;return{success:!0,data:{entityType:W,entityId:N.id,platformId:_.id,url:_.url},message:`Published ${W}:${N.id}`}}return bHw(f,H,V)}}}function bHw(A,Q,w){let B=new Date(Date.now()+JHw).toISOString(),$=Eo1(A,w,B),f=NHw(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 LHw(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 D=Date.parse(f);if(Number.isNaN(D))return{success:!1,error:"Invalid publish confirmation expiry. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};if(D<=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!==Eo1(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 Eo1(A,Q,w){return qHw("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 NHw(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}c0();Z0();var An0=K.object({entityType:K.string().min(1).describe("Entity type to reconcile"),status:K.string().min(1).optional().describe("Optional metadata status filter, e.g. published"),assetType:K.string().min(1).optional().describe("Optional attachment type filter, e.g. og-image")}),Qn0=K.object({success:K.literal(!0),data:K.object({entityType:K.string(),assetType:K.string().optional(),checkedEntities:K.number(),checkedAssets:K.number(),enqueued:K.number(),skipped:K.number()}),message:K.string().optional()});function $D0(A,Q,w,B){return{...Sw(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",An0,async(f,D)=>{if(A.permissions.assertEntityActionAllowed(f.entityType,"publish",D),w.list(f.entityType).filter((G)=>G.autoGenerate===!0).filter((G)=>!f.assetType||G.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 X=await A.entityService.listEntities({entityType:f.entityType,options:{...f.status&&{filter:{metadata:{status:f.status}}}}}),H=0,W=0,Z=0;for(let G of X){let F=await B.ensureForEntity(G,{...f.assetType&&{attachmentType:f.assetType}});H+=F.checked,W+=F.enqueued,Z+=F.skipped}return{success:!0,data:{entityType:f.entityType,...f.assetType&&{assetType:f.assetType},checkedEntities:X.length,checkedAssets:H,enqueued:W,skipped:Z},message:`Queued ${W} publish asset job(s)`}},{sideEffects:"writes"}),outputSchema:Qn0}}c0();Z0();function go1(A,Q){jHw(A,Q),MHw(A,Q),_Hw(A,Q),PHw(A,Q)}function jHw(A,Q){A.messaging.subscribe(Rf.REGISTER,async(w)=>kHw(Q,w.payload)),A.messaging.subscribe(Rf.QUEUE,async(w)=>hHw(A,Q,w.payload)),A.messaging.subscribe(Rf.DIRECT,async(w)=>vHw(A,Q,w.payload)),A.messaging.subscribe(Rf.REMOVE,async(w)=>CHw(Q,w.payload)),A.messaging.subscribe(Rf.REORDER,async(w)=>yHw(Q,w.payload)),A.messaging.subscribe(Rf.LIST,async(w)=>EHw(A,Q,w.payload)),A.messaging.subscribe(Rf.REPORT_SUCCESS,async(w)=>gHw(Q,w.payload)),A.messaging.subscribe(Rf.REPORT_FAILURE,async(w)=>THw(Q,w.payload)),Q.logger.debug("Subscribed to publish messages")}function MHw(A,Q){A.messaging.subscribe(vb.REPORT_SUCCESS,async(w)=>SHw(Q,w.payload)),A.messaging.subscribe(vb.REPORT_FAILURE,async(w)=>mHw(Q,w.payload)),Q.logger.debug("Subscribed to generation messages")}function _Hw(A,Q){A.messaging.subscribe(Io1.REGISTER,async(w)=>OHw(Q,w.payload)),Q.logger.debug("Subscribed to publish asset messages")}function PHw(A,Q){let w=async(B)=>xHw(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 kHw(A,Q){let{entityType:w,provider:B,config:$}=Q;try{let f=$?Jo1.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 D=vA(f);return A.logger.error(`Failed to register provider: ${D}`),{success:!1}}}async function OHw(A,Q){let w=ef0.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 xHw(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(!RHw(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:vA(B)}),{success:!1}}}function RHw(A){if(!A)return!1;let Q=Vo1.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function hHw(A,Q,w){let{entityType:B,entityId:$}=w;try{let f=w.authContext??Xo;A.permissions.assertEntityActionAllowed(B,"publish",f);let D=await Q.queueManager.add(B,$,f);return await A.messaging.send({type:Rf.QUEUED,payload:{entityType:B,entityId:$,position:D.position}}),Q.logger.debug(`Entity queued: ${$}`,{entityType:B,position:D.position}),{success:!0}}catch(f){let D=vA(f);return Q.logger.error(`Failed to queue entity: ${D}`),{success:!1}}}async function vHw(A,Q,w){let{entityType:B,entityId:$}=w,f=w.authContext??Xo;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 D=await Q.publishExecutor.publish({entityType:B,id:$});if("error"in D)return Q.scheduler.failPublish(B,$,D.error),{success:!1};return Q.scheduler.completePublish(B,$,D.result),Q.logger.debug(`Direct publish completed: ${$}`,{entityType:B}),{success:!0}}catch(D){let Y=vA(D);return Q.logger.error(`Failed direct publish request: ${Y}`),{success:!1}}}async function CHw(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=vA($);return A.logger.error(`Failed to remove entity: ${f}`),{success:!1}}}async function yHw(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 D=vA(f);return A.logger.error(`Failed to reorder entity: ${D}`),{success:!1}}}async function EHw(A,Q,w){let{entityType:B}=w;try{let $=await Q.queueManager.list(B);return await A.messaging.send({type:Rf.LIST_RESPONSE,payload:{entityType:B,queue:$.map((f)=>({entityId:f.entityId,position:f.position,queuedAt:f.queuedAt}))}}),{success:!0}}catch($){let f=vA($);return Q.logger.error(`Failed to list queue: ${f}`),{success:!1}}}async function gHw(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 THw(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 SHw(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 mHw(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}}Z0();async function To1(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:vA($)}),{shouldGenerate:!1,reason:`Condition check failed: ${vA($)}`}}}function So1(A){let{context:Q,config:w,queueManager:B,providerRegistry:$,retryTracker:f,publishExecutor:D,logger:Y}=A,X=uHw(Q);return LK.createFresh({queueManager:B,providerRegistry:$,retryTracker:f,logger:Y,backend:new tf0,...w.entitySchedules&&{entitySchedules:w.entitySchedules},...w.generationSchedules&&{generationSchedules:w.generationSchedules},...w.generationConditions&&{generationConditions:w.generationConditions},messageBus:X,publishExecutor:D,onCheckGenerationConditions:(H,W)=>To1(Q.entityService,Y,H,W)})}function uHw(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 mo1(A,Q,w){let B=A.getEntityTypes();for(let f of B){let D=await A.listEntities({entityType:f,options:{filter:{metadata:{status:"queued"}}}});for(let Y of D)await Q.add(Y.entityType,Y.id)}let $=0;for(let f of B){let D=await Q.list(f);$+=D.length}if($>0)w.info(`Rebuilt queue with ${$} queued entities`)}var cHw=["draft","queued","published","failed"];async function uo1(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:()=>lHw(A)}})}async function lHw(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 D of f){let Y=pHw(D.metadata.status);if(!Y)continue;B[Y]++,w.push({id:D.id,title:iHw(D.id,D.metadata.title),type:$,status:Y})}}return{summary:B,items:w}}function pHw(A){return cHw.find((Q)=>Q===A)}function iHw(A,Q){return typeof Q==="string"?Q:A}var co1={name:"@brains/content-pipeline",private:!0,version:"0.2.0-alpha.134",description:"Content pipeline plugin for managing entity publishing queues, scheduling, and generation",type:"module",main:"src/index.ts",types:"src/index.ts",scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",croner:"^9.1.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14",typescript:"^5.3.3"},exports:{".":{types:"./src/index.ts",default:"./src/index.ts"}},files:["src"]};class wn0 extends RQ{pluginContext;queueManager;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A){super("content-pipeline",co1,A??{},bo1)}async onRegister(A){this.pluginContext=A,this.queueManager=sG.createFresh(),this.providerRegistry=aG.createFresh(),this.retryTracker=tG.createFresh(),this.publishAssetRegistry=eG.createFresh(),this.publishAssetPreflight=new AD0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new NE({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=So1({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),go1(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 mo1(A.entityService,this.queueManager,this.logger),await uo1(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[QD0(this.pluginContext,this.id,this.queueManager),BD0(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),$D0(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.\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(),sG.resetInstance(),aG.resetInstance(),tG.resetInstance(),eG.resetInstance()}}function Bn0(A){return new wn0(A)}c0();Z0();var lo1=K.object({accountId:K.string().describe("Cloudflare account ID"),apiToken:K.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:K.string().describe("Cloudflare Web Analytics site tag")}),$n0=K.object({cloudflare:lo1.optional()});c0();Z0();var nHw=K.object({date:K.string().describe("Single date in YYYY-MM-DD format").optional(),days:K.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:K.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:K.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:K.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function rHw(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 po1(A,Q,w){let B=[];if(!w)return B;return B.push(Sw(A,"query",`Query website analytics from Cloudflare.
6623
6623
 
6624
6624
  Date range options (use only one):
6625
6625
  - No params: yesterday only
@@ -6757,7 +6757,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,nHw,
6757
6757
  }
6758
6758
  }
6759
6759
  }
6760
- `,variables:w})});if(!B.ok){let D=await B.text();throw Error(`Cloudflare API error: ${B.status} - ${D}`)}let $=await B.json();if($.errors&&$.errors.length>0)throw Error(`Cloudflare GraphQL error: ${$.errors.map((D)=>D.message).join(", ")}`);return($.data.viewer.accounts[0]?.rumPageloadEventsAdaptiveGroups??[]).map((D)=>({country:D.dimensions.countryName,visits:D.sum.visits}))}}Z0();var Dn0=7,oHw=10;function do1(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=ZO(),w=bt(Dn0),B=_V(w),$=_V(Q);try{let[f,D]=await Promise.all([A.getWebsiteStats({startDate:B,endDate:$}),A.getTopPages({startDate:B,endDate:$,limit:oHw})]);return{days:Dn0,startDate:B,endDate:$,pageviews:f.pageviews,visitors:f.visitors,topPages:D}}catch(f){return{error:f instanceof Error?f.message:"Failed to fetch analytics",days:Dn0}}}}var no1={name:"@brains/analytics",private:!0,version:"0.2.0-alpha.133",description:"Analytics plugin for collecting website and social media metrics",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class ro1 extends RQ{cloudflareClient;constructor(A={}){super("analytics",no1,A,$n0)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new fn0(this.config.cloudflare):void 0,A.insights.register("traffic-overview",do1(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:io1(Q)}})}async getTools(){return po1(this.id,this.getContext(),this.cloudflareClient)}}function aHw(A={}){return new ro1(A)}var fD0=aHw;import{randomBytes as BWw}from"crypto";c0();Z0();aB();var tHw=new Set(["description","excerpt","summary","tagline","story"]);function eHw(A){if(A.endsWith("s"))return A;return UY(A)}function Yn0(A,Q=!1,w){let B=A._def.typeName;if(B==="ZodOptional"||B==="ZodNullable")return Yn0(A._def.innerType,!0,w);if(B==="ZodDefault")return Yn0(A._def.innerType,Q,A._def.defaultValue());return{inner:A,isOptional:Q,defaultValue:w}}function Xn0(A,Q){let{inner:w,isOptional:B,defaultValue:$}=Yn0(Q),f=w._def.typeName,D={name:A,label:fU(A),widget:"string",...B&&{required:!1},...$!==void 0&&{default:$}};switch(f){case"ZodString":{if((w._def.checks??[]).some((X)=>X.kind==="datetime"))return{...D,widget:"datetime"};if(tHw.has(A))return{...D,widget:"text"};return{...D,widget:"string"}}case"ZodNumber":return{...D,widget:"number"};case"ZodBoolean":return{...D,widget:"boolean"};case"ZodEnum":{let Y=w._def.values;return{...D,widget:"select",options:Y}}case"ZodArray":{let Y=w._def.type,X=Xn0("item",Y);if(X.widget==="object"&&X.fields)return{...D,widget:"list",fields:X.fields};return{...D,widget:"list",field:{name:A,label:fU(A),widget:X.widget}}}case"ZodObject":{let Y=w.shape,X=Object.entries(Y).map(([H,W])=>Xn0(H,W));return{...D,widget:"object",fields:X}}default:return{...D,widget:"string"}}}function oo1(A,Q){let w=Object.entries(A.shape).map(([B,$])=>Xn0(B,$));if(Q)w.push({name:"body",label:"Body",widget:"markdown"});return w}function so1(A){let Q=[],w=[];for(let B of A.entityTypes){let $=A.getFrontmatterSchema(B);if(!$)continue;let f=A.getAdapter(B),D=f?.hasBody!==!1,Y=A.entityDisplay?.[B],X=B===he?"Note":fU(B),H=Y?.label??X,W=Y?.pluralName??eHw(H);if(f?.isSingleton){w.push({name:B,label:H,file:`${B}/${B}.md`,fields:oo1($,D)});continue}if(B===he){Q.push({name:B,label:W,folder:".",create:!0,extension:"md",format:"raw",fields:[{name:"body",label:"Body",widget:"markdown"}]});continue}Q.push({name:B,label:W,folder:B,create:!0,extension:"md",format:"frontmatter",fields:oo1($,D)})}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 AWw=new RegExp("[<>&\\u2028\\u2029]","g");function jE(A){return JSON.stringify(A).replace(AWw,(Q)=>`\\u${Q.charCodeAt(0).toString(16).padStart(4,"0")}`)}var ao1="https://unpkg.com/@sveltia/cms@0.165.1/dist/sveltia-cms.js";function DD0(A){let Q=`<script src="${ao1}"></script>`;return`<!doctype html>
6760
+ `,variables:w})});if(!B.ok){let D=await B.text();throw Error(`Cloudflare API error: ${B.status} - ${D}`)}let $=await B.json();if($.errors&&$.errors.length>0)throw Error(`Cloudflare GraphQL error: ${$.errors.map((D)=>D.message).join(", ")}`);return($.data.viewer.accounts[0]?.rumPageloadEventsAdaptiveGroups??[]).map((D)=>({country:D.dimensions.countryName,visits:D.sum.visits}))}}Z0();var Dn0=7,oHw=10;function do1(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=ZO(),w=bt(Dn0),B=_V(w),$=_V(Q);try{let[f,D]=await Promise.all([A.getWebsiteStats({startDate:B,endDate:$}),A.getTopPages({startDate:B,endDate:$,limit:oHw})]);return{days:Dn0,startDate:B,endDate:$,pageviews:f.pageviews,visitors:f.visitors,topPages:D}}catch(f){return{error:f instanceof Error?f.message:"Failed to fetch analytics",days:Dn0}}}}var no1={name:"@brains/analytics",private:!0,version:"0.2.0-alpha.134",description:"Analytics plugin for collecting website and social media metrics",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class ro1 extends RQ{cloudflareClient;constructor(A={}){super("analytics",no1,A,$n0)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new fn0(this.config.cloudflare):void 0,A.insights.register("traffic-overview",do1(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:io1(Q)}})}async getTools(){return po1(this.id,this.getContext(),this.cloudflareClient)}}function aHw(A={}){return new ro1(A)}var fD0=aHw;import{randomBytes as BWw}from"crypto";c0();Z0();aB();var tHw=new Set(["description","excerpt","summary","tagline","story"]);function eHw(A){if(A.endsWith("s"))return A;return UY(A)}function Yn0(A,Q=!1,w){let B=A._def.typeName;if(B==="ZodOptional"||B==="ZodNullable")return Yn0(A._def.innerType,!0,w);if(B==="ZodDefault")return Yn0(A._def.innerType,Q,A._def.defaultValue());return{inner:A,isOptional:Q,defaultValue:w}}function Xn0(A,Q){let{inner:w,isOptional:B,defaultValue:$}=Yn0(Q),f=w._def.typeName,D={name:A,label:fU(A),widget:"string",...B&&{required:!1},...$!==void 0&&{default:$}};switch(f){case"ZodString":{if((w._def.checks??[]).some((X)=>X.kind==="datetime"))return{...D,widget:"datetime"};if(tHw.has(A))return{...D,widget:"text"};return{...D,widget:"string"}}case"ZodNumber":return{...D,widget:"number"};case"ZodBoolean":return{...D,widget:"boolean"};case"ZodEnum":{let Y=w._def.values;return{...D,widget:"select",options:Y}}case"ZodArray":{let Y=w._def.type,X=Xn0("item",Y);if(X.widget==="object"&&X.fields)return{...D,widget:"list",fields:X.fields};return{...D,widget:"list",field:{name:A,label:fU(A),widget:X.widget}}}case"ZodObject":{let Y=w.shape,X=Object.entries(Y).map(([H,W])=>Xn0(H,W));return{...D,widget:"object",fields:X}}default:return{...D,widget:"string"}}}function oo1(A,Q){let w=Object.entries(A.shape).map(([B,$])=>Xn0(B,$));if(Q)w.push({name:"body",label:"Body",widget:"markdown"});return w}function so1(A){let Q=[],w=[];for(let B of A.entityTypes){let $=A.getFrontmatterSchema(B);if(!$)continue;let f=A.getAdapter(B),D=f?.hasBody!==!1,Y=A.entityDisplay?.[B],X=B===he?"Note":fU(B),H=Y?.label??X,W=Y?.pluralName??eHw(H);if(f?.isSingleton){w.push({name:B,label:H,file:`${B}/${B}.md`,fields:oo1($,D)});continue}if(B===he){Q.push({name:B,label:W,folder:".",create:!0,extension:"md",format:"raw",fields:[{name:"body",label:"Body",widget:"markdown"}]});continue}Q.push({name:B,label:W,folder:B,create:!0,extension:"md",format:"frontmatter",fields:oo1($,D)})}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 AWw=new RegExp("[<>&\\u2028\\u2029]","g");function jE(A){return JSON.stringify(A).replace(AWw,(Q)=>`\\u${Q.charCodeAt(0).toString(16).padStart(4,"0")}`)}var ao1="https://unpkg.com/@sveltia/cms@0.165.1/dist/sveltia-cms.js";function DD0(A){let Q=`<script src="${ao1}"></script>`;return`<!doctype html>
6761
6761
  <html>
6762
6762
  <head>
6763
6763
  <meta charset="utf-8" />
@@ -6796,7 +6796,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,nHw,
6796
6796
  showError(error instanceof Error ? error.message : String(error));
6797
6797
  }
6798
6798
  })();
6799
- `}Z0();var to1={name:"@brains/cms",private:!0,version:"0.2.0-alpha.133",description:"CMS plugin for config and browser authoring routes",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/auth-service":"workspace:*","@brains/cms-config":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var Wn0="brains_cms_oauth_state",$Ww=600,fWw="auth",DWw=K.object({label:K.string().optional(),pluralName:K.string().optional()}).passthrough(),YWw=K.object({clientId:K.string().optional(),clientSecret:K.string().optional(),scope:K.string().optional()}),XWw=K.object({contentRepoToken:K.string().optional()}),HWw=K.object({entityDisplay:K.record(DWw).optional(),routePath:K.string().default("/cms"),githubOAuth:YWw.optional(),passkeyLogin:XWw.optional()}).refine((A)=>{let Q=Boolean(kP(A.githubOAuth?.clientId)&&kP(A.githubOAuth?.clientSecret)),w=Boolean(kP(A.passkeyLogin?.contentRepoToken));return!(Q&&w)},{message:"CMS login supports a single method per brain: configure githubOAuth or passkeyLogin, not both."});function WWw(A){return`${A.endsWith("/")?A:`${A}/`}config.yml`}function kP(A){if(!A)return;let Q=A.trim();return Q.length>0?Q:void 0}function ZWw(A){let Q=kP(A.githubOAuth?.clientId),w=kP(A.githubOAuth?.clientSecret),B=kP(A.passkeyLogin?.contentRepoToken);return{...Q&&w?{githubOAuth:{clientId:Q,clientSecret:w,scope:kP(A.githubOAuth?.scope)??"repo"}}:{},...B?{passkeyLogin:{contentRepoToken:B}}:{}}}function KWw(A){return Boolean(A.githubOAuth??A.passkeyLogin)}function UWw(A,Q,w){let B=A.entityDisplay??w?.entityDisplay;return{...B?{entityDisplay:B}:{},...KWw(Q)?{authEndpoint:fWw}:{}}}async function GWw(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 zWw(A,Q={}){let{repo:w,branch:B}=await GWw(A);return so1({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 Qs1(A,Q={}){return $U(await zWw(A,Q))}class Zn0 extends RQ{constructor(A={}){super("cms",to1,A,HWw)}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=WWw(this.config.routePath),Q=ZWw(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 As1(B))return new Response(null,{status:302,headers:{Location:`/login?return_to=${encodeURIComponent(this.config.routePath)}`,"Cache-Control":"no-store"}});return Ko(DD0({cmsConfigPath:A,authTokenEndpoint:"/auth/cms-token"}))}return Ko(DD0({cmsConfigPath:A}))}},{path:A,method:"GET",public:!0,handler:async(B)=>{try{let $=UWw(this.config,Q,this.getContext()),f=await Qs1(this.getContext(),{...$,...$.authEndpoint?{baseUrl:Zo(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 As1(A)?LWw:bWw;return Ko(w(Zo(this.getContext(),A)))}return JWw("CMS login is not enabled",404)}redirectToGitHub(A,Q){let w=BWw(32).toString("base64url"),B=`${Zo(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":VWw(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 YD0(`GitHub OAuth failed: ${H}`)}let $=w.searchParams.get("state"),f=IWw(A.headers.get("cookie"),Wn0);if(!$||!f||$!==f)return YD0("GitHub OAuth state did not match");let D=w.searchParams.get("code");if(!D)return YD0("GitHub OAuth callback did not include a code");let Y=`${Zo(this.getContext(),A)}/auth/callback`,X=await qWw(Q,D,Y);if(!X.success)return YD0(X.error);return Ko(NWw(X.token,Zo(this.getContext(),A)),200,{"Set-Cookie":Bs1()})}async handleCmsToken(A,Q){if(!await gH()?.getOperatorSession(A))return eo1({error:"Operator session required"},401);return eo1({token:Q.contentRepoToken,provider:"github"},200,{"Cache-Control":"no-store"})}}function OP(A){return new Zn0(A)}async function qWw(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"}}if(!$.ok)return{success:!1,error:FWw(f)??"GitHub token exchange failed"};if(Hn0(f)&&typeof f.error==="string")return{success:!1,error:typeof f.error_description==="string"?f.error_description:f.error};let D=Hn0(f)?f.access_token:void 0;if(typeof D!=="string"||D.length===0)return{success:!1,error:"GitHub token response omitted token"};return{success:!0,token:D}}function FWw(A){if(!Hn0(A))return;if(typeof A.error_description==="string")return A.error_description;return typeof A.error==="string"?A.error:void 0}function Hn0(A){return Boolean(A&&typeof A==="object"&&!Array.isArray(A))}function Zo(A,Q){let w=new URL(Q.url).origin;if(ws1(w))return w;return A.siteUrl??w}function ws1(A){let{hostname:Q}=new URL(A);return Q==="localhost"||Q==="127.0.0.1"||Q==="::1"||Q==="[::1]"}function VWw(A,Q){let w=ws1(new URL(Q.url).origin)?"":"; Secure";return`${Wn0}=${A}; Path=/auth; HttpOnly; SameSite=Lax; Max-Age=${$Ww}${w}`}function Bs1(){return`${Wn0}=; Path=/auth; HttpOnly; SameSite=Lax; Max-Age=0`}function IWw(A,Q){if(!A)return;for(let w of A.split(";")){let[B,...$]=w.trim().split("=");if(B===Q)return $.join("=")}return}function Ko(A,Q=200,w={}){return new Response(A,{status:Q,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store",...w}})}function JWw(A,Q=200){return new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8","Cache-Control":"no-store"}})}function eo1(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 YD0(A){return Ko(`<!doctype html><html><body><h1>CMS login failed</h1><p>${_Ww(A)}</p></body></html>`,400,{"Set-Cookie":Bs1()})}async function As1(A){return Boolean(await gH()?.getOperatorSession(A))}function bWw(A){return`<!doctype html>
6799
+ `}Z0();var to1={name:"@brains/cms",private:!0,version:"0.2.0-alpha.134",description:"CMS plugin for config and browser authoring routes",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/auth-service":"workspace:*","@brains/cms-config":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var Wn0="brains_cms_oauth_state",$Ww=600,fWw="auth",DWw=K.object({label:K.string().optional(),pluralName:K.string().optional()}).passthrough(),YWw=K.object({clientId:K.string().optional(),clientSecret:K.string().optional(),scope:K.string().optional()}),XWw=K.object({contentRepoToken:K.string().optional()}),HWw=K.object({entityDisplay:K.record(DWw).optional(),routePath:K.string().default("/cms"),githubOAuth:YWw.optional(),passkeyLogin:XWw.optional()}).refine((A)=>{let Q=Boolean(kP(A.githubOAuth?.clientId)&&kP(A.githubOAuth?.clientSecret)),w=Boolean(kP(A.passkeyLogin?.contentRepoToken));return!(Q&&w)},{message:"CMS login supports a single method per brain: configure githubOAuth or passkeyLogin, not both."});function WWw(A){return`${A.endsWith("/")?A:`${A}/`}config.yml`}function kP(A){if(!A)return;let Q=A.trim();return Q.length>0?Q:void 0}function ZWw(A){let Q=kP(A.githubOAuth?.clientId),w=kP(A.githubOAuth?.clientSecret),B=kP(A.passkeyLogin?.contentRepoToken);return{...Q&&w?{githubOAuth:{clientId:Q,clientSecret:w,scope:kP(A.githubOAuth?.scope)??"repo"}}:{},...B?{passkeyLogin:{contentRepoToken:B}}:{}}}function KWw(A){return Boolean(A.githubOAuth??A.passkeyLogin)}function UWw(A,Q,w){let B=A.entityDisplay??w?.entityDisplay;return{...B?{entityDisplay:B}:{},...KWw(Q)?{authEndpoint:fWw}:{}}}async function GWw(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 zWw(A,Q={}){let{repo:w,branch:B}=await GWw(A);return so1({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 Qs1(A,Q={}){return $U(await zWw(A,Q))}class Zn0 extends RQ{constructor(A={}){super("cms",to1,A,HWw)}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=WWw(this.config.routePath),Q=ZWw(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 As1(B))return new Response(null,{status:302,headers:{Location:`/login?return_to=${encodeURIComponent(this.config.routePath)}`,"Cache-Control":"no-store"}});return Ko(DD0({cmsConfigPath:A,authTokenEndpoint:"/auth/cms-token"}))}return Ko(DD0({cmsConfigPath:A}))}},{path:A,method:"GET",public:!0,handler:async(B)=>{try{let $=UWw(this.config,Q,this.getContext()),f=await Qs1(this.getContext(),{...$,...$.authEndpoint?{baseUrl:Zo(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 As1(A)?LWw:bWw;return Ko(w(Zo(this.getContext(),A)))}return JWw("CMS login is not enabled",404)}redirectToGitHub(A,Q){let w=BWw(32).toString("base64url"),B=`${Zo(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":VWw(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 YD0(`GitHub OAuth failed: ${H}`)}let $=w.searchParams.get("state"),f=IWw(A.headers.get("cookie"),Wn0);if(!$||!f||$!==f)return YD0("GitHub OAuth state did not match");let D=w.searchParams.get("code");if(!D)return YD0("GitHub OAuth callback did not include a code");let Y=`${Zo(this.getContext(),A)}/auth/callback`,X=await qWw(Q,D,Y);if(!X.success)return YD0(X.error);return Ko(NWw(X.token,Zo(this.getContext(),A)),200,{"Set-Cookie":Bs1()})}async handleCmsToken(A,Q){if(!await gH()?.getOperatorSession(A))return eo1({error:"Operator session required"},401);return eo1({token:Q.contentRepoToken,provider:"github"},200,{"Cache-Control":"no-store"})}}function OP(A){return new Zn0(A)}async function qWw(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"}}if(!$.ok)return{success:!1,error:FWw(f)??"GitHub token exchange failed"};if(Hn0(f)&&typeof f.error==="string")return{success:!1,error:typeof f.error_description==="string"?f.error_description:f.error};let D=Hn0(f)?f.access_token:void 0;if(typeof D!=="string"||D.length===0)return{success:!1,error:"GitHub token response omitted token"};return{success:!0,token:D}}function FWw(A){if(!Hn0(A))return;if(typeof A.error_description==="string")return A.error_description;return typeof A.error==="string"?A.error:void 0}function Hn0(A){return Boolean(A&&typeof A==="object"&&!Array.isArray(A))}function Zo(A,Q){let w=new URL(Q.url).origin;if(ws1(w))return w;return A.siteUrl??w}function ws1(A){let{hostname:Q}=new URL(A);return Q==="localhost"||Q==="127.0.0.1"||Q==="::1"||Q==="[::1]"}function VWw(A,Q){let w=ws1(new URL(Q.url).origin)?"":"; Secure";return`${Wn0}=${A}; Path=/auth; HttpOnly; SameSite=Lax; Max-Age=${$Ww}${w}`}function Bs1(){return`${Wn0}=; Path=/auth; HttpOnly; SameSite=Lax; Max-Age=0`}function IWw(A,Q){if(!A)return;for(let w of A.split(";")){let[B,...$]=w.trim().split("=");if(B===Q)return $.join("=")}return}function Ko(A,Q=200,w={}){return new Response(A,{status:Q,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store",...w}})}function JWw(A,Q=200){return new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8","Cache-Control":"no-store"}})}function eo1(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 YD0(A){return Ko(`<!doctype html><html><body><h1>CMS login failed</h1><p>${_Ww(A)}</p></body></html>`,400,{"Set-Cookie":Bs1()})}async function As1(A){return Boolean(await gH()?.getOperatorSession(A))}function bWw(A){return`<!doctype html>
6800
6800
  <html lang="en">
6801
6801
  <head>
6802
6802
  <meta charset="utf-8" />
@@ -8201,7 +8201,7 @@ ${fs1}`;import{jsxDEV as NK,Fragment as Xs1}from"preact/jsx-dev-runtime";functio
8201
8201
  }
8202
8202
  });
8203
8203
  })();`;function YZw({input:A}){let Q=A.appInfo.entities,w=A.appInfo.entityCounts,B=$Zw(A.widgets),$=Boolean(A.character.role)||Boolean(A.character.purpose)||A.character.values.length>0,f=A.appInfo.interactions,D=`layout${$?" has-identity":""}`,Y=A.operatorAccess&&!A.operatorAccess.isOperator&&A.operatorAccess.hiddenWidgetCount>0,X=new Date;return Lw("html",{lang:"en","data-theme":"dark",children:[Lw("head",{children:[Lw("meta",{charSet:"utf-8"},void 0,!1,void 0,this),Lw("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"},void 0,!1,void 0,this),Lw("title",{children:A.title},void 0,!1,void 0,this),Lw("link",{rel:"preconnect",href:"https://fonts.googleapis.com"},void 0,!1,void 0,this),Lw("link",{rel:"preconnect",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"},void 0,!1,void 0,this),Lw("link",{href:BZw,rel:"stylesheet"},void 0,!1,void 0,this),A.themeCSS!==void 0&&Lw("style",{"data-dashboard-theme":!0,dangerouslySetInnerHTML:{__html:A.themeCSS}},void 0,!1,void 0,this),Lw("style",{"data-dashboard-styles":!0,dangerouslySetInnerHTML:{__html:Ys1}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Lw("body",{children:[Lw("main",{class:"console","data-component":"dashboard:dashboard",children:[Lw(Hs1,{title:A.title,tagline:A.profile.description,operatorAccess:A.operatorAccess},void 0,!1,void 0,this),Lw("section",{class:D,children:[$&&Lw("div",{class:"identity-column",children:[Lw(Zs1,{character:A.character},void 0,!1,void 0,this),Lw(zn0,{interactions:f,baseUrl:A.baseUrl},void 0,!1,void 0,this),Y&&A.operatorAccess&&Lw(Vs1,{hiddenWidgetCount:A.operatorAccess.hiddenWidgetCount,loginUrl:A.operatorAccess.loginUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Lw("div",{class:"main-column",children:[Lw(Ws1,{total:Q,entityCounts:w},void 0,!1,void 0,this),!$&&Y&&A.operatorAccess&&Lw(Vs1,{hiddenWidgetCount:A.operatorAccess.hiddenWidgetCount,loginUrl:A.operatorAccess.loginUrl},void 0,!1,void 0,this),B.primary.map((H)=>Lw(ZD0,{widget:H},`${H.widget.pluginId}:${H.widget.id}`,!1,void 0,this)),B.secondary.map((H)=>Lw(ZD0,{widget:H},`${H.widget.pluginId}:${H.widget.id}`,!1,void 0,this))]},void 0,!0,void 0,this),Lw("div",{class:"sidebar-column",children:[!$&&Lw(zn0,{interactions:f,baseUrl:A.baseUrl},void 0,!1,void 0,this),B.sidebar.map((H)=>Lw(ZD0,{widget:H},`${H.widget.pluginId}:${H.widget.id}`,!1,void 0,this)),Lw(Ks1,{endpoints:A.appInfo.endpoints,baseUrl:A.baseUrl},void 0,!1,void 0,this),Lw(qs1,{appInfo:A.appInfo,now:X},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Lw(Fs1,{title:A.title,appInfo:A.appInfo,baseUrl:A.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Lw("script",{dangerouslySetInnerHTML:{__html:fZw}},void 0,!1,void 0,this),Lw("script",{dangerouslySetInnerHTML:{__html:DZw}},void 0,!1,void 0,this),A.widgetScripts.map((H,W)=>Lw("script",{dangerouslySetInnerHTML:{__html:H}},`widget-script:${W}`,!1,void 0,this))]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Is1(A){return`<!doctype html>
8204
- ${wZw(Lw(YZw,{input:A},void 0,!1,void 0,this))}`}function Js1(A,Q){let w={},B=new Set;for(let[$,f]of Object.entries(A)){let D=Q?.get(f.widget.pluginId,f.widget.id);if(w[$]={...f,...D?.component?{component:D.component}:{}},D?.clientScript)B.add(D.clientScript)}return{widgets:w,widgetScripts:Array.from(B)}}var bs1={name:"@brains/dashboard",private:!0,version:"0.2.0-alpha.133",description:"Dashboard plugin with extensible widget system",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts,.tsx","lint:fix":"eslint . --ext .ts,.tsx --fix"},dependencies:{"@brains/auth-service":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2","preact-render-to-string":"^6.3.1"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var HZw=K.object({version:K.string().default("1.0.0"),routePath:K.string().default("/dashboard"),themeCSS:K.string().optional()}),WZw=K.object({id:K.string(),pluginId:K.string(),title:K.string(),description:K.string().optional(),priority:K.number().default(50),section:K.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:K.string(),visibility:s4.default("public"),component:K.custom().optional(),clientScript:K.string().optional(),dataProvider:K.function().returns(K.promise(K.unknown()))}).superRefine((A,Q)=>{if(!Gn0(A.rendererName)&&!A.component)Q.addIssue({code:K.ZodIssueCode.custom,message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),ZZw=K.object({pluginId:K.string(),widgetId:K.string().optional()});function KZw(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 Fn0 extends RQ{widgetRegistry=null;datasource=null;siteUrl;ctx;constructor(A){super("dashboard",bs1,A??{},HZw)}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new HD0(this.logger),this.datasource=new WD0(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=WZw.parse(Q.payload),B=KZw(w);return this.widgetRegistry?.register(B),this.logger.debug("Widget registered via messaging",{widgetId:w.id,pluginId:w.pluginId,rendererName:w.rendererName,builtIn:XD0.includes(w.rendererName)}),{success:!0}}catch(w){return this.logger.error("Failed to register widget",{error:vA(w),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{let w=ZZw.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}}),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 gH()?.getOperatorSession(A),B=Boolean(w),$=B?"anchor":"public",f=this.widgetRegistry?.list({permissionLevel:"anchor"})??[],D=f.filter((g)=>m$.hasPermission($,g.visibility)),Y=f.length-D.length,[X,H]=await Promise.all([this.datasource.getDashboardData({permissionLevel:$,widgets:D}),Q.appInfo()]),W=Q.identity.get(),Z=Q.identity.getProfile(),G=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),F={...H,endpoints:H.endpoints.filter((g)=>m$.hasPermission($,g.visibility)),interactions:H.interactions.filter((g)=>m$.hasPermission($,g.visibility))},V=Z.name||H.model||"Brain Dashboard",b=new URL(A.url),L=`${b.pathname}${b.search}`,N=encodeURIComponent(L),_=Js1(X.widgets,this.widgetRegistry),j={title:V,baseUrl:G,widgets:_.widgets,widgetScripts:_.widgetScripts,character:W,profile:Z,appInfo:F,...this.config.themeCSS!==void 0&&{themeCSS:this.config.themeCSS},operatorAccess:{isOperator:B,hiddenWidgetCount:Y,loginUrl:`/login?return_to=${N}`,logoutUrl:`/logout?return_to=${N}`}};return new Response(Is1(j),{headers:{"Content-Type":"text/html; charset=utf-8"}})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function yb(A){return new Fn0(A)}c0();Z0();var UZw=K.object({id:K.string(),pluginId:K.string(),title:K.string(),description:K.string().optional(),priority:K.number(),section:K.enum(["primary","secondary","sidebar"]),rendererName:K.string(),visibility:s4,component:K.custom().optional()}),GZw=K.object({widget:UZw,data:K.unknown()}),zZw=K.object({widgets:K.record(GZw)});Z0();c0();Z0();import{h as OZw}from"preact";Z0();bY();c0();var ME=K.enum(["generating","draft","queued","published","failed"]),Go=K.object({subject:K.string(),status:ME,entityIds:K.array(K.string()).optional(),scheduledFor:K.string().datetime().optional(),sentAt:K.string().datetime().optional(),buttondownId:K.string().optional(),sourceEntityType:K.string().optional()}),Ls1=Go.pick({subject:!0,status:!0,entityIds:!0,scheduledFor:!0,sentAt:!0,buttondownId:!0,sourceEntityType:!0}).extend({error:K.string().optional()}),zo=o1.extend({entityType:K.literal("newsletter"),metadata:Ls1});c0();class Ns1 extends I2{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:zo,frontmatterSchema:Go})}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 js1=new Ns1;c0();c0();Z0();var qZw=qU.extend({status:K.enum(["generating","draft","queued","published","failed"]).optional()}),FZw=FU.extend({query:qZw.optional()});function Ms1(A){try{let{content:Q}=v2(A.content,Go);return Q}catch{return A.content}}class Vn0 extends W${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=FZw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=Ms1(A),w={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:r7(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,D=f?{filter:{metadata:{status:f}}}:void 0,{items:Y,pagination:X}=await this.fetchList(B,$,D);return Q.parse(this.buildListResult(Y,X,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 X=B.metadata.sourceEntityType??"post";f=(await Promise.all(B.metadata.entityIds.map(async(W)=>{let Z=await w.getEntity({entityType:X,id:W});if(Z){let G=Z.metadata;return{id:W,title:G.title??W,url:`/${X}s/${G.slug??W}`}}return null}))).filter((W)=>W!==null)}let D=Ms1(B),Y={id:B.id,subject:B.metadata.subject,status:B.metadata.status,content:D,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(Y)}}c0();Z0();var VZw=K.object({prompt:K.string().optional().describe("AI generation prompt"),sourceEntityIds:K.array(K.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:K.enum(["post"]).optional().describe("Type of source entities"),content:K.string().optional().describe("Direct content (skip AI)"),subject:K.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:K.boolean().optional().describe("Create as queued (true) or draft (false)")});class In0 extends Q4{constructor(A,Q){super(A,Q,{schema:VZw,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let w=A.addToQueue??!1,{prompt:B,sourceEntityIds:$,sourceEntityType:f}=A,{content:D,subject:Y}=A;if(D){if(!Y)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if($&&$.length>0){let G=f??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${$.length} source entities`});let V=(await Promise.all($.map((j)=>this.context.entityService.getEntity({entityType:G,id:j})))).filter((j)=>j!=null);if(V.length===0)this.failEarly(`No source entities found for IDs: ${$.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${V.length} posts`});let L=`Create an engaging newsletter that highlights these blog posts:
8204
+ ${wZw(Lw(YZw,{input:A},void 0,!1,void 0,this))}`}function Js1(A,Q){let w={},B=new Set;for(let[$,f]of Object.entries(A)){let D=Q?.get(f.widget.pluginId,f.widget.id);if(w[$]={...f,...D?.component?{component:D.component}:{}},D?.clientScript)B.add(D.clientScript)}return{widgets:w,widgetScripts:Array.from(B)}}var bs1={name:"@brains/dashboard",private:!0,version:"0.2.0-alpha.134",description:"Dashboard plugin with extensible widget system",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts,.tsx","lint:fix":"eslint . --ext .ts,.tsx --fix"},dependencies:{"@brains/auth-service":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2","preact-render-to-string":"^6.3.1"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var HZw=K.object({version:K.string().default("1.0.0"),routePath:K.string().default("/dashboard"),themeCSS:K.string().optional()}),WZw=K.object({id:K.string(),pluginId:K.string(),title:K.string(),description:K.string().optional(),priority:K.number().default(50),section:K.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:K.string(),visibility:s4.default("public"),component:K.custom().optional(),clientScript:K.string().optional(),dataProvider:K.function().returns(K.promise(K.unknown()))}).superRefine((A,Q)=>{if(!Gn0(A.rendererName)&&!A.component)Q.addIssue({code:K.ZodIssueCode.custom,message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),ZZw=K.object({pluginId:K.string(),widgetId:K.string().optional()});function KZw(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 Fn0 extends RQ{widgetRegistry=null;datasource=null;siteUrl;ctx;constructor(A){super("dashboard",bs1,A??{},HZw)}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new HD0(this.logger),this.datasource=new WD0(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=WZw.parse(Q.payload),B=KZw(w);return this.widgetRegistry?.register(B),this.logger.debug("Widget registered via messaging",{widgetId:w.id,pluginId:w.pluginId,rendererName:w.rendererName,builtIn:XD0.includes(w.rendererName)}),{success:!0}}catch(w){return this.logger.error("Failed to register widget",{error:vA(w),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{let w=ZZw.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}}),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 gH()?.getOperatorSession(A),B=Boolean(w),$=B?"anchor":"public",f=this.widgetRegistry?.list({permissionLevel:"anchor"})??[],D=f.filter((g)=>m$.hasPermission($,g.visibility)),Y=f.length-D.length,[X,H]=await Promise.all([this.datasource.getDashboardData({permissionLevel:$,widgets:D}),Q.appInfo()]),W=Q.identity.get(),Z=Q.identity.getProfile(),G=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),F={...H,endpoints:H.endpoints.filter((g)=>m$.hasPermission($,g.visibility)),interactions:H.interactions.filter((g)=>m$.hasPermission($,g.visibility))},V=Z.name||H.model||"Brain Dashboard",b=new URL(A.url),L=`${b.pathname}${b.search}`,N=encodeURIComponent(L),_=Js1(X.widgets,this.widgetRegistry),j={title:V,baseUrl:G,widgets:_.widgets,widgetScripts:_.widgetScripts,character:W,profile:Z,appInfo:F,...this.config.themeCSS!==void 0&&{themeCSS:this.config.themeCSS},operatorAccess:{isOperator:B,hiddenWidgetCount:Y,loginUrl:`/login?return_to=${N}`,logoutUrl:`/logout?return_to=${N}`}};return new Response(Is1(j),{headers:{"Content-Type":"text/html; charset=utf-8"}})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function yb(A){return new Fn0(A)}c0();Z0();var UZw=K.object({id:K.string(),pluginId:K.string(),title:K.string(),description:K.string().optional(),priority:K.number(),section:K.enum(["primary","secondary","sidebar"]),rendererName:K.string(),visibility:s4,component:K.custom().optional()}),GZw=K.object({widget:UZw,data:K.unknown()}),zZw=K.object({widgets:K.record(GZw)});Z0();c0();Z0();import{h as OZw}from"preact";Z0();bY();c0();var ME=K.enum(["generating","draft","queued","published","failed"]),Go=K.object({subject:K.string(),status:ME,entityIds:K.array(K.string()).optional(),scheduledFor:K.string().datetime().optional(),sentAt:K.string().datetime().optional(),buttondownId:K.string().optional(),sourceEntityType:K.string().optional()}),Ls1=Go.pick({subject:!0,status:!0,entityIds:!0,scheduledFor:!0,sentAt:!0,buttondownId:!0,sourceEntityType:!0}).extend({error:K.string().optional()}),zo=o1.extend({entityType:K.literal("newsletter"),metadata:Ls1});c0();class Ns1 extends I2{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:zo,frontmatterSchema:Go})}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 js1=new Ns1;c0();c0();Z0();var qZw=qU.extend({status:K.enum(["generating","draft","queued","published","failed"]).optional()}),FZw=FU.extend({query:qZw.optional()});function Ms1(A){try{let{content:Q}=v2(A.content,Go);return Q}catch{return A.content}}class Vn0 extends W${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=FZw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=Ms1(A),w={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:r7(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,D=f?{filter:{metadata:{status:f}}}:void 0,{items:Y,pagination:X}=await this.fetchList(B,$,D);return Q.parse(this.buildListResult(Y,X,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 X=B.metadata.sourceEntityType??"post";f=(await Promise.all(B.metadata.entityIds.map(async(W)=>{let Z=await w.getEntity({entityType:X,id:W});if(Z){let G=Z.metadata;return{id:W,title:G.title??W,url:`/${X}s/${G.slug??W}`}}return null}))).filter((W)=>W!==null)}let D=Ms1(B),Y={id:B.id,subject:B.metadata.subject,status:B.metadata.status,content:D,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(Y)}}c0();Z0();var VZw=K.object({prompt:K.string().optional().describe("AI generation prompt"),sourceEntityIds:K.array(K.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:K.enum(["post"]).optional().describe("Type of source entities"),content:K.string().optional().describe("Direct content (skip AI)"),subject:K.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:K.boolean().optional().describe("Create as queued (true) or draft (false)")});class In0 extends Q4{constructor(A,Q){super(A,Q,{schema:VZw,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let w=A.addToQueue??!1,{prompt:B,sourceEntityIds:$,sourceEntityType:f}=A,{content:D,subject:Y}=A;if(D){if(!Y)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if($&&$.length>0){let G=f??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${$.length} source entities`});let V=(await Promise.all($.map((j)=>this.context.entityService.getEntity({entityType:G,id:j})))).filter((j)=>j!=null);if(V.length===0)this.failEarly(`No source entities found for IDs: ${$.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${V.length} posts`});let L=`Create an engaging newsletter that highlights these blog posts:
8205
8205
 
8206
8206
  ${V.map((j)=>`## ${j.metadata.title}
8207
8207
 
@@ -8270,17 +8270,17 @@ Newsletter-specific guidelines:
8270
8270
  - "Reply and let me know..."
8271
8271
  - "Until next time..."
8272
8272
 
8273
- The goal is to build a relationship with readers through valuable, authentic content.`});Z0();c0();import{jsxDEV as hf,Fragment as NZw}from"preact/jsx-dev-runtime";var JZw=K.object({id:K.string(),subject:K.string(),status:ME,excerpt:K.string(),created:K.string(),sentAt:K.string().optional(),url:K.string()}),bZw=K.object({newsletters:K.array(JZw),totalCount:K.number(),pagination:e7.nullable()}),LZw=({newsletters:A,totalCount:Q,pageTitle:w,pagination:B,baseUrl:$="/newsletters"})=>{let f=w??"Newsletters",D=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return hf(NZw,{children:[hf(NQ,{title:f,description:D},void 0,!1,void 0,this),hf("div",{className:"newsletter-list bg-theme",children:hf("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[hf("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:f},void 0,!1,void 0,this),A.length===0?hf("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):hf("div",{className:"space-y-4",children:A.map((Y)=>hf(uw,{href:Y.url,children:[hf(d9,{className:"text-lg",children:Y.subject},void 0,!1,void 0,this),hf(N7,{children:hf("div",{className:"flex items-center gap-3",children:[hf(CD,{status:Y.status},void 0,!1,void 0,this),hf("span",{className:"text-sm text-theme-muted",children:Z5(Y.sentAt??Y.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Y.excerpt&&hf("p",{className:"text-theme-muted line-clamp-2",children:Y.excerpt},void 0,!1,void 0,this)]},Y.id,!0,void 0,this))},void 0,!1,void 0,this),B&&B.totalPages>1&&hf(d3,{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)},Ps1=R1({name:"newsletter-list",description:"Newsletter list page template",schema:bZw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:LZw}});Z0();c0();import{jsxDEV as y8,Fragment as PZw}from"preact/jsx-dev-runtime";var jZw=K.object({id:K.string(),title:K.string(),url:K.string()}),ks1=K.object({id:K.string(),subject:K.string(),url:K.string()}),MZw=K.object({id:K.string(),subject:K.string(),status:ME,content:K.string(),created:K.string(),updated:K.string(),sentAt:K.string().optional(),scheduledFor:K.string().optional(),sourceEntities:K.array(jZw).optional(),prevNewsletter:ks1.nullable().optional(),nextNewsletter:ks1.nullable().optional()}),_Zw=({subject:A,status:Q,content:w,created:B,sentAt:$,scheduledFor:f,sourceEntities:D,prevNewsletter:Y,nextNewsletter:X})=>{let H=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],W=$??B,Z=$?"Sent":"Created";return y8(PZw,{children:[y8(NQ,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),y8("section",{className:"newsletter-detail-section",children:y8("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:y8("div",{className:"max-w-3xl mx-auto",children:[y8(_G,{items:H},void 0,!1,void 0,this),y8("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),y8("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[y8(CD,{status:Q},void 0,!1,void 0,this),y8("span",{children:[Z,": ",Z5(W,{style:"long"})]},void 0,!0,void 0,this),f&&Q==="queued"&&y8("span",{children:["Scheduled for: ",Z5(f,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D&&D.length>0&&y8(uw,{variant:"compact",className:"mb-8",children:[y8("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),y8("ul",{className:"space-y-1",children:D.map((G)=>y8("li",{children:y8("a",{href:G.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:G.title},void 0,!1,void 0,this)},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y8($9,{markdown:w},void 0,!1,void 0,this),(Y??X)&&y8("nav",{className:"mt-12 pt-8 border-t border-theme",children:y8("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[Y?y8(uw,{href:Y.url,variant:"compact",children:[y8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),y8("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:Y.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this):y8("div",{},void 0,!1,void 0,this),X&&y8(uw,{href:X.url,variant:"compact",className:"md:text-right",children:[y8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),y8("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)]},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)},Os1=R1({name:"newsletter-detail",description:"Individual newsletter detail template",schema:MZw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:_Zw}});var xs1={name:"@brains/newsletter-entity",private:!0,version:"0.2.0-alpha.133",description:"Newsletter entity type with AI generation and publish pipeline",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts,.tsx","lint:fix":"eslint src test --ext .ts,.tsx --fix"},dependencies:{"@brains/contracts":"workspace:*","@brains/entity-service":"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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var xZw=K.object({});class Jn0 extends PQ{entityType="newsletter";schema=zo;adapter=js1;constructor(A={}){super("newsletter",xs1,A,xZw)}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}createGenerationHandler(A){return new In0(this.logger,A)}getTemplates(){return{generation:_s1,"newsletter-list":Ps1,"newsletter-detail":Os1}}getDataSources(){return[new Vn0(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(ru0,{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:vA(w)}}),{success:!0}}})}registerEvalHandlers(A){let Q=K.object({prompt:K.string().optional(),content:K.string().optional()});A.eval.registerHandler("generation",async(w)=>{let B=Q.parse(w),$=B.content?`Create an engaging newsletter based on this content:
8273
+ The goal is to build a relationship with readers through valuable, authentic content.`});Z0();c0();import{jsxDEV as hf,Fragment as NZw}from"preact/jsx-dev-runtime";var JZw=K.object({id:K.string(),subject:K.string(),status:ME,excerpt:K.string(),created:K.string(),sentAt:K.string().optional(),url:K.string()}),bZw=K.object({newsletters:K.array(JZw),totalCount:K.number(),pagination:e7.nullable()}),LZw=({newsletters:A,totalCount:Q,pageTitle:w,pagination:B,baseUrl:$="/newsletters"})=>{let f=w??"Newsletters",D=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return hf(NZw,{children:[hf(NQ,{title:f,description:D},void 0,!1,void 0,this),hf("div",{className:"newsletter-list bg-theme",children:hf("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[hf("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:f},void 0,!1,void 0,this),A.length===0?hf("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):hf("div",{className:"space-y-4",children:A.map((Y)=>hf(uw,{href:Y.url,children:[hf(d9,{className:"text-lg",children:Y.subject},void 0,!1,void 0,this),hf(N7,{children:hf("div",{className:"flex items-center gap-3",children:[hf(CD,{status:Y.status},void 0,!1,void 0,this),hf("span",{className:"text-sm text-theme-muted",children:Z5(Y.sentAt??Y.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Y.excerpt&&hf("p",{className:"text-theme-muted line-clamp-2",children:Y.excerpt},void 0,!1,void 0,this)]},Y.id,!0,void 0,this))},void 0,!1,void 0,this),B&&B.totalPages>1&&hf(d3,{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)},Ps1=R1({name:"newsletter-list",description:"Newsletter list page template",schema:bZw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:LZw}});Z0();c0();import{jsxDEV as y8,Fragment as PZw}from"preact/jsx-dev-runtime";var jZw=K.object({id:K.string(),title:K.string(),url:K.string()}),ks1=K.object({id:K.string(),subject:K.string(),url:K.string()}),MZw=K.object({id:K.string(),subject:K.string(),status:ME,content:K.string(),created:K.string(),updated:K.string(),sentAt:K.string().optional(),scheduledFor:K.string().optional(),sourceEntities:K.array(jZw).optional(),prevNewsletter:ks1.nullable().optional(),nextNewsletter:ks1.nullable().optional()}),_Zw=({subject:A,status:Q,content:w,created:B,sentAt:$,scheduledFor:f,sourceEntities:D,prevNewsletter:Y,nextNewsletter:X})=>{let H=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],W=$??B,Z=$?"Sent":"Created";return y8(PZw,{children:[y8(NQ,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),y8("section",{className:"newsletter-detail-section",children:y8("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:y8("div",{className:"max-w-3xl mx-auto",children:[y8(_G,{items:H},void 0,!1,void 0,this),y8("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),y8("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[y8(CD,{status:Q},void 0,!1,void 0,this),y8("span",{children:[Z,": ",Z5(W,{style:"long"})]},void 0,!0,void 0,this),f&&Q==="queued"&&y8("span",{children:["Scheduled for: ",Z5(f,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D&&D.length>0&&y8(uw,{variant:"compact",className:"mb-8",children:[y8("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),y8("ul",{className:"space-y-1",children:D.map((G)=>y8("li",{children:y8("a",{href:G.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:G.title},void 0,!1,void 0,this)},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y8($9,{markdown:w},void 0,!1,void 0,this),(Y??X)&&y8("nav",{className:"mt-12 pt-8 border-t border-theme",children:y8("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[Y?y8(uw,{href:Y.url,variant:"compact",children:[y8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),y8("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:Y.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this):y8("div",{},void 0,!1,void 0,this),X&&y8(uw,{href:X.url,variant:"compact",className:"md:text-right",children:[y8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),y8("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)]},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)},Os1=R1({name:"newsletter-detail",description:"Individual newsletter detail template",schema:MZw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:_Zw}});var xs1={name:"@brains/newsletter-entity",private:!0,version:"0.2.0-alpha.134",description:"Newsletter entity type with AI generation and publish pipeline",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts,.tsx","lint:fix":"eslint src test --ext .ts,.tsx --fix"},dependencies:{"@brains/contracts":"workspace:*","@brains/entity-service":"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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var xZw=K.object({});class Jn0 extends PQ{entityType="newsletter";schema=zo;adapter=js1;constructor(A={}){super("newsletter",xs1,A,xZw)}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}createGenerationHandler(A){return new In0(this.logger,A)}getTemplates(){return{generation:_s1,"newsletter-list":Ps1,"newsletter-detail":Os1}}getDataSources(){return[new Vn0(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(ru0,{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:vA(w)}}),{success:!0}}})}registerEvalHandlers(A){let Q=K.object({prompt:K.string().optional(),content:K.string().optional()});A.eval.registerHandler("generation",async(w)=>{let B=Q.parse(w),$=B.content?`Create an engaging newsletter based on this content:
8274
8274
 
8275
- ${B.content}`:B.prompt??"Write an engaging newsletter";return A.ai.generate({prompt:$,templateName:"newsletter:generation"})})}}function bn0(A={}){return new Jn0(A)}c0();Z0();class _E{config;logger;constructor(A,Q){this.config=A;this.logger=Q}async request(A,Q={}){let w=`https://api.buttondown.email/v1${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=$.detail??$.message??`HTTP ${B.status}`;throw this.logger.error("Buttondown API error",{endpoint:A,status:B.status,error:f}),Error(`Buttondown API error: ${f}`)}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 await this.request("/subscribers",{method:"POST",body:JSON.stringify(Q)})}catch(w){if(w instanceof Error&&w.message.includes("already subscribed")){let B=w.message.match(/id=([a-f0-9-]+)/);return this.logger.info("Subscriber already exists",{email:A.email}),{id:B?.[1]??"existing",email:A.email,subscriber_type:"already_subscribed"}}throw w}}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 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"}),this.request("/emails",{method:"POST",body:JSON.stringify(Q)})}async getEmail(A){return this.request(`/emails/${A}`)}async validateCredentials(){try{return await this.request("/subscribers?page_size=1"),!0}catch{return!1}}}c0();Z0();var RZw=K.object({email:K.string().email().describe("Email address to subscribe"),name:K.string().optional().describe("Subscriber name (optional)"),tags:K.array(K.string()).optional().describe("Tags to apply to subscriber (optional)")}),hZw=K.object({email:K.string().email().describe("Email address to unsubscribe")}),vZw=K.object({type:K.enum(["unactivated","regular","unsubscribed"]).optional().describe("Filter by subscriber status"),limit:K.number().optional().describe("Maximum number of results")});function Rs1(A,Q,w){let B=new _E(Q,w);return[Sw(A,"subscribe","Subscribe an email address to the newsletter. Uses double opt-in by default.",RZw,async($)=>{try{let f=await B.createSubscriber({email:$.email,...$.name&&{name:$.name},...$.tags&&{tags:$.tags}}),D=f.subscriber_type==="already_subscribed";return l8({subscriberId:f.id,email:f.email,status:f.subscriber_type,message:D?"already_subscribed":"subscribed"},D?`${$.email} is already subscribed`:`Subscribed ${$.email} successfully`)}catch(f){return P9(vA(f))}}),Sw(A,"unsubscribe","Unsubscribe an email address from the newsletter.",hZw,async($)=>{try{return await B.unsubscribe($.email),l8({email:$.email},`Unsubscribed ${$.email} successfully`)}catch(f){return P9(vA(f))}}),Sw(A,"list_subscribers","List newsletter subscribers with optional filtering by status.",vZw,async($)=>{try{let f=await B.listSubscribers({...$.type&&{type:$.type},...$.limit&&{limit:$.limit}});return l8({subscribers:f.results.map((D)=>({id:D.id,email:D.email,status:D.subscriber_type})),count:f.count},`Found ${f.count} subscribers`)}catch(f){return P9(vA(f))}})]}Z0();async function hs1(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 D=vA(f);return B.error("Failed to send newsletter for post",{postId:$.id,error:D}),{success:!1,error:D}}}var vs1={name:"@brains/buttondown",private:!0,version:"0.2.0-alpha.133",description:"Buttondown newsletter integration \u2014 subscriber management and API routes",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var yZw=K.object({apiKey:K.string().optional().describe("Buttondown API key"),doubleOptIn:K.boolean().default(!0).describe("Require email confirmation for new subscribers"),autoSendOnPublish:K.boolean().default(!1).describe("Automatically send newsletter when a blog post is published")});class Ln0 extends RQ{constructor(A={}){super("buttondown",vs1,A,yZw)}async onRegister(A){if(A.messaging.subscribe("buttondown:is-configured",async()=>{return{success:!!this.config.apiKey}}),this.config.apiKey){let Q=new _E({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:vA(B)}),{success:!1}}}),this.config.autoSendOnPublish)A.messaging.subscribe("publish:completed",async(w)=>{return await hs1(w.payload,Q,A.entityService,this.logger),{success:!0}}),this.logger.info("Buttondown auto-send on publish enabled")}}async getTools(){if(!this.config.apiKey)return[];return Rs1(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 Nn0(A={}){return new Ln0(A)}var EZw=K.object({apiKey:K.string().optional().describe("Buttondown API key"),doubleOptIn:K.boolean().optional().describe("Require email confirmation for new subscribers"),autoSendOnPublish:K.boolean().optional().describe("Automatically send newsletter when a blog post is published")});function Cs1(A={}){let Q=EZw.parse(A);return[bn0({}),Nn0({...Q.apiKey!==void 0&&{apiKey:Q.apiKey},...Q.doubleOptIn!==void 0&&{doubleOptIn:Q.doubleOptIn},...Q.autoSendOnPublish!==void 0&&{autoSendOnPublish:Q.autoSendOnPublish}})]}c0();Z0();import{existsSync as rZw,mkdirSync as oZw,writeFileSync as sZw}from"fs";import{join as VF}from"path";Z0();var jn0=K.object({baseFolder:K.string().default("_obsidian")});Z0();function gZw(A){let Q=A,w=!0,B=void 0,$=!1,f=!0;while(f){if(f=!1,Q instanceof K.ZodOptional)w=!1,Q=Q._def.innerType,f=!0;if(Q instanceof K.ZodDefault)w=!1,$=!0,B=Q._def.defaultValue(),Q=Q._def.innerType,f=!0;if(Q instanceof K.ZodNullable)w=!1,Q=Q._def.innerType,f=!0}let D={inner:Q,required:w};if($)D.defaultValue=B;return D}function TZw(A){if(A instanceof K.ZodEnum)return{type:"enum",enumValues:A._def.values};if(A instanceof K.ZodLiteral)return{type:"string",defaultValue:A._def.value};if(A instanceof K.ZodString)return{type:"string"};if(A instanceof K.ZodNumber)return{type:"number"};if(A instanceof K.ZodBoolean)return{type:"boolean"};if(A instanceof K.ZodArray)return{type:"array"};if(A instanceof K.ZodDate)return{type:"date"};if(A instanceof K.ZodPipeline){if(A._def.out instanceof K.ZodDate)return{type:"date"}}return{type:"unknown"}}function ys1(A){let Q=A.shape,w=[];for(let[B,$]of Object.entries(Q)){let{inner:f,required:D,defaultValue:Y}=gZw($),X=TZw(f),H={name:B,type:X.type,required:D},W=Y!==void 0?Y:X.defaultValue;if(W!==void 0)H.defaultValue=W;if(X.enumValues)H.enumValues=X.enumValues;w.push(H)}return w}function SZw(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 Es1(A,Q,w=""){let B=["---"];for(let $ of Q){let f=SZw($,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(`
8275
+ ${B.content}`:B.prompt??"Write an engaging newsletter";return A.ai.generate({prompt:$,templateName:"newsletter:generation"})})}}function bn0(A={}){return new Jn0(A)}c0();Z0();class _E{config;logger;constructor(A,Q){this.config=A;this.logger=Q}async request(A,Q={}){let w=`https://api.buttondown.email/v1${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=$.detail??$.message??`HTTP ${B.status}`;throw this.logger.error("Buttondown API error",{endpoint:A,status:B.status,error:f}),Error(`Buttondown API error: ${f}`)}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 await this.request("/subscribers",{method:"POST",body:JSON.stringify(Q)})}catch(w){if(w instanceof Error&&w.message.includes("already subscribed")){let B=w.message.match(/id=([a-f0-9-]+)/);return this.logger.info("Subscriber already exists",{email:A.email}),{id:B?.[1]??"existing",email:A.email,subscriber_type:"already_subscribed"}}throw w}}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 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"}),this.request("/emails",{method:"POST",body:JSON.stringify(Q)})}async getEmail(A){return this.request(`/emails/${A}`)}async validateCredentials(){try{return await this.request("/subscribers?page_size=1"),!0}catch{return!1}}}c0();Z0();var RZw=K.object({email:K.string().email().describe("Email address to subscribe"),name:K.string().optional().describe("Subscriber name (optional)"),tags:K.array(K.string()).optional().describe("Tags to apply to subscriber (optional)")}),hZw=K.object({email:K.string().email().describe("Email address to unsubscribe")}),vZw=K.object({type:K.enum(["unactivated","regular","unsubscribed"]).optional().describe("Filter by subscriber status"),limit:K.number().optional().describe("Maximum number of results")});function Rs1(A,Q,w){let B=new _E(Q,w);return[Sw(A,"subscribe","Subscribe an email address to the newsletter. Uses double opt-in by default.",RZw,async($)=>{try{let f=await B.createSubscriber({email:$.email,...$.name&&{name:$.name},...$.tags&&{tags:$.tags}}),D=f.subscriber_type==="already_subscribed";return l8({subscriberId:f.id,email:f.email,status:f.subscriber_type,message:D?"already_subscribed":"subscribed"},D?`${$.email} is already subscribed`:`Subscribed ${$.email} successfully`)}catch(f){return P9(vA(f))}}),Sw(A,"unsubscribe","Unsubscribe an email address from the newsletter.",hZw,async($)=>{try{return await B.unsubscribe($.email),l8({email:$.email},`Unsubscribed ${$.email} successfully`)}catch(f){return P9(vA(f))}}),Sw(A,"list_subscribers","List newsletter subscribers with optional filtering by status.",vZw,async($)=>{try{let f=await B.listSubscribers({...$.type&&{type:$.type},...$.limit&&{limit:$.limit}});return l8({subscribers:f.results.map((D)=>({id:D.id,email:D.email,status:D.subscriber_type})),count:f.count},`Found ${f.count} subscribers`)}catch(f){return P9(vA(f))}})]}Z0();async function hs1(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 D=vA(f);return B.error("Failed to send newsletter for post",{postId:$.id,error:D}),{success:!1,error:D}}}var vs1={name:"@brains/buttondown",private:!0,version:"0.2.0-alpha.134",description:"Buttondown newsletter integration \u2014 subscriber management and API routes",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var yZw=K.object({apiKey:K.string().optional().describe("Buttondown API key"),doubleOptIn:K.boolean().default(!0).describe("Require email confirmation for new subscribers"),autoSendOnPublish:K.boolean().default(!1).describe("Automatically send newsletter when a blog post is published")});class Ln0 extends RQ{constructor(A={}){super("buttondown",vs1,A,yZw)}async onRegister(A){if(A.messaging.subscribe("buttondown:is-configured",async()=>{return{success:!!this.config.apiKey}}),this.config.apiKey){let Q=new _E({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:vA(B)}),{success:!1}}}),this.config.autoSendOnPublish)A.messaging.subscribe("publish:completed",async(w)=>{return await hs1(w.payload,Q,A.entityService,this.logger),{success:!0}}),this.logger.info("Buttondown auto-send on publish enabled")}}async getTools(){if(!this.config.apiKey)return[];return Rs1(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 Nn0(A={}){return new Ln0(A)}var EZw=K.object({apiKey:K.string().optional().describe("Buttondown API key"),doubleOptIn:K.boolean().optional().describe("Require email confirmation for new subscribers"),autoSendOnPublish:K.boolean().optional().describe("Automatically send newsletter when a blog post is published")});function Cs1(A={}){let Q=EZw.parse(A);return[bn0({}),Nn0({...Q.apiKey!==void 0&&{apiKey:Q.apiKey},...Q.doubleOptIn!==void 0&&{doubleOptIn:Q.doubleOptIn},...Q.autoSendOnPublish!==void 0&&{autoSendOnPublish:Q.autoSendOnPublish}})]}c0();Z0();import{existsSync as rZw,mkdirSync as oZw,writeFileSync as sZw}from"fs";import{join as VF}from"path";Z0();var jn0=K.object({baseFolder:K.string().default("_obsidian")});Z0();function gZw(A){let Q=A,w=!0,B=void 0,$=!1,f=!0;while(f){if(f=!1,Q instanceof K.ZodOptional)w=!1,Q=Q._def.innerType,f=!0;if(Q instanceof K.ZodDefault)w=!1,$=!0,B=Q._def.defaultValue(),Q=Q._def.innerType,f=!0;if(Q instanceof K.ZodNullable)w=!1,Q=Q._def.innerType,f=!0}let D={inner:Q,required:w};if($)D.defaultValue=B;return D}function TZw(A){if(A instanceof K.ZodEnum)return{type:"enum",enumValues:A._def.values};if(A instanceof K.ZodLiteral)return{type:"string",defaultValue:A._def.value};if(A instanceof K.ZodString)return{type:"string"};if(A instanceof K.ZodNumber)return{type:"number"};if(A instanceof K.ZodBoolean)return{type:"boolean"};if(A instanceof K.ZodArray)return{type:"array"};if(A instanceof K.ZodDate)return{type:"date"};if(A instanceof K.ZodPipeline){if(A._def.out instanceof K.ZodDate)return{type:"date"}}return{type:"unknown"}}function ys1(A){let Q=A.shape,w=[];for(let[B,$]of Object.entries(Q)){let{inner:f,required:D,defaultValue:Y}=gZw($),X=TZw(f),H={name:B,type:X.type,required:D},W=Y!==void 0?Y:X.defaultValue;if(W!==void 0)H.defaultValue=W;if(X.enumValues)H.enumValues=X.enumValues;w.push(H)}return w}function SZw(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 Es1(A,Q,w=""){let B=["---"];for(let $ of Q){let f=SZw($,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(`
8276
8276
  `)}Z0();var mZw={string:"Input",number:"Number",boolean:"Boolean",date:"Date",enum:"Select",array:"Multi",unknown:"Input"};function uZw(A){let Q={name:A.name,id:A.name,type:mZw[A.type]};if(A.type==="enum"&&A.enumValues){let w={};A.enumValues.forEach((B,$)=>{w[String($)]=B}),Q.options=w}return Q}function gs1(A,Q){let w={filesPaths:A,fields:Q.map(uZw)};return`---
8277
8277
  ${$U(w)}---
8278
- `}Z0();var cZw=new Set(["entityType"]),lZw={base:"Notes"},pZw=new Set(["note"]);function iZw(A){let Q=["file.name"];for(let w of A)if(!cZw.has(w.name))Q.push(w.name);return Q}function dZw(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function Ts1(A,Q){let w=lZw[A]??It(A),B=dZw(Q),$=iZw(Q),f=[{type:"table",name:`All ${w}`,order:$}];if(B)f.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:$});let Y={filters:{and:[pZw.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:f};return{filename:`${w}.base`,content:$U(Y),hasStatus:B}}function Ss1(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 $U(w)}function ms1(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 $U(w)}var us1={name:"@brains/obsidian-vault",private:!0,version:"0.2.0-alpha.133",description:"Obsidian vault integration \u2014 generates templates from entity schemas",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var aZw={mkdir:oZw,writeFile:sZw,existsFile:rZw},tZw=K.object({entityTypes:K.array(K.string()).optional().describe("Entity types to generate templates for (default: all)")});class Mn0 extends RQ{deps;constructor(A={},Q={}){super("obsidian-vault",us1,A,jn0);this.deps={...aZw,...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[Sw(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",tZw,async(Q)=>{return this.sync(A,Q.entityTypes)},{sideEffects:"external"})]}async sync(A,Q){try{let w=A.entityService.getEntityTypes(),B=Q?w.filter((L)=>Q.includes(L)):w,$=VF(A.dataDir,this.config.baseFolder),f=VF($,"templates"),D=VF($,"fileClasses"),Y=VF($,"bases");this.deps.mkdir(f,{recursive:!0}),this.deps.mkdir(D,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0});let X=[],H=[],W=[],Z=[],G=[],F=[];for(let L of B){let N=A.entities.getEffectiveFrontmatterSchema(L);if(!N){this.logger.debug(`Skipping ${L}: no frontmatter schema`),H.push(L);continue}let _=ys1(N),j=A.entities.getAdapter(L),g=j?.isSingleton===!0,E=gs1(L,_);if(this.deps.writeFile(VF(D,`${L}.md`),E),W.push(L),g){G.push(L),this.logger.debug(`Generated fileClass (singleton): ${L}`);continue}let y=j?.getBodyTemplate()??"",h=Es1(L,_,y);this.deps.writeFile(VF(f,`${L}.md`),h),X.push(L);let T=Ts1(L,_),S=VF(Y,T.filename);if(!this.deps.existsFile(S))this.deps.writeFile(S,T.content),Z.push(L),this.logger.debug(`Generated base: ${T.filename}`);if(T.hasStatus)F.push({entityType:L,fields:_});this.logger.debug(`Generated template + fileClass: ${L}`)}let V=Ss1(G);if(V){let L=VF(Y,"Settings.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,V),Z.push("Settings"),this.logger.debug("Generated Settings.base")}let b=ms1(F);if(b){let L=VF(Y,"Pipeline.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,b),Z.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${X.length} templates, ${W.length} fileClasses, ${Z.length} bases (${H.length} skipped)`),l8({generated:X,skipped:H,fileClasses:W,bases:Z})}catch(w){return this.logger.error("Failed to sync",{error:w}),P9(w instanceof Error?w.message:"Unknown error")}}}function _n0(A,Q){return new Mn0(A,Q)}c0();c0();Z0();l$();c0();Z0();var Pn0=K.enum(["draft","active","archived"]),kn0=K.enum(["anchor","trusted","public"]),On0=K.enum(["agent-confirmed","manual"]),uD=K.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,K.string().min(1).optional()),cs1=K.object({event:K.string().min(1),target:K.string().min(1),operatorAction:K.boolean().optional(),label:uD,description:uD,operatorDescription:uD}),ls1=K.object({id:K.string().min(1),title:K.string().min(1),prompt:uD,requiredDetails:K.array(K.string().min(1)).default([]),instructions:K.array(K.string().min(1)).default([]),doneWhen:K.array(K.string().min(1)).default([]),transitions:K.array(cs1).default([])}),xn0=K.object({purpose:K.string().min(1),operatingRules:K.array(K.string().min(1)).default([]),initialState:K.string().min(1),states:K.array(ls1).min(1),finalStates:K.array(K.string().min(1)).min(1),nextPrompts:K.array(K.string().min(1)).default([])}),qo=K.object({title:K.string(),status:Pn0.default("active"),audience:kn0.default("anchor"),trigger:uD,lifecycle:uD,once:K.boolean().optional(),starterText:uD,description:uD,starterPrompt:uD,completionMode:On0.default("agent-confirmed")}),ps1=K.object({title:K.string(),status:Pn0,audience:kn0,trigger:uD,lifecycle:uD,once:K.boolean().optional(),starterText:uD,description:uD,starterPrompt:uD,completionMode:On0}),Fo=o1.extend({entityType:K.literal("playbook"),metadata:ps1}),Rn0=K.object({});class Cn0 extends pw{constructor(){super(xn0,{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:hn0,parser:vn0},{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:eZw,parser:AKw},{key:"label",label:"Label",type:"custom",formatter:hn0,parser:vn0},{key:"description",label:"Description",type:"string"},{key:"operatorDescription",label:"Operator Description",type:"custom",formatter:hn0,parser:vn0}]}]},{key:"finalStates",label:"Final States",type:"array",itemType:"string"},{key:"nextPrompts",label:"Next Prompts",type:"array",itemType:"string"}]})}}var KD0=new Cn0;function hn0(A){return typeof A==="string"?A:""}function vn0(A){let Q=A.trim();return Q.length>0?Q:void 0}function eZw(A){return typeof A==="boolean"?String(A):""}function AKw(A){let Q=A.trim().toLowerCase();if(Q==="true")return!0;if(Q==="false")return!1;return}function is1(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 QKw(A,w))Q.push(`Playbook state '${$}' is unreachable.`);return{valid:Q.length===0,errors:Q}}function Vo(A){let Q=is1(A);if(!Q.valid)throw Error(Q.errors.join(`
8278
+ `}Z0();var cZw=new Set(["entityType"]),lZw={base:"Notes"},pZw=new Set(["note"]);function iZw(A){let Q=["file.name"];for(let w of A)if(!cZw.has(w.name))Q.push(w.name);return Q}function dZw(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function Ts1(A,Q){let w=lZw[A]??It(A),B=dZw(Q),$=iZw(Q),f=[{type:"table",name:`All ${w}`,order:$}];if(B)f.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:$});let Y={filters:{and:[pZw.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:f};return{filename:`${w}.base`,content:$U(Y),hasStatus:B}}function Ss1(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 $U(w)}function ms1(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 $U(w)}var us1={name:"@brains/obsidian-vault",private:!0,version:"0.2.0-alpha.134",description:"Obsidian vault integration \u2014 generates templates from entity schemas",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var aZw={mkdir:oZw,writeFile:sZw,existsFile:rZw},tZw=K.object({entityTypes:K.array(K.string()).optional().describe("Entity types to generate templates for (default: all)")});class Mn0 extends RQ{deps;constructor(A={},Q={}){super("obsidian-vault",us1,A,jn0);this.deps={...aZw,...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[Sw(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",tZw,async(Q)=>{return this.sync(A,Q.entityTypes)},{sideEffects:"external"})]}async sync(A,Q){try{let w=A.entityService.getEntityTypes(),B=Q?w.filter((L)=>Q.includes(L)):w,$=VF(A.dataDir,this.config.baseFolder),f=VF($,"templates"),D=VF($,"fileClasses"),Y=VF($,"bases");this.deps.mkdir(f,{recursive:!0}),this.deps.mkdir(D,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0});let X=[],H=[],W=[],Z=[],G=[],F=[];for(let L of B){let N=A.entities.getEffectiveFrontmatterSchema(L);if(!N){this.logger.debug(`Skipping ${L}: no frontmatter schema`),H.push(L);continue}let _=ys1(N),j=A.entities.getAdapter(L),g=j?.isSingleton===!0,E=gs1(L,_);if(this.deps.writeFile(VF(D,`${L}.md`),E),W.push(L),g){G.push(L),this.logger.debug(`Generated fileClass (singleton): ${L}`);continue}let y=j?.getBodyTemplate()??"",h=Es1(L,_,y);this.deps.writeFile(VF(f,`${L}.md`),h),X.push(L);let T=Ts1(L,_),S=VF(Y,T.filename);if(!this.deps.existsFile(S))this.deps.writeFile(S,T.content),Z.push(L),this.logger.debug(`Generated base: ${T.filename}`);if(T.hasStatus)F.push({entityType:L,fields:_});this.logger.debug(`Generated template + fileClass: ${L}`)}let V=Ss1(G);if(V){let L=VF(Y,"Settings.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,V),Z.push("Settings"),this.logger.debug("Generated Settings.base")}let b=ms1(F);if(b){let L=VF(Y,"Pipeline.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,b),Z.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${X.length} templates, ${W.length} fileClasses, ${Z.length} bases (${H.length} skipped)`),l8({generated:X,skipped:H,fileClasses:W,bases:Z})}catch(w){return this.logger.error("Failed to sync",{error:w}),P9(w instanceof Error?w.message:"Unknown error")}}}function _n0(A,Q){return new Mn0(A,Q)}c0();c0();Z0();l$();c0();Z0();var Pn0=K.enum(["draft","active","archived"]),kn0=K.enum(["anchor","trusted","public"]),On0=K.enum(["agent-confirmed","manual"]),uD=K.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,K.string().min(1).optional()),cs1=K.object({event:K.string().min(1),target:K.string().min(1),operatorAction:K.boolean().optional(),label:uD,description:uD,operatorDescription:uD}),ls1=K.object({id:K.string().min(1),title:K.string().min(1),prompt:uD,requiredDetails:K.array(K.string().min(1)).default([]),instructions:K.array(K.string().min(1)).default([]),doneWhen:K.array(K.string().min(1)).default([]),transitions:K.array(cs1).default([])}),xn0=K.object({purpose:K.string().min(1),operatingRules:K.array(K.string().min(1)).default([]),initialState:K.string().min(1),states:K.array(ls1).min(1),finalStates:K.array(K.string().min(1)).min(1),nextPrompts:K.array(K.string().min(1)).default([])}),qo=K.object({title:K.string(),status:Pn0.default("active"),audience:kn0.default("anchor"),trigger:uD,lifecycle:uD,once:K.boolean().optional(),starterText:uD,description:uD,starterPrompt:uD,completionMode:On0.default("agent-confirmed")}),ps1=K.object({title:K.string(),status:Pn0,audience:kn0,trigger:uD,lifecycle:uD,once:K.boolean().optional(),starterText:uD,description:uD,starterPrompt:uD,completionMode:On0}),Fo=o1.extend({entityType:K.literal("playbook"),metadata:ps1}),Rn0=K.object({});class Cn0 extends pw{constructor(){super(xn0,{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:hn0,parser:vn0},{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:eZw,parser:AKw},{key:"label",label:"Label",type:"custom",formatter:hn0,parser:vn0},{key:"description",label:"Description",type:"string"},{key:"operatorDescription",label:"Operator Description",type:"custom",formatter:hn0,parser:vn0}]}]},{key:"finalStates",label:"Final States",type:"array",itemType:"string"},{key:"nextPrompts",label:"Next Prompts",type:"array",itemType:"string"}]})}}var KD0=new Cn0;function hn0(A){return typeof A==="string"?A:""}function vn0(A){let Q=A.trim();return Q.length>0?Q:void 0}function eZw(A){return typeof A==="boolean"?String(A):""}function AKw(A){let Q=A.trim().toLowerCase();if(Q==="true")return!0;if(Q==="false")return!1;return}function is1(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 QKw(A,w))Q.push(`Playbook state '${$}' is unreachable.`);return{valid:Q.length===0,errors:Q}}function Vo(A){let Q=is1(A);if(!Q.valid)throw Error(Q.errors.join(`
8279
8279
  `))}function QKw(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((D)=>D.id===$);if(!f)continue;for(let D of f.transitions)if(Q.has(D.target)&&!w.has(D.target))B.push(D.target)}return A.states.map(($)=>$.id).filter(($)=>!w.has($))}class yn0 extends I2{constructor(){super({entityType:"playbook",purpose:"A guided multi-step workflow the assistant runs together with the user.",schema:Fo,frontmatterSchema:qo})}createPlaybookContent(A,Q){return this.buildMarkdown(KD0.format(Q),A)}parsePlaybookContent(A){let Q=this.parseFrontMatter(A,qo),w=this.extractBody(A).trim(),B=wKw(w)?BKw(w):KD0.parse(w);return Vo(B),{frontmatter:qo.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 xP=new yn0;function wKw(A){return/^##\s+Steps\s*$/im.test(A)}function BKw(A){let Q=$Kw(En0(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((D,Y)=>({event:`CHOICE_${Y+1}`,target:w1(D.target),operatorAction:!0,label:D.label})),...B.skip?[{event:"SKIP",target:w1(B.skip.target),operatorAction:!0,label:B.skip.label}]:[]]}});return{purpose:fKw(A,"Purpose"),operatingRules:ds1(A,"Operating Rules"),initialState:Q[0]?.id??"",states:w,finalStates:[Q.at(-1)?.id??""],nextPrompts:ds1(A,"Next Prompts")}}function $Kw(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(`
8280
8280
  `);return{title:B.title,id:w1(B.title),...ns1($,"Say")?{prompt:ns1($,"Say")}:{},requiredDetails:UD0($,"Required details"),instructions:UD0($,"To do"),doneWhen:UD0($,"Done when"),choices:DKw($,"Choices"),...rs1($)?{skip:rs1($)}:{}}})}function En0(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(`
8281
8281
  `).trim()}function fKw(A,Q){return En0(A,Q).split(/\r?\n/).map((w)=>w.trim()).filter((w)=>w.length>0&&!w.startsWith("#")).join(`
8282
8282
  `).trim()}function ds1(A,Q){return os1(En0(A,Q))}function ns1(A,Q){return new RegExp(`^${XKw(Q)}:\\s*(.+?)\\s*$`,"im").exec(A)?.[1]?.trim()}function UD0(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 D=f.trim();if(D.length===0)continue;if(/^[A-Za-z][A-Za-z ]+:/.test(D)||/^#{1,6}\s+/.test(D))break;$.push(f)}return os1($.join(`
8283
- `))}function DKw(A,Q){return UD0(A,Q).map(YKw)}function YKw(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 rs1(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 os1(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function XKw(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ss1={name:"@brains/playbook",private:!0,version:"0.2.0-alpha.133",description:"Playbook entity for durable guided agent workflows",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/content-formatters":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class as1 extends PQ{entityType=xP.entityType;schema=Fo;adapter=xP;constructor(A={}){super("playbook",ss1,A,Rn0)}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 ts1(A={}){return new as1(A)}CB();c0();Z0();bY();J10();var es1={name:"@brains/playbooks",private:!0,version:"0.2.0-alpha.133",description:"Runtime orchestration for chat-native playbook runs",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},dependencies:{"@brains/contracts":"workspace:*","@brains/playbook":"workspace:*","@brains/plugins":"workspace:*","@brains/runtime-state":"workspace:*","@brains/utils":"workspace:*",xstate:"^5.28.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};Z0();var Qa1=K.enum(["offered","active","completed","dismissed"]),GD0=K.object({id:K.string().min(1),kind:K.enum(["entity_event"]),stateId:K.string().min(1).optional(),observedAt:K.string().datetime(),data:K.record(K.string(),K.unknown())}).strict(),wa1=K.object({stateId:K.string().min(1),goal:K.array(K.string().min(1)),met:K.boolean(),reason:K.string().min(1),evaluatedAt:K.string().datetime()}).strict(),RP=K.object({id:K.string().min(1),playbookId:K.string().min(1),playbookVersion:K.string().min(1),lifecycle:K.string().min(1).optional(),status:Qa1,conversationId:K.string().min(1).optional(),currentState:K.string().min(1),completedStates:K.array(K.string().min(1)).default([]),snapshot:K.unknown().optional(),context:K.record(K.string(),K.unknown()).default({}),evidence:K.array(GD0).default([]),gateVerdicts:K.array(wa1).default([]),startedAt:K.string().datetime().optional(),completedAt:K.string().datetime().optional(),updatedAt:K.string().datetime()}).strict(),ZKw="playbooks.runs",KKw=RP;class zD0{store;writeQueue=Promise.resolve();constructor(A){this.store=A.scoped({namespace:ZKw,schema:KKw})}async list(){return await this.waitForWrites(),(await this.store.list()).map((Q)=>Q.value)}async findById(A){return await this.store.get(A)??void 0}async findActiveByPlaybook(A){return(await this.list()).find((Q)=>Q.playbookId===A&&(Q.status==="active"||Q.status==="offered"))}async findByLifecycle(A){return(await this.list()).find((Q)=>Q.lifecycle===A)}async findActiveByConversation(A){return(await this.listActiveByConversation(A))[0]}async listActiveByConversation(A){return(await this.list()).filter((Q)=>Q.conversationId===A&&(Q.status==="active"||Q.status==="offered"))}async upsert(A){return this.enqueueMutation(async()=>{let Q=await this.store.get(A.id),w=RP.parse({...A,evidence:Aa1(Q?.evidence??[],A.evidence),gateVerdicts:UKw(Q?.gateVerdicts??[],A.gateVerdicts),updatedAt:new Date().toISOString()});return await this.store.set(w.id,w),w})}async appendEvidence(A,Q){return this.enqueueMutation(async()=>{let w=await this.store.get(A);if(!w)throw Error(`Playbook run not found: ${A}`);let B=RP.parse({...w,evidence:Aa1(w.evidence,[Q]),updatedAt:new Date().toISOString()});return await this.store.set(B.id,B),B})}async reset(A){await this.enqueueMutation(async()=>{if(!A){await this.store.clear();return}await this.store.delete(A)})}async enqueueMutation(A){let Q=this.writeQueue,w=()=>{};this.writeQueue=new Promise((B)=>{w=B}),await Q;try{return await A()}finally{w()}}async waitForWrites(){await this.writeQueue}}function gn0(A){let Q=new Date().toISOString();return RP.parse({id:NV("playbook_run"),playbookId:A.playbookId,playbookVersion:A.playbookVersion,...A.lifecycle?{lifecycle:A.lifecycle}:{},status:A.status??"active",...A.conversationId?{conversationId:A.conversationId}:{},currentState:A.initialState,completedStates:[],...A.snapshot!==void 0?{snapshot:A.snapshot}:{},context:{},evidence:[],gateVerdicts:[],...A.status==="active"||A.status===void 0?{startedAt:Q}:{},updatedAt:Q})}function Aa1(A,Q){let w=new Map;for(let B of[...A,...Q])w.set(B.id,B);return Array.from(w.values())}function UKw(A,Q){let w=new Map;for(let B of[...A,...Q])w.set(GKw(B),B);return Array.from(w.values())}function GKw(A){return[A.stateId,...A.goal].join("\x00")}var Ua1="playbooks:lifecycle-starters",zKw=K.object({trigger:K.string().min(1),playbookId:K.string().min(1),once:K.boolean().default(!0),starterText:K.string().min(1),description:K.string().min(1).optional(),starterPrompt:K.string().min(1)}).strict(),qKw=K.object({lifecycle:K.record(K.string(),zKw).default({}),triggers:K.record(K.string(),K.boolean()).default({})}).strict(),FKw=K.object({lifecycle:K.string().min(1).optional(),interfaceType:K.string().min(1),userPermissionLevel:K.enum(["anchor","trusted","public"])}).strict(),Ba1=K.object({id:K.string().min(1),entityType:K.literal("playbook"),content:K.string().min(1),metadata:K.object({title:K.string().min(1),status:K.enum(["draft","active","archived"]),audience:K.enum(["anchor","trusted","public"]),trigger:K.string().min(1).optional(),lifecycle:K.string().min(1).optional(),once:K.boolean().optional(),starterText:K.string().min(1).optional(),description:K.string().min(1).optional(),starterPrompt:K.string().min(1).optional(),completionMode:K.enum(["agent-confirmed","manual"])}).passthrough()}).passthrough(),$a1={runId:K.string().min(1).optional(),playbookId:K.string().min(1).optional(),lifecycle:K.string().min(1).optional()},fa1={playbookId:K.string().min(1),lifecycle:K.string().min(1).optional()},Da1={runId:K.string().min(1).optional(),event:K.string().min(1),context:K.record(K.string(),K.unknown()).optional()},VKw=K.object({met:K.boolean(),reason:K.string().min(1)}).strict(),IKw=K.object({event:K.string().min(1),target:K.string().min(1),operatorAction:K.boolean().optional(),label:K.string().min(1).optional(),description:K.string().min(1).optional(),operatorDescription:K.string().min(1).optional()}).strict(),JKw=K.object({id:K.string().min(1),title:K.string().min(1),instructions:K.array(K.string().min(1)),requiredDetails:K.array(K.string().min(1)).default([]),doneWhen:K.array(K.string().min(1)).default([]),transitions:K.array(IKw).default([])}).passthrough(),bKw=K.object({run:RP,state:JKw,goal:K.array(K.string().min(1)),evidence:K.array(GD0).default([])}).strict();class mn0 extends RQ{store;ctx;goalCheck;injectedGoalCheck;startLocks=new Map;constructor(A={},Q={}){super("playbooks",es1,A,qKw);this.injectedGoalCheck=Q.goalCheck,this.goalCheck=Q.goalCheck??CKw}async onRegister(A){await super.onRegister(A),this.ctx=A,this.store=new zD0(A.runtimeState),this.goalCheck=this.injectedGoalCheck??xKw(A),A.registerInstructions(this.buildInstructions()),A.eval.registerHandler("goalCheck",async(Q)=>this.goalCheck.evaluate(bKw.parse(Q))),A.messaging.subscribe(Ua1,async(Q)=>{let w=FKw.parse(Q.payload);return{success:!0,data:{starters:await this.resolveLifecycleStarters(w)}}}),A.messaging.subscribe(BN,async(Q)=>{let w=cT.parse(Q.payload),B=await this.buildAgentContextItem(w.conversationId);return{success:!0,data:{items:B?[B]:[]}}}),A.messaging.subscribe(mT,async(Q)=>{let w=RZ0.parse(Q.payload),B=await this.handleAgentAction(w);return B?{success:!0,data:B}:{success:!1}}),A.messaging.subscribe("entity:created",async(Q)=>({success:!0,data:await this.recordEntityEventEvidence("created",Q.payload)})),A.messaging.subscribe("entity:updated",async(Q)=>({success:!0,data:await this.recordEntityEventEvidence("updated",Q.payload)}))}async getTools(){return[{name:"playbook_status",description:"Get playbook lifecycle config, active runs, current state, valid events, and parsed playbook body. After meaningful tool actions, use the reported current state as source of truth. Do not send an extra NEXT after runtime evidence already advanced the run. Do not claim the playbook is finished unless the run has reached a final state.",inputSchema:$a1,visibility:"anchor",sideEffects:"none",handler:async(A,Q)=>{let w=K.object($a1).parse(A);try{return{success:!0,data:await this.getStatus({...w,conversationId:Q.conversationId})}}catch(B){return{success:!1,error:Tn0(B)}}}},{name:"playbook_start",description:"Start a playbook run, or resume an existing active run. If the operator asks to start a playbook by title, use the stable slug/id form when known (for example lowercase words joined by hyphens) instead of claiming it is unavailable without calling this tool. Do not call this to continue an already active playbook; use playbook_status and playbook_send_event with a valid event instead.",inputSchema:fa1,visibility:"anchor",sideEffects:"writes",handler:async(A,Q)=>{let w=K.object(fa1).parse(A),B=Q.conversationId,$=B?`${B}:${w.playbookId}`:`playbook:${w.playbookId}`;return this.withStartLock($,async()=>{let f=await this.requirePlaybook(w.playbookId);Vo(f.body);let D=f.entity.metadata.lifecycle??w.lifecycle,Y=B?(await this.store.listActiveByConversation(B)).find((W)=>W.playbookId===w.playbookId):await this.store.findActiveByPlaybook(w.playbookId),X=Y?await this.store.upsert({...Y,status:"active",...B?{conversationId:B}:{},...Y.startedAt?{}:{startedAt:new Date().toISOString()}}):await this.createStartedRun({playbookId:w.playbookId,playbookVersion:f.version,body:f.body,lifecycle:D,conversationId:B});return{success:!0,data:await this.getStatus({runId:X.id})}})}},{name:"playbook_send_event",description:"Send an event to a playbook run state machine and persist the resulting state. Invalid events return an error. Only use this when the operator positively selects a valid event/action or when a gated Done When condition is actually met. For durable gated states, user-provided details are not enough; do not send NEXT until the required system_create/system_update/system_delete tool has succeeded or current run evidence already shows the Done When condition is met. Operator actions and choices are not generic continuation events; do not use this for generic next/continue to select an operator action, even if only one operator action is currently valid. Do not use this when the operator explicitly says they have not chosen, selected, asked for, or used the available action. Skip-style events require a positive request to skip. This tool only changes playbook state; it does not retrieve, show, save, create, update, or transform domain entities. When the operator message only selects a playbook action, call this tool without unrelated domain mutation tools such as system_create or system_update. If the operator also asks to find/show/retrieve content, call system_get or system_search before answering.",inputSchema:Da1,visibility:"anchor",sideEffects:"writes",handler:async(A,Q)=>{let w=K.object(Da1).parse(A),B=await this.resolveScopedRunResponse({runId:w.runId,conversationId:Q.conversationId});if(!B.success)return B;let $=await this.sendEventForRun(B.data,w.event,w.context);return $.success?{success:!0,data:$.data}:{success:!1,error:$.error}}}]}async withStartLock(A,Q){let w=this.startLocks.get(A);if(w)return w;let B=Q().finally(()=>{this.startLocks.delete(A)});return this.startLocks.set(A,B),B}async handleAgentAction(A){if(A.userPermissionLevel!=="anchor")return;let Q=await this.resolveScopedRunResponse({conversationId:A.conversationId});if(!Q.success)return;let w=await this.sendEventForRun(Q.data,A.action.event);if(!w.success)return{text:`I couldn't continue the playbook: ${w.error}`,toolResults:[{toolName:"playbook_send_event",args:{runId:Q.data.id,event:A.action.event}}],usage:Xa1()};let B=this.getCurrentRunState(w.data);return{text:MKw(B),...w.data.cards?{cards:w.data.cards}:{},toolResults:[{toolName:"playbook_send_event",args:{runId:Q.data.id,event:A.action.event},data:w.data}],usage:Xa1()}}getCurrentRunState(A){return A.currentState}async sendEventForRun(A,Q,w){let B=await this.requirePlaybook(A.playbookId);if(A.playbookVersion!==B.version)return{success:!1,error:`Playbook definition changed for '${A.playbookId}'. Run version ${A.playbookVersion} does not match current version ${B.version}.`};let $=this.getState(B.body,A.currentState),f=$?.transitions.find((W)=>W.event===Q),D=await this.transitionRun(A,B.body,Q);if(!D.success){if(D.gateVerdicts)await this.store.upsert({...A,gateVerdicts:D.gateVerdicts});return{success:!1,error:D.error}}let Y=B.body.finalStates.includes(D.currentState),X=await this.store.upsert({...A,currentState:D.currentState,completedStates:Ha1(A.completedStates,A.currentState),snapshot:D.snapshot,gateVerdicts:D.gateVerdicts,context:{...A.context,...w??{}},...Y?{status:"completed",completedAt:new Date().toISOString()}:{}}),H=await this.getStatus({runId:X.id});return{success:!0,data:$&&f?.operatorAction===!0?LKw(H,$,f):H}}async createStartedRun(A){let Q=gn0({playbookId:A.playbookId,playbookVersion:A.playbookVersion,initialState:A.body.initialState,lifecycle:A.lifecycle,conversationId:A.conversationId}),w=this.buildMachine(A.playbookId,A.body,Q),B=E1.createActor(w);B.start();let $=B.getPersistedSnapshot();return B.stop(),this.store.upsert({...Q,snapshot:$})}async transitionRun(A,Q,w){let B=this.getState(Q,A.currentState);if(!B)return{success:!1,error:`Playbook state not found: ${A.currentState}`};let $=await this.prepareGateVerdicts(A,B,w);if(!$.success)return $;let f={...A,gateVerdicts:$.gateVerdicts},D=this.buildMachine(A.playbookId,Q,f),Y=E1.createActor(D,{...A.snapshot?{snapshot:A.snapshot}:{}});Y.start();let X=Y.getSnapshot(),H={type:w};if(!X.can(H))return Y.stop(),{success:!1,error:`Invalid playbook event '${w}' from state '${A.currentState}'.`,gateVerdicts:$.gateVerdicts};Y.send(H);let W=Y.getSnapshot(),Z=String(W.value),G=B.transitions.find((V)=>V.event===w)?.target;if(G&&Z!==G)return Y.stop(),{success:!1,error:`Playbook event '${w}' is blocked from state '${A.currentState}'. Complete the state's Done When conditions before sending this event.`,gateVerdicts:$.gateVerdicts};let F=Y.getPersistedSnapshot();return Y.stop(),{success:!0,currentState:Z,snapshot:F,gateVerdicts:$.gateVerdicts}}async prepareGateVerdicts(A,Q,w){if(!this.transitionRequiresGateVerdict(Q,w))return{success:!0,gateVerdicts:A.gateVerdicts};if(this.hasSatisfiedGateVerdicts(Q,A))return{success:!0,gateVerdicts:A.gateVerdicts};let B=this.evidenceForState(A,Q.id),$;try{$=await this.goalCheck.evaluate({run:A,state:Q,goal:Q.doneWhen,evidence:B})}catch(Y){$={met:!1,reason:`Playbook goal check failed: ${Tn0(Y)}`}}let f={stateId:Q.id,goal:Q.doneWhen,met:$.met,reason:$.reason,evaluatedAt:new Date().toISOString()};return{success:!0,gateVerdicts:PKw(A.gateVerdicts,[f])}}evidenceForState(A,Q){return A.evidence.filter((w)=>!w.stateId||w.stateId===Q)}buildMachine(A,Q,w){return E1.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,...this.transitionRequiresGateVerdict(B,f.event)?{guard:()=>this.hasSatisfiedGateVerdicts(B,w)}:{}}]))}}]}))})}async resolveLifecycleStarters(A){if(A.interfaceType!=="web-chat"||A.userPermissionLevel!=="anchor")return[];let Q=[],w=new Set,B=Object.entries(this.config.lifecycle).filter(([f])=>!A.lifecycle||f===A.lifecycle);for(let[f,D]of B){let Y=await this.resolveConfiguredLifecycleStarter(f,D);if(!Y)continue;Q.push(Y),w.add(f)}let $=new Set(Object.entries(this.config.triggers).filter(([,f])=>f).map(([f])=>f));if($.size===0)return Q;for(let f of await this.listPlaybooks()){let D=f.entity.metadata;if(D.status!=="active"||D.audience!=="anchor")continue;let Y=D.trigger;if(!Y||!$.has(Y))continue;let X=D.lifecycle??f.entity.id;if(w.has(X))continue;if(A.lifecycle&&X!==A.lifecycle)continue;let H=await this.store.findByLifecycle(X);if((D.once??!0)&&(H?.status==="completed"||H?.status==="dismissed"))continue;Q.push({id:X,title:D.starterText??D.title,...D.description??f.body.purpose?{description:D.description??f.body.purpose}:{},playbookId:f.entity.id,lifecycle:X,starterPrompt:D.starterPrompt??`Start the ${D.title} playbook.`}),w.add(X)}return Q}async resolveConfiguredLifecycleStarter(A,Q){let w=await this.store.findByLifecycle(A);if(Q.once&&(w?.status==="completed"||w?.status==="dismissed"))return;if((await this.getPlaybook(Q.playbookId))?.entity.metadata.status!=="active")return;return{id:A,title:Q.starterText,...Q.description?{description:Q.description}:{},playbookId:Q.playbookId,lifecycle:A,starterPrompt:Q.starterPrompt}}async listPlaybooks(){if(!this.ctx)return[];return(await this.ctx.entityService.listEntities({entityType:"playbook"})).flatMap((Q)=>{let w=Ba1.safeParse(Q);if(!w.success)return[];let{body:B}=xP.parsePlaybookContent(w.data.content);return[{entity:w.data,body:B,version:xw(w.data.content)}]})}async getStatus(A){let Q=await this.store.list(),w=A.conversationId?Q.filter((b)=>b.conversationId===A.conversationId):[],B=w.filter((b)=>b.status==="active"||b.status==="offered"),$=_Kw(w.filter((b)=>(!A.playbookId||b.playbookId===A.playbookId)&&(!A.lifecycle||b.lifecycle===A.lifecycle))),f=A.runId?Q.find((b)=>b.id===A.runId)??$:A.conversationId&&A.lifecycle?B.find((b)=>b.lifecycle===A.lifecycle)??$:A.conversationId&&A.playbookId?B.find((b)=>b.playbookId===A.playbookId)??$:A.conversationId?B.length>0?await this.requireScopedRun({conversationId:A.conversationId}):$:A.lifecycle?Q.find((b)=>b.lifecycle===A.lifecycle):A.playbookId?Q.find((b)=>b.playbookId===A.playbookId):void 0;if(A.conversationId&&!f&&!A.runId&&!A.playbookId&&!A.lifecycle)throw Error(`No active or completed playbook run for conversation '${A.conversationId}'.`);let D=A.playbookId??f?.playbookId??(A.lifecycle?this.config.lifecycle[A.lifecycle]?.playbookId:void 0),Y=D?await this.getPlaybook(D):void 0,X=Y&&f?this.getState(Y.body,f.currentState):void 0,H=X&&f&&Y?this.getValidTransitions(f,Y.body,X):X?.transitions??[],W=H.filter((b)=>b.operatorAction!==!0),Z=H.filter((b)=>b.operatorAction===!0),G=X&&f&&Y?this.getBlockedTransitions(f,Y.body,X):[],F=X&&f&&Y?this.buildStateGuidance(f,Y.body,X):void 0,V=f&&Y&&Z.length>0?jKw({run:f,title:Y.entity.metadata.title,transitions:Z}):void 0;return{runs:(A.conversationId?w:Q).map(Ya1),...f?{activeRun:Ya1(f)}:{},...Y?{playbook:Y.entity}:{},...Y?{body:Y.body}:{},...X?{currentState:X}:{},...W.length>0?{validEvents:W}:{},...Z.length>0?{operatorActions:Z}:{},...G.length>0?{blockedEvents:G}:{},...F?{guidance:F}:{},...V?{cards:[V]}:{},lifecycle:this.config.lifecycle}}buildStateGuidance(A,Q,w){let B=this.getValidTransitions(A,Q,w),$=B.filter((X)=>X.operatorAction!==!0),f=B.filter((X)=>X.operatorAction===!0),D=this.getBlockedTransitions(A,Q,w),Y=A.gateVerdicts.find((X)=>X.stateId===w.id&&Sn0(X.goal,w.doneWhen));return[`Current state: ${w.id} (${w.title})`,"Instructions:",...w.instructions.map((X)=>`- ${X}`),"Done When:",...w.doneWhen.length>0?w.doneWhen.map((X)=>`- ${X}`):["- none"],"Goal status:",Y?`- ${Y.met?"Met":"Not yet met"}: ${Y.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((X)=>this.formatTransition(X)):["- none"],"Available operator actions:",...f.length>0?f.map((X)=>this.formatTransition(X)):["- none"],"Blocked events:",...D.length>0?D.map((X)=>this.formatTransition(X)):["- none"]].join(`
8283
+ `))}function DKw(A,Q){return UD0(A,Q).map(YKw)}function YKw(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 rs1(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 os1(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function XKw(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ss1={name:"@brains/playbook",private:!0,version:"0.2.0-alpha.134",description:"Playbook entity for durable guided agent workflows",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/content-formatters":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class as1 extends PQ{entityType=xP.entityType;schema=Fo;adapter=xP;constructor(A={}){super("playbook",ss1,A,Rn0)}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 ts1(A={}){return new as1(A)}CB();c0();Z0();bY();J10();var es1={name:"@brains/playbooks",private:!0,version:"0.2.0-alpha.134",description:"Runtime orchestration for chat-native playbook runs",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},dependencies:{"@brains/contracts":"workspace:*","@brains/playbook":"workspace:*","@brains/plugins":"workspace:*","@brains/runtime-state":"workspace:*","@brains/utils":"workspace:*",xstate:"^5.28.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};Z0();var Qa1=K.enum(["offered","active","completed","dismissed"]),GD0=K.object({id:K.string().min(1),kind:K.enum(["entity_event"]),stateId:K.string().min(1).optional(),observedAt:K.string().datetime(),data:K.record(K.string(),K.unknown())}).strict(),wa1=K.object({stateId:K.string().min(1),goal:K.array(K.string().min(1)),met:K.boolean(),reason:K.string().min(1),evaluatedAt:K.string().datetime()}).strict(),RP=K.object({id:K.string().min(1),playbookId:K.string().min(1),playbookVersion:K.string().min(1),lifecycle:K.string().min(1).optional(),status:Qa1,conversationId:K.string().min(1).optional(),currentState:K.string().min(1),completedStates:K.array(K.string().min(1)).default([]),snapshot:K.unknown().optional(),context:K.record(K.string(),K.unknown()).default({}),evidence:K.array(GD0).default([]),gateVerdicts:K.array(wa1).default([]),startedAt:K.string().datetime().optional(),completedAt:K.string().datetime().optional(),updatedAt:K.string().datetime()}).strict(),ZKw="playbooks.runs",KKw=RP;class zD0{store;writeQueue=Promise.resolve();constructor(A){this.store=A.scoped({namespace:ZKw,schema:KKw})}async list(){return await this.waitForWrites(),(await this.store.list()).map((Q)=>Q.value)}async findById(A){return await this.store.get(A)??void 0}async findActiveByPlaybook(A){return(await this.list()).find((Q)=>Q.playbookId===A&&(Q.status==="active"||Q.status==="offered"))}async findByLifecycle(A){return(await this.list()).find((Q)=>Q.lifecycle===A)}async findActiveByConversation(A){return(await this.listActiveByConversation(A))[0]}async listActiveByConversation(A){return(await this.list()).filter((Q)=>Q.conversationId===A&&(Q.status==="active"||Q.status==="offered"))}async upsert(A){return this.enqueueMutation(async()=>{let Q=await this.store.get(A.id),w=RP.parse({...A,evidence:Aa1(Q?.evidence??[],A.evidence),gateVerdicts:UKw(Q?.gateVerdicts??[],A.gateVerdicts),updatedAt:new Date().toISOString()});return await this.store.set(w.id,w),w})}async appendEvidence(A,Q){return this.enqueueMutation(async()=>{let w=await this.store.get(A);if(!w)throw Error(`Playbook run not found: ${A}`);let B=RP.parse({...w,evidence:Aa1(w.evidence,[Q]),updatedAt:new Date().toISOString()});return await this.store.set(B.id,B),B})}async reset(A){await this.enqueueMutation(async()=>{if(!A){await this.store.clear();return}await this.store.delete(A)})}async enqueueMutation(A){let Q=this.writeQueue,w=()=>{};this.writeQueue=new Promise((B)=>{w=B}),await Q;try{return await A()}finally{w()}}async waitForWrites(){await this.writeQueue}}function gn0(A){let Q=new Date().toISOString();return RP.parse({id:NV("playbook_run"),playbookId:A.playbookId,playbookVersion:A.playbookVersion,...A.lifecycle?{lifecycle:A.lifecycle}:{},status:A.status??"active",...A.conversationId?{conversationId:A.conversationId}:{},currentState:A.initialState,completedStates:[],...A.snapshot!==void 0?{snapshot:A.snapshot}:{},context:{},evidence:[],gateVerdicts:[],...A.status==="active"||A.status===void 0?{startedAt:Q}:{},updatedAt:Q})}function Aa1(A,Q){let w=new Map;for(let B of[...A,...Q])w.set(B.id,B);return Array.from(w.values())}function UKw(A,Q){let w=new Map;for(let B of[...A,...Q])w.set(GKw(B),B);return Array.from(w.values())}function GKw(A){return[A.stateId,...A.goal].join("\x00")}var Ua1="playbooks:lifecycle-starters",zKw=K.object({trigger:K.string().min(1),playbookId:K.string().min(1),once:K.boolean().default(!0),starterText:K.string().min(1),description:K.string().min(1).optional(),starterPrompt:K.string().min(1)}).strict(),qKw=K.object({lifecycle:K.record(K.string(),zKw).default({}),triggers:K.record(K.string(),K.boolean()).default({})}).strict(),FKw=K.object({lifecycle:K.string().min(1).optional(),interfaceType:K.string().min(1),userPermissionLevel:K.enum(["anchor","trusted","public"])}).strict(),Ba1=K.object({id:K.string().min(1),entityType:K.literal("playbook"),content:K.string().min(1),metadata:K.object({title:K.string().min(1),status:K.enum(["draft","active","archived"]),audience:K.enum(["anchor","trusted","public"]),trigger:K.string().min(1).optional(),lifecycle:K.string().min(1).optional(),once:K.boolean().optional(),starterText:K.string().min(1).optional(),description:K.string().min(1).optional(),starterPrompt:K.string().min(1).optional(),completionMode:K.enum(["agent-confirmed","manual"])}).passthrough()}).passthrough(),$a1={runId:K.string().min(1).optional(),playbookId:K.string().min(1).optional(),lifecycle:K.string().min(1).optional()},fa1={playbookId:K.string().min(1),lifecycle:K.string().min(1).optional()},Da1={runId:K.string().min(1).optional(),event:K.string().min(1),context:K.record(K.string(),K.unknown()).optional()},VKw=K.object({met:K.boolean(),reason:K.string().min(1)}).strict(),IKw=K.object({event:K.string().min(1),target:K.string().min(1),operatorAction:K.boolean().optional(),label:K.string().min(1).optional(),description:K.string().min(1).optional(),operatorDescription:K.string().min(1).optional()}).strict(),JKw=K.object({id:K.string().min(1),title:K.string().min(1),instructions:K.array(K.string().min(1)),requiredDetails:K.array(K.string().min(1)).default([]),doneWhen:K.array(K.string().min(1)).default([]),transitions:K.array(IKw).default([])}).passthrough(),bKw=K.object({run:RP,state:JKw,goal:K.array(K.string().min(1)),evidence:K.array(GD0).default([])}).strict();class mn0 extends RQ{store;ctx;goalCheck;injectedGoalCheck;startLocks=new Map;constructor(A={},Q={}){super("playbooks",es1,A,qKw);this.injectedGoalCheck=Q.goalCheck,this.goalCheck=Q.goalCheck??CKw}async onRegister(A){await super.onRegister(A),this.ctx=A,this.store=new zD0(A.runtimeState),this.goalCheck=this.injectedGoalCheck??xKw(A),A.registerInstructions(this.buildInstructions()),A.eval.registerHandler("goalCheck",async(Q)=>this.goalCheck.evaluate(bKw.parse(Q))),A.messaging.subscribe(Ua1,async(Q)=>{let w=FKw.parse(Q.payload);return{success:!0,data:{starters:await this.resolveLifecycleStarters(w)}}}),A.messaging.subscribe(BN,async(Q)=>{let w=cT.parse(Q.payload),B=await this.buildAgentContextItem(w.conversationId);return{success:!0,data:{items:B?[B]:[]}}}),A.messaging.subscribe(mT,async(Q)=>{let w=RZ0.parse(Q.payload),B=await this.handleAgentAction(w);return B?{success:!0,data:B}:{success:!1}}),A.messaging.subscribe("entity:created",async(Q)=>({success:!0,data:await this.recordEntityEventEvidence("created",Q.payload)})),A.messaging.subscribe("entity:updated",async(Q)=>({success:!0,data:await this.recordEntityEventEvidence("updated",Q.payload)}))}async getTools(){return[{name:"playbook_status",description:"Get playbook lifecycle config, active runs, current state, valid events, and parsed playbook body. After meaningful tool actions, use the reported current state as source of truth. Do not send an extra NEXT after runtime evidence already advanced the run. Do not claim the playbook is finished unless the run has reached a final state.",inputSchema:$a1,visibility:"anchor",sideEffects:"none",handler:async(A,Q)=>{let w=K.object($a1).parse(A);try{return{success:!0,data:await this.getStatus({...w,conversationId:Q.conversationId})}}catch(B){return{success:!1,error:Tn0(B)}}}},{name:"playbook_start",description:"Start a playbook run, or resume an existing active run. If the operator asks to start a playbook by title, use the stable slug/id form when known (for example lowercase words joined by hyphens) instead of claiming it is unavailable without calling this tool. Do not call this to continue an already active playbook; use playbook_status and playbook_send_event with a valid event instead.",inputSchema:fa1,visibility:"anchor",sideEffects:"writes",handler:async(A,Q)=>{let w=K.object(fa1).parse(A),B=Q.conversationId,$=B?`${B}:${w.playbookId}`:`playbook:${w.playbookId}`;return this.withStartLock($,async()=>{let f=await this.requirePlaybook(w.playbookId);Vo(f.body);let D=f.entity.metadata.lifecycle??w.lifecycle,Y=B?(await this.store.listActiveByConversation(B)).find((W)=>W.playbookId===w.playbookId):await this.store.findActiveByPlaybook(w.playbookId),X=Y?await this.store.upsert({...Y,status:"active",...B?{conversationId:B}:{},...Y.startedAt?{}:{startedAt:new Date().toISOString()}}):await this.createStartedRun({playbookId:w.playbookId,playbookVersion:f.version,body:f.body,lifecycle:D,conversationId:B});return{success:!0,data:await this.getStatus({runId:X.id})}})}},{name:"playbook_send_event",description:"Send an event to a playbook run state machine and persist the resulting state. Invalid events return an error. Only use this when the operator positively selects a valid event/action or when a gated Done When condition is actually met. For durable gated states, user-provided details are not enough; do not send NEXT until the required system_create/system_update/system_delete tool has succeeded or current run evidence already shows the Done When condition is met. Operator actions and choices are not generic continuation events; do not use this for generic next/continue to select an operator action, even if only one operator action is currently valid. Do not use this when the operator explicitly says they have not chosen, selected, asked for, or used the available action. Skip-style events require a positive request to skip. This tool only changes playbook state; it does not retrieve, show, save, create, update, or transform domain entities. When the operator message only selects a playbook action, call this tool without unrelated domain mutation tools such as system_create or system_update. If the operator also asks to find/show/retrieve content, call system_get or system_search before answering.",inputSchema:Da1,visibility:"anchor",sideEffects:"writes",handler:async(A,Q)=>{let w=K.object(Da1).parse(A),B=await this.resolveScopedRunResponse({runId:w.runId,conversationId:Q.conversationId});if(!B.success)return B;let $=await this.sendEventForRun(B.data,w.event,w.context);return $.success?{success:!0,data:$.data}:{success:!1,error:$.error}}}]}async withStartLock(A,Q){let w=this.startLocks.get(A);if(w)return w;let B=Q().finally(()=>{this.startLocks.delete(A)});return this.startLocks.set(A,B),B}async handleAgentAction(A){if(A.userPermissionLevel!=="anchor")return;let Q=await this.resolveScopedRunResponse({conversationId:A.conversationId});if(!Q.success)return;let w=await this.sendEventForRun(Q.data,A.action.event);if(!w.success)return{text:`I couldn't continue the playbook: ${w.error}`,toolResults:[{toolName:"playbook_send_event",args:{runId:Q.data.id,event:A.action.event}}],usage:Xa1()};let B=this.getCurrentRunState(w.data);return{text:MKw(B),...w.data.cards?{cards:w.data.cards}:{},toolResults:[{toolName:"playbook_send_event",args:{runId:Q.data.id,event:A.action.event},data:w.data}],usage:Xa1()}}getCurrentRunState(A){return A.currentState}async sendEventForRun(A,Q,w){let B=await this.requirePlaybook(A.playbookId);if(A.playbookVersion!==B.version)return{success:!1,error:`Playbook definition changed for '${A.playbookId}'. Run version ${A.playbookVersion} does not match current version ${B.version}.`};let $=this.getState(B.body,A.currentState),f=$?.transitions.find((W)=>W.event===Q),D=await this.transitionRun(A,B.body,Q);if(!D.success){if(D.gateVerdicts)await this.store.upsert({...A,gateVerdicts:D.gateVerdicts});return{success:!1,error:D.error}}let Y=B.body.finalStates.includes(D.currentState),X=await this.store.upsert({...A,currentState:D.currentState,completedStates:Ha1(A.completedStates,A.currentState),snapshot:D.snapshot,gateVerdicts:D.gateVerdicts,context:{...A.context,...w??{}},...Y?{status:"completed",completedAt:new Date().toISOString()}:{}}),H=await this.getStatus({runId:X.id});return{success:!0,data:$&&f?.operatorAction===!0?LKw(H,$,f):H}}async createStartedRun(A){let Q=gn0({playbookId:A.playbookId,playbookVersion:A.playbookVersion,initialState:A.body.initialState,lifecycle:A.lifecycle,conversationId:A.conversationId}),w=this.buildMachine(A.playbookId,A.body,Q),B=E1.createActor(w);B.start();let $=B.getPersistedSnapshot();return B.stop(),this.store.upsert({...Q,snapshot:$})}async transitionRun(A,Q,w){let B=this.getState(Q,A.currentState);if(!B)return{success:!1,error:`Playbook state not found: ${A.currentState}`};let $=await this.prepareGateVerdicts(A,B,w);if(!$.success)return $;let f={...A,gateVerdicts:$.gateVerdicts},D=this.buildMachine(A.playbookId,Q,f),Y=E1.createActor(D,{...A.snapshot?{snapshot:A.snapshot}:{}});Y.start();let X=Y.getSnapshot(),H={type:w};if(!X.can(H))return Y.stop(),{success:!1,error:`Invalid playbook event '${w}' from state '${A.currentState}'.`,gateVerdicts:$.gateVerdicts};Y.send(H);let W=Y.getSnapshot(),Z=String(W.value),G=B.transitions.find((V)=>V.event===w)?.target;if(G&&Z!==G)return Y.stop(),{success:!1,error:`Playbook event '${w}' is blocked from state '${A.currentState}'. Complete the state's Done When conditions before sending this event.`,gateVerdicts:$.gateVerdicts};let F=Y.getPersistedSnapshot();return Y.stop(),{success:!0,currentState:Z,snapshot:F,gateVerdicts:$.gateVerdicts}}async prepareGateVerdicts(A,Q,w){if(!this.transitionRequiresGateVerdict(Q,w))return{success:!0,gateVerdicts:A.gateVerdicts};if(this.hasSatisfiedGateVerdicts(Q,A))return{success:!0,gateVerdicts:A.gateVerdicts};let B=this.evidenceForState(A,Q.id),$;try{$=await this.goalCheck.evaluate({run:A,state:Q,goal:Q.doneWhen,evidence:B})}catch(Y){$={met:!1,reason:`Playbook goal check failed: ${Tn0(Y)}`}}let f={stateId:Q.id,goal:Q.doneWhen,met:$.met,reason:$.reason,evaluatedAt:new Date().toISOString()};return{success:!0,gateVerdicts:PKw(A.gateVerdicts,[f])}}evidenceForState(A,Q){return A.evidence.filter((w)=>!w.stateId||w.stateId===Q)}buildMachine(A,Q,w){return E1.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,...this.transitionRequiresGateVerdict(B,f.event)?{guard:()=>this.hasSatisfiedGateVerdicts(B,w)}:{}}]))}}]}))})}async resolveLifecycleStarters(A){if(A.interfaceType!=="web-chat"||A.userPermissionLevel!=="anchor")return[];let Q=[],w=new Set,B=Object.entries(this.config.lifecycle).filter(([f])=>!A.lifecycle||f===A.lifecycle);for(let[f,D]of B){let Y=await this.resolveConfiguredLifecycleStarter(f,D);if(!Y)continue;Q.push(Y),w.add(f)}let $=new Set(Object.entries(this.config.triggers).filter(([,f])=>f).map(([f])=>f));if($.size===0)return Q;for(let f of await this.listPlaybooks()){let D=f.entity.metadata;if(D.status!=="active"||D.audience!=="anchor")continue;let Y=D.trigger;if(!Y||!$.has(Y))continue;let X=D.lifecycle??f.entity.id;if(w.has(X))continue;if(A.lifecycle&&X!==A.lifecycle)continue;let H=await this.store.findByLifecycle(X);if((D.once??!0)&&(H?.status==="completed"||H?.status==="dismissed"))continue;Q.push({id:X,title:D.starterText??D.title,...D.description??f.body.purpose?{description:D.description??f.body.purpose}:{},playbookId:f.entity.id,lifecycle:X,starterPrompt:D.starterPrompt??`Start the ${D.title} playbook.`}),w.add(X)}return Q}async resolveConfiguredLifecycleStarter(A,Q){let w=await this.store.findByLifecycle(A);if(Q.once&&(w?.status==="completed"||w?.status==="dismissed"))return;if((await this.getPlaybook(Q.playbookId))?.entity.metadata.status!=="active")return;return{id:A,title:Q.starterText,...Q.description?{description:Q.description}:{},playbookId:Q.playbookId,lifecycle:A,starterPrompt:Q.starterPrompt}}async listPlaybooks(){if(!this.ctx)return[];return(await this.ctx.entityService.listEntities({entityType:"playbook"})).flatMap((Q)=>{let w=Ba1.safeParse(Q);if(!w.success)return[];let{body:B}=xP.parsePlaybookContent(w.data.content);return[{entity:w.data,body:B,version:xw(w.data.content)}]})}async getStatus(A){let Q=await this.store.list(),w=A.conversationId?Q.filter((b)=>b.conversationId===A.conversationId):[],B=w.filter((b)=>b.status==="active"||b.status==="offered"),$=_Kw(w.filter((b)=>(!A.playbookId||b.playbookId===A.playbookId)&&(!A.lifecycle||b.lifecycle===A.lifecycle))),f=A.runId?Q.find((b)=>b.id===A.runId)??$:A.conversationId&&A.lifecycle?B.find((b)=>b.lifecycle===A.lifecycle)??$:A.conversationId&&A.playbookId?B.find((b)=>b.playbookId===A.playbookId)??$:A.conversationId?B.length>0?await this.requireScopedRun({conversationId:A.conversationId}):$:A.lifecycle?Q.find((b)=>b.lifecycle===A.lifecycle):A.playbookId?Q.find((b)=>b.playbookId===A.playbookId):void 0;if(A.conversationId&&!f&&!A.runId&&!A.playbookId&&!A.lifecycle)throw Error(`No active or completed playbook run for conversation '${A.conversationId}'.`);let D=A.playbookId??f?.playbookId??(A.lifecycle?this.config.lifecycle[A.lifecycle]?.playbookId:void 0),Y=D?await this.getPlaybook(D):void 0,X=Y&&f?this.getState(Y.body,f.currentState):void 0,H=X&&f&&Y?this.getValidTransitions(f,Y.body,X):X?.transitions??[],W=H.filter((b)=>b.operatorAction!==!0),Z=H.filter((b)=>b.operatorAction===!0),G=X&&f&&Y?this.getBlockedTransitions(f,Y.body,X):[],F=X&&f&&Y?this.buildStateGuidance(f,Y.body,X):void 0,V=f&&Y&&Z.length>0?jKw({run:f,title:Y.entity.metadata.title,transitions:Z}):void 0;return{runs:(A.conversationId?w:Q).map(Ya1),...f?{activeRun:Ya1(f)}:{},...Y?{playbook:Y.entity}:{},...Y?{body:Y.body}:{},...X?{currentState:X}:{},...W.length>0?{validEvents:W}:{},...Z.length>0?{operatorActions:Z}:{},...G.length>0?{blockedEvents:G}:{},...F?{guidance:F}:{},...V?{cards:[V]}:{},lifecycle:this.config.lifecycle}}buildStateGuidance(A,Q,w){let B=this.getValidTransitions(A,Q,w),$=B.filter((X)=>X.operatorAction!==!0),f=B.filter((X)=>X.operatorAction===!0),D=this.getBlockedTransitions(A,Q,w),Y=A.gateVerdicts.find((X)=>X.stateId===w.id&&Sn0(X.goal,w.doneWhen));return[`Current state: ${w.id} (${w.title})`,"Instructions:",...w.instructions.map((X)=>`- ${X}`),"Done When:",...w.doneWhen.length>0?w.doneWhen.map((X)=>`- ${X}`):["- none"],"Goal status:",Y?`- ${Y.met?"Met":"Not yet met"}: ${Y.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((X)=>this.formatTransition(X)):["- none"],"Available operator actions:",...f.length>0?f.map((X)=>this.formatTransition(X)):["- none"],"Blocked events:",...D.length>0?D.map((X)=>this.formatTransition(X)):["- none"]].join(`
8284
8284
  `)}async recordEntityEventEvidence(A,Q){let w=PE(Q,"entityType"),B=PE(Q,"entityId");if(!w||!B)return{recorded:!1};let $=PE(Q,"runId"),f=PE(Q,"conversationId"),D=$?await this.store.findById($):f?await this.store.findActiveByConversation(f):void 0;if(D?.status!=="active")return{recorded:!1};let Y={id:NV("playbook_evidence"),kind:"entity_event",stateId:D.currentState,observedAt:new Date().toISOString(),data:{entityType:w,entityId:B,operation:A,...kKw(Q),...f?{conversationId:f}:{},...PE(Q,"toolCallId")?{toolCallId:PE(Q,"toolCallId")}:{}}},X=await this.store.appendEvidence(D.id,Y);return await this.evaluateGateAfterEvidence(X),{recorded:!0}}async evaluateGateAfterEvidence(A){if(this.hasSatisfiedGateForCurrentState(A))return;let Q=await this.getPlaybook(A.playbookId);if(A.playbookVersion!==Q?.version)return;let w=this.getState(Q.body,A.currentState);if(!w?.doneWhen.length)return;if(w.transitions.filter((X)=>X.event==="NEXT").length!==1)return;let $=await this.prepareGateVerdicts(A,w,"NEXT");if(!$.success)return;let f={...A,gateVerdicts:$.gateVerdicts};if(!this.hasSatisfiedGateVerdicts(w,f)){await this.store.upsert(f);return}let D=await this.transitionRun(f,Q.body,"NEXT");if(!D.success){await this.store.upsert(f);return}let Y=Q.body.finalStates.includes(D.currentState);await this.store.upsert({...f,currentState:D.currentState,completedStates:Ha1(f.completedStates,f.currentState),snapshot:D.snapshot,gateVerdicts:D.gateVerdicts,...Y?{status:"completed",completedAt:new Date().toISOString()}:{}})}hasSatisfiedGateForCurrentState(A){return A.gateVerdicts.some((Q)=>Q.stateId===A.currentState&&Q.met)}async getPlaybook(A){if(!this.ctx)return;let Q=await this.ctx.entityService.getEntity({entityType:"playbook",id:A,visibilityScope:p8("anchor")}),w=Ba1.safeParse(Q);if(!w.success)return;let{body:B}=xP.parsePlaybookContent(w.data.content);return{entity:w.data,body:B,version:xw(w.data.content)}}async requirePlaybook(A){let Q=await this.getPlaybook(A);if(!Q)throw Error(`Playbook not found: ${A}`);return Q}async requireRun(A){let Q=await this.store.findById(A);if(!Q)throw Error(`Playbook run not found: ${A}`);return Q}async resolveScopedRunResponse(A){try{return{success:!0,data:await this.requireScopedRun(A)}}catch(Q){return{success:!1,error:Tn0(Q)}}}async requireScopedRun(A){if(A.runId)return this.requireRun(A.runId);let Q=A.conversationId;if(!Q)throw Error("Missing runId and no active conversation id.");let w=await this.store.listActiveByConversation(Q);if(w.length===0)throw Error(`No active playbook run for conversation '${Q}'.`);if(w.length>1)throw Error(`Multiple active playbook runs for conversation '${Q}'. Provide runId explicitly.`);let B=w[0];if(!B)throw Error(`No active playbook run for conversation '${Q}'.`);return B}transitionRequiresGateVerdict(A,Q){return Q==="NEXT"&&A.doneWhen.length>0}hasSatisfiedGateVerdicts(A,Q){return Q.gateVerdicts.some((w)=>w.stateId===A.id&&Sn0(w.goal,A.doneWhen)&&w.met)}getValidTransitions(A,Q,w){return w.transitions.filter((B)=>this.canTransition(A,Q,B.event))}getBlockedTransitions(A,Q,w){let B=new Set(this.getValidTransitions(A,Q,w).map(($)=>`${$.event}\x00${$.target}`));return w.transitions.filter(($)=>!B.has(`${$.event}\x00${$.target}`))}canTransition(A,Q,w){let B=this.buildMachine(A.playbookId,Q,A),$=E1.createActor(B,{...A.snapshot?{snapshot:A.snapshot}:{}});$.start();let f=$.getSnapshot().can({type:w});return $.stop(),f}formatTransition(A){let Q=A.operatorDescription??A.description??A.label;return Q?`- ${A.event} -> ${A.target}: ${Q}`:`- ${A.event} -> ${A.target}`}getState(A,Q){return A.states.find((w)=>w.id===Q)}formatVerifierStatus(A,Q){if(Q.doneWhen.length===0)return"- no gated Done When conditions";let w=A.gateVerdicts.find((B)=>B.stateId===Q.id&&Sn0(B.goal,Q.doneWhen));if(!w)return`- Not yet met: ${Q.doneWhen.join("; ")}`;return w.met?`- Met: ${w.reason}`:`- Not yet met: ${w.reason}`}async buildAgentContextItem(A){let Q=await this.store.findActiveByConversation(A);if(!Q)return;let w=await this.getPlaybook(Q.playbookId);if(!w)return;let B=this.getState(w.body,Q.currentState);if(!B)return;let $=this.getValidTransitions(Q,w.body,B),f=$.filter((L)=>L.operatorAction!==!0),D=$.filter((L)=>L.operatorAction===!0),Y=new Set($.map((L)=>`${L.event}\x00${L.target}`)),X=B.transitions.filter((L)=>!Y.has(`${L.event}\x00${L.target}`)),H=f.map((L)=>this.formatTransition(L)).join(`
8285
8285
  `),W=D.map((L)=>this.formatTransition(L)).join(`
8286
8286
  `),Z=X.map((L)=>this.formatTransition(L)).join(`
@@ -8353,9 +8353,9 @@ ${Object.entries(this.config.lifecycle).map(([Q,w])=>`- ${Q}: playbookId=${w.pla
8353
8353
  ${A.guidance}`:$}}function Ya1(A){return{...A,evidence:A.evidence.map((Q)=>({...Q,data:NKw(Q.data)}))}}function NKw(A){return Object.fromEntries(["entityType","entityId","operation"].flatMap((Q)=>A[Q]!==void 0?[[Q,A[Q]]]:[]))}function jKw(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,...Q.operatorDescription??Q.description?{description:Q.operatorDescription??Q.description}:{}}))}}function MKw(A){if(!A)return"Continuing.";return A.prompt??`Continuing to ${A.title}.`}function Xa1(){return{promptTokens:0,completionTokens:0,totalTokens:0}}function Ha1(A,Q){return A.includes(Q)?A:[...A,Q]}function _Kw(A){return[...A].sort((Q,w)=>(w.completedAt??w.updatedAt).localeCompare(Q.completedAt??Q.updatedAt))[0]}function Tn0(A){return A instanceof Error?A.message:String(A)}function Sn0(A,Q){return A.length===Q.length&&A.every((w,B)=>w===Q[B])}function PKw(A,Q){let w=new Set(Q.map(Wa1));return[...A.filter((B)=>!w.has(Wa1(B))),...Q]}function Wa1(A){return[A.stateId,...A.goal].join("\x00")}function PE(A,Q){let w=A[Q];return typeof w==="string"&&w.length>0?w:void 0}function kKw(A){let Q=Za1(A.entity);if(!Q)return{};let w=Za1(Q.metadata),B=Ka1(w?.title,w?.name,Q.title),$=Ka1(Q.content),f=$?OKw($):void 0;return{...B?{title:B}:{},...f?{contentPreview:f}:{}}}function Za1(A){if(typeof A!=="object"||A===null||Array.isArray(A))return;return A}function Ka1(...A){return A.find((Q)=>typeof Q==="string"&&Q.trim().length>0)?.trim()}function OKw(A){let Q=A.replace(/\s+/g," ").trim();return Q.length>500?`${Q.slice(0,497)}...`:Q}function xKw(A){return{async evaluate(Q){let w=Q.goal.join(`
8354
8354
  `),B=await A.entityService.search({query:w,options:{limit:8,excludeTypes:["playbook"],visibilityScope:p8("anchor")}}),$=RKw(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:VKw});return f}}}function RKw(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)=>hKw(B+1,w)):["No runtime evidence collected for this state."],"","## KB excerpts",...Q.length>0?Q.map((w,B)=>vKw(B+1,w)):["No relevant KB excerpts found."]].join(`
8355
8355
  `)}function hKw(A,Q){return`${A}. ${Q.kind} at ${Q.observedAt}: ${Ga1(Q.data)}`}function vKw(A,Q){return[`${A}. ${Q.entity.entityType}/${Q.entity.id} (score ${Q.score})`,`Excerpt: ${Q.excerpt}`,`Content: ${za1(Q.entity.content,1200)}`,`Metadata: ${Ga1(Q.entity.metadata)}`].join(`
8356
- `)}function Ga1(A){try{return za1(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function za1(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var CKw={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function un0(A={},Q={}){return new mn0(A,Q)}c0();Z0();c0();var cn0=K.enum(["new","planned","in-progress","done","declined"]),ln0=K.enum(["low","medium","high","critical"]),Io=K.object({title:K.string(),status:cn0,priority:ln0.default("medium"),requested:K.number().int().default(1),declinedReason:K.string().optional()}),qa1=K.object({title:K.string(),status:cn0,priority:ln0,requested:K.number().int(),slug:K.string()}),Jo=o1.extend({entityType:K.literal("wish"),metadata:qa1}),pn0=K.object({});c0();Z0();class bo extends I2{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:Jo,frontmatterSchema:Io})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,Io);return{frontmatter:Io.parse(Q),description:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),w=w1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:w}}}}var in0=new bo;Z0();Z0();async function Fa1(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=w1(Q.title);return A.getEntity({entityType:"wish",id:f})}class qD0{logger;context;adapter=new bo;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 Fa1({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:W}=this.adapter.parseWishContent(f.content),Z=H.requested+1,G=this.adapter.createWishContent({...H,requested:Z},W);return await this.context.entityService.updateEntity({entity:{...f,content:G,metadata:{...f.metadata,requested:Z}}}),this.logger.info("Incremented wish request count",{id:f.id,requested:Z}),{success:!0,entityId:f.id,existed:!0,requested:Z}}let D=w1(B),Y=A.options?.priority??"medium",X=this.adapter.createWishContent({title:B,status:"new",priority:Y,requested:1},$);return await this.context.entityService.createEntity({entity:{id:D,entityType:"wish",content:X,metadata:{title:B,status:"new",priority:Y,requested:1,slug:D}}}),this.logger.info("Created new wish",{id:D,title:B}),{success:!0,entityId:D,existed:!1,requested:1}}}var Va1={critical:0,high:1,medium:2,low:3};function Ia1(A){A.sort((Q,w)=>{let B=w.metadata.requested-Q.metadata.requested;if(B!==0)return B;return Va1[Q.metadata.priority]-Va1[w.metadata.priority]})}var Ja1={name:"@brains/wishlist",private:!0,version:"0.2.0-alpha.133",description:"Wishlist plugin for tracking unfulfilled user requests",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class ba1 extends PQ{entityType=in0.entityType;schema=Jo;adapter=in0;constructor(A={}){super("wishlist",Ja1,A,pn0)}async interceptCreate(A,Q,w){let B=await new qD0(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 Ia1(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 qD0(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 EKw(A={}){return new ba1(A)}var FD0=EKw;c0();Z0();c0();var Lo=K.object({title:K.string(),target:K.string()}),La1=K.object({title:K.string(),target:K.string(),slug:K.string().optional()}),No=o1.extend({entityType:K.literal("prompt"),metadata:La1});c0();Z0();class dn0 extends I2{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:No,frontmatterSchema:Lo})}toMarkdown(A){let Q=this.extractBody(A.content),w=this.parseFrontMatter(A.content,Lo);return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,Lo),w=w1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:w}}}}var VD0=new dn0;var Na1={name:"@brains/prompt",private:!0,version:"0.2.0-alpha.133",description:"Prompt entity type \u2014 AI prompts as editable markdown entities",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","bun-types":"latest",typescript:"^5.3.3"}};class nn0 extends PQ{entityType=VD0.entityType;schema=No;adapter=VD0;constructor(){super("prompt",Na1,{},void 0)}getEntityTypeConfig(){return{embeddable:!1}}}function hP(){return new nn0}c0();Z0();class ID0{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 $=await B.json();return{photos:$.results.map(TKw),total:$.total,totalPages:$.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}function TKw(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}}Z0();var ja1={query:K.string().describe("Search terms for stock photos"),perPage:K.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:K.number().min(1).default(1).describe("Page number")},Ma1={photoId:K.string().describe("Photo ID from search results"),downloadLocation:K.string().url().describe("Download tracking URL (required by provider ToS)"),photographerName:K.string().describe("Photographer name for attribution"),photographerUrl:K.string().url().describe("Photographer profile URL for attribution"),sourceUrl:K.string().url().describe("Photo page URL on provider"),imageUrl:K.string().url().describe("Image URL to download"),title:K.string().optional().describe("Image entity title"),alt:K.string().optional().describe("Alt text for the image"),targetEntityType:K.string().optional().describe("Entity type to set cover image on"),targetEntityId:K.string().optional().describe("Entity ID to set cover image on")};function _a1(A,Q){return[SKw(A,Q),mKw(A,Q)]}function SKw(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:ja1,visibility:"anchor",sideEffects:"none",handler:async(w)=>{let B=K.object(ja1).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 mKw(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:Ma1,visibility:"anchor",sideEffects:"external",handler:async(w)=>{let B=K.object(Ma1).safeParse(w);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};let{photoId:$,downloadLocation:f,photographerName:D,photographerUrl:Y,sourceUrl:X,imageUrl:H,title:W,alt:Z,targetEntityType:G,targetEntityId:F}=B.data,V={photographerName:D,photographerUrl:Y,sourceUrl:X},b=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:H}}}});if(b[0]){let _={imageEntityId:b[0].id,alreadyExisted:!0,attribution:V};if(G&&F)await uKw(Q.entityService,G,F,b[0].id),_.coverSet=!0;return{success:!0,data:_}}let L=await Q.jobs.enqueue({type:"select-photo",data:{photoId:$,downloadLocation:f,photographerName:D,photographerUrl:Y,sourceUrl:X,imageUrl:H,...W!==void 0?{title:W}:{},...Z!==void 0?{alt:Z}:{},...G!==void 0?{targetEntityType:G}:{},...F!==void 0?{targetEntityId:F}:{}}}),N={imageEntityId:$,alreadyExisted:!1,attribution:V,jobId:L,status:"generating"};if(G&&F)N.coverSet=!0;return{success:!0,data:N}}}}async function uKw(A,Q,w,B){let $=await A.getEntity({entityType:Q,id:w});if(!$)return;await A.updateEntity({entity:{...$,metadata:{...$.metadata,coverImageId:B}}})}c0();Z0();D4();var cKw=K.object({photoId:K.string(),downloadLocation:K.string().url(),photographerName:K.string(),photographerUrl:K.string().url(),sourceUrl:K.string().url(),imageUrl:K.string().url(),title:K.string().optional(),alt:K.string().optional(),targetEntityType:K.string().optional(),targetEntityId:K.string().optional()});class rn0 extends _w{deps;constructor(A,Q){super(A,{schema:cKw,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=vY.createImageEntity({dataUrl:B,title:$,alt:A.alt??$});await this.reportProgress(w,{progress:75,message:"Saving stock photo"});let{entityId:D}=await this.deps.entityService.createEntity({entity:{id:A.photoId,...f,metadata:{...f.metadata,sourceUrl:A.imageUrl}}}),Y={imageEntityId:D,alreadyExisted:!1};if(A.targetEntityType&&A.targetEntityId)await lKw(this.deps.entityService,A.targetEntityType,A.targetEntityId,D),Y.coverSet=!0;return await this.reportProgress(w,{progress:100,message:"Stock photo selected"}),Y}summarizeDataForLog(A){return{photoId:A.photoId,hasTarget:A.targetEntityType!==void 0}}}async function lKw(A,Q,w,B){let $=await A.getEntity({entityType:Q,id:w});if(!$)return;await A.updateEntity({entity:{...$,metadata:{...$.metadata,coverImageId:B}}})}D4();var Pa1={name:"@brains/stock-photo",private:!0,version:"0.2.0-alpha.133",description:"Stock photo search and selection \u2014 Unsplash provider",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var iKw=K.object({provider:K.enum(["unsplash"]).default("unsplash"),apiKey:K.string().optional().describe("Stock photo provider API key")});class on0 extends RQ{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",Pa1,A,iKw);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=_a1(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??NH,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new rn0(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??NH}))}createProvider(){return new ID0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function sn0(A={},Q={}){return new on0(A,Q)}c0();Z0();c0();c0();Z0();var ka1=K.enum(["ai","foundation","work"]),Oa1=K.object({suffix:ka1,title:K.string(),body:K.string(),linkLabel:K.string(),linkHref:K.string()}),jo=K.object({eyebrow:K.string(),headline:K.string(),cards:K.array(Oa1).min(1)}),JD0=K.object({title:K.string(),slug:K.string(),status:K.enum(["draft","published"])}),Mo=o1.extend({entityType:K.literal("ecosystem-section"),metadata:JD0});class xa1 extends I2{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:Mo,frontmatterSchema:JD0})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var an0=new xa1;Z0();function dKw(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function tn0(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function _o(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function bD0(A){let Q=dKw(A),B=tn0(Q,"Cards").split(/^### Card \d+\s*$/m).map(($)=>$.trim()).filter(Boolean);return jo.parse({eyebrow:tn0(Q,"Eyebrow"),headline:tn0(Q,"Headline"),cards:B.map(($)=>({suffix:_o($,"Suffix"),title:_o($,"Title"),body:_o($,"Body"),linkLabel:_o($,"Link Label"),linkHref:_o($,"Link Href")}))})}function Ra1(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(`
8356
+ `)}function Ga1(A){try{return za1(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function za1(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var CKw={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function un0(A={},Q={}){return new mn0(A,Q)}c0();Z0();c0();var cn0=K.enum(["new","planned","in-progress","done","declined"]),ln0=K.enum(["low","medium","high","critical"]),Io=K.object({title:K.string(),status:cn0,priority:ln0.default("medium"),requested:K.number().int().default(1),declinedReason:K.string().optional()}),qa1=K.object({title:K.string(),status:cn0,priority:ln0,requested:K.number().int(),slug:K.string()}),Jo=o1.extend({entityType:K.literal("wish"),metadata:qa1}),pn0=K.object({});c0();Z0();class bo extends I2{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:Jo,frontmatterSchema:Io})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,Io);return{frontmatter:Io.parse(Q),description:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),w=w1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:w}}}}var in0=new bo;Z0();Z0();async function Fa1(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=w1(Q.title);return A.getEntity({entityType:"wish",id:f})}class qD0{logger;context;adapter=new bo;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 Fa1({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:W}=this.adapter.parseWishContent(f.content),Z=H.requested+1,G=this.adapter.createWishContent({...H,requested:Z},W);return await this.context.entityService.updateEntity({entity:{...f,content:G,metadata:{...f.metadata,requested:Z}}}),this.logger.info("Incremented wish request count",{id:f.id,requested:Z}),{success:!0,entityId:f.id,existed:!0,requested:Z}}let D=w1(B),Y=A.options?.priority??"medium",X=this.adapter.createWishContent({title:B,status:"new",priority:Y,requested:1},$);return await this.context.entityService.createEntity({entity:{id:D,entityType:"wish",content:X,metadata:{title:B,status:"new",priority:Y,requested:1,slug:D}}}),this.logger.info("Created new wish",{id:D,title:B}),{success:!0,entityId:D,existed:!1,requested:1}}}var Va1={critical:0,high:1,medium:2,low:3};function Ia1(A){A.sort((Q,w)=>{let B=w.metadata.requested-Q.metadata.requested;if(B!==0)return B;return Va1[Q.metadata.priority]-Va1[w.metadata.priority]})}var Ja1={name:"@brains/wishlist",private:!0,version:"0.2.0-alpha.134",description:"Wishlist plugin for tracking unfulfilled user requests",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class ba1 extends PQ{entityType=in0.entityType;schema=Jo;adapter=in0;constructor(A={}){super("wishlist",Ja1,A,pn0)}async interceptCreate(A,Q,w){let B=await new qD0(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 Ia1(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 qD0(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 EKw(A={}){return new ba1(A)}var FD0=EKw;c0();Z0();c0();var Lo=K.object({title:K.string(),target:K.string()}),La1=K.object({title:K.string(),target:K.string(),slug:K.string().optional()}),No=o1.extend({entityType:K.literal("prompt"),metadata:La1});c0();Z0();class dn0 extends I2{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:No,frontmatterSchema:Lo})}toMarkdown(A){let Q=this.extractBody(A.content),w=this.parseFrontMatter(A.content,Lo);return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,Lo),w=w1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:w}}}}var VD0=new dn0;var Na1={name:"@brains/prompt",private:!0,version:"0.2.0-alpha.134",description:"Prompt entity type \u2014 AI prompts as editable markdown entities",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","bun-types":"latest",typescript:"^5.3.3"}};class nn0 extends PQ{entityType=VD0.entityType;schema=No;adapter=VD0;constructor(){super("prompt",Na1,{},void 0)}getEntityTypeConfig(){return{embeddable:!1}}}function hP(){return new nn0}c0();Z0();class ID0{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 $=await B.json();return{photos:$.results.map(TKw),total:$.total,totalPages:$.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}function TKw(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}}Z0();var ja1={query:K.string().describe("Search terms for stock photos"),perPage:K.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:K.number().min(1).default(1).describe("Page number")},Ma1={photoId:K.string().describe("Photo ID from search results"),downloadLocation:K.string().url().describe("Download tracking URL (required by provider ToS)"),photographerName:K.string().describe("Photographer name for attribution"),photographerUrl:K.string().url().describe("Photographer profile URL for attribution"),sourceUrl:K.string().url().describe("Photo page URL on provider"),imageUrl:K.string().url().describe("Image URL to download"),title:K.string().optional().describe("Image entity title"),alt:K.string().optional().describe("Alt text for the image"),targetEntityType:K.string().optional().describe("Entity type to set cover image on"),targetEntityId:K.string().optional().describe("Entity ID to set cover image on")};function _a1(A,Q){return[SKw(A,Q),mKw(A,Q)]}function SKw(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:ja1,visibility:"anchor",sideEffects:"none",handler:async(w)=>{let B=K.object(ja1).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 mKw(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:Ma1,visibility:"anchor",sideEffects:"external",handler:async(w)=>{let B=K.object(Ma1).safeParse(w);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};let{photoId:$,downloadLocation:f,photographerName:D,photographerUrl:Y,sourceUrl:X,imageUrl:H,title:W,alt:Z,targetEntityType:G,targetEntityId:F}=B.data,V={photographerName:D,photographerUrl:Y,sourceUrl:X},b=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:H}}}});if(b[0]){let _={imageEntityId:b[0].id,alreadyExisted:!0,attribution:V};if(G&&F)await uKw(Q.entityService,G,F,b[0].id),_.coverSet=!0;return{success:!0,data:_}}let L=await Q.jobs.enqueue({type:"select-photo",data:{photoId:$,downloadLocation:f,photographerName:D,photographerUrl:Y,sourceUrl:X,imageUrl:H,...W!==void 0?{title:W}:{},...Z!==void 0?{alt:Z}:{},...G!==void 0?{targetEntityType:G}:{},...F!==void 0?{targetEntityId:F}:{}}}),N={imageEntityId:$,alreadyExisted:!1,attribution:V,jobId:L,status:"generating"};if(G&&F)N.coverSet=!0;return{success:!0,data:N}}}}async function uKw(A,Q,w,B){let $=await A.getEntity({entityType:Q,id:w});if(!$)return;await A.updateEntity({entity:{...$,metadata:{...$.metadata,coverImageId:B}}})}c0();Z0();D4();var cKw=K.object({photoId:K.string(),downloadLocation:K.string().url(),photographerName:K.string(),photographerUrl:K.string().url(),sourceUrl:K.string().url(),imageUrl:K.string().url(),title:K.string().optional(),alt:K.string().optional(),targetEntityType:K.string().optional(),targetEntityId:K.string().optional()});class rn0 extends _w{deps;constructor(A,Q){super(A,{schema:cKw,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=vY.createImageEntity({dataUrl:B,title:$,alt:A.alt??$});await this.reportProgress(w,{progress:75,message:"Saving stock photo"});let{entityId:D}=await this.deps.entityService.createEntity({entity:{id:A.photoId,...f,metadata:{...f.metadata,sourceUrl:A.imageUrl}}}),Y={imageEntityId:D,alreadyExisted:!1};if(A.targetEntityType&&A.targetEntityId)await lKw(this.deps.entityService,A.targetEntityType,A.targetEntityId,D),Y.coverSet=!0;return await this.reportProgress(w,{progress:100,message:"Stock photo selected"}),Y}summarizeDataForLog(A){return{photoId:A.photoId,hasTarget:A.targetEntityType!==void 0}}}async function lKw(A,Q,w,B){let $=await A.getEntity({entityType:Q,id:w});if(!$)return;await A.updateEntity({entity:{...$,metadata:{...$.metadata,coverImageId:B}}})}D4();var Pa1={name:"@brains/stock-photo",private:!0,version:"0.2.0-alpha.134",description:"Stock photo search and selection \u2014 Unsplash provider",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var iKw=K.object({provider:K.enum(["unsplash"]).default("unsplash"),apiKey:K.string().optional().describe("Stock photo provider API key")});class on0 extends RQ{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",Pa1,A,iKw);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=_a1(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??NH,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new rn0(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??NH}))}createProvider(){return new ID0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function sn0(A={},Q={}){return new on0(A,Q)}c0();Z0();c0();c0();Z0();var ka1=K.enum(["ai","foundation","work"]),Oa1=K.object({suffix:ka1,title:K.string(),body:K.string(),linkLabel:K.string(),linkHref:K.string()}),jo=K.object({eyebrow:K.string(),headline:K.string(),cards:K.array(Oa1).min(1)}),JD0=K.object({title:K.string(),slug:K.string(),status:K.enum(["draft","published"])}),Mo=o1.extend({entityType:K.literal("ecosystem-section"),metadata:JD0});class xa1 extends I2{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:Mo,frontmatterSchema:JD0})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var an0=new xa1;Z0();function dKw(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function tn0(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function _o(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function bD0(A){let Q=dKw(A),B=tn0(Q,"Cards").split(/^### Card \d+\s*$/m).map(($)=>$.trim()).filter(Boolean);return jo.parse({eyebrow:tn0(Q,"Eyebrow"),headline:tn0(Q,"Headline"),cards:B.map(($)=>({suffix:_o($,"Suffix"),title:_o($,"Title"),body:_o($,"Body"),linkLabel:_o($,"Link Label"),linkHref:_o($,"Link Href")}))})}function Ra1(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(`
8357
8357
  `)}var nKw=K.object({query:K.object({id:K.string().optional()}).optional()}).passthrough();class LD0{id="rizom-ecosystem:entities";name="Rizom Ecosystem";description="Fetches an ecosystem-section entity for rendering";async fetch(A,Q,w){let $=nKw.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(bD0(f.content))}}c0();var rKw=p$0({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 Az(...A){return rKw(Ay(A))}import{jsxDEV as F86}from"preact/jsx-dev-runtime";import{jsxDEV as b86}from"preact/jsx-dev-runtime";import{jsxDEV as M86}from"preact/jsx-dev-runtime";import{jsxDEV as sKw}from"preact/jsx-dev-runtime";var en0="px-6 md:px-10 xl:px-20",oKw=`${en0} relative z-[1]`,Ar0=({id:A,className:Q,children:w})=>sKw("section",{id:A,className:Az(oKw,Q),children:w},void 0,!1,void 0,this);import{jsxDEV as ND0}from"preact/jsx-dev-runtime";var aKw=new Map([["work","text-accent"],["foundation","text-secondary"],["ai","text-accent-bright"]]),Po=({name:A="rizom",brandSuffix:Q,className:w,dotClassName:B,suffixClassName:$})=>{let f=aKw.get(Q);return ND0("span",{className:Az("inline-flex items-baseline gap-0 font-display font-medium tracking-[-0.015em] [font-variation-settings:'opsz'_24]",w),children:[ND0("span",{className:"text-theme",children:A},void 0,!1,void 0,this),ND0("span",{className:Az(f??"text-accent",B),children:"."},void 0,!1,void 0,this),ND0("span",{className:Az("italic font-normal text-theme-muted",$),children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as g86}from"preact/jsx-dev-runtime";import{jsxDEV as u86}from"preact/jsx-dev-runtime";import{jsxDEV as i86,Fragment as p86}from"preact/jsx-dev-runtime";import{jsxDEV as r86}from"preact/jsx-dev-runtime";import{Fragment as Qr0}from"preact";import{jsxDEV as ko}from"preact/jsx-dev-runtime";var tKw=/(\*[^*]+\*)/;function wr0(A,Q){let w=A.split(`
8358
- `);return ko(Qr0,{children:w.map((B,$)=>ko(Qr0,{children:[$>0&&ko("br",{},void 0,!1,void 0,this),B.split(tKw).map((f,D)=>{if(f.length>=3&&f.startsWith("*")&&f.endsWith("*"))return ko("span",{className:Q,children:f.slice(1,-1)},D,!1,void 0,this);return ko(Qr0,{children:f},D,!1,void 0,this)})]},$,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as cD,Fragment as HUw}from"preact/jsx-dev-runtime";var eKw="italic text-accent font-normal",AUw="You are here",QUw={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},wUw={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},BUw={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},$Uw="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",fUw="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",DUw="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",YUw="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",XUw=({card:A})=>{let Q=A.linkLabel===AUw,w=A.linkHref.trim().length===0,B=cD(HUw,{children:[cD(Po,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),cD("span",{className:`${$Uw} ${QUw[A.suffix]}`,children:A.title},void 0,!1,void 0,this),cD("p",{className:fUw,children:A.body},void 0,!1,void 0,this),Q?cD("span",{className:YUw,children:A.linkLabel},void 0,!1,void 0,this):cD("span",{className:DUw,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?wUw[A.suffix]:"border-white/10"}`;return Q||w?cD("div",{className:$,children:B},void 0,!1,void 0,this):cD("a",{href:A.linkHref,className:`${$} text-inherit no-underline transition-colors ${BUw[A.suffix]}`,children:B},void 0,!1,void 0,this)},Br0=({eyebrow:A,headline:Q,cards:w})=>cD(Ar0,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[cD("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[cD("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),cD("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:wr0(Q,eKw)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),cD("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)=>cD(XUw,{card:B},B.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);var WUw=[{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 ha1(A){return{eyebrow:"The Ecosystem",headline:"One practice. *Three faces.*",cards:WUw.map((Q)=>Q.suffix===A?{...Q,linkLabel:"You are here",linkHref:""}:Q)}}var ZUw=ha1();var $r0=R1({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:jo,formatter:{parse:bD0,format:Ra1},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:Br0}});var va1={name:"@brains/rizom-ecosystem",private:!0,version:"0.2.0-alpha.133",description:"Entity-backed Rizom ecosystem section",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts,.tsx","lint:fix":"eslint . --ext .ts,.tsx --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@rizom/ui":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class fr0 extends PQ{entityType="ecosystem-section";schema=Mo;adapter=an0;constructor(A={}){super("rizom-ecosystem",va1,A,K.object({}).default({}))}getTemplates(){return{ecosystem:$r0}}getDataSources(){return[new LD0]}}function vP(A={}){return new fr0(A)}Z0();c0();c0();Z0();l$();Z0();c0();var K9="agent",Ca1="agent-discovery";var ya1="agent-network",Ea1="AgentNetworkWidget",Oo="agent-discovery:entities",Dr0="agent-list",Yr0="agent-detail",z5="skill",ga1="skill",jD0="skill-derivation",Ta1="skill:project",Sa1="skill-derivation",ma1="skill:skill-derivation",ua1="skills";var kE=K.object({name:K.string(),description:K.string(),tags:K.array(K.string())}),HW=K.enum(["discovered","approved"]).describe("Discovered for review or approved for calling"),jK=QZ.pick({name:!0,kind:!0,organization:!0}).extend({brainName:K.string().describe("Name of the brain instance"),url:K.string().url().describe("Brain endpoint URL"),did:K.string().optional().describe("Decentralized identifier (public)"),repoDid:K.string().optional().describe("ATProto repo DID"),brainDid:K.string().optional().describe("ATProto brain DID"),anchorDid:K.string().optional().describe("ATProto anchor DID"),cardUri:K.string().optional().describe("ATProto brain card URI"),cardCid:K.string().optional().describe("ATProto brain card CID"),a2aEndpoint:K.string().url().optional().describe("A2A endpoint URL"),status:HW,discoveredAt:K.string().datetime().describe("When this agent was first discovered")}),ca1=jK.pick({name:!0,url:!0,status:!0}).extend({discoveredAt:K.string().datetime().optional(),slug:K.string(),repoDid:K.string().optional(),brainDid:K.string().optional(),anchorDid:K.string().optional(),cardUri:K.string().optional(),cardCid:K.string().optional(),a2aEndpoint:K.string().url().optional()}),OE=o1.extend({entityType:K.literal(K9),metadata:ca1}),xo=OE.extend({frontmatter:jK,about:K.string(),skills:K.array(kE),notes:K.string()}),xE=xo.extend({url:K.string().optional(),typeLabel:K.string().optional()}),UUw=xo.extend({url:K.string(),typeLabel:K.string()});Z0();var GUw=K.array(kE);function la1(A){let Q=GUw.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(`
8358
+ `);return ko(Qr0,{children:w.map((B,$)=>ko(Qr0,{children:[$>0&&ko("br",{},void 0,!1,void 0,this),B.split(tKw).map((f,D)=>{if(f.length>=3&&f.startsWith("*")&&f.endsWith("*"))return ko("span",{className:Q,children:f.slice(1,-1)},D,!1,void 0,this);return ko(Qr0,{children:f},D,!1,void 0,this)})]},$,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as cD,Fragment as HUw}from"preact/jsx-dev-runtime";var eKw="italic text-accent font-normal",AUw="You are here",QUw={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},wUw={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},BUw={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},$Uw="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",fUw="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",DUw="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",YUw="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",XUw=({card:A})=>{let Q=A.linkLabel===AUw,w=A.linkHref.trim().length===0,B=cD(HUw,{children:[cD(Po,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),cD("span",{className:`${$Uw} ${QUw[A.suffix]}`,children:A.title},void 0,!1,void 0,this),cD("p",{className:fUw,children:A.body},void 0,!1,void 0,this),Q?cD("span",{className:YUw,children:A.linkLabel},void 0,!1,void 0,this):cD("span",{className:DUw,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?wUw[A.suffix]:"border-white/10"}`;return Q||w?cD("div",{className:$,children:B},void 0,!1,void 0,this):cD("a",{href:A.linkHref,className:`${$} text-inherit no-underline transition-colors ${BUw[A.suffix]}`,children:B},void 0,!1,void 0,this)},Br0=({eyebrow:A,headline:Q,cards:w})=>cD(Ar0,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[cD("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[cD("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),cD("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:wr0(Q,eKw)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),cD("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)=>cD(XUw,{card:B},B.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);var WUw=[{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 ha1(A){return{eyebrow:"The Ecosystem",headline:"One practice. *Three faces.*",cards:WUw.map((Q)=>Q.suffix===A?{...Q,linkLabel:"You are here",linkHref:""}:Q)}}var ZUw=ha1();var $r0=R1({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:jo,formatter:{parse:bD0,format:Ra1},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:Br0}});var va1={name:"@brains/rizom-ecosystem",private:!0,version:"0.2.0-alpha.134",description:"Entity-backed Rizom ecosystem section",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts,.tsx","lint:fix":"eslint . --ext .ts,.tsx --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@rizom/ui":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class fr0 extends PQ{entityType="ecosystem-section";schema=Mo;adapter=an0;constructor(A={}){super("rizom-ecosystem",va1,A,K.object({}).default({}))}getTemplates(){return{ecosystem:$r0}}getDataSources(){return[new LD0]}}function vP(A={}){return new fr0(A)}Z0();c0();c0();Z0();l$();Z0();c0();var K9="agent",Ca1="agent-discovery";var ya1="agent-network",Ea1="AgentNetworkWidget",Oo="agent-discovery:entities",Dr0="agent-list",Yr0="agent-detail",z5="skill",ga1="skill",jD0="skill-derivation",Ta1="skill:project",Sa1="skill-derivation",ma1="skill:skill-derivation",ua1="skills";var kE=K.object({name:K.string(),description:K.string(),tags:K.array(K.string())}),HW=K.enum(["discovered","approved"]).describe("Discovered for review or approved for calling"),jK=QZ.pick({name:!0,kind:!0,organization:!0}).extend({brainName:K.string().describe("Name of the brain instance"),url:K.string().url().describe("Brain endpoint URL"),did:K.string().optional().describe("Decentralized identifier (public)"),repoDid:K.string().optional().describe("ATProto repo DID"),brainDid:K.string().optional().describe("ATProto brain DID"),anchorDid:K.string().optional().describe("ATProto anchor DID"),cardUri:K.string().optional().describe("ATProto brain card URI"),cardCid:K.string().optional().describe("ATProto brain card CID"),a2aEndpoint:K.string().url().optional().describe("A2A endpoint URL"),status:HW,discoveredAt:K.string().datetime().describe("When this agent was first discovered")}),ca1=jK.pick({name:!0,url:!0,status:!0}).extend({discoveredAt:K.string().datetime().optional(),slug:K.string(),repoDid:K.string().optional(),brainDid:K.string().optional(),anchorDid:K.string().optional(),cardUri:K.string().optional(),cardCid:K.string().optional(),a2aEndpoint:K.string().url().optional()}),OE=o1.extend({entityType:K.literal(K9),metadata:ca1}),xo=OE.extend({frontmatter:jK,about:K.string(),skills:K.array(kE),notes:K.string()}),xE=xo.extend({url:K.string().optional(),typeLabel:K.string().optional()}),UUw=xo.extend({url:K.string(),typeLabel:K.string()});Z0();var GUw=K.array(kE);function la1(A){let Q=GUw.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(`
8359
8359
  `)}function pa1(A){if(!A.trim())return[];let Q=[];for(let w of A.split(`
8360
8360
  `)){let B=w.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/);if(!B)continue;let $=B[1]??"",f=B[2]??"",D=B[3],Y=D?D.split(",").map((X)=>X.trim()).filter(Boolean):[];Q.push({name:$,description:f,tags:Y})}return Q}var zUw=K.object({about:K.string(),skills:K.array(kE),notes:K.string()}),ia1=new pw(zUw,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:la1,parser:pa1},{key:"notes",label:"Notes",type:"string"}]});class k4 extends I2{constructor(){super({entityType:K9,purpose:"A saved remote peer-brain contact in the local agent directory.",schema:OE,frontmatterSchema:jK})}fromMarkdown(A){let Q=this.parseFrontMatter(A,jK),w=jV(Q.url);return{content:A,entityType:K9,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:HW.parse(A.status),discoveredAt:A.discoveredAt},w=ia1.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=ia1.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,jK),body:this.parseAgentContent(A.content)}}}c0();var qUw=new k4,FUw=qU.extend({status:HW.optional()}),VUw=FU.extend({query:FUw.optional()});function IUw(A){let Q=v2(A.content,jK),w=qUw.parseAgentContent(A.content);return xo.parse({...A,frontmatter:Q.metadata,about:w.about,skills:w.skills,notes:w.notes})}class MD0 extends W${id=Oo;name="Agent Directory DataSource";description="Fetches and transforms agent entities for rendering";config={entityType:K9,defaultSort:[{field:"discoveredAt",direction:"desc"}],defaultLimit:50,lookupField:"slug",enableNavigation:!0};constructor(A){super(A)}transformEntity(A){return IUw(A)}buildDetailResult(A,Q){return{agent:A,prevAgent:Q?.prev??null,nextAgent:Q?.next??null}}parseQuery(A){let Q=VUw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}buildListResult(A,Q,w){let B=HW.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))}}c0();Z0();CB();c0();async function _D0(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 ES(f)}catch{return null}}function Ro(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""}Z0();var JUw=new k4;function da1(A){return A.trim().toLowerCase().replace(/[_\s]+/g,"-")}function Eb(A){let Q=new Set,w=[];for(let B of A){let $=da1(B);if(!$||Q.has($))continue;Q.add($),w.push($)}return w}function bUw(A,Q){if(Q.count!==A.count)return Q.count-A.count;return A.tag.localeCompare(Q.tag)}async function na1(A,Q={}){let w=Q.minCount??1,B=Q.topN??12,$=Q.visibilityScope??"public",f=new Map,[D,Y]=await Promise.all([A.entityService.listEntities({entityType:z5,options:{filter:{visibilityScope:$}}}),A.entityService.listEntities({entityType:K9,options:{filter:{visibilityScope:$}}})]),X=(H)=>{for(let W of Eb(H))f.set(W,(f.get(W)??0)+1)};for(let H of D)X(H.metadata.tags);for(let H of Y){let W=JUw.parseAgentContent(H.content);X(W.skills.flatMap((Z)=>Z.tags))}return Array.from(f.entries()).map(([H,W])=>({tag:H,count:W})).filter((H)=>H.count>=w).sort(bUw).slice(0,B)}function ra1(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(`
8361
8361
  `)}var LUw=new k4;function PD0(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",D=new Date().toISOString();return{content:LUw.createAgentContent({name:w,kind:B,...A.anchor?.organization&&{organization:A.anchor.organization},brainName:A.brainName,url:A.url,status:f,discoveredAt:D,about:$.join(`
@@ -8456,7 +8456,7 @@ ${A.guidance}`:$}}function Ya1(A){return{...A,evidence:A.evidence.map((Q)=>({...
8456
8456
  setTagFilter("all");
8457
8457
  });
8458
8458
  })();`;import{jsxDEV as Aw}from"preact/jsx-dev-runtime";function RUw({item:A}){return Aw("li",{class:"list-item",children:[Aw("div",{class:"list-main",children:[Aw("span",{class:"list-name",children:A.name},void 0,!1,void 0,this),Aw("span",{class:"list-desc",children:A.description},void 0,!1,void 0,this),A.tags.length>0&&Aw("div",{class:"list-tags",children:A.tags.map((Q)=>Aw("span",{class:"tag",children:Q},`${A.id}:${Q}`,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Aw("div",{class:"list-meta",children:A.status==="discovered"&&Aw("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 hUw({item:A}){return Aw("li",{class:"list-item agent-network-skill-row","data-agent-network-skill-row":!0,"data-agent-network-tags":JSON.stringify(A.tags),children:[Aw("div",{class:"list-main",children:Aw("span",{class:"list-name",children:A.name},void 0,!1,void 0,this)},void 0,!1,void 0,this),Aw("div",{class:"list-meta",children:Aw("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 vUw({kind:A,items:Q,active:w}){return Aw("div",{class:`agent-network-panel${w?" is-active":""}`,"data-agent-network-panel":A,children:Q.length>0?Aw("ul",{class:"list agent-network-list",children:Q.map((B)=>Aw(RUw,{item:B},B.id,!1,void 0,this))},void 0,!1,void 0,this):Aw("p",{class:"agent-network-empty",children:"Nothing to show yet."},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function CUw({skills:A,count:Q,filters:w}){return Aw("div",{class:"agent-network-panel","data-agent-network-panel":"skills",children:[Aw("div",{class:"agent-network-filter-row",role:"tablist","aria-label":"Filter skills by tag",children:[Aw("button",{class:"agent-network-filter is-active",type:"button","data-agent-network-tag-filter":"all","aria-pressed":"true",children:[Aw("span",{class:"count",children:Q},void 0,!1,void 0,this),Aw("span",{class:"label",children:"all"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),w.map((B)=>Aw("button",{class:`agent-network-filter${B.variant==="gap"?" is-gap":""}`,type:"button","data-agent-network-tag-filter":B.tag,"aria-pressed":"false",children:[Aw("span",{class:"count",children:B.count},void 0,!1,void 0,this),Aw("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?Aw("ul",{class:"list agent-network-list agent-network-skills-list",children:A.map((B)=>Aw(hUw,{item:B},B.id,!1,void 0,this))},void 0,!1,void 0,this):Aw("p",{class:"agent-network-empty",children:"Nothing to show yet."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Wr0({data:A}){let Q=ea1.safeParse(A);if(!Q.success)return Aw("p",{class:"muted",children:"Nothing to show yet."},void 0,!1,void 0,this);let w=Q.data;return Aw("div",{"data-agent-network-widget":!0,"data-agent-network-view":"agents",children:[Aw("div",{class:"agent-network-view-tabs",role:"tablist","aria-label":"Browse the agent network",children:[Aw("button",{class:"agent-network-view-tab is-active",type:"button","data-agent-network-view-tab":"agents","aria-pressed":"true",children:["Agents",Aw("span",{class:"agent-network-view-count",children:w.counts.agents},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Aw("button",{class:"agent-network-view-tab",type:"button","data-agent-network-view-tab":"skills","aria-pressed":"false",children:["Skills",Aw("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),Aw("div",{class:"agent-network-kind-tabs",role:"tablist","aria-label":"Filter agents by kind",children:Hr0.map((B)=>{let $=B==="all";return Aw("button",{class:`agent-network-kind-tab${$?" is-active":""}`,type:"button","data-agent-network-kind-tab":B,"aria-pressed":$?"true":"false",children:[Aw("span",{class:"agent-network-kind-count",children:w.agents[B].length},void 0,!1,void 0,this),Aw("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),Hr0.map((B)=>Aw(vUw,{kind:B,items:w.agents[B],active:B==="all"},B,!1,void 0,this)),Aw(CUw,{skills:w.skills,count:w.counts.skills,filters:w.skillFilters},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Qt1(A,Q){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:ya1,pluginId:Q,title:"Agent Network",section:"secondary",priority:15,rendererName:Ea1,component:Wr0,clientScript:OD0,dataProvider:async()=>At1(A)}}),{success:!0}})}Z0();var wt1=new k4;function yUw(A){return A.skills.map((Q)=>({name:Q.name,description:Q.description,tags:Q.tags??[]}))}function EUw(A){return new URL(A).hostname}function gUw(A){return[`ATProto card: ${A.uri}`,`ATProto card CID: ${A.cid}`,`ATProto repo DID: ${A.repoDid}`].join(`
8459
- `)}function TUw(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 SUw(A,Q,w){await A.messaging.send({type:Q,payload:w,broadcast:!0})}async function mUw(A,Q,w=new Date().toISOString()){let{record:B}=Q,$=EUw(B.siteUrl),f=await A.entityService.getEntity({entityType:"agent",id:$}),D=f?wt1.parseEntity(f):void 0,Y=B.brain.did,X=B.anchor.did,H=yUw(B),W=f?.metadata.status??"discovered",Z=f?.metadata.url??B.siteUrl,G=f?.metadata.slug??jV(Z),F=f?.metadata.name??B.anchor.name,V=D?.frontmatter.kind??B.anchor.kind,b=f?.metadata.discoveredAt??w,L=B.brain.purpose||D?.body.about||"",N=H.length>0?H:D?.body.skills??[],_={...f?.metadata??{},name:F,url:Z,status:W,discoveredAt:b,slug:G,repoDid:Q.repoDid,...Y&&{brainDid:Y},...X&&{anchorDid:X},cardUri:Q.uri,cardCid:Q.cid},j=wt1.createAgentContent({name:F,kind:V,...D?.frontmatter.organization&&{organization:D.frontmatter.organization},brainName:B.brain.name,url:Z,...Y&&{did:Y,brainDid:Y},...X&&{anchorDid:X},repoDid:Q.repoDid,cardUri:Q.uri,cardCid:Q.cid,...D?.frontmatter.a2aEndpoint&&{a2aEndpoint:D.frontmatter.a2aEndpoint},status:W,discoveredAt:b,about:L,skills:N,notes:gUw({repoDid:Q.repoDid,uri:Q.uri,cid:Q.cid})});if(f){let E={...f,content:j,metadata:_,updated:w};return await A.entityService.updateEntity({entity:E}),{agent:E,created:!1}}let g={id:$,entityType:"agent",content:j,metadata:_,contentHash:"",visibility:"public",created:w,updated:w};return await A.entityService.createEntity({entity:g}),{agent:g,created:!0}}function Bt1(A){A.messaging.subscribe(M40,async(Q)=>{let w=Sp1.parse(Q.payload),B=await mUw(A,w),$=TUw({agent:B.agent,repoDid:w.repoDid,uri:w.uri,cid:w.cid,record:w.record});return await SUw(A,B.created?gp1:Tp1,$),{success:!0,data:$}})}function $t1(){return["Agent entities represent saved peer-brain contacts in the local agent directory. List saved agent contacts with system_list on entityType agent.","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 calls.","Agent lifecycle is tracked with status fields such as discovered, approved, and archived; approval and archive operations are system_update field changes for already saved discovered contacts. If the user asks to approve or archive a saved agent contact by exact id such as approval-candidate.io or old-agent.io, call system_update on entityType agent with that id and the requested status; do not use agent_connect for approval.","Calling remote agents and saving local contact records are separate capabilities. Archived agents are not active call targets."].join(" ")}c0();JB();Z0();import{jsxDEV as ft1}from"preact/jsx-dev-runtime";function xD0(A){try{return new URL(A).hostname}catch{return A}}var RD0=({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 ft1("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)},hD0=({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 ft1("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 j2,Fragment as lUw}from"preact/jsx-dev-runtime";var uUw=({skills:A})=>{if(A.length===0)return null;return j2("div",{className:"flex gap-1.5 flex-wrap mt-2",children:A.map((Q)=>j2("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 cUw(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric"})}function Dt1(A,Q,w){let B=new URLSearchParams({status:Q});if(w>1)B.set("page",String(w));return`${A}?${B.toString()}`}var Zr0=({agent:A})=>{let{frontmatter:Q,about:w,skills:B,url:$}=A,f=Q.status==="approved";return j2("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:[j2(RD0,{name:Q.name,className:"w-12 h-12 text-lg"},void 0,!1,void 0,this),j2("div",{className:"flex-1 min-w-0",children:[j2("div",{className:"flex items-center gap-2 mb-1 flex-wrap",children:[j2("span",{className:"text-lg font-semibold text-heading",children:Q.name},void 0,!1,void 0,this),j2(hD0,{kind:Q.kind,size:"sm"},void 0,!1,void 0,this),Q.organization&&j2("span",{className:"text-xs text-theme-muted",children:["\xB7 ",Q.organization]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"text-sm text-theme-muted mb-1",children:Q.brainName},void 0,!1,void 0,this),w&&j2("p",{className:"text-sm text-theme-muted line-clamp-2 mb-0",children:w},void 0,!1,void 0,this),f&&j2(uUw,{skills:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"flex flex-col items-end gap-1 flex-shrink-0 text-right",children:[j2("span",{className:"text-xs text-theme-muted",children:xD0(Q.url)},void 0,!1,void 0,this),j2("span",{className:"text-[11px] text-theme-muted opacity-60",children:f?`Discovered ${cUw(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)},Yt1=({agents:A,pageTitle:Q,pagination:w,baseUrl:B="/agents",selectedStatus:$})=>{let f=Q??"Agent Directory",D=w?.totalItems??A.length,Y=A.filter((G)=>G.frontmatter.status==="approved"),X=A.filter((G)=>G.frontmatter.status==="discovered"),H=Y.length,W=X.length,Z=`Your network of ${D} ${D===1?"brain":"brains"} and their anchors`;return j2(lUw,{children:[j2(NQ,{title:f,description:Z},void 0,!1,void 0,this),j2("div",{className:"agent-list bg-theme",children:j2("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[j2("div",{className:"mb-8 pb-6 border-b border-theme",children:[j2("h1",{className:"text-4xl font-bold text-heading mb-2",children:f},void 0,!1,void 0,this),j2("p",{className:"text-theme-muted mb-4",children:Z},void 0,!1,void 0,this),j2("div",{className:"flex flex-wrap gap-2 text-sm mb-4",children:[j2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-heading",children:[D," total"]},void 0,!0,void 0,this),j2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-status-success",children:[H," approved"]},void 0,!0,void 0,this),j2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-theme-muted",children:[W," discovered"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"flex flex-wrap gap-2 text-sm",children:[j2("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),j2("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),j2("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"&&Y.length>0&&j2("section",{className:"mb-10",children:[j2("div",{className:"flex items-center justify-between mb-4",children:[j2("h2",{className:"text-lg font-semibold text-heading",children:"Approved brains"},void 0,!1,void 0,this),j2("span",{className:"text-sm text-theme-muted",children:Y.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"flex flex-col gap-4",children:Y.map((G)=>j2(Zr0,{agent:G},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$==="all"&&X.length>0&&j2("section",{children:[j2("div",{className:"flex items-center justify-between mb-4",children:[j2("div",{children:[j2("h2",{className:"text-lg font-semibold text-heading",children:"Discovered brains"},void 0,!1,void 0,this),j2("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),j2("span",{className:"text-sm text-theme-muted",children:X.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"flex flex-col gap-4",children:X.map((G)=>j2(Zr0,{agent:G},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$!=="all"&&A.length>0&&j2("section",{children:[j2("div",{className:"flex items-center justify-between mb-4",children:[j2("h2",{className:"text-lg font-semibold text-heading",children:$==="approved"?"Approved brains":"Discovered brains"},void 0,!1,void 0,this),j2("span",{className:"text-sm text-theme-muted",children:A.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"flex flex-col gap-4",children:A.map((G)=>j2(Zr0,{agent:G},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length===0&&j2("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"&&j2("div",{className:"mt-12",children:j2(d3,{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"&&j2("nav",{"aria-label":"Pagination",className:"flex items-center justify-center gap-3 mt-12",children:[w.hasPrevPage?j2("a",{href:Dt1(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):j2("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),j2("span",{className:"text-sm text-theme-muted",children:["Page ",w.currentPage," of ",w.totalPages]},void 0,!0,void 0,this),w.hasNextPage?j2("a",{href:Dt1(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):j2("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 U2,Fragment as nUw}from"preact/jsx-dev-runtime";function pUw(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}var ho=({children:A})=>U2("h2",{className:"text-sm font-semibold text-theme-muted uppercase tracking-wide mb-3",children:A},void 0,!1,void 0,this),iUw=({skill:A})=>U2("div",{className:"flex items-start gap-3 px-4 py-3 bg-theme-subtle rounded-lg",children:[U2("div",{className:"flex-1",children:[U2("div",{className:"text-sm font-semibold text-heading",children:A.name},void 0,!1,void 0,this),U2("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&&U2("div",{className:"flex gap-1 flex-shrink-0",children:A.tags.map((Q)=>U2("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),dUw=({label:A,value:Q,valueClassName:w})=>U2("div",{className:"flex justify-between text-[13px]",children:[U2("span",{className:"text-theme-muted",children:A},void 0,!1,void 0,this),U2("span",{className:w??"text-heading",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Xt1=({agent:A,prevAgent:Q,nextAgent:w})=>{let{frontmatter:B,about:$,skills:f,notes:D}=A,Y=xD0(B.url),X=B.status==="approved";return U2(nUw,{children:[U2(NQ,{title:B.name,description:$||`Agent profile for ${B.name}`},void 0,!1,void 0,this),U2("article",{className:"agent-detail",children:U2("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:[U2("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),U2("div",{className:"flex items-start gap-6 mb-8",children:[U2(RD0,{name:B.name,className:"w-[72px] h-[72px] text-3xl"},void 0,!1,void 0,this),U2("div",{children:[U2("div",{className:"flex items-center gap-3 mb-1",children:[U2("h1",{className:"text-3xl md:text-4xl font-bold text-heading",children:B.name},void 0,!1,void 0,this),U2(hD0,{kind:B.kind},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U2("div",{className:"text-base text-theme-muted mb-2",children:B.brainName},void 0,!1,void 0,this),U2("div",{className:"flex items-center gap-3 text-theme-muted",children:[B.organization&&U2("span",{className:"text-[15px]",children:B.organization},void 0,!1,void 0,this),B.organization&&U2("span",{className:"text-theme-muted opacity-40",children:"\xB7"},void 0,!1,void 0,this),U2("span",{className:"text-sm",children:["Discovered ",pUw(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),U2("div",{className:"border-b border-theme mb-8"},void 0,!1,void 0,this),!X&&U2("div",{className:"mb-8 rounded-xl border border-theme bg-theme-subtle px-5 py-4",children:[U2("div",{className:"text-sm font-semibold text-heading mb-1",children:"Saved for review"},void 0,!1,void 0,this),U2("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),U2("div",{className:"flex flex-col md:flex-row gap-12",children:[U2("div",{className:"flex-[2] min-w-0",children:[$&&U2("section",{className:"mb-8",children:[U2(ho,{children:"About"},void 0,!1,void 0,this),U2("p",{className:"text-[15px] text-theme leading-relaxed",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),f.length>0&&U2("section",{className:"mb-8",children:[U2(ho,{children:"Skills"},void 0,!1,void 0,this),U2("div",{className:"flex flex-col gap-2.5",children:f.map((H)=>U2(iUw,{skill:H},H.name,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D&&U2("section",{className:"mb-8",children:[U2(ho,{children:"Notes"},void 0,!1,void 0,this),U2("p",{className:"text-[15px] text-theme leading-relaxed",children:D},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),U2("aside",{className:"flex-1 md:pl-8 md:border-l border-theme-muted/20",children:[U2("section",{className:"mb-8",children:[U2(ho,{children:"Brain"},void 0,!1,void 0,this),U2("div",{className:"p-4 bg-theme-subtle rounded-xl",children:[U2("div",{className:"text-[15px] font-semibold text-heading mb-1",children:B.brainName},void 0,!1,void 0,this),B.did&&U2("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),U2("section",{className:"mb-8",children:[U2(ho,{children:"Connection"},void 0,!1,void 0,this),U2("div",{className:"flex flex-col gap-3",children:[U2("div",{children:[U2("div",{className:"text-[13px] text-theme-muted mb-0.5",children:"Endpoint"},void 0,!1,void 0,this),U2("div",{className:"text-xs text-heading font-mono",children:B.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U2(dUw,{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),U2("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 ",Y," \u2197"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),(Q??w)&&U2("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:[U2("div",{className:"min-h-[1px]",children:Q&&U2("a",{href:Q.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[U2("span",{children:"\u2190 Previous"},void 0,!1,void 0,this),U2("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),U2("div",{className:"min-h-[1px] md:text-right",children:w&&U2("a",{href:w.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[U2("span",{children:"Next \u2192"},void 0,!1,void 0,this),U2("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 rUw=K.object({agents:K.array(xE),pageTitle:K.string().optional(),pagination:e7.nullable(),baseUrl:K.string().optional(),selectedStatus:K.union([K.literal("all"),HW])});function Ht1(){return{[Dr0]:R1({name:Dr0,description:"Agent directory list page template",schema:rUw,dataSourceId:Oo,requiredPermission:"public",layout:{component:Yt1}}),[Yr0]:R1({name:Yr0,description:"Individual agent profile template",schema:K.object({agent:xE,prevAgent:xE.nullable(),nextAgent:xE.nullable()}),dataSourceId:Oo,requiredPermission:"public",layout:{component:Xt1}})}}var RE={name:"@brains/agent-discovery",private:!0,version:"0.2.0-alpha.133",description:"Agent discovery \u2014 brain+anchor contacts and skills",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts,.tsx","lint:fix":"eslint . --ext .ts,.tsx --fix"},dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"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/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var sUw=new k4;class Kr0 extends PQ{entityType=K9;schema=OE;adapter=sUw;constructor(){super(Ca1,RE)}createGenerationHandler(A){return new Xr0(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return Ht1()}getDataSources(){return[new MD0(this.logger.child("AgentDataSource"))]}async onRegister(A){Bt1(A),Qt1(A,this.id)}async getInstructions(){return $t1()}}function Ur0(){return new Kr0}c0();Z0();k9();Z0();var Wt1=K.object({source:K.object({kind:K.literal("url"),url:K.string().min(1).describe("Remote agent domain or URL to verify and connect. Preserve bare domains as bare domains.")}),confirmed:K.boolean().optional(),confirmationToken:K.string().optional()}),aUw=new k4;function tUw(A){let Q=Ro(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function eUw(A,Q){return(Ro(Q)||A).toLowerCase()}async function AGw(A){let{context:Q,entityId:w,card:B}=A,$=new Date().toISOString(),f=await Q.entityService.getEntity({entityType:K9,id:w}),D=PD0(B,{status:"approved"}),X={...aUw.fromMarkdown(D.content).metadata,...D.metadata,a2aEndpoint:B.url};if(f){let W={...f,content:D.content,metadata:X,updated:$};return await Q.entityService.updateEntity({entity:W}),{entity:W,created:!1}}let H={id:w,entityType:K9,content:D.content,metadata:X,contentHash:"",visibility:"public",created:$,updated:$};return await Q.entityService.createEntity({entity:H}),{entity:H,created:!0}}function Zt1(A,Q=globalThis.fetch){let B=new pW;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 calls. This establishes and approves the contact; it does not message the remote agent. 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:Wt1.shape,visibility:"trusted",sideEffects:"external",handler:async($,f)=>{let D=Wt1.safeParse($);if(!D.success)return{success:!1,error:`Invalid input: ${D.error.errors.map((W)=>`${W.path.join(".")}: ${W.message}`).join(", ")}`};let Y=D.data,X=tUw(Y.source.url);if(!X)return{success:!1,error:"Provide a valid remote agent domain or URL to connect.",code:"invalid_agent_url"};try{A.permissions.assertEntityActionAllowed(K9,"create",f)}catch(W){return{success:!1,error:W instanceof Error?W.message:String(W)}}if(Y.confirmed){let W=Y.confirmationToken,Z=B.validate(W,Y);if(Z.status==="missing")return{success:!1,error:"No pending agent connection confirmation found. Please request connection again and confirm the new approval."};if(Z.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 G=await _D0(X.fetchTarget,Q);if(!G)return{success:!1,error:`Could not verify an A2A Agent Card for ${X.domain}.`,code:"not_an_agent"};let F=eUw(X.domain,G.url),{entity:V,created:b}=await AGw({context:A,entityId:F,sourceUrl:Y.source.url,card:G});return{success:!0,data:{status:V.metadata.status,entityId:V.id,connected:!0,created:b,a2aEndpoint:G.url,skills:G.skills.map((L)=>({name:L.name,description:L.description,tags:L.tags}))}}}let H=B.create((W)=>({source:Y.source,confirmed:!0,confirmationToken:W}));return{needsConfirmation:!0,toolName:"agent_connect",summary:`Verify and connect agent ${X.domain}?`,preview:`This will fetch and validate ${X.domain}'s A2A Agent Card, then save the verified contact as approved for future calls. It will not message the remote agent.`,args:H}}}}var QGw=K.object({}).strict();class Gr0 extends RQ{fetchFn;constructor(A){super("agent",RE,{},QGw);this.fetchFn=A}async getTools(){return[Zt1(this.getContext(),this.fetchFn)]}}function zr0(){return new Gr0}c0();Z0();c0();var hE=jY,Kt1=jY,vo=o1.extend({entityType:K.literal(z5),metadata:Kt1});c0();class vE extends I2{constructor(){super({entityType:z5,purpose:"A capability advertised by a remote agent.",schema:vo,frontmatterSchema:hE})}fromMarkdown(A){let Q=this.parseFrontMatter(A,hE);return{content:A,entityType:z5,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}c0();Z0();var wGw=K.object({skills:K.array(hE).max(4)}),Ut1=R1({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:wGw,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
8459
+ `)}function TUw(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 SUw(A,Q,w){await A.messaging.send({type:Q,payload:w,broadcast:!0})}async function mUw(A,Q,w=new Date().toISOString()){let{record:B}=Q,$=EUw(B.siteUrl),f=await A.entityService.getEntity({entityType:"agent",id:$}),D=f?wt1.parseEntity(f):void 0,Y=B.brain.did,X=B.anchor.did,H=yUw(B),W=f?.metadata.status??"discovered",Z=f?.metadata.url??B.siteUrl,G=f?.metadata.slug??jV(Z),F=f?.metadata.name??B.anchor.name,V=D?.frontmatter.kind??B.anchor.kind,b=f?.metadata.discoveredAt??w,L=B.brain.purpose||D?.body.about||"",N=H.length>0?H:D?.body.skills??[],_={...f?.metadata??{},name:F,url:Z,status:W,discoveredAt:b,slug:G,repoDid:Q.repoDid,...Y&&{brainDid:Y},...X&&{anchorDid:X},cardUri:Q.uri,cardCid:Q.cid},j=wt1.createAgentContent({name:F,kind:V,...D?.frontmatter.organization&&{organization:D.frontmatter.organization},brainName:B.brain.name,url:Z,...Y&&{did:Y,brainDid:Y},...X&&{anchorDid:X},repoDid:Q.repoDid,cardUri:Q.uri,cardCid:Q.cid,...D?.frontmatter.a2aEndpoint&&{a2aEndpoint:D.frontmatter.a2aEndpoint},status:W,discoveredAt:b,about:L,skills:N,notes:gUw({repoDid:Q.repoDid,uri:Q.uri,cid:Q.cid})});if(f){let E={...f,content:j,metadata:_,updated:w};return await A.entityService.updateEntity({entity:E}),{agent:E,created:!1}}let g={id:$,entityType:"agent",content:j,metadata:_,contentHash:"",visibility:"public",created:w,updated:w};return await A.entityService.createEntity({entity:g}),{agent:g,created:!0}}function Bt1(A){A.messaging.subscribe(M40,async(Q)=>{let w=Sp1.parse(Q.payload),B=await mUw(A,w),$=TUw({agent:B.agent,repoDid:w.repoDid,uri:w.uri,cid:w.cid,record:w.record});return await SUw(A,B.created?gp1:Tp1,$),{success:!0,data:$}})}function $t1(){return["Agent entities represent saved peer-brain contacts in the local agent directory. List saved agent contacts with system_list on entityType agent.","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 calls.","Agent lifecycle is tracked with status fields such as discovered, approved, and archived; approval and archive operations are system_update field changes for already saved discovered contacts. If the user asks to approve or archive a saved agent contact by exact id such as approval-candidate.io or old-agent.io, call system_update on entityType agent with that id and the requested status; do not use agent_connect for approval.","Calling remote agents and saving local contact records are separate capabilities. Archived agents are not active call targets."].join(" ")}c0();JB();Z0();import{jsxDEV as ft1}from"preact/jsx-dev-runtime";function xD0(A){try{return new URL(A).hostname}catch{return A}}var RD0=({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 ft1("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)},hD0=({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 ft1("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 j2,Fragment as lUw}from"preact/jsx-dev-runtime";var uUw=({skills:A})=>{if(A.length===0)return null;return j2("div",{className:"flex gap-1.5 flex-wrap mt-2",children:A.map((Q)=>j2("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 cUw(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric"})}function Dt1(A,Q,w){let B=new URLSearchParams({status:Q});if(w>1)B.set("page",String(w));return`${A}?${B.toString()}`}var Zr0=({agent:A})=>{let{frontmatter:Q,about:w,skills:B,url:$}=A,f=Q.status==="approved";return j2("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:[j2(RD0,{name:Q.name,className:"w-12 h-12 text-lg"},void 0,!1,void 0,this),j2("div",{className:"flex-1 min-w-0",children:[j2("div",{className:"flex items-center gap-2 mb-1 flex-wrap",children:[j2("span",{className:"text-lg font-semibold text-heading",children:Q.name},void 0,!1,void 0,this),j2(hD0,{kind:Q.kind,size:"sm"},void 0,!1,void 0,this),Q.organization&&j2("span",{className:"text-xs text-theme-muted",children:["\xB7 ",Q.organization]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"text-sm text-theme-muted mb-1",children:Q.brainName},void 0,!1,void 0,this),w&&j2("p",{className:"text-sm text-theme-muted line-clamp-2 mb-0",children:w},void 0,!1,void 0,this),f&&j2(uUw,{skills:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"flex flex-col items-end gap-1 flex-shrink-0 text-right",children:[j2("span",{className:"text-xs text-theme-muted",children:xD0(Q.url)},void 0,!1,void 0,this),j2("span",{className:"text-[11px] text-theme-muted opacity-60",children:f?`Discovered ${cUw(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)},Yt1=({agents:A,pageTitle:Q,pagination:w,baseUrl:B="/agents",selectedStatus:$})=>{let f=Q??"Agent Directory",D=w?.totalItems??A.length,Y=A.filter((G)=>G.frontmatter.status==="approved"),X=A.filter((G)=>G.frontmatter.status==="discovered"),H=Y.length,W=X.length,Z=`Your network of ${D} ${D===1?"brain":"brains"} and their anchors`;return j2(lUw,{children:[j2(NQ,{title:f,description:Z},void 0,!1,void 0,this),j2("div",{className:"agent-list bg-theme",children:j2("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[j2("div",{className:"mb-8 pb-6 border-b border-theme",children:[j2("h1",{className:"text-4xl font-bold text-heading mb-2",children:f},void 0,!1,void 0,this),j2("p",{className:"text-theme-muted mb-4",children:Z},void 0,!1,void 0,this),j2("div",{className:"flex flex-wrap gap-2 text-sm mb-4",children:[j2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-heading",children:[D," total"]},void 0,!0,void 0,this),j2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-status-success",children:[H," approved"]},void 0,!0,void 0,this),j2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-theme-muted",children:[W," discovered"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"flex flex-wrap gap-2 text-sm",children:[j2("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),j2("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),j2("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"&&Y.length>0&&j2("section",{className:"mb-10",children:[j2("div",{className:"flex items-center justify-between mb-4",children:[j2("h2",{className:"text-lg font-semibold text-heading",children:"Approved brains"},void 0,!1,void 0,this),j2("span",{className:"text-sm text-theme-muted",children:Y.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"flex flex-col gap-4",children:Y.map((G)=>j2(Zr0,{agent:G},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$==="all"&&X.length>0&&j2("section",{children:[j2("div",{className:"flex items-center justify-between mb-4",children:[j2("div",{children:[j2("h2",{className:"text-lg font-semibold text-heading",children:"Discovered brains"},void 0,!1,void 0,this),j2("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),j2("span",{className:"text-sm text-theme-muted",children:X.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"flex flex-col gap-4",children:X.map((G)=>j2(Zr0,{agent:G},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$!=="all"&&A.length>0&&j2("section",{children:[j2("div",{className:"flex items-center justify-between mb-4",children:[j2("h2",{className:"text-lg font-semibold text-heading",children:$==="approved"?"Approved brains":"Discovered brains"},void 0,!1,void 0,this),j2("span",{className:"text-sm text-theme-muted",children:A.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j2("div",{className:"flex flex-col gap-4",children:A.map((G)=>j2(Zr0,{agent:G},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length===0&&j2("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"&&j2("div",{className:"mt-12",children:j2(d3,{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"&&j2("nav",{"aria-label":"Pagination",className:"flex items-center justify-center gap-3 mt-12",children:[w.hasPrevPage?j2("a",{href:Dt1(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):j2("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),j2("span",{className:"text-sm text-theme-muted",children:["Page ",w.currentPage," of ",w.totalPages]},void 0,!0,void 0,this),w.hasNextPage?j2("a",{href:Dt1(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):j2("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 U2,Fragment as nUw}from"preact/jsx-dev-runtime";function pUw(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}var ho=({children:A})=>U2("h2",{className:"text-sm font-semibold text-theme-muted uppercase tracking-wide mb-3",children:A},void 0,!1,void 0,this),iUw=({skill:A})=>U2("div",{className:"flex items-start gap-3 px-4 py-3 bg-theme-subtle rounded-lg",children:[U2("div",{className:"flex-1",children:[U2("div",{className:"text-sm font-semibold text-heading",children:A.name},void 0,!1,void 0,this),U2("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&&U2("div",{className:"flex gap-1 flex-shrink-0",children:A.tags.map((Q)=>U2("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),dUw=({label:A,value:Q,valueClassName:w})=>U2("div",{className:"flex justify-between text-[13px]",children:[U2("span",{className:"text-theme-muted",children:A},void 0,!1,void 0,this),U2("span",{className:w??"text-heading",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Xt1=({agent:A,prevAgent:Q,nextAgent:w})=>{let{frontmatter:B,about:$,skills:f,notes:D}=A,Y=xD0(B.url),X=B.status==="approved";return U2(nUw,{children:[U2(NQ,{title:B.name,description:$||`Agent profile for ${B.name}`},void 0,!1,void 0,this),U2("article",{className:"agent-detail",children:U2("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:[U2("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),U2("div",{className:"flex items-start gap-6 mb-8",children:[U2(RD0,{name:B.name,className:"w-[72px] h-[72px] text-3xl"},void 0,!1,void 0,this),U2("div",{children:[U2("div",{className:"flex items-center gap-3 mb-1",children:[U2("h1",{className:"text-3xl md:text-4xl font-bold text-heading",children:B.name},void 0,!1,void 0,this),U2(hD0,{kind:B.kind},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U2("div",{className:"text-base text-theme-muted mb-2",children:B.brainName},void 0,!1,void 0,this),U2("div",{className:"flex items-center gap-3 text-theme-muted",children:[B.organization&&U2("span",{className:"text-[15px]",children:B.organization},void 0,!1,void 0,this),B.organization&&U2("span",{className:"text-theme-muted opacity-40",children:"\xB7"},void 0,!1,void 0,this),U2("span",{className:"text-sm",children:["Discovered ",pUw(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),U2("div",{className:"border-b border-theme mb-8"},void 0,!1,void 0,this),!X&&U2("div",{className:"mb-8 rounded-xl border border-theme bg-theme-subtle px-5 py-4",children:[U2("div",{className:"text-sm font-semibold text-heading mb-1",children:"Saved for review"},void 0,!1,void 0,this),U2("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),U2("div",{className:"flex flex-col md:flex-row gap-12",children:[U2("div",{className:"flex-[2] min-w-0",children:[$&&U2("section",{className:"mb-8",children:[U2(ho,{children:"About"},void 0,!1,void 0,this),U2("p",{className:"text-[15px] text-theme leading-relaxed",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),f.length>0&&U2("section",{className:"mb-8",children:[U2(ho,{children:"Skills"},void 0,!1,void 0,this),U2("div",{className:"flex flex-col gap-2.5",children:f.map((H)=>U2(iUw,{skill:H},H.name,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D&&U2("section",{className:"mb-8",children:[U2(ho,{children:"Notes"},void 0,!1,void 0,this),U2("p",{className:"text-[15px] text-theme leading-relaxed",children:D},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),U2("aside",{className:"flex-1 md:pl-8 md:border-l border-theme-muted/20",children:[U2("section",{className:"mb-8",children:[U2(ho,{children:"Brain"},void 0,!1,void 0,this),U2("div",{className:"p-4 bg-theme-subtle rounded-xl",children:[U2("div",{className:"text-[15px] font-semibold text-heading mb-1",children:B.brainName},void 0,!1,void 0,this),B.did&&U2("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),U2("section",{className:"mb-8",children:[U2(ho,{children:"Connection"},void 0,!1,void 0,this),U2("div",{className:"flex flex-col gap-3",children:[U2("div",{children:[U2("div",{className:"text-[13px] text-theme-muted mb-0.5",children:"Endpoint"},void 0,!1,void 0,this),U2("div",{className:"text-xs text-heading font-mono",children:B.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U2(dUw,{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),U2("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 ",Y," \u2197"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),(Q??w)&&U2("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:[U2("div",{className:"min-h-[1px]",children:Q&&U2("a",{href:Q.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[U2("span",{children:"\u2190 Previous"},void 0,!1,void 0,this),U2("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),U2("div",{className:"min-h-[1px] md:text-right",children:w&&U2("a",{href:w.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[U2("span",{children:"Next \u2192"},void 0,!1,void 0,this),U2("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 rUw=K.object({agents:K.array(xE),pageTitle:K.string().optional(),pagination:e7.nullable(),baseUrl:K.string().optional(),selectedStatus:K.union([K.literal("all"),HW])});function Ht1(){return{[Dr0]:R1({name:Dr0,description:"Agent directory list page template",schema:rUw,dataSourceId:Oo,requiredPermission:"public",layout:{component:Yt1}}),[Yr0]:R1({name:Yr0,description:"Individual agent profile template",schema:K.object({agent:xE,prevAgent:xE.nullable(),nextAgent:xE.nullable()}),dataSourceId:Oo,requiredPermission:"public",layout:{component:Xt1}})}}var RE={name:"@brains/agent-discovery",private:!0,version:"0.2.0-alpha.134",description:"Agent discovery \u2014 brain+anchor contacts and skills",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts,.tsx","lint:fix":"eslint . --ext .ts,.tsx --fix"},dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"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/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var sUw=new k4;class Kr0 extends PQ{entityType=K9;schema=OE;adapter=sUw;constructor(){super(Ca1,RE)}createGenerationHandler(A){return new Xr0(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return Ht1()}getDataSources(){return[new MD0(this.logger.child("AgentDataSource"))]}async onRegister(A){Bt1(A),Qt1(A,this.id)}async getInstructions(){return $t1()}}function Ur0(){return new Kr0}c0();Z0();k9();Z0();var Wt1=K.object({source:K.object({kind:K.literal("url"),url:K.string().min(1).describe("Remote agent domain or URL to verify and connect. Preserve bare domains as bare domains.")}),confirmed:K.boolean().optional(),confirmationToken:K.string().optional()}),aUw=new k4;function tUw(A){let Q=Ro(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function eUw(A,Q){return(Ro(Q)||A).toLowerCase()}async function AGw(A){let{context:Q,entityId:w,card:B}=A,$=new Date().toISOString(),f=await Q.entityService.getEntity({entityType:K9,id:w}),D=PD0(B,{status:"approved"}),X={...aUw.fromMarkdown(D.content).metadata,...D.metadata,a2aEndpoint:B.url};if(f){let W={...f,content:D.content,metadata:X,updated:$};return await Q.entityService.updateEntity({entity:W}),{entity:W,created:!1}}let H={id:w,entityType:K9,content:D.content,metadata:X,contentHash:"",visibility:"public",created:$,updated:$};return await Q.entityService.createEntity({entity:H}),{entity:H,created:!0}}function Zt1(A,Q=globalThis.fetch){let B=new pW;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 calls. This establishes and approves the contact; it does not message the remote agent. 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:Wt1.shape,visibility:"trusted",sideEffects:"external",handler:async($,f)=>{let D=Wt1.safeParse($);if(!D.success)return{success:!1,error:`Invalid input: ${D.error.errors.map((W)=>`${W.path.join(".")}: ${W.message}`).join(", ")}`};let Y=D.data,X=tUw(Y.source.url);if(!X)return{success:!1,error:"Provide a valid remote agent domain or URL to connect.",code:"invalid_agent_url"};try{A.permissions.assertEntityActionAllowed(K9,"create",f)}catch(W){return{success:!1,error:W instanceof Error?W.message:String(W)}}if(Y.confirmed){let W=Y.confirmationToken,Z=B.validate(W,Y);if(Z.status==="missing")return{success:!1,error:"No pending agent connection confirmation found. Please request connection again and confirm the new approval."};if(Z.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 G=await _D0(X.fetchTarget,Q);if(!G)return{success:!1,error:`Could not verify an A2A Agent Card for ${X.domain}.`,code:"not_an_agent"};let F=eUw(X.domain,G.url),{entity:V,created:b}=await AGw({context:A,entityId:F,sourceUrl:Y.source.url,card:G});return{success:!0,data:{status:V.metadata.status,entityId:V.id,connected:!0,created:b,a2aEndpoint:G.url,skills:G.skills.map((L)=>({name:L.name,description:L.description,tags:L.tags}))}}}let H=B.create((W)=>({source:Y.source,confirmed:!0,confirmationToken:W}));return{needsConfirmation:!0,toolName:"agent_connect",summary:`Verify and connect agent ${X.domain}?`,preview:`This will fetch and validate ${X.domain}'s A2A Agent Card, then save the verified contact as approved for future calls. It will not message the remote agent.`,args:H}}}}var QGw=K.object({}).strict();class Gr0 extends RQ{fetchFn;constructor(A){super("agent",RE,{},QGw);this.fetchFn=A}async getTools(){return[Zt1(this.getContext(),this.fetchFn)]}}function zr0(){return new Gr0}c0();Z0();c0();var hE=jY,Kt1=jY,vo=o1.extend({entityType:K.literal(z5),metadata:Kt1});c0();class vE extends I2{constructor(){super({entityType:z5,purpose:"A capability advertised by a remote agent.",schema:vo,frontmatterSchema:hE})}fromMarkdown(A){let Q=this.parseFrontMatter(A,hE);return{content:A,entityType:z5,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}c0();Z0();var wGw=K.object({skills:K.array(hE).max(4)}),Ut1=R1({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:wGw,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
8460
8460
 
8461
8461
  Given knowledge domains, CONSOLIDATE related topics into broader skills.
8462
8462
  There should be FEWER skills than topics \u2014 combine related domains.
@@ -8606,9 +8606,9 @@ Context:
8606
8606
  ${JSON.stringify(B,null,2)}
8607
8607
 
8608
8608
  Draft SWOT:
8609
- ${JSON.stringify(w,null,2)}`}function mD0(A){return A.map((Q)=>Q.detail===null?{title:Q.title}:{title:Q.title,detail:Q.detail})}function jGw(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 D=f.sourceTheme.trim().toLowerCase();if(!$.has(D))throw Error(`SWOT refinement invented theme "${f.sourceTheme}" in ${B}`)}}}class uD0{logger;context;adapter=new IF;constructor(A,Q){this.logger=A;this.context=Q}validateAndParse(A){let Q=Vr0.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 Nr0(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 bGw(this.context,B),Ir0),W=Ir0.parse(H);await w.report({progress:0.75,message:"Refining SWOT language"});let Z=await this.context.ai.generateObject(await NGw(this.context,B,W),gD0);$=gD0.parse(Z.object),jGw(W,$)}let D=new Date().toISOString(),Y=this.adapter.createSwotContent({strengths:mD0($.strengths),weaknesses:mD0($.weaknesses),opportunities:mD0($.opportunities),threats:mD0($.threats),derivedAt:D});await w.report({progress:0.9,message:"Saving SWOT entity"});let X=await this.context.entityService.getEntity({entityType:"swot",id:"swot"});if(X)await this.context.entityService.updateEntity({entity:{...X,content:Y,metadata:{derivedAt:D}}});else await this.context.entityService.createEntity({entity:{id:"swot",entityType:"swot",content:Y,metadata:{derivedAt:D}}});return this.logger.info("SWOT derivation complete",{derivedAt:D,brainSkillCount:B.summary.brainSkillCount,approvedAgentCount:B.summary.approvedAgentCount,discoveredAgentCount:B.summary.discoveredAgentCount}),{entityId:"swot"}}}Z0();import{jsxDEV as O4}from"preact/jsx-dev-runtime";var cD0=K.object({title:K.string(),detail:K.string().optional()}),MGw=K.discriminatedUnion("status",[K.object({status:K.literal("generating")}),K.object({status:K.literal("ready"),strengths:K.array(cD0).default([]),weaknesses:K.array(cD0).default([]),opportunities:K.array(cD0).default([]),threats:K.array(cD0).default([]),derivedAt:K.string()})]);function _Gw({items:A}){if(A.length===0)return O4("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return O4("ul",{class:"swot-list",children:A.map((Q)=>O4("li",{class:"swot-item",children:[O4("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?O4("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 lD0({title:A,tone:Q,items:w}){return O4("section",{class:`swot-cell is-${Q}`,children:[O4("div",{class:"swot-head",children:A},void 0,!1,void 0,this),O4(_Gw,{items:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function _r0({data:A}){let Q=MGw.safeParse(A);if(!Q.success||Q.data.status==="generating")return O4("div",{"data-swot-widget":!0,children:O4("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let w=Q.data;return O4("div",{"data-swot-widget":!0,children:O4("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[O4(lD0,{title:"Strengths",tone:"s",items:w.strengths},void 0,!1,void 0,this),O4(lD0,{title:"Weaknesses",tone:"w",items:w.weaknesses},void 0,!1,void 0,this),O4(lD0,{title:"Opportunities",tone:"o",items:w.opportunities},void 0,!1,void 0,this),O4(lD0,{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)}Z0();var Pr0={name:"@brains/assessment",private:!0,version:"0.2.0-alpha.133",description:"Assessment outputs and capability-profile analysis",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts,.tsx","lint:fix":"eslint . --ext .ts,.tsx --fix",eval:"cd evals && bun run brain-eval"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var kr0=new IF;class Or0 extends PQ{entityType="swot";schema=CE;adapter=kr0;initialSyncComplete=!1;constructor(){super("swot",Pr0)}async onRegister(A){let Q=new uD0(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q),A.eval.registerHandler("deriveSwot",async()=>{let f=D7.from(async()=>{});if(!f)throw Error("Expected progress reporter to be created");await Q.process({reason:"eval"},"eval-swot-derive",f);let D=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!D)throw Error("Expected SWOT entity to be created during eval");return kr0.parseSwotContent(D.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(D){return this.logger.error("Failed to queue SWOT derivation",{error:D,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:_r0,dataProvider:async()=>{let f=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!f)return{status:"generating"};let{frontmatter:D}=kr0.parseSwotContent(f.content);return{status:"ready",...D}}}}),{success:!0}});let $=async(f)=>{let{entityType:D}=f.payload;if(!this.initialSyncComplete)return{success:!0};if(D!=="agent"&&D!=="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 xr0(){return new Or0}c0();l$();Z0();var j76=new IF,Pt1=K.object({name:K.string(),description:K.string(),tags:K.array(K.string())}),Rr0=K.enum(["discovered","approved"]),kGw=K.object({name:K.string(),kind:K.enum(["professional","team","collective"]),organization:K.string().optional(),brainName:K.string(),url:K.string().url(),did:K.string().optional(),status:Rr0,discoveredAt:K.string().datetime()}),OGw=o1.extend({entityType:K.literal("agent"),metadata:K.object({name:K.string(),url:K.string().url(),status:Rr0,slug:K.string()})}),xGw=o1.extend({entityType:K.literal("skill"),metadata:jY}),RGw=K.object({about:K.string(),skills:K.array(Pt1),notes:K.string()});function hGw(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(`
8609
+ ${JSON.stringify(w,null,2)}`}function mD0(A){return A.map((Q)=>Q.detail===null?{title:Q.title}:{title:Q.title,detail:Q.detail})}function jGw(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 D=f.sourceTheme.trim().toLowerCase();if(!$.has(D))throw Error(`SWOT refinement invented theme "${f.sourceTheme}" in ${B}`)}}}class uD0{logger;context;adapter=new IF;constructor(A,Q){this.logger=A;this.context=Q}validateAndParse(A){let Q=Vr0.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 Nr0(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 bGw(this.context,B),Ir0),W=Ir0.parse(H);await w.report({progress:0.75,message:"Refining SWOT language"});let Z=await this.context.ai.generateObject(await NGw(this.context,B,W),gD0);$=gD0.parse(Z.object),jGw(W,$)}let D=new Date().toISOString(),Y=this.adapter.createSwotContent({strengths:mD0($.strengths),weaknesses:mD0($.weaknesses),opportunities:mD0($.opportunities),threats:mD0($.threats),derivedAt:D});await w.report({progress:0.9,message:"Saving SWOT entity"});let X=await this.context.entityService.getEntity({entityType:"swot",id:"swot"});if(X)await this.context.entityService.updateEntity({entity:{...X,content:Y,metadata:{derivedAt:D}}});else await this.context.entityService.createEntity({entity:{id:"swot",entityType:"swot",content:Y,metadata:{derivedAt:D}}});return this.logger.info("SWOT derivation complete",{derivedAt:D,brainSkillCount:B.summary.brainSkillCount,approvedAgentCount:B.summary.approvedAgentCount,discoveredAgentCount:B.summary.discoveredAgentCount}),{entityId:"swot"}}}Z0();import{jsxDEV as O4}from"preact/jsx-dev-runtime";var cD0=K.object({title:K.string(),detail:K.string().optional()}),MGw=K.discriminatedUnion("status",[K.object({status:K.literal("generating")}),K.object({status:K.literal("ready"),strengths:K.array(cD0).default([]),weaknesses:K.array(cD0).default([]),opportunities:K.array(cD0).default([]),threats:K.array(cD0).default([]),derivedAt:K.string()})]);function _Gw({items:A}){if(A.length===0)return O4("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return O4("ul",{class:"swot-list",children:A.map((Q)=>O4("li",{class:"swot-item",children:[O4("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?O4("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 lD0({title:A,tone:Q,items:w}){return O4("section",{class:`swot-cell is-${Q}`,children:[O4("div",{class:"swot-head",children:A},void 0,!1,void 0,this),O4(_Gw,{items:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function _r0({data:A}){let Q=MGw.safeParse(A);if(!Q.success||Q.data.status==="generating")return O4("div",{"data-swot-widget":!0,children:O4("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let w=Q.data;return O4("div",{"data-swot-widget":!0,children:O4("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[O4(lD0,{title:"Strengths",tone:"s",items:w.strengths},void 0,!1,void 0,this),O4(lD0,{title:"Weaknesses",tone:"w",items:w.weaknesses},void 0,!1,void 0,this),O4(lD0,{title:"Opportunities",tone:"o",items:w.opportunities},void 0,!1,void 0,this),O4(lD0,{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)}Z0();var Pr0={name:"@brains/assessment",private:!0,version:"0.2.0-alpha.134",description:"Assessment outputs and capability-profile analysis",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts,.tsx","lint:fix":"eslint . --ext .ts,.tsx --fix",eval:"cd evals && bun run brain-eval"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var kr0=new IF;class Or0 extends PQ{entityType="swot";schema=CE;adapter=kr0;initialSyncComplete=!1;constructor(){super("swot",Pr0)}async onRegister(A){let Q=new uD0(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q),A.eval.registerHandler("deriveSwot",async()=>{let f=D7.from(async()=>{});if(!f)throw Error("Expected progress reporter to be created");await Q.process({reason:"eval"},"eval-swot-derive",f);let D=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!D)throw Error("Expected SWOT entity to be created during eval");return kr0.parseSwotContent(D.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(D){return this.logger.error("Failed to queue SWOT derivation",{error:D,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:_r0,dataProvider:async()=>{let f=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!f)return{status:"generating"};let{frontmatter:D}=kr0.parseSwotContent(f.content);return{status:"ready",...D}}}}),{success:!0}});let $=async(f)=>{let{entityType:D}=f.payload;if(!this.initialSyncComplete)return{success:!0};if(D!=="agent"&&D!=="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 xr0(){return new Or0}c0();l$();Z0();var j76=new IF,Pt1=K.object({name:K.string(),description:K.string(),tags:K.array(K.string())}),Rr0=K.enum(["discovered","approved"]),kGw=K.object({name:K.string(),kind:K.enum(["professional","team","collective"]),organization:K.string().optional(),brainName:K.string(),url:K.string().url(),did:K.string().optional(),status:Rr0,discoveredAt:K.string().datetime()}),OGw=o1.extend({entityType:K.literal("agent"),metadata:K.object({name:K.string(),url:K.string().url(),status:Rr0,slug:K.string()})}),xGw=o1.extend({entityType:K.literal("skill"),metadata:jY}),RGw=K.object({about:K.string(),skills:K.array(Pt1),notes:K.string()});function hGw(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(`
8610
8610
  `)}function vGw(A){if(!A.trim())return[];return A.split(`
8611
- `).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 CGw=new pw(RGw,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:hGw,parser:vGw},{key:"notes",label:"Notes",type:"string"}]});class kt1 extends I2{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:OGw,frontmatterSchema:kGw})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=CGw.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 Ot1 extends I2{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:xGw,frontmatterSchema:jY})}fromMarkdown(A){let Q=this.parseFrontMatter(A,jY);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var M76=new kt1,_76=new Ot1,P76=K.object({skills:K.array(jY),agents:K.array(K.object({id:K.string().optional(),name:K.string(),kind:K.enum(["professional","team","collective"]),organization:K.string().optional(),brainName:K.string(),url:K.string().url(),did:K.string().optional(),status:Rr0,discoveredAt:K.string().datetime().optional(),about:K.string(),skills:K.array(Pt1),notes:K.string().default("")}))});var yGw=K.object({}).strict();function pD0(A={}){return yGw.parse(A),[xr0()]}c0();Z0();Z0();var hr0=K.object({enabled:K.boolean().default(!0),pdsEndpoint:K.string().url().default("https://bsky.social").describe("AT Protocol PDS service endpoint"),identifier:K.string().optional().describe("PDS login identifier, usually a handle or account DID"),repoDid:K.string().optional().describe("DID of the PDS repo that owns records"),appPassword:K.string().optional().describe("App password for prototype authentication; supply via ${ENV_VAR} interpolation, never a committed literal"),anchorDid:K.string().optional().describe("Optional human/operator DID referenced from records; defaults to did:web:<site-host>:anchor when omitted"),brainDid:K.string().optional().describe("Optional public brain DID referenced from records; defaults to did:web:<site-host> when omitted")});function EGw(A){return A.replace(/\/+$/,"")}var gGw=(A,Q)=>fetch(A,Q);async function yo(A){let Q=await A.json();if(!A.ok){let w=typeof Q==="object"&&Q!==null&&"message"in Q&&typeof Q.message==="string"?Q.message:`AT Protocol request failed with ${A.status}`;throw Error(w)}return Q}class Eo{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=EGw(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??gGw}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 yo(A);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 yo(w)}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 yo(w)}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 yo(w)}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 yo(w)}async getSession(){return this.session??=await this.createSession(),this.session}}function yP(A){return A?.startsWith("did:web:")??!1}function iD0(A){if(!yP(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 Rt1(A){if(!yP(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 ht1(A){return A.replace(/\/+$/,"")}function go(A){return`did:web:${encodeURIComponent(A)}`}function dD0(A){return`${go(A)}:anchor`}function vr0(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function vt1(A,Q){let w=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...vr0(Q),...w&&{alsoKnownAs:w},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:ht1(A.pdsEndpoint)}]}}function Ct1(A){if(!yP(A.brainDid))return null;return vt1(A,A.brainDid)}function xt1(A,Q){if(!A||!Q)return;let w=iD0(A),B=Rt1(A);if(!w||!B)return;return{path:B,hostname:w,document:Q}}function nD0(A){let Q=[],w=xt1(A.brainDid,Ct1(A));if(w)Q.push(w);if(yP(A.anchorDid)&&A.anchorDid!==A.brainDid){let B=xt1(A.anchorDid,vr0(A.anchorDid));if(B)Q.push(B)}return Q}function Cr0(A,Q){let w=[];if(!A.brainDid){let B=go(Q);w.push({path:"/.well-known/did.json",hostname:Q,document:vt1(A,B)})}if(!A.anchorDid){let B=dD0(Q);w.push({path:"/anchor/did.json",hostname:Q,document:vr0(B)})}return w}function TGw(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function SGw(A){let Q=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,200);return Q.length>0?Q:"skill"}function yt1(A,Q){let w=A[Q];return typeof w==="string"&&w.length>0?w:void 0}function Et1(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 mGw(A){let Q=A.metadata,w=yt1(Q,"name"),B=yt1(Q,"description");if(!w||!B)return;let $=Et1(Q,"tags"),f=Et1(Q,"examples");return{id:SGw(w),name:w,description:B,...$&&{tags:$},...f&&{examples:f}}}async function uGw(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map((w)=>mGw(w)).filter((w)=>w!==void 0).slice(0,100)}async function yr0(A,Q,w=new Date){let B=A.identity.get(),$=A.identity.getProfile(),f=await A.identity.getAppInfo(),D=TGw(A.siteUrl??$.website,void 0);if(!D)throw Error("AT Protocol brain card publishing requires siteUrl");let Y=new URL(D).hostname,X=Q.brainDid??go(Y),H=Q.anchorDid??dD0(Y);if(yP(X)){if(iD0(X)!==Y)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let W=await uGw(A);return{$type:"ai.rizom.brain.card",siteUrl:D,brain:{did:X,name:B.name,role:B.role,purpose:B.purpose,values:B.values},anchor:{did:H,name:$.name,kind:$.kind},skills:W,model:f.model,version:f.version,createdAt:w.toISOString(),updatedAt:w.toISOString()}}var gt1={name:"@brains/atproto",private:!0,version:"0.2.0-alpha.133",description:"AT Protocol integration for identity, publishing, discovery, and feeds",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var Tt1=MB["ai.rizom.brain.card"],lGw="ai.rizom.brain.card",pGw="self",St1=50;class Er0 extends RQ{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",gt1,A,hr0);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??U5.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=nD0(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,D=[...nD0(this.config),...Cr0(this.config,f)].filter((X)=>X.path===B),Y=D.find((X)=>X.hostname===f)??D[0];if(!Y)return new Response("Not found",{status:404});return new Response(JSON.stringify(Y.document),{headers:{"Content-Type":"application/did+json"}})}}))}async publishBrainCard(A,Q={}){let w=await yr0(A,this.config);Vb(Tt1,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($),D=await f.createSession(),Y=B??D.did;if(!f.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let X=await f.putRecord({repo:Y,collection:"ai.rizom.brain.card",rkey:"self",validate:!1,record:w});return{record:w,repo:Y,uri:X.uri,cid:X.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>St1)throw Error(`AT Protocol discovery accepts at most ${St1} repos per batch`);let B=new Set,$=[];for(let f of w)try{let D=await this.resolveRepoPdsEndpoint(f),Y=this.createPublicPdsClient(D.pdsEndpoint);if(!Y.getRecord)throw Error("AT Protocol PDS client does not support record reads");let X=await Y.getRecord({repo:D.repoDid,collection:lGw,rkey:pGw});Vb(Tt1,X.value);let H=dGw(X.uri)??D.repoDid,W=`${H}:${X.uri}:${X.cid}`;if(B.has(W)){$.push({repo:f,status:"skipped",repoDid:H,uri:X.uri,cid:X.cid,error:"Duplicate brain card in discovery batch"});continue}B.add(W),await A.messaging.send({type:M40,payload:{repoDid:H,uri:X.uri,cid:X.cid,record:X.value},broadcast:!0}),$.push({repo:f,status:"discovered",repoDid:H,uri:X.uri,cid:X.cid})}catch(D){$.push({repo:f,status:"skipped",error:vA(D)})}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:vA(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 G=await w.buildRecord({entity:B,context:A,config:this.config,...Q.topics&&{topics:Q.topics},dryRun:!0});return Vb(w.lexicon,G),{record:G,dryRun:!0,...f&&{repo:f}}}let D=this.resolveAppPassword();if(!this.config.identifier||!D)throw Error("AT Protocol publishing requires identifier and app password configuration");let Y=this.createPdsClient(D),X=await Y.createSession(),H=f??X.did,W=await w.buildRecord({entity:B,context:A,config:this.config,client:Y,...Q.topics&&{topics:Q.topics}});if(Vb(w.lexicon,W),!Y.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let Z=await Y.putRecord({repo:H,collection:w.collection,rkey:iGw(B.id),...w.validate!==void 0&&{validate:w.validate},record:W});return await w.onPublished?.({entity:B,context:A,record:W,uri:Z.uri,cid:Z.cid}),{record:W,repo:H,uri:Z.uri,cid:Z.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 Eo({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=await w.json();if(typeof B!=="object"||B===null||!("did"in B))return;return typeof B.did==="string"?B.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(nGw(A)):void 0;if(typeof Q!=="object"||Q===null)return;let w=Q.service;if(!Array.isArray(w))return;let B=w.find(($)=>{return typeof $==="object"&&$!==null&&($.id==="#atproto_pds"||$.type==="AtprotoPersonalDataServer")});return typeof B?.serviceEndpoint==="string"?B.serviceEndpoint:void 0}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 Eo({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function iGw(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function dGw(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function nGw(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 rD0(A,Q){return new Er0(A,Q)}c0();Z0();var oD0={name:"@brains/rover",version:"0.2.0-alpha.133",type:"module",private:!0,main:"./src/index.ts",files:["src","brain.eval.yaml","env.schema.template"],scripts:{"build:web-chat":"turbo run build --filter=@brains/web-chat","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",typecheck:"tsc --noEmit",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 .","lint:fix":"eslint . --fix"},dependencies:{"@brains/a2a":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/analytics":"workspace:*","@brains/app":"workspace:*","@brains/assessment":"workspace:*","@brains/atproto":"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/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/playbook":"workspace:*","@brains/playbooks":"workspace:*","@brains/portfolio":"workspace:*","@brains/prompt":"workspace:*","@brains/rizom-ecosystem":"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:"^5.3.3"}};var oGw=K.object({}).strict();class mt1 extends RQ{constructor(A={}){super("rover-profile",oD0,A,oGw)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",ON)}}function ut1(A={}){return new mt1(A)}c0();Z0();JB();_5();c0();var gb=QZ.extend(ON.shape);c0();zq();Z0();var sGw=new VU;class sD0{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,D,Y]=await Promise.all([Wx(B),B.listEntities({entityType:"post",options:{limit:20}}),B.listEntities({entityType:"deck",options:{limit:20}}),Gr(B)]),X=sGw.parseProfileBody($,gb),H=f.sort(OT).slice(0,3).map(Fr),W=D.sort(OT).slice(0,3).map(Nr);if(!Y.cta)throw Error("CTA not configured in site-info");let Z={profile:X,posts:H,decks:W,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:Y.cta,sections:Y.sections??{}};return Q.parse(Z)}}c0();zq();var aGw=new VU;class aD0{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,w){let B=await Wx(w.entityService),f={profile:aGw.parseProfileBody(B,gb)};return Q.parse(f)}}import{jsxDEV as F8,Fragment as Azw}from"preact/jsx-dev-runtime";var tGw="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",eGw="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",gr0=({number:A,title:Q,blurb:w,children:B})=>F8("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:F8("div",{className:"max-w-6xl mx-auto",children:F8("div",{className:tGw,children:[F8(lu0,{title:Q,number:A,blurb:w},void 0,!1,void 0,this),F8("div",{className:eGw,"aria-hidden":"true"},void 0,!1,void 0,this),F8("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),Tr0=({profile:A,posts:Q,decks:w,postsListUrl:B,decksListUrl:$,cta:f,sections:D})=>{let Y=A.tagline||A.description,X=Q.map((F)=>({id:F.id,url:F.url,title:F.metadata.title,date:F.metadata.publishedAt||F.created,description:F.frontmatter.excerpt,series:F.frontmatter.seriesName&&F.frontmatter.seriesIndex?{name:F.frontmatter.seriesName,index:F.frontmatter.seriesIndex}:void 0})),H=w.map((F)=>({id:F.id,url:F.url,title:F.frontmatter.title||F.id,date:F.frontmatter.publishedAt??F.created,description:F.frontmatter.description})),W=A.name||"Home",Z=A.intro||A.description||Y||"Professional site",G=Boolean(A.description)||A.expertise!==void 0&&A.expertise.length>0;return F8(Azw,{children:[F8(NQ,{title:W,description:Z,ogType:"website"},void 0,!1,void 0,this),F8("div",{className:"homepage-list bg-theme",children:[F8("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:F8("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&F8("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[F8("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),F8("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Y&&F8("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:S90(Y,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&F8("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:S90(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),F8(gr0,{number:"01",title:"Essays",blurb:D.essays?.blurb,children:F8(T90,{items:X,viewAllUrl:B,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),H.length>0&&F8(gr0,{number:"02",title:"Presentations",blurb:D.presentations?.blurb,children:F8(T90,{items:H,viewAllUrl:$,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),G&&F8(gr0,{number:"03",title:"About",blurb:D.about?.blurb,children:F8("div",{className:"flex flex-col gap-8",children:[A.description&&F8("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&&F8(pu0,{subjects:A.expertise},void 0,!1,void 0,this),F8("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",F8("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),F8(ku0,{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 PB,Fragment as Qzw}from"preact/jsx-dev-runtime";var Sr0=({profile:A})=>{let Q=`About ${A.name||"Me"}`,w=A.description||A.intro||"About page",B=A.expertise&&A.expertise.length>0||A.currentFocus||A.availability||A.email||A.website||A.socialLinks&&A.socialLinks.length>0;return PB(Qzw,{children:[PB(NQ,{title:Q,description:w,ogType:"profile"},void 0,!1,void 0,this),PB("div",{className:"about-page bg-theme",children:[PB("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:PB("div",{className:"relative z-10 max-w-4xl mx-auto",children:[PB("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&&PB("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),PB("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&PB("section",{className:"content-section-reveal mb-20 md:mb-28",children:PB($9,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),B&&PB("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&PB("section",{children:[PB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),PB("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map(($,f)=>PB("li",{className:zn({variant:"accent",size:"lg"}),children:$},f,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&PB("section",{children:[PB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),PB("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&&PB("section",{children:[PB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),PB("p",{className:"text-lg text-theme leading-relaxed",children:A.availability},void 0,!1,void 0,this)]},void 0,!0,void 0,this),(A.email||A.website||A.socialLinks&&A.socialLinks.length>0)&&PB("section",{children:[PB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),PB("div",{className:"space-y-4",children:[A.email&&PB("p",{className:"text-lg",children:PB("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&&PB("p",{className:"text-lg",children:PB("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&&PB("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map(($,f)=>PB(B9,{href:$.url,external:!0,variant:"secondary",size:"md",children:$.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 x4,Fragment as ct1}from"preact/jsx-dev-runtime";var mr0=()=>{return x4(ct1,{children:[x4(NQ,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),x4("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:x4("div",{className:"text-center max-w-md",children:[x4("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),x4("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),x4("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),x4(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)},ur0=()=>{return x4(ct1,{children:[x4(NQ,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),x4("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:x4("div",{className:"text-center max-w-md",children:[x4("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),x4("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),x4("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),x4(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)};Z0();var lt1=K.object({label:K.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:K.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),pt1=K.object({entityDisplay:K.object({post:lt1,deck:lt1}).describe("Display metadata for post and deck entity types (required for homepage)")});var it1={name:"@brains/site-professional",private:!0,version:"0.2.0-alpha.133",description:"Professional site composition package",type:"module",exports:{".":"./src/index.ts"},files:["src"],scripts:{typecheck:"tsc --noEmit",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/blog":"workspace:*","@brains/decks":"workspace:*","@brains/identity-service":"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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class cr0 extends RQ{dependencies=["blog","decks"];constructor(A){super("professional-site",it1,A,pt1)}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 sD0(B,$);A.entities.registerDataSource(f);let D=new aD0;A.entities.registerDataSource(D);let Y=K.object({profile:gb,posts:K.array(YF),decks:K.array(zP),postsListUrl:K.string(),decksListUrl:K.string(),cta:Wp0,sections:K.record(K.string(),et)}),X=K.object({profile:gb}),H=K.object({});A.templates.register({"homepage-list":R1({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:Y,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:Tr0}}),about:R1({name:"about",description:"About page with full profile information",schema:X,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:Sr0}}),"subscribe-thanks":R1({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:H,requiredPermission:"public",layout:{component:mr0}}),"subscribe-error":R1({name:"subscribe-error",description:"Newsletter subscription error page",schema:H,requiredPermission:"public",layout:{component:ur0}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function dt1(A){return new cr0(A??{})}var nt1=[{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 tD0}from"preact/jsx-dev-runtime";function rt1({sections:A,siteInfo:Q,slots:w,wordmark:B}){return tD0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[tD0(hu0,{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),tD0("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),tD0(xu0,{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 Bzw={layouts:{default:rt1},routes:nt1,plugin:dt1,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=Bzw;var ot1=`/*
8611
+ `).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 CGw=new pw(RGw,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:hGw,parser:vGw},{key:"notes",label:"Notes",type:"string"}]});class kt1 extends I2{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:OGw,frontmatterSchema:kGw})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=CGw.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 Ot1 extends I2{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:xGw,frontmatterSchema:jY})}fromMarkdown(A){let Q=this.parseFrontMatter(A,jY);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var M76=new kt1,_76=new Ot1,P76=K.object({skills:K.array(jY),agents:K.array(K.object({id:K.string().optional(),name:K.string(),kind:K.enum(["professional","team","collective"]),organization:K.string().optional(),brainName:K.string(),url:K.string().url(),did:K.string().optional(),status:Rr0,discoveredAt:K.string().datetime().optional(),about:K.string(),skills:K.array(Pt1),notes:K.string().default("")}))});var yGw=K.object({}).strict();function pD0(A={}){return yGw.parse(A),[xr0()]}c0();Z0();Z0();var hr0=K.object({enabled:K.boolean().default(!0),pdsEndpoint:K.string().url().default("https://bsky.social").describe("AT Protocol PDS service endpoint"),identifier:K.string().optional().describe("PDS login identifier, usually a handle or account DID"),repoDid:K.string().optional().describe("DID of the PDS repo that owns records"),appPassword:K.string().optional().describe("App password for prototype authentication; supply via ${ENV_VAR} interpolation, never a committed literal"),anchorDid:K.string().optional().describe("Optional human/operator DID referenced from records; defaults to did:web:<site-host>:anchor when omitted"),brainDid:K.string().optional().describe("Optional public brain DID referenced from records; defaults to did:web:<site-host> when omitted")});function EGw(A){return A.replace(/\/+$/,"")}var gGw=(A,Q)=>fetch(A,Q);async function yo(A){let Q=await A.json();if(!A.ok){let w=typeof Q==="object"&&Q!==null&&"message"in Q&&typeof Q.message==="string"?Q.message:`AT Protocol request failed with ${A.status}`;throw Error(w)}return Q}class Eo{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=EGw(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??gGw}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 yo(A);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 yo(w)}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 yo(w)}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 yo(w)}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 yo(w)}async getSession(){return this.session??=await this.createSession(),this.session}}function yP(A){return A?.startsWith("did:web:")??!1}function iD0(A){if(!yP(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 Rt1(A){if(!yP(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 ht1(A){return A.replace(/\/+$/,"")}function go(A){return`did:web:${encodeURIComponent(A)}`}function dD0(A){return`${go(A)}:anchor`}function vr0(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function vt1(A,Q){let w=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...vr0(Q),...w&&{alsoKnownAs:w},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:ht1(A.pdsEndpoint)}]}}function Ct1(A){if(!yP(A.brainDid))return null;return vt1(A,A.brainDid)}function xt1(A,Q){if(!A||!Q)return;let w=iD0(A),B=Rt1(A);if(!w||!B)return;return{path:B,hostname:w,document:Q}}function nD0(A){let Q=[],w=xt1(A.brainDid,Ct1(A));if(w)Q.push(w);if(yP(A.anchorDid)&&A.anchorDid!==A.brainDid){let B=xt1(A.anchorDid,vr0(A.anchorDid));if(B)Q.push(B)}return Q}function Cr0(A,Q){let w=[];if(!A.brainDid){let B=go(Q);w.push({path:"/.well-known/did.json",hostname:Q,document:vt1(A,B)})}if(!A.anchorDid){let B=dD0(Q);w.push({path:"/anchor/did.json",hostname:Q,document:vr0(B)})}return w}function TGw(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function SGw(A){let Q=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,200);return Q.length>0?Q:"skill"}function yt1(A,Q){let w=A[Q];return typeof w==="string"&&w.length>0?w:void 0}function Et1(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 mGw(A){let Q=A.metadata,w=yt1(Q,"name"),B=yt1(Q,"description");if(!w||!B)return;let $=Et1(Q,"tags"),f=Et1(Q,"examples");return{id:SGw(w),name:w,description:B,...$&&{tags:$},...f&&{examples:f}}}async function uGw(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map((w)=>mGw(w)).filter((w)=>w!==void 0).slice(0,100)}async function yr0(A,Q,w=new Date){let B=A.identity.get(),$=A.identity.getProfile(),f=await A.identity.getAppInfo(),D=TGw(A.siteUrl??$.website,void 0);if(!D)throw Error("AT Protocol brain card publishing requires siteUrl");let Y=new URL(D).hostname,X=Q.brainDid??go(Y),H=Q.anchorDid??dD0(Y);if(yP(X)){if(iD0(X)!==Y)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let W=await uGw(A);return{$type:"ai.rizom.brain.card",siteUrl:D,brain:{did:X,name:B.name,role:B.role,purpose:B.purpose,values:B.values},anchor:{did:H,name:$.name,kind:$.kind},skills:W,model:f.model,version:f.version,createdAt:w.toISOString(),updatedAt:w.toISOString()}}var gt1={name:"@brains/atproto",private:!0,version:"0.2.0-alpha.134",description:"AT Protocol integration for identity, publishing, discovery, and feeds",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var Tt1=MB["ai.rizom.brain.card"],lGw="ai.rizom.brain.card",pGw="self",St1=50;class Er0 extends RQ{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",gt1,A,hr0);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??U5.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=nD0(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,D=[...nD0(this.config),...Cr0(this.config,f)].filter((X)=>X.path===B),Y=D.find((X)=>X.hostname===f)??D[0];if(!Y)return new Response("Not found",{status:404});return new Response(JSON.stringify(Y.document),{headers:{"Content-Type":"application/did+json"}})}}))}async publishBrainCard(A,Q={}){let w=await yr0(A,this.config);Vb(Tt1,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($),D=await f.createSession(),Y=B??D.did;if(!f.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let X=await f.putRecord({repo:Y,collection:"ai.rizom.brain.card",rkey:"self",validate:!1,record:w});return{record:w,repo:Y,uri:X.uri,cid:X.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>St1)throw Error(`AT Protocol discovery accepts at most ${St1} repos per batch`);let B=new Set,$=[];for(let f of w)try{let D=await this.resolveRepoPdsEndpoint(f),Y=this.createPublicPdsClient(D.pdsEndpoint);if(!Y.getRecord)throw Error("AT Protocol PDS client does not support record reads");let X=await Y.getRecord({repo:D.repoDid,collection:lGw,rkey:pGw});Vb(Tt1,X.value);let H=dGw(X.uri)??D.repoDid,W=`${H}:${X.uri}:${X.cid}`;if(B.has(W)){$.push({repo:f,status:"skipped",repoDid:H,uri:X.uri,cid:X.cid,error:"Duplicate brain card in discovery batch"});continue}B.add(W),await A.messaging.send({type:M40,payload:{repoDid:H,uri:X.uri,cid:X.cid,record:X.value},broadcast:!0}),$.push({repo:f,status:"discovered",repoDid:H,uri:X.uri,cid:X.cid})}catch(D){$.push({repo:f,status:"skipped",error:vA(D)})}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:vA(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 G=await w.buildRecord({entity:B,context:A,config:this.config,...Q.topics&&{topics:Q.topics},dryRun:!0});return Vb(w.lexicon,G),{record:G,dryRun:!0,...f&&{repo:f}}}let D=this.resolveAppPassword();if(!this.config.identifier||!D)throw Error("AT Protocol publishing requires identifier and app password configuration");let Y=this.createPdsClient(D),X=await Y.createSession(),H=f??X.did,W=await w.buildRecord({entity:B,context:A,config:this.config,client:Y,...Q.topics&&{topics:Q.topics}});if(Vb(w.lexicon,W),!Y.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let Z=await Y.putRecord({repo:H,collection:w.collection,rkey:iGw(B.id),...w.validate!==void 0&&{validate:w.validate},record:W});return await w.onPublished?.({entity:B,context:A,record:W,uri:Z.uri,cid:Z.cid}),{record:W,repo:H,uri:Z.uri,cid:Z.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 Eo({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=await w.json();if(typeof B!=="object"||B===null||!("did"in B))return;return typeof B.did==="string"?B.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(nGw(A)):void 0;if(typeof Q!=="object"||Q===null)return;let w=Q.service;if(!Array.isArray(w))return;let B=w.find(($)=>{return typeof $==="object"&&$!==null&&($.id==="#atproto_pds"||$.type==="AtprotoPersonalDataServer")});return typeof B?.serviceEndpoint==="string"?B.serviceEndpoint:void 0}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 Eo({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function iGw(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function dGw(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function nGw(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 rD0(A,Q){return new Er0(A,Q)}c0();Z0();var oD0={name:"@brains/rover",version:"0.2.0-alpha.134",type:"module",private:!0,main:"./src/index.ts",files:["src","brain.eval.yaml","env.schema.template"],scripts:{"build:web-chat":"turbo run build --filter=@brains/web-chat","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",typecheck:"tsc --noEmit",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 .","lint:fix":"eslint . --fix"},dependencies:{"@brains/a2a":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/analytics":"workspace:*","@brains/app":"workspace:*","@brains/assessment":"workspace:*","@brains/atproto":"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/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/playbook":"workspace:*","@brains/playbooks":"workspace:*","@brains/portfolio":"workspace:*","@brains/prompt":"workspace:*","@brains/rizom-ecosystem":"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:"^5.3.3"}};var oGw=K.object({}).strict();class mt1 extends RQ{constructor(A={}){super("rover-profile",oD0,A,oGw)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",ON)}}function ut1(A={}){return new mt1(A)}c0();Z0();JB();_5();c0();var gb=QZ.extend(ON.shape);c0();zq();Z0();var sGw=new VU;class sD0{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,D,Y]=await Promise.all([Wx(B),B.listEntities({entityType:"post",options:{limit:20}}),B.listEntities({entityType:"deck",options:{limit:20}}),Gr(B)]),X=sGw.parseProfileBody($,gb),H=f.sort(OT).slice(0,3).map(Fr),W=D.sort(OT).slice(0,3).map(Nr);if(!Y.cta)throw Error("CTA not configured in site-info");let Z={profile:X,posts:H,decks:W,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:Y.cta,sections:Y.sections??{}};return Q.parse(Z)}}c0();zq();var aGw=new VU;class aD0{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,w){let B=await Wx(w.entityService),f={profile:aGw.parseProfileBody(B,gb)};return Q.parse(f)}}import{jsxDEV as F8,Fragment as Azw}from"preact/jsx-dev-runtime";var tGw="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",eGw="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",gr0=({number:A,title:Q,blurb:w,children:B})=>F8("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:F8("div",{className:"max-w-6xl mx-auto",children:F8("div",{className:tGw,children:[F8(lu0,{title:Q,number:A,blurb:w},void 0,!1,void 0,this),F8("div",{className:eGw,"aria-hidden":"true"},void 0,!1,void 0,this),F8("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),Tr0=({profile:A,posts:Q,decks:w,postsListUrl:B,decksListUrl:$,cta:f,sections:D})=>{let Y=A.tagline||A.description,X=Q.map((F)=>({id:F.id,url:F.url,title:F.metadata.title,date:F.metadata.publishedAt||F.created,description:F.frontmatter.excerpt,series:F.frontmatter.seriesName&&F.frontmatter.seriesIndex?{name:F.frontmatter.seriesName,index:F.frontmatter.seriesIndex}:void 0})),H=w.map((F)=>({id:F.id,url:F.url,title:F.frontmatter.title||F.id,date:F.frontmatter.publishedAt??F.created,description:F.frontmatter.description})),W=A.name||"Home",Z=A.intro||A.description||Y||"Professional site",G=Boolean(A.description)||A.expertise!==void 0&&A.expertise.length>0;return F8(Azw,{children:[F8(NQ,{title:W,description:Z,ogType:"website"},void 0,!1,void 0,this),F8("div",{className:"homepage-list bg-theme",children:[F8("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:F8("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&F8("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[F8("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),F8("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Y&&F8("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:S90(Y,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&F8("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:S90(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),F8(gr0,{number:"01",title:"Essays",blurb:D.essays?.blurb,children:F8(T90,{items:X,viewAllUrl:B,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),H.length>0&&F8(gr0,{number:"02",title:"Presentations",blurb:D.presentations?.blurb,children:F8(T90,{items:H,viewAllUrl:$,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),G&&F8(gr0,{number:"03",title:"About",blurb:D.about?.blurb,children:F8("div",{className:"flex flex-col gap-8",children:[A.description&&F8("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&&F8(pu0,{subjects:A.expertise},void 0,!1,void 0,this),F8("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",F8("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),F8(ku0,{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 PB,Fragment as Qzw}from"preact/jsx-dev-runtime";var Sr0=({profile:A})=>{let Q=`About ${A.name||"Me"}`,w=A.description||A.intro||"About page",B=A.expertise&&A.expertise.length>0||A.currentFocus||A.availability||A.email||A.website||A.socialLinks&&A.socialLinks.length>0;return PB(Qzw,{children:[PB(NQ,{title:Q,description:w,ogType:"profile"},void 0,!1,void 0,this),PB("div",{className:"about-page bg-theme",children:[PB("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:PB("div",{className:"relative z-10 max-w-4xl mx-auto",children:[PB("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&&PB("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),PB("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&PB("section",{className:"content-section-reveal mb-20 md:mb-28",children:PB($9,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),B&&PB("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&PB("section",{children:[PB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),PB("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map(($,f)=>PB("li",{className:zn({variant:"accent",size:"lg"}),children:$},f,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&PB("section",{children:[PB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),PB("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&&PB("section",{children:[PB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),PB("p",{className:"text-lg text-theme leading-relaxed",children:A.availability},void 0,!1,void 0,this)]},void 0,!0,void 0,this),(A.email||A.website||A.socialLinks&&A.socialLinks.length>0)&&PB("section",{children:[PB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),PB("div",{className:"space-y-4",children:[A.email&&PB("p",{className:"text-lg",children:PB("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&&PB("p",{className:"text-lg",children:PB("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&&PB("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map(($,f)=>PB(B9,{href:$.url,external:!0,variant:"secondary",size:"md",children:$.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 x4,Fragment as ct1}from"preact/jsx-dev-runtime";var mr0=()=>{return x4(ct1,{children:[x4(NQ,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),x4("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:x4("div",{className:"text-center max-w-md",children:[x4("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),x4("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),x4("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),x4(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)},ur0=()=>{return x4(ct1,{children:[x4(NQ,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),x4("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:x4("div",{className:"text-center max-w-md",children:[x4("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),x4("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),x4("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),x4(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)};Z0();var lt1=K.object({label:K.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:K.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),pt1=K.object({entityDisplay:K.object({post:lt1,deck:lt1}).describe("Display metadata for post and deck entity types (required for homepage)")});var it1={name:"@brains/site-professional",private:!0,version:"0.2.0-alpha.134",description:"Professional site composition package",type:"module",exports:{".":"./src/index.ts"},files:["src"],scripts:{typecheck:"tsc --noEmit",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/blog":"workspace:*","@brains/decks":"workspace:*","@brains/identity-service":"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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class cr0 extends RQ{dependencies=["blog","decks"];constructor(A){super("professional-site",it1,A,pt1)}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 sD0(B,$);A.entities.registerDataSource(f);let D=new aD0;A.entities.registerDataSource(D);let Y=K.object({profile:gb,posts:K.array(YF),decks:K.array(zP),postsListUrl:K.string(),decksListUrl:K.string(),cta:Wp0,sections:K.record(K.string(),et)}),X=K.object({profile:gb}),H=K.object({});A.templates.register({"homepage-list":R1({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:Y,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:Tr0}}),about:R1({name:"about",description:"About page with full profile information",schema:X,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:Sr0}}),"subscribe-thanks":R1({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:H,requiredPermission:"public",layout:{component:mr0}}),"subscribe-error":R1({name:"subscribe-error",description:"Newsletter subscription error page",schema:H,requiredPermission:"public",layout:{component:ur0}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function dt1(A){return new cr0(A??{})}var nt1=[{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 tD0}from"preact/jsx-dev-runtime";function rt1({sections:A,siteInfo:Q,slots:w,wordmark:B}){return tD0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[tD0(hu0,{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),tD0("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),tD0(xu0,{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 Bzw={layouts:{default:rt1},routes:nt1,plugin:dt1,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=Bzw;var ot1=`/*
8612
8612
  * Default theme \u2014 simplified editorial base inspired by the Rizom family.
8613
8613
  *
8614
8614
  * This theme is intentionally less branded than @brains/theme-rizom. It
@@ -8996,8 +8996,8 @@ ${JSON.stringify(w,null,2)}`}function mD0(A){return A.map((Q)=>Q.detail===null?{
8996
8996
 
8997
8997
  .btn-primary:disabled { opacity: 0.5; }
8998
8998
  }
8999
- `;var EE=ot1;import{join as fzw}from"path";var st1=["prompt","rover-profile","image","document","note","link","wishlist","topics","directory-sync","atproto","agents","assessment","auth-service","notifications","playbook","playbooks","email-resend","cms","dashboard-root","mcp","webserver","web-chat","discord","a2a"],at1=[...st1.filter((A)=>A!=="dashboard-root"),"dashboard","blog","series","decks","analytics","obsidian-vault","site-info","site-builder"],Dzw=[...at1,"portfolio","topics","content-pipeline","social-media","newsletter","stock-photo"],Yzw=["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.","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."],tt1=VI({name:"rover",version:oD0.version,model:"gpt-5.4-mini",site:To,theme:EE,presets:{core:st1,default:at1,full:Dzw},evalDisable:["discord","chat","webserver","web-chat","mcp","atproto","analytics","dashboard","dashboard-root","email-resend"],agentInstructions:Yzw,capabilities:[["prompt",hP,void 0],["rover-profile",ut1,{}],["image",Uc,void 0],["cms",OP,(A)=>({...A.CMS_CONTENT_REPO_PAT?{passkeyLogin:{contentRepoToken:A.CMS_CONTENT_REPO_PAT}}:{}})],["auth-service",$p,void 0],["notifications",ow0,void 0],["playbook",ts1,{}],["playbooks",un0,{}],["email-resend",l$0,void 0],["dashboard",yb,void 0],["dashboard-root",yb,{routePath:"/"}],["blog",Rp0,{}],["series",gp0,void 0],["decks",jr,void 0],["document",ci0,void 0],["note",bP,{}],["link",NP,{}],["portfolio",qd0,{}],["topics",lf0,{includeEntityTypes:["post","deck","project","link","anchor-profile"]}],["content-pipeline",Bn0,{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",Yo,{autoGenerateOnBlogPublish:!0}],["newsletter",Cs1,{doubleOptIn:!0}],["obsidian-vault",_n0,{autoSync:!0}],["wishlist",FD0,{}],["stock-photo",sn0,{}],["agents",CD0,void 0],["assessment",pD0,void 0],["atproto",rD0,(A)=>({...A.ATPROTO_APP_PASSWORD?{appPassword:A.ATPROTO_APP_PASSWORD}:{}})],["directory-sync",j_,()=>({seedContent:!0,seedContentPath:fzw(import.meta.dir,"..","seed-content-core"),initialSync:!0})],["analytics",fD0,{}],["rizom-ecosystem",vP,void 0],["site-info",HP,void 0],["site-builder",XP,{cms:{}}]],interfaces:[["mcp",eI,()=>({})],["discord",gJ,()=>({})],["chat",F50,()=>({})],["webserver",uJ,()=>({})],["web-chat",TC,()=>({})],["a2a",SC,()=>({})]],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"}}});bI();c0();Z0();var et1={name:"@brains/atproto-registry",private:!0,version:"0.2.0-alpha.133",description:"Canonical Rizom AT Protocol lexicon registry",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var Qe1=K.object({enabled:K.boolean().default(!0)}),lr0="/atproto/lexicons";function Ae1(A){return new Response(`${JSON.stringify(A,null,2)}
9000
- `,{headers:{"Content-Type":"application/json"}})}class pr0 extends RQ{constructor(A={}){super("atproto-registry",et1,A,Qe1)}getWebRoutes(){if(!this.config.enabled)return[];return[{path:`${lr0}/index.json`,method:"GET",public:!0,handler:()=>Ae1(this.getIndex())},...WP().map((A)=>({path:`${lr0}/${A.id}.json`,method:"GET",public:!0,handler:()=>Ae1(A)}))]}getIndex(){return{lexicons:zp0().map((A)=>({...A,path:`${lr0}/${A.id}.json`}))}}getLexicon(A){return Gp0(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:K.string().describe("Canonical lexicon NSID"),record:K.record(K.unknown()).describe("Record payload to validate")},handler:async(A)=>{let Q=K.object({nsid:K.string(),record:K.record(K.unknown())}).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 Vb(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:WP().length,nsids:WP().map((A)=>A.id),metadata:zp0()}})}}}function ir0(A={}){return new pr0(A)}c0();Z0();Z0();c0();var eD0=K.object({routeId:K.string(),sectionId:K.string()}),So=o1.extend({entityType:K.literal("site-content"),template:K.string().optional(),content:K.string(),metadata:eD0});c0();class we1 extends I2{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:So,frontmatterSchema:eD0})}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 dr0=new we1;Z0();var AY0=K.object({routeId:K.string().optional().describe("Optional: specific route filter"),sectionId:K.string().optional().describe("Optional: specific section filter"),dryRun:K.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:K.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),OD6=K.object({jobs:K.array(K.object({jobId:K.string(),routeId:K.string(),sectionId:K.string()})),totalSections:K.number(),queuedSections:K.number(),skippedSections:K.number().optional(),batchId:K.string().optional()});class nr0{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");return A.data}async generate(A,Q,w){let B=this.context.logger.child("SiteContentOperations"),$=await this.fetchRoutes(),f=$;if(A.routeId){if(f=$.filter((W)=>W.id===A.routeId),f.length===0)throw Error(`Route not found: ${A.routeId}`)}let D=[];for(let W of f)for(let Z of W.sections){if(A.sectionId&&Z.id!==A.sectionId)continue;if(Z.content){B.debug("Section has static content, skipping",{routeId:W.id,sectionId:Z.id});continue}if(Z.template){let G=this.context.templates.getCapabilities(Z.template);if(!G){B.warn("Template not found, skipping section",{routeId:W.id,sectionId:Z.id,templateName:Z.template});continue}if(!G.canGenerate){B.debug("Template doesn't support generation, skipping",{routeId:W.id,sectionId:Z.id,templateName:Z.template,capabilities:G});continue}}else{B.debug("Section has no template, skipping",{routeId:W.id,sectionId:Z.id});continue}if(!A.force&&!A.dryRun){let G=`${W.id}:${Z.id}`;if(await this.context.entityService.getEntity({entityType:"site-content",id:G})){B.debug("Content already exists, skipping",{routeId:W.id,sectionId:Z.id});continue}}D.push({route:W,section:Z})}let Y=D.length;if(A.dryRun)return{jobs:[],totalSections:Y,queuedSections:Y,batchId:`dry-run-${Date.now()}`};let X=[],H=[];for(let{route:W,section:Z}of D){let G=`${W.id}:${Z.id}`,F=Z.template,V={routeId:W.id,sectionId:Z.id,entityId:G,entityType:"site-content",templateName:F,context:{prompt:typeof Z.content==="string"?Z.content:void 0,data:{routeId:W.id,sectionId:Z.id,routeTitle:W.title??Q?.title??"",routeDescription:W.description??Q?.description??"",sectionContent:Z.content},conversationId:"system"},siteConfig:Q};H.push({type:"shell:content-generation",data:V})}if(H.length>0){let W=this.createJobOptions(w,"site:content-generation"),Z=await this.context.jobs.enqueueBatch(H,W);for(let G=0;G<D.length;G++){let F=D[G];if(F)X.push({jobId:`${Z}-${G}`,routeId:F.route.id,sectionId:F.section.id})}return{jobs:X,totalSections:Y,queuedSections:X.length,batchId:Z}}return{jobs:[],totalSections:Y,queuedSections:0,batchId:`empty-${Date.now()}`}}}class rr0{siteConfig;operations;constructor(A,Q){this.siteConfig=Q;this.operations=new nr0(A)}async generateContent(A,Q){let w=AY0.parse(A);return this.operations.generate(w,this.siteConfig,Q)}}l$();Z0();function mo(A,Q){return Q?A.optional():A}function sr0(A){switch(A.type){case"string":return mo(K.string(),A.optional);case"number":return mo(K.number(),A.optional);case"enum":{let Q=[...A.options];return mo(K.enum(Q),A.optional)}case"object":{let Q={};for(let[w,B]of Object.entries(A.fields))Q[w]=sr0(B);return mo(K.object(Q),A.optional)}case"array":{let Q=K.array(Hzw(A));if(A.minItems!==void 0)Q=Q.min(A.minItems);if(A.length!==void 0)Q=Q.length(A.length);return mo(Q,A.optional)}}}function Hzw(A){let{items:Q}=A;switch(Q.type){case"string":return K.string();case"number":return K.number();case"enum":{let w=[...Q.options];return K.enum(w)}case"object":{let w={};for(let[B,$]of Object.entries(Q.fields))w[B]=sr0($);return K.object(w)}}}function or0(A,Q){switch(Q.type){case"string":case"enum":return{key:A,label:Q.label,type:"string"};case"number":return{key:A,label:Q.label,type:"number"};case"object":return{key:A,label:Q.label,type:"object",children:Object.entries(Q.fields).map(([w,B])=>or0(w,B))};case"array":{let w={key:A,label:Q.label,type:"array"};switch(Q.items.type){case"string":case"enum":return w.itemType="string",w;case"number":return w.itemType="number",w;case"object":return w.itemType="object",w.itemMappings=Object.entries(Q.items.fields).map(([B,$])=>or0(B,$)),w}}}}function Wzw(A,Q){let w={};for(let[f,D]of Object.entries(Q.fields))w[f]=sr0(D);let B=K.object(w),$=new pw(B,{title:Q.title,mappings:Object.entries(Q.fields).map(([f,D])=>or0(f,D))});return{name:A,description:Q.description,schema:B,formatter:$,requiredPermission:Q.requiredPermission??"public",layout:{component:Q.layout,...Q.fullscreen!==void 0?{fullscreen:Q.fullscreen}:{}},...Q.runtimeScripts?{runtimeScripts:Q.runtimeScripts}:{}}}function ar0(A){return Object.fromEntries(Object.entries(A.sections).map(([Q,w])=>[Q,Wzw(Q,w)]))}Z0();var Be1=K.object({namespace:K.string(),sections:K.record(K.any())}),$e1=K.object({definitions:K.union([Be1,K.array(Be1)]).optional()});c0();function fe1(A,Q){return[Sw(Q,"generate","Generate content for all routes, a specific route, or a specific section",AY0,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},D=await $.generateContent(w,f);return{success:!0,message:`Generated ${D.queuedSections} of ${D.totalSections} sections. ${D.queuedSections>0?"Jobs are running in the background.":"No new content to generate."}`,data:{batchId:D.batchId,jobsQueued:D.queuedSections,totalSections:D.totalSections,jobs:D.jobs}}})]}var De1={name:"@brains/site-content",private:!0,version:"0.2.0-alpha.133",description:"Site content entity and generation orchestration",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/content-formatters":"workspace:*","@brains/plugins":"workspace:*","@brains/site-info":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class tr0 extends RQ{siteContentService;constructor(A={}){super("site-content",De1,A,$e1)}async onRegister(A){A.entities.register("site-content",So,dr0);for(let Q of YU(this.config.definitions))A.templates.register(ar0(Q),Q.namespace);this.siteContentService=new rr0(A)}async getTools(){return fe1(()=>this.siteContentService,this.id)}}function uo(A={}){return new tr0(A)}c0();Z0();JB();Z0();c0();var Ye1=K.enum(["available","early access","coming soon","planned"]),Xe1=K.object({title:K.string(),description:K.string()}),vX=K.object({name:K.string(),availability:Ye1,order:K.number(),ogImageId:K.string().optional()}),QY0=K.object({tagline:K.string(),promise:K.string(),role:K.string(),purpose:K.string(),audience:K.string(),values:K.array(K.string()).min(1),features:K.array(Xe1).min(1).max(6),story:K.string()}),Kzw=vX.pick({name:!0,availability:!0,order:!0}).extend({slug:K.string()}),gE=o1.extend({entityType:K.literal("product"),metadata:Kzw}),wY0=gE.extend({frontmatter:vX,body:QY0,labels:K.record(K.string(),K.string()),ogImageUrl:K.string().optional()}),BY0=wY0.extend({url:K.string().optional(),typeLabel:K.string().optional(),listUrl:K.string().optional(),listLabel:K.string().optional(),ogImageUrl:K.string().optional()});c0();Z0();l$();class TE extends pw{constructor(){super(QY0,{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 er0 extends I2{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:gE,frontmatterSchema:vX,bodyFormatter:new TE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,vX);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,vX),w=w1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:w,availability:Q.availability,order:Q.order}}}}var $Y0=new er0;Z0();c0();var He1=K.object({title:K.string(),description:K.string()}),We1=K.object({title:K.string(),description:K.string()}),Uzw=K.object({title:K.string(),description:K.string()}),Ze1=K.object({heading:K.string(),buttonText:K.string(),link:K.string()}),JF=K.object({headline:K.string(),tagline:K.string()}),Gzw=K.object({title:K.string(),description:K.string()}),fY0=K.object({vision:K.string(),pillars:K.array(He1).min(1).max(6),approach:K.array(Gzw).min(1).max(6),productsIntro:K.string(),technologies:K.array(Uzw).min(1).max(6),benefits:K.array(We1).min(1).max(6),cta:Ze1}),Ke1=JF.pick({headline:!0}).extend({slug:K.string()}),SE=o1.extend({entityType:K.literal("products-overview"),metadata:Ke1}),co=SE.extend({frontmatter:JF,body:fY0,labels:K.record(K.string(),K.string())});c0();Z0();l$();class mE extends pw{constructor(){super(fY0,{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 Ao0 extends I2{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:SE,frontmatterSchema:JF,bodyFormatter:new mE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,JF);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,JF),w=w1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:w}}}}var Qo0=new Ao0;c0();Z0();var zzw=K.object({entityType:K.string(),query:K.object({id:K.string().optional()}).optional()});function Ue1(A,Q){let w=v2(A.content,vX),B=Q.parse(w.content),$=Q.getLabels();return wY0.parse({...A,frontmatter:w.metadata,body:B,labels:$})}function Ge1(A,Q){let w=v2(A.content,JF),B=Q.parse(w.content),$=Q.getLabels();return co.parse({...A,frontmatter:w.metadata,body:B,labels:$})}class DY0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new mE;productFormatter=new TE;constructor(A){this.logger=A;this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,w){let B=zzw.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 W=Ge1(H,this.overviewFormatter);return Q.parse(W)}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:Ue1(H,this.productFormatter)})}let[f,D]=await Promise.all([$.listEntities({entityType:"products-overview",options:{limit:1}}),$.listEntities({entityType:"product",options:{sortFields:[{field:"order",direction:"asc"}]}})]),Y=f[0];if(!Y)throw Error("Products overview entity not found");return Q.parse({overview:Ge1(Y,this.overviewFormatter),products:D.map((X)=>Ue1(X,this.productFormatter))})}}import{jsxDEV as B1,Fragment as Vzw}from"preact/jsx-dev-runtime";var ze1=({overview:A,products:Q})=>{let{frontmatter:w,body:B,labels:$}=A;return B1(Vzw,{children:[B1(NQ,{title:w.headline,description:w.tagline},void 0,!1,void 0,this),B1("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[B1("style",{children:`
8999
+ `;var EE=ot1;import{join as fzw}from"path";var st1=["prompt","rover-profile","image","document","note","link","wishlist","topics","directory-sync","atproto","agents","assessment","auth-service","notifications","playbook","playbooks","email-resend","cms","dashboard-root","mcp","webserver","web-chat","discord","a2a"],at1=[...st1.filter((A)=>A!=="dashboard-root"),"dashboard","blog","series","decks","analytics","obsidian-vault","site-info","site-builder"],Dzw=[...at1,"portfolio","topics","content-pipeline","social-media","newsletter","stock-photo"],Yzw=["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.","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."],tt1=VI({name:"rover",version:oD0.version,model:"gpt-5.4-mini",site:To,theme:EE,presets:{core:st1,default:at1,full:Dzw},evalDisable:["discord","chat","webserver","web-chat","mcp","atproto","analytics","dashboard","dashboard-root","email-resend"],agentInstructions:Yzw,capabilities:[["prompt",hP,void 0],["rover-profile",ut1,{}],["image",Uc,void 0],["cms",OP,(A)=>({...A.CMS_CONTENT_REPO_PAT?{passkeyLogin:{contentRepoToken:A.CMS_CONTENT_REPO_PAT}}:{}})],["auth-service",$p,void 0],["notifications",ow0,void 0],["playbook",ts1,{}],["playbooks",un0,{}],["email-resend",l$0,void 0],["dashboard",yb,void 0],["dashboard-root",yb,{routePath:"/"}],["blog",Rp0,{}],["series",gp0,void 0],["decks",jr,void 0],["document",ci0,void 0],["note",bP,{}],["link",NP,{}],["portfolio",qd0,{}],["topics",lf0,{includeEntityTypes:["post","deck","project","link","anchor-profile"]}],["content-pipeline",Bn0,{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",Yo,{autoGenerateOnBlogPublish:!0}],["newsletter",Cs1,{doubleOptIn:!0}],["obsidian-vault",_n0,{autoSync:!0}],["wishlist",FD0,{}],["stock-photo",sn0,{}],["agents",CD0,void 0],["assessment",pD0,void 0],["atproto",rD0,(A)=>({...A.ATPROTO_APP_PASSWORD?{appPassword:A.ATPROTO_APP_PASSWORD}:{}})],["directory-sync",j_,()=>({seedContent:!0,seedContentPath:fzw(import.meta.dir,"..","seed-content-core"),initialSync:!0})],["analytics",fD0,{}],["rizom-ecosystem",vP,void 0],["site-info",HP,void 0],["site-builder",XP,{cms:{}}]],interfaces:[["mcp",eI,()=>({})],["discord",gJ,()=>({})],["chat",F50,()=>({})],["webserver",uJ,()=>({})],["web-chat",TC,()=>({})],["a2a",SC,()=>({})]],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"}}});bI();c0();Z0();var et1={name:"@brains/atproto-registry",private:!0,version:"0.2.0-alpha.134",description:"Canonical Rizom AT Protocol lexicon registry",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint src test --ext .ts","lint:fix":"eslint src test --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var Qe1=K.object({enabled:K.boolean().default(!0)}),lr0="/atproto/lexicons";function Ae1(A){return new Response(`${JSON.stringify(A,null,2)}
9000
+ `,{headers:{"Content-Type":"application/json"}})}class pr0 extends RQ{constructor(A={}){super("atproto-registry",et1,A,Qe1)}getWebRoutes(){if(!this.config.enabled)return[];return[{path:`${lr0}/index.json`,method:"GET",public:!0,handler:()=>Ae1(this.getIndex())},...WP().map((A)=>({path:`${lr0}/${A.id}.json`,method:"GET",public:!0,handler:()=>Ae1(A)}))]}getIndex(){return{lexicons:zp0().map((A)=>({...A,path:`${lr0}/${A.id}.json`}))}}getLexicon(A){return Gp0(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:K.string().describe("Canonical lexicon NSID"),record:K.record(K.unknown()).describe("Record payload to validate")},handler:async(A)=>{let Q=K.object({nsid:K.string(),record:K.record(K.unknown())}).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 Vb(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:WP().length,nsids:WP().map((A)=>A.id),metadata:zp0()}})}}}function ir0(A={}){return new pr0(A)}c0();Z0();Z0();c0();var eD0=K.object({routeId:K.string(),sectionId:K.string()}),So=o1.extend({entityType:K.literal("site-content"),template:K.string().optional(),content:K.string(),metadata:eD0});c0();class we1 extends I2{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:So,frontmatterSchema:eD0})}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 dr0=new we1;Z0();var AY0=K.object({routeId:K.string().optional().describe("Optional: specific route filter"),sectionId:K.string().optional().describe("Optional: specific section filter"),dryRun:K.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:K.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),OD6=K.object({jobs:K.array(K.object({jobId:K.string(),routeId:K.string(),sectionId:K.string()})),totalSections:K.number(),queuedSections:K.number(),skippedSections:K.number().optional(),batchId:K.string().optional()});class nr0{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");return A.data}async generate(A,Q,w){let B=this.context.logger.child("SiteContentOperations"),$=await this.fetchRoutes(),f=$;if(A.routeId){if(f=$.filter((W)=>W.id===A.routeId),f.length===0)throw Error(`Route not found: ${A.routeId}`)}let D=[];for(let W of f)for(let Z of W.sections){if(A.sectionId&&Z.id!==A.sectionId)continue;if(Z.content){B.debug("Section has static content, skipping",{routeId:W.id,sectionId:Z.id});continue}if(Z.template){let G=this.context.templates.getCapabilities(Z.template);if(!G){B.warn("Template not found, skipping section",{routeId:W.id,sectionId:Z.id,templateName:Z.template});continue}if(!G.canGenerate){B.debug("Template doesn't support generation, skipping",{routeId:W.id,sectionId:Z.id,templateName:Z.template,capabilities:G});continue}}else{B.debug("Section has no template, skipping",{routeId:W.id,sectionId:Z.id});continue}if(!A.force&&!A.dryRun){let G=`${W.id}:${Z.id}`;if(await this.context.entityService.getEntity({entityType:"site-content",id:G})){B.debug("Content already exists, skipping",{routeId:W.id,sectionId:Z.id});continue}}D.push({route:W,section:Z})}let Y=D.length;if(A.dryRun)return{jobs:[],totalSections:Y,queuedSections:Y,batchId:`dry-run-${Date.now()}`};let X=[],H=[];for(let{route:W,section:Z}of D){let G=`${W.id}:${Z.id}`,F=Z.template,V={routeId:W.id,sectionId:Z.id,entityId:G,entityType:"site-content",templateName:F,context:{prompt:typeof Z.content==="string"?Z.content:void 0,data:{routeId:W.id,sectionId:Z.id,routeTitle:W.title??Q?.title??"",routeDescription:W.description??Q?.description??"",sectionContent:Z.content},conversationId:"system"},siteConfig:Q};H.push({type:"shell:content-generation",data:V})}if(H.length>0){let W=this.createJobOptions(w,"site:content-generation"),Z=await this.context.jobs.enqueueBatch(H,W);for(let G=0;G<D.length;G++){let F=D[G];if(F)X.push({jobId:`${Z}-${G}`,routeId:F.route.id,sectionId:F.section.id})}return{jobs:X,totalSections:Y,queuedSections:X.length,batchId:Z}}return{jobs:[],totalSections:Y,queuedSections:0,batchId:`empty-${Date.now()}`}}}class rr0{siteConfig;operations;constructor(A,Q){this.siteConfig=Q;this.operations=new nr0(A)}async generateContent(A,Q){let w=AY0.parse(A);return this.operations.generate(w,this.siteConfig,Q)}}l$();Z0();function mo(A,Q){return Q?A.optional():A}function sr0(A){switch(A.type){case"string":return mo(K.string(),A.optional);case"number":return mo(K.number(),A.optional);case"enum":{let Q=[...A.options];return mo(K.enum(Q),A.optional)}case"object":{let Q={};for(let[w,B]of Object.entries(A.fields))Q[w]=sr0(B);return mo(K.object(Q),A.optional)}case"array":{let Q=K.array(Hzw(A));if(A.minItems!==void 0)Q=Q.min(A.minItems);if(A.length!==void 0)Q=Q.length(A.length);return mo(Q,A.optional)}}}function Hzw(A){let{items:Q}=A;switch(Q.type){case"string":return K.string();case"number":return K.number();case"enum":{let w=[...Q.options];return K.enum(w)}case"object":{let w={};for(let[B,$]of Object.entries(Q.fields))w[B]=sr0($);return K.object(w)}}}function or0(A,Q){switch(Q.type){case"string":case"enum":return{key:A,label:Q.label,type:"string"};case"number":return{key:A,label:Q.label,type:"number"};case"object":return{key:A,label:Q.label,type:"object",children:Object.entries(Q.fields).map(([w,B])=>or0(w,B))};case"array":{let w={key:A,label:Q.label,type:"array"};switch(Q.items.type){case"string":case"enum":return w.itemType="string",w;case"number":return w.itemType="number",w;case"object":return w.itemType="object",w.itemMappings=Object.entries(Q.items.fields).map(([B,$])=>or0(B,$)),w}}}}function Wzw(A,Q){let w={};for(let[f,D]of Object.entries(Q.fields))w[f]=sr0(D);let B=K.object(w),$=new pw(B,{title:Q.title,mappings:Object.entries(Q.fields).map(([f,D])=>or0(f,D))});return{name:A,description:Q.description,schema:B,formatter:$,requiredPermission:Q.requiredPermission??"public",layout:{component:Q.layout,...Q.fullscreen!==void 0?{fullscreen:Q.fullscreen}:{}},...Q.runtimeScripts?{runtimeScripts:Q.runtimeScripts}:{}}}function ar0(A){return Object.fromEntries(Object.entries(A.sections).map(([Q,w])=>[Q,Wzw(Q,w)]))}Z0();var Be1=K.object({namespace:K.string(),sections:K.record(K.any())}),$e1=K.object({definitions:K.union([Be1,K.array(Be1)]).optional()});c0();function fe1(A,Q){return[Sw(Q,"generate","Generate content for all routes, a specific route, or a specific section",AY0,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},D=await $.generateContent(w,f);return{success:!0,message:`Generated ${D.queuedSections} of ${D.totalSections} sections. ${D.queuedSections>0?"Jobs are running in the background.":"No new content to generate."}`,data:{batchId:D.batchId,jobsQueued:D.queuedSections,totalSections:D.totalSections,jobs:D.jobs}}})]}var De1={name:"@brains/site-content",private:!0,version:"0.2.0-alpha.134",description:"Site content entity and generation orchestration",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/content-formatters":"workspace:*","@brains/plugins":"workspace:*","@brains/site-info":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};class tr0 extends RQ{siteContentService;constructor(A={}){super("site-content",De1,A,$e1)}async onRegister(A){A.entities.register("site-content",So,dr0);for(let Q of YU(this.config.definitions))A.templates.register(ar0(Q),Q.namespace);this.siteContentService=new rr0(A)}async getTools(){return fe1(()=>this.siteContentService,this.id)}}function uo(A={}){return new tr0(A)}c0();Z0();JB();Z0();c0();var Ye1=K.enum(["available","early access","coming soon","planned"]),Xe1=K.object({title:K.string(),description:K.string()}),vX=K.object({name:K.string(),availability:Ye1,order:K.number(),ogImageId:K.string().optional()}),QY0=K.object({tagline:K.string(),promise:K.string(),role:K.string(),purpose:K.string(),audience:K.string(),values:K.array(K.string()).min(1),features:K.array(Xe1).min(1).max(6),story:K.string()}),Kzw=vX.pick({name:!0,availability:!0,order:!0}).extend({slug:K.string()}),gE=o1.extend({entityType:K.literal("product"),metadata:Kzw}),wY0=gE.extend({frontmatter:vX,body:QY0,labels:K.record(K.string(),K.string()),ogImageUrl:K.string().optional()}),BY0=wY0.extend({url:K.string().optional(),typeLabel:K.string().optional(),listUrl:K.string().optional(),listLabel:K.string().optional(),ogImageUrl:K.string().optional()});c0();Z0();l$();class TE extends pw{constructor(){super(QY0,{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 er0 extends I2{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:gE,frontmatterSchema:vX,bodyFormatter:new TE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,vX);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,vX),w=w1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:w,availability:Q.availability,order:Q.order}}}}var $Y0=new er0;Z0();c0();var He1=K.object({title:K.string(),description:K.string()}),We1=K.object({title:K.string(),description:K.string()}),Uzw=K.object({title:K.string(),description:K.string()}),Ze1=K.object({heading:K.string(),buttonText:K.string(),link:K.string()}),JF=K.object({headline:K.string(),tagline:K.string()}),Gzw=K.object({title:K.string(),description:K.string()}),fY0=K.object({vision:K.string(),pillars:K.array(He1).min(1).max(6),approach:K.array(Gzw).min(1).max(6),productsIntro:K.string(),technologies:K.array(Uzw).min(1).max(6),benefits:K.array(We1).min(1).max(6),cta:Ze1}),Ke1=JF.pick({headline:!0}).extend({slug:K.string()}),SE=o1.extend({entityType:K.literal("products-overview"),metadata:Ke1}),co=SE.extend({frontmatter:JF,body:fY0,labels:K.record(K.string(),K.string())});c0();Z0();l$();class mE extends pw{constructor(){super(fY0,{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 Ao0 extends I2{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:SE,frontmatterSchema:JF,bodyFormatter:new mE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,JF);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,JF),w=w1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:w}}}}var Qo0=new Ao0;c0();Z0();var zzw=K.object({entityType:K.string(),query:K.object({id:K.string().optional()}).optional()});function Ue1(A,Q){let w=v2(A.content,vX),B=Q.parse(w.content),$=Q.getLabels();return wY0.parse({...A,frontmatter:w.metadata,body:B,labels:$})}function Ge1(A,Q){let w=v2(A.content,JF),B=Q.parse(w.content),$=Q.getLabels();return co.parse({...A,frontmatter:w.metadata,body:B,labels:$})}class DY0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new mE;productFormatter=new TE;constructor(A){this.logger=A;this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,w){let B=zzw.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 W=Ge1(H,this.overviewFormatter);return Q.parse(W)}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:Ue1(H,this.productFormatter)})}let[f,D]=await Promise.all([$.listEntities({entityType:"products-overview",options:{limit:1}}),$.listEntities({entityType:"product",options:{sortFields:[{field:"order",direction:"asc"}]}})]),Y=f[0];if(!Y)throw Error("Products overview entity not found");return Q.parse({overview:Ge1(Y,this.overviewFormatter),products:D.map((X)=>Ue1(X,this.productFormatter))})}}import{jsxDEV as B1,Fragment as Vzw}from"preact/jsx-dev-runtime";var ze1=({overview:A,products:Q})=>{let{frontmatter:w,body:B,labels:$}=A;return B1(Vzw,{children:[B1(NQ,{title:w.headline,description:w.tagline},void 0,!1,void 0,this),B1("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[B1("style",{children:`
9001
9001
  @keyframes wave-drift {
9002
9002
  from { transform: translateX(0); }
9003
9003
  to { transform: translateX(-50%); }
@@ -9192,7 +9192,7 @@ ${JSON.stringify(w,null,2)}`}function mD0(A){return A.map((Q)=>Q.detail===null?{
9192
9192
  font: 10px/1.45 var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
9193
9193
  }
9194
9194
  `}},void 0,!1,void 0,this),CX("section",{className:"product-shell",children:[CX("header",{className:"product-hero",children:[Q.brandLabel&&CX("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),CX("h1",{className:"printable-title",children:Q.name},void 0,!1,void 0,this),Q.availability&&CX("div",{className:"printable-meta",children:CX("span",{children:Q.availability},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),CX("div",{className:"product-body-wrap",children:[CX("aside",{className:"product-rail","aria-hidden":"true",children:CX("p",{className:"product-rail-label",children:"Product brief / capabilities"},void 0,!1,void 0,this)},void 0,!1,void 0,this),CX($9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q.brandLabel&&CX("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 _zw=26214400,Pzw=60000;class Bo0{context;metadata={outputEntityType:"document"};renderPdf;constructor(A,Q={}){this.context=A;this.renderPdf=Q.renderPdf??VK}async resolve(A){if(A.sourceEntityType!=="product"||A.attachmentType!==YY0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let w=kzw(Q,{brandLabel:this.resolveBrandLabel()}),B=await Lzw(Mzw(jzw(),"brain-product-printable-"));try{let $=await MX({outputDir:B,mediaPath:`/_media/printable/product/${Q.id}`,template:Ve1,format:"pdf",content:w,siteConfig:{title:w.name,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await _X({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:_zw,timeoutMs:Pzw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${Ozw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await Nzw(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 kzw(A,Q={}){let{frontmatter:w,content:B}=lw(A.content),$=vX.parse(w);return{name:$.name,body:B,availability:$.availability,...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function Ozw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.name)}Z0();Z0();import{jsxDEV as hzw}from"preact/jsx-dev-runtime";var XY0="og-image",xzw="products:og-image",Ie1=K.object({name:K.string().min(1),tagline:K.string().optional(),availability:K.string().optional(),brandLabel:K.string().optional()}),Je1={name:xzw,pluginId:"products",schema:Ie1,renderers:{image:Rzw}};function Rzw(A){let Q=Ie1.parse(A);return hzw(l3,{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 $o0{context;deps;metadata={outputEntityType:"image",targetField:"ogImageId"};constructor(A,Q={}){this.context=A;this.deps=Q}async resolve(A){if(A.sourceEntityType!=="product"||A.attachmentType!==XY0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:B}=lw(Q.content),$=vX.parse(w),f=vzw(B,"Tagline"),D=this.resolveBrandLabel(),Y={name:$.name,availability:$.availability,...f?{tagline:f}:{},...D?{brandLabel:D}:{}};return{type:"image",data:await KP({mediaPath:`/_media/og/product/${Q.id}`,template:Je1,content:Y,title:Y.name,themeMode:"light",themeCSS:this.context.themeCSS,tmpPrefix:"brain-product-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${Czw(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 vzw(A,Q){let w=A.split(/\r?\n/),B=w.findIndex((D)=>D.trim().toLowerCase()===`## ${Q.toLowerCase()}`);if(B===-1)return;let $=[];for(let D of w.slice(B+1)){if(D.trim().startsWith("## "))break;$.push(D)}let f=$.join(`
9195
- `).trim();return f.length>0?f:void 0}function Czw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.name)}var be1={name:"@brains/products",private:!0,version:"0.2.0-alpha.133",description:"Product entity management and overview page for marketing showcase",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var Ezw=K.object({overview:co,products:K.array(BY0)}),gzw=K.object({product:BY0});class fo0 extends PQ{entityType=$Y0.entityType;schema=gE;adapter=$Y0;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("products",be1,A,wo0)}getTemplates(){return{"product-list":R1({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:Ezw,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:ze1}}),"product-detail":R1({name:"product-detail",description:"Individual product detail page",schema:gzw,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:qe1}})}}getDataSources(){return[new DY0(this.logger.child("ProductsDataSource"))]}async onRegister(A){this.unregisterPrintableAttachmentProvider=A.attachments.register("product",YY0,new Bo0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("product",XY0,new $o0(A)),A.entities.register("products-overview",SE,Qo0)}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0}}function Do0(A={}){return new fo0(A)}import{join as Zqw}from"path";import{jsxDEV as HY0,Fragment as Tzw}from"preact/jsx-dev-runtime";var uE=({children:A})=>HY0(Tzw,{children:[HY0("div",{id:"bgCanvasWrap",className:"rizom-frame-canvas-wrap fixed top-0 left-0 w-full h-full pointer-events-none",children:HY0("canvas",{id:"heroCanvas",className:"w-full h-full block"},void 0,!1,void 0,this)},void 0,!1,void 0,this),HY0("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 uX6}from"preact/jsx-dev-runtime";import{jsxDEV as mzw}from"preact/jsx-dev-runtime";var WY0="px-6 md:px-10 xl:px-20",Szw=`${WY0} relative z-[1]`,Tb=({id:A,className:Q,children:w})=>mzw("section",{id:A,className:$2(Szw,Q),children:w},void 0,!1,void 0,this);import{jsxDEV as oX6}from"preact/jsx-dev-runtime";import{jsxDEV as tX6}from"preact/jsx-dev-runtime";import{jsxDEV as izw}from"preact/jsx-dev-runtime";var uzw="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)]",czw={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)]"},lzw={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)]"},pzw="w-full md:w-auto",EP=({href:A,variant:Q="primary",size:w="md",block:B=!1,className:$,children:f})=>izw("a",{href:A,className:$2("rizom-btn",`rizom-btn-${Q}`,`rizom-btn-${w}`,B&&"rizom-btn-block",uzw,czw[Q],lzw[w],B&&pzw,$),children:f},void 0,!1,void 0,this);import{jsxDEV as fH6}from"preact/jsx-dev-runtime";import{jsxDEV as HH6}from"preact/jsx-dev-runtime";import{Fragment as KH6}from"preact";import{jsxDEV as GH6}from"preact/jsx-dev-runtime";import{jsxDEV as Le1}from"preact/jsx-dev-runtime";var ZY0=({sections:A})=>Le1(uE,{children:Le1("main",{children:A},void 0,!1,void 0,this)},void 0,!1,void 0,this);c0();Z0();var Ne1=`/*
9195
+ `).trim();return f.length>0?f:void 0}function Czw(A){let Q=A.metadata.slug;return Q.length>0?Q:w1(A.metadata.name)}var be1={name:"@brains/products",private:!0,version:"0.2.0-alpha.134",description:"Product entity management and overview page for marketing showcase",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},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":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var Ezw=K.object({overview:co,products:K.array(BY0)}),gzw=K.object({product:BY0});class fo0 extends PQ{entityType=$Y0.entityType;schema=gE;adapter=$Y0;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("products",be1,A,wo0)}getTemplates(){return{"product-list":R1({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:Ezw,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:ze1}}),"product-detail":R1({name:"product-detail",description:"Individual product detail page",schema:gzw,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:qe1}})}}getDataSources(){return[new DY0(this.logger.child("ProductsDataSource"))]}async onRegister(A){this.unregisterPrintableAttachmentProvider=A.attachments.register("product",YY0,new Bo0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("product",XY0,new $o0(A)),A.entities.register("products-overview",SE,Qo0)}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0}}function Do0(A={}){return new fo0(A)}import{join as Zqw}from"path";import{jsxDEV as HY0,Fragment as Tzw}from"preact/jsx-dev-runtime";var uE=({children:A})=>HY0(Tzw,{children:[HY0("div",{id:"bgCanvasWrap",className:"rizom-frame-canvas-wrap fixed top-0 left-0 w-full h-full pointer-events-none",children:HY0("canvas",{id:"heroCanvas",className:"w-full h-full block"},void 0,!1,void 0,this)},void 0,!1,void 0,this),HY0("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 uX6}from"preact/jsx-dev-runtime";import{jsxDEV as mzw}from"preact/jsx-dev-runtime";var WY0="px-6 md:px-10 xl:px-20",Szw=`${WY0} relative z-[1]`,Tb=({id:A,className:Q,children:w})=>mzw("section",{id:A,className:$2(Szw,Q),children:w},void 0,!1,void 0,this);import{jsxDEV as oX6}from"preact/jsx-dev-runtime";import{jsxDEV as tX6}from"preact/jsx-dev-runtime";import{jsxDEV as izw}from"preact/jsx-dev-runtime";var uzw="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)]",czw={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)]"},lzw={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)]"},pzw="w-full md:w-auto",EP=({href:A,variant:Q="primary",size:w="md",block:B=!1,className:$,children:f})=>izw("a",{href:A,className:$2("rizom-btn",`rizom-btn-${Q}`,`rizom-btn-${w}`,B&&"rizom-btn-block",uzw,czw[Q],lzw[w],B&&pzw,$),children:f},void 0,!1,void 0,this);import{jsxDEV as fH6}from"preact/jsx-dev-runtime";import{jsxDEV as HH6}from"preact/jsx-dev-runtime";import{Fragment as KH6}from"preact";import{jsxDEV as GH6}from"preact/jsx-dev-runtime";import{jsxDEV as Le1}from"preact/jsx-dev-runtime";var ZY0=({sections:A})=>Le1(uE,{children:Le1("main",{children:A},void 0,!1,void 0,this)},void 0,!1,void 0,this);c0();Z0();var Ne1=`/*
9196
9196
  * Shared globals + helpers used by tree / constellation / roots canvas
9197
9197
  * scripts. Loaded as a shared static asset by the Rizom runtime package
9198
9198
  * so the variant canvases
@@ -11682,7 +11682,7 @@ facts, owners, or tasks. Return only the required structured JSON.`});Z0();var N
11682
11682
  `);return this.truncateContent(B||Q||sE(A))}truncateContent(A){if(A.length<=D02)return A;let Q=A.slice(0,D02-1),w=Q.search(/\s\S*$/);return`${(w>0?Q.slice(0,w):Q).trimEnd()}\u2026`}isSummaryEntity(A){return A.entityType===q5}isDecisionEntity(A){return A.entityType===yX}getEntitySpaceId(A){let Q=A.metadata;if("spaceId"in Q&&typeof Q.spaceId==="string")return Q.spaceId;return MK(Q)}}var rqw=5,oqw=3;function qo0(A){A.messaging.subscribe(BN,async(Q)=>{let w=cT.parse(Q.payload);return{success:!0,data:await jY0(A,w)}})}async function jY0(A,Q){let w=p8(Q.userPermissionLevel);if(!Q.channelId)return Y02(A,Q,{visibilityScope:w,reason:"no-channel-context",items:[]}),{items:[]};let B=new aE(A),$=await B.retrieve({query:Q.message,conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:rqw,visibilityScope:w}),f=$.results.length===0?await B.retrieve({conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:oqw,visibilityScope:w}):void 0,D=$.results.length>0,Y=D?$.results:f?.results??[];return Y02(A,Q,{visibilityScope:w,spaceId:$.spaceId??f?.spaceId,reason:Y.length>0?"memory-injected":"no-same-space-memory",items:Y.map((X)=>sqw(X,D))}),{items:Y.map(aqw)}}function Y02(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 sqw(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 aqw(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}}}c0();CB();Z0();bY();var Vo0=K.object({role:Aq,content:K.string(),timestamp:K.string().datetime().optional(),actor:bN.optional(),source:LN.optional()}),tqw=K.object({conversationId:K.string().default("eval-conversation"),messages:K.array(Vo0)}),eqw=K.object({conversationId:K.string()}),A3w=K.object({conversationId:K.string().default("eval-conversation"),interfaceType:K.string().default("eval"),channelId:K.string().default("eval-channel"),channelName:K.string().optional(),projectionDecision:K.enum(["update","append"]).default("update"),existingSummary:K.string().optional(),existingMessageCount:K.number().int().min(0).default(0),messages:K.array(Vo0)}),MY0=K.object({actorId:K.string(),canonicalId:K.string().optional(),displayName:K.string().optional()}),Q3w=MY0.extend({roles:K.array(K.enum(["user","assistant","system"])).default(["user"]),sourceActorIds:K.array(K.string()).optional()}),w3w=K.object({actorId:K.string().optional(),canonicalId:K.string().optional(),displayName:K.string()}),W02=K.object({id:K.string(),entityType:K.enum(["summary","decision","action-item"]),content:K.string(),excerpt:K.string().optional(),score:K.number().optional(),conversationId:K.string(),interfaceType:K.string(),channelId:K.string(),channelName:K.string().optional(),updated:K.string().datetime().optional(),visibility:X7,status:K.string().optional(),participants:K.array(Q3w).optional(),decidedBy:K.array(MY0).optional(),mentionedBy:K.array(MY0).optional(),assignedTo:K.array(w3w).optional(),requestedBy:K.array(MY0).optional()}),B3w=K.object({query:K.string().optional(),conversationId:K.string().optional(),interfaceType:K.string().optional(),channelId:K.string().optional(),limit:K.number().int().min(1).optional(),includeOtherSpaces:K.boolean().optional(),actorId:K.string().optional(),canonicalId:K.string().optional(),visibilityScope:X7.optional(),memory:K.array(W02).optional()}),$3w=K.object({conversationId:K.string().default("eval-conversation"),message:K.string(),interfaceType:K.string().default("eval"),channelId:K.string().optional(),channelName:K.string().optional(),userPermissionLevel:K.enum(["anchor","trusted","public"]).default("trusted"),memory:K.array(W02).optional()}),f3w=K.object({conversationId:K.string().default("eval-conversation"),existingSummary:K.string().optional(),existingMessageCount:K.number().int().min(0).default(0),messages:K.array(Vo0)});function Z02(A){let{context:Q,logger:w,config:B}=A;Q.eval.registerHandler("summarizeMessages",async($)=>{let f=tqw.parse($),D=Fo0(f.messages,f.conversationId),X=await new nE(Q,w,B).extract(D);return X.entries.map((H)=>{let W=X.decisions.filter((G)=>G.timeRange.start>=H.timeRange.start).filter((G)=>G.timeRange.end<=H.timeRange.end).map((G)=>G.text),Z=X.actionItems.filter((G)=>G.timeRange.start>=H.timeRange.start).filter((G)=>G.timeRange.end<=H.timeRange.end).map((G)=>G.text);return{...H,decisions:W,actionItems:Z,keyPointsText:H.keyPoints.join(`
11683
11683
  `),decisionsText:W.join(`
11684
11684
  `),actionItemsText:Z.join(`
11685
- `)}})}),Q.eval.registerHandler("decideProjection",async($)=>{let f=f3w.parse($),D=Fo0(f.messages,f.conversationId),Y=f.existingSummary?X02({conversationId:f.conversationId,content:f.existingSummary,messageCount:f.existingMessageCount,projectionVersion:B.projectionVersion,visibility:B.memoryVisibility}):null;return new mb(Q,w,B).decideProjection(D,Y)}),Q.eval.registerHandler("retrieveMemory",async($)=>{let f=B3w.parse($),D=f.memory?H02(Q,f.memory):Q;return new aE(D).retrieve(f)}),Q.eval.registerHandler("buildAgentContext",async($)=>{let f=$3w.parse($),D=f.memory?H02(Q,f.memory):Q;return jY0(D,f)}),Q.eval.registerHandler("projectMessages",async($)=>{let f=A3w.parse($),D=Fo0(f.messages,f.conversationId),Y=D3w({conversationId:f.conversationId,interfaceType:f.interfaceType,channelId:f.channelId,channelName:f.channelName,messages:D}),X=f.existingSummary?X02({conversationId:f.conversationId,content:f.existingSummary,messageCount:f.existingMessageCount,projectionVersion:B.projectionVersion,visibility:B.memoryVisibility}):null,H=[],W=[],Z=Y3w({context:Q,conversation:Y,messages:D,existing:X,upserted:H,deleted:W,projectionDecision:f.projectionDecision});return{result:await new mb(Z,w,B).projectConversation(f.conversationId),summaries:H.filter((V)=>V.entityType==="summary"),decisions:H.filter((V)=>V.entityType==="decision"),actionItems:H.filter((V)=>V.entityType==="action-item"),deleted:W}}),Q.eval.registerHandler("projectConversation",async($)=>{let f=eqw.parse($);return new mb(Q,w,B).projectConversation(f.conversationId)})}function X02(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 Fo0(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 D3w(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 Y3w(A){let Q=MK(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 H02(A,Q){let w=Q.map(X3w),B=w.map(($,f)=>({entity:$,score:Q[f]?.score??1,excerpt:Q[f]?.excerpt??sE($)}));return{...A,entityService:{...A.entityService,search:async()=>B,listEntities:async({entityType:$})=>w.filter((f)=>f.entityType===$)}}}function X3w(A){if(A.entityType==="summary")return H3w(A);if(A.entityType==="decision")return W3w(A);return Z3w(A)}function Io0(A){let Q=A.updated??"2026-01-01T00:00:00.000Z";return{id:A.id,content:A.content,contentHash:xw(A.content),visibility:A.visibility,created:Q,updated:Q}}function H3w(A){return{...Io0(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 W3w(A){return{...Io0(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:MK(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 Z3w(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...Io0(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:MK(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 K02={name:"@brains/conversation-memory",private:!0,version:"0.2.0-alpha.133",description:"Plugin for deriving durable conversation memory",type:"module",main:"./src/index.ts",exports:{".":"./src/index.ts"},scripts:{test:"bun test",typecheck:"tsc --noEmit",lint:"eslint src test --ext .ts,.tsx",eval:"cd evals && bun run brain-eval","lint:fix":"eslint src test --ext .ts,.tsx --fix"},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.0.0",eslint:"^8.56.0",typescript:"^5.3.3"}};var U3w=new ZW,G3w=new pE,z3w=new iE,q3w=K.object({conversationId:K.string()});class Jo0 extends PQ{entityType=q5;schema=po;adapter=U3w;constructor(A={}){super(UY0,K02,A,Wo0)}getConfig(){return this.config}getTemplates(){return{"summary-list":Te1,"summary-detail":Se1,"ai-response":me1}}getDataSources(){return[new zo0(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:q5,job:{type:Re1,handler:new IY0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await qN(A,q5,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:Ho0,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:UY0}}},sourceChange:{sourceKind:LS,sourceTypes:[LS],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[tO],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:Ho0,deduplication:"skip",deduplicationKey:`conversation-memory:${w}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${w}`,pluginId:UY0}}}}}]}parseConversationMessagePayload(A){return q3w.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:w}=this.parseConversationMessagePayload(Q),B=await A.conversations.get(w);if(!B)return!1;return SP({conversation:B,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(yX,io,G3w),A.entities.register(WW,no,z3w),le1({context:A,pluginId:this.id}),ie1({context:A,pluginId:this.id}),Q02({context:A,pluginId:this.id}),$02({context:A,pluginId:this.id,config:this.config}),qo0(A),Z02({context:A,logger:this.logger,config:this.config})}}function bo0(A){return new Jo0(A)}c0();Z0();c0();var bF=K.object({title:K.string(),section:K.string(),order:K.number().int(),sourcePath:K.string(),description:K.string().optional(),slug:K.string().optional()}),U02=bF.pick({title:!0,section:!0,order:!0,description:!0}).extend({slug:K.string()}),tE=o1.extend({entityType:K.literal("doc"),metadata:U02}),LF=tE.extend({frontmatter:bF,body:K.string()});c0();Z0();class Lo0 extends I2{constructor(){super({entityType:"doc",purpose:"A structured documentation page.",schema:tE,frontmatterSchema:bF})}toMarkdown(A){let Q=this.extractBody(A.content),w=this.parseFrontMatter(A.content,bF);return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,bF),w=Q.slug??w1(Q.title);return{content:A,entityType:"doc",metadata:{title:Q.title,section:Q.section,order:Q.order,slug:w,...Q.description?{description:Q.description}:{}}}}}var _Y0=new Lo0;c0();function G02(A){return[...A].sort((Q,w)=>{let B=Q.metadata.order-w.metadata.order;if(B!==0)return B;return Q.metadata.title.localeCompare(w.metadata.title)})}function z02(A){let Q=v2(A.content,bF);return LF.parse({...A,frontmatter:Q.metadata,body:Q.content})}class PY0 extends W${id="docs:entities";name="Docs Entity DataSource";description="Fetches and transforms doc entities for rendering";config={entityType:"doc",defaultSort:[{field:"order",direction:"asc"},{field:"section",direction:"asc"},{field:"title",direction:"asc"}],defaultLimit:100,enableNavigation:!0};constructor(A){super(A)}transformEntity(A){return z02(A)}async fetch(A,Q,w){let B=this.parseQuery(A);if(!B.query.id){let W=await this.fetchList({...B.query,limit:1000,page:void 0,pageSize:void 0},w.entityService);return Q.parse(this.buildListResult(W.items,null,B.query))}let[$,f]=await Promise.all([this.fetchDetail(B.query.id,w.entityService),this.fetchList({limit:1000},w.entityService)]),D=G02(f.items),Y=D.findIndex((W)=>W.id===$.item.id),X=Y>0?D[Y-1]:null,H=Y>=0&&Y<D.length-1?D[Y+1]:null;return Q.parse({doc:$.item,docs:D,prevDoc:X,nextDoc:H})}buildDetailResult(A,Q){return{doc:A,docs:[A],prevDoc:Q?.prev??null,nextDoc:Q?.next??null}}buildListResult(A,Q,w){return{docs:G02(A),pagination:Q,baseUrl:w.baseUrl}}}c0();JB();Z0();import{jsxDEV as x$}from"preact/jsx-dev-runtime";var F3w=["I","II","III","IV","V","VI","VII","VIII","IX","X"];function so(A){return[...A].sort((Q,w)=>{let B=Q.metadata.order-w.metadata.order;if(B!==0)return B;return Q.metadata.title.localeCompare(w.metadata.title)})}function kY0(A){let Q=new Map;for(let w of so(A)){let B=w.metadata.section;Q.set(B,[...Q.get(B)??[],w])}return[...Q.entries()].map(([w,B])=>({section:w,docs:B}))}function eE(A){return`/docs/${A.metadata.slug}`}function OY0(A){return`section-${A+1}`}function Ag(A){return F3w[A]??String(A+1)}var V02="text-[var(--docs-text)] font-bold",I02="text-[var(--docs-accent)] font-bold",J02="text-[var(--docs-text-muted)]",V3w="docs-font-label text-xs uppercase tracking-[0.18em] text-[var(--docs-accent)]",I3w="docs-font-display text-[var(--docs-heading)]",q02="inline-flex items-center justify-center rounded-lg border px-[18px] py-2.5 text-sm font-semibold transition-colors duration-150",F02="relative hidden py-1 text-[15px] text-[var(--docs-text-muted)] transition-colors duration-150 after:absolute after:bottom-0 after:left-0 after:h-px after:w-0 after:bg-[var(--docs-accent)] after:transition-[width] after:duration-300 hover:text-[var(--docs-text)] hover:after:w-full min-[861px]:inline-block",No0="docs-font-label text-[13px] text-[var(--docs-text-light)] transition-colors duration-150 hover:text-[var(--docs-text)]",Qz={wrap:"mx-auto max-w-6xl px-6 pt-20 md:px-12 md:pt-24",label:V3w,display:I3w,button:`${q02} border-[var(--docs-text)] text-[var(--docs-text)] hover:border-[var(--docs-accent)] hover:text-[var(--docs-accent)]`,primaryButton:`${q02} border-[var(--docs-accent)] bg-[var(--docs-accent)] text-white hover:bg-transparent hover:text-[var(--docs-accent)]`},b02=()=>x$("nav",{className:"docs-header fixed inset-x-0 top-0 z-[100] flex items-center justify-between px-6 py-4 md:px-10 md:py-5 xl:px-20",children:[x$("a",{href:"/docs",className:"docs-font-body text-xl font-bold","aria-label":"Brains docs",children:[x$("span",{className:V02,children:"brains"},void 0,!1,void 0,this),x$("span",{className:I02,children:"."},void 0,!1,void 0,this),x$("span",{className:J02,children:"docs"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x$("div",{className:"docs-header__nav flex items-center gap-4 md:gap-8",children:[x$("a",{className:F02,href:"/docs/roadmap",children:"Roadmap"},void 0,!1,void 0,this),x$("a",{className:F02,href:"https://github.com/rizom-ai/brains",children:"GitHub"},void 0,!1,void 0,this),x$("a",{href:"https://rizom.ai",className:"inline-flex items-center justify-center rounded-lg border border-[var(--docs-text)] px-4 py-2 text-[13px] font-semibold text-[var(--docs-text)] transition-colors duration-150 hover:border-[var(--docs-accent)] hover:text-[var(--docs-accent)] md:px-6 md:py-2.5 md:text-[15px]",children:"Get Brains"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),L02=()=>x$("footer",{className:"flex flex-col items-center justify-between gap-4 border-t border-[var(--docs-border-light)] py-8 text-center md:flex-row md:gap-6 md:py-6 md:text-left",children:[x$("a",{href:"https://rizom.ai",className:"docs-font-body text-[15px] font-bold",children:[x$("span",{className:V02,children:"rizom"},void 0,!1,void 0,this),x$("span",{className:I02,children:"."},void 0,!1,void 0,this),x$("span",{className:J02,children:"ai"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x$("div",{className:"flex flex-wrap items-center justify-center gap-6 md:justify-end",children:[x$("a",{className:No0,href:"/docs/roadmap",children:"Roadmap"},void 0,!1,void 0,this),x$("a",{className:No0,href:"https://github.com/rizom-ai/brains",children:"GitHub"},void 0,!1,void 0,this),x$("a",{className:No0,href:"https://rizom.ai",children:"Rizom"},void 0,!1,void 0,this),x$("button",{id:"themeToggle",className:"docs-font-label cursor-pointer rounded-md border border-[var(--docs-text-light)] bg-transparent px-2.5 py-1.5 text-[13px] text-[var(--docs-text-light)] transition-colors duration-150 hover:border-[var(--docs-text)] hover:text-[var(--docs-text)]",type:"button",children:"\u2600 Light"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),J3w=`
11685
+ `)}})}),Q.eval.registerHandler("decideProjection",async($)=>{let f=f3w.parse($),D=Fo0(f.messages,f.conversationId),Y=f.existingSummary?X02({conversationId:f.conversationId,content:f.existingSummary,messageCount:f.existingMessageCount,projectionVersion:B.projectionVersion,visibility:B.memoryVisibility}):null;return new mb(Q,w,B).decideProjection(D,Y)}),Q.eval.registerHandler("retrieveMemory",async($)=>{let f=B3w.parse($),D=f.memory?H02(Q,f.memory):Q;return new aE(D).retrieve(f)}),Q.eval.registerHandler("buildAgentContext",async($)=>{let f=$3w.parse($),D=f.memory?H02(Q,f.memory):Q;return jY0(D,f)}),Q.eval.registerHandler("projectMessages",async($)=>{let f=A3w.parse($),D=Fo0(f.messages,f.conversationId),Y=D3w({conversationId:f.conversationId,interfaceType:f.interfaceType,channelId:f.channelId,channelName:f.channelName,messages:D}),X=f.existingSummary?X02({conversationId:f.conversationId,content:f.existingSummary,messageCount:f.existingMessageCount,projectionVersion:B.projectionVersion,visibility:B.memoryVisibility}):null,H=[],W=[],Z=Y3w({context:Q,conversation:Y,messages:D,existing:X,upserted:H,deleted:W,projectionDecision:f.projectionDecision});return{result:await new mb(Z,w,B).projectConversation(f.conversationId),summaries:H.filter((V)=>V.entityType==="summary"),decisions:H.filter((V)=>V.entityType==="decision"),actionItems:H.filter((V)=>V.entityType==="action-item"),deleted:W}}),Q.eval.registerHandler("projectConversation",async($)=>{let f=eqw.parse($);return new mb(Q,w,B).projectConversation(f.conversationId)})}function X02(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 Fo0(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 D3w(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 Y3w(A){let Q=MK(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 H02(A,Q){let w=Q.map(X3w),B=w.map(($,f)=>({entity:$,score:Q[f]?.score??1,excerpt:Q[f]?.excerpt??sE($)}));return{...A,entityService:{...A.entityService,search:async()=>B,listEntities:async({entityType:$})=>w.filter((f)=>f.entityType===$)}}}function X3w(A){if(A.entityType==="summary")return H3w(A);if(A.entityType==="decision")return W3w(A);return Z3w(A)}function Io0(A){let Q=A.updated??"2026-01-01T00:00:00.000Z";return{id:A.id,content:A.content,contentHash:xw(A.content),visibility:A.visibility,created:Q,updated:Q}}function H3w(A){return{...Io0(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 W3w(A){return{...Io0(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:MK(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 Z3w(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...Io0(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:MK(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 K02={name:"@brains/conversation-memory",private:!0,version:"0.2.0-alpha.134",description:"Plugin for deriving durable conversation memory",type:"module",main:"./src/index.ts",exports:{".":"./src/index.ts"},scripts:{test:"bun test",typecheck:"tsc --noEmit",lint:"eslint src test --ext .ts,.tsx",eval:"cd evals && bun run brain-eval","lint:fix":"eslint src test --ext .ts,.tsx --fix"},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.0.0",eslint:"^8.56.0",typescript:"^5.3.3"}};var U3w=new ZW,G3w=new pE,z3w=new iE,q3w=K.object({conversationId:K.string()});class Jo0 extends PQ{entityType=q5;schema=po;adapter=U3w;constructor(A={}){super(UY0,K02,A,Wo0)}getConfig(){return this.config}getTemplates(){return{"summary-list":Te1,"summary-detail":Se1,"ai-response":me1}}getDataSources(){return[new zo0(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:q5,job:{type:Re1,handler:new IY0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await qN(A,q5,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:Ho0,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:UY0}}},sourceChange:{sourceKind:LS,sourceTypes:[LS],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[tO],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:Ho0,deduplication:"skip",deduplicationKey:`conversation-memory:${w}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${w}`,pluginId:UY0}}}}}]}parseConversationMessagePayload(A){return q3w.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:w}=this.parseConversationMessagePayload(Q),B=await A.conversations.get(w);if(!B)return!1;return SP({conversation:B,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(yX,io,G3w),A.entities.register(WW,no,z3w),le1({context:A,pluginId:this.id}),ie1({context:A,pluginId:this.id}),Q02({context:A,pluginId:this.id}),$02({context:A,pluginId:this.id,config:this.config}),qo0(A),Z02({context:A,logger:this.logger,config:this.config})}}function bo0(A){return new Jo0(A)}c0();Z0();c0();var bF=K.object({title:K.string(),section:K.string(),order:K.number().int(),sourcePath:K.string(),description:K.string().optional(),slug:K.string().optional()}),U02=bF.pick({title:!0,section:!0,order:!0,description:!0}).extend({slug:K.string()}),tE=o1.extend({entityType:K.literal("doc"),metadata:U02}),LF=tE.extend({frontmatter:bF,body:K.string()});c0();Z0();class Lo0 extends I2{constructor(){super({entityType:"doc",purpose:"A structured documentation page.",schema:tE,frontmatterSchema:bF})}toMarkdown(A){let Q=this.extractBody(A.content),w=this.parseFrontMatter(A.content,bF);return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,bF),w=Q.slug??w1(Q.title);return{content:A,entityType:"doc",metadata:{title:Q.title,section:Q.section,order:Q.order,slug:w,...Q.description?{description:Q.description}:{}}}}}var _Y0=new Lo0;c0();function G02(A){return[...A].sort((Q,w)=>{let B=Q.metadata.order-w.metadata.order;if(B!==0)return B;return Q.metadata.title.localeCompare(w.metadata.title)})}function z02(A){let Q=v2(A.content,bF);return LF.parse({...A,frontmatter:Q.metadata,body:Q.content})}class PY0 extends W${id="docs:entities";name="Docs Entity DataSource";description="Fetches and transforms doc entities for rendering";config={entityType:"doc",defaultSort:[{field:"order",direction:"asc"},{field:"section",direction:"asc"},{field:"title",direction:"asc"}],defaultLimit:100,enableNavigation:!0};constructor(A){super(A)}transformEntity(A){return z02(A)}async fetch(A,Q,w){let B=this.parseQuery(A);if(!B.query.id){let W=await this.fetchList({...B.query,limit:1000,page:void 0,pageSize:void 0},w.entityService);return Q.parse(this.buildListResult(W.items,null,B.query))}let[$,f]=await Promise.all([this.fetchDetail(B.query.id,w.entityService),this.fetchList({limit:1000},w.entityService)]),D=G02(f.items),Y=D.findIndex((W)=>W.id===$.item.id),X=Y>0?D[Y-1]:null,H=Y>=0&&Y<D.length-1?D[Y+1]:null;return Q.parse({doc:$.item,docs:D,prevDoc:X,nextDoc:H})}buildDetailResult(A,Q){return{doc:A,docs:[A],prevDoc:Q?.prev??null,nextDoc:Q?.next??null}}buildListResult(A,Q,w){return{docs:G02(A),pagination:Q,baseUrl:w.baseUrl}}}c0();JB();Z0();import{jsxDEV as x$}from"preact/jsx-dev-runtime";var F3w=["I","II","III","IV","V","VI","VII","VIII","IX","X"];function so(A){return[...A].sort((Q,w)=>{let B=Q.metadata.order-w.metadata.order;if(B!==0)return B;return Q.metadata.title.localeCompare(w.metadata.title)})}function kY0(A){let Q=new Map;for(let w of so(A)){let B=w.metadata.section;Q.set(B,[...Q.get(B)??[],w])}return[...Q.entries()].map(([w,B])=>({section:w,docs:B}))}function eE(A){return`/docs/${A.metadata.slug}`}function OY0(A){return`section-${A+1}`}function Ag(A){return F3w[A]??String(A+1)}var V02="text-[var(--docs-text)] font-bold",I02="text-[var(--docs-accent)] font-bold",J02="text-[var(--docs-text-muted)]",V3w="docs-font-label text-xs uppercase tracking-[0.18em] text-[var(--docs-accent)]",I3w="docs-font-display text-[var(--docs-heading)]",q02="inline-flex items-center justify-center rounded-lg border px-[18px] py-2.5 text-sm font-semibold transition-colors duration-150",F02="relative hidden py-1 text-[15px] text-[var(--docs-text-muted)] transition-colors duration-150 after:absolute after:bottom-0 after:left-0 after:h-px after:w-0 after:bg-[var(--docs-accent)] after:transition-[width] after:duration-300 hover:text-[var(--docs-text)] hover:after:w-full min-[861px]:inline-block",No0="docs-font-label text-[13px] text-[var(--docs-text-light)] transition-colors duration-150 hover:text-[var(--docs-text)]",Qz={wrap:"mx-auto max-w-6xl px-6 pt-20 md:px-12 md:pt-24",label:V3w,display:I3w,button:`${q02} border-[var(--docs-text)] text-[var(--docs-text)] hover:border-[var(--docs-accent)] hover:text-[var(--docs-accent)]`,primaryButton:`${q02} border-[var(--docs-accent)] bg-[var(--docs-accent)] text-white hover:bg-transparent hover:text-[var(--docs-accent)]`},b02=()=>x$("nav",{className:"docs-header fixed inset-x-0 top-0 z-[100] flex items-center justify-between px-6 py-4 md:px-10 md:py-5 xl:px-20",children:[x$("a",{href:"/docs",className:"docs-font-body text-xl font-bold","aria-label":"Brains docs",children:[x$("span",{className:V02,children:"brains"},void 0,!1,void 0,this),x$("span",{className:I02,children:"."},void 0,!1,void 0,this),x$("span",{className:J02,children:"docs"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x$("div",{className:"docs-header__nav flex items-center gap-4 md:gap-8",children:[x$("a",{className:F02,href:"/docs/roadmap",children:"Roadmap"},void 0,!1,void 0,this),x$("a",{className:F02,href:"https://github.com/rizom-ai/brains",children:"GitHub"},void 0,!1,void 0,this),x$("a",{href:"https://rizom.ai",className:"inline-flex items-center justify-center rounded-lg border border-[var(--docs-text)] px-4 py-2 text-[13px] font-semibold text-[var(--docs-text)] transition-colors duration-150 hover:border-[var(--docs-accent)] hover:text-[var(--docs-accent)] md:px-6 md:py-2.5 md:text-[15px]",children:"Get Brains"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),L02=()=>x$("footer",{className:"flex flex-col items-center justify-between gap-4 border-t border-[var(--docs-border-light)] py-8 text-center md:flex-row md:gap-6 md:py-6 md:text-left",children:[x$("a",{href:"https://rizom.ai",className:"docs-font-body text-[15px] font-bold",children:[x$("span",{className:V02,children:"rizom"},void 0,!1,void 0,this),x$("span",{className:I02,children:"."},void 0,!1,void 0,this),x$("span",{className:J02,children:"ai"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x$("div",{className:"flex flex-wrap items-center justify-center gap-6 md:justify-end",children:[x$("a",{className:No0,href:"/docs/roadmap",children:"Roadmap"},void 0,!1,void 0,this),x$("a",{className:No0,href:"https://github.com/rizom-ai/brains",children:"GitHub"},void 0,!1,void 0,this),x$("a",{className:No0,href:"https://rizom.ai",children:"Rizom"},void 0,!1,void 0,this),x$("button",{id:"themeToggle",className:"docs-font-label cursor-pointer rounded-md border border-[var(--docs-text-light)] bg-transparent px-2.5 py-1.5 text-[13px] text-[var(--docs-text-light)] transition-colors duration-150 hover:border-[var(--docs-text)] hover:text-[var(--docs-text)]",type:"button",children:"\u2600 Light"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),J3w=`
11686
11686
  .docs-handbook {
11687
11687
  --docs-bg: var(--color-bg, #0d0a1a);
11688
11688
  --docs-bg-card: var(--color-bg-card, #1a0a3e);
@@ -11834,7 +11834,7 @@ facts, owners, or tasks. Return only the required structured JSON.`});Z0();var N
11834
11834
  background: transparent;
11835
11835
  }
11836
11836
 
11837
- `,N02=()=>x$("style",{children:J3w},void 0,!1,void 0,this);import{jsxDEV as F2,Fragment as b3w}from"preact/jsx-dev-runtime";var xY0=({title:A,description:Q,children:w,detail:B=!1,footer:$=!1,contentClassName:f=""})=>F2(b3w,{children:[F2(NQ,{title:A,description:Q},void 0,!1,void 0,this),F2(N02,{},void 0,!1,void 0,this),F2("div",{className:`docs-handbook${B?" docs-handbook--detail":""}`,children:[F2(b02,{},void 0,!1,void 0,this),F2("div",{className:`${Qz.wrap} ${f}`.trim(),children:[w,$&&F2(L02,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j02=({docsCount:A,sectionsCount:Q,startDoc:w})=>F2("section",{className:"border-b border-[var(--docs-text)] py-14 md:py-24 md:pb-[72px]",children:[F2("p",{className:`${Qz.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),F2("h1",{className:`${Qz.display} m-0 max-w-[16ch] text-5xl leading-[1.05] tracking-[-0.02em] md:text-7xl`,children:["Build, run, and publish"," ",F2("em",{className:"text-[var(--docs-accent)]",children:"brains."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),F2("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),F2("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:[F2("div",{children:[F2("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),F2("div",{children:[F2("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),F2("div",{children:[F2("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),F2("div",{className:"mt-9 flex flex-wrap gap-3.5",children:[w&&F2("a",{className:Qz.primaryButton,href:eE(w),children:"Start reading"},void 0,!1,void 0,this),F2("a",{className:Qz.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),M02=({groups:A})=>F2("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:[F2("p",{className:"m-0 mb-3.5 font-medium text-[var(--docs-text)]",children:"Sections"},void 0,!1,void 0,this),F2("ol",{className:"m-0 list-none p-0",children:A.map((Q,w)=>F2("li",{className:"grid grid-cols-[32px_1fr] gap-2 py-1.5",children:[F2("span",{className:"docs-font-display text-[var(--docs-text-light)] italic",children:[Ag(w),"."]},void 0,!0,void 0,this),F2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${OY0(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),_02=({group:A,index:Q})=>F2("article",{className:"mb-16 last:mb-0",id:OY0(Q),children:[F2("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:[F2("span",{className:"text-right docs-font-display text-3xl leading-[1.1] text-[var(--docs-accent)] italic md:text-4xl",children:[Ag(Q),"."]},void 0,!0,void 0,this),F2("h2",{className:`${Qz.display} m-0 text-3xl leading-[1.1] tracking-[-0.015em] md:text-4xl`,children:A.section},void 0,!1,void 0,this),F2("span",{className:"docs-chapter__leader"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),F2("ol",{className:"m-0 list-none p-0",children:A.docs.map((w)=>F2("li",{className:"border-b border-[var(--docs-border-light)] last:border-b-0",children:F2("a",{className:"group block py-[18px] pl-12 md:pl-[68px]",href:eE(w),children:[F2("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&&F2("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),P02=({title:A})=>F2("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:[F2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/",children:"Home"},void 0,!1,void 0,this),F2("span",{children:"/"},void 0,!1,void 0,this),F2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/docs",children:"Docs"},void 0,!1,void 0,this),F2("span",{children:"/"},void 0,!1,void 0,this),F2("span",{children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this),k02=({groups:A,activeGroupIndex:Q,activeSlug:w})=>F2("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:F2("nav",{className:"docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)]",children:[F2("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),F2("ol",{className:"m-0 list-none p-0",children:A.map((B,$)=>{let f=$===Q;return F2("li",{className:f?"mb-[22px]":"mb-3.5",children:[F2("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#${OY0($)}`,children:[F2("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[Ag($),"."]},void 0,!0,void 0,this)," ",B.section]},void 0,!0,void 0,this),f&&F2("ol",{className:"mt-0.5 list-none p-0",children:B.docs.map((D)=>{let Y=D.metadata.slug===w;return F2("li",{children:F2("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)] ${Y?"pl-3.5 font-medium text-[var(--docs-accent)]":"text-[var(--docs-text-muted)]"}`,href:eE(D),"aria-current":Y?"page":void 0,children:D.metadata.title},void 0,!1,void 0,this)},D.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),O02=({prevDoc:A,nextDoc:Q})=>{if(!A&&!Q)return null;return F2("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?F2("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] transition-colors duration-150 hover:border-[var(--docs-accent)]",href:eE(A),children:[F2("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),F2("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):F2("span",{},void 0,!1,void 0,this),Q&&F2("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:eE(Q),children:[F2("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),F2("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 Qg}from"preact/jsx-dev-runtime";var jo0=({docs:A})=>{let Q=so(A),w=kY0(Q),$=Q.filter((f)=>f.metadata.slug!=="index")[0]??Q[0];return Qg(xY0,{title:"Documentation",description:"Brains documentation",children:[Qg(j02,{docsCount:A.length,sectionsCount:w.length,startDoc:$},void 0,!1,void 0,this),Qg("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:[Qg(M02,{groups:w},void 0,!1,void 0,this),Qg("div",{children:w.map((f,D)=>Qg(_02,{group:f,index:D},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 EX}from"preact/jsx-dev-runtime";var Mo0=({doc:A,docs:Q,prevDoc:w,nextDoc:B})=>{let $=kY0(Q.length>0?Q:[A]),f=so(Q.length>0?Q:[A]),D=f.findIndex((X)=>X.metadata.slug===A.metadata.slug),Y=Math.max($.findIndex((X)=>X.docs.some((H)=>H.metadata.slug===A.metadata.slug)),0);return EX(xY0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[EX(P02,{title:A.metadata.title},void 0,!1,void 0,this),EX("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[EX(k02,{groups:$,activeGroupIndex:Y,activeSlug:A.metadata.slug},void 0,!1,void 0,this),EX("article",{className:"min-w-0",children:[EX("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[EX("p",{className:`${Qz.label} m-0 mb-6 flex items-baseline gap-3`,children:[EX("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[Ag(Y),"."]},void 0,!0,void 0,this)," ",A.metadata.section,D>=0?` \xB7 ${D+1}/${f.length}`:""]},void 0,!0,void 0,this),EX("h1",{className:`${Qz.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&&EX("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),EX("div",{className:"docs-article__body",children:EX($9,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),EX(O02,{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 L3w=K.object({docs:K.array(LF),pagination:e7.nullable(),baseUrl:K.string().optional()}),N3w=K.object({doc:LF,docs:K.array(LF),prevDoc:LF.nullable(),nextDoc:LF.nullable()});function x02(){return{"doc-list":R1({name:"doc-list",description:"Documentation index template",schema:L3w,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:jo0}}),"doc-detail":R1({name:"doc-detail",description:"Documentation page template",schema:N3w,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:Mo0}})}}var R02={name:"@brains/doc",private:!0,version:"0.2.0-alpha.133",description:"Documentation entity type \u2014 markdown docs as first-class brain content",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},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":"latest",typescript:"^5.3.3"}};class _o0 extends PQ{entityType=_Y0.entityType;schema=tE;adapter=_Y0;constructor(){super("docs",R02,{},void 0)}getTemplates(){return x02()}getDataSources(){return[new PY0(this.logger.child("DocDataSource"))]}}function Po0(){return new _o0}c0();Z0();Z0();l$();var h02=K.object({label:K.string(),href:K.string()}),v02=K.object({label:K.string(),title:K.string(),detail:K.string()}),M3w=K.object({eyebrow:K.string(),name:K.string(),sub:K.string()}),_3w=K.object({tone:K.enum(["capture","synthesis","share"]),title:K.string(),text:K.string()}),ko0=K.object({captures:K.number(),links:K.number(),topics:K.number(),summaries:K.number(),peers:K.number()}),wg=K.object({eyebrow:K.string(),headline:K.string(),intro:K.string(),primaryCta:h02,secondaryCta:h02,inputs:K.array(v02).min(1),outputs:K.array(v02).min(1),core:M3w,legend:K.array(_3w).min(1)}),Oo0=wg.extend({counts:ko0}),C02={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."}]},y02=new pw(wg,{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 RY0(A){return y02.parse(A)}function E02(A){return y02.format(A)}Z0();var P3w=K.object({query:K.object({routeId:K.string().default("home"),sectionId:K.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}).passthrough(),k3w={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class xo0{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=P3w.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 C02;return wg.parse(RY0(B.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(k3w).map(async([w,B])=>[w,await this.countOrZero(A,B)]));return ko0.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 $1}from"preact/jsx-dev-runtime";var g02=K.object({label:K.string(),href:K.string()}),O3w=K.object({eyebrow:K.string(),headline:K.string(),intro:K.string(),primaryCta:g02,secondaryCta:g02,signals:K.array(K.object({label:K.string(),value:K.string(),note:K.string()}))}),x3w=K.object({eyebrow:K.string(),title:K.string(),intro:K.string(),steps:K.array(K.object({phase:K.string(),title:K.string(),text:K.string()}))}),R3w=K.object({title:K.string(),intro:K.string(),cards:K.array(K.object({label:K.string(),title:K.string(),text:K.string()}))}),h3w=K.object({title:K.string(),intro:K.string(),points:K.array(K.string())}),v3w={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."]},C3w="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function T02({href:A,label:Q}){return $1("a",{href:A,className:C3w,children:Q},void 0,!1,void 0,this)}function y3w({siteInfo:A,children:Q}){let w=[...A.navigation.primary,...A.navigation.secondary],B=A.cta??{buttonText:"Start here",buttonLink:"/about"};return $1(uE,{children:[$1("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:[$1("a",{href:"/",className:"font-nav text-[20px]","aria-label":"Relay home",children:[$1("span",{className:"font-bold text-theme",children:"relay"},void 0,!1,void 0,this),$1("span",{className:"font-bold text-accent",children:"."},void 0,!1,void 0,this),$1("span",{className:"text-theme-muted",children:"brain"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$1("div",{className:"flex items-center gap-5 md:gap-8",children:[$1("div",{className:"hidden items-center gap-6 md:flex",children:w.map(($)=>$1(T02,{...$},`${$.href}-${$.label}`,!1,void 0,this))},void 0,!1,void 0,this),$1("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),$1("main",{children:Q},void 0,!1,void 0,this),$1("footer",{className:"relative z-[1] border-t border-theme-light px-6 py-8 md:px-10 xl:px-20",children:$1("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[$1("div",{children:[$1("p",{className:"font-label text-label-sm uppercase tracking-[0.22em] text-theme-light",children:A.copyright},void 0,!1,void 0,this),$1("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),$1("div",{className:"flex flex-wrap items-center gap-5",children:[w.map(($)=>$1(T02,{...$},`footer-${$.href}-${$.label}`,!1,void 0,this)),$1("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 E3w=({sections:A,siteInfo:Q})=>$1(y3w,{siteInfo:Q,children:A},void 0,!1,void 0,this);function g3w({eyebrow:A,headline:Q,intro:w,primaryCta:B,secondaryCta:$,signals:f}){return $1(Tb,{className:"min-h-[92vh] pt-[152px] pb-20 md:pt-[190px]",children:$1("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_420px] lg:items-end",children:[$1("div",{children:[$1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),$1("h1",{className:"mt-7 max-w-[980px] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),$1("p",{className:"mt-7 max-w-[720px] font-body text-body-lg text-theme-muted",children:w},void 0,!1,void 0,this),$1("div",{className:"mt-10 flex flex-col gap-3 sm:flex-row",children:[$1(EP,{href:B.href,size:"lg",variant:"primary-strong",children:B.label},void 0,!1,void 0,this),$1(EP,{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),$1("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:[$1("p",{className:"font-label text-label-xs uppercase tracking-[0.24em] text-theme-light",children:"Live relay signals"},void 0,!1,void 0,this),$1("div",{className:"mt-5 grid gap-3",children:f.map((D)=>$1("div",{className:"rounded-[22px] border border-card-divider bg-bg-muted p-5",children:[$1("div",{className:"flex items-center justify-between gap-4",children:[$1("p",{className:"font-label text-label-xs uppercase tracking-[0.18em] text-secondary",children:D.label},void 0,!1,void 0,this),$1("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),$1("p",{className:"mt-4 font-display text-display-sm text-theme",children:D.value},void 0,!1,void 0,this),$1("p",{className:"mt-2 font-body text-body-xs text-theme-muted",children:D.note},void 0,!1,void 0,this)]},D.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 T3w({eyebrow:A,title:Q,intro:w,steps:B}){return $1(Tb,{id:"operating-loop",className:"py-section",children:[$1("div",{className:"max-w-[840px]",children:[$1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-secondary",children:A},void 0,!1,void 0,this),$1("h2",{className:"mt-5 font-display text-display-md text-theme",children:Q},void 0,!1,void 0,this),$1("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),$1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:B.map(($)=>$1("article",{className:"min-h-[300px] rounded-[28px] border border-card-panel-border bg-card-panel-bg p-6",children:[$1("p",{className:"font-label text-label-sm text-accent",children:$.phase},void 0,!1,void 0,this),$1("h3",{className:"mt-16 font-display text-display-sm text-theme",children:$.title},void 0,!1,void 0,this),$1("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 S3w({title:A,intro:Q,cards:w}){return $1(Tb,{className:"py-section",children:$1("div",{className:"rounded-[36px] border border-theme-light bg-bg-muted p-6 md:p-10",children:$1("div",{className:"grid gap-8 lg:grid-cols-[360px_1fr]",children:[$1("div",{children:[$1("h2",{className:"font-display text-display-md text-theme",children:A},void 0,!1,void 0,this),$1("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),$1("div",{className:"grid gap-4",children:w.map((B)=>$1("article",{className:"rounded-[24px] border border-card-divider bg-bg-subtle/70 p-5",children:[$1("p",{className:"font-label text-label-xs uppercase tracking-[0.22em] text-accent",children:B.label},void 0,!1,void 0,this),$1("h3",{className:"mt-3 font-nav text-heading-lg text-theme",children:B.title},void 0,!1,void 0,this),$1("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 m3w({title:A,intro:Q,points:w}){return $1(Tb,{className:"min-h-[78vh] pt-[150px] pb-section md:pt-[190px]",children:[$1("div",{className:"max-w-[920px]",children:[$1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:"Relay model"},void 0,!1,void 0,this),$1("h1",{className:"mt-6 font-display text-display-lg text-theme",children:A},void 0,!1,void 0,this),$1("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),$1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:w.map((B)=>$1("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 u3w=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},c3w=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),ao=(A,Q,w=`${Q}s`)=>`${c3w(A)} ${A===1?Q:w}`;function l3w({eyebrow:A,headline:Q,intro:w,primaryCta:B,secondaryCta:$,inputs:f,outputs:D,core:Y,legend:X,counts:H}){let W=[{key:"captures",className:"top-[-10px] left-1/2 -translate-x-1/2",label:ao(H.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:ao(H.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:ao(H.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:ao(H.summaries,"summary","summaries")}];return $1(Tb,{className:"pt-[150px] pb-section md:pt-[190px]",id:"diagram",children:[$1("div",{className:"mx-auto max-w-[1040px] text-center",children:[$1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),$1("h1",{className:"mx-auto mt-7 max-w-[22ch] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),$1("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),$1("div",{className:"mt-10 flex flex-col justify-center gap-3 sm:flex-row",children:[$1(EP,{href:B.href,size:"lg",variant:"primary-strong",children:B.label},void 0,!1,void 0,this),$1(EP,{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),$1("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:[$1("div",{className:"grid items-center gap-8 lg:grid-cols-[1fr_1.4fr_1fr]",children:[$1("div",{className:"flex flex-col gap-3.5",children:f.map((Z)=>$1("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:[$1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:Z.label},void 0,!1,void 0,this),$1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:Z.title},void 0,!1,void 0,this),$1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:Z.detail},void 0,!1,void 0,this)]},`${Z.label}-${Z.title}`,!0,void 0,this))},void 0,!1,void 0,this),$1("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:[$1("div",{className:"absolute inset-0 rounded-full border border-dashed border-accent/30"},void 0,!1,void 0,this),$1("div",{className:"absolute inset-6 animate-spin rounded-full border border-dashed border-secondary/40 [animation-duration:28s]"},void 0,!1,void 0,this),W.map((Z)=>$1("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 ${Z.className}`,children:Z.label},Z.key,!1,void 0,this)),$1("div",{className:"relative z-[1] px-6 text-center",children:[$1("p",{className:"font-label text-[10px] uppercase tracking-[0.28em] text-accent",children:Y.eyebrow},void 0,!1,void 0,this),$1("p",{className:"mt-2 font-display text-[36px] leading-none text-theme",children:Y.name},void 0,!1,void 0,this),$1("p",{className:"mt-2 font-body text-[13px] text-theme-muted",children:Y.sub},void 0,!1,void 0,this),$1("p",{className:"mt-4 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light",children:[ao(H.links,"link")," indexed"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),$1("div",{className:"flex flex-col gap-3.5",children:D.map((Z)=>$1("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:[$1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:Z.label},void 0,!1,void 0,this),$1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:Z.title},void 0,!1,void 0,this),$1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:Z.detail},void 0,!1,void 0,this)]},`${Z.label}-${Z.title}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$1("div",{className:"mt-14 grid gap-4 border-t border-theme-light pt-8 md:grid-cols-3",children:X.map((Z)=>$1("div",{className:"text-left",children:[$1("h2",{className:"font-display text-[16px] font-medium text-theme",children:[$1("span",{className:`mr-2.5 inline-block h-3 w-3 rounded-[3px] align-middle ${u3w(Z.tone)}`},void 0,!1,void 0,this),Z.title]},void 0,!0,void 0,this),$1("p",{className:"mt-1.5 font-body text-[13px] leading-[1.6] text-theme-muted",children:Z.text},void 0,!1,void 0,this)]},Z.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var p3w=R1({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:Oo0,formatter:{parse:(A)=>Oo0.parse({...RY0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>E02(wg.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:l3w}}),i3w=(A)=>g3w(O3w.parse(A)),d3w=(A)=>T3w(x3w.parse(A)),n3w=(A)=>S3w(R3w.parse(A)),r3w=(A)=>m3w(h3w.parse(A)),S02={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},m02={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:i3w,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...S02,label:"Primary CTA"},secondaryCta:{...S02,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:d3w,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:n3w,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:r3w,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},o3w=[{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:v3w}]}],u02=Xo0({packageName:"@brains/relay/site",contentNamespace:"relay-site",themeProfile:"studio",layout:E3w,routes:o3w,templates:{"home-diagram":p3w},dataSources:[new xo0]});var c02={name:"@brains/relay",private:!0,version:"0.2.0-alpha.133",description:"Relay brain model \u2014 collaborative knowledge management",type:"module",files:["src","brain.eval.yaml","env.schema.template"],exports:{".":"./src/index.ts"},scripts:{"build:web-chat":"turbo run build --filter=@brains/web-chat","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","start:docs":"bun run build:web-chat && cd test-apps/docs && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start",typecheck:"tsc --noEmit",test:"bun test",eval:"brain-eval",lint:"eslint . --ext .ts,.tsx","lint:fix":"eslint . --ext .ts,.tsx --fix"},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/site-rizom":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/topics":"workspace:*","@brains/utils":"workspace:*","@brains/web-chat":"workspace:*","@brains/webserver":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/ai-evaluation":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*",typescript:"^5.3.3"}};var l02=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],p02=[...l02,"image","site-info","site-content","site-builder"],t3w=[...p02,"docs","decks"],e3w=["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."],i02=VI({name:"relay",version:c02.version,model:"gpt-5.4-mini",site:u02,theme:cE,presets:{core:l02,default:p02,full:t3w},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:e3w,capabilities:[["prompt",hP,void 0],["note",bP,{}],["link",NP,{}],["image",Uc,void 0],["topics",lf0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",bo0,{memoryVisibility:"shared"}],["docs",Po0,void 0],["decks",jr,void 0],["agents",CD0,void 0],["assessment",pD0,void 0],["auth-service",$p,void 0],["notifications",ow0,void 0],["email-resend",l$0,void 0],["cms",OP,{}],["dashboard",yb,void 0],["directory-sync",j_,{seedContent:!0,seedContentPath:a3w(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",uo,{definitions:m02}],["rizom-ecosystem",vP,void 0],["site-info",HP,void 0],["site-builder",XP,{}]],interfaces:[["mcp",eI,()=>({})],["discord",gJ,()=>({captureUrls:!0})],["a2a",SC,()=>({})],["webserver",uJ,()=>({})],["web-chat",TC,()=>({})]],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"}}});import{readFileSync as hJw}from"fs";import{join as vJw}from"path";import{execSync as CJw}from"child_process";import{parseArgs as wFw}from"util";var BFw={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 _K(A,Q){let w=A[Q];return typeof w==="string"?w:void 0}function ub(A,Q){let w=A[Q];return typeof w==="boolean"?w:void 0}function d02(A){let{values:Q,positionals:w}=wFw({args:A,options:BFw,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:_K(Q,"model"),domain:_K(Q,"domain"),"content-repo":_K(Q,"content-repo"),backend:_K(Q,"backend"),"push-to":_K(Q,"push-to"),"ai-api-key":_K(Q,"ai-api-key"),"no-interactive":ub(Q,"no-interactive"),preview:ub(Q,"preview"),deploy:ub(Q,"deploy"),regen:ub(Q,"regen"),all:ub(Q,"all"),only:_K(Q,"only"),"dry-run":ub(Q,"dry-run"),"startup-check":ub(Q,"startup-check"),"storage-dir":_K(Q,"storage-dir"),yes:ub(Q,"yes"),remote:_K(Q,"remote"),token:_K(Q,"token"),outputDir:_K(Q,"outputDir")}}}to();import{mkdirSync as LJw}from"fs";import{join as NJw}from"path";import{execSync as jJw}from"child_process";var vY0={name:"@rizom/brain",version:"0.2.0-alpha.133",description:"Brain runtime + CLI \u2014 scaffold, run, and manage AI brain instances",type:"module",bin:{brain:"./dist/brain.js"},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"],scripts:{build:"bun scripts/build.ts",prepublishOnly:"bun scripts/build.ts","dev:start":"bun scripts/build.ts && bun dist/brain.js start",typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts"},dependencies:{"@clack/prompts":"^0.11.0","@modelcontextprotocol/sdk":"^1.24.0","@tailwindcss/postcss":"^4.1.13","@tailwindcss/typography":"^0.5.19",postcss:"^8.5.6",preact:"^10.27.2","preact-render-to-string":"^6.3.1",tailwindcss:"^4.1.11"},optionalDependencies:{"@bitwarden/sdk-napi":"^1.0.0","@libsql/client":"^0.15.7","@tailwindcss/oxide":"^4.1.4","better-sqlite3":"^11.8.1",lightningcss:"^1.29.2","playwright-core":"^1.56.0","react-devtools-core":"^6.1.1",sharp:"^0.34.5"},devDependencies:{"@brains/app":"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":"latest",rollup:"^4.60.2","rollup-plugin-dts":"^6.4.1",typescript:"^5.3.3"},publishConfig:{access:"public"},repository:{type:"git",url:"https://github.com/rizom-ai/brains.git",directory:"packages/brain-cli"},license:"Apache-2.0",author:"Yeehaa <yeehaa@rizom.ai> (https://rizom.ai)",homepage:"https://github.com/rizom-ai/brains/tree/main/packages/brain-cli#readme",bugs:"https://github.com/rizom-ai/brains/issues",engines:{bun:">=1.3.3"},keywords:["brain","ai","cli","mcp","agent","personal-ai","knowledge-management"]};import{mkdirSync as YA2,writeFileSync as As,chmodSync as Qs,existsSync as mo0,readFileSync as uo0}from"fs";import{basename as co0,dirname as lo0,join as L6,resolve as gFw}from"path";import{fileURLToPath as TFw}from"url";var n02=`ARG BUN_VERSION=1.3.10
11837
+ `,N02=()=>x$("style",{children:J3w},void 0,!1,void 0,this);import{jsxDEV as F2,Fragment as b3w}from"preact/jsx-dev-runtime";var xY0=({title:A,description:Q,children:w,detail:B=!1,footer:$=!1,contentClassName:f=""})=>F2(b3w,{children:[F2(NQ,{title:A,description:Q},void 0,!1,void 0,this),F2(N02,{},void 0,!1,void 0,this),F2("div",{className:`docs-handbook${B?" docs-handbook--detail":""}`,children:[F2(b02,{},void 0,!1,void 0,this),F2("div",{className:`${Qz.wrap} ${f}`.trim(),children:[w,$&&F2(L02,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j02=({docsCount:A,sectionsCount:Q,startDoc:w})=>F2("section",{className:"border-b border-[var(--docs-text)] py-14 md:py-24 md:pb-[72px]",children:[F2("p",{className:`${Qz.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),F2("h1",{className:`${Qz.display} m-0 max-w-[16ch] text-5xl leading-[1.05] tracking-[-0.02em] md:text-7xl`,children:["Build, run, and publish"," ",F2("em",{className:"text-[var(--docs-accent)]",children:"brains."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),F2("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),F2("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:[F2("div",{children:[F2("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),F2("div",{children:[F2("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),F2("div",{children:[F2("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),F2("div",{className:"mt-9 flex flex-wrap gap-3.5",children:[w&&F2("a",{className:Qz.primaryButton,href:eE(w),children:"Start reading"},void 0,!1,void 0,this),F2("a",{className:Qz.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),M02=({groups:A})=>F2("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:[F2("p",{className:"m-0 mb-3.5 font-medium text-[var(--docs-text)]",children:"Sections"},void 0,!1,void 0,this),F2("ol",{className:"m-0 list-none p-0",children:A.map((Q,w)=>F2("li",{className:"grid grid-cols-[32px_1fr] gap-2 py-1.5",children:[F2("span",{className:"docs-font-display text-[var(--docs-text-light)] italic",children:[Ag(w),"."]},void 0,!0,void 0,this),F2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${OY0(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),_02=({group:A,index:Q})=>F2("article",{className:"mb-16 last:mb-0",id:OY0(Q),children:[F2("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:[F2("span",{className:"text-right docs-font-display text-3xl leading-[1.1] text-[var(--docs-accent)] italic md:text-4xl",children:[Ag(Q),"."]},void 0,!0,void 0,this),F2("h2",{className:`${Qz.display} m-0 text-3xl leading-[1.1] tracking-[-0.015em] md:text-4xl`,children:A.section},void 0,!1,void 0,this),F2("span",{className:"docs-chapter__leader"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),F2("ol",{className:"m-0 list-none p-0",children:A.docs.map((w)=>F2("li",{className:"border-b border-[var(--docs-border-light)] last:border-b-0",children:F2("a",{className:"group block py-[18px] pl-12 md:pl-[68px]",href:eE(w),children:[F2("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&&F2("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),P02=({title:A})=>F2("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:[F2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/",children:"Home"},void 0,!1,void 0,this),F2("span",{children:"/"},void 0,!1,void 0,this),F2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/docs",children:"Docs"},void 0,!1,void 0,this),F2("span",{children:"/"},void 0,!1,void 0,this),F2("span",{children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this),k02=({groups:A,activeGroupIndex:Q,activeSlug:w})=>F2("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:F2("nav",{className:"docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)]",children:[F2("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),F2("ol",{className:"m-0 list-none p-0",children:A.map((B,$)=>{let f=$===Q;return F2("li",{className:f?"mb-[22px]":"mb-3.5",children:[F2("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#${OY0($)}`,children:[F2("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[Ag($),"."]},void 0,!0,void 0,this)," ",B.section]},void 0,!0,void 0,this),f&&F2("ol",{className:"mt-0.5 list-none p-0",children:B.docs.map((D)=>{let Y=D.metadata.slug===w;return F2("li",{children:F2("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)] ${Y?"pl-3.5 font-medium text-[var(--docs-accent)]":"text-[var(--docs-text-muted)]"}`,href:eE(D),"aria-current":Y?"page":void 0,children:D.metadata.title},void 0,!1,void 0,this)},D.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),O02=({prevDoc:A,nextDoc:Q})=>{if(!A&&!Q)return null;return F2("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?F2("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] transition-colors duration-150 hover:border-[var(--docs-accent)]",href:eE(A),children:[F2("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),F2("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):F2("span",{},void 0,!1,void 0,this),Q&&F2("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:eE(Q),children:[F2("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),F2("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 Qg}from"preact/jsx-dev-runtime";var jo0=({docs:A})=>{let Q=so(A),w=kY0(Q),$=Q.filter((f)=>f.metadata.slug!=="index")[0]??Q[0];return Qg(xY0,{title:"Documentation",description:"Brains documentation",children:[Qg(j02,{docsCount:A.length,sectionsCount:w.length,startDoc:$},void 0,!1,void 0,this),Qg("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:[Qg(M02,{groups:w},void 0,!1,void 0,this),Qg("div",{children:w.map((f,D)=>Qg(_02,{group:f,index:D},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 EX}from"preact/jsx-dev-runtime";var Mo0=({doc:A,docs:Q,prevDoc:w,nextDoc:B})=>{let $=kY0(Q.length>0?Q:[A]),f=so(Q.length>0?Q:[A]),D=f.findIndex((X)=>X.metadata.slug===A.metadata.slug),Y=Math.max($.findIndex((X)=>X.docs.some((H)=>H.metadata.slug===A.metadata.slug)),0);return EX(xY0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[EX(P02,{title:A.metadata.title},void 0,!1,void 0,this),EX("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[EX(k02,{groups:$,activeGroupIndex:Y,activeSlug:A.metadata.slug},void 0,!1,void 0,this),EX("article",{className:"min-w-0",children:[EX("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[EX("p",{className:`${Qz.label} m-0 mb-6 flex items-baseline gap-3`,children:[EX("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[Ag(Y),"."]},void 0,!0,void 0,this)," ",A.metadata.section,D>=0?` \xB7 ${D+1}/${f.length}`:""]},void 0,!0,void 0,this),EX("h1",{className:`${Qz.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&&EX("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),EX("div",{className:"docs-article__body",children:EX($9,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),EX(O02,{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 L3w=K.object({docs:K.array(LF),pagination:e7.nullable(),baseUrl:K.string().optional()}),N3w=K.object({doc:LF,docs:K.array(LF),prevDoc:LF.nullable(),nextDoc:LF.nullable()});function x02(){return{"doc-list":R1({name:"doc-list",description:"Documentation index template",schema:L3w,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:jo0}}),"doc-detail":R1({name:"doc-detail",description:"Documentation page template",schema:N3w,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:Mo0}})}}var R02={name:"@brains/doc",private:!0,version:"0.2.0-alpha.134",description:"Documentation entity type \u2014 markdown docs as first-class brain content",type:"module",exports:{".":"./src/index.ts"},scripts:{typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"},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":"latest",typescript:"^5.3.3"}};class _o0 extends PQ{entityType=_Y0.entityType;schema=tE;adapter=_Y0;constructor(){super("docs",R02,{},void 0)}getTemplates(){return x02()}getDataSources(){return[new PY0(this.logger.child("DocDataSource"))]}}function Po0(){return new _o0}c0();Z0();Z0();l$();var h02=K.object({label:K.string(),href:K.string()}),v02=K.object({label:K.string(),title:K.string(),detail:K.string()}),M3w=K.object({eyebrow:K.string(),name:K.string(),sub:K.string()}),_3w=K.object({tone:K.enum(["capture","synthesis","share"]),title:K.string(),text:K.string()}),ko0=K.object({captures:K.number(),links:K.number(),topics:K.number(),summaries:K.number(),peers:K.number()}),wg=K.object({eyebrow:K.string(),headline:K.string(),intro:K.string(),primaryCta:h02,secondaryCta:h02,inputs:K.array(v02).min(1),outputs:K.array(v02).min(1),core:M3w,legend:K.array(_3w).min(1)}),Oo0=wg.extend({counts:ko0}),C02={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."}]},y02=new pw(wg,{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 RY0(A){return y02.parse(A)}function E02(A){return y02.format(A)}Z0();var P3w=K.object({query:K.object({routeId:K.string().default("home"),sectionId:K.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}).passthrough(),k3w={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class xo0{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=P3w.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 C02;return wg.parse(RY0(B.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(k3w).map(async([w,B])=>[w,await this.countOrZero(A,B)]));return ko0.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 $1}from"preact/jsx-dev-runtime";var g02=K.object({label:K.string(),href:K.string()}),O3w=K.object({eyebrow:K.string(),headline:K.string(),intro:K.string(),primaryCta:g02,secondaryCta:g02,signals:K.array(K.object({label:K.string(),value:K.string(),note:K.string()}))}),x3w=K.object({eyebrow:K.string(),title:K.string(),intro:K.string(),steps:K.array(K.object({phase:K.string(),title:K.string(),text:K.string()}))}),R3w=K.object({title:K.string(),intro:K.string(),cards:K.array(K.object({label:K.string(),title:K.string(),text:K.string()}))}),h3w=K.object({title:K.string(),intro:K.string(),points:K.array(K.string())}),v3w={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."]},C3w="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function T02({href:A,label:Q}){return $1("a",{href:A,className:C3w,children:Q},void 0,!1,void 0,this)}function y3w({siteInfo:A,children:Q}){let w=[...A.navigation.primary,...A.navigation.secondary],B=A.cta??{buttonText:"Start here",buttonLink:"/about"};return $1(uE,{children:[$1("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:[$1("a",{href:"/",className:"font-nav text-[20px]","aria-label":"Relay home",children:[$1("span",{className:"font-bold text-theme",children:"relay"},void 0,!1,void 0,this),$1("span",{className:"font-bold text-accent",children:"."},void 0,!1,void 0,this),$1("span",{className:"text-theme-muted",children:"brain"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$1("div",{className:"flex items-center gap-5 md:gap-8",children:[$1("div",{className:"hidden items-center gap-6 md:flex",children:w.map(($)=>$1(T02,{...$},`${$.href}-${$.label}`,!1,void 0,this))},void 0,!1,void 0,this),$1("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),$1("main",{children:Q},void 0,!1,void 0,this),$1("footer",{className:"relative z-[1] border-t border-theme-light px-6 py-8 md:px-10 xl:px-20",children:$1("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[$1("div",{children:[$1("p",{className:"font-label text-label-sm uppercase tracking-[0.22em] text-theme-light",children:A.copyright},void 0,!1,void 0,this),$1("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),$1("div",{className:"flex flex-wrap items-center gap-5",children:[w.map(($)=>$1(T02,{...$},`footer-${$.href}-${$.label}`,!1,void 0,this)),$1("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 E3w=({sections:A,siteInfo:Q})=>$1(y3w,{siteInfo:Q,children:A},void 0,!1,void 0,this);function g3w({eyebrow:A,headline:Q,intro:w,primaryCta:B,secondaryCta:$,signals:f}){return $1(Tb,{className:"min-h-[92vh] pt-[152px] pb-20 md:pt-[190px]",children:$1("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_420px] lg:items-end",children:[$1("div",{children:[$1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),$1("h1",{className:"mt-7 max-w-[980px] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),$1("p",{className:"mt-7 max-w-[720px] font-body text-body-lg text-theme-muted",children:w},void 0,!1,void 0,this),$1("div",{className:"mt-10 flex flex-col gap-3 sm:flex-row",children:[$1(EP,{href:B.href,size:"lg",variant:"primary-strong",children:B.label},void 0,!1,void 0,this),$1(EP,{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),$1("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:[$1("p",{className:"font-label text-label-xs uppercase tracking-[0.24em] text-theme-light",children:"Live relay signals"},void 0,!1,void 0,this),$1("div",{className:"mt-5 grid gap-3",children:f.map((D)=>$1("div",{className:"rounded-[22px] border border-card-divider bg-bg-muted p-5",children:[$1("div",{className:"flex items-center justify-between gap-4",children:[$1("p",{className:"font-label text-label-xs uppercase tracking-[0.18em] text-secondary",children:D.label},void 0,!1,void 0,this),$1("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),$1("p",{className:"mt-4 font-display text-display-sm text-theme",children:D.value},void 0,!1,void 0,this),$1("p",{className:"mt-2 font-body text-body-xs text-theme-muted",children:D.note},void 0,!1,void 0,this)]},D.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 T3w({eyebrow:A,title:Q,intro:w,steps:B}){return $1(Tb,{id:"operating-loop",className:"py-section",children:[$1("div",{className:"max-w-[840px]",children:[$1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-secondary",children:A},void 0,!1,void 0,this),$1("h2",{className:"mt-5 font-display text-display-md text-theme",children:Q},void 0,!1,void 0,this),$1("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),$1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:B.map(($)=>$1("article",{className:"min-h-[300px] rounded-[28px] border border-card-panel-border bg-card-panel-bg p-6",children:[$1("p",{className:"font-label text-label-sm text-accent",children:$.phase},void 0,!1,void 0,this),$1("h3",{className:"mt-16 font-display text-display-sm text-theme",children:$.title},void 0,!1,void 0,this),$1("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 S3w({title:A,intro:Q,cards:w}){return $1(Tb,{className:"py-section",children:$1("div",{className:"rounded-[36px] border border-theme-light bg-bg-muted p-6 md:p-10",children:$1("div",{className:"grid gap-8 lg:grid-cols-[360px_1fr]",children:[$1("div",{children:[$1("h2",{className:"font-display text-display-md text-theme",children:A},void 0,!1,void 0,this),$1("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),$1("div",{className:"grid gap-4",children:w.map((B)=>$1("article",{className:"rounded-[24px] border border-card-divider bg-bg-subtle/70 p-5",children:[$1("p",{className:"font-label text-label-xs uppercase tracking-[0.22em] text-accent",children:B.label},void 0,!1,void 0,this),$1("h3",{className:"mt-3 font-nav text-heading-lg text-theme",children:B.title},void 0,!1,void 0,this),$1("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 m3w({title:A,intro:Q,points:w}){return $1(Tb,{className:"min-h-[78vh] pt-[150px] pb-section md:pt-[190px]",children:[$1("div",{className:"max-w-[920px]",children:[$1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:"Relay model"},void 0,!1,void 0,this),$1("h1",{className:"mt-6 font-display text-display-lg text-theme",children:A},void 0,!1,void 0,this),$1("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),$1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:w.map((B)=>$1("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 u3w=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},c3w=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),ao=(A,Q,w=`${Q}s`)=>`${c3w(A)} ${A===1?Q:w}`;function l3w({eyebrow:A,headline:Q,intro:w,primaryCta:B,secondaryCta:$,inputs:f,outputs:D,core:Y,legend:X,counts:H}){let W=[{key:"captures",className:"top-[-10px] left-1/2 -translate-x-1/2",label:ao(H.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:ao(H.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:ao(H.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:ao(H.summaries,"summary","summaries")}];return $1(Tb,{className:"pt-[150px] pb-section md:pt-[190px]",id:"diagram",children:[$1("div",{className:"mx-auto max-w-[1040px] text-center",children:[$1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),$1("h1",{className:"mx-auto mt-7 max-w-[22ch] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),$1("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),$1("div",{className:"mt-10 flex flex-col justify-center gap-3 sm:flex-row",children:[$1(EP,{href:B.href,size:"lg",variant:"primary-strong",children:B.label},void 0,!1,void 0,this),$1(EP,{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),$1("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:[$1("div",{className:"grid items-center gap-8 lg:grid-cols-[1fr_1.4fr_1fr]",children:[$1("div",{className:"flex flex-col gap-3.5",children:f.map((Z)=>$1("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:[$1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:Z.label},void 0,!1,void 0,this),$1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:Z.title},void 0,!1,void 0,this),$1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:Z.detail},void 0,!1,void 0,this)]},`${Z.label}-${Z.title}`,!0,void 0,this))},void 0,!1,void 0,this),$1("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:[$1("div",{className:"absolute inset-0 rounded-full border border-dashed border-accent/30"},void 0,!1,void 0,this),$1("div",{className:"absolute inset-6 animate-spin rounded-full border border-dashed border-secondary/40 [animation-duration:28s]"},void 0,!1,void 0,this),W.map((Z)=>$1("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 ${Z.className}`,children:Z.label},Z.key,!1,void 0,this)),$1("div",{className:"relative z-[1] px-6 text-center",children:[$1("p",{className:"font-label text-[10px] uppercase tracking-[0.28em] text-accent",children:Y.eyebrow},void 0,!1,void 0,this),$1("p",{className:"mt-2 font-display text-[36px] leading-none text-theme",children:Y.name},void 0,!1,void 0,this),$1("p",{className:"mt-2 font-body text-[13px] text-theme-muted",children:Y.sub},void 0,!1,void 0,this),$1("p",{className:"mt-4 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light",children:[ao(H.links,"link")," indexed"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),$1("div",{className:"flex flex-col gap-3.5",children:D.map((Z)=>$1("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:[$1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:Z.label},void 0,!1,void 0,this),$1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:Z.title},void 0,!1,void 0,this),$1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:Z.detail},void 0,!1,void 0,this)]},`${Z.label}-${Z.title}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$1("div",{className:"mt-14 grid gap-4 border-t border-theme-light pt-8 md:grid-cols-3",children:X.map((Z)=>$1("div",{className:"text-left",children:[$1("h2",{className:"font-display text-[16px] font-medium text-theme",children:[$1("span",{className:`mr-2.5 inline-block h-3 w-3 rounded-[3px] align-middle ${u3w(Z.tone)}`},void 0,!1,void 0,this),Z.title]},void 0,!0,void 0,this),$1("p",{className:"mt-1.5 font-body text-[13px] leading-[1.6] text-theme-muted",children:Z.text},void 0,!1,void 0,this)]},Z.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var p3w=R1({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:Oo0,formatter:{parse:(A)=>Oo0.parse({...RY0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>E02(wg.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:l3w}}),i3w=(A)=>g3w(O3w.parse(A)),d3w=(A)=>T3w(x3w.parse(A)),n3w=(A)=>S3w(R3w.parse(A)),r3w=(A)=>m3w(h3w.parse(A)),S02={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},m02={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:i3w,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...S02,label:"Primary CTA"},secondaryCta:{...S02,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:d3w,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:n3w,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:r3w,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},o3w=[{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:v3w}]}],u02=Xo0({packageName:"@brains/relay/site",contentNamespace:"relay-site",themeProfile:"studio",layout:E3w,routes:o3w,templates:{"home-diagram":p3w},dataSources:[new xo0]});var c02={name:"@brains/relay",private:!0,version:"0.2.0-alpha.134",description:"Relay brain model \u2014 collaborative knowledge management",type:"module",files:["src","brain.eval.yaml","env.schema.template"],exports:{".":"./src/index.ts"},scripts:{"build:web-chat":"turbo run build --filter=@brains/web-chat","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","start:docs":"bun run build:web-chat && cd test-apps/docs && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start",typecheck:"tsc --noEmit",test:"bun test",eval:"brain-eval",lint:"eslint . --ext .ts,.tsx","lint:fix":"eslint . --ext .ts,.tsx --fix"},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/site-rizom":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/topics":"workspace:*","@brains/utils":"workspace:*","@brains/web-chat":"workspace:*","@brains/webserver":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/ai-evaluation":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*",typescript:"^5.3.3"}};var l02=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],p02=[...l02,"image","site-info","site-content","site-builder"],t3w=[...p02,"docs","decks"],e3w=["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."],i02=VI({name:"relay",version:c02.version,model:"gpt-5.4-mini",site:u02,theme:cE,presets:{core:l02,default:p02,full:t3w},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:e3w,capabilities:[["prompt",hP,void 0],["note",bP,{}],["link",NP,{}],["image",Uc,void 0],["topics",lf0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",bo0,{memoryVisibility:"shared"}],["docs",Po0,void 0],["decks",jr,void 0],["agents",CD0,void 0],["assessment",pD0,void 0],["auth-service",$p,void 0],["notifications",ow0,void 0],["email-resend",l$0,void 0],["cms",OP,{}],["dashboard",yb,void 0],["directory-sync",j_,{seedContent:!0,seedContentPath:a3w(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",uo,{definitions:m02}],["rizom-ecosystem",vP,void 0],["site-info",HP,void 0],["site-builder",XP,{}]],interfaces:[["mcp",eI,()=>({})],["discord",gJ,()=>({captureUrls:!0})],["a2a",SC,()=>({})],["webserver",uJ,()=>({})],["web-chat",TC,()=>({})]],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"}}});import{readFileSync as hJw}from"fs";import{join as vJw}from"path";import{execSync as CJw}from"child_process";import{parseArgs as wFw}from"util";var BFw={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 _K(A,Q){let w=A[Q];return typeof w==="string"?w:void 0}function ub(A,Q){let w=A[Q];return typeof w==="boolean"?w:void 0}function d02(A){let{values:Q,positionals:w}=wFw({args:A,options:BFw,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:_K(Q,"model"),domain:_K(Q,"domain"),"content-repo":_K(Q,"content-repo"),backend:_K(Q,"backend"),"push-to":_K(Q,"push-to"),"ai-api-key":_K(Q,"ai-api-key"),"no-interactive":ub(Q,"no-interactive"),preview:ub(Q,"preview"),deploy:ub(Q,"deploy"),regen:ub(Q,"regen"),all:ub(Q,"all"),only:_K(Q,"only"),"dry-run":ub(Q,"dry-run"),"startup-check":ub(Q,"startup-check"),"storage-dir":_K(Q,"storage-dir"),yes:ub(Q,"yes"),remote:_K(Q,"remote"),token:_K(Q,"token"),outputDir:_K(Q,"outputDir")}}}to();import{mkdirSync as LJw}from"fs";import{join as NJw}from"path";import{execSync as jJw}from"child_process";var vY0={name:"@rizom/brain",version:"0.2.0-alpha.134",description:"Brain runtime + CLI \u2014 scaffold, run, and manage AI brain instances",type:"module",bin:{brain:"./dist/brain.js"},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"],scripts:{build:"bun scripts/build.ts",prepublishOnly:"bun scripts/build.ts","dev:start":"bun scripts/build.ts && bun dist/brain.js start",typecheck:"tsc --noEmit",test:"bun test",lint:"eslint . --ext .ts"},dependencies:{"@clack/prompts":"^0.11.0","@modelcontextprotocol/sdk":"^1.24.0","@tailwindcss/postcss":"^4.1.13","@tailwindcss/typography":"^0.5.19",postcss:"^8.5.6",preact:"^10.27.2","preact-render-to-string":"^6.3.1",tailwindcss:"^4.1.11"},optionalDependencies:{"@bitwarden/sdk-napi":"^1.0.0","@libsql/client":"^0.15.7","@tailwindcss/oxide":"^4.1.4","better-sqlite3":"^11.8.1",lightningcss:"^1.29.2","playwright-core":"^1.56.0","react-devtools-core":"^6.1.1",sharp:"^0.34.5"},devDependencies:{"@brains/app":"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":"latest",rollup:"^4.60.2","rollup-plugin-dts":"^6.4.1",typescript:"^5.3.3"},publishConfig:{access:"public"},repository:{type:"git",url:"https://github.com/rizom-ai/brains.git",directory:"packages/brain-cli"},license:"Apache-2.0",author:"Yeehaa <yeehaa@rizom.ai> (https://rizom.ai)",homepage:"https://github.com/rizom-ai/brains/tree/main/packages/brain-cli#readme",bugs:"https://github.com/rizom-ai/brains/issues",engines:{bun:">=1.3.3"},keywords:["brain","ai","cli","mcp","agent","personal-ai","knowledge-management"]};import{mkdirSync as YA2,writeFileSync as As,chmodSync as Qs,existsSync as mo0,readFileSync as uo0}from"fs";import{basename as co0,dirname as lo0,join as L6,resolve as gFw}from"path";import{fileURLToPath as TFw}from"url";var n02=`ARG BUN_VERSION=1.3.10
11838
11838
  FROM oven/bun:\${BUN_VERSION}-slim AS runtime
11839
11839
 
11840
11840
  WORKDIR /app